Okay, let's give this another try... After browsing through the source code of lua-mode, I've come up with the following approach.
The reason for the admittedly strange default indentation is a function called "lua-calculate-indentation" which computes the column to which to indent the current line. Unfortunately, the values returned by it do not match your desired specification.
For instance, if you enter a single line into a fresh .lua file like this one:
local foo = function()
and hit enter to move the point to the second line, you can invoke the above function by typing M-: (lua-calculate-indentation)
. The result is 15, which means that lua-mode will indent the second to column 15. This is the reason for the unorthodox indentation you've described and exemplified in your original question.
Now, to fix this I suggest re-defining the function "lua-calculate-indentation" so that it returns the indentation you want. For this, put the following code into an otherwise empty file, and save it under the name "my-lua.el" in the same directory where "lua-mode.el" lives.
;; 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 code sets the indentation level to two spaces (instead of 3), modifies a regular expression that detects if a statement stretches over multiple lines, and finally redefines the indentation function using an auxiliary.
All that's left to do is make sure this code is actually loaded. That must happen after the original lua-mode is loaded, or else that code would re-install the original indentation function.
The way we do that here is a little hacky: we install a call-back function that is invoked each time a buffer changes its major-mode to lua-mode. It then checks if the auxiliary function mentioned before is defined - if not, it loads "my-lua.el". That is a little fragile, but as long as you don't play around with the lua source code, you should be fine.
Add the following lines to your ~/emacs.d/agladysh.el file (assuming that "agladysh" is your username):
(add-hook 'lua-mode-hook
(lambda () (unless (fboundp 'lua-calculate-indentation-right-shift-next)
(load-file (locate-file "my-lua.el" load-path)))))
I assume that lua-mode is on your load-path which it should be if you followed lua-mode's installation instructions.
I hope that it works for you this time, if not, let me know.
Here is an improved version that works for Windows and Unix paths and also handles files without dots (or files with multiple dots):
= string.match([[/mnt/tmp/myfile.txt]], "(.-)([^\\/]-%.?([^%.\\/]*))$")
"/mnt/tmp/" "myfile.txt" "txt"
= string.match([[/mnt/tmp/myfile.txt.1]], "(.-)([^\\/]-%.?([^%.\\/]*))$")
"/mnt/tmp/" "myfile.txt.1" "1"
= string.match([[c:\temp\test\myfile.txt]], "(.-)([^\\/]-%.?([^%.\\/]*))$")
"c:\\temp\\test\\" "myfile.txt" "txt"
= string.match([[/test.i/directory.here/filename]], "(.-)([^\\/]-%.?([^%.\\/]*))$")
"/test.i/directory.here/" "filename" "filename"
Best Answer
You could use
The
.*
is greedy so it chews up as much as it can before it matches (in this case, it chews up all the earlier matches and gives you the last).Or if you really wanted, you could reverse your string and (sort of) your pattern too, but I think it's better to rely on the greedy
.*
:P