2010-10

Playing with AsciiDoc

2010-10-31 12:10:25 +0900 / tag:asciidoc / Comments

Git is an well-documented project. There are comprehensive reference manuals and user guide. When I read the reference manuals to learn about Git, I found that some sections are appeared in several manuals. For example, both git show manual and git log manual have the same “PRETTY FORMATS” section. I assumed that there is a file for such section and the file is included into each manual. I wondered how the manuals are written.

Then I found that the documents of Git are written in AsciiDoc. At first I thought that it’s yet another lightweight markup language. But I noticed that it’s interesting enough. Because ‘the most of AsciiDoc syntax is defined at higher level’, so that ‘it’s easy to customize AsciiDoc syntax’.

For example, a link in AsciiDoc is written as follows:

http://github.com/kana[github:kana]

If you want to write github:kana instead, you can define a macro like the following:

[macros]
(?su)(?P<name>github):(?P<target>\w+)=
 
# For DocBook backend.
[github-inlinemacro]
<ulink url="http://github.com/{target}">github:{target}</ulink>

Save the above text as a file, then convert arbitrary text with a command like asciidoc -b docbook -f custom.conf source.txt. Though macros in AsciiDoc are not expanded recursively, it seems to be enough for practical use.

Vim: Thought on :set foldopen+=map

2010-10-30 21:48:10 +0900 / tag:vim / Comments

Problem

As I wrote before, there is a firm reason why 'foldopen' ignores cursor movement via key mappings. It’s like why s: (script-local prefix) must be written as <SID> in key mappings.

It’s nearly impossible to automatically distinguish whether s: in {rhs} is a script-local prefix or not, because s: may be remapped to other key sequence, so that the meaning of a s: cannot be determined when a key mapping is defined.

Like this, the meaning of {rhs} of a key mapping can be determined only by a user who wrote the key mapping. For example, let’s consider about the following key mapping:

noremap <Esc>)  ])

It seems that the author of the key mapping defined a new motion. If so, the key mapping should open a closed fold by default. But it cannot be asserted that the author intended to define the key mapping as a motion. That’s why 'foldopen' ignores cursor movement via key mappings.

Therefore I have to add zv for each key mappinpg which moves the cursor position. But there are a few problems to add zv:

Idea

How about the following syntax?

Movement noremap <Esc>)  ])
Movement cnoremap qj  :<C-u>cnext<Return>

It will be translated into the following definition (it’s just an image; not tested):

noremap <script> <Esc>)  <SID>(movement-begin)<SID>(movement:<Esc>))<SID>(movement-end)
noremap <SID>(movement:<Esc>))  ])
cnoremap <script> qj  <SID>(movement-begin)<SID>(movement:qj)<SID>(movement-end)
cnoremap <SID>(movement:qj)  :<C-u>cnext<Return>
noremap <expr> <SID>(movement-begin)  <SID>movement_begin()
noremap! <expr> <SID>(movement-begin)  <SID>movement_begin()
noremap <expr> <SID>(movement-end)  <SID>movement_end()
noremap! <expr> <SID>(movement-end)  <SID>movement_end()
 
let s:movement_nest = 0
let s:original_cursor_position = []
 
function s:movement_begin()
  let s:movement_nest += 1
  let s:original_cursor_position = getpos('.')
  return ''
endfunction
 
function s:movement_end()
  let s:movement_nest -= 1
  if s:movement_nest == 0
    if s:original_cursor_position != getpos('.')
      normal! zv
    endif
  endif
  return ''
endfunction

Vim patch: :set foldopen+=map

2010-10-23 00:23:15 +0900 / tag:vim / Comments

Introduction

When the cursor is moved into a closed fold, the fold is automatially opened in many cases. Most of movement commands automatially opens a fold while several commands don’t open. This behavior is configurable by the global option 'foldopen'.

And a closed fold is not automatically opened by a movement command which is executed via any key mapping. For example, moving the cursor with h or l in a closed fold opens the fold by default. If h or l are mapped from some key mappings like the following, they don’t open a closed fold anymore:

noremap h  h
noremap l  l

It’s possible to fix the behavior by adding zv (which opens all folds including the cursor) to mapped commands. For example:

noremap h  hzv
noremap l  lzv

The Problem

The problem is that the current behavior of 'foldopen' is not intuitive. And :help 'foldopen' doesn’t describe why it behaves so. Many users stumbled on the behavior and reported to vim-dev and vim-use.

Advanced users define many key mappings. It’s a painful work to add zv for each key mapping. And it’s easy to forget about zv even if the number of key mappings is small. It also makes vimrc crappy. For example, I define more than 300 key mappings in my vimrc. No one wants to add zv to such stuffs.

And what was even worse, it’s not practical to add zv for all key mappings. For example:

noremap /  :<C-u>set noincsearch<Return>/
noremap g/  :<C-u>set incsearch<Return>/

It adjusts how /, the search command behaves. / requires a search pattern and the search pattern is inputted interactively. How do I add zv for it? There are other cases like this.

The Solution

So I wrote a patch to improve the current behavior of 'foldopen'. The patch introduces new item “map” for 'foldopen'. If the value of 'foldopen' contains “map”, a closed fold will be automatically opened by a movement command, regardless of key mappings.

Add the following line into your vimrc to take effect the patch:

set foldopen+=map

Notes

(2010-10-24T02:55:16+09:00) As I reconsidered about the patch, it doesn’t make a sense. :help 'foldopen' should have a description like the following:

When user defines a key mapping like the following:

noremap <C-n>  }}}

The user probably expects <C-n> to work as a new motion, not moving the cursor 3 times. So if <C-n> should open a fold automatically, it should behave }}}zv, not }zv}zv}zv. That’s why the current 'foldopen' doesn’t work for any key mappings.