add td week subcommand, nvim centralization, and README
td week parses git log for task create/complete events and joins with time.csv for weekly "what got done" reports. Nvim integration moved into dotfiles/nvim/ (symlinked in by new deploy_nvim step) so all three td surfaces live under dotfiles. README covers the deploy pattern and td. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
f27b5656c0
commit
fcf1132a61
@ -149,6 +149,7 @@ alias tdop='rg "\- \[[^(x|~)]\].*(🔼|⏫)" --line-number | fzf | awk -F: "{pri
|
|||||||
tstart() { command td start "$@"; }
|
tstart() { command td start "$@"; }
|
||||||
tstop() { command td stop; }
|
tstop() { command td stop; }
|
||||||
treport() { command td report "$@"; }
|
treport() { command td report "$@"; }
|
||||||
|
tweek() { command td week "$@"; }
|
||||||
|
|
||||||
alias gr='git reset HEAD'
|
alias gr='git reset HEAD'
|
||||||
alias gc='git commit -v'
|
alias gc='git commit -v'
|
||||||
|
|||||||
94
dotfiles/README.md
Normal file
94
dotfiles/README.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# dotfiles
|
||||||
|
|
||||||
|
Symlink-deployed config. The parent `~/setup_env/setup_env.sh` installs each file here to its destination path — edit the file in this repo, the change goes live.
|
||||||
|
|
||||||
|
| Source in this repo | Deployed to | Deployed by |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `.bashrc`, `.vimrc`, `.gitconfig`, `.pspgconf`, `.psqlrc`, `.tmux.conf`, `.bashrc_local` | `~/<filename>` | `deploy_configs` |
|
||||||
|
| `bin/*` | `~/.local/bin/<name>` | `deploy_bin` |
|
||||||
|
| `nvim/*.lua` | `~/.config/nvim/lua/<name>.lua` | `deploy_nvim` |
|
||||||
|
|
||||||
|
On a fresh machine: clone the `setup_env` repo, then from `~/setup_env/` run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./install_neovim.sh
|
||||||
|
./install_nvchad.sh
|
||||||
|
./install_python3.sh
|
||||||
|
./setup_env.sh # creates all the symlinks + installs apt packages
|
||||||
|
```
|
||||||
|
|
||||||
|
After install you still need to add one line to the NvChad-provided `~/.config/nvim/lua/mappings.lua` (it's not tracked here because NvChad owns that file):
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("td_mappings")
|
||||||
|
```
|
||||||
|
|
||||||
|
Everything else picks up automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## td — markdown todo time tracking
|
||||||
|
|
||||||
|
Track time on markdown todos identified by an Obsidian block-ref `^tid-*` at the end of the task line. Data lives in `time.csv` at the vault root; reports cross-join time with git history to show what was created vs. completed.
|
||||||
|
|
||||||
|
### The three surfaces (one script)
|
||||||
|
|
||||||
|
All logic is in `bin/td` — a Python 3 stdlib script. The other surfaces are thin wrappers so the script is reachable from each editing context.
|
||||||
|
|
||||||
|
| Surface | Location | Purpose |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Python script | `bin/td` → `~/.local/bin/td` | Single source of truth. All subcommands. |
|
||||||
|
| Shell wrappers | `.bashrc` (`tstart` / `tstop` / `treport` / `tweek`) | Bypass the `td` alias (see gotcha). |
|
||||||
|
| Nvim module | `nvim/td.lua` + `nvim/td_mappings.lua` | `:TdStart` / `:TdStop` / `:TdReport` / `:TdWeek` commands + `<leader>t{s,p,r,w}` keymaps. |
|
||||||
|
|
||||||
|
### Data model
|
||||||
|
|
||||||
|
`time.csv` at the vault root:
|
||||||
|
|
||||||
|
```
|
||||||
|
started_at, stopped_at, tid, file, description
|
||||||
|
```
|
||||||
|
|
||||||
|
- `tid` — block-ref identifier, format `tid-YYYYMMDD-HHMMSS`, appended as `^tid-...` to the task line in the markdown file
|
||||||
|
- `started_at` / `stopped_at` — ISO-8601 local timestamps; a running entry has an empty `stopped_at`
|
||||||
|
- one row per time segment; `td stop` fills in `stopped_at` on the open row
|
||||||
|
|
||||||
|
Vault root is discovered by walking up from the current buffer file looking for `time.csv` or `.obsidian/`.
|
||||||
|
|
||||||
|
### Subcommands
|
||||||
|
|
||||||
|
| Command | What it does |
|
||||||
|
| --- | --- |
|
||||||
|
| `td start <tid> [--file PATH] [--desc TEXT]` | Start a timer. Auto-stops any running entry first. If `--file` / `--desc` aren't given, greps the vault for the tid to populate them. |
|
||||||
|
| `td stop` | Close the open entry. |
|
||||||
|
| `td report [FILTER]` | Total time per tid (filter matches tid or file substring). |
|
||||||
|
| `td current` | Print the currently-running tid (or nothing). |
|
||||||
|
| `td tidgen` | Print a fresh `tid-YYYYMMDD-HHMMSS`. |
|
||||||
|
| `td week [--since DATE]` | Task create/complete events from `git log -p`, joined with `time.csv`. Default range: since Monday 00:00 of this week. |
|
||||||
|
|
||||||
|
### How `td week` works
|
||||||
|
|
||||||
|
Scans `git log -p --reverse --no-renames` from cwd, pairs `-`/`+` task-line diffs within each commit by tid, classifies each event:
|
||||||
|
|
||||||
|
- `[x]` **done** — `- [ ]` → `- [x]` transition in one commit
|
||||||
|
- `[ ]` **new** — added `- [ ]` line with a fresh tid
|
||||||
|
- `[+]` **done+new** — `- [x]` added with no prior `- [ ]` for that tid (created and completed in the same commit)
|
||||||
|
- `[o]` **reopen** — `- [x]` → `- [ ]` transition
|
||||||
|
|
||||||
|
Event timestamp is commit time, not toggle time — batched commits share one timestamp. Fine for weekly "what did I get done" reports; not precise enough for hourly auditing.
|
||||||
|
|
||||||
|
### Nvim integration
|
||||||
|
|
||||||
|
`<leader>ts` / `:TdStart` on a `- [ ]` task line:
|
||||||
|
1. If the line has no `^tid-*` block ref, auto-generates `tid-YYYYMMDD-HHMMSS`, appends it, saves the buffer.
|
||||||
|
2. Starts the timer with the file path (relative to vault root) and the task text (minus checkbox + block ref) as description.
|
||||||
|
|
||||||
|
Other mappings: `<leader>tp` stop, `<leader>tr` report float, `<leader>tw` week float. `q` or `<Esc>` closes a float.
|
||||||
|
|
||||||
|
Known limitation: NvChad defers `mappings.lua` via `vim.schedule`, so `:TdStart` etc. aren't available inside `-c` arguments on headless invocations. Interactive use is fine.
|
||||||
|
|
||||||
|
### Gotchas
|
||||||
|
|
||||||
|
- **`td` alone is aliased to `rg`** (for the `td` / `tdp` / `tdo` todo-grep family, defined in `.bashrc`). So `td week` runs `rg "\- \[[^(x|~)]\]" week` and errors out. Use `tweek` (shell wrapper that calls `command td week`) or `command td week` directly.
|
||||||
|
- **CSV is cwd-scoped.** `$TD_LOG` defaults to `./time.csv`, so subcommands must be run from (or under) the vault root. The nvim wrapper handles this by walking up to find the vault root; the shell wrappers trust your cwd.
|
||||||
|
- **Data-model changes go in `bin/td`.** The shell and nvim surfaces should stay thin — if a new subcommand is useful in nvim too, add it to `bin/td`, then a one-line `tfoo()` wrapper in `.bashrc` and a `M.foo` + mapping in `nvim/td.lua` / `nvim/td_mappings.lua`.
|
||||||
102
dotfiles/bin/td
102
dotfiles/bin/td
@ -7,11 +7,12 @@ Usage:
|
|||||||
td report [FILTER] # FILTER matches tid or file substring
|
td report [FILTER] # FILTER matches tid or file substring
|
||||||
td current # print the currently-running tid (or nothing)
|
td current # print the currently-running tid (or nothing)
|
||||||
td tidgen # print a new unique tid
|
td tidgen # print a new unique tid
|
||||||
|
td week [--since DATE] # task create/complete events from git log, joined with time.csv
|
||||||
|
|
||||||
Log location: $TD_LOG (default ./time.csv)
|
Log location: $TD_LOG (default ./time.csv)
|
||||||
"""
|
"""
|
||||||
import argparse, csv, os, re, subprocess, sys
|
import argparse, csv, os, re, subprocess, sys
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
LOG = os.environ.get("TD_LOG", "./time.csv")
|
LOG = os.environ.get("TD_LOG", "./time.csv")
|
||||||
@ -113,6 +114,104 @@ def cmd_current(args):
|
|||||||
def cmd_tidgen(args):
|
def cmd_tidgen(args):
|
||||||
print(f"tid-{datetime.now().strftime('%Y%m%d-%H%M%S')}")
|
print(f"tid-{datetime.now().strftime('%Y%m%d-%H%M%S')}")
|
||||||
|
|
||||||
|
TID_RE = re.compile(r"\^(tid-[\w-]+)")
|
||||||
|
TASK_ADD_RE = re.compile(r"^\+(?!\+\+)\s*-\s*\[([ xX])\]\s*(.*)$")
|
||||||
|
TASK_REM_RE = re.compile(r"^-(?!--)\s*-\s*\[([ xX])\]\s*(.*)$")
|
||||||
|
|
||||||
|
def _tid_totals():
|
||||||
|
totals = defaultdict(int)
|
||||||
|
for r in read_rows():
|
||||||
|
if r["stopped_at"]:
|
||||||
|
start = datetime.fromisoformat(r["started_at"])
|
||||||
|
stop = datetime.fromisoformat(r["stopped_at"])
|
||||||
|
totals[r["tid"]] += int((stop - start).total_seconds())
|
||||||
|
return totals
|
||||||
|
|
||||||
|
def _scan_git(since):
|
||||||
|
SEP = "---TDWEEK-COMMIT---"
|
||||||
|
try:
|
||||||
|
out = subprocess.check_output(
|
||||||
|
["git", "log", f"--since={since}", "--reverse",
|
||||||
|
f"--format={SEP}%n%cI", "-p", "--no-color", "--no-renames"],
|
||||||
|
text=True, stderr=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
return
|
||||||
|
for chunk in out.split(SEP + "\n"):
|
||||||
|
if not chunk.strip():
|
||||||
|
continue
|
||||||
|
lines = chunk.split("\n")
|
||||||
|
ts = lines[0]
|
||||||
|
current_file = None
|
||||||
|
adds, removes = [], []
|
||||||
|
for ln in lines[1:]:
|
||||||
|
if ln.startswith("+++ b/"):
|
||||||
|
current_file = ln[6:].split("\t")[0].rstrip(); continue
|
||||||
|
if ln.startswith("--- ") or ln.startswith("diff --git") or ln.startswith("index ") or ln.startswith("@@"):
|
||||||
|
continue
|
||||||
|
if not current_file or current_file == "/dev/null":
|
||||||
|
continue
|
||||||
|
m = TASK_ADD_RE.match(ln)
|
||||||
|
if m:
|
||||||
|
status = m.group(1).lower().strip() or " "
|
||||||
|
tm = TID_RE.search(m.group(2))
|
||||||
|
if tm:
|
||||||
|
desc = TID_RE.sub("", m.group(2)).strip()
|
||||||
|
adds.append((current_file, status, tm.group(1), desc))
|
||||||
|
continue
|
||||||
|
m = TASK_REM_RE.match(ln)
|
||||||
|
if m:
|
||||||
|
status = m.group(1).lower().strip() or " "
|
||||||
|
tm = TID_RE.search(m.group(2))
|
||||||
|
if tm:
|
||||||
|
removes.append((current_file, status, tm.group(1)))
|
||||||
|
rem_by_tid = {t[2]: t for t in removes}
|
||||||
|
for file, status, tid, desc in adds:
|
||||||
|
prior = rem_by_tid.get(tid)
|
||||||
|
if prior:
|
||||||
|
if prior[1] == " " and status == "x":
|
||||||
|
yield (ts, "done", tid, file, desc)
|
||||||
|
elif prior[1] == "x" and status == " ":
|
||||||
|
yield (ts, "reopen", tid, file, desc)
|
||||||
|
else:
|
||||||
|
yield (ts, "done+new" if status == "x" else "new", tid, file, desc)
|
||||||
|
|
||||||
|
def _default_since():
|
||||||
|
today = datetime.now()
|
||||||
|
monday = today - timedelta(days=today.weekday())
|
||||||
|
return monday.strftime("%Y-%m-%d 00:00")
|
||||||
|
|
||||||
|
def _fmt_dur(secs):
|
||||||
|
return f"{secs // 3600}h{(secs % 3600) // 60:02d}m"
|
||||||
|
|
||||||
|
def cmd_week(args):
|
||||||
|
since = args.since or _default_since()
|
||||||
|
events = list(_scan_git(since))
|
||||||
|
totals = _tid_totals()
|
||||||
|
if not events:
|
||||||
|
print(f"no task events since {since}"); return
|
||||||
|
by_day = defaultdict(list)
|
||||||
|
for ts, kind, tid, file, desc in events:
|
||||||
|
day = ts[:10]
|
||||||
|
by_day[day].append((ts, kind, tid, file, desc))
|
||||||
|
marker = {"done": "[x]", "new": "[ ]", "done+new": "[+]", "reopen": "[o]"}
|
||||||
|
n_done = n_new = total_secs = 0
|
||||||
|
counted_tids = set()
|
||||||
|
print(f"Week since {since}\n")
|
||||||
|
for day in sorted(by_day):
|
||||||
|
dt = datetime.fromisoformat(day)
|
||||||
|
print(f"{dt.strftime('%a %Y-%m-%d')}")
|
||||||
|
for ts, kind, tid, file, desc in by_day[day]:
|
||||||
|
t = totals.get(tid, 0)
|
||||||
|
dur = _fmt_dur(t) if t else " "
|
||||||
|
print(f" {marker.get(kind,'? ')} {tid:<24} {dur:>6} {file} — {desc[:60]}")
|
||||||
|
if kind in ("done", "done+new"): n_done += 1
|
||||||
|
if kind in ("new", "done+new"): n_new += 1
|
||||||
|
if tid not in counted_tids:
|
||||||
|
counted_tids.add(tid); total_secs += t
|
||||||
|
print()
|
||||||
|
print(f"Totals: completed {n_done} created {n_new} time {_fmt_dur(total_secs)}")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
p = argparse.ArgumentParser(prog="td", description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
p = argparse.ArgumentParser(prog="td", description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
sp = p.add_subparsers(dest="cmd", required=True)
|
sp = p.add_subparsers(dest="cmd", required=True)
|
||||||
@ -121,6 +220,7 @@ def main():
|
|||||||
s = sp.add_parser("report"); s.add_argument("filter", nargs="?"); s.set_defaults(func=cmd_report)
|
s = sp.add_parser("report"); s.add_argument("filter", nargs="?"); s.set_defaults(func=cmd_report)
|
||||||
sp.add_parser("current").set_defaults(func=cmd_current)
|
sp.add_parser("current").set_defaults(func=cmd_current)
|
||||||
sp.add_parser("tidgen").set_defaults(func=cmd_tidgen)
|
sp.add_parser("tidgen").set_defaults(func=cmd_tidgen)
|
||||||
|
s = sp.add_parser("week"); s.add_argument("--since", default=None); s.set_defaults(func=cmd_week)
|
||||||
args = p.parse_args()
|
args = p.parse_args()
|
||||||
args.func(args)
|
args.func(args)
|
||||||
|
|
||||||
|
|||||||
119
dotfiles/nvim/td.lua
Normal file
119
dotfiles/nvim/td.lua
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
local function vault_root()
|
||||||
|
local file = vim.api.nvim_buf_get_name(0)
|
||||||
|
local dir = file ~= "" and vim.fn.fnamemodify(file, ":p:h") or vim.fn.getcwd()
|
||||||
|
local probe = dir
|
||||||
|
while probe ~= "/" and probe ~= "" do
|
||||||
|
if vim.loop.fs_stat(probe .. "/time.csv") or vim.loop.fs_stat(probe .. "/.obsidian") then
|
||||||
|
return probe
|
||||||
|
end
|
||||||
|
local parent = vim.fn.fnamemodify(probe, ":h")
|
||||||
|
if parent == probe then break end
|
||||||
|
probe = parent
|
||||||
|
end
|
||||||
|
return vim.fn.getcwd()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function relpath(abs, base)
|
||||||
|
local a = vim.fn.fnamemodify(abs, ":p")
|
||||||
|
local b = vim.fn.fnamemodify(base, ":p"):gsub("/$", "")
|
||||||
|
if a:sub(1, #b + 1) == b .. "/" then return a:sub(#b + 2) end
|
||||||
|
return a
|
||||||
|
end
|
||||||
|
|
||||||
|
local function run(cmd, cwd, on_done)
|
||||||
|
local stdout, stderr = {}, {}
|
||||||
|
vim.fn.jobstart(cmd, {
|
||||||
|
cwd = cwd,
|
||||||
|
stdout_buffered = true,
|
||||||
|
stderr_buffered = true,
|
||||||
|
on_stdout = function(_, d) for _, l in ipairs(d) do if l ~= "" then stdout[#stdout + 1] = l end end end,
|
||||||
|
on_stderr = function(_, d) for _, l in ipairs(d) do if l ~= "" then stderr[#stderr + 1] = l end end end,
|
||||||
|
on_exit = function(_, code)
|
||||||
|
vim.schedule(function() if on_done then on_done(stdout, stderr, code) end end)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function notify(lines, level)
|
||||||
|
if #lines == 0 then return end
|
||||||
|
vim.notify(table.concat(lines, "\n"), level or vim.log.levels.INFO)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function extract_desc(line)
|
||||||
|
return (line:gsub("^%s*%-%s*%[.%]%s*", ""):gsub("%s*%^%S+%s*$", ""):gsub("%s+$", ""))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ensure_tid_on_line()
|
||||||
|
local line = vim.api.nvim_get_current_line()
|
||||||
|
local tid = line:match("%^(tid%-%S+)")
|
||||||
|
if tid then return tid end
|
||||||
|
if not line:match("^%s*%-%s*%[.%]") then
|
||||||
|
vim.notify("td: not on a todo line (- [ ] ...)", vim.log.levels.WARN)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
tid = os.date("tid-%Y%m%d-%H%M%S")
|
||||||
|
local new = line:gsub("%s+$", "") .. " ^" .. tid
|
||||||
|
vim.api.nvim_set_current_line(new)
|
||||||
|
vim.cmd("silent! write")
|
||||||
|
return tid
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.start()
|
||||||
|
local tid = ensure_tid_on_line()
|
||||||
|
if not tid then return end
|
||||||
|
local cwd = vault_root()
|
||||||
|
local file = relpath(vim.api.nvim_buf_get_name(0), cwd)
|
||||||
|
local desc = extract_desc(vim.api.nvim_get_current_line())
|
||||||
|
run({ "td", "start", tid, "--file", file, "--desc", desc }, cwd, function(out, err)
|
||||||
|
notify(out); notify(err, vim.log.levels.WARN)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.stop()
|
||||||
|
run({ "td", "stop" }, vault_root(), function(out, err)
|
||||||
|
notify(out); notify(err, vim.log.levels.WARN)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function float(title, lines)
|
||||||
|
local buf = vim.api.nvim_create_buf(false, true)
|
||||||
|
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
|
||||||
|
vim.api.nvim_buf_set_option(buf, "modifiable", false)
|
||||||
|
local width = math.min(120, vim.o.columns - 4)
|
||||||
|
local height = math.min(30, #lines + 2)
|
||||||
|
vim.api.nvim_open_win(buf, true, {
|
||||||
|
relative = "editor",
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
row = math.floor((vim.o.lines - height) / 2),
|
||||||
|
col = math.floor((vim.o.columns - width) / 2),
|
||||||
|
style = "minimal",
|
||||||
|
border = "rounded",
|
||||||
|
title = " " .. title .. " ",
|
||||||
|
title_pos = "center",
|
||||||
|
})
|
||||||
|
vim.api.nvim_buf_set_keymap(buf, "n", "q", "<cmd>close<cr>", { noremap = true, silent = true })
|
||||||
|
vim.api.nvim_buf_set_keymap(buf, "n", "<Esc>", "<cmd>close<cr>", { noremap = true, silent = true })
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.report()
|
||||||
|
run({ "td", "report" }, vault_root(), function(out, err)
|
||||||
|
if #out == 0 then notify(err, vim.log.levels.WARN); return end
|
||||||
|
float("td report", out)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.week(opts)
|
||||||
|
local cmd = { "td", "week" }
|
||||||
|
if opts and opts.args and opts.args ~= "" then
|
||||||
|
for w in opts.args:gmatch("%S+") do cmd[#cmd + 1] = w end
|
||||||
|
end
|
||||||
|
run(cmd, vault_root(), function(out, err)
|
||||||
|
if #out == 0 then notify(err, vim.log.levels.WARN); return end
|
||||||
|
float("td week", out)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
11
dotfiles/nvim/td_mappings.lua
Normal file
11
dotfiles/nvim/td_mappings.lua
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- td: time-track markdown todos (logic lives in ~/.local/bin/td and td.lua)
|
||||||
|
-- Loaded from ~/.config/nvim/lua/mappings.lua via require("td_mappings").
|
||||||
|
local td = require("td")
|
||||||
|
vim.api.nvim_create_user_command("TdStart", td.start, {})
|
||||||
|
vim.api.nvim_create_user_command("TdStop", td.stop, {})
|
||||||
|
vim.api.nvim_create_user_command("TdReport", td.report, {})
|
||||||
|
vim.api.nvim_create_user_command("TdWeek", td.week, { nargs = "*" })
|
||||||
|
vim.keymap.set("n", "<leader>ts", td.start, { desc = "td: start timer on current task" })
|
||||||
|
vim.keymap.set("n", "<leader>tp", td.stop, { desc = "td: stop (pause) timer" })
|
||||||
|
vim.keymap.set("n", "<leader>tr", td.report, { desc = "td: report floating window" })
|
||||||
|
vim.keymap.set("n", "<leader>tw", td.week, { desc = "td: week (tasks from git log)" })
|
||||||
18
setup_env.sh
18
setup_env.sh
@ -77,6 +77,23 @@ deploy_bin() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Deploy nvim lua modules from dotfiles/nvim/ into ~/.config/nvim/lua/
|
||||||
|
# NOTE: requires ~/.config/nvim/ to already exist (see install_neovim.sh + install_nvchad.sh).
|
||||||
|
# Modules are required by name from ~/.config/nvim/lua/mappings.lua — e.g. require("td_mappings").
|
||||||
|
deploy_nvim() {
|
||||||
|
echo "Deploying nvim lua modules to ~/.config/nvim/lua/ ..."
|
||||||
|
local src_dir="$(pwd)/dotfiles/nvim"
|
||||||
|
[[ -d "$src_dir" ]] || return 0
|
||||||
|
if [[ ! -d ~/.config/nvim/lua ]]; then
|
||||||
|
echo " ~/.config/nvim/lua missing — run install_neovim.sh + install_nvchad.sh first. Skipping."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
for mod in "$src_dir"/*.lua; do
|
||||||
|
[[ -f "$mod" ]] || continue
|
||||||
|
create_symlink "$mod" ~/.config/nvim/lua/"$(basename "$mod")"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
# Main script
|
# Main script
|
||||||
main() {
|
main() {
|
||||||
install_packages
|
install_packages
|
||||||
@ -85,6 +102,7 @@ main() {
|
|||||||
install_git_bash_prompt
|
install_git_bash_prompt
|
||||||
deploy_configs
|
deploy_configs
|
||||||
deploy_bin
|
deploy_bin
|
||||||
|
deploy_nvim
|
||||||
echo "Setup complete! Please restart your shell or run 'source ~/.bashrc' for changes to take effect."
|
echo "Setup complete! Please restart your shell or run 'source ~/.bashrc' for changes to take effect."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user