Saturday, February 9, 2013

SinTax Overdue

Syntax highlighting in Vim sucks.

I know. I haven't done as much of it as you have, but I've heard your cries from my cubicle, your desperate pleas for compassion whispered over and again at your desk to an uncaring Vim, your brave face masking knots of terror while chatting at the water cooler, and your wails of despair in the toilet stall when you thought everyone else had gone. It's been hard watching you go through this and for long now I've wished there was something I could do to ease your burden, to still your trembling hand, wipe the tears from your keyboard and tell you that "It's going to be okay." Of course, I couldn't do that. Nobody could. I'd be lying and you know it. My words would come across as naive, empty platitudes at best or, at worst, taken for cruel taunts to mock your effort, halt your progress and rob you of your due standing among the Nerds of Vim.

That was how we all lived. That is... before THEY came!



SinTax is a Vim plugin that provides a DSL for crafting syntax highlighting files.

It takes this:


" Vim syntax plugin for filetype name.
" Maintainer: Barry Arthur <barry.arthur@gmail.com>
" Israel Chauca F. <israelchauca@gmail.com>
" Version: 0.1
" Description: Long description.
" Last Change: 2013-02-01
" License: Vim License (see :help license)
" Location: syntax/vrs.vim
" Website: https://github.com/Raimondi/vrs

name    vrs
case    ignore
spell   default

keyword vrsTodo    .Todo : TODO FIXME XXX

partial token \S\+\s\+

partial separator
    \%(
      \\}          # an_escaped_\}
    \|             # or
      [^}]         # anything_but_a_}
    \)

match vrsNameErr   .Error      contained : ^\%{token}

match vrsName      .Identifier contained : ^\w\+\s\+

match vrsFlavorErr .Error      contained
  \%(
    ^\%{token}     # if_the_line_starts_with_a_token
  \)\@<=           #   before
  \%{token}        # a_token

match vrsFlavor    .Type       contained
  \%(
    ^\%{token}     # if_the_line_starts_with_a_token
  \)\@<=           #   before
  \%{vrsName}      # a_vrsName

match vrsCompItem  .Normal     contained
    \w\+           # a_word
  \|               # or
    \d\+           # a_number
  \|               # or
    ,\@<=          # a_separator_if_proceeded_by_a_comma
    \%{separator}\+

" match a composition atom: \%{pattern-name,count,separator}
match vrsCompose   .PreProc    contained contains=vrsCompItem
  \\%{             # a_literal_\{
    \S\+           # a_word_(pattern-name)
    ,              # a_comma
    \d\+           # a_number_(count)
    ,              # a_comma
    \%{separator}* # an_optional_separator
  }                # and_a_literal_}

match vrsRegExp    .String     contains=vrsCompose contained
  \%(
    ^\%{token,2}   # if_the_line_starts_with_two_tokens
  \)\@<=           #   before
  .*               # anything

match vrsCommand              contains=vrsName,vrsFlavor,vrsNameErr,vrsFlavorErr,vrsRegExp,vrsComment
  ^\%{token,2}\S.* # a_line_with_three_'tokens'_minimum

match vrsContinued .String     contains=vrsComment
  ^\s\+\S.*        # a_line_with_leading_whitespace_and_a_'token'

match vrsComment   .Comment    containedin=ALL contains=vrsTodo
  \%(              # as_long_as
    \%(
      \\ \\        #   (ignoring_any_number_of_double_backslashes_(\\))
    \)*
    \\             #   a_backslash
  \)\@<!           # doesn't_precede
  #.*$             # a_literal_#_followed_by_anything

match vrsError     .Error
  ^                # any_line_starting_with
  [^a-zA-Z0-9_#\ ] # anything_that's_not_alphanumeric,_underscore,_hash_or_a_space
  .*               # and_anything_afterwards



And generates this:



" Vim syntax plugin for filetype name.
" Maintainer: Barry Arthur <barry.arthur@gmail.com>
" Israel Chauca F. <israelchauca@gmail.com>
" Version: 0.1
" Description: Long description.
" Last Change: 2013-02-01
" License: Vim License (see :help license)
" Location: syntax/vrs.vim
" Website: https://github.com/Raimondi/vrs

" Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax")
  finish
endif

" Allow use of line continuation.
let s:save_cpo = &cpo
set cpo&vim

syntax case ignore
syntax spell default
syntax keyword vrsTodo  TODO FIXME XXX 
syntax match vrsNameErr /^\S\+\s\+/ contained 
syntax match vrsName /^\w\+\s\+/ contained 
syntax match vrsFlavorErr /\%(^\S\+\s\+\)\@<=\S\+\s\+/ contained
syntax match vrsFlavor /\%(^\S\+\s\+\)\@<=^\w\+\s\+/ contained
" match a composition atom: \%{pattern-name,count,separator}
syntax match vrsCompItem /\w\+\|\d\+\|,\@<=\%(\\}\|[^}]\)\+/ contained
syntax match vrsCompose /\\%{\S\+,\d\+,\%(\\}\|[^}]\)*}/ contained contains=vrsCompItem
syntax match vrsRegExp /\%(^\S\+\s\+\S\+\s\+\)\@<=.*/ contains=vrsCompose contained
syntax match vrsCommand /^\S\+\s\+\S\+\s\+\S.*/ contains=vrsName,vrsFlavor,vrsNameErr,vrsFlavorErr,vrsRegExp,vrsComment
syntax match vrsContinued /^\s\+\S.*/ contains=vrsComment
syntax match vrsComment /\%(\%(\\\\\)*\\\)\@<!#.*$/ containedin=ALL contains=vrsTodo
syntax match vrsError /^[^a-zA-Z0-9_#\ ].*/ 
syntax match vrsError /foo/ 

hi def link vrsTodo Todo
hi def link vrsNameErr Error
hi def link vrsName Identifier
hi def link vrsFlavorErr Error
hi def link vrsFlavor Type
hi def link vrsCompItem Normal
hi def link vrsCompose PreProc
hi def link vrsRegExp String
hi def link vrsContinued String
hi def link vrsComment Comment
hi def link vrsError Error
hi def link vrsError Error

let b:current_syntax = "vrs"

let &cpo = s:save_cpo
unlet s:save_cpo

" vim: set sw=2 sts=2 et fdm=marker:



Now I feel more equipped to take your hand and say, "there, there."

Depends On: Raimondi's VimRegStyle
Coming Soon! SinTax is still in development but is ready for user testing. Feedback welcome.

Saturday, February 2, 2013

Evimosaurus Rex

E-Rex

because everyone deserves extended regular expressions

A couple posts back I compared some idiomatic Ruby with equivalent Vim forms. One of those was the multiline, whitespace-insensitive extended regular expression mode that the /x flag gives the PCRE wielder. I showed how this might be achieved in Vim as:

let PHONE_NUMBER_PATTERN = substitute(substitute('
      \ ^
      \ \%(
      \   \(\d\)           # prefix_digit
      \   [\ \-\.]\?       # optional_separator
      \ \)\?
      \ \%(
      \   (\?\(\d\{3}\))\? # area_code
      \ [\ \-\.]           # separator
      \ \)\?
      \ \(\d\{3}\)         # trunk
      \ [\ \-\.]           # separator
      \ \(\d\{4}\)         # line
      \ \%(:\ \?x\?        # optional_space_or_x
      \   \(\d\+\)         # extension
      \ \)\?
      \ $', '# \S\+', '', 'g'), '\\\@<! ', '', 'g')

echo string(PHONE_NUMBER_PATTERN)
let a_phone_number = '1-234-567-0987:1234'

echo matchlist(a_phone_number, PHONE_NUMBER_PATTERN)

Which is all good and well, but wouldn’t it be nicer if we could just do this instead:

let PHONE_NUMBER_PATTERN = ERex.parse('
      \ ^
      \ \%(
      \   \(\d\)           # prefix_digit
      \   [\ \-\.]\?       # optional_separator
      \ \)\?
      \ \%(
      \   (\?\(\d\{3}\))\? # area_code
      \ [\ \-\.]           # separator
      \ \)\?
      \ \(\d\{3}\)         # trunk
      \ [\ \-\.]           # separator
      \ \(\d\{4}\)         # line
      \ \%(:\ \?x\?        # optional_space_or_x
      \   \(\d\+\)         # extension
      \ \)\?
      \ $')

echo string(PHONE_NUMBER_PATTERN)
let a_phone_number = '1-234-567-0987:1234'

echo matchlist(a_phone_number, PHONE_NUMBER_PATTERN)

Where the ERex object was just magically waiting in the background for all of our extended regex needs…?

Install https://github.com/Raimondi/VimRegStyle and you can!


“There is no charge for awesomeness.”
— Po

This just in! the awesomeness of Extended Regular Expressions has just been added to vimple.

RFC on VimRegStyle


VimRegStyle

more than just a pattern library for sexy regex

This is a request for feedback on a new plugin: https://github.com/Raimondi/VimRegStyle

VimRegStyle is designed to be a repository of PCRE ←→ Vim regex equivalences and general pattern library for Vimmers.

Our goal is to have somewhere for the collection of common regex patterns expressed in the Vim regex flavour. We frequently get regex help requests on #vim that are answered with “look that common pattern up on a regex lib site” only to have them come back and say “it didn’t work” because they plugged the PCRE into Vim and got spanked for it.

No more! Now we have a library of our own!

So… what do I want from you? Feedback on:
  1. Design issues (concerns & improvements)(*)
  2. Ideas for tools, commands, maps and scripts surrounding such a pattern library.
(*) This might be the place to mention that we’ve taken several rather bold steps in the implementation of the pattern repository files:
  1. the patterns/ directory contains *.vrs files with the following format:
    name flavour pattern
    Where:
    • name contains no whitespace
    • flavour can be vim or pcre
    • pattern is not delimited — use a bare regex
  2. the patterns are further enhanced in the following two ways; they:
    • accept PCRE style multiline, whitespace insensitive syntax. All multiline patterns must commence on the line below the named entry and must be indented with whitespace.
    • accept a new regex atom: \%{name,count,separator} providing pattern composition by inline-expanding the named pattern at the current point in the regex (optionally count times, each one separated by separator.)

      As an example:, assuming the VRS library had a pattern called _ip4_segment that represented a single 0-255 chunk, an ip4 regex could then be written using this composition atom as: \<\%{_ip4_segment,4,.}>
      As a side note, the Extended Regex features mentioned here will be further elaborated on in a separate article. These features can be freely used in other projects, pulling from arbitrary lookup sources, including the runtime vars in Vim itself. But more on that later.
When we’re finished with this RFC process we will be looking for pattern contributions. Thanks to all who contribute their time and energy into this project! :-)