繁体   English   中英

如何在 emacs lua-mode 中配置缩进?

[英]How to configure indentation in emacs lua-mode?

在这里完成 emacs 新手。

我在 Ubuntu 上使用 emacs 23.1.1 和emacs starter kit 我主要在 lua 模式下工作(使用package-install lua-mode )。

我需要调整缩进的工作方式,使其符合我的编码指南。

指导方针是:

  • 制表符到空格;
  • 每个缩进两个空格;
  • 每行最多 80 个字符,没有尾随空格。

示例:

local foo = function()
  print("Hello, world!")
end

如果我不尝试与它的自动缩进作斗争,我会用 emacs 得到什么:

local foo = function()
               print("Hello, world")
end

更新:

(这属于评论,但因为需要额外的格式,所以我必须把它放在这里。)

如果我尝试 Thomas 的解决方案,我会得到:

local foo = function()
               print("Hello, world")
        end

请注意, end缩进一个制表符和四个空格。 不太行...

更新 2:

这件事也以错误的方式缩进:

local bar = foo(
    "one",
    "two",
   baz(), -- Note three spaces
   "quo"
)

应该是:

local bar = foo(
    "one",
    "two",
    baz(),
    "quo"
  )

更新 3:

错误缩进的第三种情况:

local bar = foo(
    "one",
    "two"
  )

  local t = 5 -- This line should not be indented, 
              -- also note tab between local and t.

更新 4:

以下是我从 Thomas 那里得到的当前版本:

local foo = function()
               print("Hello, world")
        end

            local bar = 5 -- Emacs put \t before 5

            local zzz = foo( -- Emacs put \t before foo
                "one", -- Pressed TAB here twice
                "two",
               three(),
               "four"
            )

除了明确指出的地方,我没有做任何缩进,只是输入代码并在每行末尾按回车键。 我实际上没有输入任何评论。

它应该如下所示:

local foo = function()
  print("Hello, world")
end

local bar = 5

local zzz = foo(
    "one",
    "two",
    three(),
    "four"
  )

更新 5:

另一个错误的缩进情况:

local foo =
{
bar(); -- Did press a TAB here, but closing brace killed it
baz;
}

应该是:

local foo =
{
  bar();
  baz;
}

更新 6:

为了完整起见,这里是我使用当前 lua-mode 的 Git HEAD 得到的,没有 Thomas 的配置调整:

local foo = function()
               print("Hello, world!")
            end

local bar = 5

local foo = bar(
bar,
   baz(),
   quo(),
aaa
)

local t =
{
"one",
two(),
}

带调谐:

local foo = function()
           print("Hello, world!")
            end

            local bar = 5

            local foo = bar(
            bar,
               baz(),
               quo(),
               aaa
            )

            local t =
            {
            "one",
            two(),
         }

为了符合我的编码指南,它应该如下所示:

local foo = function()
  print("Hello, world!")
end

local bar = 5

local foo = bar(
    bar,
    baz(),
    quo(),
    aaa
  )

local t =
{
  "one",
  two(),
}

好吧,让我们再试一次…… 浏览了 lua-mode 的源代码后,我想出了以下方法。

公认奇怪的默认缩进的原因是一个名为“lua-calculate-indentation”的函数,它计算当前行缩进的列。 不幸的是,它返回的值与您想要的规格不匹配。

例如,如果您在新的 .lua 文件中输入一行,如下所示:

local foo = function()

并按回车键将点移动到第二行,您可以通过键入M-: (lua-calculate-indentation)来调用上述函数。 结果是 15,这意味着 lua-mode 会将第二个缩进到第 15 列。这就是您在原始问题中描述和举例说明的非正统缩进的原因。

现在,为了解决这个问题,我建议重新定义函数“lua-calculate-indentation”,以便它返回您想要的缩进。 为此,将以下代码放入一个空文件中,并将其保存在“lua-mode.el”所在目录中的“my-lua.el”名称下。

;; use an indentation width of two spaces
(setq lua-indent-level 2)

;; Add dangling '(', remove '='
(setq lua-cont-eol-regexp
      (eval-when-compile
        (concat
         "\\((\\|\\_<"
         (regexp-opt '("and" "or" "not" "in" "for" "while"
                       "local" "function") t)
         "\\_>\\|"
         "\\(^\\|[^" lua-operator-class "]\\)"
         (regexp-opt '("+" "-" "*" "/" "^" ".." "==" "<" ">" "<=" ">=" "~=") t)
         "\\)"
         "\\s *\\=")))

(defun lua-calculate-indentation (&optional parse-start)
  "Overwrites the default lua-mode function that calculates the
column to which the current line should be indented to."
  (save-excursion
    (when parse-start
      (goto-char parse-start))

    ;; We calculate the indentation column depending on the previous
    ;; non-blank, non-comment code line. Also, when the current line
    ;; is a continuation of that previous line, we add one additional
    ;; unit of indentation.
    (+ (if (lua-is-continuing-statement-p) lua-indent-level 0)
       (if (lua-goto-nonblank-previous-line)
           (+ (current-indentation) (lua-calculate-indentation-right-shift-next))
         0))))

(defun lua-calculate-indentation-right-shift-next (&optional parse-start)
  "Assuming that the next code line is not a block ending line,
this function returns the column offset that line should be
indented to with respect to the current line."
  (let ((eol)
        (token)
        (token-info)
        (shift 0))
    (save-excursion
      (when parse-start
        (goto-char parse-start))

      ; count the balance of block-opening and block-closing tokens
      ; from the beginning to the end of this line.
      (setq eol (line-end-position))
      (beginning-of-line)
      (while (and (lua-find-regexp 'forward lua-indentation-modifier-regexp)
                  (<= (point) eol)
                  (setq token (match-string 0))
                  (setq token-info (assoc token lua-block-token-alist)))
        ; we found a token. Now, is it an opening or closing token?
        (if (eq (nth 2 token-info) 'open)
            (setq shift (+ shift lua-indent-level))
          (when (or (> shift 0)
                    (string= token ")"))
            (setq shift (- shift lua-indent-level))))))
    shift))

这段代码将缩进级别设置为两个空格(而不是 3 个),修改一个正则表达式来检测语句是否延伸到多行,最后使用辅助函数重新定义缩进函数。

剩下要做的就是确保实际加载此代码。 这必须加载原始 lua-mode之后发生,否则该代码将重新安装原始缩进功能。

我们这样做的方式有点棘手:我们安装了一个回调函数,每次缓冲区将其主要模式更改为 lua 模式时都会调用该函数。 然后它检查是否定义了前面提到的辅助函数——如果没有,它加载“my-lua.el”。 这有点脆弱,但只要你不玩 lua 源代码,你应该没问题。

将以下行添加到您的 ~/emacs.d/agladysh.el 文件(假设“agladysh”是您的用户名):

(add-hook 'lua-mode-hook 
          (lambda () (unless (fboundp 'lua-calculate-indentation-right-shift-next)
                       (load-file (locate-file "my-lua.el" load-path)))))

我假设 lua-mode 在你的加载路径上,如果你遵循 lua-mode 的安装说明,它应该是。

我希望这次它对你有用,如果没有,请告诉我。

我知道自从问这个问题已经有一段时间了,但我只想指出这仍然是一个问题,lua-mode 是通过 Emacs 包系统安装的。

但是, GitHub 上的最新版本运行良好,没有发现任何缩进异常。 为了符合Lua 风格指南,你所要做的就是将indent-tabs-modenil并将lua-indent-level2

如果您在主目录中的.emacs文件中输入以下代码,它将使 lua-mode(并且仅 lua-mode)表现如下:

  • 如果按 ENTER,将插入一个换行符,默认情况下下一行将像上一行一样缩进。
  • 每当您按 TAB 缩进该行时,point 要么跳转到该行的第一个非空白字符,要么,如果该行为空,point 已在该字符处,则插入两个空格。

尤其是后者可能不是您想要的,但可能是第一个近似值。

(defvar my-lua-indent 2
  "The number of spaces to insert for indentation")

(defun my-lua-enter ()
  "Inserts a newline and indents the line like the previous
non-empty line."
  (interactive)
  (newline)
  (indent-relative-maybe))

(defun my-lua-indent ()
  "Moves point to the first non-whitespace character of the
line if it is left of it. If point is already at that
position, or if it is at the beginning of an empty line,
inserts two spaces at point."
  (interactive)
  (when (looking-back "^\\s *")
    (if (looking-at "[\t ]")
        (progn (back-to-indentation)
               (when (looking-at "$")
                 (kill-line 0)
                 (indent-relative-maybe)
                 (insert (make-string my-lua-indent ? ))))
      (insert (make-string my-lua-indent ? )))))

(defun my-lua-setup ()
  "Binds ENTER to my-lua-enter and configures indentation the way
I want it. Makes sure spaces are used for indentation, not tabs."
  (setq indent-tabs-mode nil)
  (local-set-key "\r" 'my-lua-enter)
  (setq indent-line-function 'my-lua-indent))

;; add `my-lua-setup' as a call-back that is invoked whenever lua-mode
;; is activated.
(add-hook 'lua-mode-hook 'my-lua-setup)

重新启动 Emacs 以使这些更改生效。

2019添加了一种更lua-indent- ,以两个lua-indent- variables 的形式。 这让我们几乎到了那里,但由于某种原因它仍然对嵌套块进行双缩进。 添加一点建议 hack 即可完成工作。

(setq lua-indent-nested-block-content-align nil)
(setq lua-indent-close-paren-align nil)

(defun lua-at-most-one-indent (old-function &rest arguments)
  (let ((old-res (apply old-function arguments)))
    (if (> old-res lua-indent-level) lua-indent-level old-res)))

(advice-add #'lua-calculate-indentation-block-modifier
            :around #'lua-at-most-one-indent)

我现在帮不上什么忙 - 我有两天的最后期限 8-( - 但这是我在我的 .emacs 中使用的使 l​​ua 模式对我可用的东西......

(setq lua-indent-level 2)
(setq lua-electric-flag nil)
(defun lua-abbrev-mode-off () (abbrev-mode 0))
(add-hook 'lua-mode-hook 'lua-abbrev-mode-off)
(setq save-abbrevs nil)   ;; is this still needed?

我以一种不寻常的方式缩进了我的代码 - 请参阅下面的示例 - 所以我训练自己只有在 lua-mode 可以从上面的行中正确推断出正确的缩进时才按 TAB ......

map = function (f, A, n)
    local B = {}                 -- TAB here doesn't work
    for i=1,(n or #A) do         -- TAB here works
      table.insert(B, f(A[i]))   -- TAB here works
    end                          -- TAB here works
    return B                     -- TAB here works
  end                            -- TAB here works

我是 lua-mode.el 的维护者(但不是作者)。 由于与此线程的其他贡献者相比,我对 Emacs Lisp 的熟练程度要低得多,因此我欢迎补丁。 我只想指出,默认规则没有任何奇怪或不正确的地方:据我所知,这个想法很简单,当你在匿名函数中时,缩进应该将 function 关键字作为它的左边距。 当您考虑在其他地方使用函数表达式时,这很有意义,例如作为函数参数。

因此,一种简单的解决方法是不要编写

局部 f = 函数...

但是

局部函数 f...

除非您使用的 Lua 版本早于“本地函数”语法。

话虽如此,我可以理解为什么您可能想要以不同的方式缩进。 在这种情况下,我认为有一个配置变量 lua-indent-function-from-function-keyword (更好的名字,有人吗?),我很乐意接受一个实现它的补丁。

我认为您正在寻找的很多内容都可以在关于自定义 C 缩进定义emacs 手册中找到,这些定义属于一般缩进引擎描述。

你可以让它做任何你能想象的事情,这比做任何你想象的事情都要好得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM