6

私は最近emacsに入ろうとしていますが、正しく理解するために必要なことの1つはインデントです。

例1:

sub foo {
    my $bar = 'quux';
    |

例2:

sub foo {
    my $bar = 'quux';       |# foo

上記の例のパイプ文字がカーソル位置を示していると想像してください。現在、すべてのインデントレベル(タブなし)に(4)スペースを使用しており、それを念頭に置いてコードを自動的にインデントするようにemacsを設定しています。そこに問題はありません。しかし、上記の例では、指定されたカーソル位置でバックスペースを押す場合、emacsが次のインデントレベル(列/ 4)までバックスペースするようにします。つまり、前の空白をタブで構成されているかのように処理する必要があります。代わりに、常に1つのスペース文字を消去するだけです。

vimでは、「expandtab」をオンにしてタブの代わりにスペースを挿入し、「softtabstop」をオンにして(とりわけ)上記のように次の「ソフトタブストップ」にバックスペースします。

emacsでは、(emacs / elispをよく知っていれば)バックスペースを次のような関数にバインドできると思います。

if indent-tabs-mode is nil
    if the cursor position is preceded by whitespace
        calculate the position of the previous "soft tabstop"
        if there's enough whitespace
            backspace all the way to that point
        else
            backspace by one character

私が知りたいのは、これを行うためのより簡単な方法はありますか、および/または誰かが既存のソリューションを知っていますか?

4

1 に答える 1

7

これは私にとってはうまくいきます。ここで'tab-widthは、が列の幅として使用されます。適切なキーマップにキーを設定します...

(local-set-key (kbd "DEL") 'backward-delete-whitespace-to-column)
(defun backward-delete-whitespace-to-column ()
  "delete back to the previous column of whitespace, or as much whitespace as possible,
or just one char if that's not possible"
  (interactive)
  (if indent-tabs-mode
      (call-interactively 'backward-delete-char-untabify)
    (let ((movement (% (current-column) tab-width))
          (p (point)))
      (when (= movement 0) (setq movement tab-width))
      (save-match-data
        (if (string-match "\\w*\\(\\s-+\\)$" (buffer-substring-no-properties (- p movement) p))
            (backward-delete-char-untabify (- (match-end 1) (match-beginning 1)))
        (call-interactively 'backward-delete-char-untabify))))))
于 2009-09-20T06:35:52.777 に答える