#+title: Editor Integration
#+options: num:nil toc:nil

* Emacs (Apheleia)

[[https://github.com/radian-software/apheleia][Apheleia]] runs external formatters on buffer save, preserving cursor position.

#+begin_src elisp
(with-eval-after-load 'apheleia
  (push '(snapper . ("snapper" "--format" "org")) apheleia-formatters)
  (push '(org-mode . snapper) apheleia-mode-alist)
  ;; Add for other formats:
  (push '(latex-mode . snapper) apheleia-mode-alist)
  (push '(markdown-mode . snapper) apheleia-mode-alist))
#+end_src

The =--format= flag auto-detects from the file extension, so you can omit it if your files have standard extensions.

* Vim / Neovim

Use =formatprg= to pipe through snapper:

#+begin_src vim
autocmd FileType org setlocal formatprg=snapper\ --format\ org
autocmd FileType tex setlocal formatprg=snapper\ --format\ latex
autocmd FileType markdown setlocal formatprg=snapper\ --format\ markdown
#+end_src

Then =gq= to reformat selected text, or =gggqG= to reformat the entire buffer.

For Neovim with =conform.nvim=:

#+begin_src lua
require("conform").setup({
  formatters = {
    snapper = {
      command = "snapper",
      args = { "--format", "$FILETYPE" },
      stdin = true,
    },
  },
  formatters_by_ft = {
    org = { "snapper" },
    tex = { "snapper" },
    markdown = { "snapper" },
  },
})
#+end_src

* VS Code extension (recommended)

Install the snapper extension from the VS Code Marketplace (or from the repo at =editors/vscode/=).
It uses the LSP server for format-on-save, range formatting, and diagnostics.

Configure the path to the snapper binary in settings:

#+begin_src json
{
  "snapper.path": "snapper",
  "snapper.formatOnSave": true
}
#+end_src

** Manual VS Code setup (without extension)

Use the "Run on Save" extension with a custom command:

#+begin_src json
{
  "emeraldwalk.runonsave": {
    "commands": [
      {
        "match": "\\.(org|tex|md|rst)$",
        "cmd": "snapper --in-place ${file}"
      }
    ]
  }
}
#+end_src

* LSP (any editor with LSP support)

Snapper ships a Language Server Protocol implementation.
Start it with:

#+begin_src bash
snapper lsp
#+end_src

This provides document formatting, range formatting, and diagnostics (flags lines with multiple sentences) over the standard LSP protocol on stdin/stdout.

** Neovim (native LSP)

#+begin_src lua
vim.api.nvim_create_autocmd("FileType", {
  pattern = { "org", "tex", "markdown" },
  callback = function()
    vim.lsp.start({
      name = "snapper",
      cmd = { "snapper", "lsp" },
    })
  end,
})
#+end_src

** Emacs (eglot)

#+begin_src elisp
(add-to-list 'eglot-server-programs
             '((org-mode latex-mode markdown-mode) "snapper" "lsp"))
#+end_src

** VS Code

Add to =settings.json= (requires a generic LSP client extension):

#+begin_src json
{
  "lsp.servers": {
    "snapper": {
      "command": "snapper",
      "args": ["lsp"],
      "filetypes": ["org", "tex", "markdown"]
    }
  }
}
#+end_src

** Helix

Add to =~/.config/helix/languages.toml=:

#+begin_src toml
[[language]]
name = "org"
language-servers = ["snapper"]

[language-server.snapper]
command = "snapper"
args = ["lsp"]
#+end_src

* Generic (any editor)

Snapper reads stdin and writes stdout by default.
Any editor that supports piping through an external program works:

#+begin_src bash
cat paper.org | snapper --format org
#+end_src
