diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..295523b --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,149 @@ +name: main + +on: + push: + branches: [main] + pull_request: + types: [opened, synchronize] + +env: + LUA_LS_VERSION: 3.7.4 + +concurrency: + group: github.head_ref + cancel-in-progress: true + +jobs: + lint: + runs-on: ubuntu-latest + name: lint + steps: + - uses: actions/checkout@v4 + + - uses: JohnnyMorganz/stylua-action@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + version: latest + args: --check . -g '*.lua' -g '!deps/' + + documentation: + runs-on: ubuntu-latest + name: documentation + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: setup neovim + uses: rhysd/action-setup-vim@v1 + with: + neovim: true + version: v0.10.1 + + - name: generate documentation + run: make documentation-ci + + - name: check docs diff + run: exit $(git status --porcelain doc | wc -l | tr -d " ") + + tests: + needs: + - lint + - documentation + runs-on: ubuntu-latest + strategy: + matrix: + neovim_version: ['v0.9.5', 'v0.10.1'] + + steps: + - uses: actions/checkout@v4 + + - run: date +%F > todays-date + + - name: restore cache for today's nightly. + uses: actions/cache@v4 + with: + path: _neovim + key: ${{ runner.os }}-x64-${{ hashFiles('todays-date') }} + + - name: restore luals cache + uses: actions/cache@v4 + id: cache + with: + path: .ci/lua-ls + key: ${{ env.LUA_LS_VERSION }} + + - name: setup luals + if: ${{ steps.cache.outputs.cache-hit != 'true' }} + run: mkdir -p .ci/lua-ls && curl -sL "https://github.com/LuaLS/lua-language-server/releases/download/${{ env.LUA_LS_VERSION }}/lua-language-server-${{ env.LUA_LS_VERSION }}-linux-x64.tar.gz" | tar xzf - -C "${PWD}/.ci/lua-ls" + + - name: setup neovim + uses: rhysd/action-setup-vim@v1 + with: + neovim: true + version: ${{ matrix.neovim_version }} + + - uses: cachix/install-nix-action@v25 + - uses: cachix/cachix-action@v14 + with: + name: forester + signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' + + - run: nix profile install sourcehut:~jonsterling/ocaml-forester + + - name: run tests + run: make test-ci + + - name: Release + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + + tests-nightly: + needs: + - lint + - documentation + runs-on: ubuntu-latest + continue-on-error: true + + steps: + - uses: actions/checkout@v4 + + - run: date +%F > todays-date + + - name: restore cache for today's nightly. + uses: actions/cache@v4 + with: + path: _neovim + key: ${{ runner.os }}-x64-${{ hashFiles('todays-date') }} + + - name: restore luals cache + uses: actions/cache@v4 + id: cache + with: + path: .ci/lua-ls + key: ${{ env.LUA_LS_VERSION }} + + - name: setup luals + if: ${{ steps.cache.outputs.cache-hit != 'true' }} + run: mkdir -p .ci/lua-ls && curl -sL "https://github.com/LuaLS/lua-language-server/releases/download/${{ env.LUA_LS_VERSION }}/lua-language-server-${{ env.LUA_LS_VERSION }}-linux-x64.tar.gz" | tar xzf - -C "${PWD}/.ci/lua-ls" + + - name: setup neovim + uses: rhysd/action-setup-vim@v1 + with: + neovim: true + version: nightly + + - uses: cachix/install-nix-action@v25 + - uses: cachix/cachix-action@v14 + with: + name: forester + signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' + + - run: nix profile install sourcehut:~jonsterling/ocaml-forester + + - name: run tests + run: make test-ci + + - name: Release + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') diff --git a/.gitignore b/.gitignore index 5d44fa5..30e68fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +deps forest.json forest.toml build/ diff --git a/Makefile b/Makefile index 387e43d..b5b1645 100644 --- a/Makefile +++ b/Makefile @@ -1,28 +1,22 @@ -.PHONY: test lint docs init +# Run all test files +test: deps/mini.nvim + nvim --headless --noplugin -u ./scripts/minimal_init.lua -c "lua MiniTest.run()" -TESTS_DIR := test/ -PLUGIN_DIR := lua/ +# Run test from file at `$FILE` environment variable +test_file: deps/mini.nvim + nvim --headless --noplugin -u ./scripts/minimal_init.lua -c "lua MiniTest.run_file('$(FILE)')" -DOC_GEN_SCRIPT := ./scripts/docs.lua -MINIMAL_INIT := ./scripts/minimal_init.lua +# Download 'mini.nvim' to use its 'mini.test' testing module +deps: + @mkdir -p deps + git clone --filter=blob:none https://github.com/echasnovski/mini.nvim $@/mini.nvim + git clone --filter=blob:none https://github.com/nvim-lua/plenary.nvim $@/plenary.nvim + git clone --filter=blob:none https://github.com/nvim-telescope/telescope.nvim $@/telescope.nvim + git clone --filter=blob:none https://github.com/nvim-treesitter/nvim-treesitter $@/nvim-treesitter -test: - nvim --headless --noplugin -u ${MINIMAL_INIT} \ - -c "PlenaryBustedDirectory ${TESTS_DIR} { minimal_init = '${MINIMAL_INIT}' }" +documentation: + nvim --headless --noplugin -u ./scripts/minimal_init.lua -c "luafile scripts/minidoc.lua" -c "qa!" -lint: - luacheck ${PLUGIN_DIR} +documentation-ci: deps documentation -docs: - nvim --headless --noplugin -u ${MINIMAL_INIT} \ - -c "luafile ${DOC_GEN_SCRIPT}" -c 'qa' - -init: - @nvim --headless --noplugin \ - -c "vimgrep /my_awesome_plugin/gj **/*.lua **/*.vim Makefile" \ - -c "cfdo %s/my_awesome_plugin/$(name)/ge | update" \ - -c "qa" - @find . -depth -type d -name '*my_awesome_plugin*' | \ - while read dir; do mv "$$dir" "$${dir//my_awesome_plugin/$(name)}"; done - @find . -type f -name '*my_awesome_plugin*' | \ - while read file; do mv "$$file" "$${file//my_awesome_plugin/$(name)}"; done +test-ci: deps test diff --git a/README.md b/README.md index bca3f2d..3493041 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ # 🌲 forester.nvim 🌲 +[![main](https://github.com/kentookura/forester.nvim/actions/workflows/main.yml/badge.svg)](https://github.com/kentookura/forester.nvim/actions/workflows/main.yml) + Filetype plugin for [forester](https://sr.ht/~jonsterling/forester/), a tool for writing mathematical hypertext # Features -- Tree-sitter syntax highlighting +- Tree-sitter syntax highlighting. Please report any issues with the grammar in the [relevant repository](https://github.com/kentookura/tree-sitter-forester) - following links and transclusions with `gf` - Searching for trees by title with [telescope](https://github.com/nvim-telescope/telescope.nvim) diff --git a/doc/demo.tree b/doc/demo.tree deleted file mode 100644 index 1c41d83..0000000 --- a/doc/demo.tree +++ /dev/null @@ -1,52 +0,0 @@ -\title{Highlighting} -\taxon{demo} -\meta{external}{https://github.com/kentookura/forester.nvim} - -\tag{neovim} -\tag{treesitter} - -\p{ - \ul{ - \li{list} - \li{items} - \li{Todo: show surrounding braces when inside list} - - - } - \ol{ - \li{ordered list items would be awesome. Need to compute stuff in lua} - \li{Querying section numbering via forester 👀 } - } - - [Install the plugin](foo-0001) and try it out! See the example [neovim config](./init.lua) - - - Embedded syntax highlighting would be awesome. Requires syntax change in forester. - \code{ - def function() - end - } - - #{a = b} - - ##{ - \f\relax{x} = \int_{-\infty}^\infty - \f\hat\xi\,e^{2 \pi i \xi x} - \,d\xi - } -} - - -\def\my-object{ - \object[self]{ - [method1]{ - the implementation of this method \em{asdf} \strong{asdf} - } - [method2]{ - the implementation of another method - \self#method1 - } - } -} - - diff --git a/doc/forester.nvim.txt b/doc/forester.nvim.txt deleted file mode 100644 index dac1843..0000000 --- a/doc/forester.nvim.txt +++ /dev/null @@ -1,109 +0,0 @@ -*forester.nvim.txt* For NVIM v0.8.0 Last change: 2024 May 23 - -============================================================================== -Table of Contents *forester.nvim-table-of-contents* - -1. 🌲 forester.nvim 🌲 |forester.nvim-🌲-forester.nvim-🌲| -2. Features |forester.nvim-features| -3. Installation |forester.nvim-installation| -4. Configuration |forester.nvim-configuration| -5. Roadmap |forester.nvim-roadmap| -6. Links |forester.nvim-links| - -============================================================================== -1. 🌲 forester.nvim 🌲 *forester.nvim-🌲-forester.nvim-🌲* - -DOES NOT YET WORK WITH FORESTER 4.0 - -DOES NOT YET WORK WITH FORESTER 4.0 - -Filetype plugin for forester , a tool for -writing mathematical hypertext - - -============================================================================== -2. Features *forester.nvim-features* - -This plugin is pre-alpha, expect breaking changes. - -- Tree-sitter syntax highlighting - -Please report any issues with the grammar in the relevant repository - - -- following links and transclusions with `gf` -- Browsing forests with telescope -- Creating new trees within neovim - -Available user commands: - -- `Forester browse`: Telescope picker, search trees by title. TODO: support browsing by tag/taxon/… -- `Forester new`: Create a new tree by specifying a prefix -- `Forester config`: Choose the config file from which to source the tree directories - -These features need work: - -- `Forester transclude`: transclude a new tree at cursor position -- `Forester link`: link a new tree at cursor position - - -============================================================================== -3. Installation *forester.nvim-installation* - -With lazy: - ->lua - { - "kentookura/forester.nvim", - dependencies = { - { "nvim-treesitter/nvim-treesitter" }, - { "nvim-lua/plenary.nvim" }, - { "hrsh7th/nvim-cmp" }, - }, - }, -< - -You might need to run `:TSInstall toml` - - -============================================================================== -4. Configuration *forester.nvim-configuration* - ->lua - { - opts = { - forests = { "~/forest/"}, -- Global forests - tree_dirs = {"trees", "notes"} -- Where the plugin will look for trees relative to the current directory. - }; -- Works outside of global forests - - config = function() - local forester = require("forester") - vim.g.mapleader = " " - - vim.keymap.set("n", "n.", "Forester browse", { silent = true }) - vim.keymap.set("n", "nn", "Forester new", { silent = true }) - vim.keymap.set("i", "", "Forester transclude", { silent = true }) - vim.keymap.set("i", "", "Forester link", { silent = true }) - end, - } - - require("nvim-web-devicons").setup({ override_by_extension = { ["tree"] = { icon = "🌲" } } }) -< - - -============================================================================== -5. Roadmap *forester.nvim-roadmap* - -- Adding more telescope pickers and previewers, making use of the `forester query` commands -- Link & transclude existing trees at cursor position. -- autocomplete -- … - -============================================================================== -6. Links *forester.nvim-links* - -1. *Screenshot showcasing the conceal feature*: ./doc/highlight.png - -Generated by panvimdoc - -vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/doc/forester.txt b/doc/forester.txt new file mode 100644 index 0000000..5910212 --- /dev/null +++ b/doc/forester.txt @@ -0,0 +1,23 @@ +*forester.nvim* Forester filetype plugin + +========================================================================= + +Supported features: +- Autocomplete +- following links via `gf` +- fuzzy finding + +# Setup ~ + +Initialize the plugin via `require("forester").setup()` + +In your `forest.toml`, add the list of prefixes you wish to use: +>toml +prefixes = ["foo", "bar"] +< +This plugin currently does not support user configuration via lua. +I think it is preferrable to use the forester configuration files and +extracting the relevant keys via treesitter + + + vim:tw=78:ts=8:noet:ft=help:norl: \ No newline at end of file diff --git a/doc/nvm-0001.tree b/doc/nvm-0001.tree deleted file mode 100644 index f86890a..0000000 --- a/doc/nvm-0001.tree +++ /dev/null @@ -1,39 +0,0 @@ -\title{Forester.nvim} -\date{2024-01-08} -\tag{todo} -\tag{documentation} -\taxon{README} - -\subtree{ - \title{asdf} -} - -\scope{ - \put\transclude/title{Installation} - \transclude{nvm-0002} - } - -\p{ - See the example [[init.lua]] for installing with - [lazy.vim](https://github.com/folke/lazy.nvim). -} - - -\scope{\put\transclude/title{Todos} - \query{ \query/tag{todo} } -} - -\p{ - increment/decrement tree addrs using \code{} and \code{} - \code{h: nrformats} -} - -\p{ - no commands for inserting existing links, this should be handled by - completion provider. -} - -\p{ - nixvim -} - diff --git a/doc/nvm-0002.tree b/doc/nvm-0002.tree deleted file mode 100644 index 2e2400c..0000000 --- a/doc/nvm-0002.tree +++ /dev/null @@ -1,7 +0,0 @@ -\title{templating} -\tag{feature} - -\p{ - It might actually be better to use neovim templates than forester's - builtin templating functionality. -} diff --git a/doc/nvm-0003.tree b/doc/nvm-0003.tree deleted file mode 100644 index 397712b..0000000 --- a/doc/nvm-0003.tree +++ /dev/null @@ -1,7 +0,0 @@ -\title{templating} -\tag{bug} -\tag{todo} - -\p{ - strip leading whitespace and otherwise verify user inputh -} diff --git a/doc/tags b/doc/tags new file mode 100644 index 0000000..86a0c1e --- /dev/null +++ b/doc/tags @@ -0,0 +1 @@ +forester.nvim forester.txt /*forester.nvim* diff --git a/flake.lock b/flake.lock index 3ed6b42..f84c9cc 100644 --- a/flake.lock +++ b/flake.lock @@ -131,17 +131,18 @@ "opam-repository": "opam-repository_2" }, "locked": { - "lastModified": 1716654291, - "narHash": "sha256-ZtsGU0XSBOKBEUZZzSiChvL+dmxWc0bn2TqzMj3Kvz8=", - "owner": "~jonsterling", - "repo": "ocaml-forester", - "rev": "f106b90b6ac9bd12703a026c0271908ea66ada4e", - "type": "sourcehut" + "lastModified": 1728590048, + "narHash": "sha256-GAB7PFn8vCXewUNj/smfzo63/irXVOMWyvFL3Mp5Ris=", + "ref": "iri", + "rev": "10c214207f56454d7f7bcd8c7ac2bfb0b33ad3f2", + "revCount": 692, + "type": "git", + "url": "file:///home/kento/ocaml-forester" }, "original": { - "owner": "~jonsterling", - "repo": "ocaml-forester", - "type": "sourcehut" + "ref": "iri", + "type": "git", + "url": "file:///home/kento/ocaml-forester" } }, "mirage-opam-overlays": { @@ -192,16 +193,18 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1714809261, - "narHash": "sha256-hfBmnYFyz9I1mdrC3tX1A+dF9cOUcds5PIMPxrT+cRk=", + "lastModified": 1725634671, + "narHash": "sha256-v3rIhsJBOMLR8e/RNWxr828tB+WywYIoajrZKFM+0Gg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d32560238207b8e26d88b265207b216ee46b8450", + "rev": "574d1eac1c200690e27b8eb4e24887f8df7ac27c", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" } }, "nixpkgs_4": { @@ -245,11 +248,11 @@ "opam2json": "opam2json" }, "locked": { - "lastModified": 1712645768, - "narHash": "sha256-9dUh8nElGtC74Q4gIDV6DM0FKgF1oXh0PUkCxdbp+sg=", + "lastModified": 1716292162, + "narHash": "sha256-UOJNCbqvxABD56JZtZkv3C9ufdqrs7/Ep4AKkCHgPuo=", "owner": "tweag", "repo": "opam-nix", - "rev": "464863fba44c7ecc50bd1a2967274482a2c33daf", + "rev": "1d3cbd6d3f247db77cb581c88c9a1d72e4acad60", "type": "github" }, "original": { @@ -293,11 +296,11 @@ "opam-repository_2": { "flake": false, "locked": { - "lastModified": 1714767341, - "narHash": "sha256-JNtvibn9cj63fA258op64OzTyanjgF9YVqTKnl5F/Kk=", + "lastModified": 1725740801, + "narHash": "sha256-hlf57jytCuBRZnFwQilT59q4HP2g6XMiQLKdxl4dho0=", "owner": "ocaml", "repo": "opam-repository", - "rev": "3648176cc095f9106427fe05f07f0dc87ca27773", + "rev": "16e8d80cc51ddd05b3fa5c000eb2739cf0ee3a74", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b46534e..0f77110 100644 --- a/flake.nix +++ b/flake.nix @@ -2,14 +2,28 @@ inputs = { flake-utils.url = "github:numtide/flake-utils"; forest-server.url = "github:kentookura/forest-server"; - forester = { url = "sourcehut:~jonsterling/ocaml-forester"; }; + forester = { + # url = "sourcehut:~jonsterling/ocaml-forester"; + url = "/home/kento/ocaml-forester/?ref=iri"; + }; }; - outputs = { self, forest-server, flake-utils, nixpkgs, forester }@inputs: - flake-utils.lib.eachDefaultSystem (system: - let pkgs = import nixpkgs { inherit system; }; - in { + outputs = + { + self, + forest-server, + flake-utils, + nixpkgs, + forester, + }@inputs: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { inherit system; }; + in + { devShells.default = pkgs.mkShell { buildInputs = with pkgs; [ + act teseq forester.packages.${system}.default tree-sitter @@ -26,5 +40,6 @@ forest-server.packages.${system}.default ]; }; - }); + } + ); } diff --git a/lua/forester.lua b/lua/forester.lua index 840533d..2fc05d7 100644 --- a/lua/forester.lua +++ b/lua/forester.lua @@ -1,3 +1,25 @@ +--- *forester.nvim* Forester filetype plugin +--- +--- ========================================================================= +--- +--- Supported features: +--- - Autocomplete +--- - following links via `gf` +--- - fuzzy finding +--- +--- # Setup ~ +--- +--- Initialize the plugin via `require("forester").setup()` +--- +--- In your `forest.toml`, add the list of prefixes you wish to use: +--- >toml +--- prefixes = ["foo", "bar"] +--- < +--- This plugin currently does not support user configuration via lua. +--- I think it is preferrable to use the forester configuration files and +--- extracting the relevant keys via treesitter +--- + local completionSource = require("forester.completion") local commands = require("forester.commands") local ui = require("forester.ui") @@ -22,6 +44,7 @@ end local function setup() vim.filetype.add({ extension = { tree = "forester" } }) + local forester_group = vim.api.nvim_create_augroup("ForesterGroup", { clear = true }) local cfg = config.find_default_config() if cfg ~= "" then @@ -45,6 +68,24 @@ local function setup() }) end + -- Make links followable with `gf` + local add_treedirs_to_path = function() + pcall(function() + local dirs = config.tree_dirs() + for _, v in pairs(dirs) do + vim.opt.path:append(v) + end + end) + end + + vim.api.nvim_create_autocmd("User", { + group = forester_group, + pattern = "SwitchedForesterConfig", + callback = function() + add_treedirs_to_path() + end, + }) + local cmp = require("cmp") cmp.register_source("forester", completionSource) @@ -52,15 +93,9 @@ local function setup() add_treesitter_config() - -- Make links followable with `gf` - - local _ = pcall(function() - local dirs = config.tree_dirs() - for _, v in pairs(dirs) do - vim.opt.path:append(v) - end - end) vim.opt.suffixesadd:prepend(".tree") + + add_treedirs_to_path() ui.setup() end diff --git a/lua/forester/bindings.lua b/lua/forester/bindings.lua index acd08b7..6282a7b 100644 --- a/lua/forester/bindings.lua +++ b/lua/forester/bindings.lua @@ -11,13 +11,35 @@ local Job = require("plenary.job") local bindings = {} +local function init(dir) + local d_arg + if dir then + d_arg = { "--dir", dir } + else + d_arg = {} + end + return Job:new({ command = "forester", args = { "init", table.unpack(d_arg) } }) +end + local function watch(tree_dir, port) local _port = port or 1234 return Job:new({ command = "forest", args = { "watch", _port, tree_dir } }) end -local function build(config) - local job = Job:new({ command = "forester", args = { "build", config } }) +local function build(config, opts) + opts = opts or {} + local args = { "build" } + if opts.no_assets ~= nil and opts.no_assets then + table.insert(args, "--no-assets=true") + end + if opts.no_theme ~= nil and opts.no_theme then + table.insert(args, "--no-theme=true") + end + if opts.render_only ~= nil then + table.insert(args, "--render-only=" .. opts.render_only) + end + table.insert(args, config) + local job = Job:new({ command = "forester", args = args }) job:sync() return job:result() end @@ -119,6 +141,7 @@ local function template(pfx, tmpl_addr, dest, config) end bindings.watch = watch +bindings.init = init bindings.build = build bindings.query = query bindings.query_all = query_all diff --git a/lua/forester/commands.lua b/lua/forester/commands.lua index 5e1d111..f61ebd3 100644 --- a/lua/forester/commands.lua +++ b/lua/forester/commands.lua @@ -2,12 +2,13 @@ local util = require("forester.util") local Forester = require("forester.bindings") local Job = require("plenary.job") local pickers = require("forester.pickers") -local Config = require("forester.config") +local config = require("forester.config") local M = {} M.commands = { + -- Select the forester configuration file to use config = function() - Config.switch_config() + config.switch() end, build = function() @@ -31,7 +32,7 @@ M.commands = { end, new_random = function() - local prefixes = Config.all_prefixes() + local prefixes = config.all_prefixes() vim.ui.select(prefixes, { -- TODO: Don't select when #all_prefixes == 1 format_item = function(item) return item @@ -43,7 +44,7 @@ M.commands = { end else do - local path = Config.dir_of_latest_tree_of_prefix(choice) + local path = config.dir_of_latest_tree_of_prefix(choice) local new_tree = Forester.new_random(choice, path, vim.g.forester_current_config)[1] vim.cmd("edit " .. new_tree) end @@ -52,7 +53,7 @@ M.commands = { end, new = function() - local prefixes = Config.all_prefixes() + local prefixes = config.all_prefixes() vim.ui.select(prefixes, { -- TODO: Don't select when #all_prefixes == 1 format_item = function(item) return item @@ -64,7 +65,7 @@ M.commands = { end else do - local path = Config.dir_of_latest_tree_of_prefix(choice) + local path = config.dir_of_latest_tree_of_prefix(choice) local new_tree = Forester.new(choice, path, vim.g.forester_current_config)[1] vim.cmd("edit " .. new_tree) end @@ -73,7 +74,7 @@ M.commands = { end, transclude_new = function() - local prefixes = Config.all_prefixes() + local prefixes = config.all_prefixes() vim.ui.select(prefixes, { -- TODO: Don't select when #all_prefixes == 1 format_item = function(item) return item @@ -85,7 +86,7 @@ M.commands = { end else do - local path = Config.dir_of_latest_tree_of_prefix(choice) + local path = config.dir_of_latest_tree_of_prefix(choice) local new_tree = Forester.new(choice, path, vim.g.forester_current_config)[1] local addr = util.filename(new_tree):match("(.+)%..+$") local content = { "\\transclude{" .. addr .. "}" } @@ -96,7 +97,7 @@ M.commands = { end, link_new = function() - local prefixes = Config.all_prefixes() + local prefixes = config.all_prefixes() vim.ui.select(prefixes, { format_item = function(item) return item @@ -108,7 +109,7 @@ M.commands = { end else do - local path = Config.dir_of_latest_tree_of_prefix(choice) + local path = config.dir_of_latest_tree_of_prefix(choice) local new_tree = Forester.new(choice, path)[1] local addr = util.filename(new_tree):match("(.+)%..+$") local content = { "[](" .. addr .. ")" } -- NOTE: We should improve the workflow with snippets or something similar diff --git a/lua/forester/completion.lua b/lua/forester/completion.lua index 68797fc..e09b8d1 100644 --- a/lua/forester/completion.lua +++ b/lua/forester/completion.lua @@ -1,3 +1,4 @@ +--- Autocomplete for builtin functions and tree addresses local forester = require("forester.bindings") local config = require("forester.config") local util = require("forester.util") diff --git a/lua/forester/config.lua b/lua/forester/config.lua index a56bf7b..14a691d 100644 --- a/lua/forester/config.lua +++ b/lua/forester/config.lua @@ -2,7 +2,6 @@ local pickers = require("forester.pickers") local Scan = require("plenary.scandir") local Path = require("plenary.path") local util = require("forester.util") ---local Config = require("forester.config") local M = {} @@ -103,13 +102,14 @@ local function all_prefixes() return pfxs end -local function switch_config() +local function switch() local configs = all_configs() pickers.pick_config(configs) + vim.api.nvim_exec_autocmds("User", { pattern = "SwitchedForesterConfig" }) end M.all_prefixes = all_prefixes M.tree_dirs = tree_dirs -M.switch_config = switch_config +M.switch_config = switch return M diff --git a/lua/forester/util.lua b/lua/forester/util.lua index 774daf1..93d5510 100644 --- a/lua/forester/util.lua +++ b/lua/forester/util.lua @@ -1,7 +1,7 @@ -local Scan = require("plenary.scandir") -local Path = require("plenary.path") +local scan = require("plenary.scandir") +local path = require("plenary.path") -local os_sep = Path.path.sep +local os_sep = path.path.sep local M = {} @@ -17,13 +17,13 @@ local function filename(url) return url:match("[^/]+$") end -local split_path = function(path) +local split_path = function(p) -- Returns the Path, Filename, and Extension as 3 values - return string.match(path, "^(.-)([^\\/]-)(%.[^\\/%.]-)%.?$") + return string.match(p, "^(.-)([^\\/]-)(%.[^\\/%.]-)%.?$") end -local to_addr = function(path) - local _, addr, _ = split_path(path) +local to_addr = function(p) + local _, addr, _ = split_path(p) return addr end @@ -188,7 +188,7 @@ local extract_id = function(fname) end local highest_in_dir = function(pfx, dir) - local files = map(Scan.scan_dir(dir), function(file) + local files = map(scan.scan_dir(dir), function(file) local split = vim.split(file, os_sep) return split[#split] end) diff --git a/scripts/docs.lua b/scripts/docs.lua deleted file mode 100644 index 49e6602..0000000 --- a/scripts/docs.lua +++ /dev/null @@ -1,37 +0,0 @@ -local docgen = require("docgen") - -local docs = {} - -docs.test = function() - -- Filepaths that should generate docs - local input_files = { - "./lua/forester/bindings.lua", - "./lua/forester/commands.lua", - "./lua/forester/config.lua", - "./lua/forester/generate.lua", - "./lua/forester/navigation.lua", - "./lua/forester/ui.lua", - } - - -- Maybe sort them that depends what you want and need - table.sort(input_files, function(a, b) - return #a < #b - end) - - -- Output file - local output_file = "./doc/forester.txt" - local output_file_handle = io.open(output_file, "w") - assert(output_file_handle, "Could not open " .. output_file) - - for _, input_file in ipairs(input_files) do - docgen.write(input_file, output_file_handle) - end - - output_file_handle:write(" vim:tw=78:ts=8:ft=help:norl:\n") - output_file_handle:close() - vim.cmd([[checktime]]) -end - -docs.test() - -return docs diff --git a/scripts/minidoc.lua b/scripts/minidoc.lua new file mode 100644 index 0000000..7386975 --- /dev/null +++ b/scripts/minidoc.lua @@ -0,0 +1,17 @@ +local minidoc = require("mini.doc") + +if _G.MiniDoc == nil then + minidoc.setup() +end + +local hooks = vim.deepcopy(MiniDoc.default_hooks) + +hooks.write_pre = function(lines) + -- Remove first two lines with `======` and `------` delimiters to comply + -- with `:h local-additions` template + table.remove(lines, 1) + table.remove(lines, 1) + return lines +end + +MiniDoc.generate({ "lua/forester/commands.lua", "lua/forester.lua" }, "doc/forester.txt", { hooks = hooks }) diff --git a/scripts/minimal_init.lua b/scripts/minimal_init.lua index 24ed2d8..6d394b1 100644 --- a/scripts/minimal_init.lua +++ b/scripts/minimal_init.lua @@ -1,122 +1,19 @@ -vim.g.mapleader = " " - -local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" -if not vim.loop.fs_stat(lazypath) then - vim.fn.system({ - "git", - "clone", - "--filter=blob:none", - "https://github.com/folke/lazy.nvim.git", - "--branch=stable", - lazypath, - }) -end -vim.opt.rtp:prepend(lazypath) - -require("lazy").setup({ - - { "L3MON4D3/LuaSnip" }, - { "hrsh7th/nvim-cmp" }, - { - dir = "./.", -- change this to line to: "kentookura/neovim", - name = "forester.nvim", - opts = { - forests = { "~/glade/notes", "~/forest" }, -- global forest config - tree_dirs = { "trees" }, -- plugin will check if current directory contains these - preview = { port = "1234" }, - conceal = true, - }, - config = function(opts) - local forester = require("forester").setup() - - -- vim.keymap.set("n", "k", require("hover").hover, { desc = "hover.nvim" }) - vim.keymap.set("n", "n.", "Forester browse", { silent = true }) - -- vim.keymap.set("n", "nn", "Forester new", { silent = true }) - -- vim.keymap.set("i", "", "Forester transclude", { silent = true }) - -- vim.keymap.set("i", "", "Forester link", { silent = true }) - end, - dependencies = { - { "nvim-telescope/telescope.nvim" }, - { "nvim-treesitter/nvim-treesitter" }, - { "nvim-lua/plenary.nvim" }, - { "hrsh7th/nvim-cmp" }, - { "MunifTanjim/nui.nvim" }, - -- { "lewis6991/hover.nvim" }, - }, - }, - { "nvim-treesitter/nvim-treesitter" }, - { "nvim-lualine/lualine.nvim", dependencies = { "nvim-tree/nvim-web-devicons" } }, - { - "nvim-neo-tree/neo-tree.nvim", - config = function() - require("neo-tree").setup({ - sources = { "filesystem"}, - forest = { - window = { - mappings = { - -- - }, - }, - }, - }) - vim.keymap.set("n", "f", ":Neotree forest") - vim.keymap.set("n", "\\", ":Neotree toggle") - end, - }, - { - "navarasu/onedark.nvim", - priority = 1000, - config = function() - vim.cmd.colorscheme("onedark") - end, - }, -}) - -local cmp = require("cmp") -local luasnip = require("luasnip") -luasnip.config.setup({}) -cmp.setup({ - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - completion = { completeopt = "menu,menuone,noinsert" }, - - mapping = cmp.mapping.preset.insert({ - [""] = cmp.mapping.select_next_item(), - [""] = cmp.mapping.select_prev_item(), - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.complete({}), - [""] = cmp.mapping.confirm({ - behavior = cmp.ConfirmBehavior.Replace, - select = true, - }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif luasnip.expand_or_locally_jumpable() then - luasnip.expand_or_jump() - else - fallback() - end - end, { "i", "s" }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif luasnip.locally_jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, { "i", "s" }), - }), -}) - -require("nvim-web-devicons").setup({ override_by_extension = { ["tree"] = { icon = "🌲" } } }) -require("lualine").setup() - -vim.keymap.set("n", "t", "PlenaryTestFile %") -vim.keymap.set("n", "r", "Lazy reload forester.nvim") -vim.opt.termguicolors = true +-- Add current directory to 'runtimepath' to be able to use 'lua' files +vim.cmd([[let &rtp.=','.getcwd()]]) + +-- Set up 'mini.test' only when calling headless Neovim (like with `make test`) +-- if #vim.api.nvim_list_uis() == 0 then +-- Add 'mini.nvim' to 'runtimepath' to be able to use 'mini.test' +-- Assumed that 'mini.nvim' is stored in 'deps/mini.nvim' +vim.cmd("set rtp+=deps/plenary.nvim") +vim.cmd("set rtp+=deps/mini.nvim") +vim.cmd("set rtp+=deps/telescope.nvim") +vim.cmd("set rtp+=deps/nvim-treesitter") +vim.cmd("set rtp+=scripts/minidoc") + +require("nvim-treesitter.configs").setup({ ensure_installed = { "toml" }, auto_install = true, sync_install = true }) + +require("mini.test").setup() +require("mini.doc").setup() +-- require("mini.doc").setup() +-- end diff --git a/test/bindings.lua b/test/bindings.lua deleted file mode 100644 index a000d58..0000000 --- a/test/bindings.lua +++ /dev/null @@ -1,42 +0,0 @@ -local forester = require("forester.bindings") -local util = require("forester.util") -local scan = require("plenary.scandir") - -local tree_dir = "test/trees" - -describe("forester bindings", function() - --describe("complete", function() - -- it("works", function() - -- assert( - -- vim.deep_equal( - -- forester.titles(tree_dir), - -- { { addr = "foo-0001", title = "foo" }, { addr = "foo-0002", title = "bar" } } - -- ) - -- ) - -- end) - --end) - --describe("query", function() - -- it("works", function() - -- assert(vim.deep_equal(forester.query("prefix", tree_dir), { "foo" })) - -- end) - --end) - describe("new", function() - it("creates a new tree", function() - local count = 0 - scan.scan_dir(tree_dir, { - on_insert = function() - count = count + 1 - end, - }) - local output = forester.new("foo", tree_dir) - vim.print(vim.inspect(output)) - local scan_again = scan.scan_dir(tree_dir, {}) - assert(count + 1 == #scan_again) - end) - end) - --describe("template", function() - -- it("works", function() - -- --forester.template("foo", "test", "test") - -- end) - --end) -end) diff --git a/test/forester.lua b/test/forester.lua deleted file mode 100644 index eb389b6..0000000 --- a/test/forester.lua +++ /dev/null @@ -1,8 +0,0 @@ -local forester = require("forester") -local util = require("forester.util") -local scan = require("plenary.scandir") - -local tree_dir = "test/trees" - -forester.transclude_tree(tree_dir) -forester.link_tree(tree_dir) diff --git a/test/init.lua b/test/init.lua deleted file mode 100644 index 84b3121..0000000 --- a/test/init.lua +++ /dev/null @@ -1,101 +0,0 @@ -vim.g.mapleader = " " - -local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" -if not vim.loop.fs_stat(lazypath) then - vim.fn.system({ - "git", - "clone", - "--filter=blob:none", - "https://github.com/folke/lazy.nvim.git", - "--branch=stable", - lazypath, - }) -end -vim.opt.rtp:prepend(lazypath) - -require("lazy").setup({ - { - dir = "./.", -- change this to line to: "kentookura/neovim", - name = "forester.nvim", - config = function() - local forester = require("forester").setup() - - vim.keymap.set("n", "n.", "Forester browse", { silent = true }) - vim.keymap.set("n", "nn", "Forester new", { silent = true }) - -- vim.keymap.set("n", "k", require("hover").hover, { desc = "hover.nvim" }) - -- vim.keymap.set("i", "", "Forester transclude", { silent = true }) - -- vim.keymap.set("i", "", "Forester link", { silent = true }) - end, - dependencies = { - { "L3MON4D3/LuaSnip" }, - { "nvim-telescope/telescope.nvim" }, - { - "nvim-telescope/telescope-fzf-native.nvim", - build = "make", - cond = function() - return vim.fn.executable("make") == 1 - end, - }, - { "nvim-treesitter/nvim-treesitter" }, - { "nvim-lua/plenary.nvim" }, - { "hrsh7th/nvim-cmp" }, - { "MunifTanjim/nui.nvim" }, - -- { "lewis6991/hover.nvim" }, - }, - }, - { "nvim-treesitter/nvim-treesitter" }, -}) - -local cmp = require("cmp") -local luasnip = require("luasnip") - -cmp.setup({ - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - completion = { - completeopt = "menu,menuone,noinsert", - }, - mapping = cmp.mapping.preset.insert({ - [""] = cmp.mapping.select_next_item(), - [""] = cmp.mapping.select_prev_item(), - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.complete({}), - [""] = cmp.mapping.confirm({ - behavior = cmp.ConfirmBehavior.Replace, - select = true, - }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif luasnip.expand_or_locally_jumpable() then - luasnip.expand_or_jump() - else - fallback() - end - end, { "i", "s" }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif luasnip.locally_jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, { "i", "s" }), - }), - sources = { - { name = "nvim_lsp" }, - { name = "luasnip" }, - { name = "path" }, - { name = "forester" }, - }, -}) - ---require("nvim-web-devicons").setup({ override_by_extension = { ["tree"] = { icon = "🌲" } } }) -vim.keymap.set("n", "t", "PlenaryTestFile %") -vim.keymap.set("n", "r", "Lazy reload forester.nvim") -vim.opt.termguicolors = true diff --git a/test/util.lua b/test/util.lua deleted file mode 100644 index f2ae1d4..0000000 --- a/test/util.lua +++ /dev/null @@ -1,29 +0,0 @@ -local forester = require("forester") -local util = require("forester.util") -local scan = require("plenary.scandir") - -describe("forester functions", function() - describe("pad_addr", function() - it("works", function() - assert("0001" == util.pad_addr(1)) - assert("01TA" == util.pad_addr(2350)) - end) - end) - describe("next_addr", function() - it("works", function() - assert("foo-0002" == util.inc_addr("foo", 1)) - assert("foo-000A" == util.inc_addr("foo", 9)) - assert("foo-000F" == util.inc_addr("foo", 14)) - assert("foo-1000" == util.inc_addr("foo", 46655)) -- base36: ZZZ - end) - end) - - describe("prev_addr", function() - it("works", function() - assert("foo-0001" == util.decr_addr("foo", 2)) - assert("foo-0009" == util.decr_addr("foo", 10)) - assert("foo-000D" == util.decr_addr("foo", 14)) - assert("foo-0ZZY" == util.decr_addr("foo", 46655)) -- base36: ZZZ - end) - end) -end) diff --git a/tests/test_bindings.lua b/tests/test_bindings.lua new file mode 100644 index 0000000..3cd2434 --- /dev/null +++ b/tests/test_bindings.lua @@ -0,0 +1,47 @@ +local forester = require("forester.bindings") +local config = require("forester.config") +local path = require("plenary.path") +local map = require("forester.util").map +local expect, eq = MiniTest.expect, MiniTest.expect.equality +local T = MiniTest.new_set() + +local test_forest = path:new("test_forest") +local cfg = path:new("forest.toml") + +local clean_test_forest = function() + path.rmdir(test_forest) + path.rm(cfg) +end + +local setup_test_forest = function() + local p = path:new("trees") + p:mkdir() + cfg:write( + '[forest]\ +trees = ["trees", "foo", "bar"]\ +prefixes = ["test", "pfx"]', + "w", + 438 + ) + vim.g.forester_current_config = "forest.toml" +end + +T["bindings"] = MiniTest.new_set({ hooks = { pre_once = setup_test_forest, post_once = clean_test_forest } }) + +T["bindings"]["config"] = function() + local expected_tree_dirs = { "trees", "foo", "bar" } + local cwd = map(expected_tree_dirs, function(p) + return path:new(p):absolute() + end) + eq(config.all_prefixes(), { "test", "pfx" }) + eq(config.tree_dirs(), cwd) +end + +T["bindings"]["build"] = function() + local res = forester.build("forest.toml", { no_assets = true, no_theme = true }) + eq(res, {}) +end + +T["bindings"]["new_tree"] = function() end + +return T diff --git a/tests/test_forester.lua b/tests/test_forester.lua new file mode 100644 index 0000000..795dc0e --- /dev/null +++ b/tests/test_forester.lua @@ -0,0 +1,15 @@ +local new_set = MiniTest.new_set +local expect, eq = MiniTest.expect, MiniTest.expect.equality + +local T = new_set() + +-- Actual tests definitions will go here + +T["works"] = function() + local x = 1 + 1 + if x ~= 2 then + error("`x` is not equal to 2") + end +end + +return T diff --git a/tests/test_util.lua b/tests/test_util.lua new file mode 100644 index 0000000..91436fb --- /dev/null +++ b/tests/test_util.lua @@ -0,0 +1,25 @@ +local T = MiniTest.new_set() +local expect, eq = MiniTest.expect, MiniTest.expect.equality + +local util = require("forester.util") + +T["pad_addr"] = function() + eq("0001", util.pad_addr(1)) + eq("01TA", util.pad_addr(2350)) +end + +T["next_addr"] = function() + eq("foo-0002", util.inc_addr("foo", 1)) + eq("foo-000A", util.inc_addr("foo", 9)) + eq("foo-000F", util.inc_addr("foo", 14)) + eq("foo-1000", util.inc_addr("foo", 46655)) -- base36: ZZZ +end + +T["prev_addr"] = function() + eq("foo-0001", util.decr_addr("foo", 2)) + eq("foo-0009", util.decr_addr("foo", 10)) + eq("foo-000D", util.decr_addr("foo", 14)) + eq("foo-0ZZY", util.decr_addr("foo", 46655)) -- base36: ZZZ +end + +return T