diff --git a/vis/.config/vis/lexers/terraform.lua b/vis/.config/vis/lexers/terraform.lua new file mode 100644 index 0000000..8f6dadc --- /dev/null +++ b/vis/.config/vis/lexers/terraform.lua @@ -0,0 +1,43 @@ +-- ~/.config/vis/lexers/terraform.lua +-- HCL/Terraform LPeg lexer for the vis editor. +-- Uses the modern Scintillua style for robust syntax highlighting. + +local lexer = lexer +local P, S = lpeg.P, lpeg.S + +local lex = lexer.new('terraform', {fold_by_indentation = true}) + +-- Comments (# or // or /* */) +local line_comment = lexer.to_eol('#') + lexer.to_eol('//') +local block_comment = lexer.range('/*', '*/') +lex:add_rule('comment', lex:tag(lexer.COMMENT, line_comment + block_comment)) + +-- Strings (double-quoted and heredoc) +local dq_str = lexer.range('"', true) +-- Basic heredoc pattern: '<<' (optionally with '-') followed by identifier, up to matching newline-identifier-newline +local heredoc = '<<' * P('-')^-1 * lexer.word +lex:add_rule('string', lex:tag(lexer.STRING, dq_str + heredoc)) + +-- Keywords +lex:add_rule('keyword', lex:tag(lexer.KEYWORD, lexer.word_match[[ + resource data provider variable output locals module terraform + required_providers required_version source version for_each count + if else for in true false null +]])) + +-- Numbers +lex:add_rule('number', lex:tag(lexer.NUMBER, lexer.number)) + +-- Identifiers / function names +lex:add_rule('identifier', lex:tag(lexer.IDENTIFIER, lexer.word)) + +-- Operators +lex:add_rule('operator', lex:tag(lexer.OPERATOR, S('={}[]().,;:<+-*/&|!?@'))) + +-- Fold points +lex:add_fold_point(lexer.OPERATOR, '[', ']') +lex:add_fold_point(lexer.OPERATOR, '{', '}') + +lexer.property['scintillua.comment'] = '#' + +return lex diff --git a/vis/.config/vis/visrc.lua b/vis/.config/vis/visrc.lua new file mode 100644 index 0000000..e6fc942 --- /dev/null +++ b/vis/.config/vis/visrc.lua @@ -0,0 +1,148 @@ +-- ~/.config/vis/visrc.lua +-- Sourced by the vis editor during startup. +-- Highly customized based on your .vimrc configuration. + +-- Load standard vis runtime files (must be done first) +require('vis') + +-- Register HCL/Terraform file extensions to the terraform lexer +vis.ftdetect = vis.ftdetect or {} +vis.ftdetect.filetypes = vis.ftdetect.filetypes or {} +vis.ftdetect.filetypes.terraform = { + ext = { "%.tf$", "%.tfvars$", "%.hcl$" } +} + + +vis.events.subscribe(vis.events.INIT, function() + -- Enable 256 colors themes + -- vis:command('set theme default-256') -- or base-16 / default-256 +end) + +-- Global Editor Options (ported from vimrc) +vis.events.subscribe(vis.events.WIN_OPEN, function(win) + + -- Filetype-specific indentation and soft-wrapping + if syntax == "markdown" or syntax == "text" or syntax == "gitcommit" then + vis:command("set tabwidth 4") + vis:command("set expandtab on") + vis:command("set autoindent on") + -- In vis, wrapping occurs at the minimum of window width and wrapcolumn. + -- Setting wrapcolumn to a large number (e.g., 1000) acts as soft-wrap. + vis:command("set wrapcolumn 1000") + else + -- Default options for code and structured data (go, python, sh, yaml, json, etc.) + vis:command("set tabwidth 2") + vis:command("set expandtab on") + vis:command("set autoindent on") + vis:command("set wrapcolumn 0") -- No wrap for code/config + end + + -- Highlight current cursor line + vis:command("set cursorline on") +end) + +------------------------------------------------------------------------------- +-- Key Mappings (ported from vimrc) +------------------------------------------------------------------------------- + +-- Use semicolon as colon for commands +vis:map(vis.modes.NORMAL, ";", ":") + +-- Navigate visual display lines instead of logical lines (gj/gk mapping) +vis:map(vis.modes.NORMAL, "j", "gj") +vis:map(vis.modes.NORMAL, "k", "gk") +vis:map(vis.modes.VISUAL, "j", "gj") +vis:map(vis.modes.VISUAL, "k", "gk") + +-- Optional list/hidden characters toggle commands (commented like in vimrc) +-- vis:command('set showtabs on') +-- vis:command('set shownewlines on') +-- vis:command('set showspaces on') + +------------------------------------------------------------------------------- +-- Insert Mode Helpers (ported from vimrc) +------------------------------------------------------------------------------- + +-- Insert markdown triple backticks code block with Ctrl-b in insert mode +vis:map(vis.modes.INSERT, "", function() + local win = vis.win + local file = win.file + local pos = win.selection.pos + + -- Insert "```\n\n```" and place cursor inside + file:insert(pos, "```\n\n```") + win.selection.pos = pos + 4 -- Position cursor in the empty middle line +end, "Insert markdown triple backticks code block") + +-- typing idate inserts the current date (insert-mode abbreviation equivalent) +vis:map(vis.modes.INSERT, "idate", function() + local win = vis.win + local date_str = os.date("%Y-%m-%d") + win.file:insert(win.selection.pos, date_str) +end, "Insert current date") + +------------------------------------------------------------------------------- +-- External Formatter Pipelines (ported from vimrc leader bindings) +------------------------------------------------------------------------------- + +-- Helper function to pipe full buffer to external formatting commands +local function format_buffer(cmd) + local win = vis.win + local file = win.file + local pos = win.selection.pos -- save cursor pos + + -- Pipe entire file range to formatter in fullscreen=false mode + local status, out, err = vis:pipe(file, {start = 0, finish = file.size}, cmd) + if status ~= 0 then + vis:info(err or "Format failed") + else + file:delete({start = 0, finish = file.size}) + file:insert(0, out) + -- Restore cursor position safely + if pos < file.size then + win.selection.pos = pos + else + win.selection.pos = file.size + end + end +end + +-- Key bindings using standard backslash prefix (\) +vis:map(vis.modes.NORMAL, "\\tf", function() format_buffer("tofu fmt -no-color -") end, "Format buffer as Terraform/Tofu") +vis:map(vis.modes.NORMAL, "\\js", function() format_buffer("jq .") end, "Format buffer as JSON") +vis:map(vis.modes.NORMAL, "\\jn", function() format_buffer("jsonnetfmt -") end, "Format buffer as Jsonnet") +vis:map(vis.modes.NORMAL, "\\yq", function() format_buffer("yq .") end, "Format buffer as YAML") + +------------------------------------------------------------------------------- +-- Fuzzy Finder Integration (ported from vimrc fzf shortcuts) +------------------------------------------------------------------------------- + +-- Define fuzzy finder function using fzf via io.popen +local function fzf_find() + -- Run fzf using io.popen so it inherits the terminal's stdin/stderr + local file = io.popen("fzf") + if not file then return end + local output = file:read("*l") -- Read the selected file path + local success, msg, status = file:close() + + if output and output ~= "" then + -- Strip any trailing spaces or newlines + output = output:gsub("%s+$", "") + if output ~= "" then + vis:command("e '" .. output .. "'") + end + end + + -- Redraw the editor screen since fzf drew over the terminal + vis:feedkeys("") +end + +-- Register ':fzf' command to trigger the fuzzy finder +vis:command_register("fzf", function(argv, force, win, selection, range) + fzf_find() + return true +end) + +vis:map(vis.modes.NORMAL, "", function() + fzf_find() +end, "Fuzzy finder file selection using fzf")