Skip to content

Commit

Permalink
Merge pull request #65 from Isrothy/focus
Browse files Browse the repository at this point in the history
Focus
  • Loading branch information
Isrothy authored Aug 7, 2024
2 parents 76a521b + 1ddf896 commit cac6655
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 22 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
![GitHub language count](https://img.shields.io/github/languages/count/Isrothy/neominimap.nvim)
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/Isrothy/neominimap.nvim)


## Overview

This plugin provides a visual representation of your code structure on the side
Expand Down Expand Up @@ -128,6 +127,9 @@ vim.g.neominimap = {
-- minimap is refreshed after a certain delay
-- Set the delay in milliseconds
delay = 200,

-- Sync the cursor position with the minimap
sync_cursor = true,

-- Z-index for the floating window
z_index = 1,
Expand Down Expand Up @@ -226,6 +228,8 @@ Notice that a minimap is shown if and only if
| `Neominimap winOff [window_list]` | Disable the minimap for specified windows. If no windows are specified, disable for the current window. | Optional: List of windows |
| `Neominimap winToggle [window_list]` | Toggle the minimap for specified windows. If no windows are specified, toggle for the current window. | Optional: List of windows |
| `Neominimap winRefresh [window_list]` | Refresh the minimap for specified windows. If no windows are specified, refresh for the current window. | Optional: List of windows |
| `Neominimap focus` | Focus on the minimap. Set cursor to the minimap window. | None |
| `Neominimap blur` | Unfocus the minimap. Set cursor back. | None |

### Usage Examples

Expand Down Expand Up @@ -265,6 +269,8 @@ These are the corresponding commands in the Lua API.
| `Neominimap winOff [args]` | Turns off the minimap for specified windows. | `require('neominimap').winOff({"3", "4"})` |
| `Neominimap winToggle [args]` | Toggles the minimap for specified windows. | `require('neominimap').winToggle({"3", "4"})` |
| `Neominimap winRefresh [args]` | Refreshes the minimap for specified windows. | `require('neominimap').winRefresh({"3", "4"})` |
| `Neominimap focus` | Focuses the minimap. | `require('neominimap').focus()` |
| `Neominimap unfocus` | Unfocuses the minimap. | `require('neominimap').unfocus()` |`

## How it works

Expand Down
12 changes: 12 additions & 0 deletions lua/neominimap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,22 @@ M.winRefresh = function(args, opts)
require("neominimap.command.window").subcommand_tbl.winRefresh.impl(args, opts)
end

---@param args string[]
---@param opts table
M.perf = function(args, opts)
require("neominimap.command.perf").subcommand_tbl.perf.impl(args, opts)
end

---@param args string[]
---@param opts table
M.focus = function(args, opts)
require("neominimap.command.focus").subcommand_tbl.focus.impl(args, opts)
end

M.unfocus = function(args, opts)
require("neominimap.command.focus").subcommand_tbl.unfocus.impl(args, opts)
end

M.setup = function()
local gid = api.nvim_create_augroup("Neominimap", { clear = true })

Expand Down
22 changes: 18 additions & 4 deletions lua/neominimap/autocmds.lua
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,23 @@ M.create_autocmds = function()
logger.log(string.format("Window ID: %d", winid), vim.log.levels.TRACE)
vim.schedule(function()
local window = require("neominimap.window")
logger.log(string.format("Refreshing minimap for window %d.", winid), vim.log.levels.TRACE)
window.reset_cursor_line(winid)
logger.log(string.format("Minimap refreshed for window %d.", winid), vim.log.levels.TRACE)
if window.is_minimap_window(winid) then
if config.sync_cursor then
logger.log(
string.format("Resetting parent cursor line for minimap window %d.", winid),
vim.log.levels.TRACE
)
window.reset_parent_window_cursor_line(winid)
logger.log(
string.format("Parent cursor line reset for window %d.", winid),
vim.log.levels.TRACE
)
end
else
logger.log(string.format("Resettting cursor line for window %d.", winid), vim.log.levels.TRACE)
window.reset_mwindow_cursor_line(winid)
logger.log(string.format("Cursor line reset for window %d.", winid), vim.log.levels.TRACE)
end
end)
end,
})
Expand Down Expand Up @@ -198,7 +212,7 @@ M.create_autocmds = function()
end
for _, winid in ipairs(updated_windows) do
logger.log(string.format("Refreshing minimap for window %d.", winid), vim.log.levels.TRACE)
window.reset_cursor_line(winid)
window.reset_mwindow_cursor_line(winid)
logger.log(string.format("Minimap refreshed for window %d.", winid), vim.log.levels.TRACE)
end
end)
Expand Down
27 changes: 27 additions & 0 deletions lua/neominimap/command/focus.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local api = vim.api
local window = require("neominimap.window")
local logger = require("neominimap.logger")

local M = {}

---@type table<string, Neominimap.Subcommand>
M.subcommand_tbl = {
focus = {
impl = function(args, opts)
local winid = api.nvim_get_current_win()
if not window.focus(winid) then
logger.notify("Minimap can not be focused for current window", vim.log.levels.ERROR)
end
end,
},
unfocus = {
impl = function(args, opts)
local winid = api.nvim_get_current_win()
if not window.unfocus(winid) then
logger.notify("Minimap can not be unfocused for current window", vim.log.levels.ERROR)
end
end,
},
}

return M
3 changes: 2 additions & 1 deletion lua/neominimap/command/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ M.subcommand_tbl = vim.tbl_deep_extend(
require("neominimap.command.window").subcommand_tbl,
require("neominimap.command.buffer").subcommand_tbl,
require("neominimap.command.global").subcommand_tbl,
require("neominimap.command.perf").subcommand_tbl
require("neominimap.command.perf").subcommand_tbl,
require("neominimap.command.focus").subcommand_tbl
)

return M
1 change: 1 addition & 0 deletions lua/neominimap/config/internal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ M.default_config = {
minimap_width = 20, ---@type integer
x_multiplier = 4, ---@type integer
y_multiplier = 1, ---@type integer
sync_cursor = true, ---@type boolean
delay = 200, ---@type integer
diagnostic = {
enabled = true, ---@type boolean
Expand Down
1 change: 1 addition & 0 deletions lua/neominimap/config/meta.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ local M = {}
---@field minimap_width? integer
---@field x_multiplier? integer
---@field y_multiplier? integer
---@field sync_cursor? boolean
---@field delay? integer
---@field diagnostic? Neominimap.DiagnosticConfig
---@field treesitter? Neominimap.TreesitterConfig
Expand Down
56 changes: 42 additions & 14 deletions lua/neominimap/map/coord.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,69 @@ local braille_chars = ""

local braille_codes = vim.fn.str2list(braille_chars)

--- @param bitmap integer
--- @return string
---@param bitmap integer
---@return string
M.bitmap_to_code = function(bitmap)
return braille_codes[bitmap + 1]
end

--- @param y integer
--- @param x integer
--- @return integer
---@param y integer
---@param x integer
---@return integer
M.map_point_to_flag = function(y, x)
local relRow = bit.band(y, 3)
local relCol = bit.band(x, 1)
return bit.lshift(1, bit.bor(relRow, relCol * 4))
end

--- @param y integer
--- @param x integer
--- @return integer ...
---@param y integer
---@param x integer
---@return integer
---@return integer
M.map_point_to_mcodepoint = function(y, x)
return bit.rshift(y, 2) + 1, bit.rshift(x, 1) + 1
end

--- @param row integer
--- @param col integer
--- @return integer ...
---@param y integer
---@param x integer
---@return integer
---@return integer
M.map_point_to_codepoint = function(y, x)
return y * config.y_multiplier + 1, x * config.x_multiplier + 1
end

---@param mrow integer
---@param mcol integer
---@return integer
---@return integer
M.mcodepoint_to_map_point = function(mrow, mcol)
return bit.lshift(mrow - 1, 2), bit.lshift(mcol - 1, 1)
end

---@param row integer
---@param col integer
---@return integer
---@return integer
M.codepoint_to_map_point = function(row, col)
return math.floor((row - 1) / config.y_multiplier), math.floor((col - 1) / config.x_multiplier)
end

--- @param row integer
--- @param col integer
--- @return integer ...
---@param row integer
---@param col integer
---@return integer
---@return integer
M.codepoint_to_mcodepoint = function(row, col)
local y, x = M.codepoint_to_map_point(row, col)
return M.map_point_to_mcodepoint(y, x)
end

---@param mrow integer
---@param mcol integer
---@return integer
---@return integer
M.mcodepoint_to_codepoint = function(mrow, mcol)
local y, x = M.mcodepoint_to_map_point(mrow, mcol)
return M.map_point_to_codepoint(y, x)
end

return M
71 changes: 69 additions & 2 deletions lua/neominimap/window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ M.get_minimap_winid = function(winid)
return mwinid
end

---@param mwinid integer
---@return integer?
M.get_parent_winid = function(mwinid)
for winid, mwinid_ in pairs(winid_to_mwinid) do
if mwinid_ == mwinid then
return winid
end
end
return nil
end

--- Set the winid of the minimap attached to the given window
---@param winid integer
---@param mwinid integer?
Expand All @@ -83,6 +94,12 @@ M.list_windows = function()
return vim.tbl_keys(winid_to_mwinid)
end

---@param mwinid integer
---@return boolean
M.is_minimap_window = function(mwinid)
return M.get_parent_winid(mwinid) ~= nil
end

---@param winid integer
---@return boolean
M.should_show_minimap = function(winid)
Expand Down Expand Up @@ -250,7 +267,7 @@ end

---@param winid integer
---@return boolean
M.reset_cursor_line = function(winid)
M.reset_mwindow_cursor_line = function(winid)
logger.log(string.format("Resetting cursor line for window %d", winid), vim.log.levels.TRACE)
local mwinid = M.get_minimap_winid(winid)
if not mwinid then
Expand All @@ -270,6 +287,56 @@ M.reset_cursor_line = function(winid)
return false
end

---@param mwinid integer
---@return boolean
M.reset_parent_window_cursor_line = function(mwinid)
logger.log(string.format("Resetting cursor line for minimap window %d", mwinid), vim.log.levels.TRACE)
local winid = M.get_parent_winid(mwinid)
if not winid then
logger.log("Window not found", vim.log.levels.TRACE)
return false
end
local rowCol = vim.api.nvim_win_get_cursor(mwinid)
local row = rowCol[1]
local col = rowCol[2]
row, col = coord.mcodepoint_to_codepoint(row, col)
local bufnr = api.nvim_win_get_buf(winid)
local line_cnt = api.nvim_buf_line_count(bufnr)
if row <= line_cnt then
vim.schedule_wrap(util.noautocmd(vim.api.nvim_win_set_cursor))(winid, { row, 0 })
end
logger.log(string.format("Cursor line reset for minimap window %d", mwinid), vim.log.levels.TRACE)
return false
end

---@param winid integer
---@return boolean
M.focus = function(winid)
logger.log(string.format("Focusing window %d", winid), vim.log.levels.TRACE)
local mwinid = M.get_minimap_winid(winid)
if not mwinid then
logger.log(string.format("Minimap window %d is not valid", winid), vim.log.levels.TRACE)
return false
end
api.nvim_set_current_win(mwinid)
logger.log(string.format("Window %d focused", winid), vim.log.levels.TRACE)
return true
end

--- @param mwinid integer
--- @return boolean
M.unfocus = function(mwinid)
logger.log(string.format("Unfocusing window %d", mwinid), vim.log.levels.TRACE)
local winid = M.get_parent_winid(mwinid)
if not winid then
logger.log("Window not found", vim.log.levels.TRACE)
return false
end
api.nvim_set_current_win(winid)
logger.log(string.format("Window %d unfocused", mwinid), vim.log.levels.TRACE)
return true
end

--- Refresh the minimap attached to the given window
--- Close window if minimap should not be shown or if the minimap buffer is not available
--- Otherwise, create the minimap if it does not exist
Expand Down Expand Up @@ -310,7 +377,7 @@ M.refresh_minimap_window = function(winid)
api.nvim_win_set_buf(mwinid, mbufnr)
end

M.reset_cursor_line(winid)
M.reset_mwindow_cursor_line(winid)

logger.log(string.format("Minimap for window %d refreshed", winid), vim.log.levels.TRACE)
return mwinid
Expand Down

0 comments on commit cac6655

Please sign in to comment.