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

时间:2011-01-10 02:22:57

标签: emacs lua lua-mode

在这里完成emacs新手。

我在使用emacs starter kit的Ubuntu上使用emacs 23.1.1。我主要在lua模式下工作(与package-install lua-mode一起安装)。

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

指南是:

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

示例:

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

如果我不尝试使用自动缩进对抗,我会使用emacs:

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

更新

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

如果我尝试托马斯的解决方案,我明白了:

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:

以下是我从托马斯当前版本获得的内容:

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"
            )

除非明确指出,否则我没有为缩进做任何事情,只输入代码并在每行末尾按 RETURN 。我实际上没有输入任何评论。

它应如下所示:

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:

为了完整起见,这是我在current Git HEAD of lua-mode得到的,没有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(),
}

7 个答案:

答案 0 :(得分:9)

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

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

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

local foo = function()

然后按Enter键将点移动到第二行,您可以通过键入M-: (lua-calculate-indentation)来调用上述功能。结果是15,这意味着lua-mode将第二列缩进到第15列。这就是你在原始问题中描述和例证的非正统缩进的原因。

现在,为了解决这个问题,我建议重新定义函数“lua-calculate-indentation”,以便它返回你想要的缩进。为此,将以下代码放入另外的空文件中,并将其保存在名为“my-lua.el”的“lua-mode.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之后,必须发生,否则该代码将重新安装原始缩进函数。

我们这样做的方式有点hacky:我们安装一个回调函数,每次缓冲区将其主模式更改为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的安装说明应该是这样。

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

答案 1 :(得分:3)

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

然而,GitHub上的最新版本效果很好,没有注意到任何缩进的怪异。为了符合Lua style guide,您只需将indent-tabs-mode设置为nil,将lua-indent-level设置为2

答案 2 :(得分:2)

如果您在主目录中的.emacs文件中输入以下代码,它将使lua-mode(并且只有lua-mode)的行为符合以下方式:

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

特别是后者可能不是你想要的,但也许是它的第一个近似值。

(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以使这些更改生效。

答案 3 :(得分:1)

更简洁的方法是 added in 2019,采用两个 lua-indent- 变量的形式。这让我们几乎到了那里,但由于某种原因它仍然对嵌套块进行双缩进。添加一点建议 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)

答案 4 :(得分:0)

我现在无能为力 - 我有两天的截止日期8-( - 但是 这是我在.emacs中使用的方法,使我可以使用lua-mode ...

(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

答案 5 :(得分:0)

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

因此,一个简单的解决方法是不写

本地f =功能......

本地功能...

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

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

答案 6 :(得分:-1)

我认为您所寻找的很多内容都可以在emacs manual on custom C indentation definitions中找到,这些内容属于indentation engine一般说明。

你可以做任何你能想象到的事情,这比做你想象的任何事都强烈。