This is a file type plugin (ftplugin
) for Vim.
It provides support for working efficiently with AsciiDoc files in Vim.
I recommend using git
and Tim Pope’s pathogen plugin:
cd ~/.vim/bundle && \
git clone git://github.com/jjaderberg/vim-ft-asciidoc.git
If you are concerned about having your configuration overridden by a plugin, I salute you and please see Appendix A.
-
Bindings for common editing operations
-
One sentence per line
-
Insert blocks (code, quote, NOTE, etc.)
-
Format text (words and chars)
-
Change/delete/yank document sections.
-
Insert macros (kbd, image, include, etc.)
-
Insert cross references
-
Toggle title (ATX/SetExt style)
-
Support for working with tables and lists
-
-
Set
'makeprg'
for easy compiling (withasciidoctor
, minimal support for parameters through buffer local variables.) -
Support compile on save
-
Basic folding support
-
Navigation
-
Follow cross references
-
Follow external links
-
-
Set basic options, like the correct
'commentstring'
. -
Experimental
-
Block formatting by motions
-
Text objects for blocks and list items
-
Delete or change block delimiters (surroundings)
-
-
Incomplete help. A first iteration is there, but plenty of work before it’s up to snuff.
-
Bias.
-
I use the Asciidoctor processor and abide by a company style guide. This informs how the plugin works.
-
I mostly use a Mac with Vim 7.4.903 and Firefox. I have not really tested the plugin with other systems.
-
Some things are hard coded in the plugin that shouldn’t be.
-
Bloat. The plugin does too much and not enough. The compile stuff should be in a compiler plugin, for example, but then I would have to define error format for consumption in quick list, and…
-
I’d like to see these things improved, but I don’t know when (if) I’ll have time.
Editing support includes:
-
Turn a paragraph into one-sentence-per-line.
-
Insert different kinds of paragraphs (blocks).
-
Format text.
-
Insert and edit tables.
-
Operate on sections.
-
Insert macros and cross references.
Important
|
All maps defined in the plugin begin with |
You have a paragraph of text. It contains multiple sentences. Are they written on the same line? Do they contain arbitrary line breaks? Do you wish there were a convenient way to Zenify the paragraph? You know, so that you get the benefits of easy diffing, efficient editing, and the bonus safeguard: very long sentences stick out like a sore thumb?
If you abide by the Zen of "one sentence per line", position the cursor anywhere in the paragraph and type ,spl.
You have a paragraph of text. It contains multiple sentences. Are they written on the same line? Do they contain arbitrary line breaks? Do you wish there were a convenient way to Zenify the paragraph? You know, so that you get the benefits of easy diffing, efficient editing, and the bonus safeguard: very long sentences stick out like a sore thumb?
The operation will recognize some paragraph boundaries: empty line or line beginning with two or more of -_.*+=
.
It therefore usually works just fine to do this on a formatted block.
The operation may fail to recognize the boundaries of some paragraph, or you may want to format part of a paragraph. In this case, visually select the lines to format and the operation will limit itself to these lines.
Work with different kinds of paragraphs/blocks. Insert a new code block, or turn a sentence or paragraph into a quote or admonition.
Let’s say I write documentation and want to provide a "before" and "after" example. For this I may use two literal blocks, containing the "before" and "after" text. In insert mode I type ,literal. This gives me a literal block:
.... [] ....
[]
signifies the location of the cursor.
Most editing operations have maps defined for normal, insert or visual mode. These use the same left hand side. If I have some text already present in a paragraph, I can insert that text into a block using the same keys. Take a paragraph like
Paragraph. Short but sweet. Indeed.
If I visually select this paragraph, for instance with vip, and then type ,literal, I get
.... Paragraph. Short but sweet. Indeed. ....
To comment out the visually selected block, I type ,comment.
//// Paragraph. Short but sweet. Indeed. ////
For blocks, the normal mode maps generally operate on the cursor line. If instead of selecting the paragraph I rest the cursor on the middle line, ,example gives
Paragraph. ==== Short but sweet. ==== Indeed.
Similar to code and example blocks, admonitions can be created from normal, insert and visual modes. Typing ,note in insert mode will give:
[NOTE] -- --
With a visual selection, the selected text will be inside the block.
Note
|
I use open blocks for admonitions. To use a different block type you will have to fork and change the code. It would be desirable to let the block type be controlled by an option or parameter. If you decide to implement this, please consider sharing your improvements by submitting a PR. |
admonitions (NOTE, etc.) |
,caution, ,important, ,note, ,tip, ,warning |
comment |
,comment |
example |
,example |
listing (code) |
,code |
literal |
,literal |
passthrough |
,passthrough |
quote |
,quote |
sidebar |
,sidebar |
source |
,source |
verse |
,verse |
Each of these operations have maps with the same left hand side for normal, insert and visual modes.
Typing ,passthrough looks like about the same amount of work as making the corresponding edit manually.
However, for all their verbosity, I find these maps tremendously helpful.
I do think shorter lhs
is desirable—I just haven’t come up with the right convention yet.
Some operations have added sugar. For example, typing ,quote to get a quote block will add the quote attribute, along with placeholder author and source. The author and source will be visually selected, and can easily be edited or removed with normal Vim commands.
[quote, author, source] ____ Parvus error in principio magnus est in fine. ____
Inline text formatting can be achieved for all the quote or format styles.
To emphasize a word, rest the cursor on it and type ,te.
To mark part of a word as strong, visually select that part and type ,ts.
To ma**rk** p**ar**t of a **wor**d as *strong*, **visu**ally select **tha**t part and type kbd:[,ts].
If the visual selection is over the entire word, the single format character is added. If the visual selection is over part of a word, the double format character is added. The same maps handle both of these notations.
In addition to the ordinary text formatting operations there are maps for strike out, and for "empty" attributes:
Strike me out and give me an attribute!
Select the first three words and press ,t-, then select the last four words and type ,ta.
[line-through]#Strike me out# and []#give me an attribute#!
When adding an empty attribute, the operation leaves the cursor in insert mode between the brackets.
code |
,tc |
emphasis |
,te |
passthrough |
,tp |
strong |
,ts |
subscript |
,tj |
superscript |
,tk |
strike-out |
,t- |
attribute |
,ta |
Tip
|
Mnemonic: text emphasis, etc. For subscript and superscript the memory devise is j for down and k for up. For strike-out, it’s a dash. |
The plugin includes some table support:
-
Insert tables (or insert text into tables).
-
Operate on tables as text objects ,it ,at.
-
Add attributes to existing table.
Similar to blocks, tables can be inserted with ,table. In insert mode this gives:
|=== | |===
For normal and visual modes also, behaviour is similar to block editing.
Paragraph. Short but sweet. Indeed.
In normal mode, the table will contain the cursor line. If necessary, a blank line is added above and below.
Paragraph. |=== | Short but sweet. |=== Indeed.
For visual selections, the lines will be put into the table. Newline padding is added above and below, as needed. Selecting the two first lines in before and typing ,table will result in:
|=== | Paragraph. | Short but sweet. |=== Indeed.
There are two table text objects: ,it and ,at. To visually select "inner table", that is, the lines within the table, use v,it. To delete "a table", use d,at.
The cursor motions ]] and [[ move forward and backward to section titles. These motions can be used with all the ordinary Vim operators, allowing them to operate over document sections.
c][ |
Change from cursor to end of section. |
d2][ |
Delete from cursor to end of section and the following section. |
y[[ |
Yank from cursor to beginning of section. |
[]d[[ |
Delete the previous section. |
[[v][ |
Visually select the whole current section. |
]]g?][ |
ROT13-encode the section following the current section. |
There is some support for inserting macros. Operations with macros are handled in two by two ways. A macro is either inserted as a block, or an inline macro. Additionally, input to the operation (if there is any) is treated as either macro attributes or macro target. Consider:
Look at images/image.img it is beautiful!
To turn the file path above into an image macro, rest the cursor on it and type ,img. (Visually selecting also works.)
Look at image:images/image.img[] it is beautiful!
In this case, the file path is the target of the image macro.
There are other cases, like the ]
macros that are littered throughout this document.
The text from which I want to create a kbd macro is not going to make sense as a target+but as attributes in the macro.
If the cursor is over the text+or the text is visually selected+typing kbd:[,kbd will turn
\kbd
into
kbd:[,kbd]
The ,btn, ,kbd, and ,menu normal mode maps operate on the big WORD under the cursor.
Macros | |
---|---|
image |
,img |
keyboard |
,kbd |
menu |
,menu |
button |
,btn |
include |
,inc |
Another editing operation that is mapped is turning a string into a cross reference.
Check out the section on Macros if you haven't already.
Position the cursor over a word, or visually select some text, then type ,xr.
Check out the <<section-on-Macros, section on Macros>> if you haven't already.
The operation does some substitutions on the input to generate a valid ref target (though it doesn’t validate that the target exists). The input text remains and is now the name of the reference.
It is recommended to use the ATX style for titles rather than the Setex style. Both are valid AsciiDoc, however, and whether one chooses to go against recommendation, or is working with source created by others, it can be useful to toggle between the two styles. Typing ,tt will toggle the title of the current section between the two styles.
The plugin sets up Vim’s 'makeprg'
to use asciidoctor
.
Some buffer local variables can be set in order to pass parameters to the processor.
|
|
|
|
|
|
The buffer local variables are included in 'makefile'
when the plugin is loaded.
You can begin editing your file, set these options, and then reload the plugin by 're-editing', with :e.
If you compile most of your documents on a proper build system, this is useful for the one-off open ended edits.
For anything else this workflow is somewhat broken.
I would like to see it improved, deo volente.
The nice feature here, however, is "compile on save". By typing ,qi, "Quick Iteration" mode is toggled. Every time the buffer is saved, the file is compiled. Use the same command to toggle it off.
A simple expression folding function is included to fold on section titles.
The plugin sets fdm=expr
without consideration for your preferences.
If you don’t like this, consider removing that code, or setting a modeline.
If you fork and edit the plugin to handle this more gracefully, please consider issuing a PR.
To preview the file being edited in an external application, type ,pf.
This will run an !open
command for the current file and ask application g:asciidoc_preview_app
to open the current file.
The preview command is not very portable, especially since the preview application is hard coded to be Firefox. If you don’t use Firefox and asciidoctor.js for previewing, then you should change or not use this feature. (If you improve it, consider issuing a PR!)
For navigating between titles, use the ]] and [[ motions. These move to the next and previous section titles, respectively. ][ and [] move to next and previous section end. These motions can be used with operators, see Editing: Motions.
Vim has excellent support for navigating between files, including the gf
command to edit a file whose name is the text under the cursor.
Similarly, with ctags
or cscope
, navigating different references between files is a breeze.
With AsciiDoc, there are cases where these don’t work well, however.
Particularly this is true when links or filenames contain attribute references.
Tip
|
Unrelated to this plugin, for --langdef=asciidoc --langmap=asciidoc:.ad.adoc.asciidoc --regex-asciidoc=/^=[ \t]+(.*)/# \1/h/ --regex-asciidoc=/^==[ \t]+(.*)/. \1/h/ --regex-asciidoc=/^===[ \t]+(.*)/. . \1/h/ --regex-asciidoc=/^====[ \t]+(.*)/. . . \1/h/ --regex-asciidoc=/^=====[ \t]+(.*)/. . . . \1/h/ --regex-asciidoc=/^======[ \t]+(.*)/. . . . \1/h/ --regex-asciidoc=/^=======[ \t]+(.*)/. . . . \1/h/ --regex-asciidoc=/\[\[([^]]+)\]\]/\1/a/ --regex-asciidoc=/^\.([^ \t].+)/\1/t/ --regex-asciidoc=/image::([^\[]+)/\1/i/ --regex-asciidoc=/image:([^:][^\[]+)/\1/I/ --regex-asciidoc=/include::([^\[]+)/\1/n/ |
This plugin has mappings for navigating both internal and external links, and will substitute attribute values for their references in links. Consider this document:
= Doc :attr1: some :attr2: some-other :attr3: someone-else Compare <<{attr1}-section, Some section>> to <<other.adoc#{attr2}-section, Some other section>>. Submit your questions to link:http://www.{attr3}.org[someone's website]. [[some-section]] == Some section
Let’s assume that there is a file called other-doc.adoc
containing the [[some-other-section]]
anchor.
With the cursor on either cross reference, type ,gf to go to the corresponding anchor.
The plugin reads off all attributes in the document and performs the substitution.
If the resulting link contains both a filename and an anchor reference, then the file is opened and the anchor is searched for. If there is no filename, the anchor is searched for in the current document.
If there is a filename, but the file doesn’t exist, the user is prompted whether to proceed editing a new file. This is useful for creating a link before creating a new document, for instance in a note taking system or Wiki. If editing proceeds, a new buffer is opened for the file, but it is not saved. The anchor is put into the buffer as a reminder to include the link target which was used to navigate to the file.
Note
|
Attribute substitution only works for attributes that are set in the current document. If the attribute is set in another document, which includes the current document, the substitution will fail. |
As with cross references, external links can be navigated, using the same command.
For the link above, the attribute attr3
is interpolated and the link http://www.someone-else.org/
is then followed.
External links are opened with the application recorded in g:asciidoc_browser
with a simple !open
command.
For now, the browser option is hard coded as Firefox.
It should be easy to set that up properly, but it’s not a priority for me at the moment.
Preview file with |
,of |
Follow link under cursor in |
|
… the current buffer or browser |
,gf |
… a horizontal split or browser |
,<C-W>f |
… a vertical split or browser |
,<C-W><C-F> |
… a new tab or browser |
,<C-W>gf |
Experimental features that may or may note mature.
By typing ,bl followed by a motion, the text encompassed by the motion can be formatted as a block. The command requests user input to determine which block type to produce:
'q': 'quote' '-': 'listing' 'v': 'verse' 'o': 'open' '*': 'sidebar' '+': 'passthrough' '=': 'example' '.': 'literal' '/': 'comment'
,blip/<CR> will format the inner paragraph surrounding the cursor as a comment block.
Doing c,ab changes a block, d,ib deletes inner block, v,il visually selects inner list item (useful for multi-line list items).
There is also a poor man’s surround functionality for deleting or changing the delimiters of a block: ,dsb and ,csb respectively.
The experimental block operations generally prompt for which type of block to work with. The change block delimiters operation prompts twice: once for the removal and once for the replacement.
By default, the plugin will set a few options and variables, and create lots of maps.
All maps are buffer local and begin with <LocalLeader>
.
You can prevent this by setting let g:asciidoc_use_defaults = []
in your vimrc.
The functions and commands will be created, but they will not be mapped and no options will be set.
Here is how the plugin sets it if you don’t, use it for inspiration:
let g:asciidoc_use_defaults = ['folding', 'editing', 'navigating', 'compiling', 'options']
Tip
|
Not loading the defaults will render the plugin rather useless, why would you want to do that?
For a start, it is polite to make it easy to prevent a plugin from overwriting ones configuration.
Additionally, you may want to use some of the functionality but provide your own maps.
For example, disable 'editing'.
Then yank-put the editing section from |