Part-of-speech highlighting for Neovim
  • Lua 79.8%
  • JavaScript 20.2%
Find a file
Max Vim 1cbe6be670 node: helpful error message when missing, command -> node_command
node_command argument is renamed from command argument that wasn't
documented before. it is now documented and renamed to node_command
2026-06-07 16:56:59 +03:00
assets docs: add demo.gif 2026-06-07 14:43:55 +03:00
bin initial commit 2026-06-07 14:29:41 +03:00
js initial commit 2026-06-07 14:29:41 +03:00
lua/hi_pos node: helpful error message when missing, command -> node_command 2026-06-07 16:56:59 +03:00
.gitignore initial commit 2026-06-07 14:29:41 +03:00
LICENSE docs: added gplv3 license 2026-06-07 14:44:26 +03:00
package-lock.json initial commit 2026-06-07 14:29:41 +03:00
package.json initial commit 2026-06-07 14:29:41 +03:00
README.md node: helpful error message when missing, command -> node_command 2026-06-07 16:56:59 +03:00

hi-pos.nvim

hi-pos.nvim demo

Natural language part-of-speech highlighting for Neovim, powered by Compromise.

Inspired by the Obsidian plugin Natural Language Syntax Highlighting.

Requirements

  • Neovim 0.10+
  • Node.js

Installation

With lazy.nvim:

{
  "maxonvim/hi-pos.nvim",
  config = function()
    local pos = require("hi_pos").setup()

    vim.keymap.set("n", "<leader>ps", pos.start, { desc = "Start POS highlighting" })
    vim.keymap.set("n", "<leader>pS", pos.stop, { desc = "Stop POS highlighting" })
    vim.keymap.set("n", "<leader>pt", pos.toggle, { desc = "Toggle POS highlighting" })
  end,
}

API

local pos = require("hi_pos").setup({
  debounce_ms = 250,
  disable_uppercase_filenames = true,
  max_buffer_size = 200000,
  filetypes = { "markdown", "text", "gitcommit" },
  node_command = { "node" },
  markdown = {
    include = {
      paragraphs = true,
      lists = true,
      blockquotes = false,
      headings = false,
    },
  },
  highlight = {
    Noun = "Identifier",
    Verb = "Statement",
    Adjective = "Type",
    Adverb = "PreProc",
    Preposition = "Operator",
    Conjunction = "Conditional",
    Determiner = "Comment",
    Pronoun = "Special",
    Value = "Number",
    QuestionWord = "Question",
    Expression = "String",
    Url = "Underlined",
    HashTag = "Tag",
    AtMention = "Tag",
  },
})

pos.start()      -- current buffer
pos.stop()       -- current buffer
pos.toggle()     -- current buffer
pos.refresh()    -- rerun compromise for current buffer
pos.is_running() -- current buffer

filetypes defaults to { "markdown", "text", "gitcommit" } and controls auto-start only. Set filetypes = false or filetypes = {} to disable auto-start. Manual pos.start() still works for any buffer.

disable_uppercase_filenames defaults to true, so files like README.md, CHANGELOG.md, and LICENSE are ignored. Set it to false to highlight those files too.

Markdown uses a whitelist. By default, only paragraph lines and list item lines are highlighted. Code fences, frontmatter, tables, HTML blocks, thematic breaks, headings, and blockquotes are not highlighted.

Enable headings or blockquotes with:

require("hi_pos").setup({
  markdown = {
    include = {
      headings = true,
      blockquotes = true,
    },
  },
})

Each method accepts an optional buffer number:

pos.start(7)

Highlight Groups

The plugin maps compromise tags to existing highlight groups by default:

{
  Noun = "Identifier",
  Verb = "Statement",
  Adjective = "Type",
  Adverb = "PreProc",
  Preposition = "Operator",
  Conjunction = "Conditional",
  Determiner = "Comment",
  Pronoun = "Special",
  Value = "Number",
}

Override any tag by passing highlight to setup. The full default map is also available as:

require("hi_pos").default_highlight

Contributing/Development

Any contributions are welcome!

The runtime helper in bin/hi-pos.js is bundled and committed, so users do not need npm install.

To rebuild it after changing js/hi-pos.js:

npm install
npm run build