矩形入力スクリプトもどき

たとえば下の|のところにカーソルを置いて呼び出すと入力受け付けのループに入って、こういう表を(ソースのレイアウトを崩さずに)縦方向に項目を埋めていけるというもの。

\begin{array}{cccc}
 試料No &測定値1 & 測定値2 & 測定値3 \\
\hline
 &|& & \\    % <-- ここで起動
 & & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
\end{array}

↓ 1 return

\begin{array}{cccc}
 試料No &測定値1 & 測定値2 & 測定値3 \\
\hline
 & 1   & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
\end{array}

↓ 100000 return とするとさっきの1の後ろの空白もあわせて伸びる

\begin{array}{cccc}
 試料No &測定値1 & 測定値2 & 測定値3 \\
\hline
 & 1     & & \\
 & 100000& & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
 & & & \\
\end{array}

↓ ...

\begin{array}{cccc}
 試料No &測定値1 & 測定値2 & 測定値3 \\
\hline
 & 1       & & \\
 & 100000  & & \\
 & 20      & & \\
 & 12      & & \\
 & 12345   & & \\
 & 12345678& & \\
 & 15      & & \\
 & 2       & & \\
\end{array}

みたいな感じで入力の末尾に空白をくっつけてレイアウトが崩れないようにする。

LaTeXで↑こういう表を打とうとするといちいち&の間にカーソルを動かすのが面倒*1なので中途半端に自動化してみようとしたもの。

(defun nspace (n)
  (if (<= n 0) "" (concat " " (nspace (1- n)))))

(defun input-vertically ()
  (interactive)
  (let ((width      4)
	(done-lines 0)
	(start-column (current-column))
	(start-line (current-line-number)))
    (loop
      (let ((str (concat (read-string "?: "))))
	(if (<= (count-column str) width)
	    (insert (concat str (nspace (- width (count-column str)))))
	  (let ((expansion (- (count-column str) width))) ; widthより広かったらそれまでの行を全部広げてwidthを更新
	    (insert str)
	    (dotimes (i done-lines)
	      (previous-line)
	      (goto-column (+ start-column width))
	      (insert (nspace expansion)))
	    (goto-line (+ start-line done-lines))
	    (incf width expansion)
	    (goto-column width)))
	
	(incf done-lines)
	(if (= (buffer-lines) (current-line-number))
	    (progn
	      (end-of-line)
	      (newline))
	  (progn
	    (next-line)
	    (goto-column start-column))))
      (insert (nspace (- start-column (current-column)))))))

(defun input-vertically-with-comma-separation ()
  (interactive)
  (let ((width      5)
	(done-lines 0)
	(start-column (current-column))
	(start-line (current-line-number)))
    (loop
      (let ((str (concat (read-string "?: "))))
	(if (<= (+ (count-column str) 1) width)
	    (insert (concat str (nspace (- width (count-column str) 1)) ","))
	  (let ((expansion (- (+ (count-column str) 1) width))) ; widthより広かったらそれまでの行を全部広げてwidthを更新
	    (insert (concat str ","))
	    (dotimes (i done-lines)
	      (previous-line)
	      (goto-column (+ start-column width -1))
	      (insert (nspace expansion)))
	    (goto-line (+ start-line done-lines))
	    (incf width expansion)
	    (goto-column width)))
	
	(incf done-lines)
	(if (= (buffer-lines) (current-line-number))
	    (progn
	      (end-of-line)
	      (newline))
	  (progn
	    (next-line)
	    (goto-column start-column))))
	  (insert (nspace (- start-column (current-column)))))))

適当な場所にカーソルを置いてM-x input-verticallyでミニバッファからの入力受け付けループに入る。何か入力してreturnで次の行へ。C-gで終わる。

gnuplotとかのデータを手打ちするときとかは少し便利かもしれない。CSVを書きたいとかいうことがあったらinput-vertically-with-comma-separationがちょっとだけ便利かも?さっきの矩形の右端にカンマが勝手にくっつくだけだけど。

*1:ちなみにkatex入れてれば'&'たちはAlt+Returnで入れられて便利