immerrr / lua-mode

Emacs major mode for editing Lua
http://immerrr.github.io/lua-mode
GNU General Public License v3.0
319 stars 74 forks source link

lua-find-matching-token-word get wrong position #144

Open twlz0ne opened 6 years ago

twlz0ne commented 6 years ago

Steps to reproduce

(with-temp-buffer
  (insert "\
local x = function() return {{}} end

if true then
   if false then
      return 0
   end
   return 1
end")
  (lua-mode)
  (goto-char (point-max))
  (lua-find-matching-token-word "end" 'backward)
  (buffer-substring-no-properties (point-min) (point)))

Expected

"local x = function() return {{}} end
if true "

;; --- or ---

"local x = function() return {{}} end
"

Actual

"local x = "

Evironment

immerrr commented 6 years ago

Hi! Good catch, and an even better bugreport, thank you! I'll try to have a look this week.

immerrr commented 5 years ago

Apologies for the Valve-time-ish "this week" delay.

lua-find-matching-token-word function is meant to be internal-ish. It expects point to be at the beginning of the token whose pair you are trying to find to disambiguate situations like (with | being point)

{{    }|}   -- which close-brace are you trying to match, the first or the second one?

In this case point is beyond the closing end and thus the if-if-end-end block is skipped and then it tries to find a matching token that precedes them and fails to do so stopping at local for no specific reason.

I'll add the necessary documentation, but could you elaborate how did you end up using that lua-find-matching-token-word directly?

twlz0ne commented 5 years ago

Currently, I can forward step by step from <0> to <1> to <2> by (lua-forward-sexp) / (lua-find-matching-token-word "function" 'forward):

local x = <0>function() return {{}} end<1>

function foobar() end<2>

But how can I backward step by step from <2> to <1> to <0>? The (lua-find-matching-token-word "end" 'backward) straight from <2> to <0>, the <1> was skipped.

immerrr commented 5 years ago

Sorry that this went under my radar for so long. To answer your question, as I said, lua-find-matching-token-word expects point to be at the beginning of the token whose counterpart you want to find.

In your example to get to point <A> and <B> from their respective end, you need your point to be at point <A'> and <B'> respectively


local x = <A>function() return {{}} <A'>end

<B>function foobar() <B'>end

I know it is a bit counter-intuitive. Back in the day I remembered it as "it starts at the beginning of the open/close token and goes past the corresponding close token". It is not very user-friendly that

<X>function foobar() <Y>end<Z>

forward from X means Z and to go backward to X you need to go from Y, but it was not meant as a direct replacement for forward/backward-sexp functions that maintain that nice stability when hopping forward and backward.