Finding file path in current line

Vim had a great feature gf which automatically selected file path in current line and jumped to the file.

I have these three bits in my config to acheive the same thing:
smart-select-file, search-file, and gf mapping.

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.

1 Like