= Vim ❤️ Asciidoctor :author: Maxim Kim :experimental: :toc: left :toclevels: 3 :icons: font :autofit-option: :source-highlighter: rouge :rouge-style: github :source-linenums-option: :revdate: 2018-11-19 :imagesdir: images image::image1.png[] == Intro Vim has syntax highlighting for asciidoc out of the box. And it is/was really slow for me, probably because it tries to be very smart about syntax. This plugin: - has different syntax highlighting; - is way faster (your vim lags less :) ); - has folding; - has commands to compile documents (html, pdf, docx). == Installation === Vim8 built in packages You can use git command on your command line: [source,bash] -------- git clone https://github.com/habamax/vim-asciidoctor.git ~/.vim/pack/my-packages/start/vim-asciidoctor -------- For windows users you should change `~/.vim` to `%USERPROFILE%/vimfiles` [source,cmd] -------- git clone https://github.com/habamax/vim-asciidoctor.git %USERPROFILE%/vimfiles/pack/my-packages/start/vim-asciidoctor -------- or `minpac` package manager (to add to your `.vimrc`): [source,vim] -------- call minpac#add('habamax/vim-asciidoctor') -------- === vim-plug .Add to your .vimrc next to your other plugs [source,vim] -------- Plug 'habamax/vim-asciidoctor' -------- == Setup NOTE: To use basic asciidoctor with vim you don't have to setup anything in vim. At least this was the intention. :) The following is an example setup. Part of it might not work for you if you don't have asciidoctor extensions installed. Or you don't have custom PDF themes and fonts. .asciidoctor [source,vim] -------- " What to use for HTML, default `asciidoctor`. let g:asciidoctor_executable = 'asciidoctor' " What extensions to use for HTML, default `[]`. let g:asciidoctor_extensions = ['asciidoctor-diagram', 'asciidoctor-rouge'] " Path to the custom css let g:asciidoctor_css_path = '~/docs/AsciiDocThemes' " Custom css name to use instead of built-in let g:asciidoctor_css = 'haba-asciidoctor.css' -------- .asciidoctor-pdf [source,vim] -------- " What to use for PDF, default `asciidoctor-pdf`. let g:asciidoctor_pdf_executable = 'asciidoctor-pdf' " What extensions to use for PDF, default `[]`. let g:asciidoctor_pdf_extensions = ['asciidoctor-diagram'] " Path to PDF themes, default `''`. let g:asciidoctor_pdf_themes_path = '~/docs/AsciiDocThemes' " Path to PDF fonts, default `''`. let g:asciidoctor_pdf_fonts_path = '~/docs/AsciiDocThemes/fonts' -------- .asciidoctor-docx [source,vim] -------- " What to use for DOCX, default `pandoc`. " The DOCX 'compilation' process is to generate `docbook` using " `g:asciidoctor_executable` and then to generate DOCX out of `docbook` " using `pandoc`. let g:asciidoctor_pandoc_executable = 'pandoc' "" --data-dir let g:asciidoctor_pandoc_data_dir = '~/docs/.pandoc' " Other parameters you want to feed pandoc let g:asciidoctor_pandoc_other_params = '--toc' " Reference document to reuse styles " If not set up asciidoctor looks for the theme name " :pdf-style: mytheme " in the first 30 lines and generate reference-doc filename: " g:asciidoctor_pandoc_data_dir + mytheme + '-reference.docx' " for example: ~/docs/.pandoc/mytheme-reference.docx let g:asciidoctor_pandoc_reference_doc = 'custom-reference.docx' -------- .folding [source,vim] -------- " Fold sections, default `0`. let g:asciidoctor_folding = 1 " Fold options, default `0`. let g:asciidoctor_fold_options = 1 -------- .syntax [source,vim] -------- " Conceal *bold*, _italic_, `code` and urls in lists and paragraphs, default `0`. " See limitations in end of the README let g:asciidoctor_syntax_conceal = 1 " Highlight indented text, default `1`. let g:asciidoctor_syntax_indented = 0 -------- .syntax highlighting for languages in [source] blocks [source,vim] -------- " List of filetypes to highlight, default `[]` let g:asciidoctor_fenced_languages = ['python', 'c', 'javascript'] -------- .default mappings... there are no default mappings [source,vim] -------- " Function to create buffer local mappings and add default compiler fun! AsciidoctorMappings() nnoremap oo :AsciidoctorOpenRAW nnoremap op :AsciidoctorOpenPDF nnoremap oh :AsciidoctorOpenHTML nnoremap ox :AsciidoctorOpenDOCX nnoremap ch :Asciidoctor2HTML nnoremap cp :Asciidoctor2PDF nnoremap cx :Asciidoctor2DOCX nnoremap p :AsciidoctorPasteImage " :make will build pdfs compiler asciidoctor2pdf endfun " Call AsciidoctorMappings for all `*.adoc` and `*.asciidoc` files augroup asciidoctor au! au BufEnter *.adoc,*.asciidoc call AsciidoctorMappings() augroup END -------- == Commands All commands are buffer local -- available only for asciidoctor files (`set filetype=asciidoctor`) * `Asciidoctor2HTML` -- convert current file to `HTML`. * `Asciidoctor2PDF` -- convert current file to `PDF`. * `Asciidoctor2DOCX` -- convert current file to `DOCX`. * `AsciidoctorOpenRAW` -- open current file in a browser. Chrome and Firefox has extentsions to render barebone `adoc` files. * `AsciidoctorOpenPDF` -- open `PDF` of the current file using default PDF viewer. * `AsciidoctorOpenHTML` -- open `HTML` of the current file using default web browser. * `AsciidoctorOpenDOCX` -- open `DOCX` of the current file using default DOCX viewer. (I haven't tried it with LibreOffice or whatever else there might be. Also haven't tried it on linux and OSX...) [NOTE] ====== Commands: `Asciidoctor2HTML`, `Asciidoctor2PDF` should convert files if link:https://asciidoctor.org/docs/user-manual/#installing-the-asciidoctor-ruby-gem[asciidoctor] and link:https://github.com/asciidoctor/asciidoctor-pdf#getting-started[asciidoctor-pdf] are installed. Command `Asciidoctor2DOCX` should also have link:https://pandoc.org/installing.html[pandoc] installed. ====== == Usage 1. Open `~/test.adoc` 2. Enter: + [literal] ......... = Asciidoctor Title: Hanging around This is the first para and it will be rendered with bigger text. == Section 1 Text of section 1 == Section 2 Text of section 2 ......... 3. Save it and export to `HTML` + [literal] ......... :w :Asciidoctor2HTML ......... 4. Open the `HTML` file: + [literal] ......... :AsciidoctorOpenHTML ......... // pics === HTML output That should look something like this: .HTML output image::test_html.png[] === DOCX output If you use `:Asciidoctor2DOCX` and `:AsciidoctorOpenDOCX` commands instead, you should see something like this (provided you have `pandoc` and `MSWord` installed:) .DOCX output image::test_docx.png[] === PDF output And if you use `:Asciidoctor2PDF` and `:AsciidoctorOpenPDF` commands, you should see something like this (I have my own default theme and fonts, so you probably see it a bit different) : .PDF title page output image::test_pdf1.png[] .PDF first page output image::test_pdf2.png[] // add some short youtube videos == Paste images from clipboard Vim can't access graphical part of clipboard thus an external tool should be used to save clipboard image to a png file. * For Windows I use GraphicsMagic (could be installed using `scoop`) * For OSX I use `pngpaste` (could be installed using `brew`) * For Linux -- `xclip` could be used (thx Matthias Fulz @mfulz) image::https://github.com/habamax/habamax.github.io/blob/master/assets/gifs/asciidoctor-pasteimg.gif[animated screen with image pasting] .setup [source,vim] -------- " first `%s` is a path " second `%s` is an image file name " this is default for windows let g:asciidoctor_img_paste_command = 'gm convert clipboard: %s%s' " for osx " let g:asciidoctor_img_paste_command = 'pngpaste %s%s' " for linux " let g:asciidoctor_img_paste_command = 'xclip -selection clipboard -t image/png -o > %s%s' " first `%s` is a base document name: " (~/docs/hello-world.adoc => hello-world) " second `%s` is a number of the image. let g:asciidoctor_img_paste_pattern = 'img_%s_%s.png' -------- If there is `:imagesdir:` as an option set up in a document, clipboard image is saved there (relative to the document). Otherwise image is saved in the documents directory. The name of the image is generated according to the pattern. By default it is img_ + document_base_name + next_image_number + .png == Bibliography completion There is initial support for bibliography completion. Works with `*.bib` files placed to the same folder as file being edited. No setup is needed although additional setting for a base bibtex folder might be added in the future. It uses vim's `completefunc` which is usually called in insert mode with kbd:[], and it works for [source] ---- cite:[ cite:[cit citenp:[cit ---- [NOTE] ====== To create bibliography in asciidoctor, i.e., to put it into PDF or HTML you should install https://github.com/asciidoctor/asciidoctor-bibtex[asciidoctor-bibtex] extension and provide it to vim-asciidoctor extension list(s): [source,vim] " For asciidoctor backend let g:asciidoctor_extensions = ['asciidoctor-bibtex'] " For asciidoctor-pdf backend let g:asciidoctor_pdf_extensions = ['asciidoctor-bibtex'] ====== == Misc === Generate HTML on file save Add following snippet to your vim config to generate an HTML file upon saving: [source,vim] -------- augroup ON_ASCIIDOCTOR_SAVE | au! au BufWritePost *.adoc :Asciidoctor2HTML augroup end -------- If you want to add text files to the mix you can have something similar to: [source,vim] -------- func! ConvertAsciidoctorToHTML() " Text file with asciidoctor contents? if &filetype == 'text' && getline(1) =~ '^= .*$' " text files have no asciidoctor commands set filetype=asciidoctor Asciidoctor2HTML set filetype=text elseif &filetype == 'asciidoctor' Asciidoctor2HTML endif endfunc augroup ON_ASCIIDOCTOR_SAVE | au! au BufWritePost *.adoc,*.txt call ConvertAsciidoctorToHTML() augroup end -------- NOTE: if you have link:https://github.com/tpope/vim-dispatch[vim-dispatch] installed HTML conversion would be done in background. === Highlight group names Colorschemes can use following highlight groups to redefine default highlighting: [cols=".^1,.^1", options="header"] |=== | Highlight Group Name | Default Value |asciidoctorTitle |Title |asciidoctorSetextHeader |Title |asciidoctorH1 |Title |asciidoctorH2 |Title |asciidoctorH3 |Title |asciidoctorH4 |Title |asciidoctorH5 |Title |asciidoctorH6 |Title |asciidoctorTitleDelimiter |Type |asciidoctorH1Delimiter |Type |asciidoctorH2Delimiter |Type |asciidoctorH3Delimiter |Type |asciidoctorH4Delimiter |Type |asciidoctorH5Delimiter |Type |asciidoctorH6Delimiter |Type |asciidoctorSetextHeaderDelimiter |Type |asciidoctorListMarker |Delimiter |asciidoctorOrderedListMarker |asciidoctorListMarker |asciidoctorListContinuation |PreProc |asciidoctorComment |Comment |asciidoctorIndented |Comment |asciidoctorPlus |PreProc |asciidoctorPageBreak |PreProc |asciidoctorCallout |Float |asciidoctorCalloutDesc |String |asciidoctorListingBlock |Comment |asciidoctorLiteralBlock |Comment |asciidoctorFile |Underlined |asciidoctorUrl |Underlined |asciidoctorEmail |Underlined |asciidoctorUrlAuto |Underlined |asciidoctorEmailAuto |Underlined |asciidoctorUrlDescription |String |asciidoctorLink |Underlined |asciidoctorAnchor |Underlined |asciidoctorAttribute |Identifier |asciidoctorCode |Constant |asciidoctorOption |PreProc |asciidoctorBlock |PreProc |asciidoctorBlockOptions |PreProc |asciidoctorTableSep |PreProc |asciidoctorTableCell |PreProc |asciidoctorTableEmbed |PreProc |asciidoctorInlineAnchor |PreProc |asciidoctorMacro |Macro |asciidoctorIndexTerm |Macro |asciidoctorBold |gui=bold cterm=bold |asciidoctorItalic |gui=italic cterm=italic |asciidoctorBoldItalic |gui=bold,italic cterm=bold,italic |=== If you want to change highlight yourself for existing colorscheme without touching it, add the following to you vimrc: [source,vim] -------- func! AsciidoctorHighlight() " Highlight asciidoctor syntax with colors you like. " For solarized8 colorscheme if get(g:, "colors_name", "default") == "solarized8" hi asciidoctorTitle guifg=#ff0000 gui=bold ctermfg=red cterm=bold hi asciidoctorOption guifg=#00ff00 ctermfg=green hi link asciidoctorH1 Directory elseif get(g:, "colors_name", "default") == "default" hi link asciidoctorIndented PreProc endif endfunc augroup ASCIIDOCTOR_COLORS | au! au Colorscheme * call AsciidoctorHighlight() au BufNew,BufRead *.adoc call AsciidoctorHighlight() augroup end -------- == Limitations === Indented text is highlighted for all table cells Works for all table cells, although should only be applied to `a|` cells. [source] -------- [cols=".^1,.^2", options="header"] |=== | header1 | header1 | Regular table cell Indented text is highlighted as indented which is kind of incorrect a| Asciidoctor cell Indented text is highlighted as indented which is correct |=== -------- === Setext-style headers highlighting Proper setext-style highlighting should have equal numbers of underlined chars: ---- This Header level 1 =================== This Header level 2 ------------------- This Header level 3 ~~~~~~~~~~~~~~~~~~~ This Header level 4 ^^^^^^^^^^^^^^^^^^^ This Header level 5 +++++++++++++++++++ ---- Vim can't do it so setext-style headers are highlighted no matter if there is matched underline or not. ---- This Header level 1 ====================== This Header level 2 ----- This Header level 3 ~~~~~~~~~~~~~~~~ This Header level 4 ^^^^^^^^^^^^^^^^^^^^ This Header level 5 +++++++++++++ ---- You can also use following mappings: [source,vim] -------- " Underline current line func! s:underline(chars) let nextnr = line('.') + 1 let underline = repeat(a:chars[0], strchars(getline('.'))) if index(a:chars, trim(getline(nextnr))[0]) != -1 call setline(nextnr, underline) else call append('.', underline) endif endfunc nnoremap - :call underline(['-', '=', '~', '^', '+']) nnoremap = :call underline(['=', '-', '~', '^', '+']) nnoremap ~ :call underline(['~', '=', '-', '^', '+']) nnoremap ^ :call underline(['^', '=', '-', '~', '+']) nnoremap + :call underline(['+', '=', '-', '~', '^']) -------- === URL Conceal Links with additional attributes are not concealed to description: https://discuss.asciidoctor.org[Discuss Asciidoctor,role=external,window=_blank] https://discuss.asciidoctor.org[Discuss Asciidoctor^] https://example.org["Google, Yahoo, Bing^",role=teal] With `set conceallevel=3` looks like: Discuss Asciidoctor,role=external,window=_blank Discuss Asciidoctor^ "Google, Yahoo, Bing^",role=teal Although it should look like: Discuss Asciidoctor Discuss Asciidoctor Google, Yahoo, Bing