<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Armand Halbert</title>
    <description>The latest articles on DEV Community by Armand Halbert (@ahalbert).</description>
    <link>https://dev.to/ahalbert</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F396666%2F355a6ed8-637a-4f56-88e0-d39ee652cf4c.png</url>
      <title>DEV Community: Armand Halbert</title>
      <link>https://dev.to/ahalbert</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahalbert"/>
    <language>en</language>
    <item>
      <title>Vim + Markdown = Writer's Heaven</title>
      <dc:creator>Armand Halbert</dc:creator>
      <pubDate>Wed, 25 Mar 2026 11:09:02 +0000</pubDate>
      <link>https://dev.to/ahalbert/vim-markdown-writers-heaven-24m8</link>
      <guid>https://dev.to/ahalbert/vim-markdown-writers-heaven-24m8</guid>
      <description>&lt;p&gt;I use Jekyll, Markdown and Vim to write content for my blog. Rather than&lt;br&gt;
wrestling with a full-fledged CMS or writing raw HTML, I can use a human&lt;br&gt;
readable markup language to write my posts. Vim is my editor of choice, and&lt;br&gt;
while I like the friendliness of GUI markdown tools, I miss my shortcuts,&lt;br&gt;
autocomplete and plugins in vim. Having a minimalistic text editor gives me an&lt;br&gt;
environment that is distraction free, version controlled and easy to publish.&lt;br&gt;
This article will go into how to set up vim to effectively edit Markdown with&lt;br&gt;
these features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spelling&lt;/li&gt;
&lt;li&gt;English Auto-Completion&lt;/li&gt;
&lt;li&gt;Auto-Formatting&lt;/li&gt;
&lt;li&gt;Grammar Checking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some notes before we begin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I use &lt;a href="https://github.com/junegunn/vim-plug" rel="noopener noreferrer"&gt;vim-plug&lt;/a&gt; to manage my plugins,
and this guide assumes you do too.&lt;/li&gt;
&lt;li&gt;There are two .vimrc files used here: &lt;code&gt;~/.vimrc&lt;/code&gt; and
&lt;code&gt;~/.vim/after/ftplugin/markdown.vim&lt;/code&gt;, which is a file that runs only after
&lt;code&gt;~/.vimrc&lt;/code&gt; is loaded and a markdown file is detected.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Basics
&lt;/h2&gt;

&lt;p&gt;Vanilla vim itself comes with a lot of markdown support, such as frontmatter&lt;br&gt;
highlighting and spelling.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.vim/after/ftplugin/markdown.vim&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" Disable line numbers&lt;/span&gt;
&lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;nonumber&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I never found much value in line numbers when writing, so I turned them off&lt;br&gt;
specifically for Markdown.&lt;/p&gt;
&lt;h3&gt;
  
  
  Spelling
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;~/.vim/after/ftplugin/markdown.vim&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" Turn spellcheck on&lt;/span&gt;
&lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;spell&lt;/span&gt;
nnoremap zs &lt;span class="m"&gt;1&lt;/span&gt;z&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="c"&gt;" Disable check for sentence capitalization&lt;/span&gt;
&lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;spellcapcheck&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vim has a very effective spellchecking system that you can enable with&lt;br&gt;
&lt;code&gt;set spell&lt;/code&gt;, and a few keystrokes that make correcting your spelling easy. &lt;code&gt;z=&lt;/code&gt;&lt;br&gt;
brings up a list of possible corrections, while &lt;code&gt;1z=&lt;/code&gt; picks the most likely one.&lt;br&gt;
I remapped it to &lt;code&gt;zs&lt;/code&gt; to make it easy to correct spelling. If it's a word vim&lt;br&gt;
doesn't recognize, you can use &lt;code&gt;zg&lt;/code&gt; to add it to the dictionary.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;spellcapcheck&lt;/code&gt; is a feature that detects if you forgot to capitalize the&lt;br&gt;
beginning of a sentence. Unfortunately, it is just a regular expression, so if&lt;br&gt;
you write something like "vs." it will decide that you forgot to capitalize the&lt;br&gt;
next word and highlight it. You can disable it by emptying the regex, as I did&lt;br&gt;
with &lt;code&gt;setlocal spellcapcheck=&lt;/code&gt; .&lt;/p&gt;
&lt;h2&gt;
  
  
  vim-markdown
&lt;/h2&gt;

&lt;p&gt;Vim-markdown, &lt;a href="https://github.com/preservim/vim-markdown" rel="noopener noreferrer"&gt;&lt;code&gt;preservim/vim-markdown&lt;/code&gt;&lt;/a&gt; is a plugin that provides several nice&lt;br&gt;
features, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Folding&lt;/li&gt;
&lt;li&gt;Highlighting of fenced code blocks&lt;/li&gt;
&lt;li&gt;Highlighting of front matter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and some useful commands like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:Toc&lt;/code&gt; — Create a table of contents in the quickfix list&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:InsertToc&lt;/code&gt; — insert a table of contents into the buffer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:SetexToAtx&lt;/code&gt;, &lt;code&gt;:HeaderDecrease&lt;/code&gt;, &lt;code&gt;:HeaderIncrease&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;~/.vimrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;Plug &lt;span class="s1"&gt;'preservim/vim-markdown'&lt;/span&gt;
&lt;span class="c"&gt;" Enable folding.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:vim_markdown_folding_disabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

&lt;span class="c"&gt;" Fold heading in with the contents.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:vim_markdown_folding_style_pythonic&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="c"&gt;" Don't use the shipped key bindings.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:vim_markdown_no_default_key_mappings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="c"&gt;" Filetype names and aliases for fenced code blocks.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:vim_markdown_fenced_languages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'php'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'py=python'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'js=javascript'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bash=sh'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'viml=vim'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c"&gt;" Highlight front matter (useful for Jekyll/Hugo posts).&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:vim_markdown_toml_frontmatter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:vim_markdown_frontmatter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:vim_markdown_json_frontmatter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An explanation of the settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;vim_markdown_folding_disabled&lt;/code&gt; is set to &lt;code&gt;0&lt;/code&gt; to enable folding, which lets
you collapse sections of your document under their headings. To understand
folding behavior, see &lt;code&gt;:help folding&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim_markdown_folding_style_pythonic&lt;/code&gt; changes the fold behavior so that the
heading line itself stays visible when folded, rather than being hidden with
the rest of the section.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim_markdown_no_default_key_mappings&lt;/code&gt; disables the plugin's built-in key
mappings, letting you define your own without conflicts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim_markdown_fenced_languages&lt;/code&gt; defines a list of language names and aliases
for syntax highlighting inside fenced code blocks, so that e.g. a block tagged
&lt;code&gt;bash&lt;/code&gt; gets highlighted as &lt;code&gt;sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim_markdown_frontmatter&lt;/code&gt;, &lt;code&gt;vim_markdown_toml_frontmatter&lt;/code&gt;, and
&lt;code&gt;vim_markdown_json_frontmatter&lt;/code&gt; enable syntax highlighting for YAML, TOML, and
JSON front matter respectively, which is useful if you write Jekyll or Hugo
posts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Completion
&lt;/h2&gt;

&lt;p&gt;Why type each word by hand when you can tab-complete it? I use the plugin&lt;br&gt;
&lt;a href="https://github.com/girishji/vimcomplete" rel="noopener noreferrer"&gt;&lt;code&gt;girishji/vimcomplete&lt;/code&gt;&lt;/a&gt; and its companion, &lt;a href="https://github.com/girishji/ngram-complete.vim" rel="noopener noreferrer"&gt;&lt;code&gt;girishji/ngram-complete.vim&lt;/code&gt;&lt;/a&gt; to&lt;br&gt;
provide auto-completion for English.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.vimrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;Plug &lt;span class="s1"&gt;'girishji/vimcomplete'&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:vimcomplete_tab_enable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
Plug &lt;span class="s1"&gt;'girishji/ngram-complete.vim'&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; vimcompleteoptions &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt; &lt;span class="s1"&gt;'buffer'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;     &lt;span class="s1"&gt;'enable'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;     &lt;span class="s1"&gt;'priority'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;  &lt;span class="s1"&gt;'ngram'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;     &lt;span class="s1"&gt;'enable'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;     &lt;span class="s1"&gt;'priority'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;     &lt;span class="s1"&gt;'filetypes'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'markdown'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;     &lt;span class="s1"&gt;'bigram'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
autocmd &lt;span class="nb"&gt;VimEnter&lt;/span&gt; * &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nv"&gt;g:VimCompleteOptionsSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;vimcompleteoptions&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;priority&lt;/code&gt; determines which completions show up first in the completion menu,&lt;br&gt;
with larger numbers == higher priority.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ngram-complete.vim&lt;/code&gt; allows for completion based on the frequency of words,&lt;br&gt;
making it much more useful than standard dictionary completion, which picks&lt;br&gt;
words in alphabetical order. The &lt;code&gt;bigram&lt;/code&gt; option allows completion based on&lt;br&gt;
frequency of words given the previous word rather than just the frequency of the&lt;br&gt;
current word you are completing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Auto-formatting
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;~/.vimrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;Plug &lt;span class="s1"&gt;'dense-analysis/ale'&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_fixers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="s1"&gt;'markdown'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'prettier'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/dense-analysis/ale" rel="noopener noreferrer"&gt;&lt;code&gt;ale&lt;/code&gt;&lt;/a&gt; plugin (Asynchronous Lint Engine) allows auto-formatting and linting&lt;br&gt;
in vim, running external tools asynchronously so they don't block your editing.&lt;br&gt;
With the configuration above, you can run &lt;code&gt;:ALEFix&lt;/code&gt; to format the current file,&lt;br&gt;
or add the following to have it format on save:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.vimrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_fix_on_save&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prettier
&lt;/h3&gt;

&lt;p&gt;I use &lt;a href="https://prettier.io/docs/install" rel="noopener noreferrer"&gt;&lt;code&gt;prettier&lt;/code&gt;&lt;/a&gt; to auto-format my markdown&lt;br&gt;
files so that they are easy to read.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.prettierrc.yaml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;overrides&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*.md"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*.markdown"&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;proseWrap&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;always"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;proseWrap&lt;/code&gt; automatically wraps lines into 80 character columns. Be careful when&lt;br&gt;
enabling it if you haven't started your post with it, as it can create large&lt;br&gt;
diffs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Linting
&lt;/h2&gt;

&lt;p&gt;The ale plugin enables automatic linting of your posts on save. While I don't&lt;br&gt;
use the lint features personally, I will guide you on how to set them up in case&lt;br&gt;
you find them useful.&lt;/p&gt;
&lt;h3&gt;
  
  
  Markdown-lint
&lt;/h3&gt;

&lt;p&gt;Markdown-lint highlights common issues with Markdown files. You can install it&lt;br&gt;
with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g markdownlint-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set it up with a &lt;code&gt;.markdownlint.yaml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.markdownlint.yaml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Enable all rules by default&lt;/span&gt;
&lt;span class="c1"&gt;# https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md&lt;/span&gt;
&lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="c1"&gt;# Allow inline HTML which is useful in Github-flavour markdown for:&lt;/span&gt;
&lt;span class="c1"&gt;# - crafting headings with friendly hash fragments.&lt;/span&gt;
&lt;span class="c1"&gt;# - adding collapsible sections with &amp;lt;details&amp;gt; and &amp;lt;summary&amp;gt;.&lt;/span&gt;
&lt;span class="na"&gt;MD033&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;# Ignore line length rules (as Prettier handles this).&lt;/span&gt;
&lt;span class="na"&gt;MD013&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;~/.vimrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_linters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="s1"&gt;'markdown'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'markdownlint'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Vale
&lt;/h3&gt;

&lt;p&gt;Vale is a command-line tool that brings code-like linting to prose. It is not a&lt;br&gt;
grammar checker. You can find it &lt;a href="https://vale.sh/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I did find it took a bit of effort to install and get working. Here's a guide&lt;br&gt;
for what I did:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install Vale. You can find instructions &lt;a href="https://vale.sh/docs/install" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;~/.vale.ini&lt;/code&gt; file
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# Where the styles are kept.
&lt;/span&gt;&lt;span class="py"&gt;StylesPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;.vale&lt;/span&gt;
&lt;span class="py"&gt;Packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;write-good, proselint&lt;/span&gt;

&lt;span class="py"&gt;MinAlertLevel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;suggestion&lt;/span&gt;

&lt;span class="c"&gt;# Where to look for local vocabulary files.
&lt;/span&gt;&lt;span class="py"&gt;Vocab&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Local&lt;/span&gt;

&lt;span class="c"&gt;# Define which styles to use for Markdown.
&lt;/span&gt;&lt;span class="nn"&gt;[*.{md,markdown,txt}]&lt;/span&gt;
&lt;span class="py"&gt;BasedOnStyles&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Vale, write-good, proselint&lt;/span&gt;

&lt;span class="nn"&gt;[*]&lt;/span&gt;
&lt;span class="py"&gt;BasedOnStyles&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Vale&lt;/span&gt;

&lt;span class="c"&gt;# Disable any rules that are more annoying than useful
&lt;/span&gt;&lt;span class="py"&gt;write-good.E-Prime&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;NO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create the folder &lt;code&gt;~/.vale&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;vale sync&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the folder &lt;code&gt;~/.vale/config&lt;/code&gt; and &lt;code&gt;~/.vale/config/vocabularies/Local&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the files &lt;code&gt;~/.vale/config/vocabularies/Local/accept.txt&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;~/.vale/config/vocabularies/Local/reject.txt&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you've completed these instructions, you can change your &lt;code&gt;~/.vimrc&lt;/code&gt; as&lt;br&gt;
follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.vimrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_linters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="s1"&gt;'markdown'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'vale'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'markdownlint'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Harper
&lt;/h3&gt;

&lt;p&gt;However, I found the above linters didn't highlight anything useful, and were&lt;br&gt;
more an annoyance than anything else. I next turned to &lt;a href="https://github.com/Automattic/harper" rel="noopener noreferrer"&gt;&lt;code&gt;harper&lt;/code&gt;&lt;/a&gt;, which is not&lt;br&gt;
supported by ALE, so I had to build in support for it.&lt;/p&gt;

&lt;p&gt;I am currently trying to merge the PR into the main ALE repository, and will&lt;br&gt;
update this post when it happens. But for now, you can use &lt;a href="https://github.com/ahalbert/ale" rel="noopener noreferrer"&gt;my fork&lt;/a&gt; if you want&lt;br&gt;
to try it.&lt;/p&gt;

&lt;p&gt;You can find instructions on how to install Harper&lt;br&gt;
&lt;a href="https://writewithharper.com/docs/integrations/language-server" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.vimrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" Not the standard ALE repository!&lt;/span&gt;
Plug &lt;span class="s1"&gt;'ahalbert/ale'&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_linters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="s1"&gt;'markdown'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'harper'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_markdown_harper_config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;   &lt;span class="s1"&gt;'harper-ls'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;       &lt;span class="s1"&gt;'diagnosticSeverity'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'warning'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;       &lt;span class="s1"&gt;'dialect'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'American'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;       &lt;span class="s1"&gt;'linters'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;           &lt;span class="s1"&gt;'SpellCheck'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;false&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;           &lt;span class="s1"&gt;'SentenceCapitalization'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;           &lt;span class="s1"&gt;'RepeatedWords'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;           &lt;span class="s1"&gt;'LongSentences'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;           &lt;span class="s1"&gt;'AnA'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;           &lt;span class="s1"&gt;'Spaces'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;           &lt;span class="s1"&gt;'SpelledNumbers'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;false&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;           &lt;span class="s1"&gt;'WrongQuotes'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;false&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;       &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;   &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Grammar Checking
&lt;/h2&gt;

&lt;p&gt;While Harper was more sophisticated than the linters above, none of the above&lt;br&gt;
tools really worked for me. I wanted a more sophisticated grammar checker for my&lt;br&gt;
writing. I thought an LLM was ideally suited to this task, so I built my own&lt;br&gt;
plugin &lt;a href="https://github.com/ahalbert/vim-gramaculate" rel="noopener noreferrer"&gt;&lt;code&gt;ahalbert/vim-gramaculate&lt;/code&gt;&lt;/a&gt; to check my grammar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;Plug &lt;span class="s1"&gt;'ahalbert/vim-gramaculate'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasd4mtegbvyz78i3jyxp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasd4mtegbvyz78i3jyxp.gif" alt="Gramaculate in action" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then use &lt;code&gt;:Gramaculate&lt;/code&gt; to check your grammar. By default, this uses a&lt;br&gt;
local model with Ollama, but you can&lt;br&gt;
&lt;a href="https://github.com/ahalbert/vim-gramaculate/blob/main/doc/gramaculate.txt" rel="noopener noreferrer"&gt;read the docs&lt;/a&gt;&lt;br&gt;
to configure it with any model you want, local or remote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writer's Heaven
&lt;/h2&gt;

&lt;p&gt;I find writing with vim a breeze once I got this all set up, and I hope this&lt;br&gt;
guide helps you do the same. Between spellcheck, auto-completion, formatting and&lt;br&gt;
grammar checking, vim becomes a surprisingly capable writing environment that&lt;br&gt;
stays out of your way and lets you focus on the words. If you have any&lt;br&gt;
suggestions for other plugins or workflows, feel free to reach out.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>markdown</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
