From a31e6ff391a44afed361ddf8585dcbaa942141c8 Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 18 Oct 2023 22:19:55 +0000 Subject: [PATCH] Deployed 94b7c7d with MkDocs version: 1.5.3 --- neovim-basics/index.html | 15 ++++++++++++++- search/search_index.json | 2 +- sitemap.xml.gz | Bin 797 -> 797 bytes 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/neovim-basics/index.html b/neovim-basics/index.html index 31d11e11..4766143d 100644 --- a/neovim-basics/index.html +++ b/neovim-basics/index.html @@ -2483,6 +2483,13 @@ Fundamentals + + +
  • + + Keyboard mappings + +
  • @@ -2549,6 +2556,12 @@

    Using NeovimFundamentalsλ︎

    File Buffer Window and Tab page Multi-modal Editing

    +

    Keyboard mappingsλ︎

    +

    :verbose map followed by a key binding shows the location of the configuration that was last used to set the key mapping. Use when its not clear what command a key mapping is calling or if a plugin is over-riding an expected mapping.

    +

    Space f n to list all notifications and Enter on the relevant notification to see the details.

    +

    :verbose map <C-Up> shows the last place in the neovim config that defines a mapping for Ctrl+Up arrow.

    +

    Listing Mappings: Neovim documentation +Key Notation: Neovim documentation

    Editing Toolsλ︎

    Multiple Cursors

    Writing Toolsλ︎

    @@ -2579,7 +2592,7 @@

    SpellcheckOctober 5, 2023 + October 18, 2023 diff --git a/search/search_index.json b/search/search_index.json index adee3408..f4c1ae55 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Neovim for Clojure development","text":"

    coding at the speed of thought

    Neovim is incredibly fast and efficient, so thoughts flow from brain to editor without unnecessary delay.

    Touch typing is fast, Neovim and multi-modal editing makes it even faster.

    Neovim is a highly extensible and powerful editor, supporting multi-modal editing and Vim-style sequential key bindings. Highly responsive and low resource use makes Neovim ideal for development on any computer or mobile device, e.g. tablet, smartphone.

    Neovim has a diverse set of plugins and Practicalli curated configurations use these plugins to provide a rich set of features for Clojure development and wider engineering tasks.

    Practicalli Neovim provides install & user guide focused on a simple, powerful and satisfying REPL Driven workflow for Clojure.

    "},{"location":"#quick-start","title":"Quick Start","text":"

    Install Clojure, Neovim and choose a community configuration

    • [Lua] AstroNvim
    • [Fennel] Practicalli Neovim Config Redux
    "},{"location":"#external-reverences","title":"External reverences","text":"

    Getting started with Neovim and Conjure

    Neovim user guide

    This Week In Neovim - community update

    Conjure install guide Conjuring Clojure in Vim

    "},{"location":"#navigate-the-book","title":"Navigate the book","text":"

    Use the mouse or built-in key bindings to navigate the pages of the book

    • P , , : go to previous page
    • N , . : go to next page

    Use the search box to quickly find a specific topic

    • F , S , / : open search dialog
    • Down , Up : select next / previous result
    • Esc , Tab : close search dialog
    • Enter : follow selected result
    "},{"location":"#sponsor-my-work","title":"Sponsor my work","text":"

    All sponsorship recieved is used to maintain and further develop the Practicalli series of books and videos, although most of the work is still done with my own time and cost.

    Thank you to Cognitect, Nubank and a wide range of other sponsors from the Clojure community for your continued support

    "},{"location":"#creative-commons-license","title":"Creative commons license","text":"This work is licensed under a Creative Commons Attribution 4.0 ShareAlike License (including images & style sheets)."},{"location":"api-tools/","title":"API Tools","text":"

    Astrocommunity proivdes plugins to support working with APIs and the JSON format

    • nvim-jqx
    • rest-nvim

    Included in Practicalli Astronvim Config

    Practicalli Astronvim Config includes nvim-jqx and rest.nvim plugins

    "},{"location":"api-tools/#inspect-json","title":"Inspect JSON","text":"

    Browse and preview json files in neovim.

    :JqxList prettify JSON and start the inspector

    JqxQuery to run complex jq commands

    jq binary required

    jq binary should be available on the command line as nvim-jqx runs jq queries internally

    nvim-jqx

    "},{"location":"api-tools/#call-apis","title":"Call APIs","text":"

    Space r r to run an http request under the cursor from within an *.http file.

    A fast Neovim http client written in Lua, providing a curl wrapper.

    "},{"location":"api-tools/#http-file","title":"http file","text":"

    Open a file with an *.http extension

    Write a call to an API, e.g. a call to a local server health care endpoint

    Call locally running API

    health-check.http
    GET http://localhost:8080/system-admin/status\n

    A new window opens with the result of the API call

    Result of API call with rest.nvim
    GET http://localhost:8080/system-admin/status\nCommand :curl -sSL --compressed -X 'GET' --data-raw '' 'http://localhost:8080/system-admin/status'\n#+END\nHTTP/1.1 200 OK\nContent-Type: application/json; charset=utf-8\nContent-Length: 66\nServer: http-kit\nDate: Mon, 10 Jul 2023 16:21:33 GMT\n\n#+RESPONSE\n{\"application\":\"practicalli hole-in-one Service\",\"status\":\"Alive\"}\n#+END\n

    The Content-Type can be explicitly set, especially useful when not using JSON

    API call returning EDN data

    GET http://localhost:8080/api/v1/scoreboard\naccept: application/edn\n

    rest.nvim test examples

    rest.nvim

    "},{"location":"assets/images/social/","title":"Social Cards","text":"

    Social Cards are visual previews of the website that are included when sending links via social media platforms.

    Material for MkDocs is configured to generate beautiful social cards automatically, using the colors, fonts and logos defined in mkdocs.yml

    Generated images are stored in this directory.

    "},{"location":"configuration/","title":"Neovim Configuration","text":"

    Practicalli Neovim covers the following configurations.

    • AstroNvim - thoughtful configuration, supports Neovim 0.9 onward, polished UI, many community extensions
    • Practicalli Neovim Config Redux - mnemonic key bindings, packer, telescope selector, written in Fennel
    "},{"location":"configuration/#multiple-configurations","title":"Multiple Configurations","text":"

    Install multiple configurations, e.g. AstroNvim, lazyvim, Nvchad, etc. in the $HOME/.config directory using unique directory names.

    Set NVIM_APPNAME to specific the configuration to use when running nvim.

    NVIM_APPNAME=astronvim nvim\n

    NVIM_APPNAME variable should be set to the directory name containing the configuration, relative to the .config directory.

    The configuration directory name is used to hold share, state and cache files for that specific configuration.

    Create shell aliases for each configuration. Optionalliy, define a terminal UI selection to choose a configuration.

    Shell AliasesTerminal UI Selector

    Create a Shell alias for each configuration that will be used, to avoid setting the NVIM_APPNAME variable each time.

    Define Shell Aliases to run each configuration

    alias astro=\"NVIM_APPNAME=astronvim nvim\"\nalias lazyvim=\"NVIM_APPNAME=lazyvim nvim\"\nalias practicalli-redux=\"NVIM_APPNAME=neovim-config-redux nvim\"\n

    Create an nvim configuration selector script, with items listing the directory name of each configuration

    Z Shell nvim-selector script

    .local/bin/nvim-selector
    function nvim-selector() {\n  items=(\"astronvim\" \"neovim-config-redux\" \"lazyvim\")\n  config=$(printf \"%s\\n\" \"${items[@]}\" | fzf --prompt=\"\ue62b Neovim Config \uf63d \" --height=~50% --layout=reverse --border --exit-0)\n  if [[ -z $config ]]; then\n    echo \"Nothing selected\"\n    return 0\n  elif [[ $config == \"default\" ]]; then\n    config=\"\"\n  fi\n  NVIM_APPNAME=$config nvim $@\n}\n
    "},{"location":"configuration/astronvim/","title":"AstroNvim","text":"

    AstroNvim is a community configuration with an engaging UI, using Lazy for plugin management (Neovim packages) and Mason for package management (LSP, DAP, format and lint tools)

    Practicalli AstroNvim Config is a user configuration that extends AstroNvim and imports packages from the AstroNvim Community.

    "},{"location":"configuration/astronvim/#prerequisits","title":"Prerequisits","text":"
    • Nerd Fonts version 3 - download a full font or only the symbols
    • fzf fuzzy finder (ubuntu archive)
    • gtu (Ubuntu package archive)
    • btm from GitHub repository releases
    • node.js (version 20) for Mason install of many LSP servers

    AstroNvim requires node.js

    AstroNvim uses Mason to install LSP servers, format and lint tools. Many LSP servers require node.js to install and function.

    Node.js install - Practicalli Engineering Playbook

    Kitty Terminal with Nerd Fonts

    Kitty Terminal - Practicalli Engineering Playbook provides examples of using Nerd Fonts or Nerd Font symbols with the Kitty terminal.

    "},{"location":"configuration/astronvim/#clone-astronvim","title":"Clone AstroNvim","text":"

    Clone AstroNvim repository to $HOME/.config/astronvim/

    git clone --depth 1 https://github.com/AstroNvim/AstroNvim ~/.config/astronvim\n

    $HOME/.config/nvim can be used instead if only ever using one configuration for Neovim.

    "},{"location":"configuration/astronvim/#clone-astronvim-user-config","title":"Clone AstroNvim user config","text":"

    AstroNvim provides a template repository to create a user configuration. The template includes AstroNvim Community configuration to make it easier to extend the feature of AstroNvim.

    Practicalli AstroNvim Config is a clone of the AstroNvim user config with additional configuration to support Clojure development.

    Practicalli AstroNvim ConfigAstroNvim User Config

    Clone the Practicalli AstroNvim config which provides a user configuration with Clojure support

    git clone http://github.com/practicalli/astronvim-config $HOME/.config/astronvim/lua/user\n

    Or clone to a separate directory and create a symbolic link

    git clone http://github.com/practicalli/astronvim-config $HOME/.config/astronvim-config && \\\nln -s $HOME/.config/astronvim-config/ $HOME/.config/astronvim/lua/user\n

    Create your own user configuration using the AstroNvim user configuration template repository.

    Create a repository from the AstroNvim/user_example repository template

    Clone the newly created repository into the existing AstroNvim configuration, in a user directory

    git clone git@github.com/<github-account>/<new-repository> $HOME/.config/astronvim/lua/user\n

    "},{"location":"configuration/astronvim/#configure-shell-alias","title":"Configure shell alias","text":"

    Create a shell alias that sets NVIM_APPNAME to the location of the AstroNvim community config

    Add alias to .bashrc for Bash shell or .zshenv for Zsh

    alias astro=\"NVIM_APPNAME=astronvim nvim\"\n

    Configure shell alias

    "},{"location":"configuration/astronvim/#post-install","title":"Post install","text":"

    Open a terminal and use the astro alias to run Neovim.

    astro\n

    NVIM_APPNAME=astronvim nvim to run Neovim with astronvim without setting a shell alias.

    Neovim will open and display the Lazy plugin manager UI, showing the progress of plugin installation. This should only happen on the first run.

    Unattended post install

    Plugins can be installed without running the Neovim editor UI

    nvim --headless -c 'autocmd User LazyDone quitall'\n
    "},{"location":"configuration/astronvim/#check-health","title":"Check Health","text":"

    Run the Neovim :checkhealth command to report on the general Neovim install and supporting tools

    "},{"location":"configuration/astronvim/#add-lsp-dap-lint-and-format-tools","title":"Add LSP DAP Lint and Format tools","text":"

    SPC p m to launch Mason which manages LSP servers, linters, filters ...

    "},{"location":"configuration/astronvim/#configure-format-rules","title":"Configure format rules","text":"

    The configuration files for each lint and format tool should be used by Neovim.

    Setting a different location for these files has proved challenging. plugin/null-ls.lua has a section to override its builtin configuration for each lint and format tool, however, in tests Practicalli was unable to succeffuly set a different location.

    "},{"location":"configuration/astronvim/config-design/","title":"\ud83d\udce6 Practicalli AstroNvim Config Design","text":"

    A guide to the AstroNvim Config user configuration created by Practicalli to support Clojure development.

    AstroCommunity used where possible

    Plugins and configuration is added vial AstroCommunity were possible, to minimise the code size and maintenance of the configuration

    "},{"location":"configuration/astronvim/config-design/#user-config-overview","title":"User Config overview","text":"

    core.lua is for tuning plugins shipped with astronvim config

    plugins/ for additional plugins organised logically. All .lua files are read from this directory

    • user.lua for general user defined plugins
    • clojure.lua adds Conjure and parinf, ensuring Clojure treesitter parser and Clojure LSP
    "},{"location":"configuration/astronvim/config-design/#clojure-support","title":"Clojure support","text":"

    The AstroCommunity provides a Clojure language pack that adds Conjure and nvim-parinfer, along with clojure Treesitter parser and clojure-lsp support.

    AstroCommunity PackManually add plugins

    Edit the plugins/community.lua file and import the Clojure pack. The \"AstroNvim/astrocommunity\", repository is already added to to the file.

    -- Packs\n-- Treesitter: clojure , Lsp: clojure-lsp, Lint/format:\n{ import = \"astrocommunity.pack.clojure\" },\n
    Override AstroCommunity Pack

    Create a plugins/clojure.lua file and add the AstroCommunity repository, Clojure pack and additional configuration to your own preferences

    Clojure configuration with user configration overrides

    return {\n  \"AstroNvim/astrocommunity\",\n  { import = \"astrocommunity.pack.clojure\" },\n  {\n    \"Olical/conjure\",\n    -- load plugin on filetypes\n    ft = { \"clojure\", \"fennel\" },\n    config = function()\n      -- HUD\n      -- Example: Set to `\"SE\"` and HUD width to `1.0` for full width HUD at bottom of screen\n      vim.g[\"conjure#log#hud#width\"] = 1 -- Width of HUD as percentage of the editor width, 0.0 and 1.0.\n      vim.g[\"conjure#log#hud#enabled\"] = false -- Display HUD\n      vim.g[\"conjure#log#hud#anchor\"] = \"SE\" -- Preferred corner position for the HUD\n      vim.g[\"conjure#log#botright\"] = true -- Open log at bottom or far right of editor\n      -- REPL\n      vim.g[\"conjure#extract#context_header_lines\"] = 100 -- Number of lines to check for `ns` form\n      vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false -- ;; Start \"auto-repl\" process, eg. babashka\n      vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true -- ;; Hide auto-repl buffer when triggered\n      vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil -- ;; Command to start the auto-repl\n      -- ;; Automatically require namespace of new buffer or current buffer after connection\n      vim.g[\"conjure#client#clojure#nrepl#eval#auto_require\"] = false\n      -- Reloading code\n      -- Function to call on refresh (reloading) the log, namespace-qualified name of a zero-arity\n      -- vim.g[\"conjure#client#clojure#nrepl#refresh#after\"] = nil\n      -- The namespace-qualified name of a zero-arity function to call before reloading.\n      -- vim.g[\"conjure#client#clojure#nrepl#refresh#before\"] = nil\n      -- List of directories to scan. If no directories given, defaults to all directories on the classpath.\n      -- vim.g[\"conjure#client#clojure#nrepl#refresh#dirs\"] = nil\n      -- Testing\n      -- ;; Test runner called from the test key mappings\n      vim.g[\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\"\n      -- Print raw test evaluation result, suppressing prefix for stdout lines `; (out)`\n      -- vim.g[\"conjure#client#clojure#nrepl#test#raw_out\"] = nil\n      -- Override string appended to the end of the test runner calls\n      -- vim.g[\"conjure#client#clojure#nrepl#test#call_suffix\"] = nil\n    end\n  },\n  {\n    \"gpanders/nvim-parinfer\",\n    ft = lisp_dialects,\n    config = function()\n      vim.g.parinfer_force_balance = true\n      vim.g.parinfer_comment_chars = \";;\"\n    end,\n  },\n}\n

    Add Conjure and parinfer plugin that will load when Clojure or Fennel file is opened.

    Clojure Packages in AstroNvim user configuration

    ```lua title=\".config/astronvim-config/plugins/clojure.lua\"\n-- Lazy Package manager configuration\nreturn {\n  {\n    \"Olical/conjure\",\n    -- load plugin on filetypes\n    ft = { \"clojure\", \"fennel\" },\n  },\n\n  {\n    \"gpanders/nvim-parinfer\",\n    ft = { \"clojure\", \"fennel\" },\n    config = function()\n      vim.g.parinfer_force_balance = true\n      vim.g.parinfer_comment_chars = \";;\"\n    end,\n  },\n}\n```\n

    Improve syntax highlighting by installing the Clojure parser for Treesitter.

    Treesitter Parser for clojure in AstroNvim user configuration

    .config/astronvim-config/plugins/treesitter.lua
    return {\n  \"nvim-treesitter/nvim-treesitter\",\n  opts = function(_, opts)\n    -- add more things to the ensure_installed table protecting against community packs modifying it\n    opts.ensure_installed = require(\"astronvim.utils\").list_insert_unique(opts.ensure_installed, {\n      -- \"lua\"\n    \"clojure\"\n    })\n  end,\n}\n

    Install Treesitter Clojure Parser manually

    :TSInstall clojure in Neovim will install the parser. A parser not included in the opts.ensure_installed configuration must be updated manually each time treesitter plugin is updated

    "},{"location":"configuration/astronvim/config-design/#clojure-mappings","title":"Clojure Mappings","text":"

    Conjure mappings are defined respective to a <localleader> value. Define a local leader in the AstroNvim user configuration, e.g. , and all Conjure mappings become available.

    AstroNvim 3.17.0 has localleader

    AstroNvim 3.17.0 release sets localleader to , so a separate setting is not required in the user configuration (unless a different localleader is preferred)

    Set localleader in user config

    options.lua in the user configuration provides a consistent way to set Neovim options.

    .config/astronvim-config/options.lua
    -- set vim options here (vim.<first_key>.<second_key> = value)\nreturn {\n  opt = {\n    -- set to true or false etc.\n    relativenumber = true, -- sets vim.opt.relativenumber\n    number = true,         -- sets vim.opt.number\n    spell = false,         -- sets vim.opt.spell\n    signcolumn = \"auto\",   -- sets vim.opt.signcolumn to auto\n    wrap = false,          -- sets vim.opt.wrap\n  },\n  g = {\n    mapleader = \" \",                 -- sets vim.g.mapleader\n    maplocalleader = \",\",            -- Set local leader key binding (supports Conjure key bindings)\n    autoformat_enabled = true,       -- enable or disable auto formatting at start (lsp.formatting.format_on_save must be enabled)\n    cmp_enabled = true,              -- enable completion at start\n    autopairs_enabled = true,        -- enable autopairs at start\n    diagnostics_mode = 3,            -- set the visibility of diagnostics in the UI (0=off, 1=only show in status line, 2=virtual text off, 3=all on)\n    icons_enabled = true,            -- disable icons in the UI (disable if no nerd font is available, requires :PackerSync after changing)\n    ui_notifications_enabled = true, -- disable notifications when toggling UI elements\n    VM_leader = \"gm\"                 -- Visual Multi Leader (multiple cursors)\n  },\n}\n
    "},{"location":"configuration/astronvim/config-design/#clojure-lsp","title":"Clojure LSP","text":"

    Clojure LSP support is enabled via the AstroCommunity Clojure pack.

    clojure_lsp can be added using Mason UI, SPC p m or in the plugins/mason.lua file

    Manual user config of clojure lsp server
    -- customize mason plugins\nreturn {\n  -- use mason-lspconfig to configure LSP installations\n  {\n    \"williamboman/mason-lspconfig.nvim\",\n    -- overrides `require(\"mason-lspconfig\").setup(...)`\n    opts = function(_, opts)\n      -- add more things to the ensure_installed table protecting against community packs modifying it\n      opts.ensure_installed = require(\"astronvim.utils\").list_insert_unique(opts.ensure_installed, {\n        -- \"clojure_lsp\",  -- provide by Clojure pack\n        \"marksman\", -- Markdown structure (also in markdown pack)\n        \"yamlls\",\n      })\n    end,\n  },\n}\n
    "},{"location":"configuration/astronvim/config-design/#snippets","title":"Snippets","text":"

    The AstroNvim user example includes a commented LuaSnip configuration

    .config/astronvim-config/plugins/core.lua
      -- {\n  --   \"L3MON4D3/LuaSnip\",\n  --   config = function(plugin, opts)\n  --     require \"plugins.configs.luasnip\" (plugin, opts)  -- include the default astronvim config that calls the setup call\n  --     -- add more custom luasnip configuration such as filetype extend or custom snippets\n  --     local luasnip = require \"luasnip\"\n  --     luasnip.filetype_extend(\"javascript\", { \"javascriptreact\" })\n  --   end,\n  -- },\n

    AstroNvim includes a Recipe for custom snippets

    return {\n  plugins = {\n    {\n      \"L3MON4D3/LuaSnip\",\n      config = function(plugin, opts)\n        require \"plugins.configs.luasnip\"(plugin, opts) -- include the default astronvim config that calls the setup call\n        require(\"luasnip.loaders.from_vscode\").lazy_load { paths = { \"./lua/user/snippets\" } } -- load snippets paths\n      end,\n    },\n  },\n}\n

    Practicalli AstroNvim Config combines the two examples to get

    AstroNvim config with custom VS Code style snippets

    .config/astronvim-config/plugins/core.lua
    {\n  \"L3MON4D3/LuaSnip\",\n  config = function(plugin, opts)\n    require \"plugins.configs.luasnip\" (plugin, opts) -- include the default astronvim config that calls the setup call\n    -- add more custom luasnip configuration such as filetype extend or custom snippets\n    require(\"luasnip.loaders.from_vscode\").lazy_load { paths = { \"./lua/user/snippets\" } } -- load snippets paths\n    local luasnip = require \"luasnip\"\n    luasnip.filetype_extend(\"javascript\", { \"javascriptreact\" })\nend,\n},\n
    "},{"location":"configuration/astronvim/config-design/#astronvim-community-packages","title":"AstroNvim Community packages","text":"

    AstroNvim Community provides a large number of packages currated by the community.

    Visit the AstroNvim Community repository on GitHub and browse the packages available.

    import each package of interest to the plugins/community.lua file in the AstroNvim user configuration.

    AstroNvim Community Packages in AstroNvim user configuration

    .config/astronvim-config/plugins/community.lua
    return {\n  -- Add the community repository of plugin specifications\n  \"AstroNvim/astrocommunity\",\n  -- Import each plugin from the Astro Community as required\n  { import = \"astrocommunity.editing-support.todo-comments\" },\n  { import = \"astrocommunity.git.neogit\" },\n  { import = \"astrocommunity.git.octo\" },\n  { import = \"astrocommunity.git.openingh\" },\n}\n

    AstroCommunity packs set up support for each language

    Language packs enabled in Practicalli AstroNvim Config

    .config/astronvim-config/plugin/community.lua
      -- Packs\n  -- Treesitter: dockerfile , Lsp: dockerls & docker_compose_language_service, Lint/format: hadolint\n  { import = \"astrocommunity.pack.docker\" },\n  -- Treesitter: json & jsonc, Lsp: jsonls, Lint/format: stylua\n  { import = \"astrocommunity.pack.json\" },\n  -- Treesitter: lua, Lsp: lua_ls, Lint/format: stylua\n  { import = \"astrocommunity.pack.lua\" },\n  -- Treesitter: markdown & markdown_inline, Lsp: marksman, Lint/format: prettierd\n  -- Pack disabled as prettierd too agressive with format\n  -- { import = \"astrocommunity.pack.markdown\" },\n  -- Treesitter: markdown & markdown_inline, Lsp: marksman, Lint/format: prettierd\n  { import = \"astrocommunity.pack.yaml\" },\n
    "},{"location":"configuration/astronvim/config-design/#themes","title":"Themes","text":"

    Themes are a collection of one or more colorschemes to affect the apperance of text, icons, highlights, etc.

    Themes supporting vim.opt.background can change between dark and light colorscheme (SPC u b UI > background in AstroNvim)

    SPC f t selector shows themes colorschemes, as long as the themes are configured to disable lazy loading

    The default astrodark theme is set via the colorscheme option in init.lua

    Everforest provides a good dark and light theme and supports the background option to toggle between each colorscheme.

    Practicalli AstroNvim Config - default theme

    colorscheme = \"everforest\",\n

    AstroCommunity themes

    Practicalli AstroNvim Config themes

    return {\n{\n\"AstroNvim/astrotheme\", -- default AstroNvim theme\nlazy = false,\n},\n  -- Add the community repository of plugin specifications\n  \"AstroNvim/astrocommunity\",\n  { import = \"astrocommunity.colorscheme.everforest\" },\n  {\n    \"sainnhe/everforest\",\n    lazy = false,\n  },\n  { import = \"astrocommunity.colorscheme.nightfox-nvim\" },\n  {\n    \"EdenEast/nightfox.nvim\",\n    lazy = false,\n  },\n  { import = \"astrocommunity.colorscheme.kanagawa-nvim\" },\n  {\n    \"rebelot/kanagawa.nvim\",\n    lazy = false,\n  },\n  { import = \"astrocommunity.colorscheme.github-nvim-theme\" }, -- no background support\n  {\n    \"projekt0n/github-nvim-theme\",\n    lazy = false,\n  },\n
    "},{"location":"configuration/astronvim/config-design/#configure-lazy-plugins","title":"Configure Lazy plugins","text":"

    Lazy.nvim Plugin specification

    "},{"location":"configuration/astronvim/config-design/#config-format-and-lint-tools","title":"Config Format and Lint tools","text":"

    Disable format on save when tools provide unexpected results

    SPC u f toggles if the respective format tool should run for the current buffer. SPC u F for all buffers of the current kind.

    init.lua lsp section can enable or disable format on save for specific file types.

    Mason is responsible for installing lint and format tools

    null-ls is responsible for running each tool and provides default configuration for code_actions, completion, diagnostics, formatting and hover.

    null-ls built-in configuration

    Override config file unconsistent

    The configuration file defined by -config-path does not always seem to be used when running astronvim. Quit and start Neovim again seems to use the configuration file.

    Override null-ls builtin configuration

    Specify configuration files to use that override the null-ls builtin configuration

    return {\n  \"jose-elias-alvarez/null-ls.nvim\",\n  opts = function(_, config)\n    -- config variable is the default configuration table for the setup function call\n    local null_ls = require \"null-ls\"\n    config.sources = {\n      null_ls.builtins.formatting.markdownlint.with {\n        -- pass arguments to modify/override the null-ls builtin configuration\n        extra_args = { \n          \"--config-path\", \n          vim.fn.expand(\"~/.config/astro-config/tool-config/markdownlint.yaml\") },\n      },\n    }\n    return config -- return final config table\n  end,\n}\n

    vim.fn.expand() reports luacheck error accessing undefined variable but seems to work regardless

    General configuration for LSP Servers .config/astronvim-config/init.lua
      lsp = {\n    -- customize lsp formatting options\n    formatting = {\n      -- control auto formatting on save\n      format_on_save = {\n        enabled = true,     -- format on save globally\n        allow_filetypes = { -- format on save for specified filetypes only\n          -- \"go\",\n        },\n        ignore_filetypes = { -- turn off format on save for specified filetypes\n          -- \"python\",\n        },\n      },\n      disabled = { -- switch off formatting capabilities for the listed language servers\n        -- turn off lua_ls formatting capability if you want to use StyLua to format your lua code\n        -- \"lua_ls\",\n        \"markdownlint\",\n      },\n      timeout_ms = 1000, -- default format timeout\n      -- filter = function(client) -- fully override the default formatting function\n      --   return true\n      -- end\n    },\n    -- enable servers that you already have installed without mason\n    servers = {\n      -- \"pyright\"\n    },\n  },\n
    "},{"location":"configuration/astronvim/config-design/#override-key-binding","title":"Override Key binding","text":"

    AstroNvim uses Lazy package manager to set keys for packages.

    Astrocommunity configuration defines a keys table that is used by Lazy.

    In the user configuration, return a function that sets key bindings to overide the keys table provided by astrocommunity

    Override Key bindings for vim highlighter .config/astronvim-config/plugins/community.lua
    {\n    \"vim-highlighter\",\n    keys = function() \n        return {\n            { \"<leader>nn\", \"<cmd>Hi><CR>\", desc = \"Next Recently Set Highlight\" },\n            { \"<leader>ng\", \"<cmd>Hi<<CR>\", desc = \"Previous Recently Set Highlight\" },\n            { \"<leader>n[\", \"<cmd>Hi{<CR>\", desc = \"Next Nearest Highlight\" },\n            { \"<leader>n]\", \"<cmd>Hi}<CR>\", desc = \"Previous Nearest Highlight\" },\n        }\n    end,\n}\n
    "},{"location":"configuration/astronvim/config-design/#plugin-key-binding","title":"Plugin Key binding","text":"

    Add key binding if a plugin is available wrapped in an if statement, when defining keys in a different place to adding the plugin, e.g whichkey mappings.lua

    if is_available \"plugin-name\" then\n  ,,,\nelse\n
    "},{"location":"configuration/practicalli/","title":"Neovim Config Redux","text":"

    practicalli/neovim-config-redux

    practicalli/neovim-config-redux is a Fennel based configuraion with a wide range of plugins and telescope extensions.

    Clone practicalli/neovim-config-redux or create a fork if intending to customise that configuration

    Multiple Neovim ConfigsSingle Neovim Configs
    git clone https://github.com/practicalli/neovim-config-redux.git ~/.config/neovim-config-redux\n
    git clone https://github.com/practicalli/neovim-config-redux.git ~/.config/nvim\n
    "},{"location":"configuration/practicalli/#screenshots","title":"Screenshots","text":"

    Dashboard using the startup plugin

    Mnemonic menu with which-key

    Telescope buffer selection

    Neogit Git client with diffview panel

    "},{"location":"configuration/practicalli/config-design/","title":"Config Design","text":"

    The overall design of the Practicalli Neovim Config Redux

    "},{"location":"configuration/practicalli/config-design/#initlua","title":"init.lua","text":"
    • bootstrap the aniseed package which compiles the Fennel configuration into Lua, which is then read by Neovim. Defines the entry point to the Fennel configuration as fnl/config/init.fnl
    • installs packer.nvim for package management
    • examples to disable language providers if programming language support is not required (node, perl, python3, ruby)
    "},{"location":"configuration/practicalli/config-design/#fnlconfiginitfnl","title":"fnl/config/init.fnl","text":"
    • load plugin configuration namespace config.plugin
    • load config.util namespace to streamline key binding definitions
    • set the leader key as space and local-leader as ,
    • define key bindings - uses config.util (mapping to be moved to their own namespace)
    • set global Neovim options
    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginfnl","title":"fnl/config/plugin.fnl","text":"

    Define plugins to add functionality to Neovim.

    use is a private function that searches the plugin configuration map for the keyword :mod and loads the associated namespace (namespace defined with a keyword with the same name)

    e.g. in the telescope plugin configuration :mod has a value of :telescope which will load the file fnl/config/plugin/telescope.fnl

      :nvim-telescope/telescope.nvim\n  {:requires [:nvim-lua/popup.nvim\n              :nvim-lua/plenary.nvim]\n   :mod :telescope}\n

    Packer downloads the nvim-telescope/telescope.nvim plugin and all the plugins in :requires section and search for the namespace telescope in file located in the following path fnl/config/plugin/telescope

    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginconjurefnl","title":"fnl/config/plugin/conjure.fnl","text":"

    The majority of default configuration settings are used for Conjure, with the exception of a few commonly used key bindings from Emacs CIDER & Spacemacs. The Heads Up Display (HUD) is also configured to be less intrusive, relying on mostly on inline results.

    Include the conjure and aniseed namespaces

    (module config.plugin.conjure\n  {autoload {nvim aniseed.nvim}})\n

    Configure keybindings to be closer to Spacemacs

    ;; Set e register for evaluation result\n(set nvim.g.conjure#eval#result_register :e)\n\n;; Evaluate root form (top level form) under the cursor\n;; Default: `\"er\"`\n(set nvim.g.conjure#mapping#eval_root_form \"ef\")\n\n;; Evaluate root form under the cursor & insert result as comment\n;; Default: `\"ecr\"`\n(set nvim.g.conjure#mapping#eval_comment_root_form \"e;\")\n\n;; Evaluate file loaded from disk\n;; Default: `\"ef\"`\n(set nvim.g.conjure#mapping#eval_file \"el\")\n

    Configure the HUD to be less intrusive.

    ;; Width of HUD as percentage of the editor width\n;; A float between 0.0 and 1.0.\n;; Default: `0.42`\n(set nvim.g.conjure#log#hud#width 1)\n\n;; Display HUD\n;; Default: `true`\n(set nvim.g.conjure#log#hud#enabled false)\n\n;; Preferred corner position for the HUD, over-ridden by HUD cursor detection\n;; Example: Set to `\"SE\"` and HUD width to `1.0` for full width HUD at bottom of screen\n;; Default: `\"NE\"`\n(set nvim.g.conjure#log#hud#anchor \"SE\")\n\n;; Open log at bottom or far right of editor, using full width or height\n;; Default: `false`\n(set nvim.g.conjure#log#botright true)\n

    Practicalli encourages header comments at the start of each file to describe the purpose of the namespace, so the Clojure ns lookup is extended

    ;; Number of lines to check for `ns` form, used for setting evaluation context\n;; `b:conjure#context` to override a specific buffer that isn't finding the context\n;; Default: `24`\n(set nvim.g.conjure#extract#context_header_lines 100)\n

    Disable the auto-repl as practicalli prefers manage repl connections themselves

    ;; Start \"auto-repl\" process, eg. babashka\n;; when Conjure unable to find candidate REPL process via to an existing nREPL connection\n;; Default: `true`\n(set nvim.g.conjure#client#clojure#nrepl#connection#auto_repl#enabled false)\n\n;; Hide auto-repl buffer when triggered, to avoid the need to interact with that buffer\n;; Default: `false`\n(set nvim.g.conjure#client#clojure#nrepl#connection#auto_repl#hidden true)\n\n;; Command to start the auto-repl\n;; Default: `\"bb nrepl-server localhost:8794\"`\n(set nvim.g.conjure#client#clojure#nrepl#connection#auto_repl#cmd nil)\n\n;; Print raw evaluation result, suppressing prefix for stdout lines `; (out)`\n;; Default: `false`\n(set nvim.g.conjure#client#clojure#nrepl#eval#raw_out true)\n\n;; Automatically require namespace of new buffer or current buffer after connection\n;; Ensures buffers are loaded, required code to compile and (re)loadable.\n;; Default: `true`\n(set nvim.g.conjure#client#clojure#nrepl#eval#auto_require false)\n

    Use lambdaisland/kaocha as the test runner rather, which has a fail fast feature which can be more effective when adding or changing functionality

    ;; Test runner called from the test key mappings\n;; Default: `\"clojure\"`\n(set nvim.g.conjure#client#clojure#nrepl#test#runner \"kaocha\")\n\n;; Print raw test evaluation result, suppressing prefix for stdout lines `; (out)`\n;; Default: `true`\n(set nvim.g.conjure#client#clojure#nrepl#test#raw_out true)\n
    "},{"location":"configuration/practicalli/config-design/#fnlconfigplugintelescopefnl","title":"fnl/config/plugin/telescope.fnl","text":"

    Settings like ignore node_modules and everything in .gitignore to be listed in the file finder.

    Defines a ripgrep command to set parameters for searching files

    Add --hidden to see all dotfiles (regardless of .gitignore patterns)

    Keymaps:

    • <leader>ff open the find files
    • <leader>fg open the fuzzy finder
    • <leader>fb open the find open buffer
    • <leader>fh open the nvim help fuzzy finder
    "},{"location":"configuration/practicalli/config-design/#fnlconfigplugintreesitterfnl","title":"fnl/config/plugin/treesitter.fnl","text":"

    Defines which language parsers and modules to use.

    • automatically use clojure, fennel and markdown parsers (and compile on first run of Neovim)
    • automatically update language parsers when nvim-treesitter plugin updated
    • enable highlight module
    • enable indent module
    (treesitter.setup\n  {:ensure_installed [\"clojure\" \"fennel\" \"markdown\"]\n   :sync_install true\n   :highlight {:enable true}\n   :indent    {:enable true}})\n
    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginlspconfigfnl","title":"fnl/config/plugin/lspconfig.fnl","text":"

    Language Server Protocol for static analysis of code, to provide common formatting, linting and refactoring tooling across all programming languages.

    Define which symbols to show for lsp diagnostics

    (defn define-signs\n  [prefix]\n  (let [error (.. prefix \"SignError\")\n        warn  (.. prefix \"SignWarn\")\n        info  (.. prefix \"SignInfo\")\n        hint  (.. prefix \"SignHint\")]\n  (vim.fn.sign_define error {:text \"\uf057\" :texthl error})\n  (vim.fn.sign_define warn  {:text \"\uf071\" :texthl warn})\n  (vim.fn.sign_define info  {:text \"\uf05a\" :texthl info})\n  (vim.fn.sign_define hint  {:text \"\uf059\" :texthl hint})))\n
    • features and server settings to enable/customize.
    • Handler defines features and how we want to render the server outputs.
    • Capabilities we link with our autocompletion plugin (nvim-cmp), to say to the lsp servers that we have this feature enabled.
    • On_Attach we customize our interaction with the LSP server, here we define the following keymaps:
    • configure all settings above in clojure-lsp server instance.
    "},{"location":"configuration/practicalli/config-design/#fnlconfigplugincmpfnl","title":"fnl/config/plugin/cmp.fnl","text":"

    Configure sources to show in the autocomple menu (i.e. conjure, lsp, buffer) and key bindings to navigate the autocomplete popup menu.

    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginthemefnl","title":"fnl/config/plugin/theme.fnl","text":"

    Add the Neovim GitHub theme which gives 3 dark and 3 light themes to choose from. Individual colors and styles can be configured to change specific parts of the theme.

    The light theme is used by default, with a custom softer background colour that is slightly red-shifted.

    Options are specified in the theme.setup function, where the option names are keywords and the values are strings, boolean or hash-map of more option keywords and values.

    (theme.setup {:theme_style \"light\"\n              :colors {:bg \"#f8f2e6\"}\n              :comment_style \"italic\"})\n

    The colors (Hex values) for each theme are in the github-nvim-theme/lua/github-theme/palette with the overal theme definition in github-nvim-theme/lua/github-theme/theme.lua

    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginsexpfnl","title":"fnl/config/plugin/sexp.fnl","text":"

    Settings for vim-sexp like enabling it for another lisp languages like Fennel and Jannet

    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginlualinefnl","title":"fnl/config/plugin/lualine.fnl","text":"

    Configure the status line (lualine) that shows at the bottom of Neovim, defining colors and elements that appear on that line.

    The Neovim GitHub theme includes definitions to set the look of the status line.

    "},{"location":"configuration/practicalli/packer/","title":"Package Manager","text":"

    Packer is a use-package inspired package management for Neovim.

    Packer is used as the package manager in this guide as it is built on native Neovim packages and supports Luarocks dependencies, use the :help packages command in Neovim for more details.

    Packer is written in Lua and is installed via the init.lua configuration file, although Practicalli Neovim configuration uses Fennel to configure each package added by Packer.

    "},{"location":"configuration/practicalli/packer/#install","title":"Install","text":"

    init.lua is the entry point to the configuration and is the only part that is written in Lua language.

    The configuration bootstraps the Packer package manager and installs the Aniseed compiler required to process the fennel configuration.

    Aniseed compiles and loads fnl/config/init.fnl and all the required namespaces in that file.

    Packer will process the use form in fnl/config/plugin.fnl and install all the packages defined in that form, along with any package specific configuration defined in that package {:mod :namespace-name} file.

    local execute = vim.api.nvim_command\nlocal fn = vim.fn\n\nlocal pack_path = fn.stdpath(\"data\") .. \"/site/pack\"\nlocal fmt = string.format\n\nfunction ensure (user, repo)\n  -- Ensures a given github.com/USER/REPO is cloned in the pack/packer/start directory.\n  local install_path = fmt(\"%s/packer/start/%s\", pack_path, repo, repo)\n  if fn.empty(fn.glob(install_path)) > 0 then\n    execute(fmt(\"!git clone https://github.com/%s/%s %s\", user, repo, install_path))\n    execute(fmt(\"packadd %s\", repo))\n  end\nend\n\n-- Bootstrap essential plugins required for installing and loading the rest.\nensure(\"wbthomason\", \"packer.nvim\")\nensure(\"Olical\", \"aniseed\")\n\n-- Enable Aniseed's automatic compilation and loading of Fennel source code.\nvim.g[\"aniseed#env\"] = {\n  module = \"config.init\",\n  compile = true\n}\n
    "},{"location":"configuration/practicalli/packer/#packages","title":"Packages","text":"

    Neovim packages add extra functionality to Neovim, e.g. conjure package provides an excellent Clojure REPL experience (and supports several other languages too).

    See the packages section for details of the packages used and a breakdown of their configuration.

    "},{"location":"configuration/practicalli/packages/","title":"Add Neovim Packages","text":"

    Evolving Packages in Practicalli config

    Check the practicalli/neovim-config-reduct configuration. Many packages have been added to the configuration and fnl/config/package.fnl is the most up to date list of packages currently used.

    List of packages and their purpose

    Package Description conjure Clojure REPL Driven Development (and other language REPLs) sexp Structured Editing newpaper theme Clean and simple UI & colour scheme, aimed at readably lualine Fast and configurable statusline nvim-treesitter Parse code highly efficiently, client for LSP servers telescope Completion tool, e.g. select files, buffers tabs, packages, etc nvim-tree Visual file manager - open, create, delete, etc. files & directories neogit Magit style visual Git client Octo Git Issues and Pull Requests gitsigns Show diff changes in buffer gutter and status line

    Any specific package configuration & key bindings (on sub page if significant content)

    "},{"location":"configuration/practicalli/packages/#package-selection-criteria","title":"Package selection criteria","text":"

    Packages are more likely to be adopted if:

    • provide valuable (or fun) features
    • work reliably, without generating errors
    • do not conflict with other valuable packages in this configuration
    • written in fennel or lua to aid maintenance
    • provides a setup or config function for setting package options
    • use features provided by Neovim (e.g treesitter)
    • are well documented
    • are easy to configure
    • are easy to use
    • work well with themes (where relevant)
    "},{"location":"configuration/practicalli/packages/#package-updates","title":"Package Updates","text":"

    This Week In Neovim - community update

    "},{"location":"configuration/practicalli/packages/lualine/","title":"Lualine - modeline theme","text":"

    nvim-lualine/lualine.nvim is a fast and configurable statusline for neovim

    Example status line: evil_lualine

    "},{"location":"configuration/practicalli/packages/lualine/#lualine-configuration-in-fennel","title":"Lualine configuration in Fennel","text":"

    nvim/fnl/config/plugin/lualine.fnl

    (module config.plugin.lualine\n  {autoload {core aniseed.core\n             lualine lualine\n             lsp config.plugin.lspconfig}})\n\n(defn lsp_connection []\n  (if (vim.tbl_isempty (vim.lsp.buf_get_clients 0)) \"\uf096\" \"\uf0c8\"))\n\n(def github-lua-theme\n  (core.assoc\n    (require :lualine.themes.auto)\n    :inactive {:a {:bg \"#19181e\" :fg \"#a4a3a6\"}\n               :b {:bg \"#19181e\" :fg \"#a4a3a6\"}\n               :c {:bg \"#19181e\" :fg \"#a4a3a6\"}}\n    :normal {:a {:bg \"#131217\" :fg \"#24292e\"}\n             :b {:bg \"#131217\" :fg \"#3b8eea\"}\n             :c {:bg \"#19181e\" :fg \"#d1d5da\"}}\n    :command {:a {:bg \"#131217\" :fg \"#24292e\"}\n              :b {:bg \"#131217\" :fg \"#ccbed8\"}\n              :c {:bg \"#19181e\" :fg \"#d1d5da\"}}\n    :visual {:a {:bg \"#131217\" :fg \"#24292e\"}\n             :b {:bg \"#131217\" :fg \"#ced4b1\"}\n             :c {:bg \"#19181e\" :fg \"#d1d5da\"}}\n    :replace {:a {:bg \"#131217\" :fg \"#24292e\"}\n              :b {:bg \"#131217\" :fg \"#d1b6bd\"}\n              :c {:bg \"#19181e\" :fg \"#d1d5da\"}}\n    :insert {:a {:bg \"#131217\" :fg \"#24292e\"}\n             :b {:bg \"#131217\" :fg \"#a8d1c9\"}\n             :c {:bg \"#19181e\" :fg \"#d1d5da\"}}))\n\n(lualine.setup\n  {:options {:theme github-lua-theme\n             :icons_enabled true\n             :section_separators [\"\" \"\"]\n             :component_separators [\"\uf44a\" \"\uf438\"]}\n   :sections {:lualine_a []\n              :lualine_b [[:mode {:upper true}]]\n              :lualine_c [[\"FugitiveHead\"]\n                          [:filename {:filestatus true\n                                      :path 1}]]\n              :lualine_x [[:diagnostics {:sections [:error\n                                                    :warn\n                                                    :info\n                                                    :hint]\n                                         :sources [:nvim_lsp]}]\n                          [lsp_connection]\n                          :location\n                          :filetype]\n              :lualine_y [:encoding]\n              :lualine_z []}\n   :inactive_sections {:lualine_a []\n                       :lualine_b []\n                       :lualine_c [[:filename {:filestatus true\n                                               :path 1}]]\n                       :lualine_x []\n                       :lualine_y []\n                       :lualine_z []}})\n
    "},{"location":"configuration/practicalli/packages/nvim-treesitter/","title":"Nvim Treesitter","text":"

    Treesitter provides language specific parsing, highlight and indent features and so is a fundamental plugin to use with Neovim.

    clojure, fennel, markdown and org parsers are automatically installed in the practicalli/neovim-config-redux configuration.

    • :TSInstallInfo lists language parsers and install status
    • :TSUpdate {language} to update a parser to the latest compatible version (specified in nvim-treesitter lockfile.json).
    • :TSInstall {language} compiles and installs a parser for the given language.
    • :TSUpdateSync to update all parsers to the latest available versions
    "},{"location":"configuration/practicalli/packages/nvim-treesitter/#nvim-treesitter-configuration","title":"nvim-treesitter configuration","text":"

    clojure, fennel, markdown and org parsers are automatically installed if not already available.

    :sync_install true automatically updates the parsers when the nvim-treesitter plugin is updated. Treesitter and its parsers are actively developed, so its important to ensure parsers are kept up to date. This is the equivalent of manually running :TSUpdateSync.

    Parser highlight and indent modules are enabled by default

    In fnl/config/plugin/treesitter.fnl

    (module config.plugin.treesitter\n  {autoload {treesitter nvim-treesitter.configs}})\n\n(treesitter.setup\n  {:ensure_installed [\"clojure\" \"fennel\" \"markdown\" \"org\"]\n   :sync_install true\n   :highlight {:enable true}\n   :indent    {:enable true}})\n
    "},{"location":"configuration/practicalli/packages/nvim-treesitter/#manually-install-parsers","title":"Manually Install Parsers","text":"

    nvim-treesitter provides the TSInstall command to generate a parser for a specific language, assuming that language is supported.

    A compiler (gcc, clang, etc) should be installed in the operating system on which nvim is running

    :TSInstall {language}\n

    TAB completion lists the available language parsers, TAB and S-TAB to navigate the auto-completion popup.

    "},{"location":"install/","title":"Install Overview","text":"

    Practicalli Neovim provides a feature rich configuration for Neovim and all the tools required for effective Clojure development (and other Lisp dialects too).

    • Clojure tooling and a Java SDK (Java Virtual Machine)
    • Neovim 0.9.x or nightly build
    • Neovim package manager and packages
    • NerdFonts for icon support in themes and status line

    Neovim 0.9.x latest stable release

    Content and configuration in this book has been tested against Neovim 0.9.x over the summer of 2023

    "},{"location":"install/#install-summary","title":"Install summary","text":"

    If you are familiar with most of the tools required, then the quick start list below provides an ultra-terse version on how to get started with Neovim and Clojure development.

    • Install Neovim 0.9.x or greater
      • Linux AppImage
      • brew install --HEAD neovim for Homebrew install of development version
    • Install supporting tools
      • tar & curl and a C compiler, e.g. gcc for Linux or clang for android/termix (required by nvim-treesitter)
      • ripgrep & fd to search for files (used by telescope)
      • luarocks for LSP support in AstroNvim
    • Clone Neovim Config
    • Run nvim in a terminal and ignore warnings, press RTN
      • SPC P i or :PackerInstall command in Neovim to install packages
    • Install Clojure CLI and supporting tools
    • Clone / fork practicalli/clojure-deps-edn or add an alias with the required config to use nrepl and cider-nrepl
    • Run a Clojure REPL process - in a terminal session with nREPL, e.g. using one of the REPL aliases from practicalli/clojure-deps-edn
      • clojure -M:repl/rebel for a rich REPL UI with auto-completion & docs
      • clojure -M:repl/headless - headless REPL process when working exclusively in a Clojure connected editor
    • Open a Clojure file in Neovim - Conjure will automatically connect
    "},{"location":"install/#next-steps","title":"Next Steps","text":"

    Learn how to use Neovim and how to use Conjure for REPL driven development

    "},{"location":"install/clojure/","title":"Install Clojure","text":"

    A rich Clojure REPL workflow is provided by the Conjure package, which works with Clojure CLI and Leiningen projects, assuming the respective tool is installed.

    Clojure LSP is highly recommended and packages to use an installed clojure-lsp tool are in the practicalli/neovim-config-redux configuration

    "},{"location":"install/clojure/#clojure-cli","title":"Clojure CLI","text":"

    Practicalli Clojure install guide

    Clojure CLI provides a way to run Clojure code, packaged Clojure (jar) and run a Clojure REPL.

    Practicalli Clojure install guide details prerequisites, Clojure install options and supporting tools for an enhanced developer workflow.

    Visit the Clojure Getting Started guide for the Clojure CLI or to check the latest release version.

    Practicalli Clojure CLI Config provides a wide range of community tools that extend the features of Clojure CLI, creating a rich development environment for use across all projects.

    Aliases are required for many examples

    Without Practicalli Clojure CLI Config many commands provided in this book are not available unless similar alias definitions are added to a either a project or user level deps.edn configuration.

    "},{"location":"install/clojure/#language-server-protocol","title":"Language Server Protocol","text":"

    Neovim Treesitter surfaces information from Language Server Protocol (LSP) servers to assist with development and refactor of Clojure code.

    Clojure LSP installation guide shows how to install the Clojure LSP binary for the relevant operating system.

    Once installed, run clojure-lsp -v in a terminal to ensure the command is working.

    practicalli/clojure-lsp-config

    practicalli/clojure-lsp-config provides a complete configuration for clojure-lsp (config.edn), including a wide range of snippets and less restrictive formatting rules (cljfmt.edn)

    clj-kondo provides static analysis of source code files, providing subtle warnings as Clojure code is written to help the developer follow idioms and avoid syntatic errors.

    Clojure LSP includes clj-kondo to provide an implementation of the Language Server Protocol for the Clojure Language.

    Clojure LSP installation guide Treesitter Fennel Configuration

    "},{"location":"install/clojure/#leiningen","title":"Leiningen","text":"

    Many existing Clojure projects use Leiningen build automation tool (although many new projects use Clojure CLI as well or instead of Leiningen).

    The code is the same regardless of tooling choice. The overall workflow is the same, although Clojure CLI may provide more workflow options.

    Follow the install instructions at Leiningen.org if required.

    "},{"location":"install/neovim/","title":"Install Neovim","text":"

    Neovim releases

    Neovim 8 is the minimum version for this configuration and Neovim 0.9.0 is currently being tested.

    Follow the install Neovim guide for the specific operating system.

    "},{"location":"install/neovim/#suppoting-tools","title":"Suppoting Tools","text":"

    Neovim uses several external tools for searching for files, search file contents and using the operating system clipbaord.

    AstroNvim requires node.js

    AstroNvim uses Mason to install LSP servers, format and lint tools. Many LSP servers require node.js to install and function.

    Node.js install - Practicalli Engineering Playbook

    Debian / Ubuntu

    Install the following packages to support Neovim

    • ripgrep fast file contents search (used by telescope)
    • find-fd advanced search tool
    • xclip clipboard as a provider tools for Neovim copy/paste
    • luarocks for LSP servers (AstroNvim)
    sudo apt install find-fd xclip luarocks\n

    Add set clipboard+=unnamedplus to the Neovim configuration to use the Linux clipboard tool

    Wayland requires wl-clipboard

    Install the wl-clipboard package to use the Wayland desktop clipboard with Neovim

    sudo apt install wl-clipboard\n

    "},{"location":"install/neovim/#install-neovim_1","title":"Install Neovim","text":"Linux AppImageUbuntu/DebianBuild from Source

    Download the AppImage from the Neovim Release page and place the file on the executable path, e.g. $HOME/.local/bin

    Make the AppImage executable

    chmod u+x nvim.appimage\n

    Run neovim from the AppImage

    nvim.appimage\n

    Create a symbolic link called nvim to the nvim.appimage

    ln -s $HOME/.local/bin/nvim.appimage $HOME/.local/bin/nvim\n

    Download the Linux AppImage from the Neovim Releases page

    Or build Neovim from source and generate a .deb file from the build.

    Linux version only packaged as AppImage from Neovim 0.9 onward

    Neovim Build Prerequisites for each operating system

    Ubuntu/Debian Packages

    Install packages to support building Neovim

    sudo apt-get install ninja-build gettext cmake unzip curl\n

    Clone the Neovim GitHub repository

    git clone --origin neovim https://github.com/neovim/neovim.git\n
    Change into the cloned directory and change to the stable release to build version 0.9.0

    git checkout stable\n

    Build a release

    make CMAKE_BUILD_TYPE=Release                                                                                                              \u2500\u256f\n

    Once the nvim release has been built, create a debian package for use with Ubuntu and Debian systems

    cpack -G DEB\n
    "},{"location":"install/neovim/#post-install-checks","title":"Post Install checks","text":"

    Ensure supporting tools and binaries are available in the operating system by running the Neovim Heath Check.

    nvim in a terminal to run NeoVim and check the installation is working without error.

    :checkhealth to run a check supporting tools are available to NeoVim.

    A report is generated and shown in NeoVim

    j / k to scroll through the checkhealth report

    Review the warnings and install tooling that is required for languages that will be used.

    Ignore Provider Warnings

    It is safe to ignore language provider warnings.

    Language Providers can be disabled in the Neovim configuration to remove the warnings from :checkhealth report. Examples of disabling language provders are in the practicalli/neovim-config-redux configuration, covered in the Neovim Config install step

    "},{"location":"introduction/community-projects/","title":"Community Configuration Projects","text":"

    Practicalli Neovim book covers the following configurations:

    "},{"location":"introduction/community-projects/#practicalli-neovim-config-redux","title":"Practicalli Neovim Config Redux","text":"

    Practicalli Neovim Config Redux

    • Fennel configuration
    • Packer package manager & Treesitter support
    • Mnemonic key bindings
    • Telescope selectors
    • Autocompletion (cmp) & snippets (luasnip)
    • Esc with center row keys, e.g. \"fd\"
    "},{"location":"introduction/community-projects/#astronvim-and-practicalli-astronvim-config","title":"AstroNvim and Practicalli AstroNvim Config","text":"

    AstroNvim and Practicalli AstroNvim Config organised configuration with a polished UI

    • Neovim 9 support
    • Lazy for plugins (packages for Neovim)
    • Mason to manage install for LSP, DAP, lint and format tools
    • Treesitter and language parser support
    • Telescope selectors
    • Notification dialogs
    • Autocompletion (cmp) & snippets (luasnip)
    • Neovim 9 background switch (live toggle light & dark theme)
    • Hidden command line cmdheight=0 (Neovim 0.8 onward)
    • Esc with center row keys, e.g. \"fd\" (user: plugins/core.lua)
    "},{"location":"introduction/community-projects/#alternative-configurations","title":"Alternative configurations","text":"

    Practicalli Neovim does not cover the following Community configurations.

    • Magit Kit fennel configuration from the author of Conjure
    • cajus-nvim inspiration for practicalli/neovim-config-redux
    • LazyVim lazy & mason configuration
    • NvChad polished UI with Lazy optomisations

    Long term project: Fennel config with AstroNvim-like UI experience

    A very long term goal for Practicalli is to create a Neovim configuration written predominatly in Fennel, providing a rich user experience on par with the very polished experience of AstroNvim.

    Lazy and Mason should be used to manage packages and tools (LSP & DAP servers, lint & format tools).

    Which-key should provide a mnemonic menu system similar to the Spacemacs experience.

    "},{"location":"introduction/contributing/","title":"Contributing to Practicalli","text":"

    Practicalli books are written in markdown and use MkDocs to generate the published website via a GitHub workflow. MkDocs can also run a local server using the make docs target from the Makefile

    By submitting content ideas and corrections you are agreeing they can be used in this book under the Creative Commons Attribution ShareAlike 4.0 International license. Attribution will be detailed via GitHub contributors.

    All content and interaction with any persons or systems must be done so with respect and within the Practicalli Code of Conduct.

    "},{"location":"introduction/contributing/#book-status","title":"Book status","text":""},{"location":"introduction/contributing/#submit-and-issue-or-idea","title":"Submit and issue or idea","text":"

    If something doesnt seem quite right or something is missing from the book, please raise an issue via the GitHub repository explaining in as much detail as you can.

    Raising an issue before creating a pull request will save you and the maintainer time.

    "},{"location":"introduction/contributing/#considering-a-pull-request","title":"Considering a Pull request?","text":"

    Before investing any time in a pull request, please raise an issue explaining the situation. This can save you and the maintainer time and avoid rejected pull requests.

    Please keep pull requests small and focused, as they are much quicker to review and easier to accept. Ideally PR's should be for a specific page or at most a section.

    A PR with a list of changes across different sections will not be merged, it will be reviewed eventually though.

    "},{"location":"introduction/contributing/#thank-you-to-everyone-that-has-contributed","title":"Thank you to everyone that has contributed","text":"

    A huge thank you to Rich Hickey and the team at Cognitect for creating and continually guiding the Clojure language. Special thank you to Alex Miller who has provided excellent advice on working with Clojure and the CLI tooling.

    The Clojure community has been highly supportive of everyone using Clojure and I'd like to thank everyone for the feedback and contributions. I would also like to thank everyone that has joined in with the London Clojurins community, ClojureBridgeLondon, Clojurians Slack community, Clojurians Zulip community and Clojureverse community.

    Thank you to everyone who sponsors the Practicalli websites and videos and for the Clojurists Together sponsorship, it helps me continue the work at a much faster pace.

    Special thanks to Bruce Durling for getting me into Cloure in the first place.

    "},{"location":"introduction/features/","title":"Neovim features","text":"

    A clean UI provides for a distraction free development experience, with only the essential information presented in the Neovim statusline or inline with the code

    • Conjure - automatic Clojure REPL connection, evaluation, test runners
    • Treesitter
    • Plug-in Manager (e.g. Lazy.nvim)
    • LSP - auto-completion, snippets, inline linting, reference navigation, refactor and unit test coverage
    • statusline - LSP status, diff changes, filetype, cursor position
    • Selection narrowing completion of files, packages, colour schemes, etc
    • File browser - telescope selection narrowing and visual file system navigation
    • Version Control gutter indicators for changed lines
    • todo comments todo, fix, notes, indicators with gutter icons
    • relative line numbers for vim-style navigation
    "},{"location":"introduction/features/#conjure","title":"Conjure","text":"

    Conjure An interactive environment for evaluating code, e.g. a Clojure REPL. Conjure automatically connects to an nREPL process running in the current project.

    Evaluate Clojure code as its developed for an instant feedback workflow.

    Run unit tests with Kaocha test runner (Cognitect Labs and ClojureScript runners also available)

    Fireplace has been a long-standing plugin for Vim to support Clojure REPL connection.

    "},{"location":"introduction/features/#lazy-plugin-manager","title":"Lazy Plugin manager","text":"

    Lazy.nvim manages neovim plugins with a rich UI that provides an enjoyable user experience. Plugins are automatically installed during startup and lists the status of each plugins.

    Plugins are automatic cached & bytecode compiled and can be lazy loaded to streamline startup time and resource usage based on events, commands, filetypes, and key mappings. Efficient plugin downlaods using partial blobless clones of plugin repositories, i.e. --filter=blob:none

    Lazy.nvim

    "},{"location":"introduction/features/#treesitter","title":"Treesitter","text":"

    Neovim provides highly effective syntax highlighting of source code due to Treesitter.

    Tree-sitter parses files opened in Neovim and builds a concrete syntax tree that any Neovim plugin can use to efficiently provide feedback. Treesitter uses incremental parsing to efficiently update the syntax tree as a file is edited.

    • parse on every keystroke in a text editor
    • provide useful results even in the presence of syntax errors

    Treesitter

    "},{"location":"introduction/features/#language-server-protocol","title":"Language Server Protocol","text":"

    Neovim includes an LSP client which uses the information recieved from a language specific LSP server in real-time to provide a range of services:

    • auto-completion of function and symbol names
    • live linting as code is typed or opened from a file
    • formatting
    • function signatures and help documentation
    • diagnostics (syntax errors & idioms)
    • symantic analysis providing rename through project, go-to-definition & find-references

    LSP feedback is often presented in the buffer, file browser and status line of Neovim.

    LSP Server implementation is not universal

    LSP is a relatively new specification and many server implmentations are still evolving or are yet to be created.

    Lint tools tend to be more prevelent and may be required in concert with or in the absence of an LSP server.

    LSP related Plugins
    • neovim/nvim-lspconfig - connect Neovim lsp client to lsp servers
    • jose-elias-alvarez/null-ls.nvim - hook format and lint tools into the Neovim LSP client
    • jayp0521/mason-null-ls.nvim - automatically install formatters/linters to be used by null-ls
    • williamboman/mason - install and manage LSP servers, DAP servers, linters, and formatters
    • williamboman/mason-lspconfig - register LSP configs with neovim so LSP client can connect to servers
    "},{"location":"introduction/features/#lint-and-format-tools","title":"Lint and format tools:","text":"

    Linters check code for common problems and provide hints on how to correct any detected issues.

    Format tools suppor code to conforming to a specified coding style, typically these run when save-file is run.

    null-ls provides extensive builtin configuration for programming languages and configuration formats. null-ls also passes lint and format tool information to the Neovim LSP client, extending the range of language support.

    "},{"location":"introduction/features/#selection-narrowing","title":"Selection Narrowing","text":"

    telescope.nvim is a highly extendable fuzzy finder over lists with community driven pickers, sorters and previewers.

    Navigate and narrow lists of files, packages, environment variables, ports, colour schemes (themes) and any other list of items effectively.

    Telescope File browser popup also explores the file system and in Normal mode can be used to create files and directories

    The telescope list narrows matches as characters are typed

    "},{"location":"introduction/features/#version-control","title":"Version Control","text":"

    Gitsigns hightlights buffer changes in the gutter

    Lualine shows number of Git changes in status line

    Diffview to review all changes for any git revision

    Neogit provides a rich git client to add, stash, commit, push & pull changes.

    Octo provides a GitHub specific client to manage issues and pull requests, using GitHub CLI authentication.

    LazyGit UI

    "},{"location":"introduction/features/#file-browser","title":"File Browser","text":"

    neo-tree provides a visual file system explorer that can also create and delete files and directories

    "},{"location":"introduction/features/#todo-comments","title":"TODO Comments","text":"

    Highlight tasks, fixes, notes and dragons comments, including icons in the gutter. Use Telescope to navigate TODO comments in the current project.

    "},{"location":"introduction/features/#status-line","title":"Status Line","text":"

    LSP feedback

    "},{"location":"introduction/features/#markdown","title":"Markdown","text":"
    • LSP server
    • Marksman: select anchors and pages for links
    "},{"location":"introduction/fennel/","title":"Fennel","text":"

    Lua is the defacto language for Neovim plugin development and configuration.

    Fennel can be used to write Neovim packages and configuration, using nfnl to generate the equivalent Lua code that Neovim runs.

    Although Neovim fully supports Vimscript, Practicalli encourages Fennel or Lua, as Vimscript is a niche language with quite complex syntax.

    "},{"location":"introduction/fennel/#overview","title":"Overview","text":"

    Fennel is a programming language that brings together the speed, simplicity, and reach of Lua with the flexibility of a lisp syntax and macro system.

    • Full Lua compatibility: Easily call any Lua function or library from Fennel and vice-versa.
    • Zero overhead: Compiled code should be just as efficient as hand-written Lua.
    • Compile-time macros: Ship compiled code with no runtime dependency on Fennel.
    • Embeddable: Fennel is a one-file library as well as an executable. Embed it in other programs to support runtime extensibility and interactive development.

    Anywhere you can run Lua code, you can run Fennel code.

    Translate Lua to Fennel

    See Fennel is an online antifennel tool to convert Lua to Fennel or Fennel to Lua.

    practicalli/neovim-config-redux configuration provides helper functions to minimise the translation required.

    "},{"location":"introduction/fennel/#fennel-packages","title":"Fennel Packages","text":"

    The Conjure package which provides the Clojure REPL (and much more) is written in Fennel.

    "},{"location":"introduction/fennel/#nfnl","title":"nfnl","text":"

    nfnl generates Lua code from Fennel code. Neovim runs the generated Lua code.

    nfnl loads only when working in directories containing a .nfnl.fnl configuration file, so has zero overhead when not working with fennel.

    *.fnl files are automatically compiled to *.lua when changes are saved, showing any compilation errors to provide an effective feedback loop.

    nfnl standard library

    nfnl plugin example

    "},{"location":"introduction/fennel/#development-tooling","title":"Development tooling","text":"

    Neovim support

    • Anti-fennel - convert from Lua code to Fennel code.
    • nfnl - write plugins or configuration for Neovim with great runtime performance
    • hotpot - seamless Fennel inside Neovim

    See Fennel is an online antifennel tool to convert between Lua and Fennel.

    Guide to plugin development with fennel

    Emacs support:

    • technomancy/fennel-mode and Emacs mirror repository
    "},{"location":"introduction/fennel/#playing-games","title":"Playing Games","text":"

    TIC-80 is a simulated computer environment to to write code, design art, compose music and retro style game games.

    L\u00d6VE is a framework for making games with the Lua programming language, allows import from external resources and can use any resolution or memory resources required.

    TIC-80 and L\u00d6VE provide cross-platform support across Windows, Mac and Linux systems. TIC-80 games can also be played in the browser.

    "},{"location":"introduction/repl-workflow/","title":"REPL Driven Development","text":"

    Always be REPL'ing

    Coding without a REPL feels limiting. The REPL provides fast feedback from code as its crafted, testing assumptions and design choices every step of the journey to a solution - John Stevenson, Practical.li

    Clojure is a powerful, fun and highly productive language for developing applications and services. The clear language design is supported by a powerful development environment known as the REPL (read, evaluate, print, loop). The REPL gives you instant feedback on what your code does and enables you to test either a single expression or run the whole application (including tests).

    REPL driven development is the foundation of working with Clojure effectively

    An effective Clojure workflow begins by running a REPL process. Clojure expressions are written and evaluated immediately to provide instant feedback. The REPL feedback helps test the assumptions that are driving the design choices.

    • Read - code is read by the Clojure reader, passing any macros to the macro reader which converts those macros into Clojure code.
    • Evaluate - code is compiled into the host language (e.g. Java bytecode) and executed
    • Print - results of the code are displayed, either in the REPL or as part of the application.
    • Loop - the REPL is a continuous process that evaluates code, either a single expression or the whole application.

    Design decisions and valuable data from REPL experiments can be codified as specifications and unit tests

    Practicalli REPL Reloaded Workflow

    The principles of REPL driven development are implemented in practice using the Practicalli REPL Reloaded Workflow and supporting tooling. This workflow uses Portal to inspect all evaluation results and log events, hot-load libraries into the running REPL process and reloads namespaces to support major refactor changes.

    "},{"location":"introduction/repl-workflow/#evaluating-source-code","title":"Evaluating source code","text":"

    A REPL connected editor is the primary tool for evaluating Clojure code from source code files, displaying the results inline.

    Source code is automatically evaluated in its respective namespace, removing the need to change namespaces in the REPL with (in-ns) or use fully qualified names to call functions.

    Evaluate Clojure in Neovim with Conjure

    , e b evaluates the code in the current buffer

    Evaluate Clojure in a Terminal UI REPL

    Entering expressions at the REPL prompt evaluates the expression immediately, returning the result directly underneath

    "},{"location":"introduction/repl-workflow/#rich-comment-blocks-living-documentation","title":"Rich Comment blocks - living documentation","text":"

    The (comment ,,,) function wraps code that is only run directly by the developer using a Clojure aware editor.

    Expressions in rich comment blocks can represent how to use the functions that make up the namespace API. For example, starting/restarting the system, updating the database, etc. Expressions provide examples of calling functions with typical arguments and make a project more accessible and easier to work with.

    Clojure Rich Comment to manage a service

    (ns practicalli.gameboard.service)\n\n(defn app-server-start [port] ,,,)\n(defn app-server-start [] ,,,)\n(defn app-server-restart [] ,,,)\n\n(defn -main\n  \"Start the service using system components\"\n  [& options] ,,,)\n\n(comment\n  (-main)\n  (app-server-start 8888)\n  (app-server-stop)\n  (app-server-restart 8888)\n\n  (System/getenv \"PORT\")\n  (def environment (System/getenv))\n  (def system-properties (System/getProperties))\n  ) ; End of rich comment block\n

    Rich comment blocks are very useful for rapidly iterating over different design decisions by including the same function but with different implementations. Hide clj-kondo linter warnings for redefined vars (def, defn) when using this approach.

    ;; Rich comment block with redefined vars ignored\n#_{:clj-kondo/ignore [:redefined-var]}\n(comment\n  (defn value-added-tax []\n    ;; algorithm design - first idea)\n\n  (defn value-added-tax []\n    ;; algorithm design - second idea)\n\n  ) ;; End of rich comment block\n

    The \"Rich\" in the name is an honourary mention to Rich Hickey, the author and benevolent dictator of Clojure design.

    "},{"location":"introduction/repl-workflow/#design-journal","title":"Design Journal","text":"

    A journal of design decisions makes the code easier to understand and maintain. Code examples of design decisions and alternative design discussions are captured, reducing the time spent revisiting those discussions.

    Journals simplify the developer on-boarding processes as the journey through design decisions are already documented.

    A Design Journal is usually created in a separate namespace, although it may start as a rich comment at the bottom of a namespace.

    A journal should cover the following aspects

    • Relevant expressions use to test assumptions about design options.
    • Examples of design choices not taken and discussions why (saves repeating the same design discussions)
    • Expressions that can be evaluated to explain how a function or parts of a function work

    The design journal can be used to create meaningful documentation for the project very easily and should prevent time spent on repeating the same conversations.

    Example design journal

    Design journal for TicTacToe game using Reagent, ClojureScript and Scalable Vector Graphics

    "},{"location":"introduction/repl-workflow/#viewing-data-structures","title":"Viewing data structures","text":"

    Pretty print shows the structure of results from function calls in a human-friendly form, making it easier for a developer to parse and more likely to notice incorrect results.

    Tools to view and navigate code

    • Cider inspector is an effective way to navigate nested data and page through large data sets.
    • Portal Inspector to visualise many kinds of data in many different forms.

    "},{"location":"introduction/repl-workflow/#code-style-and-idiomatic-clojure","title":"Code Style and idiomatic Clojure","text":"

    Clojure aware editors should automatically apply formatting that follows the Clojure Style guide.

    Live linting with clj-kondo suggests common idioms and highlights a wide range of syntax errors as code is written, minimizing bugs and therefore speeding up the development process.

    Clojure LSP is build on top of clj-kondo

    Clojure LSP uses clj-kondo static analysis to provide a standard set of development tools (format, refactor, auto-complete, syntax highlighting, syntax & idiom warnings, code navigation, etc).

    Clojure LSP can be used with any Clojure aware editor that provides an LSP client, e.g. Spacemacs, Doom Emacs, Neovim, VSCode.

    Clojure Style Guide

    The Clojure Style guide provides examples of common formatting approaches, although the development team should decide which of these to adopt. Emacs clojure-mode will automatically format code and so will Clojure LSP (via cljfmt). These tools are configurable and should be tailored to the teams standard.

    "},{"location":"introduction/repl-workflow/#data-and-function-specifications","title":"Data and Function specifications","text":"

    Clojure spec is used to define a contract on incoming and outgoing data, to ensure it is of the correct form.

    As data structures are identified in REPL experiments, create data specification to validate the keys and value types of that data.

    ;; ---------------------------------------------------\n;; Address specifications\n(spec/def ::house-number string?)\n(spec/def ::street string?)\n(spec/def ::postal-code string?)\n(spec/def ::city string?)\n(spec/def ::country string?)\n(spec/def ::additional string?)\n\n(spec/def ::address   ; Composite data specification\n  (spec/keys\n   :req-un [::street ::postal-code ::city ::country]\n   :opt-un [::house-number ::additional]))\n;; ---------------------------------------------------\n

    As the public API is designed, specifications for each functions arguments are added to validate the correct data is used when calling those functions.

    Generative testing provides a far greater scope of test values used incorporated into unit tests. Data uses clojure.spec to randomly generate data for testing on each test run.

    "},{"location":"introduction/repl-workflow/#test-driven-development-and-repl-driven-development","title":"Test Driven Development and REPL Driven Development","text":"

    Test Driven Development (TDD) and REPL Driven Development (RDD) complement each other as they both encourage incremental changes and continuous feedback.

    Test Driven Development fits well with Hammock Time, as good design comes from deep thought

    • RDD enables rapid design experiments so different approaches can easily and quickly be evaluated .
    • TDD focuses the results of the REPL experiments into design decisions, codified as unit tests. These tests guide the correctness of specific implementations and provide critical feedback when changes break that design.

    Unit tests should support the public API of each namespace in a project to help prevent regressions in the code. Its far more efficient in terms of thinking time to define unit tests as the design starts to stabilize than as an after thought.

    clojure.test library is part of the Clojure standard library that provides a simple way to start writing unit tests.

    Clojure spec can also be used for generative testing, providing far greater scope in values used when running unit tests. Specifications can be defined for values and functions.

    Clojure has a number of test runners available. Kaocha is a test runner that will run unit tests and function specification checks.

    Automate local test runner

    Use kaocha test runner in watch mode to run tests and specification check automatically (when changes are saved)

    clojure -X:test/watch\n

    "},{"location":"introduction/repl-workflow/#continuous-integration-and-deployment","title":"Continuous Integration and Deployment","text":"

    Add a continuous integration service to run tests and builds code on every shared commit. Spin up testable review deployments when commits pushed to a pull request branch, before pushing commits to the main deployment branch, creating an effective pipeline to gain further feedback.

    • CircleCI provides a simple to use service that supports Clojure projects.
    • GitHub Workflows and GitHub actions marketplace to quickly build a tailored continuous integration service, e.g. Setup Clojure GitHub Action.
    • GitLab CI

    "},{"location":"introduction/repl-workflow/#live-coding-with-data-stuart-halloway","title":"Live Coding with Data - Stuart Halloway","text":"

    There are few novel features of programming languages, but each combination has different properties. The combination of dynamic, hosted, functional and extended Lisp in Clojure gives developers the tools for making effective programs. The ways in which Clojure's unique combination of features can yield a highly effective development process.

    Over more than a decade we have developed an effective approach to writing code in Clojure whose power comes from composing many of its key features. As different as Clojure programs are from e.g. Java programs, so to can and should be the development experience. You are not in Kansas anymore!

    This talk presents a demonstration of the leverage you can get when writing programs in Clojure, with examples, based on my experiences as a core developer of Clojure and Datomic.

    "},{"location":"introduction/writing-tips/","title":"Writing tips for MkDocs","text":"

    Making the docs more engaging using the mkdocs-material theme reference guide

    Configuring Colors

    Material for MkDocs - Changing the colors lists the primary and accent colors available.

    HSL Color Picker for codes to modify the theme style, overriding colors in docs/assets/stylesheets/extra.css

    "},{"location":"introduction/writing-tips/#hypertext-links","title":"Hypertext links","text":"

    Links open in the same browser window/tab by default.

    Add {target=_blank} to the end of a link to configure opening in a new tab

    [link text](url){target=_blank}\n
    "},{"location":"introduction/writing-tips/#buttons","title":"Buttons","text":"

    Convert any link into a button by adding {.md-button} class names to end of the markdown for a link, which uses .md-button-primary by default. Include target=_blank for buttons with links to external sites.

    [link text](http://practical.li/blog){.md-button target=_blank}\n

    Or specify a different class

    [link text](http://practical.li/blog){.md-button .md-button-primary}\n

    Add an icon to the button

    Practicalli Issues Practicalli Blog

    [:fontawesome-brands-github: Practicalli Issues](http://practical.li/blog){ .md-button .md-button-primary }\n[:octicons-heart-fill-24: Practicalli Blog](http://practical.li/blog){ .md-button .md-button-primary }\n

    Search all supported icons

    "},{"location":"introduction/writing-tips/#youtube-video","title":"YouTube video","text":"

    Use an iframe element to include a YouTube video, wrapping in a paragraph tag with center alignment to place the video in a centered horizontal position

    <p style=\"text-align:center\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/rQ802kSaip4\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</p>\n

    mkdocs material does not have direct support for adding a YouTube video via markdown.

    "},{"location":"introduction/writing-tips/#admonitions","title":"Admonitions","text":"

    Supported admonition types

    Note

    Use !!! followed by NOTE

    Adding a title

    Use !!! followed by NOTE and a \"title in double quotes\"

    Shh, no title bar just the text... Use !!! followed by NOTE and a \"\" empty double quotes

    Abstract

    Use !!! followed by ABSTRACT

    Info

    Use !!! followed by INFO

    Tip

    Use !!! followed by TIP

    Success

    Use !!! followed by SUCCESS

    Question

    Use !!! followed by QUESTION

    Warning

    Use !!! followed by WARNING

    Failure

    Use !!! followed by FAILURE

    Danger

    Use !!! followed by DANGER

    Bug

    Use !!! followed by BUG

    Example

    Use !!! followed by EXAMPLE

    Quote

    Use !!! followed by QUOTE

    "},{"location":"introduction/writing-tips/#collapsing-admonitions","title":"Collapsing admonitions","text":"Note

    Collapse those admonitions using ??? instead of !!!

    Replace with a title

    Use ??? followed by NOTE and a \"title in double quotes\"

    Expanded by default

    Use ???+, note the + character, followed by NOTE and a \"title in double quotes\"

    "},{"location":"introduction/writing-tips/#inline-blocks","title":"Inline blocks","text":"

    Inline blocks of text to make a very specific callout within text

    Info

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Adding something to then end of text is probably my favourite

    Info

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    "},{"location":"introduction/writing-tips/#code-blocks","title":"Code blocks","text":"

    Code blocks include a copy icon automatically

    Syntax highlighting in code blocks

    (defn my-function  ; Write a simple function\n  \"With a lovely doc-string\"\n  [arguments]\n  (map inc [1 2 3]))\n

    Give the code block a title using title=\"\" after the backtics and language name

    src/practicalli/gameboard.clj
    (defn my-function\n  \"With a lovely doc-string\"\n  [arguments]\n  (map inc [1 2 3]))\n

    We all like line numbers, especially when you can set the starting line

    src/practicalli/gameboard.clj
    (defn my-function\n  \"With a lovely doc-string\"\n  [arguments]\n  (map inc [1 2 3]))\n

    Add linenums=42 to start line numbers from 42 onward

    clojure linenums=\"42\" title=\"src/practicalli/gameboard.clj\"\n
    "},{"location":"introduction/writing-tips/#annotations","title":"Annotations","text":"

    Annotations in a code block help to highlight important aspects. Use the comment character for the language followed by a space and a number in brackets

    For example, in a shell code block, use # (1) where 1 is the number of the annotation

    Use a number after the code block to add the text for the annotation, e.g. 1.. Ensure there is a space between the code block and the annotation text.

    ls -la $HOME/Downloads  # (1)\n
    1. I'm a code annotation! I can contain code, formatted text, images, ... basically anything that can be written in Markdown.

    Code blocks with annotation, add ! after the annotation number to suppress the # character

    (defn helper-function\n  \"Doc-string with description of function purpose\" ; (1)!\n  [data]\n  (merge {:fish 1} data)\n  )\n
    1. Always include a doc-string in every function to describe the purpose of that function, identifying why it was added and what its value is.

    GitHub action example with multiple annotations

    name: ci # (1)!\non:\n  push:\n    branches:\n      - master # (2)!\n      - main\npermissions:\n  contents: write\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.x\n      - run: pip install mkdocs-material # (3)!\n      - run: mkdocs gh-deploy --force\n
    1. You can change the name to your liking.

    2. At some point, GitHub renamed master to main. If your default branch is named master, you can safely remove main, vice versa.

    3. This is the place to install further [MkDocs plugins] or Markdown extensions with pip to be used during the build:

      pip install \\\n  mkdocs-material \\\n  mkdocs-awesome-pages-plugin \\\n  ...\n
    "},{"location":"introduction/writing-tips/#highlight-lines-in-code-blocks","title":"Highlight lines in code blocks","text":"

    Add highlight line meta data to a code block after the opening backticks and code block language.

    hl_lines=\"2\" highlights line 2 in the codeblock

    hl_lines=\"2 3 4\" highlights line 2, 3 and 4 in the codeblock

    (defn my-function\n  \"With a lovely doc-string\"\n  [arguments]\n  (map\n   inc\n   [1 2 3]))\n
    "},{"location":"introduction/writing-tips/#embed-external-files","title":"Embed external files","text":"

    --8<-- in a code block inserts code from a source code file or other text file

    Specify a local file from the root of the book project (the directory containing mkdocs.yml)

    Scheduled Version Check GitHub Workflow from source code file scheduled version check
    ---\n# ------------------------------------------\n# Scheduled check of versions\n# - use as non-urgent report on versions\n# - Uses POSIX Cron syntax\n#   - Minute [0,59]\n#   - Hour [0,23]\n#   - Day of the month [1,31]\n#   - Month of the year [1,12]\n#   - Day of the week ([0,6] with 0=Sunday)\n#\n# Using liquidz/anta to check:\n# - GitHub workflows\n# - deps.edn\n# ------------------------------------------\n\nname: \"Scheduled Version Check\"\non:\n  schedule:\n    # - cron: \"0 4 * * *\" # at 04:04:04 ever day\n    # - cron: \"0 4 * * 5\" # at 04:04:04 ever Friday\n    - cron: \"0 4 1 * *\" # at 04:04:04 on first day of month\n  workflow_dispatch: # Run manually via GitHub Actions Workflow page\n\njobs:\n  scheduled-version-check:\n    name: \"Scheduled Version Check\"\n    runs-on: ubuntu-latest\n    steps:\n      - run: echo \"\ud83d\ude80 Job automatically triggered by ${{ github.event_name }}\"\n      - run: echo \"\ud83d\udc27 Job running on ${{ runner.os }} server\"\n      - run: echo \"\ud83d\udc19 Using ${{ github.ref }} branch from ${{ github.repository }} repository\"\n\n      - name: \"Checkout code\"\n        uses: actions/checkout@v4\n      - run: echo \"\ud83d\udc19 ${{ github.repository }} repository was cloned to the runner.\"\n\n      - name: \"Antq Check versions\"\n        uses: liquidz/antq-action@main\n        with:\n          excludes: \"\"\n          skips: \"boot clojure-cli pom shadow-cljs leiningen\"\n\n      # Summary\n      - run: echo \"\ud83c\udfa8 library versions checked with liquidz/antq\"\n      - run: echo \"\ud83c\udf4f Job status is ${{ job.status }}.\"\n
    Practicalli Project Templates Emacs project configuration - .dir-locals.el
    ((clojure-mode . ((cider-preferred-build-tool . clojure-cli)\n                  (cider-clojure-cli-aliases . \":test/env:dev/reloaded\"))))\n

    Code example reuse

    Use an embedded local or external file (URL) when the same content is required in more than one place in the book.

    An effective way of sharing code and configuration mutliple times in a book or across multiple books.

    "},{"location":"introduction/writing-tips/#content-tabs","title":"Content tabs","text":"

    Create in page tabs that can also be

    Setting up a project

    Clojure CLILeiningen
    clojure -T:project/new :template app :name practicalli/gameboard\n
    lein new app practicalli/gameboard\n

    Or nest the content tabs in an admonition

    Run a terminal REPL

    Clojure CLILeiningen
    clojure -T:repl/rebel\n
    lein repl\n
    "},{"location":"introduction/writing-tips/#diagrams","title":"Diagrams","text":"

    Neat flow diagrams

    Diagrams - Material for MkDocs

    graph LR\n  A[Start] --> B{Error?};\n  B -->|Yes| C[Hmm...];\n  C --> D[Debug];\n  D --> B;\n  B ---->|No| E[Yay!];

    UML Sequence Diagrams

    sequenceDiagram\n  Alice->>John: Hello John, how are you?\n  loop Healthcheck\n      John->>John: Fight against hypochondria\n  end\n  Note right of John: Rational thoughts!\n  John-->>Alice: Great!\n  John->>Bob: How about you?\n  Bob-->>John: Jolly good!

    state transition diagrams

    stateDiagram-v2\n  state fork_state <<fork>>\n    [*] --> fork_state\n    fork_state --> State2\n    fork_state --> State3\n\n    state join_state <<join>>\n    State2 --> join_state\n    State3 --> join_state\n    join_state --> State4\n    State4 --> [*]

    Class diagrams - not needed for Clojure

    Entity relationship diagrams are handy though

    erDiagram\n  CUSTOMER ||--o{ ORDER : places\n  ORDER ||--|{ LINE-ITEM : contains\n  LINE-ITEM {\n    customer-name string\n    unit-price int\n  }\n  CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
    "},{"location":"introduction/writing-tips/#keyboard-keys","title":"Keyboard keys","text":"

    Represent key bindings with Keyboard keys. Each number and alphabet character has their own key.

    • 1 ++1++ for numbers
    • l ++\"l\"++ for lowercase character
    • U ++u++ for uppercase character or ++\"U\"++ for consistency

    Punctionation keys use their name

    • Space ++spc++
    • , ++comma++
    • Left ++arrow-left++

    For key sequences, place a space between each keyboard character

    • Space g s ++spc++ ++\"g\"++ ++\"s\"++

    For key combinations, use join they key identifies with a +

    • Meta+X ++meta+x++
    • Ctrl+Alt+Del ++ctrl+alt+del++

    MkDocs keyboard keys reference

    "},{"location":"introduction/writing-tips/#images","title":"Images","text":"

    Markdown images can be appended with material tags to set the size of the image, whether to appear on light or dark theme and support lazy image loading in browsers

    SizeLazy LoadingAlignTheme SpecificAll Image Attributes

    {style=\"height:150px;width:150px\"} specifies the image size

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png#only-dark){style=\"height:150px;width:150px\"}\n

    {loading=lazy} specifies an image should lazily load in the browser

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png){loading=lazy}\n

    {aligh=left} or {aligh=right} specifies the page alignment of an image.

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png#only-dark){align=right}\n![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-dark.png#only-light){align=right}\n

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    ![Kitty Logo](image/kitty-light.png#only-dark) or ![Kitty Logo](image/kitty-light.png#only-light) specifies the theme the image should be shown, allowing different versions of images to be shown based on the theme.

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png#only-dark){style=\"height:150px;width:150px\"}\n![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-dark.png#only-light){style=\"height:150px;width:150px\"}\n
    Use the theme toggle in the top nav bar to see the icon change between light and dark.

    Requires the color pallet toggle

    Alight right, lazy load and set image to 150x150

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png#only-dark){align=right loading=lazy style=\"height:64px;width:64px\"}\n![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-dark.png#only-light){align=right loading=lazy style=\"height:64px;width:64px\"}\n

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    "},{"location":"introduction/writing-tips/#lists","title":"Lists","text":"

    Task lists

    • Lorem ipsum dolor sit amet, consectetur adipiscing elit
    • Vestibulum convallis sit amet nisi a tincidunt
    • In hac habitasse platea dictumst
    • In scelerisque nibh non dolor mollis congue sed et metus
    • Praesent sed risus massa
    • Aenean pretium efficitur erat, donec pharetra, ligula non scelerisque

    Task List example

    - [x] Lorem ipsum dolor sit amet, consectetur adipiscing elit\n- [ ] Vestibulum convallis sit amet nisi a tincidunt\n    * [x] In hac habitasse platea dictumst\n    * [x] In scelerisque nibh non dolor mollis congue sed et metus\n    * [ ] Praesent sed risus massa\n- [ ] Aenean pretium efficitur erat, donec pharetra, ligula non scelerisque\n
    "},{"location":"introduction/writing-tips/#tooltips","title":"Tooltips","text":"

    The humble tool tip

    Hover me

    with references

    Hover me

    Icon tool tip with a title

    "},{"location":"introduction/writing-tips/#abreviations","title":"Abreviations","text":"

    The HTML specification is maintained by the W3C.

    [HTML]: Hyper Text Markup Language [W3C]: World Wide Web Consortium

    "},{"location":"introduction/writing-tips/#magic-links","title":"Magic links","text":"

    MagicLink can auto-link HTML, FTP, and email links. It can auto-convert repository links (GitHub, GitLab, and Bitbucket) and display them in a more concise, shorthand format.

    Email Practicalli

    Practicalli Neovim

    "},{"location":"neovim-basics/","title":"Using Neovim","text":"

    The fundamental controls of Neovim which apply across all editing tasks.

    "},{"location":"neovim-basics/#fundamentals","title":"Fundamentals","text":"

    File Buffer Window and Tab page Multi-modal Editing

    "},{"location":"neovim-basics/#editing-tools","title":"Editing Tools","text":"

    Multiple Cursors

    "},{"location":"neovim-basics/#writing-tools","title":"Writing Tools","text":"

    Snippets

    "},{"location":"neovim-basics/#development-tools","title":"Development Tools","text":"

    Comments Clojure Development Version Control

    Format and Lint tools are installed via Mason

    "},{"location":"neovim-basics/#spellcheck","title":"Spellcheck","text":"AstroNvim

    SPC u s toggles spellcheck, marking misspelt words with a rew wavy underline

    ] s jumps to next misspelt word, [ s jumps to previous misspelt word,

    z = shows numbered list of possible words, enter the number next to the work to replace the misspelt word.

    z g to add the current word to the spell list, infroming spellcheck that this is a correct word.

    "},{"location":"neovim-basics/comments/","title":"Comments","text":"

    comment.nvim toggles a comment for lines, visual selections or for motions

    gcc comment current line, 4gcc comment current line and next 4 lines

    gc comment region or use with motion e.g. gcap comment paragraph,

    gc in operator pending mode to target a comment TODO: what is operator pending mode

    :7,17Commentary comment a range

    :g/TODO/Commentary as part of a :global invocation

    gcgc removes comments from a set of adjacent commented lines.

    "},{"location":"neovim-basics/file-buffer-window-tab/","title":"Files Buffers Windows and Tabs","text":"

    Files are text written to perminant storage, e.g. disk or usb drive and are names with an extension that represents the file type, e.g. .clj for clojure, .md for markdown, etc.

    A Buffer hold the contents of a file or any other information from processes, e.g. the REPL evaluation log.

    Windows are a view on a buffer and windows can swap which buffer they show. Multiple windows, also known as splits, can be present in a Neovim frame.

    A tab page (or tab) can hold one or more windows and multiple tab pages can be shown on a tab-line.

    "},{"location":"neovim-basics/file-buffer-window-tab/#files","title":"Files","text":"

    Use Neo-tree.nvim to visually navigate and manage files using a tree view of the current project. Files and directories can be added, renamed, moved and deleted.

    Use Telescope to select files, typing a name narrows the file list.

    "},{"location":"neovim-basics/file-buffer-window-tab/#using-neo-tree","title":"Using Neo-tree","text":"AstronvimPracticalli Neovim Config Redux

    Space e toggles neo-tree file browser

    Space o toggles between buffer and neo-tree

    Space f t t to open file explorer

    Within Neo-tree:

    h j k l to navigate the file tree hierachy

    < and > to navigate between File, Bufs and Git sources tabs

    ? shows neotree help, listing key bindings

    a adds a file, prompting for a name relative to the directory where a was pressed. The name can include new directories to be created. A name ending with ++forward-slash++ will create a directory rather than a file.

    d deletes the current file or directory (including sub-directories), a conformation prompt is shown

    r to rename a file or directory (use move to change the path)

    m to move a file or directory, optionally renaming too

    Neotree icons

    • yellow dot - unsaved changes
    • pencil - git added changes
    • cross - git deleted changes
    • Warning triangle - lsp diagnostics issues
    "},{"location":"neovim-basics/file-buffer-window-tab/#telescope","title":"Telescope","text":"

    Telescope provides a selector which will narrow the list of matches as a pattern is typed, providing a fast way to find an item in a list.

    Telescope provides a preview of the selected file (only if there is sufficient space in the Neovim frame)

    File lists are relative to the directory Neovim was opened from (or Path subsequently set in Neovim).

    AstroNvimPracticalli Neovim Config Redux

    SPC f f selector for files within the scope of the current directory path. SPC f F to also show hidden files from the current directory path.

    SPC f a selector for AstroNvim user configuration files

    SPC f p selector for previously opened files (oldfiles)

    SPC f f to list files within the scope of the current directory path.

    SPC f b provides a file browser to open files, navigate the file space and create new files and directories

    "},{"location":"neovim-basics/file-buffer-window-tab/#save-file","title":"Save File","text":"

    Files and directories are created in the path given, relative to the directory in which Neovim was opened.

    A file must exist for Neovim to write to it. Neo-tree and Telescope can be used to create files and directories, as can a terminal and the command line integration (!)

    AstronvimPracticalli Neovim Config ReduxNeovim

    Space w will write all buffer changes to the associate file.

    Space n creates a new buffer that can be written to a given file using :write path/to/filename

    :write path/to/filename will write the current buffer to a new file.

    SPC f b ESC C to create a new file or directory. The base path is shown in the command bar. Type the name of directories and file name as required. RTN to create or ESC to cancel. The newly created directories or file name appears n the Telescope list and scan be selected for opening.

    Telescope Normal mode and help

    ESC in Telescope to switch to Normal mode and use comannds, c for Create, r to rename.

    ? to show all the commands available in Telescope

    :lcd to set the current local directory

    :write path/to/filename will write the current buffer to a new file

    :!mkdir path/to/directory will create a new directory

    If a file is already opened, i.e. with :edit, there is some short-hand syntax to simplify the typing

    :!mkdir -p %:h

    -p option createst any parts of the path required to make the full path

    % is the neovim name of the current file

    :h for the current directory (the \u201chead\u201d of the path).

    ! is the NeoVim terminal shell command, e.g. :!mkdir -p path/to/new/directory creates a new directory and any intermediate path

    "},{"location":"neovim-basics/file-buffer-window-tab/#swap-file","title":"Swap file","text":"

    Neovim creates a swap file, .swp, containing the changes made in a buffer to minimise loss should there be an issue with the computer or Neovim. Changes are written to the swap file after 200 characters or after 4 seconds pause.

    Swap file location

    :swapname shows the full path to the swap file for the current buffer, e.g.

    /home/practicalli/.local/state/astronvim/swap//%home%practicalli%projects%practicalli%books%neovim%docs%neovim-basics%files-buffers-windows.md.swp`\n

    :preserve command will write all text from current buffer to the swap file.

    :recover command overwrites the current buffer with the data from the swap file. :recover! command must be use if the buffer has newer changes than the swap file. Add a filename after the command to recover to a different file than that contained in the current buffer.

    Opening a file checks if there is an associated swap file and prompts the user

    • (A)bort opening the file
    • (D)elete the swap file
    • (E)dit anyway, select if the file is newer than the swap file
    • (R)ecover the data in the swap file into the file buffer

    :edit after the file is open also prompts if there is a swap file. Selecting (D)elete will delete the swap file without changing the current buffer

    "},{"location":"neovim-basics/file-buffer-window-tab/#buffers","title":"Buffers","text":"AstroNvimPracticalli Neovim Config Redux

    SPC f b selector for currently open buffers

    SPC b b to select a buffer from the tab line, pressing the character that appears next to the buffer tab (case sensitive)

    SPC b D to delete a buffer from the tab line, pressing the character that appears next to the buffer tab (case sensitive)

    Open multiple buffers when starting Neovim by specifying multiple files to open

    astro README.md deps.edn src/practicalli/playground.clj test/practicalli/playground.clj\n

    SPC b b switch between buffers in the current window, using a Telescope popup that lists all current buffers (includes files, Conjure REPL Log, etc.).

    SPC b n (:next) and SPC b n (:previous) to cycle through buffers in the current window

    SPC TAB (C-^) opens the previous buffer, useful to toggle between two buffers in the same window

    Use Telescope to switch between buffers

    Open multiple buffers when starting Neovim by specifying multiple files to open

    nvim README.md deps.edn src/practicalli/playground.clj test/practicalli/playground.clj\n
    "},{"location":"neovim-basics/file-buffer-window-tab/#buffer-text-wrapping","title":"Buffer text wrapping","text":"

    The test in a buffer is not wrapped by default. Set and unset soft text wrapping in a buffer

    AstroNvimPracticalli Neovim Config ReduxNeovim

    SPC u w toggles wrapping of text

    line wrap not enabled in configuration by default.

    fnl/config/init.fnl
    (nvim.ex.set :nowrap)\n

    :set wrap to set soft wrapping on current buffer

    :set nowrap to show lines in full (scroll sideways to see lines longer than the window)

    "},{"location":"neovim-basics/file-buffer-window-tab/#windows","title":"Windows","text":"

    Windows can be active (contains the cursor), hidden (open but not shown) or inactive.

    AstroNvimPracticalli Neovim Config ReduxNeovim

    \\ creates an horizontal split

    SPC q removes the current split

    SPC h / SPC l to jump to left / right buffer, SPC j / SPC k to jump to buffer below / above

    SPC b b to list current buffers and switch between them using telescope

    C-w and hjkl to navigate windows is the classic Vim approach

    C-w menu to manage Windows, also known as splits.

    C-w with one of hjkl will move the cursor to the next window in that direction. Also works with arrow keys.

    C-w w toggle between open windows

    :q or C-w q closes the active window, closing Neovim if it is the last active window.

    :wincmd can be used as an alternative to the Normal mode key bindings

    Open file in a new window

    :sp relative-or-full-filename-path\n

    Resize windows

    C-w -, +, < or > for vertical or horizontal size adjustment

    "},{"location":"neovim-basics/file-buffer-window-tab/#tab-pages","title":"Tab pages","text":"

    A Tab page can hold one or more tabs and are useful for grouping different types of files and information.

    A Tab page holds one or more windows, each window is a view on a buffer, a buffer holds the contents of a file or any other information in the editor memory (repl log, etc).

    A tab page can provide a logical grouping of windows, e.g. Clojure source code in one tab, tests in a second tab and REPL log in a third.

    Neovim window commands may be constrained within the bounds of a tab page (without using the :tab modifier)

    Tab pages are often referred to as tabs.

    AstroNvim

    g Tab jump to previously selected tab, commonly used to toggle between two tabs (Practicalli AstroNvim mapping)

    g t jump to next tab page

    g T jump to previous tab page

    "},{"location":"neovim-basics/multi-modal-editing/","title":"Multi-modal Editing","text":"

    TODO: Add multi-modal editing in Neovim guide

    Practicalli Spacemacs has useful reference content on multi-modal editing (Evil mode).

    Most of this content is the same in Neovim with a few exceptions

    "},{"location":"neovim-basics/multi-modal-editing/#selecting-text","title":"Selecting text","text":"

    vi) selects all the text within (), e.g. (http://oldwebsite.doh)

    "},{"location":"neovim-basics/multi-modal-editing/#surround","title":"Surround","text":"

    viw selects the current word, using j/k to modify the selection where required. o toggles which end of the selection is expanded/shrunk

    s substitues the selection, type the characters to surround the selection.

    p to pase the original text

    "},{"location":"neovim-basics/multi-modal-editing/#nvim-surround","title":"nvim-surround","text":"

    nvim-surround provides enhancments over the neovim surround command.

    nvim-surround included in Practicalli AstroNvim Config

    "},{"location":"neovim-basics/multi-modal-editing/#visual-mode","title":"Visual Mode","text":"

    viw to select the current word (visual in word)

    S on a visual selection to surround with next that character, e.g. S) to surround with parens.

    Closing paren surrounds without spaces

    ), ], } surrounds the selected text without spaces between the text and the open and closing parens.

    (, [, { surrounds the selected text with a space between the text and the open and closing parens.

    "},{"location":"neovim-basics/multi-modal-editing/#normal-mode","title":"Normal mode","text":"

    cs inside an existing pair of characters to change them to another pair of surrounding characters, e.g. cs(} to change (text) to {text}

    ds inside a pair of surrounding characters to delete them, e.g. ds( to change (text) to text

    ys you surround followed by motion and character, e.g. ysw) surrounds word with (parens)

    yS to surround current line

    ySS to surround current line, placing characters on new lines, e.g. ySS{ will change \"Olical/conjure\" to:

    {\n    \"Olical/conjure\"\n}\n

    The three \"core\" operations of add/delete/change can be done with the keymaps ys{motion}{char}, ds{char}, and cs{target}{replacement}, respectively. For the following examples, * will denote the cursor position:

    Old text                    Command         New text\n----------------------------------------------------\nsurr*ound_words             ysiw)           (surround_words)\n*make strings               ys$\"            \"make strings\"\n[delete ar*ound me!]        ds]             delete around me!\nremove <b>HTML t*ags</b>    dst             remove HTML tags\n'change quot*es'            cs'\"            \"change quotes\"\n<b>or tag* types</b>        csth1<CR>       <h1>or tag types</h1>\ndelete(functi*on calls)     dsf             function calls\n

    Neovim help provides details on using nvim-surround

    :help nvim-surround.usage\n
    "},{"location":"neovim-basics/multi-modal-editing/#web-links","title":"Web Links","text":"

    g x on a URL to open in the default browser

    "},{"location":"neovim-basics/multi-modal-editing/#markdown","title":"Markdown","text":"

    s in visual mode substitues the selection with the next character typed

    v to create visual selection, s to substitute the current selection, **** to create a bold style, P with the cursor on the second * pastes the text that was visually selected.

    "},{"location":"neovim-basics/multi-modal-editing/#text-style","title":"Text style","text":"

    ysiw* surrounds current word with * to create italic text, . repeats to make bold text style.

    ds* removes * from current word.

    "},{"location":"neovim-basics/multi-modal-editing/#nvim-surround_1","title":"nvim-surround","text":"

    nvim-surround plugin assists with adding style characters around text, e.g adding links, italic or bold text, etc.

    S on a visual selection will surround the text with the next character. . repeat not supported.

    Create a link

    v and motion keys to select text, S [ to surround text with [] creating the text of a link anchor. Use S ( to surround the URL of the link.

    "},{"location":"neovim-basics/multiple-cursors/","title":"Multiple cursors","text":"

    Visual-Multi (VM) is a multiple selections/cursors plugin that uses modal editing and provide visual feedback when editing multiple lines simultaneously.

    Mulitple cursors is generally useful when editing smilarly structured lines with diffferent content. Cursors are moved by column position or by using vim motions.

    AstroNvimPracticalli Neovim Config Redux

    Space g m opens the visual-multi menu

    Using visual select is a simple way to edit multiple lines as the same time.

    Space g m c on visually selected lines creates a cursor on each line.

    Esc or f d to close multiple cursors.

    \\ \\ c creates a cursor at the start of every visual selection line

    \\ \\ \\ toggle cursor at position

    "},{"location":"neovim-basics/multiple-cursors/#search-and-replace","title":"Search and Replace","text":"

    Select a text pattern to search for and use multiple cursors to add a cursor each match, then change each selected occurance concurrently.

    AstroNvimPracticalli Neovim Config Redux

    Select the pattern with visual select

    Space g m a on each matching text pattern in the buffer

    c to change the original text and type the new pattern. All cursors will update concurrently.

    Esc or f d to close multiple cursors.

    \\ \\ a creates a cursor at the start of every visual selection line

    \\ \\ \\ toggle cursor at position

    c to change the original text and type the new pattern. All cursors will update concurrently.

    Esc or f d to close multiple cursors.

    "},{"location":"neovim-basics/multiple-cursors/#command-quick-reference","title":"Command quick reference","text":"

    :help g:VM_maps for a reference of all mappings and instructions on how to change them

    AstroNvim

    SPC g m opens the Visual-Multi menu in normal mode

    g m opens the Visual-Multi menu in visual mode

    c to add a cursor to every line in the visually selected region

    Practicalli Neovim Config Redux

    \\ \\ is the leader for multiple cursors and will show the visual-multi menu in which-key.

    These commands cover the large majority of use cases for multiple cursors.

    Action Key Command Add Cursor at Position \\\\\\ vm-add-cursor Alignm VM cursors with cursor \\\\a vm-align Select All Words \\\\A vm-select-all Transposition \\\\t vm-transpose Toggle Mappings \\\\<Space> vm-mappings-toggle Find with Regex \\\\/ vm-regex-search Reselect Last \\\\gS vm-reselect-last

    Once visual-multi has started the vm-mappings-buffer mappings are available:

    Action Key Command Find Word <C-n> vm-find-word Next/Previous/Skip n / N / q vm-find-next Remove Region Q vm-remove-region Add Cursors Down/Up <C-Down> / <C-Up> vm-add-cursors Select Right/Left <S-Right>, <S-Left> vm-shift-select Slash motion g/ vm-slash Select Operator s vm-select-operator Find Operator m vm-find-operator

    NOTE: C-n conflicts with the Termux binding for naming a session

    "},{"location":"neovim-basics/multiple-cursors/#searching","title":"Searching","text":"

    g/ to search for a match to add when visual-multi is active, rather than the usual / vim search.

    n and N can't be used to repeat the search, as they are used to get the next visual-multi match.

    "},{"location":"neovim-basics/multiple-cursors/#find-with-regex","title":"Find with Regex","text":"

    \\ \\ / followed by a regex pattern will create a selection with that pattern.

    n and N finds the next occurrence of the regex pattern

    "},{"location":"neovim-basics/multiple-cursors/#smart-case-change","title":"Smart case change","text":"

    gc In extend-mode will use smartcase to change a selection

    • at main cursor, text is always inserted as typed
    • at other cursors, if region text was fully uppercased, replacement will be uppercased as well
    • if the region text was capitalized, the replacement will be as well
    "},{"location":"neovim-basics/multiple-cursors/#filter-regions","title":"Filter regions","text":"

    \\ \\ f filter out (remove) regions based on pattern or expression.

    C-x to cycle filtering method:

    • pattern: remove regions that don't match the pattern
    • !pattern: remove regions that match the pattern
    • expression: remove regions that don't match the expression (same as below)
    "},{"location":"neovim-basics/multiple-cursors/#transform-regions-with-expression","title":"Transform regions with expression","text":"

    \\ \\ e to transform a region with a vim expression, run on each region

    Placeholders can be used in the expression

    • `%t~ region's text as a string (as-is)
    • `%f~ region's text evaluated as a floating point number
    • `%n~ region's text evaluated as an integer number
    • `%i~ region's index
    • `%N~ total number of regions

    Examples: - %f * 0.5 divide text of all regions by 2 - %t .\" \". %i .\" / \". %n append index / total to text of each region - %i%2 ? %t : toupper(%t) uppercase all odd regions (1,3,5...) - %i%3-2 ? %t : '' delete every third region

    "},{"location":"neovim-basics/multiple-cursors/#vm-motions","title":"VM Motions","text":"

    visual-multi supports vim motions although they behave differently as their result is dependent on the mode:

    • cursor mode will move cursors
    • extend mode motions extend selections

    Unless multiline-mode is enabled motions are restricted to the current line and cannot cross line boundaries

    Some object-motions and various-motions require multiline-mode and aliased to avoid conflict with VM mappings:

    vim VM~ Description / g/ to next match (for all regions) ( ( [count] sentences backward ) ) [count] sentences forward { { [count] paragraphs backward } } [count] paragraphs forward [( g( go to [count] previous unmatched '(' [{ g{ go to [count] previous unmatched '{' ]) g) go to [count] next unmatched ')' ]} g} go to [count] next unmatched '}'"},{"location":"neovim-basics/multiple-cursors/#vm-operators","title":"vm-operators","text":"

    Visual-Multi supports several operators by default:

    • y / d / c to yank / delete / change
    • gu / gU to change text case

    Visual-Multi uses its own registers that are lists of strings. One element for each region that is yanked/deleted.

    There is also built-in support for:

    • vim-surround e.g. ysiw( to enclose in parentheses
    • vim-abolish e.g. cr_ to change current word to snake case

    `:help g:VM_user_operators to disccover how to doefine other operators

    "},{"location":"neovim-basics/multiple-cursors/#vm-multiline-mode","title":"vm-multiline-mode","text":"

    In normal and insert mode, cursors and selections are kept within their own line. Cursors are blocked from moving off the current line to the next line.

    M enables multiline-mode that allows cuursors to move onto another line.

    Multiline mode must be enabled for an object motions, or they will fail. See |vm-motions|.

    "},{"location":"neovim-basics/multiple-cursors/#alignment","title":"Alignment","text":"

    \\\\a aligns by setting the minimum column to the highest of all regions \\\\< aligns by character, or [count] characters \\\\> aligns by regex pattern

    In extend-mode selections are collapsed to cursors first, although will work regardless.

    "},{"location":"neovim-basics/multiple-cursors/#replace-pattern-in-regions","title":"Replace pattern in regions","text":"

    R to replace with a pattern and then the replacement text

    substitution will take place in all selected regions, leaving unselected text untouched.

    Only working in |extend-mode|. When |R| is pressed in |cursor-mode|, it will start |vm-replace-mode| instead.

    "},{"location":"neovim-basics/multiple-cursors/#subtract-pattern-from-regions","title":"Subtract pattern from regions","text":"

    \\\\s subtract the entered pattern from regions, splitting them. Only working in |extend-mode|.

    "},{"location":"neovim-basics/multiple-cursors/#transposition","title":"Transposition","text":"

    \\ \\ t swaps the contents of selections, cycling them if there are more than two.

    If there is an equal number of selections in each line, swapping takes place within the same line only. Only in |extend-mode|.

    "},{"location":"neovim-basics/multiple-cursors/#duplication","title":"Duplication","text":"

    \\ \\ d duplicates in place the contents of the selections, reselecting the original ones. Only in extend-mode.

    "},{"location":"neovim-basics/multiple-cursors/#shift-selections","title":"Shift Selections","text":"

    and move the selections right or left, preserving the surroundings."},{"location":"neovim-basics/multiple-cursors/#case-conversion","title":"Case conversion","text":"

    \\\\C runs on inner words in cursor mode

    • u lowercase
    • U UPPERCASE
    • C Captialize
    • t Title Case
    • c camelCase
    • P PascalCase
    • s snake_case
    • S SNAKE_UPPERCASE
    • - dash-case
    • . dot.case
    • <space> space case
    "},{"location":"neovim-basics/multiple-cursors/#modes","title":"Modes","text":"

    cursor-mode and extend-mode are two Visual-Multi modes, roughly corresponding to normal-mode and visual-mode

    TAB switches between cursor-mode and extended-mode

    "},{"location":"neovim-basics/multiple-cursors/#vm-cursor-mode","title":"VM Cursor Mode","text":"

    cursor-mode commands expect a motion, e.g. c should be followed by a text object to be changed.

    Key Description operators see vm-operators motions see vm-motions | set column for all cursors (to current column or [count]) r replace single character R enter vm-replace-mode ~ change case of single character & repeat last substitution <C-A> increase numbers <C-X> decrease numbers g<C-A> progressively increase numbers (v_g_CTRL-A) g<C-X> progressively decrease numbers (v_g_CTRL-X)

    You can enter |insert-mode| with i, I, a, A, and only from cursor mode also with o and O.

    Also see vm-motions for supported motions in VM (some with differences).

    "},{"location":"neovim-basics/multiple-cursors/#vm-extend-mode","title":"VM Extend Mode","text":"

    extend-mode is like having multiple visual selections. motions extend the slections and change / yank / delete commands don't wait for a motion, just like in visual mode.

    Even the key o works as in visual mode, inverting the anchor of the selections.

    Some commands are specific to |extend-mode|, such as:

    • s vim-surround
    • R replace pattern in regions
    • \\\\s split regions by pattern
    • \\\\e transform regions text with vim expression

    Some commands enforce cursor-mode when run from extend-mode:

    • <C-A> increase numbers
    • <C-X> decrease numbers

    Others can use a different mapping:

    • gu/gU change case (instead of vim u / U)
    • o and O mappings are used to invert the facing of the selected regions and not to start insert mode.
    "},{"location":"neovim-basics/notifications/","title":"Notifications","text":"Notifications only in AstroNvim, not the Practicalli Neovim configuration

    Space f n lists the history of notifications for the current sesion

    Enter to open the highlighted item in the list in its own popup

    Notification popups show information, warnings and errors.

    "},{"location":"neovim-basics/notifications/#configure-notifications","title":"Configure notifications","text":"

    Notifications are controlled by nvim-notify

    Practicalli astronvim-config overrides several default values in plugins/core.lua

    • top_down position of notifications, false shows popups from bottom of screen
    • timeout value controls how long a popup displays, defautl 3000
    • level of information displayed, level 3 hides less important information, e.g. file write messages, default 5

    Practicalli Configuration for notifications

    plugins/core.lua
      -- Configure notify popups\n  {\n    \"rcarriga/nvim-notify\",\n    opts = {\n      top_down = false,\n      timeout = 1000,\n      -- log level - 3 hide file write messages - default 5\n      level = 3,\n      -- background_color = \"#000000\",\n    },\n  },\n

    Noice uses nvim-notify configuration

    Noice replaces the UI for messages, command line and popup menus, although uses the configuration of nvim-notify for position and popup timing.

    "},{"location":"neovim-basics/plugin-manager/","title":"Plugin Manager","text":"

    Neovim community provides a wide range of plugins to greatly extend the features of Neovim

    There is a wide range of plugin managers too, including a built-in plugin manager in Neovim.

    • Lazy - AstroNvim Config
    • Packer - Practicalli Neovim Config Redux

    Lazy plugin manager recommeded

    Practicalli recommends Lazy plugin manager as it feels much easier to use and has a more engaing and understandable user interface

    Neovim evolving

    Neovim and its plugins are evolving quite rapidly, so it is recommended to update plugins if there are issue or when a newer version of Neovim has been installed

    Plugin issue are not that common and typically fixed quite quickly by the community

    AstroNvimPracticalli Neovim Config Redux

    Lazy plugin manager

    SPC P u to update packages to their latest versions (:PackerUpdate). Details of updated changes will be shown at the end of the update.

    r in the package update screen gives the option to revert an update if something has gone wrong (although this seem to be a rare issue).

    When packages are all at the latest available version, Packer update reports packages already up to date.

    Packer downloads packages and documentation from the Internet, so a connection is required

    "},{"location":"neovim-basics/plugin-manager/#package-list-and-documentation","title":"Package List and documentation","text":"AstroNvimPracticalli Neovim Config Redux

    Lazy plugin manager

    SPC P l to list the current packages added to the configuration

    Selecting a package will display the website documentation for the package (although this may be in HTML so not the cleanest way to read the docs).

    "},{"location":"neovim-basics/plugin-manager/#adding-packages","title":"Adding packages","text":"AstroNvimPracticalli Neovim Config Redux

    Lazy plugin manager

    Add package names as keywords in the use expression in fnl/config/plugin.fnl file.

    :requires to add a package that is a dependency for the package being added

    :mod defines the namespace that contains the package configuration, typically a setup function with options. The namespace matches the file name under fnl/config/plugin

    SPC P i to install packages that have been added to fnl/config/plugin.fnl

    q to quit once all packages are up to date

    "},{"location":"neovim-basics/search-replace/","title":"Search and Replace","text":"

    :substitute or :s vim command will highlight the matches for a text pattern and substitute for a new pattern

    Built-in help for the command

    :help :substitute\n
    Multiple cursors can also be used for multiple substitutions

    multiple cursors created on each occurance can be used to search and replace a pattern

    Subsitute the first matching patterns in the current line

    :s/current-pattern/new-pattern\n

    Subsitute all the matching patterns in the current line, g representing all occurances in a line

    :s/current-pattern/new-pattern/g\n

    Use % to specify the current buffer as the scope to change all matches

    :%s/current-pattern/new-pattern/g\n
    "},{"location":"neovim-basics/snippets/","title":"Snippets","text":"

    LuaSnip can use several different sources for snippets

    • VSCode JSON snippets (Friendly-snippets)
    • LSP style snippets
    LuaSnip Configuration

    Practicalli Neovim Config Redux includes the LuaSnip package which also adds friendly-snippets and cmp_luasnip.

      ; snippets\n  :L3MON4D3/LuaSnip \n  {:requires [:rafamadriz/friendly-snippets\n              :saadparwaiz1/cmp_luasnip]\n   :mod :lua-snip}\n
    Configure LSP snippet locations
    {\n  \"name\": \"practicalli-snippets\",\n  \"engines\": {\n    \"vscode\": \"^1.11.0\"\n  },\n  \"contributes\": {\n    \"snippets\": [\n      {\n        \"language\": [\n          \"markdown\",\n          \"global\",\n          \"all\"\n        ],\n        \"comment\": \"snippets accross several languages\",\n        \"path\": \"./global.json\"\n      },\n      {\n        \"language\": \n          \"markdown\",\n        \"path\": \"./markdown.json\"\n      }\n    ]\n  }\n}\n

    "},{"location":"neovim-basics/snippets/#snippet-definitions","title":"Snippet Definitions","text":"

    snippets directory contains snippet definitions, with a JSON file for each language, e.g. markdown.json

    Practicalli Neovim Config Redux contains several groups of snippet definitions

    • MkDocs format and icons (markdown.json VSCode syntax)

    Restart Neovim to load new defintions

    Snippets added to VSCode JSON snippets are only loaded when Neovim starts, so newly added snippets will only be available after Neovim is restarted.

    "},{"location":"neovim-basics/terminal/","title":"Terminal","text":"

    akinsho/toggleterm.nvim plugin provides a terminal session within Neovim, using a float, split or tab.

    AstroNvim

    SPC t for the Terminal sub-menu

    SPC t f opens a terminal in a floating window, useful for one-off commands

    SPC t h opens a terminal in a horizontal split, useful for a process that prints valuable feedback, e.g. a test runner in watch mode

    SPC t t opens a terminal in a tab, useful for background processes that do not need attendtion

    "},{"location":"neovim-basics/zen-mode/","title":"Focus Modes","text":"

    Focus on the code or text being created, without distractions

    zZ toggles Zen mode

    SPC z a ataraxis focus mode

    SPC z f focus current buffer

    SPC z n narrow to current buffer

    SPC z n remove status bar and window decorations

    v SPC z n narrow to selection

    "},{"location":"neovim-basics/zen-mode/#zen-mode","title":"Zen Mode","text":"

    Zen Mode distraction-free coding for Neovim

    Available via the Astrocommunity repository.

    Zen Mode configuration for AstroNvim

    .config/astronvim-config/plugins/community.lua
      { import = \"astrocommunity.editing-support.zen-mode-nvim\" },\n  {\n    \"folke/zen-mode.nvim\",\n    opts = {\n      -- override default configuration\n      -- https://github.com/folke/zen-mode.nvim#%EF%B8%8F-configuration\n      plugins = {\n        options = {\n          enabled = true,\n        },\n        kitty = {\n          enabled = true,\n          font = \"+4\", -- font size increment\n        },\n      },\n    },\n  },\n

    kitty configuration enables Zen Mode to resize kitty fonts.

    "},{"location":"neovim-basics/zen-mode/#true-zen","title":"True Zen","text":"

    true-zen.nvim clean and elegant distraction-free writing for NeoVim

    True Zen Mode configuration for AstroNvim

      {\n    \"Pocco81/true-zen.nvim\",\n    lazy = false,\n    opts = {\n      integrations = {\n        kitty = {\n          -- increment font size in Kitty.\n          enabled = true,\n          font = \"+4\",\n        },\n      },\n    },\n  },\n

    See kitty configuration to enable Zen Mode to resize kitty fonts.

    "},{"location":"neovim-basics/zen-mode/#kitty-configuration","title":"Kitty configuration","text":"

    Add allow_remote_control socket-only and listen_on unix:/tmp/kitty to the kitty config

    Kitty support for Zen Mode

    .config/kitty/kitty.config
    # ---------------------------------------------------------\n#  Neovim zen-mode-nvim\n#  - change the font size on kitty when in zen mode\nallow_remote_control socket-only\nlisten_on unix:/tmp/kitty\n# ---------------------------------------------------------\n
    "},{"location":"reference/lua-language/","title":"Lua","text":"

    Lua is the default language for Neovim configuration.

    "},{"location":"reference/lua-language/#learning-lua","title":"Learning Lua","text":"

    Neovim Lua introduction

    Lua.org - Programming in Lua (first edition)

    Codecademy - learn lua course

    "},{"location":"reference/lua-language/#reference","title":"Reference","text":"

    Lua.org 5.4 Reference Manual

    "},{"location":"reference/neovim/","title":"Neovim Reference","text":"
    • Language Providers
    • Key mappings
    "},{"location":"reference/neovim/language-providers/","title":"Language Providers","text":"

    Neovim delegates some features to language providers.

    :checkhealth command in Neovim shows if the binaries and tools required by each provider are available in the operating system.

    Resolve the issue with providers that generate a warning in the checkhealth report, following the ADVICE steps provided.

    "},{"location":"reference/neovim/language-providers/#disable-language-providers","title":"Disable Language Providers","text":"

    If a language is not used with Neovim, then its provider can be disabled. Details on how to disable a provider are included at the end of the ADVICE in the report section for that provider.

    Disable language providers in the init.lua configuration file

    init.lua
    -- Disable Language providers\nvim.g.loaded_node_provider = 0       --- (1)!\nvim.g.loaded_perl_provider = 0\nvim.g.loaded_python3_provider = 0\nvim.g.loaded_ruby_provider = 0\n
    1. Example configuration to disable providers is provided in the practicalli/neovim-config-redux configuration

    Ignore Language Provider warnings

    If the programming language is not used, there are no issues with using Neovim if the warnings are simply ignored

    "},{"location":"reference/neovim/standard-path/","title":"Neovim Standard Path","text":"

    View the standard paths used by Neovim using the help menu

    :help standard-path\n

    Output of command

    Standard Paths                  *standard-path*\n\nNvim stores configuration, data, and logs in standard locations. Plugins are\nstrongly encouraged to follow this pattern also. Use |stdpath()| to get the\npaths.\n\n                        *base-directories* *xdg*\nThe \"base\" (root) directories conform to the XDG Base Directory Specification.\nhttps://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\nThe $XDG_CONFIG_HOME, $XDG_DATA_HOME, $XDG_RUNTIME_DIR, and $XDG_STATE_HOME\nenvironment variables are used if defined, else default values (listed below)\nare used.\n\nCONFIG DIRECTORY (DEFAULT) ~\n                  *$XDG_CONFIG_HOME*            Nvim: stdpath(\"config\")\n    Unix:         ~/.config                   ~/.config/nvim\n    Windows:      ~/AppData/Local             ~/AppData/Local/nvim\n\nDATA DIRECTORY (DEFAULT) ~\n                  *$XDG_DATA_HOME*              Nvim: stdpath(\"data\")\n    Unix:         ~/.local/share              ~/.local/share/nvim\n    Windows:      ~/AppData/Local             ~/AppData/Local/nvim-data\n\nRUN DIRECTORY (DEFAULT) ~\n                  *$XDG_RUNTIME_DIR*            Nvim: stdpath(\"run\")\n    Unix:         /tmp/nvim.user/xxx          /tmp/nvim.user/xxx\n    Windows:      $TMP/nvim.user/xxx          $TMP/nvim.user/xxx\n\nSTATE DIRECTORY (DEFAULT) ~\n                  *$XDG_STATE_HOME*             Nvim: stdpath(\"state\")\n    Unix:         ~/.local/state              ~/.local/state/nvim\n    Windows:      ~/AppData/Local             ~/AppData/Local/nvim-data\n\nNote: Throughout the user manual these defaults are used as placeholders, e.g.\n\"~/.config\" is understood to mean \"$XDG_CONFIG_HOME or ~/.config\".\n\nLOG FILE                    *$NVIM_LOG_FILE* *E5430*\nBesides 'debug' and 'verbose', Nvim keeps a general log file for internal\ndebugging, plugins and RPC clients. >\n    :echo $NVIM_LOG_FILE\nBy default, the file is located at stdpath('log')/log unless that path\nis inaccessible or if $NVIM_LOG_FILE was set before |startup|.\n
    "},{"location":"reference/vim-style/","title":"Reference: Learn Vim-style Editing","text":"

    Learning vim-style multi-modal editing takes time and practice. Most importantly this approach can be learned in stages, as insert mode is the same editing experience as using most other editors.

    Start with the multi-modal concept and the basics of navigation. Then adopt more normal and visual mode actions, including motions

    "},{"location":"reference/vim-style/#getting-started","title":"Getting started","text":"

    :Tutor runs the intteractive tutorial built into neovim (:help tutor also runs the tutor)

    vim adventures isa simple online game to teach you the fundamentals of vim-style editing.

    "},{"location":"reference/vim-style/#navigation-and-searching","title":"Navigation and searching","text":"
    • moving the cursor
    • Motions
    • line numbers
    • jumping around a buffer
    • search and replace
    "},{"location":"reference/vim-style/#text-wrangling","title":"Text wrangling","text":"
    • iedit
    • text case
    "},{"location":"reference/vim-style/#clojure-editing","title":"Clojure Editing","text":"

    traversing expressions structural editing

    "},{"location":"reference/vim-style/case/","title":"Modifying text case","text":"

    Convert Characters and regioins to upper or lower case text.

    "},{"location":"reference/vim-style/case/#toggle-case-with-visual-select","title":"Toggle case with visual select","text":"

    v to visually select a character or use the vim motion keys to select a region

    U to uppercase current character or selected region

    u to lowercase current character or selected region

    ~ to toggle the case of the text in the selected region

    . will repeat the previous selection size and case toggle

    "},{"location":"reference/vim-style/case/#toggle-case-menu","title":"Toggle case menu","text":"

    Toggle the current character using vim motion keys, without needing to select a region.

    g ~ opens the toggle case menu

    TODO: Add screenshot of g ~ toggle case menu

    g ~ ~ uppercase current line (also works for RET and maybe other none-menu characters, but not SPC)

    "},{"location":"reference/vim-style/case/#cheatsheet","title":"Cheatsheet","text":"
    • ~ Changes the case of current character
    • guu Change current line from upper to lower.
    • gUU Change current LINE from lower to upper.
    • guw Change to end of current WORD from upper to lower.
    • guaw Change all of current WORD to lower.
    • gUw Change to end of current WORD from lower to upper.
    • gUaw Change all of current WORD to upper.
    • g~~ Invert case to entire line
    • g~w Invert case to current WORD
    • guG Change to lowercase until the end of document.
    • gU) Change until end of sentence to upper case
    • gu} Change to end of paragraph to lower case
    • gU5j Change 5 lines below to upper case
    • gu3k Change 3 lines above to lower case
    "},{"location":"reference/vim-style/g-menu/","title":"Evil G menu","text":"

    g` in normal mode opens a menu of convenient utilities. Practicalli uses this menu to comment existing lines, jumping to top or bottom of the buffer and changing text case.

    "},{"location":"reference/vim-style/g-menu/#comment-lines-and-regions","title":"Comment lines and regions","text":"

    g c c will comment the current line using the buffer major mode comment character(s). A prompt will ask if no comment character is set for the major mode.

    g c with a selected region will comment all lines with the major mode comment character(s)

    "},{"location":"reference/vim-style/g-menu/#jumping-around","title":"Jumping around","text":"

    g g jumps to the top of the buffer, g G to the bottom of the buffer

    g d to jump to the source code of a function definition, g D to open that in a different window.

    g f to jump to file name under cursor (if file exists).

    "},{"location":"reference/vim-style/g-menu/#changing-text-case","title":"Changing text case","text":"

    g u to change the current character or selection to lowercase, g U for uppercase.

    Toggle case with ~

    ~ will toggle the case of the current character or selected region.

    "},{"location":"reference/vim-style/key-binding-reference/","title":"Evil Keybinding Reference","text":"

    An alphabetically ordered reference of Vim-style key bindings.

    "},{"location":"reference/vim-style/key-binding-reference/#normal-mode-keybindings","title":"Normal mode keybindings","text":"

    Keybindings available in Evil normal mode and the resultant state they leave you in.

    Keybinding Description State @ execute keyboard macro (defined by q) Normal ' jump to mark (defined by m) Normal a append text after cursor Insert a append text after cursor Insert A append text to end of sentence Insert b move cursor back to start of previous word Normal B move cursor back to start of last word Normal c change (use with modifier) Insert C change rest of sentence Insert d delete (use with modifier) Normal D delete rest of sentence Normal e end of word Normal E end of word (seems same as above) Normal f find character forward (type character) Normal F find character backward (type character) Normal fd Escape (press almost together) Normal g go menu Normal G Jump to end of buffer Normal h move cursor left Normal H move cursor to top of buffer Normal i insert text Insert I insert text at start of sentence Insert j Move cursor down a line Normal J Join next line to end of current Normal k Move cursor up a line Normal K spacemacs/evil-smart-doc-lookup Normal l Move cursor right Normal L Move cursor to bottom of buffer Normal m Create marker (next character is marker name) Normal M Jump to middle of buffer Normal n Next search occurrence Normal N Previous search occurrence Normal o New line below Insert O New line above Insert p Paste (after / below cursor) Insert P Paste (before / above cursor) Insert q Record keyboard macro attached to given character Normal Q undefined Normal r Replace character under cursor Normal R Replace character state Replace s Substitute character Insert S Substitute current line Insert t Find character forward - cursor before character Normal T Find character backward - cursor after character Normal u Undo last change (C-R to redo) Normal U Undefined Normal v Visual select Visual V Visual select sentence Visual w Jump cursor to start of next word Normal W Jump cursor to start of next word Normal x Delete character under cursor Normal X Delete character backwards Normal y y Yank (copy) line Normal Y Yank (copy) line Normal z Menu - code folding / keyboard macros Normal"},{"location":"reference/vim-style/motions/","title":"Motions","text":"

    Todo

    Moving the cursor around by context rather than individual characters

    "},{"location":"reference/vim-style/moving-around/","title":"Moving around the cursor","text":"

    Scrolling is quite inefficient in most editors and moving (jumping) the curor around is far more effective.

    Using the h j k l as a common part of navigation provides consistency and keeps fingers on the most convienient part of the keyboard.

    "},{"location":"reference/vim-style/moving-around/#moving-by-charater","title":"Moving by charater","text":"

    h j k l keys move the cursor once character or can be used with numbers to move further.

    • h move left (often used to move up a path or tree, e.g. a directory path)
    • j move down
    • k move up
    • l move right (often used to move down a path or tree, e.g. a directory path)
    "},{"location":"reference/vim-style/moving-around/#moving-with-numbers","title":"Moving with numbers","text":"

    : followed by a number then one of h j k l keys will move the cursor that number in the director of the key.

    3j will move 3 lines down the buffer (or to the end of the fuffer if there are fewer lines remaining)

    Using Relative line numbers showws how far each line is from the current line. The practicalli/neovim-config sets :relativenames true in fnl/config/init.fnl.

    42l moves 42 charaters to the right

    moving by motions avoids the need to count characters

    "},{"location":"reference/vim-style/moving-around/#moving-around-the-buffer","title":"Moving around the buffer","text":"

    g g to jump to the top of the current buffer

    G to jump to the bottom of the buffer

    z z moves the current line and cursor to the middle of the window

    z t moves the current line and cursor to the top of the window

    z t moves the current line and cursor to the bottom of the window (or as far as the buffer will move in the window)

    "},{"location":"reference/vim-style/narrowing/","title":"Narrowing","text":"

    Narrowing to a region enables vim commands to be applied to a specific part of the current buffer, rather than the whole buffer.

    Common examples include - replacing local variables within a specific function (avoiding affecting other function definitions)

    "},{"location":"reference/vim-style/narrowing/#nrrwrgn-plugin","title":"NrrwRgn plugin","text":"

    [NrrwRgn plugin] is inspired by the Narrowing feature of Emacs and means to focus on a selected region while making the rest inaccessible.

    SPC n r opens a select region in a new split window. The original buffer is protected from changes.

    :w to write changes in the narrowed window to the original buffer

    "},{"location":"reference/vim-style/narrowing/#commands","title":"Commands","text":"

    :NR - Open the selected region in a new narrowed window :NW - Open the current visual window in a new narrowed window :WR - (In the narrowed window) write the changes back to the original buffer. :NRV - Open the narrowed window for the region that was last visually selected. :NUD - (In a unified diff) open the selected diff in 2 Narrowed windows :NRP - Mark a region for a Multi narrowed window :NRM - Create a new Multi narrowed window (after :NRP) - experimental! :NRS - Enable Syncing the buffer content back (default on) :NRN - Disable Syncing the buffer content back :NRL - Reselect the last selected region and open it again in a narrowed window

    Appending ! to most commands opens the narrowed part in the current window instead of a new window.

    :WR! closes the narrowed window in addition to writing to the original buffer.

    "},{"location":"reference/vim-style/narrowing/#documentation","title":"Documentation","text":"

    :help NarrowRegion to view the documetation on the NrrwRgn plug use

    "},{"location":"reference/vim-style/narrowing/#attention","title":"Attention","text":"

    :NRM is described as experimental by the project readme.

    "},{"location":"reference/vim-style/speaking-vim/","title":"Learning to speak Vim","text":"

    Neovim is easier to learn and gain much more benefit from if you learn to speak commands as sentences.

    First learn some verbs:

    • c change
    • d delete
    • g go,
    • v visual select
    • y yank (copy)

    Then use those verbs with some modifiers

    • ' mark
    • { } beginning/end of paragraph
    • 0 start of line
    • ^ first non white-space character of line
    • $ end of line
    • a around
    • f find (includes character)
    • i inside a range (e.g. word, paren,)
    • s surround
    • t till (move just before specified character)

    Then learn the text objects you can apply verbs and modifiers too

    • b block/parentheses
    • p paragraph,
    • s sentence
    • t tag e.g. html/xml
    • w word
    "},{"location":"reference/vim-style/speaking-vim/#examples-of-speaking-vim","title":"Examples of speaking Vim","text":"

    Practice speaking evil with these examples

    Keybinding Description c i s change inside current sentence (change the whole sentence) c i \" change inside double quotes c f ) change from cursor to next ) character c s ' \" change by the surrounding single quotes with double quotes c t X change till the character X (not including X) c /foo change until the first search result of \u2018foo\u2019 d d delete current line D delete current line from cursor onward d i w delete inside the current word (delete word) v t SPC visual select till the next Space character v s ] visually select and surround with [] without spaces v s [ as above with [ ] with spaces between parens and content g v go to last visual selection (select last visual selection) v a p visually select around current paragraph v i w S \" visually select, insert around current word, and surround with quotes y y yank (copy) current line y w yank (copy) current word y @ a yank (copy) to mark a (m a creates a mark called a)"},{"location":"reference/vim-style/vim-quick-reference/","title":"Neovim Quick Reference","text":"

    A reference of the most common keybindings available in Vim Normal mode. Spacemacs DOCUMENTATION key bindings section contains full details

    . repeats the last keybinding sequence used in Vim Normal mode or a change made within a complete Vim Insert session.

    "},{"location":"reference/vim-style/vim-quick-reference/#moving-around","title":"Moving around","text":"

    In Normal mode you can keep your fingers resting on the main row of your keyboard to move around.

    Key action j move cursor down one line k move cursor up one line l move cursor right one character h move cursor left one character

    In menus such as helm you can move around using Ctrl and these keybindings. So C-j will move the cursor down one item in a menu.

    "},{"location":"reference/vim-style/vim-quick-reference/#navigating-the-current-line","title":"Navigating the current line","text":"Key Action f to next character (you specify) t to just before the next character ; repeat f or t search w start of next word W start of next word, white space delimited e end of current word b start of previous word W end of next word, white space delimited * to next matching symbol name $ end of current line 0 start of current line ^ start of non-whitespace % jump to matching parens or next closed paren"},{"location":"reference/vim-style/vim-quick-reference/#navigating-the-current-buffer","title":"Navigating the current buffer","text":"Key action gg start of buffer G end of buffer H move cursor to head of buffer M move cursor to middle of buffer L move cursor to bottom line of buffer C-u jump up half a page C-d jump down half a page } move cursor forward by paragraph or block { move cursor backward by paragraph or block ma mark a line in a file with marker \"a\" `a after moving around, go back to the exact position of marker \"a\" 'a after moving around, go back to line of marker \"a\" :marks view all the marks '' go to the last place you were [{ jump back to the \"{\" at the beginning of the current code block C-o jump back to previous cursor location (evil-jump-backwards) C-i Go to newer position in jump list (opposite of C-o) : 4 go to line 4"},{"location":"reference/vim-style/vim-quick-reference/#text-editing","title":"Text Editing","text":"

    The following commands put you into the Evil Insert state

    Key Action i insert state at cursor I insert state at start of line a append - insert state after cursor A append - insert state at end of line o new line after cursor O new line before cursor"},{"location":"reference/vim-style/vim-quick-reference/#return-to-normal-state","title":"Return to Normal state","text":"

    Regularly switch back to normal state should become common practice. As soon as you finish typing some new text, it should become second nature to go back to normal state.

    ESC or press fd keys in extremely quick succession.

    fd shortcut for Esc

    Using f d together is low risk as if you dont get it right it will either add the characters or try find the next d character (as f moves to the next character). Keep trying this key combination as once in normal state you can use u to undo any f d characters inserted.

    "},{"location":"reference/vim-style/vim-quick-reference/#copy-cut-paste-undo-redo","title":"Copy, cut, paste, undo, redo","text":"

    v in Vim normal mode changes to Visual select mode. Use the navigation keys or any other movement keys to select text to copy or cut.

    Key Action y copy (yank) selection and add to kill ring x delete character at point and add to kill ring X delete character before point and add to kill ring p paste (put) u undo Ctrl-r redo

    Undo tips

    Undo will revert the last action in normal mode or all the changes you made in insert state

    "},{"location":"reference/vim-style/vim-quick-reference/#replace-and-changing-text","title":"Replace and changing text","text":"Key Action r replace the character under cursor R replace multiple characters until ESC cw change word from cursor to end 4 c w change 4 words v (select) c change region v (select) d delete region v i w c change current word v i d delete current word d w delete from cursor to end of word C change from cursor to end of line D , d $ delete from cursor to end of line"},{"location":"reference/vim-style/vim-quick-reference/#delete-commands","title":"Delete commands","text":"Key Action de delete to end of word, not including space dw delete to end of word, including space d$ delete to end of line dd delete the current line 4 d w delete 4 words 4 d $ delete 4 lines to end dt delete to a character (not including character) dab delete a whole block / expression dib delete contents of a block / expression cab change all the block / expression cib change inner block contents / expression yab yank all block / expression yib yank inner block contents / expression"},{"location":"reference/vim-style/vim-quick-reference/#repeat-commands","title":"Repeat commands","text":"Key Action . repeat last command again <number> <cmd> repeat command a number of times

    The . keybinding will repeat the last command in normal mode or the last text edit in insert mode.

    Type a number before a command and that command will run that number of times.

    Inserting a comment border

    Use the number repeat to create a border of 42 ; characters.

    Type 42 to repeat the command 42 times

    Press i for insert mode

    Press ; as the character to repeat insert

    Press ESC or fd to leave insert mode and insert all 42 ; characters

    "},{"location":"reference/vim-style/vim-quick-reference/#transposing-swap","title":"Transposing / swap","text":"Key Description x p transpose the current character with the next character"},{"location":"reference/vim-style/vim-quick-reference/#comments-works-for-all-major-modes","title":"Comments - works for all major modes","text":"

    g c c to comment out the current line

    g c to comment out the currently selected region

    To comment multiple lines you can use the repeat command style, especially useful if you are using relative line numbers.

    g c 3 j will comment the current line and the following two lines below. Comment in reverse using g c 3 k.

    In Visual state, v, select the lines you wish to comment and use g c to comment all the marked lines. Partially marked lines are not commented.

    "},{"location":"reference/vim-style/vim-quick-reference/#managing-files","title":"Managing Files","text":"

    Files in practicalli/neovim-config can be managed with Telescope plugin, although the neovim commands can also be used

    SPC p t toggles a visual file explorer on as a leftmost window, providing a further way to navigate files and directories.

    Key Description SPC f f find existing file (from current local root of neovim) SPC f / copy file - save current buffer with a new file name SPC f b browse files - Esc to run commands SPC f b Esc r change file name of current buffer

    Telescope file browser opens in Insert mode to allow typing filenames, to narrow the results in the Telescope popup.

    "},{"location":"reference/vim-style/vim-quick-reference/#telescope-browser-commands","title":"Telescope browser commands","text":"

    SPC f b opens telescope browser which allows commands to be run over the current file or directory.

    Esc swiches the Telescope popup to normal mode, allowing commands to be used

    • c create file / directory (any missing parts of a path are created)
    • r rename a file / directory
    • R replace

    TAB selects files and directories, allowing for commands (i.e. rename) to be done in batch mode (acting on all selected files / directories)

    "},{"location":"reference/vim-style/vim-quick-reference/#working-with-buffers","title":"Working with Buffers","text":"

    To work with files in Neovim they are loaded into a Buffer.

    Buffers are displayed in a window and you can change the window to show any of the current buffers.

    SPC b displays the buffer menu and the most common commands include:

    Key Command Description SPC b b :Telescope buffers List current buffers SPC b d :bdelete Kill current buffer SPC b n :bnext Switch to next buffer SPC b p :bprevious Switch to previous buffer SPC b a :ball Switch to previous buffer"},{"location":"reference/vim-style/vim-quick-reference/#quit-or-restart-emacs","title":"Quit or Restart Emacs","text":"

    I recommend using the Spacemacs menu from normal mode to quit / restart Spacemacs.

    Key Action SPC q a Quit Neovim (blocked if unsaved change in buffers) SPC q q Quit buffer (blocked if unsaved change in buffers) SPS q Q Force quit of Neovim"},{"location":"reference/vim-style/vim-quick-reference/#external-commands","title":"External commands","text":"

    run external commands using :! followed by a command. For example:

    :!ls - run the ls command

    "},{"location":"reference/vim-style/vim-tips-for-developers/","title":"Vim editing for Clojure developers","text":"

    Vim keybindings that drive Vim editing tools that are common for developers

    "},{"location":"reference/vim-style/vim-tips-for-developers/#comments-and-commenting-code","title":"Comments and Commenting code","text":"
    • g c c comment line
    • g c c comment line
    • v (select) g c comment region
    • g c 9 j comment 9 lines from current, downwards
    "},{"location":"reference/vim-style/vim-tips-for-developers/#simulated-structural-editing-with-surround","title":"Simulated structural editing with surround","text":"Keybinding Description v s ] surround with [characters] without spaces v s [ surround with [ characters ] without spaces c s ( [ change surrounding from ( to [ c i ( change in ( c a ( change \u201caround\u201d ( % jump forwards to next paren, further % toggles between open and close parens. x p transpose characters (cut current, paste after)"},{"location":"reference/vim-style/vim-tips-for-developers/#moving-around-quickly","title":"Moving around quickly","text":"

    f to jump forward to a given character on the current line. F to jump backwards.

    zt, zz, and zb to pull the current line to the top/middle/bottom of the screen.

    [number] G jump to line number or :22 to jump to line 22

    :7j to jump 7 lines down

    gf jump to file name under the cursor - try this in the summary.md file

    "},{"location":"reference/vim-style/vim-tips-for-developers/#selection-find-and-replace","title":"Selection, find and replace","text":"

    viw to visual-select in (within) the current word

    "},{"location":"reference/vim-style/vim-tips-for-developers/#source-code-and-configuration-files","title":"Source code and configuration files","text":"

    g Dopen definition in another window

    = (code-aware indenting) operator. Nice with the ap (a paragraph) text object.

    C-] Jump to definition of keyword under the cursor

    "},{"location":"reference/vim-style/vim-tips-for-developers/#code-folding","title":"code folding","text":"

    zc and zo are useful to close and open folds, which can be a nice way of focusing on certain pieces of code.

    "},{"location":"reference/vim-style/vim-tips-for-developers/#transposing-characters-and-sections","title":"Transposing characters and sections","text":"

    x p simple transpose of the current and next character

    M-t transpose words before and after cursor position

    {, } motions jump to next and previous empty lines. This motion makes it simple to rearrange paragraphs

    { d } will kill the paragraph (or multiple paragraphs)

    { will jump to the start of the previous paragraph

    p pastes the killed paragraph before the current paragraph

    > and < (indent and dedent) operators, useful with the aforementioned }/{ motions.

    / ## multi-replace with iedit and narrowing /

    "},{"location":"reference/vim-style/visual-select/","title":"Visual Select","text":"

    Select characters, words, lines and regions with visual select. The background changes color to visually indicate which text is selected

    v enters visual select mode and can be with objects such as word w and locations such as end of line $.

    o to expand from left side of selection and O to expand from the right side of a selection, using the hjkl navigation keys

    "},{"location":"reference/vim-style/visual-select/#visual-line-selection","title":"Visual Line selection","text":"

    V to select by lines, using j and k.

    "},{"location":"reference/vim-style/z-menu/","title":"Evil Z menu","text":"

    z in normal mode opens a menu of convenient utilities

    "},{"location":"reference/vim-style/z-menu/#folding-code-comments-and-other-content","title":"Folding code, comments and other content","text":"

    Code folding is very useful for hiding different levels of detail, for example you could hide everything but the function names in a namespace, showing just the API for that namespace.

    Comments and documentation can be folded to help you focus on a specific part of the content.

    Key Description z a toggle fold of code, comment, section, etc. z A toggle all folds z c close fold z f create fold z M close all folds z o open fold z O open fold recursive (capital o) z r fewer folds z R open all folds z x update folds

    See narrowing for a focused approach to editing.

    "},{"location":"reference/vim-style/z-menu/#scrolling","title":"Scrolling","text":"

    Jump the current line to the center, top or bottom of the buffer.

    Key Description z b scroll the current line to bottom of buffer z t scroll the current line to top of buffer z z scroll the current line to center of buffer"},{"location":"reference/vim-style/z-menu/#spelling","title":"Spelling","text":"

    z = with the cursor on a word shows a list of possible spelling and similar words.

    Select a word using its number in tye list to repace the word under the cursor, or q to quit the spelling list.

    Key Description z = spelling suggestions z g add word to spelling list z w mark word as misspelled"},{"location":"repl-driven-development/","title":"REPL Driven Development with Clojure","text":"

    Conjure provides the REPL driven development workflow for Clojure (and many other fun languages) and includes a built-in tutorial.

    • Vim style Editing
    • Starting a REPL & Evaluating code - using Conjure
    • Structural Editing - parinfer or paredit
    • Refactor tools - Language Server Protocol features
    • Unit Testing - run REPL or external test runners
    • Inspecting data, e.g. Portal

    Practicalli Clojure CLI Config

    Practicalli Clojure CLI config contains aliases used extensively through the Clojure sections of this book

    Practicalli Neovim config replaces some key bindings

    practicalli/neovim-config-redux replaces several key bindings to make them consistent with other Clojure editors

    "},{"location":"repl-driven-development/#references","title":"References","text":"
    • Which Clojure CLI execution option - M T X P - should be used
    • Make task to simplify Clojure development
    "},{"location":"repl-driven-development/conjure/","title":"Conjure","text":"

    Conjure is the Clojure REPL client for Neovim. Code in source code buffers can be evaluated and show the results in-line, providing instant feedback on the behaviour of the code as it develops.

    Conjure School interative tutorial

    :ConjureSchool runs an interactive tutorial in Neovim, walking through the essential Conjure commands and key bindings. Use the commands provided to move through the guide or j / k to scroll through the guide content.

    "},{"location":"repl-driven-development/conjure/#start-repl","title":"Start REPL","text":"

    Start a REPL on the command line in the root of a Clojure project. The REPL should also start an nREPL server for Conjure to connect too.

    Conjure will detect an nREPL server (via .nrepl-port file) when a Clojure file is opended (.clj .edn .cljs .cljc) and connect to the REPL process via that nREPL server.

    Practicalli Clojure CLI ConfigManual Alias definition

    Practicalli Clojure CLI config contains aliases to start a REPL process that also start an nREPL server.

    Use repl make task for projects created by Practicalli Project templates

    make repl\n

    Or use the Clojure CLI command with the :repl/rebel alias directly

    clojure -M:repl/rebel\n
    Simplify the command line

    Add a Makefile to define common tasks to simplify and add consistency to working with Clojure across projects or shell script to simplify the commands used to call clojure to run common tasks

    repl:  ## Run Clojure REPL with rich terminal UI (Rebel Readline)\n    $(info --------- Run Rebel REPL ---------)\n    clojure -M:env/dev:env/test:repl/rebel\n\n\nrepl-reloaded:  ## Run Clojure REPL with hotload, reload and rich terminal UI (Rebel Readline)\n    $(info --------- Run Rebel REPL ---------)\n    clojure -M:env/dev:env/test:lib/reloaded:repl/rebel\n

    A Makefile can also include supporting commands, such as lint and format tools.

    # Run MegaLinter with custom configuration\nlint:\n    $(info --------- MegaLinter Runner ---------)\n    mega-linter-runner --flavor java --env 'MEGALINTER_CONFIG=.github/linters/mega-linter.yml'\n

    practicalli/dotfiles/Makefile contains tasks for Clojure development, including running a REPL, preparing dependencies, building an uberjar, lint & format Clojure and configuration files.

    Docker related tasks to build, run and compose common images and containers are also included.

    Add aliases to the user configuration for Clojure, e.g. XDG_HOME_CONFIG/clojure/deps.edn or HOME/.clojure/deps.edn

      ;; Interactive client REPL with nREPL server for Clojure Editor support\n  :repl/basic\n  {:extra-deps {nrepl/nrepl       {:mvn/version \"1.0.0\"}\n                cider/cider-nrepl {:mvn/version \"0.40.0\"}}\n   :main-opts  [\"--main\" \"nrepl.cmdline\"\n                \"--middleware\" \"[cider.nrepl/cider-middleware]\"\n                \"--interactive\"]}\n\n  ;; Headless REPL with nREPL server for Clojure Editor support\n  :repl/headless\n  {:extra-deps {nrepl/nrepl       {:mvn/version \"1.0.0\"}\n                cider/cider-nrepl {:mvn/version \"0.40.0\"}}\n   :main-opts  [\"--main\" \"nrepl.cmdline\"\n                \"--middleware\" \"[cider.nrepl/cider-middleware]\"]}\n

    clojure -M:repl/basic starts a REPL with nREPL with a minimal REPL UI

    clojure -M:repl/headless starts a REPL with nREPL server but without a REPL prompt (to prevent accidental interaction via the command line)

    Practicalli Clojure CLI Config aliases

    Practicalli Clojure CLI config defines aliases for a wide range of community tools and libraries that extend the features of Clojure CLI

    "},{"location":"repl-driven-development/conjure/#evaluation","title":"Evaluation","text":"

    Clojure REPL workflow encourages code expressions to be evaluated as the are written, providing instant feedback to ensure expected results are returned (or learn the kind of results a function returns).

    Results of evaluating an expression are shown in-line. Open the REPL log to see larger results and a complete REPL history for the current session.

    ,eb - evaluate current buffer - used after first starting the REPL to load in a whole namespace and any required namespaces. Use to ensure all changes have been evaluated in the REPL (except those within a (comment ) form or otherwise commented)

    ,er - evaluate top-level expression (root), ignoring a surrounding (comment ) form to support the rich comments approach

    ,ee - evaluate expression (from start of current form) - especially useful for nested forms

    ,ei - interrupt evaluation (stop long running evaluations) - stop a long running evaluation

    ,ew - evaluate word (symbol) - inspect value of form - i.e. for def names

    ,e! - replace form with its result - helps understand a more complex function by replacing code with a specific value

    ,emf - evaluate marked form - mark forms regularly re-evaluted with mf (or any character with m) to avoid jumping to that form each time . A capital letter to mark form in a different namespace and evaluate from the current buffer.

    \"cp - paste contents of the register into buffer. The result of every evaluation is stored in a Neovim register as well as the log.

    "},{"location":"repl-driven-development/conjure/#repl-log","title":"REPL log","text":"

    The Conjure REPL log shows the results of every evaluation for the current session.

    ,lt opens log in a new tab page (tab), ,ls in horizontal split, ,lv in vertical tab

    ,lq - close log window / tab page

    ,lr - soft REPL reset, leave window open

    ,lR - hard REPL reset, close window & delete buffer

    Inline evaluation over HUD log popup

    Practicalli Neovim configurations hide the HUD log popup that is otherwise shown when Conjure connects to the REPL process, i.e. vim.g[\"conjure#log#hud#enabled\"] = false

    In-line evaluation results are the main feedback approach used by Practicalli when evaluating code.

    Practicalli recommends using the REPL log when larger results are returned

    Portal data inspector can be sent evaluation history and provides rich visualisation and navigation tools to explore that history in detail.

    "},{"location":"repl-driven-development/conjure/#rich-comments","title":"Rich comments","text":"

    Rich comments are a useful way to contain experimental expressions, or expresisons only evaluated directly by a person developing the code (e.g. starting / stoping services, testing api calls, etc.)

    Expressions in rich comments are not included when evaluating the buffer or when expressions are evaluated via a namespace require.

    ,er to evaluate the top level form within the rich comment, without evaluating the comment expression itself.

    Start REPL from Neovim

    Practicalli Configurations require the vim-jack-in plugin to be added before this approach will work.

    Start Neovim with a Clojure file, e.g. nvim src/practialli/playground.clj or run nvim and open a Clojure file, e.g. *.clj, *.cljc, *.cljs or .edn.

    • :Clj command to start a REPL using Clojure CLI Tools
    • :Lein command to start a REPL using Leiningen

    Neovim switches to a terminal state, use C-\\ C-n to leave the terminal state. Use :N or :previous to switch back to the source code buffer

    , c f to connect to the REPL from Conjure, or simply open a Clojure file. Automated connection will be added in a future version on Conjure.

    The vim-jack-in plugin enables Neovim to call out to Clojure tools or Leiningen to start a REPL and connect to it once its started.

    A full screen REPL log is displayed. , l q to close the log window and return to the Clojure file. , l v to create a vertical split between code and REPL log, , l s for a horizontal split.

    "},{"location":"repl-driven-development/refactor-tools/","title":"Refactor tools","text":"

    Neovim and common plugins provide many text oriented tools useful for refactoring code.

    Clojure LSP server and Neovim LSP client support use static analysis of the project source code to allow provide common code refactor tools.

    "},{"location":"repl-driven-development/refactor-tools/#language-server-protocol-lsp","title":"Language Server Protocol (LSP)","text":"

    Using clojure-lsp server and Neovim Treesitter as an LSP client, code is statically analysed to provide auto-completion data, advanced editing actions such as refactor, live formatting, etc.

    Function help

    SPC l h or K displays help for the function under the cursor

    Repeat the key binding to move the cursor to the documentation popup window and use j k to scroll the documentation

    "},{"location":"repl-driven-development/refactor-tools/#key-maps","title":"Key maps","text":"Practicalli AstroNvim ConfigPracticalli Neovim Config Redux
    • <leader>la code actions (popup with available actions)
    • <leader>ld hover diagnostics
    • <leader>lD search diagnostics
    • <leader>lf format buffer
    • <leader>lG search workspace symbols
    • <leader>lh function signature help
    • <leader>li information about the LSP client and running LSP servers
    • <leader>lI null-ls information (format & lint tools)
    • <leader>ll code lens refresh
    • <leader>lL code lens run
    • <leader>lr rename current symbol (namespace rename not supported it seems)
    • <leader>lR search references
    • <leader>ls search symbols
    • <leader>lS symbols outline
    • gd Go to definition
    • K Show documentations
    • <leader>ld Function declarations
    • <leader>lt Type Definitions
    • <leader>lh Signature Help
    • <leader>ln Rename
    • <leader>le Show line diagnostics
    • <leader>lq Show all diagnostics information
    • <leader>lf Auto format
    • <leader>lj Go to next diagnostic
    • <leader>lk Go to previous diagnostic
    • <leader>la Open code actions menu (Using telescope plugin interface)
    • <leader>la Open code actions menu for the selected text in VISUAL mode (Using telescope plugin interface)
    • <leader>lw Open workspace diagnostics list (Using telescope plugin interface)
    • <leader>lr Show all references list for item under the cursor (Using telescope plugin interface)
    • <leader>lr Show all implementations list for item under the cursor (Using telescope plugin interface)
    "},{"location":"repl-driven-development/refactor-tools/#limitations-to-investigate","title":"Limitations to investigate","text":"
    • Neovim client does not seem to support namespace rename (AstroNvim)
    "},{"location":"repl-driven-development/structural-editing/","title":"Structural Editing","text":"

    Structural editing seeks to ensure that parenthesis (parens) and other pairs of characters remain balanced, i.e. an open paren is not removed without removing the closing paren.

    • parinfer uses an indent approach, aligning code manages parens locations
    • paredit uses a structural approach
    AstroNvim Community Clojure Pack includes parinfer

    nvim-parinfer plugin is included in the AstroNvim Community Clojure pack

      { import = \"astrocommunity.pack.clojure\" },\n
    "},{"location":"repl-driven-development/structural-editing/#parinfer","title":"Parinfer","text":"

    Parinfer works very well with vim-style modal editing.

    The author of the code focuses on aligning code and parinfer takes care of balancing the parens.

    To include new lines of code within an expression, create a new line o and indent.

    Parinfer will move the preceeding closing paren(s) to the new line, enclosing the new code in the overall expression.

    Parinfer website

    "},{"location":"repl-driven-development/testing/","title":"Unit tests and test runners","text":"

    Run unit tests from within Neovim, showing a summary of test results or a full test report (especially if there are failures)

    Or run and external test runner via a terminal session, optionally using watch mode to re-run tests on every saved change.

    Practicalli sets Kaocha test runner as default

    practicalli/neovim-config-redux sets Kaocha as the default test runner

    Kaocha test runner set in Astrocommunity Clojure language pack

    Astrocommunity Clojure language pack
    {\n  \"Olical/conjure\",\n  -- load plugin on filetypes\n  ft = { \"clojure\" },\n  init = function()\n    vim.g[\"conjure#log#hud#width\"] = 1\n    vim.g[\"conjure#log#hud#enabled\"] = false\n    vim.g[\"conjure#log#hud#anchor\"] = \"SE\"\n    vim.g[\"conjure#log#botright\"] = true\n    vim.g[\"conjure#extract#context_header_lines\"] = 100\n    vim.g[\"conjure#eval#comment_prefix\"] = \";; \"\n    vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false\n    vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true\n    vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil\n    vim.g[\"conjure#client#clojure#nrepl#eval#auto_require\"] = false\n    vim.g[\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\"\n\n    vim.api.nvim_create_autocmd(\"BufNewFile\", {\n      group = vim.api.nvim_create_augroup(\"conjure_log_disable_lsp\", { clear = true }),\n      pattern = { \"conjure-log-*\" },\n      callback = function() vim.diagnostic.disable(0) end,\n      desc = \"Conjure Log disable LSP diagnostics\",\n    })\n
    "},{"location":"repl-driven-development/testing/#include-test-path","title":"Include test path","text":"

    Ensure the test directory is included in the classpath when starting a REPL. Use a project or user level alias which defines an :extra-paths key with the [\"test\"] path

    clojure -M:test/env:repl/reloaded\n
    "},{"location":"repl-driven-development/testing/#conjure-test-runners","title":"Conjure Test runners","text":"

    , t n to run the tests for the current namespace

    , t a to run all tests in the project

    "},{"location":"repl-driven-development/testing/#external-test-runner","title":"External test runner","text":"

    Open a terminal in Neovim or a separate terminal session to run start a test runner in watch mode. Tests run automatically when the code changes are saved

    Practicalli Clojure CLI Config

    Practicalli Clojure CLI config contains aliases for test runner tools

    • :test/run uses Kaocha to run all tests, stopping on first failing test. Add :fail-fast? false argument to run all tests regardless of failure

    • :test/watch as above and puts Kaocha in watch mode, triggering a test run each time a file is saved

    Projects created with Practicalli Project Templates include a test and test-watch task to run Kaocha test runner

    Run all tests, stoping on first failing test

    make test\n

    Watch for changes and run all tests, stoping on first failing test

    make test-watch\n

    The make tasks call Clojure CLI with the appropriate alias, e.g. clojure -X:test/run and clojure -X:test/watch

    "},{"location":"repl-driven-development/testing/#test-selectors","title":"Test Selectors","text":"

    Use Test selectors to run a sub-set of tests based on selector meta data added to deftest code

    (deftest ^:infrastructure function-name-test\n  (testing \"\"\n    (is ,,,))\n\n(deftest ^:persistence function-name-test\n  (testing \"\"\n    (is ,,,))\n
    Kaocha test runnerCognitect Labs Test Runner

    Kaocha test runner can focus or skip on a sub-set of unit tests using test id, metadata, namespaces or a specific deftest.

    • :focus or :skip a given namespace or specific test var, i.e. deftest
    • :focus-meta or :skip-meta test selectors (metadata) on test vars, i.e. ^:persistence

    Specifying test :id in the tests.edn configuration file allows different test suites to be run, e.g. :unit for unit tests, :spec for specification tests

    Focus and skip works with a single test run or with a continuous watcher.

    Skip all tests with :persistence metadata

    clojure -X:test/watch :skip-meta :persistence\n

    Focus on a specific test namespace

    clojure -X:test/watch :focus '[\"practicalli.gameboard.api.scoreboard-test\"]\n

    Focus on a specific unit test (deftest)

    clojure -X:test/watch :focus '[\"practicalli.gameboard.api.scoreboard-test/total-score-test\"]\n

    Refine the tests that are watched

    Start the watcher with focused or skiped tests by name or meta data (test selectors)

    Cognitect Labs Test Runner can include or exclude a sub-set of tests, identified by metadata on the var (deftest)

    Cognitect Labs Test Runner - inclusions & exclusions

    "},{"location":"termux/","title":"NeoVim on Termux","text":"

    A smart phone or tablet and an external keyboard can make an excellent ultra-portable development environment, especially when travelling with limited space or restricted weight constraints.

    Termux can be installed using the F-Droid marketplace, as with installing any other Android app.

    Do not install Termux App from the Google Play store

    The Termux App in Google Play store is significantly out of date and will not work properly and probably not at all

    "},{"location":"termux/#keyboard","title":"Keyboard","text":"

    Atreus from Keyboardio is an excellent travel keyboard and was used to write most of the Practicalli Neovim configuration and Neovim book (especially during delays at airports)

    Model 100 from Keyboardio is used by Practicalli at the office

    "},{"location":"termux/#running-termux","title":"Running Termux","text":"

    Run Termux from the app launcher added as an android app by the F-Droid install.

    A help menu will show the basic command needed to work with packages.

    Software keys for Termux specific controls are shown. Keys can be toggled with the Volume Up + q key combination.

    Termux may not display in fullscreen when Android productivity mode, usually activated on tablets when physical keyboard or mouse is attached. Disabling productivity mode in the Android settings is recommended.

    "},{"location":"termux/clojure-development/","title":"Clojure development environment","text":"

    A comprehensive development environment for Clojure, supporting a REPL workflow and static analysis of code via Clojure Language Server Protocol.

    "},{"location":"termux/clojure-development/#java-host-platform","title":"Java host platform","text":"

    Install OpenJDK to host the Clojure REPL process and run packaged Clojure applications.

    Java 17 Long Term Support version is recommended as it is very stable, receives security updates and has the latest highly tested performance improvements.

    pkg install openjdk-17\n
    "},{"location":"termux/clojure-development/#install-clojure","title":"Install Clojure","text":"

    Clone practicalli/clojure-deps-edn to add a wide range of community tools to the Clojure CLI

    git clone git@github.com:practicalli/clojure-deps-edn.git ~/.config/clojure\n

    Use the Linux install with a prefix path pointing to Termux equivalent of /usr/local. Find the path using echo $PATH and remove bin from the end. Without the prefix Clojure will not install correctly

    curl -O https://download.clojure.org/install/linux-install-1.11.1.1149.sh\n\nchmod +x linux-install-1.11.1.1149.sh\n\n./linux-install-1.11.1.1149.sh --prefix /data/data/com.termux/files/usr/\n

    clojure binary is installed in the existing bin, lib and share directories in /data/..../usr/, placing that binary on the system execution path.

    Test by running a REPL session, for example with Rebel Readline

    clojure -M:repl/rebel\n

    optionally install rlwrap package if using the basic repl terminal UI

    "},{"location":"termux/clojure-development/#install-clojure-lsp","title":"Install Clojure LSP","text":"

    Visit clojure-lsp GitHub releases page and download the clojure-lsp file

    • visit the relases page in firefox and copy the link to the file.
    • use wget and paste the link to the file to download
    • make executable chmod 755 clojure-lsp
    • test locally ./clojure-lsp --version - should print clojure-lsp version and clj-kondo version
    • copy or move file to path mv clojure-lsp $PATH

    If the practicalli/clojure-lsp-config repository was cloned, move or link the clojure-lsp directory to ~/.config/clojure-lsp

    "},{"location":"termux/custom-shell/","title":"Customise shell","text":"

    Customising the shell is optional, although gives an enhanced experience.

    Zsh provides the richest command line experience, providing many advanced features over bash. Oh My Zsh is a community configuration that provides a simple way to configure Zsh features and also supports powerline10k terminal theme, providing context specific information and a more engaging visual experience.

    Oh My Zsh community configuration enhances the Zsh experience. Practicalli normally uses Prezto community configuration, unfortunately this did not work well on Termux.

    "},{"location":"termux/custom-shell/#install-zsh","title":"Install Zsh","text":"

    Install the zsh package using the Termux package manager

    pkg install zsh\n

    Start zsh, which will show a % character as the prompt

    zsh\n

    Set the shell to run zsh by default

    chsh -s zsh\n
    "},{"location":"termux/custom-shell/#install-oh-my-zsh","title":"Install Oh My Zsh","text":"

    Install Oh My Zsh via curl (or wget if preferred) in the .oh-my-zsh/ directory

    sh -c \"$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"\n
    "},{"location":"termux/custom-shell/#install-powerline10k","title":"Install Powerline10k","text":"

    Powerline10k is a visually appealing prompt with a setup script to visually choose the presentation of the prompt.

    git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k\n

    Edit ~/.zshrc and set the theme to ZSH_THEME=\"powerlevel10k/powerlevel10k\"

    nano ~/.zshrc\n

    Save the changes exit termux.

    Next time zsh is run, powerline10k setup script will run. If Meslo is not set as the terminal font, the setup script offers to install the font. Installing the font will restart Termux (without prompting for a restart).

    The powerline10k setup script provides a wizard to configure each part of the prompt.

    p10k configure command will manually run the powerline10k setup script.

    Prezto Zsh community configuration

    NOTE: previous attempts to use Prezto proved to have issues

    Clone prezto and its sub-modules into XDG_CONFIG_HOME/zsh which is typically ~/.config/zsh

    git clone --recursive https://github.com/sorin-ionescu/prezto.git \"${ZDOTDIR:-${XDG_CONFIG_HOME:-$HOME/.config}/zsh}/.zprezto\"\n

    Set the location of the Zsh configuration home with $ZDOTDIR, relative to the XDG locations

    export ZDOTDIR=\"${ZDOTDIR:=$XDG_CONFIG_HOME/zsh}\"\n

    Create a new Zsh configuration by copying/linking the Zsh configuration files provided:

    setopt EXTENDED_GLOB\nfor rcfile in \"${ZDOTDIR:-$HOME}\"/.zprezto/runcoms/^README.md(.N); do\n  ln -s \"$rcfile\" \"${ZDOTDIR:-$HOME}/.${rcfile:t}\"\ndone\n

    Practicalli Zsh configuration

    Clone practicalli/dotfiles and replace the symbolic links in $XDG_CONFIG_HOME/zsh with links to the respective Zsh configuration files in the cloned repository (or copy the files if you prefer)

    Copy or create a symbolic like for the .p10k configuration or skip this to create your own configuration when next startingzsh.

    Edit $XDG_CONFIG_HOME/.config/zsh/.zshenv and add the following lines to enable zsh to find the prezto configuration

    export XDG_CONFIG_HOME=\"${XDG_CONFIG_HOME:=$HOME/.config}\"\nexport ZDOTDIR=\"${ZDOTDIR:=$XDG_CONFIG_HOME/zsh}\"\n

    Create a symbolic link from $HOME/.zshenv to $XDG_CONFIG_HOME/.config/zsh/.zshenv (or to the .zshenv file from practicalli/dotfiles)

    ln -s $XDG_CONFIG_HOME/.config/zsh/.zshenv $HOME/.zshenv\n

    Check the configuration is working by loading the .zshenv configuration

    source \"$ZDOTDIR/.zshenv\"\n

    Using Oh My Bash

    If preferring Bash, then ohmybash provides a nice command line experience, showing completions clearer, nice themes that provide information.

    "},{"location":"termux/fdroid-install/","title":"Install Termux via the F-Droid App","text":"

    Visit the FDroid app website and download F-Droid, which saves an F-Droid.apk file. Android may display a security prompt stating the browser does not have permissions to install software. The popup should include a configure link that opens the Android settings to allow the browser to install software.

    F-Droid should now be installed and its icon added to the Android system alongside all other Android apps.

    Open the F-Droid App and allow it to update its repositories, to ensure the latest list of apps are shown.

    Search for the Termux application, clicking on the Termux name if more details are required.

    Select the Install button.

    When installing apps from F-Droid for the first time, a security prompt is show as F-Droid is an unknown source.

    Select Settings to open the Android settings and enable Allow from this source for the F-Droid app.

    A Termux App launcher will be added to the Android screen. Consider adding the Termux icon to the commonly used icons bar.

    "},{"location":"termux/fdroid-install/#termux-styling","title":"Termux Styling","text":"

    Styling is a Termux plugin that provides a visually richer experience. Styling contains beautiful color schemes and powerline-reaqdy fonts to customise the appearance of the terminal

    Install the package via F-Droid

    The styling menu is accessed via a long press on the Termux app screen, showing a More > Style option on the usual cut/copy/paste popup menu. Practicalli recommends FiraCode fonts.

    "},{"location":"termux/git/","title":"Git version control","text":"

    A Git client is used to version control projects and to clone projects and configuration from GitHub/GitLab. Practicalli maintains several editor configurations in shared repositories on GitHub

    • Install a Git Client (and optionally GitHub CLI)
    • [optionally] clone the practicalli/dotfiles repository for the Git config and global ignores
    • Configure an SSH key to access remote repositories (or Developer token if you cannot use SSH keys)
    "},{"location":"termux/git/#install-a-git-client-and-github-cli","title":"Install a git client and GitHub CLI","text":"
    pkg install git gh\n

    Clone the practicalli/dotfiles repository

    git clone https://github.com/practicalli/dotfiles projects/dotfiles\n

    Move or symbolically link the top-level directories to ~/.config, e.g. for the Git configuration:

    ln -s projects/dotfiles/git ~/.config/git\n

    Edit the .config/git/config and update the core.user, core.name and github or gitlab identities

    "},{"location":"termux/git/#create-ssh-key-for-remote-repository-access","title":"Create SSH Key for remote repository access","text":"

    Install the openssh package which contains the ssh-keygen command to generate a new public/private key combinations for use with GitHub SSH repository URLs

    pkg install openssh\n

    Generate a key using the email address of the GitHub or GitLab account

    ssh-keygen -t rsa -C name@domain.tld\n

    RET to confirm storing the keys in the default location.

    Usually a passphrase is recommended, however, termux does not seem to save a keyring to save the key passphrase using ssh-add. So the passphrase must be entered each time the key is used, unless a blank passphrase is used.

    Vist your GitHub account settings and create a new SSH key

    Use cat ~/.ssh/id_rsa.pub to show the public key contents. Press the screen to select and copy the public key to the clipboard.

    Paste the public key into the GitHub new key form.

    "},{"location":"termux/git/#optional-create-a-developer-token","title":"[optional] Create a developer token","text":"

    A developer token (or ssh key) is required to access GitHub {and far more secure over password}

    Should the android device become lost or compromised, the developer token can be deleted to protect the repositories from any malicious access. The developer token should be limited to the minimal access. The developer token does not give access to the GitHub or GitLab account.

    HTTPS URLs should be used with a developer token. git@git.com URLs are for SSH keys only.

    Visit GitHub / GitLab settings for your account

    Create a new developer token specifically for Termux

    Add a descriptive name for the token, based on the device Termuxc is runniung on, e.g. Termux Pixel2XL

    Check the public_repo and status repo scopes

    Generate button creates a new token.

    Copy the token using the copy icon.

    Edit the .config/git/config file and add a github section with the GitHub account name and token

    [github]\n    name = practicalli\n    token = ghp_************************************\n

    Consider using GitHub CLI to cache the developer token rather than write the token to the Git configuration file for greater security.

    "},{"location":"termux/neovim/","title":"Install neovim","text":"

    Neovim version 8 availabe as current package

    pkg install neovim\n
    "},{"location":"termux/neovim/#neovim-treesitter","title":"Neovim treesitter","text":"

    Treesitter provides excellent language syntax parsing and highlighting and is a very attractive feature of the recent neovim releases. Treesitter is a major attraction, bringing in a new audience for Neovim.

    The nvim-treesitter package is included in the practicalli/neovim-config-redux configuration.

    "},{"location":"termux/neovim/#c-compiler","title":"C Compiler","text":"

    Install C compiler for neovim-treesitter, to compile a parser for each specific programming language.

    pkg install clang\n

    gcc is not packaged for Termux, although there are guides to install gcc if preferred. clang has proved to be capable of creating the parsers used in the Practicalli configuration.

    "},{"location":"termux/neovim/#searching-files","title":"Searching files","text":"

    Telescope and other packages that involve searching for files recommend using ripgrep, a highly optomised tool for finding files on the operating system.

    pkg install ripgrep\n
    "},{"location":"termux/neovim/#optional-nodejs","title":"[optional] nodejs","text":"

    Optional. Only if node.js is required as a Neovim provider and JavaScript or ClojureScript development is to be done.

    pkg install nodejs\n
    "},{"location":"termux/setup/","title":"Termux Setup","text":"

    Launch Termux via its application icon. A black terminal screen will appear with a bash shell prompt.

    "},{"location":"termux/setup/#update-packages","title":"Update packages","text":"

    Check for new packages and update them all

    pkg upgrade -y\n

    If you wish to first check the packages that will be updated, use pkg --list-upgradable

    Select a specific region to minimise the number of mirrors checked during package upgrades, especially useful if on a limited data plan.

    termux-change-repo\n

    At time of writing, the Termux package on F-Droid was around 6 months old so there will be a number of packages that should be updated before any further installation steps are undertaken.

    "},{"location":"termux/setup/#configure-freedesktoporg-xdg-locations","title":"Configure Freedesktop.org XDG locations","text":"

    Edit the ~/.profile file, adding export directives to set the XDG locations:

    nano ~/.profile\n
    XDG locations
    # Common Free desktop.org locations\nexport XDG_CONFIG_HOME=$HOME/.config\nexport XDG_DATA_HOME=$HOME/.local/share\nexport XDG_STATE_HOME=$HOME/.local/state\nexport XDG_CACHE_HOME=$HOME/.cache\n\n# Set XDG location of Emacs Spacemacs configuration\nexport SPACEMACSDIR=\"$XDG_CONFIG_HOME/spacemacs\"\n

    Load the environment variables into the shell, or exit Termux and restart.

    Load .profile into shell
    source ~/.profile\n

    nano editor installed by default

    nano editor is used to edit the commands as the package is installed by default in termux. vim, neovim, emacs or any other Linux command line editor can be used if the package is first installed. Termux will list packages to install when trying to run a command that is from a package not yet installed.

    "},{"location":"termux/setup/#tools-to-download-binaries-and-configuration","title":"Tools to download binaries and configuration","text":"

    Many tools can be installed via the pkg tool, although specific Clojure tools and configuration require additional tools:

    • wget and curl - download tools not packaged, i.e. clojure-lsp binary
    • git - clone configuration files and projects (see Git version control section)
    • openssh - SSH service and tools to generate SSH keys
    pkg install curl wget git openssh\n

    Configure a Git Identify and SSH key to before committing and pushing changes, or cloning repositories using the SSH protocol. practicalli/dotfiles contains example configuration, ignore patterns and commit template for using Git.

    "},{"location":"termux/setup/#optional-configure-termux-settings","title":"[Optional] Configure Termux Settings","text":"

    Edit ~/.termux/termux.properties to configure the default settings for termux.

    nano ~/.termux/termux.properties\n

    Load termux.properties if values are changed (restarting Termux is not enough to load setting changes)

    termux-reload-settings\n

    The defaults are suitable for the majority of uses, although you may wish to consider:

    • fullscreen set to true to us the whole screen, hiding Android menu bars, etc.
    • hide-soft-keyboard-on-startup set to true if always using a physical keyboard
    • default-working-directory to save files user files and directories in an alternative location,

    If swiping from left edge of the screen is already taken, set key bindings for creating a new termux session, naming a session and switching between sessions. Alternatively, use byobu to create and switch between its tabs for multiple terminal sessions.

    "},{"location":"termux/setup/#set-color-scheme-and-font","title":"Set Color Scheme and Font","text":"

    The Termux:Styling plug provides menus for selecting terminal color scheme and font to use

    Press and hold on the Termux screen to show the context menu and select the Style menu. On smaller screens select More > Style

    If Termux:Styling plugin was not installed, a prompt will display asking if the plugin should be installed

    A menu appears with Choose Color and Choose Font

    Select Choose Color to select from the available list of colour schemes, e.g. Gruvbox Dark or Gruvbox Light

    ~/.termux/colors.properties file is added when selecting a colour scheme, defining Hex colors from the theme selected.

    Select Choose Font to select from the available fonts, e.g. FiraCode or Ubuntu

    ~/.termux/font.ttf font file is added when selecting a font.

    Termux:Styling uses NerdFonts for icons

    All fonts installed via Termux:Styling have been patched with NerdFonts, providing several thousand icons to use within the terminal prompt and Neovim itself (e.g. VimDevIcons).

    "},{"location":"termux/using-termux/","title":"Using Termux","text":"

    Start Termux app and a terminal prompt is shown, along with the standard Android software keyboard. An extended keyboard is provided with common key bindings for the command line interface (Tab, Esc, Ctrl, arrow keys, etc.).

    "},{"location":"termux/using-termux/#keyboards","title":"Keyboards","text":"

    Termux provides an extended keyboard with key combinations not possible with the Android software keyboard, i.e Ctrl-c, arrow keys, etc. TAB is especially useful for driving command and filename completion.

    Volume Up + q toggles the extended keyboard, so more screen is available when using a hardware keyboard.

    Connect a hardware keyboard for the best experience, e.g the Keyboard.io atreus is an excellent and highly portable mechanical keyboard. The software keyboard is automatically switched off when a hardware keyboard is connected, although the extended keyboard is still displayed by default.

    "},{"location":"termux/using-termux/#adjusting-font-size","title":"Adjusting Font size","text":"

    Pinch the screen inwards to zoom out making the text font smaller.

    Pinch the screen outwards to zoom in making the text font larger.

    "},{"location":"termux/using-termux/#termux-menus","title":"Termux menus","text":"

    Termux has three menus: A context menu, navigation drawer and Termux section of the Android notification.

    The context menu is shown by a long press anywhere on the terminal screen:

    • Select and Paste text to share text with other applications
    • Reset the terminal if it gets stuck or Hangup to exit the current terminal session
    • Style the terminal by selecting a font and a color scheme

    The navigation drawer is shown by swiping inwards from the left of the screen

    • list and select terminal sessions, set a name for a session with a long press
    • A button to toggle visibility of the touch keyboard.
    • A button to create new terminal sessions (long press for creating a named session or a fail-safe one).

    If gesture navigation is enabled in Android, hold the edge of the screen briefly before swiping to bring up the navigation drawer

    The Android notification menu contains a Termux section. Press the Termux section to show the current terminal session or expand the Termux section to exiting all running terminal sessions or aquire a wake lock to avoid Termux entering sleep mode. A wake lock allows server and other background processes to run reliably and to continue to receive notifications

    "},{"location":"termux/using-termux/#package-management","title":"Package management","text":"

    Termux provides a Linux command line experience, providing a wide range of Unix tools and development environments. Termux uses a Debian based system and packages are easily installed

    • apt install add tools and libraries to the Linux environment from the curated packages in the software center
    • apt update updates the list of packages fromhe software center
    • apt list --upgradable shows list of packages with new versions
    • apt upgrade install new versions of currently installed packages
    • apt-cache search --names-only - search for packages that include a specific pattern in their name.
    • apt-cache show - shows detail of the supplied package name, including a description

    pkg is an alias for apt, the advance package tool, although there seems little benefit to using pkg if familiar with apt (they are both 3 characters)

    "},{"location":"termux/using-termux/#byobu-terminal-tab-manager","title":"Byobu terminal tab manager","text":"

    Byobu is an alternative to Termux provides a single terminal prompt. Byobu provides multiple shell prompts, allowing individual Clojure tools and editors to be run from the Termux prompt simultaneously. Practicalli uses byobu to run Neovim, a Clojure REPL and unit test watcher in separate byobu tabs with the ability to add further tabs for other command line tools.

    pkg install byobu\n
    • F2 to create a new tab
    • F3 to select previous tab
    • F4 to select next tab

    byobu-enable command will configure the current shell to run byobu on startup. Test this is working by typing exit in Termux and start Termux app again. byobu-disable stops this behaviour and byobu will need to be run manually after starting Termux.

    Run the byobu-enable command again if zsh is configured after this step or if adding any other shell to Termux.

    "},{"location":"version-control/","title":"Version Control","text":"

    There are several ways to interact with Git version control, although Practicalli recommends Neogit interactive git client and Octo to manage GitHub issues and pull requests

    • lazygit terminal UI, embedded in Neovim (AstroNvim only)
    • Neogit git client similar to Emacs Magit, with Diffview integration
    • Octo for GitHub Issue and Pull Requests
    • Open in GitHub
    • Shell out to the command line, :!
    • Git commands in Neovim terminal buffer
    "},{"location":"version-control/#init-local-repository","title":"Init local repository","text":"AstroNvim

    Space t f opens floating terminal window in the current project directory root (or which ever directory Neovim was started from).

    Initialise a local git repository in the current directory.

    git init .\n

    "},{"location":"version-control/#stage-in-buffer","title":"Stage in buffer","text":"AstroNvimPracticalli Neovim Config Redux

    The current hunk or the whole buffer can be staged from the buffer using Git Signs, saving a trip to the Git Status buffer.

    Space g H stages the current hunk

    Space g S stages the current buffer

    Not supported.

    "},{"location":"version-control/#git-status","title":"Git Status","text":"AstroNvimPracticalli Neovim Config Redux

    SPC g g opens lazygit status, for minimal UI

    Space g s Space g n ++\"t\" opens neogit in a new tab for Magit style experience

    SPC g s opens Git Status tab, by running :Neogit

    "},{"location":"version-control/#github-integration","title":"GitHub integration","text":"

    Interact with the remote GitHub repository using Octo

    List issues from a specific repository

    :Octo issue list practicalli/neovim\n

    Create a pull request on a specific repository

    :Octo pr create practicalli/neovim\n
    "},{"location":"version-control/diff/","title":"Diff","text":"

    Compare differences between different files or between a file and its versions.

    :diffsplit filename Neovim command opens a split containing the selected filename, showing a diff comparision to the currently opened file

    file path completion helps select the correct file for comparison

    "},{"location":"version-control/diff/#git-diff","title":"Git Diff","text":"

    DiffView compares working space and staged changes side by side, or a diff for git merge conflicts.

    ++SPC++ g d or d in neogit status buffer (SPC g s) will open diffview in a new tab

    q to return to neogit status buffer

    • Green - added lines
    • Yellow - changed line
    • Red - deleted lines
    AstroNvimPracticalli Neovim Config

    Ctrl h / j / k / l to navigate between open splits

    SPC b toggles the sidebar buffer

    SPC w l and SPC w h to move cursor between diff buffer and sidebar buffer

    "},{"location":"version-control/lazygit/","title":"Lazygit version control","text":"Command Line or AstroNvim configuration

    Lazygit interface not provided by Practicalli Neovim Config Redux

    "},{"location":"version-control/lazygit/#requirements","title":"Requirements","text":"

    Install lazygit command line tool

    "},{"location":"version-control/lazygit/#open-lazygit","title":"Open Lazygit","text":"AstroNvimCommand Line

    SPC g g to open git status with lazygit in a popup window

    Change to the root directory of the git managed project.

    Run the lazygit rich terminal UI

    lazygit\n
    "},{"location":"version-control/lazygit/#use-lazygit","title":"Use Lazygit","text":"

    SPC to stage files or directories in the files section of the UI

    c for a simple commit message prompt in the lazygit UI

    C to create a commit message within the

    Define Editor for Git Commit Messages

    Set core.editor in the user Git configuration (i.e. .config/git/config) to the name of the editor to use for commit messages, e.g. nvim, emacsclient) shell title= git config --global core.editor = nvim Alternatively, use the VISUAL or EDITOR environment variable to the choice of editor

    "},{"location":"version-control/neogit/","title":"Neogit - interactive client for Git","text":"

    Neogit is an interactive git client that provides the core features of version control with Git. Neogit emulates many of the features found in magit.

    SPC g s to open :Neogit status buffer

    TAB toggles expansion of sections, files and hunks

    d provide a side-by-side view of changes

    q to quit Neogit and return to the previous tab

    Neovim is configured to use the magit style key bindings in practicalli/neovim-config-redux

    "},{"location":"version-control/neogit/#branching","title":"Branching","text":"

    b opens the branch menu,

    • b - checkout a branch
    • c - create a new branch
    • d - delete a branch, D deletes local and remote branch
    • l - checkout a remote branch and create a local tracking branch
    • m - rename an existing local branch
    • n - create a new branch
    "},{"location":"version-control/neogit/#staging-changes","title":"Staging changes","text":"

    s to stage change under cursor, either file or hunk. S to stage all changes

    u to unstage change under cursor, U to unstage all changes

    v to select lines to stage within a hunk using s or unstage with u

    "},{"location":"version-control/neogit/#commit","title":"Commit","text":"

    c for the commit menu

    c for a new commit, a to amend the latest commit, w to reword a commit message, e to add staged changes to existing commit

    A new commit or amend commit qill open a new window to write a commit message (using a git commit message template if defined)

    :wq to save a commit message and initiate the commit.

    :q! to cancel the commit from the commit message buffer.

    "},{"location":"version-control/neogit/#stashing-changes","title":"Stashing changes","text":"

    Z to open the stash menu

    z to stash the working copy and staged files (index)

    i to only stash the staged files (index)

    "},{"location":"version-control/neogit/#remote-changes","title":"Remote changes","text":"

    F to open the pull menu, p to pull changes (fetch and merge) from the remote repository, u t pull from the upstream repository, or e to specify the remote and branch names.

    P to open the push menu to open, -u to push to the current remote

    Confused when remote is not origin

    Use e option to push to elsewhere when the remote name is not set to origin. The e option will prompt for a remote name and branch.

    "},{"location":"version-control/neogit/#commit-history","title":"Commit history","text":"

    L l to view git commit history log

    RET on a log entry shows the commit details in a new window (split)

    q to close the commit details window

    "},{"location":"version-control/neogit/#modify-git-commit-history","title":"Modify Git commit history","text":"

    r opens the rebase menu

    "},{"location":"version-control/octo/","title":"Octo - GitHub issues and PRs","text":"

    List, create and edit issues and pull requests from Neovim with Octo package.

    Octo connects to GitHub via the GitHub CLI, using a developer token for authentication

    Neogit provides a Magit style client, creating commits, pull & push changes with remote repositories.

    "},{"location":"version-control/octo/#github-interaction","title":"GitHub interaction","text":"

    GitHub CLI

    Work with GitHub issues and Pull Requests from the comfort of Neovim.

    GitHub CLI to authentication to a GitHub account. Successful login creates a local developer token that is used by Octo to communicate with GitHub.

    gh auth login\n
    "},{"location":"version-control/octo/#octo-commands","title":"Octo commands","text":"

    Command line form: Octo <object> <action> [arguments] - Object, Action and Arguments commands

    List issues from current project (optionally add a specific repository)

    :Octo issue list practicalli/neovim\n

    The account/repository-name is required if Octo cannot find the repository

    Create a pull requests from current project

    :Octo pr create\n

    Add a comment to the current topic (issue/pr)

    :Octo comment add\n

    :Octo gist list\n

    Octo.nvim configuration options

    Octo.nvim configuration options

    "},{"location":"version-control/open-in-github/","title":"Open In GitHub","text":"

    Open a file under local version control in the GitHub web UI (browser window).

    Neovim

    :OpenInGHFile

    :OpenInGHRepo

    "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Neovim for Clojure development","text":"

    coding at the speed of thought

    Neovim is incredibly fast and efficient, so thoughts flow from brain to editor without unnecessary delay.

    Touch typing is fast, Neovim and multi-modal editing makes it even faster.

    Neovim is a highly extensible and powerful editor, supporting multi-modal editing and Vim-style sequential key bindings. Highly responsive and low resource use makes Neovim ideal for development on any computer or mobile device, e.g. tablet, smartphone.

    Neovim has a diverse set of plugins and Practicalli curated configurations use these plugins to provide a rich set of features for Clojure development and wider engineering tasks.

    Practicalli Neovim provides install & user guide focused on a simple, powerful and satisfying REPL Driven workflow for Clojure.

    "},{"location":"#quick-start","title":"Quick Start","text":"

    Install Clojure, Neovim and choose a community configuration

    • [Lua] AstroNvim
    • [Fennel] Practicalli Neovim Config Redux
    "},{"location":"#external-reverences","title":"External reverences","text":"

    Getting started with Neovim and Conjure

    Neovim user guide

    This Week In Neovim - community update

    Conjure install guide Conjuring Clojure in Vim

    "},{"location":"#navigate-the-book","title":"Navigate the book","text":"

    Use the mouse or built-in key bindings to navigate the pages of the book

    • P , , : go to previous page
    • N , . : go to next page

    Use the search box to quickly find a specific topic

    • F , S , / : open search dialog
    • Down , Up : select next / previous result
    • Esc , Tab : close search dialog
    • Enter : follow selected result
    "},{"location":"#sponsor-my-work","title":"Sponsor my work","text":"

    All sponsorship recieved is used to maintain and further develop the Practicalli series of books and videos, although most of the work is still done with my own time and cost.

    Thank you to Cognitect, Nubank and a wide range of other sponsors from the Clojure community for your continued support

    "},{"location":"#creative-commons-license","title":"Creative commons license","text":"This work is licensed under a Creative Commons Attribution 4.0 ShareAlike License (including images & style sheets)."},{"location":"api-tools/","title":"API Tools","text":"

    Astrocommunity proivdes plugins to support working with APIs and the JSON format

    • nvim-jqx
    • rest-nvim

    Included in Practicalli Astronvim Config

    Practicalli Astronvim Config includes nvim-jqx and rest.nvim plugins

    "},{"location":"api-tools/#inspect-json","title":"Inspect JSON","text":"

    Browse and preview json files in neovim.

    :JqxList prettify JSON and start the inspector

    JqxQuery to run complex jq commands

    jq binary required

    jq binary should be available on the command line as nvim-jqx runs jq queries internally

    nvim-jqx

    "},{"location":"api-tools/#call-apis","title":"Call APIs","text":"

    Space r r to run an http request under the cursor from within an *.http file.

    A fast Neovim http client written in Lua, providing a curl wrapper.

    "},{"location":"api-tools/#http-file","title":"http file","text":"

    Open a file with an *.http extension

    Write a call to an API, e.g. a call to a local server health care endpoint

    Call locally running API

    health-check.http
    GET http://localhost:8080/system-admin/status\n

    A new window opens with the result of the API call

    Result of API call with rest.nvim
    GET http://localhost:8080/system-admin/status\nCommand :curl -sSL --compressed -X 'GET' --data-raw '' 'http://localhost:8080/system-admin/status'\n#+END\nHTTP/1.1 200 OK\nContent-Type: application/json; charset=utf-8\nContent-Length: 66\nServer: http-kit\nDate: Mon, 10 Jul 2023 16:21:33 GMT\n\n#+RESPONSE\n{\"application\":\"practicalli hole-in-one Service\",\"status\":\"Alive\"}\n#+END\n

    The Content-Type can be explicitly set, especially useful when not using JSON

    API call returning EDN data

    GET http://localhost:8080/api/v1/scoreboard\naccept: application/edn\n

    rest.nvim test examples

    rest.nvim

    "},{"location":"assets/images/social/","title":"Social Cards","text":"

    Social Cards are visual previews of the website that are included when sending links via social media platforms.

    Material for MkDocs is configured to generate beautiful social cards automatically, using the colors, fonts and logos defined in mkdocs.yml

    Generated images are stored in this directory.

    "},{"location":"configuration/","title":"Neovim Configuration","text":"

    Practicalli Neovim covers the following configurations.

    • AstroNvim - thoughtful configuration, supports Neovim 0.9 onward, polished UI, many community extensions
    • Practicalli Neovim Config Redux - mnemonic key bindings, packer, telescope selector, written in Fennel
    "},{"location":"configuration/#multiple-configurations","title":"Multiple Configurations","text":"

    Install multiple configurations, e.g. AstroNvim, lazyvim, Nvchad, etc. in the $HOME/.config directory using unique directory names.

    Set NVIM_APPNAME to specific the configuration to use when running nvim.

    NVIM_APPNAME=astronvim nvim\n

    NVIM_APPNAME variable should be set to the directory name containing the configuration, relative to the .config directory.

    The configuration directory name is used to hold share, state and cache files for that specific configuration.

    Create shell aliases for each configuration. Optionalliy, define a terminal UI selection to choose a configuration.

    Shell AliasesTerminal UI Selector

    Create a Shell alias for each configuration that will be used, to avoid setting the NVIM_APPNAME variable each time.

    Define Shell Aliases to run each configuration

    alias astro=\"NVIM_APPNAME=astronvim nvim\"\nalias lazyvim=\"NVIM_APPNAME=lazyvim nvim\"\nalias practicalli-redux=\"NVIM_APPNAME=neovim-config-redux nvim\"\n

    Create an nvim configuration selector script, with items listing the directory name of each configuration

    Z Shell nvim-selector script

    .local/bin/nvim-selector
    function nvim-selector() {\n  items=(\"astronvim\" \"neovim-config-redux\" \"lazyvim\")\n  config=$(printf \"%s\\n\" \"${items[@]}\" | fzf --prompt=\"\ue62b Neovim Config \uf63d \" --height=~50% --layout=reverse --border --exit-0)\n  if [[ -z $config ]]; then\n    echo \"Nothing selected\"\n    return 0\n  elif [[ $config == \"default\" ]]; then\n    config=\"\"\n  fi\n  NVIM_APPNAME=$config nvim $@\n}\n
    "},{"location":"configuration/astronvim/","title":"AstroNvim","text":"

    AstroNvim is a community configuration with an engaging UI, using Lazy for plugin management (Neovim packages) and Mason for package management (LSP, DAP, format and lint tools)

    Practicalli AstroNvim Config is a user configuration that extends AstroNvim and imports packages from the AstroNvim Community.

    "},{"location":"configuration/astronvim/#prerequisits","title":"Prerequisits","text":"
    • Nerd Fonts version 3 - download a full font or only the symbols
    • fzf fuzzy finder (ubuntu archive)
    • gtu (Ubuntu package archive)
    • btm from GitHub repository releases
    • node.js (version 20) for Mason install of many LSP servers

    AstroNvim requires node.js

    AstroNvim uses Mason to install LSP servers, format and lint tools. Many LSP servers require node.js to install and function.

    Node.js install - Practicalli Engineering Playbook

    Kitty Terminal with Nerd Fonts

    Kitty Terminal - Practicalli Engineering Playbook provides examples of using Nerd Fonts or Nerd Font symbols with the Kitty terminal.

    "},{"location":"configuration/astronvim/#clone-astronvim","title":"Clone AstroNvim","text":"

    Clone AstroNvim repository to $HOME/.config/astronvim/

    git clone --depth 1 https://github.com/AstroNvim/AstroNvim ~/.config/astronvim\n

    $HOME/.config/nvim can be used instead if only ever using one configuration for Neovim.

    "},{"location":"configuration/astronvim/#clone-astronvim-user-config","title":"Clone AstroNvim user config","text":"

    AstroNvim provides a template repository to create a user configuration. The template includes AstroNvim Community configuration to make it easier to extend the feature of AstroNvim.

    Practicalli AstroNvim Config is a clone of the AstroNvim user config with additional configuration to support Clojure development.

    Practicalli AstroNvim ConfigAstroNvim User Config

    Clone the Practicalli AstroNvim config which provides a user configuration with Clojure support

    git clone http://github.com/practicalli/astronvim-config $HOME/.config/astronvim/lua/user\n

    Or clone to a separate directory and create a symbolic link

    git clone http://github.com/practicalli/astronvim-config $HOME/.config/astronvim-config && \\\nln -s $HOME/.config/astronvim-config/ $HOME/.config/astronvim/lua/user\n

    Create your own user configuration using the AstroNvim user configuration template repository.

    Create a repository from the AstroNvim/user_example repository template

    Clone the newly created repository into the existing AstroNvim configuration, in a user directory

    git clone git@github.com/<github-account>/<new-repository> $HOME/.config/astronvim/lua/user\n

    "},{"location":"configuration/astronvim/#configure-shell-alias","title":"Configure shell alias","text":"

    Create a shell alias that sets NVIM_APPNAME to the location of the AstroNvim community config

    Add alias to .bashrc for Bash shell or .zshenv for Zsh

    alias astro=\"NVIM_APPNAME=astronvim nvim\"\n

    Configure shell alias

    "},{"location":"configuration/astronvim/#post-install","title":"Post install","text":"

    Open a terminal and use the astro alias to run Neovim.

    astro\n

    NVIM_APPNAME=astronvim nvim to run Neovim with astronvim without setting a shell alias.

    Neovim will open and display the Lazy plugin manager UI, showing the progress of plugin installation. This should only happen on the first run.

    Unattended post install

    Plugins can be installed without running the Neovim editor UI

    nvim --headless -c 'autocmd User LazyDone quitall'\n
    "},{"location":"configuration/astronvim/#check-health","title":"Check Health","text":"

    Run the Neovim :checkhealth command to report on the general Neovim install and supporting tools

    "},{"location":"configuration/astronvim/#add-lsp-dap-lint-and-format-tools","title":"Add LSP DAP Lint and Format tools","text":"

    SPC p m to launch Mason which manages LSP servers, linters, filters ...

    "},{"location":"configuration/astronvim/#configure-format-rules","title":"Configure format rules","text":"

    The configuration files for each lint and format tool should be used by Neovim.

    Setting a different location for these files has proved challenging. plugin/null-ls.lua has a section to override its builtin configuration for each lint and format tool, however, in tests Practicalli was unable to succeffuly set a different location.

    "},{"location":"configuration/astronvim/config-design/","title":"\ud83d\udce6 Practicalli AstroNvim Config Design","text":"

    A guide to the AstroNvim Config user configuration created by Practicalli to support Clojure development.

    AstroCommunity used where possible

    Plugins and configuration is added vial AstroCommunity were possible, to minimise the code size and maintenance of the configuration

    "},{"location":"configuration/astronvim/config-design/#user-config-overview","title":"User Config overview","text":"

    core.lua is for tuning plugins shipped with astronvim config

    plugins/ for additional plugins organised logically. All .lua files are read from this directory

    • user.lua for general user defined plugins
    • clojure.lua adds Conjure and parinf, ensuring Clojure treesitter parser and Clojure LSP
    "},{"location":"configuration/astronvim/config-design/#clojure-support","title":"Clojure support","text":"

    The AstroCommunity provides a Clojure language pack that adds Conjure and nvim-parinfer, along with clojure Treesitter parser and clojure-lsp support.

    AstroCommunity PackManually add plugins

    Edit the plugins/community.lua file and import the Clojure pack. The \"AstroNvim/astrocommunity\", repository is already added to to the file.

    -- Packs\n-- Treesitter: clojure , Lsp: clojure-lsp, Lint/format:\n{ import = \"astrocommunity.pack.clojure\" },\n
    Override AstroCommunity Pack

    Create a plugins/clojure.lua file and add the AstroCommunity repository, Clojure pack and additional configuration to your own preferences

    Clojure configuration with user configration overrides

    return {\n  \"AstroNvim/astrocommunity\",\n  { import = \"astrocommunity.pack.clojure\" },\n  {\n    \"Olical/conjure\",\n    -- load plugin on filetypes\n    ft = { \"clojure\", \"fennel\" },\n    config = function()\n      -- HUD\n      -- Example: Set to `\"SE\"` and HUD width to `1.0` for full width HUD at bottom of screen\n      vim.g[\"conjure#log#hud#width\"] = 1 -- Width of HUD as percentage of the editor width, 0.0 and 1.0.\n      vim.g[\"conjure#log#hud#enabled\"] = false -- Display HUD\n      vim.g[\"conjure#log#hud#anchor\"] = \"SE\" -- Preferred corner position for the HUD\n      vim.g[\"conjure#log#botright\"] = true -- Open log at bottom or far right of editor\n      -- REPL\n      vim.g[\"conjure#extract#context_header_lines\"] = 100 -- Number of lines to check for `ns` form\n      vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false -- ;; Start \"auto-repl\" process, eg. babashka\n      vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true -- ;; Hide auto-repl buffer when triggered\n      vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil -- ;; Command to start the auto-repl\n      -- ;; Automatically require namespace of new buffer or current buffer after connection\n      vim.g[\"conjure#client#clojure#nrepl#eval#auto_require\"] = false\n      -- Reloading code\n      -- Function to call on refresh (reloading) the log, namespace-qualified name of a zero-arity\n      -- vim.g[\"conjure#client#clojure#nrepl#refresh#after\"] = nil\n      -- The namespace-qualified name of a zero-arity function to call before reloading.\n      -- vim.g[\"conjure#client#clojure#nrepl#refresh#before\"] = nil\n      -- List of directories to scan. If no directories given, defaults to all directories on the classpath.\n      -- vim.g[\"conjure#client#clojure#nrepl#refresh#dirs\"] = nil\n      -- Testing\n      -- ;; Test runner called from the test key mappings\n      vim.g[\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\"\n      -- Print raw test evaluation result, suppressing prefix for stdout lines `; (out)`\n      -- vim.g[\"conjure#client#clojure#nrepl#test#raw_out\"] = nil\n      -- Override string appended to the end of the test runner calls\n      -- vim.g[\"conjure#client#clojure#nrepl#test#call_suffix\"] = nil\n    end\n  },\n  {\n    \"gpanders/nvim-parinfer\",\n    ft = lisp_dialects,\n    config = function()\n      vim.g.parinfer_force_balance = true\n      vim.g.parinfer_comment_chars = \";;\"\n    end,\n  },\n}\n

    Add Conjure and parinfer plugin that will load when Clojure or Fennel file is opened.

    Clojure Packages in AstroNvim user configuration

    ```lua title=\".config/astronvim-config/plugins/clojure.lua\"\n-- Lazy Package manager configuration\nreturn {\n  {\n    \"Olical/conjure\",\n    -- load plugin on filetypes\n    ft = { \"clojure\", \"fennel\" },\n  },\n\n  {\n    \"gpanders/nvim-parinfer\",\n    ft = { \"clojure\", \"fennel\" },\n    config = function()\n      vim.g.parinfer_force_balance = true\n      vim.g.parinfer_comment_chars = \";;\"\n    end,\n  },\n}\n```\n

    Improve syntax highlighting by installing the Clojure parser for Treesitter.

    Treesitter Parser for clojure in AstroNvim user configuration

    .config/astronvim-config/plugins/treesitter.lua
    return {\n  \"nvim-treesitter/nvim-treesitter\",\n  opts = function(_, opts)\n    -- add more things to the ensure_installed table protecting against community packs modifying it\n    opts.ensure_installed = require(\"astronvim.utils\").list_insert_unique(opts.ensure_installed, {\n      -- \"lua\"\n    \"clojure\"\n    })\n  end,\n}\n

    Install Treesitter Clojure Parser manually

    :TSInstall clojure in Neovim will install the parser. A parser not included in the opts.ensure_installed configuration must be updated manually each time treesitter plugin is updated

    "},{"location":"configuration/astronvim/config-design/#clojure-mappings","title":"Clojure Mappings","text":"

    Conjure mappings are defined respective to a <localleader> value. Define a local leader in the AstroNvim user configuration, e.g. , and all Conjure mappings become available.

    AstroNvim 3.17.0 has localleader

    AstroNvim 3.17.0 release sets localleader to , so a separate setting is not required in the user configuration (unless a different localleader is preferred)

    Set localleader in user config

    options.lua in the user configuration provides a consistent way to set Neovim options.

    .config/astronvim-config/options.lua
    -- set vim options here (vim.<first_key>.<second_key> = value)\nreturn {\n  opt = {\n    -- set to true or false etc.\n    relativenumber = true, -- sets vim.opt.relativenumber\n    number = true,         -- sets vim.opt.number\n    spell = false,         -- sets vim.opt.spell\n    signcolumn = \"auto\",   -- sets vim.opt.signcolumn to auto\n    wrap = false,          -- sets vim.opt.wrap\n  },\n  g = {\n    mapleader = \" \",                 -- sets vim.g.mapleader\n    maplocalleader = \",\",            -- Set local leader key binding (supports Conjure key bindings)\n    autoformat_enabled = true,       -- enable or disable auto formatting at start (lsp.formatting.format_on_save must be enabled)\n    cmp_enabled = true,              -- enable completion at start\n    autopairs_enabled = true,        -- enable autopairs at start\n    diagnostics_mode = 3,            -- set the visibility of diagnostics in the UI (0=off, 1=only show in status line, 2=virtual text off, 3=all on)\n    icons_enabled = true,            -- disable icons in the UI (disable if no nerd font is available, requires :PackerSync after changing)\n    ui_notifications_enabled = true, -- disable notifications when toggling UI elements\n    VM_leader = \"gm\"                 -- Visual Multi Leader (multiple cursors)\n  },\n}\n
    "},{"location":"configuration/astronvim/config-design/#clojure-lsp","title":"Clojure LSP","text":"

    Clojure LSP support is enabled via the AstroCommunity Clojure pack.

    clojure_lsp can be added using Mason UI, SPC p m or in the plugins/mason.lua file

    Manual user config of clojure lsp server
    -- customize mason plugins\nreturn {\n  -- use mason-lspconfig to configure LSP installations\n  {\n    \"williamboman/mason-lspconfig.nvim\",\n    -- overrides `require(\"mason-lspconfig\").setup(...)`\n    opts = function(_, opts)\n      -- add more things to the ensure_installed table protecting against community packs modifying it\n      opts.ensure_installed = require(\"astronvim.utils\").list_insert_unique(opts.ensure_installed, {\n        -- \"clojure_lsp\",  -- provide by Clojure pack\n        \"marksman\", -- Markdown structure (also in markdown pack)\n        \"yamlls\",\n      })\n    end,\n  },\n}\n
    "},{"location":"configuration/astronvim/config-design/#snippets","title":"Snippets","text":"

    The AstroNvim user example includes a commented LuaSnip configuration

    .config/astronvim-config/plugins/core.lua
      -- {\n  --   \"L3MON4D3/LuaSnip\",\n  --   config = function(plugin, opts)\n  --     require \"plugins.configs.luasnip\" (plugin, opts)  -- include the default astronvim config that calls the setup call\n  --     -- add more custom luasnip configuration such as filetype extend or custom snippets\n  --     local luasnip = require \"luasnip\"\n  --     luasnip.filetype_extend(\"javascript\", { \"javascriptreact\" })\n  --   end,\n  -- },\n

    AstroNvim includes a Recipe for custom snippets

    return {\n  plugins = {\n    {\n      \"L3MON4D3/LuaSnip\",\n      config = function(plugin, opts)\n        require \"plugins.configs.luasnip\"(plugin, opts) -- include the default astronvim config that calls the setup call\n        require(\"luasnip.loaders.from_vscode\").lazy_load { paths = { \"./lua/user/snippets\" } } -- load snippets paths\n      end,\n    },\n  },\n}\n

    Practicalli AstroNvim Config combines the two examples to get

    AstroNvim config with custom VS Code style snippets

    .config/astronvim-config/plugins/core.lua
    {\n  \"L3MON4D3/LuaSnip\",\n  config = function(plugin, opts)\n    require \"plugins.configs.luasnip\" (plugin, opts) -- include the default astronvim config that calls the setup call\n    -- add more custom luasnip configuration such as filetype extend or custom snippets\n    require(\"luasnip.loaders.from_vscode\").lazy_load { paths = { \"./lua/user/snippets\" } } -- load snippets paths\n    local luasnip = require \"luasnip\"\n    luasnip.filetype_extend(\"javascript\", { \"javascriptreact\" })\nend,\n},\n
    "},{"location":"configuration/astronvim/config-design/#astronvim-community-packages","title":"AstroNvim Community packages","text":"

    AstroNvim Community provides a large number of packages currated by the community.

    Visit the AstroNvim Community repository on GitHub and browse the packages available.

    import each package of interest to the plugins/community.lua file in the AstroNvim user configuration.

    AstroNvim Community Packages in AstroNvim user configuration

    .config/astronvim-config/plugins/community.lua
    return {\n  -- Add the community repository of plugin specifications\n  \"AstroNvim/astrocommunity\",\n  -- Import each plugin from the Astro Community as required\n  { import = \"astrocommunity.editing-support.todo-comments\" },\n  { import = \"astrocommunity.git.neogit\" },\n  { import = \"astrocommunity.git.octo\" },\n  { import = \"astrocommunity.git.openingh\" },\n}\n

    AstroCommunity packs set up support for each language

    Language packs enabled in Practicalli AstroNvim Config

    .config/astronvim-config/plugin/community.lua
      -- Packs\n  -- Treesitter: dockerfile , Lsp: dockerls & docker_compose_language_service, Lint/format: hadolint\n  { import = \"astrocommunity.pack.docker\" },\n  -- Treesitter: json & jsonc, Lsp: jsonls, Lint/format: stylua\n  { import = \"astrocommunity.pack.json\" },\n  -- Treesitter: lua, Lsp: lua_ls, Lint/format: stylua\n  { import = \"astrocommunity.pack.lua\" },\n  -- Treesitter: markdown & markdown_inline, Lsp: marksman, Lint/format: prettierd\n  -- Pack disabled as prettierd too agressive with format\n  -- { import = \"astrocommunity.pack.markdown\" },\n  -- Treesitter: markdown & markdown_inline, Lsp: marksman, Lint/format: prettierd\n  { import = \"astrocommunity.pack.yaml\" },\n
    "},{"location":"configuration/astronvim/config-design/#themes","title":"Themes","text":"

    Themes are a collection of one or more colorschemes to affect the apperance of text, icons, highlights, etc.

    Themes supporting vim.opt.background can change between dark and light colorscheme (SPC u b UI > background in AstroNvim)

    SPC f t selector shows themes colorschemes, as long as the themes are configured to disable lazy loading

    The default astrodark theme is set via the colorscheme option in init.lua

    Everforest provides a good dark and light theme and supports the background option to toggle between each colorscheme.

    Practicalli AstroNvim Config - default theme

    colorscheme = \"everforest\",\n

    AstroCommunity themes

    Practicalli AstroNvim Config themes

    return {\n{\n\"AstroNvim/astrotheme\", -- default AstroNvim theme\nlazy = false,\n},\n  -- Add the community repository of plugin specifications\n  \"AstroNvim/astrocommunity\",\n  { import = \"astrocommunity.colorscheme.everforest\" },\n  {\n    \"sainnhe/everforest\",\n    lazy = false,\n  },\n  { import = \"astrocommunity.colorscheme.nightfox-nvim\" },\n  {\n    \"EdenEast/nightfox.nvim\",\n    lazy = false,\n  },\n  { import = \"astrocommunity.colorscheme.kanagawa-nvim\" },\n  {\n    \"rebelot/kanagawa.nvim\",\n    lazy = false,\n  },\n  { import = \"astrocommunity.colorscheme.github-nvim-theme\" }, -- no background support\n  {\n    \"projekt0n/github-nvim-theme\",\n    lazy = false,\n  },\n
    "},{"location":"configuration/astronvim/config-design/#configure-lazy-plugins","title":"Configure Lazy plugins","text":"

    Lazy.nvim Plugin specification

    "},{"location":"configuration/astronvim/config-design/#config-format-and-lint-tools","title":"Config Format and Lint tools","text":"

    Disable format on save when tools provide unexpected results

    SPC u f toggles if the respective format tool should run for the current buffer. SPC u F for all buffers of the current kind.

    init.lua lsp section can enable or disable format on save for specific file types.

    Mason is responsible for installing lint and format tools

    null-ls is responsible for running each tool and provides default configuration for code_actions, completion, diagnostics, formatting and hover.

    null-ls built-in configuration

    Override config file unconsistent

    The configuration file defined by -config-path does not always seem to be used when running astronvim. Quit and start Neovim again seems to use the configuration file.

    Override null-ls builtin configuration

    Specify configuration files to use that override the null-ls builtin configuration

    return {\n  \"jose-elias-alvarez/null-ls.nvim\",\n  opts = function(_, config)\n    -- config variable is the default configuration table for the setup function call\n    local null_ls = require \"null-ls\"\n    config.sources = {\n      null_ls.builtins.formatting.markdownlint.with {\n        -- pass arguments to modify/override the null-ls builtin configuration\n        extra_args = { \n          \"--config-path\", \n          vim.fn.expand(\"~/.config/astro-config/tool-config/markdownlint.yaml\") },\n      },\n    }\n    return config -- return final config table\n  end,\n}\n

    vim.fn.expand() reports luacheck error accessing undefined variable but seems to work regardless

    General configuration for LSP Servers .config/astronvim-config/init.lua
      lsp = {\n    -- customize lsp formatting options\n    formatting = {\n      -- control auto formatting on save\n      format_on_save = {\n        enabled = true,     -- format on save globally\n        allow_filetypes = { -- format on save for specified filetypes only\n          -- \"go\",\n        },\n        ignore_filetypes = { -- turn off format on save for specified filetypes\n          -- \"python\",\n        },\n      },\n      disabled = { -- switch off formatting capabilities for the listed language servers\n        -- turn off lua_ls formatting capability if you want to use StyLua to format your lua code\n        -- \"lua_ls\",\n        \"markdownlint\",\n      },\n      timeout_ms = 1000, -- default format timeout\n      -- filter = function(client) -- fully override the default formatting function\n      --   return true\n      -- end\n    },\n    -- enable servers that you already have installed without mason\n    servers = {\n      -- \"pyright\"\n    },\n  },\n
    "},{"location":"configuration/astronvim/config-design/#override-key-binding","title":"Override Key binding","text":"

    AstroNvim uses Lazy package manager to set keys for packages.

    Astrocommunity configuration defines a keys table that is used by Lazy.

    In the user configuration, return a function that sets key bindings to overide the keys table provided by astrocommunity

    Override Key bindings for vim highlighter .config/astronvim-config/plugins/community.lua
    {\n    \"vim-highlighter\",\n    keys = function() \n        return {\n            { \"<leader>nn\", \"<cmd>Hi><CR>\", desc = \"Next Recently Set Highlight\" },\n            { \"<leader>ng\", \"<cmd>Hi<<CR>\", desc = \"Previous Recently Set Highlight\" },\n            { \"<leader>n[\", \"<cmd>Hi{<CR>\", desc = \"Next Nearest Highlight\" },\n            { \"<leader>n]\", \"<cmd>Hi}<CR>\", desc = \"Previous Nearest Highlight\" },\n        }\n    end,\n}\n
    "},{"location":"configuration/astronvim/config-design/#plugin-key-binding","title":"Plugin Key binding","text":"

    Add key binding if a plugin is available wrapped in an if statement, when defining keys in a different place to adding the plugin, e.g whichkey mappings.lua

    if is_available \"plugin-name\" then\n  ,,,\nelse\n
    "},{"location":"configuration/practicalli/","title":"Neovim Config Redux","text":"

    practicalli/neovim-config-redux

    practicalli/neovim-config-redux is a Fennel based configuraion with a wide range of plugins and telescope extensions.

    Clone practicalli/neovim-config-redux or create a fork if intending to customise that configuration

    Multiple Neovim ConfigsSingle Neovim Configs
    git clone https://github.com/practicalli/neovim-config-redux.git ~/.config/neovim-config-redux\n
    git clone https://github.com/practicalli/neovim-config-redux.git ~/.config/nvim\n
    "},{"location":"configuration/practicalli/#screenshots","title":"Screenshots","text":"

    Dashboard using the startup plugin

    Mnemonic menu with which-key

    Telescope buffer selection

    Neogit Git client with diffview panel

    "},{"location":"configuration/practicalli/config-design/","title":"Config Design","text":"

    The overall design of the Practicalli Neovim Config Redux

    "},{"location":"configuration/practicalli/config-design/#initlua","title":"init.lua","text":"
    • bootstrap the aniseed package which compiles the Fennel configuration into Lua, which is then read by Neovim. Defines the entry point to the Fennel configuration as fnl/config/init.fnl
    • installs packer.nvim for package management
    • examples to disable language providers if programming language support is not required (node, perl, python3, ruby)
    "},{"location":"configuration/practicalli/config-design/#fnlconfiginitfnl","title":"fnl/config/init.fnl","text":"
    • load plugin configuration namespace config.plugin
    • load config.util namespace to streamline key binding definitions
    • set the leader key as space and local-leader as ,
    • define key bindings - uses config.util (mapping to be moved to their own namespace)
    • set global Neovim options
    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginfnl","title":"fnl/config/plugin.fnl","text":"

    Define plugins to add functionality to Neovim.

    use is a private function that searches the plugin configuration map for the keyword :mod and loads the associated namespace (namespace defined with a keyword with the same name)

    e.g. in the telescope plugin configuration :mod has a value of :telescope which will load the file fnl/config/plugin/telescope.fnl

      :nvim-telescope/telescope.nvim\n  {:requires [:nvim-lua/popup.nvim\n              :nvim-lua/plenary.nvim]\n   :mod :telescope}\n

    Packer downloads the nvim-telescope/telescope.nvim plugin and all the plugins in :requires section and search for the namespace telescope in file located in the following path fnl/config/plugin/telescope

    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginconjurefnl","title":"fnl/config/plugin/conjure.fnl","text":"

    The majority of default configuration settings are used for Conjure, with the exception of a few commonly used key bindings from Emacs CIDER & Spacemacs. The Heads Up Display (HUD) is also configured to be less intrusive, relying on mostly on inline results.

    Include the conjure and aniseed namespaces

    (module config.plugin.conjure\n  {autoload {nvim aniseed.nvim}})\n

    Configure keybindings to be closer to Spacemacs

    ;; Set e register for evaluation result\n(set nvim.g.conjure#eval#result_register :e)\n\n;; Evaluate root form (top level form) under the cursor\n;; Default: `\"er\"`\n(set nvim.g.conjure#mapping#eval_root_form \"ef\")\n\n;; Evaluate root form under the cursor & insert result as comment\n;; Default: `\"ecr\"`\n(set nvim.g.conjure#mapping#eval_comment_root_form \"e;\")\n\n;; Evaluate file loaded from disk\n;; Default: `\"ef\"`\n(set nvim.g.conjure#mapping#eval_file \"el\")\n

    Configure the HUD to be less intrusive.

    ;; Width of HUD as percentage of the editor width\n;; A float between 0.0 and 1.0.\n;; Default: `0.42`\n(set nvim.g.conjure#log#hud#width 1)\n\n;; Display HUD\n;; Default: `true`\n(set nvim.g.conjure#log#hud#enabled false)\n\n;; Preferred corner position for the HUD, over-ridden by HUD cursor detection\n;; Example: Set to `\"SE\"` and HUD width to `1.0` for full width HUD at bottom of screen\n;; Default: `\"NE\"`\n(set nvim.g.conjure#log#hud#anchor \"SE\")\n\n;; Open log at bottom or far right of editor, using full width or height\n;; Default: `false`\n(set nvim.g.conjure#log#botright true)\n

    Practicalli encourages header comments at the start of each file to describe the purpose of the namespace, so the Clojure ns lookup is extended

    ;; Number of lines to check for `ns` form, used for setting evaluation context\n;; `b:conjure#context` to override a specific buffer that isn't finding the context\n;; Default: `24`\n(set nvim.g.conjure#extract#context_header_lines 100)\n

    Disable the auto-repl as practicalli prefers manage repl connections themselves

    ;; Start \"auto-repl\" process, eg. babashka\n;; when Conjure unable to find candidate REPL process via to an existing nREPL connection\n;; Default: `true`\n(set nvim.g.conjure#client#clojure#nrepl#connection#auto_repl#enabled false)\n\n;; Hide auto-repl buffer when triggered, to avoid the need to interact with that buffer\n;; Default: `false`\n(set nvim.g.conjure#client#clojure#nrepl#connection#auto_repl#hidden true)\n\n;; Command to start the auto-repl\n;; Default: `\"bb nrepl-server localhost:8794\"`\n(set nvim.g.conjure#client#clojure#nrepl#connection#auto_repl#cmd nil)\n\n;; Print raw evaluation result, suppressing prefix for stdout lines `; (out)`\n;; Default: `false`\n(set nvim.g.conjure#client#clojure#nrepl#eval#raw_out true)\n\n;; Automatically require namespace of new buffer or current buffer after connection\n;; Ensures buffers are loaded, required code to compile and (re)loadable.\n;; Default: `true`\n(set nvim.g.conjure#client#clojure#nrepl#eval#auto_require false)\n

    Use lambdaisland/kaocha as the test runner rather, which has a fail fast feature which can be more effective when adding or changing functionality

    ;; Test runner called from the test key mappings\n;; Default: `\"clojure\"`\n(set nvim.g.conjure#client#clojure#nrepl#test#runner \"kaocha\")\n\n;; Print raw test evaluation result, suppressing prefix for stdout lines `; (out)`\n;; Default: `true`\n(set nvim.g.conjure#client#clojure#nrepl#test#raw_out true)\n
    "},{"location":"configuration/practicalli/config-design/#fnlconfigplugintelescopefnl","title":"fnl/config/plugin/telescope.fnl","text":"

    Settings like ignore node_modules and everything in .gitignore to be listed in the file finder.

    Defines a ripgrep command to set parameters for searching files

    Add --hidden to see all dotfiles (regardless of .gitignore patterns)

    Keymaps:

    • <leader>ff open the find files
    • <leader>fg open the fuzzy finder
    • <leader>fb open the find open buffer
    • <leader>fh open the nvim help fuzzy finder
    "},{"location":"configuration/practicalli/config-design/#fnlconfigplugintreesitterfnl","title":"fnl/config/plugin/treesitter.fnl","text":"

    Defines which language parsers and modules to use.

    • automatically use clojure, fennel and markdown parsers (and compile on first run of Neovim)
    • automatically update language parsers when nvim-treesitter plugin updated
    • enable highlight module
    • enable indent module
    (treesitter.setup\n  {:ensure_installed [\"clojure\" \"fennel\" \"markdown\"]\n   :sync_install true\n   :highlight {:enable true}\n   :indent    {:enable true}})\n
    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginlspconfigfnl","title":"fnl/config/plugin/lspconfig.fnl","text":"

    Language Server Protocol for static analysis of code, to provide common formatting, linting and refactoring tooling across all programming languages.

    Define which symbols to show for lsp diagnostics

    (defn define-signs\n  [prefix]\n  (let [error (.. prefix \"SignError\")\n        warn  (.. prefix \"SignWarn\")\n        info  (.. prefix \"SignInfo\")\n        hint  (.. prefix \"SignHint\")]\n  (vim.fn.sign_define error {:text \"\uf057\" :texthl error})\n  (vim.fn.sign_define warn  {:text \"\uf071\" :texthl warn})\n  (vim.fn.sign_define info  {:text \"\uf05a\" :texthl info})\n  (vim.fn.sign_define hint  {:text \"\uf059\" :texthl hint})))\n
    • features and server settings to enable/customize.
    • Handler defines features and how we want to render the server outputs.
    • Capabilities we link with our autocompletion plugin (nvim-cmp), to say to the lsp servers that we have this feature enabled.
    • On_Attach we customize our interaction with the LSP server, here we define the following keymaps:
    • configure all settings above in clojure-lsp server instance.
    "},{"location":"configuration/practicalli/config-design/#fnlconfigplugincmpfnl","title":"fnl/config/plugin/cmp.fnl","text":"

    Configure sources to show in the autocomple menu (i.e. conjure, lsp, buffer) and key bindings to navigate the autocomplete popup menu.

    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginthemefnl","title":"fnl/config/plugin/theme.fnl","text":"

    Add the Neovim GitHub theme which gives 3 dark and 3 light themes to choose from. Individual colors and styles can be configured to change specific parts of the theme.

    The light theme is used by default, with a custom softer background colour that is slightly red-shifted.

    Options are specified in the theme.setup function, where the option names are keywords and the values are strings, boolean or hash-map of more option keywords and values.

    (theme.setup {:theme_style \"light\"\n              :colors {:bg \"#f8f2e6\"}\n              :comment_style \"italic\"})\n

    The colors (Hex values) for each theme are in the github-nvim-theme/lua/github-theme/palette with the overal theme definition in github-nvim-theme/lua/github-theme/theme.lua

    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginsexpfnl","title":"fnl/config/plugin/sexp.fnl","text":"

    Settings for vim-sexp like enabling it for another lisp languages like Fennel and Jannet

    "},{"location":"configuration/practicalli/config-design/#fnlconfigpluginlualinefnl","title":"fnl/config/plugin/lualine.fnl","text":"

    Configure the status line (lualine) that shows at the bottom of Neovim, defining colors and elements that appear on that line.

    The Neovim GitHub theme includes definitions to set the look of the status line.

    "},{"location":"configuration/practicalli/packer/","title":"Package Manager","text":"

    Packer is a use-package inspired package management for Neovim.

    Packer is used as the package manager in this guide as it is built on native Neovim packages and supports Luarocks dependencies, use the :help packages command in Neovim for more details.

    Packer is written in Lua and is installed via the init.lua configuration file, although Practicalli Neovim configuration uses Fennel to configure each package added by Packer.

    "},{"location":"configuration/practicalli/packer/#install","title":"Install","text":"

    init.lua is the entry point to the configuration and is the only part that is written in Lua language.

    The configuration bootstraps the Packer package manager and installs the Aniseed compiler required to process the fennel configuration.

    Aniseed compiles and loads fnl/config/init.fnl and all the required namespaces in that file.

    Packer will process the use form in fnl/config/plugin.fnl and install all the packages defined in that form, along with any package specific configuration defined in that package {:mod :namespace-name} file.

    local execute = vim.api.nvim_command\nlocal fn = vim.fn\n\nlocal pack_path = fn.stdpath(\"data\") .. \"/site/pack\"\nlocal fmt = string.format\n\nfunction ensure (user, repo)\n  -- Ensures a given github.com/USER/REPO is cloned in the pack/packer/start directory.\n  local install_path = fmt(\"%s/packer/start/%s\", pack_path, repo, repo)\n  if fn.empty(fn.glob(install_path)) > 0 then\n    execute(fmt(\"!git clone https://github.com/%s/%s %s\", user, repo, install_path))\n    execute(fmt(\"packadd %s\", repo))\n  end\nend\n\n-- Bootstrap essential plugins required for installing and loading the rest.\nensure(\"wbthomason\", \"packer.nvim\")\nensure(\"Olical\", \"aniseed\")\n\n-- Enable Aniseed's automatic compilation and loading of Fennel source code.\nvim.g[\"aniseed#env\"] = {\n  module = \"config.init\",\n  compile = true\n}\n
    "},{"location":"configuration/practicalli/packer/#packages","title":"Packages","text":"

    Neovim packages add extra functionality to Neovim, e.g. conjure package provides an excellent Clojure REPL experience (and supports several other languages too).

    See the packages section for details of the packages used and a breakdown of their configuration.

    "},{"location":"configuration/practicalli/packages/","title":"Add Neovim Packages","text":"

    Evolving Packages in Practicalli config

    Check the practicalli/neovim-config-reduct configuration. Many packages have been added to the configuration and fnl/config/package.fnl is the most up to date list of packages currently used.

    List of packages and their purpose

    Package Description conjure Clojure REPL Driven Development (and other language REPLs) sexp Structured Editing newpaper theme Clean and simple UI & colour scheme, aimed at readably lualine Fast and configurable statusline nvim-treesitter Parse code highly efficiently, client for LSP servers telescope Completion tool, e.g. select files, buffers tabs, packages, etc nvim-tree Visual file manager - open, create, delete, etc. files & directories neogit Magit style visual Git client Octo Git Issues and Pull Requests gitsigns Show diff changes in buffer gutter and status line

    Any specific package configuration & key bindings (on sub page if significant content)

    "},{"location":"configuration/practicalli/packages/#package-selection-criteria","title":"Package selection criteria","text":"

    Packages are more likely to be adopted if:

    • provide valuable (or fun) features
    • work reliably, without generating errors
    • do not conflict with other valuable packages in this configuration
    • written in fennel or lua to aid maintenance
    • provides a setup or config function for setting package options
    • use features provided by Neovim (e.g treesitter)
    • are well documented
    • are easy to configure
    • are easy to use
    • work well with themes (where relevant)
    "},{"location":"configuration/practicalli/packages/#package-updates","title":"Package Updates","text":"

    This Week In Neovim - community update

    "},{"location":"configuration/practicalli/packages/lualine/","title":"Lualine - modeline theme","text":"

    nvim-lualine/lualine.nvim is a fast and configurable statusline for neovim

    Example status line: evil_lualine

    "},{"location":"configuration/practicalli/packages/lualine/#lualine-configuration-in-fennel","title":"Lualine configuration in Fennel","text":"

    nvim/fnl/config/plugin/lualine.fnl

    (module config.plugin.lualine\n  {autoload {core aniseed.core\n             lualine lualine\n             lsp config.plugin.lspconfig}})\n\n(defn lsp_connection []\n  (if (vim.tbl_isempty (vim.lsp.buf_get_clients 0)) \"\uf096\" \"\uf0c8\"))\n\n(def github-lua-theme\n  (core.assoc\n    (require :lualine.themes.auto)\n    :inactive {:a {:bg \"#19181e\" :fg \"#a4a3a6\"}\n               :b {:bg \"#19181e\" :fg \"#a4a3a6\"}\n               :c {:bg \"#19181e\" :fg \"#a4a3a6\"}}\n    :normal {:a {:bg \"#131217\" :fg \"#24292e\"}\n             :b {:bg \"#131217\" :fg \"#3b8eea\"}\n             :c {:bg \"#19181e\" :fg \"#d1d5da\"}}\n    :command {:a {:bg \"#131217\" :fg \"#24292e\"}\n              :b {:bg \"#131217\" :fg \"#ccbed8\"}\n              :c {:bg \"#19181e\" :fg \"#d1d5da\"}}\n    :visual {:a {:bg \"#131217\" :fg \"#24292e\"}\n             :b {:bg \"#131217\" :fg \"#ced4b1\"}\n             :c {:bg \"#19181e\" :fg \"#d1d5da\"}}\n    :replace {:a {:bg \"#131217\" :fg \"#24292e\"}\n              :b {:bg \"#131217\" :fg \"#d1b6bd\"}\n              :c {:bg \"#19181e\" :fg \"#d1d5da\"}}\n    :insert {:a {:bg \"#131217\" :fg \"#24292e\"}\n             :b {:bg \"#131217\" :fg \"#a8d1c9\"}\n             :c {:bg \"#19181e\" :fg \"#d1d5da\"}}))\n\n(lualine.setup\n  {:options {:theme github-lua-theme\n             :icons_enabled true\n             :section_separators [\"\" \"\"]\n             :component_separators [\"\uf44a\" \"\uf438\"]}\n   :sections {:lualine_a []\n              :lualine_b [[:mode {:upper true}]]\n              :lualine_c [[\"FugitiveHead\"]\n                          [:filename {:filestatus true\n                                      :path 1}]]\n              :lualine_x [[:diagnostics {:sections [:error\n                                                    :warn\n                                                    :info\n                                                    :hint]\n                                         :sources [:nvim_lsp]}]\n                          [lsp_connection]\n                          :location\n                          :filetype]\n              :lualine_y [:encoding]\n              :lualine_z []}\n   :inactive_sections {:lualine_a []\n                       :lualine_b []\n                       :lualine_c [[:filename {:filestatus true\n                                               :path 1}]]\n                       :lualine_x []\n                       :lualine_y []\n                       :lualine_z []}})\n
    "},{"location":"configuration/practicalli/packages/nvim-treesitter/","title":"Nvim Treesitter","text":"

    Treesitter provides language specific parsing, highlight and indent features and so is a fundamental plugin to use with Neovim.

    clojure, fennel, markdown and org parsers are automatically installed in the practicalli/neovim-config-redux configuration.

    • :TSInstallInfo lists language parsers and install status
    • :TSUpdate {language} to update a parser to the latest compatible version (specified in nvim-treesitter lockfile.json).
    • :TSInstall {language} compiles and installs a parser for the given language.
    • :TSUpdateSync to update all parsers to the latest available versions
    "},{"location":"configuration/practicalli/packages/nvim-treesitter/#nvim-treesitter-configuration","title":"nvim-treesitter configuration","text":"

    clojure, fennel, markdown and org parsers are automatically installed if not already available.

    :sync_install true automatically updates the parsers when the nvim-treesitter plugin is updated. Treesitter and its parsers are actively developed, so its important to ensure parsers are kept up to date. This is the equivalent of manually running :TSUpdateSync.

    Parser highlight and indent modules are enabled by default

    In fnl/config/plugin/treesitter.fnl

    (module config.plugin.treesitter\n  {autoload {treesitter nvim-treesitter.configs}})\n\n(treesitter.setup\n  {:ensure_installed [\"clojure\" \"fennel\" \"markdown\" \"org\"]\n   :sync_install true\n   :highlight {:enable true}\n   :indent    {:enable true}})\n
    "},{"location":"configuration/practicalli/packages/nvim-treesitter/#manually-install-parsers","title":"Manually Install Parsers","text":"

    nvim-treesitter provides the TSInstall command to generate a parser for a specific language, assuming that language is supported.

    A compiler (gcc, clang, etc) should be installed in the operating system on which nvim is running

    :TSInstall {language}\n

    TAB completion lists the available language parsers, TAB and S-TAB to navigate the auto-completion popup.

    "},{"location":"install/","title":"Install Overview","text":"

    Practicalli Neovim provides a feature rich configuration for Neovim and all the tools required for effective Clojure development (and other Lisp dialects too).

    • Clojure tooling and a Java SDK (Java Virtual Machine)
    • Neovim 0.9.x or nightly build
    • Neovim package manager and packages
    • NerdFonts for icon support in themes and status line

    Neovim 0.9.x latest stable release

    Content and configuration in this book has been tested against Neovim 0.9.x over the summer of 2023

    "},{"location":"install/#install-summary","title":"Install summary","text":"

    If you are familiar with most of the tools required, then the quick start list below provides an ultra-terse version on how to get started with Neovim and Clojure development.

    • Install Neovim 0.9.x or greater
      • Linux AppImage
      • brew install --HEAD neovim for Homebrew install of development version
    • Install supporting tools
      • tar & curl and a C compiler, e.g. gcc for Linux or clang for android/termix (required by nvim-treesitter)
      • ripgrep & fd to search for files (used by telescope)
      • luarocks for LSP support in AstroNvim
    • Clone Neovim Config
    • Run nvim in a terminal and ignore warnings, press RTN
      • SPC P i or :PackerInstall command in Neovim to install packages
    • Install Clojure CLI and supporting tools
    • Clone / fork practicalli/clojure-deps-edn or add an alias with the required config to use nrepl and cider-nrepl
    • Run a Clojure REPL process - in a terminal session with nREPL, e.g. using one of the REPL aliases from practicalli/clojure-deps-edn
      • clojure -M:repl/rebel for a rich REPL UI with auto-completion & docs
      • clojure -M:repl/headless - headless REPL process when working exclusively in a Clojure connected editor
    • Open a Clojure file in Neovim - Conjure will automatically connect
    "},{"location":"install/#next-steps","title":"Next Steps","text":"

    Learn how to use Neovim and how to use Conjure for REPL driven development

    "},{"location":"install/clojure/","title":"Install Clojure","text":"

    A rich Clojure REPL workflow is provided by the Conjure package, which works with Clojure CLI and Leiningen projects, assuming the respective tool is installed.

    Clojure LSP is highly recommended and packages to use an installed clojure-lsp tool are in the practicalli/neovim-config-redux configuration

    "},{"location":"install/clojure/#clojure-cli","title":"Clojure CLI","text":"

    Practicalli Clojure install guide

    Clojure CLI provides a way to run Clojure code, packaged Clojure (jar) and run a Clojure REPL.

    Practicalli Clojure install guide details prerequisites, Clojure install options and supporting tools for an enhanced developer workflow.

    Visit the Clojure Getting Started guide for the Clojure CLI or to check the latest release version.

    Practicalli Clojure CLI Config provides a wide range of community tools that extend the features of Clojure CLI, creating a rich development environment for use across all projects.

    Aliases are required for many examples

    Without Practicalli Clojure CLI Config many commands provided in this book are not available unless similar alias definitions are added to a either a project or user level deps.edn configuration.

    "},{"location":"install/clojure/#language-server-protocol","title":"Language Server Protocol","text":"

    Neovim Treesitter surfaces information from Language Server Protocol (LSP) servers to assist with development and refactor of Clojure code.

    Clojure LSP installation guide shows how to install the Clojure LSP binary for the relevant operating system.

    Once installed, run clojure-lsp -v in a terminal to ensure the command is working.

    practicalli/clojure-lsp-config

    practicalli/clojure-lsp-config provides a complete configuration for clojure-lsp (config.edn), including a wide range of snippets and less restrictive formatting rules (cljfmt.edn)

    clj-kondo provides static analysis of source code files, providing subtle warnings as Clojure code is written to help the developer follow idioms and avoid syntatic errors.

    Clojure LSP includes clj-kondo to provide an implementation of the Language Server Protocol for the Clojure Language.

    Clojure LSP installation guide Treesitter Fennel Configuration

    "},{"location":"install/clojure/#leiningen","title":"Leiningen","text":"

    Many existing Clojure projects use Leiningen build automation tool (although many new projects use Clojure CLI as well or instead of Leiningen).

    The code is the same regardless of tooling choice. The overall workflow is the same, although Clojure CLI may provide more workflow options.

    Follow the install instructions at Leiningen.org if required.

    "},{"location":"install/neovim/","title":"Install Neovim","text":"

    Neovim releases

    Neovim 8 is the minimum version for this configuration and Neovim 0.9.0 is currently being tested.

    Follow the install Neovim guide for the specific operating system.

    "},{"location":"install/neovim/#suppoting-tools","title":"Suppoting Tools","text":"

    Neovim uses several external tools for searching for files, search file contents and using the operating system clipbaord.

    AstroNvim requires node.js

    AstroNvim uses Mason to install LSP servers, format and lint tools. Many LSP servers require node.js to install and function.

    Node.js install - Practicalli Engineering Playbook

    Debian / Ubuntu

    Install the following packages to support Neovim

    • ripgrep fast file contents search (used by telescope)
    • find-fd advanced search tool
    • xclip clipboard as a provider tools for Neovim copy/paste
    • luarocks for LSP servers (AstroNvim)
    sudo apt install find-fd xclip luarocks\n

    Add set clipboard+=unnamedplus to the Neovim configuration to use the Linux clipboard tool

    Wayland requires wl-clipboard

    Install the wl-clipboard package to use the Wayland desktop clipboard with Neovim

    sudo apt install wl-clipboard\n

    "},{"location":"install/neovim/#install-neovim_1","title":"Install Neovim","text":"Linux AppImageUbuntu/DebianBuild from Source

    Download the AppImage from the Neovim Release page and place the file on the executable path, e.g. $HOME/.local/bin

    Make the AppImage executable

    chmod u+x nvim.appimage\n

    Run neovim from the AppImage

    nvim.appimage\n

    Create a symbolic link called nvim to the nvim.appimage

    ln -s $HOME/.local/bin/nvim.appimage $HOME/.local/bin/nvim\n

    Download the Linux AppImage from the Neovim Releases page

    Or build Neovim from source and generate a .deb file from the build.

    Linux version only packaged as AppImage from Neovim 0.9 onward

    Neovim Build Prerequisites for each operating system

    Ubuntu/Debian Packages

    Install packages to support building Neovim

    sudo apt-get install ninja-build gettext cmake unzip curl\n

    Clone the Neovim GitHub repository

    git clone --origin neovim https://github.com/neovim/neovim.git\n
    Change into the cloned directory and change to the stable release to build version 0.9.0

    git checkout stable\n

    Build a release

    make CMAKE_BUILD_TYPE=Release                                                                                                              \u2500\u256f\n

    Once the nvim release has been built, create a debian package for use with Ubuntu and Debian systems

    cpack -G DEB\n
    "},{"location":"install/neovim/#post-install-checks","title":"Post Install checks","text":"

    Ensure supporting tools and binaries are available in the operating system by running the Neovim Heath Check.

    nvim in a terminal to run NeoVim and check the installation is working without error.

    :checkhealth to run a check supporting tools are available to NeoVim.

    A report is generated and shown in NeoVim

    j / k to scroll through the checkhealth report

    Review the warnings and install tooling that is required for languages that will be used.

    Ignore Provider Warnings

    It is safe to ignore language provider warnings.

    Language Providers can be disabled in the Neovim configuration to remove the warnings from :checkhealth report. Examples of disabling language provders are in the practicalli/neovim-config-redux configuration, covered in the Neovim Config install step

    "},{"location":"introduction/community-projects/","title":"Community Configuration Projects","text":"

    Practicalli Neovim book covers the following configurations:

    "},{"location":"introduction/community-projects/#practicalli-neovim-config-redux","title":"Practicalli Neovim Config Redux","text":"

    Practicalli Neovim Config Redux

    • Fennel configuration
    • Packer package manager & Treesitter support
    • Mnemonic key bindings
    • Telescope selectors
    • Autocompletion (cmp) & snippets (luasnip)
    • Esc with center row keys, e.g. \"fd\"
    "},{"location":"introduction/community-projects/#astronvim-and-practicalli-astronvim-config","title":"AstroNvim and Practicalli AstroNvim Config","text":"

    AstroNvim and Practicalli AstroNvim Config organised configuration with a polished UI

    • Neovim 9 support
    • Lazy for plugins (packages for Neovim)
    • Mason to manage install for LSP, DAP, lint and format tools
    • Treesitter and language parser support
    • Telescope selectors
    • Notification dialogs
    • Autocompletion (cmp) & snippets (luasnip)
    • Neovim 9 background switch (live toggle light & dark theme)
    • Hidden command line cmdheight=0 (Neovim 0.8 onward)
    • Esc with center row keys, e.g. \"fd\" (user: plugins/core.lua)
    "},{"location":"introduction/community-projects/#alternative-configurations","title":"Alternative configurations","text":"

    Practicalli Neovim does not cover the following Community configurations.

    • Magit Kit fennel configuration from the author of Conjure
    • cajus-nvim inspiration for practicalli/neovim-config-redux
    • LazyVim lazy & mason configuration
    • NvChad polished UI with Lazy optomisations

    Long term project: Fennel config with AstroNvim-like UI experience

    A very long term goal for Practicalli is to create a Neovim configuration written predominatly in Fennel, providing a rich user experience on par with the very polished experience of AstroNvim.

    Lazy and Mason should be used to manage packages and tools (LSP & DAP servers, lint & format tools).

    Which-key should provide a mnemonic menu system similar to the Spacemacs experience.

    "},{"location":"introduction/contributing/","title":"Contributing to Practicalli","text":"

    Practicalli books are written in markdown and use MkDocs to generate the published website via a GitHub workflow. MkDocs can also run a local server using the make docs target from the Makefile

    By submitting content ideas and corrections you are agreeing they can be used in this book under the Creative Commons Attribution ShareAlike 4.0 International license. Attribution will be detailed via GitHub contributors.

    All content and interaction with any persons or systems must be done so with respect and within the Practicalli Code of Conduct.

    "},{"location":"introduction/contributing/#book-status","title":"Book status","text":""},{"location":"introduction/contributing/#submit-and-issue-or-idea","title":"Submit and issue or idea","text":"

    If something doesnt seem quite right or something is missing from the book, please raise an issue via the GitHub repository explaining in as much detail as you can.

    Raising an issue before creating a pull request will save you and the maintainer time.

    "},{"location":"introduction/contributing/#considering-a-pull-request","title":"Considering a Pull request?","text":"

    Before investing any time in a pull request, please raise an issue explaining the situation. This can save you and the maintainer time and avoid rejected pull requests.

    Please keep pull requests small and focused, as they are much quicker to review and easier to accept. Ideally PR's should be for a specific page or at most a section.

    A PR with a list of changes across different sections will not be merged, it will be reviewed eventually though.

    "},{"location":"introduction/contributing/#thank-you-to-everyone-that-has-contributed","title":"Thank you to everyone that has contributed","text":"

    A huge thank you to Rich Hickey and the team at Cognitect for creating and continually guiding the Clojure language. Special thank you to Alex Miller who has provided excellent advice on working with Clojure and the CLI tooling.

    The Clojure community has been highly supportive of everyone using Clojure and I'd like to thank everyone for the feedback and contributions. I would also like to thank everyone that has joined in with the London Clojurins community, ClojureBridgeLondon, Clojurians Slack community, Clojurians Zulip community and Clojureverse community.

    Thank you to everyone who sponsors the Practicalli websites and videos and for the Clojurists Together sponsorship, it helps me continue the work at a much faster pace.

    Special thanks to Bruce Durling for getting me into Cloure in the first place.

    "},{"location":"introduction/features/","title":"Neovim features","text":"

    A clean UI provides for a distraction free development experience, with only the essential information presented in the Neovim statusline or inline with the code

    • Conjure - automatic Clojure REPL connection, evaluation, test runners
    • Treesitter
    • Plug-in Manager (e.g. Lazy.nvim)
    • LSP - auto-completion, snippets, inline linting, reference navigation, refactor and unit test coverage
    • statusline - LSP status, diff changes, filetype, cursor position
    • Selection narrowing completion of files, packages, colour schemes, etc
    • File browser - telescope selection narrowing and visual file system navigation
    • Version Control gutter indicators for changed lines
    • todo comments todo, fix, notes, indicators with gutter icons
    • relative line numbers for vim-style navigation
    "},{"location":"introduction/features/#conjure","title":"Conjure","text":"

    Conjure An interactive environment for evaluating code, e.g. a Clojure REPL. Conjure automatically connects to an nREPL process running in the current project.

    Evaluate Clojure code as its developed for an instant feedback workflow.

    Run unit tests with Kaocha test runner (Cognitect Labs and ClojureScript runners also available)

    Fireplace has been a long-standing plugin for Vim to support Clojure REPL connection.

    "},{"location":"introduction/features/#lazy-plugin-manager","title":"Lazy Plugin manager","text":"

    Lazy.nvim manages neovim plugins with a rich UI that provides an enjoyable user experience. Plugins are automatically installed during startup and lists the status of each plugins.

    Plugins are automatic cached & bytecode compiled and can be lazy loaded to streamline startup time and resource usage based on events, commands, filetypes, and key mappings. Efficient plugin downlaods using partial blobless clones of plugin repositories, i.e. --filter=blob:none

    Lazy.nvim

    "},{"location":"introduction/features/#treesitter","title":"Treesitter","text":"

    Neovim provides highly effective syntax highlighting of source code due to Treesitter.

    Tree-sitter parses files opened in Neovim and builds a concrete syntax tree that any Neovim plugin can use to efficiently provide feedback. Treesitter uses incremental parsing to efficiently update the syntax tree as a file is edited.

    • parse on every keystroke in a text editor
    • provide useful results even in the presence of syntax errors

    Treesitter

    "},{"location":"introduction/features/#language-server-protocol","title":"Language Server Protocol","text":"

    Neovim includes an LSP client which uses the information recieved from a language specific LSP server in real-time to provide a range of services:

    • auto-completion of function and symbol names
    • live linting as code is typed or opened from a file
    • formatting
    • function signatures and help documentation
    • diagnostics (syntax errors & idioms)
    • symantic analysis providing rename through project, go-to-definition & find-references

    LSP feedback is often presented in the buffer, file browser and status line of Neovim.

    LSP Server implementation is not universal

    LSP is a relatively new specification and many server implmentations are still evolving or are yet to be created.

    Lint tools tend to be more prevelent and may be required in concert with or in the absence of an LSP server.

    LSP related Plugins
    • neovim/nvim-lspconfig - connect Neovim lsp client to lsp servers
    • jose-elias-alvarez/null-ls.nvim - hook format and lint tools into the Neovim LSP client
    • jayp0521/mason-null-ls.nvim - automatically install formatters/linters to be used by null-ls
    • williamboman/mason - install and manage LSP servers, DAP servers, linters, and formatters
    • williamboman/mason-lspconfig - register LSP configs with neovim so LSP client can connect to servers
    "},{"location":"introduction/features/#lint-and-format-tools","title":"Lint and format tools:","text":"

    Linters check code for common problems and provide hints on how to correct any detected issues.

    Format tools suppor code to conforming to a specified coding style, typically these run when save-file is run.

    null-ls provides extensive builtin configuration for programming languages and configuration formats. null-ls also passes lint and format tool information to the Neovim LSP client, extending the range of language support.

    "},{"location":"introduction/features/#selection-narrowing","title":"Selection Narrowing","text":"

    telescope.nvim is a highly extendable fuzzy finder over lists with community driven pickers, sorters and previewers.

    Navigate and narrow lists of files, packages, environment variables, ports, colour schemes (themes) and any other list of items effectively.

    Telescope File browser popup also explores the file system and in Normal mode can be used to create files and directories

    The telescope list narrows matches as characters are typed

    "},{"location":"introduction/features/#version-control","title":"Version Control","text":"

    Gitsigns hightlights buffer changes in the gutter

    Lualine shows number of Git changes in status line

    Diffview to review all changes for any git revision

    Neogit provides a rich git client to add, stash, commit, push & pull changes.

    Octo provides a GitHub specific client to manage issues and pull requests, using GitHub CLI authentication.

    LazyGit UI

    "},{"location":"introduction/features/#file-browser","title":"File Browser","text":"

    neo-tree provides a visual file system explorer that can also create and delete files and directories

    "},{"location":"introduction/features/#todo-comments","title":"TODO Comments","text":"

    Highlight tasks, fixes, notes and dragons comments, including icons in the gutter. Use Telescope to navigate TODO comments in the current project.

    "},{"location":"introduction/features/#status-line","title":"Status Line","text":"

    LSP feedback

    "},{"location":"introduction/features/#markdown","title":"Markdown","text":"
    • LSP server
    • Marksman: select anchors and pages for links
    "},{"location":"introduction/fennel/","title":"Fennel","text":"

    Lua is the defacto language for Neovim plugin development and configuration.

    Fennel can be used to write Neovim packages and configuration, using nfnl to generate the equivalent Lua code that Neovim runs.

    Although Neovim fully supports Vimscript, Practicalli encourages Fennel or Lua, as Vimscript is a niche language with quite complex syntax.

    "},{"location":"introduction/fennel/#overview","title":"Overview","text":"

    Fennel is a programming language that brings together the speed, simplicity, and reach of Lua with the flexibility of a lisp syntax and macro system.

    • Full Lua compatibility: Easily call any Lua function or library from Fennel and vice-versa.
    • Zero overhead: Compiled code should be just as efficient as hand-written Lua.
    • Compile-time macros: Ship compiled code with no runtime dependency on Fennel.
    • Embeddable: Fennel is a one-file library as well as an executable. Embed it in other programs to support runtime extensibility and interactive development.

    Anywhere you can run Lua code, you can run Fennel code.

    Translate Lua to Fennel

    See Fennel is an online antifennel tool to convert Lua to Fennel or Fennel to Lua.

    practicalli/neovim-config-redux configuration provides helper functions to minimise the translation required.

    "},{"location":"introduction/fennel/#fennel-packages","title":"Fennel Packages","text":"

    The Conjure package which provides the Clojure REPL (and much more) is written in Fennel.

    "},{"location":"introduction/fennel/#nfnl","title":"nfnl","text":"

    nfnl generates Lua code from Fennel code. Neovim runs the generated Lua code.

    nfnl loads only when working in directories containing a .nfnl.fnl configuration file, so has zero overhead when not working with fennel.

    *.fnl files are automatically compiled to *.lua when changes are saved, showing any compilation errors to provide an effective feedback loop.

    nfnl standard library

    nfnl plugin example

    "},{"location":"introduction/fennel/#development-tooling","title":"Development tooling","text":"

    Neovim support

    • Anti-fennel - convert from Lua code to Fennel code.
    • nfnl - write plugins or configuration for Neovim with great runtime performance
    • hotpot - seamless Fennel inside Neovim

    See Fennel is an online antifennel tool to convert between Lua and Fennel.

    Guide to plugin development with fennel

    Emacs support:

    • technomancy/fennel-mode and Emacs mirror repository
    "},{"location":"introduction/fennel/#playing-games","title":"Playing Games","text":"

    TIC-80 is a simulated computer environment to to write code, design art, compose music and retro style game games.

    L\u00d6VE is a framework for making games with the Lua programming language, allows import from external resources and can use any resolution or memory resources required.

    TIC-80 and L\u00d6VE provide cross-platform support across Windows, Mac and Linux systems. TIC-80 games can also be played in the browser.

    "},{"location":"introduction/repl-workflow/","title":"REPL Driven Development","text":"

    Always be REPL'ing

    Coding without a REPL feels limiting. The REPL provides fast feedback from code as its crafted, testing assumptions and design choices every step of the journey to a solution - John Stevenson, Practical.li

    Clojure is a powerful, fun and highly productive language for developing applications and services. The clear language design is supported by a powerful development environment known as the REPL (read, evaluate, print, loop). The REPL gives you instant feedback on what your code does and enables you to test either a single expression or run the whole application (including tests).

    REPL driven development is the foundation of working with Clojure effectively

    An effective Clojure workflow begins by running a REPL process. Clojure expressions are written and evaluated immediately to provide instant feedback. The REPL feedback helps test the assumptions that are driving the design choices.

    • Read - code is read by the Clojure reader, passing any macros to the macro reader which converts those macros into Clojure code.
    • Evaluate - code is compiled into the host language (e.g. Java bytecode) and executed
    • Print - results of the code are displayed, either in the REPL or as part of the application.
    • Loop - the REPL is a continuous process that evaluates code, either a single expression or the whole application.

    Design decisions and valuable data from REPL experiments can be codified as specifications and unit tests

    Practicalli REPL Reloaded Workflow

    The principles of REPL driven development are implemented in practice using the Practicalli REPL Reloaded Workflow and supporting tooling. This workflow uses Portal to inspect all evaluation results and log events, hot-load libraries into the running REPL process and reloads namespaces to support major refactor changes.

    "},{"location":"introduction/repl-workflow/#evaluating-source-code","title":"Evaluating source code","text":"

    A REPL connected editor is the primary tool for evaluating Clojure code from source code files, displaying the results inline.

    Source code is automatically evaluated in its respective namespace, removing the need to change namespaces in the REPL with (in-ns) or use fully qualified names to call functions.

    Evaluate Clojure in Neovim with Conjure

    , e b evaluates the code in the current buffer

    Evaluate Clojure in a Terminal UI REPL

    Entering expressions at the REPL prompt evaluates the expression immediately, returning the result directly underneath

    "},{"location":"introduction/repl-workflow/#rich-comment-blocks-living-documentation","title":"Rich Comment blocks - living documentation","text":"

    The (comment ,,,) function wraps code that is only run directly by the developer using a Clojure aware editor.

    Expressions in rich comment blocks can represent how to use the functions that make up the namespace API. For example, starting/restarting the system, updating the database, etc. Expressions provide examples of calling functions with typical arguments and make a project more accessible and easier to work with.

    Clojure Rich Comment to manage a service

    (ns practicalli.gameboard.service)\n\n(defn app-server-start [port] ,,,)\n(defn app-server-start [] ,,,)\n(defn app-server-restart [] ,,,)\n\n(defn -main\n  \"Start the service using system components\"\n  [& options] ,,,)\n\n(comment\n  (-main)\n  (app-server-start 8888)\n  (app-server-stop)\n  (app-server-restart 8888)\n\n  (System/getenv \"PORT\")\n  (def environment (System/getenv))\n  (def system-properties (System/getProperties))\n  ) ; End of rich comment block\n

    Rich comment blocks are very useful for rapidly iterating over different design decisions by including the same function but with different implementations. Hide clj-kondo linter warnings for redefined vars (def, defn) when using this approach.

    ;; Rich comment block with redefined vars ignored\n#_{:clj-kondo/ignore [:redefined-var]}\n(comment\n  (defn value-added-tax []\n    ;; algorithm design - first idea)\n\n  (defn value-added-tax []\n    ;; algorithm design - second idea)\n\n  ) ;; End of rich comment block\n

    The \"Rich\" in the name is an honourary mention to Rich Hickey, the author and benevolent dictator of Clojure design.

    "},{"location":"introduction/repl-workflow/#design-journal","title":"Design Journal","text":"

    A journal of design decisions makes the code easier to understand and maintain. Code examples of design decisions and alternative design discussions are captured, reducing the time spent revisiting those discussions.

    Journals simplify the developer on-boarding processes as the journey through design decisions are already documented.

    A Design Journal is usually created in a separate namespace, although it may start as a rich comment at the bottom of a namespace.

    A journal should cover the following aspects

    • Relevant expressions use to test assumptions about design options.
    • Examples of design choices not taken and discussions why (saves repeating the same design discussions)
    • Expressions that can be evaluated to explain how a function or parts of a function work

    The design journal can be used to create meaningful documentation for the project very easily and should prevent time spent on repeating the same conversations.

    Example design journal

    Design journal for TicTacToe game using Reagent, ClojureScript and Scalable Vector Graphics

    "},{"location":"introduction/repl-workflow/#viewing-data-structures","title":"Viewing data structures","text":"

    Pretty print shows the structure of results from function calls in a human-friendly form, making it easier for a developer to parse and more likely to notice incorrect results.

    Tools to view and navigate code

    • Cider inspector is an effective way to navigate nested data and page through large data sets.
    • Portal Inspector to visualise many kinds of data in many different forms.

    "},{"location":"introduction/repl-workflow/#code-style-and-idiomatic-clojure","title":"Code Style and idiomatic Clojure","text":"

    Clojure aware editors should automatically apply formatting that follows the Clojure Style guide.

    Live linting with clj-kondo suggests common idioms and highlights a wide range of syntax errors as code is written, minimizing bugs and therefore speeding up the development process.

    Clojure LSP is build on top of clj-kondo

    Clojure LSP uses clj-kondo static analysis to provide a standard set of development tools (format, refactor, auto-complete, syntax highlighting, syntax & idiom warnings, code navigation, etc).

    Clojure LSP can be used with any Clojure aware editor that provides an LSP client, e.g. Spacemacs, Doom Emacs, Neovim, VSCode.

    Clojure Style Guide

    The Clojure Style guide provides examples of common formatting approaches, although the development team should decide which of these to adopt. Emacs clojure-mode will automatically format code and so will Clojure LSP (via cljfmt). These tools are configurable and should be tailored to the teams standard.

    "},{"location":"introduction/repl-workflow/#data-and-function-specifications","title":"Data and Function specifications","text":"

    Clojure spec is used to define a contract on incoming and outgoing data, to ensure it is of the correct form.

    As data structures are identified in REPL experiments, create data specification to validate the keys and value types of that data.

    ;; ---------------------------------------------------\n;; Address specifications\n(spec/def ::house-number string?)\n(spec/def ::street string?)\n(spec/def ::postal-code string?)\n(spec/def ::city string?)\n(spec/def ::country string?)\n(spec/def ::additional string?)\n\n(spec/def ::address   ; Composite data specification\n  (spec/keys\n   :req-un [::street ::postal-code ::city ::country]\n   :opt-un [::house-number ::additional]))\n;; ---------------------------------------------------\n

    As the public API is designed, specifications for each functions arguments are added to validate the correct data is used when calling those functions.

    Generative testing provides a far greater scope of test values used incorporated into unit tests. Data uses clojure.spec to randomly generate data for testing on each test run.

    "},{"location":"introduction/repl-workflow/#test-driven-development-and-repl-driven-development","title":"Test Driven Development and REPL Driven Development","text":"

    Test Driven Development (TDD) and REPL Driven Development (RDD) complement each other as they both encourage incremental changes and continuous feedback.

    Test Driven Development fits well with Hammock Time, as good design comes from deep thought

    • RDD enables rapid design experiments so different approaches can easily and quickly be evaluated .
    • TDD focuses the results of the REPL experiments into design decisions, codified as unit tests. These tests guide the correctness of specific implementations and provide critical feedback when changes break that design.

    Unit tests should support the public API of each namespace in a project to help prevent regressions in the code. Its far more efficient in terms of thinking time to define unit tests as the design starts to stabilize than as an after thought.

    clojure.test library is part of the Clojure standard library that provides a simple way to start writing unit tests.

    Clojure spec can also be used for generative testing, providing far greater scope in values used when running unit tests. Specifications can be defined for values and functions.

    Clojure has a number of test runners available. Kaocha is a test runner that will run unit tests and function specification checks.

    Automate local test runner

    Use kaocha test runner in watch mode to run tests and specification check automatically (when changes are saved)

    clojure -X:test/watch\n

    "},{"location":"introduction/repl-workflow/#continuous-integration-and-deployment","title":"Continuous Integration and Deployment","text":"

    Add a continuous integration service to run tests and builds code on every shared commit. Spin up testable review deployments when commits pushed to a pull request branch, before pushing commits to the main deployment branch, creating an effective pipeline to gain further feedback.

    • CircleCI provides a simple to use service that supports Clojure projects.
    • GitHub Workflows and GitHub actions marketplace to quickly build a tailored continuous integration service, e.g. Setup Clojure GitHub Action.
    • GitLab CI

    "},{"location":"introduction/repl-workflow/#live-coding-with-data-stuart-halloway","title":"Live Coding with Data - Stuart Halloway","text":"

    There are few novel features of programming languages, but each combination has different properties. The combination of dynamic, hosted, functional and extended Lisp in Clojure gives developers the tools for making effective programs. The ways in which Clojure's unique combination of features can yield a highly effective development process.

    Over more than a decade we have developed an effective approach to writing code in Clojure whose power comes from composing many of its key features. As different as Clojure programs are from e.g. Java programs, so to can and should be the development experience. You are not in Kansas anymore!

    This talk presents a demonstration of the leverage you can get when writing programs in Clojure, with examples, based on my experiences as a core developer of Clojure and Datomic.

    "},{"location":"introduction/writing-tips/","title":"Writing tips for MkDocs","text":"

    Making the docs more engaging using the mkdocs-material theme reference guide

    Configuring Colors

    Material for MkDocs - Changing the colors lists the primary and accent colors available.

    HSL Color Picker for codes to modify the theme style, overriding colors in docs/assets/stylesheets/extra.css

    "},{"location":"introduction/writing-tips/#hypertext-links","title":"Hypertext links","text":"

    Links open in the same browser window/tab by default.

    Add {target=_blank} to the end of a link to configure opening in a new tab

    [link text](url){target=_blank}\n
    "},{"location":"introduction/writing-tips/#buttons","title":"Buttons","text":"

    Convert any link into a button by adding {.md-button} class names to end of the markdown for a link, which uses .md-button-primary by default. Include target=_blank for buttons with links to external sites.

    [link text](http://practical.li/blog){.md-button target=_blank}\n

    Or specify a different class

    [link text](http://practical.li/blog){.md-button .md-button-primary}\n

    Add an icon to the button

    Practicalli Issues Practicalli Blog

    [:fontawesome-brands-github: Practicalli Issues](http://practical.li/blog){ .md-button .md-button-primary }\n[:octicons-heart-fill-24: Practicalli Blog](http://practical.li/blog){ .md-button .md-button-primary }\n

    Search all supported icons

    "},{"location":"introduction/writing-tips/#youtube-video","title":"YouTube video","text":"

    Use an iframe element to include a YouTube video, wrapping in a paragraph tag with center alignment to place the video in a centered horizontal position

    <p style=\"text-align:center\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/rQ802kSaip4\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</p>\n

    mkdocs material does not have direct support for adding a YouTube video via markdown.

    "},{"location":"introduction/writing-tips/#admonitions","title":"Admonitions","text":"

    Supported admonition types

    Note

    Use !!! followed by NOTE

    Adding a title

    Use !!! followed by NOTE and a \"title in double quotes\"

    Shh, no title bar just the text... Use !!! followed by NOTE and a \"\" empty double quotes

    Abstract

    Use !!! followed by ABSTRACT

    Info

    Use !!! followed by INFO

    Tip

    Use !!! followed by TIP

    Success

    Use !!! followed by SUCCESS

    Question

    Use !!! followed by QUESTION

    Warning

    Use !!! followed by WARNING

    Failure

    Use !!! followed by FAILURE

    Danger

    Use !!! followed by DANGER

    Bug

    Use !!! followed by BUG

    Example

    Use !!! followed by EXAMPLE

    Quote

    Use !!! followed by QUOTE

    "},{"location":"introduction/writing-tips/#collapsing-admonitions","title":"Collapsing admonitions","text":"Note

    Collapse those admonitions using ??? instead of !!!

    Replace with a title

    Use ??? followed by NOTE and a \"title in double quotes\"

    Expanded by default

    Use ???+, note the + character, followed by NOTE and a \"title in double quotes\"

    "},{"location":"introduction/writing-tips/#inline-blocks","title":"Inline blocks","text":"

    Inline blocks of text to make a very specific callout within text

    Info

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Adding something to then end of text is probably my favourite

    Info

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    "},{"location":"introduction/writing-tips/#code-blocks","title":"Code blocks","text":"

    Code blocks include a copy icon automatically

    Syntax highlighting in code blocks

    (defn my-function  ; Write a simple function\n  \"With a lovely doc-string\"\n  [arguments]\n  (map inc [1 2 3]))\n

    Give the code block a title using title=\"\" after the backtics and language name

    src/practicalli/gameboard.clj
    (defn my-function\n  \"With a lovely doc-string\"\n  [arguments]\n  (map inc [1 2 3]))\n

    We all like line numbers, especially when you can set the starting line

    src/practicalli/gameboard.clj
    (defn my-function\n  \"With a lovely doc-string\"\n  [arguments]\n  (map inc [1 2 3]))\n

    Add linenums=42 to start line numbers from 42 onward

    clojure linenums=\"42\" title=\"src/practicalli/gameboard.clj\"\n
    "},{"location":"introduction/writing-tips/#annotations","title":"Annotations","text":"

    Annotations in a code block help to highlight important aspects. Use the comment character for the language followed by a space and a number in brackets

    For example, in a shell code block, use # (1) where 1 is the number of the annotation

    Use a number after the code block to add the text for the annotation, e.g. 1.. Ensure there is a space between the code block and the annotation text.

    ls -la $HOME/Downloads  # (1)\n
    1. I'm a code annotation! I can contain code, formatted text, images, ... basically anything that can be written in Markdown.

    Code blocks with annotation, add ! after the annotation number to suppress the # character

    (defn helper-function\n  \"Doc-string with description of function purpose\" ; (1)!\n  [data]\n  (merge {:fish 1} data)\n  )\n
    1. Always include a doc-string in every function to describe the purpose of that function, identifying why it was added and what its value is.

    GitHub action example with multiple annotations

    name: ci # (1)!\non:\n  push:\n    branches:\n      - master # (2)!\n      - main\npermissions:\n  contents: write\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.x\n      - run: pip install mkdocs-material # (3)!\n      - run: mkdocs gh-deploy --force\n
    1. You can change the name to your liking.

    2. At some point, GitHub renamed master to main. If your default branch is named master, you can safely remove main, vice versa.

    3. This is the place to install further [MkDocs plugins] or Markdown extensions with pip to be used during the build:

      pip install \\\n  mkdocs-material \\\n  mkdocs-awesome-pages-plugin \\\n  ...\n
    "},{"location":"introduction/writing-tips/#highlight-lines-in-code-blocks","title":"Highlight lines in code blocks","text":"

    Add highlight line meta data to a code block after the opening backticks and code block language.

    hl_lines=\"2\" highlights line 2 in the codeblock

    hl_lines=\"2 3 4\" highlights line 2, 3 and 4 in the codeblock

    (defn my-function\n  \"With a lovely doc-string\"\n  [arguments]\n  (map\n   inc\n   [1 2 3]))\n
    "},{"location":"introduction/writing-tips/#embed-external-files","title":"Embed external files","text":"

    --8<-- in a code block inserts code from a source code file or other text file

    Specify a local file from the root of the book project (the directory containing mkdocs.yml)

    Scheduled Version Check GitHub Workflow from source code file scheduled version check
    ---\n# ------------------------------------------\n# Scheduled check of versions\n# - use as non-urgent report on versions\n# - Uses POSIX Cron syntax\n#   - Minute [0,59]\n#   - Hour [0,23]\n#   - Day of the month [1,31]\n#   - Month of the year [1,12]\n#   - Day of the week ([0,6] with 0=Sunday)\n#\n# Using liquidz/anta to check:\n# - GitHub workflows\n# - deps.edn\n# ------------------------------------------\n\nname: \"Scheduled Version Check\"\non:\n  schedule:\n    # - cron: \"0 4 * * *\" # at 04:04:04 ever day\n    # - cron: \"0 4 * * 5\" # at 04:04:04 ever Friday\n    - cron: \"0 4 1 * *\" # at 04:04:04 on first day of month\n  workflow_dispatch: # Run manually via GitHub Actions Workflow page\n\njobs:\n  scheduled-version-check:\n    name: \"Scheduled Version Check\"\n    runs-on: ubuntu-latest\n    steps:\n      - run: echo \"\ud83d\ude80 Job automatically triggered by ${{ github.event_name }}\"\n      - run: echo \"\ud83d\udc27 Job running on ${{ runner.os }} server\"\n      - run: echo \"\ud83d\udc19 Using ${{ github.ref }} branch from ${{ github.repository }} repository\"\n\n      - name: \"Checkout code\"\n        uses: actions/checkout@v4\n      - run: echo \"\ud83d\udc19 ${{ github.repository }} repository was cloned to the runner.\"\n\n      - name: \"Antq Check versions\"\n        uses: liquidz/antq-action@main\n        with:\n          excludes: \"\"\n          skips: \"boot clojure-cli pom shadow-cljs leiningen\"\n\n      # Summary\n      - run: echo \"\ud83c\udfa8 library versions checked with liquidz/antq\"\n      - run: echo \"\ud83c\udf4f Job status is ${{ job.status }}.\"\n
    Practicalli Project Templates Emacs project configuration - .dir-locals.el
    ((clojure-mode . ((cider-preferred-build-tool . clojure-cli)\n                  (cider-clojure-cli-aliases . \":test/env:dev/reloaded\"))))\n

    Code example reuse

    Use an embedded local or external file (URL) when the same content is required in more than one place in the book.

    An effective way of sharing code and configuration mutliple times in a book or across multiple books.

    "},{"location":"introduction/writing-tips/#content-tabs","title":"Content tabs","text":"

    Create in page tabs that can also be

    Setting up a project

    Clojure CLILeiningen
    clojure -T:project/new :template app :name practicalli/gameboard\n
    lein new app practicalli/gameboard\n

    Or nest the content tabs in an admonition

    Run a terminal REPL

    Clojure CLILeiningen
    clojure -T:repl/rebel\n
    lein repl\n
    "},{"location":"introduction/writing-tips/#diagrams","title":"Diagrams","text":"

    Neat flow diagrams

    Diagrams - Material for MkDocs

    graph LR\n  A[Start] --> B{Error?};\n  B -->|Yes| C[Hmm...];\n  C --> D[Debug];\n  D --> B;\n  B ---->|No| E[Yay!];

    UML Sequence Diagrams

    sequenceDiagram\n  Alice->>John: Hello John, how are you?\n  loop Healthcheck\n      John->>John: Fight against hypochondria\n  end\n  Note right of John: Rational thoughts!\n  John-->>Alice: Great!\n  John->>Bob: How about you?\n  Bob-->>John: Jolly good!

    state transition diagrams

    stateDiagram-v2\n  state fork_state <<fork>>\n    [*] --> fork_state\n    fork_state --> State2\n    fork_state --> State3\n\n    state join_state <<join>>\n    State2 --> join_state\n    State3 --> join_state\n    join_state --> State4\n    State4 --> [*]

    Class diagrams - not needed for Clojure

    Entity relationship diagrams are handy though

    erDiagram\n  CUSTOMER ||--o{ ORDER : places\n  ORDER ||--|{ LINE-ITEM : contains\n  LINE-ITEM {\n    customer-name string\n    unit-price int\n  }\n  CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
    "},{"location":"introduction/writing-tips/#keyboard-keys","title":"Keyboard keys","text":"

    Represent key bindings with Keyboard keys. Each number and alphabet character has their own key.

    • 1 ++1++ for numbers
    • l ++\"l\"++ for lowercase character
    • U ++u++ for uppercase character or ++\"U\"++ for consistency

    Punctionation keys use their name

    • Space ++spc++
    • , ++comma++
    • Left ++arrow-left++

    For key sequences, place a space between each keyboard character

    • Space g s ++spc++ ++\"g\"++ ++\"s\"++

    For key combinations, use join they key identifies with a +

    • Meta+X ++meta+x++
    • Ctrl+Alt+Del ++ctrl+alt+del++

    MkDocs keyboard keys reference

    "},{"location":"introduction/writing-tips/#images","title":"Images","text":"

    Markdown images can be appended with material tags to set the size of the image, whether to appear on light or dark theme and support lazy image loading in browsers

    SizeLazy LoadingAlignTheme SpecificAll Image Attributes

    {style=\"height:150px;width:150px\"} specifies the image size

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png#only-dark){style=\"height:150px;width:150px\"}\n

    {loading=lazy} specifies an image should lazily load in the browser

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png){loading=lazy}\n

    {aligh=left} or {aligh=right} specifies the page alignment of an image.

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png#only-dark){align=right}\n![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-dark.png#only-light){align=right}\n

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    ![Kitty Logo](image/kitty-light.png#only-dark) or ![Kitty Logo](image/kitty-light.png#only-light) specifies the theme the image should be shown, allowing different versions of images to be shown based on the theme.

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png#only-dark){style=\"height:150px;width:150px\"}\n![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-dark.png#only-light){style=\"height:150px;width:150px\"}\n
    Use the theme toggle in the top nav bar to see the icon change between light and dark.

    Requires the color pallet toggle

    Alight right, lazy load and set image to 150x150

    ![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-light.png#only-dark){align=right loading=lazy style=\"height:64px;width:64px\"}\n![Kitty Logo](https://raw.githubusercontent.com/practicalli/graphic-design/live/icons/kitty-dark.png#only-light){align=right loading=lazy style=\"height:64px;width:64px\"}\n

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

    "},{"location":"introduction/writing-tips/#lists","title":"Lists","text":"

    Task lists

    • Lorem ipsum dolor sit amet, consectetur adipiscing elit
    • Vestibulum convallis sit amet nisi a tincidunt
    • In hac habitasse platea dictumst
    • In scelerisque nibh non dolor mollis congue sed et metus
    • Praesent sed risus massa
    • Aenean pretium efficitur erat, donec pharetra, ligula non scelerisque

    Task List example

    - [x] Lorem ipsum dolor sit amet, consectetur adipiscing elit\n- [ ] Vestibulum convallis sit amet nisi a tincidunt\n    * [x] In hac habitasse platea dictumst\n    * [x] In scelerisque nibh non dolor mollis congue sed et metus\n    * [ ] Praesent sed risus massa\n- [ ] Aenean pretium efficitur erat, donec pharetra, ligula non scelerisque\n
    "},{"location":"introduction/writing-tips/#tooltips","title":"Tooltips","text":"

    The humble tool tip

    Hover me

    with references

    Hover me

    Icon tool tip with a title

    "},{"location":"introduction/writing-tips/#abreviations","title":"Abreviations","text":"

    The HTML specification is maintained by the W3C.

    [HTML]: Hyper Text Markup Language [W3C]: World Wide Web Consortium

    "},{"location":"introduction/writing-tips/#magic-links","title":"Magic links","text":"

    MagicLink can auto-link HTML, FTP, and email links. It can auto-convert repository links (GitHub, GitLab, and Bitbucket) and display them in a more concise, shorthand format.

    Email Practicalli

    Practicalli Neovim

    "},{"location":"neovim-basics/","title":"Using Neovim","text":"

    The fundamental controls of Neovim which apply across all editing tasks.

    "},{"location":"neovim-basics/#fundamentals","title":"Fundamentals","text":"

    File Buffer Window and Tab page Multi-modal Editing

    "},{"location":"neovim-basics/#keyboard-mappings","title":"Keyboard mappings","text":"

    :verbose map followed by a key binding shows the location of the configuration that was last used to set the key mapping. Use when its not clear what command a key mapping is calling or if a plugin is over-riding an expected mapping.

    Space f n to list all notifications and Enter on the relevant notification to see the details.

    :verbose map <C-Up> shows the last place in the neovim config that defines a mapping for Ctrl+Up arrow.

    Listing Mappings: Neovim documentation Key Notation: Neovim documentation

    "},{"location":"neovim-basics/#editing-tools","title":"Editing Tools","text":"

    Multiple Cursors

    "},{"location":"neovim-basics/#writing-tools","title":"Writing Tools","text":"

    Snippets

    "},{"location":"neovim-basics/#development-tools","title":"Development Tools","text":"

    Comments Clojure Development Version Control

    Format and Lint tools are installed via Mason

    "},{"location":"neovim-basics/#spellcheck","title":"Spellcheck","text":"AstroNvim

    SPC u s toggles spellcheck, marking misspelt words with a rew wavy underline

    ] s jumps to next misspelt word, [ s jumps to previous misspelt word,

    z = shows numbered list of possible words, enter the number next to the work to replace the misspelt word.

    z g to add the current word to the spell list, infroming spellcheck that this is a correct word.

    "},{"location":"neovim-basics/comments/","title":"Comments","text":"

    comment.nvim toggles a comment for lines, visual selections or for motions

    gcc comment current line, 4gcc comment current line and next 4 lines

    gc comment region or use with motion e.g. gcap comment paragraph,

    gc in operator pending mode to target a comment TODO: what is operator pending mode

    :7,17Commentary comment a range

    :g/TODO/Commentary as part of a :global invocation

    gcgc removes comments from a set of adjacent commented lines.

    "},{"location":"neovim-basics/file-buffer-window-tab/","title":"Files Buffers Windows and Tabs","text":"

    Files are text written to perminant storage, e.g. disk or usb drive and are names with an extension that represents the file type, e.g. .clj for clojure, .md for markdown, etc.

    A Buffer hold the contents of a file or any other information from processes, e.g. the REPL evaluation log.

    Windows are a view on a buffer and windows can swap which buffer they show. Multiple windows, also known as splits, can be present in a Neovim frame.

    A tab page (or tab) can hold one or more windows and multiple tab pages can be shown on a tab-line.

    "},{"location":"neovim-basics/file-buffer-window-tab/#files","title":"Files","text":"

    Use Neo-tree.nvim to visually navigate and manage files using a tree view of the current project. Files and directories can be added, renamed, moved and deleted.

    Use Telescope to select files, typing a name narrows the file list.

    "},{"location":"neovim-basics/file-buffer-window-tab/#using-neo-tree","title":"Using Neo-tree","text":"AstronvimPracticalli Neovim Config Redux

    Space e toggles neo-tree file browser

    Space o toggles between buffer and neo-tree

    Space f t t to open file explorer

    Within Neo-tree:

    h j k l to navigate the file tree hierachy

    < and > to navigate between File, Bufs and Git sources tabs

    ? shows neotree help, listing key bindings

    a adds a file, prompting for a name relative to the directory where a was pressed. The name can include new directories to be created. A name ending with ++forward-slash++ will create a directory rather than a file.

    d deletes the current file or directory (including sub-directories), a conformation prompt is shown

    r to rename a file or directory (use move to change the path)

    m to move a file or directory, optionally renaming too

    Neotree icons

    • yellow dot - unsaved changes
    • pencil - git added changes
    • cross - git deleted changes
    • Warning triangle - lsp diagnostics issues
    "},{"location":"neovim-basics/file-buffer-window-tab/#telescope","title":"Telescope","text":"

    Telescope provides a selector which will narrow the list of matches as a pattern is typed, providing a fast way to find an item in a list.

    Telescope provides a preview of the selected file (only if there is sufficient space in the Neovim frame)

    File lists are relative to the directory Neovim was opened from (or Path subsequently set in Neovim).

    AstroNvimPracticalli Neovim Config Redux

    SPC f f selector for files within the scope of the current directory path. SPC f F to also show hidden files from the current directory path.

    SPC f a selector for AstroNvim user configuration files

    SPC f p selector for previously opened files (oldfiles)

    SPC f f to list files within the scope of the current directory path.

    SPC f b provides a file browser to open files, navigate the file space and create new files and directories

    "},{"location":"neovim-basics/file-buffer-window-tab/#save-file","title":"Save File","text":"

    Files and directories are created in the path given, relative to the directory in which Neovim was opened.

    A file must exist for Neovim to write to it. Neo-tree and Telescope can be used to create files and directories, as can a terminal and the command line integration (!)

    AstronvimPracticalli Neovim Config ReduxNeovim

    Space w will write all buffer changes to the associate file.

    Space n creates a new buffer that can be written to a given file using :write path/to/filename

    :write path/to/filename will write the current buffer to a new file.

    SPC f b ESC C to create a new file or directory. The base path is shown in the command bar. Type the name of directories and file name as required. RTN to create or ESC to cancel. The newly created directories or file name appears n the Telescope list and scan be selected for opening.

    Telescope Normal mode and help

    ESC in Telescope to switch to Normal mode and use comannds, c for Create, r to rename.

    ? to show all the commands available in Telescope

    :lcd to set the current local directory

    :write path/to/filename will write the current buffer to a new file

    :!mkdir path/to/directory will create a new directory

    If a file is already opened, i.e. with :edit, there is some short-hand syntax to simplify the typing

    :!mkdir -p %:h

    -p option createst any parts of the path required to make the full path

    % is the neovim name of the current file

    :h for the current directory (the \u201chead\u201d of the path).

    ! is the NeoVim terminal shell command, e.g. :!mkdir -p path/to/new/directory creates a new directory and any intermediate path

    "},{"location":"neovim-basics/file-buffer-window-tab/#swap-file","title":"Swap file","text":"

    Neovim creates a swap file, .swp, containing the changes made in a buffer to minimise loss should there be an issue with the computer or Neovim. Changes are written to the swap file after 200 characters or after 4 seconds pause.

    Swap file location

    :swapname shows the full path to the swap file for the current buffer, e.g.

    /home/practicalli/.local/state/astronvim/swap//%home%practicalli%projects%practicalli%books%neovim%docs%neovim-basics%files-buffers-windows.md.swp`\n

    :preserve command will write all text from current buffer to the swap file.

    :recover command overwrites the current buffer with the data from the swap file. :recover! command must be use if the buffer has newer changes than the swap file. Add a filename after the command to recover to a different file than that contained in the current buffer.

    Opening a file checks if there is an associated swap file and prompts the user

    • (A)bort opening the file
    • (D)elete the swap file
    • (E)dit anyway, select if the file is newer than the swap file
    • (R)ecover the data in the swap file into the file buffer

    :edit after the file is open also prompts if there is a swap file. Selecting (D)elete will delete the swap file without changing the current buffer

    "},{"location":"neovim-basics/file-buffer-window-tab/#buffers","title":"Buffers","text":"AstroNvimPracticalli Neovim Config Redux

    SPC f b selector for currently open buffers

    SPC b b to select a buffer from the tab line, pressing the character that appears next to the buffer tab (case sensitive)

    SPC b D to delete a buffer from the tab line, pressing the character that appears next to the buffer tab (case sensitive)

    Open multiple buffers when starting Neovim by specifying multiple files to open

    astro README.md deps.edn src/practicalli/playground.clj test/practicalli/playground.clj\n

    SPC b b switch between buffers in the current window, using a Telescope popup that lists all current buffers (includes files, Conjure REPL Log, etc.).

    SPC b n (:next) and SPC b n (:previous) to cycle through buffers in the current window

    SPC TAB (C-^) opens the previous buffer, useful to toggle between two buffers in the same window

    Use Telescope to switch between buffers

    Open multiple buffers when starting Neovim by specifying multiple files to open

    nvim README.md deps.edn src/practicalli/playground.clj test/practicalli/playground.clj\n
    "},{"location":"neovim-basics/file-buffer-window-tab/#buffer-text-wrapping","title":"Buffer text wrapping","text":"

    The test in a buffer is not wrapped by default. Set and unset soft text wrapping in a buffer

    AstroNvimPracticalli Neovim Config ReduxNeovim

    SPC u w toggles wrapping of text

    line wrap not enabled in configuration by default.

    fnl/config/init.fnl
    (nvim.ex.set :nowrap)\n

    :set wrap to set soft wrapping on current buffer

    :set nowrap to show lines in full (scroll sideways to see lines longer than the window)

    "},{"location":"neovim-basics/file-buffer-window-tab/#windows","title":"Windows","text":"

    Windows can be active (contains the cursor), hidden (open but not shown) or inactive.

    AstroNvimPracticalli Neovim Config ReduxNeovim

    \\ creates an horizontal split

    SPC q removes the current split

    SPC h / SPC l to jump to left / right buffer, SPC j / SPC k to jump to buffer below / above

    SPC b b to list current buffers and switch between them using telescope

    C-w and hjkl to navigate windows is the classic Vim approach

    C-w menu to manage Windows, also known as splits.

    C-w with one of hjkl will move the cursor to the next window in that direction. Also works with arrow keys.

    C-w w toggle between open windows

    :q or C-w q closes the active window, closing Neovim if it is the last active window.

    :wincmd can be used as an alternative to the Normal mode key bindings

    Open file in a new window

    :sp relative-or-full-filename-path\n

    Resize windows

    C-w -, +, < or > for vertical or horizontal size adjustment

    "},{"location":"neovim-basics/file-buffer-window-tab/#tab-pages","title":"Tab pages","text":"

    A Tab page can hold one or more tabs and are useful for grouping different types of files and information.

    A Tab page holds one or more windows, each window is a view on a buffer, a buffer holds the contents of a file or any other information in the editor memory (repl log, etc).

    A tab page can provide a logical grouping of windows, e.g. Clojure source code in one tab, tests in a second tab and REPL log in a third.

    Neovim window commands may be constrained within the bounds of a tab page (without using the :tab modifier)

    Tab pages are often referred to as tabs.

    AstroNvim

    g Tab jump to previously selected tab, commonly used to toggle between two tabs (Practicalli AstroNvim mapping)

    g t jump to next tab page

    g T jump to previous tab page

    "},{"location":"neovim-basics/multi-modal-editing/","title":"Multi-modal Editing","text":"

    TODO: Add multi-modal editing in Neovim guide

    Practicalli Spacemacs has useful reference content on multi-modal editing (Evil mode).

    Most of this content is the same in Neovim with a few exceptions

    "},{"location":"neovim-basics/multi-modal-editing/#selecting-text","title":"Selecting text","text":"

    vi) selects all the text within (), e.g. (http://oldwebsite.doh)

    "},{"location":"neovim-basics/multi-modal-editing/#surround","title":"Surround","text":"

    viw selects the current word, using j/k to modify the selection where required. o toggles which end of the selection is expanded/shrunk

    s substitues the selection, type the characters to surround the selection.

    p to pase the original text

    "},{"location":"neovim-basics/multi-modal-editing/#nvim-surround","title":"nvim-surround","text":"

    nvim-surround provides enhancments over the neovim surround command.

    nvim-surround included in Practicalli AstroNvim Config

    "},{"location":"neovim-basics/multi-modal-editing/#visual-mode","title":"Visual Mode","text":"

    viw to select the current word (visual in word)

    S on a visual selection to surround with next that character, e.g. S) to surround with parens.

    Closing paren surrounds without spaces

    ), ], } surrounds the selected text without spaces between the text and the open and closing parens.

    (, [, { surrounds the selected text with a space between the text and the open and closing parens.

    "},{"location":"neovim-basics/multi-modal-editing/#normal-mode","title":"Normal mode","text":"

    cs inside an existing pair of characters to change them to another pair of surrounding characters, e.g. cs(} to change (text) to {text}

    ds inside a pair of surrounding characters to delete them, e.g. ds( to change (text) to text

    ys you surround followed by motion and character, e.g. ysw) surrounds word with (parens)

    yS to surround current line

    ySS to surround current line, placing characters on new lines, e.g. ySS{ will change \"Olical/conjure\" to:

    {\n    \"Olical/conjure\"\n}\n

    The three \"core\" operations of add/delete/change can be done with the keymaps ys{motion}{char}, ds{char}, and cs{target}{replacement}, respectively. For the following examples, * will denote the cursor position:

    Old text                    Command         New text\n----------------------------------------------------\nsurr*ound_words             ysiw)           (surround_words)\n*make strings               ys$\"            \"make strings\"\n[delete ar*ound me!]        ds]             delete around me!\nremove <b>HTML t*ags</b>    dst             remove HTML tags\n'change quot*es'            cs'\"            \"change quotes\"\n<b>or tag* types</b>        csth1<CR>       <h1>or tag types</h1>\ndelete(functi*on calls)     dsf             function calls\n

    Neovim help provides details on using nvim-surround

    :help nvim-surround.usage\n
    "},{"location":"neovim-basics/multi-modal-editing/#web-links","title":"Web Links","text":"

    g x on a URL to open in the default browser

    "},{"location":"neovim-basics/multi-modal-editing/#markdown","title":"Markdown","text":"

    s in visual mode substitues the selection with the next character typed

    v to create visual selection, s to substitute the current selection, **** to create a bold style, P with the cursor on the second * pastes the text that was visually selected.

    "},{"location":"neovim-basics/multi-modal-editing/#text-style","title":"Text style","text":"

    ysiw* surrounds current word with * to create italic text, . repeats to make bold text style.

    ds* removes * from current word.

    "},{"location":"neovim-basics/multi-modal-editing/#nvim-surround_1","title":"nvim-surround","text":"

    nvim-surround plugin assists with adding style characters around text, e.g adding links, italic or bold text, etc.

    S on a visual selection will surround the text with the next character. . repeat not supported.

    Create a link

    v and motion keys to select text, S [ to surround text with [] creating the text of a link anchor. Use S ( to surround the URL of the link.

    "},{"location":"neovim-basics/multiple-cursors/","title":"Multiple cursors","text":"

    Visual-Multi (VM) is a multiple selections/cursors plugin that uses modal editing and provide visual feedback when editing multiple lines simultaneously.

    Mulitple cursors is generally useful when editing smilarly structured lines with diffferent content. Cursors are moved by column position or by using vim motions.

    AstroNvimPracticalli Neovim Config Redux

    Space g m opens the visual-multi menu

    Using visual select is a simple way to edit multiple lines as the same time.

    Space g m c on visually selected lines creates a cursor on each line.

    Esc or f d to close multiple cursors.

    \\ \\ c creates a cursor at the start of every visual selection line

    \\ \\ \\ toggle cursor at position

    "},{"location":"neovim-basics/multiple-cursors/#search-and-replace","title":"Search and Replace","text":"

    Select a text pattern to search for and use multiple cursors to add a cursor each match, then change each selected occurance concurrently.

    AstroNvimPracticalli Neovim Config Redux

    Select the pattern with visual select

    Space g m a on each matching text pattern in the buffer

    c to change the original text and type the new pattern. All cursors will update concurrently.

    Esc or f d to close multiple cursors.

    \\ \\ a creates a cursor at the start of every visual selection line

    \\ \\ \\ toggle cursor at position

    c to change the original text and type the new pattern. All cursors will update concurrently.

    Esc or f d to close multiple cursors.

    "},{"location":"neovim-basics/multiple-cursors/#command-quick-reference","title":"Command quick reference","text":"

    :help g:VM_maps for a reference of all mappings and instructions on how to change them

    AstroNvim

    SPC g m opens the Visual-Multi menu in normal mode

    g m opens the Visual-Multi menu in visual mode

    c to add a cursor to every line in the visually selected region

    Practicalli Neovim Config Redux

    \\ \\ is the leader for multiple cursors and will show the visual-multi menu in which-key.

    These commands cover the large majority of use cases for multiple cursors.

    Action Key Command Add Cursor at Position \\\\\\ vm-add-cursor Alignm VM cursors with cursor \\\\a vm-align Select All Words \\\\A vm-select-all Transposition \\\\t vm-transpose Toggle Mappings \\\\<Space> vm-mappings-toggle Find with Regex \\\\/ vm-regex-search Reselect Last \\\\gS vm-reselect-last

    Once visual-multi has started the vm-mappings-buffer mappings are available:

    Action Key Command Find Word <C-n> vm-find-word Next/Previous/Skip n / N / q vm-find-next Remove Region Q vm-remove-region Add Cursors Down/Up <C-Down> / <C-Up> vm-add-cursors Select Right/Left <S-Right>, <S-Left> vm-shift-select Slash motion g/ vm-slash Select Operator s vm-select-operator Find Operator m vm-find-operator

    NOTE: C-n conflicts with the Termux binding for naming a session

    "},{"location":"neovim-basics/multiple-cursors/#searching","title":"Searching","text":"

    g/ to search for a match to add when visual-multi is active, rather than the usual / vim search.

    n and N can't be used to repeat the search, as they are used to get the next visual-multi match.

    "},{"location":"neovim-basics/multiple-cursors/#find-with-regex","title":"Find with Regex","text":"

    \\ \\ / followed by a regex pattern will create a selection with that pattern.

    n and N finds the next occurrence of the regex pattern

    "},{"location":"neovim-basics/multiple-cursors/#smart-case-change","title":"Smart case change","text":"

    gc In extend-mode will use smartcase to change a selection

    • at main cursor, text is always inserted as typed
    • at other cursors, if region text was fully uppercased, replacement will be uppercased as well
    • if the region text was capitalized, the replacement will be as well
    "},{"location":"neovim-basics/multiple-cursors/#filter-regions","title":"Filter regions","text":"

    \\ \\ f filter out (remove) regions based on pattern or expression.

    C-x to cycle filtering method:

    • pattern: remove regions that don't match the pattern
    • !pattern: remove regions that match the pattern
    • expression: remove regions that don't match the expression (same as below)
    "},{"location":"neovim-basics/multiple-cursors/#transform-regions-with-expression","title":"Transform regions with expression","text":"

    \\ \\ e to transform a region with a vim expression, run on each region

    Placeholders can be used in the expression

    • `%t~ region's text as a string (as-is)
    • `%f~ region's text evaluated as a floating point number
    • `%n~ region's text evaluated as an integer number
    • `%i~ region's index
    • `%N~ total number of regions

    Examples: - %f * 0.5 divide text of all regions by 2 - %t .\" \". %i .\" / \". %n append index / total to text of each region - %i%2 ? %t : toupper(%t) uppercase all odd regions (1,3,5...) - %i%3-2 ? %t : '' delete every third region

    "},{"location":"neovim-basics/multiple-cursors/#vm-motions","title":"VM Motions","text":"

    visual-multi supports vim motions although they behave differently as their result is dependent on the mode:

    • cursor mode will move cursors
    • extend mode motions extend selections

    Unless multiline-mode is enabled motions are restricted to the current line and cannot cross line boundaries

    Some object-motions and various-motions require multiline-mode and aliased to avoid conflict with VM mappings:

    vim VM~ Description / g/ to next match (for all regions) ( ( [count] sentences backward ) ) [count] sentences forward { { [count] paragraphs backward } } [count] paragraphs forward [( g( go to [count] previous unmatched '(' [{ g{ go to [count] previous unmatched '{' ]) g) go to [count] next unmatched ')' ]} g} go to [count] next unmatched '}'"},{"location":"neovim-basics/multiple-cursors/#vm-operators","title":"vm-operators","text":"

    Visual-Multi supports several operators by default:

    • y / d / c to yank / delete / change
    • gu / gU to change text case

    Visual-Multi uses its own registers that are lists of strings. One element for each region that is yanked/deleted.

    There is also built-in support for:

    • vim-surround e.g. ysiw( to enclose in parentheses
    • vim-abolish e.g. cr_ to change current word to snake case

    `:help g:VM_user_operators to disccover how to doefine other operators

    "},{"location":"neovim-basics/multiple-cursors/#vm-multiline-mode","title":"vm-multiline-mode","text":"

    In normal and insert mode, cursors and selections are kept within their own line. Cursors are blocked from moving off the current line to the next line.

    M enables multiline-mode that allows cuursors to move onto another line.

    Multiline mode must be enabled for an object motions, or they will fail. See |vm-motions|.

    "},{"location":"neovim-basics/multiple-cursors/#alignment","title":"Alignment","text":"

    \\\\a aligns by setting the minimum column to the highest of all regions \\\\< aligns by character, or [count] characters \\\\> aligns by regex pattern

    In extend-mode selections are collapsed to cursors first, although will work regardless.

    "},{"location":"neovim-basics/multiple-cursors/#replace-pattern-in-regions","title":"Replace pattern in regions","text":"

    R to replace with a pattern and then the replacement text

    substitution will take place in all selected regions, leaving unselected text untouched.

    Only working in |extend-mode|. When |R| is pressed in |cursor-mode|, it will start |vm-replace-mode| instead.

    "},{"location":"neovim-basics/multiple-cursors/#subtract-pattern-from-regions","title":"Subtract pattern from regions","text":"

    \\\\s subtract the entered pattern from regions, splitting them. Only working in |extend-mode|.

    "},{"location":"neovim-basics/multiple-cursors/#transposition","title":"Transposition","text":"

    \\ \\ t swaps the contents of selections, cycling them if there are more than two.

    If there is an equal number of selections in each line, swapping takes place within the same line only. Only in |extend-mode|.

    "},{"location":"neovim-basics/multiple-cursors/#duplication","title":"Duplication","text":"

    \\ \\ d duplicates in place the contents of the selections, reselecting the original ones. Only in extend-mode.

    "},{"location":"neovim-basics/multiple-cursors/#shift-selections","title":"Shift Selections","text":"

    and move the selections right or left, preserving the surroundings."},{"location":"neovim-basics/multiple-cursors/#case-conversion","title":"Case conversion","text":"

    \\\\C runs on inner words in cursor mode

    • u lowercase
    • U UPPERCASE
    • C Captialize
    • t Title Case
    • c camelCase
    • P PascalCase
    • s snake_case
    • S SNAKE_UPPERCASE
    • - dash-case
    • . dot.case
    • <space> space case
    "},{"location":"neovim-basics/multiple-cursors/#modes","title":"Modes","text":"

    cursor-mode and extend-mode are two Visual-Multi modes, roughly corresponding to normal-mode and visual-mode

    TAB switches between cursor-mode and extended-mode

    "},{"location":"neovim-basics/multiple-cursors/#vm-cursor-mode","title":"VM Cursor Mode","text":"

    cursor-mode commands expect a motion, e.g. c should be followed by a text object to be changed.

    Key Description operators see vm-operators motions see vm-motions | set column for all cursors (to current column or [count]) r replace single character R enter vm-replace-mode ~ change case of single character & repeat last substitution <C-A> increase numbers <C-X> decrease numbers g<C-A> progressively increase numbers (v_g_CTRL-A) g<C-X> progressively decrease numbers (v_g_CTRL-X)

    You can enter |insert-mode| with i, I, a, A, and only from cursor mode also with o and O.

    Also see vm-motions for supported motions in VM (some with differences).

    "},{"location":"neovim-basics/multiple-cursors/#vm-extend-mode","title":"VM Extend Mode","text":"

    extend-mode is like having multiple visual selections. motions extend the slections and change / yank / delete commands don't wait for a motion, just like in visual mode.

    Even the key o works as in visual mode, inverting the anchor of the selections.

    Some commands are specific to |extend-mode|, such as:

    • s vim-surround
    • R replace pattern in regions
    • \\\\s split regions by pattern
    • \\\\e transform regions text with vim expression

    Some commands enforce cursor-mode when run from extend-mode:

    • <C-A> increase numbers
    • <C-X> decrease numbers

    Others can use a different mapping:

    • gu/gU change case (instead of vim u / U)
    • o and O mappings are used to invert the facing of the selected regions and not to start insert mode.
    "},{"location":"neovim-basics/notifications/","title":"Notifications","text":"Notifications only in AstroNvim, not the Practicalli Neovim configuration

    Space f n lists the history of notifications for the current sesion

    Enter to open the highlighted item in the list in its own popup

    Notification popups show information, warnings and errors.

    "},{"location":"neovim-basics/notifications/#configure-notifications","title":"Configure notifications","text":"

    Notifications are controlled by nvim-notify

    Practicalli astronvim-config overrides several default values in plugins/core.lua

    • top_down position of notifications, false shows popups from bottom of screen
    • timeout value controls how long a popup displays, defautl 3000
    • level of information displayed, level 3 hides less important information, e.g. file write messages, default 5

    Practicalli Configuration for notifications

    plugins/core.lua
      -- Configure notify popups\n  {\n    \"rcarriga/nvim-notify\",\n    opts = {\n      top_down = false,\n      timeout = 1000,\n      -- log level - 3 hide file write messages - default 5\n      level = 3,\n      -- background_color = \"#000000\",\n    },\n  },\n

    Noice uses nvim-notify configuration

    Noice replaces the UI for messages, command line and popup menus, although uses the configuration of nvim-notify for position and popup timing.

    "},{"location":"neovim-basics/plugin-manager/","title":"Plugin Manager","text":"

    Neovim community provides a wide range of plugins to greatly extend the features of Neovim

    There is a wide range of plugin managers too, including a built-in plugin manager in Neovim.

    • Lazy - AstroNvim Config
    • Packer - Practicalli Neovim Config Redux

    Lazy plugin manager recommeded

    Practicalli recommends Lazy plugin manager as it feels much easier to use and has a more engaing and understandable user interface

    Neovim evolving

    Neovim and its plugins are evolving quite rapidly, so it is recommended to update plugins if there are issue or when a newer version of Neovim has been installed

    Plugin issue are not that common and typically fixed quite quickly by the community

    AstroNvimPracticalli Neovim Config Redux

    Lazy plugin manager

    SPC P u to update packages to their latest versions (:PackerUpdate). Details of updated changes will be shown at the end of the update.

    r in the package update screen gives the option to revert an update if something has gone wrong (although this seem to be a rare issue).

    When packages are all at the latest available version, Packer update reports packages already up to date.

    Packer downloads packages and documentation from the Internet, so a connection is required

    "},{"location":"neovim-basics/plugin-manager/#package-list-and-documentation","title":"Package List and documentation","text":"AstroNvimPracticalli Neovim Config Redux

    Lazy plugin manager

    SPC P l to list the current packages added to the configuration

    Selecting a package will display the website documentation for the package (although this may be in HTML so not the cleanest way to read the docs).

    "},{"location":"neovim-basics/plugin-manager/#adding-packages","title":"Adding packages","text":"AstroNvimPracticalli Neovim Config Redux

    Lazy plugin manager

    Add package names as keywords in the use expression in fnl/config/plugin.fnl file.

    :requires to add a package that is a dependency for the package being added

    :mod defines the namespace that contains the package configuration, typically a setup function with options. The namespace matches the file name under fnl/config/plugin

    SPC P i to install packages that have been added to fnl/config/plugin.fnl

    q to quit once all packages are up to date

    "},{"location":"neovim-basics/search-replace/","title":"Search and Replace","text":"

    :substitute or :s vim command will highlight the matches for a text pattern and substitute for a new pattern

    Built-in help for the command

    :help :substitute\n
    Multiple cursors can also be used for multiple substitutions

    multiple cursors created on each occurance can be used to search and replace a pattern

    Subsitute the first matching patterns in the current line

    :s/current-pattern/new-pattern\n

    Subsitute all the matching patterns in the current line, g representing all occurances in a line

    :s/current-pattern/new-pattern/g\n

    Use % to specify the current buffer as the scope to change all matches

    :%s/current-pattern/new-pattern/g\n
    "},{"location":"neovim-basics/snippets/","title":"Snippets","text":"

    LuaSnip can use several different sources for snippets

    • VSCode JSON snippets (Friendly-snippets)
    • LSP style snippets
    LuaSnip Configuration

    Practicalli Neovim Config Redux includes the LuaSnip package which also adds friendly-snippets and cmp_luasnip.

      ; snippets\n  :L3MON4D3/LuaSnip \n  {:requires [:rafamadriz/friendly-snippets\n              :saadparwaiz1/cmp_luasnip]\n   :mod :lua-snip}\n
    Configure LSP snippet locations
    {\n  \"name\": \"practicalli-snippets\",\n  \"engines\": {\n    \"vscode\": \"^1.11.0\"\n  },\n  \"contributes\": {\n    \"snippets\": [\n      {\n        \"language\": [\n          \"markdown\",\n          \"global\",\n          \"all\"\n        ],\n        \"comment\": \"snippets accross several languages\",\n        \"path\": \"./global.json\"\n      },\n      {\n        \"language\": \n          \"markdown\",\n        \"path\": \"./markdown.json\"\n      }\n    ]\n  }\n}\n

    "},{"location":"neovim-basics/snippets/#snippet-definitions","title":"Snippet Definitions","text":"

    snippets directory contains snippet definitions, with a JSON file for each language, e.g. markdown.json

    Practicalli Neovim Config Redux contains several groups of snippet definitions

    • MkDocs format and icons (markdown.json VSCode syntax)

    Restart Neovim to load new defintions

    Snippets added to VSCode JSON snippets are only loaded when Neovim starts, so newly added snippets will only be available after Neovim is restarted.

    "},{"location":"neovim-basics/terminal/","title":"Terminal","text":"

    akinsho/toggleterm.nvim plugin provides a terminal session within Neovim, using a float, split or tab.

    AstroNvim

    SPC t for the Terminal sub-menu

    SPC t f opens a terminal in a floating window, useful for one-off commands

    SPC t h opens a terminal in a horizontal split, useful for a process that prints valuable feedback, e.g. a test runner in watch mode

    SPC t t opens a terminal in a tab, useful for background processes that do not need attendtion

    "},{"location":"neovim-basics/zen-mode/","title":"Focus Modes","text":"

    Focus on the code or text being created, without distractions

    zZ toggles Zen mode

    SPC z a ataraxis focus mode

    SPC z f focus current buffer

    SPC z n narrow to current buffer

    SPC z n remove status bar and window decorations

    v SPC z n narrow to selection

    "},{"location":"neovim-basics/zen-mode/#zen-mode","title":"Zen Mode","text":"

    Zen Mode distraction-free coding for Neovim

    Available via the Astrocommunity repository.

    Zen Mode configuration for AstroNvim

    .config/astronvim-config/plugins/community.lua
      { import = \"astrocommunity.editing-support.zen-mode-nvim\" },\n  {\n    \"folke/zen-mode.nvim\",\n    opts = {\n      -- override default configuration\n      -- https://github.com/folke/zen-mode.nvim#%EF%B8%8F-configuration\n      plugins = {\n        options = {\n          enabled = true,\n        },\n        kitty = {\n          enabled = true,\n          font = \"+4\", -- font size increment\n        },\n      },\n    },\n  },\n

    kitty configuration enables Zen Mode to resize kitty fonts.

    "},{"location":"neovim-basics/zen-mode/#true-zen","title":"True Zen","text":"

    true-zen.nvim clean and elegant distraction-free writing for NeoVim

    True Zen Mode configuration for AstroNvim

      {\n    \"Pocco81/true-zen.nvim\",\n    lazy = false,\n    opts = {\n      integrations = {\n        kitty = {\n          -- increment font size in Kitty.\n          enabled = true,\n          font = \"+4\",\n        },\n      },\n    },\n  },\n

    See kitty configuration to enable Zen Mode to resize kitty fonts.

    "},{"location":"neovim-basics/zen-mode/#kitty-configuration","title":"Kitty configuration","text":"

    Add allow_remote_control socket-only and listen_on unix:/tmp/kitty to the kitty config

    Kitty support for Zen Mode

    .config/kitty/kitty.config
    # ---------------------------------------------------------\n#  Neovim zen-mode-nvim\n#  - change the font size on kitty when in zen mode\nallow_remote_control socket-only\nlisten_on unix:/tmp/kitty\n# ---------------------------------------------------------\n
    "},{"location":"reference/lua-language/","title":"Lua","text":"

    Lua is the default language for Neovim configuration.

    "},{"location":"reference/lua-language/#learning-lua","title":"Learning Lua","text":"

    Neovim Lua introduction

    Lua.org - Programming in Lua (first edition)

    Codecademy - learn lua course

    "},{"location":"reference/lua-language/#reference","title":"Reference","text":"

    Lua.org 5.4 Reference Manual

    "},{"location":"reference/neovim/","title":"Neovim Reference","text":"
    • Language Providers
    • Key mappings
    "},{"location":"reference/neovim/language-providers/","title":"Language Providers","text":"

    Neovim delegates some features to language providers.

    :checkhealth command in Neovim shows if the binaries and tools required by each provider are available in the operating system.

    Resolve the issue with providers that generate a warning in the checkhealth report, following the ADVICE steps provided.

    "},{"location":"reference/neovim/language-providers/#disable-language-providers","title":"Disable Language Providers","text":"

    If a language is not used with Neovim, then its provider can be disabled. Details on how to disable a provider are included at the end of the ADVICE in the report section for that provider.

    Disable language providers in the init.lua configuration file

    init.lua
    -- Disable Language providers\nvim.g.loaded_node_provider = 0       --- (1)!\nvim.g.loaded_perl_provider = 0\nvim.g.loaded_python3_provider = 0\nvim.g.loaded_ruby_provider = 0\n
    1. Example configuration to disable providers is provided in the practicalli/neovim-config-redux configuration

    Ignore Language Provider warnings

    If the programming language is not used, there are no issues with using Neovim if the warnings are simply ignored

    "},{"location":"reference/neovim/standard-path/","title":"Neovim Standard Path","text":"

    View the standard paths used by Neovim using the help menu

    :help standard-path\n

    Output of command

    Standard Paths                  *standard-path*\n\nNvim stores configuration, data, and logs in standard locations. Plugins are\nstrongly encouraged to follow this pattern also. Use |stdpath()| to get the\npaths.\n\n                        *base-directories* *xdg*\nThe \"base\" (root) directories conform to the XDG Base Directory Specification.\nhttps://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\nThe $XDG_CONFIG_HOME, $XDG_DATA_HOME, $XDG_RUNTIME_DIR, and $XDG_STATE_HOME\nenvironment variables are used if defined, else default values (listed below)\nare used.\n\nCONFIG DIRECTORY (DEFAULT) ~\n                  *$XDG_CONFIG_HOME*            Nvim: stdpath(\"config\")\n    Unix:         ~/.config                   ~/.config/nvim\n    Windows:      ~/AppData/Local             ~/AppData/Local/nvim\n\nDATA DIRECTORY (DEFAULT) ~\n                  *$XDG_DATA_HOME*              Nvim: stdpath(\"data\")\n    Unix:         ~/.local/share              ~/.local/share/nvim\n    Windows:      ~/AppData/Local             ~/AppData/Local/nvim-data\n\nRUN DIRECTORY (DEFAULT) ~\n                  *$XDG_RUNTIME_DIR*            Nvim: stdpath(\"run\")\n    Unix:         /tmp/nvim.user/xxx          /tmp/nvim.user/xxx\n    Windows:      $TMP/nvim.user/xxx          $TMP/nvim.user/xxx\n\nSTATE DIRECTORY (DEFAULT) ~\n                  *$XDG_STATE_HOME*             Nvim: stdpath(\"state\")\n    Unix:         ~/.local/state              ~/.local/state/nvim\n    Windows:      ~/AppData/Local             ~/AppData/Local/nvim-data\n\nNote: Throughout the user manual these defaults are used as placeholders, e.g.\n\"~/.config\" is understood to mean \"$XDG_CONFIG_HOME or ~/.config\".\n\nLOG FILE                    *$NVIM_LOG_FILE* *E5430*\nBesides 'debug' and 'verbose', Nvim keeps a general log file for internal\ndebugging, plugins and RPC clients. >\n    :echo $NVIM_LOG_FILE\nBy default, the file is located at stdpath('log')/log unless that path\nis inaccessible or if $NVIM_LOG_FILE was set before |startup|.\n
    "},{"location":"reference/vim-style/","title":"Reference: Learn Vim-style Editing","text":"

    Learning vim-style multi-modal editing takes time and practice. Most importantly this approach can be learned in stages, as insert mode is the same editing experience as using most other editors.

    Start with the multi-modal concept and the basics of navigation. Then adopt more normal and visual mode actions, including motions

    "},{"location":"reference/vim-style/#getting-started","title":"Getting started","text":"

    :Tutor runs the intteractive tutorial built into neovim (:help tutor also runs the tutor)

    vim adventures isa simple online game to teach you the fundamentals of vim-style editing.

    "},{"location":"reference/vim-style/#navigation-and-searching","title":"Navigation and searching","text":"
    • moving the cursor
    • Motions
    • line numbers
    • jumping around a buffer
    • search and replace
    "},{"location":"reference/vim-style/#text-wrangling","title":"Text wrangling","text":"
    • iedit
    • text case
    "},{"location":"reference/vim-style/#clojure-editing","title":"Clojure Editing","text":"

    traversing expressions structural editing

    "},{"location":"reference/vim-style/case/","title":"Modifying text case","text":"

    Convert Characters and regioins to upper or lower case text.

    "},{"location":"reference/vim-style/case/#toggle-case-with-visual-select","title":"Toggle case with visual select","text":"

    v to visually select a character or use the vim motion keys to select a region

    U to uppercase current character or selected region

    u to lowercase current character or selected region

    ~ to toggle the case of the text in the selected region

    . will repeat the previous selection size and case toggle

    "},{"location":"reference/vim-style/case/#toggle-case-menu","title":"Toggle case menu","text":"

    Toggle the current character using vim motion keys, without needing to select a region.

    g ~ opens the toggle case menu

    TODO: Add screenshot of g ~ toggle case menu

    g ~ ~ uppercase current line (also works for RET and maybe other none-menu characters, but not SPC)

    "},{"location":"reference/vim-style/case/#cheatsheet","title":"Cheatsheet","text":"
    • ~ Changes the case of current character
    • guu Change current line from upper to lower.
    • gUU Change current LINE from lower to upper.
    • guw Change to end of current WORD from upper to lower.
    • guaw Change all of current WORD to lower.
    • gUw Change to end of current WORD from lower to upper.
    • gUaw Change all of current WORD to upper.
    • g~~ Invert case to entire line
    • g~w Invert case to current WORD
    • guG Change to lowercase until the end of document.
    • gU) Change until end of sentence to upper case
    • gu} Change to end of paragraph to lower case
    • gU5j Change 5 lines below to upper case
    • gu3k Change 3 lines above to lower case
    "},{"location":"reference/vim-style/g-menu/","title":"Evil G menu","text":"

    g` in normal mode opens a menu of convenient utilities. Practicalli uses this menu to comment existing lines, jumping to top or bottom of the buffer and changing text case.

    "},{"location":"reference/vim-style/g-menu/#comment-lines-and-regions","title":"Comment lines and regions","text":"

    g c c will comment the current line using the buffer major mode comment character(s). A prompt will ask if no comment character is set for the major mode.

    g c with a selected region will comment all lines with the major mode comment character(s)

    "},{"location":"reference/vim-style/g-menu/#jumping-around","title":"Jumping around","text":"

    g g jumps to the top of the buffer, g G to the bottom of the buffer

    g d to jump to the source code of a function definition, g D to open that in a different window.

    g f to jump to file name under cursor (if file exists).

    "},{"location":"reference/vim-style/g-menu/#changing-text-case","title":"Changing text case","text":"

    g u to change the current character or selection to lowercase, g U for uppercase.

    Toggle case with ~

    ~ will toggle the case of the current character or selected region.

    "},{"location":"reference/vim-style/key-binding-reference/","title":"Evil Keybinding Reference","text":"

    An alphabetically ordered reference of Vim-style key bindings.

    "},{"location":"reference/vim-style/key-binding-reference/#normal-mode-keybindings","title":"Normal mode keybindings","text":"

    Keybindings available in Evil normal mode and the resultant state they leave you in.

    Keybinding Description State @ execute keyboard macro (defined by q) Normal ' jump to mark (defined by m) Normal a append text after cursor Insert a append text after cursor Insert A append text to end of sentence Insert b move cursor back to start of previous word Normal B move cursor back to start of last word Normal c change (use with modifier) Insert C change rest of sentence Insert d delete (use with modifier) Normal D delete rest of sentence Normal e end of word Normal E end of word (seems same as above) Normal f find character forward (type character) Normal F find character backward (type character) Normal fd Escape (press almost together) Normal g go menu Normal G Jump to end of buffer Normal h move cursor left Normal H move cursor to top of buffer Normal i insert text Insert I insert text at start of sentence Insert j Move cursor down a line Normal J Join next line to end of current Normal k Move cursor up a line Normal K spacemacs/evil-smart-doc-lookup Normal l Move cursor right Normal L Move cursor to bottom of buffer Normal m Create marker (next character is marker name) Normal M Jump to middle of buffer Normal n Next search occurrence Normal N Previous search occurrence Normal o New line below Insert O New line above Insert p Paste (after / below cursor) Insert P Paste (before / above cursor) Insert q Record keyboard macro attached to given character Normal Q undefined Normal r Replace character under cursor Normal R Replace character state Replace s Substitute character Insert S Substitute current line Insert t Find character forward - cursor before character Normal T Find character backward - cursor after character Normal u Undo last change (C-R to redo) Normal U Undefined Normal v Visual select Visual V Visual select sentence Visual w Jump cursor to start of next word Normal W Jump cursor to start of next word Normal x Delete character under cursor Normal X Delete character backwards Normal y y Yank (copy) line Normal Y Yank (copy) line Normal z Menu - code folding / keyboard macros Normal"},{"location":"reference/vim-style/motions/","title":"Motions","text":"

    Todo

    Moving the cursor around by context rather than individual characters

    "},{"location":"reference/vim-style/moving-around/","title":"Moving around the cursor","text":"

    Scrolling is quite inefficient in most editors and moving (jumping) the curor around is far more effective.

    Using the h j k l as a common part of navigation provides consistency and keeps fingers on the most convienient part of the keyboard.

    "},{"location":"reference/vim-style/moving-around/#moving-by-charater","title":"Moving by charater","text":"

    h j k l keys move the cursor once character or can be used with numbers to move further.

    • h move left (often used to move up a path or tree, e.g. a directory path)
    • j move down
    • k move up
    • l move right (often used to move down a path or tree, e.g. a directory path)
    "},{"location":"reference/vim-style/moving-around/#moving-with-numbers","title":"Moving with numbers","text":"

    : followed by a number then one of h j k l keys will move the cursor that number in the director of the key.

    3j will move 3 lines down the buffer (or to the end of the fuffer if there are fewer lines remaining)

    Using Relative line numbers showws how far each line is from the current line. The practicalli/neovim-config sets :relativenames true in fnl/config/init.fnl.

    42l moves 42 charaters to the right

    moving by motions avoids the need to count characters

    "},{"location":"reference/vim-style/moving-around/#moving-around-the-buffer","title":"Moving around the buffer","text":"

    g g to jump to the top of the current buffer

    G to jump to the bottom of the buffer

    z z moves the current line and cursor to the middle of the window

    z t moves the current line and cursor to the top of the window

    z t moves the current line and cursor to the bottom of the window (or as far as the buffer will move in the window)

    "},{"location":"reference/vim-style/narrowing/","title":"Narrowing","text":"

    Narrowing to a region enables vim commands to be applied to a specific part of the current buffer, rather than the whole buffer.

    Common examples include - replacing local variables within a specific function (avoiding affecting other function definitions)

    "},{"location":"reference/vim-style/narrowing/#nrrwrgn-plugin","title":"NrrwRgn plugin","text":"

    [NrrwRgn plugin] is inspired by the Narrowing feature of Emacs and means to focus on a selected region while making the rest inaccessible.

    SPC n r opens a select region in a new split window. The original buffer is protected from changes.

    :w to write changes in the narrowed window to the original buffer

    "},{"location":"reference/vim-style/narrowing/#commands","title":"Commands","text":"

    :NR - Open the selected region in a new narrowed window :NW - Open the current visual window in a new narrowed window :WR - (In the narrowed window) write the changes back to the original buffer. :NRV - Open the narrowed window for the region that was last visually selected. :NUD - (In a unified diff) open the selected diff in 2 Narrowed windows :NRP - Mark a region for a Multi narrowed window :NRM - Create a new Multi narrowed window (after :NRP) - experimental! :NRS - Enable Syncing the buffer content back (default on) :NRN - Disable Syncing the buffer content back :NRL - Reselect the last selected region and open it again in a narrowed window

    Appending ! to most commands opens the narrowed part in the current window instead of a new window.

    :WR! closes the narrowed window in addition to writing to the original buffer.

    "},{"location":"reference/vim-style/narrowing/#documentation","title":"Documentation","text":"

    :help NarrowRegion to view the documetation on the NrrwRgn plug use

    "},{"location":"reference/vim-style/narrowing/#attention","title":"Attention","text":"

    :NRM is described as experimental by the project readme.

    "},{"location":"reference/vim-style/speaking-vim/","title":"Learning to speak Vim","text":"

    Neovim is easier to learn and gain much more benefit from if you learn to speak commands as sentences.

    First learn some verbs:

    • c change
    • d delete
    • g go,
    • v visual select
    • y yank (copy)

    Then use those verbs with some modifiers

    • ' mark
    • { } beginning/end of paragraph
    • 0 start of line
    • ^ first non white-space character of line
    • $ end of line
    • a around
    • f find (includes character)
    • i inside a range (e.g. word, paren,)
    • s surround
    • t till (move just before specified character)

    Then learn the text objects you can apply verbs and modifiers too

    • b block/parentheses
    • p paragraph,
    • s sentence
    • t tag e.g. html/xml
    • w word
    "},{"location":"reference/vim-style/speaking-vim/#examples-of-speaking-vim","title":"Examples of speaking Vim","text":"

    Practice speaking evil with these examples

    Keybinding Description c i s change inside current sentence (change the whole sentence) c i \" change inside double quotes c f ) change from cursor to next ) character c s ' \" change by the surrounding single quotes with double quotes c t X change till the character X (not including X) c /foo change until the first search result of \u2018foo\u2019 d d delete current line D delete current line from cursor onward d i w delete inside the current word (delete word) v t SPC visual select till the next Space character v s ] visually select and surround with [] without spaces v s [ as above with [ ] with spaces between parens and content g v go to last visual selection (select last visual selection) v a p visually select around current paragraph v i w S \" visually select, insert around current word, and surround with quotes y y yank (copy) current line y w yank (copy) current word y @ a yank (copy) to mark a (m a creates a mark called a)"},{"location":"reference/vim-style/vim-quick-reference/","title":"Neovim Quick Reference","text":"

    A reference of the most common keybindings available in Vim Normal mode. Spacemacs DOCUMENTATION key bindings section contains full details

    . repeats the last keybinding sequence used in Vim Normal mode or a change made within a complete Vim Insert session.

    "},{"location":"reference/vim-style/vim-quick-reference/#moving-around","title":"Moving around","text":"

    In Normal mode you can keep your fingers resting on the main row of your keyboard to move around.

    Key action j move cursor down one line k move cursor up one line l move cursor right one character h move cursor left one character

    In menus such as helm you can move around using Ctrl and these keybindings. So C-j will move the cursor down one item in a menu.

    "},{"location":"reference/vim-style/vim-quick-reference/#navigating-the-current-line","title":"Navigating the current line","text":"Key Action f to next character (you specify) t to just before the next character ; repeat f or t search w start of next word W start of next word, white space delimited e end of current word b start of previous word W end of next word, white space delimited * to next matching symbol name $ end of current line 0 start of current line ^ start of non-whitespace % jump to matching parens or next closed paren"},{"location":"reference/vim-style/vim-quick-reference/#navigating-the-current-buffer","title":"Navigating the current buffer","text":"Key action gg start of buffer G end of buffer H move cursor to head of buffer M move cursor to middle of buffer L move cursor to bottom line of buffer C-u jump up half a page C-d jump down half a page } move cursor forward by paragraph or block { move cursor backward by paragraph or block ma mark a line in a file with marker \"a\" `a after moving around, go back to the exact position of marker \"a\" 'a after moving around, go back to line of marker \"a\" :marks view all the marks '' go to the last place you were [{ jump back to the \"{\" at the beginning of the current code block C-o jump back to previous cursor location (evil-jump-backwards) C-i Go to newer position in jump list (opposite of C-o) : 4 go to line 4"},{"location":"reference/vim-style/vim-quick-reference/#text-editing","title":"Text Editing","text":"

    The following commands put you into the Evil Insert state

    Key Action i insert state at cursor I insert state at start of line a append - insert state after cursor A append - insert state at end of line o new line after cursor O new line before cursor"},{"location":"reference/vim-style/vim-quick-reference/#return-to-normal-state","title":"Return to Normal state","text":"

    Regularly switch back to normal state should become common practice. As soon as you finish typing some new text, it should become second nature to go back to normal state.

    ESC or press fd keys in extremely quick succession.

    fd shortcut for Esc

    Using f d together is low risk as if you dont get it right it will either add the characters or try find the next d character (as f moves to the next character). Keep trying this key combination as once in normal state you can use u to undo any f d characters inserted.

    "},{"location":"reference/vim-style/vim-quick-reference/#copy-cut-paste-undo-redo","title":"Copy, cut, paste, undo, redo","text":"

    v in Vim normal mode changes to Visual select mode. Use the navigation keys or any other movement keys to select text to copy or cut.

    Key Action y copy (yank) selection and add to kill ring x delete character at point and add to kill ring X delete character before point and add to kill ring p paste (put) u undo Ctrl-r redo

    Undo tips

    Undo will revert the last action in normal mode or all the changes you made in insert state

    "},{"location":"reference/vim-style/vim-quick-reference/#replace-and-changing-text","title":"Replace and changing text","text":"Key Action r replace the character under cursor R replace multiple characters until ESC cw change word from cursor to end 4 c w change 4 words v (select) c change region v (select) d delete region v i w c change current word v i d delete current word d w delete from cursor to end of word C change from cursor to end of line D , d $ delete from cursor to end of line"},{"location":"reference/vim-style/vim-quick-reference/#delete-commands","title":"Delete commands","text":"Key Action de delete to end of word, not including space dw delete to end of word, including space d$ delete to end of line dd delete the current line 4 d w delete 4 words 4 d $ delete 4 lines to end dt delete to a character (not including character) dab delete a whole block / expression dib delete contents of a block / expression cab change all the block / expression cib change inner block contents / expression yab yank all block / expression yib yank inner block contents / expression"},{"location":"reference/vim-style/vim-quick-reference/#repeat-commands","title":"Repeat commands","text":"Key Action . repeat last command again <number> <cmd> repeat command a number of times

    The . keybinding will repeat the last command in normal mode or the last text edit in insert mode.

    Type a number before a command and that command will run that number of times.

    Inserting a comment border

    Use the number repeat to create a border of 42 ; characters.

    Type 42 to repeat the command 42 times

    Press i for insert mode

    Press ; as the character to repeat insert

    Press ESC or fd to leave insert mode and insert all 42 ; characters

    "},{"location":"reference/vim-style/vim-quick-reference/#transposing-swap","title":"Transposing / swap","text":"Key Description x p transpose the current character with the next character"},{"location":"reference/vim-style/vim-quick-reference/#comments-works-for-all-major-modes","title":"Comments - works for all major modes","text":"

    g c c to comment out the current line

    g c to comment out the currently selected region

    To comment multiple lines you can use the repeat command style, especially useful if you are using relative line numbers.

    g c 3 j will comment the current line and the following two lines below. Comment in reverse using g c 3 k.

    In Visual state, v, select the lines you wish to comment and use g c to comment all the marked lines. Partially marked lines are not commented.

    "},{"location":"reference/vim-style/vim-quick-reference/#managing-files","title":"Managing Files","text":"

    Files in practicalli/neovim-config can be managed with Telescope plugin, although the neovim commands can also be used

    SPC p t toggles a visual file explorer on as a leftmost window, providing a further way to navigate files and directories.

    Key Description SPC f f find existing file (from current local root of neovim) SPC f / copy file - save current buffer with a new file name SPC f b browse files - Esc to run commands SPC f b Esc r change file name of current buffer

    Telescope file browser opens in Insert mode to allow typing filenames, to narrow the results in the Telescope popup.

    "},{"location":"reference/vim-style/vim-quick-reference/#telescope-browser-commands","title":"Telescope browser commands","text":"

    SPC f b opens telescope browser which allows commands to be run over the current file or directory.

    Esc swiches the Telescope popup to normal mode, allowing commands to be used

    • c create file / directory (any missing parts of a path are created)
    • r rename a file / directory
    • R replace

    TAB selects files and directories, allowing for commands (i.e. rename) to be done in batch mode (acting on all selected files / directories)

    "},{"location":"reference/vim-style/vim-quick-reference/#working-with-buffers","title":"Working with Buffers","text":"

    To work with files in Neovim they are loaded into a Buffer.

    Buffers are displayed in a window and you can change the window to show any of the current buffers.

    SPC b displays the buffer menu and the most common commands include:

    Key Command Description SPC b b :Telescope buffers List current buffers SPC b d :bdelete Kill current buffer SPC b n :bnext Switch to next buffer SPC b p :bprevious Switch to previous buffer SPC b a :ball Switch to previous buffer"},{"location":"reference/vim-style/vim-quick-reference/#quit-or-restart-emacs","title":"Quit or Restart Emacs","text":"

    I recommend using the Spacemacs menu from normal mode to quit / restart Spacemacs.

    Key Action SPC q a Quit Neovim (blocked if unsaved change in buffers) SPC q q Quit buffer (blocked if unsaved change in buffers) SPS q Q Force quit of Neovim"},{"location":"reference/vim-style/vim-quick-reference/#external-commands","title":"External commands","text":"

    run external commands using :! followed by a command. For example:

    :!ls - run the ls command

    "},{"location":"reference/vim-style/vim-tips-for-developers/","title":"Vim editing for Clojure developers","text":"

    Vim keybindings that drive Vim editing tools that are common for developers

    "},{"location":"reference/vim-style/vim-tips-for-developers/#comments-and-commenting-code","title":"Comments and Commenting code","text":"
    • g c c comment line
    • g c c comment line
    • v (select) g c comment region
    • g c 9 j comment 9 lines from current, downwards
    "},{"location":"reference/vim-style/vim-tips-for-developers/#simulated-structural-editing-with-surround","title":"Simulated structural editing with surround","text":"Keybinding Description v s ] surround with [characters] without spaces v s [ surround with [ characters ] without spaces c s ( [ change surrounding from ( to [ c i ( change in ( c a ( change \u201caround\u201d ( % jump forwards to next paren, further % toggles between open and close parens. x p transpose characters (cut current, paste after)"},{"location":"reference/vim-style/vim-tips-for-developers/#moving-around-quickly","title":"Moving around quickly","text":"

    f to jump forward to a given character on the current line. F to jump backwards.

    zt, zz, and zb to pull the current line to the top/middle/bottom of the screen.

    [number] G jump to line number or :22 to jump to line 22

    :7j to jump 7 lines down

    gf jump to file name under the cursor - try this in the summary.md file

    "},{"location":"reference/vim-style/vim-tips-for-developers/#selection-find-and-replace","title":"Selection, find and replace","text":"

    viw to visual-select in (within) the current word

    "},{"location":"reference/vim-style/vim-tips-for-developers/#source-code-and-configuration-files","title":"Source code and configuration files","text":"

    g Dopen definition in another window

    = (code-aware indenting) operator. Nice with the ap (a paragraph) text object.

    C-] Jump to definition of keyword under the cursor

    "},{"location":"reference/vim-style/vim-tips-for-developers/#code-folding","title":"code folding","text":"

    zc and zo are useful to close and open folds, which can be a nice way of focusing on certain pieces of code.

    "},{"location":"reference/vim-style/vim-tips-for-developers/#transposing-characters-and-sections","title":"Transposing characters and sections","text":"

    x p simple transpose of the current and next character

    M-t transpose words before and after cursor position

    {, } motions jump to next and previous empty lines. This motion makes it simple to rearrange paragraphs

    { d } will kill the paragraph (or multiple paragraphs)

    { will jump to the start of the previous paragraph

    p pastes the killed paragraph before the current paragraph

    > and < (indent and dedent) operators, useful with the aforementioned }/{ motions.

    / ## multi-replace with iedit and narrowing /

    "},{"location":"reference/vim-style/visual-select/","title":"Visual Select","text":"

    Select characters, words, lines and regions with visual select. The background changes color to visually indicate which text is selected

    v enters visual select mode and can be with objects such as word w and locations such as end of line $.

    o to expand from left side of selection and O to expand from the right side of a selection, using the hjkl navigation keys

    "},{"location":"reference/vim-style/visual-select/#visual-line-selection","title":"Visual Line selection","text":"

    V to select by lines, using j and k.

    "},{"location":"reference/vim-style/z-menu/","title":"Evil Z menu","text":"

    z in normal mode opens a menu of convenient utilities

    "},{"location":"reference/vim-style/z-menu/#folding-code-comments-and-other-content","title":"Folding code, comments and other content","text":"

    Code folding is very useful for hiding different levels of detail, for example you could hide everything but the function names in a namespace, showing just the API for that namespace.

    Comments and documentation can be folded to help you focus on a specific part of the content.

    Key Description z a toggle fold of code, comment, section, etc. z A toggle all folds z c close fold z f create fold z M close all folds z o open fold z O open fold recursive (capital o) z r fewer folds z R open all folds z x update folds

    See narrowing for a focused approach to editing.

    "},{"location":"reference/vim-style/z-menu/#scrolling","title":"Scrolling","text":"

    Jump the current line to the center, top or bottom of the buffer.

    Key Description z b scroll the current line to bottom of buffer z t scroll the current line to top of buffer z z scroll the current line to center of buffer"},{"location":"reference/vim-style/z-menu/#spelling","title":"Spelling","text":"

    z = with the cursor on a word shows a list of possible spelling and similar words.

    Select a word using its number in tye list to repace the word under the cursor, or q to quit the spelling list.

    Key Description z = spelling suggestions z g add word to spelling list z w mark word as misspelled"},{"location":"repl-driven-development/","title":"REPL Driven Development with Clojure","text":"

    Conjure provides the REPL driven development workflow for Clojure (and many other fun languages) and includes a built-in tutorial.

    • Vim style Editing
    • Starting a REPL & Evaluating code - using Conjure
    • Structural Editing - parinfer or paredit
    • Refactor tools - Language Server Protocol features
    • Unit Testing - run REPL or external test runners
    • Inspecting data, e.g. Portal

    Practicalli Clojure CLI Config

    Practicalli Clojure CLI config contains aliases used extensively through the Clojure sections of this book

    Practicalli Neovim config replaces some key bindings

    practicalli/neovim-config-redux replaces several key bindings to make them consistent with other Clojure editors

    "},{"location":"repl-driven-development/#references","title":"References","text":"
    • Which Clojure CLI execution option - M T X P - should be used
    • Make task to simplify Clojure development
    "},{"location":"repl-driven-development/conjure/","title":"Conjure","text":"

    Conjure is the Clojure REPL client for Neovim. Code in source code buffers can be evaluated and show the results in-line, providing instant feedback on the behaviour of the code as it develops.

    Conjure School interative tutorial

    :ConjureSchool runs an interactive tutorial in Neovim, walking through the essential Conjure commands and key bindings. Use the commands provided to move through the guide or j / k to scroll through the guide content.

    "},{"location":"repl-driven-development/conjure/#start-repl","title":"Start REPL","text":"

    Start a REPL on the command line in the root of a Clojure project. The REPL should also start an nREPL server for Conjure to connect too.

    Conjure will detect an nREPL server (via .nrepl-port file) when a Clojure file is opended (.clj .edn .cljs .cljc) and connect to the REPL process via that nREPL server.

    Practicalli Clojure CLI ConfigManual Alias definition

    Practicalli Clojure CLI config contains aliases to start a REPL process that also start an nREPL server.

    Use repl make task for projects created by Practicalli Project templates

    make repl\n

    Or use the Clojure CLI command with the :repl/rebel alias directly

    clojure -M:repl/rebel\n
    Simplify the command line

    Add a Makefile to define common tasks to simplify and add consistency to working with Clojure across projects or shell script to simplify the commands used to call clojure to run common tasks

    repl:  ## Run Clojure REPL with rich terminal UI (Rebel Readline)\n    $(info --------- Run Rebel REPL ---------)\n    clojure -M:env/dev:env/test:repl/rebel\n\n\nrepl-reloaded:  ## Run Clojure REPL with hotload, reload and rich terminal UI (Rebel Readline)\n    $(info --------- Run Rebel REPL ---------)\n    clojure -M:env/dev:env/test:lib/reloaded:repl/rebel\n

    A Makefile can also include supporting commands, such as lint and format tools.

    # Run MegaLinter with custom configuration\nlint:\n    $(info --------- MegaLinter Runner ---------)\n    mega-linter-runner --flavor java --env 'MEGALINTER_CONFIG=.github/linters/mega-linter.yml'\n

    practicalli/dotfiles/Makefile contains tasks for Clojure development, including running a REPL, preparing dependencies, building an uberjar, lint & format Clojure and configuration files.

    Docker related tasks to build, run and compose common images and containers are also included.

    Add aliases to the user configuration for Clojure, e.g. XDG_HOME_CONFIG/clojure/deps.edn or HOME/.clojure/deps.edn

      ;; Interactive client REPL with nREPL server for Clojure Editor support\n  :repl/basic\n  {:extra-deps {nrepl/nrepl       {:mvn/version \"1.0.0\"}\n                cider/cider-nrepl {:mvn/version \"0.40.0\"}}\n   :main-opts  [\"--main\" \"nrepl.cmdline\"\n                \"--middleware\" \"[cider.nrepl/cider-middleware]\"\n                \"--interactive\"]}\n\n  ;; Headless REPL with nREPL server for Clojure Editor support\n  :repl/headless\n  {:extra-deps {nrepl/nrepl       {:mvn/version \"1.0.0\"}\n                cider/cider-nrepl {:mvn/version \"0.40.0\"}}\n   :main-opts  [\"--main\" \"nrepl.cmdline\"\n                \"--middleware\" \"[cider.nrepl/cider-middleware]\"]}\n

    clojure -M:repl/basic starts a REPL with nREPL with a minimal REPL UI

    clojure -M:repl/headless starts a REPL with nREPL server but without a REPL prompt (to prevent accidental interaction via the command line)

    Practicalli Clojure CLI Config aliases

    Practicalli Clojure CLI config defines aliases for a wide range of community tools and libraries that extend the features of Clojure CLI

    "},{"location":"repl-driven-development/conjure/#evaluation","title":"Evaluation","text":"

    Clojure REPL workflow encourages code expressions to be evaluated as the are written, providing instant feedback to ensure expected results are returned (or learn the kind of results a function returns).

    Results of evaluating an expression are shown in-line. Open the REPL log to see larger results and a complete REPL history for the current session.

    ,eb - evaluate current buffer - used after first starting the REPL to load in a whole namespace and any required namespaces. Use to ensure all changes have been evaluated in the REPL (except those within a (comment ) form or otherwise commented)

    ,er - evaluate top-level expression (root), ignoring a surrounding (comment ) form to support the rich comments approach

    ,ee - evaluate expression (from start of current form) - especially useful for nested forms

    ,ei - interrupt evaluation (stop long running evaluations) - stop a long running evaluation

    ,ew - evaluate word (symbol) - inspect value of form - i.e. for def names

    ,e! - replace form with its result - helps understand a more complex function by replacing code with a specific value

    ,emf - evaluate marked form - mark forms regularly re-evaluted with mf (or any character with m) to avoid jumping to that form each time . A capital letter to mark form in a different namespace and evaluate from the current buffer.

    \"cp - paste contents of the register into buffer. The result of every evaluation is stored in a Neovim register as well as the log.

    "},{"location":"repl-driven-development/conjure/#repl-log","title":"REPL log","text":"

    The Conjure REPL log shows the results of every evaluation for the current session.

    ,lt opens log in a new tab page (tab), ,ls in horizontal split, ,lv in vertical tab

    ,lq - close log window / tab page

    ,lr - soft REPL reset, leave window open

    ,lR - hard REPL reset, close window & delete buffer

    Inline evaluation over HUD log popup

    Practicalli Neovim configurations hide the HUD log popup that is otherwise shown when Conjure connects to the REPL process, i.e. vim.g[\"conjure#log#hud#enabled\"] = false

    In-line evaluation results are the main feedback approach used by Practicalli when evaluating code.

    Practicalli recommends using the REPL log when larger results are returned

    Portal data inspector can be sent evaluation history and provides rich visualisation and navigation tools to explore that history in detail.

    "},{"location":"repl-driven-development/conjure/#rich-comments","title":"Rich comments","text":"

    Rich comments are a useful way to contain experimental expressions, or expresisons only evaluated directly by a person developing the code (e.g. starting / stoping services, testing api calls, etc.)

    Expressions in rich comments are not included when evaluating the buffer or when expressions are evaluated via a namespace require.

    ,er to evaluate the top level form within the rich comment, without evaluating the comment expression itself.

    Start REPL from Neovim

    Practicalli Configurations require the vim-jack-in plugin to be added before this approach will work.

    Start Neovim with a Clojure file, e.g. nvim src/practialli/playground.clj or run nvim and open a Clojure file, e.g. *.clj, *.cljc, *.cljs or .edn.

    • :Clj command to start a REPL using Clojure CLI Tools
    • :Lein command to start a REPL using Leiningen

    Neovim switches to a terminal state, use C-\\ C-n to leave the terminal state. Use :N or :previous to switch back to the source code buffer

    , c f to connect to the REPL from Conjure, or simply open a Clojure file. Automated connection will be added in a future version on Conjure.

    The vim-jack-in plugin enables Neovim to call out to Clojure tools or Leiningen to start a REPL and connect to it once its started.

    A full screen REPL log is displayed. , l q to close the log window and return to the Clojure file. , l v to create a vertical split between code and REPL log, , l s for a horizontal split.

    "},{"location":"repl-driven-development/refactor-tools/","title":"Refactor tools","text":"

    Neovim and common plugins provide many text oriented tools useful for refactoring code.

    Clojure LSP server and Neovim LSP client support use static analysis of the project source code to allow provide common code refactor tools.

    "},{"location":"repl-driven-development/refactor-tools/#language-server-protocol-lsp","title":"Language Server Protocol (LSP)","text":"

    Using clojure-lsp server and Neovim Treesitter as an LSP client, code is statically analysed to provide auto-completion data, advanced editing actions such as refactor, live formatting, etc.

    Function help

    SPC l h or K displays help for the function under the cursor

    Repeat the key binding to move the cursor to the documentation popup window and use j k to scroll the documentation

    "},{"location":"repl-driven-development/refactor-tools/#key-maps","title":"Key maps","text":"Practicalli AstroNvim ConfigPracticalli Neovim Config Redux
    • <leader>la code actions (popup with available actions)
    • <leader>ld hover diagnostics
    • <leader>lD search diagnostics
    • <leader>lf format buffer
    • <leader>lG search workspace symbols
    • <leader>lh function signature help
    • <leader>li information about the LSP client and running LSP servers
    • <leader>lI null-ls information (format & lint tools)
    • <leader>ll code lens refresh
    • <leader>lL code lens run
    • <leader>lr rename current symbol (namespace rename not supported it seems)
    • <leader>lR search references
    • <leader>ls search symbols
    • <leader>lS symbols outline
    • gd Go to definition
    • K Show documentations
    • <leader>ld Function declarations
    • <leader>lt Type Definitions
    • <leader>lh Signature Help
    • <leader>ln Rename
    • <leader>le Show line diagnostics
    • <leader>lq Show all diagnostics information
    • <leader>lf Auto format
    • <leader>lj Go to next diagnostic
    • <leader>lk Go to previous diagnostic
    • <leader>la Open code actions menu (Using telescope plugin interface)
    • <leader>la Open code actions menu for the selected text in VISUAL mode (Using telescope plugin interface)
    • <leader>lw Open workspace diagnostics list (Using telescope plugin interface)
    • <leader>lr Show all references list for item under the cursor (Using telescope plugin interface)
    • <leader>lr Show all implementations list for item under the cursor (Using telescope plugin interface)
    "},{"location":"repl-driven-development/refactor-tools/#limitations-to-investigate","title":"Limitations to investigate","text":"
    • Neovim client does not seem to support namespace rename (AstroNvim)
    "},{"location":"repl-driven-development/structural-editing/","title":"Structural Editing","text":"

    Structural editing seeks to ensure that parenthesis (parens) and other pairs of characters remain balanced, i.e. an open paren is not removed without removing the closing paren.

    • parinfer uses an indent approach, aligning code manages parens locations
    • paredit uses a structural approach
    AstroNvim Community Clojure Pack includes parinfer

    nvim-parinfer plugin is included in the AstroNvim Community Clojure pack

      { import = \"astrocommunity.pack.clojure\" },\n
    "},{"location":"repl-driven-development/structural-editing/#parinfer","title":"Parinfer","text":"

    Parinfer works very well with vim-style modal editing.

    The author of the code focuses on aligning code and parinfer takes care of balancing the parens.

    To include new lines of code within an expression, create a new line o and indent.

    Parinfer will move the preceeding closing paren(s) to the new line, enclosing the new code in the overall expression.

    Parinfer website

    "},{"location":"repl-driven-development/testing/","title":"Unit tests and test runners","text":"

    Run unit tests from within Neovim, showing a summary of test results or a full test report (especially if there are failures)

    Or run and external test runner via a terminal session, optionally using watch mode to re-run tests on every saved change.

    Practicalli sets Kaocha test runner as default

    practicalli/neovim-config-redux sets Kaocha as the default test runner

    Kaocha test runner set in Astrocommunity Clojure language pack

    Astrocommunity Clojure language pack
    {\n  \"Olical/conjure\",\n  -- load plugin on filetypes\n  ft = { \"clojure\" },\n  init = function()\n    vim.g[\"conjure#log#hud#width\"] = 1\n    vim.g[\"conjure#log#hud#enabled\"] = false\n    vim.g[\"conjure#log#hud#anchor\"] = \"SE\"\n    vim.g[\"conjure#log#botright\"] = true\n    vim.g[\"conjure#extract#context_header_lines\"] = 100\n    vim.g[\"conjure#eval#comment_prefix\"] = \";; \"\n    vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false\n    vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true\n    vim.g[\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil\n    vim.g[\"conjure#client#clojure#nrepl#eval#auto_require\"] = false\n    vim.g[\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\"\n\n    vim.api.nvim_create_autocmd(\"BufNewFile\", {\n      group = vim.api.nvim_create_augroup(\"conjure_log_disable_lsp\", { clear = true }),\n      pattern = { \"conjure-log-*\" },\n      callback = function() vim.diagnostic.disable(0) end,\n      desc = \"Conjure Log disable LSP diagnostics\",\n    })\n
    "},{"location":"repl-driven-development/testing/#include-test-path","title":"Include test path","text":"

    Ensure the test directory is included in the classpath when starting a REPL. Use a project or user level alias which defines an :extra-paths key with the [\"test\"] path

    clojure -M:test/env:repl/reloaded\n
    "},{"location":"repl-driven-development/testing/#conjure-test-runners","title":"Conjure Test runners","text":"

    , t n to run the tests for the current namespace

    , t a to run all tests in the project

    "},{"location":"repl-driven-development/testing/#external-test-runner","title":"External test runner","text":"

    Open a terminal in Neovim or a separate terminal session to run start a test runner in watch mode. Tests run automatically when the code changes are saved

    Practicalli Clojure CLI Config

    Practicalli Clojure CLI config contains aliases for test runner tools

    • :test/run uses Kaocha to run all tests, stopping on first failing test. Add :fail-fast? false argument to run all tests regardless of failure

    • :test/watch as above and puts Kaocha in watch mode, triggering a test run each time a file is saved

    Projects created with Practicalli Project Templates include a test and test-watch task to run Kaocha test runner

    Run all tests, stoping on first failing test

    make test\n

    Watch for changes and run all tests, stoping on first failing test

    make test-watch\n

    The make tasks call Clojure CLI with the appropriate alias, e.g. clojure -X:test/run and clojure -X:test/watch

    "},{"location":"repl-driven-development/testing/#test-selectors","title":"Test Selectors","text":"

    Use Test selectors to run a sub-set of tests based on selector meta data added to deftest code

    (deftest ^:infrastructure function-name-test\n  (testing \"\"\n    (is ,,,))\n\n(deftest ^:persistence function-name-test\n  (testing \"\"\n    (is ,,,))\n
    Kaocha test runnerCognitect Labs Test Runner

    Kaocha test runner can focus or skip on a sub-set of unit tests using test id, metadata, namespaces or a specific deftest.

    • :focus or :skip a given namespace or specific test var, i.e. deftest
    • :focus-meta or :skip-meta test selectors (metadata) on test vars, i.e. ^:persistence

    Specifying test :id in the tests.edn configuration file allows different test suites to be run, e.g. :unit for unit tests, :spec for specification tests

    Focus and skip works with a single test run or with a continuous watcher.

    Skip all tests with :persistence metadata

    clojure -X:test/watch :skip-meta :persistence\n

    Focus on a specific test namespace

    clojure -X:test/watch :focus '[\"practicalli.gameboard.api.scoreboard-test\"]\n

    Focus on a specific unit test (deftest)

    clojure -X:test/watch :focus '[\"practicalli.gameboard.api.scoreboard-test/total-score-test\"]\n

    Refine the tests that are watched

    Start the watcher with focused or skiped tests by name or meta data (test selectors)

    Cognitect Labs Test Runner can include or exclude a sub-set of tests, identified by metadata on the var (deftest)

    Cognitect Labs Test Runner - inclusions & exclusions

    "},{"location":"termux/","title":"NeoVim on Termux","text":"

    A smart phone or tablet and an external keyboard can make an excellent ultra-portable development environment, especially when travelling with limited space or restricted weight constraints.

    Termux can be installed using the F-Droid marketplace, as with installing any other Android app.

    Do not install Termux App from the Google Play store

    The Termux App in Google Play store is significantly out of date and will not work properly and probably not at all

    "},{"location":"termux/#keyboard","title":"Keyboard","text":"

    Atreus from Keyboardio is an excellent travel keyboard and was used to write most of the Practicalli Neovim configuration and Neovim book (especially during delays at airports)

    Model 100 from Keyboardio is used by Practicalli at the office

    "},{"location":"termux/#running-termux","title":"Running Termux","text":"

    Run Termux from the app launcher added as an android app by the F-Droid install.

    A help menu will show the basic command needed to work with packages.

    Software keys for Termux specific controls are shown. Keys can be toggled with the Volume Up + q key combination.

    Termux may not display in fullscreen when Android productivity mode, usually activated on tablets when physical keyboard or mouse is attached. Disabling productivity mode in the Android settings is recommended.

    "},{"location":"termux/clojure-development/","title":"Clojure development environment","text":"

    A comprehensive development environment for Clojure, supporting a REPL workflow and static analysis of code via Clojure Language Server Protocol.

    "},{"location":"termux/clojure-development/#java-host-platform","title":"Java host platform","text":"

    Install OpenJDK to host the Clojure REPL process and run packaged Clojure applications.

    Java 17 Long Term Support version is recommended as it is very stable, receives security updates and has the latest highly tested performance improvements.

    pkg install openjdk-17\n
    "},{"location":"termux/clojure-development/#install-clojure","title":"Install Clojure","text":"

    Clone practicalli/clojure-deps-edn to add a wide range of community tools to the Clojure CLI

    git clone git@github.com:practicalli/clojure-deps-edn.git ~/.config/clojure\n

    Use the Linux install with a prefix path pointing to Termux equivalent of /usr/local. Find the path using echo $PATH and remove bin from the end. Without the prefix Clojure will not install correctly

    curl -O https://download.clojure.org/install/linux-install-1.11.1.1149.sh\n\nchmod +x linux-install-1.11.1.1149.sh\n\n./linux-install-1.11.1.1149.sh --prefix /data/data/com.termux/files/usr/\n

    clojure binary is installed in the existing bin, lib and share directories in /data/..../usr/, placing that binary on the system execution path.

    Test by running a REPL session, for example with Rebel Readline

    clojure -M:repl/rebel\n

    optionally install rlwrap package if using the basic repl terminal UI

    "},{"location":"termux/clojure-development/#install-clojure-lsp","title":"Install Clojure LSP","text":"

    Visit clojure-lsp GitHub releases page and download the clojure-lsp file

    • visit the relases page in firefox and copy the link to the file.
    • use wget and paste the link to the file to download
    • make executable chmod 755 clojure-lsp
    • test locally ./clojure-lsp --version - should print clojure-lsp version and clj-kondo version
    • copy or move file to path mv clojure-lsp $PATH

    If the practicalli/clojure-lsp-config repository was cloned, move or link the clojure-lsp directory to ~/.config/clojure-lsp

    "},{"location":"termux/custom-shell/","title":"Customise shell","text":"

    Customising the shell is optional, although gives an enhanced experience.

    Zsh provides the richest command line experience, providing many advanced features over bash. Oh My Zsh is a community configuration that provides a simple way to configure Zsh features and also supports powerline10k terminal theme, providing context specific information and a more engaging visual experience.

    Oh My Zsh community configuration enhances the Zsh experience. Practicalli normally uses Prezto community configuration, unfortunately this did not work well on Termux.

    "},{"location":"termux/custom-shell/#install-zsh","title":"Install Zsh","text":"

    Install the zsh package using the Termux package manager

    pkg install zsh\n

    Start zsh, which will show a % character as the prompt

    zsh\n

    Set the shell to run zsh by default

    chsh -s zsh\n
    "},{"location":"termux/custom-shell/#install-oh-my-zsh","title":"Install Oh My Zsh","text":"

    Install Oh My Zsh via curl (or wget if preferred) in the .oh-my-zsh/ directory

    sh -c \"$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"\n
    "},{"location":"termux/custom-shell/#install-powerline10k","title":"Install Powerline10k","text":"

    Powerline10k is a visually appealing prompt with a setup script to visually choose the presentation of the prompt.

    git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k\n

    Edit ~/.zshrc and set the theme to ZSH_THEME=\"powerlevel10k/powerlevel10k\"

    nano ~/.zshrc\n

    Save the changes exit termux.

    Next time zsh is run, powerline10k setup script will run. If Meslo is not set as the terminal font, the setup script offers to install the font. Installing the font will restart Termux (without prompting for a restart).

    The powerline10k setup script provides a wizard to configure each part of the prompt.

    p10k configure command will manually run the powerline10k setup script.

    Prezto Zsh community configuration

    NOTE: previous attempts to use Prezto proved to have issues

    Clone prezto and its sub-modules into XDG_CONFIG_HOME/zsh which is typically ~/.config/zsh

    git clone --recursive https://github.com/sorin-ionescu/prezto.git \"${ZDOTDIR:-${XDG_CONFIG_HOME:-$HOME/.config}/zsh}/.zprezto\"\n

    Set the location of the Zsh configuration home with $ZDOTDIR, relative to the XDG locations

    export ZDOTDIR=\"${ZDOTDIR:=$XDG_CONFIG_HOME/zsh}\"\n

    Create a new Zsh configuration by copying/linking the Zsh configuration files provided:

    setopt EXTENDED_GLOB\nfor rcfile in \"${ZDOTDIR:-$HOME}\"/.zprezto/runcoms/^README.md(.N); do\n  ln -s \"$rcfile\" \"${ZDOTDIR:-$HOME}/.${rcfile:t}\"\ndone\n

    Practicalli Zsh configuration

    Clone practicalli/dotfiles and replace the symbolic links in $XDG_CONFIG_HOME/zsh with links to the respective Zsh configuration files in the cloned repository (or copy the files if you prefer)

    Copy or create a symbolic like for the .p10k configuration or skip this to create your own configuration when next startingzsh.

    Edit $XDG_CONFIG_HOME/.config/zsh/.zshenv and add the following lines to enable zsh to find the prezto configuration

    export XDG_CONFIG_HOME=\"${XDG_CONFIG_HOME:=$HOME/.config}\"\nexport ZDOTDIR=\"${ZDOTDIR:=$XDG_CONFIG_HOME/zsh}\"\n

    Create a symbolic link from $HOME/.zshenv to $XDG_CONFIG_HOME/.config/zsh/.zshenv (or to the .zshenv file from practicalli/dotfiles)

    ln -s $XDG_CONFIG_HOME/.config/zsh/.zshenv $HOME/.zshenv\n

    Check the configuration is working by loading the .zshenv configuration

    source \"$ZDOTDIR/.zshenv\"\n

    Using Oh My Bash

    If preferring Bash, then ohmybash provides a nice command line experience, showing completions clearer, nice themes that provide information.

    "},{"location":"termux/fdroid-install/","title":"Install Termux via the F-Droid App","text":"

    Visit the FDroid app website and download F-Droid, which saves an F-Droid.apk file. Android may display a security prompt stating the browser does not have permissions to install software. The popup should include a configure link that opens the Android settings to allow the browser to install software.

    F-Droid should now be installed and its icon added to the Android system alongside all other Android apps.

    Open the F-Droid App and allow it to update its repositories, to ensure the latest list of apps are shown.

    Search for the Termux application, clicking on the Termux name if more details are required.

    Select the Install button.

    When installing apps from F-Droid for the first time, a security prompt is show as F-Droid is an unknown source.

    Select Settings to open the Android settings and enable Allow from this source for the F-Droid app.

    A Termux App launcher will be added to the Android screen. Consider adding the Termux icon to the commonly used icons bar.

    "},{"location":"termux/fdroid-install/#termux-styling","title":"Termux Styling","text":"

    Styling is a Termux plugin that provides a visually richer experience. Styling contains beautiful color schemes and powerline-reaqdy fonts to customise the appearance of the terminal

    Install the package via F-Droid

    The styling menu is accessed via a long press on the Termux app screen, showing a More > Style option on the usual cut/copy/paste popup menu. Practicalli recommends FiraCode fonts.

    "},{"location":"termux/git/","title":"Git version control","text":"

    A Git client is used to version control projects and to clone projects and configuration from GitHub/GitLab. Practicalli maintains several editor configurations in shared repositories on GitHub

    • Install a Git Client (and optionally GitHub CLI)
    • [optionally] clone the practicalli/dotfiles repository for the Git config and global ignores
    • Configure an SSH key to access remote repositories (or Developer token if you cannot use SSH keys)
    "},{"location":"termux/git/#install-a-git-client-and-github-cli","title":"Install a git client and GitHub CLI","text":"
    pkg install git gh\n

    Clone the practicalli/dotfiles repository

    git clone https://github.com/practicalli/dotfiles projects/dotfiles\n

    Move or symbolically link the top-level directories to ~/.config, e.g. for the Git configuration:

    ln -s projects/dotfiles/git ~/.config/git\n

    Edit the .config/git/config and update the core.user, core.name and github or gitlab identities

    "},{"location":"termux/git/#create-ssh-key-for-remote-repository-access","title":"Create SSH Key for remote repository access","text":"

    Install the openssh package which contains the ssh-keygen command to generate a new public/private key combinations for use with GitHub SSH repository URLs

    pkg install openssh\n

    Generate a key using the email address of the GitHub or GitLab account

    ssh-keygen -t rsa -C name@domain.tld\n

    RET to confirm storing the keys in the default location.

    Usually a passphrase is recommended, however, termux does not seem to save a keyring to save the key passphrase using ssh-add. So the passphrase must be entered each time the key is used, unless a blank passphrase is used.

    Vist your GitHub account settings and create a new SSH key

    Use cat ~/.ssh/id_rsa.pub to show the public key contents. Press the screen to select and copy the public key to the clipboard.

    Paste the public key into the GitHub new key form.

    "},{"location":"termux/git/#optional-create-a-developer-token","title":"[optional] Create a developer token","text":"

    A developer token (or ssh key) is required to access GitHub {and far more secure over password}

    Should the android device become lost or compromised, the developer token can be deleted to protect the repositories from any malicious access. The developer token should be limited to the minimal access. The developer token does not give access to the GitHub or GitLab account.

    HTTPS URLs should be used with a developer token. git@git.com URLs are for SSH keys only.

    Visit GitHub / GitLab settings for your account

    Create a new developer token specifically for Termux

    Add a descriptive name for the token, based on the device Termuxc is runniung on, e.g. Termux Pixel2XL

    Check the public_repo and status repo scopes

    Generate button creates a new token.

    Copy the token using the copy icon.

    Edit the .config/git/config file and add a github section with the GitHub account name and token

    [github]\n    name = practicalli\n    token = ghp_************************************\n

    Consider using GitHub CLI to cache the developer token rather than write the token to the Git configuration file for greater security.

    "},{"location":"termux/neovim/","title":"Install neovim","text":"

    Neovim version 8 availabe as current package

    pkg install neovim\n
    "},{"location":"termux/neovim/#neovim-treesitter","title":"Neovim treesitter","text":"

    Treesitter provides excellent language syntax parsing and highlighting and is a very attractive feature of the recent neovim releases. Treesitter is a major attraction, bringing in a new audience for Neovim.

    The nvim-treesitter package is included in the practicalli/neovim-config-redux configuration.

    "},{"location":"termux/neovim/#c-compiler","title":"C Compiler","text":"

    Install C compiler for neovim-treesitter, to compile a parser for each specific programming language.

    pkg install clang\n

    gcc is not packaged for Termux, although there are guides to install gcc if preferred. clang has proved to be capable of creating the parsers used in the Practicalli configuration.

    "},{"location":"termux/neovim/#searching-files","title":"Searching files","text":"

    Telescope and other packages that involve searching for files recommend using ripgrep, a highly optomised tool for finding files on the operating system.

    pkg install ripgrep\n
    "},{"location":"termux/neovim/#optional-nodejs","title":"[optional] nodejs","text":"

    Optional. Only if node.js is required as a Neovim provider and JavaScript or ClojureScript development is to be done.

    pkg install nodejs\n
    "},{"location":"termux/setup/","title":"Termux Setup","text":"

    Launch Termux via its application icon. A black terminal screen will appear with a bash shell prompt.

    "},{"location":"termux/setup/#update-packages","title":"Update packages","text":"

    Check for new packages and update them all

    pkg upgrade -y\n

    If you wish to first check the packages that will be updated, use pkg --list-upgradable

    Select a specific region to minimise the number of mirrors checked during package upgrades, especially useful if on a limited data plan.

    termux-change-repo\n

    At time of writing, the Termux package on F-Droid was around 6 months old so there will be a number of packages that should be updated before any further installation steps are undertaken.

    "},{"location":"termux/setup/#configure-freedesktoporg-xdg-locations","title":"Configure Freedesktop.org XDG locations","text":"

    Edit the ~/.profile file, adding export directives to set the XDG locations:

    nano ~/.profile\n
    XDG locations
    # Common Free desktop.org locations\nexport XDG_CONFIG_HOME=$HOME/.config\nexport XDG_DATA_HOME=$HOME/.local/share\nexport XDG_STATE_HOME=$HOME/.local/state\nexport XDG_CACHE_HOME=$HOME/.cache\n\n# Set XDG location of Emacs Spacemacs configuration\nexport SPACEMACSDIR=\"$XDG_CONFIG_HOME/spacemacs\"\n

    Load the environment variables into the shell, or exit Termux and restart.

    Load .profile into shell
    source ~/.profile\n

    nano editor installed by default

    nano editor is used to edit the commands as the package is installed by default in termux. vim, neovim, emacs or any other Linux command line editor can be used if the package is first installed. Termux will list packages to install when trying to run a command that is from a package not yet installed.

    "},{"location":"termux/setup/#tools-to-download-binaries-and-configuration","title":"Tools to download binaries and configuration","text":"

    Many tools can be installed via the pkg tool, although specific Clojure tools and configuration require additional tools:

    • wget and curl - download tools not packaged, i.e. clojure-lsp binary
    • git - clone configuration files and projects (see Git version control section)
    • openssh - SSH service and tools to generate SSH keys
    pkg install curl wget git openssh\n

    Configure a Git Identify and SSH key to before committing and pushing changes, or cloning repositories using the SSH protocol. practicalli/dotfiles contains example configuration, ignore patterns and commit template for using Git.

    "},{"location":"termux/setup/#optional-configure-termux-settings","title":"[Optional] Configure Termux Settings","text":"

    Edit ~/.termux/termux.properties to configure the default settings for termux.

    nano ~/.termux/termux.properties\n

    Load termux.properties if values are changed (restarting Termux is not enough to load setting changes)

    termux-reload-settings\n

    The defaults are suitable for the majority of uses, although you may wish to consider:

    • fullscreen set to true to us the whole screen, hiding Android menu bars, etc.
    • hide-soft-keyboard-on-startup set to true if always using a physical keyboard
    • default-working-directory to save files user files and directories in an alternative location,

    If swiping from left edge of the screen is already taken, set key bindings for creating a new termux session, naming a session and switching between sessions. Alternatively, use byobu to create and switch between its tabs for multiple terminal sessions.

    "},{"location":"termux/setup/#set-color-scheme-and-font","title":"Set Color Scheme and Font","text":"

    The Termux:Styling plug provides menus for selecting terminal color scheme and font to use

    Press and hold on the Termux screen to show the context menu and select the Style menu. On smaller screens select More > Style

    If Termux:Styling plugin was not installed, a prompt will display asking if the plugin should be installed

    A menu appears with Choose Color and Choose Font

    Select Choose Color to select from the available list of colour schemes, e.g. Gruvbox Dark or Gruvbox Light

    ~/.termux/colors.properties file is added when selecting a colour scheme, defining Hex colors from the theme selected.

    Select Choose Font to select from the available fonts, e.g. FiraCode or Ubuntu

    ~/.termux/font.ttf font file is added when selecting a font.

    Termux:Styling uses NerdFonts for icons

    All fonts installed via Termux:Styling have been patched with NerdFonts, providing several thousand icons to use within the terminal prompt and Neovim itself (e.g. VimDevIcons).

    "},{"location":"termux/using-termux/","title":"Using Termux","text":"

    Start Termux app and a terminal prompt is shown, along with the standard Android software keyboard. An extended keyboard is provided with common key bindings for the command line interface (Tab, Esc, Ctrl, arrow keys, etc.).

    "},{"location":"termux/using-termux/#keyboards","title":"Keyboards","text":"

    Termux provides an extended keyboard with key combinations not possible with the Android software keyboard, i.e Ctrl-c, arrow keys, etc. TAB is especially useful for driving command and filename completion.

    Volume Up + q toggles the extended keyboard, so more screen is available when using a hardware keyboard.

    Connect a hardware keyboard for the best experience, e.g the Keyboard.io atreus is an excellent and highly portable mechanical keyboard. The software keyboard is automatically switched off when a hardware keyboard is connected, although the extended keyboard is still displayed by default.

    "},{"location":"termux/using-termux/#adjusting-font-size","title":"Adjusting Font size","text":"

    Pinch the screen inwards to zoom out making the text font smaller.

    Pinch the screen outwards to zoom in making the text font larger.

    "},{"location":"termux/using-termux/#termux-menus","title":"Termux menus","text":"

    Termux has three menus: A context menu, navigation drawer and Termux section of the Android notification.

    The context menu is shown by a long press anywhere on the terminal screen:

    • Select and Paste text to share text with other applications
    • Reset the terminal if it gets stuck or Hangup to exit the current terminal session
    • Style the terminal by selecting a font and a color scheme

    The navigation drawer is shown by swiping inwards from the left of the screen

    • list and select terminal sessions, set a name for a session with a long press
    • A button to toggle visibility of the touch keyboard.
    • A button to create new terminal sessions (long press for creating a named session or a fail-safe one).

    If gesture navigation is enabled in Android, hold the edge of the screen briefly before swiping to bring up the navigation drawer

    The Android notification menu contains a Termux section. Press the Termux section to show the current terminal session or expand the Termux section to exiting all running terminal sessions or aquire a wake lock to avoid Termux entering sleep mode. A wake lock allows server and other background processes to run reliably and to continue to receive notifications

    "},{"location":"termux/using-termux/#package-management","title":"Package management","text":"

    Termux provides a Linux command line experience, providing a wide range of Unix tools and development environments. Termux uses a Debian based system and packages are easily installed

    • apt install add tools and libraries to the Linux environment from the curated packages in the software center
    • apt update updates the list of packages fromhe software center
    • apt list --upgradable shows list of packages with new versions
    • apt upgrade install new versions of currently installed packages
    • apt-cache search --names-only - search for packages that include a specific pattern in their name.
    • apt-cache show - shows detail of the supplied package name, including a description

    pkg is an alias for apt, the advance package tool, although there seems little benefit to using pkg if familiar with apt (they are both 3 characters)

    "},{"location":"termux/using-termux/#byobu-terminal-tab-manager","title":"Byobu terminal tab manager","text":"

    Byobu is an alternative to Termux provides a single terminal prompt. Byobu provides multiple shell prompts, allowing individual Clojure tools and editors to be run from the Termux prompt simultaneously. Practicalli uses byobu to run Neovim, a Clojure REPL and unit test watcher in separate byobu tabs with the ability to add further tabs for other command line tools.

    pkg install byobu\n
    • F2 to create a new tab
    • F3 to select previous tab
    • F4 to select next tab

    byobu-enable command will configure the current shell to run byobu on startup. Test this is working by typing exit in Termux and start Termux app again. byobu-disable stops this behaviour and byobu will need to be run manually after starting Termux.

    Run the byobu-enable command again if zsh is configured after this step or if adding any other shell to Termux.

    "},{"location":"version-control/","title":"Version Control","text":"

    There are several ways to interact with Git version control, although Practicalli recommends Neogit interactive git client and Octo to manage GitHub issues and pull requests

    • lazygit terminal UI, embedded in Neovim (AstroNvim only)
    • Neogit git client similar to Emacs Magit, with Diffview integration
    • Octo for GitHub Issue and Pull Requests
    • Open in GitHub
    • Shell out to the command line, :!
    • Git commands in Neovim terminal buffer
    "},{"location":"version-control/#init-local-repository","title":"Init local repository","text":"AstroNvim

    Space t f opens floating terminal window in the current project directory root (or which ever directory Neovim was started from).

    Initialise a local git repository in the current directory.

    git init .\n

    "},{"location":"version-control/#stage-in-buffer","title":"Stage in buffer","text":"AstroNvimPracticalli Neovim Config Redux

    The current hunk or the whole buffer can be staged from the buffer using Git Signs, saving a trip to the Git Status buffer.

    Space g H stages the current hunk

    Space g S stages the current buffer

    Not supported.

    "},{"location":"version-control/#git-status","title":"Git Status","text":"AstroNvimPracticalli Neovim Config Redux

    SPC g g opens lazygit status, for minimal UI

    Space g s Space g n ++\"t\" opens neogit in a new tab for Magit style experience

    SPC g s opens Git Status tab, by running :Neogit

    "},{"location":"version-control/#github-integration","title":"GitHub integration","text":"

    Interact with the remote GitHub repository using Octo

    List issues from a specific repository

    :Octo issue list practicalli/neovim\n

    Create a pull request on a specific repository

    :Octo pr create practicalli/neovim\n
    "},{"location":"version-control/diff/","title":"Diff","text":"

    Compare differences between different files or between a file and its versions.

    :diffsplit filename Neovim command opens a split containing the selected filename, showing a diff comparision to the currently opened file

    file path completion helps select the correct file for comparison

    "},{"location":"version-control/diff/#git-diff","title":"Git Diff","text":"

    DiffView compares working space and staged changes side by side, or a diff for git merge conflicts.

    ++SPC++ g d or d in neogit status buffer (SPC g s) will open diffview in a new tab

    q to return to neogit status buffer

    • Green - added lines
    • Yellow - changed line
    • Red - deleted lines
    AstroNvimPracticalli Neovim Config

    Ctrl h / j / k / l to navigate between open splits

    SPC b toggles the sidebar buffer

    SPC w l and SPC w h to move cursor between diff buffer and sidebar buffer

    "},{"location":"version-control/lazygit/","title":"Lazygit version control","text":"Command Line or AstroNvim configuration

    Lazygit interface not provided by Practicalli Neovim Config Redux

    "},{"location":"version-control/lazygit/#requirements","title":"Requirements","text":"

    Install lazygit command line tool

    "},{"location":"version-control/lazygit/#open-lazygit","title":"Open Lazygit","text":"AstroNvimCommand Line

    SPC g g to open git status with lazygit in a popup window

    Change to the root directory of the git managed project.

    Run the lazygit rich terminal UI

    lazygit\n
    "},{"location":"version-control/lazygit/#use-lazygit","title":"Use Lazygit","text":"

    SPC to stage files or directories in the files section of the UI

    c for a simple commit message prompt in the lazygit UI

    C to create a commit message within the

    Define Editor for Git Commit Messages

    Set core.editor in the user Git configuration (i.e. .config/git/config) to the name of the editor to use for commit messages, e.g. nvim, emacsclient) shell title= git config --global core.editor = nvim Alternatively, use the VISUAL or EDITOR environment variable to the choice of editor

    "},{"location":"version-control/neogit/","title":"Neogit - interactive client for Git","text":"

    Neogit is an interactive git client that provides the core features of version control with Git. Neogit emulates many of the features found in magit.

    SPC g s to open :Neogit status buffer

    TAB toggles expansion of sections, files and hunks

    d provide a side-by-side view of changes

    q to quit Neogit and return to the previous tab

    Neovim is configured to use the magit style key bindings in practicalli/neovim-config-redux

    "},{"location":"version-control/neogit/#branching","title":"Branching","text":"

    b opens the branch menu,

    • b - checkout a branch
    • c - create a new branch
    • d - delete a branch, D deletes local and remote branch
    • l - checkout a remote branch and create a local tracking branch
    • m - rename an existing local branch
    • n - create a new branch
    "},{"location":"version-control/neogit/#staging-changes","title":"Staging changes","text":"

    s to stage change under cursor, either file or hunk. S to stage all changes

    u to unstage change under cursor, U to unstage all changes

    v to select lines to stage within a hunk using s or unstage with u

    "},{"location":"version-control/neogit/#commit","title":"Commit","text":"

    c for the commit menu

    c for a new commit, a to amend the latest commit, w to reword a commit message, e to add staged changes to existing commit

    A new commit or amend commit qill open a new window to write a commit message (using a git commit message template if defined)

    :wq to save a commit message and initiate the commit.

    :q! to cancel the commit from the commit message buffer.

    "},{"location":"version-control/neogit/#stashing-changes","title":"Stashing changes","text":"

    Z to open the stash menu

    z to stash the working copy and staged files (index)

    i to only stash the staged files (index)

    "},{"location":"version-control/neogit/#remote-changes","title":"Remote changes","text":"

    F to open the pull menu, p to pull changes (fetch and merge) from the remote repository, u t pull from the upstream repository, or e to specify the remote and branch names.

    P to open the push menu to open, -u to push to the current remote

    Confused when remote is not origin

    Use e option to push to elsewhere when the remote name is not set to origin. The e option will prompt for a remote name and branch.

    "},{"location":"version-control/neogit/#commit-history","title":"Commit history","text":"

    L l to view git commit history log

    RET on a log entry shows the commit details in a new window (split)

    q to close the commit details window

    "},{"location":"version-control/neogit/#modify-git-commit-history","title":"Modify Git commit history","text":"

    r opens the rebase menu

    "},{"location":"version-control/octo/","title":"Octo - GitHub issues and PRs","text":"

    List, create and edit issues and pull requests from Neovim with Octo package.

    Octo connects to GitHub via the GitHub CLI, using a developer token for authentication

    Neogit provides a Magit style client, creating commits, pull & push changes with remote repositories.

    "},{"location":"version-control/octo/#github-interaction","title":"GitHub interaction","text":"

    GitHub CLI

    Work with GitHub issues and Pull Requests from the comfort of Neovim.

    GitHub CLI to authentication to a GitHub account. Successful login creates a local developer token that is used by Octo to communicate with GitHub.

    gh auth login\n
    "},{"location":"version-control/octo/#octo-commands","title":"Octo commands","text":"

    Command line form: Octo <object> <action> [arguments] - Object, Action and Arguments commands

    List issues from current project (optionally add a specific repository)

    :Octo issue list practicalli/neovim\n

    The account/repository-name is required if Octo cannot find the repository

    Create a pull requests from current project

    :Octo pr create\n

    Add a comment to the current topic (issue/pr)

    :Octo comment add\n

    :Octo gist list\n

    Octo.nvim configuration options

    Octo.nvim configuration options

    "},{"location":"version-control/open-in-github/","title":"Open In GitHub","text":"

    Open a file under local version control in the GitHub web UI (browser window).

    Neovim

    :OpenInGHFile

    :OpenInGHRepo

    "}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 38f15a6130af1b3094b2bc0aeac80b59ee36ff07..f1331d81fcb68b021b2a66f67818c30e37c84f1c 100644 GIT binary patch delta 16 XcmbQsHkXZEzMF%CE6QLayBIS7Ar}K} delta 16 XcmbQsHkXZEzMF%i{<{7~b}?oECo=?I