簡體   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