From 0b5d044dd27a7c1b48565f2d1849611c53c7ae67 Mon Sep 17 00:00:00 2001 From: <> Date: Thu, 19 Sep 2024 07:23:20 +0000 Subject: [PATCH] Deployed c5af5f8 with MkDocs version: 1.6.1 --- index.html | 4 +- search/search_index.json | 2 +- sitemap.xml | 148 +++++++++++++++++++-------------------- sitemap.xml.gz | Bin 829 -> 829 bytes 4 files changed, 77 insertions(+), 77 deletions(-) diff --git a/index.html b/index.html index c65683a4..7ef8de90 100644 --- a/index.html +++ b/index.html @@ -2786,7 +2786,7 @@

Neovim for Clojure development Practicalli Astro configuration for Neovim provides Conjure REPL client and Clojure editing support (parinfer & paredit).

Clojure REPL Driven Development workflow

Quick Startλ︎

-

Install Clojure (Practicalli Clojure), Neovim 0.10 and Practicalli Astro configuration

+

Install terminal & tools, Clojure (Practicalli Clojure), Neovim 0.10 and Practicalli Astro configuration

Neovim overviewλ︎

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 to provide a rich set of features for Clojure development and wider engineering tasks.

@@ -2842,7 +2842,7 @@

Creative commons license - September 18, 2024 + September 19, 2024 diff --git a/search/search_index.json b/search/search_index.json index 5f0eb71d..3b6ff7b1 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":"

Practicalli Neovim provides an install & user guide for a simple and powerful REPL driven workflow for Clojure.

Practicalli Astro configuration for Neovim provides Conjure REPL client and Clojure editing support (parinfer & paredit).

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

Install Clojure (Practicalli Clojure), Neovim 0.10 and Practicalli Astro configuration

"},{"location":"#neovim-overview","title":"Neovim overview","text":"

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 to provide a rich set of features for Clojure development and wider engineering tasks.

coding at the speed of thought

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

"},{"location":"#external-reverences","title":"External reverences","text":"

Getting started with Neovim and Conjure

Neovim user guide

Conjure install guide

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

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

Use the search box to quickly find a specific topic

"},{"location":"#sponsor-practicalli","title":"Sponsor Practicalli","text":"

All sponsorship funds are used to support the continued development of Practicalli series of books and videos, although most work is done at personal cost and time.

Thanks 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

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":"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).

Neovim 0.10 latest stable release

Content and configuration in this book has been tested against Neovim 0.10, but not against Neovim nightly builds.

Practicalli Astro config should work with Neovim 0.9.0, except Neogit and ts-comment-nvim comments.

Already have Neovim installed?

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

"},{"location":"install/multiple-configurations/","title":"Multiple Configs","text":""},{"location":"install/multiple-configurations/#multiple-configurations","title":"Multiple Configurations","text":"

Many Neovim configurations can be installed in $HOME/.config/ using unique directory names, e.g. AstroNvim, cajus, lazyvim, kickstart.

Set NVIM_APPNAME to a configuration directory name (relative to $HOME/.config/`) to run Neovim with that specific config.

Run AstroNvim config in $HOME/.config/astronvim/

NVIM_APPNAME=astronvim nvim\n

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

Community Configuration Projects "},{"location":"install/multiple-configurations/#configure-shell-alias","title":"Configure shell alias","text":"

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

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

Define Shell Aliases to run each configuration

alias astro=\"NVIM_APPNAME=nvim-astro nvim\"\nalias lazy=\"NVIM_APPNAME=nvim-lazyvim nvim\"\nalias cajus=\"NVIM_APPNAME=nvim-cajus nvim\"\n
"},{"location":"install/multiple-configurations/#shell-aliases-for-bash-and-zsh","title":"shell-aliases for bash and zsh","text":"

Create a .config/shell-aliases file containing all shell aliases when often switching between different shells, avoiding the need to define aliases twice

Source the .config/shell-aliases file from within .bashrc or .zshrc

ZshBash .zshrc
# Shell Aliases\n[[ ! -f ~/.config/shell-aliases ]] || source ~/.config/shell-aliases\n
.bashrc
# Shell Aliases\nif [ -f ~/.config/shell-aliases ]; then\n    . ~/.config/shell-aliases\nfi\n
"},{"location":"install/multiple-configurations/#neovim-config-selector","title":"Neovim config selector","text":"

Create a shell function to popup a menu with the list of available Neovim configurations, defined in ~/.config where the configuration directories are prefixed with nvim-, e.g. ~/.config/nvim-astro/

Neovim Config Fuzzy Finder

.local/bin/nvim-fuzy-find
nvim-fuzy-find() {\n  # All config paths are prefixed with ~/.config/nvim-\n  local config=$(fdfind --max-depth 1 --glob 'nvim-*' ~/.config | fzf --prompt=\"Neovim Configs > \" --height=15% --layout=reverse --border --exit-0)\n\n  [[ -z $config ]] && echo \"No config selected, Neovim not starting\" && return\n\n  # Open Neovim with selected config\n  NVIM_APPNAME=$(basename $config) nvim $@\n}\n
Neovim Config simple Selector

Add the Neovim config directory names from ~/.config/ .local/bin/nvim-selector

 nvim-selector() {\n  select config in nvim-astro nvim-astronvim-template nvim-lazyvim nvim-kickstart\n  do NVIM_APPNAME=nvim-$config nvim $@; break; done\n}\n

"},{"location":"install/neovide/","title":"Neovide GUI","text":"

Neovide provides a GUI for Neovim and supports the use of AstroNvim community configuration.

Neovide features

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

Download from Neovide.dev website

DebianMacOSX

Download neovide.AppImage

Move the neovide.AppImage to the execution path, e.g. $HOME/.local/bin

Create the $HOME/.local/bin/neovide symbolic link pointing to the neovide.AppImage

ln -s $HOME/.local/bin/neovide.AppImage $HOME/.local/bin/neovide\n

Download the MacOSX dmg.zip file

Extract the .zip file

Run the extracted dmg file and use the install wizard to copy Neovide to the Applications directory.

Create symbolic link from Neovide install to ~/.local/bin

ln -s /Applications/neovide.app/Contents/MacOS/neovide ~/.local/bin/neovide\n

Add alias to use neovide with astronvim configuration to .bashrc , .zshrc or shared shell-aliases file

alias neovide=\"NVIM_APPNAME=astronvim neovide\"\n
"},{"location":"install/neovide/#neovide-with-nvim_appname","title":"Neovide with NVIM_APPNAME","text":"

NVIM_APPNAME sets the configuration used when starting Neovim.

Use a shell alias to run Neovide with a specific configuration

# Neovide alias with AstroNvim configuration\nalias neovide=\"NVIM_APPNAME=astronvim neovide\"\n
"},{"location":"install/neovide/#set-neovide-font","title":"Set Neovide Font","text":"

The guifont Neovim option is used to set a font family and size specifically for a GUI appliction, i.e. Neovide. It is not used by Neovim itself.

Ctrl+= and Ctrl+- increase & decrease the font size in Neovide (move the cursor if no immediate effect is seen)

Neovide recipe

Astro Community provides an neovide recipe with recommended options.

lua/plugins/community.lua
{ import = \"astrocommunity.recipes.neovide\" },\n

This recipe is include in the lua/community.lua file from Practicalli Astro configuration, with a font override in lua/plugins/user-practicalli.lua to set the preferred font.

  {\n    \"AstroNvim/astrocore\",\n    ---@type AstroCoreOpts\n    opts = {\n      options = {\n        -- configure general options: vim.opt.<key>\n        opt = {\n          guifont = \"Fira Code:h16\", -- neovide font family & size (height)\n        },\n      },\n    },\n  }\n

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

Neovim 0.10.x is the latest stable version

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

Neovim uses several command line tools for searching for files and their contents, using the operating system clipbaord and compiling Treesitter language parsers.

Install the following tools to support Neovim and AstroNvim

Treesitter requires a C compiler

nvim-treesitter requires a C compiler , e.g. gcc for Linux or clang for android/termix

The C compiler is used to compile langauge support for treesiter.

AstroNvim requires node.js

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

Node.js install - Practicalli Engineering Playbook

Debian PackagesMacOSX Homebrew
apt install fd-find xclip luarocks nodejs\n
Wayland requires wl-clipboard

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

apt install wl-clipboard\n

MacOSX requires the libintl and gettext tools as well as the other supporting tools.

brew install libintl gettext ripgrep fd luarocks\n
"},{"location":"install/neovim/#install-neovim","title":"Install Neovim","text":"

Install from the Neovim GitHub releases for the latest version of Neovim, or use a Package manager for the operating system.

Linux AppImageMacOSX HomebrewMacOSX GitHub ReleaseDebian PackageBuild from Source

Download the Linux 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 $HOME/.local/bin/nvim.appimage\n

Create a symbolic link called nvim to the nvim.appimage file.

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

nvim command can now be run in a terminal from any directory.

Install from Homebrew or via the Neovim Release page

Homebrew

brew install neovim\n

Neovim Release

Download nvim-macos.tar.gz From the Neovim GitHub release page

Avoid \"unknown developer\" warning from MacOSX

xattr -c ./nvim-macos.tar.gz\n

Make a local apps directory for neovim (and other things like node.js, etc.)

mkdir -P ~/.local/apps\n

Extract the neovim archive

tar zvxf nvim-macos.tar.gz -C ~/.local/apps/\n

Create the ~/.local/bin/nvim symbolic link to include Neovim on the OS execution path

echo $PATH to check .local/bin is included in the execution the path by the Operating System command line shell

ln -s ~/.local/apps/nvim-macos/bin/nvim ~/.local/bin/nvim\n

Run\u00a0nvim (or setup a Neovim configuration first, e.g. AstroNvim)

From the Neovim GitHub release page:

  1. Install\u00a0libintland\u00a0gettext\u00a0(e.g. via\u00a0brew install libintl gettext)
  2. Download\u00a0nvim-macos.tar.gz
  3. Run\u00a0xattr -c ./nvim-macos.tar.gz\u00a0(to avoid \"unknown developer\" warning)
  4. Make local apps directory for neovim (and other things like node.js, etc.)
mkdir -P ~/.local/apps\n
  1. Extract the neovim download
tar zvxf nvim-macos.tar.gz -C ~/.local/apps/\n
  1. Create nvim symbolic link in ~/.local/bin to include Neovim on the OS execution path (check .local/bin is added to the execution the path by the Operating System command line shell)
ln -s ~/.local/apps/nvim-macos/bin/nvim ~/.local/bin/nvim\n

Linux version only packaged as AppImage from Neovim 0.9 onward

A .deb file can be created after building Neovim from source.

Neovim build guide

Neovim Build Prerequisites for each operating system

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\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/#practicalli-astro-config","title":"Practicalli Astro Config","text":"

Practicalli Astro is Clojure development focused configuration, an extension of the AstroNvim template repository.

Clone the Practicalli Astro config or create your own fork and clone that repository.

Clone Practicalli Astro config

git clone https://github.com/practicalli/astro.git ~/.config/nvim\n
Multiple Neovim Configurations

Clone the configuration to a unique name within ~/.config directory.

git clone https://github.com/practicalli/astro.git ~/.config/nvim-astro\n

Set the NVIM_APPNAME environment variable to the configuration directory name under ~/.config

e.g. Run Neovim using the configuration in ~/.config/astro

export NVIM_APPNAME=nvim-astro nvim\n

Configure shell alias and selectors to simplify the command to run a specific configuration.

Practicalli Astro design & override guide

"},{"location":"install/neovim/#install-neovim-plugins","title":"Install Neovim Plugins","text":"

Enter nvim command in a terminal to launch Neovim and install all the plugins from the Practicalli Astro configuration.

Run Neovim

nvim\n

Lazy plugin manager runs automatically and installs all the plugins defined in the Neovim configuration.

Treesitter will prompt to compile its language parsers.

q to close the lazy package manager pop-up once all plugins are installed.

Plugin install without UI display

Use the --headless Neovim flag to install plugins without running whole Neovim editor user interface.

nvim --headless\n
"},{"location":"install/neovim/#post-install-checks","title":"Post Install checks","text":"

Troubleshoot the Neovim configuration and supporting tools by running the Neovim Heath Check.

Use the :checkhealth command in Neovim or start Neovim with the Health Check command.

Run Neovim and start Health Check

nvim +:checkhealth\n

A report is generated and shown in Neovim

j / j 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.

"},{"location":"install/terminal-tools/","title":"Terminal Tools and Fonts","text":"

Neovim is a terminal based application so use of a quality terminal is recommended, e.g. Kitty Terminal (or iTerm2 if only on MacOSX)

External Command line tools support search and other system information based features presented in AstroNvim.

Nodejs supports Language Server protocol servers, format and lint tools installed by Mason.

"},{"location":"install/terminal-tools/#kitty-terminal-with-nerd-fonts","title":"Kitty Terminal with Nerd Fonts","text":"

Neovim runs in a terminal, so using Kitty (or iTerm2 - MacOSX only) are recommended. Kitty provides Nerd fonts for additional symbols on top of the terminal font, providing a richer experience.

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

Nerd Fonts

"},{"location":"install/terminal-tools/#command-line-tools","title":"Command line tools","text":" Debian packagesHomebrew

Install fzf, gdu and node.js via debian package manager

apt install fzf gdu\n

Install fzf, gdu and node.js via Homebrew package manager

brew install fzf gdu\n

Install btm from its GitHub repository release page

"},{"location":"install/terminal-tools/#nodejs-for-lsp-format-lint-tools","title":"nodejs for LSP, format & lint tools","text":"

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

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

Neovim News for new developments

Keep up to date with new features within Neovim

:help news.txt\n
Use the version name to view specific features of a release
:help news-0.9.5.txt\n

"},{"location":"introduction/features/#neovim-features-for-development","title":"Neovim features for development","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

"},{"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.

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:

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 "},{"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":""},{"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.

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

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

"},{"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

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.

"},{"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":"neovim-basics/","title":"Using Neovim","text":"

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

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

Multi-modal Editing File Buffer Window and Tab page

"},{"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/#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.

Map Listing: Neovim docs Key Notation: Neovim docs

"},{"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":"

SPC e opens Neo-tree.nvim which shows a visual tree to navigate and manage files from the current project (root). Files and directories can be added, renamed, moved and deleted.

Space f f to find files with Telescope, typing a pattern narrows the selectable file list.

Set root directory in Neovim

All file commands respect the currently set directory root for Neovim.

The root is set to the current directory when opening a file.

:cd ~/new/directory/path will change the current root to the new path.

. in Neotree sets the root to the current directory (parent directory if on a file)

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

Space e toggles neo-tree file browser

Space o toggles between buffer and neo-tree

Enter in Neo-tree opens the current file in a buffer

"},{"location":"neovim-basics/file-buffer-window-tab/#key-bindings-within-neo-tree","title":"Key bindings Within Neo-tree","text":"

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 / 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

Configure hidden files

Configure Neotree to display hidden files and directories by default. They are shown with a different visual style (subtle color) compared to the other files and directories.

H with the cursor in neotree window will still toggle the display of hidden files and directories.

Optionally, specify files or directories to never show. lua/plugins/neo-tree.lua

---@type LazySpec\nreturn {\n  \"nvim-neo-tree/neo-tree.nvim\",\n  config = function()\n    require(\"neo-tree\").setup {\n      filesystem = {\n        filtered_items = {\n          visible = true, -- show hidden files in alternate style\n          hide_dotfiles = true,\n          hide_gitignored = true,\n          hide_hidden = true, -- only works on Windows for hidden files/directories\n          hide_by_name = {\n            --\"node_modules\"\n          },\n          hide_by_pattern = { -- uses glob style patterns\n            --\"*.meta\",\n            --\"*/src/*/tsconfig.json\",\n          },\n          always_show = { -- remains visible even if other settings would normally hide it\n            --\".gitignored\",\n          },\n          never_show = { -- remains hidden even if visible is toggled to true, this overrides always_show\n            --\".DS_Store\",\n            --\"thumbs.db\"\n          },\n          never_show_by_pattern = { -- uses glob style patterns\n            --\".null-ls_*\",\n          },\n        },\n      },\n    }\n  end,\n}\n

"},{"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).

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)

"},{"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 (!)

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

Space W was added to Practicalli Astro Config as a key binding for :write path/to/filename which writes the current buffer to a new file, prompting for the file name.

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

"},{"location":"neovim-basics/file-buffer-window-tab/#path-commands","title":"Path commands","text":"

: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\n

-p option creates 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/#directories","title":"Directories","text":"

a in Neotree to create a file or by adding a ++forward-slash++ at the end of the name a directory is created.

Use the mkdir shell command to create a new directory, which is created relative to the current path, which can be checked with :lcd

:!mkdir full/path/to/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\n

mkdir -p - the UNIX command to create a folder, the -p option creating any parts of the path required to make the full path

% - name of the current file

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

! - the NeoVim terminal shell command

"},{"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

: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":"

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

Open multiple buffers at starup

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
"},{"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

Space u SPC u w toggles wrapping of text

"},{"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.

\\ creates an horizontal split

SPC q removes the current split

Neovim commands

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.

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":"

Multi-modal editing has several states optomised for interacting with text

Normal mode to insert mode:

v to enter visual select, using navigation and/or motions to select a range.

Esc to leave insert or visual mode and return to normal mode.

"},{"location":"neovim-basics/multi-modal-editing/#command-language","title":"Command language","text":"

Learn to speak modal editing commands as sentences to effectively learn Multi-modal editing

Verbs start the sentence and are the action to perform

Modifiers (motions) follow verbs and define where the cursor moves to.

Text objects provide scope for verbs and modifiers

Examples of speaking Evil

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 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 SPC v s \" visually select current word and surround with \"\" 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)

Evil Reference and Tips

Evil quick reference guide Evil tips for developers Speaking Vim

"},{"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 substitutes the selection, type the characters to surround the selection.

p to paste 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.

Practicalli Spacemacs - Evil reference

"},{"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

"},{"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:

"},{"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

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:

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:

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:

`: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

"},{"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:

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

Others can use a different mapping:

"},{"location":"neovim-basics/navigation/","title":"Navigation","text":"

Move the cursor one space at a time

"},{"location":"neovim-basics/navigation/#jump-along-line","title":"Jump along line","text":"

Move to specific points within a line

Uppercase w b e consider word delimited by blank characters

Jump joined-word using W B E

Use w b e movement with a number to move the cursor larger distances

jump 3 words forward
3w\n

f jumps forward in the current line to the given character

jump to next q character
fq\n

F jumps backward in the current line to the given character

jump to previous [ character
F[\n

t jumps forward in the current line to before the given character

jump before q character
tq\n

T jumps backward in the current line to after the given character

jump after [ character
T[\n
"},{"location":"neovim-basics/navigation/#jump-around-buffer","title":"Jump around buffer","text":"

Use cursor movement with a number to move the cursor larger distances

jump down 12 lines
12j\n
Relative line numbers for line navigation

Enable relative line numbers to show how far away from the current line each other line is.

set relativenumber\nset number\n

Practicalli AstroNvim-Config enables relative line numbers

Jump to a specific line using the number as a command

jump to line number
:127\n
"},{"location":"neovim-basics/navigation/#navigate-position-history","title":"Navigate position history","text":"

++ctrl+\"o\" jumps to a previous postion in the cursor history

++ctrl+\"i\" jumps to a previous postion in the cursor history

"},{"location":"neovim-basics/navigation/#file-marks","title":"File marks","text":"

Navigate within the current file or globally using file marks.

m followed by a lower case character creates a mark within the current file.

m followed by an upper case character creates a global mark.

` (backtick) followed by a character jumps to the mark created

Space f ' displays marks in telescope popup

File marks within file

m f creates a mark lablled f

` f jumps to the mark labelled f

Global mark to jump between source and test code

m S with the cursor in the source code file.

m T with the cursor in the test code file.

` S to jump to the source code

` T to jump to the source code

"},{"location":"neovim-basics/navigation/#jumplist","title":"Jumplist","text":"

:jumps shows the Neovim jumplist containing all points from any buffer recently jumped to using neovim commands

"},{"location":"neovim-basics/navigation/#changes","title":"Changes","text":"

:changes shows the Neovim changelist containing all points in the current buffer which have changed

"},{"location":"neovim-basics/navigation/#navigation-menus","title":"Navigation menus","text":""},{"location":"neovim-basics/navigation/#search-in-buffer","title":"Search in buffer","text":"

/ searches buffer for the following pattern

AstroNvim user config enables incsearch incremental search and hlsearch to highlight every search match

"},{"location":"neovim-basics/navigation/#projects","title":"Projects","text":"

: c d followed by a path changes the root directory for Neovim.

Tab completion simplifies typing the new path of the root directory.

AstroNvim rooter

AstroNvim has a built-in project root detection utility that updates the current working directory automatically.

"},{"location":"neovim-basics/notifications/","title":"Notifications","text":"

Notification messages are shown in the bottom right corner of Neovim. Multiple messages are show bottom upwards.

Notifications are set to show for 2 seconds and then are automatically closed.

Notification popups show information, warnings and errors.

"},{"location":"neovim-basics/notifications/#message-history","title":"Message History","text":"

History of notifications can be browsed to see more detail and to select the text of a notification.

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

Enter to open the highlighted item in the list in its own pop-up

y y to yank the text of a notification when displayed in a pop-up

Noice used for notifications UI

Practicalli Astro config uses Noice to draw the UI for notification messages, command line and popup menus.

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

Notifications are controlled by nvim-notify

Practicalli Astro Configuration for notifications

lua/community.lua
  -- Configure notify popups\n  {\n    \"rcarriga/nvim-notify\",\n    opts = {\n      top_down = false,\n      timeout = 2000,\n      -- log level - 3 hide file write messages - default 5\n      level = 3,\n      -- background_color = \"#000000\",\n    },\n  },\n
"},{"location":"neovim-basics/plugin-manager/","title":"Lazy 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 plugin manager recommended

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

"},{"location":"neovim-basics/plugin-manager/#plugin-updates","title":"Plugin Updates","text":"

Space p S shows the install and loaded status for all plugins defined in the Neovim configuration, e.g. lua/community.lua and lua/plugins/*.lua files

Space p S checks for updated plugin versions and automatically installs them

The changelog is shown for all updated plugins, highlighting breaking changes. Conventional commits style is used for most plugins, making it easier to follow the most important changes.

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

Neovim use registers to store and access text using Neovim commands.

\" to access a register by name.

The name of a register is a number, alphabetical or special character.

SPC f r lists the values of registers in a telescope popup

Yank and paste commit message

Select the text of the commit message

\" m y yanks the selected text into register m

Complete the Git commit. When creating a new commit, paste the message from the register

\" m p pastes the register text into the commit message buffer

Paste last evaluation result from Conjure

When Conjure evaluates code the result is stored in the C register.

\" C p pastes the register text into the commit message buffer

"},{"location":"neovim-basics/registers/#registers","title":"Registers","text":"

Neovim help - registers

:help registers\n

\" the unnamed register, used by Neovim normal commands, e.g. c d p s x y, etc.

0 to 9 numbered registers containing yank and delete history

- small delete register for text smaller than a line

a to z named registers manually selected, A to Z to append to the text already in the register

: . and % read-only registers use with put commands (last inserted, current file name, recent command)

# alternate buffer file name

= expression register for the result of runing a Neovim command expression

+ and * selection registers for GUI

_ black hole register does not store text, use when normal commands shouldnt update other registers

/ last search pattern register used

"},{"location":"neovim-basics/registers/#find-registers","title":"Find Registers","text":"

SPC f r opens the list of registers in a telescope popup.

Registers in insert mode

C-r in insert mode pastes the content of the given register, e.g. C-r a to paste the content of \"a

"},{"location":"neovim-basics/snippets/","title":"Snippets","text":"

LuaSnip can use several different sources for 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

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/spell-check/","title":"Spell Check","text":"

Neovim has a built-in spell check tool. Grammar checks are not supported.

Incorrect words have a red squiggly underscore.

z = with the cursor on a word shows a list of possible spelling and similar words.

Select a word using its number in list to replace the word under the cursor, or Esc to close the spelling list.

Key Description z = spelling suggestions [ s next incorrect word ] s previous incorrect word z g add word to spelling list z w mark word as misspelled Space u s toggle spellcheck"},{"location":"neovim-basics/terminal/","title":"Terminal","text":"

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

Space t for the Terminal sub-menu

Space t f opens a terminal in a floating window, useful for one-off commands or short sessions

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

:Toggleterm direction=tab opens a terminal in a tab page, useful for long running processes

"},{"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":"neovim-basics/search-replace/","title":"Search and Replace","text":"

Neovim has several built-in commands to search for patterns in the current buffer and quickfix list can be used to run commands across all the files in a project.

Additional tools that work across all the files in a project:

multiple cursors for in-place editing within a buffer

"},{"location":"neovim-basics/search-replace/#buffer-search","title":"Buffer search","text":"

/ searches through the current buffer, prompting for a pattern to search.

Symbol highlight and dot repeat

# on a word highlights each occurrence in the buffer, n and N to jump backward and forward for each instance.

Change the current occurrence (e.g. cw followed by new word)

Use . to repeat the change after jumping to the next instance.

"},{"location":"neovim-basics/search-replace/#substitute-command","title":"Substitute command","text":"

Use the :substitute (:s) to replace all occurrences of the current-pattern with the new pattern within the buffer.

Replace using substitute command

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

Add the c option to confirm each replacement

:substitue neovim command examples

"},{"location":"neovim-basics/search-replace/#project-search-and-replace","title":"Project search and replace","text":"

Use search to populate the Neovim quickfix list and change occurrences across all the files in the current project, e.g.:

Search word and replace across project using quickfix list

Space f w to search for the supplied word or pattern

Ctrl q opens the search results in quickfix list

Use :cdo command to search and replace in the quickfix list

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

Including the c option to confirm each replacement

"},{"location":"neovim-basics/search-replace/#spectre","title":"Spectre","text":"

Spectre shows occurrences of a pattern throughout all project files, replace individual or all occurrences.

Search and replace with Spectre

Space s is the search and replace menu

Enter a Search pattern and all occurrences across the project are shown

Enter a Replace pattern to see occurrences with their replacement

R to replace all occurrences with the replace pattern

C to replace current occurrence

q adds the Spectre search results to quickfix list to edit occurrences with other Neovim tools

ripgrep and sed are required.

Spectre

"},{"location":"neovim-basics/search-replace/spectre/","title":"Spectre","text":"

Space s s to toggle Spectre (open/close) to search and replace tool.

? for the Spectre key mappings

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

i underneath Search and enter a search pattern, Esc to see resuts in a popup below.

i underneath Replace and enter a replace pattern, Esc to see in-line diff results

v toggles Spectre results view between diff to search to replace view

d d to toggle an occurance

R replaces all occurances (after selecting the occurances to change)

A DONE checkbox is show at then end of each selection which has been reaplaced

To replace single occurance, toggle all occurances that should not be changes and press R

Spectre does not undo changes

Use Git or Neovim undo to rollback changes made by Spectre.

Spectre is available via the AstroNvim Community project pack and included in the Practicalli astronvim-config

ripgrep and sed are required.

Spectre project

"},{"location":"neovim-basics/search-replace/substitute/","title":"Substitute command","text":"

:substitute or :s command highlights the matches for a text pattern and substitute for a new pattern

Neovim :help :substitute
:help :substitute\n

Subsitute the first matching patterns in the current line

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

If the new-pattern text is ommitted, then substitute deletes the current-pattern occurances, e.g :s/current-pattern//

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

An inclusive line range can be specified to narrow the search

:4,24s/current-pattern/new-pattern/g\n

. can be used to represent the current line of buffer

$ to represent the last line of the current buffer

:.,$s/current-pattern/new-pattern/g\n

Match the whole word

:.,$s/\\<current-pattern\\>/new-pattern/g\n
"},{"location":"neovim-basics/search-replace/substitute/#substitute-history","title":"Substitute history","text":"

:s and the Up / Down will navigate through the substitution history for the current session (from when Neovim was last opened if session was not restored)

"},{"location":"neovim-basics/search-replace/substitute/#confirm-replacement","title":"Confirm replacement","text":"

c option at the end prompt for confirmation to replace each occurance

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

y confirms the repacement

l confirms the repacement and quits

n skips the current occurance and goes to the next one

y or Esc to quit substitution

"},{"location":"neovim-basics/search-replace/substitute/#regular-expression","title":"Regular expression","text":"

regular expressions can be used as a search pattern.

To replace all lines starting with \u2018foo\u2019 with \u2018NeoVim Rocks\u2019:

:%s/^foo.*/NeoVim rocks/gc\n

Replace all instances of \u2018apple\u2019, \u2018orange\u2019, and \u2018mango\u2019 with \u2018fruit\u2019:

:%s/apple\\|orange\\|mango/fruit/g\n

Remove trailing blank space at the end of each line:

:%s/\\s\\+$//e\n
"},{"location":"neovim-basics/search-replace/substitute/#matching-case","title":"Matching case","text":"

i option disables the default case sensitive search

:%s/current-pattern/new-pattern/gi\n
"},{"location":"neovim-basics/search-replace/substitute/#visual-select","title":"Visual Select","text":"

Use a visual select to search and replace, with confirmation

Note: '<,'> is automatically included when in visual mode and : is pressed to start a command

:'<,'>s/search-text/replace-text/g\n

A potentially more effecitve approach:

"},{"location":"reference/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":"reference/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.

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":"reference/fennel/#fennel-packages","title":"Fennel Packages","text":"

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

"},{"location":"reference/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":"reference/fennel/#development-tooling","title":"Development tooling","text":"

Neovim support

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

Guide to plugin development with fennel

Emacs support:

"},{"location":"reference/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":"reference/configuration/","title":"\ud83d\udce6 Practicalli Astro Config Design","text":"

A guide to the design of AstroNvim Config created by Practicalli to support a comprehensive development workflow.

AstroCommunity Plugin Configurations used where available

Plugin configurations from AstroCommunity are used to minimise the code size and maintenance of the Practicalli configuration

Under review after migration to AstroNvim 4

"},{"location":"reference/configuration/#files-overview","title":"Files overview","text":"

The file structure as taken from the AstroNvim template and new files were created to minimise changes, making it simpler to add updates from the original template repository.

Key - AstroNvim template file changes

Icons describing if a file was added, changed or unchanged from the AstroNvim template

init.lua ensures the Lazy package manager is available when Neovim starts up. This file is unchanged from the AstroNvim template.

lua/lazy_setup.lua configures the Lazy package manager. zipPlugin enabled to support Clojure docs and source navigation inside libraries.

lua/community.lua imports plugin configurations from AstroCommunity, including the Clojure pack.

lua/polish.lua general lua configuration loaded after AstroNvim configs.

lua/plugins/ for additional plugins organised logically. All .lua files are automatically loaded from this directory when starting Neovim.

"},{"location":"reference/configuration/#disable-plugins","title":"Disable Plugins","text":"

Practicalli Astro provides a rich set of Neovim plugins. Any plugin can be configured as disabled, usually in a user configuration, e.g. lua/plugins/user-practicalli.lua

Disable parinfer and sexp plugins

lua/plugins/user-practicalli.lua
  -- ----------------------------------------------\n  { \"nvim-parinfer\", enabled = false },\n  { \"nvim-treesitter-sexp\", enabled = false },\n  -- ----------------------------------------------\n
"},{"location":"reference/configuration/#clojure-support","title":"Clojure support","text":"

The AstroCommunity provides a Clojure language pack that ensures clojure Treesitter parser and clojure-lsp support and installed automatically.

The pack contains 4 Neovim plugins:

!!! INFO: \"Practicalli AstroNvim Config includes Clojure pack\"

AstroCommunity Clojure 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
Exclude a plugin from the pack

The Clojure pack includes parinfer and paredit tools for structural editing, which both work together without issue. Should one or both of these plugins not be reqiured, set enabled to false

return {\n  \"AstroNvim/astrocommunity\",\n  { import = \"astrocommunity.pack.clojure\" },\n  { \"gpanders/nvim-parinfer\", enabled = false },\n

Override Conjure configration

Add the AstroCommunity Clojure pack and additional configuration to create a tailored experience

:help conjure for general Conjure options.

:help conjure-client-clojure-nrepl for Clojure specific options.

return {\n  \"AstroNvim/astrocommunity\",\n  { import = \"astrocommunity.pack.clojure\" },\n  {\n    \"AstroNvim/astrocore\",\n    opts = {\n      options = {\n        g = {\n          -- show HUD REPL log at startup\n          [\"conjure#log#hud#enabled\"] = false,\n\n          -- Hightlight evaluated forms\n          -- [\"conjure#highlight#enabled\"] = true,\n\n          -- Trim log after number of lines. Default: `10000`\n          -- [\"conjure#log#trim#at\"] = 200,\n          -- Trim log to number of lines. Default: `7000`\n          -- [\"conjure#log#trim#to\"] = 100,\n\n          -- auto repl (babashka)\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false,\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true,\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil,\n          [\"conjure#client#clojure#nrepl#eval#auto_require\"] = false,\n\n          -- Test runner: \"clojure\", \"clojuresCRipt\", \"kaocha\"\n          [\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\",\n        },\n      },\n    },\n  },\n}\n
Config comment for parinfer

The parinfer comment configuration may not be required when using ts-comment.nvim to set the Clojure comment pattern.

{\n  \"gpanders/nvim-parinfer\",\n  filetype = { \"clojure\" },\n  config = function()\n    vim.g.parinfer_force_balance = true\n    vim.g.parinfer_comment_chars = \";;\"\n  end,\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

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

Manual install of Treesitter Clojure Parser

: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

Switch to Parinfer Parens mode for Paredit structural editing

Changing the Parinfer mode to paren gives a structured editing experience similar to Paredit (or Smartparens).

Add the following configuration within the return {} table in the plugins/community.lua file to set the parinfef mode, i.e. paren, smart or indent (default

plugins/community.lua
  {\n    \"gpanders/nvim-parinfer\",\n    ft = { \"clojure\" },\n    config = function()\n      vim.g.parinfer_force_balance = true\n      vim.g.parinfer_comment_chars = \";;\"\n      vim.g.parinfer_mode = \"paren\"\n    end,\n  },\n
"},{"location":"reference/configuration/#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":"reference/configuration/#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":"reference/configuration/#snippets","title":"Snippets","text":"

The AstroNvim user example includes a commented LuaSnip configuration

LuaSnip with json format snippets in snippets/ directory

.config/astronvim-config/plugins/core.lua
return {\n  --LuaSnip with json format snippets in `snippets/` directory\n  {\n    \"L3MON4D3/LuaSnip\",\n    config = function(plugin, opts)\n      require \"astronvim.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 = { \"./snippets\" } } -- include JSON style snippets\n      local luasnip = require \"luasnip\"\n      luasnip.filetype_extend(\"javascript\", { \"javascriptreact\" })\n    end,\n  },\n}\n
"},{"location":"reference/configuration/#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":"reference/configuration/#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

  {\n    -- AstroUI provides the basis for configuring the AstroNvim User Interface\n    -- Configuration documentation can be found with `:h astroui`\n    \"AstroNvim/astroui\",\n    ---@type AstroUIOpts\n    opts = {\n      colorscheme = \"everforest\",\n    },\n  },\n

AstroCommunity themes

"},{"location":"reference/configuration/#configure-lazy-plugins","title":"Configure Lazy plugins","text":"

Lazy.nvim Plugin specification

"},{"location":"reference/configuration/#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":"reference/configuration/#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":"reference/configuration/#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":"reference/configuration/astrocommunity/","title":"Override Astrocommunity Configuration","text":"

Configuration in the AstroNvim Community clojure language pack can be overridden and plugins disabled to meet your needs

"},{"location":"reference/configuration/astrocommunity/#parinfer","title":"Parinfer","text":"

By aligning clojure code correctly, parinfer will automatically correct the position of parenthesis and other delimiters, i.e. (), [], {}

Parinfer can be disabled if preferred and the more traditional slurp/barf structural editing be done via nvim-treesitter-sexp

Include the Clojure language pack and disable the parinfer plugin by setting the plugin name to equal false

  { import = \"astrocommunity.pack.clojure\" },\n  { \"gpanders/nvim-parinfer\", enabled = false },\n
"},{"location":"reference/configuration/astrocommunity/#conjure","title":"Conjure","text":"

Configure the Clojure REPL client via the conjure plugin.

NOTE: :help conjure-client-clojure-nrepl for full list of Conjure options for Clojure.

Set HUD location to full width along the bottom of the screen. The HUD appears in the top right corner of the screen by default.

            [\"conjure#log#hud#enabled\"] = true,  -- enable HUD\n            [\"conjure#log#hud#width\"] = 1,\n            [\"conjure#log#hud#anchor\"] = \"SE\",\n            [\"conjure#log#botright\"] = true,\n

Disable the auto repl (babashka) if an nREPL process is not listening, i.e. .nrepl-port file does not exist or does not contain a port number.

            -- Disable auto repl (babashka)\n            [\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false,\n            [\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true,\n            [\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil,\n            [\"conjure#client#clojure#nrepl#eval#auto_require\"] = false,\n

Change the test runner used by Conjure. clojure.test runner is used by default

            -- Set Test runner: \"clojure\", \"clojuresCRipt\", \"kaocha\"\n            [\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\",\n

Working example with additional configuration options to show HUD along bottom, enable auto repl if no nREPL process found and set test runner to use lambdaisland/kaocha.

  { import = \"astrocommunity.pack.clojure\" },\n  {\n    \"AstroNvim/astrocore\",\n    opts = {\n      options = {\n        g = {\n          -- Enable HUD and show full lenght along bottom\n          [\"conjure#log#hud#enabled\"] = true, -- show log by default?\n          [\"conjure#log#hud#width\"] = 1,\n          [\"conjure#log#hud#anchor\"] = \"SE\",\n          [\"conjure#log#botright\"] = true,\n\n          -- Disable auto repl (babashka)\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false,\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true,\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil,\n          [\"conjure#client#clojure#nrepl#eval#auto_require\"] = false,\n\n          -- Set Test runner: \"clojure\", \"clojuresCRipt\", \"kaocha\"\n          [\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\",\n        },\n      },\n    },\n  },\n
"},{"location":"reference/configuration/astrocommunity/#nvim-treesitter-sexp","title":"nvim-treesitter-sexp","text":"

Treesitter based structural editing with normal mode key mappings, which can be set to false to disable. Two commands are disabled in the example.

Additional which-key keymaps can be included for greater discoverability. Example includes keymaps inspired by Spacemacs Lisp mode, SPC k.

  { import = \"astrocommunity.pack.clojure\" },\n  {\n    \"PaterJason/nvim-treesitter-sexp\",\n    dependencies = {\n      \"AstroNvim/astrocore\",\n      opts = {\n        -- configuration & keymaps overrides:\n        -- https://github.com/PaterJason/nvim-treesitter-sexp#configuration\n        -- enabled = false,  -- Set to false to disable individual keymaps\n        -- set_cursor = true,\n        -- keymaps = {\n        -- Default key bindings - set to false to disable\n        --   commands = {\n        --     promote_elem = false,\n        --     promote_form = false,\n        --   },\n        --   motions = {\n        --   },\n        --   textobjects = {\n        --   },\n        -- },\n        options = {\n          g = {},\n        },\n        mappings = {\n          n = {\n            -- Additional Which-key key bindings for nvim-treesitter-sexp\n            [\"<Leader>k\"] = { name = \"Structural Editing\" },\n            [\"<Leader>kE\"] = { \"<Cmd>TSSexp swap_prev_elem<CR>\", desc = \"Swap Previous Element\" },\n            [\"<Leader>ke\"] = { \"<Cmd>TSSexp swap_next_elem<CR>\", desc = \"Swap Previous Element\" },\n            [\"<Leader>kF\"] = { \"<Cmd>TSSexp swap_prev_form<CR>\", desc = \"Swap Previous Form\" },\n            [\"<Leader>kf\"] = { \"<Cmd>TSSexp swap_next_form<CR>\", desc = \"Swap Previous Form\" },\n            [\"<Leader>kk\"] = { \"<Cmd>TSSexp promote_elem<CR>\", desc = \"Promote Element\" },\n            [\"<Leader>kr\"] = { \"<Cmd>TSSexp promote_form<CR>\", desc = \"Promote Form\" },\n            [\"<Leader>k@\"] = { \"<Cmd>TSSexp splice<CR>\", desc = \"Splice\" },\n            [\"<Leader>kS\"] = { \"<Cmd>TSSexp slurp_left<CR>\", desc = \"Slurp Left\" },\n            [\"<Leader>ks\"] = { \"<Cmd>TSSexp slurp_right<CR>\", desc = \"Slurp Right\" },\n            [\"<Leader>kB\"] = { \"<Cmd>TSSexp barf_left<CR>\", desc = \"Barf Left\" },\n            [\"<Leader>kb\"] = { \"<Cmd>TSSexp barf_right<CR>\", desc = \"Barf Right\" },\n            [\"<Leader>kI\"] = { \"<Cmd>TSSexp barf_right<CR>\", desc = \"Insert Head\" },\n            [\"<Leader>ki\"] = { \"<Cmd>TSSexp barf_right<CR>\", desc = \"Insert Tail\" },\n          },\n          t = {\n            -- terminal? mode key bindings\n          },\n          v = {\n            -- visual mode key bindings\n          },\n        },\n      },\n    },\n  },\n
"},{"location":"reference/configuration/practicalli/","title":"Neovim Config Redux","text":"

Practicalli Config Redux has been archived

Practicalli Neovim uses the AstroNvim config.

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":"reference/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":"reference/configuration/practicalli/config-design/","title":"Config Design","text":"

The overall design of the Practicalli Neovim Config Redux

"},{"location":"reference/configuration/practicalli/config-design/#initlua","title":"init.lua","text":""},{"location":"reference/configuration/practicalli/config-design/#fnlconfiginitfnl","title":"fnl/config/init.fnl","text":""},{"location":"reference/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":"reference/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":"reference/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:

"},{"location":"reference/configuration/practicalli/config-design/#fnlconfigplugintreesitterfnl","title":"fnl/config/plugin/treesitter.fnl","text":"

Defines which language parsers and modules to use.

(treesitter.setup\n  {:ensure_installed [\"clojure\" \"fennel\" \"markdown\"]\n   :sync_install true\n   :highlight {:enable true}\n   :indent    {:enable true}})\n
"},{"location":"reference/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
"},{"location":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/configuration/practicalli/packages/#package-selection-criteria","title":"Package selection criteria","text":"

Packages are more likely to be adopted if:

"},{"location":"reference/configuration/practicalli/packages/#package-updates","title":"Package Updates","text":"

This Week In Neovim - community update

"},{"location":"reference/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":"reference/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":"reference/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.

"},{"location":"reference/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":"reference/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":"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

Introduction to Lua - Codecademy

"},{"location":"reference/modal-editing/","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/modal-editing/#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/modal-editing/#navigation-and-searching","title":"Navigation and searching","text":""},{"location":"reference/modal-editing/#text-wrangling","title":"Text wrangling","text":""},{"location":"reference/modal-editing/#clojure-editing","title":"Clojure Editing","text":"

traversing expressions structural editing

"},{"location":"reference/modal-editing/case/","title":"Modifying text case","text":"

Convert Characters and regioins to upper or lower case text.

"},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/case/#cheatsheet","title":"Cheatsheet","text":""},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/key-binding-reference/","title":"Evil Keybinding Reference","text":"

An alphabetically ordered reference of Vim-style key bindings.

"},{"location":"reference/modal-editing/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/modal-editing/motions/","title":"Motions","text":"

Todo

Moving the cursor around by context rather than individual characters

"},{"location":"reference/modal-editing/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/modal-editing/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.

"},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/narrowing/#documentation","title":"Documentation","text":"

:help NarrowRegion to view the documetation on the NrrwRgn plug use

"},{"location":"reference/modal-editing/narrowing/#attention","title":"Attention","text":"

:NRM is described as experimental by the project readme.

"},{"location":"reference/modal-editing/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:

Then use those verbs with some modifiers

Then learn the text objects you can apply verbs and modifiers too

"},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/vim-quick-reference/#transposing-swap","title":"Transposing / swap","text":"Key Description x p transpose the current character with the next character"},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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

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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/vim-tips-for-developers/#comments-and-commenting-code","title":"Comments and Commenting code","text":""},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/visual-select/#line-and-block","title":"Line and block","text":"

V enters visual line select mode

j and k alter the selection by line

Ctrl+v enters visual region select mode

Switch between visual modes

Once in visual mode:

V switches to visual line mode Ctrl+v switches to visual line mode

"},{"location":"reference/modal-editing/z-menu/","title":"Evil Z menu","text":"

z in normal mode opens a menu of convenient utilities

"},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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 list to replace the word under the cursor, or Esc to close the spelling list.

Key Description z = spelling suggestions [ s next incorrect word ] s previous incorrect word z g add word to spelling list z w mark word as misspelled"},{"location":"reference/neovim/","title":"Neovim Reference","text":""},{"location":"reference/neovim/changelist/","title":"Changelist","text":"

Initial draft - feedback welcome

:help :changelist\n

View changelist

:changes\n
"},{"location":"reference/neovim/jumplist/","title":"Jumplist","text":"

Initial draft - feedback welcome

:help :jumplist\n

View jumplist

:jumps\n
"},{"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/quickfix/","title":"Quickfix","text":"

Initial draft - feedback welcome

"},{"location":"reference/neovim/quickfix/#quickfix-mode","title":"quickfix mode","text":"Open quickfix in window
:ccopen\n

Use j k to navigate the list or :cc and a number to jump to a result

jump to the 7th result
:cc 7\n
"},{"location":"reference/neovim/quickfix/#tools","title":"Tools","text":"

Quickfix is a mode to show results of another command

Quickfix buffer can be used to jump through the errors one by one. Each error can be viewe and fix it in turn.

quickfix is used to find a list of positions in files.

The 'errorformat' option should be set to match the error messages from your compiler (see |errorformat| below).

                        *quickfix-ID*\n

Each quickfix list has a unique identifier called the quickfix ID and this number will not change within a Vim session. The |getqflist()| function can be used to get the identifier assigned to a list. There is also a quickfix list number which may change whenever more than ten lists are added to a quickfix stack.

                    *location-list* *E776*\n

A location list is a window-local quickfix list. You get one after commands like :lvimgrep, :lgrep, :lhelpgrep, :lmake, etc., which create a location list instead of a quickfix list as the corresponding :vimgrep, :grep, :helpgrep, :make do. location-list-file-window A location list is associated with a window and each window can have a separate location list. A location list can be associated with only one window. The location list is independent of the quickfix list.

When a window with a location list is split, the new window gets a copy of the location list. When there are no longer any references to a location list, the location list is destroyed.

                    *quickfix-changedtick*\n

Every quickfix and location list has a read-only changedtick variable that tracks the total number of changes made to the list. Every time the quickfix list is modified, this count is incremented. This can be used to perform an action only when the list has changed. The |getqflist()| and |getloclist()| functions can be used to query the current value of changedtick. You cannot change the changedtick variable.

The following quickfix commands can be used. The location list commands are similar to the quickfix commands, replacing the 'c' prefix in the quickfix command with 'l'.

                        *E924*\n

If the current window was closed by an |autocommand| while processing a location list command, it will be aborted.

                        *E925* *E926*\n

If the current quickfix or location list was changed by an |autocommand| while processing a quickfix or location list command, it will be aborted.

                        *:cc*\n

:cc[!] [nr] Display error [nr]. If [nr] is omitted, the same :[nr]cc[!] error is displayed again. Without [!] this doesn't work when jumping to another buffer, the current buffer has been changed, there is the only window for the buffer and both 'hidden' and 'autowrite' are off. When jumping to another buffer with [!] any changes to the current buffer are lost, unless 'hidden' is set or there is another window for this buffer. The 'switchbuf' settings are respected when jumping to a buffer. When used in the quickfix window the line number can be used, including \".\" for the current line and \"$\" for the last line.

                        *:ll*\n

:ll[!] [nr] Same as \":cc\", except the location list for the :[nr]ll[!] current window is used instead of the quickfix list.

                    *:cn* *:cne* *:cnext* *E553*\n

:[count]cn[ext][!] Display the [count] next error in the list that includes a file name. If there are no file names at all, go to the [count] next error. See |:cc| for [!] and 'switchbuf'.

                        *:lne* *:lnext*\n

:[count]lne[xt][!] Same as \":cnext\", except the location list for the current window is used instead of the quickfix list.

:[count]cN[ext][!] :cp :cprevious :cprev :cN :cNext :[count]cp[revious][!] Display the [count] previous error in the list that includes a file name. If there are no file names at all, go to the [count] previous error. See |:cc| for [!] and 'switchbuf'.

:[count]lN[ext][!] :lp :lprevious :lprev :lN :lNext :[count]lp[revious][!] Same as \":cNext\" and \":cprevious\", except the location list for the current window is used instead of the quickfix list.

                        *:cabo* *:cabove*\n

:[count]cabo[ve] Go to the [count] error above the current line in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix list are sorted by their buffer number and line number. If there are multiple errors on the same line, then only the first entry is used. If [count] exceeds the number of entries above the current line, then the first error in the file is selected.

                        *:lab* *:labove*\n

:[count]lab[ove] Same as \":cabove\", except the location list for the current window is used instead of the quickfix list.

                        *:cbel* *:cbelow*\n

:[count]cbel[ow] Go to the [count] error below the current line in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix list are sorted by their buffer number and line number. If there are multiple errors on the same line, then only the first entry is used. If [count] exceeds the number of entries below the current line, then the last error in the file is selected.

                        *:lbel* *:lbelow*\n

:[count]lbel[ow] Same as \":cbelow\", except the location list for the current window is used instead of the quickfix list.

                        *:cbe* *:cbefore*\n

:[count]cbe[fore] Go to the [count] error before the current cursor position in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix list are sorted by their buffer, line and column numbers. If [count] exceeds the number of entries before the current position, then the first error in the file is selected.

                        *:lbe* *:lbefore*\n

:[count]lbe[fore] Same as \":cbefore\", except the location list for the current window is used instead of the quickfix list.

                        *:caf* *:cafter*\n

:[count]caf[ter] Go to the [count] error after the current cursor position in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix list are sorted by their buffer, line and column numbers. If [count] exceeds the number of entries after the current position, then the last error in the file is selected.

                        *:laf* *:lafter*\n

:[count]laf[ter] Same as \":cafter\", except the location list for the current window is used instead of the quickfix list.

                        *:cnf* *:cnfile*\n

:[count]cnf[ile][!] Display the first error in the [count] next file in the list that includes a file name. If there are no file names at all or if there is no next file, go to the [count] next error. See |:cc| for [!] and 'switchbuf'.

                        *:lnf* *:lnfile*\n

:[count]lnf[ile][!] Same as \":cnfile\", except the location list for the current window is used instead of the quickfix list.

:[count]cNf[ile][!] :cpf :cpfile :cNf :cNfile :[count]cpf[ile][!] Display the last error in the [count] previous file in the list that includes a file name. If there are no file names at all or if there is no next file, go to the [count] previous error. See |:cc| for [!] and 'switchbuf'.

:[count]lNf[ile][!] :lpf :lpfile :lNf :lNfile :[count]lpf[ile][!] Same as \":cNfile\" and \":cpfile\", except the location list for the current window is used instead of the quickfix list.

                        *:crewind* *:cr*\n

:cr[ewind][!] [nr] Display error [nr]. If [nr] is omitted, the FIRST error is displayed. See |:cc|.

                        *:lrewind* *:lr*\n

:lr[ewind][!] [nr] Same as \":crewind\", except the location list for the current window is used instead of the quickfix list.

                        *:cfirst* *:cfir*\n

:cfir[st][!] [nr] Same as \":crewind\".

                        *:lfirst* *:lfir*\n

:lfir[st][!] [nr] Same as \":lrewind\".

                        *:clast* *:cla*\n

:cla[st][!] [nr] Display error [nr]. If [nr] is omitted, the LAST error is displayed. See |:cc|.

                        *:llast* *:lla*\n

:lla[st][!] [nr] Same as \":clast\", except the location list for the current window is used instead of the quickfix list.

                        *:cq* *:cquit*\n

:cq[uit][!] :{N}cq[uit][!] :cq[uit][!] {N} Quit Vim with error code {N}. {N} defaults to one. Useful when Vim is called from another program: e.g., a compiler will not compile the same file again, git commit will abort the committing process, fc (built-in for shells like bash and zsh) will not execute the command, etc. {N} can also be zero, in which case Vim exits normally. WARNING: All changes in files are lost. It works like \":qall!\" |:qall|, except that Nvim exits non-zero or [count].

                        *:cf* *:cfi* *:cfile*\n

:cf[ile][!] [errorfile] Read the error file and jump to the first error. This is done automatically when Vim is started with the -q option. You can use this command when you keep Vim running while compiling. If you give the name of the errorfile, the 'errorfile' option will be set to [errorfile]. See |:cc| for [!]. If the encoding of the error file differs from the 'encoding' option, you can use the 'makeencoding' option to specify the encoding.

                        *:lf* *:lfi* *:lfile*\n

:lf[ile][!] [errorfile] Same as \":cfile\", except the location list for the current window is used instead of the quickfix list. You can not use the -q command-line option to set the location list.

:cg[etfile] [errorfile] :cg :cgetfile Read the error file. Just like \":cfile\" but don't jump to the first error. If the encoding of the error file differs from the 'encoding' option, you can use the 'makeencoding' option to specify the encoding.

:lg[etfile] [errorfile] :lg :lge :lgetfile Same as \":cgetfile\", except the location list for the current window is used instead of the quickfix list.

                        *:caddf* *:caddfile*\n

:caddf[ile] [errorfile] Read the error file and add the errors from the errorfile to the current quickfix list. If a quickfix list is not present, then a new list is created. If the encoding of the error file differs from the 'encoding' option, you can use the 'makeencoding' option to specify the encoding.

                        *:laddf* *:laddfile*\n

:laddf[ile] [errorfile] Same as \":caddfile\", except the location list for the current window is used instead of the quickfix list.

                    *:cb* *:cbuffer* *E681*\n

:cb[uffer][!] [bufnr] Read the error list from the current buffer. When [bufnr] is given it must be the number of a loaded buffer. That buffer will then be used instead of the current buffer. A range can be specified for the lines to be used. Otherwise all lines in the buffer are used. See |:cc| for [!].

                    *:lb* *:lbuffer*\n

:lb[uffer][!] [bufnr] Same as \":cbuffer\", except the location list for the current window is used instead of the quickfix list.

                    *:cgetb* *:cgetbuffer*\n

:cgetb[uffer] [bufnr] Read the error list from the current buffer. Just like \":cbuffer\" but don't jump to the first error.

                    *:lgetb* *:lgetbuffer*\n

:lgetb[uffer] [bufnr] Same as \":cgetbuffer\", except the location list for the current window is used instead of the quickfix list.

                    *:cad* *:cadd* *:caddbuffer*\n

:cad[dbuffer] [bufnr] Read the error list from the current buffer and add the errors to the current quickfix list. If a quickfix list is not present, then a new list is created. Otherwise, same as \":cbuffer\".

                        *:laddb* *:laddbuffer*\n

:laddb[uffer] [bufnr] Same as \":caddbuffer\", except the location list for the current window is used instead of the quickfix list.

                        *:cex* *:cexpr* *E777*\n

:cex[pr][!] {expr} Create a quickfix list using the result of {expr} and jump to the first error. If {expr} is a String, then each newline terminated line in the String is processed using the global value of 'errorformat' and the result is added to the quickfix list. If {expr} is a List, then each String item in the list is processed and added to the quickfix list. Non String items in the List are ignored. See |:cc| for [!]. Examples: :cexpr system('grep -n xyz *') :cexpr getline(1, '$')

                        *:lex* *:lexpr*\n

:lex[pr][!] {expr} Same as |:cexpr|, except the location list for the current window is used instead of the quickfix list.

                        *:cgete* *:cgetexpr*\n

:cgete[xpr] {expr} Create a quickfix list using the result of {expr}. Just like |:cexpr|, but don't jump to the first error.

                        *:lgete* *:lgetexpr*\n

:lgete[xpr] {expr} Same as |:cgetexpr|, except the location list for the current window is used instead of the quickfix list.

                        *:cadde* *:caddexpr*\n

:cadde[xpr] {expr} Evaluate {expr} and add the resulting lines to the current quickfix list. If a quickfix list is not present, then a new list is created. The current cursor position will not be changed. See |:cexpr| for more information. Example: :g/mypattern/caddexpr expand(\"%\") .. \":\" .. line(\".\") .. \":\" .. getline(\".\")

                    *:lad* *:addd* *:laddexpr*\n

:lad[dexpr] {expr} Same as \":caddexpr\", except the location list for the current window is used instead of the quickfix list.

                        *:cl* *:clist*\n

:cl[ist] [from] [, [to]] List all errors that are valid |quickfix-valid|. If numbers [from] and/or [to] are given, the respective range of errors is listed. A negative number counts from the last error backwards, -1 being the last error. The |:filter| command can be used to display only the quickfix entries matching a supplied pattern. The pattern is matched against the filename, module name, pattern and text of the entry.

:cl[ist] +{count} List the current and next {count} valid errors. This is similar to \":clist from from+count\", where \"from\" is the current error position.

:cl[ist]! [from] [, [to]] List all errors.

:cl[ist]! +{count} List the current and next {count} error lines. This is useful to see unrecognized lines after the current one. For example, if \":clist\" shows: 8384 testje.java:252: error: cannot find symbol Then using \":cl! +3\" shows the reason: 8384 testje.java:252: error: cannot find symbol 8385: ZexitCode = Fmainx(); 8386: ^ 8387: symbol: method Fmainx()

:lli[st] [from] [, [to]] :lli :llist Same as \":clist\", except the location list for the current window is used instead of the quickfix list.

:lli[st]! [from] [, [to]] List all the entries in the location list for the current window.

If you insert or delete lines, mostly the correct error location is still found because hidden marks are used. Sometimes, when the mark has been deleted for some reason, the message \"line changed\" is shown to warn you that the error location may not be correct. If you quit Vim and start again the marks are lost and the error locations may not be correct anymore.

Two autocommands are available for running commands before and after a quickfix command (':make', ':grep' and so on) is executed. See |QuickFixCmdPre| and |QuickFixCmdPost| for details.

                    *QuickFixCmdPost-example*\n

When 'encoding' differs from the locale, the error messages may have a different encoding from what Vim is using. To convert the messages you can use this code: function QfMakeConv() let qflist = getqflist() for i in qflist let i.text = iconv(i.text, \"cp936\", \"utf-8\") endfor call setqflist(qflist) endfunction

au QuickfixCmdPost make call QfMakeConv()\n

Another option is using 'makeencoding'.

                        *quickfix-title*\n

Every quickfix and location list has a title. By default the title is set to the command that created the list. The |getqflist()| and |getloclist()| functions can be used to get the title of a quickfix and a location list respectively. The |setqflist()| and |setloclist()| functions can be used to modify the title of a quickfix and location list respectively. Examples: call setqflist([], 'a', {'title' : 'Cmd output'}) echo getqflist({'title' : 1}) call setloclist(3, [], 'a', {'title' : 'Cmd output'}) echo getloclist(3, {'title' : 1})

                        *quickfix-index*\n

When you jump to a quickfix/location list entry using any of the quickfix commands (e.g. |:cc|, |:cnext|, |:cprev|, etc.), that entry becomes the currently selected entry. The index of the currently selected entry in a quickfix/location list can be obtained using the getqflist()/getloclist() functions. Examples: echo getqflist({'idx' : 0}).idx echo getqflist({'id' : qfid, 'idx' : 0}).idx echo getloclist(2, {'idx' : 0}).idx

For a new quickfix list, the first entry is selected and the index is 1. Any entry in any quickfix/location list can be set as the currently selected entry using the setqflist() function. Examples: call setqflist([], 'a', {'idx' : 12}) call setqflist([], 'a', {'id' : qfid, 'idx' : 7}) call setloclist(1, [], 'a', {'idx' : 7})

                        *quickfix-size*\n

You can get the number of entries (size) in a quickfix and a location list using the |getqflist()| and |getloclist()| functions respectively. Examples: echo getqflist({'size' : 1}) echo getloclist(5, {'size' : 1})

                        *quickfix-context*\n

Any Vim type can be associated as a context with a quickfix or location list. The |setqflist()| and the |setloclist()| functions can be used to associate a context with a quickfix and a location list respectively. The |getqflist()| and the |getloclist()| functions can be used to retrieve the context of a quickfix and a location list respectively. This is useful for a Vim plugin dealing with multiple quickfix/location lists. Examples:

let somectx = {'name' : 'Vim', 'type' : 'Editor'}\ncall setqflist([], 'a', {'context' : somectx})\necho getqflist({'context' : 1})\n\nlet newctx = ['red', 'green', 'blue']\ncall setloclist(2, [], 'a', {'id' : qfid, 'context' : newctx})\necho getloclist(2, {'id' : qfid, 'context' : 1})\n\n                        *quickfix-parse*\n

You can parse a list of lines using 'errorformat' without creating or modifying a quickfix list using the |getqflist()| function. Examples: echo getqflist({'lines' : [\"F1:10:Line10\", \"F2:20:Line20\"]}) echo getqflist({'lines' : systemlist('grep -Hn quickfix *')}) This returns a dictionary where the \"items\" key contains the list of quickfix entries parsed from lines. The following shows how to use a custom 'errorformat' to parse the lines without modifying the 'errorformat' option: echo getqflist({'efm' : '%f#%l#%m', 'lines' : ['F1#10#Line']})

EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST: :cdo :cdo[!] {cmd} Execute {cmd} in each valid entry in the quickfix list. It works like doing this: :cfirst :{cmd} :cnext :{cmd} etc. When the current file can't be |abandon|ed and the [!] is not present, the command fails. When going to the next entry fails execution stops. The last buffer (or where an error occurred) becomes the current buffer. {cmd} can contain '|' to concatenate several commands.

        Only valid entries in the quickfix list are used.\n        A range can be used to select entries, e.g.:\n            :10,$cdo cmd\n        To skip entries 1 to 9.\n\n        Note: While this command is executing, the Syntax\n        autocommand event is disabled by adding it to\n        'eventignore'.  This considerably speeds up editing\n        each buffer.\n        Also see |:bufdo|, |:tabdo|, |:argdo|, |:windo|,\n        |:ldo|, |:cfdo| and |:lfdo|.\n\n                        *:cfdo*\n

:cfdo[!] {cmd} Execute {cmd} in each file in the quickfix list. It works like doing this: :cfirst :{cmd} :cnfile :{cmd} etc. Otherwise it works the same as :cdo.

                        *:ldo*\n

:ld[o][!] {cmd} Execute {cmd} in each valid entry in the location list for the current window. It works like doing this: :lfirst :{cmd} :lnext :{cmd} etc. Only valid entries in the location list are used. Otherwise it works the same as :cdo.

                        *:lfdo*\n

:lfdo[!] {cmd} Execute {cmd} in each file in the location list for the current window. It works like doing this: :lfirst :{cmd} :lnfile :{cmd} etc. Otherwise it works the same as :ldo.

FILTERING A QUICKFIX OR LOCATION LIST: cfilter-plugin :Cfilter :Lfilter If you have too many entries in a quickfix list, you can use the cfilter plugin to reduce the number of entries. Load the plugin with:

packadd cfilter\n

Then you can use the following commands to filter a quickfix/location list:

:Cfilter[!] /{pat}/\n:Lfilter[!] /{pat}/\n

The |:Cfilter| command creates a new quickfix list from the entries matching {pat} in the current quickfix list. {pat} is a Vim |regular-expression| pattern. Both the file name and the text of the entries are matched against {pat}. If the optional ! is supplied, then the entries not matching {pat} are used. The pattern can be optionally enclosed using one of the following characters: ', \", /. If the pattern is empty, then the last used search pattern is used.

The |:Lfilter| command does the same as |:Cfilter| but operates on the current location list.

The current quickfix/location list is not modified by these commands, so you can go back to the unfiltered list using the |:colder|/|:lolder| command.

============================================================================= 2. The error window quickfix-window

                    *:cope* *:copen* *w:quickfix_title*\n

:cope[n] [height] Open a window to show the current list of errors.

        When [height] is given, the window becomes that high\n        (if there is room).  When [height] is omitted the\n        window is made ten lines high.\n\n        If there already is a quickfix window, it will be made\n        the current window.  It is not possible to open a\n        second quickfix window.  If [height] is given the\n        existing window will be resized to it.\n\n                        *quickfix-buffer*\n        The window will contain a special buffer, with\n        'buftype' equal to \"quickfix\".  Don't change this!\n        The window will have the w:quickfix_title variable set\n        which will indicate the command that produced the\n        quickfix list. This can be used to compose a custom\n        status line if the value of 'statusline' is adjusted\n        properly. Whenever this buffer is modified by a\n        quickfix command or function, the |b:changedtick|\n        variable is incremented.  You can get the number of\n        this buffer using the getqflist() and getloclist()\n        functions by passing the \"qfbufnr\" item. For a\n        location list, this buffer is wiped out when the\n        location list is removed.\n\n                        *:lop* *:lopen*\n

:lop[en] [height] Open a window to show the location list for the current window. Works only when the location list for the current window is present. You can have more than one location window opened at a time. Otherwise, it acts the same as \":copen\".

                        *:ccl* *:cclose*\n

:ccl[ose] Close the quickfix window.

                        *:lcl* *:lclose*\n

:lcl[ose] Close the window showing the location list for the current window.

                        *:cw* *:cwindow*\n

:cw[indow] [height] Open the quickfix window when there are recognized errors. If the window is already open and there are no recognized errors, close the window.

                        *:lw* *:lwindow*\n

:lw[indow] [height] Same as \":cwindow\", except use the window showing the location list for the current window.

                        *:cbo* *:cbottom*\n

:cbo[ttom] Put the cursor in the last line of the quickfix window and scroll to make it visible. This is useful for when errors are added by an asynchronous callback. Only call it once in a while if there are many updates to avoid a lot of redrawing.

                        *:lbo* *:lbottom*\n

:lbo[ttom] Same as \":cbottom\", except use the window showing the location list for the current window.

Normally the quickfix window is at the bottom of the screen. If there are vertical splits, it's at the bottom of the rightmost column of windows. To make it always occupy the full width: :botright cwindow You can move the window around with |window-moving| commands. For example, to move it to the top: CTRL-W K The 'winfixheight' option will be set, which means that the window will mostly keep its height, ignoring 'winheight' and 'equalalways'. You can change the height manually (e.g., by dragging the status line above it with the mouse).

In the quickfix window, each line is one error. The line number is equal to the error number. The current entry is highlighted with the QuickFixLine highlighting. You can change it to your liking, e.g.: :hi QuickFixLine ctermbg=Yellow guibg=Yellow

You can use \":.cc\" to jump to the error under the cursor. Hitting the key or double-clicking the mouse on a line has the same effect. The file containing the error is opened in the window above the quickfix window. If there already is a window for that file, it is used instead. If the buffer in the used window has changed, and the error is in another file, jumping to the error will fail. You will first have to make sure the window contains a buffer which can be abandoned.

When you select a file from the quickfix window, the following steps are used to find a window to edit the file:

  1. If a window displaying the selected file is present in the current tabpage (starting with the window before the quickfix window), then that window is used.
  2. If the above step fails and if 'switchbuf' contains \"usetab\" and a window displaying the selected file is present in any one of the tabpages (starting with the first tabpage) then that window is used.
  3. If the above step fails then a window in the current tabpage displaying a buffer with 'buftype' not set (starting with the window before the quickfix window) is used.
  4. If the above step fails and if 'switchbuf' contains \"uselast\", then the previously accessed window is used.
  5. If the above step fails then the window before the quickfix window is used. If there is no previous window, then the window after the quickfix window is used.
  6. If the above step fails, then a new horizontally split window above the quickfix window is used.
                *CTRL-W_<Enter>* *CTRL-W_<CR>*\n

    You can use CTRL-W to open a new window and jump to the error there.

    When the quickfix window has been filled, two autocommand events are triggered. First the 'filetype' option is set to \"qf\", which triggers the FileType event (also see |qf.vim|). Then the BufReadPost event is triggered, using \"quickfix\" for the buffer name. This can be used to perform some action on the listed errors. Example: au BufReadPost quickfix setlocal modifiable \\ | silent exe 'g/^/s//\\=line(\".\") .. \" \"/' \\ | setlocal nomodifiable This prepends the line number to each line. Note the use of \"\\=\" in the substitute string of the \":s\" command, which is used to evaluate an expression. The BufWinEnter event is also triggered, again using \"quickfix\" for the buffer name.

    Note: When adding to an existing quickfix list the autocommand are not triggered.

    Note: Making changes in the quickfix window has no effect on the list of errors. 'modifiable' is off to avoid making changes. If you delete or insert lines anyway, the relation between the text and the error number is messed up. If you really want to do this, you could write the contents of the quickfix window to a file and use \":cfile\" to have it parsed and used as the new error list.

                        *location-list-window*\n

    The location list window displays the entries in a location list. When you open a location list window, it is created below the current window and displays the location list for the current window. The location list window is similar to the quickfix window, except that you can have more than one location list window open at a time. When you use a location list command in this window, the displayed location list is used.

    When you select a file from the location list window, the following steps are used to find a window to edit the file:

    1. If a non-quickfix window associated with the location list is present in the current tabpage, then that window is used.
    2. If the above step fails and if the file is already opened in another window in the current tabpage, then that window is used.
    3. If the above step fails and 'switchbuf' contains \"usetab\" and if the file is opened in a window in any one of the tabpages, then that window is used.
    4. If the above step fails then a window in the current tabpage showing a buffer with 'buftype' not set is used.
    5. If the above step fails, then the file is edited in a new window.

    In all of the above cases, if the location list for the selected window is not yet set, then it is set to the location list displayed in the location list window.

                            *quickfix-window-ID*\n

    You can use the |getqflist()| and |getloclist()| functions to obtain the window ID of the quickfix window and location list window respectively (if present). Examples: echo getqflist({'winid' : 1}).winid echo getloclist(2, {'winid' : 1}).winid

                            *getqflist-examples*\n

    The |getqflist()| and |getloclist()| functions can be used to get the various attributes of a quickfix and location list respectively. Some examples for using these functions are below:

    \" get the title of the current quickfix list\n:echo getqflist({'title' : 0}).title\n\n\" get the identifier of the current quickfix list\n:let qfid = getqflist({'id' : 0}).id\n\n\" get the identifier of the fourth quickfix list in the stack\n:let qfid = getqflist({'nr' : 4, 'id' : 0}).id\n\n\" check whether a quickfix list with a specific identifier exists\n:if getqflist({'id' : qfid}).id == qfid\n\n\" get the index of the current quickfix list in the stack\n:let qfnum = getqflist({'nr' : 0}).nr\n\n\" get the items of a quickfix list specified by an identifier\n:echo getqflist({'id' : qfid, 'items' : 0}).items\n\n\" get the number of entries in a quickfix list specified by an id\n:echo getqflist({'id' : qfid, 'size' : 0}).size\n\n\" get the context of the third quickfix list in the stack\n:echo getqflist({'nr' : 3, 'context' : 0}).context\n\n\" get the number of quickfix lists in the stack\n:echo getqflist({'nr' : '$'}).nr\n\n\" get the number of times the current quickfix list is changed\n:echo getqflist({'changedtick' : 0}).changedtick\n\n\" get the current entry in a quickfix list specified by an identifier\n:echo getqflist({'id' : qfid, 'idx' : 0}).idx\n\n\" get all the quickfix list attributes using an identifier\n:echo getqflist({'id' : qfid, 'all' : 0})\n\n\" parse text from a List of lines and return a quickfix list\n:let myList = [\"a.java:10:L10\", \"b.java:20:L20\"]\n:echo getqflist({'lines' : myList}).items\n\n\" parse text using a custom 'efm' and return a quickfix list\n:echo getqflist({'lines' : ['a.c#10#Line 10'], 'efm':'%f#%l#%m'}).items\n\n\" get the quickfix list window id\n:echo getqflist({'winid' : 0}).winid\n\n\" get the quickfix list window buffer number\n:echo getqflist({'qfbufnr' : 0}).qfbufnr\n\n\" get the context of the current location list\n:echo getloclist(0, {'context' : 0}).context\n\n\" get the location list window id of the third window\n:echo getloclist(3, {'winid' : 0}).winid\n\n\" get the location list window buffer number of the third window\n:echo getloclist(3, {'qfbufnr' : 0}).qfbufnr\n\n\" get the file window id of a location list window (winnr: 4)\n:echo getloclist(4, {'filewinid' : 0}).filewinid\n\n                        *setqflist-examples*\n

    The |setqflist()| and |setloclist()| functions can be used to set the various attributes of a quickfix and location list respectively. Some examples for using these functions are below:

    \" create an empty quickfix list with a title and a context\n:let t = 'Search results'\n:let c = {'cmd' : 'grep'}\n:call setqflist([], ' ', {'title' : t, 'context' : c})\n\n\" set the title of the current quickfix list\n:call setqflist([], 'a', {'title' : 'Mytitle'})\n\n\" change the current entry in the list specified by an identifier\n:call setqflist([], 'a', {'id' : qfid, 'idx' : 10})\n\n\" set the context of a quickfix list specified by an identifier\n:call setqflist([], 'a', {'id' : qfid, 'context' : {'val' : 100}})\n\n\" create a new quickfix list from a command output\n:call setqflist([], ' ', {'lines' : systemlist('grep -Hn main *.c')})\n\n\" parse text using a custom efm and add to a particular quickfix list\n:call setqflist([], 'a', {'id' : qfid,\n    \\ 'lines' : [\"a.c#10#L10\", \"b.c#20#L20\"], 'efm':'%f#%l#%m'})\n\n\" add items to the quickfix list specified by an identifier\n:let newItems = [{'filename' : 'a.txt', 'lnum' : 10, 'text' : \"Apple\"},\n        \\ {'filename' : 'b.txt', 'lnum' : 20, 'text' : \"Orange\"}]\n:call setqflist([], 'a', {'id' : qfid, 'items' : newItems})\n\n\" empty a quickfix list specified by an identifier\n:call setqflist([], 'r', {'id' : qfid, 'items' : []})\n\n\" free all the quickfix lists in the stack\n:call setqflist([], 'f')\n\n\" set the title of the fourth quickfix list\n:call setqflist([], 'a', {'nr' : 4, 'title' : 'SomeTitle'})\n\n\" create a new quickfix list at the end of the stack\n:call setqflist([], ' ', {'nr' : '$',\n        \\ 'lines' : systemlist('grep -Hn class *.java')})\n\n\" create a new location list from a command output\n:call setloclist(0, [], ' ', {'lines' : systemlist('grep -Hn main *.c')})\n\n\" replace the location list entries for the third window\n:call setloclist(3, [], 'r', {'items' : newItems})\n

    ============================================================================= 3. Using more than one list of errors quickfix-error-lists

    So far has been assumed that there is only one list of errors. Actually the ten last used lists are remembered. When starting a new list, the previous ones are automatically kept. Two commands can be used to access older error lists. They set one of the existing error lists as the current one.

                        *:colder* *:col* *E380*\n

    :col[der] [count] Go to older error list. When [count] is given, do this [count] times. When already at the oldest error list, an error message is given.

                        *:lolder* *:lol*\n

    :lol[der] [count] Same as :colder, except use the location list for the current window instead of the quickfix list.

                        *:cnewer* *:cnew* *E381*\n

    :cnew[er] [count] Go to newer error list. When [count] is given, do this [count] times. When already at the newest error list, an error message is given.

                        *:lnewer* *:lnew*\n

    :lnew[er] [count] Same as :cnewer, except use the location list for the current window instead of the quickfix list.

                        *:chistory* *:chi*\n

    :[count]chi[story] Show the list of error lists. The current list is marked with \">\". The output looks like: error list 1 of 3; 43 errors :make > error list 2 of 3; 0 errors :helpgrep tag error list 3 of 3; 15 errors :grep ex_help *.c

            When [count] is given, then the count'th quickfix\n        list is made the current list. Example:\n            \" Make the 4th quickfix list current\n            :4chistory\n\n                    *:lhistory* *:lhi*\n

    :[count]lhi[story] Show the list of location lists, otherwise like :chistory.

    When adding a new error list, it becomes the current list.

    When \":colder\" has been used and \":make\" or \":grep\" is used to add a new error list, one newer list is overwritten. This is especially useful if you are browsing with \":grep\" |grep|. If you want to keep the more recent error lists, use \":cnewer 99\" first.

    To get the number of lists in the quickfix and location list stack, you can use the |getqflist()| and |getloclist()| functions respectively with the list number set to the special value '$'. Examples: echo getqflist({'nr' : '$'}).nr echo getloclist(3, {'nr' : '$'}).nr To get the number of the current list in the stack: echo getqflist({'nr' : 0}).nr

    ============================================================================= 4. Using :make :make_makeprg

                            *:mak* *:make*\n

    :mak[e][!] [arguments] 1. All relevant |QuickFixCmdPre| autocommands are executed. 2. If the 'autowrite' option is on, write any changed buffers 3. An errorfile name is made from 'makeef'. If 'makeef' doesn't contain \"##\", and a file with this name already exists, it is deleted. 4. The program given with the 'makeprg' option is started (default \"make\") with the optional [arguments] and the output is saved in the errorfile (for Unix it is also echoed on the screen). 5. The errorfile is read using 'errorformat'. 6. All relevant |QuickFixCmdPost| autocommands are executed. See example below. 7. If [!] is not given the first error is jumped to. 8. The errorfile is deleted. 9. You can now move through the errors with commands like |:cnext| and |:cprevious|, see above. This command does not accept a comment, any \" characters are considered part of the arguments. If the encoding of the program output differs from the 'encoding' option, you can use the 'makeencoding' option to specify the encoding.

                            *:lmak* *:lmake*\n

    :lmak[e][!] [arguments] Same as \":make\", except the location list for the current window is used instead of the quickfix list.

    The \":make\" command executes the command given with the 'makeprg' option. This is done by passing the command to the shell given with the 'shell' option. This works almost like typing

    \":!{makeprg} [arguments] {shellpipe} {errorfile}\".\n

    {makeprg} is the string given with the 'makeprg' option. Any command can be used, not just \"make\". Characters '%' and '#' are expanded as usual on a command-line. You can use \"%<\" to insert the current file name without extension, or \"#<\" to insert the alternate file name without extension, for example: :set makeprg=make\\ #<.o

    [arguments] is anything that is typed after \":make\". {shellpipe} is the 'shellpipe' option. {errorfile} is the 'makeef' option, with ## replaced to make it unique.

    The placeholder \"$\" can be used for the argument list in {makeprg} if the command needs some additional characters after its arguments. The $ is replaced then by all arguments. Example: :set makeprg=latex\\ \\\\nonstopmode\\ \\\\input\\{$} or simpler :let &mp = 'latex \\nonstopmode \\input{$}' \"$\" can be given multiple times, for example: :set makeprg=gcc\\ -o\\ $\\ $*

    The 'shellpipe' option defaults to \"2>&1| tee\" for Win32. This means that the output of the compiler is saved in a file and not shown on the screen directly. For Unix \"| tee\" is used. The compiler output is shown on the screen and saved in a file the same time. Depending on the shell used \"|& tee\" or \"2>&1| tee\" is the default, so stderr output will be included.

    If 'shellpipe' is empty, the {errorfile} part will be omitted. This is useful for compilers that write to an errorfile themselves.

    Using QuickFixCmdPost to fix the encoding

    It may be that 'encoding' is set to an encoding that differs from the messages your build program produces. This example shows how to fix this after Vim has read the error messages:

    function QfMakeConv()\n   let qflist = getqflist()\n   for i in qflist\n      let i.text = iconv(i.text, \"cp936\", \"utf-8\")\n   endfor\n   call setqflist(qflist)\nendfunction\n\nau QuickfixCmdPost make call QfMakeConv()\n

    (Example by Faque Cheng) Another option is using 'makeencoding'.

    "},{"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":"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.

    • 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

    Pre-requisite: multi-modal editing

    Multi-modal Editing is a recommended pre-requisite

    Aliases to run Clojure REPL - Practicalli Clojure CLI Config

    Practicalli Clojure CLI config contains aliases used to start a Clojure REPL and other development tools. Aliases are used extensively through the Clojure sections of this book.

    Practicalli Neovim config replaces some key bindings

    Practicalli Neovim Config replaces several key bindings to make them consistent with other Clojure editors

    "},{"location":"repl-driven-development/#references","title":"References","text":"
    • Which Clojure CLI 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.

    Paste Evaluation result

    \" C p to paste the contents of the C register into the current buffer.

    The result of every Conjure evaluation is stored in the C register when using Practicalli AstroNvim Config.

    "},{"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/documentation/","title":"Documentation","text":"

    K or Space l h shows the documentation for the function under the cursor in a popup window.

    K a second time to jump the cursor to the popup window to scroll the text if required (or use a mouse wheel)

    "},{"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.

    "},{"location":"repl-driven-development/refactor-tools/#function-documentation","title":"Function documentation","text":"

    K or Space l h show the doc-string for function or any other var under the cursor.

    Repeat the key binding to move the cursor to the documentation popup window and use j k to scroll the documentation

    , l l code lens refresh

    , l L code lens run

    "},{"location":"repl-driven-development/refactor-tools/#navigation","title":"Navigation","text":"

    g d go to definition of current symbol, e.g. function definition

    , l G telescope search of all symbols in the project

    , l R telescope search of all references in the project

    , l s telescope search of symbols

    , l s split view of symbols

    "},{"location":"repl-driven-development/refactor-tools/#diagnostics","title":"Diagnostics","text":"

    Space l d show popup for current diagnostic indicator

    Space l D search through all diagnostics reports

    "},{"location":"repl-driven-development/refactor-tools/#code-actions","title":"Code Actions","text":"

    Space l r rename current symbol (namespace rename not supported by LSP client)

    Space l a code actions (popup with available actions)

    Space l f format buffer

    "},{"location":"repl-driven-development/refactor-tools/#troubleshooting","title":"Troubleshooting","text":"

    Space l i shows the LSP server information for the current filetype, e.g. Clojure

    Space l I shows format and lint tools supported by null-ls for the current filetype, e.g. clojure

    "},{"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":"source-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 (requires lazygit cli tool)
    • Neogit rich 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":"source-control/#common-git-actions","title":"Common Git actions","text":""},{"location":"source-control/#initialise-local-repository","title":"Initialise local repository\"","text":"

    Space t f opens floating terminal window in the current root directory root (use :cd to change the root directory).

    git init .\n
    "},{"location":"source-control/#stage-change-in-buffer","title":"Stage change in buffer","text":"

    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

    "},{"location":"source-control/#git-status","title":"Git Status","text":"

    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

    "},{"location":"source-control/#github-issues-pull-requests","title":"GitHub Issues & Pull Requests","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":"source-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":"source-control/diff/#nvimdiff","title":"nvimdiff","text":"

    The Git difftool can specify Neovim as a diff viewer to show Git diff views of all the files that have changes

    nvimdiff as a command line option

    git difftool --tool=nvimdiff <optional-filename>\n

    git difftool can be configured to use Neovim

    Git client config to set nvimdiff as difftool

    ~/.config/git/config
    [diff]\n  # Neovim diff tool\n  tool = nvimdiff\n

    Run git difftool in the root of the project to show the diff of each changed file.

    git difftool <optional-filename>\n

    : q a to close the current diff view. The command line prompts to open the next file as a diff view (assuming there are more files to view).

    "},{"location":"source-control/diff/#diffview","title":"DiffView","text":"

    DiffView compares working space and staged changes side by side, or a diff for git merge conflicts.

    AstroNvimPracticalli Neovim Config

    Space g d or d in neogit status buffer (SPC g s) will open diffview in a new tab

    [ c to move to previous hunk

    ] c to move to next hunk

    Space g to return to neovim buffer or q to return to neogit status buffer

    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

    • Green - added lines
    • Yellow - changed line
    • Red - deleted lines
    "},{"location":"source-control/lazygit/","title":"Lazygit version control","text":"Command Line or AstroNvim configuration

    Lazygit interface not provided by Practicalli Neovim Config Redux

    "},{"location":"source-control/lazygit/#requirements","title":"Requirements","text":"

    Install lazygit command line tool

    "},{"location":"source-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":"source-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":"source-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":"source-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":"source-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":"source-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":"source-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":"source-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":"source-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":"source-control/neogit/#modify-git-commit-history","title":"Modify Git commit history","text":"

    r opens the rebase menu

    "},{"location":"source-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":"source-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":"source-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":"source-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

    "},{"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 -L -O https://github.com/clojure/brew-install/releases/latest/download/linux-install.sh && \\\nchmod +x linux-install.sh && \\\n./linux-install.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 calling clojure with the --help option, which shows the options available to the command

    clojure --help\n

    Run a Clojure REPL session from a Clojure project configured with a deps.edn file

    clojure -M:repl/rebel\n

    optionally install rlwrap package if using the basic REPL terminal UI with the clj wrapper script

    "},{"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 9.5 is currenlyt available as a Termux package

    pkg install neovim\n
    "},{"location":"termux/neovim/#neovim-treesitter","title":"Neovim treesitter","text":"

    Treesitter provides excellent language syntax parsing and highlighting performance, allowing any Neovim package to benefit.

    The nvim-treesitter package is included in the practicalli/astro configuration.

    "},{"location":"termux/neovim/#c-compiler","title":"C Compiler","text":"

    Install C compiler to compile the 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.

    "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Neovim for Clojure development","text":"

    Practicalli Neovim provides an install & user guide for a simple and powerful REPL driven workflow for Clojure.

    Practicalli Astro configuration for Neovim provides Conjure REPL client and Clojure editing support (parinfer & paredit).

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

    Install terminal & tools, Clojure (Practicalli Clojure), Neovim 0.10 and Practicalli Astro configuration

    "},{"location":"#neovim-overview","title":"Neovim overview","text":"

    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 to provide a rich set of features for Clojure development and wider engineering tasks.

    coding at the speed of thought

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

    "},{"location":"#external-reverences","title":"External reverences","text":"

    Getting started with Neovim and Conjure

    Neovim user guide

    Conjure install guide

    "},{"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-practicalli","title":"Sponsor Practicalli","text":"

    All sponsorship funds are used to support the continued development of Practicalli series of books and videos, although most work is done at personal cost and time.

    Thanks 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":"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).

    • Terminal, Fonts and Tools
    • Clojure tooling and Java SDK (Practicalli Clojure)
    • Neovim 0.10.x and supporting CLI tools, with Practicalli Astro configuration
    • Optional: Neovide GUI for Neovim

    Neovim 0.10 latest stable release

    Content and configuration in this book has been tested against Neovim 0.10, but not against Neovim nightly builds.

    Practicalli Astro config should work with Neovim 0.9.0, except Neogit and ts-comment-nvim comments.

    Already have Neovim installed?

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

    "},{"location":"install/multiple-configurations/","title":"Multiple Configs","text":""},{"location":"install/multiple-configurations/#multiple-configurations","title":"Multiple Configurations","text":"

    Many Neovim configurations can be installed in $HOME/.config/ using unique directory names, e.g. AstroNvim, cajus, lazyvim, kickstart.

    Set NVIM_APPNAME to a configuration directory name (relative to $HOME/.config/`) to run Neovim with that specific config.

    Run AstroNvim config in $HOME/.config/astronvim/

    NVIM_APPNAME=astronvim nvim\n

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

    Community Configuration Projects
    • kickstart.nvim a highly documented starter configuration to effectively build your own
    • LazyVim lazy & mason configuration
    • Magit Kit fennel configuration from the author of Conjure
    • cajus-nvim inspiration for practicalli/neovim-config-redux
    "},{"location":"install/multiple-configurations/#configure-shell-alias","title":"Configure shell alias","text":"

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

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

    Define Shell Aliases to run each configuration

    alias astro=\"NVIM_APPNAME=nvim-astro nvim\"\nalias lazy=\"NVIM_APPNAME=nvim-lazyvim nvim\"\nalias cajus=\"NVIM_APPNAME=nvim-cajus nvim\"\n
    "},{"location":"install/multiple-configurations/#shell-aliases-for-bash-and-zsh","title":"shell-aliases for bash and zsh","text":"

    Create a .config/shell-aliases file containing all shell aliases when often switching between different shells, avoiding the need to define aliases twice

    Source the .config/shell-aliases file from within .bashrc or .zshrc

    ZshBash .zshrc
    # Shell Aliases\n[[ ! -f ~/.config/shell-aliases ]] || source ~/.config/shell-aliases\n
    .bashrc
    # Shell Aliases\nif [ -f ~/.config/shell-aliases ]; then\n    . ~/.config/shell-aliases\nfi\n
    "},{"location":"install/multiple-configurations/#neovim-config-selector","title":"Neovim config selector","text":"

    Create a shell function to popup a menu with the list of available Neovim configurations, defined in ~/.config where the configuration directories are prefixed with nvim-, e.g. ~/.config/nvim-astro/

    Neovim Config Fuzzy Finder

    .local/bin/nvim-fuzy-find
    nvim-fuzy-find() {\n  # All config paths are prefixed with ~/.config/nvim-\n  local config=$(fdfind --max-depth 1 --glob 'nvim-*' ~/.config | fzf --prompt=\"Neovim Configs > \" --height=15% --layout=reverse --border --exit-0)\n\n  [[ -z $config ]] && echo \"No config selected, Neovim not starting\" && return\n\n  # Open Neovim with selected config\n  NVIM_APPNAME=$(basename $config) nvim $@\n}\n
    Neovim Config simple Selector

    Add the Neovim config directory names from ~/.config/ .local/bin/nvim-selector

     nvim-selector() {\n  select config in nvim-astro nvim-astronvim-template nvim-lazyvim nvim-kickstart\n  do NVIM_APPNAME=nvim-$config nvim $@; break; done\n}\n

    "},{"location":"install/neovide/","title":"Neovide GUI","text":"

    Neovide provides a GUI for Neovim and supports the use of AstroNvim community configuration.

    Neovide features

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

    Download from Neovide.dev website

    DebianMacOSX

    Download neovide.AppImage

    Move the neovide.AppImage to the execution path, e.g. $HOME/.local/bin

    Create the $HOME/.local/bin/neovide symbolic link pointing to the neovide.AppImage

    ln -s $HOME/.local/bin/neovide.AppImage $HOME/.local/bin/neovide\n

    Download the MacOSX dmg.zip file

    Extract the .zip file

    Run the extracted dmg file and use the install wizard to copy Neovide to the Applications directory.

    Create symbolic link from Neovide install to ~/.local/bin

    ln -s /Applications/neovide.app/Contents/MacOS/neovide ~/.local/bin/neovide\n

    Add alias to use neovide with astronvim configuration to .bashrc , .zshrc or shared shell-aliases file

    alias neovide=\"NVIM_APPNAME=astronvim neovide\"\n
    "},{"location":"install/neovide/#neovide-with-nvim_appname","title":"Neovide with NVIM_APPNAME","text":"

    NVIM_APPNAME sets the configuration used when starting Neovim.

    Use a shell alias to run Neovide with a specific configuration

    # Neovide alias with AstroNvim configuration\nalias neovide=\"NVIM_APPNAME=astronvim neovide\"\n
    "},{"location":"install/neovide/#set-neovide-font","title":"Set Neovide Font","text":"

    The guifont Neovim option is used to set a font family and size specifically for a GUI appliction, i.e. Neovide. It is not used by Neovim itself.

    Ctrl+= and Ctrl+- increase & decrease the font size in Neovide (move the cursor if no immediate effect is seen)

    Neovide recipe

    Astro Community provides an neovide recipe with recommended options.

    lua/plugins/community.lua
    { import = \"astrocommunity.recipes.neovide\" },\n

    This recipe is include in the lua/community.lua file from Practicalli Astro configuration, with a font override in lua/plugins/user-practicalli.lua to set the preferred font.

      {\n    \"AstroNvim/astrocore\",\n    ---@type AstroCoreOpts\n    opts = {\n      options = {\n        -- configure general options: vim.opt.<key>\n        opt = {\n          guifont = \"Fira Code:h16\", -- neovide font family & size (height)\n        },\n      },\n    },\n  }\n

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

    Neovim 0.10.x is the latest stable version

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

    Neovim uses several command line tools for searching for files and their contents, using the operating system clipbaord and compiling Treesitter language parsers.

    Install the following tools to support Neovim and AstroNvim

    • ripgrep fast file contents search (used by telescope)
    • find-fd advanced search tool
    • xclip x11 clipboard as a provider for Neovim copy/paste (Linux only)
    • luarocks for LSP servers (AstroNvim)
    Treesitter requires a C compiler

    nvim-treesitter requires a C compiler , e.g. gcc for Linux or clang for android/termix

    The C compiler is used to compile langauge support for treesiter.

    AstroNvim requires node.js

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

    Node.js install - Practicalli Engineering Playbook

    Debian PackagesMacOSX Homebrew
    apt install fd-find xclip luarocks nodejs\n
    Wayland requires wl-clipboard

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

    apt install wl-clipboard\n

    MacOSX requires the libintl and gettext tools as well as the other supporting tools.

    brew install libintl gettext ripgrep fd luarocks\n
    "},{"location":"install/neovim/#install-neovim","title":"Install Neovim","text":"

    Install from the Neovim GitHub releases for the latest version of Neovim, or use a Package manager for the operating system.

    Linux AppImageMacOSX HomebrewMacOSX GitHub ReleaseDebian PackageBuild from Source

    Download the Linux 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 $HOME/.local/bin/nvim.appimage\n

    Create a symbolic link called nvim to the nvim.appimage file.

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

    nvim command can now be run in a terminal from any directory.

    Install from Homebrew or via the Neovim Release page

    Homebrew

    brew install neovim\n

    Neovim Release

    Download nvim-macos.tar.gz From the Neovim GitHub release page

    Avoid \"unknown developer\" warning from MacOSX

    xattr -c ./nvim-macos.tar.gz\n

    Make a local apps directory for neovim (and other things like node.js, etc.)

    mkdir -P ~/.local/apps\n

    Extract the neovim archive

    tar zvxf nvim-macos.tar.gz -C ~/.local/apps/\n

    Create the ~/.local/bin/nvim symbolic link to include Neovim on the OS execution path

    echo $PATH to check .local/bin is included in the execution the path by the Operating System command line shell

    ln -s ~/.local/apps/nvim-macos/bin/nvim ~/.local/bin/nvim\n

    Run\u00a0nvim (or setup a Neovim configuration first, e.g. AstroNvim)

    From the Neovim GitHub release page:

    1. Install\u00a0libintland\u00a0gettext\u00a0(e.g. via\u00a0brew install libintl gettext)
    2. Download\u00a0nvim-macos.tar.gz
    3. Run\u00a0xattr -c ./nvim-macos.tar.gz\u00a0(to avoid \"unknown developer\" warning)
    4. Make local apps directory for neovim (and other things like node.js, etc.)
    mkdir -P ~/.local/apps\n
    1. Extract the neovim download
    tar zvxf nvim-macos.tar.gz -C ~/.local/apps/\n
    1. Create nvim symbolic link in ~/.local/bin to include Neovim on the OS execution path (check .local/bin is added to the execution the path by the Operating System command line shell)
    ln -s ~/.local/apps/nvim-macos/bin/nvim ~/.local/bin/nvim\n

    Linux version only packaged as AppImage from Neovim 0.9 onward

    A .deb file can be created after building Neovim from source.

    Neovim build guide

    Neovim Build Prerequisites for each operating system

    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\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/#practicalli-astro-config","title":"Practicalli Astro Config","text":"

    Practicalli Astro is Clojure development focused configuration, an extension of the AstroNvim template repository.

    Clone the Practicalli Astro config or create your own fork and clone that repository.

    Clone Practicalli Astro config

    git clone https://github.com/practicalli/astro.git ~/.config/nvim\n
    Multiple Neovim Configurations

    Clone the configuration to a unique name within ~/.config directory.

    git clone https://github.com/practicalli/astro.git ~/.config/nvim-astro\n

    Set the NVIM_APPNAME environment variable to the configuration directory name under ~/.config

    e.g. Run Neovim using the configuration in ~/.config/astro

    export NVIM_APPNAME=nvim-astro nvim\n

    Configure shell alias and selectors to simplify the command to run a specific configuration.

    Practicalli Astro design & override guide

    "},{"location":"install/neovim/#install-neovim-plugins","title":"Install Neovim Plugins","text":"

    Enter nvim command in a terminal to launch Neovim and install all the plugins from the Practicalli Astro configuration.

    Run Neovim

    nvim\n

    Lazy plugin manager runs automatically and installs all the plugins defined in the Neovim configuration.

    Treesitter will prompt to compile its language parsers.

    q to close the lazy package manager pop-up once all plugins are installed.

    Plugin install without UI display

    Use the --headless Neovim flag to install plugins without running whole Neovim editor user interface.

    nvim --headless\n
    "},{"location":"install/neovim/#post-install-checks","title":"Post Install checks","text":"

    Troubleshoot the Neovim configuration and supporting tools by running the Neovim Heath Check.

    Use the :checkhealth command in Neovim or start Neovim with the Health Check command.

    Run Neovim and start Health Check

    nvim +:checkhealth\n

    A report is generated and shown in Neovim

    j / j 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.

    "},{"location":"install/terminal-tools/","title":"Terminal Tools and Fonts","text":"

    Neovim is a terminal based application so use of a quality terminal is recommended, e.g. Kitty Terminal (or iTerm2 if only on MacOSX)

    External Command line tools support search and other system information based features presented in AstroNvim.

    Nodejs supports Language Server protocol servers, format and lint tools installed by Mason.

    "},{"location":"install/terminal-tools/#kitty-terminal-with-nerd-fonts","title":"Kitty Terminal with Nerd Fonts","text":"

    Neovim runs in a terminal, so using Kitty (or iTerm2 - MacOSX only) are recommended. Kitty provides Nerd fonts for additional symbols on top of the terminal font, providing a richer experience.

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

    Nerd Fonts

    "},{"location":"install/terminal-tools/#command-line-tools","title":"Command line tools","text":"
    • ripgrep text search tool
    • fzf fuzzy finder
    • gdu
    • btm from GitHub repository releases
    Debian packagesHomebrew

    Install fzf, gdu and node.js via debian package manager

    apt install fzf gdu\n

    Install fzf, gdu and node.js via Homebrew package manager

    brew install fzf gdu\n

    Install btm from its GitHub repository release page

    "},{"location":"install/terminal-tools/#nodejs-for-lsp-format-lint-tools","title":"nodejs for LSP, format & lint tools","text":"

    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

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

    Neovim News for new developments

    Keep up to date with new features within Neovim

    :help news.txt\n
    Use the version name to view specific features of a release
    :help news-0.9.5.txt\n

    "},{"location":"introduction/features/#neovim-features-for-development","title":"Neovim features for development","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/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":"neovim-basics/","title":"Using Neovim","text":"

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

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

    Multi-modal Editing File Buffer Window and Tab page

    "},{"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/#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.

    Map Listing: Neovim docs Key Notation: Neovim docs

    "},{"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":"

    SPC e opens Neo-tree.nvim which shows a visual tree to navigate and manage files from the current project (root). Files and directories can be added, renamed, moved and deleted.

    Space f f to find files with Telescope, typing a pattern narrows the selectable file list.

    Set root directory in Neovim

    All file commands respect the currently set directory root for Neovim.

    The root is set to the current directory when opening a file.

    :cd ~/new/directory/path will change the current root to the new path.

    . in Neotree sets the root to the current directory (parent directory if on a file)

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

    Space e toggles neo-tree file browser

    Space o toggles between buffer and neo-tree

    Enter in Neo-tree opens the current file in a buffer

    "},{"location":"neovim-basics/file-buffer-window-tab/#key-bindings-within-neo-tree","title":"Key bindings Within Neo-tree","text":"

    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 / 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
    Configure hidden files

    Configure Neotree to display hidden files and directories by default. They are shown with a different visual style (subtle color) compared to the other files and directories.

    H with the cursor in neotree window will still toggle the display of hidden files and directories.

    Optionally, specify files or directories to never show. lua/plugins/neo-tree.lua

    ---@type LazySpec\nreturn {\n  \"nvim-neo-tree/neo-tree.nvim\",\n  config = function()\n    require(\"neo-tree\").setup {\n      filesystem = {\n        filtered_items = {\n          visible = true, -- show hidden files in alternate style\n          hide_dotfiles = true,\n          hide_gitignored = true,\n          hide_hidden = true, -- only works on Windows for hidden files/directories\n          hide_by_name = {\n            --\"node_modules\"\n          },\n          hide_by_pattern = { -- uses glob style patterns\n            --\"*.meta\",\n            --\"*/src/*/tsconfig.json\",\n          },\n          always_show = { -- remains visible even if other settings would normally hide it\n            --\".gitignored\",\n          },\n          never_show = { -- remains hidden even if visible is toggled to true, this overrides always_show\n            --\".DS_Store\",\n            --\"thumbs.db\"\n          },\n          never_show_by_pattern = { -- uses glob style patterns\n            --\".null-ls_*\",\n          },\n        },\n      },\n    }\n  end,\n}\n

    "},{"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).

    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)

    "},{"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 (!)

    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

    Space W was added to Practicalli Astro Config as a key binding for :write path/to/filename which writes the current buffer to a new file, prompting for the file name.

    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

    "},{"location":"neovim-basics/file-buffer-window-tab/#path-commands","title":"Path commands","text":"

    :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\n

    -p option creates 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/#directories","title":"Directories","text":"

    a in Neotree to create a file or by adding a ++forward-slash++ at the end of the name a directory is created.

    Use the mkdir shell command to create a new directory, which is created relative to the current path, which can be checked with :lcd

    :!mkdir full/path/to/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\n

    mkdir -p - the UNIX command to create a folder, the -p option creating any parts of the path required to make the full path

    % - name of the current file

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

    ! - the NeoVim terminal shell command

    "},{"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":"

    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

    Open multiple buffers at starup

    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
    "},{"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

    Space u SPC u w toggles wrapping of text

    "},{"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.

    \\ creates an horizontal split

    SPC q removes the current split

    Neovim commands

    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.

    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":"

    Multi-modal editing has several states optomised for interacting with text

    • normal - manipulating and navigating existing text (default state)
    • insert - writing new text
    • visual - selecting blocks of text

    Normal mode to insert mode:

    • i insert before the cursor
    • a append after the curor
    • o insert on new line after current line
    • O insert a new line previous to current line

    v to enter visual select, using navigation and/or motions to select a range.

    Esc to leave insert or visual mode and return to normal mode.

    "},{"location":"neovim-basics/multi-modal-editing/#command-language","title":"Command language","text":"

    Learn to speak modal editing commands as sentences to effectively learn Multi-modal editing

    Verbs start the sentence and are the action to perform

    • c change
    • d delete
    • f find character forward
    • g go
    • s substitute
    • v visual select
    • y yank (copy)

    Modifiers (motions) follow verbs and define where the cursor moves to.

    • ' a mark location
    • { } beginning/end of paragraph
    • a around
    • f find forward (includes character)
    • i inside
    • S surround (nvim-surround)
    • t till (up until)

    Text objects provide scope for verbs and modifiers

    • b block/parentheses
    • p paragraph
    • s sentence
    • t tag, e.g. html/xml tag
    • w word
    • W word delimited by only space
    Examples of speaking Evil

    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 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 SPC v s \" visually select current word and surround with \"\" 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)

    Evil Reference and Tips

    Evil quick reference guide Evil tips for developers Speaking Vim

    "},{"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 substitutes the selection, type the characters to surround the selection.

    p to paste 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.

    Practicalli Spacemacs - Evil reference

    "},{"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/navigation/","title":"Navigation","text":"

    Move the cursor one space at a time

    • h move left
    • j move down
    • k move up
    • l move right
    "},{"location":"neovim-basics/navigation/#jump-along-line","title":"Jump along line","text":"

    Move to specific points within a line

    • w jump to start of next word
    • b jump to start of word
    • e jump to end of next word
    • $ jumps to end of line
    • 0 jumps to start of line
    • ^ jumps to first character of line

    Uppercase w b e consider word delimited by blank characters

    Jump joined-word using W B E

    Use w b e movement with a number to move the cursor larger distances

    jump 3 words forward
    3w\n

    f jumps forward in the current line to the given character

    jump to next q character
    fq\n

    F jumps backward in the current line to the given character

    jump to previous [ character
    F[\n

    t jumps forward in the current line to before the given character

    jump before q character
    tq\n

    T jumps backward in the current line to after the given character

    jump after [ character
    T[\n
    "},{"location":"neovim-basics/navigation/#jump-around-buffer","title":"Jump around buffer","text":"
    • H jump to top of window
    • M jump to middle of window
    • L jump to bottom of window
    • { jump to previous paragraph
    • } jump to next paragraph
    • gg jump to first character of line
    • G jump to first character of line

    Use cursor movement with a number to move the cursor larger distances

    jump down 12 lines
    12j\n
    Relative line numbers for line navigation

    Enable relative line numbers to show how far away from the current line each other line is.

    set relativenumber\nset number\n

    Practicalli AstroNvim-Config enables relative line numbers

    Jump to a specific line using the number as a command

    jump to line number
    :127\n
    "},{"location":"neovim-basics/navigation/#navigate-position-history","title":"Navigate position history","text":"

    ++ctrl+\"o\" jumps to a previous postion in the cursor history

    ++ctrl+\"i\" jumps to a previous postion in the cursor history

    "},{"location":"neovim-basics/navigation/#file-marks","title":"File marks","text":"

    Navigate within the current file or globally using file marks.

    m followed by a lower case character creates a mark within the current file.

    m followed by an upper case character creates a global mark.

    ` (backtick) followed by a character jumps to the mark created

    Space f ' displays marks in telescope popup

    File marks within file

    m f creates a mark lablled f

    ` f jumps to the mark labelled f

    Global mark to jump between source and test code

    m S with the cursor in the source code file.

    m T with the cursor in the test code file.

    ` S to jump to the source code

    ` T to jump to the source code

    "},{"location":"neovim-basics/navigation/#jumplist","title":"Jumplist","text":"

    :jumps shows the Neovim jumplist containing all points from any buffer recently jumped to using neovim commands

    • Ctrl o jump back
    • Ctrl i jump forward
    • ctrl and navigation key (hjkl) to move to changelist window
    • q closes the jumplist buffer
    "},{"location":"neovim-basics/navigation/#changes","title":"Changes","text":"

    :changes shows the Neovim changelist containing all points in the current buffer which have changed

    • g ; jump back (previous edit)
    • g . jump forward
    • ctrl and navigation key (hjkl) to move to changelist window
    • q closes the changelist buffer
    "},{"location":"neovim-basics/navigation/#navigation-menus","title":"Navigation menus","text":"
    • [ ( & ] ) previous & next paren
    • [ brace-left & ] brace-right previous and next square brackets
    • [ g & ] g previous and next Git hunks
    • [ s & ] s previous and next misspelled word
    "},{"location":"neovim-basics/navigation/#search-in-buffer","title":"Search in buffer","text":"

    / searches buffer for the following pattern

    • n jumps to next match
    • N jumps to previous match

    AstroNvim user config enables incsearch incremental search and hlsearch to highlight every search match

    "},{"location":"neovim-basics/navigation/#projects","title":"Projects","text":"

    : c d followed by a path changes the root directory for Neovim.

    Tab completion simplifies typing the new path of the root directory.

    AstroNvim rooter

    AstroNvim has a built-in project root detection utility that updates the current working directory automatically.

    "},{"location":"neovim-basics/notifications/","title":"Notifications","text":"

    Notification messages are shown in the bottom right corner of Neovim. Multiple messages are show bottom upwards.

    Notifications are set to show for 2 seconds and then are automatically closed.

    Notification popups show information, warnings and errors.

    "},{"location":"neovim-basics/notifications/#message-history","title":"Message History","text":"

    History of notifications can be browsed to see more detail and to select the text of a notification.

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

    Enter to open the highlighted item in the list in its own pop-up

    y y to yank the text of a notification when displayed in a pop-up

    Noice used for notifications UI

    Practicalli Astro config uses Noice to draw the UI for notification messages, command line and popup menus.

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

    Notifications are controlled by nvim-notify

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

    Practicalli Astro Configuration for notifications

    lua/community.lua
      -- Configure notify popups\n  {\n    \"rcarriga/nvim-notify\",\n    opts = {\n      top_down = false,\n      timeout = 2000,\n      -- log level - 3 hide file write messages - default 5\n      level = 3,\n      -- background_color = \"#000000\",\n    },\n  },\n
    "},{"location":"neovim-basics/plugin-manager/","title":"Lazy 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 plugin manager recommended

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

    "},{"location":"neovim-basics/plugin-manager/#plugin-updates","title":"Plugin Updates","text":"

    Space p S shows the install and loaded status for all plugins defined in the Neovim configuration, e.g. lua/community.lua and lua/plugins/*.lua files

    Space p S checks for updated plugin versions and automatically installs them

    The changelog is shown for all updated plugins, highlighting breaking changes. Conventional commits style is used for most plugins, making it easier to follow the most important changes.

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

    Neovim use registers to store and access text using Neovim commands.

    \" to access a register by name.

    The name of a register is a number, alphabetical or special character.

    SPC f r lists the values of registers in a telescope popup

    Yank and paste commit message

    Select the text of the commit message

    \" m y yanks the selected text into register m

    Complete the Git commit. When creating a new commit, paste the message from the register

    \" m p pastes the register text into the commit message buffer

    Paste last evaluation result from Conjure

    When Conjure evaluates code the result is stored in the C register.

    \" C p pastes the register text into the commit message buffer

    "},{"location":"neovim-basics/registers/#registers","title":"Registers","text":"

    Neovim help - registers

    :help registers\n

    \" the unnamed register, used by Neovim normal commands, e.g. c d p s x y, etc.

    0 to 9 numbered registers containing yank and delete history

    - small delete register for text smaller than a line

    a to z named registers manually selected, A to Z to append to the text already in the register

    : . and % read-only registers use with put commands (last inserted, current file name, recent command)

    # alternate buffer file name

    = expression register for the result of runing a Neovim command expression

    + and * selection registers for GUI

    _ black hole register does not store text, use when normal commands shouldnt update other registers

    / last search pattern register used

    "},{"location":"neovim-basics/registers/#find-registers","title":"Find Registers","text":"

    SPC f r opens the list of registers in a telescope popup.

    Registers in insert mode

    C-r in insert mode pastes the content of the given register, e.g. C-r a to paste the content of \"a

    "},{"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/spell-check/","title":"Spell Check","text":"

    Neovim has a built-in spell check tool. Grammar checks are not supported.

    Incorrect words have a red squiggly underscore.

    z = with the cursor on a word shows a list of possible spelling and similar words.

    Select a word using its number in list to replace the word under the cursor, or Esc to close the spelling list.

    Key Description z = spelling suggestions [ s next incorrect word ] s previous incorrect word z g add word to spelling list z w mark word as misspelled Space u s toggle spellcheck"},{"location":"neovim-basics/terminal/","title":"Terminal","text":"

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

    Space t for the Terminal sub-menu

    Space t f opens a terminal in a floating window, useful for one-off commands or short sessions

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

    :Toggleterm direction=tab opens a terminal in a tab page, useful for long running processes

    "},{"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":"neovim-basics/search-replace/","title":"Search and Replace","text":"

    Neovim has several built-in commands to search for patterns in the current buffer and quickfix list can be used to run commands across all the files in a project.

    Additional tools that work across all the files in a project:

    • Space s s search and replace commands using Spectre
    • Space l r to rename symbols using Clojure LSP

    multiple cursors for in-place editing within a buffer

    "},{"location":"neovim-basics/search-replace/#buffer-search","title":"Buffer search","text":"

    / searches through the current buffer, prompting for a pattern to search.

    Symbol highlight and dot repeat

    # on a word highlights each occurrence in the buffer, n and N to jump backward and forward for each instance.

    Change the current occurrence (e.g. cw followed by new word)

    Use . to repeat the change after jumping to the next instance.

    "},{"location":"neovim-basics/search-replace/#substitute-command","title":"Substitute command","text":"

    Use the :substitute (:s) to replace all occurrences of the current-pattern with the new pattern within the buffer.

    Replace using substitute command

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

    Add the c option to confirm each replacement

    :substitue neovim command examples

    "},{"location":"neovim-basics/search-replace/#project-search-and-replace","title":"Project search and replace","text":"

    Use search to populate the Neovim quickfix list and change occurrences across all the files in the current project, e.g.:

    Search word and replace across project using quickfix list

    Space f w to search for the supplied word or pattern

    Ctrl q opens the search results in quickfix list

    Use :cdo command to search and replace in the quickfix list

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

    Including the c option to confirm each replacement

    "},{"location":"neovim-basics/search-replace/#spectre","title":"Spectre","text":"

    Spectre shows occurrences of a pattern throughout all project files, replace individual or all occurrences.

    Search and replace with Spectre

    Space s is the search and replace menu

    Enter a Search pattern and all occurrences across the project are shown

    Enter a Replace pattern to see occurrences with their replacement

    R to replace all occurrences with the replace pattern

    C to replace current occurrence

    q adds the Spectre search results to quickfix list to edit occurrences with other Neovim tools

    ripgrep and sed are required.

    Spectre

    "},{"location":"neovim-basics/search-replace/spectre/","title":"Spectre","text":"

    Space s s to toggle Spectre (open/close) to search and replace tool.

    ? for the Spectre key mappings

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

    i underneath Search and enter a search pattern, Esc to see resuts in a popup below.

    i underneath Replace and enter a replace pattern, Esc to see in-line diff results

    v toggles Spectre results view between diff to search to replace view

    d d to toggle an occurance

    R replaces all occurances (after selecting the occurances to change)

    A DONE checkbox is show at then end of each selection which has been reaplaced

    To replace single occurance, toggle all occurances that should not be changes and press R

    Spectre does not undo changes

    Use Git or Neovim undo to rollback changes made by Spectre.

    Spectre is available via the AstroNvim Community project pack and included in the Practicalli astronvim-config

    ripgrep and sed are required.

    Spectre project

    "},{"location":"neovim-basics/search-replace/substitute/","title":"Substitute command","text":"

    :substitute or :s command highlights the matches for a text pattern and substitute for a new pattern

    Neovim :help :substitute
    :help :substitute\n

    Subsitute the first matching patterns in the current line

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

    If the new-pattern text is ommitted, then substitute deletes the current-pattern occurances, e.g :s/current-pattern//

    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

    An inclusive line range can be specified to narrow the search

    :4,24s/current-pattern/new-pattern/g\n

    . can be used to represent the current line of buffer

    $ to represent the last line of the current buffer

    :.,$s/current-pattern/new-pattern/g\n

    Match the whole word

    :.,$s/\\<current-pattern\\>/new-pattern/g\n
    "},{"location":"neovim-basics/search-replace/substitute/#substitute-history","title":"Substitute history","text":"

    :s and the Up / Down will navigate through the substitution history for the current session (from when Neovim was last opened if session was not restored)

    "},{"location":"neovim-basics/search-replace/substitute/#confirm-replacement","title":"Confirm replacement","text":"

    c option at the end prompt for confirmation to replace each occurance

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

    y confirms the repacement

    l confirms the repacement and quits

    n skips the current occurance and goes to the next one

    y or Esc to quit substitution

    "},{"location":"neovim-basics/search-replace/substitute/#regular-expression","title":"Regular expression","text":"

    regular expressions can be used as a search pattern.

    To replace all lines starting with \u2018foo\u2019 with \u2018NeoVim Rocks\u2019:

    :%s/^foo.*/NeoVim rocks/gc\n

    Replace all instances of \u2018apple\u2019, \u2018orange\u2019, and \u2018mango\u2019 with \u2018fruit\u2019:

    :%s/apple\\|orange\\|mango/fruit/g\n

    Remove trailing blank space at the end of each line:

    :%s/\\s\\+$//e\n
    "},{"location":"neovim-basics/search-replace/substitute/#matching-case","title":"Matching case","text":"

    i option disables the default case sensitive search

    :%s/current-pattern/new-pattern/gi\n
    "},{"location":"neovim-basics/search-replace/substitute/#visual-select","title":"Visual Select","text":"

    Use a visual select to search and replace, with confirmation

    Note: '<,'> is automatically included when in visual mode and : is pressed to start a command

    :'<,'>s/search-text/replace-text/g\n

    A potentially more effecitve approach:

    • visually select the text
    • * to select all matching occurances
    • :%s//replace-text/g
    "},{"location":"reference/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":"reference/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":"reference/fennel/#fennel-packages","title":"Fennel Packages","text":"

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

    "},{"location":"reference/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":"reference/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":"reference/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":"reference/configuration/","title":"\ud83d\udce6 Practicalli Astro Config Design","text":"

    A guide to the design of AstroNvim Config created by Practicalli to support a comprehensive development workflow.

    AstroCommunity Plugin Configurations used where available

    Plugin configurations from AstroCommunity are used to minimise the code size and maintenance of the Practicalli configuration

    Under review after migration to AstroNvim 4

    "},{"location":"reference/configuration/#files-overview","title":"Files overview","text":"

    The file structure as taken from the AstroNvim template and new files were created to minimise changes, making it simpler to add updates from the original template repository.

    Key - AstroNvim template file changes

    Icons describing if a file was added, changed or unchanged from the AstroNvim template

    • unchanged
    • changed
    • added
    • config not activated (comment if statement to activate)

    init.lua ensures the Lazy package manager is available when Neovim starts up. This file is unchanged from the AstroNvim template.

    lua/lazy_setup.lua configures the Lazy package manager. zipPlugin enabled to support Clojure docs and source navigation inside libraries.

    lua/community.lua imports plugin configurations from AstroCommunity, including the Clojure pack.

    lua/polish.lua general lua configuration loaded after AstroNvim configs.

    lua/plugins/ for additional plugins organised logically. All .lua files are automatically loaded from this directory when starting Neovim.

    • astrocore.lua, astrolsp.lua, astroui.lua examples of overriding AstroNvim defaults
    • clojure.lua alternative approach to configure clojure, extending the AstroNvim Clojure pack
    • github.lua issue & PR management with octo.nvim (requires GitHub CLI)
    • mason.lua ensure tools are installed by default (LSP servers, format & lint tools, DAP debug tools)
    • neo-tree.lua visual file navigator - example config
    • none-ls.lua example config for format & lint tools
    • platuml.lua UML diagrams defined with code - requires plantuml.com install
    • snippets.lua load JSON style snippet definitions
    • telescope.lua ensure Treesitter languages are installed (AstroCommunity language packs also ensure parsers installed)
    • treesittter.lua ensure Treesitter languages are installed (AstroCommunity language packs also ensure parsers installed)
    • user.lua example user configuration, added via lua/plugins/user-practicalli.lua
    • user-practicalli.lua theme, dashboard & key binding preferences enjoyed by Practicalli
    • user-termux.lua mason lsp server overrides, pinned plugin versions for neovim 0.9.x
    "},{"location":"reference/configuration/#disable-plugins","title":"Disable Plugins","text":"

    Practicalli Astro provides a rich set of Neovim plugins. Any plugin can be configured as disabled, usually in a user configuration, e.g. lua/plugins/user-practicalli.lua

    Disable parinfer and sexp plugins

    lua/plugins/user-practicalli.lua
      -- ----------------------------------------------\n  { \"nvim-parinfer\", enabled = false },\n  { \"nvim-treesitter-sexp\", enabled = false },\n  -- ----------------------------------------------\n
    "},{"location":"reference/configuration/#clojure-support","title":"Clojure support","text":"

    The AstroCommunity provides a Clojure language pack that ensures clojure Treesitter parser and clojure-lsp support and installed automatically.

    The pack contains 4 Neovim plugins:

    • conjure REPL client to evaluate code
    • nvim-parinfer code indenting structural editing
    • nvim-treesitter-sexp paredit (slurp/barf etc) structural editing
    • ts-comment.nvim Clojure comment patterns

    !!! INFO: \"Practicalli AstroNvim Config includes Clojure pack\"

    AstroCommunity Clojure 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
    Exclude a plugin from the pack

    The Clojure pack includes parinfer and paredit tools for structural editing, which both work together without issue. Should one or both of these plugins not be reqiured, set enabled to false

    return {\n  \"AstroNvim/astrocommunity\",\n  { import = \"astrocommunity.pack.clojure\" },\n  { \"gpanders/nvim-parinfer\", enabled = false },\n

    Override Conjure configration

    Add the AstroCommunity Clojure pack and additional configuration to create a tailored experience

    :help conjure for general Conjure options.

    :help conjure-client-clojure-nrepl for Clojure specific options.

    return {\n  \"AstroNvim/astrocommunity\",\n  { import = \"astrocommunity.pack.clojure\" },\n  {\n    \"AstroNvim/astrocore\",\n    opts = {\n      options = {\n        g = {\n          -- show HUD REPL log at startup\n          [\"conjure#log#hud#enabled\"] = false,\n\n          -- Hightlight evaluated forms\n          -- [\"conjure#highlight#enabled\"] = true,\n\n          -- Trim log after number of lines. Default: `10000`\n          -- [\"conjure#log#trim#at\"] = 200,\n          -- Trim log to number of lines. Default: `7000`\n          -- [\"conjure#log#trim#to\"] = 100,\n\n          -- auto repl (babashka)\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false,\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true,\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil,\n          [\"conjure#client#clojure#nrepl#eval#auto_require\"] = false,\n\n          -- Test runner: \"clojure\", \"clojuresCRipt\", \"kaocha\"\n          [\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\",\n        },\n      },\n    },\n  },\n}\n
    Config comment for parinfer

    The parinfer comment configuration may not be required when using ts-comment.nvim to set the Clojure comment pattern.

    {\n  \"gpanders/nvim-parinfer\",\n  filetype = { \"clojure\" },\n  config = function()\n    vim.g.parinfer_force_balance = true\n    vim.g.parinfer_comment_chars = \";;\"\n  end,\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

    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

    Manual install of Treesitter Clojure Parser

    :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

    Switch to Parinfer Parens mode for Paredit structural editing

    Changing the Parinfer mode to paren gives a structured editing experience similar to Paredit (or Smartparens).

    Add the following configuration within the return {} table in the plugins/community.lua file to set the parinfef mode, i.e. paren, smart or indent (default

    plugins/community.lua
      {\n    \"gpanders/nvim-parinfer\",\n    ft = { \"clojure\" },\n    config = function()\n      vim.g.parinfer_force_balance = true\n      vim.g.parinfer_comment_chars = \";;\"\n      vim.g.parinfer_mode = \"paren\"\n    end,\n  },\n
    "},{"location":"reference/configuration/#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":"reference/configuration/#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":"reference/configuration/#snippets","title":"Snippets","text":"

    The AstroNvim user example includes a commented LuaSnip configuration

    LuaSnip with json format snippets in snippets/ directory

    .config/astronvim-config/plugins/core.lua
    return {\n  --LuaSnip with json format snippets in `snippets/` directory\n  {\n    \"L3MON4D3/LuaSnip\",\n    config = function(plugin, opts)\n      require \"astronvim.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 = { \"./snippets\" } } -- include JSON style snippets\n      local luasnip = require \"luasnip\"\n      luasnip.filetype_extend(\"javascript\", { \"javascriptreact\" })\n    end,\n  },\n}\n
    "},{"location":"reference/configuration/#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":"reference/configuration/#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

      {\n    -- AstroUI provides the basis for configuring the AstroNvim User Interface\n    -- Configuration documentation can be found with `:h astroui`\n    \"AstroNvim/astroui\",\n    ---@type AstroUIOpts\n    opts = {\n      colorscheme = \"everforest\",\n    },\n  },\n

    AstroCommunity themes

    "},{"location":"reference/configuration/#configure-lazy-plugins","title":"Configure Lazy plugins","text":"

    Lazy.nvim Plugin specification

    "},{"location":"reference/configuration/#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":"reference/configuration/#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":"reference/configuration/#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":"reference/configuration/astrocommunity/","title":"Override Astrocommunity Configuration","text":"

    Configuration in the AstroNvim Community clojure language pack can be overridden and plugins disabled to meet your needs

    "},{"location":"reference/configuration/astrocommunity/#parinfer","title":"Parinfer","text":"

    By aligning clojure code correctly, parinfer will automatically correct the position of parenthesis and other delimiters, i.e. (), [], {}

    Parinfer can be disabled if preferred and the more traditional slurp/barf structural editing be done via nvim-treesitter-sexp

    Include the Clojure language pack and disable the parinfer plugin by setting the plugin name to equal false

      { import = \"astrocommunity.pack.clojure\" },\n  { \"gpanders/nvim-parinfer\", enabled = false },\n
    "},{"location":"reference/configuration/astrocommunity/#conjure","title":"Conjure","text":"

    Configure the Clojure REPL client via the conjure plugin.

    NOTE: :help conjure-client-clojure-nrepl for full list of Conjure options for Clojure.

    Set HUD location to full width along the bottom of the screen. The HUD appears in the top right corner of the screen by default.

                [\"conjure#log#hud#enabled\"] = true,  -- enable HUD\n            [\"conjure#log#hud#width\"] = 1,\n            [\"conjure#log#hud#anchor\"] = \"SE\",\n            [\"conjure#log#botright\"] = true,\n

    Disable the auto repl (babashka) if an nREPL process is not listening, i.e. .nrepl-port file does not exist or does not contain a port number.

                -- Disable auto repl (babashka)\n            [\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false,\n            [\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true,\n            [\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil,\n            [\"conjure#client#clojure#nrepl#eval#auto_require\"] = false,\n

    Change the test runner used by Conjure. clojure.test runner is used by default

    • \"clojure\" clojure.test (default)
    • `\"clojuresCRipt\" cljs.test
    • \"kaocha\" lambdaisland/kaocha
                -- Set Test runner: \"clojure\", \"clojuresCRipt\", \"kaocha\"\n            [\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\",\n

    Working example with additional configuration options to show HUD along bottom, enable auto repl if no nREPL process found and set test runner to use lambdaisland/kaocha.

      { import = \"astrocommunity.pack.clojure\" },\n  {\n    \"AstroNvim/astrocore\",\n    opts = {\n      options = {\n        g = {\n          -- Enable HUD and show full lenght along bottom\n          [\"conjure#log#hud#enabled\"] = true, -- show log by default?\n          [\"conjure#log#hud#width\"] = 1,\n          [\"conjure#log#hud#anchor\"] = \"SE\",\n          [\"conjure#log#botright\"] = true,\n\n          -- Disable auto repl (babashka)\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#enabled\"] = false,\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#hidden\"] = true,\n          [\"conjure#client#clojure#nrepl#connection#auto_repl#cmd\"] = nil,\n          [\"conjure#client#clojure#nrepl#eval#auto_require\"] = false,\n\n          -- Set Test runner: \"clojure\", \"clojuresCRipt\", \"kaocha\"\n          [\"conjure#client#clojure#nrepl#test#runner\"] = \"kaocha\",\n        },\n      },\n    },\n  },\n
    "},{"location":"reference/configuration/astrocommunity/#nvim-treesitter-sexp","title":"nvim-treesitter-sexp","text":"

    Treesitter based structural editing with normal mode key mappings, which can be set to false to disable. Two commands are disabled in the example.

    Additional which-key keymaps can be included for greater discoverability. Example includes keymaps inspired by Spacemacs Lisp mode, SPC k.

      { import = \"astrocommunity.pack.clojure\" },\n  {\n    \"PaterJason/nvim-treesitter-sexp\",\n    dependencies = {\n      \"AstroNvim/astrocore\",\n      opts = {\n        -- configuration & keymaps overrides:\n        -- https://github.com/PaterJason/nvim-treesitter-sexp#configuration\n        -- enabled = false,  -- Set to false to disable individual keymaps\n        -- set_cursor = true,\n        -- keymaps = {\n        -- Default key bindings - set to false to disable\n        --   commands = {\n        --     promote_elem = false,\n        --     promote_form = false,\n        --   },\n        --   motions = {\n        --   },\n        --   textobjects = {\n        --   },\n        -- },\n        options = {\n          g = {},\n        },\n        mappings = {\n          n = {\n            -- Additional Which-key key bindings for nvim-treesitter-sexp\n            [\"<Leader>k\"] = { name = \"Structural Editing\" },\n            [\"<Leader>kE\"] = { \"<Cmd>TSSexp swap_prev_elem<CR>\", desc = \"Swap Previous Element\" },\n            [\"<Leader>ke\"] = { \"<Cmd>TSSexp swap_next_elem<CR>\", desc = \"Swap Previous Element\" },\n            [\"<Leader>kF\"] = { \"<Cmd>TSSexp swap_prev_form<CR>\", desc = \"Swap Previous Form\" },\n            [\"<Leader>kf\"] = { \"<Cmd>TSSexp swap_next_form<CR>\", desc = \"Swap Previous Form\" },\n            [\"<Leader>kk\"] = { \"<Cmd>TSSexp promote_elem<CR>\", desc = \"Promote Element\" },\n            [\"<Leader>kr\"] = { \"<Cmd>TSSexp promote_form<CR>\", desc = \"Promote Form\" },\n            [\"<Leader>k@\"] = { \"<Cmd>TSSexp splice<CR>\", desc = \"Splice\" },\n            [\"<Leader>kS\"] = { \"<Cmd>TSSexp slurp_left<CR>\", desc = \"Slurp Left\" },\n            [\"<Leader>ks\"] = { \"<Cmd>TSSexp slurp_right<CR>\", desc = \"Slurp Right\" },\n            [\"<Leader>kB\"] = { \"<Cmd>TSSexp barf_left<CR>\", desc = \"Barf Left\" },\n            [\"<Leader>kb\"] = { \"<Cmd>TSSexp barf_right<CR>\", desc = \"Barf Right\" },\n            [\"<Leader>kI\"] = { \"<Cmd>TSSexp barf_right<CR>\", desc = \"Insert Head\" },\n            [\"<Leader>ki\"] = { \"<Cmd>TSSexp barf_right<CR>\", desc = \"Insert Tail\" },\n          },\n          t = {\n            -- terminal? mode key bindings\n          },\n          v = {\n            -- visual mode key bindings\n          },\n        },\n      },\n    },\n  },\n
    "},{"location":"reference/configuration/practicalli/","title":"Neovim Config Redux","text":"

    Practicalli Config Redux has been archived

    Practicalli Neovim uses the AstroNvim config.

    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":"reference/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":"reference/configuration/practicalli/config-design/","title":"Config Design","text":"

    The overall design of the Practicalli Neovim Config Redux

    "},{"location":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"reference/configuration/practicalli/packages/#package-updates","title":"Package Updates","text":"

    This Week In Neovim - community update

    "},{"location":"reference/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":"reference/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":"reference/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":"reference/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":"reference/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":"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

    Introduction to Lua - Codecademy

    "},{"location":"reference/modal-editing/","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/modal-editing/#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/modal-editing/#navigation-and-searching","title":"Navigation and searching","text":"
    • moving the cursor
    • Motions
    • line numbers
    • jumping around a buffer
    • search and replace
    "},{"location":"reference/modal-editing/#text-wrangling","title":"Text wrangling","text":"
    • iedit
    • text case
    "},{"location":"reference/modal-editing/#clojure-editing","title":"Clojure Editing","text":"

    traversing expressions structural editing

    "},{"location":"reference/modal-editing/case/","title":"Modifying text case","text":"

    Convert Characters and regioins to upper or lower case text.

    "},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/key-binding-reference/","title":"Evil Keybinding Reference","text":"

    An alphabetically ordered reference of Vim-style key bindings.

    "},{"location":"reference/modal-editing/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/modal-editing/motions/","title":"Motions","text":"

    Todo

    Moving the cursor around by context rather than individual characters

    "},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/narrowing/#documentation","title":"Documentation","text":"

    :help NarrowRegion to view the documetation on the NrrwRgn plug use

    "},{"location":"reference/modal-editing/narrowing/#attention","title":"Attention","text":"

    :NRM is described as experimental by the project readme.

    "},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/vim-quick-reference/#transposing-swap","title":"Transposing / swap","text":"Key Description x p transpose the current character with the next character"},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/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/modal-editing/visual-select/#line-and-block","title":"Line and block","text":"

    V enters visual line select mode

    j and k alter the selection by line

    Ctrl+v enters visual region select mode

    Switch between visual modes

    Once in visual mode:

    V switches to visual line mode Ctrl+v switches to visual line mode

    "},{"location":"reference/modal-editing/z-menu/","title":"Evil Z menu","text":"

    z in normal mode opens a menu of convenient utilities

    "},{"location":"reference/modal-editing/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/modal-editing/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/modal-editing/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 list to replace the word under the cursor, or Esc to close the spelling list.

    Key Description z = spelling suggestions [ s next incorrect word ] s previous incorrect word z g add word to spelling list z w mark word as misspelled"},{"location":"reference/neovim/","title":"Neovim Reference","text":"
    • Language Providers
    • Key mappings
    "},{"location":"reference/neovim/changelist/","title":"Changelist","text":"

    Initial draft - feedback welcome

    :help :changelist\n

    View changelist

    :changes\n
    • ctrl and navigation key (hjkl) to move to changelist window
    • q closes the changelist buffer
    "},{"location":"reference/neovim/jumplist/","title":"Jumplist","text":"

    Initial draft - feedback welcome

    :help :jumplist\n

    View jumplist

    :jumps\n
    • ctrl and navigation key (hjkl) to move to jumplist window
    • q closes the jumplist buffer
    "},{"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/quickfix/","title":"Quickfix","text":"

    Initial draft - feedback welcome

    "},{"location":"reference/neovim/quickfix/#quickfix-mode","title":"quickfix mode","text":"Open quickfix in window
    :ccopen\n

    Use j k to navigate the list or :cc and a number to jump to a result

    jump to the 7th result
    :cc 7\n
    • ctrl and navigation key (hjkl) to move to quickfix window
    • q closes the quickfix buffer
    "},{"location":"reference/neovim/quickfix/#tools","title":"Tools","text":"
    • qf.nvim - Quickfix and location list management for Neovim
    • nvim-bqf enhanced quickfix window

    Quickfix is a mode to show results of another command

    • a make compile task
    • the results of a search
    • lsp analysis errors

    Quickfix buffer can be used to jump through the errors one by one. Each error can be viewe and fix it in turn.

    quickfix is used to find a list of positions in files.

    • :vimgrep| finds pattern matches.

    The 'errorformat' option should be set to match the error messages from your compiler (see |errorformat| below).

                            *quickfix-ID*\n

    Each quickfix list has a unique identifier called the quickfix ID and this number will not change within a Vim session. The |getqflist()| function can be used to get the identifier assigned to a list. There is also a quickfix list number which may change whenever more than ten lists are added to a quickfix stack.

                        *location-list* *E776*\n

    A location list is a window-local quickfix list. You get one after commands like :lvimgrep, :lgrep, :lhelpgrep, :lmake, etc., which create a location list instead of a quickfix list as the corresponding :vimgrep, :grep, :helpgrep, :make do. location-list-file-window A location list is associated with a window and each window can have a separate location list. A location list can be associated with only one window. The location list is independent of the quickfix list.

    When a window with a location list is split, the new window gets a copy of the location list. When there are no longer any references to a location list, the location list is destroyed.

                        *quickfix-changedtick*\n

    Every quickfix and location list has a read-only changedtick variable that tracks the total number of changes made to the list. Every time the quickfix list is modified, this count is incremented. This can be used to perform an action only when the list has changed. The |getqflist()| and |getloclist()| functions can be used to query the current value of changedtick. You cannot change the changedtick variable.

    The following quickfix commands can be used. The location list commands are similar to the quickfix commands, replacing the 'c' prefix in the quickfix command with 'l'.

                            *E924*\n

    If the current window was closed by an |autocommand| while processing a location list command, it will be aborted.

                            *E925* *E926*\n

    If the current quickfix or location list was changed by an |autocommand| while processing a quickfix or location list command, it will be aborted.

                            *:cc*\n

    :cc[!] [nr] Display error [nr]. If [nr] is omitted, the same :[nr]cc[!] error is displayed again. Without [!] this doesn't work when jumping to another buffer, the current buffer has been changed, there is the only window for the buffer and both 'hidden' and 'autowrite' are off. When jumping to another buffer with [!] any changes to the current buffer are lost, unless 'hidden' is set or there is another window for this buffer. The 'switchbuf' settings are respected when jumping to a buffer. When used in the quickfix window the line number can be used, including \".\" for the current line and \"$\" for the last line.

                            *:ll*\n

    :ll[!] [nr] Same as \":cc\", except the location list for the :[nr]ll[!] current window is used instead of the quickfix list.

                        *:cn* *:cne* *:cnext* *E553*\n

    :[count]cn[ext][!] Display the [count] next error in the list that includes a file name. If there are no file names at all, go to the [count] next error. See |:cc| for [!] and 'switchbuf'.

                            *:lne* *:lnext*\n

    :[count]lne[xt][!] Same as \":cnext\", except the location list for the current window is used instead of the quickfix list.

    :[count]cN[ext][!] :cp :cprevious :cprev :cN :cNext :[count]cp[revious][!] Display the [count] previous error in the list that includes a file name. If there are no file names at all, go to the [count] previous error. See |:cc| for [!] and 'switchbuf'.

    :[count]lN[ext][!] :lp :lprevious :lprev :lN :lNext :[count]lp[revious][!] Same as \":cNext\" and \":cprevious\", except the location list for the current window is used instead of the quickfix list.

                            *:cabo* *:cabove*\n

    :[count]cabo[ve] Go to the [count] error above the current line in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix list are sorted by their buffer number and line number. If there are multiple errors on the same line, then only the first entry is used. If [count] exceeds the number of entries above the current line, then the first error in the file is selected.

                            *:lab* *:labove*\n

    :[count]lab[ove] Same as \":cabove\", except the location list for the current window is used instead of the quickfix list.

                            *:cbel* *:cbelow*\n

    :[count]cbel[ow] Go to the [count] error below the current line in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix list are sorted by their buffer number and line number. If there are multiple errors on the same line, then only the first entry is used. If [count] exceeds the number of entries below the current line, then the last error in the file is selected.

                            *:lbel* *:lbelow*\n

    :[count]lbel[ow] Same as \":cbelow\", except the location list for the current window is used instead of the quickfix list.

                            *:cbe* *:cbefore*\n

    :[count]cbe[fore] Go to the [count] error before the current cursor position in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix list are sorted by their buffer, line and column numbers. If [count] exceeds the number of entries before the current position, then the first error in the file is selected.

                            *:lbe* *:lbefore*\n

    :[count]lbe[fore] Same as \":cbefore\", except the location list for the current window is used instead of the quickfix list.

                            *:caf* *:cafter*\n

    :[count]caf[ter] Go to the [count] error after the current cursor position in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix list are sorted by their buffer, line and column numbers. If [count] exceeds the number of entries after the current position, then the last error in the file is selected.

                            *:laf* *:lafter*\n

    :[count]laf[ter] Same as \":cafter\", except the location list for the current window is used instead of the quickfix list.

                            *:cnf* *:cnfile*\n

    :[count]cnf[ile][!] Display the first error in the [count] next file in the list that includes a file name. If there are no file names at all or if there is no next file, go to the [count] next error. See |:cc| for [!] and 'switchbuf'.

                            *:lnf* *:lnfile*\n

    :[count]lnf[ile][!] Same as \":cnfile\", except the location list for the current window is used instead of the quickfix list.

    :[count]cNf[ile][!] :cpf :cpfile :cNf :cNfile :[count]cpf[ile][!] Display the last error in the [count] previous file in the list that includes a file name. If there are no file names at all or if there is no next file, go to the [count] previous error. See |:cc| for [!] and 'switchbuf'.

    :[count]lNf[ile][!] :lpf :lpfile :lNf :lNfile :[count]lpf[ile][!] Same as \":cNfile\" and \":cpfile\", except the location list for the current window is used instead of the quickfix list.

                            *:crewind* *:cr*\n

    :cr[ewind][!] [nr] Display error [nr]. If [nr] is omitted, the FIRST error is displayed. See |:cc|.

                            *:lrewind* *:lr*\n

    :lr[ewind][!] [nr] Same as \":crewind\", except the location list for the current window is used instead of the quickfix list.

                            *:cfirst* *:cfir*\n

    :cfir[st][!] [nr] Same as \":crewind\".

                            *:lfirst* *:lfir*\n

    :lfir[st][!] [nr] Same as \":lrewind\".

                            *:clast* *:cla*\n

    :cla[st][!] [nr] Display error [nr]. If [nr] is omitted, the LAST error is displayed. See |:cc|.

                            *:llast* *:lla*\n

    :lla[st][!] [nr] Same as \":clast\", except the location list for the current window is used instead of the quickfix list.

                            *:cq* *:cquit*\n

    :cq[uit][!] :{N}cq[uit][!] :cq[uit][!] {N} Quit Vim with error code {N}. {N} defaults to one. Useful when Vim is called from another program: e.g., a compiler will not compile the same file again, git commit will abort the committing process, fc (built-in for shells like bash and zsh) will not execute the command, etc. {N} can also be zero, in which case Vim exits normally. WARNING: All changes in files are lost. It works like \":qall!\" |:qall|, except that Nvim exits non-zero or [count].

                            *:cf* *:cfi* *:cfile*\n

    :cf[ile][!] [errorfile] Read the error file and jump to the first error. This is done automatically when Vim is started with the -q option. You can use this command when you keep Vim running while compiling. If you give the name of the errorfile, the 'errorfile' option will be set to [errorfile]. See |:cc| for [!]. If the encoding of the error file differs from the 'encoding' option, you can use the 'makeencoding' option to specify the encoding.

                            *:lf* *:lfi* *:lfile*\n

    :lf[ile][!] [errorfile] Same as \":cfile\", except the location list for the current window is used instead of the quickfix list. You can not use the -q command-line option to set the location list.

    :cg[etfile] [errorfile] :cg :cgetfile Read the error file. Just like \":cfile\" but don't jump to the first error. If the encoding of the error file differs from the 'encoding' option, you can use the 'makeencoding' option to specify the encoding.

    :lg[etfile] [errorfile] :lg :lge :lgetfile Same as \":cgetfile\", except the location list for the current window is used instead of the quickfix list.

                            *:caddf* *:caddfile*\n

    :caddf[ile] [errorfile] Read the error file and add the errors from the errorfile to the current quickfix list. If a quickfix list is not present, then a new list is created. If the encoding of the error file differs from the 'encoding' option, you can use the 'makeencoding' option to specify the encoding.

                            *:laddf* *:laddfile*\n

    :laddf[ile] [errorfile] Same as \":caddfile\", except the location list for the current window is used instead of the quickfix list.

                        *:cb* *:cbuffer* *E681*\n

    :cb[uffer][!] [bufnr] Read the error list from the current buffer. When [bufnr] is given it must be the number of a loaded buffer. That buffer will then be used instead of the current buffer. A range can be specified for the lines to be used. Otherwise all lines in the buffer are used. See |:cc| for [!].

                        *:lb* *:lbuffer*\n

    :lb[uffer][!] [bufnr] Same as \":cbuffer\", except the location list for the current window is used instead of the quickfix list.

                        *:cgetb* *:cgetbuffer*\n

    :cgetb[uffer] [bufnr] Read the error list from the current buffer. Just like \":cbuffer\" but don't jump to the first error.

                        *:lgetb* *:lgetbuffer*\n

    :lgetb[uffer] [bufnr] Same as \":cgetbuffer\", except the location list for the current window is used instead of the quickfix list.

                        *:cad* *:cadd* *:caddbuffer*\n

    :cad[dbuffer] [bufnr] Read the error list from the current buffer and add the errors to the current quickfix list. If a quickfix list is not present, then a new list is created. Otherwise, same as \":cbuffer\".

                            *:laddb* *:laddbuffer*\n

    :laddb[uffer] [bufnr] Same as \":caddbuffer\", except the location list for the current window is used instead of the quickfix list.

                            *:cex* *:cexpr* *E777*\n

    :cex[pr][!] {expr} Create a quickfix list using the result of {expr} and jump to the first error. If {expr} is a String, then each newline terminated line in the String is processed using the global value of 'errorformat' and the result is added to the quickfix list. If {expr} is a List, then each String item in the list is processed and added to the quickfix list. Non String items in the List are ignored. See |:cc| for [!]. Examples: :cexpr system('grep -n xyz *') :cexpr getline(1, '$')

                            *:lex* *:lexpr*\n

    :lex[pr][!] {expr} Same as |:cexpr|, except the location list for the current window is used instead of the quickfix list.

                            *:cgete* *:cgetexpr*\n

    :cgete[xpr] {expr} Create a quickfix list using the result of {expr}. Just like |:cexpr|, but don't jump to the first error.

                            *:lgete* *:lgetexpr*\n

    :lgete[xpr] {expr} Same as |:cgetexpr|, except the location list for the current window is used instead of the quickfix list.

                            *:cadde* *:caddexpr*\n

    :cadde[xpr] {expr} Evaluate {expr} and add the resulting lines to the current quickfix list. If a quickfix list is not present, then a new list is created. The current cursor position will not be changed. See |:cexpr| for more information. Example: :g/mypattern/caddexpr expand(\"%\") .. \":\" .. line(\".\") .. \":\" .. getline(\".\")

                        *:lad* *:addd* *:laddexpr*\n

    :lad[dexpr] {expr} Same as \":caddexpr\", except the location list for the current window is used instead of the quickfix list.

                            *:cl* *:clist*\n

    :cl[ist] [from] [, [to]] List all errors that are valid |quickfix-valid|. If numbers [from] and/or [to] are given, the respective range of errors is listed. A negative number counts from the last error backwards, -1 being the last error. The |:filter| command can be used to display only the quickfix entries matching a supplied pattern. The pattern is matched against the filename, module name, pattern and text of the entry.

    :cl[ist] +{count} List the current and next {count} valid errors. This is similar to \":clist from from+count\", where \"from\" is the current error position.

    :cl[ist]! [from] [, [to]] List all errors.

    :cl[ist]! +{count} List the current and next {count} error lines. This is useful to see unrecognized lines after the current one. For example, if \":clist\" shows: 8384 testje.java:252: error: cannot find symbol Then using \":cl! +3\" shows the reason: 8384 testje.java:252: error: cannot find symbol 8385: ZexitCode = Fmainx(); 8386: ^ 8387: symbol: method Fmainx()

    :lli[st] [from] [, [to]] :lli :llist Same as \":clist\", except the location list for the current window is used instead of the quickfix list.

    :lli[st]! [from] [, [to]] List all the entries in the location list for the current window.

    If you insert or delete lines, mostly the correct error location is still found because hidden marks are used. Sometimes, when the mark has been deleted for some reason, the message \"line changed\" is shown to warn you that the error location may not be correct. If you quit Vim and start again the marks are lost and the error locations may not be correct anymore.

    Two autocommands are available for running commands before and after a quickfix command (':make', ':grep' and so on) is executed. See |QuickFixCmdPre| and |QuickFixCmdPost| for details.

                        *QuickFixCmdPost-example*\n

    When 'encoding' differs from the locale, the error messages may have a different encoding from what Vim is using. To convert the messages you can use this code: function QfMakeConv() let qflist = getqflist() for i in qflist let i.text = iconv(i.text, \"cp936\", \"utf-8\") endfor call setqflist(qflist) endfunction

    au QuickfixCmdPost make call QfMakeConv()\n

    Another option is using 'makeencoding'.

                            *quickfix-title*\n

    Every quickfix and location list has a title. By default the title is set to the command that created the list. The |getqflist()| and |getloclist()| functions can be used to get the title of a quickfix and a location list respectively. The |setqflist()| and |setloclist()| functions can be used to modify the title of a quickfix and location list respectively. Examples: call setqflist([], 'a', {'title' : 'Cmd output'}) echo getqflist({'title' : 1}) call setloclist(3, [], 'a', {'title' : 'Cmd output'}) echo getloclist(3, {'title' : 1})

                            *quickfix-index*\n

    When you jump to a quickfix/location list entry using any of the quickfix commands (e.g. |:cc|, |:cnext|, |:cprev|, etc.), that entry becomes the currently selected entry. The index of the currently selected entry in a quickfix/location list can be obtained using the getqflist()/getloclist() functions. Examples: echo getqflist({'idx' : 0}).idx echo getqflist({'id' : qfid, 'idx' : 0}).idx echo getloclist(2, {'idx' : 0}).idx

    For a new quickfix list, the first entry is selected and the index is 1. Any entry in any quickfix/location list can be set as the currently selected entry using the setqflist() function. Examples: call setqflist([], 'a', {'idx' : 12}) call setqflist([], 'a', {'id' : qfid, 'idx' : 7}) call setloclist(1, [], 'a', {'idx' : 7})

                            *quickfix-size*\n

    You can get the number of entries (size) in a quickfix and a location list using the |getqflist()| and |getloclist()| functions respectively. Examples: echo getqflist({'size' : 1}) echo getloclist(5, {'size' : 1})

                            *quickfix-context*\n

    Any Vim type can be associated as a context with a quickfix or location list. The |setqflist()| and the |setloclist()| functions can be used to associate a context with a quickfix and a location list respectively. The |getqflist()| and the |getloclist()| functions can be used to retrieve the context of a quickfix and a location list respectively. This is useful for a Vim plugin dealing with multiple quickfix/location lists. Examples:

    let somectx = {'name' : 'Vim', 'type' : 'Editor'}\ncall setqflist([], 'a', {'context' : somectx})\necho getqflist({'context' : 1})\n\nlet newctx = ['red', 'green', 'blue']\ncall setloclist(2, [], 'a', {'id' : qfid, 'context' : newctx})\necho getloclist(2, {'id' : qfid, 'context' : 1})\n\n                        *quickfix-parse*\n

    You can parse a list of lines using 'errorformat' without creating or modifying a quickfix list using the |getqflist()| function. Examples: echo getqflist({'lines' : [\"F1:10:Line10\", \"F2:20:Line20\"]}) echo getqflist({'lines' : systemlist('grep -Hn quickfix *')}) This returns a dictionary where the \"items\" key contains the list of quickfix entries parsed from lines. The following shows how to use a custom 'errorformat' to parse the lines without modifying the 'errorformat' option: echo getqflist({'efm' : '%f#%l#%m', 'lines' : ['F1#10#Line']})

    EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST: :cdo :cdo[!] {cmd} Execute {cmd} in each valid entry in the quickfix list. It works like doing this: :cfirst :{cmd} :cnext :{cmd} etc. When the current file can't be |abandon|ed and the [!] is not present, the command fails. When going to the next entry fails execution stops. The last buffer (or where an error occurred) becomes the current buffer. {cmd} can contain '|' to concatenate several commands.

            Only valid entries in the quickfix list are used.\n        A range can be used to select entries, e.g.:\n            :10,$cdo cmd\n        To skip entries 1 to 9.\n\n        Note: While this command is executing, the Syntax\n        autocommand event is disabled by adding it to\n        'eventignore'.  This considerably speeds up editing\n        each buffer.\n        Also see |:bufdo|, |:tabdo|, |:argdo|, |:windo|,\n        |:ldo|, |:cfdo| and |:lfdo|.\n\n                        *:cfdo*\n

    :cfdo[!] {cmd} Execute {cmd} in each file in the quickfix list. It works like doing this: :cfirst :{cmd} :cnfile :{cmd} etc. Otherwise it works the same as :cdo.

                            *:ldo*\n

    :ld[o][!] {cmd} Execute {cmd} in each valid entry in the location list for the current window. It works like doing this: :lfirst :{cmd} :lnext :{cmd} etc. Only valid entries in the location list are used. Otherwise it works the same as :cdo.

                            *:lfdo*\n

    :lfdo[!] {cmd} Execute {cmd} in each file in the location list for the current window. It works like doing this: :lfirst :{cmd} :lnfile :{cmd} etc. Otherwise it works the same as :ldo.

    FILTERING A QUICKFIX OR LOCATION LIST: cfilter-plugin :Cfilter :Lfilter If you have too many entries in a quickfix list, you can use the cfilter plugin to reduce the number of entries. Load the plugin with:

    packadd cfilter\n

    Then you can use the following commands to filter a quickfix/location list:

    :Cfilter[!] /{pat}/\n:Lfilter[!] /{pat}/\n

    The |:Cfilter| command creates a new quickfix list from the entries matching {pat} in the current quickfix list. {pat} is a Vim |regular-expression| pattern. Both the file name and the text of the entries are matched against {pat}. If the optional ! is supplied, then the entries not matching {pat} are used. The pattern can be optionally enclosed using one of the following characters: ', \", /. If the pattern is empty, then the last used search pattern is used.

    The |:Lfilter| command does the same as |:Cfilter| but operates on the current location list.

    The current quickfix/location list is not modified by these commands, so you can go back to the unfiltered list using the |:colder|/|:lolder| command.

    ============================================================================= 2. The error window quickfix-window

                        *:cope* *:copen* *w:quickfix_title*\n

    :cope[n] [height] Open a window to show the current list of errors.

            When [height] is given, the window becomes that high\n        (if there is room).  When [height] is omitted the\n        window is made ten lines high.\n\n        If there already is a quickfix window, it will be made\n        the current window.  It is not possible to open a\n        second quickfix window.  If [height] is given the\n        existing window will be resized to it.\n\n                        *quickfix-buffer*\n        The window will contain a special buffer, with\n        'buftype' equal to \"quickfix\".  Don't change this!\n        The window will have the w:quickfix_title variable set\n        which will indicate the command that produced the\n        quickfix list. This can be used to compose a custom\n        status line if the value of 'statusline' is adjusted\n        properly. Whenever this buffer is modified by a\n        quickfix command or function, the |b:changedtick|\n        variable is incremented.  You can get the number of\n        this buffer using the getqflist() and getloclist()\n        functions by passing the \"qfbufnr\" item. For a\n        location list, this buffer is wiped out when the\n        location list is removed.\n\n                        *:lop* *:lopen*\n

    :lop[en] [height] Open a window to show the location list for the current window. Works only when the location list for the current window is present. You can have more than one location window opened at a time. Otherwise, it acts the same as \":copen\".

                            *:ccl* *:cclose*\n

    :ccl[ose] Close the quickfix window.

                            *:lcl* *:lclose*\n

    :lcl[ose] Close the window showing the location list for the current window.

                            *:cw* *:cwindow*\n

    :cw[indow] [height] Open the quickfix window when there are recognized errors. If the window is already open and there are no recognized errors, close the window.

                            *:lw* *:lwindow*\n

    :lw[indow] [height] Same as \":cwindow\", except use the window showing the location list for the current window.

                            *:cbo* *:cbottom*\n

    :cbo[ttom] Put the cursor in the last line of the quickfix window and scroll to make it visible. This is useful for when errors are added by an asynchronous callback. Only call it once in a while if there are many updates to avoid a lot of redrawing.

                            *:lbo* *:lbottom*\n

    :lbo[ttom] Same as \":cbottom\", except use the window showing the location list for the current window.

    Normally the quickfix window is at the bottom of the screen. If there are vertical splits, it's at the bottom of the rightmost column of windows. To make it always occupy the full width: :botright cwindow You can move the window around with |window-moving| commands. For example, to move it to the top: CTRL-W K The 'winfixheight' option will be set, which means that the window will mostly keep its height, ignoring 'winheight' and 'equalalways'. You can change the height manually (e.g., by dragging the status line above it with the mouse).

    In the quickfix window, each line is one error. The line number is equal to the error number. The current entry is highlighted with the QuickFixLine highlighting. You can change it to your liking, e.g.: :hi QuickFixLine ctermbg=Yellow guibg=Yellow

    You can use \":.cc\" to jump to the error under the cursor. Hitting the key or double-clicking the mouse on a line has the same effect. The file containing the error is opened in the window above the quickfix window. If there already is a window for that file, it is used instead. If the buffer in the used window has changed, and the error is in another file, jumping to the error will fail. You will first have to make sure the window contains a buffer which can be abandoned.

    When you select a file from the quickfix window, the following steps are used to find a window to edit the file:

    1. If a window displaying the selected file is present in the current tabpage (starting with the window before the quickfix window), then that window is used.
    2. If the above step fails and if 'switchbuf' contains \"usetab\" and a window displaying the selected file is present in any one of the tabpages (starting with the first tabpage) then that window is used.
    3. If the above step fails then a window in the current tabpage displaying a buffer with 'buftype' not set (starting with the window before the quickfix window) is used.
    4. If the above step fails and if 'switchbuf' contains \"uselast\", then the previously accessed window is used.
    5. If the above step fails then the window before the quickfix window is used. If there is no previous window, then the window after the quickfix window is used.
    6. If the above step fails, then a new horizontally split window above the quickfix window is used.
                  *CTRL-W_<Enter>* *CTRL-W_<CR>*\n

      You can use CTRL-W to open a new window and jump to the error there.

      When the quickfix window has been filled, two autocommand events are triggered. First the 'filetype' option is set to \"qf\", which triggers the FileType event (also see |qf.vim|). Then the BufReadPost event is triggered, using \"quickfix\" for the buffer name. This can be used to perform some action on the listed errors. Example: au BufReadPost quickfix setlocal modifiable \\ | silent exe 'g/^/s//\\=line(\".\") .. \" \"/' \\ | setlocal nomodifiable This prepends the line number to each line. Note the use of \"\\=\" in the substitute string of the \":s\" command, which is used to evaluate an expression. The BufWinEnter event is also triggered, again using \"quickfix\" for the buffer name.

      Note: When adding to an existing quickfix list the autocommand are not triggered.

      Note: Making changes in the quickfix window has no effect on the list of errors. 'modifiable' is off to avoid making changes. If you delete or insert lines anyway, the relation between the text and the error number is messed up. If you really want to do this, you could write the contents of the quickfix window to a file and use \":cfile\" to have it parsed and used as the new error list.

                          *location-list-window*\n

      The location list window displays the entries in a location list. When you open a location list window, it is created below the current window and displays the location list for the current window. The location list window is similar to the quickfix window, except that you can have more than one location list window open at a time. When you use a location list command in this window, the displayed location list is used.

      When you select a file from the location list window, the following steps are used to find a window to edit the file:

      1. If a non-quickfix window associated with the location list is present in the current tabpage, then that window is used.
      2. If the above step fails and if the file is already opened in another window in the current tabpage, then that window is used.
      3. If the above step fails and 'switchbuf' contains \"usetab\" and if the file is opened in a window in any one of the tabpages, then that window is used.
      4. If the above step fails then a window in the current tabpage showing a buffer with 'buftype' not set is used.
      5. If the above step fails, then the file is edited in a new window.

      In all of the above cases, if the location list for the selected window is not yet set, then it is set to the location list displayed in the location list window.

                              *quickfix-window-ID*\n

      You can use the |getqflist()| and |getloclist()| functions to obtain the window ID of the quickfix window and location list window respectively (if present). Examples: echo getqflist({'winid' : 1}).winid echo getloclist(2, {'winid' : 1}).winid

                              *getqflist-examples*\n

      The |getqflist()| and |getloclist()| functions can be used to get the various attributes of a quickfix and location list respectively. Some examples for using these functions are below:

      \" get the title of the current quickfix list\n:echo getqflist({'title' : 0}).title\n\n\" get the identifier of the current quickfix list\n:let qfid = getqflist({'id' : 0}).id\n\n\" get the identifier of the fourth quickfix list in the stack\n:let qfid = getqflist({'nr' : 4, 'id' : 0}).id\n\n\" check whether a quickfix list with a specific identifier exists\n:if getqflist({'id' : qfid}).id == qfid\n\n\" get the index of the current quickfix list in the stack\n:let qfnum = getqflist({'nr' : 0}).nr\n\n\" get the items of a quickfix list specified by an identifier\n:echo getqflist({'id' : qfid, 'items' : 0}).items\n\n\" get the number of entries in a quickfix list specified by an id\n:echo getqflist({'id' : qfid, 'size' : 0}).size\n\n\" get the context of the third quickfix list in the stack\n:echo getqflist({'nr' : 3, 'context' : 0}).context\n\n\" get the number of quickfix lists in the stack\n:echo getqflist({'nr' : '$'}).nr\n\n\" get the number of times the current quickfix list is changed\n:echo getqflist({'changedtick' : 0}).changedtick\n\n\" get the current entry in a quickfix list specified by an identifier\n:echo getqflist({'id' : qfid, 'idx' : 0}).idx\n\n\" get all the quickfix list attributes using an identifier\n:echo getqflist({'id' : qfid, 'all' : 0})\n\n\" parse text from a List of lines and return a quickfix list\n:let myList = [\"a.java:10:L10\", \"b.java:20:L20\"]\n:echo getqflist({'lines' : myList}).items\n\n\" parse text using a custom 'efm' and return a quickfix list\n:echo getqflist({'lines' : ['a.c#10#Line 10'], 'efm':'%f#%l#%m'}).items\n\n\" get the quickfix list window id\n:echo getqflist({'winid' : 0}).winid\n\n\" get the quickfix list window buffer number\n:echo getqflist({'qfbufnr' : 0}).qfbufnr\n\n\" get the context of the current location list\n:echo getloclist(0, {'context' : 0}).context\n\n\" get the location list window id of the third window\n:echo getloclist(3, {'winid' : 0}).winid\n\n\" get the location list window buffer number of the third window\n:echo getloclist(3, {'qfbufnr' : 0}).qfbufnr\n\n\" get the file window id of a location list window (winnr: 4)\n:echo getloclist(4, {'filewinid' : 0}).filewinid\n\n                        *setqflist-examples*\n

      The |setqflist()| and |setloclist()| functions can be used to set the various attributes of a quickfix and location list respectively. Some examples for using these functions are below:

      \" create an empty quickfix list with a title and a context\n:let t = 'Search results'\n:let c = {'cmd' : 'grep'}\n:call setqflist([], ' ', {'title' : t, 'context' : c})\n\n\" set the title of the current quickfix list\n:call setqflist([], 'a', {'title' : 'Mytitle'})\n\n\" change the current entry in the list specified by an identifier\n:call setqflist([], 'a', {'id' : qfid, 'idx' : 10})\n\n\" set the context of a quickfix list specified by an identifier\n:call setqflist([], 'a', {'id' : qfid, 'context' : {'val' : 100}})\n\n\" create a new quickfix list from a command output\n:call setqflist([], ' ', {'lines' : systemlist('grep -Hn main *.c')})\n\n\" parse text using a custom efm and add to a particular quickfix list\n:call setqflist([], 'a', {'id' : qfid,\n    \\ 'lines' : [\"a.c#10#L10\", \"b.c#20#L20\"], 'efm':'%f#%l#%m'})\n\n\" add items to the quickfix list specified by an identifier\n:let newItems = [{'filename' : 'a.txt', 'lnum' : 10, 'text' : \"Apple\"},\n        \\ {'filename' : 'b.txt', 'lnum' : 20, 'text' : \"Orange\"}]\n:call setqflist([], 'a', {'id' : qfid, 'items' : newItems})\n\n\" empty a quickfix list specified by an identifier\n:call setqflist([], 'r', {'id' : qfid, 'items' : []})\n\n\" free all the quickfix lists in the stack\n:call setqflist([], 'f')\n\n\" set the title of the fourth quickfix list\n:call setqflist([], 'a', {'nr' : 4, 'title' : 'SomeTitle'})\n\n\" create a new quickfix list at the end of the stack\n:call setqflist([], ' ', {'nr' : '$',\n        \\ 'lines' : systemlist('grep -Hn class *.java')})\n\n\" create a new location list from a command output\n:call setloclist(0, [], ' ', {'lines' : systemlist('grep -Hn main *.c')})\n\n\" replace the location list entries for the third window\n:call setloclist(3, [], 'r', {'items' : newItems})\n

      ============================================================================= 3. Using more than one list of errors quickfix-error-lists

      So far has been assumed that there is only one list of errors. Actually the ten last used lists are remembered. When starting a new list, the previous ones are automatically kept. Two commands can be used to access older error lists. They set one of the existing error lists as the current one.

                          *:colder* *:col* *E380*\n

      :col[der] [count] Go to older error list. When [count] is given, do this [count] times. When already at the oldest error list, an error message is given.

                          *:lolder* *:lol*\n

      :lol[der] [count] Same as :colder, except use the location list for the current window instead of the quickfix list.

                          *:cnewer* *:cnew* *E381*\n

      :cnew[er] [count] Go to newer error list. When [count] is given, do this [count] times. When already at the newest error list, an error message is given.

                          *:lnewer* *:lnew*\n

      :lnew[er] [count] Same as :cnewer, except use the location list for the current window instead of the quickfix list.

                          *:chistory* *:chi*\n

      :[count]chi[story] Show the list of error lists. The current list is marked with \">\". The output looks like: error list 1 of 3; 43 errors :make > error list 2 of 3; 0 errors :helpgrep tag error list 3 of 3; 15 errors :grep ex_help *.c

              When [count] is given, then the count'th quickfix\n        list is made the current list. Example:\n            \" Make the 4th quickfix list current\n            :4chistory\n\n                    *:lhistory* *:lhi*\n

      :[count]lhi[story] Show the list of location lists, otherwise like :chistory.

      When adding a new error list, it becomes the current list.

      When \":colder\" has been used and \":make\" or \":grep\" is used to add a new error list, one newer list is overwritten. This is especially useful if you are browsing with \":grep\" |grep|. If you want to keep the more recent error lists, use \":cnewer 99\" first.

      To get the number of lists in the quickfix and location list stack, you can use the |getqflist()| and |getloclist()| functions respectively with the list number set to the special value '$'. Examples: echo getqflist({'nr' : '$'}).nr echo getloclist(3, {'nr' : '$'}).nr To get the number of the current list in the stack: echo getqflist({'nr' : 0}).nr

      ============================================================================= 4. Using :make :make_makeprg

                              *:mak* *:make*\n

      :mak[e][!] [arguments] 1. All relevant |QuickFixCmdPre| autocommands are executed. 2. If the 'autowrite' option is on, write any changed buffers 3. An errorfile name is made from 'makeef'. If 'makeef' doesn't contain \"##\", and a file with this name already exists, it is deleted. 4. The program given with the 'makeprg' option is started (default \"make\") with the optional [arguments] and the output is saved in the errorfile (for Unix it is also echoed on the screen). 5. The errorfile is read using 'errorformat'. 6. All relevant |QuickFixCmdPost| autocommands are executed. See example below. 7. If [!] is not given the first error is jumped to. 8. The errorfile is deleted. 9. You can now move through the errors with commands like |:cnext| and |:cprevious|, see above. This command does not accept a comment, any \" characters are considered part of the arguments. If the encoding of the program output differs from the 'encoding' option, you can use the 'makeencoding' option to specify the encoding.

                              *:lmak* *:lmake*\n

      :lmak[e][!] [arguments] Same as \":make\", except the location list for the current window is used instead of the quickfix list.

      The \":make\" command executes the command given with the 'makeprg' option. This is done by passing the command to the shell given with the 'shell' option. This works almost like typing

      \":!{makeprg} [arguments] {shellpipe} {errorfile}\".\n

      {makeprg} is the string given with the 'makeprg' option. Any command can be used, not just \"make\". Characters '%' and '#' are expanded as usual on a command-line. You can use \"%<\" to insert the current file name without extension, or \"#<\" to insert the alternate file name without extension, for example: :set makeprg=make\\ #<.o

      [arguments] is anything that is typed after \":make\". {shellpipe} is the 'shellpipe' option. {errorfile} is the 'makeef' option, with ## replaced to make it unique.

      The placeholder \"$\" can be used for the argument list in {makeprg} if the command needs some additional characters after its arguments. The $ is replaced then by all arguments. Example: :set makeprg=latex\\ \\\\nonstopmode\\ \\\\input\\{$} or simpler :let &mp = 'latex \\nonstopmode \\input{$}' \"$\" can be given multiple times, for example: :set makeprg=gcc\\ -o\\ $\\ $*

      The 'shellpipe' option defaults to \"2>&1| tee\" for Win32. This means that the output of the compiler is saved in a file and not shown on the screen directly. For Unix \"| tee\" is used. The compiler output is shown on the screen and saved in a file the same time. Depending on the shell used \"|& tee\" or \"2>&1| tee\" is the default, so stderr output will be included.

      If 'shellpipe' is empty, the {errorfile} part will be omitted. This is useful for compilers that write to an errorfile themselves.

      Using QuickFixCmdPost to fix the encoding

      It may be that 'encoding' is set to an encoding that differs from the messages your build program produces. This example shows how to fix this after Vim has read the error messages:

      function QfMakeConv()\n   let qflist = getqflist()\n   for i in qflist\n      let i.text = iconv(i.text, \"cp936\", \"utf-8\")\n   endfor\n   call setqflist(qflist)\nendfunction\n\nau QuickfixCmdPost make call QfMakeConv()\n

      (Example by Faque Cheng) Another option is using 'makeencoding'.

      "},{"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":"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.

      • 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

      Pre-requisite: multi-modal editing

      Multi-modal Editing is a recommended pre-requisite

      Aliases to run Clojure REPL - Practicalli Clojure CLI Config

      Practicalli Clojure CLI config contains aliases used to start a Clojure REPL and other development tools. Aliases are used extensively through the Clojure sections of this book.

      Practicalli Neovim config replaces some key bindings

      Practicalli Neovim Config replaces several key bindings to make them consistent with other Clojure editors

      "},{"location":"repl-driven-development/#references","title":"References","text":"
      • Which Clojure CLI 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.

      Paste Evaluation result

      \" C p to paste the contents of the C register into the current buffer.

      The result of every Conjure evaluation is stored in the C register when using Practicalli AstroNvim Config.

      "},{"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/documentation/","title":"Documentation","text":"

      K or Space l h shows the documentation for the function under the cursor in a popup window.

      K a second time to jump the cursor to the popup window to scroll the text if required (or use a mouse wheel)

      "},{"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.

      "},{"location":"repl-driven-development/refactor-tools/#function-documentation","title":"Function documentation","text":"

      K or Space l h show the doc-string for function or any other var under the cursor.

      Repeat the key binding to move the cursor to the documentation popup window and use j k to scroll the documentation

      , l l code lens refresh

      , l L code lens run

      "},{"location":"repl-driven-development/refactor-tools/#navigation","title":"Navigation","text":"

      g d go to definition of current symbol, e.g. function definition

      , l G telescope search of all symbols in the project

      , l R telescope search of all references in the project

      , l s telescope search of symbols

      , l s split view of symbols

      "},{"location":"repl-driven-development/refactor-tools/#diagnostics","title":"Diagnostics","text":"

      Space l d show popup for current diagnostic indicator

      Space l D search through all diagnostics reports

      "},{"location":"repl-driven-development/refactor-tools/#code-actions","title":"Code Actions","text":"

      Space l r rename current symbol (namespace rename not supported by LSP client)

      Space l a code actions (popup with available actions)

      Space l f format buffer

      "},{"location":"repl-driven-development/refactor-tools/#troubleshooting","title":"Troubleshooting","text":"

      Space l i shows the LSP server information for the current filetype, e.g. Clojure

      Space l I shows format and lint tools supported by null-ls for the current filetype, e.g. clojure

      "},{"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":"source-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 (requires lazygit cli tool)
      • Neogit rich 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":"source-control/#common-git-actions","title":"Common Git actions","text":""},{"location":"source-control/#initialise-local-repository","title":"Initialise local repository\"","text":"

      Space t f opens floating terminal window in the current root directory root (use :cd to change the root directory).

      git init .\n
      "},{"location":"source-control/#stage-change-in-buffer","title":"Stage change in buffer","text":"

      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

      "},{"location":"source-control/#git-status","title":"Git Status","text":"

      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

      "},{"location":"source-control/#github-issues-pull-requests","title":"GitHub Issues & Pull Requests","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":"source-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":"source-control/diff/#nvimdiff","title":"nvimdiff","text":"

      The Git difftool can specify Neovim as a diff viewer to show Git diff views of all the files that have changes

      nvimdiff as a command line option

      git difftool --tool=nvimdiff <optional-filename>\n

      git difftool can be configured to use Neovim

      Git client config to set nvimdiff as difftool

      ~/.config/git/config
      [diff]\n  # Neovim diff tool\n  tool = nvimdiff\n

      Run git difftool in the root of the project to show the diff of each changed file.

      git difftool <optional-filename>\n

      : q a to close the current diff view. The command line prompts to open the next file as a diff view (assuming there are more files to view).

      "},{"location":"source-control/diff/#diffview","title":"DiffView","text":"

      DiffView compares working space and staged changes side by side, or a diff for git merge conflicts.

      AstroNvimPracticalli Neovim Config

      Space g d or d in neogit status buffer (SPC g s) will open diffview in a new tab

      [ c to move to previous hunk

      ] c to move to next hunk

      Space g to return to neovim buffer or q to return to neogit status buffer

      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

      • Green - added lines
      • Yellow - changed line
      • Red - deleted lines
      "},{"location":"source-control/lazygit/","title":"Lazygit version control","text":"Command Line or AstroNvim configuration

      Lazygit interface not provided by Practicalli Neovim Config Redux

      "},{"location":"source-control/lazygit/#requirements","title":"Requirements","text":"

      Install lazygit command line tool

      "},{"location":"source-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":"source-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":"source-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":"source-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":"source-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":"source-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":"source-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":"source-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":"source-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":"source-control/neogit/#modify-git-commit-history","title":"Modify Git commit history","text":"

      r opens the rebase menu

      "},{"location":"source-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":"source-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":"source-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":"source-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

      "},{"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 -L -O https://github.com/clojure/brew-install/releases/latest/download/linux-install.sh && \\\nchmod +x linux-install.sh && \\\n./linux-install.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 calling clojure with the --help option, which shows the options available to the command

      clojure --help\n

      Run a Clojure REPL session from a Clojure project configured with a deps.edn file

      clojure -M:repl/rebel\n

      optionally install rlwrap package if using the basic REPL terminal UI with the clj wrapper script

      "},{"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 9.5 is currenlyt available as a Termux package

      pkg install neovim\n
      "},{"location":"termux/neovim/#neovim-treesitter","title":"Neovim treesitter","text":"

      Treesitter provides excellent language syntax parsing and highlighting performance, allowing any Neovim package to benefit.

      The nvim-treesitter package is included in the practicalli/astro configuration.

      "},{"location":"termux/neovim/#c-compiler","title":"C Compiler","text":"

      Install C compiler to compile the 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.

      "}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index ace2ccc2..58ac9892 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,298 +2,298 @@ https://practical.li/neovim/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/api-tools/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/assets/images/social/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/install/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/install/multiple-configurations/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/install/neovide/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/install/neovim/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/install/terminal-tools/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/introduction/features/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/introduction/repl-workflow/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/comments/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/file-buffer-window-tab/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/multi-modal-editing/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/multiple-cursors/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/navigation/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/notifications/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/plugin-manager/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/registers/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/snippets/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/spell-check/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/terminal/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/zen-mode/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/search-replace/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/search-replace/spectre/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/neovim-basics/search-replace/substitute/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/fennel/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/configuration/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/configuration/astrocommunity/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/configuration/practicalli/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/configuration/practicalli/config-design/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/configuration/practicalli/packer/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/configuration/practicalli/packages/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/configuration/practicalli/packages/lualine/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/configuration/practicalli/packages/nvim-treesitter/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/lua-language/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/case/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/g-menu/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/key-binding-reference/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/motions/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/moving-around/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/narrowing/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/speaking-vim/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/vim-quick-reference/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/vim-tips-for-developers/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/visual-select/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/modal-editing/z-menu/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/neovim/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/neovim/changelist/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/neovim/jumplist/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/neovim/language-providers/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/neovim/quickfix/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/reference/neovim/standard-path/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/repl-driven-development/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/repl-driven-development/conjure/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/repl-driven-development/documentation/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/repl-driven-development/refactor-tools/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/repl-driven-development/structural-editing/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/repl-driven-development/testing/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/source-control/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/source-control/diff/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/source-control/lazygit/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/source-control/neogit/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/source-control/octo/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/source-control/open-in-github/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/termux/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/termux/clojure-development/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/termux/custom-shell/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/termux/fdroid-install/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/termux/git/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/termux/neovim/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/termux/setup/ - 2024-09-18 + 2024-09-19 https://practical.li/neovim/termux/using-termux/ - 2024-09-18 + 2024-09-19 \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 037835bad126f1497bcc8ee129efa927e117d76d..65c4a282dcb933857f07630971c6dc31366da00e 100644 GIT binary patch delta 760 zcmV(zR>fZ$?_p}${#|Mt~b_bG4Aq*um*;`rP^GHe)X&-K1st{yx1BUJZz}#(nN4UoMo%-VB{3;AIM^P< zX3?Sb^Acbnwq8l;P&{MuU|b9x_9a`EIY>G%(_;&Y$_E|Y40*s{y@mr|;2hiH#&K_d zIRPEw0Kwwpd4kapVOV>d*M+|K|8n#Nr#AESX|f9jssv*iWHbl_D~BBB78%-h(7xdJJZ;L9%+*B+1YtNqAQ^ z2L((Cbi)ZH@ZQMM)a^AfUNfyG!wZCeF^YleaDdHjXU1e}T}>o1PaNl}h{~22x$w+T z86@>e83?i}3jw^A_IH&*9T3uej^iS!1mx#BnBHVXv^t>EH>L%`KGcVotlQ6>r~j5~ z+83yo%opo1K*fY%46PEi%^hRplQU}X_9-hrs zie9-lzhtUF8=^vabs6R`n#kr@LR$w?usO$LHU1^*S-T%?H2db_C89AL|0wA8wax4) zPhcX`#Vkve1NfL`ubeN#kz`s!;H5sP1L;LIU~24_|DoOOB%^~zVr7uWGNcMHUKcnf z<>@Fz&wI`dQ=sYaNg0FKhSuhP)+Ecjxml7oZN>wH*Pu4;?biVz%lF5Up$?cfx-#CV zY&3j~Boj%5B^@ao%w1w4&c(5mTxylX$6O3FKMci^-E?}*IeJyyEq0wMfVVHtJ+dl; zv}z+naadh|B%Xo6h#_`m<`dKLe4{+6=yX1gxkN9?y>b-dI2hW&+%MHHoB_HvM{JGC qdp&1_*?sV=SEDF6t0v%*R5TYF>-+!pyy+r;V)GM5r1Gi`C;$NNmuhwZ delta 760 zcmVb_^JyWUv4hjy^ttoVZN^?mx=GnOMrZxX zV-p}AaA@wDQR4R>SmGhJo9p%UXS2RFS2rSZZaZmc-c`S&RbC7gkrpFc(l@B_)8S;R^dJPA_z&Wb zbYQt;&_u|PygA0a?|eMY%W=AxttE7%soKS1fWWE@9ZFQ#mac{x|&F2o;c1`5tS`5a^abw zGDzx`G7w}{76N!J?e8jsIv}L`9LGgc3CPcNFulo&XmvoRZ%hk>eW(vFS+}1%Pya2~ zv@cLEnJ?C3fQkvj7+NKy%iLqu8)Y$+@iz2DptKkiYnMw9&Qc}j=#A98r4E*VJv^JO z6uok9e#umUHbjN;>N3n>G?C4*gtiW(U~`VgYWz#qvvxn)X!gy;OGINh{!!5FYn$0q zp1?$=i&>T`2kAxzs9&kGU9Vei(`+yXo|rbM&gZTkJYj0B>KOdt_Ax zY1KxE;;^~^Njw9C5ku_C%qOPf`9^tC(dm2~bBSJ(d*vv^aWJ%lxnHU;IRkWUj@TNN q_j=9