Как мне подражать "softtabstop" Vim в Emacs?

В последнее время я пытался попасть в emacs, и одна из вещей, которые мне нужно исправить, - это отступы.

Пример 1:

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

Пример 2:

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

Представьте, что вертикальная черта в приведенных выше примерах указывает на позицию курсора. Теперь я использую (4) пробела для каждого уровня отступа (без вкладок), и у меня есть настройка emacs для автоматического отступа моего кода с учетом этого. Никаких проблем нет. Но в приведенных выше примерах, если бы я нажал клавишу возврата на указанную позицию курсора, я хочу, чтобы emacs полностью вернул назад на следующий уровень отступа (столбец / 4). То есть я хочу, чтобы предыдущий пробел обрабатывался так, как если бы он состоял из вкладок. Вместо этого он всегда просто стирает один пробел.

В vim я включаю 'expandtab', чтобы он вставлял пробелы вместо табуляции, и 'softtabstop', что делает (среди прочего) backspace до следующей «мягкой табуляции», как описано выше.

В emacs, я полагаю, я мог бы (если бы я знал emacs / elisp лучше) связать backspace с функцией, которая делает что-то вроде следующего:

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

Я хочу знать, есть ли более простой способ сделать это и / или знает ли кто-нибудь о существующем решении?


person Hinrik    schedule 20.09.2009    source источник
comment
Это осложняется тем фактом, что похоже, что вы пишете Perl, а cperl-mode (лучший режим Perl для Emacs) уже связывает backspace с cperl-electric-backspace. (Хотя эта функция не делает ничего критического, поэтому вы можете обойтись без того поведения, которое она обеспечивает.)   -  person cjm    schedule 20.09.2009
comment
Одно небольшое обновление: я ошибся в одном. Когда vim не может вернуться к следующей мягкой табуляции, он удаляет как можно больше пробелов (например, от 1 до 3), а не только 1.   -  person Hinrik    schedule 20.09.2009
comment
Решение обновлено, чтобы удалить как можно больше пробелов (до позиции табуляции)   -  person Trey Jackson    schedule 21.09.2009


Ответы (1)


Это работает для меня, где '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))))))
person Trey Jackson    schedule 20.09.2009
comment
См .: emacswiki.org/emacs/BackspaceWhitespaceToTabStop (имеет улучшенный версия). - person ideasman42; 17.10.2016
comment
Красиво, но backward-delete-char-untabify показалось ему довольно раздражающим, некоторые пользователи могут захотеть заменить его на backward-delete-char. - person ideasman42; 17.10.2016