Compare commits
5 Commits
00cbb851ec
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8258f31107 | ||
|
|
955ceb2f61 | ||
|
|
83b45009e3 | ||
|
|
d8d0c45bc3 | ||
|
|
bd8f338b4a |
4
init.lua
4
init.lua
@@ -1,6 +1,6 @@
|
|||||||
-- adjust proxy on Windows
|
-- adjust proxy on Windows
|
||||||
if vim.loop.os_environ().OS == 'Windows_NT' then
|
if vim.loop.os_environ().OS == 'Windows_NT' then
|
||||||
-- TODO move out of the tree and do not check in
|
-- TODO move out of the tree
|
||||||
vim.fn.setenv("http_proxy", "http://10.167.16.21:80")
|
vim.fn.setenv("http_proxy", "http://10.167.16.21:80")
|
||||||
vim.fn.setenv("https_proxy", "http://10.167.16.21:80")
|
vim.fn.setenv("https_proxy", "http://10.167.16.21:80")
|
||||||
end
|
end
|
||||||
@@ -15,8 +15,6 @@ require('lsp')
|
|||||||
require('keybindings')
|
require('keybindings')
|
||||||
require('layout')
|
require('layout')
|
||||||
|
|
||||||
require('stopwatch').setup({ big_display = true, update_ms = 1000 })
|
|
||||||
|
|
||||||
if vim.loop.os_gethostname() == 'slaptop' then
|
if vim.loop.os_gethostname() == 'slaptop' then
|
||||||
require('diary')
|
require('diary')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
-- define your colorscheme here
|
-- define your colorscheme here
|
||||||
local colorscheme = 'lunaperche-sl'
|
local COLORSCHEME = 'lunaperche-sl'
|
||||||
|
|
||||||
local is_ok, _ = pcall(vim.cmd, "colorscheme " .. colorscheme)
|
local is_ok, _ = pcall(vim.cmd, "colorscheme " .. COLORSCHEME)
|
||||||
if not is_ok then
|
if not is_ok then
|
||||||
vim.notify('colorscheme ' .. colorscheme .. ' not found!')
|
vim.notify('colorscheme ' .. COLORSCHEME .. ' not found!')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -83,13 +83,13 @@ dashboard.section.header.val = vim.split(adjustedLogo, '\n')
|
|||||||
local buttons = {
|
local buttons = {
|
||||||
dashboard.button('n', ' New file', ':ene <BAR> startinsert <CR>'),
|
dashboard.button('n', ' New file', ':ene <BAR> startinsert <CR>'),
|
||||||
dashboard.button('s', ' Settings', '<cmd>WorkspacesOpen config-nvim<CR>'),
|
dashboard.button('s', ' Settings', '<cmd>WorkspacesOpen config-nvim<CR>'),
|
||||||
dashboard.button('t', ' Todo List', '<cmd>Org agenda t<CR>'),
|
dashboard.button('a', ' Agenda & TODOs', '<cmd>Org agenda t<CR>'),
|
||||||
dashboard.button('u', ' Update plugins', '<cmd>Lazy update<CR>'),
|
dashboard.button('u', ' Update plugins', '<cmd>Lazy update<CR>'),
|
||||||
dashboard.button('w', ' Workspaces', '<cmd>WorkspacesOpen<CR>'),
|
dashboard.button('w', ' Workspaces', '<cmd>WorkspacesOpen<CR>'),
|
||||||
dashboard.button('q', ' Quit', '<cmd>qa<CR>'),
|
dashboard.button('q', ' Quit', '<cmd>qa<CR>'),
|
||||||
}
|
}
|
||||||
|
|
||||||
if vim.loop.os_gethostname() == 'ccflow' then
|
if vim.loop.os_gethostname() == 'slaptop' then
|
||||||
table.insert(buttons, 1,
|
table.insert(buttons, 1,
|
||||||
dashboard.button('d', ' Diary Entry', '<cmd>Diary<CR>'))
|
dashboard.button('d', ' Diary Entry', '<cmd>Diary<CR>'))
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
local DIARY_FOLDER = vim.fs.joinpath(vim.env.HOME, '.diary/asciidoc')
|
||||||
|
|
||||||
local diary_open = function(opts)
|
local diary_open = function(opts)
|
||||||
local date = opts.args ~= '' and opts.args or os.date('%Y-%m-%d')
|
local date = opts.args ~= '' and opts.args or os.date('%Y-%m-%d')
|
||||||
local year, month = date:match('(%d%d%d%d)-(%d%d)')
|
local year, month = date:match('(%d%d%d%d)-(%d%d)')
|
||||||
local folder = vim.fs.joinpath(vim.env.HOME, string.format('.diary/asciidoc/%s', year))
|
local folder = vim.fs.joinpath(DIARY_FOLDER, string.format('%s', year))
|
||||||
vim.fn.mkdir(folder, "p")
|
vim.fn.mkdir(folder, "p")
|
||||||
local file = string.format('%s/diary-%s-%s.adoc', folder, year, month)
|
local file = string.format('%s/diary-%s-%s.adoc', folder, year, month)
|
||||||
print("file is:", file)
|
print("file is:", file)
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ vim.keymap.set('n', '<leader>of',
|
|||||||
end,
|
end,
|
||||||
{ desc = "Open org folder" })
|
{ desc = "Open org folder" })
|
||||||
vim.keymap.set('n', '<leader>a', ':silent Org agenda t<cr>', { desc = "Org Agenda" })
|
vim.keymap.set('n', '<leader>a', ':silent Org agenda t<cr>', { desc = "Org Agenda" })
|
||||||
vim.keymap.set('n', '<leader>i', ':silent Org capture i<cr>', { desc = "Org Interruption" })
|
vim.keymap.set('n', '<leader>Q', ':silent Org capture t<cr>', { desc = "Org new TODO"})
|
||||||
|
vim.keymap.set('n', '<leader>q', ':silent Org capture i<cr>', { desc = "Org new interruption" })
|
||||||
|
|
||||||
-- toggle colorscheme between dark and light
|
-- toggle colorscheme between dark and light
|
||||||
vim.keymap.set('n', '<leader>m', function()
|
vim.keymap.set('n', '<leader>m', function()
|
||||||
|
|||||||
16
lua/lsp.lua
16
lua/lsp.lua
@@ -19,7 +19,7 @@ vim.api.nvim_create_autocmd('LspAttach', {
|
|||||||
vim.keymap.set("n", '<space>F', ":silent !dx fmt --file %<cr>", { desc = "DX format rsx! regions", unpack(bufopts) })
|
vim.keymap.set("n", '<space>F', ":silent !dx fmt --file %<cr>", { desc = "DX format rsx! regions", unpack(bufopts) })
|
||||||
vim.keymap.set("v", "<space>f", LSPRangeFormatFunction, { desc = "LSP Format region" })
|
vim.keymap.set("v", "<space>f", LSPRangeFormatFunction, { desc = "LSP Format region" })
|
||||||
|
|
||||||
-- 2024-09-09 - some ccflow commands for diagnostics, symbols and code actions
|
-- 2024-09-09 - some commands for diagnostics, symbols and code actions
|
||||||
local fzf = require('fzf-lua')
|
local fzf = require('fzf-lua')
|
||||||
vim.keymap.set('n', '<space>d', fzf.diagnostics_document, { desc = "Document diagnostics" })
|
vim.keymap.set('n', '<space>d', fzf.diagnostics_document, { desc = "Document diagnostics" })
|
||||||
vim.keymap.set('n', '<space>D', fzf.diagnostics_workspace, { desc = "Workspace diagnostics" })
|
vim.keymap.set('n', '<space>D', fzf.diagnostics_workspace, { desc = "Workspace diagnostics" })
|
||||||
@@ -67,7 +67,7 @@ function LSPRangeFormatFunction()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local enable_this_lsp = {}
|
local enable_this_lsp = {}
|
||||||
if vim.loop.os_gethostname() == 'ccflow' then
|
if vim.loop.os_gethostname() == 'slaptop' then
|
||||||
-- VUE and Typescript as of vue-language-server 3.0.x
|
-- VUE and Typescript as of vue-language-server 3.0.x
|
||||||
-- taken from:
|
-- taken from:
|
||||||
-- https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#vtsls
|
-- https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#vtsls
|
||||||
@@ -108,8 +108,20 @@ if vim.loop.os_gethostname() == 'ccflow' then
|
|||||||
'wgsl_analyzer',
|
'wgsl_analyzer',
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
-- local project_library_path = "$HOME/onedrive/Development/sm-rosenheim/frontend/node_modules"
|
||||||
|
-- local project_library_path = 'C:\\Users\\260057\\onedrive\\Development\\sm-rosenheim\\frontend\\node_modules'
|
||||||
|
local project_library_path = 'C:/Users/260057/onedrive/Development/sm-rosenheim/frontend/node_modules'
|
||||||
|
local cmd = { "ngserver", "--stdio", "--tsProbeLocations", project_library_path, "--ngProbeLocations",
|
||||||
|
project_library_path }
|
||||||
|
|
||||||
|
vim.lsp.config('angularls', {
|
||||||
|
cmd = cmd,
|
||||||
|
})
|
||||||
|
|
||||||
-- any lsp which should be enabled in all situations
|
-- any lsp which should be enabled in all situations
|
||||||
enable_this_lsp = {
|
enable_this_lsp = {
|
||||||
|
'bashls',
|
||||||
|
'angularls',
|
||||||
'emmylua_ls',
|
'emmylua_ls',
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
-- this is specific for a machine
|
-- this is specific for a machine
|
||||||
if vim.loop.os_gethostname() == 'ccflow' then
|
-- // TODO.2026-09-17 - improve windows and onedrive check
|
||||||
_G.ORG_BASE_FOLDER = '~/Documents/Eigene (Briefe etc.)/org'
|
local ORG_BASE_FOLDER = '~/Documents/Eigene (Briefe etc.)/org'
|
||||||
else
|
if vim.loop.os_gethostname() ~= 'slaptop' then
|
||||||
_G.ORG_BASE_FOLDER = '~/OneDrive - Stadt Rosenheim/Desktop/orgfiles'
|
ORG_BASE_FOLDER = '~/OneDrive/Desktop/orgfiles'
|
||||||
end
|
end
|
||||||
sl_opt = {
|
sl_opt = {
|
||||||
org_base_folder = ORG_BASE_FOLDER,
|
org_base_folder = ORG_BASE_FOLDER,
|
||||||
@@ -46,7 +46,7 @@ vim.opt.splitbelow = true -- open new vertical split bottom
|
|||||||
vim.opt.splitright = true -- open new horizontal splits right
|
vim.opt.splitright = true -- open new horizontal splits right
|
||||||
vim.opt.termguicolors = true -- enable 24-bit RGB color in the TUI
|
vim.opt.termguicolors = true -- enable 24-bit RGB color in the TUI
|
||||||
vim.opt.showmode = false -- we are experienced, wo don't need the "-- INSERT --" mode hint
|
vim.opt.showmode = false -- we are experienced, wo don't need the "-- INSERT --" mode hint
|
||||||
vim.opt.showtabline = 0 -- never show top line with tabs, not used anyways
|
vim.opt.showtabline = 1 -- never show top line with tabs, not used anyways
|
||||||
vim.opt.winborder = 'rounded' -- UI borders are rounded
|
vim.opt.winborder = 'rounded' -- UI borders are rounded
|
||||||
|
|
||||||
-- Searching
|
-- Searching
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ require("lazy").setup({
|
|||||||
config = function()
|
config = function()
|
||||||
-- Setup orgmode
|
-- Setup orgmode
|
||||||
require('orgmode').setup({
|
require('orgmode').setup({
|
||||||
win_split_mode = 'auto',
|
win_split_mode = '0tabnew',
|
||||||
org_log_done = false,
|
org_log_done = false,
|
||||||
-- cf: https://github.com/nvim-orgmode/orgmode/blob/master/docs/configuration.org#mappings
|
-- cf: https://github.com/nvim-orgmode/orgmode/blob/master/docs/configuration.org#mappings
|
||||||
mappings = {
|
mappings = {
|
||||||
@@ -209,7 +209,7 @@ require("lazy").setup({
|
|||||||
org_default_notes_file = sl_opt.org_default_notes_file,
|
org_default_notes_file = sl_opt.org_default_notes_file,
|
||||||
org_archive_location = sl_opt.org_archive_location,
|
org_archive_location = sl_opt.org_archive_location,
|
||||||
org_capture_templates = {
|
org_capture_templates = {
|
||||||
t = { description = 'Task', template = "* TODO %?\n %u" },
|
t = { description = 'Task', template = "* TODO %u %?" },
|
||||||
i = { description = 'Interruption', template = "* STARTED [#A] %^{Working on}\n %U\n %a\n" },
|
i = { description = 'Interruption', template = "* STARTED [#A] %^{Working on}\n %U\n %a\n" },
|
||||||
},
|
},
|
||||||
org_todo_keywords = { 'TODO(t)', 'STARTED(s)', 'PLANNED(p)', '|', 'DONE(d)', 'UNPLANNED(u)' },
|
org_todo_keywords = { 'TODO(t)', 'STARTED(s)', 'PLANNED(p)', '|', 'DONE(d)', 'UNPLANNED(u)' },
|
||||||
@@ -263,6 +263,21 @@ require("lazy").setup({
|
|||||||
end
|
end
|
||||||
},
|
},
|
||||||
|
|
||||||
|
-- -- org-super-agenda try it 2026-07-21
|
||||||
|
-- https://github.com/hamidi-dev/org-super-agenda.nvim
|
||||||
|
-- {
|
||||||
|
-- 'hamidi-dev/org-super-agenda.nvim',
|
||||||
|
-- dependencies = {
|
||||||
|
-- 'nvim-orgmode/orgmode', -- required
|
||||||
|
-- { 'lukas-reineke/headlines.nvim', config = true }, -- optional nicety
|
||||||
|
-- },
|
||||||
|
-- config = function()
|
||||||
|
-- require('org-super-agenda').setup({
|
||||||
|
-- org_directories = sl_opt.org_agenda_files, -- recurse for *.org
|
||||||
|
-- })
|
||||||
|
-- end
|
||||||
|
-- },
|
||||||
|
|
||||||
-- comfortable table editing, esp. used in orgmode
|
-- comfortable table editing, esp. used in orgmode
|
||||||
{ 'dhruvasagar/vim-table-mode' },
|
{ 'dhruvasagar/vim-table-mode' },
|
||||||
|
|
||||||
|
|||||||
@@ -1,398 +0,0 @@
|
|||||||
-- ~/.config/nvim/lua/stopwatch.lua
|
|
||||||
-- Visible stopwatch for Neovim with centered big display and clickable buttons
|
|
||||||
local M = {}
|
|
||||||
local uv = vim.loop
|
|
||||||
|
|
||||||
local state = {
|
|
||||||
running = false,
|
|
||||||
start_hr = 0,
|
|
||||||
elapsed_ns = 0,
|
|
||||||
name = nil,
|
|
||||||
timer = nil,
|
|
||||||
bufnr = nil,
|
|
||||||
win = nil,
|
|
||||||
opts = nil,
|
|
||||||
big_mode = false,
|
|
||||||
button_spans = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function ns_to_time(ns)
|
|
||||||
local s = ns / 1e9
|
|
||||||
local h = math.floor(s / 3600)
|
|
||||||
s = s - h * 3600
|
|
||||||
local m = math.floor(s / 60)
|
|
||||||
local sec = s - m * 60
|
|
||||||
local secs = math.floor(sec)
|
|
||||||
local ms = math.floor((sec - secs) * 1000)
|
|
||||||
if h > 0 then
|
|
||||||
return string.format("%02d:%02d:%02d.%03d", h, m, secs, ms)
|
|
||||||
else
|
|
||||||
return string.format("%02d:%02d.%03d", m, secs, ms)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local BIG_DIGITS = {
|
|
||||||
["0"] = {" ███ ","█ █","█ █","█ █"," ███ "},
|
|
||||||
["1"] = {" █ "," ██ "," █ "," █ "," ███ "},
|
|
||||||
["2"] = {" ███ ","█ █"," ██ "," ██ ","█████"},
|
|
||||||
["3"] = {" ███ "," █"," ██ "," █"," ███ "},
|
|
||||||
["4"] = {"█ █ ","█ █ ","█████"," █ "," █ "},
|
|
||||||
["5"] = {"█████","█ ","████ "," █","████ "},
|
|
||||||
["6"] = {" ███ ","█ ","████ ","█ █"," ███ "},
|
|
||||||
["7"] = {"█████"," █"," █ "," █ "," █ "},
|
|
||||||
["8"] = {" ███ ","█ █"," ███ ","█ █"," ███ "},
|
|
||||||
["9"] = {" ███ ","█ █"," ████"," █"," ███ "},
|
|
||||||
[":"] = {" "," ░ "," "," ░ "," "},
|
|
||||||
[" "] = {" "," "," "," "," "},
|
|
||||||
["-"] = {" "," ","█████"," "," "},
|
|
||||||
["."] = {" "," "," "," "," ░ "},
|
|
||||||
}
|
|
||||||
|
|
||||||
local function big_time_lines(timestr)
|
|
||||||
local rows = {"","","","",""}
|
|
||||||
for i = 1, #timestr do
|
|
||||||
local ch = timestr:sub(i,i)
|
|
||||||
local pat = BIG_DIGITS[ch] or BIG_DIGITS[" "]
|
|
||||||
for r = 1,5 do
|
|
||||||
rows[r] = rows[r] .. pat[r] .. " "
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return rows
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_elapsed_ns()
|
|
||||||
if state.running then
|
|
||||||
return state.elapsed_ns + (uv.hrtime() - state.start_hr)
|
|
||||||
else
|
|
||||||
return state.elapsed_ns
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ensure_win()
|
|
||||||
if state.win and vim.api.nvim_win_is_valid(state.win) then return end
|
|
||||||
if not state.bufnr or not vim.api.nvim_buf_is_valid(state.bufnr) then
|
|
||||||
state.bufnr = vim.api.nvim_create_buf(false, true)
|
|
||||||
vim.api.nvim_buf_set_option(state.bufnr, "bufhidden", "wipe")
|
|
||||||
vim.api.nvim_buf_set_option(state.bufnr, "modifiable", false)
|
|
||||||
vim.api.nvim_buf_set_option(state.bufnr, "filetype", "stopwatch")
|
|
||||||
end
|
|
||||||
|
|
||||||
local width = state.opts.width or 28
|
|
||||||
local height = 1
|
|
||||||
if state.opts.big_display or state.big_mode then
|
|
||||||
local chars = state.opts.big_chars or 8
|
|
||||||
local char_width = 6
|
|
||||||
width = chars * char_width
|
|
||||||
height = 8
|
|
||||||
height = height + 1 -- plus button line
|
|
||||||
else
|
|
||||||
height = 1 + 1 -- one line time + button line
|
|
||||||
end
|
|
||||||
|
|
||||||
local col = (vim.o.columns - width) - (state.opts.margin_right or 2)
|
|
||||||
local row = state.opts.row or 1
|
|
||||||
|
|
||||||
local win_opts = {
|
|
||||||
relative = "editor",
|
|
||||||
anchor = "NW",
|
|
||||||
row = row,
|
|
||||||
col = math.max(0, col),
|
|
||||||
width = math.min(width, vim.o.columns - 1),
|
|
||||||
height = height,
|
|
||||||
style = "minimal",
|
|
||||||
focusable = true, -- <-- must be focusable for clicks to work reliably
|
|
||||||
noautocmd = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.win and vim.api.nvim_win_is_valid(state.win) then
|
|
||||||
pcall(vim.api.nvim_win_close, state.win, true)
|
|
||||||
end
|
|
||||||
state.win = vim.api.nvim_open_win(state.bufnr, false, win_opts)
|
|
||||||
vim.api.nvim_win_set_option(state.win, "winblend", state.opts.winblend or 5)
|
|
||||||
vim.api.nvim_buf_set_option(state.bufnr, "buftype", "nofile")
|
|
||||||
vim.api.nvim_buf_set_option(state.bufnr, "wrap", false)
|
|
||||||
|
|
||||||
-- buffer-local mouse mapping: LeftMouse triggers click handler
|
|
||||||
pcall(function()
|
|
||||||
vim.api.nvim_buf_set_keymap(state.bufnr, "n", "<LeftMouse>", "<Cmd>lua require('stopwatch')._on_click()<CR>", {nowait=true, noremap=true, silent=true})
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function close_win()
|
|
||||||
if state.win and vim.api.nvim_win_is_valid(state.win) then
|
|
||||||
pcall(vim.api.nvim_win_close, state.win, true)
|
|
||||||
end
|
|
||||||
state.win = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function build_button_line()
|
|
||||||
local btns = { "> Toggle", "O Reset", "X Hide" }
|
|
||||||
local sep = " "
|
|
||||||
local line = table.concat(btns, sep)
|
|
||||||
local spans = {}
|
|
||||||
local cur = 1
|
|
||||||
for i, b in ipairs(btns) do
|
|
||||||
local s = line:find(b, cur, true)
|
|
||||||
if s then
|
|
||||||
local e = s + #b - 1
|
|
||||||
table.insert(spans, {name = b, s = s, e = e})
|
|
||||||
cur = e + #sep + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return line, spans
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update_win()
|
|
||||||
if not state.opts.visible then return end
|
|
||||||
ensure_win()
|
|
||||||
if not state.bufnr or not vim.api.nvim_buf_is_valid(state.bufnr) then return end
|
|
||||||
|
|
||||||
local lines = {}
|
|
||||||
local label = state.name and ("[" .. state.name .. "] ") or ""
|
|
||||||
|
|
||||||
if state.opts.big_display or state.big_mode then
|
|
||||||
-- compute time string
|
|
||||||
local total_s = math.floor(get_elapsed_ns() / 1e9)
|
|
||||||
local h = math.floor(total_s / 3600)
|
|
||||||
local m = math.floor((total_s % 3600) / 60)
|
|
||||||
local s = total_s % 60
|
|
||||||
local timestr
|
|
||||||
if h > 0 then
|
|
||||||
timestr = string.format("%02d:%02d:%02d", h, m, s)
|
|
||||||
else
|
|
||||||
timestr = string.format("%02d:%02d", m, s)
|
|
||||||
end
|
|
||||||
|
|
||||||
local b_lines = big_time_lines(timestr)
|
|
||||||
-- center horizontally inside window by adding left padding
|
|
||||||
local win_w = vim.api.nvim_win_get_width(state.win)
|
|
||||||
local char_width = 6 -- matches BIG_DIGITS width+gap
|
|
||||||
local displayed_w = #timestr * char_width
|
|
||||||
local leftpad = math.max(0, math.floor((win_w - displayed_w) / 2))
|
|
||||||
local pad = string.rep(" ", leftpad)
|
|
||||||
|
|
||||||
table.insert(lines, "") -- top blank line
|
|
||||||
for _, l in ipairs(b_lines) do table.insert(lines, pad .. l) end
|
|
||||||
table.insert(lines, "") -- blank between time and buttons
|
|
||||||
local btn_line, spans = build_button_line()
|
|
||||||
btn_line = pad .. btn_line
|
|
||||||
-- adjust spans by leftpad
|
|
||||||
for _, sp in ipairs(spans) do
|
|
||||||
sp.s = sp.s + leftpad
|
|
||||||
sp.e = sp.e + leftpad
|
|
||||||
end
|
|
||||||
table.insert(lines, btn_line)
|
|
||||||
table.insert(lines, "") -- bottom blank
|
|
||||||
state.button_spans = spans
|
|
||||||
|
|
||||||
else
|
|
||||||
local status_sym = state.running and "⏱ " or "⏸ "
|
|
||||||
local txt = status_sym .. label .. ns_to_time(get_elapsed_ns())
|
|
||||||
local win_w = vim.api.nvim_win_get_width(state.win)
|
|
||||||
local strw = vim.fn.strwidth(txt)
|
|
||||||
local leftpad = math.max(0, math.floor((win_w - strw) / 2))
|
|
||||||
local pad = string.rep(" ", leftpad)
|
|
||||||
|
|
||||||
table.insert(lines, "") -- top blank
|
|
||||||
table.insert(lines, pad .. txt)
|
|
||||||
table.insert(lines, "") -- blank between time and buttons
|
|
||||||
local btn_line, spans = build_button_line()
|
|
||||||
btn_line = pad .. btn_line
|
|
||||||
for _, sp in ipairs(spans) do
|
|
||||||
sp.s = sp.s + leftpad
|
|
||||||
sp.e = sp.e + leftpad
|
|
||||||
end
|
|
||||||
table.insert(lines, btn_line)
|
|
||||||
table.insert(lines, "") -- bottom blank
|
|
||||||
state.button_spans = spans
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.api.nvim_buf_set_option(state.bufnr, "modifiable", true)
|
|
||||||
vim.api.nvim_buf_set_lines(state.bufnr, 0, -1, false, lines)
|
|
||||||
vim.api.nvim_buf_set_option(state.bufnr, "modifiable", false)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function start_timer_loop()
|
|
||||||
if state.timer then return end
|
|
||||||
state.timer = uv.new_timer()
|
|
||||||
state.timer:start(0, state.opts.update_ms or 250, vim.schedule_wrap(function()
|
|
||||||
if state.win and not vim.api.nvim_win_is_valid(state.win) then
|
|
||||||
state.win = nil
|
|
||||||
end
|
|
||||||
update_win()
|
|
||||||
end))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function stop_timer_loop()
|
|
||||||
if state.timer then
|
|
||||||
pcall(function() state.timer:stop() end)
|
|
||||||
state.timer:close()
|
|
||||||
state.timer = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.start(name)
|
|
||||||
if state.running then return end
|
|
||||||
state.name = name or state.name
|
|
||||||
state.start_hr = uv.hrtime() - state.elapsed_ns
|
|
||||||
state.running = true
|
|
||||||
if state.opts.visible then ensure_win() end
|
|
||||||
start_timer_loop()
|
|
||||||
update_win()
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.stop()
|
|
||||||
if not state.running then return end
|
|
||||||
state.elapsed_ns = get_elapsed_ns()
|
|
||||||
state.running = false
|
|
||||||
stop_timer_loop()
|
|
||||||
update_win()
|
|
||||||
if state.opts.log_on_stop then
|
|
||||||
local log_path = state.opts.log_path or (vim.fn.stdpath("data") .. "/stopwatch_log.md")
|
|
||||||
local time_str = os.date("%Y-%m-%d %H:%M:%S")
|
|
||||||
local name = state.name or "-"
|
|
||||||
local duration = ns_to_time(state.elapsed_ns)
|
|
||||||
local line = string.format("- %s | %s | %s\n", time_str, name, duration)
|
|
||||||
local f = io.open(log_path, "a")
|
|
||||||
if f then f:write(line) f:close() end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Pause (anhalten, aber nicht als "Stop"/Log)
|
|
||||||
function M.pause()
|
|
||||||
if not state.running then return end
|
|
||||||
state.elapsed_ns = get_elapsed_ns()
|
|
||||||
state.running = false
|
|
||||||
stop_timer_loop()
|
|
||||||
update_win()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Resume (fortsetzen)
|
|
||||||
function M.resume()
|
|
||||||
if state.running then return end
|
|
||||||
state.start_hr = uv.hrtime() - state.elapsed_ns
|
|
||||||
state.running = true
|
|
||||||
start_timer_loop()
|
|
||||||
update_win()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Toggle zwischen Pause und Resume (für Button/Command)
|
|
||||||
function M.toggle(name)
|
|
||||||
if state.running then
|
|
||||||
M.pause()
|
|
||||||
else
|
|
||||||
-- optional: wenn name übergeben wurde, setze neuen Namen
|
|
||||||
if name and name ~= "" then state.name = name end
|
|
||||||
M.resume()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function M.reset()
|
|
||||||
state.running = false
|
|
||||||
state.elapsed_ns = 0
|
|
||||||
state.start_hr = 0
|
|
||||||
stop_timer_loop()
|
|
||||||
update_win()
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.show()
|
|
||||||
state.opts.visible = true
|
|
||||||
ensure_win()
|
|
||||||
start_timer_loop()
|
|
||||||
update_win()
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.hide()
|
|
||||||
state.opts.visible = false
|
|
||||||
close_win()
|
|
||||||
stop_timer_loop()
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.log_now()
|
|
||||||
local log_path = state.opts.log_path or (vim.fn.stdpath("data") .. "/stopwatch_log.md")
|
|
||||||
local time_str = os.date("%Y-%m-%d %H:%M:%S")
|
|
||||||
local name = state.name or "-"
|
|
||||||
local duration = ns_to_time(get_elapsed_ns())
|
|
||||||
local line = string.format("- %s | %s | %s\n", time_str, name, duration)
|
|
||||||
local f = io.open(log_path, "a")
|
|
||||||
if f then f:write(line) f:close() end
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.status()
|
|
||||||
local elapsed = get_elapsed_ns()
|
|
||||||
local prefix = state.running and "⏱" or "⏸"
|
|
||||||
local name = state.name and (" " .. state.name) or ""
|
|
||||||
return prefix .. name .. " " .. ns_to_time(elapsed)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.toggle_big()
|
|
||||||
state.big_mode = not state.big_mode
|
|
||||||
update_win()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mouse click handler
|
|
||||||
function M._on_click()
|
|
||||||
-- only proceed when our floating window is focused
|
|
||||||
local cur = vim.api.nvim_get_current_win()
|
|
||||||
if cur ~= state.win then return end
|
|
||||||
|
|
||||||
local pos = vim.fn.getmousepos()
|
|
||||||
if not pos then return end
|
|
||||||
local click_line = pos.line
|
|
||||||
local col = pos.column
|
|
||||||
|
|
||||||
-- button line is the second-to-last line because we add a bottom blank line
|
|
||||||
local total = vim.api.nvim_buf_line_count(state.bufnr)
|
|
||||||
local btn_line_index = total - 1
|
|
||||||
if click_line ~= btn_line_index then return end
|
|
||||||
if not state.button_spans then return end
|
|
||||||
|
|
||||||
for _, sp in ipairs(state.button_spans) do
|
|
||||||
if col >= sp.s and col <= sp.e then
|
|
||||||
local name = sp.name
|
|
||||||
if name:find("Toggle",1,true) then M.toggle()
|
|
||||||
elseif name:find("Hide",1,true) then M.hide()
|
|
||||||
elseif name:find("Reset",1,true) then M.reset() end
|
|
||||||
|
|
||||||
-- visual feedback
|
|
||||||
pcall(function()
|
|
||||||
local ns = vim.api.nvim_create_namespace("stopwatch_click")
|
|
||||||
vim.api.nvim_buf_add_highlight(state.bufnr, ns, "Visual", btn_line_index-1, sp.s-1, sp.e)
|
|
||||||
vim.defer_fn(function() vim.api.nvim_buf_clear_namespace(state.bufnr, ns, 0, -1) end, 120)
|
|
||||||
end)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.setup(opts)
|
|
||||||
opts = opts or {}
|
|
||||||
state.opts = vim.tbl_extend("keep", opts, {
|
|
||||||
visible = true,
|
|
||||||
update_ms = 250,
|
|
||||||
width = 28,
|
|
||||||
row = 1,
|
|
||||||
margin_right = 2,
|
|
||||||
winblend = 5,
|
|
||||||
log_on_stop = false,
|
|
||||||
log_path = nil,
|
|
||||||
big_display = false,
|
|
||||||
big_chars = 8,
|
|
||||||
})
|
|
||||||
state.big_mode = state.opts.big_display or false
|
|
||||||
|
|
||||||
vim.api.nvim_create_user_command("StopwatchStart", function(opts) M.start(opts.args ~= "" and opts.args or nil) end, { nargs = "?" })
|
|
||||||
vim.api.nvim_create_user_command("StopwatchStop", function() M.stop() end, {})
|
|
||||||
vim.api.nvim_create_user_command("StopwatchToggle", function(opts) M.toggle(opts.args ~= "" and opts.args or nil) end, { nargs = "?" })
|
|
||||||
vim.api.nvim_create_user_command("StopwatchReset", function() M.reset() end, {})
|
|
||||||
vim.api.nvim_create_user_command("StopwatchShow", function() M.show() end, {})
|
|
||||||
vim.api.nvim_create_user_command("StopwatchHide", function() M.hide() end, {})
|
|
||||||
vim.api.nvim_create_user_command("StopwatchLog", function() M.log_now() end, {})
|
|
||||||
vim.api.nvim_create_user_command("StopwatchToggleBig", function() M.toggle_big() end, {})
|
|
||||||
|
|
||||||
if state.opts.visible then ensure_win() update_win() end
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# ccflow local snippets for all modes
|
# local snippets for all modes
|
||||||
|
|
||||||
snippet todo "Add a TODO marker"
|
snippet todo "Add a TODO marker"
|
||||||
// TODO.`strftime("%Y-%m-%d -")`
|
// TODO.`strftime("%Y-%m-%d -")`
|
||||||
|
|||||||
Reference in New Issue
Block a user