4d3a32c

Branches > main > 4d3a32c > files / nvim / pack / plugins / opt / conjure / dev / python / sandbox.py

Make jump and smart_n into isolated modules :)

Grahp, 2026-02-02

Commit: 4d3a32c100c6aadc9ba95af6b94f1fa61312b460
Parent: 2bb8fe1

4 changed files:

nvim/lua/jump.lua modified (view file)

@@ -1,83 +1,77 @@-local ns = vim.api.nvim_create_namespace("dev.grahp.nvim.jump")-local utils = require("utils")+--- License: 0BSD+local ns = vim.api.nvim_create_namespace("dev.grahp.nvim-jump")  --- Name meanings: --- Jump target: Somewhere you can jump to - Union of Match and table of optional Disambiguator --- Disambiguator: A third character used to differentiate jump targets when there are multiple --- Match: Union Pos and a table of Char---- Row: The number of lines into the buffer line is? (0-based?) TODO rename?+--- Row: The number of lines into the buffer line is? (0-based?) --- Col: The number of characters into the line? (1-based?) --- Pos: table of row, col --- Char: A character used for jumping, entered by the user --- Label: A hint painted to the screen to show where jump targets are, and what disambiguator you might need to press ---- ALL CAPS- --- Blocks and reads one char of user input. --- Returns the char or nil local function read_char()   local char = vim.fn.getcharstr()-  if char == "" then-    return nil-  else-    return char-  end+  return char == "" and nil or char end -local function smart_case_find_index(s, pattern, pos)-  if not pattern:match("%u") then+local function is_all_lower_case(s)+  return not s:match("%u")+end++--- Returns a sequential table of the indecies of all instances of 'subs' in 's'.+--- If 'subs' is all lower case, 's' will be search case insensitive, otherwise it will be case sensitive+local function smart_case_find_all(s, subs)+  local pos = 1+  local acc = {}++  if is_all_lower_case(subs) then     s = s:lower()   end -  local match_start, match_end = string.find(s, pattern, pos, true)-  if match_start and match_end then-    return match_end+  while true do+    local match_pos = string.find(s, subs, pos, true)+    if not match_pos then break end+    table.insert(acc, match_pos)+    pos = match_pos + 1   end+  return acc end  local function string_get(s, i)   return s:sub(i, i) end --local function lines()-  local bufnr = vim.api.nvim_get_current_buf()-  return vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)+local function get_all_buffer_lines()+  return vim.api.nvim_buf_get_lines(0, 0, -1, false) end  --- Returns all matches on the screen that start with "char". local function find_matches(char)-  local lines = lines()+  local lines = get_all_buffer_lines() -  local out = {}+  local matches = {}    local start_line = vim.fn.line("w0")   local end_line   = vim.fn.line("w$") +  --- Because jump_to() and paint_labels() are buffer-based and non screen-based when it comes to lines,+  ---  this instead gets all the lines in the buffer and filters down the lines that are actually on the screen   for row, line in ipairs(lines) do-    -- I miss filter lol     if row >= start_line and row <= end_line then-      local i = 1--      while true do-        local pos = smart_case_find_index(line, char, i)-        if not pos then-          break-        end-+      for _, pos in ipairs(smart_case_find_all(line, char)) do         local char = string_get(line, pos + 1)         if char then-          table.insert(out, {row = row,-          col = pos,

Show all 246 lines

nvim/lua/keybindings.lua modified (view file)

@@ -34,56 +34,11 @@  keymap("n", "<Esc>", "<CMD>noh<CR>") -keymap("n", "<Space>u", require("plugins.oil").open)+keymap("n", "<Space>u", function() require("plugins.oil").open() end)  keymap("n", "<Space>f", function() require("fuzzy").fuzzy_find() end) -keymap({"n", "v", "o"}, ";", function()-  local pos = require("jump").jump()-  if pos then-    vim.api.nvim_win_set_cursor(0, {pos.row, pos.col - 1})-  end-  return ""-end)+keymap({"n", "v", "o"}, ";", function() require("jump").jump() end) ---- Either nil, "f/t", or "space"---- TODO should probably be per-buffer :p-local last_n_type = nil--vim.api.nvim_create_autocmd("CmdlineLeave", {-  callback = function()-    local t = vim.fn.getcmdtype()-    if t == "/" or t == "?" then-      last_n_type = "search"-    end-  end})--for _, key in ipairs({"f", "F", "t", "T"}) do-  vim.keymap.set({"n", "x", "o"}, key, function()-    last_n_type = "f/t"-    return key-  end, {expr = true, noremap = true})-end---local function smart_n(reverse)-  if last_n_type == nil then-    return ""-  elseif last_n_type == "f/t" then-    local cs = vim.fn.getcharsearch()-    if reverse then-      return cs.forward == 1 and "," or ";"-    else-      return cs.forward == 1 and ";" or ","-    end-  elseif last_n_type == "search" then-    if reverse then-      return vim.v.searchforward == 1 and "N" or "n"-    else-      return vim.v.searchforward == 1 and "n" or "N"-    end-  end-end--vim.keymap.set({"n", "v", "o"}, "n", function() return smart_n(false) end, {expr = true, noremap = true})-vim.keymap.set({"n", "v", "o"}, "N", function() return smart_n(true) end, {expr = true, noremap = true})+keymap({"n", "v", "o"}, "n", function() return require("smart_n").smart_n(false) end, {expr = true, noremap = true})+keymap({"n", "v", "o"}, "N", function() return require("smart_n").smart_n(true) end, {expr = true, noremap = true})

nvim/lua/smart_n.lua added (view file)

@@ -0,0 +1,60 @@+--- License: 0BSD++--- In case you use something else :p+FT_MOTIONS = {"f", "F", "t", "T"}++SEARCH = "search"+FT = "f/t"+--- Holds the last type of search performed+--- Either SEARCH, FT, or nil+vim.b.last_n_type = nil++vim.api.nvim_create_autocmd("CmdlineLeave", {+  callback = function()+    local t = vim.fn.getcmdtype()+    if t == "/" or t == "?" then+      vim.b.last_n_type = SEARCH+    end+  end})++for _, key in ipairs(FT_MOTIONS) do+  vim.keymap.set({"n", "x", "o"}, key, function()+    vim.b.last_n_type = FT+    return key+  end, {expr = true, noremap = true})+end++local function smart_n(reverse, not_smart)+  if vim.b.last_n_type == nil then+    return ""+  elseif vim.b.last_n_type == FT then+    local cs = vim.fn.getcharsearch()+    if reverse then+      return (not_smart and ",") or cs.forward == 1 and "," or ";"+    else+      return (not_smart and ";") or cs.forward == 1 and ";" or ","+    end+  elseif vim.b.last_n_type == SEARCH then+    if reverse then+      return (not_smart and "N") or vim.v.searchforward == 1 and "N" or "n"+    else+      return (not_smart and "n") or vim.v.searchforward == 1 and "n" or "N"+    end+  end+end++--- Goes based on search direction which is dumb but suit yourself :p+local function not_smart_n(reverse)+  return smart_n(reverse, true)+end++--- Keybindings+-- vim.keymap.set({"n", "v", "o"}, "n", function() return smart_n(false) end, {expr = true, noremap = true})+-- vim.keymap.set({"n", "v", "o"}, "N", function() return smart_n(true) end, {expr = true, noremap = true})++--- Or lazily from another file+-- vim.keymap.set({"n", "v", "o"}, "n", function() return require("smart_n").smart_n(false) end, {expr = true, noremap = true})+-- vim.keymap.set({"n", "v", "o"}, "N", function() return require("smart_n").smart_n(true) end, {expr = true, noremap = true})++return {smart_n = smart_n,+        not_smart_n = not_smart_n}

nvim/lua/utils.lua deleted (view file)

@@ -1,9 +0,0 @@-local function seq_iterator(t)-  local i = 0-  return function()-    i = i + 1-    return t[i]-  end-end--return {seq_iterator = seq_iterator}