48e5e95
Branches > main > 48e5e95 > files / nvim / pack
Merge pc and chromebook dotfiles
Commit: 48e5e95d788afa747af490965fae031974e434c2
Parent: a1efde1
Parent: 751a2dd
157 changed files:
i3/config view file
@@ -36,7 +36,7 @@ bindsym $mod+Shift+0 move container to workspace number 0 bindsym $mod+r reload-bindsym $mod+Shift+R restart+bindsym $mod+Shift+r restart bindsym $mod+e exec maim | tee ~/Pictures/$(date '+%Y-%m-%d_%H-%M-%S').png | xclip -selection clipboard -t image/png bindsym $mod+w exec maim -s | tee ~/Pictures/$(date '+%Y-%m-%d_%H-%M-%S').png | xclip -selection clipboard -t image/pngnixos/machines/pc/configuration.nix view file
@@ -27,6 +27,9 @@ package = config.boot.kernelPackages.nvidiaPackages.stable; }; + ## More ai smiesmie+ boot.kernelParams = [ "usbcore.autosuspend=-1" ];+ services.usbmuxd = { enable = true; package = pkgs.usbmuxd2;@@ -56,6 +59,8 @@ services.openssh = { enable = true;+ passwordAuthentication = false;+ permitRootLogin = "no"; }; programs.fish.enable = true;@@ -71,6 +76,17 @@ hardware.steam-hardware.enable = true; + boot.extraModulePackages = with config.boot.kernelPackages; [+ v4l2loopback+ ];+ boot.kernelModules = [ "v4l2loopback" ];+ boot.extraModprobeConfig = ''+ options v4l2loopback devices=1 video_nr=2 card_label="OBS Virtual Camera" exclusive_caps=1 formats=YUYV,MJPEG+ '';+ security.polkit.enable = true;++ programs.obs-studio.enableVirtualCamera = true;+ ## No touchy says the comment! system.stateVersion = "24.11"; }nixos/machines/pc/home.nix view file
@@ -49,9 +49,11 @@ clojure-lsp cljfmt lua-language-server+ jdt-language-server fzf librewolf ## TODO config!+ qutebrowser tor-browser ungoogled-chromium @@ -89,6 +91,8 @@ flatpak jdk25+ # jdk21+ kotlin-language-server # K****n clojure babashka@@ -123,5 +127,15 @@ killall filezilla++ signal-desktop++ docker+ zig++ protontricks+ freetype++ qgis ]; }nixos/pkgs/base.nix view file
@@ -0,0 +1,97 @@+{ pkgs, ... }:++with pkgs; [+ nerd-fonts.jetbrains-mono+ # steam+ ghostty++ # vesktop+ # slack++ neovim+ tree-sitter+ fennel-ls+ fnlfmt+ clj-kondo+ clojure-lsp+ cljfmt+ lua-language-server+ jdt-language-server+ fzf++ librewolf ## TODO config!+ # tor-browser+ # ungoogled-chromium++ obsidian+ # gimp+ i3+ nautilus+ pavucontrol++ # libimobiledevice+ # ifuse++ # prismlauncher++ libreoffice+ maim+ xclip++ usbutils+ inotify-tools++ unzip+ git+ lazygit+ rlwrap+ # ed # It's the standard editor, you know?+ fish+ lsd+ dig+ ripgrep+ dmenu++ bluez++ flatpak++ jdk25++ clojure+ babashka++ # gcc++ lua54Packages.fennel++ luajit++ # nodejs+ # bun++ cloc+ mpv+ loupe+ vlc+ ffmpeg++ # obs-studio+ # audacity++ bundler+ jekyll++ # shotcut++ # amberol++ killall++ # filezilla++ # signal-desktop++ # docker+ zig+]nixos/pkgs/laptop.nix view file
nixos/pkgs/pc.nix view file
nvim/ftplugin/clojure.lua view file
@@ -0,0 +1 @@+require("plugins.conjure")nvim/ftplugin/markdown.lua view file
@@ -0,0 +1,5 @@+local ol = vim.opt_local+ol.wrap = true+ol.linebreak = true+ol.spell = true+ol.columns = 80nvim/init.lua view file
@@ -5,16 +5,17 @@ require("center") require("opts")-require("filetype") local nvim_arg = vim.fn.argv(0) if vim.fn.isdirectory(nvim_arg) == 1 then require("plugins.oil").open(nvim_arg) end -vim.schedule(function() require("keybindings") end)-vim.schedule(function() require("lsp") end)-vim.schedule(function() require("lazy_ui") end)+vim.schedule(function()+ require("keybindings")+ require("lsp")+ require("lazy_ui")+end) --- TODO there's a bug tha parens and virtual text likes to stick around for longer than it should... nvim/lua/filetype.lua view file
@@ -1,6 +0,0 @@-vim.api.nvim_create_autocmd("FileType", {- pattern = "clojure",- callback = function()- require("plugins.conjure")- end,-})nvim/lua/keybindings.lua view file
@@ -50,6 +50,7 @@ keymap({"n", "v", "o"}, ";", function() require("jump").jump() end) +-- Needs to hook into things so is loaded here local smart_n = require("smart_n").smart_n keymap({"n", "v", "o"}, "n", function() return smart_n(false) end, {expr = true, noremap = true})nvim/lua/lsp.lua view file
@@ -19,12 +19,27 @@ lsp.enable(name) end ---- TODO hopefully this works :p config({name = "clojure-lsp", filetypes = {"clojure"}, root_markers = {"project.clj", "deps.edn", "build.boot", "shadow-cljs.edn", ".git", "bb.edn"}}) +config({name = "kotlin-language-server",+ filetypes = {"kotlin"},+ root_markers = {"build.gradle.kts", "gradlew", ".git"}})+ config({name = "lua-language-server", filetypes = {"lua"}, settings = {Lua = {diagnostics = {globals = {"vim"}}}}, root_markers = {".luarc.json", ".luarc.jsonc", ".luacheckrc", ".stylua.toml", "stylua.toml", "selene.toml", "selene.yml", ".git"}})++config({name = "jdtls",+ filetypes = {"java"},+ root_markers = {"mvnw",+ "gradlew",+ "settings.gradle",+ "settings.gradle.kts",+ ".git",+ "build.xml",+ "pom.xml",+ "build.gradle",+ "build.gradle.kts"}})nvim/lua/oil/LICENSE nvim/pack/plugins/opt/oil.nvim/LICENSE view file
nvim/lua/oil/actions.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/actions.lua view file
nvim/lua/oil/adapters/files.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/files.lua view file
nvim/lua/oil/adapters/files/permissions.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/files/permissions.lua view file
nvim/lua/oil/adapters/s3.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/s3.lua view file
nvim/lua/oil/adapters/s3/s3fs.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/s3/s3fs.lua view file
nvim/lua/oil/adapters/ssh.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/ssh.lua view file
nvim/lua/oil/adapters/ssh/connection.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/ssh/connection.lua view file
nvim/lua/oil/adapters/ssh/sshfs.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/ssh/sshfs.lua view file
nvim/lua/oil/adapters/test.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/test.lua view file
nvim/lua/oil/adapters/trash.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/trash.lua view file
nvim/lua/oil/adapters/trash/freedesktop.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/trash/freedesktop.lua view file
nvim/lua/oil/adapters/trash/mac.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/trash/mac.lua view file
nvim/lua/oil/adapters/trash/windows.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/trash/windows.lua view file
nvim/lua/oil/adapters/trash/windows/powershell-connection.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/trash/windows/powershell-connection.lua view file
nvim/lua/oil/adapters/trash/windows/powershell-trash.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/adapters/trash/windows/powershell-trash.lua view file
nvim/lua/oil/cache.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/cache.lua view file
nvim/lua/oil/clipboard.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/clipboard.lua view file
nvim/lua/oil/columns.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/columns.lua view file
nvim/lua/oil/config.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/config.lua view file
nvim/lua/oil/constants.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/constants.lua view file
nvim/lua/oil/fs.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/fs.lua view file
nvim/lua/oil/git.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/git.lua view file
nvim/lua/oil/init.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/init.lua view file
nvim/lua/oil/keymap_util.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/keymap_util.lua view file
nvim/lua/oil/layout.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/layout.lua view file
nvim/lua/oil/loading.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/loading.lua view file
nvim/lua/oil/log.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/log.lua view file
nvim/lua/oil/lsp/helpers.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/lsp/helpers.lua view file
nvim/lua/oil/lsp/workspace.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/lsp/workspace.lua view file
nvim/lua/oil/mutator/confirmation.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/mutator/confirmation.lua view file
nvim/lua/oil/mutator/init.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/mutator/init.lua view file
nvim/lua/oil/mutator/parser.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/mutator/parser.lua view file
nvim/lua/oil/mutator/progress.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/mutator/progress.lua view file
nvim/lua/oil/mutator/trie.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/mutator/trie.lua view file
nvim/lua/oil/pathutil.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/pathutil.lua view file
nvim/lua/oil/ringbuf.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/ringbuf.lua view file
nvim/lua/oil/shell.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/shell.lua view file
nvim/lua/oil/util.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/util.lua view file
nvim/lua/oil/view.lua nvim/pack/plugins/opt/oil.nvim/lua/oil/view.lua view file
nvim/lua/parinfer/LICENSE view file
@@ -0,0 +1,674 @@+ GNU GENERAL PUBLIC LICENSE+ Version 3, 29 June 2007++ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++ Preamble++ The GNU General Public License is a free, copyleft license for+ software and other kinds of works.++ The licenses for most software and other practical works are designed+ to take away your freedom to share and change the works. By contrast,+ the GNU General Public License is intended to guarantee your freedom to+ share and change all versions of a program--to make sure it remains free+ software for all its users. We, the Free Software Foundation, use the+ GNU General Public License for most of our software; it applies also to+ any other work released this way by its authors. You can apply it to+ your programs, too.++ When we speak of free software, we are referring to freedom, not+ price. Our General Public Licenses are designed to make sure that you+ have the freedom to distribute copies of free software (and charge for+ them if you wish), that you receive source code or can get it if you+ want it, that you can change the software or use pieces of it in new+ free programs, and that you know you can do these things.++ To protect your rights, we need to prevent others from denying you+ these rights or asking you to surrender the rights. Therefore, you have+ certain responsibilities if you distribute copies of the software, or if+ you modify it: responsibilities to respect the freedom of others.++ For example, if you distribute copies of such a program, whether+ gratis or for a fee, you must pass on to the recipients the same+ freedoms that you received. You must make sure that they, too, receive+ or can get the source code. And you must show them these terms so they+ know their rights.++ Developers that use the GNU GPL protect your rights with two steps:+ (1) assert copyright on the software, and (2) offer you this License+ giving you legal permission to copy, distribute and/or modify it.++ For the developers' and authors' protection, the GPL clearly explains+ that there is no warranty for this free software. For both users' and+ authors' sake, the GPL requires that modified versions be marked as+ changed, so that their problems will not be attributed erroneously to+ authors of previous versions.++ Some devices are designed to deny users access to install or run+ modified versions of the software inside them, although the manufacturer+ can do so. This is fundamentally incompatible with the aim of+ protecting users' freedom to change the software. The systematic+ pattern of such abuse occurs in the area of products for individuals to+ use, which is precisely where it is most unacceptable. Therefore, we+ have designed this version of the GPL to prohibit the practice for those+ products. If such problems arise substantially in other domains, we+ stand ready to extend this provision to those domains in future versions+ of the GPL, as needed to protect the freedom of users.++ Finally, every program is threatened constantly by software patents.+ States should not allow patents to restrict development and use of+ software on general-purpose computers, but in those that do, we wish to+ avoid the special danger that patents applied to a free program could+ make it effectively proprietary. To prevent this, the GPL assures that+ patents cannot be used to render the program non-free.++ The precise terms and conditions for copying, distribution and+ modification follow.++ TERMS AND CONDITIONS++ 0. Definitions.++ "This License" refers to version 3 of the GNU General Public License.++ "Copyright" also means copyright-like laws that apply to other kinds of+ works, such as semiconductor masks.++ "The Program" refers to any copyrightable work licensed under this+ License. Each licensee is addressed as "you". "Licensees" and+ "recipients" may be individuals or organizations.++ To "modify" a work means to copy from or adapt all or part of the work+ in a fashion requiring copyright permission, other than the making of an+ exact copy. The resulting work is called a "modified version" of the+ earlier work or a work "based on" the earlier work.++ A "covered work" means either the unmodified Program or a work based+ on the Program.++ To "propagate" a work means to do anything with it that, without+ permission, would make you directly or secondarily liable for+ infringement under applicable copyright law, except executing it on a+ computer or modifying a private copy. Propagation includes copying,+ distribution (with or without modification), making available to the+ public, and in some countries other activities as well.++ To "convey" a work means any kind of propagation that enables othernvim/lua/parinfer/parinfer.lua view file
@@ -0,0 +1,1778 @@+-- parinfer.lua - a Parinfer implementation in Lua+-- v0.1.0+-- https://github.com/oakmac/parinfer-lua+--+-- More information about Parinfer can be found here:+-- http://shaunlebron.github.io/parinfer/+--+-- Copyright (c) 2021, Chris Oakman+-- Released under the ISC license+-- https://github.com/oakmac/parinfer-lua/blob/master/LICENSE.md++local M = {}++-- forward declarations+local resetParenTrail, rememberParenTrail, updateRememberedParenTrail++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Constants++local UINT_NULL = -999++local INDENT_MODE = "INDENT_MODE"+local PAREN_MODE = "PAREN_MODE"++local BACKSLASH = "\\"+local BLANK_SPACE = " "+local DOUBLE_SPACE = " "+local DOUBLE_QUOTE = '"'+local NEWLINE = "\n"+local TAB = "\t"++-- local LINE_ENDING_REGEX = /\r?\n/++local MATCH_PAREN = {}+MATCH_PAREN["{"] = "}"+MATCH_PAREN["}"] = "{"+MATCH_PAREN["["] = "]"+MATCH_PAREN["]"] = "["+MATCH_PAREN["("] = ")"+MATCH_PAREN[")"] = "("++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Development Helpers++-- NOTE: this is useful for development and debugging purposes+-- not required for the core library+-- local inspect = require("libs/inspect")++-- toggle this to check the asserts during development+local RUN_ASSERTS = false++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Type Predicates++local function isBoolean(x)+ return x == true or x == false+end++local function isTable(t)+ return type(t) == "table"+end++local function isInteger(i)+ return type(i) == "number" and i == math.floor(i)+end++if RUN_ASSERTS then+ assert(isInteger(1))+ assert(isInteger(-97))+ assert(not isInteger(3.14))+ assert(not isInteger())+ assert(not isInteger({}))+ assert(not isInteger("6"))+end++local function isPositiveInt(i)+ return isInteger(i) and i >= 0+end++local function isString(s)+ return type(s) == "string"+end++if RUN_ASSERTS then+ assert(isString("s"))+ assert(not isString(true))+end++local function isChar(c)+ return isString(c) and string.len(c) == 1+end++if RUN_ASSERTS then+ assert(isChar("s"))+ assert(not isChar("xx"))+ assert(not isChar(true))+end++local function isTableOfChars(t)+ if not isTable(t) then+ return false+ end++ for _key, ch in pairs(t) do+ if not isChar(ch) then+ return false+ end+ end++ return true+end++if RUN_ASSERTS then+ assert(isTableOfChars({}))+ assert(isTableOfChars({"a", "b", "c"}))+ assert(not isTableOfChars({"a", "b", "ccc"}))+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Language Helpers++local function isTableEmpty(t)+ for _key, _val in pairs(t) do+ return false+ end+ return true+end++if RUN_ASSERTS then+ assert(isTableEmpty({}))+ assert(not isTableEmpty({"a", "b"}))+end++local function tableSize(t)+ if RUN_ASSERTS then+ assert(isTable(t), "used tableSize with not an Table")+ end++ local count = 0+ for _key, _val in pairs(t) do+ count = count + 1+ end+ return count+end++if RUN_ASSERTS then+ assert(tableSize({}) == 0)+ assert(tableSize({"a", "b"}) == 2)+ assert(tableSize({"a", "b", "c", "d", "e"}) == 5)+ assert(tableSize({a = "a", b = "b"}) == 2)+end++local function strLen(s)+ if RUN_ASSERTS then+ assert(isString(s), "used strLen with not a String")+ end+ return string.len(s)+end++local function strConcat(s1, s2)+ if RUN_ASSERTS then+ assert(isString(s1), "strConcat argument s1 is not a String")+ assert(isString(s2), "strConcat argument s2 is not a String")+ end+ return s1 .. s2+end++local function getCharFromString(s, idx)+ if RUN_ASSERTS then+ assert(isString(s), "getCharFromString argument s is not a String")+ assert(isInteger(idx), "getCharFromString argument idx is not an Integer")+ end+ return string.sub(s, idx, idx)+end++if RUN_ASSERTS then+ assert(getCharFromString("abc", 1) == "a")+ assert(getCharFromString("abc", 2) == "b")+end++local function strJoin(tbl, delimiter)+ if RUN_ASSERTS then+ assert(isTable(tbl), "strJoin argument tbl is not a Table")+ assert(isString(delimiter), "strJoin argument delimiter is not a String")+ end++ return table.concat(tbl, delimiter)+end++if RUN_ASSERTS then+ assert(strJoin({"a", "b", "c"}, "") == "abc")+ assert(strJoin({"a", "b", "c"}, "x") == "axbxc")+ assert(strJoin({"a", "b", "c"}, "\n") == "a\nb\nc")+ assert(strJoin({"a", "b", "c", "dd"}, "zz") == "azzbzzczzdd")+ assert(strJoin({}, "z") == "")+ assert(strJoin({}, "") == "")+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- String Operations++local function replaceWithinString(orig, startIdx, endIdx, replace)+ local head = string.sub(orig, 1, startIdx - 1)+ local tail = string.sub(orig, endIdx, -1)+ return head .. replace .. tail+end++if RUN_ASSERTS then+ assert(replaceWithinString("abc", 1, 3, "") == "c")+ assert(replaceWithinString("abc", 1, 2, "x") == "xbc")+ assert(replaceWithinString("abc", 1, 3, "x") == "xc")+ assert(replaceWithinString("abcdef", 4, 26, "") == "abc")+end++local function repeatString(text, n)+ return string.rep(text, n)+end++if RUN_ASSERTS then+ assert(repeatString("a", 2) == "aa")+ assert(repeatString("aa", 3) == "aaaaaa")+ assert(repeatString("aa", 0) == "")+ assert(repeatString("", 0) == "")+ assert(repeatString("", 5) == "")+end++local function getLineEnding(text)+ -- TODO: allow for "\r\n" as well as "\n" here+ return "\n"+end++-- modified from penlight: https://tinyurl.com/37fqwxy8+local function splitLines(s)+ if s == "" then+ return {""}+ end++ local res = {}+ local pos = 1+ while true do+ local line_end_pos = string.find(s, "[\r\n]", pos)+ if not line_end_pos then+ break+ end++ local line_end = string.sub(s, line_end_pos, line_end_pos)+ if line_end == "\r" and string.sub(s, line_end_pos + 1, line_end_pos + 1) == "\n" then+ line_end = "\r\n"+ end++ local line = string.sub(s, pos, line_end_pos - 1)+ table.insert(res, line)++ pos = line_end_pos + #line_end+ end++ if pos <= #s then+ table.insert(res, string.sub(s, pos))+ end++ local len = strLen(s)+ local lastCh = getCharFromString(s, len)+ if lastCh == "\n" then+ table.insert(res, "")+ end++ return res+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Stack Operations++local function isStackEmpty(t)+ if RUN_ASSERTS then+ assert(isTable(t), "used isStackEmpty with not a Table")+ end++ for _key, _val in pairs(t) do+ return false+ end+ return true+end++if RUN_ASSERTS then+ assert(isStackEmpty({}))+ assert(not isStackEmpty({"a"}))+ assert(not isStackEmpty({"a", "b"}))+end++local function peek(arr, idxFromBack)+ idxFromBack = idxFromBack + 1+ local maxIdx = tableSize(arr)+ if (idxFromBack > maxIdx) then+ return nil+ end+ return arr[maxIdx - idxFromBack + 1]+end++if RUN_ASSERTS then+ assert(peek({"a"}, 0) == "a")+ assert(peek({"a"}, 1) == nil)+ assert(peek({"a", "b", "c"}, 0) == "c")+ assert(peek({"a", "b", "c"}, 1) == "b")+ assert(peek({"a", "b", "c"}, 5) == nil)+ assert(peek({}, 0) == nil)+ assert(peek({}, 1) == nil)+end++local function stackPop(s)+ if RUN_ASSERTS then+ assert(isTable(s), "used stackPop with not an Table")+ end++ return table.remove(s)+end++if RUN_ASSERTS then+ assert(stackPop({"a"}) == "a")+ assert(stackPop({"a", "b", "c"}) == "c")+ local testTable1 = {"a", "b"}+ assert(stackPop(testTable1) == "b")+ assert(tableSize(testTable1) == 1)+ assert(stackPop(testTable1) == "a")+ assert(tableSize(testTable1) == 0)+ stackPop(testTable1)+ assert(tableSize(testTable1) == 0)+end++local function stackPush(s, itm)+ if RUN_ASSERTS then+ assert(isTable(s), "used stackPush with not an Table")+ assert(isString(itm) or itm, "used stackPush without a second itm")+ end++ table.insert(s, itm)+ return nil+end++if RUN_ASSERTS then+ local testTable2 = {"a", "b"}+ stackPush(testTable2, "c")+ assert(tableSize(testTable2) == 3)+ assert(peek(testTable2, 0) == "c")+ assert(peek(testTable2, 1) == "b")+end++-- returns a new table with elements of tbl+-- startIdx and endIdx are both inclusive+local function sliceTable(tbl, startIdx, endIdx)+ local newTable = {}++ for idx, v in pairs(tbl) do+ if idx >= startIdx and idx <= endIdx then+ table.insert(newTable, v)+ end+ end++ return newTable+end++if RUN_ASSERTS then+ assert(strJoin(sliceTable({"a", "b", "c"}, 1, 1), "") == strJoin({"a"}, ""))+ assert(strJoin(sliceTable({"a", "b", "c"}, 2, 2), "") == strJoin({"b"}, ""))+ assert(strJoin(sliceTable({"a", "b", "c", "d", "e"}, 2, 3), "") == strJoin({"b", "c"}, ""))+ assert(strJoin(sliceTable({"a", "b", "c", "d", "e"}, 3, 25), "") == strJoin({"c", "d", "e"}, ""))+ assert(strJoin(sliceTable({}, 2, 3), "") == strJoin({}, ""))+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Options Structure++local function transformChange(change)+ if not change then+ return nil+ end++ local newLines = splitLines(change.newText)+ local oldLines = splitLines(change.oldText)++ -- single line case:+ -- (defn foo| [])+ -- ^ newEndX, newEndLineNo+ -- +++++ -- multi line case:+ -- (defn foo+ -- +++++ -- "docstring."+ -- +++++++++++++++++ -- |[])+ -- ++^ newEndX, newEndLineNo++ local prevOldLine = peek(oldLines, 0)+ local lastOldLineLen = strLen(prevOldLine)++ local prevNewLine = peek(newLines, 0)+ local lastNewLineLen = strLen(prevNewLine)++ local carryOverOldX = 1 -- Lua ONE INDEX+ if tableSize(oldLines) == 1 then+ carryOverOldX = change.x+ end+ local oldEndX = carryOverOldX + lastOldLineLen++ local carryOverNewX = 1 -- Lua ONE INDEX+ if tableSize(newLines) == 1 then+ carryOverNewX = change.x+ end+ local newEndX = carryOverNewX + lastNewLineLen++ local newEndLineNo = change.lineNo + tableSize(newLines) - 1++ return {+ x = change.x,+ lineNo = change.lineNo,+ oldText = change.oldText,+ newText = change.newText,+ oldEndX = oldEndX,+ newEndX = newEndX,+ newEndLineNo = newEndLineNo,+ lookupLineNo = newEndLineNo,+ lookupX = newEndX+ }+end++local function transformChanges(changes)+ if tableSize(changes) == 0 then+ return nil+ else+ local lines = {}+ local changesLen = tableSize(changes)+ local i = 1 -- Lua ONE INDEX+ while i <= changesLen do+ local change = transformChange(changes[i])+ local line = lines[change.lookupLineNo]+ if not line then+ line = {}+ lines[change.lookupLineNo] = line+ end+ line[change.lookupX] = change++ i = i + 1+ end+ return lines+ end+end++local function parseOptions(options)+ if (not isTable(options)) then+ options = {}+ end++ return {+ changes = options.changes,+ commentChars = options.commentChars,+ cursorLine = options.cursorLine,+ cursorX = options.cursorX,+ forceBalance = options.forceBalance,+ partialResult = options.partialResult,+ prevCursorLine = options.prevCursorLine,+ prevCursorX = options.prevCursorX,+ returnParens = options.returnParens,+ selectionStartLine = options.selectionStartLine+ }+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Result Structure++local function initialParenTrail()+ return {+ lineNo = UINT_NULL,+ startX = UINT_NULL,+ endX = UINT_NULL,+ openers = {},+ clamped = {+ startX = UINT_NULL,+ endX = UINT_NULL,+ openers = {}+ }+ }+end++local function getInitialResult(text, options, mode, smart)+ local result = {+ mode = mode,+ smart = smart,+ origText = text,+ origCursorX = UINT_NULL,+ origCursorLine = UINT_NULL,+ inputLines = splitLines(text),+ inputLineNo = 0, -- Lua ONE INDEX+ inputX = 0, -- Lua ONE INDEX+ lines = {},+ lineNo = 0, -- Lua ONE INDEX+ ch = "",+ x = 0, -- Lua ONE INDEX+ indentX = UINT_NULL,+ parenStack = {},+ tabStops = {},+ parenTrail = initialParenTrail(),+ parenTrails = {},+ returnParens = false,+ parens = {},+ cursorX = UINT_NULL,+ cursorLine = UINT_NULL,+ prevCursorX = UINT_NULL,+ prevCursorLine = UINT_NULL,+ commentChars = {";"},+ selectionStartLine = UINT_NULL,+ changes = nil,+ isInCode = true,+ isEscaping = false,+ isEscaped = false,+ isInStr = false,+ isInComment = false,+ commentX = UINT_NULL,+ quoteDanger = false,+ trackingIndent = false,+ skipChar = false,+ success = false,+ partialResult = false,+ forceBalance = false,+ maxIndent = UINT_NULL,+ indentDelta = 0,+ trackingArgTabStop = nil,+ ["error"] = {+ name = nil,+ message = nil,+ lineNo = nil,+ x = nil,+ extra = {+ name = nil,+ lineNo = nil,+ x = nil+ }+ },+ errorPosCache = {}+ }++ -- merge user options if they are valid+ if (options) then+ if isInteger(options.cursorX) then+ result.cursorX = options.cursorX+ result.origCursorX = options.cursorX+ end++ if isInteger(options.cursorLine) then+ result.cursorLine = options.cursorLine+ result.origCursorLine = options.cursorLine+ end++ if isInteger(options.prevCursorX) then+ result.prevCursorX = options.prevCursorX+ end+ if isInteger(options.prevCursorLine) then+ result.prevCursorLine = options.prevCursorLine+ end+ if isInteger(options.selectionStartLine) then+ result.selectionStartLine = options.selectionStartLine+ end+ if isTable(options.changes) then+ result.changes = transformChanges(options.changes)+ end+ if isBoolean(options.partialResult) then+ result.partialResult = options.partialResult+ end+ if isBoolean(options.forceBalance) then+ result.forceBalance = options.forceBalance+ end+ if isBoolean(options.returnParens) then+ result.returnParens = options.returnParens+ end+ if isChar(options.commentChars) then+ result.commentChars = {options.commentChars}+ end+ if isTableOfChars(options.commentChars) then+ result.commentChars = options.commentChars+ end+ end++ return result+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Possible Errors++-- `result.error.name` is set to any of these+local ERROR_QUOTE_DANGER = "quote-danger"+local ERROR_EOL_BACKSLASH = "eol-backslash"+local ERROR_UNCLOSED_QUOTE = "unclosed-quote"+local ERROR_UNCLOSED_PAREN = "unclosed-paren"+local ERROR_UNMATCHED_CLOSE_PAREN = "unmatched-close-paren"+local ERROR_UNMATCHED_OPEN_PAREN = "unmatched-open-paren"+local ERROR_LEADING_CLOSE_PAREN = "leading-close-paren"+local ERROR_UNHANDLED = "unhandled"++local errorMessages = {}+errorMessages[ERROR_QUOTE_DANGER] = "Quotes must balanced inside comment blocks."+errorMessages[ERROR_EOL_BACKSLASH] = "Line cannot end in a hanging backslash."+errorMessages[ERROR_UNCLOSED_QUOTE] = "String is missing a closing quote."+errorMessages[ERROR_UNCLOSED_PAREN] = "Unclosed open-paren."+errorMessages[ERROR_UNMATCHED_CLOSE_PAREN] = "Unmatched close-paren."+errorMessages[ERROR_UNMATCHED_OPEN_PAREN] = "Unmatched open-paren."+errorMessages[ERROR_LEADING_CLOSE_PAREN] = "Line cannot lead with a close-paren."+errorMessages[ERROR_UNHANDLED] = "Unhandled error."++local function cacheErrorPos(result, errorName)+ local e = {+ lineNo = result.lineNo,+ x = result.x,+ inputLineNo = result.inputLineNo,+ inputX = result.inputX+ }+ result.errorPosCache[errorName] = e+ return e+end++local function createError(result, name)+ local cache = result.errorPosCache[name]++ local keyLineNo = "inputLineNo"+ local keyX = "inputX"+ if result.partialResult then+ keyLineNo = "lineNo"+ keyX = "x"+ end++ local lineNo = 0+ local x = 0+ if cache then+ lineNo = cache[keyLineNo]+ x = cache[keyX]+ else+ lineNo = result[keyLineNo]+ x = result[keyX]+ end++ local err = {+ parinferError = true,+ name = name,+ message = errorMessages[name],+ lineNo = lineNo,+ x = x+ }+ local opener = peek(result.parenStack, 0)++ if name == ERROR_UNMATCHED_CLOSE_PAREN then+ -- extra error info for locating the open-paren that it should've matched+ local cache2 = result.errorPosCache[ERROR_UNMATCHED_OPEN_PAREN]+ if cache2 or opener then+ local lineNo2 = 0+ local x2 = 0+ if cache2 then+ lineNo2 = cache2[keyLineNo]+ x2 = cache2[keyX]+ else+ lineNo2 = opener[keyLineNo]+ x2 = opener[keyX]+ end++ err.extra = {+ name = ERROR_UNMATCHED_OPEN_PAREN,+ lineNo = lineNo2,+ x = x2+ }+ end+ elseif name == ERROR_UNCLOSED_PAREN then+ err.lineNo = opener[keyLineNo]+ err.x = opener[keyX]+ end++ return err+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Line Operations++local function isCursorAffected(result, startIdx, endIdx)+ if (result.cursorX == startIdx and result.cursorX == endIdx) then+ return result.cursorX == 1 -- Lua ONE INDEX+ end+ return result.cursorX >= endIdx+end++local function shiftCursorOnEdit(result, lineNo, startIdx, endIdx, replaceTxt)+ local oldLength = endIdx - startIdx+ local newLength = strLen(replaceTxt)+ local dx = newLength - oldLength++ if+ (dx ~= 0 and result.cursorLine == lineNo and result.cursorX ~= UINT_NULL and+ isCursorAffected(result, startIdx, endIdx))+ then+ result.cursorX = result.cursorX + dx+ end+end++local function replaceWithinLine(result, lineNo, startIdx, endIdx, replaceTxt)+ local line = result.lines[lineNo]++ local newLine = replaceWithinString(line, startIdx, endIdx, replaceTxt)+ result.lines[lineNo] = newLine++ shiftCursorOnEdit(result, lineNo, startIdx, endIdx, replaceTxt)+end++local function insertWithinLine(result, lineNo, idx, insert)+ replaceWithinLine(result, lineNo, idx, idx, insert)+end++local function initLine(result)+ result.x = 1 -- Lua ONE INDEX+ result.lineNo = result.lineNo + 1++ -- reset line-specific state+ result.indentX = UINT_NULL+ result.commentX = UINT_NULL+ result.indentDelta = 0+ result.errorPosCache[ERROR_UNMATCHED_CLOSE_PAREN] = nil+ result.errorPosCache[ERROR_UNMATCHED_OPEN_PAREN] = nil+ result.errorPosCache[ERROR_LEADING_CLOSE_PAREN] = nil++ result.trackingArgTabStop = nil+ result.trackingIndent = not result.isInStr+end++-- if the current character has changed, commit its change to the current line.+local function commitChar(result, origCh)+ local ch = result.ch+ local origChLength = strLen(origCh)+ local chLength = strLen(ch)++ if origCh ~= ch then+ replaceWithinLine(result, result.lineNo, result.x, result.x + origChLength, ch)+ result.indentDelta = result.indentDelta - origChLength - chLength+ end++ result.x = result.x + chLength+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Misc Util++local function clamp(val, minN, maxN)+ if (minN ~= UINT_NULL) then+ val = math.max(minN, val)+ end+ if (maxN ~= UINT_NULL) then+ val = math.min(maxN, val)+ end+ return val+end++if RUN_ASSERTS then+ assert(clamp(1, 3, 5) == 3)+ assert(clamp(9, 3, 5) == 5)+ assert(clamp(1, 3, UINT_NULL) == 3)+ assert(clamp(5, 3, UINT_NULL) == 5)+ assert(clamp(1, UINT_NULL, 5) == 1)+ assert(clamp(9, UINT_NULL, 5) == 5)+ assert(clamp(1, UINT_NULL, UINT_NULL) == 1)+end++-- concat the elements in t2 onto t1+-- returns a new table+local function concatTables(t1, t2)+ local newTable = {}++ for k, v in pairs(t1) do+ table.insert(newTable, v)+ end++ for k, v in pairs(t2) do+ table.insert(newTable, v)+ end++ return newTable+end++if RUN_ASSERTS then+ assert(strJoin(concatTables({}, {}), "") == strJoin({}, ""))+ assert(strJoin(concatTables({"a"}, {}), "") == strJoin({"a"}, ""))+ assert(strJoin(concatTables({}, {"a"}), "") == strJoin({"a"}, ""))+ assert(strJoin(concatTables({"a", "b", "c"}, {"d", "e"}), "") == strJoin({"a", "b", "c", "d", "e"}, ""))+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Character Predicates++local function isOpenParen(ch)+ return ch == "{" or ch == "(" or ch == "["+end++local function isCloseParen(ch)+ return ch == "}" or ch == ")" or ch == "]"+end++if RUN_ASSERTS then+ assert(isOpenParen("(") == true)+ assert(isOpenParen("]") == false)+ assert(isCloseParen("}") == true)+ assert(isCloseParen("a") == false)+end++local function isValidCloseParen(parenStack, ch)+ if isStackEmpty(parenStack) then+ return false+ end++ local lastOnStack = peek(parenStack, 0)+ return lastOnStack.ch == MATCH_PAREN[ch]+end++local function isWhitespace(result)+ local ch = result.ch+ return (not result.isEscaped) and (ch == BLANK_SPACE or ch == DOUBLE_SPACE)+end++-- can this be the last code character of a list?+local function isClosable(result)+ local ch = result.ch+ local isCloser = isCloseParen(ch) and not result.isEscaped+ return result.isInCode and not isWhitespace(result) and ch ~= "" and not isCloser+end++local function isCommentChar(ch, commentChars)+ for _key, commentCh in pairs(commentChars) do+ if ch == commentCh then+ return true+ end+ end+ return false+end++if RUN_ASSERTS then+ assert(isCommentChar(";", {";"}))+ assert(isCommentChar(";", {";", "#"}))+ assert(isCommentChar("#", {";", "#"}))+ assert(not isCommentChar("x", {";"}))+ assert(not isCommentChar("", {";"}))+ assert(not isCommentChar("#", {";", "a"}))+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Advanced Character Operations++local function checkCursorHolding(result)+ local opener = peek(result.parenStack, 0)+ local parent = peek(result.parenStack, 1)+ local holdMinX = 1 -- Lua ONE INDEX+ if parent then+ holdMinX = parent.x + 1+ end+ local holdMaxX = opener.x++ local holding = result.cursorLine == opener.lineNo and holdMinX <= result.cursorX and result.cursorX <= holdMaxX+ local shouldCheckPrev = not result.changes and result.prevCursorLine ~= UINT_NULL+ if shouldCheckPrev then+ local prevHolding =+ result.prevCursorLine == opener.lineNo and holdMinX <= result.prevCursorX and result.prevCursorX <= holdMaxX+ if prevHolding and not holding then+ error({releaseCursorHold = true})+ end+ end++ return holding+end++local function trackArgTabStop(result, state)+ if state == "space" then+ if result.isInCode and isWhitespace(result) then+ result.trackingArgTabStop = "arg"+ end+ elseif state == "arg" then+ if not isWhitespace(result) then+ local opener = peek(result.parenStack, 0)+ opener.argX = result.x+ result.trackingArgTabStop = nil+ end+ end+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Literal Character Events++local function onOpenParen(result)+ if result.isInCode then+ local opener = {+ inputLineNo = result.inputLineNo,+ inputX = result.inputX,+ lineNo = result.lineNo,+ x = result.x,+ ch = result.ch,+ indentDelta = result.indentDelta,+ maxChildIndent = UINT_NULL+ }++ if result.returnParens then+ opener.children = {}+ opener.closer = {+ lineNo = UINT_NULL,+ x = UINT_NULL,+ ch = ""+ }++ local parent1 = peek(result.parenStack, 0)+ local parent2 = result.parens+ if parent1 then+ parent2 = parent1.children+ end++ stackPush(parent2, opener)+ end++ stackPush(result.parenStack, opener)+ result.trackingArgTabStop = "space"+ end+end++local function setCloser(opener, lineNo, x, ch)+ opener.closer.lineNo = lineNo+ opener.closer.x = x+ opener.closer.ch = ch+end++local function onMatchedCloseParen(result)+ local opener = peek(result.parenStack, 0)+ if result.returnParens then+ setCloser(opener, result.lineNo, result.x, result.ch)+ end++ result.parenTrail.endX = result.x + 1+ stackPush(result.parenTrail.openers, opener)++ if (result.mode == INDENT_MODE and result.smart and checkCursorHolding(result)) then+ local origStartX = result.parenTrail.startX+ local origEndX = result.parenTrail.endX+ local origOpeners = result.parenTrail.openers+ resetParenTrail(result, result.lineNo, result.x + 1)+ result.parenTrail.clamped.startX = origStartX+ result.parenTrail.clamped.endX = origEndX+ result.parenTrail.clamped.openers = origOpeners+ end+ stackPop(result.parenStack)+ result.trackingArgTabStop = nil+end++local function onUnmatchedCloseParen(result)+ if (result.mode == PAREN_MODE) then+ local trail = result.parenTrail+ local inLeadingParenTrail = (trail.lineNo == result.lineNo) and (trail.startX == result.indentX)+ local canRemove = result.smart and inLeadingParenTrail+ if not canRemove then+ error(createError(result, ERROR_UNMATCHED_CLOSE_PAREN))+ end+ elseif (result.mode == INDENT_MODE and not result.errorPosCache[ERROR_UNMATCHED_CLOSE_PAREN]) then+ cacheErrorPos(result, ERROR_UNMATCHED_CLOSE_PAREN)+ local opener = peek(result.parenStack, 0)+ if opener then+ local e = cacheErrorPos(result, ERROR_UNMATCHED_OPEN_PAREN)+ e.inputLineNo = opener.inputLineNo+ e.inputX = opener.inputX+ end+ end+ result.ch = ""+end++local function onCloseParen(result)+ if result.isInCode then+ if isValidCloseParen(result.parenStack, result.ch) then+ onMatchedCloseParen(result)+ else+ onUnmatchedCloseParen(result)+ end+ end+end++local function onTab(result)+ if result.isInCode then+ result.ch = DOUBLE_SPACE+ end+end++local function onCommentChar(result)+ if result.isInCode then+ result.isInComment = true+ result.commentX = result.x+ result.trackingArgTabStop = nil+ end+end++local function onNewline(result)+ result.isInComment = false+ result.ch = ""+end++local function onQuote(result)+ if result.isInStr then+ result.isInStr = false+ elseif result.isInComment then+ result.quoteDanger = not result.quoteDanger+ if result.quoteDanger then+ cacheErrorPos(result, ERROR_QUOTE_DANGER)+ end+ else+ result.isInStr = true+ cacheErrorPos(result, ERROR_UNCLOSED_QUOTE)+ end+end++local function onBackslash(result)+ result.isEscaping = true+end++local function afterBackslash(result)+ result.isEscaping = false+ result.isEscaped = true++ if result.ch == NEWLINE then+ if result.isInCode then+ error(createError(result, ERROR_EOL_BACKSLASH))+ end+ onNewline(result)+ end+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Character Dispatch++local function onChar(result)+ local ch = result.ch+ result.isEscaped = false++ if result.isEscaping then+ afterBackslash(result)+ elseif isOpenParen(ch) then+ onOpenParen(result)+ elseif isCloseParen(ch) then+ onCloseParen(result)+ elseif ch == DOUBLE_QUOTE then+ onQuote(result)+ elseif isCommentChar(ch, result.commentChars) then+ onCommentChar(result)+ elseif ch == BACKSLASH then+ onBackslash(result)+ elseif ch == TAB then+ onTab(result)+ elseif ch == NEWLINE then+ onNewline(result)+ end++ ch = result.ch++ result.isInCode = (not result.isInComment) and (not result.isInStr)++ if isClosable(result) then+ resetParenTrail(result, result.lineNo, result.x + strLen(ch))+ end++ local state = result.trackingArgTabStop+ if state then+ trackArgTabStop(result, state)+ end+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Cursor Functions++local function isCursorLeftOf(cursorX, cursorLine, x, lineNo)+ return cursorLine == lineNo and x ~= UINT_NULL and cursorX ~= UINT_NULL and cursorX <= x+end++local function isCursorRightOf(cursorX, cursorLine, x, lineNo)+ return cursorLine == lineNo and x ~= UINT_NULL and cursorX ~= UINT_NULL and cursorX > x+end++local function isCursorInComment(result, cursorX, cursorLine)+ return isCursorRightOf(cursorX, cursorLine, result.commentX, result.lineNo)+end++local function handleChangeDelta(result)+ if (result.changes and (result.smart or result.mode == PAREN_MODE)) then+ local line = result.changes[result.inputLineNo]+ if (line) then+ local change = line[result.inputX]+ if (change) then+ result.indentDelta = result.indentDelta + change.newEndX - change.oldEndX+ end+ end+ end+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Paren Trail Functions++resetParenTrail = function(result, lineNo, x)+ result.parenTrail.lineNo = lineNo+ result.parenTrail.startX = x+ result.parenTrail.endX = x+ result.parenTrail.openers = {}+ result.parenTrail.clamped.startX = UINT_NULL+ result.parenTrail.clamped.endX = UINT_NULL+ result.parenTrail.clamped.openers = {}+end++local function isCursorClampingParenTrail(result, cursorX, cursorLine)+ return (isCursorRightOf(cursorX, cursorLine, result.parenTrail.startX, result.lineNo) and+ not isCursorInComment(result, cursorX, cursorLine))+end++local function clampParenTrailToCursor(result)+ local startX = result.parenTrail.startX+ local endX = result.parenTrail.endX++ local clamping = isCursorClampingParenTrail(result, result.cursorX, result.cursorLine)++ if clamping then+ local newStartX = math.max(startX, result.cursorX)+ local newEndX = math.max(endX, result.cursorX)++ local line = result.lines[result.lineNo]+ local removeCount = 0++ local i = startX+ while i <= newStartX do -- Lua ONE INDEX+ local ch = getCharFromString(line, i)+ if isCloseParen(ch) then+ removeCount = removeCount + 1+ end+ i = i + 1+ end++ local openers = {}+ for _, v in ipairs(result.parenTrail.openers) do+ table.insert(openers, v)+ end++ local openersLen = tableSize(openers)+ result.parenTrail.openers = sliceTable(openers, removeCount, openersLen)+ result.parenTrail.startX = newStartX+ result.parenTrail.endX = newEndX++ result.parenTrail.clamped.openers = sliceTable(openers, 1, removeCount) -- Lua ONE INDEX+ result.parenTrail.clamped.startX = startX+ result.parenTrail.clamped.endX = endX+ end+end++local function popParenTrail(result)+ local startX = result.parenTrail.startX+ local endX = result.parenTrail.endX++ if (startX == endX) then+ return+ else+ local openers = result.parenTrail.openers+ while not isStackEmpty(openers) do+ local itm = stackPop(openers)+ stackPush(result.parenStack, itm)+ end+ end+end++local function getParentOpenerIndex(result, indentX)+ local parenStackLength = tableSize(result.parenStack)+ local i = 0+ while i < parenStackLength do+ local opener = peek(result.parenStack, i)+ local currOutside = (opener.x < indentX)+ local prevIndentX = indentX - result.indentDelta+ local prevOutside = (opener.x - opener.indentDelta < prevIndentX)++ local isParent = false++ if (prevOutside and currOutside) then+ isParent = true+ elseif (not prevOutside and not currOutside) then+ isParent = false+ elseif (prevOutside and not currOutside) then+ -- 1. PREVENT FRAGMENTATION+ if (result.indentDelta == 0) then+ -- 2. ALLOW FRAGMENTATION+ isParent = true+ elseif (opener.indentDelta == 0) then+ isParent = false+ else+ isParent = false+ end+ elseif (not prevOutside and currOutside) then+ local nextOpener = peek(result.parenStack, i + 1)++ -- 1. DISALLOW ADOPTION+ if (nextOpener and nextOpener.indentDelta <= opener.indentDelta) then+ -- 2. ALLOW ADOPTION+ if (indentX + nextOpener.indentDelta > opener.x) then+ isParent = true+ else+ isParent = false+ end+ elseif (nextOpener and nextOpener.indentDelta > opener.indentDelta) then+ -- 3. ALLOW ADOPTION+ isParent = true+ elseif (result.indentDelta > opener.indentDelta) then+ isParent = true+ end++ -- if new parent+ if isParent then+ opener.indentDelta = 0+ end+ end++ if isParent then+ break+ end++ i = i + 1+ end++ return i+end++local function correctParenTrail(result, indentX)+ local openerIdx = getParentOpenerIndex(result, indentX)+ local parens = ""+ local i = 0+ while i < openerIdx do+ local opener = stackPop(result.parenStack)+ stackPush(result.parenTrail.openers, opener)+ local closeCh = MATCH_PAREN[opener.ch]+ parens = strConcat(parens, closeCh)++ if result.returnParens then+ setCloser(opener, result.parenTrail.lineNo, result.parenTrail.startX + i, closeCh)+ end++ i = i + 1+ end++ if result.parenTrail.lineNo ~= UINT_NULL then+ replaceWithinLine(result, result.parenTrail.lineNo, result.parenTrail.startX, result.parenTrail.endX, parens)+ result.parenTrail.endX = result.parenTrail.startX + strLen(parens)+ rememberParenTrail(result)+ end+end++-- PAREN MODE: remove spaces from the paren trail+local function cleanParenTrail(result)+ local startX = result.parenTrail.startX+ local endX = result.parenTrail.endX++ if (startX == endX or result.lineNo ~= result.parenTrail.lineNo) then+ return+ end++ local line = result.lines[result.lineNo]+ local newTrail = ""+ local spaceCount = 0+ local i = startX+ while i < endX do+ local lineCh = getCharFromString(line, i)+ if (isCloseParen(lineCh)) then+ newTrail = strConcat(newTrail, lineCh)+ else+ spaceCount = spaceCount + 1+ end++ i = i + 1+ end++ if spaceCount > 0 then+ replaceWithinLine(result, result.lineNo, startX, endX, newTrail)+ result.parenTrail.endX = result.parenTrail.endX - spaceCount+ end+end++local function setMaxIndent(result, opener)+ if opener then+ local parent = peek(result.parenStack, 0)+ if parent then+ parent.maxChildIndent = opener.x+ else+ result.maxIndent = opener.x+ end+ end+end++local function appendParenTrail(result)+ local opener = stackPop(result.parenStack)+ local closeCh = MATCH_PAREN[opener.ch]+ if (result.returnParens) then+ setCloser(opener, result.parenTrail.lineNo, result.parenTrail.endX, closeCh)+ end++ setMaxIndent(result, opener)+ insertWithinLine(result, result.parenTrail.lineNo, result.parenTrail.endX, closeCh)++ result.parenTrail.endX = result.parenTrail.endX + 1+ stackPush(result.parenTrail.openers, opener)+ updateRememberedParenTrail(result)+end++local function invalidateParenTrail(result)+ result.parenTrail = initialParenTrail()+end++local function checkUnmatchedOutsideParenTrail(result)+ local cache = result.errorPosCache[ERROR_UNMATCHED_CLOSE_PAREN]+ if (cache and cache.x < result.parenTrail.startX) then+ error(createError(result, ERROR_UNMATCHED_CLOSE_PAREN))+ end+end++rememberParenTrail = function(result)+ local trail = result.parenTrail+ local openers = concatTables(trail.clamped.openers, trail.openers)+ if not isTableEmpty(openers) then+ local isClamped = trail.clamped.startX ~= UINT_NULL+ local allClamped = isTableEmpty(trail.openers)++ local startX = trail.startX+ if isClamped then+ startX = trail.clamped.startX+ end++ local endX = trail.endX+ if allClamped then+ endX = trail.clamped.endX+ end++ local shortTrail = {+ lineNo = trail.lineNo,+ startX = startX,+ endX = endX+ }+ stackPush(result.parenTrails, shortTrail)++ -- TODO: this almost certainly is not working due to openers+ -- being a deep copy here and then not being returned anywhere+ -- possibly a bug in parinfer.js as well+ if result.returnParens then+ for _, v in ipairs(trail.clamped.openers) do+ v.closer.trail = shortTrail+ end+ for _, v in ipairs(trail.openers) do+ v.closer.trail = shortTrail+ end+ end+ end+end++updateRememberedParenTrail = function(result)+ local trail = peek(result.parenTrails, 0)+ if not trail or trail.lineNo ~= result.parenTrail.lineNo then+ rememberParenTrail(result)+ else+ trail.endX = result.parenTrail.endX+ if result.returnParens then+ -- this is almost certainly buggy+ -- commenting this out has no effect on the test suite+ -- -- C. Oakman, 19 Feb 2021+ local opener = peek(result.parenTrail.openers, 0)+ opener.closer.trail = trail+ end+ end+end++local function finishNewParenTrail(result)+ if (result.isInStr) then+ invalidateParenTrail(result)+ elseif (result.mode == INDENT_MODE) then+ clampParenTrailToCursor(result)+ popParenTrail(result)+ elseif (result.mode == PAREN_MODE) then+ setMaxIndent(result, peek(result.parenTrail.openers, 0))+ if (result.lineNo ~= result.cursorLine) then+ cleanParenTrail(result)+ end+ rememberParenTrail(result)+ end+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Indentation Functions++local function addIndent(result, delta)+ local origIndent = result.x+ local newIndent = origIndent + delta+ local indentStr = repeatString(BLANK_SPACE, newIndent - 1) -- Lua ONE INDEX+ replaceWithinLine(result, result.lineNo, 1, origIndent, indentStr) -- Lua ONE INDEX+ result.x = newIndent+ result.indentX = newIndent+ result.indentDelta = result.indentDelta + delta+end++local function shouldAddOpenerIndent(result, opener)+ -- Don't add opener.indentDelta if the user already added it.+ -- (happens when multiple lines are indented together)+ return opener.indentDelta ~= result.indentDelta+end++local function correctIndent(result)+ local origIndent = result.x+ local newIndent = origIndent+ local minIndent = 0+ local maxIndent = result.maxIndent++ local opener = peek(result.parenStack, 0)+ if opener then+ minIndent = opener.x + 1+ maxIndent = opener.maxChildIndent+ if shouldAddOpenerIndent(result, opener) then+ newIndent = newIndent + opener.indentDelta+ end+ end++ newIndent = clamp(newIndent, minIndent, maxIndent)++ if newIndent ~= origIndent then+ addIndent(result, newIndent - origIndent)+ end+end++local function onIndent(result)+ result.indentX = result.x+ result.trackingIndent = false++ if (result.quoteDanger) then+ error(createError(result, ERROR_QUOTE_DANGER))+ end++ if result.mode == INDENT_MODE then+ correctParenTrail(result, result.x)++ local opener = peek(result.parenStack, 0)+ if opener and shouldAddOpenerIndent(result, opener) then+ addIndent(result, opener.indentDelta)+ end+ elseif result.mode == PAREN_MODE then+ correctIndent(result)+ end+end++local function checkLeadingCloseParen(result)+ if result.errorPosCache[ERROR_LEADING_CLOSE_PAREN] and result.parenTrail.lineNo == result.lineNo then+ error(createError(result, ERROR_LEADING_CLOSE_PAREN))+ end+end++local function onLeadingCloseParen(result)+ if result.mode == INDENT_MODE then+ if not result.forceBalance then+ if result.smart then+ error({leadingCloseParen = true})+ end+ if not result.errorPosCache[ERROR_LEADING_CLOSE_PAREN] then+ cacheErrorPos(result, ERROR_LEADING_CLOSE_PAREN)+ end+ end+ result.skipChar = true+ end++ if result.mode == PAREN_MODE then+ if not isValidCloseParen(result.parenStack, result.ch) then+ if result.smart then+ result.skipChar = true+ else+ error(createError(result, ERROR_UNMATCHED_CLOSE_PAREN))+ end+ elseif isCursorLeftOf(result.cursorX, result.cursorLine, result.x, result.lineNo) then+ resetParenTrail(result, result.lineNo, result.x)+ onIndent(result)+ else+ appendParenTrail(result)+ result.skipChar = true+ end+ end+end++local function onCommentLine(result)+ local parenTrailLen = tableSize(result.parenTrail.openers)++ -- restore the openers matching the previous paren trail+ if result.mode == PAREN_MODE then+ local i = 0+ while i < parenTrailLen do+ local opener = peek(result.parenTrail.openers, i)+ stackPush(result.parenStack, opener)+ i = i + 1+ end+ end++ local openerIdx = getParentOpenerIndex(result, result.x)+ local opener = peek(result.parenStack, openerIdx)+ if opener then+ -- shift the comment line based on the parent open paren+ if shouldAddOpenerIndent(result, opener) then+ addIndent(result, opener.indentDelta)+ end+ -- TODO: store some information here if we need to place close-parens after comment lines+ end++ -- repop the openers matching the previous paren trail+ if result.mode == PAREN_MODE then+ local i2 = 0+ while i2 < parenTrailLen do+ stackPop(result.parenStack)+ i2 = i2 + 1+ end+ end+end++local function checkIndent(result)+ if isCloseParen(result.ch) then+ onLeadingCloseParen(result)+ elseif isCommentChar(result.ch, result.commentChars) then+ -- comments don't count as indentation points+ onCommentLine(result)+ result.trackingIndent = false+ elseif result.ch ~= NEWLINE and result.ch ~= BLANK_SPACE and result.ch ~= TAB then+ onIndent(result)+ end+end++local function makeTabStop(result, opener)+ local tabStop = {+ ch = opener.ch,+ x = opener.x,+ lineNo = opener.lineNo+ }+ if isPositiveInt(opener.argX) then+ tabStop.argX = opener.argX+ end+ return tabStop+end++local function getTabStopLine(result)+ if result.selectionStartLine ~= UINT_NULL then+ return result.selectionStartLine+ end+ return result.cursorLine+end++local function setTabStops(result)+ if getTabStopLine(result) ~= result.lineNo then+ return+ end++ local parenStackLen = tableSize(result.parenStack)+ local i = 1+ while (i <= parenStackLen) do -- Lua ONE INDEX+ local ts = makeTabStop(result, result.parenStack[i])+ stackPush(result.tabStops, ts)+ i = i + 1+ end++ if result.mode == PAREN_MODE then+ local parenTrailOpenersLen = tableSize(result.parenTrail.openers)+ local i2 = parenTrailOpenersLen -- Lua ONE INDEX+ while (i2 > 0) do+ local ts2 = makeTabStop(result, result.parenTrail.openers[i2])+ stackPush(result.tabStops, ts2)+ i2 = i2 - 1+ end+ end++ -- remove argX if it falls to the right of the next stop+ local tabStopsLen = tableSize(result.tabStops)+ local i3 = 1+ while i3 <= tabStopsLen do -- Lua ONE INDEX+ local currentX = result.tabStops[i3].x+ local prevTabStop = result.tabStops[i3 - 1]+ if prevTabStop then+ local prevArgX = prevTabStop.argX+ if isInteger(prevArgX) and prevArgX >= currentX then+ prevTabStop.argX = nil+ end+ end+ i3 = i3 + 1+ end+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- High-level processing functions++local function processChar(result, ch)+ local origCh = ch++ result.ch = ch+ result.skipChar = false++ handleChangeDelta(result)++ if result.trackingIndent then+ checkIndent(result)+ end++ if result.skipChar then+ result.ch = ""+ else+ onChar(result)+ end+ commitChar(result, origCh)+end++local function processLine(result, lineNo)+ initLine(result)++ local line = result.inputLines[lineNo]+ stackPush(result.lines, line)++ setTabStops(result)++ local lineLength = strLen(line)+ local x = 1 -- Lua ONE INDEX+ while x <= lineLength do+ result.inputX = x+ local line2 = result.inputLines[lineNo]+ local ch = getCharFromString(line2, x)+ processChar(result, ch)++ x = x + 1+ end+ processChar(result, NEWLINE)++ if not result.forceBalance then+ checkUnmatchedOutsideParenTrail(result)+ checkLeadingCloseParen(result)+ end++ if result.lineNo == result.parenTrail.lineNo then+ finishNewParenTrail(result)+ end+end++local function finalizeResult(result)+ if result.quoteDanger then+ error(createError(result, ERROR_QUOTE_DANGER))+ end+ if result.isInStr then+ error(createError(result, ERROR_UNCLOSED_QUOTE))+ end++ if not isStackEmpty(result.parenStack) then+ if (result.mode == PAREN_MODE) then+ error(createError(result, ERROR_UNCLOSED_PAREN))+ end+ end+ if result.mode == INDENT_MODE then+ initLine(result)+ onIndent(result)+ end++ result.success = true+end++local function processError(result, err)+ result.success = false+ if err.parinferError then+ err.parinferError = nil+ result.error = err+ else+ result.error.name = ERROR_UNHANDLED+ result.error.message = err.stack+ error(err)+ end+end++local function processTextInternal(result)+ for idx, line in pairs(result.inputLines) do+ result.inputLineNo = idx+ processLine(result, idx)+ end+ finalizeResult(result)+end++local doThePcall = true++local function processText(text, options, mode, smart)+ local result = getInitialResult(text, options, mode, smart)++ if doThePcall then+ local status, err =+ pcall(+ function()+ return processTextInternal(result)+ end+ )++ if status then+ return result+ else+ if err.leadingCloseParen or err.releaseCursorHold then+ return processText(text, options, PAREN_MODE, smart)+ end++ processError(result, err)+ return result+ end+ else+ processTextInternal(result)+ return result+ end+end++-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Public API++local function publicResult(result)+ local lineEnding = getLineEnding(result.origText)+ local final = {}+ if result.success then+ final.text = strJoin(result.lines, lineEnding)+ final.cursorX = result.cursorX+ final.cursorLine = result.cursorLine+ final.success = true+ final.tabStops = result.tabStops+ final.parenTrails = result.parenTrails+ if result.returnParens then+ final.parens = result.parens+ end+ else+ final.success = false+ final["error"] = result["error"]++ if result.partialResult then+ final.text = strJoin(result.lines, lineEnding)+ final.cursorX = result.cursorX+ final.cursorLine = result.cursorLine+ final.parenTrails = result.parenTrails+ else+ final.text = result.origText+ final.cursorX = result.origCursorX+ final.cursorLine = result.origCursorLine+ final.parenTrails = nil+ end++ if result.partialResult and result.returnParens then+ final.parens = result.parens+ end+ end++ if final.cursorX == UINT_NULL then+ final.cursorX = nil+ end+ if final.cursorLine == UINT_NULL then+ final.cursorLine = nil+ end+ if final.tabStops and isTableEmpty(final.tabStops) then+ final.tabStops = nil+ end++ return final+end++local function indentMode(text, options)+ options = parseOptions(options)+ return publicResult(processText(text, options, INDENT_MODE))+end++local function parenMode(text, options)+ options = parseOptions(options)+ return publicResult(processText(text, options, PAREN_MODE))+end++local function smartMode(text, options)+ options = parseOptions(options)+ local smart = options.selectionStartLine == nil+ return publicResult(processText(text, options, INDENT_MODE, smart))+end++M.version = "0.1.0"+M.indentMode = indentMode+M.parenMode = parenMode+M.smartMode = smartMode++return Mnvim/lua/parinfer/plugin.lua view file
@@ -0,0 +1,251 @@+--- Modified version of https://github.com/gpanders/nvim-parinfer+--- See ./LICENSE++vim.g.parinfer_mode = "smart"+vim.g.parinfer_enabled = true+vim.g.parinfer_force_balance = false+vim.g.parinfer_comment_chars = {";"}++local api = vim.api+local diff = (vim.text.diff or vim.diff)+local parinfer = require("parinfer.parinfer")+local modes = {indent = parinfer.indentMode,+ paren = parinfer.parenMode,+ smart = parinfer.smartMode}++local ns = api.nvim_create_namespace("parinfer")++local state = setmetatable({}, {__index = function(t, k)+ t[k] = {}+ return t[k]+end})++-- TODO I don't really get the point of this+local function normalize_bool(val)+ if type(val) == "boolean" then+ return val+ end++ if val == nil then+ return nil+ end++ return val ~= 0+end++local function get_option(opt)+ local b = vim.b[opt] or vim.g[opt]+ if b == nil then+ return vim.g[opt]+ else+ return b+ end+end++local function invoke_parinfer(bufnr, text, lnum, col)+ local _let_32_ = (state[bufnr]["prev-cursor"] or {})+ local prev_lnum = _let_32_[1]+ local prev_col = _let_32_[2]+ local changes = state[bufnr].changes+ local request = {commentChars = get_option("parinfer_comment_chars"), prevCursorLine = prev_lnum, prevCursorX = prev_col, cursorLine = lnum, cursorX = (col + 1), changes = changes, forceBalance = normalize_bool(get_option("parinfer_force_balance"))}+ local response = modes[get_option("parinfer_mode")](text, request)+ state[bufnr]["changes"] = {}+ return response+end++-- Does kidna flicker+-- Also bad still+local function update_buffer(bufnr, old_contents, new_contents)+ api.nvim_command("silent! undojoin")+ state[bufnr]["locked"] = true+ do+ local new_lines = vim.split(new_contents, "\n")+ local hunks = diff(old_contents, new_contents, {result_type = "indices"})+ for _, hunk in ipairs(hunks) do+ local start_a = hunk[1]+ local count_a = hunk[2]+ local start_b = hunk[3]+ local count_b = hunk[4]+ local lines+ do+ local t = {}+ local i = 0+ for num = start_b, start_b + count_b do+ local new_line = new_lines[num]+ if new_line ~= nil then+ i = i + 1+ t[i] = new_line+ else+ end+ end+ lines = t+ end++ api.nvim_buf_set_lines(bufnr, start_a - 1, start_a + count_a, false, lines)+ end+ end+ local function _35_()+ state[bufnr]["locked"] = false+ return nil+ end+ return vim.schedule(_35_)+end++local function highlight_error(bufnr, err)+ api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)+ if err then+ local lnum,col = (err.lineNo - 1), (err.x - 1)+ return vim.highlight.range(bufnr, ns, "Error", {lnum, col}, {lnum, (col + 1)}, "c")+ elsenvim/lua/plugins/oil.lua view file
@@ -1,5 +1,3 @@-vim.cmd("packadd oil.nvim")- require("oil").setup({skip_confirm_for_simple_edits = true, default_file_explorer = true, watch_for_changes = true,nvim/lua/ui.lua view file
@@ -19,7 +19,7 @@ o.smartcase = true o.list = true-o.listchars = {tab = "» ", nbsp = "␣", trail = '·'}+o.listchars = {tab = "» ", nbsp = "␣", trail = "·"} o.fillchars = {eob = " "} o.wrap = falsenvim/pack/plugins/opt/oil.nvim/.envrc view file
@@ -1,3 +0,0 @@-export VIRTUAL_ENV=venv-layout python-python -c 'import pyparsing' 2>/dev/null || pip install -r scripts/requirements.txtnvim/pack/plugins/opt/oil.nvim/.luacheckrc view file
@@ -1,19 +0,0 @@-max_comment_line_length = false-codes = true--exclude_files = {- "tests/treesitter",-}--ignore = {- "212", -- Unused argument- "631", -- Line is too long- "122", -- Setting a readonly global- "542", -- Empty if branch-}--read_globals = {- "vim",- "a",- "assert",-}nvim/pack/plugins/opt/oil.nvim/.luarc.json view file
@@ -1,9 +0,0 @@-{- "runtime": {- "version": "LuaJIT",- "pathStrict": true- },- "type": {- "checkTableShape": true- }-}nvim/pack/plugins/opt/oil.nvim/.stylua.toml view file
@@ -1,5 +0,0 @@-column_width = 100-indent_type = "Spaces"-indent_width = 2-[sort_requires]-enabled = truenvim/pack/plugins/opt/oil.nvim/CHANGELOG.md view file
@@ -1,530 +0,0 @@-# Changelog--## [2.15.0](https://github.com/stevearc/oil.nvim/compare/v2.14.0...v2.15.0) (2025-02-13)---### Features--* add support for bufnr in column rendering functions ([#575](https://github.com/stevearc/oil.nvim/issues/575)) ([8abc58b](https://github.com/stevearc/oil.nvim/commit/8abc58b038f84078121ab1cac6ecad0163fe1635))-* API to automatically open preview window after opening oil ([#339](https://github.com/stevearc/oil.nvim/issues/339)) ([57528bf](https://github.com/stevearc/oil.nvim/commit/57528bf9c58080ca891e8d362d0a578895c136ce))-* can selectively add entries to quickfix ([#564](https://github.com/stevearc/oil.nvim/issues/564)) ([b594b9a](https://github.com/stevearc/oil.nvim/commit/b594b9a9052618669ccf6520b2d0c0d942eb8118))-* floating window max width/height can be percentages ([#553](https://github.com/stevearc/oil.nvim/issues/553)) ([1df90fa](https://github.com/stevearc/oil.nvim/commit/1df90faf927e78f5aacf278abd0bfdcb5f45e825))-* most moves and copies will copy the undofile ([#583](https://github.com/stevearc/oil.nvim/issues/583)) ([32dd3e3](https://github.com/stevearc/oil.nvim/commit/32dd3e378d47673679e76a773451f82f971a66df))-* pass oil bufnr to custom filename highlight function ([#552](https://github.com/stevearc/oil.nvim/issues/552)) ([f5c563a](https://github.com/stevearc/oil.nvim/commit/f5c563a074a38cee5a09f98e98b74dcd2c322490))---### Bug Fixes--* crash in preview on nvim 0.8 ([81b2c5f](https://github.com/stevearc/oil.nvim/commit/81b2c5f04ae24a8c83b20ecbd017fecac15faca0))-* directory rendering with custom highlights ([#551](https://github.com/stevearc/oil.nvim/issues/551)) ([a6a4f48](https://github.com/stevearc/oil.nvim/commit/a6a4f48b14b4a51fded531c86f6c04b4503a2ef8))-* disable_preview respected when preview_method != "load" ([#577](https://github.com/stevearc/oil.nvim/issues/577)) ([7cde5aa](https://github.com/stevearc/oil.nvim/commit/7cde5aab10f564408e9ac349d457d755422d58cd))-* error when non-current oil buffer has validation errors ([#561](https://github.com/stevearc/oil.nvim/issues/561)) ([8d11a2a](https://github.com/stevearc/oil.nvim/commit/8d11a2abf3039b1974d4acd65fbc83ada2ca1084))-* gracefully handle fs_stat failures ([#558](https://github.com/stevearc/oil.nvim/issues/558)) ([7c26a59](https://github.com/stevearc/oil.nvim/commit/7c26a59ac0061b199bf9f44b19d45cfadd9b14f5))-* guard against nil metadata values ([#548](https://github.com/stevearc/oil.nvim/issues/548)) ([254bc66](https://github.com/stevearc/oil.nvim/commit/254bc6635cb3f77e6e9a89155652f368e5535160))-* more consistent cursor position when entering a new directory ([#536](https://github.com/stevearc/oil.nvim/issues/536)) ([c80fa5c](https://github.com/stevearc/oil.nvim/commit/c80fa5c415b882c1c694a32748cea09b7dafc2c5))-* more robust parsing of custom column timestamp formats ([#582](https://github.com/stevearc/oil.nvim/issues/582)) ([5313690](https://github.com/stevearc/oil.nvim/commit/5313690956d27cc6b53d5a2583df05e717c59b16))-* open files in correct window from floating oil ([#560](https://github.com/stevearc/oil.nvim/issues/560)) ([83ac518](https://github.com/stevearc/oil.nvim/commit/83ac5185f79ab8d869bccea792dc516ad02ad06e))-* preview sometimes causes oil buffers to be stuck in unloaded state ([#563](https://github.com/stevearc/oil.nvim/issues/563)) ([1488f0d](https://github.com/stevearc/oil.nvim/commit/1488f0d96b1cb820dd12f05a7bf5283a631a7c4d))-* stat files if fs_readdir doesn't provide a type ([#543](https://github.com/stevearc/oil.nvim/issues/543)) ([c6a39a6](https://github.com/stevearc/oil.nvim/commit/c6a39a69b2df7c10466f150dde0bd23e49c1fba3))-* support permissions checks on windows and virtual filesystems ([#555](https://github.com/stevearc/oil.nvim/issues/555)) ([7041528](https://github.com/stevearc/oil.nvim/commit/7041528bdedb350ad66e650684deec8456e053cc))-* work around incorrect link detection on windows ([#557](https://github.com/stevearc/oil.nvim/issues/557)) ([09fa1d2](https://github.com/stevearc/oil.nvim/commit/09fa1d22f5edf0730824d2b222d726c8c81bbdc9))--## [2.14.0](https://github.com/stevearc/oil.nvim/compare/v2.13.0...v2.14.0) (2024-12-21)---### Features--* add `win_options` to `preview_win` ([#514](https://github.com/stevearc/oil.nvim/issues/514)) ([bbeed86](https://github.com/stevearc/oil.nvim/commit/bbeed86bde134da8d09bed64b6aa0d65642e6b23))-* add highlight group for orphaned links ([#502](https://github.com/stevearc/oil.nvim/issues/502)) ([740b8fd](https://github.com/stevearc/oil.nvim/commit/740b8fd425a2b77f7f40eb5ac155ebe66ff9515c))-* better merging of action desc when overriding keymaps ([f2b3249](https://github.com/stevearc/oil.nvim/commit/f2b324933f4d505cff6f7d445fd61fad02dcd9ae))-* config option to customize filename highlight group ([#508](https://github.com/stevearc/oil.nvim/issues/508)) ([99ce32f](https://github.com/stevearc/oil.nvim/commit/99ce32f4a2ecf76263b72fcc31efb163faa1a941))-* config option to disable previewing a file ([3fa3161](https://github.com/stevearc/oil.nvim/commit/3fa3161aa9515ff6a7cf7e44458b6a2114262870))-* disable preview for large files ([#511](https://github.com/stevearc/oil.nvim/issues/511)) ([c23fe08](https://github.com/stevearc/oil.nvim/commit/c23fe08e0546d9efc242e19f0d829efa7e7b2743))-* highlight groups for hidden files ([#459](https://github.com/stevearc/oil.nvim/issues/459)) ([60e6896](https://github.com/stevearc/oil.nvim/commit/60e68967e51ff1ecd264c29e3de0d52bfff22df3))-* option to quite vim if oil is closed as last buffer ([#491](https://github.com/stevearc/oil.nvim/issues/491)) ([81cc9c3](https://github.com/stevearc/oil.nvim/commit/81cc9c3f62ddbef3687931d119e505643496fa0a))-* use scratch buffer for file previews ([#467](https://github.com/stevearc/oil.nvim/issues/467)) ([21705a1](https://github.com/stevearc/oil.nvim/commit/21705a1debe6d85a53c138ab944484b685432b2b))---### Bug Fixes--* cursor sometimes does not hover previous file ([8ea40b5](https://github.com/stevearc/oil.nvim/commit/8ea40b5506115b6d355e304dd9ee5089f7d78601))-* don't take over the preview window until it's opened for oil ([#532](https://github.com/stevearc/oil.nvim/issues/532)) ([78ab7ca](https://github.com/stevearc/oil.nvim/commit/78ab7ca1073731ebdf82efa474202defa028d5a4))-* handle files with newlines in the name ([#534](https://github.com/stevearc/oil.nvim/issues/534)) ([dba0375](https://github.com/stevearc/oil.nvim/commit/dba037598843973b8c54bc5ce0318db4a0da439d))-* image.nvim previews with preview_method=scratch ([5acab3d](https://github.com/stevearc/oil.nvim/commit/5acab3d8a9bc85a571688db432f2702dd7d901a4))-* improper file name escaping ([#530](https://github.com/stevearc/oil.nvim/issues/530)) ([7a55ede](https://github.com/stevearc/oil.nvim/commit/7a55ede5e745e31ea8e4cb5483221524922294bf))-* set alternate when using floating windows ([#526](https://github.com/stevearc/oil.nvim/issues/526)) ([c5f7c56](https://github.com/stevearc/oil.nvim/commit/c5f7c56644425e2b77e71904da98cda0331b3342))-* work around performance issue with treesitter, folds, and large directories ([da93d55](https://github.com/stevearc/oil.nvim/commit/da93d55e32d73a17c447067d168d80290ae96590))---### Performance Improvements--* change default view_options.natural_order behavior to disable on large directories ([01b0b9d](https://github.com/stevearc/oil.nvim/commit/01b0b9d8ef79b7b631e92f6b5fed1c639262d570))-* only sort entries after we have them all ([792f0db](https://github.com/stevearc/oil.nvim/commit/792f0db6ba8b626b14bc127e1ce7247185b3be91))-* optimize rendering cadence ([c96f93d](https://github.com/stevearc/oil.nvim/commit/c96f93d894cc97e76b0871bec4058530eee8ece4))-* replace vim.endswith and vim.startswith with string.match ([4de3025](https://github.com/stevearc/oil.nvim/commit/4de30256c32cd272482bc6df0c6de78ffc389153))--## [2.13.0](https://github.com/stevearc/oil.nvim/compare/v2.12.2...v2.13.0) (2024-11-11)---### Features--* config option to customize floating window title ([#482](https://github.com/stevearc/oil.nvim/issues/482)) ([5d2dfae](https://github.com/stevearc/oil.nvim/commit/5d2dfae655b9b689bd4017b3bdccd52cbee5b92f))-* config option to disable lsp file methods ([#477](https://github.com/stevearc/oil.nvim/issues/477)) ([f60bb7f](https://github.com/stevearc/oil.nvim/commit/f60bb7f793477d99ef1acf39e920bf2ca4e644de))---### Bug Fixes--* actions.preview accepts options ([#497](https://github.com/stevearc/oil.nvim/issues/497)) ([cca1631](https://github.com/stevearc/oil.nvim/commit/cca1631d5ea450c09ba72f3951a9e28105a3632c))-* add trailing slash to directories on yank_entry ([#504](https://github.com/stevearc/oil.nvim/issues/504)) ([42333bb](https://github.com/stevearc/oil.nvim/commit/42333bb46e34dd47e13927010b1dcd30e6e4ca96))-* don't deep merge keymaps ([#510](https://github.com/stevearc/oil.nvim/issues/510)) ([709403c](https://github.com/stevearc/oil.nvim/commit/709403ccd6f22d859c2e42c780ab558ae89284d9))-* guard against nil keymaps ([621f8ba](https://github.com/stevearc/oil.nvim/commit/621f8ba4fa821724e9b646732a26fb2e795fe008))-* only map ~ for normal mode ([#484](https://github.com/stevearc/oil.nvim/issues/484)) ([ccab9d5](https://github.com/stevearc/oil.nvim/commit/ccab9d5e09e2d0042fbbe5b6bd05e82426247067))-* sort keymap help entries by description ([#506](https://github.com/stevearc/oil.nvim/issues/506)) ([52cc8a1](https://github.com/stevearc/oil.nvim/commit/52cc8a1fb35ea6ce1df536143add7ce7215c63c0)), closes [#376](https://github.com/stevearc/oil.nvim/issues/376)--## [2.12.2](https://github.com/stevearc/oil.nvim/compare/v2.12.1...v2.12.2) (2024-09-10)---### Bug Fixes--* ensure win_options are being set on correct window ([#469](https://github.com/stevearc/oil.nvim/issues/469)) ([30e0438](https://github.com/stevearc/oil.nvim/commit/30e0438ff08f197d7ce4a417445ab97ee72efe2d))-* wrap git rm callback in schedule_wrap ([#475](https://github.com/stevearc/oil.nvim/issues/475)) ([b053744](https://github.com/stevearc/oil.nvim/commit/b05374428e5136d9b6c8e1e8e62a75f82283b1f8))---### Performance Improvements-nvim/pack/plugins/opt/oil.nvim/Makefile view file
@@ -1,66 +0,0 @@-## help: print this help message-.PHONY: help-help:- @echo 'Usage:'- @sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'--## all: generate docs, lint, and run tests-.PHONY: all-all: doc lint test--venv:- python3 -m venv venv- venv/bin/pip install -r scripts/requirements.txt--## doc: generate documentation-.PHONY: doc-doc: scripts/nvim_doc_tools venv- venv/bin/python scripts/main.py generate- venv/bin/python scripts/main.py lint--## test: run tests-.PHONY: test-test:- ./run_tests.sh--## lint: run linters and LuaLS typechecking-.PHONY: lint-lint: scripts/nvim-typecheck-action fastlint- ./scripts/nvim-typecheck-action/typecheck.sh --workdir scripts/nvim-typecheck-action lua--## fastlint: run only fast linters-.PHONY: fastlint-fastlint: scripts/nvim_doc_tools venv- venv/bin/python scripts/main.py lint- luacheck lua tests --formatter plain- stylua --check lua tests--## profile: use LuaJIT profiler to profile the plugin-.PHONY: profile-profile: scripts/benchmark.nvim- nvim --clean -u perf/bootstrap.lua -c 'lua jit_profile()'--## flame_profile: create a trace in the chrome profiler format-.PHONY: flame_profile-flame_profile: scripts/benchmark.nvim- nvim --clean -u perf/bootstrap.lua -c 'lua flame_profile()'--## benchmark: benchmark performance opening directory with many files-.PHONY: benchmark-benchmark: scripts/benchmark.nvim- nvim --clean -u perf/bootstrap.lua -c 'lua benchmark()'- @cat perf/tmp/benchmark.txt--scripts/nvim_doc_tools:- git clone https://github.com/stevearc/nvim_doc_tools scripts/nvim_doc_tools--scripts/nvim-typecheck-action:- git clone https://github.com/stevearc/nvim-typecheck-action scripts/nvim-typecheck-action--scripts/benchmark.nvim:- git clone https://github.com/stevearc/benchmark.nvim scripts/benchmark.nvim--## clean: reset the repository to a clean state-.PHONY: clean-clean:- rm -rf scripts/nvim_doc_tools scripts/nvim-typecheck-action venv .testenv perf/tmp profile.jsonnvim/pack/plugins/opt/oil.nvim/README.md view file
@@ -1,448 +0,0 @@-# oil.nvim--A [vim-vinegar](https://github.com/tpope/vim-vinegar) like file explorer that lets you edit your filesystem like a normal Neovim buffer.--https://user-images.githubusercontent.com/506791/209727111-6b4a11f4-634a-4efa-9461-80e9717cea94.mp4--<!-- TOC -->--- [Requirements](#requirements)-- [Installation](#installation)-- [Quick start](#quick-start)-- [Options](#options)-- [Adapters](#adapters)-- [Recipes](#recipes)-- [Third-party extensions](#third-party-extensions)-- [API](#api)-- [FAQ](#faq)--<!-- /TOC -->--## Requirements--- Neovim 0.8+-- Icon provider plugin (optional)- - [mini.icons](https://github.com/nvim-mini/mini.nvim/blob/main/readmes/mini-icons.md) for file and folder icons- - [nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) for file icons--## Installation--oil.nvim supports all the usual plugin managers--<details>- <summary>lazy.nvim</summary>--```lua-{- 'stevearc/oil.nvim',- ---@module 'oil'- ---@type oil.SetupOpts- opts = {},- -- Optional dependencies- dependencies = { { "nvim-mini/mini.icons", opts = {} } },- -- dependencies = { "nvim-tree/nvim-web-devicons" }, -- use if you prefer nvim-web-devicons- -- Lazy loading is not recommended because it is very tricky to make it work correctly in all situations.- lazy = false,-}-```--</details>--<details>- <summary>Packer</summary>--```lua-require("packer").startup(function()- use({- "stevearc/oil.nvim",- config = function()- require("oil").setup()- end,- })-end)-```--</details>--<details>- <summary>Paq</summary>--```lua-require("paq")({- { "stevearc/oil.nvim" },-})-```--</details>--<details>- <summary>vim-plug</summary>--```vim-Plug 'stevearc/oil.nvim'-```--</details>--<details>- <summary>dein</summary>--```vim-call dein#add('stevearc/oil.nvim')-```--</details>--<details>- <summary>Pathogen</summary>--```shnvim/pack/plugins/opt/oil.nvim/doc/api.md view file
@@ -1,205 +0,0 @@-# API--<!-- TOC -->--- [get_entry_on_line(bufnr, lnum)](#get_entry_on_linebufnr-lnum)-- [get_cursor_entry()](#get_cursor_entry)-- [discard_all_changes()](#discard_all_changes)-- [set_columns(cols)](#set_columnscols)-- [set_sort(sort)](#set_sortsort)-- [set_is_hidden_file(is_hidden_file)](#set_is_hidden_fileis_hidden_file)-- [toggle_hidden()](#toggle_hidden)-- [get_current_dir(bufnr)](#get_current_dirbufnr)-- [open_float(dir, opts, cb)](#open_floatdir-opts-cb)-- [toggle_float(dir, opts, cb)](#toggle_floatdir-opts-cb)-- [open(dir, opts, cb)](#opendir-opts-cb)-- [close(opts)](#closeopts)-- [open_preview(opts, callback)](#open_previewopts-callback)-- [select(opts, callback)](#selectopts-callback)-- [save(opts, cb)](#saveopts-cb)-- [setup(opts)](#setupopts)--<!-- /TOC -->--<!-- API -->--## get_entry_on_line(bufnr, lnum)--`get_entry_on_line(bufnr, lnum): nil|oil.Entry` \-Get the entry on a specific line (1-indexed)--| Param | Type | Desc |-| ----- | --------- | ---- |-| bufnr | `integer` | |-| lnum | `integer` | |--## get_cursor_entry()--`get_cursor_entry(): nil|oil.Entry` \-Get the entry currently under the cursor---## discard_all_changes()--`discard_all_changes()` \-Discard all changes made to oil buffers---## set_columns(cols)--`set_columns(cols)` \-Change the display columns for oil--| Param | Type | Desc |-| ----- | ------------------ | ---- |-| cols | `oil.ColumnSpec[]` | |--## set_sort(sort)--`set_sort(sort)` \-Change the sort order for oil--| Param | Type | Desc |-| ----- | ---------------- | ------------------------------------------------------------------------------------- |-| sort | `oil.SortSpec[]` | List of columns plus direction. See :help oil-columns to see which ones are sortable. |--**Examples:**-```lua-require("oil").set_sort({ { "type", "asc" }, { "size", "desc" } })-```--## set_is_hidden_file(is_hidden_file)--`set_is_hidden_file(is_hidden_file)` \-Change how oil determines if the file is hidden--| Param | Type | Desc |-| -------------- | ------------------------------------------------ | -------------------------------------------- |-| is_hidden_file | `fun(filename: string, bufnr: integer): boolean` | Return true if the file/dir should be hidden |--## toggle_hidden()--`toggle_hidden()` \-Toggle hidden files and directories---## get_current_dir(bufnr)--`get_current_dir(bufnr): nil|string` \-Get the current directory--| Param | Type | Desc |-| ----- | -------------- | ---- |-| bufnr | `nil\|integer` | |--## open_float(dir, opts, cb)--`open_float(dir, opts, cb)` \-Open oil browser in a floating window-nvim/pack/plugins/opt/oil.nvim/doc/oil.txt view file
@@ -1,778 +0,0 @@-*oil.txt*-*Oil* *oil* *oil.nvim*----------------------------------------------------------------------------------CONTENTS *oil-contents*-- 1. Config |oil-config|- 2. Options |oil-options|- 3. Api |oil-api|- 4. Columns |oil-columns|- 5. Actions |oil-actions|- 6. Highlights |oil-highlights|- 7. Trash |oil-trash|-----------------------------------------------------------------------------------CONFIG *oil-config*-->lua- require("oil").setup({- -- Oil will take over directory buffers (e.g. `vim .` or `:e src/`)- -- Set to false if you want some other plugin (e.g. netrw) to open when you edit directories.- default_file_explorer = true,- -- Id is automatically added at the beginning, and name at the end- -- See :help oil-columns- columns = {- "icon",- -- "permissions",- -- "size",nvim/pack/plugins/opt/oil.nvim/doc/recipes.md view file
nvim/pack/plugins/opt/oil.nvim/lua/resession/extensions/oil.lua view file
nvim/pack/plugins/opt/oil.nvim/perf/bootstrap.lua view file
nvim/pack/plugins/opt/oil.nvim/run_tests.sh view file
nvim/pack/plugins/opt/oil.nvim/scripts/generate.py view file
nvim/pack/plugins/opt/oil.nvim/scripts/main.py view file
nvim/pack/plugins/opt/oil.nvim/scripts/requirements.txt view file
nvim/pack/plugins/opt/oil.nvim/syntax/oil.vim view file
nvim/pack/plugins/opt/oil.nvim/syntax/oil_preview.vim view file
nvim/pack/plugins/opt/oil.nvim/tests/altbuf_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/files_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/manual_progress.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/minimal_init.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/move_rename_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/mutator_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/parser_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/path_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/preview_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/regression_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/select_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/test_util.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/tmpdir.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/trash_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/url_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/util_spec.lua view file
nvim/pack/plugins/opt/oil.nvim/tests/win_options_spec.lua view file
nvim/pack/plugins/opt/parinfer-rust/.envrc view file
nvim/pack/plugins/opt/parinfer-rust/.gitignore view file
nvim/pack/plugins/opt/parinfer-rust/.nvmrc view file
nvim/pack/plugins/opt/parinfer-rust/CHANGELOG.adoc view file
nvim/pack/plugins/opt/parinfer-rust/Cargo.lock view file
nvim/pack/plugins/opt/parinfer-rust/Cargo.toml view file
nvim/pack/plugins/opt/parinfer-rust/LICENSE.md view file
nvim/pack/plugins/opt/parinfer-rust/Makefile view file
nvim/pack/plugins/opt/parinfer-rust/README.adoc view file
nvim/pack/plugins/opt/parinfer-rust/Web.toml view file
nvim/pack/plugins/opt/parinfer-rust/benches/perf.rs view file
nvim/pack/plugins/opt/parinfer-rust/benches/perf/long_map_with_strings view file
nvim/pack/plugins/opt/parinfer-rust/benches/perf/really_long_file view file
nvim/pack/plugins/opt/parinfer-rust/benches/perf/really_long_file_with_unclosed_paren view file
nvim/pack/plugins/opt/parinfer-rust/benches/perf/really_long_file_with_unclosed_quote view file
nvim/pack/plugins/opt/parinfer-rust/derivation.nix view file
nvim/pack/plugins/opt/parinfer-rust/dist/parinfer_rust.js view file
nvim/pack/plugins/opt/parinfer-rust/dist/parinfer_rust.wasm view file
nvim/pack/plugins/opt/parinfer-rust/dist/wrapper.js view file
nvim/pack/plugins/opt/parinfer-rust/doc/parinfer.txt view file
nvim/pack/plugins/opt/parinfer-rust/extra-docs/MacOS-Code-Signing.adoc view file
nvim/pack/plugins/opt/parinfer-rust/flake.lock view file
nvim/pack/plugins/opt/parinfer-rust/flake.nix view file
nvim/pack/plugins/opt/parinfer-rust/package.json view file
nvim/pack/plugins/opt/parinfer-rust/plugin/parinfer.vim view file
nvim/pack/plugins/opt/parinfer-rust/rc/parinfer.kak view file
nvim/pack/plugins/opt/parinfer-rust/script/release view file
nvim/pack/plugins/opt/parinfer-rust/src/c_wrapper.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/changes.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/cli_options.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/common_wrapper.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/emacs_wrapper.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/kakoune.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/lib.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/main.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/parinfer.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/types.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/wasm_wrapper.rs view file
nvim/pack/plugins/opt/parinfer-rust/src/webcore/runtime.js view file
nvim/pack/plugins/opt/parinfer-rust/src/webcore/runtime_wasm.js view file
nvim/pack/plugins/opt/parinfer-rust/tests/cases.rs view file
nvim/pack/plugins/opt/parinfer-rust/tests/cases/indent-mode.json view file
nvim/pack/plugins/opt/parinfer-rust/tests/cases/paren-mode.json view file
nvim/pack/plugins/opt/parinfer-rust/tests/cases/smart-mode.json view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/insert/cmd view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/insert/in view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/insert/out view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/janet/cmd view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/janet/in view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/janet/out view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/open-bracket/cmd view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/open-bracket/in view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/open-bracket/out view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/open-bracket/selections view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/picolisp/cmd view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/picolisp/in view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/picolisp/out view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/run.sh view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/select-word/cmd view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/select-word/in view file
nvim/pack/plugins/opt/parinfer-rust/tests/kakoune/select-word/selections view file
nvim/pack/plugins/opt/parinfer-rust/tests/vim/run.vim view file
nvim/pack/plugins/opt/parinfer-rust/tests/vim/tests-cases.md view file
nvim/pack/plugins/opt/parinfer-rust/tests/vim/vimrc view file
nvim/syntax/oil.vim view file