julienvincent / nvim-paredit

A Paredit implementation for Neovim, built using Treesitter and written in Lua.
MIT License
175 stars 9 forks source link

Feature request: Move to toplevel form #49

Open phogh opened 11 months ago

phogh commented 11 months ago

I miss the [[ and ]] features of vim-sexp to jump to the toplevel form start and end. I initially implemented a solution by iterating the api function move_to_parent_form_{start,end} used in (. It worked fine but it was neater to create new api functions move_to_root_{start,end}. The code is based on move_to_parent_form (Apologies I don't know enough treesitter and nvim lua to know if there's a better approach!):

-- Helper to get cursor pos for form edge.
local function form_node_edge_pos(form_node, direction, lang)
  local form_edges = lang.get_form_edges(form_node)
  local edge_cursor_pos = {
    form_edges[direction].range[1] + 1,
    form_edges[direction].range[2]
  }
  return edge_cursor_pos
end

local function move_to_root(direction)
  local lang = langs.get_language_api()
  local cur_node = ts.get_node_at_cursor()

  local nearest_form_node = traversal.find_nearest_form(cur_node, { lang = lang })
  if not nearest_form_node or nearest_form_node:type() == "source" then
    return
  end

  local cur_cursor_pos = vim.api.nvim_win_get_cursor(0)
  local form_node_to_move_to = nearest_form_node
  repeat
    prev_form = form_node_to_move_to
    form_node_to_move_to = lang.get_node_root(form_node_to_move_to):parent()
  until not form_node_to_move_to or
        form_node_to_move_to:type() == "source" or
        is_cursor_at_form_edge(form_node_to_move_to, direction,  
          form_node_edge_pos(prev_form, direction, lang), lang)

  form_node_to_move_to = prev_form
  move_to_form_edge(form_node_to_move_to, direction, lang)
end

function M.move_to_root_start()
  move_to_root(MOTION_DIRECTIONS.LEFT)
end

function M.move_to_root_end()
  move_to_root(MOTION_DIRECTIONS.RIGHT)
end
julienvincent commented 9 months ago

Hi, sorry for taking so long to reply here.

Thanks for your interest!

A similar category of request came in today (#53) and I want to share the comment I made there with this issue: https://github.com/julienvincent/nvim-paredit/issues/53#issuecomment-1967983091

Essentially I think this kind of motion can be solved using the existing and more language agnostic nvim-treesitter-textobjects plugin found here: https://github.com/nvim-treesitter/nvim-treesitter-textobjects?tab=readme-ov-file#text-objects-move.

Let me know what you think.