├── snippets ├── global.json ├── clojure.json ├── package.json ├── lua.json └── markdown.json ├── neovim.yml ├── .github ├── config │ ├── devskim.json │ ├── secretlintrc.json │ ├── markdown-link-check.json │ ├── gitleaks.toml │ ├── lychee.toml │ ├── megalinter.yaml │ └── markdown-lint.jsonc ├── CODEOWNERS ├── pull_request_template.md └── workflows │ ├── changelog-check.yaml │ ├── scheduled-version-check.yaml │ ├── scheduled-stale-check.yaml │ └── megalinter.yaml ├── selene.toml ├── .stylua.toml ├── ftdetect └── bb.vim ├── .neoconf.json ├── .gitignore ├── init.lua ├── after └── ftplugin │ └── clojure.lua ├── lua ├── lazy_setup.lua ├── plugins │ ├── none-ls.lua │ ├── termux.lua │ └── practicalli.lua └── community.lua ├── CHANGELOG.md └── README.md /snippets/global.json: -------------------------------------------------------------------------------- 1 | {} 2 | 3 | -------------------------------------------------------------------------------- /neovim.yml: -------------------------------------------------------------------------------- 1 | --- 2 | base: lua51 3 | 4 | globals: 5 | vim: 6 | any: true 7 | -------------------------------------------------------------------------------- /.github/config/devskim.json: -------------------------------------------------------------------------------- 1 | { 2 | "Globs": [ 3 | ".github/**" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Codeowners 2 | 3 | # Default owner accounts for the current repository 4 | # Automatically added as a reviewr to all pull requests (not including drafts) 5 | 6 | * @practicalli-johnny 7 | -------------------------------------------------------------------------------- /selene.toml: -------------------------------------------------------------------------------- 1 | std = "neovim" 2 | 3 | [rules] 4 | global_usage = "allow" 5 | if_same_then_else = "allow" 6 | incorrect_standard_library_use = "allow" 7 | mixed_table = "allow" 8 | multiple_statements = "allow" 9 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 120 2 | line_endings = "Unix" 3 | indent_type = "Spaces" 4 | indent_width = 2 5 | quote_style = "AutoPreferDouble" 6 | call_parentheses = "None" 7 | collapse_simple_statement = "Always" 8 | -------------------------------------------------------------------------------- /ftdetect/bb.vim: -------------------------------------------------------------------------------- 1 | " Quick hack to set Babashka files as Clojure filetype 2 | " https://neovim.io/doc/user/filetype.html#ftdetect 3 | " 4 | " Alternative solutions welcome 5 | " 6 | " TODO: consider a lua solution 7 | " TODO: contribute bb support for clojure to Neovim (vim) 8 | 9 | au BufRead,BufNewFile *.bb set filetype=clojure 10 | -------------------------------------------------------------------------------- /.neoconf.json: -------------------------------------------------------------------------------- 1 | { 2 | "neodev": { 3 | "library": { 4 | "enabled": true, 5 | "plugins": true 6 | } 7 | }, 8 | "neoconf": { 9 | "plugins": { 10 | "lua_ls": { 11 | "enabled": true 12 | } 13 | } 14 | }, 15 | "lspconfig": { 16 | "lua_ls": { 17 | "Lua.format.enable": false 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/config/secretlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": [ 3 | { 4 | "id": "@secretlint/secretlint-rule-basicauth", 5 | "options": { 6 | "allows": [ 7 | "hostname.domain.com", 8 | "jdbc:postgresql://:port/?user=&password=", 9 | "postgres://postgres://username:password@hostname.domain.com:1234/database-name" 10 | ] 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.github/config/markdown-link-check.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignorePatterns": [ 3 | { 4 | "pattern": "^http://localhost" 5 | }, 6 | { 7 | "pattern": "^mailto:*" 8 | }, 9 | { 10 | "pattern": "^#*" 11 | }, 12 | { 13 | "pattern": "^https://127.0.0.0/" 14 | } 15 | ], 16 | "timeout": "20s", 17 | "retryOn429": true, 18 | "retryCount": 5, 19 | "fallbackRetryDelay": "30s", 20 | "aliveStatusCodes": [ 21 | 200, 22 | 206 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /.github/config/gitleaks.toml: -------------------------------------------------------------------------------- 1 | title = "gitleaks config" 2 | 3 | [allowlist] 4 | description = "global allow lists" 5 | paths = [ 6 | '''gitleaks.toml''', 7 | '''(.*?)(jpg|gif|doc|docx|zip|xls|pdf|bin|svg|socket)$''', 8 | '''(go.mod|go.sum)$''', 9 | '''gradle.lockfile''', 10 | '''node_modules''', 11 | '''package-lock.json''', 12 | '''pnpm-lock.yaml''', 13 | '''Database.refactorlog''', 14 | '''vendor''', 15 | ] 16 | 17 | [[rules]] 18 | description = "AWS Example API Key" 19 | id = "aws-example-api-key" 20 | regex = '''AKIAIOSFODNN7EXAMPLE''' 21 | keywords = [ 22 | "awstoken", 23 | ] 24 | -------------------------------------------------------------------------------- /snippets/clojure.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment header": { 3 | "prefix": "comment-header", 4 | "body": [ 5 | ";; ---------------------------------------------------------\n;; ${1:Heading summary title}\n;;\n;; ${2:Brief description}\n;; ---------------------------------------------------------\n\n$0" 6 | ], 7 | "description": "Comment Header" 8 | }, 9 | "comment section": { 10 | "prefix": "comment-section", 11 | "body": [ 12 | ";; ---------------------------------------------------------\n;; ${1:Section title}\n\n$0\n\n\n;; End of $1\n;; ---------------------------------------------------------\n\n" 13 | ], 14 | "description": "Comment Header" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /snippets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "practicalli-snippets", 3 | "engines": { 4 | "vscode": "^1.11.0" 5 | }, 6 | "contributes": { 7 | "snippets": [ 8 | { 9 | "language": [ 10 | "markdown", 11 | "global", 12 | "all" 13 | ], 14 | "comment": "snippets accross several languages", 15 | "path": "./global.json" 16 | }, 17 | { 18 | "language": "clojure", 19 | "path": "./clojure.json" 20 | }, 21 | { 22 | "language": "lua", 23 | "path": "./lua.json" 24 | }, 25 | { 26 | "language": "markdown", 27 | "path": "./markdown.json" 28 | } 29 | ] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ------------------------ 2 | # Lua Project Git Ignore file patterns 3 | # 4 | # Ignore all except patterns starting with ! 5 | # Add comments on separate lines, not same line as pattern 6 | # ------------------------ 7 | 8 | # ------------------------ 9 | # Ignore everything in root directory 10 | /* 11 | # ------------------------ 12 | 13 | # ------------------------ 14 | # Common project files 15 | !CHANGELOG.md 16 | !README.md 17 | !Makefile 18 | # ------------------------ 19 | 20 | # ------------------------ 21 | # Include Lua project & config 22 | !after/ 23 | !ftdetect/ 24 | !lua/ 25 | !snippets/ 26 | !.neoconf.json 27 | !.stylua.toml 28 | !init.lua 29 | !neovim.yml 30 | !selene.toml 31 | # ------------------------ 32 | 33 | # ------------------------ 34 | # Include Git & CI workflow 35 | !.gitattributes 36 | !.gitignore 37 | !.github/ 38 | # ------------------------ 39 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | -- This file simply bootstraps the installation of Lazy.nvim and then calls other files for execution 2 | -- This file doesn't necessarily need to be touched, BE CAUTIOUS editing this file and proceed at your own risk. 3 | local lazypath = vim.env.LAZY or vim.fn.stdpath "data" .. "/lazy/lazy.nvim" 4 | if not (vim.env.LAZY or (vim.uv or vim.loop).fs_stat(lazypath)) then 5 | -- stylua: ignore 6 | vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath }) 7 | end 8 | vim.opt.rtp:prepend(lazypath) 9 | 10 | -- validate that lazy is available 11 | if not pcall(require, "lazy") then 12 | -- stylua: ignore 13 | vim.api.nvim_echo({ { ("Unable to load lazy from: %s\n"):format(lazypath), "ErrorMsg" }, { "Press any key to exit...", "MoreMsg" } }, true, {}) 14 | vim.fn.getchar() 15 | vim.cmd.quit() 16 | end 17 | 18 | require "lazy_setup" 19 | -- require "polish" 20 | -------------------------------------------------------------------------------- /after/ftplugin/clojure.lua: -------------------------------------------------------------------------------- 1 | -- Clojure specific configuration 2 | -- Loads after clojure filetype set 3 | 4 | local whichkey = require "which-key" 5 | 6 | return { 7 | { 8 | "folke/which-key.nvim", 9 | -- Define Conjure Groups only for Clojure filetypes 10 | whichkey.add { 11 | -- Conjure sub-menus 12 | { "c", group = "Connect" }, 13 | { "e", group = "Evaluate" }, 14 | { "ec", group = "Comment" }, 15 | { "g", group = "Go" }, 16 | { "l", group = "REPl Log" }, 17 | { "r", group = "Refresh" }, 18 | { "s", group = "Session" }, 19 | { "t", group = "Test" }, 20 | { "v", group = "Values" }, 21 | { "x", group = "macroXpand" }, 22 | -- Structural Editing 23 | { "p", "ParinferToggle", desc = "Toggle Parinfer", mode = "n" }, 24 | }, 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /.github/config/lychee.toml: -------------------------------------------------------------------------------- 1 | # ---------------------------------------- 2 | # Base URL or website root directory to check relative URLs. 3 | base = "https://practical.li/clojure/" 4 | 5 | # Only test links with the given schemes (e.g. https). 6 | # Omit to check links with any other scheme. 7 | # At the moment, we support http, https, file, and mailto. 8 | scheme = ["https"] 9 | 10 | # ---------------------------------------- 11 | # Exclusions 12 | 13 | # Exclude URLs and mail addresses from checking (supports regex). 14 | exclude = ['^https://www\.linkedin\.com', 15 | '^https://www\.parkrun\.org\.uk', 16 | '^https://github\.com\/search*', 17 | '^https://packages\.debian\.org', 18 | '^https://practicalli\.grafana\.net', 19 | '^https://127.0.0.0'] 20 | 21 | # Exclude these filesystem paths from getting checked. 22 | exclude_path = ["mkdocs.yml", "overrides", "includes", ".github", ".git"] 23 | 24 | # Exclude all private IPs from checking. 25 | # Equivalent to setting `exclude_private`, `exclude_link_local`, and 26 | # `exclude_loopback` to true. 27 | exclude_all_private = true 28 | 29 | # Check mail addresses 30 | include_mail = false 31 | # ---------------------------------------- 32 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | :memo: Description 2 | 3 | 4 | :white_check_mark: Checklist 5 | 6 | - [ ] Commits should be cryptographically signed (SSH or GPG) 7 | 8 | 9 | ## Practicalli Guidelines 10 | 11 | Please follow these guidelines when submitting a pull request 12 | 13 | - refer to issues using `#` followed by the issue number (or paste full link to the issue) 14 | - PR should contain the smallest possible change 15 | - PR should contain a very specific change 16 | - PR should contain only a single commit (squash your commits locally if required) 17 | - Avoid multiple changes across multiple files (raise an issue so we can discuss) 18 | - Avoid a long list of spelling or grammar corrections. These take too long to review and cherry pick. 19 | 20 | ## Submitting articles 21 | 22 | [Create an issue using the article template](https://github.com/practicalli/blog-content/issues/new?assignees=&labels=article&template=article.md&title=Suggested+article+title), 23 | providing as much detail as possible. 24 | 25 | ## Website design 26 | 27 | Suggestions about website design changes are most welcome, especially in terms of usability and accessibility. 28 | 29 | Please raise an issue so we can discuss changes first, especially changes related to aesthetics. 30 | 31 | ## Review process 32 | 33 | All pull requests are reviewed by @practicalli-johnny and feedback provided, usually the same day but please be patient. 34 | -------------------------------------------------------------------------------- /.github/workflows/changelog-check.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Check CHANGELOG.md file updated for every pull request 3 | 4 | name: Changelog Check 5 | on: 6 | pull_request: 7 | paths-ignore: 8 | - "README.md" 9 | types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled] 10 | 11 | jobs: 12 | changelog: 13 | name: Changelog Update Check 14 | runs-on: ubuntu-24.04 15 | steps: 16 | - run: echo "🚀 Job automatically triggered by ${{ github.event_name }}" 17 | - run: echo "🐧 Job running on ${{ runner.os }} server" 18 | - run: echo "🐙 Using ${{ github.ref }} branch from ${{ github.repository }} repository" 19 | 20 | # Git Checkout 21 | - name: Checkout Code 22 | uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | sparse-checkout: | 26 | docs 27 | overrides 28 | .github 29 | CHANGELOG.md 30 | - run: echo "🐙 Sparse Checkout of ${{ github.repository }} repository to the CI runner." 31 | 32 | # Changelog Enforcer 33 | - name: Changelog Enforcer 34 | uses: dangoslen/changelog-enforcer@v3 35 | with: 36 | changeLogPath: "CHANGELOG.md" 37 | skipLabels: "skip-changelog-check" 38 | 39 | # Summary and status 40 | - run: echo "🎨 Changelog Enforcer quality checks completed" 41 | - run: echo "🍏 Job status is ${{ job.status }}." 42 | -------------------------------------------------------------------------------- /lua/lazy_setup.lua: -------------------------------------------------------------------------------- 1 | require("lazy").setup({ 2 | { 3 | "AstroNvim/AstroNvim", 4 | version = "^5", -- Remove version tracking to elect for nightly AstroNvim 5 | import = "astronvim.plugins", 6 | opts = { -- AstroNvim options must be set here with the `import` key 7 | mapleader = " ", -- This ensures the leader key must be configured before Lazy is set up 8 | maplocalleader = ",", -- This ensures the localleader key must be configured before Lazy is set up 9 | icons_enabled = true, -- Set to false to disable icons (if no Nerd Font is available) 10 | pin_plugins = nil, -- Default will pin plugins when tracking `version` of AstroNvim, set to true/false to override 11 | update_notifications = true, -- Enable/disable notification about running `:Lazy update` twice to update pinned plugins 12 | }, 13 | }, 14 | { import = "community" }, 15 | { import = "plugins" }, 16 | } --[[@as LazySpec]], { 17 | -- Configure any other `lazy.nvim` configuration options here 18 | install = { colorscheme = { "astrotheme", "catppuccin" } }, 19 | ui = { backdrop = 100 }, 20 | performance = { 21 | rtp = { 22 | -- disable some rtp plugins, add more to your liking 23 | disabled_plugins = { 24 | "gzip", 25 | "netrwPlugin", 26 | "tarPlugin", 27 | "tohtml", 28 | -- "zipPlugin", -- enabled to access jar files 29 | }, 30 | }, 31 | }, 32 | } --[[@as LazyConfig]]) 33 | -------------------------------------------------------------------------------- /lua/plugins/none-ls.lua: -------------------------------------------------------------------------------- 1 | -- --------------------------------------------------------- 2 | -- Configure format & lint tools 3 | -- 4 | -- Ensure tools are installed via Mason 5 | -- Pass configuration files to each tool 6 | -- --------------------------------------------------------- 7 | 8 | -- if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE 9 | 10 | -- INFO: Config in this file skipped if `PRACTICALLI_NONELS_CONFIG` environment variable is not set to true 11 | local nonels_config = vim.env.PRACTICALLI_NONELS_CONFIG 12 | if nonels_config ~= "true" then return {} end 13 | 14 | ---@type LazySpec 15 | return { 16 | -- use mason-lspconfig to configure LSP installations 17 | -- use mason-null-ls to configure Formatters/Linter installation for null-ls sources 18 | { 19 | "jay-babu/mason-null-ls.nvim", 20 | -- overrides `require("mason-null-ls").setup(...)` 21 | opts = function(_, opts) 22 | -- add more things to the ensure_installed table protecting against community packs modifying it 23 | opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { 24 | "markdownlint", 25 | -- add more arguments for adding more null-ls sources 26 | }) 27 | opts.handlers = { 28 | markdownlint = function(source_name, methods) 29 | local null_ls = require "null-ls" 30 | null_ls.register(null_ls.builtins.diagnostics.markdownlint.with { 31 | -- extra_args = { "--config", "~/.config/markdownlint.yaml" }, 32 | extra_args = { "--config", "~/.config/markdown-lint.jsonc" }, 33 | }) 34 | end, 35 | } 36 | end, 37 | }, 38 | } 39 | -------------------------------------------------------------------------------- /.github/workflows/scheduled-version-check.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # ------------------------------------------ 3 | # Scheduled check of versions 4 | # - use as non-urgent report on versions 5 | # - Uses POSIX Cron syntax 6 | # - Minute [0,59] 7 | # - Hour [0,23] 8 | # - Day of the month [1,31] 9 | # - Month of the year [1,12] 10 | # - Day of the week ([0,6] with 0=Sunday) 11 | # 12 | # Using liquidz/anta to check: 13 | # - GitHub workflows 14 | # - deps.edn 15 | # ------------------------------------------ 16 | 17 | name: "Scheduled Version Check" 18 | on: 19 | schedule: 20 | # - cron: "0 4 * * *" # at 04:04:04 ever day 21 | # - cron: "0 4 * * 5" # at 04:04:04 ever Friday 22 | - cron: "0 4 1 * *" # at 04:04:04 on first day of month 23 | workflow_dispatch: # Run manually via GitHub Actions Workflow page 24 | 25 | jobs: 26 | scheduled-version-check: 27 | name: "Scheduled Version Check" 28 | runs-on: ubuntu-24.04 29 | steps: 30 | - run: echo "🚀 Job automatically triggered by ${{ github.event_name }}" 31 | - run: echo "🐧 Job running on ${{ runner.os }} server" 32 | - run: echo "🐙 Using ${{ github.ref }} branch from ${{ github.repository }} repository" 33 | 34 | - name: Checkout Code 35 | uses: actions/checkout@v4 36 | with: 37 | fetch-depth: 0 38 | sparse-checkout: | 39 | .github 40 | - run: echo "🐙 ${{ github.repository }} repository sparse-checkout to the CI runner." 41 | - name: "Antq Check versions" 42 | uses: liquidz/antq-action@main 43 | with: 44 | excludes: "" 45 | skips: "boot clojure-cli pom shadow-cljs leiningen" 46 | 47 | # Summary 48 | - run: echo "🎨 library versions checked with liquidz/antq" 49 | - run: echo "🍏 Job status is ${{ job.status }}." 50 | -------------------------------------------------------------------------------- /lua/plugins/termux.lua: -------------------------------------------------------------------------------- 1 | -- ------------------------------------------ 2 | -- Termux (Android) Overrides 3 | -- 4 | -- Use local LSP language servers as mason fails to install 5 | -- Clojure LSP server 6 | -- Lua Language server 7 | -- ------------------------------------------ 8 | 9 | -- ------------------------------------------ 10 | -- INFO: conditional loads if `OS_TERMUX` is true 11 | local termux = vim.env.OS_TERMUX 12 | if not termux then return {} end 13 | -- ------------------------------------------ 14 | 15 | -- ------------------------------------------ 16 | ---@type LazySpec 17 | return { 18 | { 19 | "WhoIsSethDaniel/mason-tool-installer.nvim", 20 | -- INFO: prevent Mason loading Clojure & Lua LSP servers 21 | -- overrides `require("mason-tool-installer").setup(...)` 22 | -- Language server names found in `:Mason` 23 | opts = { 24 | ensure_installed = { 25 | -- Conditional install of language servers 26 | "lua-language-server", 27 | "clojure-lsp", 28 | condition = function() return not termux end, 29 | }, 30 | }, 31 | }, 32 | { 33 | "AstroNvim/astrolsp", 34 | ---@type AstroLSPOpts 35 | -- INFO: Use local Clojure & Lua LSP servers 36 | opts = { 37 | -- Configuration table of features provided by AstroLSP 38 | features = { 39 | autoformat = true, -- enable or disable auto formatting on start 40 | codelens = true, -- enable/disable codelens refresh on start 41 | inlay_hints = false, -- enable/disable inlay hints on start 42 | semantic_tokens = true, -- enable/disable semantic token highlighting 43 | }, 44 | -- Use local servers (not mason installed) 45 | servers = { 46 | -- "pyright" 47 | "clojure-lsp", 48 | "lua-language-server", 49 | }, 50 | }, 51 | }, 52 | } 53 | -- ------------------------------------------ 54 | -------------------------------------------------------------------------------- /.github/workflows/scheduled-stale-check.yaml: -------------------------------------------------------------------------------- 1 | # ---------------------------------------- 2 | # Scheduled stale issue & pull request check 3 | # 4 | # Adds 'stale' label after a set piece of time, 5 | # then closes stale issues & pull requests a short period after 6 | # 7 | # Using "Close Stale Issues" action 8 | # https://github.com/marketplace/actions/close-stale-issues 9 | # ---------------------------------------- 10 | 11 | name: 'Scheduled stale check' 12 | on: 13 | workflow_dispatch: 14 | schedule: 15 | - cron: "0 1 1 * *" # at 01:00 on first day of month 16 | 17 | jobs: 18 | stale: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - run: echo "🚀 Job automatically triggered by ${{ github.event_name }}" 22 | - run: echo "🐧 Job running on ${{ runner.os }} server" 23 | - run: echo "🐙 Using ${{ github.ref }} branch from ${{ github.repository }} repository" 24 | 25 | - uses: actions/stale@v9 26 | with: 27 | stale-issue-message: 'After 30 days with no activity, the issue was automatically marked stale. Remove stale label or add a comment to prevent the issue being closed in 5 days.' 28 | stale-pr-message: 'After 45 days with no activity, the Pull Request was automatically marked stale. Remove stale label or comment to prevent the PR being closed in 10 days.' 29 | close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.' 30 | close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.' 31 | days-before-issue-stale: 30 32 | days-before-pr-stale: 45 33 | days-before-issue-close: 5 34 | days-before-pr-close: 10 35 | start-date: '2025-04-05T00:00:00Z' # only affect issues/PRs from date created (ISO 8601 or RFC 2822 format) 36 | any-of-labels: 'future,keep' # labels to keep 37 | exempt-issue-assignees: 'practicalli-johnny' 38 | exempt-pr-assignees: 'practicalli-johnny' 39 | 40 | # Summary 41 | - run: echo "🎨 Issues & Pull Request checked with actions/stale" 42 | - run: echo "🍏 Job status is ${{ job.status }}." 43 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Unreleased 2 | 3 | ## Added 4 | - none-ls: use configuration file for markdown lint cli 5 | 6 | # 2025-07-03 7 | 8 | ## Added 9 | - community: add rainbow-delimiters with theme support 10 | - community: add color picker ccc-nvim 11 | - community: add emoji completion blink-cmp-emoji 12 | - community: add advanced surround nvim-surround 13 | - community: add search & replace grug-far-nvim 14 | - ftdetect: set *.bb files as clojure filetype #49 15 | 16 | ## Changed 17 | - practicalli: revert to upstream other.nvim 18 | - practicalli: remove parpar in favor of clojure pack 19 | - dev: ci scheduled stale issue & pr check (monthly) 20 | - practicalli: snacks notifier wrap text 21 | 22 | # 2025-04-24 23 | 24 | ## Added 25 | - readme: describe purpose & use of project 26 | - dev: ci workflows including stylua & stale actions 27 | - dev: git ignore inclusive patterns 28 | - community: neogit plugin rich git client 29 | - community: clojure pack & sub-menu descriptions 30 | - practicalli: personal preferences with conditional skip 31 | - practicalli: startup dashboard logo 32 | - community: proffered plugins from astrocommunity 33 | - colorscheme: load and set catppuccin as theme 34 | - snippets: include vscode snippets from practicalli astro 35 | - practicalli: neovim & plugin preferences, custom key maps 36 | - termux: use locally installed lsp servers 37 | - snippets: comment header & section snippets for lua 38 | - practicalli: toggle between Clojure src and test files 39 | - practicalli: showkeys visualise key presses in neovim 40 | - community: neovide GUI recipe from Astrocommunity 41 | - snippets: neovim api examples in lua from folke/dots 42 | - practicalli: git related key mappings (neogit, gist-nvim) 43 | - ftplugin: parinfer toggle key map for clojure 44 | - practicalli: notifier log level WARN 45 | - practicalli: buffer tab navigation key mappings 46 | 47 | ## Changed 48 | - lazy: enable zipPlugin to view src inside jar files 49 | - community: picker-lsp-mappings recipe replaces custom code 50 | - practicalli: disable snacks indent guides by default 51 | - community: remove gitlinker-nvim (replaced by snack gitbrowse) 52 | - practicalli: configure showkeys for lazy loading 53 | - practicalli: configure trim for lazy loading 54 | - practicalli: configure other for lazy loading 55 | - practicalli: disable default_mappings in better-escape (#32) 56 | - config: remove unused files from astronvim template 57 | - practicalli: use other-nvim from astrocommunity 58 | - practicalli: rename user-practicalli.lua to practicalli.lua 59 | - practicalli: use other.nvim from practicalli fork (until pr merged) 60 | - community: include parpar.nvim until Astrocommunity Clojure pack updated 61 | - practicalli: vertical split for other-nvim `,tS` key map 62 | - practicalli: fix troubleshoot options for conjure 63 | - community: remove parpar-nvim in favour of clojure pack 64 | -------------------------------------------------------------------------------- /snippets/lua.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment header": { 3 | "prefix": "comment-header", 4 | "body": [ 5 | "-- ---------------------------------------------------------\n-- ${1:Heading summary title}\n--\n-- ${2:Brief description}\n-- ---------------------------------------------------------\n\n$0" 6 | ], 7 | "description": "Comment Header" 8 | }, 9 | "comment section": { 10 | "prefix": "comment-section", 11 | "body": [ 12 | "-- ---------------------------------------------------------\n-- ${1:Section title}\n\n$0\n\n\n-- End of $1\n-- ---------------------------------------------------------\n\n" 13 | ], 14 | "description": "Comment Header" 15 | }, 16 | "Create Auto Command": { 17 | "prefix": "autocmd", 18 | "body": [ 19 | "vim.api.nvim_create_autocmd(\"${1:event}\", {", 20 | " group = vim.api.nvim_create_augroup(\"${2:group}\", { clear = true }),", 21 | " callback = function(ev)", 22 | " ${0}", 23 | " end", 24 | "})" 25 | ] 26 | }, 27 | "Create Auto Command Group": { 28 | "prefix": "augroup", 29 | "body": [ 30 | "vim.api.nvim_create_augroup(\"${1:group}\", { clear = true })$0" 31 | ] 32 | }, 33 | "Current Win": { 34 | "prefix": "win", 35 | "body": "local win = vim.api.nvim_get_current_win()\n$0" 36 | }, 37 | "Current Buf": { 38 | "prefix": "buf", 39 | "body": "local buf = vim.api.nvim_get_current_buf()\n$0" 40 | }, 41 | "Buf Valid": { 42 | "prefix": "bufvalid", 43 | "body": "vim.api.nvim_buf_is_valid(${1:buf})" 44 | }, 45 | "Win Valid": { 46 | "prefix": "winvalid", 47 | "body": "vim.api.nvim_win_is_valid(${1:win})" 48 | }, 49 | "Win Call": { 50 | "prefix": "wincall", 51 | "body": [ 52 | "vim.api.nvim_win_call(${1:win}, function(win)", 53 | " ${0}", 54 | "end)" 55 | ] 56 | }, 57 | "Buf Call": { 58 | "prefix": "bufcall", 59 | "body": [ 60 | "vim.api.nvim_buf_call(${1:buf}, function(buf)", 61 | " ${0}", 62 | "end)" 63 | ] 64 | }, 65 | "Schedule": { 66 | "prefix": "schedule", 67 | "body": [ 68 | "vim.schedule(function()", 69 | " ${0}", 70 | "end)" 71 | ] 72 | }, 73 | "Table Deep Extend": { 74 | "prefix": "deepextend", 75 | "body": "vim.tbl_deep_extend(\"force\", ${1:table}, ${2:table})$0" 76 | }, 77 | "Table Filter": { 78 | "prefix": "filter", 79 | "body": [ 80 | "vim.tbl_filter(function()", 81 | " $0", 82 | "end, ${1:table})" 83 | ] 84 | }, 85 | "Table Map": { 86 | "prefix": "map", 87 | "body": [ 88 | "vim.tbl_map(function()", 89 | " $0", 90 | "end, ${1:table})" 91 | ] 92 | }, 93 | "Table Values": { 94 | "prefix": "values", 95 | "body": "vim.tbl_values(${1:table})" 96 | }, 97 | "Table Keys": { 98 | "prefix": "keys", 99 | "body": "vim.tbl_keys(${1:table})" 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /.github/workflows/megalinter.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # MegaLinter GitHub Action configuration file 3 | # More info at https://megalinter.io 4 | # All variables described in https://megalinter.io/latest/configuration/ 5 | 6 | name: MegaLinter 7 | on: 8 | workflow_dispatch: 9 | pull_request: 10 | branches: [main] 11 | push: 12 | branches: [main] 13 | 14 | # Run Linters in parallel 15 | # Cancel running job if new job is triggered 16 | concurrency: 17 | group: "${{ github.ref }}-${{ github.workflow }}" 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | megalinter: 22 | name: MegaLinter 23 | runs-on: ubuntu-24.04 24 | 25 | # Give the default GITHUB_TOKEN write permission to commit and push, comment 26 | # issues, and post new Pull Requests; remove the ones you do not need 27 | permissions: 28 | contents: write 29 | issues: write 30 | pull-requests: write 31 | 32 | steps: 33 | - run: echo "🚀 Job automatically triggered by ${{ github.event_name }}" 34 | - run: echo "🐧 Job running on ${{ runner.os }} server" 35 | - run: echo "🐙 Using ${{ github.ref }} branch from ${{ github.repository }} repository" 36 | 37 | # Git Checkout 38 | - name: Checkout Code 39 | uses: actions/checkout@v4 40 | with: 41 | fetch-depth: 0 42 | sparse-checkout: | 43 | docs 44 | overrides 45 | .github 46 | - run: echo "🐙 Sparse Checkout of ${{ github.repository }} repository to the CI runner." 47 | 48 | # MegaLinter Configuration 49 | - name: MegaLinter Run 50 | uses: oxsecurity/megalinter@v8 51 | id: ml 52 | env: 53 | 54 | # Validate the git diff against default branch. 55 | VALIDATE_ALL_CODEBASE: >- 56 | ${{ github.event_name == 'push' && github.ref == 'refs/heads/main'}} 57 | 58 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" # report individual linter status 59 | 60 | # ADD CUSTOM ENV VARIABLES OR DEFINE IN MEGALINTER_CONFIG file 61 | MEGALINTER_CONFIG: .github/config/megalinter.yaml 62 | 63 | # Grafana Dashboard Connections - GitHub Organization secrets 64 | API_REPORTER: true 65 | API_REPORTER_URL: ${{ secrets.API_REPORTER_URL }} 66 | API_REPORTER_BASIC_AUTH_USERNAME: ${{ secrets.API_REPORTER_BASIC_AUTH_USERNAME }} 67 | API_REPORTER_BASIC_AUTH_PASSWORD: ${{ secrets.API_REPORTER_BASIC_AUTH_PASSWORD }} 68 | API_REPORTER_BEARER_TOKEN: ${{ secrets.API_REPORTER_BEARER_PASSWORD }} 69 | API_REPORTER_METRICS_URL: ${{ secrets.API_REPORTER_METRICS_URL }} 70 | API_REPORTER_METRICS_BASIC_AUTH_USERNAME: ${{ secrets.API_REPORTER_METRICS_BASIC_AUTH_USERNAME }} 71 | API_REPORTER_METRICS_BASIC_AUTH_PASSWORD: ${{ secrets.API_REPORTER_METRICS_BASIC_AUTH_PASSWORD }} 72 | API_REPORTER_METRICS_BEARER_TOKEN: ${{ secrets.API_REPORTER_METRICS_BEARER_PASSWORD }} 73 | API_REPORTER_DEBUG: false 74 | 75 | # Logging 76 | # LOG_LEVEL: DEBUG 77 | 78 | # Upload MegaLinter artifacts 79 | - name: Archive production artifacts 80 | if: success() || failure() 81 | uses: actions/upload-artifact@v4 82 | with: 83 | name: MegaLinter reports 84 | path: | 85 | megalinter-reports 86 | mega-linter.log 87 | 88 | # Summary and status 89 | - run: echo "🎨 MegaLinter quality checks completed" 90 | - run: echo "🍏 Job status is ${{ job.status }}." 91 | -------------------------------------------------------------------------------- /.github/config/megalinter.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configuration file for MegaLinter 3 | # 4 | # General configuration: 5 | # https://megalinter.io/latest/configuration/ 6 | # 7 | # Specific Linters: 8 | # https://megalinter.io/latest/supported-linters/ 9 | 10 | # ------------------------ 11 | # Validate all files if true 12 | # or new / edited files if false 13 | VALIDATE_ALL_CODEBASE: false 14 | 15 | # ------------------------ 16 | # Linters 17 | 18 | # Run linters in parallel 19 | PARALLEL: true 20 | 21 | # ENABLE specific linters, all other linters automatically disabled 22 | ENABLE: 23 | - CREDENTIALS 24 | - LUA 25 | - MAKEFILE 26 | - MARKDOWN 27 | - GIT 28 | - SPELL 29 | - YAML 30 | - REPOSITORY 31 | 32 | # Linter specific configuration 33 | 34 | # CLOJURE_CLJ_KONDO_CONFIG_FILE: ".github/config/clj-kondo-ci-config.edn" 35 | # CLOJURE_CLJ_KONDO_ARGUMENTS: "--lint deps.edn" 36 | # CLOJURE_CLJ_KONDO_FILTER_REGEX_EXCLUDE: "dev|develop" 37 | # CLOJURE_CLJ_KONDO_FILTER_REGEX_EXCLUDE: "resources" 38 | 39 | # CREDENTIALS_SECRETLINT_DISABLE_ERRORS: true 40 | CREDENTIALS_SECRETLINT_CONFIG_FILE: ".github/config/secretlintrc.json" 41 | 42 | MARKDOWN_MARKDOWNLINT_CONFIG_FILE: ".github/config/markdown-lint.jsonc" 43 | MARKDOWN_MARKDOWNLINT_FILTER_REGEX_EXCLUDE: ".github/pull_request_template.md|CHANGELOG.md|README.md|GLOSSARY.md|java-17-flags.md|abbreviations.md" 44 | # MARKDOWN_MARKDOWNLINT_DISABLE_ERRORS: true 45 | MARKDOWN_MARKDOWN_LINK_CHECK_CONFIG_FILE: ".github/config/markdown-link-check.json" 46 | # MARKDOWN_MARKDOWN_LINK_CHECK_CLI_LINT_MODE: "project" 47 | # MARKDOWN_MARKDOWN_LINK_CHECK_DISABLE_ERRORS: false 48 | MARKDOWN_REMARK_LINT_DISABLE_ERRORS: true 49 | # MARKDOWN_MARKDOWN_TABLE_FORMATTER_DISABLE_ERRORS: false 50 | 51 | REPOSITORY_DEVSKIM_CONFIG_FILE: ".github/config/devskim.json" 52 | REPOSITORY_GITLEAKS_CONFIG_FILE: ".github/config/gitleaks.toml" 53 | REPOSITORY_TRUFFLEHOG_DISABLE_ERRORS: true # Errors only as warnings 54 | REPOSITORY_KICS_DISABLE_ERRORS: true # Errors only as warnings 55 | REPOSITORY_DEVSKIM_DISABLE_ERRORS: true # Errors only as warnings 56 | 57 | # SPELL_CSPELL_DISABLE_ERRORS: true 58 | SPELL_MISSPELL_DISABLE_ERRORS: true 59 | SPELL_LYCHEE_CONFIG_FILE: ".github/config/lychee.toml" 60 | SPELL_LYCHEE_DISABLE_ERRORS: true # Errors are only warnings 61 | 62 | # YAML_PRETTIER_FILTER_REGEX_EXCLUDE: (docs/) 63 | # YAML_YAMLLINT_FILTER_REGEX_EXCLUDE: (docs/) 64 | YAML_V8R_DISABLE_ERRORS: true 65 | 66 | # Explicitly disable linters to ensure they are never run 67 | # DISABLE: 68 | # - COPYPASTE # checks for excessive copy-pastes 69 | # - SPELL # spell checking - often creates many false positives 70 | # - CSS # 71 | 72 | # Disable linter features 73 | DISABLE_LINTERS: 74 | - LUA_LUACHECK 75 | - LUA_SELENE 76 | - YAML_PRETTIER # draconian format rules 77 | - SPELL_CSPELL # many clojure references causing false positives 78 | - YAML_YAMLLINT # vague error mesages, investigation required 79 | - REPOSITORY_GIT_DIFF # warnings about LF to CRLF 80 | - REPOSITORY_SECRETLINT # reporting errors in its own config file 81 | # - REPOSITORY_DEVSKIM # unnecessary URL TLS checks 82 | - REPOSITORY_CHECKOV # fails on root user in Dockerfile 83 | - REPOSITORY_SECRETLINT 84 | 85 | # Ignore all errors and return without error status 86 | # DISABLE_ERRORS: true 87 | # ------------------------ 88 | 89 | # ------------------------ 90 | # Reporting 91 | 92 | # Activate sources reporter 93 | UPDATED_SOURCES_REPORTER: false 94 | 95 | # Show Linter timings in summary table at end of run 96 | SHOW_ELAPSED_TIME: true 97 | 98 | # Upload reports to file.io 99 | FILEIO_REPORTER: false 100 | # ------------------------ 101 | 102 | # ------------------------ 103 | # Over-ride errors 104 | 105 | # detect errors but do not block CI passing 106 | # DISABLE_ERRORS: true 107 | # ------------------------ 108 | -------------------------------------------------------------------------------- /lua/community.lua: -------------------------------------------------------------------------------- 1 | -- if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE 2 | 3 | -- AstroCommunity: import any community modules here 4 | -- We import this file in `lazy_setup.lua` before the `plugins/` folder. 5 | -- This guarantees that the specs are processed before any user plugins. 6 | 7 | -- NOTE: additional key binding defined in `lua/plugins/practicalli.lua` 8 | 9 | ---@type LazySpec 10 | return { 11 | 12 | -- ---------------------------------------------- 13 | -- Astrocommunity - include one of the following 14 | 15 | -- Astrocommunity Git Repository 16 | "AstroNvim/astrocommunity", 17 | 18 | -- Local plugin development - Astrocommunity fork in ~/project/astrocommunity 19 | -- { "AstroNvim/astrocommunity", dev = true }, 20 | 21 | -- Local plugin development - specify path to Astrocommunity fork 22 | -- { dir = "~/projects/community/neovim/astrocommunity" }, 23 | -- ---------------------------------------------- 24 | 25 | -- ---------------------------------------------- 26 | -- Themes and Color 27 | -- 28 | -- Colorscheme (Themes) 29 | { import = "astrocommunity.colorscheme.catppuccin" }, 30 | 31 | -- color picker and highlighter 32 | { import = "astrocommunity.color.ccc-nvim" }, 33 | -- ---------------------------------------------- 34 | 35 | -- ---------------------------------------------- 36 | -- Completion 37 | 38 | -- Emojis everywhere 39 | { import = "astrocommunity.completion.blink-cmp-emoji" }, 40 | -- ---------------------------------------------- 41 | 42 | -- ---------------------------------------------- 43 | 44 | -- ---------------------------------------------- 45 | -- Editing Support 46 | 47 | -- Rainbow parens 48 | { import = "astrocommunity.editing-support.rainbow-delimiters-nvim" }, 49 | 50 | -- Multiple Cursors 51 | { import = "astrocommunity.editing-support.vim-visual-multi" }, 52 | -- ---------------------------------------------- 53 | 54 | -- ---------------------------------------------- 55 | -- Motion plugins 56 | { import = "astrocommunity.motion.nvim-surround" }, 57 | -- ---------------------------------------------- 58 | 59 | -- ---------------------------------------------- 60 | -- Packs (code-runner, treesitter, lsp & lint/format support) 61 | 62 | { import = "astrocommunity.pack.clojure" }, 63 | { import = "astrocommunity.pack.json" }, 64 | { import = "astrocommunity.pack.lua" }, 65 | -- ---------------------------------------------- 66 | 67 | -- ---------------------------------------------- 68 | -- Search 69 | 70 | -- Search and replace across projects 71 | { import = "astrocommunity.search.grug-far-nvim" }, 72 | -- ---------------------------------------------- 73 | 74 | -- ---------------------------------------------- 75 | -- Recipes 76 | 77 | -- Neovide GUI configuration 78 | { import = "astrocommunity.recipes.neovide" }, 79 | 80 | -- LSP Mappings for Snacks or Telescope 81 | { import = "astrocommunity.recipes.picker-lsp-mappings" }, 82 | -- ---------------------------------------------- 83 | 84 | -- ---------------------------------------------- 85 | -- Source Control 86 | 87 | -- Diffview with neogit integration 88 | { import = "astrocommunity.git.diffview-nvim" }, 89 | 90 | -- Manage GitHub Gists 91 | { import = "astrocommunity.git.gist-nvim" }, 92 | 93 | -- Neogit interactive git client 94 | { import = "astrocommunity.git.neogit" }, 95 | 96 | -- GitHub Pull Requests and Issues 97 | { import = "astrocommunity.git.octo-nvim" }, 98 | -- ---------------------------------------------- 99 | 100 | -- ---------------------------------------------- 101 | -- Utility 102 | 103 | -- rich command prompt 104 | { import = "astrocommunity.utility.noice-nvim" }, 105 | -- ---------------------------------------------- 106 | } 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Practicalli Astro5 Neovim Configuration 2 | 3 | ```none 4 | ██████╗ ██████╗ █████╗ ██████╗████████╗██╗ ██████╗ █████╗ ██╗ ██╗ ██╗ 5 | ██╔══██╗██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██║██╔════╝██╔══██╗██║ ██║ ██║ 6 | ██████╔╝██████╔╝███████║██║ ██║ ██║██║ ███████║██║ ██║ ██║ 7 | ██╔═══╝ ██╔══██╗██╔══██║██║ ██║ ██║██║ ██╔══██║██║ ██║ ██║ 8 | ██║ ██║ ██║██║ ██║╚██████╗ ██║ ██║╚██████╗██║ ██║███████╗███████╗██║ 9 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ 10 | 11 | █████╗ ███████╗████████╗██████╗ ██████╗ ███████╗ 12 | ██╔══██╗██╔════╝╚══██╔══╝██╔══██╗██╔═══██╗ ██╔════╝ 13 | ███████║███████╗ ██║ ██████╔╝██║ ██║ ███████╗ 14 | ██╔══██║╚════██║ ██║ ██╔══██╗██║ ██║ ╚════██║ 15 | ██║ ██║███████║ ██║ ██║ ██║╚██████╔╝ ███████║ 16 | ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ 17 | ``` 18 | 19 | > NOTE: Ascii Art Generator: https://patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=Astro%205 20 | 21 | 22 | ## Overview 23 | 24 | A lazy loading rich feature configuration for [Neovim 0.11.x](https://neovim.org/), providing common development tooling, including an effective Clojure REPL workflow. 25 | 26 | This configuration is built upon [AstroNvim version 5](https://github.com/AstroNvim/AstroNvim), extending the AstroNvim v5 template with valuable plugins, options and key mappings. 27 | 28 | [Practicalli Neovim](https://practical.li/neovim/) describes the Clojure REPL workflow, rich Git and GitHub clients and easy management of plugins and tools using this configuration. 29 | 30 | 31 | ## 🛠️ Installation 32 | 33 | Recommended tools: 34 | 35 | - [Kitty Terminal](https://practical.li/engineering-playbook/command-line/kitty-terminal/) 36 | - [Neovim and supporting tools](https://practical.li/neovim/install/neovim/) 37 | - [Clojure CLI](https://practical.li/clojure/install/) 38 | 39 | Clone the Practicalli Astro5 repository (create a fork if customisation desired) 40 | 41 | ```shell 42 | git clone git@github.com:practicalli/nvim-astro5 $HOME/.config/nvim 43 | ``` 44 | 45 | Run `nvim` command and wait for all plugins to automatically install and Treesitter language parsers to compile. 46 | 47 | ```shell 48 | nvim 49 | ``` 50 | 51 | ### Multiple Neovim configs 52 | 53 | Clone to `$HOME/.config/nvim-astron5` and use the `NVIM_APPNAME=astronvim nvim` command to start Neovim with AstroNvim configuration 54 | 55 | ```shell 56 | git clone git@github.com:practicalli/nvim-astro5 $HOME/.config/nvim-astro5 57 | ``` 58 | 59 | Create a shell alias to run the new configuration, e.g. in `.bashrc` or `.zshrc` (or a `~/.config/shell-aliases` file that each shell rc file sources) 60 | 61 | ```config 62 | alias astro5="NVIM_APPNAME=nvim-astro5 nvim" 63 | ``` 64 | 65 | Load the alias into the current shell from the rc file or shell-aliases (or open a new shell), e.g. 66 | 67 | ```shell 68 | source ~/.config/shell-aliases 69 | ``` 70 | 71 | Run `astro5` and allow neovim plugins to automatically install and Treesitter language parsers to compile. 72 | 73 | ```shell 74 | astro5 75 | ``` 76 | 77 | 78 | ## Configuration overview 79 | 80 | The configuration is based on the AstroNvim v5 template config. Changes to existing file have been kept to a minimum, except for `lua/community.lua` which has additional plugins from the AstroNvim Community repository. 81 | 82 | `lua/plugins/practicalli.lua` contains Practicalli specific configuration (plugins, preferences & key maps). This also provides an example of how to modify and extend the AstroNvim configuration yourself. 83 | 84 | Set environment variable `PRACTICALLI_ASTRO` to false to skip the Practicalli config without requiring a code change. 85 | 86 | Create your own `lua/plugins/user-yourname.lua` file to: 87 | 88 | - override default plugin configuration 89 | - add new plugins (or create a new file for a plugin to make them easier to be optional) 90 | 91 | 92 | [Practicalli Astro5 config design](https://practical.li/neovim/reference/astro5-configuration/) provides a complete breakdown of this configuration. 93 | 94 | > NOTE: Lua files in the `lua/plugins` directory are loaded in alphabetical order so plugin overrides should be the last file to load, e.g `lua/plugins/user-*` 95 | 96 | 97 | ### LSP Servers 98 | 99 | Install an LSP server for each programming language used, allowing the Neovim LSP client to obtain diagnostic information. 100 | 101 | Mason is used to automatically install LSP servers, format & lint tools. [Mason Registry](https://mason-registry.dev/registry/list) maintains a list of the latest release for each tool (automatically updated). 102 | 103 | Mason can be configured to use a locally installed Clojure LSP server (using the [instructions for your operating system](https://clojure-lsp.io/installation/)). 104 | 105 | [lua/plugins/termux.lua](https://github.com/practicalli/nvim-astro5/blob/main/lua/plugins/termux.lua) shows how to configure mason to use a local Clojure and Lua LSP server (preventing Mason from automatically installing these tools) 106 | 107 | 108 | ## Sponsor Practicalli 109 | 110 | [![Sponsor Practicalli via GitHub](https://raw.githubusercontent.com/practicalli/graphic-design/live/buttons/practicalli-github-sponsors-button.png)](https://github.com/sponsors/practicalli-johnny/) 111 | 112 | All sponsorship funds are used to support the continued development of [Practicalli series of books and videos](https://practical.li/), although most work is done at personal cost and time. Infrastructure costs are kept to zero. 113 | 114 | Thanks to [Cognitect](https://www.cognitect.com/), [Nubank](https://nubank.com.br/) and a wide range of other [sponsors](https://github.com/sponsors/practicalli-johnny#sponsors) for your continued support 115 | -------------------------------------------------------------------------------- /snippets/markdown.json: -------------------------------------------------------------------------------- 1 | { 2 | "mkdocs admonition warning": { 3 | "prefix": "mkdocs-admonition-warning-draft", 4 | "body": [ 5 | "!!! WARNING \"Initial draft - feedback welcome\"" 6 | ], 7 | "description": "MkDocs Admonition Warning Draft" 8 | }, 9 | "mkdocs button tag": { 10 | "prefix": "mkdocs-button", 11 | "body": [ 12 | "{.md-button} $0" 13 | ], 14 | "description": "MkDocs Button tag" 15 | }, 16 | "mkdocs button target tag": { 17 | "prefix": "mkdocs-button-target-tag", 18 | "body": [ 19 | "{target=_blank .md-button} $0" 20 | ], 21 | "description": "MkDocs Button target blank tag" 22 | }, 23 | "mkdocs button form": { 24 | "prefix": "mkdocs-button-form", 25 | "body": [ 26 | "[${1:linktext}](${2:URL}){target=_blank .md-button} $0" 27 | ], 28 | "description": "MkDocs Button form" 29 | }, 30 | "mkdocs link target blank tag": { 31 | "prefix": "mkdocs-link-target-blank-tag", 32 | "body": [ 33 | "{target=_blank} $0" 34 | ], 35 | "description": "MkDocs Link target blank tag" 36 | }, 37 | "mkdocs link form": { 38 | "prefix": "mkdocs-link-form", 39 | "body": [ 40 | "[${1:linktext}](${2:URL}){target=_blank .md-button} $0" 41 | ], 42 | "description": "MkDocs Link form" 43 | }, 44 | "mkdocs youtube embed": { 45 | "prefix": "mkdocs-youtube-embed", 46 | "body": [ 47 | "

\n \n

$0" 48 | ], 49 | "description": "MkDocs YouTube Embed" 50 | }, 51 | "mkdocs icon book": { 52 | "prefix": "mkdocs-icon-book", 53 | "body": [ 54 | ":fontawesome-solid-book-open:$0" 55 | ], 56 | "description": "MkDocs link book icon" 57 | }, 58 | "mkdocs icon github": { 59 | "prefix": "mkdocs-icon-github", 60 | "body": [ 61 | ":fontawesome-brands-github:$0" 62 | ], 63 | "description": "MkDocs link github icon" 64 | }, 65 | "mkdocs icon globe": { 66 | "prefix": "mkdocs-icon-globe", 67 | "body": [ 68 | ":globe_with_meridians:$0" 69 | ], 70 | "description": "MkDocs link globe icon" 71 | }, 72 | "mkdocs icon mastodon": { 73 | "prefix": "mkdocs-icon-mastodon", 74 | "body": [ 75 | ":fontawesome-brands-mastodon:$0" 76 | ], 77 | "description": "MkDocs link mastodon icon" 78 | }, 79 | "mkdocs icon youtube": { 80 | "prefix": "mkdocs-icon-youtube", 81 | "body": [ 82 | ":fontawesome-brands-youtube:$0" 83 | ], 84 | "description": "MkDocs link youtube icon" 85 | }, 86 | "mkdocs image github base url": { 87 | "prefix": "mkdocs-image-github-base-url", 88 | "body": [ 89 | "https://raw.githubusercontent.com/practicalli/graphic-design/live/$0" 90 | ], 91 | "description": "MkDocs image GitHub base URL" 92 | }, 93 | "mkdocs image form": { 94 | "prefix": "mkdocs-image-form", 95 | "body": [ 96 | "![${1:alternative-text}](${2:url}#only-dark#$3){align=left$4 loading=lazy style=\"height:150px;width:150px\"}$0" 97 | ], 98 | "description": "MkDocs Image form" 99 | }, 100 | "mkdocs image GitHub form": { 101 | "prefix": "mkdocs-image-github-form", 102 | "body": [ 103 | "![${1:alternative text}](https://raw.githubusercontent.com/practicalli/graphic-design/live/${2:URL}#only-dark$3){align=left$4 loading=lazy style=\"height:150px;width:150px\"}" 104 | ], 105 | "description": "MkDocs Image GitHub form" 106 | }, 107 | "post header": { 108 | "prefix": "post-header", 109 | "body": [ 110 | "--- 111 | title: ${1:meaningful title} 112 | date: 113 | created: 2025-0${2}-${3} 114 | updated: 2025-0${2}-${3} 115 | authors: 116 | - practicalli 117 | categories: 118 | - practicalli 119 | tags: 120 | - clojure 121 | draft: true 122 | --- 123 | 124 | $0 125 | 126 | 127 | 128 | 129 | --- 130 | Thank you. 131 | 132 | [:globe_with_meridians: Practical.li Website](https://practical.li){target=_blank .md-button} 133 | 134 | [:fontawesome-brands-github: Practical.li GitHub Org](https://github.com/practicalli){target=_blank .md-button} 135 | [:fontawesome-brands-github: practicalli-johnny profile](https://github.com/practicalli-johnny){target=_blank .md-button} 136 | 137 | [:fontawesome-brands-mastodon: @practicalli@clj.social](https://clj.social/@practicalli){target=_blank .md-button} 138 | [:fontawesome-brands-twitter: @practical_li](https://twitter.com/practcial_li){target=_blank .md-button} 139 | " 140 | ], 141 | "description": "post-header" 142 | }, 143 | "mkdocs key form": { 144 | "prefix": "mkdocs-key-form", 145 | "body": [ 146 | "++$0++" 147 | ], 148 | "description": "MkDocs Key form" 149 | }, 150 | "mkdocs code block embeded": { 151 | "prefix": "mkdocs-code-embed", 152 | "body": [ 153 | "!!! EXAMPLE \"${1:title}\" 154 | ```${2:title} 155 | --8<-- \"${2:url}?raw=true\" 156 | ```" 157 | ] 158 | }, 159 | "mkdocs code block fourclojure": { 160 | "prefix": "mkdocs-code-embed-4clojure", 161 | "body": [ 162 | "!!! EXAMPLE \"Design Journal - 4Clojure #${1:number}\" 163 | ```clojure 164 | --8<-- \"https://github.com/practicalli/four-clojure/blob/master/src/four_clojure/${2:filename}?raw=true\" 165 | ```" 166 | ] 167 | }, 168 | "link": { 169 | "prefix": "link", 170 | "body": "[$1]($2)$0", 171 | "description": "Add link" 172 | }, 173 | "image": { 174 | "prefix": "img", 175 | "body": "![$1]($2)$0", 176 | "description": "Add image" 177 | }, 178 | "strikethrough": { 179 | "prefix": "strikethrough", 180 | "body": "~~$1~~$0", 181 | "description": "Insert strikethrough" 182 | }, 183 | "insert bold text": { 184 | "prefix": "bold", 185 | "body": "**$1**$0", 186 | "description": "Insert bold text" 187 | }, 188 | "insert italic text": { 189 | "prefix": "italic", 190 | "body": "*$1*$0", 191 | "description": "Insert italic text" 192 | }, 193 | "insert bold and italic text": { 194 | "prefix": "bolditalic", 195 | "body": "***$1***$0", 196 | "description": "Insert bold and italic text" 197 | }, 198 | "insert quoted text": { 199 | "prefix": "quote", 200 | "body": "> $1", 201 | "description": "Insert quoted text" 202 | }, 203 | "insert code block": { 204 | "prefix": "codeblocky", 205 | "body": "```${1:language}\n\t$2\n```$0", 206 | "description": "Insert fenced code block" 207 | }, 208 | "insert horizontal rule": { 209 | "prefix": "rule", 210 | "body": "----------\n", 211 | "description": "Insert horizontal rule" 212 | }, 213 | "collapsed detail": { 214 | "prefix": "collapsed", 215 | "body": "
\n\t$1\n\t$2\n
$0", 216 | "description": "Collapse text section" 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /lua/plugins/practicalli.lua: -------------------------------------------------------------------------------- 1 | -- ------------------------------------------ 2 | -- Practicalli preferences 3 | -- 4 | -- which-key menu vertical orientation 5 | -- catppuccin-mocha colorscheme 6 | -- Show key presses in popup (SPC u k) 7 | -- Snacks customisation 8 | -- -- Startup dashboard banner 9 | -- -- indent guides disabled 10 | -- -- notifier log level INFO 11 | -- `fd` as alternate `ESC` key mapping (better-escape.nvim) 12 | -- Trim blank space automatically 13 | -- Custom snippets 14 | -- Gist public 15 | -- Neovim global options & key mappings 16 | -- ------------------------------------------ 17 | 18 | -- INFO: Create your own preferences in `lua/plugins/your-name.lua` 19 | 20 | -- INFO: Files under `lua/plugins/*.lua` load in alphabetical order, 21 | -- so plugin overrides should be the last file to load 22 | 23 | -- INFO: Config in this file skipped if `PRACTICALLI_ASTRO` environment variable set to false 24 | local user_practicalli = vim.env.PRACTICALLI_ASTRO 25 | if user_practicalli == "false" then return {} end 26 | 27 | ---@type LazySpec 28 | return { 29 | 30 | -- ------------------------------------------ 31 | -- UI Customisation 32 | 33 | -- Vertical which-key menu 34 | { 35 | "folke/which-key.nvim", 36 | opts = { 37 | ---@type false | "classic" | "modern" | "helix" 38 | preset = "helix", 39 | }, 40 | }, 41 | -- Colorscheme (Theme) 42 | ---@type LazySpec 43 | { 44 | "AstroNvim/astroui", 45 | ---@type AstroUIOpts 46 | opts = { 47 | colorscheme = "catppuccin-mocha", 48 | }, 49 | }, 50 | -- show key presses in normal mode 51 | { 52 | "nvzone/showkeys", 53 | cmd = "ShowkeysToggle", 54 | opts = { 55 | excluded_modes = { "i", "t" }, -- skip insert and terminal 56 | position = "bottom-center", 57 | show_count = true, 58 | maxkeys = 4, 59 | timeout = 4, 60 | }, 61 | }, 62 | -- Snacks Customisation 63 | { 64 | "folke/snacks.nvim", 65 | opts = { 66 | dashboard = { 67 | preset = { 68 | -- customize the dashboard header 69 | header = table.concat({ 70 | " ██████╗ ██████╗ █████╗ ██████╗████████╗██╗ ██████╗ █████╗ ██╗ ██╗ ██╗", 71 | " ██╔══██╗██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██║██╔════╝██╔══██╗██║ ██║ ██║", 72 | " ██████╔╝██████╔╝███████║██║ ██║ ██║██║ ███████║██║ ██║ ██║", 73 | " ██╔═══╝ ██╔══██╗██╔══██║██║ ██║ ██║██║ ██╔══██║██║ ██║ ██║", 74 | " ██║ ██║ ██║██║ ██║╚██████╗ ██║ ██║╚██████╗██║ ██║███████╗███████╗██║", 75 | " ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝", 76 | }, "\n"), 77 | }, 78 | }, 79 | 80 | -- indent guides - disable by default 81 | indent = { enabled = false }, 82 | 83 | notifier = { 84 | -- log level: TRACE DEBUG ERROR WARN INFO OFF 85 | level = vim.log.levels.WARN, 86 | -- wrap words in picker right panel 87 | win = { preview = { wo = { wrap = true } } }, 88 | }, 89 | }, 90 | }, 91 | -- ------------------------------------------ 92 | 93 | -- ------------------------------------------ 94 | -- Editor tools 95 | 96 | -- Alternative to Esc key using `fd` key mapping 97 | { 98 | "max397574/better-escape.nvim", 99 | event = "InsertCharPre", 100 | opts = { 101 | timeout = vim.o.timeoutlen, 102 | default_mappings = false, 103 | mappings = { 104 | i = { f = { d = "" } }, 105 | c = { f = { d = "" } }, 106 | t = { f = { d = "" } }, 107 | v = { f = { d = "" } }, 108 | s = { f = { d = "" } }, 109 | }, 110 | }, 111 | }, 112 | -- Trim trailing blank space and blank lines 113 | { 114 | "cappyzawa/trim.nvim", 115 | event = "User AstroFile", 116 | opts = {}, 117 | }, 118 | -- Custom snippets (vscode format) 119 | { 120 | "L3MON4D3/LuaSnip", 121 | config = function(plugin, opts) 122 | -- include default astronvim config that calls the setup call 123 | require "astronvim.plugins.configs.luasnip"(plugin, opts) 124 | -- load snippets paths 125 | require("luasnip.loaders.from_vscode").lazy_load { 126 | paths = { vim.fn.stdpath "config" .. "/snippets" }, 127 | } 128 | end, 129 | }, 130 | -- Switch between src and test file 131 | -- TODO: PR #67 raised on rgroli/other.nvim 132 | { 133 | "rgroli/other.nvim", 134 | ft = { "clojure" }, 135 | main = "other-nvim", 136 | opts = { 137 | mappings = { "clojure" }, 138 | }, 139 | }, 140 | -- ------------------------------------------ 141 | 142 | -- ------------------------------------------ 143 | -- Neovim Options and Key Mappings 144 | { 145 | "AstroNvim/astrocore", 146 | ---@type AstroCoreOpts 147 | opts = { 148 | options = { 149 | -- configure general options: vim.opt. 150 | opt = { 151 | spell = true, -- sets vim.opt.spell 152 | wrap = true, -- sets vim.opt.wrap 153 | guifont = "Fira Code:h16", -- neovide font family & size 154 | }, 155 | -- configure global vim variables: vim.g 156 | g = { 157 | -- Neovim language provides - disable language integration not required 158 | loaded_perl_provider = 0, 159 | loaded_ruby_provider = 0, 160 | 161 | -- Leader key for Visual-Multi Cursors (Multiple Cursors) 162 | VM_leader = "gm", -- Visual Multi Leader (multiple cursors - user plugin) 163 | 164 | -- Conjure plugin overrides 165 | -- comment pattern for eval to comment command 166 | ["conjure#eval#comment_prefix"] = ";; ", 167 | -- Hightlight evaluated forms 168 | ["conjure#highlight#enabled"] = true, 169 | 170 | -- show HUD REPL log at startup 171 | ["conjure#log#hud#enabled"] = false, 172 | 173 | -- auto repl (babashka) 174 | ["conjure#client#clojure#nrepl#connection#auto_repl#enabled"] = false, 175 | ["conjure#client#clojure#nrepl#connection#auto_repl#hidden"] = true, 176 | ["conjure#client#clojure#nrepl#connection#auto_repl#cmd"] = nil, 177 | ["conjure#client#clojure#nrepl#eval#auto_require"] = false, 178 | 179 | -- Test runner: "clojure", "clojuresCRipt", "kaocha" 180 | ["conjure#client#clojure#nrepl#test#runner"] = "kaocha", 181 | 182 | -- Troubleshoot: Minimise very long lines slow down: 183 | -- ["conjure#log#treesitter"] = false 184 | -- ["conjure#log##treesitter"] = false, 185 | -- ["conjure#log#disable_diagnostics"] = true 186 | }, 187 | }, 188 | mappings = { 189 | n = { 190 | -- normal mode key bindings 191 | -- setting a mapping to false will disable it 192 | -- [""] = false, 193 | 194 | -- whick-key sub-menu for Visual-Multi Cursors (Multiple Cursors) 195 | ["gm"] = { name = "Multiple Cursors" }, 196 | 197 | -- Toggle last open buffer 198 | [""] = { "b#", desc = "Previous tab" }, 199 | 200 | -- navigate buffer tabs 201 | ["]b"] = { function() require("astrocore.buffer").nav(vim.v.count1) end, desc = "Next buffer" }, 202 | ["[b"] = { function() require("astrocore.buffer").nav(-vim.v.count1) end, desc = "Previous buffer" }, 203 | 204 | -- snacks file explorer 205 | ["E"] = { "lua Snacks.picker.explorer()", desc = "Snacks Explorer" }, 206 | 207 | -- Save prompting for file name 208 | ["W"] = { ":write ", desc = "Save as file" }, 209 | 210 | -- Gist Creation 211 | ["gj"] = { ":GistCreateFromFile ", desc = "Create Gist (file)" }, 212 | ["gJ"] = { "GistsList", desc = "List Gist" }, 213 | 214 | -- Neogit Status float 215 | ["gf"] = { "Neogit kind=floating", desc = "Git Status (floating)" }, 216 | 217 | -- Toggle between src and test (Clojure pack | other-nvim) 218 | ["ts"] = { "Other", desc = "Switch src & test" }, 219 | ["tS"] = { "OtherVSplit", desc = "Switch src & test (Split)" }, 220 | 221 | -- Showkeys plugin (visualise key presses in Neovim window) 222 | ["uk"] = { "ShowkeysToggle", desc = "Toggle Showkeys" }, 223 | }, 224 | t = { 225 | -- terminal mode key bindings 226 | }, 227 | v = { 228 | -- visual mode key bindings 229 | -- Gist Creation 230 | ["gj"] = { ":GistCreate ", desc = "Create Gist (region)" }, 231 | }, 232 | }, 233 | }, 234 | }, 235 | } 236 | -------------------------------------------------------------------------------- /.github/config/markdown-lint.jsonc: -------------------------------------------------------------------------------- 1 | // Example markdownlint configuration with all properties set to their default value 2 | { 3 | 4 | // Default state for all rules 5 | "default": true, 6 | 7 | // Path to configuration file to extend 8 | "extends": null, 9 | 10 | // MD001/heading-increment/header-increment - Heading levels should only increment by one level at a time 11 | "MD001": true, 12 | 13 | // MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading 14 | "MD002": { 15 | // Heading level 16 | "level": 1 17 | }, 18 | 19 | // MD003/heading-style/header-style - Heading style 20 | "MD003": { 21 | // Heading style 22 | "style": "consistent" 23 | }, 24 | 25 | // MD004/ul-style - Unordered list style 26 | "MD004": { 27 | // List style 28 | "style": "consistent" 29 | }, 30 | 31 | // MD005/list-indent - Inconsistent indentation for list items at the same level 32 | "MD005": true, 33 | 34 | // MD006/ul-start-left - Consider starting bulleted lists at the beginning of the line 35 | "MD006": true, 36 | 37 | // MD007/ul-indent - Unordered list indentation 38 | "MD007": { 39 | // Spaces for indent 40 | "indent": 2, 41 | // Whether to indent the first level of the list 42 | "start_indented": false, 43 | // Spaces for first level indent (when start_indented is set) 44 | "start_indent": 2 45 | }, 46 | 47 | // MD009/no-trailing-spaces - Trailing spaces 48 | "MD009": { 49 | // Spaces for line break 50 | "br_spaces": 2, 51 | // Allow spaces for empty lines in list items 52 | "list_item_empty_lines": false, 53 | // Include unnecessary breaks 54 | "strict": true 55 | }, 56 | 57 | // MD010/no-hard-tabs - Hard tabs 58 | "MD010": { 59 | // Include code blocks 60 | "ignore_code_blocks": false, 61 | // Fenced code languages to ignore 62 | "ignore_code_languages": [ 63 | "Makefile", 64 | "shell" 65 | ], 66 | // Number of spaces for each hard tab 67 | "spaces_per_tab": 1 68 | }, 69 | 70 | // MD011/no-reversed-links - Reversed link syntax 71 | "MD011": true, 72 | 73 | // MD012/no-multiple-blanks - Multiple consecutive blank lines 74 | "MD012": { 75 | // Consecutive blank lines 76 | "maximum": 2 77 | }, 78 | 79 | // MD013/line-length - Line length 80 | "MD013": { 81 | // Number of characters 82 | "line_length": 520, 83 | // Number of characters for headings 84 | "heading_line_length": 90, 85 | // Number of characters for code blocks 86 | "code_block_line_length": 420, 87 | // Include code blocks 88 | "code_blocks": true, 89 | // Include tables 90 | "tables": true, 91 | // Include headings 92 | "headings": true, 93 | // Include headings 94 | "headers": true, 95 | // Strict length checking 96 | "strict": false, 97 | // Stern length checking 98 | "stern": true 99 | }, 100 | 101 | // MD014/commands-show-output - Dollar signs used before commands without showing output 102 | "MD014": true, 103 | 104 | // MD018/no-missing-space-atx - No space after hash on atx style heading 105 | "MD018": true, 106 | 107 | // MD019/no-multiple-space-atx - Multiple spaces after hash on atx style heading 108 | "MD019": true, 109 | 110 | // MD020/no-missing-space-closed-atx - No space inside hashes on closed atx style heading 111 | "MD020": true, 112 | 113 | // MD021/no-multiple-space-closed-atx - Multiple spaces inside hashes on closed atx style heading 114 | "MD021": true, 115 | 116 | // MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines 117 | "MD022": { 118 | // Blank lines above heading 119 | "lines_above": 1, 120 | // Blank lines below heading 121 | "lines_below": 1 122 | }, 123 | 124 | // MD023/heading-start-left/header-start-left - Headings must start at the beginning of the line 125 | "MD023": true, 126 | 127 | // MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content 128 | "MD024": { 129 | // Only check sibling headings 130 | "allow_different_nesting": false, 131 | // Only check sibling headings 132 | "siblings_only": false 133 | }, 134 | 135 | // MD025/single-title/single-h1 - Multiple top-level headings in the same document 136 | "MD025": { 137 | // Heading level 138 | "level": 1, 139 | // RegExp for matching title in front matter 140 | "front_matter_title": "^\\s*title\\s*[:=]" 141 | }, 142 | 143 | // MD026/no-trailing-punctuation - Trailing punctuation in heading 144 | "MD026": { 145 | // Punctuation characters not allowed at end of headings 146 | "punctuation": ".,;:!。,;:!" 147 | }, 148 | 149 | // MD027/no-multiple-space-blockquote - Multiple spaces after blockquote symbol 150 | "MD027": true, 151 | 152 | // MD028/no-blanks-blockquote - Blank line inside blockquote 153 | "MD028": true, 154 | 155 | // MD029/ol-prefix - Ordered list item prefix 156 | "MD029": { 157 | // List style 158 | "style": "one_or_ordered" 159 | }, 160 | 161 | // MD030/list-marker-space - Spaces after list markers 162 | "MD030": { 163 | // Spaces for single-line unordered list items 164 | "ul_single": 1, 165 | // Spaces for single-line ordered list items 166 | "ol_single": 1, 167 | // Spaces for multi-line unordered list items 168 | "ul_multi": 1, 169 | // Spaces for multi-line ordered list items 170 | "ol_multi": 1 171 | }, 172 | 173 | // MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines 174 | "MD031": { 175 | // Include list items 176 | "list_items": true 177 | }, 178 | 179 | // MD032/blanks-around-lists - Lists should be surrounded by blank lines 180 | "MD032": true, 181 | 182 | // MD033/no-inline-html - Inline HTML 183 | "MD033": { 184 | // Allowed elements 185 | "allowed_elements": [ "a", "iframe", "img", "p", "div", "script" ] 186 | }, 187 | 188 | // MD034/no-bare-urls - Bare URL used 189 | "MD034": false, 190 | 191 | // MD035/hr-style - Horizontal rule style 192 | "MD035": { 193 | // Horizontal rule style 194 | "style": "consistent" 195 | }, 196 | 197 | // MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading 198 | "MD036": { 199 | // Punctuation characters 200 | "punctuation": ".,;:!?。,;:!?" 201 | }, 202 | 203 | // MD037/no-space-in-emphasis - Spaces inside emphasis markers 204 | "MD037": true, 205 | 206 | // MD038/no-space-in-code - Spaces inside code span elements 207 | "MD038": true, 208 | 209 | // MD039/no-space-in-links - Spaces inside link text 210 | "MD039": true, 211 | 212 | // MD040/fenced-code-language - Fenced code blocks should have a language specified 213 | "MD040": { 214 | // List of languages 215 | "allowed_languages": [], 216 | // Require language only 217 | "language_only": false 218 | }, 219 | 220 | // MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading 221 | "MD041": { 222 | // Heading level 223 | "level": 1, 224 | // RegExp for matching title in front matter 225 | "front_matter_title": "^\\s*title\\s*[:=]" 226 | }, 227 | 228 | // MD042/no-empty-links - No empty links 229 | "MD042": true, 230 | 231 | // MD043/required-headings/required-headers - Required heading structure 232 | "MD043": {}, 233 | 234 | // MD044/proper-names - Proper names should have the correct capitalization 235 | "MD044": { 236 | // List of proper names 237 | "names": [], 238 | // Include code blocks 239 | "code_blocks": true, 240 | // Include HTML elements 241 | "html_elements": true 242 | }, 243 | 244 | // MD045/no-alt-text - Images should have alternate text (alt text) 245 | "MD045": true, 246 | 247 | // MD046/code-block-style - Code block style 248 | "MD046": { 249 | // Block style 250 | "style": "consistent" 251 | }, 252 | 253 | // MD047/single-trailing-newline - Files should end with a single newline character 254 | "MD047": true, 255 | 256 | // MD048/code-fence-style - Code fence style 257 | "MD048": { 258 | // Code fence style 259 | "style": "consistent" 260 | }, 261 | 262 | // MD049/emphasis-style - Emphasis style should be consistent 263 | "MD049": { 264 | // Emphasis style should be consistent 265 | "style": "consistent" 266 | }, 267 | 268 | // MD050/strong-style - Strong style should be consistent 269 | "MD050": { 270 | // Strong style should be consistent 271 | "style": "consistent" 272 | }, 273 | 274 | // MD051/link-fragments - Link fragments should be valid 275 | "MD051": true, 276 | 277 | // MD052/reference-links-images - Reference links and images should use a label that is defined 278 | "MD052": true, 279 | 280 | // MD053/link-image-reference-definitions - Link and image reference definitions should be needed 281 | "MD053": { 282 | // Ignored definitions 283 | "ignored_definitions": ["//"] 284 | } 285 | } 286 | --------------------------------------------------------------------------------