Emacs lisp で dedent を実装する Emacs EmacsLisp
Pythonには textwrap.dedent という関数があります。
しかし、Emacs Lisp にはそのような関数は標準では用意されていません。そこで、以下のような関数を作成してみました。
コード
(defun my/dedent-string (text)
"Remove common leading whitespace from each line in TEXT."
(let* ((lines (split-string text "\n")) ; 文字列を行ごとに分割
(non-empty-lines (seq-filter (lambda (line) (not (string-match-p "^[ \t]*$" line))) lines))
(common-indent (if non-empty-lines
(apply 'min
(mapcar (lambda (line)
(if (string-match "^\\([ \t]*\\)" line)
(length (match-string 1 line))
0))
non-empty-lines))
0)))
(mapconcat (lambda (line)
(if (string-match (format "^ \\{%d\\}" common-indent) line)
(replace-match "" nil nil line)
line))
lines
"\n")))
説明
- 文字列を分割:
split-stringを使って、改行ごとに文字列を分割します。 - 空行を除外:
seq-filterで空行(空白やタブのみの行)を除外します。 - 共通のインデントを計算: 各行の先頭の空白の長さを計算し、その最小値を取得します。
- インデントを削除: 計算した共通のインデントを各行から削除します。
- 行を結合:
mapconcatを使って再度行を結合します。
この関数は、与えられた複数行の文字列の中で、共通するインデントのみを削除します。
実行例
サンプルのtest-stringを渡した場合、以下のように出力されます。
test-string
line 1
line 2
line 3
my-indent を実行。
(my/dedent-string test-string)
line 1
line 2
line 3