I’m pretty satisfied with latter two bits. find-file works really well for me, and the mapping is fine.
But the smart-select-file function is not ideal:
try %{
execute-keys "<a-k>..<ret>"
} catch %{
# guess we have nonblank character under cursor
execute-keys "<a-k>\w<ret>"
execute-keys "<a-i><a-w>"
} catch %{
# try selecting inside first occurrence of <...> string
execute-keys "<a-x>s<<ret>)<space>"
execute-keys "<a-i>a"
} catch %{
# try selecting inside first occurrence of "..."
execute-keys '<a-x>s"<ret>)<space>'
execute-keys "<a-i>Q"
} catch %{
# try selecting inside first occurrence of '...'
execute-keys "<a-x>s'<ret>)<space>"
execute-keys "<a-i>q"
} catch %{
# try select from cursor to the end of the line
execute-keys "<a-l><a-k>\w<ret>"
} catch %{
# try select from beginning to the end of the line
execute-keys "Gi<a-l><a-k>\w<ret>"
} catch %{
fail "no file can be selected"
}
try %{
execute-keys "s/?\w[\S]+(?!/)<ret>)<space>"
} catch %{
fail "failed to select file"
}
It continuously tries to select file in current line by trying different patterns, and it works, but this isn’t really searching for a path. Vim had really good guessing code, that could extract path from quotes, if it is quoted, and other interesting things.
I’ve tried to avoid shell expansions here, to make it more robust, and used only execute-keys and try catch to do conditional testing. Any recommendation on how I could improve the smart-select-file function intelligence?
} catch %{
# try selecting inside first occurrence of "..."
execute-keys '<a-x>s"<ret>)<space>'
execute-keys "<a-i>Q"
} catch %{
# try selecting inside first occurrence of '...'
execute-keys "<a-x>s'<ret>)<space>"
execute-keys "<a-i>q"
}
This part reminds me of an old experiment I tried once.
In JavaScript, there’s 3 ways to make strings: 'single-quote strings', "double-quote strings" and `back-quote strings`.
But most of the time while editing, you just want to select a string, regardless of the type of quotes. (I wish this behavior was built-into Kakoune)
This is the command I ended up with:
define-command select-quote %{
# save original
execute-keys '"oZ'
# save simple and back to original
try %{
execute-keys '<a-i>q"sZ'
}
execute-keys '"oz'
# save double and back to original
try %{
execute-keys '<a-i>Q"dZ'
}
execute-keys '"oz'
# save grave and back to original
try %{
execute-keys '<a-i>g"gZ'
}
execute-keys '"oz'
try %{
# sdg
execute-keys '"sz'
execute-keys '"d<a-z>-'
execute-keys '"g<a-z>-'
} catch %{
# sd
execute-keys '"sz'
execute-keys '"d<a-z>-'
} catch %{
# sg
execute-keys '"sz'
execute-keys '"g<a-z>-'
} catch %{
# dg
execute-keys '"dz'
execute-keys '"g<a-z>-'
} catch %{
# s
execute-keys '"sz'
} catch %{
# d
execute-keys '"dz'
} catch %{
# g
execute-keys '"gz'
} catch %{
# reset
execute-keys '"oz'
}
echo
}
Unfortunately this snippet does not really help to simplify your code, but I just wanted to share with you that I’m also often trapped in the try/catch dance.
As an exercise I tried to implement the same functionality without catch statements (may not be identical in all circumstances).
define-command -docstring "all-string-select: selects any quote type."\
all-string-select %{
# save original position for future selections.
execute-keys '"oZ'
# save original position to our 'final' register. Acts as default.
execute-keys '"fZ'
# save the whole buffer to the comparison register.
execute-keys '%"sZ'
try %{
# try and select small quote block. If successful is saved to comparison & final.
execute-keys '"oz<a-i>q"sZ"fZ'
}
try %{
# try and select double quote block.
execute-keys '"oz<a-i>Q'
# compare to previous largest selection and save smallest to comparison & final.
# EDIT - "s<a-z>-"sZ can be replaced with "s<a-Z>-
execute-keys '"s<a-z>-"sZ"fZ'
}
try %{
# repeat for grave marker
execute-keys '"oz<a-i>g'
execute-keys '"s<a-z>-"fZ'
}
# get the smallest quote object (or original cursor)
execute-keys '"fz'
echo
}
It has the benefit of scaling better if you wanted to add more checks because you perform them as you go rather than at the end, meaning you don’t have to try every option.
The approach might be applicable to andrey’s problem by doing something like
Select the smallest of
x
<a-i><a-w>
<a-i>q
<a-i>Q
<a-i>a
<a-i>g
But you end up with a function that takes get the object under the cursor rather than in the current line since <a-i>q !== "<a-x>s'<ret>)<space><a-i>q"