c4b4eb9

dotfiles.git > main > c4b4eb9 > files / ghostty

Dim wikilinks for pages that don't exist

Grahp, 2026-11-09

Commit: c4b4eb9552d28b688f1d8b43c8fc85e5f5660fc9
Parent: ff90f9b

4 changed files:

nvim/after/queries/markdown_inline/highlights.scm modified (view file)

@@ -11,3 +11,15 @@   .   "]" @markup.link.wiki.bracket   (#set! @markup.link.wiki.bracket conceal ""))++; Dim links to notes that don't exist yet, like Obsidian does+(inline+  "[" @_bracket+  .+  (shortcut_link+    "["+    (link_text) @markup.link.wiki.missing+    "]")+  .+  "]" @_bracket+  (#not-wikilink-exists? @markup.link.wiki.missing))

nvim/ftplugin/markdown.lua modified (view file)

@@ -5,6 +5,8 @@ ol.columns = 80 ol.showbreak = " " +--- Registers the predicate the wikilink highlights use+require("wikilink") vim.treesitter.start()  local follow = function(fallback) return function() require("wikilink").follow(fallback) end end

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

@@ -161,6 +161,7 @@ hl(0, "@markup.link.label", {fg = blue, underline = true}) hl(0, "@markup.link.url", {link = "Gray"}) hl(0, "@markup.link.wiki", {fg = blue, underline = true})+hl(0, "@markup.link.wiki.missing", {fg = "#466b99", underline = true}) hl(0, "@markup.link.wiki.bracket", {link = "Punctuation"})  hl(0, "OilDir", {link = "Blue"})

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

@@ -21,8 +21,9 @@ end  --- The vault is the nearest dir with .obsidian (or .git), falling back to the file's own dir-local function vault_root()-  return vim.fs.root(0, {".obsidian", ".git"}) or fn.expand("%:p:h")+local function vault_root(buf)+  buf = buf or 0+  return vim.fs.root(buf, {".obsidian", ".git"}) or vim.fs.dirname(vim.api.nvim_buf_get_name(buf)) end  --- Obsidian matches by note name anywhere in the vault, or by path if one is given@@ -74,13 +75,22 @@  local skipped_dirs = {[".git"] = true, [".obsidian"] = true, [".trash"] = true, node_modules = true} +--- Every file in the vault, relative to its root+local function vault_files(root)+  local found = {}+  for path, type in vim.fs.dir(root, {depth = math.huge, skip = function(dir)+    return not skipped_dirs[vim.fs.basename(dir)]+  end}) do+    if type == "file" then found[#found + 1] = path end+  end+  return found+end+ --- Every note in the vault as {name = "Note", path = "dir/Note"}, name is what Obsidian links by local function notes()   local found = {}-  for path, type in vim.fs.dir(vault_root(), {depth = math.huge, skip = function(dir)-    return not skipped_dirs[vim.fs.basename(dir)]-  end}) do-    if type == "file" and path:match("%.md$") then+  for _, path in ipairs(vault_files(vault_root())) do+    if path:match("%.md$") then       local rel = path:sub(1, -4)       found[#found + 1] = {name = vim.fs.basename(rel), path = rel}     end@@ -88,4 +98,49 @@   return found end +--- Linkable names and paths per vault, notes without their .md like links write them+local indexes = {}++local function vault_index(root)+  if indexes[root] then return indexes[root] end+  local index = {names = {}, paths = {}}+  for _, path in ipairs(vault_files(root)) do+    path = path:gsub("%.md$", "")+    index.names[vim.fs.basename(path)] = true+    index.paths[#index.paths + 1] = "/" .. path+  end+  indexes[root] = index+  return index+end++--- Whether following the link would land on a note that already exists+local function exists(name, buf)+  if name == "" then return true end+  name = name:gsub("%.md$", "")+  local index = vault_index(vault_root(buf))+  if not name:find("/") then return index.names[name] == true end++  local here = vim.fs.dirname(vim.api.nvim_buf_get_name(buf))+  if fn.filereadable(vim.fs.joinpath(here, name .. ".md")) == 1 then return true end+  for _, path in ipairs(index.paths) do+    if path:sub(-#name - 1) == "/" .. name then return true end+  end+  return false+end++--- Notes come and go, so rescan the next time a link gets highlighted+vim.api.nvim_create_autocmd({"BufEnter", "BufWritePost", "BufFilePost", "FocusGained"}, {+  group = vim.api.nvim_create_augroup("wikilink", {}),+  callback = function() indexes = {} end,+})++--- (#wikilink-exists? @capture) for highlighting links to missing notes differently+vim.treesitter.query.add_predicate("wikilink-exists?", function(match, _, source, pred)+  for _, node in ipairs(match[pred[2]] or {}) do+    local target = vim.treesitter.get_node_text(node, source):gsub("|.*", ""):gsub("#.*", "")+    if not exists(target, source) then return false end+  end+  return true+end, {force = true})+ return {follow = follow, notes = notes}