Как настроить отступ в emacs lua-mode? - PullRequest
18 голосов
/ 10 января 2011

Завершите emacs newbie здесь.

Я использую emacs 23.1.1 в Ubuntu с стартовым набором emacs .В основном я работаю в режиме 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 имеет отступ tab и четыре пробела.Не совсем работает ...

Обновление 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:

Ради полноты вот что я получаю с текущий Git HEAD из lua-mode , без настройки конфигурации Томаса:

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(),
}

Ответы [ 6 ]

9 голосов
/ 11 января 2011

Хорошо, давайте попробуем еще раз ... После просмотра исходного кода lua-mode я пришел к следующему подходу.

Причиной столь странного отступа по умолчанию являетсяфункция с именем "lua-Calculate-Indentation", которая вычисляет столбец, для которого нужно сделать отступ для текущей строки.К сожалению, возвращаемые им значения не соответствуют желаемой спецификации.

Например, если вы введете одну строку в новый файл .lua, например, такой:

local foo = function()

и нажметевведите, чтобы переместить точку на вторую строку, вы можете вызвать вышеуказанную функцию, набрав 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))

ThisКод устанавливает уровень отступа в два пробела (вместо 3), изменяет регулярное выражение, которое определяет, растягивается ли оператор на несколько строк, и, наконец, переопределяет функцию отступа с помощью вспомогательного элемента.

Все, что осталось сделать, этоубедитесь, что этот код действительно загружен.Это должно произойти после загрузки оригинального lua-режима, иначе этот код переустановит оригинальную функцию отступа.

То, как мы это делаем, немного хакерское: мы устанавливаемфункция обратного вызова, которая вызывается каждый раз, когда буфер меняет свой основной режим на режим 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.

Я надеюсь, что на этот раз у вас это получится, если нет, дайте мне знать.

3 голосов
/ 09 июня 2013

Я знаю, что прошло много времени с тех пор, как об этом спросили, но я просто хотел отметить, что это все еще проблема, с lua-mode, установленным через систему пакетов Emacs.на GitHub работает очень хорошо, не заметил каких-либо странностей с отступами.Все, что вам нужно сделать, чтобы соответствовать Руководству по стилю Lua , это установить indent-tabs-mode на nil и lua-indent-level на 2.

2 голосов
/ 10 января 2011

Если вы введете следующий код в файл .emacs в вашем домашнем каталоге, он будет вести себя в режиме lua (и только в режиме lua) следующим образом:

  • Если вы нажмете 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, чтобы эти изменения вступили в силу.

0 голосов
/ 11 января 2011

Я поддерживаю (но не являюсь автором) lua-mode.el. Поскольку я в Emacs Lisp гораздо менее бегло говорю, чем другие участники этой ветки, я приветствую исправления. Я просто хотел бы отметить, что в правилах по умолчанию нет ничего странного или неправильного: идея, насколько я понимаю, состоит в том, что когда вы находитесь в анонимной функции, отступ должен принимать ключевое слово function в качестве левое поле. Это имеет смысл, когда вы рассматриваете возможность использования выражений функций в других местах, например, в качестве параметров функции.

Итак, один простой обходной путь - не писать

local f = function ...

но

локальная функция f ...

Если, возможно, вы не работаете с версией Lua, которая предшествует синтаксису "локальной функции".

Сказав это, я понимаю, почему вы можете захотеть сделать отступ по-другому. В этом случае мне кажется разумным иметь конфигурационную переменную lua-indent-function-from-function-keyword (более подходящее имя, кто-нибудь?), И я был бы рад принять патч, который его реализовал.

0 голосов
/ 10 января 2011

Сейчас я ничем не могу помочь - у меня есть срок в два дня 8- (- но вот что я использую в своих .emacs, чтобы сделать режим lua пригодным для меня ...

(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?

Я делаю отступ в своем коде необычным способом - см. Пример ниже - и поэтому я дисциплинированно нажимаю клавишу TAB только тогда, когда lua-mode может правильно вывести правильный отступ из строк выше ...

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
0 голосов
/ 10 января 2011

Я думаю, многое из того, что вы ищете, можно найти в руководстве emacs по пользовательским определениям отступов C , которое подпадает под общее описание механизма отступов .

Вы можете заставить его делать все, что вы можете себе представить, что было бы гораздо предпочтительнее, чем просто делать то, что вы представляете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...