Emacs Shift-Tab 左移代码块

34

我该如何让Emacs使用ShiftTab将选中的文本向左移动4个空格?

4个回答

57

3
根据同一手册条目,您可能更喜欢使用indent-code-rigidly,因为它不会影响注释和多行字符串。 - user23987

13

这将从当前行的开头删除4个空格(如果存在空格)。

(global-set-key (kbd "<S-tab>") 'un-indent-by-removing-4-spaces)
(defun un-indent-by-removing-4-spaces ()
  "remove 4 spaces from beginning of of line"
  (interactive)
  (save-excursion
    (save-match-data
      (beginning-of-line)
      ;; get rid of tabs at beginning of line
      (when (looking-at "^\\s-+")
        (untabify (match-beginning 0) (match-end 0)))
      (when (looking-at "^    ")
        (replace-match "")))))
如果您的变量tab-width恰好为4(并且您想要“撤消”它),则可以将(looking-at "^ ")替换为更通用的内容,例如(concat "^" (make-string tab-width ?\ ))
此外,该代码将使用untabify将行首的制表符转换为空格。

1
很好!但我会使用WHEN而不是IF,因为没有else子句。 - Ken
3
对我而言,它在选择区域时无效。只有在第一行时才有效 :-/ - Ismael
3
@Mauricio A. Cinelli -- 对 (kbd "<S-tab>") 进行绑定没有生效,但是对 (kbd "<backtab>") 进行绑定可以解决问题。 - modulitos

11

我编写了一些函数,用于通过按tab或shift+tab将区域向左或向右缩进四个空格:

我编写了一些函数,用于通过按Tab键或Shift+Tab键将文本区域向左或向右缩进四个空格:

(defun indent-region-custom(numSpaces)
    (progn 
        ; default to start and end of current line
        (setq regionStart (line-beginning-position))
        (setq regionEnd (line-end-position))
        
        ; if there's a selection, use that instead of the current line
        (when (use-region-p)
            (setq regionStart (region-beginning))
            (setq regionEnd (region-end))
        )
        
        (save-excursion ; restore the position afterwards            
            (goto-char regionStart) ; go to the start of region
            (setq start (line-beginning-position)) ; save the start of the line
            (goto-char regionEnd) ; go to the end of region
            (setq end (line-end-position)) ; save the end of the line
            
            (indent-rigidly start end numSpaces) ; indent between start and end
            (setq deactivate-mark nil) ; restore the selected region
        )
    )
)

(defun untab-region (N)
    (interactive "p")
    (indent-region-custom -4)
)

(defun tab-region (N)
    (interactive "p")
    (if (active-minibuffer-window)
        (minibuffer-complete)    ; tab is pressed in minibuffer window -> do completion
    ; else
    (if (string= (buffer-name) "*shell*")
        (comint-dynamic-complete) ; in a shell, use tab completion
    ; else
    (if (use-region-p)    ; tab is pressed is any other buffer -> execute with space insertion
        (indent-region-custom 4) ; region was selected, call indent-region-custom
        (insert "    ") ; else insert four spaces as expected
    )))
)

(global-set-key (kbd "<backtab>") 'untab-region)
(global-set-key (kbd "<tab>") 'tab-region)

编辑:添加了Maven代码,以检查是否处于minibuffer中,以及在特定缓冲区(例如shell)进行选项卡补全。


2
不错,被采纳的答案只适用于一行,而不是区域。 - Hello_world
1
完美。适用于区域和行。复制其他常见编辑器的功能。 - mythicalcoder

3
我对Stanley Bak的答案进行了改进。 对我来说,这个全局键绑定会干扰minibuffer完成。 因此,我也包括了minibuffer的情况。
编辑:将indent-region重命名为indent-region-custom。 indent-region与现有命令冲突,在保存时出现缩进错误(钩子为保存之前)和其他一些按键组合。
(defun indent-region-custom(numSpaces)
  (progn
    ;; default to start and end of current line
    (setq regionStart (line-beginning-position))
    (setq regionEnd (line-end-position))
    ;; if there's a selection, use that instead of the current line
    (when (use-region-p)
      (setq regionStart (region-beginning))
      (setq regionEnd (region-end))
      )

    (save-excursion ; restore the position afterwards
      (goto-char regionStart) ; go to the start of region
      (setq start (line-beginning-position)) ; save the start of the line
      (goto-char regionEnd) ; go to the end of region
      (setq end (line-end-position)) ; save the end of the line

      (indent-rigidly start end numSpaces) ; indent between start and end
      (setq deactivate-mark nil) ; restore the selected region
      )
    )
  )

(defun untab-region (N)
  (interactive "p")
  (indent-region-custom -4)
  )

(defun tab-region (N)
  (interactive "p")
  (if (active-minibuffer-window)
      (minibuffer-complete)    ; tab is pressed in minibuffer window -> do completion
    (if (use-region-p)    ; tab is pressed is any other buffer -> execute with space insertion
        (indent-region-custom 4) ; region was selected, call indent-region-custom
      (insert "    ") ; else insert four spaces as expected
      )
    )
  )

(global-set-key (kbd "<backtab>") 'untab-region)
(global-set-key (kbd "<tab>") 'tab-region)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接