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