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 @@
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 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 @@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
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 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.httpGET http://localhost:8080/system-admin/status\n
A new window opens with the result of the API call
Result of API call with rest.nvimGET 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.
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
# 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-findnvim-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
DebianMacOSXDownload 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 toolxclip
x11 clipboard as a provider for Neovim copy/paste (Linux only)luarocks
for LSP servers (AstroNvim)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.jsAstroNvim 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 Homebrewapt 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 SourceDownload 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:
libintl
and\u00a0gettext
\u00a0(e.g. via\u00a0brew install libintl gettext
)xattr -c ./nvim-macos.tar.gz
\u00a0(to avoid \"unknown developer\" warning)mkdir -P ~/.local/apps\n
tar zvxf nvim-macos.tar.gz -C ~/.local/apps/\n
~/.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 PackagesInstall 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 displayUse 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.
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":"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 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 PluginsLinters 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":"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
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.
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.
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.
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 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)
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
: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
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
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.
: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
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
Windows can be active (contains the cursor), hidden (open but not shown) or inactive.
\\
creates an horizontal split
SPC q
removes the current split
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
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
Practice speaking evil with these examples
Keybinding Descriptionc 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
)
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
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.
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.
ysiw*
surrounds current word with *
to create italic text, .
repeats to make bold text style.
ds*
removes *
from current word.
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 ReduxSpace 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
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 ReduxSelect 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
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
\\ \\
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
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.
\\ \\ /
followed by a regex pattern will create a selection with that pattern.
n
and N
finds the next occurrence of the regex pattern
gc
In extend-mode will use smartcase to change a selection
\\ \\ f
filter out (remove) regions based on pattern or expression.
C-x
to cycle filtering method:
\\ \\ 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
visual-multi supports vim motions although they behave differently as their result is dependent on the mode:
cursor mode
will move cursorsextend mode
motions extend selectionsUnless 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 / changegu
/ gU
to change text caseVisual-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:
ysiw(
to enclose in parenthesescr_
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|.
\\ \\ 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.
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
lowercaseU
UPPERCASEC
Captializet
Title Casec
camelCaseP
PascalCases
snake_caseS
SNAKE_UPPERCASE-
dash-case.
dot.case<space>
space casecursor-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
cursor-mode commands expect a motion, e.g. c
should be followed by a text object to be changed.
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).
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-surroundR
replace pattern in regions\\\\s
split regions by pattern\\\\e
transform regions text with vim expressionSome commands enforce cursor-mode when run from extend-mode:
<C-A>
increase numbers<C-X>
decrease numbersOthers 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.Move the cursor one space at a time
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 forward3w\n
f jumps forward in the current line to the given character
jump to next q characterfq\n
F jumps backward in the current line to the given character
jump to previous [ characterF[\n
t jumps forward in the current line to before the given character
jump before q charactertq\n
T jumps backward in the current line to after the given character
jump after [ characterT[\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 lines12j\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
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
:changes
shows the Neovim changelist containing all points in the current buffer which have changed
/ searches buffer for the following pattern
AstroNvim user config enables incsearch
incremental search and hlsearch
to highlight every search match
: 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 screentimeout
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 5Practicalli 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 recommendedPracticalli 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
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 ConjureWhen 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
LuaSnip can use several different sources for snippets
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
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
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
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
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
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
: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)
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:
*
to select all matching occurances:%s//replace-text/g
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:
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 availablePlugin 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
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 defaultsclojure.lua
alternative approach to configure clojure, extending the AstroNvim Clojure packgithub.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 confignone-ls.lua
example config for format & lint toolsplatuml.lua
UML diagrams defined with code - requires plantuml.com installsnippets.lua
load JSON style snippet definitionstelescope.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 Practicalliuser-termux.lua
mason lsp server overrides, pinned plugin versions for neovim 0.9.xPracticalli 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 pluginsEdit 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.luareturn {\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
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
{\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 release sets localleader
to ,
so a separate setting is not required in the user configuration (unless a different localleader is preferred)
options.lua
in the user configuration provides a consistent way to set Neovim options.
-- 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
-- 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
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.luareturn {\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.
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
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
{\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)\"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 Configsgit 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":"fnl/config/init.fnl
fnl/config/init.fnl
","text":"config.plugin
config.util
namespace to streamline key binding definitionsspace
and local-leader as ,
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
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 finderfnl/config/plugin/treesitter.fnl
","text":"Defines which language parsers and modules to use.
clojure
, fennel
and markdown
parsers (and compile on first run of Neovim)(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
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.
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 lineAny 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:
setup
or config
function for setting package optionsThis 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 versionsclojure
, 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.
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":"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
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
)
~
Changes the case of current characterguu
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 lineg~w
Invert case to current WORDguG
Change to lowercase until the end of document.gU)
Change until end of sentence to upper casegu}
Change to end of paragraph to lower casegU5j
Change 5 lines below to upper casegu3k
Change 3 lines above to lower caseg` 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)
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).
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.
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.
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 downk
move upl
move right (often used to move down a path or tree, e.g. a directory path):
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)
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
: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.
:help NarrowRegion
to view the documetation on the NrrwRgn plug use
:NRM
is described as experimental by the project readme.
Neovim is easier to learn and gain much more benefit from if you learn to speak commands as sentences.
First learn some verbs:
c
changed
deleteg
go,v
visual selecty
yank (copy)Then use those verbs with some modifiers
'
mark{ }
beginning/end of paragraph0
start of line^
first non white-space character of line$
end of linea
aroundf
find (includes character)i
inside a range (e.g. word, paren,)s
surroundt
till (move just before specified character)Then learn the text objects you can apply verbs and modifiers too
b
block/parenthesesp
paragraph,s
sentencet
tag e.g. html/xmlw
wordPractice speaking evil with these examples
Keybinding Descriptionc 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.
In Normal mode you can keep your fingers resting on the main row of your keyboard to move around.
Key actionj
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.
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 Actioni
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.
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.
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 Actionr
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
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.
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.
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 / directoryR
replaceTAB
selects files and directories, allowing for commands (i.e. rename) to be done in batch mode (acting on all selected files / directories)
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:
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 ActionSPC 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
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 lineg c c
comment linev (select) g c
comment regiong c 9 j
comment 9 lines from current, downwardsv 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
viw
to visual-select in (within) the current word
g D
open 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
zc
and zo
are useful to close and open folds, which can be a nice way of focusing on certain pieces of code.
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
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
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 Descriptionz 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 Descriptionz 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":"Initial draft - feedback welcome
:help :changelist\n
View changelist
:changes\n
Initial draft - feedback welcome
:help :jumplist\n
View jumplist
:jumps\n
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
-- 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
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
:cc 7\n
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:
*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:
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.
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 bindingsPracticalli Neovim Config replaces several key bindings to make them consistent with other Clojure editors
"},{"location":"repl-driven-development/#references","title":"References","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.
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 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.
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.
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 LeiningenNeovim 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.
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":"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.
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 defaultpracticalli/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
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 ConfigPracticalli 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
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
:!
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
[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 ConfigSpace 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
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 LineSPC 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
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 branchc
- create a new branchd
- delete a branch, D
deletes local and remote branchl
- checkout a remote branch and create a local tracking branchm
- rename an existing local branchn
- create a new branchs
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
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.
Z
to open the stash menu
z
to stash the working copy and staged files (index)
i
to only stash the staged files (index)
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
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.
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
r
opens the rebase menu
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
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
Visit clojure-lsp GitHub releases page and download the clojure-lsp
file
chmod 755 clojure-lsp
./clojure-lsp --version
- should print clojure-lsp version and clj-kondo versionmv clojure-lsp $PATH
If the practicalli/clojure-lsp-config repository was cloned, move or link the clojure-lsp
directory to ~/.config/clojure-lsp
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.
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 starting
zsh.
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.
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
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
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.
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.
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 shellsource ~/.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.
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 binarygit
- clone configuration files and projects (see Git version control section)openssh
- SSH service and tools to generate SSH keyspkg 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 keyboarddefault-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).
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 applicationsReset
the terminal if it gets stuck or Hangup
to exit the current terminal sessionStyle
the terminal by selecting a font and a color schemeThe navigation drawer is shown by swiping inwards from the left of the screen
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 centerapt update
updates the list of packages fromhe software centerapt list --upgradable
shows list of packages with new versionsapt upgrade
install new versions of currently installed packagesapt-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 descriptionpkg
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)
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 tabF3
to select previous tabF4
to select next tabbyobu-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.
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
Use the search box to quickly find a specific topic
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 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.httpGET http://localhost:8080/system-admin/status\n
A new window opens with the result of the API call
Result of API call with rest.nvimGET 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.
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
# 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-findnvim-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
DebianMacOSXDownload 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 toolxclip
x11 clipboard as a provider for Neovim copy/paste (Linux only)luarocks
for LSP servers (AstroNvim)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.jsAstroNvim 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 Homebrewapt 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 SourceDownload 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:
libintl
and\u00a0gettext
\u00a0(e.g. via\u00a0brew install libintl gettext
)xattr -c ./nvim-macos.tar.gz
\u00a0(to avoid \"unknown developer\" warning)mkdir -P ~/.local/apps\n
tar zvxf nvim-macos.tar.gz -C ~/.local/apps/\n
~/.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 PackagesInstall 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 displayUse 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.
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":"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 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 PluginsLinters 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":"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
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.
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.
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.
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 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)
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
: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
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
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.
: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
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
Windows can be active (contains the cursor), hidden (open but not shown) or inactive.
\\
creates an horizontal split
SPC q
removes the current split
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
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
Practice speaking evil with these examples
Keybinding Descriptionc 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
)
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
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.
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.
ysiw*
surrounds current word with *
to create italic text, .
repeats to make bold text style.
ds*
removes *
from current word.
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 ReduxSpace 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
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 ReduxSelect 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
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
\\ \\
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
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.
\\ \\ /
followed by a regex pattern will create a selection with that pattern.
n
and N
finds the next occurrence of the regex pattern
gc
In extend-mode will use smartcase to change a selection
\\ \\ f
filter out (remove) regions based on pattern or expression.
C-x
to cycle filtering method:
\\ \\ 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
visual-multi supports vim motions although they behave differently as their result is dependent on the mode:
cursor mode
will move cursorsextend mode
motions extend selectionsUnless 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 / changegu
/ gU
to change text caseVisual-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:
ysiw(
to enclose in parenthesescr_
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|.
\\ \\ 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.
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
lowercaseU
UPPERCASEC
Captializet
Title Casec
camelCaseP
PascalCases
snake_caseS
SNAKE_UPPERCASE-
dash-case.
dot.case<space>
space casecursor-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
cursor-mode commands expect a motion, e.g. c
should be followed by a text object to be changed.
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).
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-surroundR
replace pattern in regions\\\\s
split regions by pattern\\\\e
transform regions text with vim expressionSome commands enforce cursor-mode when run from extend-mode:
<C-A>
increase numbers<C-X>
decrease numbersOthers 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.Move the cursor one space at a time
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 forward3w\n
f jumps forward in the current line to the given character
jump to next q characterfq\n
F jumps backward in the current line to the given character
jump to previous [ characterF[\n
t jumps forward in the current line to before the given character
jump before q charactertq\n
T jumps backward in the current line to after the given character
jump after [ characterT[\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 lines12j\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
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
:changes
shows the Neovim changelist containing all points in the current buffer which have changed
/ searches buffer for the following pattern
AstroNvim user config enables incsearch
incremental search and hlsearch
to highlight every search match
: 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 screentimeout
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 5Practicalli 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 recommendedPracticalli 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
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 ConjureWhen 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
LuaSnip can use several different sources for snippets
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
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
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
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
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
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
: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)
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:
*
to select all matching occurances:%s//replace-text/g
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:
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 availablePlugin 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
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 defaultsclojure.lua
alternative approach to configure clojure, extending the AstroNvim Clojure packgithub.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 confignone-ls.lua
example config for format & lint toolsplatuml.lua
UML diagrams defined with code - requires plantuml.com installsnippets.lua
load JSON style snippet definitionstelescope.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 Practicalliuser-termux.lua
mason lsp server overrides, pinned plugin versions for neovim 0.9.xPracticalli 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 pluginsEdit 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.luareturn {\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
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
{\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 release sets localleader
to ,
so a separate setting is not required in the user configuration (unless a different localleader is preferred)
options.lua
in the user configuration provides a consistent way to set Neovim options.
-- 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
-- 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
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.luareturn {\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.
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
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
{\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)\"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 Configsgit 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":"fnl/config/init.fnl
fnl/config/init.fnl
","text":"config.plugin
config.util
namespace to streamline key binding definitionsspace
and local-leader as ,
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
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 finderfnl/config/plugin/treesitter.fnl
","text":"Defines which language parsers and modules to use.
clojure
, fennel
and markdown
parsers (and compile on first run of Neovim)(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
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.
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 lineAny 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:
setup
or config
function for setting package optionsThis 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 versionsclojure
, 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.
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":"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
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
)
~
Changes the case of current characterguu
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 lineg~w
Invert case to current WORDguG
Change to lowercase until the end of document.gU)
Change until end of sentence to upper casegu}
Change to end of paragraph to lower casegU5j
Change 5 lines below to upper casegu3k
Change 3 lines above to lower caseg` 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)
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).
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.
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.
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 downk
move upl
move right (often used to move down a path or tree, e.g. a directory path):
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)
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
: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.
:help NarrowRegion
to view the documetation on the NrrwRgn plug use
:NRM
is described as experimental by the project readme.
Neovim is easier to learn and gain much more benefit from if you learn to speak commands as sentences.
First learn some verbs:
c
changed
deleteg
go,v
visual selecty
yank (copy)Then use those verbs with some modifiers
'
mark{ }
beginning/end of paragraph0
start of line^
first non white-space character of line$
end of linea
aroundf
find (includes character)i
inside a range (e.g. word, paren,)s
surroundt
till (move just before specified character)Then learn the text objects you can apply verbs and modifiers too
b
block/parenthesesp
paragraph,s
sentencet
tag e.g. html/xmlw
wordPractice speaking evil with these examples
Keybinding Descriptionc 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.
In Normal mode you can keep your fingers resting on the main row of your keyboard to move around.
Key actionj
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.
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 Actioni
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.
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.
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 Actionr
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
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.
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.
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 / directoryR
replaceTAB
selects files and directories, allowing for commands (i.e. rename) to be done in batch mode (acting on all selected files / directories)
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:
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 ActionSPC 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
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 lineg c c
comment linev (select) g c
comment regiong c 9 j
comment 9 lines from current, downwardsv 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
viw
to visual-select in (within) the current word
g D
open 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
zc
and zo
are useful to close and open folds, which can be a nice way of focusing on certain pieces of code.
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
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
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 Descriptionz 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 Descriptionz 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":"Initial draft - feedback welcome
:help :changelist\n
View changelist
:changes\n
Initial draft - feedback welcome
:help :jumplist\n
View jumplist
:jumps\n
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
-- 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
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
:cc 7\n
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:
*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:
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.
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 bindingsPracticalli Neovim Config replaces several key bindings to make them consistent with other Clojure editors
"},{"location":"repl-driven-development/#references","title":"References","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.
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 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.
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.
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 LeiningenNeovim 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.
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":"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.
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 defaultpracticalli/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
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 ConfigPracticalli 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
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
:!
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
[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 ConfigSpace 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
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 LineSPC 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
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 branchc
- create a new branchd
- delete a branch, D
deletes local and remote branchl
- checkout a remote branch and create a local tracking branchm
- rename an existing local branchn
- create a new branchs
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
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.
Z
to open the stash menu
z
to stash the working copy and staged files (index)
i
to only stash the staged files (index)
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
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.
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
r
opens the rebase menu
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
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
Visit clojure-lsp GitHub releases page and download the clojure-lsp
file
chmod 755 clojure-lsp
./clojure-lsp --version
- should print clojure-lsp version and clj-kondo versionmv clojure-lsp $PATH
If the practicalli/clojure-lsp-config repository was cloned, move or link the clojure-lsp
directory to ~/.config/clojure-lsp
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.
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 starting
zsh.
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.
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
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
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.
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.
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 shellsource ~/.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.
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 binarygit
- clone configuration files and projects (see Git version control section)openssh
- SSH service and tools to generate SSH keyspkg 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 keyboarddefault-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).
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 applicationsReset
the terminal if it gets stuck or Hangup
to exit the current terminal sessionStyle
the terminal by selecting a font and a color schemeThe navigation drawer is shown by swiping inwards from the left of the screen
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 centerapt update
updates the list of packages fromhe software centerapt list --upgradable
shows list of packages with new versionsapt upgrade
install new versions of currently installed packagesapt-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 descriptionpkg
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)
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 tabF3
to select previous tabF4
to select next tabbyobu-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.
RPEw0Kwwpd4kapVOV>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%46PE i%^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 zcmV b_^JyWUv4hjy^ttoVZN^?mx=GnOMrZxX zV-p}AaA@wDQR4R>SmGhJo9p%UXS2RFS2rSZZaZmc-c `S&RbC7gkrpFc(l@B_)8S;R^dJPA_z&W b 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`2k Axzs9&kGU9Vei(`+yXo|rbM&gZTkJYj0B>KOdt_Ax zY1KxE;;^~^Njw9C5ku_C%qOPf`9^tC(dm2~bBSJ(d*vv^aWJ%lxnHU;IRkWUj@TNN q_j=9