Emacs适用于Python的批量缩进

问题:Emacs适用于Python的批量缩进

如果我想在代码块中添加try / except,则在Emacs中使用Python,我经常发现我必须逐行缩进整个代码块。在Emacs中,如何立即缩进整个块。

我不是经验丰富的Emacs用户,但是发现它是通过ssh工作的最佳工具。我在命令行(Ubuntu)上使用Emacs,而不是作为gui,如果有什么不同的话。

Working with Python in Emacs if I want to add a try/except to a block of code, I often find that I am having to indent the whole block, line by line. In Emacs, how do you indent the whole block at once.

I am not an experienced Emacs user, but just find it is the best tool for working through ssh. I am using Emacs on the command line(Ubuntu), not as a gui, if that makes any difference.


回答 0

如果您正在使用Emacs编程Python,那么您可能应该使用python-mode。使用python-mode,在标记代码块之后,

C-c >C-c C-l 将区域右移4个空格

C-c <C-c C-r 将区域向左移动4个空格

如果您需要将代码缩进两个级别,或者需要一定程度的缩编,则可以在命令前加上一个参数:

C-u 8 C-c > 将区域右移8个空格

C-u 8 C-c < 将区域向左移动8个空格

另一种选择是使用M-x indent-rigidly绑定到C-x TAB

C-u 8 C-x TAB 将区域右移8个空格

C-u -8 C-x TAB 将区域向左移动8个空格

用于文本矩形而不是文本行的矩形命令也很有用。

例如,在标记矩形区域后,

C-x r o 插入空格以填充矩形区域(有效地向右移动代码)

C-x r k 杀死矩形区域(有效地将代码向左移动)

C-x r t提示输入一个字符串来替换矩形。输入C-u 8 <space>后将输入8个空格。

PS。使用Ubuntu,要将python-mode设置为所有.py文件的默认模式,只需安装该python-mode软件包。

If you are programming Python using Emacs, then you should probably be using python-mode. With python-mode, after marking the block of code,

C-c > or C-c C-l shifts the region 4 spaces to the right

C-c < or C-c C-r shifts the region 4 spaces to the left

If you need to shift code by two levels of indention, or some arbitary amount you can prefix the command with an argument:

C-u 8 C-c > shifts the region 8 spaces to the right

C-u 8 C-c < shifts the region 8 spaces to the left

Another alternative is to use M-x indent-rigidly which is bound to C-x TAB:

C-u 8 C-x TAB shifts the region 8 spaces to the right

C-u -8 C-x TAB shifts the region 8 spaces to the left

Also useful are the rectangle commands that operate on rectangles of text instead of lines of text.

For example, after marking a rectangular region,

C-x r o inserts blank space to fill the rectangular region (effectively shifting code to the right)

C-x r k kills the rectangular region (effectively shifting code to the left)

C-x r t prompts for a string to replace the rectangle with. Entering C-u 8 <space> will then enter 8 spaces.

PS. With Ubuntu, to make python-mode the default mode for all .py files, simply install the python-mode package.


回答 1

除了默认情况下indent-region映射到C-M-\的,矩形编辑命令对Python很有用。将区域标记为正常,然后:

  • C-x r tstring-rectangle):将提示您输入要插入每行的字符;非常适合插入一定数量的空格
  • C-x r kkill-rectangle):删除矩形区域;非常适合去除压痕

您也可以C-x r yyank-rectangle),但这很少有用。

In addition to indent-region, which is mapped to C-M-\ by default, the rectangle edit commands are very useful for Python. Mark a region as normal, then:

  • C-x r t (string-rectangle): will prompt you for characters you’d like to insert into each line; great for inserting a certain number of spaces
  • C-x r k (kill-rectangle): remove a rectangle region; great for removing indentation

You can also C-x r y (yank-rectangle), but that’s only rarely useful.


回答 2

indent-region映射C-M-\应该可以解决问题。

indent-region mapped to C-M-\ should do the trick.


回答 3

我一直在使用此功能来处理缩进和缩进:

(defun unindent-dwim (&optional count-arg)
  "Keeps relative spacing in the region.  Unindents to the next multiple of the current tab-width"
  (interactive)
  (let ((deactivate-mark nil)
        (beg (or (and mark-active (region-beginning)) (line-beginning-position)))
        (end (or (and mark-active (region-end)) (line-end-position)))
        (min-indentation)
        (count (or count-arg 1)))
    (save-excursion
      (goto-char beg)
      (while (< (point) end)
        (add-to-list 'min-indentation (current-indentation))
        (forward-line)))
    (if (< 0 count)
        (if (not (< 0 (apply 'min min-indentation)))
            (error "Can't indent any more.  Try `indent-rigidly` with a negative arg.")))
    (if (> 0 count)
        (indent-rigidly beg end (* (- 0 tab-width) count))
      (let (
            (indent-amount
             (apply 'min (mapcar (lambda (x) (- 0 (mod x tab-width))) min-indentation))))
        (indent-rigidly beg end (or
                                 (and (< indent-amount 0) indent-amount)
                                 (* (or count 1) (- 0 tab-width))))))))

然后将其分配给键盘快捷键:

(global-set-key (kbd "s-[") 'unindent-dwim)
(global-set-key (kbd "s-]") (lambda () (interactive) (unindent-dwim -1)))

I’ve been using this function to handle my indenting and unindenting:

(defun unindent-dwim (&optional count-arg)
  "Keeps relative spacing in the region.  Unindents to the next multiple of the current tab-width"
  (interactive)
  (let ((deactivate-mark nil)
        (beg (or (and mark-active (region-beginning)) (line-beginning-position)))
        (end (or (and mark-active (region-end)) (line-end-position)))
        (min-indentation)
        (count (or count-arg 1)))
    (save-excursion
      (goto-char beg)
      (while (< (point) end)
        (add-to-list 'min-indentation (current-indentation))
        (forward-line)))
    (if (< 0 count)
        (if (not (< 0 (apply 'min min-indentation)))
            (error "Can't indent any more.  Try `indent-rigidly` with a negative arg.")))
    (if (> 0 count)
        (indent-rigidly beg end (* (- 0 tab-width) count))
      (let (
            (indent-amount
             (apply 'min (mapcar (lambda (x) (- 0 (mod x tab-width))) min-indentation))))
        (indent-rigidly beg end (or
                                 (and (< indent-amount 0) indent-amount)
                                 (* (or count 1) (- 0 tab-width))))))))

And then I assign it to a keyboard shortcut:

(global-set-key (kbd "s-[") 'unindent-dwim)
(global-set-key (kbd "s-]") (lambda () (interactive) (unindent-dwim -1)))

回答 4

我是Emacs的新手,因此此答案可能对您毫无用处。

到目前为止,所提到的答案都没有覆盖字面量如dict或的重新缩进list。例如,如果您剪切并粘贴了以下文字并需要对其进行合理的缩进,则M-x indent-regionor或M-x python-indent-shift-rightcompany不会提供帮助:

    foo = {
  'bar' : [
     1,
    2,
        3 ],
      'baz' : {
     'asdf' : {
        'banana' : 1,
        'apple' : 2 } } }

感觉M-x indent-region应该在中做一些明智的事情python-mode,但是还不是这样。

对于将文字放在方括号中的特定情况,在相关行上使用TAB即可获得所需的内容(因为空格不起作用)。

因此,在这种情况下,我一直在快速记录键盘宏,例如<f3> C-n TAB <f4>F3,Ctrl-n(或向下箭头),TAB,F4,然后重复使用F4来应用宏可以节省几次击键。或者,您可以将C-u 10 C-x e其应用10次。

(我知道这听起来不多,但是尝试重新缩进100行垃圾文字而不丢失向下箭头,然后不得不上升5行并重复一遍;)。

I’m an Emacs newb, so this answer it probably bordering on useless.

None of the answers mentioned so far cover re-indentation of literals like dict or list. E.g. M-x indent-region or M-x python-indent-shift-right and company aren’t going to help if you’ve cut-and-pasted the following literal and need it to be re-indented sensibly:

    foo = {
  'bar' : [
     1,
    2,
        3 ],
      'baz' : {
     'asdf' : {
        'banana' : 1,
        'apple' : 2 } } }

It feels like M-x indent-region should do something sensibly in python-mode, but that’s not (yet) the case.

For the specific case where your literals are bracketed, using TAB on the lines in question gets what you want (because whitespace doesn’t play a role).

So what I’ve been doing in such cases is quickly recording a keyboard macro like <f3> C-n TAB <f4> as in F3, Ctrl-n (or down arrow), TAB, F4, and then using F4 repeatedly to apply the macro can save a couple of keystrokes. Or you can do C-u 10 C-x e to apply it 10 times.

(I know it doesn’t sound like much, but try re-indenting 100 lines of garbage literal without missing down-arrow, and then having to go up 5 lines and repeat things ;) ).


回答 5

我使用以下代码段。当选项卡处于非活动状态时,在选项卡上缩进当前行(通常如此);当选择处于非活动状态时,它将使整个区域向右缩进。

(defun my-python-tab-command (&optional _)
  "If the region is active, shift to the right; otherwise, indent current line."
  (interactive)
  (if (not (region-active-p))
      (indent-for-tab-command)
    (let ((lo (min (region-beginning) (region-end)))
          (hi (max (region-beginning) (region-end))))
      (goto-char lo)
      (beginning-of-line)
      (set-mark (point))
      (goto-char hi)
      (end-of-line)
      (python-indent-shift-right (mark) (point)))))
(define-key python-mode-map [remap indent-for-tab-command] 'my-python-tab-command)

I use the following snippet. On tab when the selection is inactive, it indents the current line (as it normally does); when the selection is inactive, it indents the whole region to the right.

(defun my-python-tab-command (&optional _)
  "If the region is active, shift to the right; otherwise, indent current line."
  (interactive)
  (if (not (region-active-p))
      (indent-for-tab-command)
    (let ((lo (min (region-beginning) (region-end)))
          (hi (max (region-beginning) (region-end))))
      (goto-char lo)
      (beginning-of-line)
      (set-mark (point))
      (goto-char hi)
      (end-of-line)
      (python-indent-shift-right (mark) (point)))))
(define-key python-mode-map [remap indent-for-tab-command] 'my-python-tab-command)

回答 6

交互进行缩进。

  1. 选择要缩进的区域。
  2. Cx TAB
  3. 使用箭头(<-->)进行交互缩进。
  4. Esc完成所需的缩进后,按三次。

从我的文章中复制:在Emacs中缩进几行

Do indentation interactively.

  1. Select the region to be indented.
  2. C-x TAB.
  3. Use arrows (<- and ->) to indent interactively.
  4. Press Esc three times when you are done with the required indentation.

Copied from my post in: Indent several lines in Emacs


回答 7

我普遍做这样的事情

;; intent whole buffer 
(defun iwb ()
  "indent whole buffer"
  (interactive)
  ;;(delete-trailing-whitespace)
  (indent-region (point-min) (point-max) nil)
  (untabify (point-min) (point-max)))

I do something like this universally

;; intent whole buffer 
(defun iwb ()
  "indent whole buffer"
  (interactive)
  ;;(delete-trailing-whitespace)
  (indent-region (point-min) (point-max) nil)
  (untabify (point-min) (point-max)))