Skip to content

📦 Practicalli Astro Config Designλ︎

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

AstroCommunity Plugin Configurations used where available

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

Under review after migration to AstroNvim 4

Files overviewλ︎

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

Key - AstroNvim template file changes

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

  • unchanged
  • changed
  • added
  • config not activated (comment if statement to activate)

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

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

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

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

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

  • astrocore.lua, astrolsp.lua, astroui.lua examples of overriding AstroNvim defaults
  • clojure.lua alternative approach to configure clojure, extending the AstroNvim Clojure pack
  • github.lua issue & PR management with octo.nvim (requires GitHub CLI)
  • mason.lua ensure tools are installed by default (LSP servers, format & lint tools, DAP debug tools)
  • neo-tree.lua visual file navigator - example config
  • none-ls.lua example config for format & lint tools
  • platuml.lua UML diagrams defined with code - requires plantuml.com install
  • snippets.lua load JSON style snippet definitions
  • telescope.lua ensure Treesitter languages are installed (AstroCommunity language packs also ensure parsers installed)
  • treesittter.lua ensure Treesitter languages are installed (AstroCommunity language packs also ensure parsers installed)
  • user.lua example user configuration, added via lua/plugins/user-practicalli.lua
  • user-practicalli.lua theme, dashboard & key binding preferences enjoyed by Practicalli
  • user-termux.lua mason lsp server overrides, pinned plugin versions for neovim 0.9.x

Disable Pluginsλ︎

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

Disable parinfer and sexp plugins

lua/plugins/user-practicalli.lua
  -- ----------------------------------------------
  { "nvim-parinfer", enabled = false },
  { "nvim-treesitter-sexp", enabled = false },
  -- ----------------------------------------------

Clojure supportλ︎

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

The pack contains 4 Neovim plugins:

  • conjure REPL client to evaluate code
  • nvim-parinfer code indenting structural editing
  • nvim-treesitter-sexp paredit (slurp/barf etc) structural editing
  • ts-comment.nvim Clojure comment patterns

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

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

-- Packs
-- Treesitter: clojure , Lsp: clojure-lsp, Lint/format:
{ import = "astrocommunity.pack.clojure" },
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 {
  "AstroNvim/astrocommunity",
  { import = "astrocommunity.pack.clojure" },
  { "gpanders/nvim-parinfer", enabled = false },

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 {
  "AstroNvim/astrocommunity",
  { import = "astrocommunity.pack.clojure" },
  {
    "AstroNvim/astrocore",
    opts = {
      options = {
        g = {
          -- show HUD REPL log at startup
          ["conjure#log#hud#enabled"] = false,

          -- Hightlight evaluated forms
          -- ["conjure#highlight#enabled"] = true,

          -- Trim log after number of lines. Default: `10000`
          -- ["conjure#log#trim#at"] = 200,
          -- Trim log to number of lines. Default: `7000`
          -- ["conjure#log#trim#to"] = 100,

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

          -- Test runner: "clojure", "clojuresCRipt", "kaocha"
          ["conjure#client#clojure#nrepl#test#runner"] = "kaocha",
        },
      },
    },
  },
}
Config comment for parinfer

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

{
  "gpanders/nvim-parinfer",
  filetype = { "clojure" },
  config = function()
    vim.g.parinfer_force_balance = true
    vim.g.parinfer_comment_chars = ";;"
  end,
},

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"
-- Lazy Package manager configuration
return {
  {
    "Olical/conjure",
    -- load plugin on filetypes
    ft = { "clojure", "fennel" },
  },
}
```

Improve syntax highlighting by installing the Clojure parser for Treesitter.

Treesitter Parser for clojure in AstroNvim user configuration

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

Manual install of Treesitter Clojure Parser

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

Switch to Parinfer Parens mode for Paredit structural editing

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

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

plugins/community.lua
  {
    "gpanders/nvim-parinfer",
    ft = { "clojure" },
    config = function()
      vim.g.parinfer_force_balance = true
      vim.g.parinfer_comment_chars = ";;"
      vim.g.parinfer_mode = "paren"
    end,
  },

Clojure Mappingsλ︎

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

AstroNvim 3.17.0 has localleader

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

Set localleader in user config

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

.config/astronvim-config/options.lua
-- set vim options here (vim.<first_key>.<second_key> = value)
return {
  opt = {
    -- set to true or false etc.
    relativenumber = true, -- sets vim.opt.relativenumber
    number = true,         -- sets vim.opt.number
    spell = false,         -- sets vim.opt.spell
    signcolumn = "auto",   -- sets vim.opt.signcolumn to auto
    wrap = false,          -- sets vim.opt.wrap
  },
  g = {
    mapleader = " ",                 -- sets vim.g.mapleader
    maplocalleader = ",",            -- Set local leader key binding (supports Conjure key bindings)
    autoformat_enabled = true,       -- enable or disable auto formatting at start (lsp.formatting.format_on_save must be enabled)
    cmp_enabled = true,              -- enable completion at start
    autopairs_enabled = true,        -- enable autopairs at start
    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)
    icons_enabled = true,            -- disable icons in the UI (disable if no nerd font is available, requires :PackerSync after changing)
    ui_notifications_enabled = true, -- disable notifications when toggling UI elements
    VM_leader = "gm"                 -- Visual Multi Leader (multiple cursors)
  },
}

Clojure LSPλ︎

Clojure LSP support is enabled via the AstroCommunity Clojure pack.

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

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

Snippetsλ︎

The AstroNvim user example includes a commented LuaSnip configuration

LuaSnip with json format snippets in snippets/ directory

.config/astronvim-config/plugins/core.lua
return {
  --LuaSnip with json format snippets in `snippets/` directory
  {
    "L3MON4D3/LuaSnip",
    config = function(plugin, opts)
      require "astronvim.plugins.configs.luasnip"(plugin, opts) -- include the default astronvim config that calls the setup call
      -- add more custom luasnip configuration such as filetype extend or custom snippets
      require("luasnip.loaders.from_vscode").lazy_load { paths = { "./snippets" } } -- include JSON style snippets
      local luasnip = require "luasnip"
      luasnip.filetype_extend("javascript", { "javascriptreact" })
    end,
  },
}

AstroNvim Community packagesλ︎

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

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

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

AstroNvim Community Packages in AstroNvim user configuration

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

AstroCommunity packs set up support for each language

Language packs enabled in Practicalli AstroNvim Config

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

Themesλ︎

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

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

AstroCommunity themes

Configure Lazy pluginsλ︎

🌐 Lazy.nvim Plugin specification

Config Format and Lint toolsλ︎

Disable format on save when tools provide unexpected results

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

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

Mason is responsible for installing lint and format tools

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

🌐 null-ls built-in configuration

Override config file unconsistent

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

Override null-ls builtin configuration

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

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

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

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

Override Key bindingλ︎

AstroNvim uses Lazy package manager to set keys for packages.

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

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

Override Key bindings for vim highlighter
.config/astronvim-config/plugins/community.lua
{
    "vim-highlighter",
    keys = function()
        return {
            { "<leader>nn", "<cmd>Hi><CR>", desc = "Next Recently Set Highlight" },
            { "<leader>ng", "<cmd>Hi<<CR>", desc = "Previous Recently Set Highlight" },
            { "<leader>n[", "<cmd>Hi{<CR>", desc = "Next Nearest Highlight" },
            { "<leader>n]", "<cmd>Hi}<CR>", desc = "Previous Nearest Highlight" },
        }
    end,
}

Plugin Key bindingλ︎

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
  ,,,
else