From 3d099d5157ce479b6a15e30ff2efbe1ee0d377c3 Mon Sep 17 00:00:00 2001 From: Raymaekers Luca Date: Thu, 20 Jun 2024 22:30:24 +0200 Subject: checkpoint --- config/essentials/vis/cursors.lua | 122 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 config/essentials/vis/cursors.lua (limited to 'config/essentials/vis/cursors.lua') diff --git a/config/essentials/vis/cursors.lua b/config/essentials/vis/cursors.lua new file mode 100644 index 0000000..a4e7fa3 --- /dev/null +++ b/config/essentials/vis/cursors.lua @@ -0,0 +1,122 @@ +local M = {} +local cursors = {} +local files = {} + +-- default maxsize +M.maxsize = 1000 + +-- get the default system cache directory +local get_default_cache_path = function() + local HOME = os.getenv('HOME') + local XDG_CACHE_HOME = os.getenv('XDG_CACHE_HOME') + local BASE = XDG_CACHE_HOME or HOME + return BASE .. '/.vis-cursors' +end + +-- default save path +M.path = get_default_cache_path() + +local read_files = function() + + -- read file + local file = io.open(M.path) + if file == nil then + return + end + + files = {} + + -- read positions per file path + for line in file:lines() do + for path, pos in string.gmatch(line, '(.+)[,%s](%d+)') do + cursors[path] = pos + table.insert(files, path) + end + end + + file:close() +end + +-- read cursors from file on init +local on_init = function() + read_files() +end + +-- apply cursor pos on win open +local on_win_open = function(win) + + if win.file == nil or win.file.path == nil then + return + end + + -- init cursor path if nil + local pos = cursors[win.file.path] + if pos == nil then + cursors[win.file.path] = win.selection.pos + return + end + + -- set current cursor + win.selection.pos = tonumber(pos) + + -- center view around cursor + vis:feedkeys("zz") +end + +-- set cursor pos on close +local on_win_close = function(win) + + if win.file == nil or win.file.path == nil then + return + end + + -- re-read files in case they've changed + read_files() + + -- remove old occurences of current path + for i, path in ipairs(files) do + if path == win.file.path then + table.remove(files, i) + end + end + + -- ignore files with cursor at the beginning + if win.selection.pos == 0 then + return + end + + + -- insert current path to top of files + table.insert(files, 1, win.file.path) + + -- set cursor pos for current file path + cursors[win.file.path] = win.selection.pos +end + +-- write cursors to file on quit +local on_quit = function() + + local file = io.open(M.path, 'w+') + if file == nil then + return + end + + -- buffer cursors string + local buffer = {} + for _, path in ipairs(files) do + table.insert(buffer, string.format('%s,%d', path, cursors[path])) + if M.maxsize and #buffer >= M.maxsize then + break + end + end + local output = table.concat(buffer, '\n') + file:write(output) + file:close() +end + +vis.events.subscribe(vis.events.INIT, on_init) +vis.events.subscribe(vis.events.WIN_OPEN, on_win_open) +vis.events.subscribe(vis.events.WIN_CLOSE, on_win_close) +vis.events.subscribe(vis.events.QUIT, on_quit) + +return M -- cgit v1.2.3 From 2f8816e47e0797083a667d5cf7e778940dd1f789 Mon Sep 17 00:00:00 2001 From: Raymaekers Luca Date: Thu, 20 Jun 2024 22:50:03 +0200 Subject: checkpoint --- config/essentials/vis/Makefile | 15 ++-- config/essentials/vis/backup.lua | 47 ++++++++++++ config/essentials/vis/build.lua | 66 +++++++++++++++++ config/essentials/vis/cursors.lua | 123 ++++++++++++++----------------- config/essentials/vis/themes/nord.lua | 132 +++++++++++++++++----------------- config/essentials/vis/title.lua | 22 +++--- config/essentials/vis/visrc.lua | 68 +++++++++--------- 7 files changed, 278 insertions(+), 195 deletions(-) create mode 100644 config/essentials/vis/backup.lua create mode 100644 config/essentials/vis/build.lua (limited to 'config/essentials/vis/cursors.lua') diff --git a/config/essentials/vis/Makefile b/config/essentials/vis/Makefile index 5f41043..be230e3 100644 --- a/config/essentials/vis/Makefile +++ b/config/essentials/vis/Makefile @@ -1,16 +1,11 @@ -.PHONY: check format check-luacheck check-format +.PHONY: check format all -LUA_FILES := $(shell find -name "*.lua") +LUA_FILES := $(shell find . -name "*.lua") -check: check-luacheck +all: check format -all: check check-format - -check-luacheck: - luacheck --globals=vis -- $(LUA_FILES) - -check-format: - set -e; for lf in $(LUA_FILES); do tools/check-format "$${lf}"; done +check: + luacheck --no-color --globals=vis -- $(LUA_FILES) format: lua-format -i $(LUA_FILES) diff --git a/config/essentials/vis/backup.lua b/config/essentials/vis/backup.lua new file mode 100644 index 0000000..f48895f --- /dev/null +++ b/config/essentials/vis/backup.lua @@ -0,0 +1,47 @@ +local backup = {} + +-- Return the backup path concatenated with the filename, replace / with % +backup.entire_path_with_double_percentage_signs = + function(backup_dir, path) + return backup_dir .. "/" .. string.gsub(path, "/", "%%") + end + +-- Return the backup path concatenated with the filename, replace / with % +-- and append the current time using time_format +backup.entire_path_with_double_percentage_signs_and_timestamp = function( + backup_dir, path) + return backup_dir .. "/" .. os.date(backup.time_format) .. + string.gsub(path, "/", "%%") +end + +-- Before saving the file, copy the current contents of the file to a backup file +vis.events.subscribe(vis.events.FILE_SAVE_PRE, function(file, path) + if file.size > backup.byte_limit then return end + + -- E.g. when editing stdin as an interactive filter + -- `vis -` + if path == nil then return end + + local backup_path = backup.get_fname(backup.directory, path) + + local backup_file = io.open(backup_path, "w") + local current_file = io.open(path) + if backup_file == nil or current_file == nil then return end + + for line in current_file:lines() do backup_file:write(line .. "\n") end + + backup_file:close() +end) + +-- Set defaults +backup.directory = os.getenv("XDG_DATA_HOME") .. "/Trash/vis-backups" + +backup.get_fname = backup.entire_path_with_double_percentage_signs + +backup.time_format = "%H-%M-" + +-- Do not make backups if the file is greater than this +-- 1MB by default +backup.byte_limit = 1000000 + +return backup diff --git a/config/essentials/vis/build.lua b/config/essentials/vis/build.lua new file mode 100644 index 0000000..8a062cd --- /dev/null +++ b/config/essentials/vis/build.lua @@ -0,0 +1,66 @@ +-- Copyright (c) 2024 Florian Fischer. All rights reserved. +-- +-- vis-build is free software: you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free Software +-- Foundation, either version 3 of the License, or (at your option) any later +-- version. +-- +-- vis-build is distributed in the hope that it will be useful, but WITHOUT +-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +-- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- vis-build found in the LICENSE file. +-- If not, see . +local M = {} +M.get_default_build_cmd = function() return 'make' end + +local build_id = 0 +local builds = {} + +M.new_build = function(cmd) + build_id = build_id + 1 + local build_name = 'build' .. build_id + local build_fd = vis:communicate(build_name, cmd) + local build = {fd = build_fd, out = '', err = '', cmd = cmd} + builds[build_name] = build +end + +vis.events.subscribe(vis.events.PROCESS_RESPONSE, + function(name, event, code, msg) + local build = builds[name] + if not build then return end + + if event == 'EXIT' or event == 'SIGNAL' then + if code ~= 0 then + vis:message('build: ' .. name .. ' cmd: ' .. build.cmd) + if event == 'EXIT' then + vis:message('failed with: ' .. code) + else + vis:message('got signal: ' .. code) + end + vis:message('stdout:\n' .. build.out) + vis:message('stderr:\n' .. build.err) + else + vis:message(name .. ':\n' .. build.out) + end + builds[name] = nil + end + + if event == 'STDOUT' then + build.out = build.out .. msg + elseif event == 'STDERR' then + build.err = build.err .. msg + end +end) + +vis:command_register('build', function(argv) + M.new_build(argv[1] or M.get_default_build_cmd()) +end, 'Asynchronously build the current file or project') + +vis:map(vis.modes.NORMAL, '', function() + vis:command('build') + return 0 +end, 'Asynchronously build the current file or project') + +return M diff --git a/config/essentials/vis/cursors.lua b/config/essentials/vis/cursors.lua index a4e7fa3..37165b6 100644 --- a/config/essentials/vis/cursors.lua +++ b/config/essentials/vis/cursors.lua @@ -7,10 +7,10 @@ M.maxsize = 1000 -- get the default system cache directory local get_default_cache_path = function() - local HOME = os.getenv('HOME') - local XDG_CACHE_HOME = os.getenv('XDG_CACHE_HOME') - local BASE = XDG_CACHE_HOME or HOME - return BASE .. '/.vis-cursors' + local HOME = os.getenv('HOME') + local XDG_CACHE_HOME = os.getenv('XDG_CACHE_HOME') + local BASE = XDG_CACHE_HOME or HOME + return BASE .. '/.vis-cursors' end -- default save path @@ -18,100 +18,83 @@ M.path = get_default_cache_path() local read_files = function() - -- read file - local file = io.open(M.path) - if file == nil then - return - end + -- read file + local file = io.open(M.path) + if file == nil then return end - files = {} + files = {} - -- read positions per file path - for line in file:lines() do - for path, pos in string.gmatch(line, '(.+)[,%s](%d+)') do - cursors[path] = pos - table.insert(files, path) - end - end + -- read positions per file path + for line in file:lines() do + for path, pos in string.gmatch(line, '(.+)[,%s](%d+)') do + cursors[path] = pos + table.insert(files, path) + end + end - file:close() + file:close() end -- read cursors from file on init -local on_init = function() - read_files() -end +local on_init = function() read_files() end -- apply cursor pos on win open local on_win_open = function(win) - if win.file == nil or win.file.path == nil then - return - end + if win.file == nil or win.file.path == nil then return end - -- init cursor path if nil - local pos = cursors[win.file.path] - if pos == nil then - cursors[win.file.path] = win.selection.pos - return - end + -- init cursor path if nil + local pos = cursors[win.file.path] + if pos == nil then + cursors[win.file.path] = win.selection.pos + return + end - -- set current cursor - win.selection.pos = tonumber(pos) + -- set current cursor + win.selection.pos = tonumber(pos) - -- center view around cursor - vis:feedkeys("zz") + -- center view around cursor + vis:feedkeys("zz") end -- set cursor pos on close local on_win_close = function(win) - if win.file == nil or win.file.path == nil then - return - end - - -- re-read files in case they've changed - read_files() + if win.file == nil or win.file.path == nil then return end - -- remove old occurences of current path - for i, path in ipairs(files) do - if path == win.file.path then - table.remove(files, i) - end - end + -- re-read files in case they've changed + read_files() - -- ignore files with cursor at the beginning - if win.selection.pos == 0 then - return - end + -- remove old occurences of current path + for i, path in ipairs(files) do + if path == win.file.path then table.remove(files, i) end + end + -- ignore files with cursor at the beginning + if win.selection.pos == 0 then return end - -- insert current path to top of files - table.insert(files, 1, win.file.path) + -- insert current path to top of files + table.insert(files, 1, win.file.path) - -- set cursor pos for current file path - cursors[win.file.path] = win.selection.pos + -- set cursor pos for current file path + cursors[win.file.path] = win.selection.pos end -- write cursors to file on quit local on_quit = function() - local file = io.open(M.path, 'w+') - if file == nil then - return - end - - -- buffer cursors string - local buffer = {} - for _, path in ipairs(files) do - table.insert(buffer, string.format('%s,%d', path, cursors[path])) - if M.maxsize and #buffer >= M.maxsize then - break - end - end - local output = table.concat(buffer, '\n') - file:write(output) - file:close() + local file = io.open(M.path, 'w+') + if file == nil then return end + + -- buffer cursors string + local buffer = {} + for _, path in ipairs(files) do + table.insert(buffer, string.format('%s,%d', path, cursors[path])) + if M.maxsize and #buffer >= M.maxsize then break end + end + local output = table.concat(buffer, '\n') + file:write(output) + file:close() end vis.events.subscribe(vis.events.INIT, on_init) diff --git a/config/essentials/vis/themes/nord.lua b/config/essentials/vis/themes/nord.lua index a21f0fa..71635cf 100644 --- a/config/essentials/vis/themes/nord.lua +++ b/config/essentials/vis/themes/nord.lua @@ -1,65 +1,64 @@ -- base16-vis (https://github.com/pshevtsov/base16-vis) -- by Petr Shevtsov -- Nord scheme by arcticicestudio - local lexers = vis.lexers local colors = { - ['bg'] = '#2E3440', - ['black'] = '#3B4252', - ['light_black'] = '#434C5E', - ['dark_gray'] = '#4C566A', - ['gray'] = '#D8DEE9', - ['light_gray'] = '#616E88', - ['fg'] = '#E5E9F0', - ['white'] = '#ECEFF4', - ['turquoise'] = '#8FBCBB', - ['light_cyan'] = '#88C0D0', - ['cyan'] = '#81A1C1', - ['blue'] = '#5E81AC', - ['red'] = '#BF616A', - ['orange'] = '#D08770', - ['yellow'] = '#EBCB8B', - ['green'] = '#A3BE8C', - ['magenta'] = '#B48EAD', + ['bg'] = '#2E3440', + ['black'] = '#3B4252', + ['light_black'] = '#434C5E', + ['dark_gray'] = '#4C566A', + ['gray'] = '#D8DEE9', + ['light_gray'] = '#616E88', + ['fg'] = '#E5E9F0', + ['white'] = '#ECEFF4', + ['turquoise'] = '#8FBCBB', + ['light_cyan'] = '#88C0D0', + ['cyan'] = '#81A1C1', + ['blue'] = '#5E81AC', + ['red'] = '#BF616A', + ['orange'] = '#D08770', + ['yellow'] = '#EBCB8B', + ['green'] = '#A3BE8C', + ['magenta'] = '#B48EAD' } lexers.colors = colors -local fg = 'fore:'..colors.fg -local bg = 'back:'..colors.bg +local fg = 'fore:' .. colors.fg +local bg = 'back:' .. colors.bg -lexers.STYLE_DEFAULT = bg..','..fg +lexers.STYLE_DEFAULT = bg .. ',' .. fg lexers.STYLE_NOTHING = bg -lexers.STYLE_CLASS = 'fore:'..colors.blue -lexers.STYLE_COMMENT = 'fore:'..colors.light_gray..',italics' -lexers.STYLE_CONSTANT = 'fore:'..colors.cyan -lexers.STYLE_DEFINITION = 'fore:'..colors.green -lexers.STYLE_ERROR = 'fore:'..colors.light_cyan..',italics' -lexers.STYLE_FUNCTION = 'fore:'..colors.light_cyan..',bold' -lexers.STYLE_HEADING = 'fore:'..colors.bg..',back:'..colors.yellow -lexers.STYLE_KEYWORD = 'fore:'..colors.cyan..',bold' -lexers.STYLE_LABEL = 'fore:'..colors.blue -lexers.STYLE_NUMBER = 'fore:'..colors.magenta -lexers.STYLE_OPERATOR = 'fore:'..colors.light_cyan -lexers.STYLE_REGEX = 'fore:'..colors.orange -lexers.STYLE_STRING = 'fore:'..colors.green -lexers.STYLE_PREPROCESSOR = 'fore:'..colors.blue -lexers.STYLE_TAG = 'fore:'..colors.blue -lexers.STYLE_TYPE = 'fore:'..colors.cyan -lexers.STYLE_VARIABLE = 'fore:'..colors.cyan..',bold' -lexers.STYLE_WHITESPACE = 'fore:'..colors.light_black -lexers.STYLE_EMBEDDED = 'fore:'..colors.magenta -lexers.STYLE_IDENTIFIER = fg..',bold' - -lexers.STYLE_LINENUMBER = 'fore:'..colors.light_black..',back:'..colors.bg -lexers.STYLE_CURSOR = 'fore:'..colors.bg..',back:'..colors.fg -lexers.STYLE_CURSOR_PRIMARY = 'fore:'..colors.bg..',back:'..colors.fg -lexers.STYLE_CURSOR_LINE = 'back:'..colors.black -lexers.STYLE_COLOR_COLUMN = 'back:'..colors.black -lexers.STYLE_SELECTION = 'back:'..colors.light_black -lexers.STYLE_STATUS = 'fore:'..colors.gray..',back:'..colors.black -lexers.STYLE_STATUS_FOCUSED = 'fore:'..colors.cyan..',back:'..colors.black +lexers.STYLE_CLASS = 'fore:' .. colors.blue +lexers.STYLE_COMMENT = 'fore:' .. colors.light_gray .. ',italics' +lexers.STYLE_CONSTANT = 'fore:' .. colors.cyan +lexers.STYLE_DEFINITION = 'fore:' .. colors.green +lexers.STYLE_ERROR = 'fore:' .. colors.light_cyan .. ',italics' +lexers.STYLE_FUNCTION = 'fore:' .. colors.light_cyan .. ',bold' +lexers.STYLE_HEADING = 'fore:' .. colors.bg .. ',back:' .. colors.yellow +lexers.STYLE_KEYWORD = 'fore:' .. colors.cyan .. ',bold' +lexers.STYLE_LABEL = 'fore:' .. colors.blue +lexers.STYLE_NUMBER = 'fore:' .. colors.magenta +lexers.STYLE_OPERATOR = 'fore:' .. colors.light_cyan +lexers.STYLE_REGEX = 'fore:' .. colors.orange +lexers.STYLE_STRING = 'fore:' .. colors.green +lexers.STYLE_PREPROCESSOR = 'fore:' .. colors.blue +lexers.STYLE_TAG = 'fore:' .. colors.blue +lexers.STYLE_TYPE = 'fore:' .. colors.cyan +lexers.STYLE_VARIABLE = 'fore:' .. colors.cyan .. ',bold' +lexers.STYLE_WHITESPACE = 'fore:' .. colors.light_black +lexers.STYLE_EMBEDDED = 'fore:' .. colors.magenta +lexers.STYLE_IDENTIFIER = fg .. ',bold' + +lexers.STYLE_LINENUMBER = 'fore:' .. colors.light_black .. ',back:' .. colors.bg +lexers.STYLE_CURSOR = 'fore:' .. colors.bg .. ',back:' .. colors.fg +lexers.STYLE_CURSOR_PRIMARY = 'fore:' .. colors.bg .. ',back:' .. colors.fg +lexers.STYLE_CURSOR_LINE = 'back:' .. colors.black +lexers.STYLE_COLOR_COLUMN = 'back:' .. colors.black +lexers.STYLE_SELECTION = 'back:' .. colors.light_black +lexers.STYLE_STATUS = 'fore:' .. colors.gray .. ',back:' .. colors.black +lexers.STYLE_STATUS_FOCUSED = 'fore:' .. colors.cyan .. ',back:' .. colors.black lexers.STYLE_SEPARATOR = lexers.STYLE_DEFAULT lexers.STYLE_INFO = 'fore:default,back:default,bold' lexers.STYLE_EOF = '' @@ -67,9 +66,9 @@ lexers.STYLE_EOF = '' -- lexer specific styles -- Diff -lexers.STYLE_ADDITION = 'back:'..colors.green..',fore:'..colors.bg -lexers.STYLE_DELETION = 'back:'..colors.red..',fore:'..colors.bg -lexers.STYLE_CHANGE = 'back:'..colors.yellow..',fore:'..colors.bg +lexers.STYLE_ADDITION = 'back:' .. colors.green .. ',fore:' .. colors.bg +lexers.STYLE_DELETION = 'back:' .. colors.red .. ',fore:' .. colors.bg +lexers.STYLE_CHANGE = 'back:' .. colors.yellow .. ',fore:' .. colors.bg -- CSS lexers.STYLE_PROPERTY = lexers.STYLE_ATTRIBUTE @@ -91,19 +90,21 @@ lexers.STYLE_TARGET = '' -- Markdown lexers.STYLE_HR = '' -lexers.STYLE_HEADING_H1 = 'fore:'..colors.orange..',bold' -lexers.STYLE_HEADING_H2 = 'fore:'..colors.red..',bold' -for i = 3,6 do lexers['STYLE_HEADING_H'..i] = 'fore:'..colors.magenta..',bold' end +lexers.STYLE_HEADING_H1 = 'fore:' .. colors.orange .. ',bold' +lexers.STYLE_HEADING_H2 = 'fore:' .. colors.red .. ',bold' +for i = 3, 6 do + lexers['STYLE_HEADING_H' .. i] = 'fore:' .. colors.magenta .. ',bold' +end lexers.STYLE_BOLD = 'bold' lexers.STYLE_ITALIC = 'italics' lexers.STYLE_LIST = lexers.STYLE_KEYWORD -lexers.STYLE_LINK = 'fore:'..colors.yellow..',italics' -lexers.STYLE_REFERENCE = 'fore:'..colors.blue -lexers.STYLE_CODE = 'back:'..colors.black..',fore:'..colors.turquoise +lexers.STYLE_LINK = 'fore:' .. colors.yellow .. ',italics' +lexers.STYLE_REFERENCE = 'fore:' .. colors.blue +lexers.STYLE_CODE = 'back:' .. colors.black .. ',fore:' .. colors.turquoise -- Output lexers.STYE_FILENAME = 'bold' -lexers.STYLE_LINE = 'fore:'..colors.green +lexers.STYLE_LINE = 'fore:' .. colors.green lexers.STYLE_COLUMN = 'underline' lexers.STYLE_MESSAGE = '' @@ -111,13 +112,12 @@ lexers.STYLE_MESSAGE = '' lexers.STYLE_KEYWORD_SOFT = '' -- YAML -lexers.STYLE_ERROR_INDENT = 'back:'..colors.red - +lexers.STYLE_ERROR_INDENT = 'back:' .. colors.red -- GO -lexers.STYLE_CONSTANT_BUILTIN = 'fore:'..colors.yellow -lexers.STYLE_FUNCTION_METHOD = 'fore:'..colors.light_cyan -lexers.STYLE_FUNCTION_BUILTIN = 'fore:'..colors.light_cyan..',bold' +lexers.STYLE_CONSTANT_BUILTIN = 'fore:' .. colors.yellow +lexers.STYLE_FUNCTION_METHOD = 'fore:' .. colors.light_cyan +lexers.STYLE_FUNCTION_BUILTIN = 'fore:' .. colors.light_cyan .. ',bold' -- Lua -lexers.STYLE_ATTRIBUTE = 'fore:'..colors.yellow..',bold' +lexers.STYLE_ATTRIBUTE = 'fore:' .. colors.yellow .. ',bold' diff --git a/config/essentials/vis/title.lua b/config/essentials/vis/title.lua index c87088b..d743b63 100644 --- a/config/essentials/vis/title.lua +++ b/config/essentials/vis/title.lua @@ -1,22 +1,16 @@ require('vis') local function set_title(title) - -- print() cannot be used here as it will mess up vis - vis:command(string.format(":!printf '\\033]2;vis %s\\007'", title)) + -- print() cannot be used here as it will mess up vis + vis:command(string.format(":!printf '\\033]2;vis %s\\007'", title)) end -vis.events.subscribe(vis.events.INIT, function() - print('\27[22;2t') -end) +vis.events.subscribe(vis.events.INIT, function() print('\27[22;2t') end) -vis.events.subscribe(vis.events.WIN_OPEN, function(win) - set_title(win.file.name or '[No Name]') -end) +vis.events.subscribe(vis.events.WIN_OPEN, + function(win) set_title(win.file.name or '[No Name]') end) -vis.events.subscribe(vis.events.FILE_SAVE_POST, function(file) - set_title(file.name) -end) +vis.events.subscribe(vis.events.FILE_SAVE_POST, + function(file) set_title(file.name) end) -vis.events.subscribe(vis.events.QUIT, function() - print('\27[23;2t') -end) +vis.events.subscribe(vis.events.QUIT, function() print('\27[23;2t') end) diff --git a/config/essentials/vis/visrc.lua b/config/essentials/vis/visrc.lua index 05df7ee..3a9ff1d 100644 --- a/config/essentials/vis/visrc.lua +++ b/config/essentials/vis/visrc.lua @@ -1,41 +1,38 @@ ------------------------------------ --- LIBRARIES ------------------------------------ - require('vis') -- plugins +require("build") require("backup") require("cursors") require("title") +vis:command_register("make", function() vis:communicate() end, "make") ------------------------------------ --- FUNCTIONS ------------------------------------ local map_cmd = function(mode, map, command, help) - vis:map(mode, map, function() vis:command(command) end, help) + vis:map(mode, map, function() vis:command(command) end, help) end local map_cmd_restore = function(mode, map, command, help) - vis:map(mode, map, function() - if (mode == vis.modes.INSERT) then - vis:feedkeys("") - end - - vis:feedkeys("m") - vis:command(command) - vis:feedkeys("M") - - if (mode == vis.modes.INSERT) then - vis:feedkeys("i") - end - end, help) + vis:map(mode, map, function() + if (mode == vis.modes.INSERT) then vis:feedkeys("") end + + vis:feedkeys("m") + vis:command(command) + vis:feedkeys("M") + + if (mode == vis.modes.INSERT) then vis:feedkeys("i") end + end, help) end local map_keys = function(mode, map, keys, help) - vis:map(mode, map, function() vis:feedkeys(keys) end, help) + vis:map(mode, map, function() vis:feedkeys(keys) end, help) end ------------------------------------ @@ -49,6 +46,9 @@ local m = vis.modes ----------------------------------- vis:command_register("Q", function() vis:command("qa!") end, "Quit all") +vis:command_register("delws", + function() vis:command("x/[ \t]+$|^[ \t]+$/d") end, + "Remove trailing whitespace") ------------------------------------- --- MAPPINGS @@ -60,39 +60,37 @@ map_cmd(m.NORMAL, " c", "e ~/.config/vis/visrc.lua", "Edit config file") map_cmd(m.NORMAL, " q", "q!", "Quit (force)") map_cmd(m.NORMAL, " s", "!doas vis $vis_filepath", "Edit as superuser") map_cmd(m.NORMAL, " w", "w", "Write") -map_cmd(m.NORMAL, " x", "!chmod u+x $vis_filepath", "Make active file executable") +map_cmd(m.NORMAL, " x", "!chmod u+x $vis_filepath", + "Make active file executable") vis:map(m.NORMAL, " eh", function() - vis:command("!lowdown $vis_filepath > ${vis_filepath%.md}.html") - vis:info("exported.") + vis:command("!lowdown $vis_filepath > ${vis_filepath%.md}.html") + vis:info("exported.") end, "Export markdown to html") map_keys(m.NORMAL, " nl", ":", "Remove trailing whitespace") -- select markdown list element: ,x/^(\d+\.|[-*])\s+.+\n(^ .+\n)*/ - - ------------------------------------ --- EVENTS ------------------------------------ vis.events.subscribe(vis.events.INIT, function() - vis.options.ignorecase = true - vis.options.autoindent = true - vis.options.shell = "/bin/sh" - local theme = "nord" - vis:command("set theme " .. theme) + vis.options.ignorecase = true + vis.options.autoindent = true + vis.options.shell = "/bin/sh" + local theme = "nord" + vis:command("set theme " .. theme) end) -vis.events.subscribe(vis.events.WIN_OPEN, function(win) -- luacheck: no unused args - win.options.relativenumbers = true - - if win.syntax == "bash" then - map_keys(m.NORMAL, " v", - "V:x/^(\\s*)(.+)$/ c/\\1>\\&2 printf '\\2: %s\\\\n' \"$\\2\"/", "Print variable") - end +vis.events.subscribe(vis.events.WIN_OPEN, + function(win) -- luacheck: no unused args + win.options.relativenumbers = true + if win.syntax == "bash" then + map_keys(m.NORMAL, " v", + "V:x/^(\\s*)(.+)$/ c/\\1>\\&2 printf '\\2: %s\\\\n' \"$\\2\"/", + "Print variable") + end end) - -- cgit v1.2.3 From a0f45aece21a6280633023ec84f60eb0d5e0849a Mon Sep 17 00:00:00 2001 From: Raymaekers Luca Date: Thu, 20 Jun 2024 23:46:00 +0200 Subject: checkpoint --- config/essentials/vis/Makefile | 2 +- config/essentials/vis/commentary.lua | 251 ++++++++++++++++++++++++++++++++ config/essentials/vis/complete-line.lua | 141 ++++++++++++++++++ config/essentials/vis/cursors.lua | 12 +- config/essentials/vis/format.lua | 131 +++++++++++++++++ config/essentials/vis/visrc.lua | 108 ++++++++------ 6 files changed, 593 insertions(+), 52 deletions(-) create mode 100644 config/essentials/vis/commentary.lua create mode 100644 config/essentials/vis/complete-line.lua create mode 100644 config/essentials/vis/format.lua (limited to 'config/essentials/vis/cursors.lua') diff --git a/config/essentials/vis/Makefile b/config/essentials/vis/Makefile index be230e3..1599b58 100644 --- a/config/essentials/vis/Makefile +++ b/config/essentials/vis/Makefile @@ -2,7 +2,7 @@ LUA_FILES := $(shell find . -name "*.lua") -all: check format +all: format check check: luacheck --no-color --globals=vis -- $(LUA_FILES) diff --git a/config/essentials/vis/commentary.lua b/config/essentials/vis/commentary.lua new file mode 100644 index 0000000..26d06b5 --- /dev/null +++ b/config/essentials/vis/commentary.lua @@ -0,0 +1,251 @@ +-- +-- vis-commentary +-- +local comment_string = { + actionscript = '//', + ada = '--', + ansi_c = '/*|*/', + antlr = '//', + apdl = '!', + apl = '#', + applescript = '--', + asp = '\'', + autoit = ';', + awk = '#', + b_lang = '//', + bash = '#', + batch = ':', + bibtex = '%', + boo = '#', + chuck = '//', + cmake = '#', + coffeescript = '#', + context = '%', + cpp = '//', + crystal = '#', + csharp = '//', + css = '/*|*/', + cuda = '//', + dart = '//', + desktop = '#', + django = '{#|#}', + dmd = '//', + dockerfile = '#', + dot = '//', + eiffel = '--', + elixir = '#', + erlang = '%', + faust = '//', + fennel = ';;', + fish = '#', + forth = '|\\', + fortran = '!', + fsharp = '//', + gap = '#', + gettext = '#', + gherkin = '#', + glsl = '//', + gnuplot = '#', + go = '//', + groovy = '//', + gtkrc = '#', + haskell = '--', + html = '', + icon = '#', + idl = '//', + inform = '!', + ini = '#', + Io = '#', + java = '//', + javascript = '//', + json = '/*|*/', + jsp = '//', + latex = '%', + ledger = '#', + less = '//', + lilypond = '%', + lisp = ';', + logtalk = '%', + lua = '--', + makefile = '#', + markdown = '', + matlab = '#', + moonscript = '--', + myrddin = '//', + nemerle = '//', + nsis = '#', + objective_c = '//', + pascal = '//', + perl = '#', + php = '//', + pico8 = '//', + pike = '//', + pkgbuild = '#', + prolog = '%', + props = '#', + protobuf = '//', + ps = '%', + pure = '//', + python = '#', + rails = '#', + rc = '#', + rebol = ';', + rest = '.. ', + rexx = '--', + rhtml = '', + rstats = '#', + ruby = '#', + rust = '//', + sass = '//', + scala = '//', + scheme = ';', + smalltalk = '"|"', + sml = '(*)', + snobol4 = '#', + sql = '#', + tcl = '#', + tex = '%', + text = '', + toml = '#', + vala = '//', + vb = '\'', + vbscript = '\'', + verilog = '//', + vhdl = '--', + wsf = '', + xml = '', + yaml = '#', + zig = '//', + nim = '#', + julia = '#', + rpmspec = '#' +} + +-- escape all magic characters with a '%' +local function esc(str) + if not str then return "" end + return (str:gsub('%%', '%%%%'):gsub('^%^', '%%^'):gsub('%$$', '%%$'):gsub( + '%(', '%%('):gsub('%)', '%%)'):gsub('%.', '%%.') + :gsub('%[', '%%['):gsub('%]', '%%]'):gsub('%*', '%%*') + :gsub('%+', '%%+'):gsub('%-', '%%-'):gsub('%?', '%%?')) +end + +-- escape '%' +local function pesc(str) + if not str then return "" end + return str:gsub('%%', '%%%%') +end + +local function rtrim(s) + local n = #s + while n > 0 and s:find("^%s", n) do n = n - 1 end + return s:sub(1, n) +end + +local function comment_line(lines, lnum, prefix, suffix) + if suffix ~= "" then suffix = " " .. suffix end + lines[lnum] = string.gsub(lines[lnum], "(%s*)(.*)", + "%1" .. pesc(prefix) .. " %2" .. pesc(suffix)) +end + +local function uncomment_line(lines, lnum, prefix, suffix) + local match_str = "^(%s*)" .. esc(prefix) .. "%s?(.*)" .. esc(suffix) + local m = table.pack(lines[lnum]:match(match_str)) + lines[lnum] = m[1] .. rtrim(m[2]) +end + +local function is_comment(line, prefix) + return (line:match("^%s*(.+)"):sub(0, #prefix) == prefix) +end + +local function toggle_line_comment(lines, lnum, prefix, suffix) + if not lines or not lines[lnum] then return end + if not lines[lnum]:match("^%s*(.+)") then return end -- ignore empty lines + if is_comment(lines[lnum], prefix) then + uncomment_line(lines, lnum, prefix, suffix) + else + comment_line(lines, lnum, prefix, suffix) + end +end + +-- if one line inside the block is not a comment, comment the block. +-- only uncomment, if every single line is comment. +local function block_comment(lines, a, b, prefix, suffix) + local uncomment = true + for i = a, b do + if lines[i]:match("^%s*(.+)") and not is_comment(lines[i], prefix) then + uncomment = false + end + end + + if uncomment then + for i = a, b do + if lines[i]:match("^%s*(.+)") then + uncomment_line(lines, i, prefix, suffix) + end + end + else + for i = a, b do + if lines[i]:match("^%s*(.+)") then + comment_line(lines, i, prefix, suffix) + end + end + end +end + +vis:map(vis.modes.NORMAL, "gcc", function() + local win = vis.win + local lines = win.file.lines + local comment = comment_string[win.syntax] + if not comment then return end + local prefix, suffix = comment:match('^([^|]+)|?([^|]*)$') + if not prefix then return end + + for sel in win:selections_iterator() do + local lnum = sel.line + local col = sel.col + + toggle_line_comment(lines, lnum, prefix, suffix) + sel:to(lnum, col) -- restore cursor position + end + + win:draw() +end, "Toggle comment on a the current line") + +local function visual_f(i) + return function() + local win = vis.win + local lines = win.file.lines + + local comment = comment_string[win.syntax] + if not comment then return end + + local prefix, suffix = comment:match('^([^|]+)|?([^|]*)$') + if not prefix then return end + + for sel in win:selections_iterator() do + local r = sel.range + local lnum = sel.line -- line number of cursor + local col = sel.col -- column of cursor + + if sel.anchored and r then + sel.pos = r.start + local a = sel.line + sel.pos = r.finish + local b = sel.line - i + + block_comment(lines, a, b, prefix, suffix) + + sel:to(lnum, col) -- restore cursor position + end + end + + win:draw() + vis.mode = vis.modes.NORMAL -- go to normal mode + end +end + +vis:map(vis.modes.VISUAL_LINE, "gc", visual_f(1), + "Toggle comment on the selected lines") +vis:map(vis.modes.VISUAL, "gc", visual_f(0), + "Toggle comment on the selected lines") diff --git a/config/essentials/vis/complete-line.lua b/config/essentials/vis/complete-line.lua new file mode 100644 index 0000000..93728a3 --- /dev/null +++ b/config/essentials/vis/complete-line.lua @@ -0,0 +1,141 @@ +-- SPDX-License-Identifier: GPL-3.0-or-later +-- © 2020 Georgi Kirilov +local progname = ... + +local lpeg = require("lpeg") +local R, C, Cmt = lpeg.R, lpeg.C, lpeg.Cmt + +-- copied from vis.h +local VIS_MOVE_NOP = 64 + +local cont = R("\128\191") + +local charpattern = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * + cont + R("\240\244") * cont * cont * cont + +local function concat_keys(tbl) + local keys = {} + for k in pairs(tbl) do table.insert(keys, k) end + return table.concat(keys, "\n"), #keys +end + +local function line_complete() + local file = vis.win.file + local sel = vis.win.selection + local cur_line = file.lines[sel.line] + local indent_patt = "^[ \t\v\f]+" + local prefix = cur_line:sub(1, sel.col - 1):gsub(indent_patt, "") + local candidates = {} + for l in file:lines_iterator() do + local unindented = l:gsub(indent_patt, "") + local start, finish = unindented:find(prefix, 1, true) + if start == 1 and finish < #unindented then + candidates[unindented] = true + end + end + local candidates_str, n = concat_keys(candidates) + if n < 2 then + if n == 1 then vis:insert(candidates_str:sub(#prefix + 1)) end + return + end + -- XXX: with too many candidates this command will become longer that the shell can handle: + local command = string.format("vis-menu -l %d <<'EOF'\n%s\nEOF\n", + math.min(n, math.ceil(vis.win.height / 2)), + candidates_str) + local status, output = vis:pipe(nil, nil, command) + if n > 0 and status == 0 then + vis:insert(output:sub(#prefix + 1):gsub("\n$", "")) + end +end + +local function selection_by_pos(pos) + for s in vis.win:selections_iterator() do + if s.pos == pos then return s end + end +end + +local function charwidth(cells_so_far, char) + if char == "\t" then + local tw = vis.tabwidth or 8 + local trail = cells_so_far % tw + return tw - trail + else + return 1 + end +end + +local function virtcol(line, col) + local ncells = 0 + local nchars = 0 + local function upto(_, _, char) + if nchars < col - 1 then + ncells = ncells + charwidth(ncells, char) + nchars = nchars + 1 + return true + end + end + (Cmt(C(charpattern), upto) ^ 0):match(line) + return ncells + 1 +end + +local function neighbor(lines, ln, col, direction) + local line = ln + direction > 0 and lines[ln + direction] + if not line then return end + local column = virtcol(lines[ln], col) + local ncells = 0 + local function upto(_, _, char) + ncells = ncells + charwidth(ncells, char) + return ncells < column + end + return + (Cmt(C(charpattern), upto) ^ (-column + 1) / 0 * C(charpattern)):match( + line) +end + +local function dup_neighbor(direction) + return function(file, _, pos) + local sel = selection_by_pos(pos) + local char = neighbor(file.lines, sel.line, sel.col, direction) + if not char then return pos end + file:insert(pos, char) + return pos + #char + end +end + +local function dup_neighbor_feedkeys(direction) + local sel = vis.win.selection + local file = vis.win.file + local char = neighbor(file.lines, sel.line, sel.col, direction) + if not char then return end + vis:feedkeys(char) +end + +local function operator(handler) + local id = vis:operator_register(handler) + return id >= 0 and function() + vis:operator(id) + vis:motion(VIS_MOVE_NOP) + end +end + +vis.events.subscribe(vis.events.INIT, function() + local function h(msg) return string.format("|@%s| %s", progname, msg) end + + local function column_complete(direction) + local binding = operator(dup_neighbor(direction)) + return function() + if #vis.win.selections == 1 then + dup_neighbor_feedkeys(direction) + else + return binding() + end + end + end + + vis:map(vis.modes.INSERT, "", column_complete(-1), + h "Insert the character which is above the cursor") + vis:map(vis.modes.INSERT, "", column_complete(1), + h "Insert the character which is below the cursor") + vis:map(vis.modes.INSERT, "", line_complete, + h "Complete the current line") +end) diff --git a/config/essentials/vis/cursors.lua b/config/essentials/vis/cursors.lua index 37165b6..5b3d43b 100644 --- a/config/essentials/vis/cursors.lua +++ b/config/essentials/vis/cursors.lua @@ -6,7 +6,7 @@ local files = {} M.maxsize = 1000 -- get the default system cache directory -local get_default_cache_path = function() +local function get_default_cache_path() local HOME = os.getenv('HOME') local XDG_CACHE_HOME = os.getenv('XDG_CACHE_HOME') local BASE = XDG_CACHE_HOME or HOME @@ -16,7 +16,7 @@ end -- default save path M.path = get_default_cache_path() -local read_files = function() +local function read_files() -- read file local file = io.open(M.path) @@ -36,10 +36,10 @@ local read_files = function() end -- read cursors from file on init -local on_init = function() read_files() end +local function on_init() read_files() end -- apply cursor pos on win open -local on_win_open = function(win) +local function on_win_open(win) if win.file == nil or win.file.path == nil then return end @@ -58,7 +58,7 @@ local on_win_open = function(win) end -- set cursor pos on close -local on_win_close = function(win) +local function on_win_close(win) if win.file == nil or win.file.path == nil then return end @@ -81,7 +81,7 @@ local on_win_close = function(win) end -- write cursors to file on quit -local on_quit = function() +local function on_quit() local file = io.open(M.path, 'w+') if file == nil then return end diff --git a/config/essentials/vis/format.lua b/config/essentials/vis/format.lua new file mode 100644 index 0000000..15488dd --- /dev/null +++ b/config/essentials/vis/format.lua @@ -0,0 +1,131 @@ +local global_options = {check_same = true} + +local function stdio_formatter(cmd, options) + local function apply(win, range, pos) + local size = win.file.size + local all = {start = 0, finish = size} + if range == nil then range = all end + local command = type(cmd) == 'function' and cmd(win, range, pos) or cmd + local check_same = (options and options.check_same ~= nil) and + options.check_same or global_options.check_same + local check = check_same == true or + (type(check_same) == 'number' and check_same >= size) + local status, out, err = vis:pipe(win.file, all, command) + if status ~= 0 then + vis:message(err) + elseif out == nil or out == '' then + vis:info('No output from formatter') + elseif not check or win.file:content(all) ~= out then + local start, finish = range.start, range.finish + win.file:delete(range) + win.file:insert(start, + out:sub(start + 1, finish + (out:len() - size))) + end + return pos + end + return { + apply = apply, + options = options or {ranged = type(cmd) == 'function'} + } +end + +local function with_filename(win, option) + if win.file.path then + return option .. "'" .. win.file.path:gsub("'", "\\'") .. "'" + else + return '' + end +end + +local formatters = {} +formatters = { + bash = stdio_formatter(function(win) + return 'shfmt ' .. with_filename(win, '--filename ') .. ' -' + end), + csharp = stdio_formatter('dotnet csharpier'), + go = stdio_formatter('gofmt'), + lua = { + pick = function(win) + local _, out = vis:pipe(win.file, + {start = 0, finish = win.file.size}, + 'test -e .lua-format && echo luaformatter || echo stylua') + return formatters[out:gsub('\n$', '')] + end + }, + luaformatter = stdio_formatter('lua-format'), + markdown = stdio_formatter(function(win) + if win.options and win.options.colorcolumn ~= 0 then + return 'prettier --parser markdown --prose-wrap always ' .. + ('--print-width ' .. (win.options.colorcolumn - 1) .. ' ') .. + with_filename(win, '--stdin-filepath ') + else + return 'prettier --parser markdown ' .. + with_filename(win, '--stdin-filepath ') + end + end, {ranged = false}), + powershell = stdio_formatter([[ + "$( (command -v powershell.exe || command -v pwsh) 2>/dev/null )" -c ' + Invoke-Formatter -ScriptDefinition ` + ([IO.StreamReader]::new([Console]::OpenStandardInput()).ReadToEnd()) + ' | sed -e :a -e '/^[\r\n]*$/{$d;N;};/\n$/ba' + ]]), + rust = stdio_formatter('rustfmt'), + stylua = stdio_formatter(function(win, range) + if range and (range.start ~= 0 or range.finish ~= win.file.size) then + return + 'stylua -s --range-start ' .. range.start .. ' --range-end ' .. + range.finish .. with_filename(win, ' --stdin-filepath ') .. + ' -' + else + return 'stylua -s ' .. with_filename(win, '--stdin-filepath ') .. + ' -' + end + end), + text = stdio_formatter(function(win) + if win.options and win.options.colorcolumn ~= 0 then + return 'fmt -w ' .. (win.options.colorcolumn - 1) + else + return 'fmt' + end + end, {ranged = false}) +} + +local function getwinforfile(file) + for win in vis:windows() do + if win and win.file and win.file.path == file.path then + return win + end + end +end + +local function apply(file_or_keys, range, pos) + local win = + type(file_or_keys) ~= 'string' and getwinforfile(file_or_keys) or + vis.win + local ret = type(file_or_keys) ~= 'string' and function() return pos end or + function() return 0 end + pos = pos or win.selection.pos + local formatter = formatters[win.syntax] + if formatter and formatter.pick then formatter = formatter.pick(win) end + if formatter == nil then + vis:info('No formatter for ' .. win.syntax) + return ret() + end + if range ~= nil and not formatter.options.ranged and range.start ~= 0 and + range.finish ~= win.file.size then + vis:info('Formatter for ' .. win.syntax .. ' does not support ranges') + return ret() + end + pos = formatter.apply(win, range, pos) or pos + vis:insert('') -- redraw and friends don't work + win.selection.pos = pos + return ret() +end + +return { + formatters = formatters, + options = global_options, + apply = apply, + stdio_formatter = stdio_formatter, + with_filename = with_filename +} diff --git a/config/essentials/vis/visrc.lua b/config/essentials/vis/visrc.lua index 3a9ff1d..60162bc 100644 --- a/config/essentials/vis/visrc.lua +++ b/config/essentials/vis/visrc.lua @@ -1,71 +1,83 @@ ------------------------------------ --- LIBRARIES ------------------------------------ -require('vis') +require("vis") -- plugins require("build") require("backup") require("cursors") require("title") +require("commentary") +require("complete-line") +local format = require("format") -vis:command_register("make", function() vis:communicate() end, "make") +-- todo: +-- c-scope +-- c-tags ------------------------------------ ---- FUNCTIONS +--- VARIABLES ------------------------------------ -local map_cmd = function(mode, map, command, help) - vis:map(mode, map, function() vis:command(command) end, help) -end - -local map_cmd_restore = function(mode, map, command, help) - vis:map(mode, map, function() - if (mode == vis.modes.INSERT) then vis:feedkeys("") end +local m = vis.modes - vis:feedkeys("m") - vis:command(command) - vis:feedkeys("M") +------------------------------------ +--- FUNCTIONS +------------------------------------ - if (mode == vis.modes.INSERT) then vis:feedkeys("i") end - end, help) +local function map_cmd(mode, map, command, help) + vis:map(mode, map, function() + vis:command(command) + end, help) end -local map_keys = function(mode, map, keys, help) - vis:map(mode, map, function() vis:feedkeys(keys) end, help) +-- TOOD: use window selection to restore position +local function wrap_restore(f, ...) + local pos = vis.win.selection.pos + f(...) + vis.win.selection.pos = pos end ------------------------------------- ---- VARIABLES ------------------------------------- - -local m = vis.modes +local function map_keys(mode, map, keys, help) + vis:map(mode, map, function() + vis:feedkeys(keys) + end, help) +end ------------------------------------ --- COMMANDS ----------------------------------- -vis:command_register("Q", function() vis:command("qa!") end, "Quit all") -vis:command_register("delws", - function() vis:command("x/[ \t]+$|^[ \t]+$/d") end, - "Remove trailing whitespace") +vis:command_register("make", function() + vis:command("!make && head -n 1") +end, "make") +vis:command_register("Q", function() + vis:command("qa!") +end, "Quit all") +vis:command_register("delws", function() + vis:command("x/[ \t]+$|^[ \t]+$/d") +end, "Remove trailing whitespace") ------------------------------------- --- MAPPINGS ------------------------------------- -map_cmd_restore(m.NORMAL, " r", "e $vis_filepath", "Reload active file") +vis:map(m.NORMAL, " r", function() + wrap_restore(vis.command, vis, "e $vis_filepath") +end, "Reload active file") + +vis:map(m.NORMAL, "=", format.apply, "Format active file") map_cmd(m.NORMAL, " c", "e ~/.config/vis/visrc.lua", "Edit config file") map_cmd(m.NORMAL, " q", "q!", "Quit (force)") map_cmd(m.NORMAL, " s", "!doas vis $vis_filepath", "Edit as superuser") map_cmd(m.NORMAL, " w", "w", "Write") -map_cmd(m.NORMAL, " x", "!chmod u+x $vis_filepath", - "Make active file executable") +map_cmd(m.NORMAL, " x", "!chmod u+x $vis_filepath", "Make active file executable") vis:map(m.NORMAL, " eh", function() - vis:command("!lowdown $vis_filepath > ${vis_filepath%.md}.html") - vis:info("exported.") + vis:command("!lowdown $vis_filepath > ${vis_filepath%.md}.html") + vis:info("exported.") end, "Export markdown to html") map_keys(m.NORMAL, " nl", ":\\&2 printf '\\2: %s\\\\n' \"$\\2\"/", - "Print variable") - end +vis.events.subscribe(vis.events.WIN_OPEN, function(win) -- luacheck: no unused args + win.options.relativenumbers = true + + if win.syntax == "bash" then + map_keys( + m.NORMAL, + " v", + "V:x/^(\\s*)(.+)$/ c/\\1>\\&2 printf '\\2: %s\\\\n' \"$\\2\"/", + "Print variable" + ) + end + + vis:command_register("pipe", function() + vis:pipe(win.file, nil, "sed 's/.*/- &/'") + end, "pipe test") end) -- cgit v1.2.3