Initial commit.

This commit is contained in:
yan
2011-11-17 15:45:33 -06:00
commit 882015bc6d
1819 changed files with 111625 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
" AnsiEscPlugin.vim
" Author: Charles E. Campbell, Jr.
" Date: Apr 07, 2010
" Version: 12
" ---------------------------------------------------------------------
" Load Once: {{{1
if &cp || exists("g:loaded_AnsiEscPlugin")
finish
endif
let g:loaded_AnsiEscPlugin = "v12"
let s:keepcpo = &cpo
set cpo&vim
" ---------------------------------------------------------------------
" Public Interface: {{{1
com! -bang -nargs=0 AnsiEsc :call AnsiEsc#AnsiEsc(<bang>0)
" DrChip Menu Support: {{{2
if has("gui_running") && has("menu") && &go =~ 'm'
if !exists("g:DrChipTopLvlMenu")
let g:DrChipTopLvlMenu= "DrChip."
endif
exe 'menu '.g:DrChipTopLvlMenu.'AnsiEsc.Start<tab>:AnsiEsc :AnsiEsc<cr>'
endif
" ---------------------------------------------------------------------
" Restore: {{{1
let &cpo= s:keepcpo
unlet s:keepcpo
" vim: ts=4 fdm=marker

900
vim/plugin/CSApprox.vim Normal file
View File

@@ -0,0 +1,900 @@
" CSApprox: Make gvim-only colorschemes Just Work terminal vim
" Maintainer: Matthew Wozniski (mjw@drexel.edu)
" Date: Wed, 01 Apr 2009 22:10:19 -0400
" Version: 3.50
" History: :help csapprox-changelog
"
" Long Description:
" It's hard to find colorschemes for terminal Vim. Most colorschemes are
" written to only support GVim, and don't work at all in terminal Vim.
"
" This plugin makes GVim-only colorschemes Just Work in terminal Vim, as long
" as the terminal supports 88 or 256 colors - and most do these days. This
" usually requires no user interaction (but see below for what to do if things
" don't Just Work). After getting this plugin happily installed, any time you
" use :colorscheme it will do its magic and make the colorscheme Just Work.
"
" Whenever you change colorschemes using the :colorscheme command this script
" will be executed. It will take the colors that the scheme specified for use
" in the GUI and use an approximation algorithm to try to gracefully degrade
" them to the closest color available in your terminal. If you are running in
" a GUI or if your terminal doesn't support 88 or 256 colors, no changes are
" made. Also, no changes will be made if the colorscheme seems to have been
" high color already.
"
" License:
" Copyright (c) 2009, Matthew J. Wozniski
" All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
" * Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
" * Redistributions in binary form must reproduce the above copyright
" notice, this list of conditions and the following disclaimer in the
" documentation and/or other materials provided with the distribution.
" * The names of the contributors may not be used to endorse or promote
" products derived from this software without specific prior written
" permission.
"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
" NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
" {>1} Basic plugin setup
" {>2} Check preconditions
" Quit if the user doesn't want or need us or is missing the gui feature. We
" need +gui to be able to check the gui color settings; vim doesn't bother to
" store them if it is not built with +gui.
if exists('g:CSApprox_loaded')
finish
elseif ! has('gui')
" Warn unless the user set g:CSApprox_verbose_level to zero.
if get(g:, 'CSApprox_verbose_level', 1)
echomsg "CSApprox needs gui support - not loading."
echomsg " See :help |csapprox-+gui| for possible workarounds."
endif
finish
endif
" {1} Mark us as loaded, and disable all compatibility options for now.
let g:CSApprox_loaded = 1
let s:savecpo = &cpo
set cpo&vim
" {>1} Collect info for the set highlights
" {>2} Determine if synIDattr is usable
" synIDattr() couldn't support 'guisp' until 7.2.052. This function returns
" true if :redir is needed to find the 'guisp' attribute, false if synIDattr()
" is functional. This test can be overridden by setting the global variable
" g:CSApprox_redirfallback to 1 (to force use of :redir) or to 0 (to force use
" of synIDattr()).
function! s:NeedRedirFallback()
if !exists("g:CSApprox_redirfallback")
let g:CSApprox_redirfallback = (v:version == 702 && !has('patch52'))
\ || v:version < 702
endif
return g:CSApprox_redirfallback
endfunction
" {>2} Collect and store the highlights
" Get a dictionary containing information for every highlight group not merely
" linked to another group. Return value is a dictionary, with highlight group
" numbers for keys and values that are dictionaries with four keys each,
" 'name', 'term', 'cterm', and 'gui'. 'name' holds the group name, and each
" of the others holds highlight information for that particular mode.
function! s:Highlights(modes)
let rv = {}
let i = 0
while 1
let i += 1
" Only interested in groups that exist and aren't linked
if synIDtrans(i) == 0
break
endif
" Handle vim bug allowing groups with name == "" to be created
if synIDtrans(i) != i || len(synIDattr(i, "name")) == 0
continue
endif
let rv[i] = {}
let rv[i].name = synIDattr(i, "name")
for where in a:modes
let rv[i][where] = {}
for attr in [ "bold", "italic", "reverse", "underline", "undercurl" ]
let rv[i][where][attr] = synIDattr(i, attr, where)
endfor
for attr in [ "fg", "bg" ]
let rv[i][where][attr] = synIDattr(i, attr.'#', where)
endfor
if where == "gui"
let rv[i][where]["sp"] = s:SynGuiSp(i, rv[i].name)
else
let rv[i][where]["sp"] = -1
endif
for attr in [ "fg", "bg", "sp" ]
if rv[i][where][attr] == -1
let rv[i][where][attr] = ''
endif
endfor
endfor
endwhile
return rv
endfunction
" {>2} Retrieve guisp
" Get guisp using whichever method is specified by _redir_fallback
function! s:SynGuiSp(idx, name)
if !s:NeedRedirFallback()
return s:SynGuiSpAttr(a:idx)
else
return s:SynGuiSpRedir(a:name)
endif
endfunction
" {>3} Implementation for retrieving guisp with redir hack
function! s:SynGuiSpRedir(name)
redir => temp
exe 'sil hi ' . a:name
redir END
let temp = matchstr(temp, 'guisp=\zs.*')
if len(temp) == 0 || temp[0] =~ '\s'
let temp = ""
else
" Make sure we can handle guisp='dark red'
let temp = substitute(temp, '[\x00].*', '', '')
let temp = substitute(temp, '\s*\(c\=term\|gui\).*', '', '')
let temp = substitute(temp, '\s*$', '', '')
endif
return temp
endfunction
" {>3} Implementation for retrieving guisp with synIDattr()
function! s:SynGuiSpAttr(idx)
return synIDattr(a:idx, 'sp#', 'gui')
endfunction
" {>1} Handle color names
" Place to store rgb.txt name to color mappings - lazy loaded if needed
let s:rgb = {}
" {>2} Builtin gui color names
" gui_x11.c and gui_gtk_x11.c have some default colors names that are searched
" if the x server doesn't know about a color. If 'showrgb' is available,
" we'll default to using these color names and values, and overwrite them with
" other values if 'showrgb' tells us about those colors.
let s:rgb_defaults = { "lightred" : "#FFBBBB",
\ "lightgreen" : "#88FF88",
\ "lightmagenta" : "#FFBBFF",
\ "darkcyan" : "#008888",
\ "darkblue" : "#0000BB",
\ "darkred" : "#BB0000",
\ "darkmagenta" : "#BB00BB",
\ "darkgrey" : "#BBBBBB",
\ "darkyellow" : "#BBBB00",
\ "gray10" : "#1A1A1A",
\ "grey10" : "#1A1A1A",
\ "gray20" : "#333333",
\ "grey20" : "#333333",
\ "gray30" : "#4D4D4D",
\ "grey30" : "#4D4D4D",
\ "gray40" : "#666666",
\ "grey40" : "#666666",
\ "gray50" : "#7F7F7F",
\ "grey50" : "#7F7F7F",
\ "gray60" : "#999999",
\ "grey60" : "#999999",
\ "gray70" : "#B3B3B3",
\ "grey70" : "#B3B3B3",
\ "gray80" : "#CCCCCC",
\ "grey80" : "#CCCCCC",
\ "gray90" : "#E5E5E5",
\ "grey90" : "#E5E5E5" }
" {>2} Colors that vim will use by name in one of the default schemes, either
" for bg=light or for bg=dark. This lets us avoid loading the entire rgb.txt
" database when the scheme itself doesn't ask for colors by name.
let s:rgb_presets = { "black" : "#000000",
\ "blue" : "#0000ff",
\ "brown" : "#a52a2a",
\ "cyan" : "#00ffff",
\ "darkblue" : "#00008b",
\ "darkcyan" : "#008b8b",
\ "darkgrey" : "#a9a9a9",
\ "darkmagenta" : "#8b008b",
\ "green" : "#00ff00",
\ "grey" : "#bebebe",
\ "grey40" : "#666666",
\ "grey90" : "#e5e5e5",
\ "lightblue" : "#add8e6",
\ "lightcyan" : "#e0ffff",
\ "lightgrey" : "#d3d3d3",
\ "lightmagenta" : "#ffbbff",
\ "magenta" : "#ff00ff",
\ "red" : "#ff0000",
\ "seagreen" : "#2e8b57",
\ "white" : "#ffffff",
\ "yellow" : "#ffff00" }
" {>2} Find available color names
" Find the valid named colors. By default, use our own rgb list, but try to
" retrieve the system's list if g:CSApprox_use_showrgb is set to true. Store
" the color names and color values to the dictionary s:rgb - the keys are
" color names (in lowercase), the values are strings representing color values
" (as '#rrggbb').
function! s:UpdateRgbHash()
try
if !exists("g:CSApprox_use_showrgb") || !g:CSApprox_use_showrgb
throw "Not using showrgb"
endif
" We want to use the 'showrgb' program, if it's around
let lines = split(system('showrgb'), '\n')
if v:shell_error || !exists('lines') || empty(lines)
throw "'showrgb' didn't give us an rgb.txt"
endif
let s:rgb = copy(s:rgb_defaults)
" fmt is (blanks?)(red)(blanks)(green)(blanks)(blue)(blanks)(name)
let parsepat = '^\s*\(\d\+\)\s\+\(\d\+\)\s\+\(\d\+\)\s\+\(.*\)$'
for line in lines
let v = matchlist(line, parsepat)
if len(v) < 0
throw "CSApprox: Bad RGB line: " . string(line)
endif
let s:rgb[tolower(v[4])] = printf("#%02x%02x%02x", v[1], v[2], v[3])
endfor
catch
try
let s:rgb = csapprox#rgb()
catch
echohl ErrorMsg
echomsg "Can't call rgb() from autoload/csapprox.vim"
echomsg "Named colors will not be available!"
echohl None
endtry
endtry
return 0
endfunction
" {>1} Derive and set cterm attributes
" {>2} Attribute overrides
" Allow the user to override a specified attribute with another attribute.
" For example, the default is to map 'italic' to 'underline' (since many
" terminals cannot display italic text, and gvim itself will replace italics
" with underlines where italicizing is impossible), and to replace 'sp' with
" 'fg' (since terminals can't use one color for the underline and another for
" the foreground, we color the entire word). This default can of course be
" overridden by the user, by setting g:CSApprox_attr_map. This map must be
" a dictionary of string keys, representing the same attributes that synIDattr
" can look up, to string values, representing the attribute mapped to or an
" empty string to disable the given attribute entirely.
function! s:attr_map(attr)
let rv = get(g:CSApprox_attr_map, a:attr, a:attr)
return rv
endfunction
function! s:NormalizeAttrMap(map)
let old = copy(a:map)
let new = filter(a:map, '0')
let valid_attrs = [ 'bg', 'fg', 'sp', 'bold', 'italic',
\ 'reverse', 'underline', 'undercurl' ]
let colorattrs = [ 'fg', 'bg', 'sp' ]
for olhs in keys(old)
if olhs ==? 'inverse'
let nlhs = 'reverse'
endif
let orhs = old[olhs]
if orhs ==? 'inverse'
let nrhs = 'reverse'
endif
let nlhs = tolower(olhs)
let nrhs = tolower(orhs)
try
if index(valid_attrs, nlhs) == -1
echomsg "CSApprox: Bad attr map (removing unrecognized attribute " . olhs . ")"
elseif nrhs != '' && index(valid_attrs, nrhs) == -1
echomsg "CSApprox: Bad attr map (removing unrecognized attribute " . orhs . ")"
elseif nrhs != '' && !!(index(colorattrs, nlhs)+1) != !!(index(colorattrs, nrhs)+1)
echomsg "CSApprox: Bad attr map (removing " . olhs . "; type mismatch with " . orhs . ")"
elseif nrhs == 'sp'
echomsg "CSApprox: Bad attr map (removing " . olhs . "; can't map to 'sp')"
else
let new[nlhs] = nrhs
endif
catch
echo v:exception
endtry
endfor
endfunction
" {>2} Normalize the GUI settings of a highlight group
" If the Normal group is cleared, set it to gvim's default, black on white
" Though this would be a really weird thing for a scheme to do... *shrug*
function! s:FixupGuiInfo(highlights)
if a:highlights[s:hlid_normal].gui.bg == ''
let a:highlights[s:hlid_normal].gui.bg = 'white'
endif
if a:highlights[s:hlid_normal].gui.fg == ''
let a:highlights[s:hlid_normal].gui.fg = 'black'
endif
endfunction
" {>2} Map gui settings to cterm settings
" Given information about a highlight group, replace the cterm settings with
" the mapped gui settings, applying any attribute overrides along the way. In
" particular, this gives special treatment to the 'reverse' attribute and the
" 'guisp' attribute. In particular, if the 'reverse' attribute is set for
" gvim, we unset it for the terminal and instead set ctermfg to match guibg
" and vice versa, since terminals can consider a 'reverse' flag to mean using
" default-bg-on-default-fg instead of current-bg-on-current-fg. We also
" ensure that the 'sp' attribute is never set for cterm, since no terminal can
" handle that particular highlight. If the user wants to display the guisp
" color, he should map it to either 'fg' or 'bg' using g:CSApprox_attr_map.
function! s:FixupCtermInfo(highlights)
for hl in values(a:highlights)
if !has_key(hl, 'cterm')
let hl["cterm"] = {}
endif
" Find attributes to be set in the terminal
for attr in [ "bold", "italic", "reverse", "underline", "undercurl" ]
let hl.cterm[attr] = ''
if hl.gui[attr] == 1
if s:attr_map(attr) != ''
let hl.cterm[ s:attr_map(attr) ] = 1
endif
endif
endfor
for color in [ "bg", "fg" ]
let eff_color = color
if hl.cterm['reverse']
let eff_color = (color == 'bg' ? 'fg' : 'bg')
endif
let hl.cterm[color] = get(hl.gui, s:attr_map(eff_color), '')
endfor
if hl.gui['sp'] != '' && s:attr_map('sp') != ''
let hl.cterm[s:attr_map('sp')] = hl.gui['sp']
endif
if hl.cterm['reverse'] && hl.cterm.bg == ''
let hl.cterm.bg = 'fg'
endif
if hl.cterm['reverse'] && hl.cterm.fg == ''
let hl.cterm.fg = 'bg'
endif
if hl.cterm['reverse']
let hl.cterm.reverse = ''
endif
endfor
endfunction
" {>2} Kludge around inability to reference autoload functions
function! s:DefaultApproximator(...)
return call('csapprox#per_component#Approximate', a:000)
endfunction
" {>2} Set cterm colors for a highlight group
" Given the information for a single highlight group (ie, the value of
" one of the items in s:Highlights() already normalized with s:FixupCtermInfo
" and s:FixupGuiInfo), handle matching the gvim colors to the closest cterm
" colors by calling the appropriate approximator as specified with the
" g:CSApprox_approximator_function variable and set the colors and attributes
" appropriately to match the gui.
function! s:SetCtermFromGui(hl)
let hl = a:hl
" Set up the default approximator function, if needed
if !exists("g:CSApprox_approximator_function")
let g:CSApprox_approximator_function = function("s:DefaultApproximator")
endif
" Clear existing highlights
exe 'hi ' . hl.name . ' cterm=NONE ctermbg=NONE ctermfg=NONE'
for which in [ 'bg', 'fg' ]
let val = hl.cterm[which]
" Skip unset colors
if val == -1 || val == ""
continue
endif
" Try translating anything but 'fg', 'bg', #rrggbb, and rrggbb from an
" rgb.txt color to a #rrggbb color
if val !~? '^[fb]g$' && val !~ '^#\=\x\{6}$'
try
" First see if it is in our preset-by-vim rgb list
let val = s:rgb_presets[tolower(val)]
catch
" Then try loading and checking our real rgb list
if empty(s:rgb)
call s:UpdateRgbHash()
endif
try
let val = s:rgb[tolower(val)]
catch
" And then barf if we still haven't found it
if &verbose
echomsg "CSApprox: Colorscheme uses unknown color \"" . val . "\""
endif
continue
endtry
endtry
endif
if val =~? '^[fb]g$'
exe 'hi ' . hl.name . ' cterm' . which . '=' . val
let hl.cterm[which] = val
elseif val =~ '^#\=\x\{6}$'
let val = substitute(val, '^#', '', '')
let r = str2nr(val[0:1], 16)
let g = str2nr(val[2:3], 16)
let b = str2nr(val[4:5], 16)
let hl.cterm[which] = g:CSApprox_approximator_function(r, g, b)
exe 'hi ' . hl.name . ' cterm' . which . '=' . hl.cterm[which]
else
throw "Internal error handling color: " . val
endif
endfor
" Finally, set the attributes
let attrs = [ 'bold', 'italic', 'underline', 'undercurl' ]
call filter(attrs, 'hl.cterm[v:val] == 1')
if !empty(attrs)
exe 'hi ' . hl.name . ' cterm=' . join(attrs, ',')
endif
endfunction
" {>1} Top-level control
" Cache the highlight ID of the normal group; it's used often and won't change
let s:hlid_normal = hlID('Normal')
" {>2} Builtin cterm color names above 15
" Vim defines some color name to high color mappings internally (see
" syntax.c:do_highlight). Since we don't want to overwrite a colorscheme that
" was actually written for a high color terminal with our choices, but have no
" way to tell if a colorscheme was written for a high color terminal, we fall
" back on guessing. If any highlight group has a cterm color set to 16 or
" higher, we assume that the user has used a high color colorscheme - unless
" that color is one of the below, which vim can set internally when a color is
" requested by name.
let s:presets_88 = []
let s:presets_88 += [32] " Brown
let s:presets_88 += [72] " DarkYellow
let s:presets_88 += [84] " Gray
let s:presets_88 += [84] " Grey
let s:presets_88 += [82] " DarkGray
let s:presets_88 += [82] " DarkGrey
let s:presets_88 += [43] " LightBlue
let s:presets_88 += [61] " LightGreen
let s:presets_88 += [63] " LightCyan
let s:presets_88 += [74] " LightRed
let s:presets_88 += [75] " LightMagenta
let s:presets_88 += [78] " LightYellow
let s:presets_256 = []
let s:presets_256 += [130] " Brown
let s:presets_256 += [130] " DarkYellow
let s:presets_256 += [248] " Gray
let s:presets_256 += [248] " Grey
let s:presets_256 += [242] " DarkGray
let s:presets_256 += [242] " DarkGrey
let s:presets_256 += [ 81] " LightBlue
let s:presets_256 += [121] " LightGreen
let s:presets_256 += [159] " LightCyan
let s:presets_256 += [224] " LightRed
let s:presets_256 += [225] " LightMagenta
let s:presets_256 += [229] " LightYellow
" {>2} Wrapper around :exe to allow :executing multiple commands.
" "cmd" is the command to be :executed.
" If the variable is a String, it is :executed.
" If the variable is a List, each element is :executed.
function! s:exe(cmd)
if type(a:cmd) == type('')
exe a:cmd
else
for cmd in a:cmd
call s:exe(cmd)
endfor
endif
endfunction
" {>2} Function to handle hooks
" Prototype: HandleHooks(type [, scheme])
" "type" is the type of hook to be executed, ie. "pre" or "post"
" "scheme" is the name of the colorscheme that is currently active, if known
"
" If the variables g:CSApprox_hook_{type} and g:CSApprox_hook_{scheme}_{type}
" exist, this will :execute them in that order. If one does not exist, it
" will silently be ignored.
"
" If the scheme name contains characters that are invalid in a variable name,
" they will simply be removed. Ie, g:colors_name = "123 foo_bar-baz456"
" becomes "foo_barbaz456"
"
" NOTE: Exceptions will be printed out, rather than end processing early. The
" rationale is that it is worse for the user to fix the hook in an editor with
" broken colors. :)
function! s:HandleHooks(type, ...)
let type = a:type
let scheme = (a:0 == 1 ? a:1 : "")
let scheme = substitute(scheme, '[^[:alnum:]_]', '', 'g')
let scheme = substitute(scheme, '^\d\+', '', '')
for cmd in [ 'g:CSApprox_hook_' . type,
\ 'g:CSApprox_' . scheme . '_hook_' . type,
\ 'g:CSApprox_hook_' . scheme . '_' . type ]
if exists(cmd)
try
call s:exe(eval(cmd))
catch
echomsg "Error processing " . cmd . ":"
echomsg v:exception
endtry
endif
endfor
endfunction
" {>2} Main function
" Wrapper around the actual implementation to make it easier to ensure that
" all temporary settings are restored by the time we return, whether or not
" something was thrown. Additionally, sets the 'verbose' option to the max of
" g:CSApprox_verbose_level (default 1) and &verbose for the duration of the
" main function. This allows us to default to a message whenever any error,
" even a recoverable one, occurs, meaning the user quickly finds out when
" something's wrong, but makes it very easy for the user to make us silent.
function! s:CSApprox(...)
try
if a:0 == 1 && a:1
if !exists('s:inhibit_hicolor_test')
let s:inhibit_hicolor_test = 0
endif
let s:inhibit_hicolor_test += 1
endif
let savelz = &lz
set lz
if exists("g:CSApprox_attr_map") && type(g:CSApprox_attr_map) == type({})
call s:NormalizeAttrMap(g:CSApprox_attr_map)
else
let g:CSApprox_attr_map = { 'italic' : 'underline', 'sp' : 'fg' }
endif
" colors_name must be unset and reset, or vim will helpfully reload the
" colorscheme when we set the background for the Normal group.
" See the help entries ':hi-normal-cterm' and 'g:colors_name'
if exists("g:colors_name")
let colors_name = g:colors_name
unlet g:colors_name
endif
" Similarly, the global variable "syntax_cmd" must be set to something vim
" doesn't recognize, lest vim helpfully switch all colors back to the
" default whenever the Normal group is changed (in syncolor.vim)...
if exists("g:syntax_cmd")
let syntax_cmd = g:syntax_cmd
endif
let g:syntax_cmd = "PLEASE DON'T CHANGE ANY COLORS!!!"
" Set up our verbosity level, if needed.
" Default to 1, so the user can know if something's wrong.
if !exists("g:CSApprox_verbose_level")
let g:CSApprox_verbose_level = 1
endif
call s:HandleHooks("pre", (exists("colors_name") ? colors_name : ""))
" Set 'verbose' set to the maximum of &verbose and CSApprox_verbose_level
exe max([&vbs, g:CSApprox_verbose_level]) 'verbose call s:CSApproxImpl()'
call s:HandleHooks("post", (exists("colors_name") ? colors_name : ""))
finally
if exists("colors_name")
let g:colors_name = colors_name
endif
unlet g:syntax_cmd
if exists("syntax_cmd")
let g:syntax_cmd = syntax_cmd
endif
let &lz = savelz
if a:0 == 1 && a:1
let s:inhibit_hicolor_test -= 1
if s:inhibit_hicolor_test == 0
unlet s:inhibit_hicolor_test
endif
endif
endtry
endfunction
" {>2} CSApprox implementation
" Verifies that the user has not started the gui, and that vim recognizes his
" terminal as having enough colors for us to go on, then gathers the existing
" highlights and sets the cterm colors to match the gui colors for all those
" highlights (unless the colorscheme was already high-color).
function! s:CSApproxImpl()
" Return if not running in an 88/256 color terminal
if &t_Co != 256 && &t_Co != 88
if &verbose && !has('gui_running')
echomsg "CSApprox skipped; terminal only has" &t_Co "colors, not 88/256"
echomsg "Try checking :help csapprox-terminal for workarounds"
endif
return
endif
" Get the current highlight colors
let highlights = s:Highlights(["gui"])
let hinums = keys(highlights)
" Make sure that the script is not already 256 color by checking to make
" sure that no groups are set to a value above 256, unless the color they're
" set to can be set internally by vim (gotten by scraping
" color_numbers_{88,256} in syntax.c:do_highlight)
"
" XXX: s:inhibit_hicolor_test allows this test to be skipped for snapshots
if !exists("s:inhibit_hicolor_test") || !s:inhibit_hicolor_test
for hlid in hinums
for type in [ 'bg', 'fg' ]
let color = synIDattr(hlid, type, 'cterm')
if color > 15 && index(s:presets_{&t_Co}, str2nr(color)) < 0
" The value is set above 15, and wasn't set by vim.
if &verbose >= 2
echomsg 'CSApprox: Exiting - high' type 'color found for' highlights[hlid].name
endif
return
endif
endfor
endfor
endif
call s:FixupGuiInfo(highlights)
call s:FixupCtermInfo(highlights)
" We need to set the Normal group first so 'bg' and 'fg' work as colors
call insert(hinums, remove(hinums, index(hinums, string(s:hlid_normal))))
" then set each color's cterm attributes to match gui
for hlid in hinums
call s:SetCtermFromGui(highlights[hlid])
endfor
endfunction
" {>2} Write out the current colors to an 88/256 color colorscheme file.
" "file" - destination filename
" "overwrite" - overwrite an existing file
function! s:CSApproxSnapshot(file, overwrite)
let force = a:overwrite
let file = fnamemodify(a:file, ":p")
if empty(file)
throw "Bad file name: \"" . file . "\""
elseif (filewritable(fnamemodify(file, ':h')) != 2)
throw "Cannot write to directory \"" . fnamemodify(file, ':h') . "\""
elseif (glob(file) || filereadable(file)) && !force
" TODO - respect 'confirm' here and prompt if it's set.
echohl ErrorMsg
echomsg "E13: File exists (add ! to override)"
echohl None
return
endif
" Sigh... This is basically a bug, but one that I have no chance of fixing.
" Vim decides that Pmenu should be highlighted in 'LightMagenta' in terminal
" vim and as 'Magenta' in gvim... And I can't ask it what color it actually
" *wants*. As far as I can see, there's no way for me to learn that
" I should output 'Magenta' when 'LightMagenta' is provided by vim for the
" terminal.
if !has('gui_running')
echohl WarningMsg
echomsg "Warning: The written colorscheme may have incorrect colors"
echomsg " when CSApproxSnapshot is used in terminal vim!"
echohl None
endif
let save_t_Co = &t_Co
let s:inhibit_hicolor_test = 1
if exists("g:CSApprox_konsole")
let save_CSApprox_konsole = g:CSApprox_konsole
endif
if exists("g:CSApprox_eterm")
let save_CSApprox_eterm = g:CSApprox_eterm
endif
" Needed just like in CSApprox()
if exists("g:colors_name")
let colors_name = g:colors_name
unlet g:colors_name
endif
" Needed just like in CSApprox()
if exists("g:syntax_cmd")
let syntax_cmd = g:syntax_cmd
endif
let g:syntax_cmd = "PLEASE DON'T CHANGE ANY COLORS!!!"
try
let lines = []
let lines += [ '" This scheme was created by CSApproxSnapshot' ]
let lines += [ '" on ' . strftime("%a, %d %b %Y") ]
let lines += [ '' ]
let lines += [ 'hi clear' ]
let lines += [ 'if exists("syntax_on")' ]
let lines += [ ' syntax reset' ]
let lines += [ 'endif' ]
let lines += [ '' ]
let lines += [ 'if v:version < 700' ]
let lines += [ ' let g:colors_name = expand("<sfile>:t:r")' ]
let lines += [ ' command! -nargs=+ CSAHi exe "hi" substitute(substitute(<q-args>, "undercurl", "underline", "g"), "guisp\\S\\+", "", "g")' ]
let lines += [ 'else' ]
let lines += [ ' let g:colors_name = expand("<sfile>:t:r")' ]
let lines += [ ' command! -nargs=+ CSAHi exe "hi" <q-args>' ]
let lines += [ 'endif' ]
let lines += [ '' ]
let lines += [ 'if 0' ]
for round in [ 'konsole', 'eterm', 'xterm', 'urxvt' ]
sil! unlet g:CSApprox_eterm
sil! unlet g:CSApprox_konsole
if round == 'konsole'
let g:CSApprox_konsole = 1
elseif round == 'eterm'
let g:CSApprox_eterm = 1
endif
if round == 'urxvt'
set t_Co=88
else
set t_Co=256
endif
call s:CSApprox()
let highlights = s:Highlights(["term", "cterm", "gui"])
call s:FixupGuiInfo(highlights)
if round == 'konsole' || round == 'eterm'
let lines += [ 'elseif has("gui_running") || (&t_Co == ' . &t_Co
\ . ' && (&term ==# "xterm" || &term =~# "^screen")'
\ . ' && exists("g:CSApprox_' . round . '")'
\ . ' && g:CSApprox_' . round . ')'
\ . ' || &term =~? "^' . round . '"' ]
else
let lines += [ 'elseif has("gui_running") || &t_Co == ' . &t_Co ]
endif
let hinums = keys(highlights)
call insert(hinums, remove(hinums, index(hinums, string(s:hlid_normal))))
for hlnum in hinums
let hl = highlights[hlnum]
let line = ' CSAHi ' . hl.name
for type in [ 'term', 'cterm', 'gui' ]
let attrs = [ 'reverse', 'bold', 'italic', 'underline', 'undercurl' ]
call filter(attrs, 'hl[type][v:val] == 1')
let line .= ' ' . type . '=' . (empty(attrs) ? 'NONE' : join(attrs, ','))
if type != 'term'
let line .= ' ' . type . 'bg=' . (len(hl[type].bg) ? hl[type].bg : 'bg')
let line .= ' ' . type . 'fg=' . (len(hl[type].fg) ? hl[type].fg : 'fg')
if type == 'gui' && hl.gui.sp !~ '^\s*$'
let line .= ' ' . type . 'sp=' . hl[type].sp
endif
endif
endfor
let lines += [ line ]
endfor
endfor
let lines += [ 'endif' ]
let lines += [ '' ]
let lines += [ 'if 1' ]
let lines += [ ' delcommand CSAHi' ]
let lines += [ 'endif' ]
call writefile(lines, file)
finally
let &t_Co = save_t_Co
if exists("save_CSApprox_konsole")
let g:CSApprox_konsole = save_CSApprox_konsole
endif
if exists("save_CSApprox_eterm")
let g:CSApprox_eterm = save_CSApprox_eterm
endif
if exists("colors_name")
let g:colors_name = colors_name
endif
unlet g:syntax_cmd
if exists("syntax_cmd")
let g:syntax_cmd = syntax_cmd
endif
call s:CSApprox()
unlet s:inhibit_hicolor_test
endtry
endfunction
" {>2} Snapshot user command
command! -bang -nargs=1 -complete=file -bar CSApproxSnapshot
\ call s:CSApproxSnapshot(<f-args>, strlen("<bang>"))
" {>2} Manual updates
command -bang -bar CSApprox call s:CSApprox(strlen("<bang>"))
" {>1} Hooks
" {>2} Autocmds
" Set up an autogroup to hook us on the completion of any :colorscheme command
augroup CSApprox
au!
au ColorScheme * call s:CSApprox()
"au User CSApproxPost highlight Normal ctermbg=none | highlight NonText ctermbg=None
augroup END
" {>2} Execute
" The last thing to do when sourced is to run and actually fix up the colors.
if !has('gui_running')
call s:CSApprox()
endif
" {>1} Restore compatibility options
let &cpo = s:savecpo
unlet s:savecpo
" {0} vim:sw=2:sts=2:et:fdm=expr:fde=substitute(matchstr(getline(v\:lnum),'^\\s*"\\s*{\\zs.\\{-}\\ze}'),'^$','=','')

View File

@@ -0,0 +1,466 @@
" theme.menu.vim: Generates Vim themes menu and organizes themes based
" upon background colors
" Maintainer: Erik Falor <rAjsBnFCybe@tzNnvy.Zpbz g?? - NOSPAM>
" Date: Aug 30, 2007
" Version: 0.4
"
" Initialization: {{{
if exists("g:loaded_theme_menu") || &cp
finish
endif
let g:loaded_theme_menu= "0.4"
let s:keepcpo = &cpo
set cpo&vim
"}}}
" Script Variables: {{{
let s:menuFile = strpart(&rtp, 0, stridx(&rtp, ',')) . '/plugin/ColorSchemes.vim'
let s:menuName = '&ColorSchemes'
let s:xdigit = '[0123456789ABCDEFabcdef]'
let s:hexvals = { 0:0, 1:1, 2:2, 3:3,
\4:4, 5:5, 6:6, 7:7,
\8:8, 9:9, 'a':10, 'b':11,
\'c':12, 'd':13, 'e':14, 'f':15,
\'A':10, 'B':11, 'C':12, 'D':13,
\'E':14, 'F':15 }
"}}}
" Library Functions {{{
function! <SID>RGBtoHSV(r, g, b) "{{{
let h = 0
let s = 0
let v = 0
if (a:b > a:g) && (a:b > a:r)
let v = a:b
if v != 0
let min = 0
if(a:r > a:g)
let min = a:g
else
let min = a:r
endif
let delta = v - min
if delta != 0
let s = (delta * 255) / v
let h = 240 + (60 * a:r - 60 * a:g) / delta
else
let s = 0
let h = 240 + (60 * a:r - 60 * a:g)
endif
if h < 0
let h = h + 360
endif
else
let s = 0
let h = 0
endif
elseif a:g > a:r
let v = a:g
if v != 0
let min = 0
if a:r > a:b
let min = a:b
else
let min = a:r
endif
let delta = v - min
if delta != 0
let s = (delta * 255) / v
let h = 120 + (60 * a:b - 60 * a:r) / delta
else
let s = 0
let h = 120 + (60 * a:b - 60 * a:r)
endif
if h < 0
let h = h + 360
endif
else
let s = 0
let h = 0
endif
else
let v = a:r
if v != 0
let min = 0
if a:g > a:b
let min = a:b
else
let min = a:g
endif
let delta = v - min
if delta != 0
let s = (delta * 255) / v
let h = (60 * a:g - 60 * a:b) / delta
else
let s = 0
let h = 60 * a:g - 60 * a:b
endif
if h < 0
let h = h + 360
endif
else
let s = 0
let h = 0
endif
endif
return [h, s, v]
endfunction "RGBtoHSV()
"}}}
function! <SID>IsBlack(r, g, b, h, s, v) "{{{
if a:r == a:g && a:g == a:b && a:b == 0
return 1
else
return 0
endif
endfunction "IsBlack()}}}
function! <SID>IsWhite(r, g, b, h, s, v) "{{{
if a:r == a:g && a:g == a:b && a:b == 255
return 1
else
return 0
endif
endfunction "IsWhite()}}}
function! <SID>IsDarkGrey(r, g, b, h, s, v) "{{{
let diffRGB = max([a:r, a:g, a:b]) - min([a:r, a:g, a:b])
let darkGreyFuzz = 20
if diffRGB <= darkGreyFuzz
return 1
else
return 0
endif
endfunction "IsDarkGrey()}}}
function! <SID>IsOffWhite(r, g, b, h, s, v) "{{{
let offWhiteSat = 32
let offWhiteVal = 255 - 32
if a:v >= offWhiteVal && a:s <= offWhiteSat
return 1
else
return 0
endif
endfunction "}}}
function! <SID>IsGrey(r, g, b, h, s, v) "{{{
let diffRGB = max([a:r, a:g, a:b]) - min([a:r, a:g, a:b])
let greyFuzz = 28
let greyVal = 32
if diffRGB > greyFuzz
return 0
elseif (a:s <= greyFuzz )
\&& (a:v <= 255 - (greyVal * 1))
\&& (a:v >= 0 + (greyVal * 1))
return 1
else
return 0
endif
endfunction "}}}
function! <SID>IsYellow(r, g, b, h, s, v) "{{{
if a:h > 30 && a:h <= 90
return 1
else
return 0
endif
endfunction "}}}
function! <SID>IsGreen(r, g, b, h, s, v) "{{{
if a:h > 90 && a:h <= 180
return 1
else
return 0
endif
endfunction "}}}
function! <SID>IsCyan(r, g, b, h, s, v) "{{{
" cyan will be 180 deg +/- 10 deg
let variance = 10
if a:h > 180 - variance && a:h < 180 + variance
return 1
else
return 0
endif
endfunction "}}}
function! <SID>IsBlue(r, g, b, h, s, v) "{{{
if a:h > 180 && a:h <= 270
return 1
else
return 0
endif
endfunction "}}}
function! <SID>IsMagenta(r, g, b, h, s, v) "{{{
if a:h > 270 && a:h <= 330
return 1
else
return 0
endif
endfunction }}}
function! <SID>IsOrange(r, g, b, h, s, v) "{{{
"a magic number found through trial and error
let greenFuzz = 172
if a:r > a:g && a:b == 0 && a:g < greenFuzz && a:g != 0
return 1
else
return 0
endif
endfunction "}}}
function! <SID>IsRed(r, g, b, h, s, v) "{{{
if a:h > 330 || a:h <= 30
return 1
else
return 0
endif
endfunction "}}}
function! <SID>RgbTxt2Hexes() "{{{
"read rgb.txt, return dictionary mapping color names to hex triplet
if exists("g:rgbtxt") && filereadable(g:rgbtxt)
let rgbtxt = g:rgbtxt
else
if has("win32") || has("win64")
let rgbtxt = expand("$VIMRUNTIME/rgb.txt")
elseif filereadable("/usr/X11R6/lib/X11/rgb.txt")
let rgbtxt = "/usr/X11R6/lib/X11/rgb.txt"
elseif filereadable("/usr/share/X11/rgb.txt")
let rgbtxt = "/usr/share/X11/rgb.txt"
endif
endif
let rgbdict = {}
if filereadable(rgbtxt)
for line in readfile(rgbtxt)
if line !~ '^\(!\|#\)'
let l = matchlist(line, '\s*\(\d\+\)\s*\(\d\+\)\s*\(\d\+\)\s*\(.*\)')
let rgbdict[tolower(l[4])] = printf('%02X%02X%02X', l[1], l[2], l[3])
endif
endfor
"note: vim treats guibg=NONE as guibg=white
let rgbdict['none'] = 'FFFFFF'
else
echoerr "ColorSchemeMenuMaker.vim could not open rgb.txt file at " . rgbtxt
endif
return rgbdict
endfunction "}}}
function! <SID>RGBHexToHexes(rgb) "{{{
let xdigits = '\(' . s:xdigit . '\{2\}\)'
let pat = '\(#\)\?' . xdigits . xdigits . xdigits
let l = matchlist(a:rgb, pat)
if len(l) > 0
return [ l[2], l[3], l[4] ]
else
return []
endif
endfunction "}}}
function! <SID>RGBHexToInts(rgbList) "{{{
return map(a:rgbList, '<SID>Hex2Int(v:val)')
endfunction "}}}
function! <SID>Hex2Int(hex) "{{{
let xdigits = split(a:hex, '\zs')
return 16 * s:hexvals[xdigits[0]] + s:hexvals[xdigits[1]]
endfunction "}}}
function! <SID>RGB2BoyColor(rgb) "{{{
let rgbL = <SID>RGBHexToInts(<SID>RGBHexToHexes(a:rgb))
let r = rgbL[0] | let g = rgbL[1] | let b = rgbL[2]
let hsvL = <SID>RGBtoHSV(r, g, b)
let h = hsvL[0] | let s = hsvL[1] | let v = hsvL[2]
if <SID>IsBlack(r, g, b, h, s, v) == 1 | return 'black' | endif
if <SID>IsWhite(r, g, b, h, s, v) == 1 | return 'white' | endif
if <SID>IsGrey(r, g, b, h, s, v) == 1 | return 'grey' | endif
if <SID>IsOffWhite(r, g, b, h, s, v) == 1 | return 'offwhite' | endif
if <SID>IsDarkGrey(r, g, b, h, s, v) == 1 | return 'darkgrey' | endif
if <SID>IsOrange(r, g, b, h, s, v) == 1 | return 'orange' | endif
if <SID>IsYellow(r, g, b, h, s, v) == 1 | return 'yellow' | endif
if <SID>IsCyan(r, g, b, h, s, v) == 1 | return 'cyan' | endif
if <SID>IsGreen(r, g, b, h, s, v) == 1 | return 'green' | endif
if <SID>IsBlue(r, g, b, h, s, v) == 1 | return 'blue' | endif
if <SID>IsMagenta(r, g, b, h, s, v) == 1 | return 'magenta' | endif
if <SID>IsRed(r, g, b, h, s, v) == 1 | return 'red' | endif
return 'unknown'
endfunction "}}}
function! <SID>GlobThemes() "{{{
"return list containing paths to all theme files in &runtimepath
return split(globpath(&rtp, 'colors/*.vim'), '\n')
endfunction "}}}
function! <SID>ScanThemeBackground() "{{{
"Read each of the theme files and find out which color
"each theme 'basically' is. Uses the last 'hi Normal'
"group found to classify by color. Notes those color
"files that do have more than one 'hi Normal' command.
let name2hex = <SID>RgbTxt2Hexes()
let themeColors = {}
let themeNames = {}
let i = 0
let pat = 'hi.*\s\+Normal\s\+.\{-}guibg=\(#\?\)\(\w\+\)'
for theme in <SID>GlobThemes()
if filereadable(theme)
"DEBUG
"let i = i + 1
"if i > 10
"break
"endif
let higroupfound = 0
let color = ''
for line in readfile(theme)
let bg = matchlist(line, pat)
if len(bg) > 0
if bg[1] == '#'
let color = <SID>RGB2BoyColor(bg[2])
else
if has_key(name2hex, tolower(bg[2]))
let color = <SID>RGB2BoyColor(name2hex[tolower(bg[2])])
else
let color = 'unknown'
endif
endif
let higroupfound += 1
endif
endfor
let themename = fnamemodify(theme, ':t:r')
let letter = toupper(strpart(themename, 0, 1))
if letter =~ '\d' | let letter = '#' | endif
if len(color) < 1
let color = 'unknown'
endif
"allocate sub-dict if needed
if !has_key(themeColors, color)
let themeColors[color] = {}
endif
"allocate sub-dict if needed
if !has_key(themeNames, letter)
let themeNames[letter] = {}
endif
if higroupfound > 1
"mark themes with many 'hi Normal' commands
if len(color) > 0
let themeColors[color][themename] = '*' . themename
endif
let themeNames[letter][themename] = '*' . themename
else
if len(color) > 0
let themeColors[color][themename] = themename
endif
let themeNames[letter][themename] = themename
endif
endif
endfor
return [themeColors, themeNames]
endfunction "}}}
function! <SID>BuildMenu(dicts) "{{{
"puts menu commands into a list
let menu = []
call add(menu, '"ColorScheme menu generated ' . strftime("%c", localtime()))
call add(menu, '')
call add(menu, '"Themes by color:')
call add(menu, '')
"count number of themes categorized by color
let totThemes = 0
for i in keys(a:dicts[0])
let totThemes += len(a:dicts[0][i])
endfor
for color in sort(keys(a:dicts[0]))
let numThemes = len(a:dicts[0][color])
call add(menu, '')
call add(menu, '"submenu '. color)
for theme in sort(keys(a:dicts[0][color]))
call add(menu, '9000amenu '. s:menuName. '.&Colors\ ('. totThemes . ').'
\. color . '\ ('. numThemes . ').'
\. a:dicts[0][color][theme]. ' :colo '. theme . '<CR>')
endfor
endfor
call add(menu, '"Themes by name:')
call add(menu, '')
"count number of themes categorized by name
let totThemes = 0
for i in keys(a:dicts[1])
let totThemes += len(a:dicts[1][i])
endfor
for letter in sort(keys(a:dicts[1]))
let numThemes = len(a:dicts[1][letter])
call add(menu, '')
call add(menu, '"submenu '. letter)
for theme in sort(keys(a:dicts[1][letter]))
call add(menu, 'amenu '. s:menuName. '.&Names\ (' . totThemes . ').'
\. letter . '\ ('. numThemes .').'
\. a:dicts[1][letter][theme] . ' :colo '. theme . '<CR>')
endfor
endfor
call add(menu, '')
"add a separator and a command to re-init the menu
call add(menu, 'amenu ' . s:menuName .'.-Sep- :')
call add(menu, 'amenu ' . s:menuName .'.Reload\ Menu :ReloadColors<CR>')
call add(menu, 'amenu ' . s:menuName .'.Refresh\ Menu :RefreshColors<CR>')
call add(menu, '')
call add(menu, 'command! -nargs=0 ReloadColors call <SID>ReloadColors()')
call add(menu, 'command! -nargs=0 RefreshColors call <SID>RefreshColors()')
call add(menu, '')
call add(menu, 'if !exists("g:running_ReloadColors")')
call add(menu, ' function! <SID>ReloadColors()')
call add(menu, ' let g:running_ReloadColors = 1')
call add(menu, ' aunmenu ' . s:menuName)
call add(menu, " execute 'source " . s:menuFile . "'")
call add(menu, ' unlet g:running_ReloadColors')
call add(menu, " echomsg 'Done Reloading " . s:menuFile . "'")
call add(menu, ' endfunction')
call add(menu, 'endif')
call add(menu, 'if !exists("g:running_RefreshColors")')
call add(menu, ' function! <SID>RefreshColors()')
call add(menu, ' let g:running_RefreshColors = 1')
call add(menu, ' call WriteColorSchemeMenu()')
call add(menu, ' call <SID>ReloadColors()')
call add(menu, ' unlet g:running_RefreshColors')
call add(menu, " echomsg 'Done Refreshing " . s:menuFile . "'")
call add(menu, ' endfunction')
call add(menu, 'endif')
return menu
endfunction "}}}
function! WriteColorSchemeMenu() "{{{
"Builds the menu from the two dicts returned by ScanThemeBackground()
"Stores menu in first plugin dir specified by &rtp
let menu = <SID>BuildMenu(<SID>ScanThemeBackground())
call writefile(menu, s:menuFile)
endfunction "}}}
function! <SID>InitMenu() "{{{
call WriteColorSchemeMenu()
execute "source " . s:menuFile
endfunction "}}}
"}}}
" Restore &cpo: {{{1
let &cpo= s:keepcpo
unlet s:keepcpo
"}}}1
"Detect absence of ColorScheme menu, and generate a new one automatically
if !filereadable(s:menuFile) "{{{
echomsg "Creating ColorScheme menu - Please Wait..."
call <SID>InitMenu()
echomsg "Done!"
endif "}}}
" vim: tabstop=4 foldmethod=marker

486
vim/plugin/ColorSchemes.vim Normal file
View File

@@ -0,0 +1,486 @@
"ColorScheme menu generated Sat 01 Sep 2007 23:21:10 NZST
"Themes by color:
"submenu black
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).adrian :colo adrian<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).*af :colo af<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).billw :colo billw<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).*black_angus :colo black_angus<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).blackbeauty :colo blackbeauty<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).blacksea :colo blacksea<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).blugrine :colo blugrine<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).brookstream :colo brookstream<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).candy :colo candy<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).colorer :colo colorer<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).dante :colo dante<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).darkblack :colo darkblack<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).darkocean :colo darkocean<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).dw_blue :colo dw_blue<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).dw_cyan :colo dw_cyan<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).dw_green :colo dw_green<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).dw_orange :colo dw_orange<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).dw_purple :colo dw_purple<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).dw_red :colo dw_red<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).dw_yellow :colo dw_yellow<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).elflord :colo elflord<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).fnaqevan :colo fnaqevan<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).golden :colo golden<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).gothic :colo gothic<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).hhdblue :colo hhdblue<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).hhdcyan :colo hhdcyan<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).hhdgray :colo hhdgray<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).hhdgreen :colo hhdgreen<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).hhdmagenta :colo hhdmagenta<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).hhdred :colo hhdred<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).hhdyellow :colo hhdyellow<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).*inkpot :colo inkpot<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).jhdark :colo jhdark<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).koehler :colo koehler<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).less :colo less<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).manxome :colo manxome<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).matrix :colo matrix<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).metacosm :colo metacosm<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).*motus :colo motus<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).murphy :colo murphy<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).neverness :colo neverness<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).nightwish :colo nightwish<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).oceanblack :colo oceanblack<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).pablo :colo pablo<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).potts :colo potts<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).*ps_color :colo ps_color<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).putty :colo putty<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).redblack :colo redblack<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).relaxedgreen :colo relaxedgreen<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).revolutions :colo revolutions<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).ron :colo ron<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).sean :colo sean<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).tango :colo tango<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).*torte :colo torte<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).vibrantink :colo vibrantink<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).*vividchalk :colo vividchalk<CR>
9000amenu &ColorSchemes.&Colors\ (190).black\ (57).wintersday :colo wintersday<CR>
"submenu blue
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).adam :colo adam<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).adaryn :colo adaryn<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).aqua :colo aqua<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).astronaut :colo astronaut<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).asu1dark :colo asu1dark<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).blue :colo blue<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).bluegreen :colo bluegreen<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).borland :colo borland<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).breeze :colo breeze<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).caramel :colo caramel<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).cleanphp :colo cleanphp<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).*cool :colo cool<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).darkblue :colo darkblue<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).darkblue2 :colo darkblue2<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).denim :colo denim<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).desertedocean :colo desertedocean<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).dusk :colo dusk<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).edo_sea :colo edo_sea<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).hhazure :colo hhazure<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).ibmedit :colo ibmedit<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).midnight :colo midnight<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).midnight2 :colo midnight2<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).navajo-night :colo navajo-night<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).nightshimmer :colo nightshimmer<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).northsky :colo northsky<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).oceandeep :colo oceandeep<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).sea :colo sea<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).softblue :colo softblue<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).transparent :colo transparent<CR>
9000amenu &ColorSchemes.&Colors\ (190).blue\ (30).turbo :colo turbo<CR>
"submenu cyan
9000amenu &ColorSchemes.&Colors\ (190).cyan\ (3).darkslategray :colo darkslategray<CR>
9000amenu &ColorSchemes.&Colors\ (190).cyan\ (3).gor :colo gor<CR>
9000amenu &ColorSchemes.&Colors\ (190).cyan\ (3).marklar :colo marklar<CR>
"submenu darkgrey
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).candycode :colo candycode<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).darkdot :colo darkdot<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).darktango :colo darktango<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).greyblue :colo greyblue<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).hhspring :colo hhspring<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).hhteal :colo hhteal<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).hhviolet :colo hhviolet<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).lettuce :colo lettuce<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).night :colo night<CR>
9000amenu &ColorSchemes.&Colors\ (190).darkgrey\ (10).rdark :colo rdark<CR>
"submenu green
9000amenu &ColorSchemes.&Colors\ (190).green\ (2).earth :colo earth<CR>
9000amenu &ColorSchemes.&Colors\ (190).green\ (2).*tabula :colo tabula<CR>
"submenu grey
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).biogoo :colo biogoo<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).blackdust :colo blackdust<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).camo :colo camo<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).*dawn :colo dawn<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).desert :colo desert<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).desertEx :colo desertEx<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).evening :colo evening<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).fog :colo fog<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).freya :colo freya<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).jhlight :colo jhlight<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).neon :colo neon<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).slate :colo slate<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).toothpik :colo toothpik<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).umber-green :colo umber-green<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).whitedust :colo whitedust<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).xemacs :colo xemacs<CR>
9000amenu &ColorSchemes.&Colors\ (190).grey\ (17).*zenburn :colo zenburn<CR>
"submenu magenta
9000amenu &ColorSchemes.&Colors\ (190).magenta\ (1).lilac :colo lilac<CR>
"submenu offwhite
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).automation :colo automation<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).autumn :colo autumn<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).autumn2 :colo autumn2<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).autumnleaf :colo autumnleaf<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).*baycomb :colo baycomb<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).bmichaelsen :colo bmichaelsen<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).fine_blue :colo fine_blue<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).fruit :colo fruit<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).habiLight :colo habiLight<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).ironman :colo ironman<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).mod_tcsoft :colo mod_tcsoft<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).morning :colo morning<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).nedit :colo nedit<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).nedit2 :colo nedit2<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).nuvola :colo nuvola<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).oceanlight :colo oceanlight<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).pyte :colo pyte<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).python :colo python<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).seashell :colo seashell<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).sf :colo sf<CR>
9000amenu &ColorSchemes.&Colors\ (190).offwhite\ (21).simpleandfriendly :colo simpleandfriendly<CR>
"submenu orange
9000amenu &ColorSchemes.&Colors\ (190).orange\ (1).*mars :colo mars<CR>
"submenu red
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).ChocolateLiquor :colo ChocolateLiquor<CR>
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).aiseered :colo aiseered<CR>
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).chocolateliquor :colo chocolateliquor<CR>
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).hhpink :colo hhpink<CR>
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).*navajo :colo navajo<CR>
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).peachpuff :colo peachpuff<CR>
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).tibet :colo tibet<CR>
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).tomatosoup :colo tomatosoup<CR>
9000amenu &ColorSchemes.&Colors\ (190).red\ (9).xian :colo xian<CR>
"submenu unknown
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).brown :colo brown<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).bw :colo bw<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).c :colo c<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).calmar256-light :colo calmar256-light<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).chela_light :colo chela_light<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).coffee :colo coffee<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).colorscheme_template :colo colorscheme_template<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).default :colo default<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).desert256 :colo desert256<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).impact :colo impact<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).psql :colo psql<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).reloaded :colo reloaded<CR>
9000amenu &ColorSchemes.&Colors\ (190).unknown\ (13).vc :colo vc<CR>
"submenu white
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).bog :colo bog<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).delek :colo delek<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).eclipse :colo eclipse<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).emacs :colo emacs<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).gobo :colo gobo<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).lingodirector :colo lingodirector<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).martin_krischik :colo martin_krischik<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).*moria :colo moria<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).print_bw :colo print_bw<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).*scite :colo scite<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).shine :colo shine<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).*sienna :colo sienna<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).taqua :colo taqua<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).tcsoft :colo tcsoft<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).tolerable :colo tolerable<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).vcbc :colo vcbc<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).white :colo white<CR>
9000amenu &ColorSchemes.&Colors\ (190).white\ (18).zellner :colo zellner<CR>
"submenu yellow
9000amenu &ColorSchemes.&Colors\ (190).yellow\ (8).PapayaWhip :colo PapayaWhip<CR>
9000amenu &ColorSchemes.&Colors\ (190).yellow\ (8).buttercream :colo buttercream<CR>
9000amenu &ColorSchemes.&Colors\ (190).yellow\ (8).hhorange :colo hhorange<CR>
9000amenu &ColorSchemes.&Colors\ (190).yellow\ (8).olive :colo olive<CR>
9000amenu &ColorSchemes.&Colors\ (190).yellow\ (8).papayawhip :colo papayawhip<CR>
9000amenu &ColorSchemes.&Colors\ (190).yellow\ (8).professional :colo professional<CR>
9000amenu &ColorSchemes.&Colors\ (190).yellow\ (8).robinhood :colo robinhood<CR>
9000amenu &ColorSchemes.&Colors\ (190).yellow\ (8).sand :colo sand<CR>
"Themes by name:
"submenu A
amenu &ColorSchemes.&Names\ (190).A\ (12).adam :colo adam<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).adaryn :colo adaryn<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).adrian :colo adrian<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).*af :colo af<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).aiseered :colo aiseered<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).aqua :colo aqua<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).astronaut :colo astronaut<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).asu1dark :colo asu1dark<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).automation :colo automation<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).autumn :colo autumn<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).autumn2 :colo autumn2<CR>
amenu &ColorSchemes.&Names\ (190).A\ (12).autumnleaf :colo autumnleaf<CR>
"submenu B
amenu &ColorSchemes.&Names\ (190).B\ (18).*baycomb :colo baycomb<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).billw :colo billw<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).biogoo :colo biogoo<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).*black_angus :colo black_angus<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).blackbeauty :colo blackbeauty<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).blackdust :colo blackdust<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).blacksea :colo blacksea<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).blue :colo blue<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).bluegreen :colo bluegreen<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).blugrine :colo blugrine<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).bmichaelsen :colo bmichaelsen<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).bog :colo bog<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).borland :colo borland<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).breeze :colo breeze<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).brookstream :colo brookstream<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).brown :colo brown<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).buttercream :colo buttercream<CR>
amenu &ColorSchemes.&Names\ (190).B\ (18).bw :colo bw<CR>
"submenu C
amenu &ColorSchemes.&Names\ (190).C\ (14).ChocolateLiquor :colo ChocolateLiquor<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).c :colo c<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).calmar256-light :colo calmar256-light<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).camo :colo camo<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).candy :colo candy<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).candycode :colo candycode<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).caramel :colo caramel<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).chela_light :colo chela_light<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).chocolateliquor :colo chocolateliquor<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).cleanphp :colo cleanphp<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).coffee :colo coffee<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).colorer :colo colorer<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).colorscheme_template :colo colorscheme_template<CR>
amenu &ColorSchemes.&Names\ (190).C\ (14).*cool :colo cool<CR>
"submenu D
amenu &ColorSchemes.&Names\ (190).D\ (24).dante :colo dante<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).darkblack :colo darkblack<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).darkblue :colo darkblue<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).darkblue2 :colo darkblue2<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).darkdot :colo darkdot<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).darkocean :colo darkocean<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).darkslategray :colo darkslategray<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).darktango :colo darktango<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).*dawn :colo dawn<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).default :colo default<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).delek :colo delek<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).denim :colo denim<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).desert :colo desert<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).desert256 :colo desert256<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).desertEx :colo desertEx<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).desertedocean :colo desertedocean<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).dusk :colo dusk<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).dw_blue :colo dw_blue<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).dw_cyan :colo dw_cyan<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).dw_green :colo dw_green<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).dw_orange :colo dw_orange<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).dw_purple :colo dw_purple<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).dw_red :colo dw_red<CR>
amenu &ColorSchemes.&Names\ (190).D\ (24).dw_yellow :colo dw_yellow<CR>
"submenu E
amenu &ColorSchemes.&Names\ (190).E\ (6).earth :colo earth<CR>
amenu &ColorSchemes.&Names\ (190).E\ (6).eclipse :colo eclipse<CR>
amenu &ColorSchemes.&Names\ (190).E\ (6).edo_sea :colo edo_sea<CR>
amenu &ColorSchemes.&Names\ (190).E\ (6).elflord :colo elflord<CR>
amenu &ColorSchemes.&Names\ (190).E\ (6).emacs :colo emacs<CR>
amenu &ColorSchemes.&Names\ (190).E\ (6).evening :colo evening<CR>
"submenu F
amenu &ColorSchemes.&Names\ (190).F\ (5).fine_blue :colo fine_blue<CR>
amenu &ColorSchemes.&Names\ (190).F\ (5).fnaqevan :colo fnaqevan<CR>
amenu &ColorSchemes.&Names\ (190).F\ (5).fog :colo fog<CR>
amenu &ColorSchemes.&Names\ (190).F\ (5).freya :colo freya<CR>
amenu &ColorSchemes.&Names\ (190).F\ (5).fruit :colo fruit<CR>
"submenu G
amenu &ColorSchemes.&Names\ (190).G\ (5).gobo :colo gobo<CR>
amenu &ColorSchemes.&Names\ (190).G\ (5).golden :colo golden<CR>
amenu &ColorSchemes.&Names\ (190).G\ (5).gor :colo gor<CR>
amenu &ColorSchemes.&Names\ (190).G\ (5).gothic :colo gothic<CR>
amenu &ColorSchemes.&Names\ (190).G\ (5).greyblue :colo greyblue<CR>
"submenu H
amenu &ColorSchemes.&Names\ (190).H\ (14).habiLight :colo habiLight<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhazure :colo hhazure<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhdblue :colo hhdblue<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhdcyan :colo hhdcyan<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhdgray :colo hhdgray<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhdgreen :colo hhdgreen<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhdmagenta :colo hhdmagenta<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhdred :colo hhdred<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhdyellow :colo hhdyellow<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhorange :colo hhorange<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhpink :colo hhpink<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhspring :colo hhspring<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhteal :colo hhteal<CR>
amenu &ColorSchemes.&Names\ (190).H\ (14).hhviolet :colo hhviolet<CR>
"submenu I
amenu &ColorSchemes.&Names\ (190).I\ (4).ibmedit :colo ibmedit<CR>
amenu &ColorSchemes.&Names\ (190).I\ (4).impact :colo impact<CR>
amenu &ColorSchemes.&Names\ (190).I\ (4).*inkpot :colo inkpot<CR>
amenu &ColorSchemes.&Names\ (190).I\ (4).ironman :colo ironman<CR>
"submenu J
amenu &ColorSchemes.&Names\ (190).J\ (2).jhdark :colo jhdark<CR>
amenu &ColorSchemes.&Names\ (190).J\ (2).jhlight :colo jhlight<CR>
"submenu K
amenu &ColorSchemes.&Names\ (190).K\ (1).koehler :colo koehler<CR>
"submenu L
amenu &ColorSchemes.&Names\ (190).L\ (4).less :colo less<CR>
amenu &ColorSchemes.&Names\ (190).L\ (4).lettuce :colo lettuce<CR>
amenu &ColorSchemes.&Names\ (190).L\ (4).lilac :colo lilac<CR>
amenu &ColorSchemes.&Names\ (190).L\ (4).lingodirector :colo lingodirector<CR>
"submenu M
amenu &ColorSchemes.&Names\ (190).M\ (13).manxome :colo manxome<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).marklar :colo marklar<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).*mars :colo mars<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).martin_krischik :colo martin_krischik<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).matrix :colo matrix<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).metacosm :colo metacosm<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).midnight :colo midnight<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).midnight2 :colo midnight2<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).mod_tcsoft :colo mod_tcsoft<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).*moria :colo moria<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).morning :colo morning<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).*motus :colo motus<CR>
amenu &ColorSchemes.&Names\ (190).M\ (13).murphy :colo murphy<CR>
"submenu N
amenu &ColorSchemes.&Names\ (190).N\ (11).*navajo :colo navajo<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).navajo-night :colo navajo-night<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).nedit :colo nedit<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).nedit2 :colo nedit2<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).neon :colo neon<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).neverness :colo neverness<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).night :colo night<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).nightshimmer :colo nightshimmer<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).nightwish :colo nightwish<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).northsky :colo northsky<CR>
amenu &ColorSchemes.&Names\ (190).N\ (11).nuvola :colo nuvola<CR>
"submenu O
amenu &ColorSchemes.&Names\ (190).O\ (4).oceanblack :colo oceanblack<CR>
amenu &ColorSchemes.&Names\ (190).O\ (4).oceandeep :colo oceandeep<CR>
amenu &ColorSchemes.&Names\ (190).O\ (4).oceanlight :colo oceanlight<CR>
amenu &ColorSchemes.&Names\ (190).O\ (4).olive :colo olive<CR>
"submenu P
amenu &ColorSchemes.&Names\ (190).P\ (12).PapayaWhip :colo PapayaWhip<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).pablo :colo pablo<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).papayawhip :colo papayawhip<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).peachpuff :colo peachpuff<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).potts :colo potts<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).print_bw :colo print_bw<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).professional :colo professional<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).*ps_color :colo ps_color<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).psql :colo psql<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).putty :colo putty<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).pyte :colo pyte<CR>
amenu &ColorSchemes.&Names\ (190).P\ (12).python :colo python<CR>
"submenu R
amenu &ColorSchemes.&Names\ (190).R\ (7).rdark :colo rdark<CR>
amenu &ColorSchemes.&Names\ (190).R\ (7).redblack :colo redblack<CR>
amenu &ColorSchemes.&Names\ (190).R\ (7).relaxedgreen :colo relaxedgreen<CR>
amenu &ColorSchemes.&Names\ (190).R\ (7).reloaded :colo reloaded<CR>
amenu &ColorSchemes.&Names\ (190).R\ (7).revolutions :colo revolutions<CR>
amenu &ColorSchemes.&Names\ (190).R\ (7).robinhood :colo robinhood<CR>
amenu &ColorSchemes.&Names\ (190).R\ (7).ron :colo ron<CR>
"submenu S
amenu &ColorSchemes.&Names\ (190).S\ (11).sand :colo sand<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).*scite :colo scite<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).sea :colo sea<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).sean :colo sean<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).seashell :colo seashell<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).sf :colo sf<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).shine :colo shine<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).*sienna :colo sienna<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).simpleandfriendly :colo simpleandfriendly<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).slate :colo slate<CR>
amenu &ColorSchemes.&Names\ (190).S\ (11).softblue :colo softblue<CR>
"submenu T
amenu &ColorSchemes.&Names\ (190).T\ (11).*tabula :colo tabula<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).tango :colo tango<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).taqua :colo taqua<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).tcsoft :colo tcsoft<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).tibet :colo tibet<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).tolerable :colo tolerable<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).tomatosoup :colo tomatosoup<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).toothpik :colo toothpik<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).*torte :colo torte<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).transparent :colo transparent<CR>
amenu &ColorSchemes.&Names\ (190).T\ (11).turbo :colo turbo<CR>
"submenu U
amenu &ColorSchemes.&Names\ (190).U\ (1).umber-green :colo umber-green<CR>
"submenu V
amenu &ColorSchemes.&Names\ (190).V\ (4).vc :colo vc<CR>
amenu &ColorSchemes.&Names\ (190).V\ (4).vcbc :colo vcbc<CR>
amenu &ColorSchemes.&Names\ (190).V\ (4).vibrantink :colo vibrantink<CR>
amenu &ColorSchemes.&Names\ (190).V\ (4).*vividchalk :colo vividchalk<CR>
"submenu W
amenu &ColorSchemes.&Names\ (190).W\ (3).white :colo white<CR>
amenu &ColorSchemes.&Names\ (190).W\ (3).whitedust :colo whitedust<CR>
amenu &ColorSchemes.&Names\ (190).W\ (3).wintersday :colo wintersday<CR>
"submenu X
amenu &ColorSchemes.&Names\ (190).X\ (2).xemacs :colo xemacs<CR>
amenu &ColorSchemes.&Names\ (190).X\ (2).xian :colo xian<CR>
"submenu Z
amenu &ColorSchemes.&Names\ (190).Z\ (2).zellner :colo zellner<CR>
amenu &ColorSchemes.&Names\ (190).Z\ (2).*zenburn :colo zenburn<CR>
amenu &ColorSchemes.-Sep- :
amenu &ColorSchemes.Reload\ Menu :ReloadColors<CR>
amenu &ColorSchemes.Refresh\ Menu :RefreshColors<CR>
command! -nargs=0 ReloadColors call <SID>ReloadColors()
command! -nargs=0 RefreshColors call <SID>RefreshColors()
if !exists("g:running_ReloadColors")
function! <SID>ReloadColors()
let g:running_ReloadColors = 1
aunmenu &ColorSchemes
execute 'source /home/marty/.vim/plugin/ColorSchemes.vim'
unlet g:running_ReloadColors
echomsg 'Done Reloading /home/marty/.vim/plugin/ColorSchemes.vim'
endfunction
endif
if !exists("g:running_RefreshColors")
function! <SID>RefreshColors()
let g:running_RefreshColors = 1
call WriteColorSchemeMenu()
call <SID>ReloadColors()
unlet g:running_RefreshColors
echomsg 'Done Refreshing /home/marty/.vim/plugin/ColorSchemes.vim'
endfunction
endif

73
vim/plugin/EasyMotion.vim Executable file
View File

@@ -0,0 +1,73 @@
" EasyMotion - Vim motions on speed!
"
" Author: Kim Silkebækken <kim.silkebaekken+vim@gmail.com>
" Source repository: https://github.com/Lokaltog/vim-easymotion
" Script initialization {{{
if exists('g:EasyMotion_loaded') || &compatible || version < 702
finish
endif
let g:EasyMotion_loaded = 1
" }}}
" Default configuration {{{
" Default options {{{
call EasyMotion#InitOptions({
\ 'leader_key' : '<Leader><Leader>'
\ , 'keys' : 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
\ , 'do_shade' : 1
\ , 'do_mapping' : 1
\ , 'grouping' : 1
\
\ , 'hl_group_target' : 'EasyMotionTarget'
\ , 'hl_group_shade' : 'EasyMotionShade'
\ })
" }}}
" Default highlighting {{{
let s:target_hl_defaults = {
\ 'gui' : ['NONE', '#ff0000' , 'bold']
\ , 'cterm256': ['NONE', '196' , 'bold']
\ , 'cterm' : ['NONE', 'red' , 'bold']
\ }
let s:shade_hl_defaults = {
\ 'gui' : ['NONE', '#777777' , 'NONE']
\ , 'cterm256': ['NONE', '242' , 'NONE']
\ , 'cterm' : ['NONE', 'grey' , 'NONE']
\ }
call EasyMotion#InitHL(g:EasyMotion_hl_group_target, s:target_hl_defaults)
call EasyMotion#InitHL(g:EasyMotion_hl_group_shade, s:shade_hl_defaults)
" Reset highlighting after loading a new color scheme {{{
augroup EasyMotionInitHL
autocmd!
autocmd ColorScheme * call EasyMotion#InitHL(g:EasyMotion_hl_group_target, s:target_hl_defaults)
autocmd ColorScheme * call EasyMotion#InitHL(g:EasyMotion_hl_group_shade, s:shade_hl_defaults)
augroup end
" }}}
" }}}
" Default key mapping {{{
call EasyMotion#InitMappings({
\ 'f' : { 'name': 'F' , 'dir': 0 }
\ , 'F' : { 'name': 'F' , 'dir': 1 }
\ , 't' : { 'name': 'T' , 'dir': 0 }
\ , 'T' : { 'name': 'T' , 'dir': 1 }
\ , 'w' : { 'name': 'WB' , 'dir': 0 }
\ , 'W' : { 'name': 'WBW', 'dir': 0 }
\ , 'b' : { 'name': 'WB' , 'dir': 1 }
\ , 'B' : { 'name': 'WBW', 'dir': 1 }
\ , 'e' : { 'name': 'E' , 'dir': 0 }
\ , 'E' : { 'name': 'EW' , 'dir': 0 }
\ , 'ge': { 'name': 'E' , 'dir': 1 }
\ , 'gE': { 'name': 'EW' , 'dir': 1 }
\ , 'j' : { 'name': 'JK' , 'dir': 0 }
\ , 'k' : { 'name': 'JK' , 'dir': 1 }
\ , 'n' : { 'name': 'Search' , 'dir': 0 }
\ , 'N' : { 'name': 'Search' , 'dir': 1 }
\ })
" }}}
" }}}
" vim: fdm=marker:noet:ts=4:sw=4:sts=4

View File

@@ -0,0 +1,61 @@
" FindInNERDTree
"
" Description: Moves the cursor to the node in the NERDTree that
" represents the current file. Will open directories
" to find it.
" Last Change: 11/9/09
" Version: 1.0
" Author: Doug McInnes <doug@dougmcinnes.com>
" URL: http://github.com/dmcinnes/find_in_nerd_tree/tree
"
" A plugin for NERDTree
" http://www.vim.org/scripts/script.php?script_id=1658
function! FindInNERDTree(...)
if a:0
let l:path = a:1
else
let l:nerdbuf = 0
for item in tabpagebuflist()
if bufname(item) =~ "^NERD_tree_"
let l:nerdbuf = item
endif
endfor
if l:nerdbuf == bufnr('%')
" already in the tree
return 0
endif
let l:path = g:NERDTreePath.New(bufname('%'))
if l:nerdbuf
silent! exec bufwinnr(l:nerdbuf) . "wincmd w"
else
silent! exec "NERDTreeToggle"
endif
call cursor(g:NERDTreeFileNode.GetRootLineNum(), 1)
endif
let l:root = g:NERDTreeDirNode.GetSelected()
if l:root.path.compareTo(l:path) == 0
return l:root.findNode(l:path)
elseif l:path.str() !~ '^' . l:root.path.str()
echo "Not in the current NERD tree!"
return 0
else
let l:node = FindInNERDTree(l:path.getParent())
if !empty(l:node)
call l:node.open()
if a:0
return l:node.findNode(l:path)
else
call NERDTreeRender()
call g:NERDTreeFileNode.New(l:path).putCursorHere(1, 0)
endif
endif
endif
return {}
endfunction

View File

@@ -0,0 +1,675 @@
"
" Copyright 2006 Tye Zdrojewski
"
" Licensed under the Apache License, Version 2.0 (the "License"); you may not
" use this file except in compliance with the License. You may obtain a copy of
" the License at
"
" http://www.apache.org/licenses/LICENSE-2.0
"
" Unless required by applicable law or agreed to in writing, software distributed
" under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
" CONDITIONS OF ANY KIND, either express or implied. See the License for the
" specific language governing permissions and limitations under the License.
"
"
"
" Plugin:
"
" Indent Anything
"
" Version: 1.2.2
"
" Description:
"
" This is an indentation script that calculates the indent level based
" on begin/end syntax pairs and line-continuation patterns. It allows one
" to create an indent script without writing any code, taking it's
" instruction from configurable values.
"
" Included with this script is Javascript indentation, an example that
" explains the configurable values.
"
"
" Installation:
"
" Place this file in your home directory under ~/.vim/indent/, or replace
" the system indent/javascript.vim file to affect all users.
"
" Maintainer: Tye Z. <zdro@yahoo.com>
"
" Customization:
"
" The only thing that can really be customized at this point is whether or
" not a line is echoed explaining the indentation result. To turn this on,
" set the following variable like so:
"
" let b:indent_anything_echo = 1
"
"
" History:
"
" 1.2 - made some functions script-local to prevent naming collisions
" - fixed some broken indentation in the middle of a block comment,
" which showed up in Javascript indentation.
"
" 1.2.2 - Fixed a bug causing the line after a single-line block comment to
" always have an indent of '0' (i.e. the line after /* comment */).
" - Added Apache 2 license
"
"
let s:supportedVimVersion = 700
if version < s:supportedVimVersion
echoerr "IndentAnything only supported for Vim " . s:supportedVimVersion . " and up."
finish
endif
"
" Initialize everything needed by this script. Only set those values that are
" not set already.
"
function! IndentAnythingInit()
let b:IndentAnythingInitialized = 1
" Start with a regular expression that will never match. Matching
" will influence behavior, which the defaults should not do.
let s:nonMatcher = '[x]\&[^x]'
if !exists('b:commentRE')
let b:commentRE = s:nonMatcher
endif
if !exists('b:lineCommentRE')
let b:lineCommentRE = s:nonMatcher
endif
if !exists('b:blockCommentRE')
let b:blockCommentRE = s:nonMatcher
endif
if !exists('b:stringRE')
let b:stringRE = s:nonMatcher
endif
if !exists('b:singleQuoteStringRE')
let b:singleQuoteStringRE = s:nonMatcher
endif
if !exists('b:doubleQuoteStringRE')
let b:doubleQuoteStringRE = s:nonMatcher
endif
if !exists('b:blockCommentStartRE')
let b:blockCommentStartRE = s:nonMatcher
endif
if !exists('b:blockCommentMiddleRE')
let b:blockCommentMiddleRE = s:nonMatcher
endif
if !exists('b:blockCommentEndRE')
let b:blockCommentEndRE = s:nonMatcher
endif
if !exists('b:blockCommentMiddleExtra')
let b:blockCommentMiddleExtra = 0
endif
if !exists('b:indentTrios')
let b:indentTrios = []
endif
if !exists('b:lineContList')
let b:lineContList = []
endif
if !exists('b:contTraversesLineComments')
let b:contTraversesLineComments = 1
endif
if !exists('b:indent_anything_echo')
let b:indent_anything_echo = 0
endif
endfunction
function! SynHere()
return synIDattr(synID(line('.'), col('.'), 1), "name")
endfunction
"
" Returns true if the cursor is currently inside a comment or a string
"
function! InCommentOrString()
let syn = synIDattr(synID(line("."), col("."), 1), "name")
if syn =~ b:commentRE || syn =~ b:stringRE
return 1
endif
return 0
endfunction
"
" Returns true if the given line is a comment line (b:lineCommentRE)
"
function! IsLineComment(linenum)
let cursor = getpos('.')
exec a:linenum
normal ^
let l:iscomment = 0
let l:syn = synIDattr(synID(line('.'), col('.'), 1), "name")
if l:syn =~ b:lineCommentRE " b:commentRE || l:syn =~ b:stringRE
let l:iscomment = 1
endif
call setpos('.', cursor)
return l:iscomment
endfunction
"
" Returns true if the given line is a comment line (b:lineCommentRE)
"
function! IsComment(linenum)
let cursor = getpos('.')
exec a:linenum
normal ^
let l:iscomment = 0
let l:syn = synIDattr(synID(line('.'), col('.'), 1), "name")
if l:syn =~ b:commentRE " b:commentRE || l:syn =~ b:stringRE
let l:iscomment = 1
endif
call setpos('.', cursor)
return l:iscomment
endfunction
"
" Returns true if the given line is a comment line (b:lineCommentRE)
"
function! IsBlockComment(linenum)
let cursor = getpos('.')
exec a:linenum
normal ^
let l:iscomment = 0
let l:syn = synIDattr(synID(line('.'), col('.'), 1), "name")
if l:syn =~ b:blockCommentRE " b:commentRE || l:syn =~ b:stringRE
let l:iscomment = 1
endif
call setpos('.', cursor)
return l:iscomment
endfunction
"
" Get the first line at or on the given line that is not blank and is not a
" comment line.
"
function! GetPrevNonBlankNonComment(begin)
let cursor = getpos('.')
let l:prevbegin = a:begin
while 1
let l:lnum = prevnonblank(l:prevbegin)
if l:lnum == 0
return 0
endif
"if IsLineComment(l:lnum)
if IsComment(l:lnum)
let l:prevbegin -= 1
continue
endif
break
endwhile
" Restore original cursor location
call setpos('.', cursor)
return l:lnum
endfunction
"
" This does all the work. Does indentation for:
"
" - All pairs defined in b:indentTrios
" - All line continuations in b:lineContList
" - Block comments
"
function! IndentAnything()
if !exists('b:IndentAnythingInitialized')
call IndentAnythingInit()
endif
let adj = 0 " Adjustment
let g:lastindent = ""
let b:hardindent = -1
let currlnum = v:lnum
let currlnum = line('.')
let currline = getline(currlnum)
let lastline = ''
let prevline = ''
" Find non-blank lines above the current line.
let lastlnum = prevnonblank(currlnum - 1)
let prevlnum = prevnonblank(lastlnum - 1)
if lastlnum != 0
let lastline = getline(lastlnum)
endif
if prevlnum != 0
let prevline = getline(prevlnum)
endif
if b:contTraversesLineComments
let lastcodelnum = GetPrevNonBlankNonComment(currlnum - 1)
let prevcodelnum = GetPrevNonBlankNonComment(lastcodelnum - 1)
if lastcodelnum !=0
let lastcodeline = getline(lastcodelnum)
endif
endif
" Start from the first char on the line. Vim doesn't seem to consistently
" place the cursor there before calling the indent routines.
call cursor(0, 1)
call search('\S', 'W')
let l:cur = getpos('.')
"
" Call indentation adjustment functions.
"
"
" Block comments
"
let l:BlockCommentAdj = 0
let l:BlockCommentAdj += s:GetBlockCommentIndent(currlnum, lastlnum)
let adj += l:BlockCommentAdj
"
" Pairs
"
let b:lastclosed = { 'at' : 0 }
let b:pairadj = 0
if !l:BlockCommentAdj
" If we're not in the middle of a block comment (because we haven't
" made any adjustments for that), then process block indentation.
for trio in b:indentTrios
let b:pairadj += s:GetPairIndent(currline, lastline, lastlnum,
\ trio[0], trio[1], trio[2])
endfor
endif
let adj += b:pairadj
"
" Line continuations
"
let contadj = 0
let isBlockCommentStart = currline =~ '^\s*' . b:blockCommentStartRE
let isBlockCommentMid = (IsBlockComment(currlnum) && !isBlockCommentStart)
if !isBlockCommentMid
" If the current line is not the middle of a block comment, then
" process line continuations.
for ContRule in b:lineContList
if b:contTraversesLineComments "&& !isBlockCommentStart
let contadj = s:GetContIndent(ContRule, currline, lastcodeline, lastcodelnum, prevcodelnum)
else
let contadj = s:GetContIndent(ContRule, currline, lastline, lastlnum, prevlnum)
endif
" This is for line continuation patterns, of which there can be only
" one per line to indicate continuation
if contadj
break
endif
endfor
let adj += contadj
endif
"
" Find the previous indent to which we will add the adjustment
"
let prevind = indent(lastlnum)
if l:BlockCommentAdj
let g:lastindent .= " indent (prevblockcomment: " . prevind . " at " . lastcodelnum . ") "
elseif contadj && b:contTraversesLineComments
" If we have adjusted for line continuation, then use the indentation
" for the previous code line
let prevind = indent(lastcodelnum)
let g:lastindent .= " indent (prevcode: " . prevind . " at " . lastcodelnum . ") "
elseif (isBlockCommentStart || !IsBlockComment(currlnum)) && IsBlockComment(lastlnum)
" If this is the first line after a block comment, then add the
" adjustment to the line where the block comment started.
let prevind = s:GetPostBlockCommentIndent(lastlnum)
let g:lastindent .= " indent (prevblock: " . prevind . " at " . lastlnum . ") "
elseif exists("b:defaultIndentExpr")
let g:lastindent .= " using defaultIndentExpr (" . b:defaultIndentExpr . ") "
exec "let prevind = " . b:defaultIndentExpr
else
" Default to adjusting the previous line's indent.
let g:lastindent .= " indent (prev: " . prevind . " at " . lastlnum . ") "
endif
" Just in case there is no previous indent.
let prevind = (prevind == -1 ? 0 : prevind)
if b:indent_anything_echo
echom g:lastindent
endif
call setpos('.', l:cur)
return adj + prevind
endfunction
"
" Get the adjustment for the second line of a block comment. The second line
" will be aligned under the start of the block, even if it is not at the
" beginning of the line. Extra adjustment (b:blockCommentMiddleExtra) will
" be added.
"
function! s:GetBlockCommentIndent(CurrLNum, LastLNum)
let l:cursor = getpos('.')
let l:adj = 0
if a:LastLNum == searchpair(b:blockCommentStartRE, '', b:blockCommentEndRE, 'bWr')
\ && a:LastLNum > 0
let l:adj = col('.') + b:blockCommentMiddleExtra
normal ^
let l:adj -= col('.')
endif
call setpos('.', l:cursor)
return l:adj
endfunction
function! s:GetPostBlockCommentIndent(LastLNum)
let l:cursor = getpos('.')
let l:ind = 0
let l:comment_start_lnum = 0;
" Find beginning of block comment containing the start of line LastLNum
exec a:LastLNum
normal ^
let l:comment_start_lnum = searchpair(
\ b:blockCommentStartRE, b:blockCommentMiddleRE, b:blockCommentEndRE, 'bWr')
" Assume that the LastLNum is a block comment. If the comment both
" started and stopped on LastLNum, then searchpair will return 0. In that
" case, we just want to return the indent of LastLNum itself.
if 0 == l:comment_start_lnum
let l:comment_start_lnum = a:LastLNum
endif
let l:ind = indent(l:comment_start_lnum)
if 1 || l:ind != 0 && b:indent_anything_echo
let g:lastindent = g:lastindent .
\ "GetPostBlockCommentIndent: " . l:ind
endif
call setpos('.', l:cursor)
"return l:ind
return l:ind > 0 ? l:ind : 0
endfunction
"
" Get additional indentation based on blocks of code, as defined by the Head
" and Tail patterns.
"
function! s:GetPairIndent(CurrLine, LastLine, LastLNum, Head, Mid, Tail)
let levels = 0
let adj = 0
let origcol = col(".")
let origline = line(".")
"
" How many levels were started on the last line? Search backwards for
" pair starters until we're not on the last nonblank. If the last line
" doesn't contain the pair-starter, then don't bother with searchpair();
" it's a performance bottleneck because (I think) it will always search
" all the way back until it finds a match or can't search any more.
"
"
if a:LastLine =~ a:Head
while 1
"
" Include the limit of the search to be the last line. BIG
" performance booster! That also means we only have to see *if*
" there was a match, and not worry about where it is.
"
"let pairstart = searchpair(a:Head, a:Mid, a:Tail, 'Wb')
"if pairstart == 0 || pairstart != a:LastLNum
let pairstart = searchpair(a:Head, a:Mid, a:Tail, 'Wb', '', a:LastLNum)
if pairstart == 0 "|| pairstart != a:LastLNum
break
endif
let syn = synIDattr(synID(line("."), col("."), 1), "name")
" Also continue on the off chance that we find the match on the
" current line. This shouldn't happen, but the pattern might
" start with whitespace.
if syn =~ b:commentRE || syn =~ b:stringRE || pairstart == origline
continue
endif
let levels += 1
endwhile
endif
" If we aren't within a level that was started on the last line, then
" check how many levels were closed on the last line.
"
if levels == 0
" Move to the beginning of the last line
call cursor(a:LastLNum,0)
normal ^
" If the line starts with an open, The close shouldn't be counted as
" such, because we're looking for closes that didn't start on this
" line.
if a:LastLine =~ '^\s*' . a:Head ||
\ (a:Mid != '' && a:LastLine =~ '^\s*' . a:Mid)
let levels = 1
endif
"
" Count the closes on the last line (i.e. LastLNum), stopping once
" we've hit comments. If the line doesn't even contain the end of the
" pair, don't bother with searchpair() (same aforementioned
" rationale).
"
if a:LastLine =~ a:Tail
while 1
"
" Include the limit of the search to be the last line. BIG
" performance booster! That also means we only have to see
" *if* there was a match, and not worry about where it is.
"
"let pairend = searchpair(a:Head, a:Mid, a:Tail, 'W')
"if pairend == 0 || a:LastLNum != pairend
"let pairend = searchpair(a:Head, a:Mid, a:Tail, 'W', '', a:LastLNum)
let pairend = searchpair(a:Head, a:Mid, a:Tail, 'W',
\'InCommentOrString()', a:LastLNum)
if pairend == 0 "|| a:LastLNum != pairend
" STARTS with a:Tail, since we already know the line
" matches it.
if b:lastclosed.at < col('.') && (
\ a:LastLine =~ '^\s*' . a:Tail
\ || (a:Mid != '' && a:LastLine =~ '^\s*' . a:Mid) )
let b:lastclosed = {
\ 'at' : col('.'),
\ 'head' : a:Head,
\ 'mid' : a:Mid,
\ 'tail' : a:Tail }
endif
break
endif
" This might not be needed with the expr included in the
" search call.
"let syn = synIDattr(synID(line("."), col("."), 1), "name")
"if syn =~ b:commentRE || syn =~ b:stringRE || syn == ''
" break
"endif
let levels -= 1
" Track the last close to try to match pairs that start on
" line continuations
if b:lastclosed.at < col('.')
let b:lastclosed = {
\ 'at' : col('.'),
\ 'head' : a:Head,
\ 'mid' : a:Mid,
\ 'tail' : a:Tail }
endif
endwhile
endif
endif
" This is redundant, as per above
" If the current line starts with a close, count it. It won't effect the
" indentation of the next line because it is the first thing on the line
" and won't be counted as a "close on the last line".
if a:CurrLine =~ '^\s*' . a:Tail
\ || (a:Mid != '' && a:CurrLine =~ '^\s*' . a:Mid)
let levels -= 1
endif
" Restore original cursor location
call cursor(origline, origcol)
let adj = &sw*levels
if adj != 0 && b:indent_anything_echo
let g:lastindent = g:lastindent .
\ "GetPairIndent(" . a:Head . "/" . b:lastclosed.at . "):" . adj . " "
endif
return adj
endfunction
function! s:GetContIndent(Rule, CurrLine, LastLine, LastLNum, PrevLNum)
let adj = 0
let origcol = col(".")
let origline = line(".")
let lastcont = 0
let prevcont = 0
let l:lastlnum = a:LastLNum
let l:prevlnum = a:PrevLNum
let l:preblockstart = -1
" Get the last matching line number. If the match occurs w/in a comment
" or string, then it's a non-match.
"
"let lastmatchlnum = search(a:Rule.pattern, 'Wb', a:PrevLNum)
let lastmatchlnum = search(a:Rule.pattern, 'Wb', a:LastLNum)
let syn = synIDattr(synID(line("."), col("."), 1), "name")
"if syn =~ b:commentRE || syn =~ b:stringRE
if syn =~ b:commentRE || syn =~ b:stringRE || b:lastclosed.at > 0
let lastmatchlnum = 0
endif
" Should be able to just search to the line....
" " Figure out the last and previous continuation status
" if lastmatchlnum && lastmatchlnum == a:LastLNum
" let lastcont = 1
" endif
if lastmatchlnum == a:LastLNum
let lastcont = 1
endif
" start checking at the start of the block that ended on the prev line
if b:lastclosed.at > 0
call cursor(a:LastLNum, b:lastclosed.at)
" TODO: add 'skip' to skip comments
let l:preblockstart = searchpair(b:lastclosed.head, b:lastclosed.mid, b:lastclosed.tail, 'bW')
let g:lastindent .= ' postpair ("' . b:lastclosed.head . '"): '
\ . l:preblockstart . '/' . col('.') . ' '
if b:contTraversesLineComments
let l:prevlnum = GetPrevNonBlankNonComment(line('.') - 1)
else
let l:prevlnum = prevnonblank(line('.') - 1)
endif
endif
" Get the previous matching line number. If the match occurs w/in a
" comment or string, then it's a non-match. Use the adjusted, local
" prevlnum as the limit of the search, since we don't care about matches
" beyond that.
let prevmatchlnum = search(a:Rule.pattern, 'Wb', l:prevlnum)
let syn = synIDattr(synID(line("."), col("."), 1), "name")
" Handle:
" if ()
" if () {
" this_line; // should not be reduced
"if syn =~ b:commentRE || syn =~ b:stringRE
if syn =~ b:commentRE || syn =~ b:stringRE
let prevmatchlnum = 0
endif
" Should be able to just search to the line....
" if ( lastmatchlnum && lastmatchlnum == a:PrevLNum )
" \ || ( prevmatchlnum && prevmatchlnum == l:prevlnum )
" let prevcont = 1
" endif
"
" If there is a previous line, it is a continued line, and we haven't
" already done a positive adjustment for a pair/block, then reduce.
" Don't undo a positive adjustment for a pair because the previous line
" was a continued line. That will happen after the end of the block.
"if prevmatchlnum == l:prevlnum && b:pairadj <= 0
if l:prevlnum && prevmatchlnum == l:prevlnum && b:pairadj <= 0
let prevcont = 1
endif
"echom "lastcont: " . lastcont .
" \ ", prevcont: " . prevcont .
" \ ", lastmatchlnum: " . lastmatchlnum .
" \ ", prevmatchlnum: " . prevmatchlnum .
" \ ", lastlnum: " . a:LastLNum .
" \ ", PrevLNum: " . a:PrevLNum
let firstcont = (lastcont && !prevcont)
let firstcont = ((lastcont && !prevcont) || (lastcont && b:pairadj))
" If we are adjusting the current line for a pair, then don't count this
" line as a post-continuation line. The post continuation line will be
" after the close of said pair.
let postcont = (!lastcont && prevcont)
"let postcont = (!lastcont && prevcont && !b:pairadj )
let g:lastindent .= 'lastcont (' . lastcont . '), prevcont (' . prevcont . ') '
"if firstcont && a:CurrLine !~ '^\s*{'
if firstcont
if has_key(a:Rule, 'ignore') && a:CurrLine =~ a:Rule.ignore
let g:lastindent .= "(ignoring '" . a:Rule.ignore . "') "
else
let adj = adj + &sw
endif
"elseif postcont && a:LastLine !~ '^\s*{' "&& !b:pairadj
elseif postcont
if has_key(a:Rule, 'ignore') && a:LastLine =~ a:Rule.ignore
let g:lastindent .= "(ignoring '" . a:Rule.ignore . "') "
else
let adj = adj - &sw
endif
endif
call cursor(origline, origcol)
if adj != 0 && b:indent_anything_echo
let g:lastindent = g:lastindent .
\ "GetContIndent('" . a:Rule.pattern . "'):" . adj . " "
endif
return adj
endfunction

View File

@@ -0,0 +1,352 @@
let g:indexed_search_colors=0
" File: IndexedSearch.vim
" Author: Yakov Lerner <iler.ml@gmail.com>
" URL: http://www.vim.org/scripts/script.php?script_id=1682
" Last change: 2006-11-21
"
" This script redefines 6 search commands (/,?,n,N,*,#). At each search,
" it shows at which match number you are, and the total number
" of matches, like this: "At Nth match out of M". This is printed
" at the bottom line at every n,N,/,?,*,# search command, automatically.
"
" To try out the plugin, source it and play with N,n,*,#,/,? commands.
" At the bottom line, you'll see wha it shows. There are no new
" commands and no new behavior to learn. Just additional info
" on the bottom line, whenever you perform search.
"
" Works on vim6 and vim7. On very large files, won't cause slowdown
" because it checks the file size.
" Don't use if you're sensitive to one of its components :-)
"
" I am posting this plugin because I find it useful.
" -----------------------------------------------------
" Checking Where You Are with respect to Search Matches
" .....................................................
" You can press \\ or \/ (that's backslach then slash),
" or :ShowSearchIndex to show at which match index you are,
" without moving cursor.
"
" If cursor is exactly on the match, the message is:
" At Nth match of M
" If cursor is between matches, following messages are displayed:
" Betwen matches 189-190 of 300
" Before first match, of 300
" After last match, of 300
" ------------------------------------------------------
" To disable colors for messages, set 'let g:indexed_search_colors=0'.
" ------------------------------------------------------
" Performance. Plugin bypasses match counting when it would take
" too much time (too many matches, too large file). You can
" tune performance limits below, after comment "Performance tuning limits"
" ------------------------------------------------------
" In case of bugs and wishes, please email: iler.ml at gmail.com
" ------------------------------------------------------
" before 061119, it worked only vim7 not on vim6 (we use winrestview())
" after 061119, works only on vim6 (we avoid winrestview on vim6)
"if version < 700 | finish | endif " we need vim7 at least. Won't work for vim6
"if &cp | echo "warning: IndexedSearch.vim need nocp" | finish | endif " we need &nocp mode
if exists("g:indexed_search_plugin") | finish | endif
let g:indexed_search_plugin = 1
if !exists('g:indexed_search_colors')
let g:indexed_search_colors=1 " 1-use colors for messages, 0-no colors
endif
if !exists('g:indexed_search_shortmess')
let g:indexed_search_shortmess=0 " 1-longer messages; 0(or undefined)-longer messages.
endif
" ------------------ "Performance tuning limits" -------------------
if !exists('g:search_index_max')
let g:search_index_max=30000 " max filesize(in lines) up to what
" ShowCurrentSearchIndex() works
endif
if !exists("g:search_index_maxhit")
let g:search_index_maxhit=1000
endif
" -------------- End of Performance tuning limits ------------------
let s:save_cpo = &cpo
set cpo&vim
command! ShowSearchIndex :call s:ShowCurrentSearchIndex(1,'')
" before 061114 we had op invocation inside the function but this
" did not properly keep @/ and direction (func.return restores @/ and direction)
" after 061114 invoking op inside the function does not work because
" @/ and direction is restored at return from function
" We must have op invocation at the toplevel of mapping even though this
" makes mappings longer.
nnoremap <silent>n :let v:errmsg=''<cr>:silent! norm! n<cr>:call <SID>ShowCurrentSearchIndex(0,'!')<cr>
nnoremap <silent>N :let v:errmsg=''<cr>:silent! norm! N<cr>:call <SID>ShowCurrentSearchIndex(0,'!')<cr>
nnoremap <silent>* :let v:errmsg=''<cr>:silent! norm! *<cr>:call <SID>ShowCurrentSearchIndex(0,'!')<cr>
nnoremap <silent># :let v:errmsg=''<cr>:silent! norm! #<cr>:call <SID>ShowCurrentSearchIndex(0,'!')<cr>
nnoremap <silent>\/ :call <SID>ShowCurrentSearchIndex(1,'')<cr>
nnoremap <silent>\\ :call <SID>ShowCurrentSearchIndex(1,'')<cr>
nnoremap <silent>g/ :call <SID>ShowCurrentSearchIndex(1,'')<cr>
" before 061120, I had cmapping for <cr> which was very intrusive. Didn't work
" with supertab iInde<c-x><c-p>(resulted in something like recursive <c-r>=
" after 061120, I remap [/?] instead of remapping <cr>. Works in vim6, too
nnoremap / :call <SID>DelaySearchIndex(0,'')<cr>/
nnoremap ? :call <SID>DelaySearchIndex(0,'')<cr>?
let s:ScheduledEcho = ''
let s:DelaySearchIndex = 0
let g:IndSearchUT = &ut
func! s:ScheduleEcho(msg,highlight)
"if &ut > 50 | let g:IndSearchUT=&ut | let &ut=50 | endif
"if &ut > 100 | let g:IndSearchUT=&ut | let &ut=100 | endif
if &ut > 200 | let g:IndSearchUT=&ut | let &ut=200 | endif
" 061116 &ut is sometimes not restored and drops permanently to 50. But how ?
let s:ScheduledEcho = a:msg
let use_colors = !exists('g:indexed_search_colors') || g:indexed_search_colors
let s:ScheduledHighlight = ( use_colors ? a:highlight : "None" )
aug IndSearchEcho
au CursorHold *
\ exe 'set ut='.g:IndSearchUT |
\ if s:DelaySearchIndex | call s:ShowCurrentSearchIndex(0,'') |
\ let s:ScheduledEcho = s:Msg | let s:ScheduledHighlight = s:Highlight |
\ let s:DelaySearchIndex = 0 | endif |
\ if s:ScheduledEcho != ""
\ | exe "echohl ".s:ScheduledHighlight | echo s:ScheduledEcho | echohl None
\ | let s:ScheduledEcho='' |
\ endif |
\ aug IndSearchEcho | exe 'au!' | aug END | aug! IndSearchEcho
" how about moving contents of this au into function
aug END
endfun " s:ScheduleEcho
func! s:DelaySearchIndex(force,cmd)
let s:DelaySearchIndex = 1
call s:ScheduleEcho('','')
endfunc
func! s:ShowCurrentSearchIndex(force, cmd)
" NB: function saves and restores @/ and direction
" this used to cause me many troubles
call s:CountCurrentSearchIndex(a:force, a:cmd) " -> s:Msg, s:Highlight
if s:Msg != ""
call s:ScheduleEcho(s:Msg, s:Highlight )
endif
endfun
function! s:MilliSince( start )
" usage: let s = reltime() | sleep 100m | let milli = MilliSince(s)
let x = reltimestr( reltime( a:start ) )
" there can be leading spaces in x
let sec = substitute(x, '^ *\([0-9]\+\)', '\1', '')
let frac = substitute(x, '\.\([0-9]\+\)', '\1', '') . "000"
let milli = strpart( frac, 0, 3)
return sec * 1000 + milli
endfun
func! s:CountCurrentSearchIndex(force, cmd)
" sets globals -> s:Msg , s:Highlight
let s:Msg = '' | let s:Highlight = ''
let builtin_errmsg = ""
" echo "" | " make sure old msg is erased
if a:cmd == '!'
" if cmd is '!', we do not execute any command but report
" last errmsg
if v:errmsg != ""
echohl Error
echomsg v:errmsg
echohl None
endif
elseif a:cmd != ''
let v:errmsg = ""
silent! exe "norm! ".a:cmd
if v:errmsg != ""
echohl Error
echomsg v:errmsg
echohl None
endif
if line('$') >= g:search_index_max
" for large files, preserve original error messages and add nothing
return ""
endif
else
endif
if !a:force && line('$') >= g:search_index_max
let too_slow=1
" when too_slow, we'll want to switch the work over to CursorHold
return ""
endif
if @/ == '' | return "" | endif
if version >= 700
let save = winsaveview()
endif
let line = line('.')
let vcol = virtcol('.')
norm gg0
let num = 0 " total # of matches in the buffer
let exact = -1
let after = 0
let too_slow = 0 " if too_slow, we'll want to switch the work over to CursorHold
let s_opt = 'Wc'
while search(@/, s_opt) && ( num <= g:search_index_maxhit || a:force)
let num = num + 1
if line('.') == line && virtcol('.') == vcol
let exact = num
elseif line('.') < line || (line('.') == line && virtcol('.') < vcol)
let after = num
endif
let s_opt = 'W'
endwh
if version >= 700
call winrestview(save)
else
exe line
exe "norm! ".vcol."|"
endif
if !a:force && num > g:search_index_maxhit
if exact >= 0
let too_slow=1 " if too_slow, we'll want to switch the work over to CursorHold
let num=">".(num-1)
else
let s:Msg = ">".(num-1)." matches"
if v:errmsg != ""
let s:Msg = "" " avoid overwriting builtin errmsg with our ">1000 matches"
endif
return ""
endif
endif
let s:Highlight = "Directory"
if num == "0"
let s:Highlight = "Error"
let prefix = "No matches "
elseif exact == 1 && num==1
" s:Highlight remains default
"let prefix = "At single match"
let prefix = "Single match"
elseif exact == 1
let s:Highlight = "Search"
"let prefix = "At 1st match, # 1 of " . num
"let prefix = "First match, # 1 of " . num
let prefix = "First of " . num . " matches "
elseif exact == num
let s:Highlight = "LineNr"
"let prefix = "Last match, # ".num." of " . num
"let prefix = "At last match, # ".num." of " . num
let prefix = "Last of " . num . " matches "
elseif exact >= 0
"let prefix = "At # ".exact." match of " . num
"let prefix = "Match # ".exact." of " . num
"let prefix = "# ".exact." match of " . num
if exists('g:indexed_search_shortmess') && g:indexed_search_shortmess
let prefix = exact." of " . num . " matches "
else
let prefix = "Match ".exact." of " . num
endif
elseif after == 0
let s:Highlight = "MoreMsg"
let prefix = "Before first match, of ".num." matches "
if num == 1
let prefix = "Before single match"
endif
elseif after == num
let s:Highlight = "WarningMsg"
let prefix = "After last match of ".num." matches "
if num == 1
let prefix = "After single match"
endif
else
let prefix = "Between matches ".after."-".(after+1)." of ".num
endif
let s:Msg = prefix . " /".@/ . "/"
return ""
endfunc
" Messages Summary
"
" Short Message Long Message
" -------------------------------------------
" %d of %d matches Match %d of %d
" Last of %d matches <-same
" First of %d matches <-same
" No matchess <-same
" -------------------------------------------
let &cpo = s:save_cpo
" Last changes
" 2006-10-20 added limitation by # of matches
" 061021 lerner fixed problem with cmap <enter> that screwed maps
" 061021 colors added
" 061022 fixed g/ when too many matches
" 061106 got message to work with check for largefile right
" 061110 addition of DelayedEcho(ScheduledEcho) fixes and simplifies things
" 061110 mapping for nN*# greately simplifified by switching to ScheduledEcho
" 061110 fixed problem with i<c-o>/pat<cr> and c/PATTERN<CR> Markus Braun
" 061110 fixed bug in / and ?, Counting moved to Delayd
" 061110 fixed bug extra line+enter prompt in [/?] by addinf redraw
" 061110 fixed overwriting builtin errmsg with ">1000 matches"
" 061111 fixed bug with gg & 'set nosol' (gg->gg0)
" 061113 fixed mysterious eschewing of @/ wfte *,#
" 061113 fixed counting of match at the very beginning of file
" 061113 added msgs "Before single match", "After single match"
" 061113 fixed bug with &ut not always restored. This could happen if
" ScheduleEcho() was called twice in a row.
" 061114 fixed problem with **#n. Direction of the last n is incorrect (must be backward
" but was incorrectly forward)
" 061114 fixed disappearrance of "Hit BOTTOM" native msg when file<max and numhits>max
" 061116 changed hlgroup os "At last match" from DiffChange to LineNr. Looks more natural.
" 061120 shortened text messages.
" 061120 made to work on vim6
" 061120 bugfix for vim6 (virtcol() not col())
" 061120 another bug with virtcol() vs col()
" 061120 fixed [/?] on vim6 (vim6 doesn't have getcmdtype())
" 061121 fixed mapping in <cr> with supertab.vim. Switched to [/?] mapping, removed <cr> mapping.
" also shortened code considerably, made vim6 and vim7 work same way, removed need
" for getcmdtype().
" 061121 fixed handling of g:indexed_search_colors (Markus Braun)
" Wishlist
" - using high-precision timer of vim7, count number of millisec
" to run the counters, and base auto-disabling on time it takes.
" very complex regexes can be terribly slow even of files like 'man bash'
" which is mere 5k lines long. Also when there are >10k matches in the file
" set limit to 200 millisec
" - implement CursorHold bg counting to which too_slow will resort
" - even on large files, we can show "At last match", "After last match"
" - define global vars for all highlights, with defaults
" hh
" hh
" hh
" hh

File diff suppressed because it is too large Load Diff

4123
vim/plugin/NERD_tree.vim Executable file

File diff suppressed because it is too large Load Diff

205
vim/plugin/autotag.vim Normal file
View File

@@ -0,0 +1,205 @@
" Increment the number below for a dynamic #include guard
let s:autotag_vim_version=1
if exists("g:autotag_vim_version_sourced")
if s:autotag_vim_version == g:autotag_vim_version_sourced
finish
endif
endif
let g:autotag_vim_version_sourced=s:autotag_vim_version
" This file supplies automatic tag regeneration when saving files
" There's a problem with ctags when run with -a (append)
" ctags doesn't remove entries for the supplied source file that no longer exist
" so this script (implemented in python) finds a tags file for the file vim has
" just saved, removes all entries for that source file and *then* runs ctags -a
if has("python")
python << EEOOFF
import os
import string
import os.path
import fileinput
import sys
import vim
import time
# Just in case the ViM build you're using doesn't have subprocess
if sys.version < '2.4':
def do_cmd(cmd, cwd):
old_cwd=os.getcwd()
os.chdir(cwd)
(ch_in, ch_out) = os.popen2(cmd)
for line in ch_out:
pass
os.chdir(old_cwd)
import traceback
def format_exc():
return ''.join(traceback.format_exception(*list(sys.exc_info())))
else:
import subprocess
def do_cmd(cmd, cwd):
p = subprocess.Popen(cmd, shell=True, stdout=None, stderr=None, cwd=cwd)
from traceback import format_exc
def echo(str):
str=str.replace('\\', '\\\\')
str=str.replace('"', "'")
vim.command("redraw | echo \"%s\"" % str)
def diag(verbosity, threshold, msg, args = None):
if msg and args:
msg = msg % args
if verbosity >= threshold:
echo(msg)
def goodTag(line, excluded):
if line[0] == '!':
return True
else:
f = string.split(line, '\t')
if len(f) > 3 and not f[1] in excluded:
return True
return False
class AutoTag:
__maxTagsFileSize = 1024 * 1024 * 7
__threshold = 1
def __init__(self):
self.tags = {}
self.excludesuffix = [ "." + s for s in vim.eval("g:autotagExcludeSuffixes").split(".") ]
verbosity = long(vim.eval("g:autotagVerbosityLevel"))
self.verbosity = verbosity if verbosity > 0 else 0
self.sep_used_by_ctags = '/'
self.ctags_cmd = vim.eval("g:autotagCtagsCmd")
self.tags_file = str(vim.eval("g:autotagTagsFile"))
self.count = 0
def findTagFile(self, source):
self.__diag('source = "%s"' % (source, ))
( drive, file ) = os.path.splitdrive(source)
while file:
file = os.path.dirname(file)
#self.__diag('drive = "%s", file = "%s"' % (drive, file))
tagsFile = os.path.join(drive, file, self.tags_file)
#self.__diag('tagsFile "%s"' % tagsFile)
if os.path.isfile(tagsFile):
st = os.stat(tagsFile)
if st:
size = getattr(st, 'st_size', None)
if size is None:
self.__diag("Could not stat tags file %s" % tagsFile)
return None
if AutoTag.__maxTagsFileSize and size > AutoTag.__maxTagsFileSize:
self.__diag("Ignoring too big tags file %s" % tagsFile)
return None
return tagsFile
elif not file or file == os.sep or file == "//" or file == "\\\\":
#self.__diag('bail (file = "%s")' % (file, ))
return None
return None
def addSource(self, source):
if not source:
self.__diag('No source')
return
if os.path.basename(source) == self.tags_file:
self.__diag("Ignoring tags file %s" % (self.tags_file,))
return
(base, suff) = os.path.splitext(source)
if suff in self.excludesuffix:
self.__diag("Ignoring excluded suffix %s for file %s" % (source, suff))
return
tagsFile = self.findTagFile(source)
if tagsFile:
relativeSource = source[len(os.path.dirname(tagsFile)):]
if relativeSource[0] == os.sep:
relativeSource = relativeSource[1:]
if os.sep != self.sep_used_by_ctags:
relativeSource = string.replace(relativeSource, os.sep, self.sep_used_by_ctags)
if self.tags.has_key(tagsFile):
self.tags[tagsFile].append(relativeSource)
else:
self.tags[tagsFile] = [ relativeSource ]
def stripTags(self, tagsFile, sources):
self.__diag("Stripping tags for %s from tags file %s", (",".join(sources), tagsFile))
backup = ".SAFE"
input = fileinput.FileInput(files=tagsFile, inplace=True, backup=backup)
try:
for l in input:
l = l.strip()
if goodTag(l, sources):
print l
finally:
input.close()
try:
os.unlink(tagsFile + backup)
except StandardError:
pass
def updateTagsFile(self, tagsFile, sources):
tagsDir = os.path.dirname(tagsFile)
self.stripTags(tagsFile, sources)
if self.tags_file:
cmd = "%s -f %s -a " % (self.ctags_cmd, self.tags_file)
else:
cmd = "%s -a " % (self.ctags_cmd,)
for source in sources:
if os.path.isfile(os.path.join(tagsDir, source)):
cmd += " '%s'" % source
self.__diag("%s: %s", (tagsDir, cmd))
do_cmd(cmd, tagsDir)
def rebuildTagFiles(self):
for (tagsFile, sources) in self.tags.items():
self.updateTagsFile(tagsFile, sources)
def __diag(self, msg, args = None):
diag(self.verbosity, AutoTag.__threshold, msg, args)
EEOOFF
function! AutoTag()
python << EEOOFF
try:
if long(vim.eval("g:autotagDisabled")) == 0:
at = AutoTag()
at.addSource(vim.eval("expand(\"%:p\")"))
at.rebuildTagFiles()
except:
diag(1, -1, format_exc())
EEOOFF
if exists(":TlistUpdate")
TlistUpdate
endif
endfunction
if !exists("g:autotagDisabled")
let g:autotagDisabled=0
endif
if !exists("g:autotagVerbosityLevel")
let g:autotagVerbosityLevel=0
endif
if !exists("g:autotagExcludeSuffixes")
let g:autotagExcludeSuffixes="tml.xml.text.txt"
endif
if !exists("g:autotagCtagsCmd")
let g:autotagCtagsCmd="ctags"
endif
if !exists("g:autotagTagsFile")
let g:autotagTagsFile="tags"
endif
augroup autotag
au!
autocmd BufWritePost,FileWritePost * call AutoTag ()
augroup END
endif " has("python")
" vim:shiftwidth=3:ts=3

1140
vim/plugin/bufexplorer.vim Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,449 @@
" camelcasemotion.vim: Mappings for motion through CamelCaseWords and
" underscore_notation.
"
" DESCRIPTION: {{{1
" VIM provides many built-in motions, e.g. to move to the next word, or
" end of the current word. Most programming languages use either CamelCase
" ("anIdentifier") or underscore_notation ("an_identifier") naming
" conventions for identifiers. The best way to navigate inside those
" identifiers using VIM built-in motions is the '[count]f{char}' motion, i.e.
" 'f<uppercase char>' or 'f_', respectively. But we can make this easier:
"
" This script defines motions ',w', ',b' and ',e' (similar to 'w', 'b', 'e'),
" which do not move word-wise (forward/backward), but Camel-wise; i.e. to word
" boundaries and uppercase letters. The motions also work on underscore
" notation, where words are delimited by underscore ('_') characters.
" From here on, both CamelCase and underscore_notation entities are referred
" to as "words" (in double quotes). Just like with the regular motions, a
" [count] can be prepended to move over multiple "words" at once.
" Outside of "words" (e.g. in non-keyword characters like // or ;), the new
" motions move just like the regular motions.
"
" VIM provides a built-in text object called 'inner word' ('iw'), which works
" in operator-pending and visual mode. Analog to that, this script defines
" inner "word" motions 'i,w', 'i,b' and 'i,e', which select the "word" (or
" multiple "words" if a [count] is given) where the cursor is located.
"
" USAGE:
" Use the new motions ',w', ',b' and ',e' in normal mode, operator-pending
" mode (cp. :help operator), and visual mode. For example, type 'bc,w' to
" change 'Camel' in 'CamelCase' to something else.
"
" EXAMPLE: motions
" Given the following CamelCase identifiers in a source code fragment:
" set Script31337PathAndNameWithoutExtension11=%~dpn0
" set Script31337PathANDNameWITHOUTExtension11=%~dpn0
" and the corresponding identifiers in underscore_notation:
" set script_31337_path_and_name_without_extension_11=%~dpn0
" set SCRIPT_31337_PATH_AND_NAME_WITHOUT_EXTENSION_11=%~dpn0
"
" ,w moves to ([x] is cursor position): [s]et, [s]cript, [3]1337, [p]ath,
" [a]nd, [n]ame, [w]ithout, [e]xtension, [1]1, [d]pn0, dpn[0], [s]et
" ,b moves to: [d]pn0, [1]1, [e]xtension, [w]ithout, ...
" ,e moves to: se[t], scrip[t], 3133[7], pat[h], an[d], nam[e], withou[t],
" extensio[n], 1[1], dpn[0]
"
" EXAMPLE: inner motions
" Given the following identifier, with the cursor positioned at [x]:
" script_31337_path_and_na[m]e_without_extension_11
"
" v3i,w selects script_31337_path_and_[name_without_extension_]11
" v3i,b selects script_31337_[path_and_name]_without_extension_11
" v3i,e selects script_31337_path_and_[name_without_extension]_11
" Instead of visual mode, you can also use c3i,w to change, d3i,w to delete,
" gU3i,w to upper-case, and so on.
"
" INSTALLATION: {{{1
" Put the script into your user or system VIM plugin directory (e.g.
" ~/.vim/plugin).
"
" DEPENDENCIES:
" - Requires VIM 7.0 or higher.
"
" CONFIGURATION:
" If you want to use different mappings, map your keys to the
" <Plug>CamelCaseMotion_? mapping targets _before_ sourcing this script
" (e.g. in your .vimrc).
"
" Example: Replace the default 'w', 'b' and 'e' mappings instead of defining
" additional mappings ',w', ',b' and ',e':
" map <silent> w <Plug>CamelCaseMotion_w
" map <silent> b <Plug>CamelCaseMotion_b
" map <silent> e <Plug>CamelCaseMotion_e
"
" Example: Replace default 'iw' text-object and define 'ib' and 'ie' motions:
" omap <silent> iw <Plug>CamelCaseMotion_iw
" vmap <silent> iw <Plug>CamelCaseMotion_iw
" omap <silent> ib <Plug>CamelCaseMotion_ib
" vmap <silent> ib <Plug>CamelCaseMotion_ib
" omap <silent> ie <Plug>CamelCaseMotion_ie
" vmap <silent> ie <Plug>CamelCaseMotion_ie
"
" LIMITATIONS:
"
" ASSUMPTIONS:
"
" KNOWN PROBLEMS:
" - A degenerate CamelCaseWord containing '\U\u\d' (e.g. "MaP1Roblem")
" confuses the operator-pending and visual mode ,e mapping if 'selection' is
" not set to "exclusive". It'll skip "P" and select "P1" in one step. As a
" workaround, use ',w' instead of ',e'; those two mappings have the same
" effect inside CamelCaseWords, anyway.
" - The operator-pending and visual mode ,e mapping doesn't work properly when
" it reaches the end of the buffer; the final character of the moved-over
" "word" remains. As a workaround, use the default 'e' motion instead of
" ',e'.
" - When the VIM setting 'selection' is not set to "exclusive", a
" forward-backward combination in visual mode (e.g. 'v,w,b') selects one
" additional character to the left, instead of only the character where the
" motion started. Likewise, extension of the visual selection from the front
" end is off by one additional character.
"
" TODO:
"
" Copyright: (C) 2007-2008 by Ingo Karkat
" The VIM LICENSE applies to this script; see ':help copyright'.
"
" Source: Based on vimtip #1016 by Anthony Van Ham.
" Maintainer: Ingo Karkat <ingo@karkat.de>
" REVISION DATE REMARKS {{{1
" 1.40.017 19-May-2008 BF: Now using :normal! to be independent from
" any user mappings. Thanks to Neil Walker for the
" patch.
" 1.40.016 28-Apr-2008 BF: Wrong forward motion stop at the second
" digit if a word starts with multiple numbers
" (e.g. 1234.56789). Thanks to Wasim Ahmed for
" reporting this.
" 1.40.015 24-Apr-2008 ENH: Added inner "word" text objects 'i,w' etc.
" that work analoguous to the built-in 'iw' text
" object. Thanks to David Kotchan for this
" suggestion.
" 1.30.014 20-Apr-2008 The motions now also stop at non-keyword
" boundaries, just like the regular motions. This
" has no effect inside a CamelCaseWord or inside
" underscore_notation, but it makes the motions
" behave like the regular motions (which is
" important if you replace the default motions).
" Thanks to Mun Johl for reporting this.
" Now using non-capturing parentheses \%() in the
" patterns.
" 1.30.013 09-Apr-2008 Refactored away s:VisualCamelCaseMotion().
" Allowing users to use mappings different than
" ,w ,b ,e by defining <Plug>CamelCaseMotion_?
" target mappings. This can even be used to
" replace the default 'w', 'b' and 'e' mappings,
" as suggested by Mun Johl.
" Mappings are now created in a generic function.
" Now requires VIM 7.0 or higher.
" 1.20.012 02-Jun-2007 BF: Corrected motions through mixed
" CamelCase_and_UnderScore words by re-ordering
" and narrowing the search patterns.
" 1.20.011 02-Jun-2007 Thanks again to Joseph Barker for discussing the
" complicated visual mode mapping on the vim-dev
" mailing list and coming up with a great
" simplification:
" Removed s:CheckForChangesToTheSelectionSetting().
" Introduced s:VisualCamelCaseMotion(), which
" handles the differences depending on the
" 'selection' setting.
" Visual mode mappings now directly map to the
" s:VisualCamelCaseMotion() function; no mark is
" clobbered, the complex mapping with the inline
" expression has been retired.
" 1.20.010 29-May-2007 BF: The operator-pending and visual mode ,e
" mapping doesn't work properly when it reaches
" the end of line; the final character of the
" moved-over "word" remains. Fixed this problem
" unless the "word" is at the very end of the
" buffer.
" ENH: The visual mode motions now also (mostly)
" work with the (default) setting
" 'set selection=inclusive', instead of selecting
" one character too much.
" ENH: All mappings will check for changes to the
" 'selection' setting and remap the visual mode
" mappings via function
" s:SetupVisualModeMappings(). We cannot rely on
" the setting while sourcing camelcasemotion.vim
" because the mswin.vim script may be sourced
" afterwards, and its 'behave mswin' changes
" 'selection'.
" Refactored the arguments of function
" s:CamelCaseMotion(...).
" 1.10.009 28-May-2007 BF: Degenerate CamelCaseWords that consist of
" only a single uppercase letter (e.g. "P" in
" "MapPRoblem") are skipped by all motions. Thanks
" to Joseph Barker for reporting this.
" BF: In CamelCaseWords that consist of uppercase
" letters followed by decimals (e.g.
" "MyUPPER123Problem", the uppercase "word" is
" skipped by all motions.
" 1.10.008 28-May-2007 Incorporated major improvements and
" simplifications done by Joseph Barker:
" Operator-pending and visual mode motions now
" accept [count] of more than 9.
" Visual selections can now be extended from
" either end.
" Instead of misusing the :[range], the special
" variable v:count1 is used. Custom commands are
" not needed anymore.
" Operator-pending and visual mode mappings are
" now generic: There's only a single mapping for
" ,w that can be repeated, rather than having a
" separate mapping for 1,w 2,w 3,w ...
" 1.00.007 22-May-2007 Added documentation for publication.
" 006 20-May-2007 BF: visual mode [1,2,3],e on pure CamelCase
" mistakenly marks [2,4,6] words. If the cursor is
" on a uppercase letter, the search pattern
" '\u\l\+' doesn't match at the cursor position,
" so another match won. Changed search pattern
" from '\l\+',
" 005 16-May-2007 Added support for underscore notation.
" Added support for "forward to end of word"
" (',e') motion.
" 004 16-May-2007 Improved search pattern so that
" UppercaseWORDSInBetween and digits are handled,
" too.
" 003 15-May-2007 Changed mappings from <Leader>w to ,w;
" other \w mappings interfere here, because it's
" irritating when the cursor jump doesn't happen
" immediately, because VIM waits whether the
" mapping is complete. ,w is faster to type that
" \w (and, because of the left-right touch,
" preferred over gw).
" Added visual mode mappings.
" 0.02 15-Feb-2006 BF: missing <SID> for omaps.
" 0.01 11-Oct-2005 file creation
" Avoid installing twice or when in compatible mode
if exists("loaded_camelcasemotion") || (v:version < 700)
finish
endif
let loaded_camelcasemotion = 1
" }}}1
"- functions ------------------------------------------------------------------"
function! s:CamelCaseMove( direction, count, mode ) " {{{1
" Note: There is no inversion of the regular expression character class
" 'keyword character' (\k). We need an inversion "non-keyword" defined as
" "any non-whitespace character that is not a keyword character (e.g.
" [!@#$%^&*()]. This can be specified via a non-whitespace character in
" whose place no keyword character matches (\k\@!\S).
"echo "count is " . a:count
let l:i = 0
while l:i < a:count
if a:direction == 'e'
" "Forward to end" motion.
"call search( '\>\|\(\a\|\d\)\+\ze_', 'We' )
" end of ...
" number | ACRONYM followed by CamelCase or number | CamelCase | underscore_notation | non-keyword | word
call search( '\d\+\|\u\+\ze\%(\u\l\|\d\)\|\u\l\+\|\%(\a\|\d\)\+\ze_\|\%(\k\@!\S\)\+\|\%(_\@!\k\)\+\>', 'We' )
" Note: word must be defined as '\k\>'; '\>' on its own somehow
" dominates over the previous branch. Plus, \k must exclude the
" underscore, or a trailing one will be incorrectly moved over:
" '\%(_\@!\k\)'.
if a:mode == 'o'
" Note: Special additional treatment for operator-pending mode
" "forward to end" motion.
" The difference between normal mode, operator-pending and visual
" mode is that in the latter two, the motion must go _past_ the
" final "word" character, so that all characters of the "word" are
" selected. This is done by appending a 'l' motion after the
" search for the next "word".
"
" In operator-pending mode, the 'l' motion only works properly
" at the end of the line (i.e. when the moved-over "word" is at
" the end of the line) when the 'l' motion is allowed to move
" over to the next line. Thus, the 'l' motion is added
" temporarily to the global 'whichwrap' setting.
" Without this, the motion would leave out the last character in
" the line. I've also experimented with temporarily setting
" "set virtualedit=onemore" , but that didn't work.
let l:save_ww = &whichwrap
set whichwrap+=l
normal! l
let &whichwrap = l:save_ww
endif
else
" Forward (a:direction == '') and backward (a:direction == 'b')
" motion.
let l:direction = (a:direction == 'w' ? '' : a:direction)
" CamelCase: Jump to beginning of either (start of word, Word, WORD,
" 123).
" Underscore_notation: Jump to the beginning of an underscore-separated
" word or number.
"call search( '\<\|\u', 'W' . l:direction )
"call search( '\<\|\u\(\l\+\|\u\+\ze\u\)\|\d\+', 'W' . l:direction )
"call search( '\<\|\u\(\l\+\|\u\+\ze\u\)\|\d\+\|_\zs\(\a\|\d\)\+', 'W' . l:direction )
" beginning of ...
" word | empty line | non-keyword after whitespaces | non-whitespace after word | number | ACRONYM followed by CamelCase or number | CamelCase | underscore followed by ACRONYM, Camel, lowercase or number
call search( '\<\D\|^$\|\%(^\|\s\)\+\zs\k\@!\S\|\>\S\|\d\+\|\u\+\ze\%(\u\l\|\d\)\|\u\l\+\|_\zs\%(\u\+\|\u\l\+\|\l\+\|\d\+\)', 'W' . l:direction )
" Note: word must be defined as '\<\D' to avoid that a word like
" 1234Test is moved over as [1][2]34[T]est instead of [1]234[T]est
" because \< matches with zero width, and \d\+ will then start
" matching '234'. To fix that, we make \d\+ be solely responsible
" for numbers by taken this away from \< via \<\D. (An alternative
" would be to replace \d\+ with \D\%#\zs\d\+, but that one is more
" complex.) All other branches are not affected, because they match
" multiple characters and not the same character multiple times.
endif
let l:i = l:i + 1
endwhile
endfunction
" }}}1
function! s:CamelCaseMotion( direction, count, mode ) " {{{1
"*******************************************************************************
"* PURPOSE:
" Perform the motion over CamelCaseWords or underscore_notation.
"* ASSUMPTIONS / PRECONDITIONS:
" none
"* EFFECTS / POSTCONDITIONS:
" Move cursor / change selection.
"* INPUTS:
" a:direction one of 'w', 'b', 'e'
" a:count number of "words" to move over
" a:mode one of 'n', 'o', 'v', 'iv' (latter one is a special visual mode
" when inside the inner "word" text objects.
"* RETURN VALUES:
" none
"*******************************************************************************
" Visual mode needs special preparations and postprocessing;
" normal and operator-pending mode breeze through to s:CamelCaseMove().
if a:mode == 'v'
" Visual mode was left when calling this function. Reselecting the current
" selection returns to visual mode and allows to call search() and issue
" normal mode motions while staying in visual mode.
normal! gv
endif
if a:mode == 'v' || a:mode == 'iv'
" Note_1a:
if &selection != 'exclusive' && a:direction == 'w'
normal! l
endif
endif
call s:CamelCaseMove( a:direction, a:count, a:mode )
if a:mode == 'v' || a:mode == 'iv'
" Note: 'selection' setting.
if &selection == 'exclusive' && a:direction == 'e'
" When set to 'exclusive', the "forward to end" motion (',e') does not
" include the last character of the moved-over "word". To include that, an
" additional 'l' motion is appended to the motion; similar to the
" special treatment in operator-pending mode.
normal! l
elseif &selection != 'exclusive' && a:direction != 'e'
" Note_1b:
" The forward and backward motions move to the beginning of the next "word".
" When 'selection' is set to 'inclusive' or 'old', this is one character too far.
" The appended 'h' motion undoes this. Because of this backward step,
" though, the forward motion finds the current "word" again, and would
" be stuck on the current "word". An 'l' motion before the CamelCase
" motion (see Note_1a) fixes that.
normal! h
end
endif
endfunction
" }}}1
function! s:CamelCaseInnerMotion( direction, count ) " {{{1
" If the cursor is positioned on the first character of a CamelWord, the
" backward motion would move to the previous word, which would result in a
" wrong selection. To fix this, first move the cursor to the right, so that
" the backward motion definitely will cover the current "word" under the
" cursor.
normal! l
" Move "word" backwards, enter visual mode, then move "word" forward. This
" selects the inner "word" in visual mode; the operator-pending mode takes
" this selection as the area covered by the motion.
if a:direction == 'b'
" Do not do the selection backwards, because the backwards "word" motion
" in visual mode + selection=inclusive has an off-by-one error.
call s:CamelCaseMotion( 'b', a:count, 'n' )
normal! v
" We decree that 'b' is the opposite of 'e', not 'w'. This makes more
" sense at the end of a line and for underscore_notation.
call s:CamelCaseMotion( 'e', a:count, 'iv' )
else
call s:CamelCaseMotion( 'b', 1, 'n' )
normal! v
call s:CamelCaseMotion( a:direction, a:count, 'iv' )
endif
endfunction
" }}}1
"- mappings -------------------------------------------------------------------
" The count is passed into the function through the special variable 'v:count1',
" which is easier than misusing the :[range] that :call supports.
" <C-U> is used to delete the unused range.
" Another option would be to use a custom 'command! -count=1', but that doesn't
" work with the normal mode mapping: When a count is typed before the mapping,
" the ':' will convert a count of 3 into ':.,+2MyCommand', but ':3MyCommand'
" would be required to use -count and <count>.
"
" We do not provide the fourth "backward to end" motion (,E), because it is
" seldomly used.
function! s:CreateMotionMappings() "{{{1
" Create mappings according to this template:
" (* stands for the mode [nov], ? for the underlying motion [wbe].)
"
" *noremap <script> <Plug>CamelCaseMotion_? :<C-U>call <SID>CamelCaseMotion('?',v:count1,'*')<CR>
" if ! hasmapto('<Plug>CamelCaseMotion_?', '*')
" *map <silent> ,? <Plug>CamelCaseMotion_?
" endif
for l:mode in ['n', 'o', 'v']
for l:motion in ['w', 'b', 'e']
let l:targetMapping = '<Plug>CamelCaseMotion_' . l:motion
execute l:mode . 'noremap <script> ' . l:targetMapping . ' :<C-U>call <SID>CamelCaseMotion(''' . l:motion . ''',v:count1,''' . l:mode . ''')<CR>'
if ! hasmapto(l:targetMapping, l:mode)
execute l:mode . 'map <silent> ,' . l:motion . ' ' . l:targetMapping
endif
endfor
endfor
endfunction
" }}}1
" To create a text motion, a mapping for operator-pending mode needs to be
" defined. This mapping should move the cursor according to the implemented
" motion, or mark the covered text via a visual selection. As inner text motions
" need to mark both to the left and right of the cursor position, the visual
" selection needs to be used.
"
" VIM's built-in inner text objects also work in visual mode; they have
" different behavior depending on whether visual mode has just been entered or
" whether text has already been selected.
" We deviate from that and always override the existing selection.
function! s:CreateInnerMotionMappings() "{{{1
" Create mappings according to this template:
" (* stands for the mode [ov], ? for the underlying motion [wbe].)
"
" *noremap <script> <Plug>CamelCaseMotion_i? :<C-U>call <SID>CamelCaseInnerMotion('?',v:count1)<CR>
" if ! hasmapto('<Plug>CamelCaseInnerMotion_i?', '*')
" *map <silent> i,? <Plug>CamelCaseInnerMotion_i?
" endif
for l:mode in ['o', 'v']
for l:motion in ['w', 'b', 'e']
let l:targetMapping = '<Plug>CamelCaseMotion_i' . l:motion
execute l:mode . 'noremap <script> ' . l:targetMapping . ' :<C-U>call <SID>CamelCaseInnerMotion(''' . l:motion . ''',v:count1)<CR>'
if ! hasmapto(l:targetMapping, l:mode)
execute l:mode . 'map <silent> i,' . l:motion . ' ' . l:targetMapping
endif
endfor
endfor
endfunction
" }}}1
call s:CreateMotionMappings()
call s:CreateInnerMotionMappings()
" vim: set sts=4 sw=4 noexpandtab ff=unix fdm=marker :

536
vim/plugin/cecutil.vim Normal file
View File

@@ -0,0 +1,536 @@
" cecutil.vim : save/restore window position
" save/restore mark position
" save/restore selected user maps
" Author: Charles E. Campbell, Jr.
" Version: 18h ASTRO-ONLY
" Date: Apr 05, 2010
"
" Saving Restoring Destroying Marks: {{{1
" call SaveMark(markname) let savemark= SaveMark(markname)
" call RestoreMark(markname) call RestoreMark(savemark)
" call DestroyMark(markname)
" commands: SM RM DM
"
" Saving Restoring Destroying Window Position: {{{1
" call SaveWinPosn() let winposn= SaveWinPosn()
" call RestoreWinPosn() call RestoreWinPosn(winposn)
" \swp : save current window/buffer's position
" \rwp : restore current window/buffer's previous position
" commands: SWP RWP
"
" Saving And Restoring User Maps: {{{1
" call SaveUserMaps(mapmode,maplead,mapchx,suffix)
" call RestoreUserMaps(suffix)
"
" GetLatestVimScripts: 1066 1 :AutoInstall: cecutil.vim
"
" You believe that God is one. You do well. The demons also {{{1
" believe, and shudder. But do you want to know, vain man, that
" faith apart from works is dead? (James 2:19,20 WEB)
"redraw!|call inputsave()|call input("Press <cr> to continue")|call inputrestore()
" ---------------------------------------------------------------------
" Load Once: {{{1
if &cp || exists("g:loaded_cecutil")
finish
endif
let g:loaded_cecutil = "v18h"
let s:keepcpo = &cpo
set cpo&vim
"DechoRemOn
" =======================
" Public Interface: {{{1
" =======================
" ---------------------------------------------------------------------
" Map Interface: {{{2
if !hasmapto('<Plug>SaveWinPosn')
map <unique> <Leader>swp <Plug>SaveWinPosn
endif
if !hasmapto('<Plug>RestoreWinPosn')
map <unique> <Leader>rwp <Plug>RestoreWinPosn
endif
nmap <silent> <Plug>SaveWinPosn :call SaveWinPosn()<CR>
nmap <silent> <Plug>RestoreWinPosn :call RestoreWinPosn()<CR>
" ---------------------------------------------------------------------
" Command Interface: {{{2
com! -bar -nargs=0 SWP call SaveWinPosn()
com! -bar -nargs=? RWP call RestoreWinPosn(<args>)
com! -bar -nargs=1 SM call SaveMark(<q-args>)
com! -bar -nargs=1 RM call RestoreMark(<q-args>)
com! -bar -nargs=1 DM call DestroyMark(<q-args>)
com! -bar -nargs=1 WLR call s:WinLineRestore(<q-args>)
if v:version < 630
let s:modifier= "sil! "
else
let s:modifier= "sil! keepj "
endif
" ===============
" Functions: {{{1
" ===============
" ---------------------------------------------------------------------
" SaveWinPosn: {{{2
" let winposn= SaveWinPosn() will save window position in winposn variable
" call SaveWinPosn() will save window position in b:cecutil_winposn{b:cecutil_iwinposn}
" let winposn= SaveWinPosn(0) will *only* save window position in winposn variable (no stacking done)
fun! SaveWinPosn(...)
" echomsg "Decho: SaveWinPosn() a:0=".a:0
if line("$") == 1 && getline(1) == ""
" echomsg "Decho: SaveWinPosn : empty buffer"
return ""
endif
let so_keep = &l:so
let siso_keep = &siso
let ss_keep = &l:ss
setlocal so=0 siso=0 ss=0
let swline = line(".") " save-window line in file
let swcol = col(".") " save-window column in file
if swcol >= col("$")
let swcol= swcol + virtcol(".") - virtcol("$") " adjust for virtual edit (cursor past end-of-line)
endif
let swwline = winline() - 1 " save-window window line
let swwcol = virtcol(".") - wincol() " save-window window column
let savedposn = ""
" echomsg "Decho: sw[".swline.",".swcol."] sww[".swwline.",".swwcol."]"
let savedposn = "call GoWinbufnr(".winbufnr(0).")"
let savedposn = savedposn."|".s:modifier.swline
let savedposn = savedposn."|".s:modifier."norm! 0z\<cr>"
if swwline > 0
let savedposn= savedposn.":".s:modifier."call s:WinLineRestore(".(swwline+1).")\<cr>"
endif
if swwcol > 0
let savedposn= savedposn.":".s:modifier."norm! 0".swwcol."zl\<cr>"
endif
let savedposn = savedposn.":".s:modifier."call cursor(".swline.",".swcol.")\<cr>"
" save window position in
" b:cecutil_winposn_{iwinposn} (stack)
" only when SaveWinPosn() is used
if a:0 == 0
if !exists("b:cecutil_iwinposn")
let b:cecutil_iwinposn= 1
else
let b:cecutil_iwinposn= b:cecutil_iwinposn + 1
endif
" echomsg "Decho: saving posn to SWP stack"
let b:cecutil_winposn{b:cecutil_iwinposn}= savedposn
endif
let &l:so = so_keep
let &siso = siso_keep
let &l:ss = ss_keep
" if exists("b:cecutil_iwinposn") " Decho
" echomsg "Decho: b:cecutil_winpos{".b:cecutil_iwinposn."}[".b:cecutil_winposn{b:cecutil_iwinposn}."]"
" else " Decho
" echomsg "Decho: b:cecutil_iwinposn doesn't exist"
" endif " Decho
" echomsg "Decho: SaveWinPosn [".savedposn."]"
return savedposn
endfun
" ---------------------------------------------------------------------
" RestoreWinPosn: {{{2
" call RestoreWinPosn()
" call RestoreWinPosn(winposn)
fun! RestoreWinPosn(...)
" echomsg "Decho: RestoreWinPosn() a:0=".a:0
" echomsg "Decho: getline(1)<".getline(1).">"
" echomsg "Decho: line(.)=".line(".")
if line("$") == 1 && getline(1) == ""
" echomsg "Decho: RestoreWinPosn : empty buffer"
return ""
endif
let so_keep = &l:so
let siso_keep = &l:siso
let ss_keep = &l:ss
setlocal so=0 siso=0 ss=0
if a:0 == 0 || a:1 == ""
" use saved window position in b:cecutil_winposn{b:cecutil_iwinposn} if it exists
if exists("b:cecutil_iwinposn") && exists("b:cecutil_winposn{b:cecutil_iwinposn}")
" echomsg "Decho: using stack b:cecutil_winposn{".b:cecutil_iwinposn."}<".b:cecutil_winposn{b:cecutil_iwinposn}.">"
try
exe s:modifier.b:cecutil_winposn{b:cecutil_iwinposn}
catch /^Vim\%((\a\+)\)\=:E749/
" ignore empty buffer error messages
endtry
" normally drop top-of-stack by one
" but while new top-of-stack doesn't exist
" drop top-of-stack index by one again
if b:cecutil_iwinposn >= 1
unlet b:cecutil_winposn{b:cecutil_iwinposn}
let b:cecutil_iwinposn= b:cecutil_iwinposn - 1
while b:cecutil_iwinposn >= 1 && !exists("b:cecutil_winposn{b:cecutil_iwinposn}")
let b:cecutil_iwinposn= b:cecutil_iwinposn - 1
endwhile
if b:cecutil_iwinposn < 1
unlet b:cecutil_iwinposn
endif
endif
else
echohl WarningMsg
echomsg "***warning*** need to SaveWinPosn first!"
echohl None
endif
else " handle input argument
" echomsg "Decho: using input a:1<".a:1.">"
" use window position passed to this function
exe a:1
" remove a:1 pattern from b:cecutil_winposn{b:cecutil_iwinposn} stack
if exists("b:cecutil_iwinposn")
let jwinposn= b:cecutil_iwinposn
while jwinposn >= 1 " search for a:1 in iwinposn..1
if exists("b:cecutil_winposn{jwinposn}") " if it exists
if a:1 == b:cecutil_winposn{jwinposn} " and the pattern matches
unlet b:cecutil_winposn{jwinposn} " unlet it
if jwinposn == b:cecutil_iwinposn " if at top-of-stack
let b:cecutil_iwinposn= b:cecutil_iwinposn - 1 " drop stacktop by one
endif
endif
endif
let jwinposn= jwinposn - 1
endwhile
endif
endif
" Seems to be something odd: vertical motions after RWP
" cause jump to first column. The following fixes that.
" Note: was using wincol()>1, but with signs, a cursor
" at column 1 yields wincol()==3. Beeping ensued.
let vekeep= &ve
set ve=all
if virtcol('.') > 1
exe s:modifier."norm! hl"
elseif virtcol(".") < virtcol("$")
exe s:modifier."norm! lh"
endif
let &ve= vekeep
let &l:so = so_keep
let &l:siso = siso_keep
let &l:ss = ss_keep
" echomsg "Decho: RestoreWinPosn"
endfun
" ---------------------------------------------------------------------
" s:WinLineRestore: {{{2
fun! s:WinLineRestore(swwline)
" echomsg "Decho: s:WinLineRestore(swwline=".a:swwline.")"
while winline() < a:swwline
let curwinline= winline()
exe s:modifier."norm! \<c-y>"
if curwinline == winline()
break
endif
endwhile
" echomsg "Decho: s:WinLineRestore"
endfun
" ---------------------------------------------------------------------
" GoWinbufnr: go to window holding given buffer (by number) {{{2
" Prefers current window; if its buffer number doesn't match,
" then will try from topleft to bottom right
fun! GoWinbufnr(bufnum)
" call Dfunc("GoWinbufnr(".a:bufnum.")")
if winbufnr(0) == a:bufnum
" call Dret("GoWinbufnr : winbufnr(0)==a:bufnum")
return
endif
winc t
let first=1
while winbufnr(0) != a:bufnum && (first || winnr() != 1)
winc w
let first= 0
endwhile
" call Dret("GoWinbufnr")
endfun
" ---------------------------------------------------------------------
" SaveMark: sets up a string saving a mark position. {{{2
" For example, SaveMark("a")
" Also sets up a global variable, g:savemark_{markname}
fun! SaveMark(markname)
" call Dfunc("SaveMark(markname<".a:markname.">)")
let markname= a:markname
if strpart(markname,0,1) !~ '\a'
let markname= strpart(markname,1,1)
endif
" call Decho("markname=".markname)
let lzkeep = &lz
set lz
if 1 <= line("'".markname) && line("'".markname) <= line("$")
let winposn = SaveWinPosn(0)
exe s:modifier."norm! `".markname
let savemark = SaveWinPosn(0)
let g:savemark_{markname} = savemark
let savemark = markname.savemark
call RestoreWinPosn(winposn)
else
let g:savemark_{markname} = ""
let savemark = ""
endif
let &lz= lzkeep
" call Dret("SaveMark : savemark<".savemark.">")
return savemark
endfun
" ---------------------------------------------------------------------
" RestoreMark: {{{2
" call RestoreMark("a") -or- call RestoreMark(savemark)
fun! RestoreMark(markname)
" call Dfunc("RestoreMark(markname<".a:markname.">)")
if strlen(a:markname) <= 0
" call Dret("RestoreMark : no such mark")
return
endif
let markname= strpart(a:markname,0,1)
if markname !~ '\a'
" handles 'a -> a styles
let markname= strpart(a:markname,1,1)
endif
" call Decho("markname=".markname." strlen(a:markname)=".strlen(a:markname))
let lzkeep = &lz
set lz
let winposn = SaveWinPosn(0)
if strlen(a:markname) <= 2
if exists("g:savemark_{markname}") && strlen(g:savemark_{markname}) != 0
" use global variable g:savemark_{markname}
" call Decho("use savemark list")
call RestoreWinPosn(g:savemark_{markname})
exe "norm! m".markname
endif
else
" markname is a savemark command (string)
" call Decho("use savemark command")
let markcmd= strpart(a:markname,1)
call RestoreWinPosn(markcmd)
exe "norm! m".markname
endif
call RestoreWinPosn(winposn)
let &lz = lzkeep
" call Dret("RestoreMark")
endfun
" ---------------------------------------------------------------------
" DestroyMark: {{{2
" call DestroyMark("a") -- destroys mark
fun! DestroyMark(markname)
" call Dfunc("DestroyMark(markname<".a:markname.">)")
" save options and set to standard values
let reportkeep= &report
let lzkeep = &lz
set lz report=10000
let markname= strpart(a:markname,0,1)
if markname !~ '\a'
" handles 'a -> a styles
let markname= strpart(a:markname,1,1)
endif
" call Decho("markname=".markname)
let curmod = &mod
let winposn = SaveWinPosn(0)
1
let lineone = getline(".")
exe "k".markname
d
put! =lineone
let &mod = curmod
call RestoreWinPosn(winposn)
" restore options to user settings
let &report = reportkeep
let &lz = lzkeep
" call Dret("DestroyMark")
endfun
" ---------------------------------------------------------------------
" QArgSplitter: to avoid \ processing by <f-args>, <q-args> is needed. {{{2
" However, <q-args> doesn't split at all, so this one returns a list
" with splits at all whitespace (only!), plus a leading length-of-list.
" The resulting list: qarglist[0] corresponds to a:0
" qarglist[i] corresponds to a:{i}
fun! QArgSplitter(qarg)
" call Dfunc("QArgSplitter(qarg<".a:qarg.">)")
let qarglist = split(a:qarg)
let qarglistlen = len(qarglist)
let qarglist = insert(qarglist,qarglistlen)
" call Dret("QArgSplitter ".string(qarglist))
return qarglist
endfun
" ---------------------------------------------------------------------
" ListWinPosn: {{{2
"fun! ListWinPosn() " Decho
" if !exists("b:cecutil_iwinposn") || b:cecutil_iwinposn == 0 " Decho
" call Decho("nothing on SWP stack") " Decho
" else " Decho
" let jwinposn= b:cecutil_iwinposn " Decho
" while jwinposn >= 1 " Decho
" if exists("b:cecutil_winposn{jwinposn}") " Decho
" call Decho("winposn{".jwinposn."}<".b:cecutil_winposn{jwinposn}.">") " Decho
" else " Decho
" call Decho("winposn{".jwinposn."} -- doesn't exist") " Decho
" endif " Decho
" let jwinposn= jwinposn - 1 " Decho
" endwhile " Decho
" endif " Decho
"endfun " Decho
"com! -nargs=0 LWP call ListWinPosn() " Decho
" ---------------------------------------------------------------------
" SaveUserMaps: this function sets up a script-variable (s:restoremap) {{{2
" which can be used to restore user maps later with
" call RestoreUserMaps()
"
" mapmode - see :help maparg for details (n v o i c l "")
" ex. "n" = Normal
" The letters "b" and "u" are optional prefixes;
" The "u" means that the map will also be unmapped
" The "b" means that the map has a <buffer> qualifier
" ex. "un" = Normal + unmapping
" ex. "bn" = Normal + <buffer>
" ex. "bun" = Normal + <buffer> + unmapping
" ex. "ubn" = Normal + <buffer> + unmapping
" maplead - see mapchx
" mapchx - "<something>" handled as a single map item.
" ex. "<left>"
" - "string" a string of single letters which are actually
" multiple two-letter maps (using the maplead:
" maplead . each_character_in_string)
" ex. maplead="\" and mapchx="abc" saves user mappings for
" \a, \b, and \c
" Of course, if maplead is "", then for mapchx="abc",
" mappings for a, b, and c are saved.
" - :something handled as a single map item, w/o the ":"
" ex. mapchx= ":abc" will save a mapping for "abc"
" suffix - a string unique to your plugin
" ex. suffix= "DrawIt"
fun! SaveUserMaps(mapmode,maplead,mapchx,suffix)
" call Dfunc("SaveUserMaps(mapmode<".a:mapmode."> maplead<".a:maplead."> mapchx<".a:mapchx."> suffix<".a:suffix.">)")
if !exists("s:restoremap_{a:suffix}")
" initialize restoremap_suffix to null string
let s:restoremap_{a:suffix}= ""
endif
" set up dounmap: if 1, then save and unmap (a:mapmode leads with a "u")
" if 0, save only
let mapmode = a:mapmode
let dounmap = 0
let dobuffer = ""
while mapmode =~ '^[bu]'
if mapmode =~ '^u'
let dounmap = 1
let mapmode = strpart(a:mapmode,1)
elseif mapmode =~ '^b'
let dobuffer = "<buffer> "
let mapmode = strpart(a:mapmode,1)
endif
endwhile
" call Decho("dounmap=".dounmap." dobuffer<".dobuffer.">")
" save single map :...something...
if strpart(a:mapchx,0,1) == ':'
" call Decho("save single map :...something...")
let amap= strpart(a:mapchx,1)
if amap == "|" || amap == "\<c-v>"
let amap= "\<c-v>".amap
endif
let amap = a:maplead.amap
let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|:silent! ".mapmode."unmap ".dobuffer.amap
if maparg(amap,mapmode) != ""
let maprhs = substitute(maparg(amap,mapmode),'|','<bar>','ge')
let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|:".mapmode."map ".dobuffer.amap." ".maprhs
endif
if dounmap
exe "silent! ".mapmode."unmap ".dobuffer.amap
endif
" save single map <something>
elseif strpart(a:mapchx,0,1) == '<'
" call Decho("save single map <something>")
let amap = a:mapchx
if amap == "|" || amap == "\<c-v>"
let amap= "\<c-v>".amap
" call Decho("amap[[".amap."]]")
endif
let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|silent! ".mapmode."unmap ".dobuffer.amap
if maparg(a:mapchx,mapmode) != ""
let maprhs = substitute(maparg(amap,mapmode),'|','<bar>','ge')
let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|".mapmode."map ".dobuffer.amap." ".maprhs
endif
if dounmap
exe "silent! ".mapmode."unmap ".dobuffer.amap
endif
" save multiple maps
else
" call Decho("save multiple maps")
let i= 1
while i <= strlen(a:mapchx)
let amap= a:maplead.strpart(a:mapchx,i-1,1)
if amap == "|" || amap == "\<c-v>"
let amap= "\<c-v>".amap
endif
let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|silent! ".mapmode."unmap ".dobuffer.amap
if maparg(amap,mapmode) != ""
let maprhs = substitute(maparg(amap,mapmode),'|','<bar>','ge')
let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|".mapmode."map ".dobuffer.amap." ".maprhs
endif
if dounmap
exe "silent! ".mapmode."unmap ".dobuffer.amap
endif
let i= i + 1
endwhile
endif
" call Dret("SaveUserMaps : restoremap_".a:suffix.": ".s:restoremap_{a:suffix})
endfun
" ---------------------------------------------------------------------
" RestoreUserMaps: {{{2
" Used to restore user maps saved by SaveUserMaps()
fun! RestoreUserMaps(suffix)
" call Dfunc("RestoreUserMaps(suffix<".a:suffix.">)")
if exists("s:restoremap_{a:suffix}")
let s:restoremap_{a:suffix}= substitute(s:restoremap_{a:suffix},'|\s*$','','e')
if s:restoremap_{a:suffix} != ""
" call Decho("exe ".s:restoremap_{a:suffix})
exe "silent! ".s:restoremap_{a:suffix}
endif
unlet s:restoremap_{a:suffix}
endif
" call Dret("RestoreUserMaps")
endfun
" ==============
" Restore: {{{1
" ==============
let &cpo= s:keepcpo
unlet s:keepcpo
" ================
" Modelines: {{{1
" ================
" vim: ts=4 fdm=marker

View File

@@ -0,0 +1,166 @@
" Vim default schemes
amenu T&hemes.D&efault.Blue :colo blue<CR>
amenu T&hemes.D&efault.DarkBlue :colo darkblue<CR>
amenu T&hemes.D&efault.Default :colo default<CR>
amenu T&hemes.D&efault.Delek :colo delek<CR>
amenu T&hemes.D&efault.Desert :colo desert<CR>
amenu T&hemes.D&efault.ElfLord :colo elflord<CR>
amenu T&hemes.D&efault.Evening :colo evening<CR>
amenu T&hemes.D&efault.Koehler :colo koehler<CR>
amenu T&hemes.D&efault.Morning :colo morning<CR>
amenu T&hemes.D&efault.Murphy :colo murphy<CR>
amenu T&hemes.D&efault.Pablo :colo pablo<CR>
amenu T&hemes.D&efault.PeachPuff :colo peachpuff<CR>
amenu T&hemes.D&efault.Ron :colo ron<CR>
amenu T&hemes.D&efault.Shine :colo shine<CR>
amenu T&hemes.D&efault.Torte :colo torte<CR>
" Recommended Themes
amenu T&hemes.&Recommendations.InkPot :colo inkpot<CR>
amenu T&hemes.&Recommendations.MetaCosm :colo metacosm<CR>
amenu T&hemes.&Recommendations.MidNight2 :colo midnight2<CR>
amenu T&hemes.&Recommendations.PS_Warm :let psc_style='warm'<CR>:colo ps_color<CR>
amenu T&hemes.-s1- :
"submenu black
amenu T&hemes.black.brookstream :colo brookstream<CR>
amenu T&hemes.black.candy :colo candy<CR>
amenu T&hemes.black.colorer :colo colorer<CR>
amenu T&hemes.black.dante :colo dante<CR>
amenu T&hemes.black.darkocean :colo darkocean<CR>
amenu T&hemes.black.dw_blue :colo dw_blue<CR>
amenu T&hemes.black.dw_cyan :colo dw_cyan<CR>
amenu T&hemes.black.dw_green :colo dw_green<CR>
amenu T&hemes.black.dw_orange :colo dw_orange<CR>
amenu T&hemes.black.dw_purple :colo dw_purple<CR>
amenu T&hemes.black.dw_red :colo dw_red<CR>
amenu T&hemes.black.dw_yellow :colo dw_yellow<CR>
amenu T&hemes.black.elflord :colo elflord<CR>
amenu T&hemes.black.fnaqevan :colo fnaqevan<CR>
amenu T&hemes.black.golden :colo golden<CR>
amenu T&hemes.black.*inkpot :colo inkpot<CR>
amenu T&hemes.black.koehler :colo koehler<CR>
amenu T&hemes.black.less :colo less<CR>
amenu T&hemes.black.manxome :colo manxome<CR>
amenu T&hemes.black.matrix :colo matrix<CR>
amenu T&hemes.black.metacosm :colo metacosm<CR>
amenu T&hemes.black.*motus :colo motus<CR>
amenu T&hemes.black.murphy :colo murphy<CR>
amenu T&hemes.black.neverness :colo neverness<CR>
amenu T&hemes.black.nightwish :colo nightwish<CR>
amenu T&hemes.black.oceanblack :colo oceanblack<CR>
amenu T&hemes.black.pablo :colo pablo<CR>
amenu T&hemes.black.*ps_color :colo ps_color<CR>
amenu T&hemes.black.relaxedgreen :colo relaxedgreen<CR>
amenu T&hemes.black.ron :colo ron<CR>
amenu T&hemes.black.tango :colo tango<CR>
amenu T&hemes.black.*torte :colo torte<CR>
amenu T&hemes.black.vibrantink :colo vibrantink<CR>
amenu T&hemes.black.*vividchalk :colo vividchalk<CR>
"submenu blue
amenu T&hemes.blue.astronaut :colo astronaut<CR>
amenu T&hemes.blue.asu1dark :colo asu1dark<CR>
amenu T&hemes.blue.blue :colo blue<CR>
amenu T&hemes.blue.bluegreen :colo bluegreen<CR>
amenu T&hemes.blue.borland :colo borland<CR>
amenu T&hemes.blue.breeze :colo breeze<CR>
amenu T&hemes.blue.darkblue :colo darkblue<CR>
amenu T&hemes.blue.darkblue2 :colo darkblue2<CR>
amenu T&hemes.blue.denim :colo denim<CR>
amenu T&hemes.blue.desertedocean :colo desertedocean<CR>
amenu T&hemes.blue.dusk :colo dusk<CR>
amenu T&hemes.blue.hhazure :colo hhazure<CR>
amenu T&hemes.blue.midnight :colo midnight<CR>
amenu T&hemes.blue.midnight2 :colo midnight2<CR>
amenu T&hemes.blue.navajo-night :colo navajo-night<CR>
amenu T&hemes.blue.oceandeep :colo oceandeep<CR>
amenu T&hemes.blue.sea :colo sea<CR>
amenu T&hemes.blue.softblue :colo softblue<CR>
"submenu cyan
amenu T&hemes.cyan.darkslategray :colo darkslategray<CR>
amenu T&hemes.cyan.marklar :colo marklar<CR>
"submenu darkgrey
amenu T&hemes.darkgrey.candycode :colo candycode<CR>
amenu T&hemes.darkgrey.darktango :colo darktango<CR>
amenu T&hemes.darkgrey.hhspring :colo hhspring<CR>
amenu T&hemes.darkgrey.hhteal :colo hhteal<CR>
amenu T&hemes.darkgrey.hhviolet :colo hhviolet<CR>
amenu T&hemes.darkgrey.lettuce :colo lettuce<CR>
amenu T&hemes.darkgrey.night :colo night<CR>
amenu T&hemes.darkgrey.rdark :colo rdark<CR>
"submenu green
amenu T&hemes.green.*tabula :colo tabula<CR>
"submenu grey
amenu T&hemes.grey.biogoo :colo biogoo<CR>
amenu T&hemes.grey.camo :colo camo<CR>
amenu T&hemes.grey.*dawn :colo dawn<CR>
amenu T&hemes.grey.desert :colo desert<CR>
amenu T&hemes.grey.desertEx :colo desertEx<CR>
amenu T&hemes.grey.evening :colo evening<CR>
amenu T&hemes.grey.fog :colo fog<CR>
amenu T&hemes.grey.freya :colo freya<CR>
amenu T&hemes.grey.neon :colo neon<CR>
amenu T&hemes.grey.slate :colo slate<CR>
amenu T&hemes.grey.umber-green :colo umber-green<CR>
amenu T&hemes.grey.xemacs :colo xemacs<CR>
amenu T&hemes.grey.*zenburn :colo zenburn<CR>
"submenu magenta
amenu T&hemes.magenta.lilac :colo lilac<CR>
"submenu offwhite
amenu T&hemes.offwhite.autumn :colo autumn<CR>
amenu T&hemes.offwhite.autumnleaf :colo autumnleaf<CR>
amenu T&hemes.offwhite.*baycomb :colo baycomb<CR>
amenu T&hemes.offwhite.fine_blue :colo fine_blue<CR>
amenu T&hemes.offwhite.fruit :colo fruit<CR>
amenu T&hemes.offwhite.habiLight :colo habiLight<CR>
amenu T&hemes.offwhite.ironman :colo ironman<CR>
amenu T&hemes.offwhite.morning :colo morning<CR>
amenu T&hemes.offwhite.nuvola :colo nuvola<CR>
amenu T&hemes.offwhite.oceanlight :colo oceanlight<CR>
amenu T&hemes.offwhite.pyte :colo pyte<CR>
amenu T&hemes.offwhite.simpleandfriendly :colo simpleandfriendly<CR>
"submenu red
amenu T&hemes.red.ChocolateLiquor :colo ChocolateLiquor<CR>
amenu T&hemes.red.hhpink :colo hhpink<CR>
amenu T&hemes.red.*navajo :colo navajo<CR>
amenu T&hemes.red.peachpuff :colo peachpuff<CR>
amenu T&hemes.red.tomatosoup :colo tomatosoup<CR>
"submenu unknown
amenu T&hemes.unknown.bw :colo bw<CR>
amenu T&hemes.unknown.calmar256-light :colo calmar256-light<CR>
amenu T&hemes.unknown.chela_light :colo chela_light<CR>
amenu T&hemes.unknown.colorscheme_template :colo colorscheme_template<CR>
amenu T&hemes.unknown.default :colo default<CR>
amenu T&hemes.unknown.desert256 :colo desert256<CR>
amenu T&hemes.unknown.impact :colo impact<CR>
amenu T&hemes.unknown.psql :colo psql<CR>
amenu T&hemes.unknown.vc :colo vc<CR>
"submenu white
amenu T&hemes.white.delek :colo delek<CR>
amenu T&hemes.white.eclipse :colo eclipse<CR>
amenu T&hemes.white.martin_krischik :colo martin_krischik<CR>
amenu T&hemes.white.*moria :colo moria<CR>
amenu T&hemes.white.print_bw :colo print_bw<CR>
amenu T&hemes.white.shine :colo shine<CR>
amenu T&hemes.white.*sienna :colo sienna<CR>
amenu T&hemes.white.tolerable :colo tolerable<CR>
amenu T&hemes.white.zellner :colo zellner<CR>
"submenu yellow
amenu T&hemes.yellow.PapayaWhip :colo PapayaWhip<CR>
amenu T&hemes.yellow.buttercream :colo buttercream<CR>
amenu T&hemes.yellow.hhorange :colo hhorange<CR>
amenu T&hemes.yellow.olive :colo olive<CR>
amenu T&hemes.yellow.professional :colo professional<CR>
amenu T&hemes.yellow.robinhood :colo robinhood<CR>

216
vim/plugin/conque_term.vim Normal file
View File

@@ -0,0 +1,216 @@
" FILE: plugin/conque_term.vim {{{
" AUTHOR: Nico Raffo <nicoraffo@gmail.com>
" WEBSITE: http://conque.googlecode.com
" MODIFIED: 2011-09-02
" VERSION: 2.3, for Vim 7.0
" LICENSE:
" Conque - Vim terminal/console emulator
" Copyright (C) 2009-2011 Nico Raffo
"
" MIT License
"
" Permission is hereby granted, free of charge, to any person obtaining a copy
" of this software and associated documentation files (the "Software"), to deal
" in the Software without restriction, including without limitation the rights
" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
" copies of the Software, and to permit persons to whom the Software is
" furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included in
" all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
" THE SOFTWARE.
" }}}
" See docs/conque_term.txt for help or type :help ConqueTerm
if exists('g:ConqueTerm_Loaded') || v:version < 700
finish
endif
" **********************************************************************************************************
" **** DEFAULT CONFIGURATION *******************************************************************************
" **********************************************************************************************************
" DO NOT EDIT CONFIGURATION SETTINGS IN THIS FILE!
" Define these variables in your local .vimrc to over-ride the default values
" {{{
" Fast mode {{{
" Disables all features which could cause Conque to run slowly, including:
" * Disables terminal colors
" * Disables some multi-byte character handling
if !exists('g:ConqueTerm_FastMode')
let g:ConqueTerm_FastMode = 0
endif " }}}
" automatically go into insert mode when entering buffer {{{
if !exists('g:ConqueTerm_InsertOnEnter')
let g:ConqueTerm_InsertOnEnter = 0
endif " }}}
" Allow user to use <C-w> keys to switch window in insert mode. {{{
if !exists('g:ConqueTerm_CWInsert')
let g:ConqueTerm_CWInsert = 0
endif " }}}
" Choose key mapping to leave insert mode {{{
" If you choose something other than '<Esc>', then <Esc> will be sent to terminal
" Using a different key will usually fix Alt/Meta key issues
if !exists('g:ConqueTerm_EscKey')
let g:ConqueTerm_EscKey = '<Esc>'
endif " }}}
" Use this key to execute the current file in a split window. {{{
" THIS IS A GLOBAL KEY MAPPING
if !exists('g:ConqueTerm_ExecFileKey')
let g:ConqueTerm_ExecFileKey = '<F11>'
endif " }}}
" Use this key to send the current file contents to conque. {{{
" THIS IS A GLOBAL KEY MAPPING
if !exists('g:ConqueTerm_SendFileKey')
let g:ConqueTerm_SendFileKey = '<F10>'
endif " }}}
" Use this key to send selected text to conque. {{{
" THIS IS A GLOBAL KEY MAPPING
if !exists('g:ConqueTerm_SendVisKey')
let g:ConqueTerm_SendVisKey = '<F9>'
endif " }}}
" Use this key to toggle terminal key mappings. {{{
" Only mapped inside of Conque buffers.
if !exists('g:ConqueTerm_ToggleKey')
let g:ConqueTerm_ToggleKey = '<F8>'
endif " }}}
" Enable color. {{{
" If your apps use a lot of color it will slow down the shell.
" 0 - no terminal colors. You still will see Vim syntax highlighting.
" 1 - limited terminal colors (recommended). Past terminal color history cleared regularly.
" 2 - all terminal colors. Terminal color history never cleared.
if !exists('g:ConqueTerm_Color')
let g:ConqueTerm_Color = 1
endif " }}}
" Color mode. Windows ONLY {{{
" Set this variable to 'conceal' to use Vim's conceal mode for terminal colors.
" This makes colors render much faster, but has some odd baggage.
if !exists('g:ConqueTerm_ColorMode')
let g:ConqueTerm_ColorMode = ''
endif " }}}
" TERM environment setting {{{
if !exists('g:ConqueTerm_TERM')
let g:ConqueTerm_TERM = 'vt100'
endif " }}}
" Syntax for your buffer {{{
if !exists('g:ConqueTerm_Syntax')
let g:ConqueTerm_Syntax = 'conque_term'
endif " }}}
" Keep on updating the shell window after you've switched to another buffer {{{
if !exists('g:ConqueTerm_ReadUnfocused')
let g:ConqueTerm_ReadUnfocused = 0
endif " }}}
" Use this regular expression to highlight prompt {{{
if !exists('g:ConqueTerm_PromptRegex')
let g:ConqueTerm_PromptRegex = '^\w\+@[0-9A-Za-z_.-]\+:[0-9A-Za-z_./\~,:-]\+\$'
endif " }}}
" Choose which Python version to attempt to load first {{{
" Valid values are 2, 3 or 0 (no preference)
if !exists('g:ConqueTerm_PyVersion')
let g:ConqueTerm_PyVersion = 2
endif " }}}
" Path to python.exe. (Windows only) {{{
" By default, Conque will check C:\PythonNN\python.exe then will search system path
" If you have installed Python in an unusual location and it's not in your path, fill in the full path below
" E.g. 'C:\Program Files\Python\Python27\python.exe'
if !exists('g:ConqueTerm_PyExe')
let g:ConqueTerm_PyExe = ''
endif " }}}
" Automatically close buffer when program exits {{{
if !exists('g:ConqueTerm_CloseOnEnd')
let g:ConqueTerm_CloseOnEnd = 0
endif " }}}
" Send function key presses to terminal {{{
if !exists('g:ConqueTerm_SendFunctionKeys')
let g:ConqueTerm_SendFunctionKeys = 0
endif " }}}
" Session support {{{
if !exists('g:ConqueTerm_SessionSupport')
let g:ConqueTerm_SessionSupport = 0
endif " }}}
" hide Conque startup messages {{{
" messages should only appear the first 3 times you start Vim with a new version of Conque
" and include important Conque feature and option descriptions
" TODO - disabled and unused for now
if !exists('g:ConqueTerm_StartMessages')
let g:ConqueTerm_StartMessages = 1
endif " }}}
" Windows character code page {{{
" Leave at 0 to use current environment code page.
" Use 65001 for utf-8, although many console apps do not support it.
if !exists('g:ConqueTerm_CodePage')
let g:ConqueTerm_CodePage = 0
endif " }}}
" InsertCharPre support {{{
" Disable this feature by default, still in Beta
if !exists('g:ConqueTerm_InsertCharPre')
let g:ConqueTerm_InsertCharPre = 0
endif " }}}
" }}}
" **********************************************************************************************************
" **** Startup *********************************************************************************************
" **********************************************************************************************************
" Startup {{{
let g:ConqueTerm_Loaded = 1
let g:ConqueTerm_Idx = 0
let g:ConqueTerm_Version = 230
command! -nargs=+ -complete=shellcmd ConqueTerm call conque_term#open(<q-args>)
command! -nargs=+ -complete=shellcmd ConqueTermSplit call conque_term#open(<q-args>, ['belowright split'])
command! -nargs=+ -complete=shellcmd ConqueTermVSplit call conque_term#open(<q-args>, ['belowright vsplit'])
command! -nargs=+ -complete=shellcmd ConqueTermTab call conque_term#open(<q-args>, ['tabnew'])
" }}}
" **********************************************************************************************************
" **** Global Mappings & Autocommands **********************************************************************
" **********************************************************************************************************
" Startup {{{
if exists('g:ConqueTerm_SessionSupport') && g:ConqueTerm_SessionSupport == 1
autocmd SessionLoadPost * call conque_term#resume_session()
endif
if maparg(g:ConqueTerm_ExecFileKey, 'n') == ''
exe 'nnoremap <silent> ' . g:ConqueTerm_ExecFileKey . ' :call conque_term#exec_file()<CR>'
endif
" }}}
" vim:foldmethod=marker

434
vim/plugin/delimitMate.vim Normal file
View File

@@ -0,0 +1,434 @@
" File: plugin/delimitMate.vim
" Version: 2.6
" Modified: 2011-01-14
" Description: This plugin provides auto-completion for quotes, parens, etc.
" Maintainer: Israel Chauca F. <israelchauca@gmail.com>
" Manual: Read ":help delimitMate".
" ============================================================================
" Initialization: {{{
if exists("g:loaded_delimitMate") || &cp
" User doesn't want this plugin or compatible is set, let's get out!
finish
endif
let g:loaded_delimitMate = 1
if exists("s:loaded_delimitMate") && !exists("g:delimitMate_testing")
" Don't define the functions if they already exist: just do the work
" (unless we are testing):
call s:DelimitMateDo()
finish
endif
if v:version < 700
echoerr "delimitMate: this plugin requires vim >= 7!"
finish
endif
let s:loaded_delimitMate = 1
let delimitMate_version = "2.6"
function! s:option_init(name, default) "{{{
let b = exists("b:delimitMate_" . a:name)
let g = exists("g:delimitMate_" . a:name)
let prefix = "_l_delimitMate_"
if !b && !g
let sufix = a:default
elseif !b && g
exec "let sufix = g:delimitMate_" . a:name
else
exec "let sufix = b:delimitMate_" . a:name
endif
if exists("b:" . prefix . a:name)
exec "unlockvar! b:" . prefix . a:name
endif
exec "let b:" . prefix . a:name . " = " . string(sufix)
exec "lockvar! b:" . prefix . a:name
endfunction "}}}
function! s:init() "{{{
" Initialize variables:
" autoclose
call s:option_init("autoclose", 1)
" matchpairs
call s:option_init("matchpairs", string(&matchpairs)[1:-2])
call s:option_init("matchpairs_list", split(b:_l_delimitMate_matchpairs, ','))
call s:option_init("left_delims", split(b:_l_delimitMate_matchpairs, ':.,\='))
call s:option_init("right_delims", split(b:_l_delimitMate_matchpairs, ',\=.:'))
" quotes
call s:option_init("quotes", "\" ' `")
call s:option_init("quotes_list", split(b:_l_delimitMate_quotes))
" nesting_quotes
call s:option_init("nesting_quotes", [])
" excluded_regions
call s:option_init("excluded_regions", "Comment")
call s:option_init("excluded_regions_list", split(b:_l_delimitMate_excluded_regions, ',\s*'))
let enabled = len(b:_l_delimitMate_excluded_regions_list) > 0
call s:option_init("excluded_regions_enabled", enabled)
" excluded filetypes
call s:option_init("excluded_ft", "")
" expand_space
if exists("b:delimitMate_expand_space") && type(b:delimitMate_expand_space) == type("")
echom "b:delimitMate_expand_space is '".b:delimitMate_expand_space."' but it must be either 1 or 0!"
echom "Read :help 'delimitMate_expand_space' for more details."
unlet b:delimitMate_expand_space
let b:delimitMate_expand_space = 1
endif
if exists("g:delimitMate_expand_space") && type(g:delimitMate_expand_space) == type("")
echom "delimitMate_expand_space is '".g:delimitMate_expand_space."' but it must be either 1 or 0!"
echom "Read :help 'delimitMate_expand_space' for more details."
unlet g:delimitMate_expand_space
let g:delimitMate_expand_space = 1
endif
call s:option_init("expand_space", 0)
" expand_cr
if exists("b:delimitMate_expand_cr") && type(b:delimitMate_expand_cr) == type("")
echom "b:delimitMate_expand_cr is '".b:delimitMate_expand_cr."' but it must be either 1 or 0!"
echom "Read :help 'delimitMate_expand_cr' for more details."
unlet b:delimitMate_expand_cr
let b:delimitMate_expand_cr = 1
endif
if exists("g:delimitMate_expand_cr") && type(g:delimitMate_expand_cr) == type("")
echom "delimitMate_expand_cr is '".g:delimitMate_expand_cr."' but it must be either 1 or 0!"
echom "Read :help 'delimitMate_expand_cr' for more details."
unlet g:delimitMate_expand_cr
let g:delimitMate_expand_cr = 1
endif
if ((&backspace !~ 'eol' || &backspace !~ 'start') && &backspace != 2) &&
\ ((exists('b:delimitMate_expand_cr') && b:delimitMate_expand_cr == 1) ||
\ (exists('g:delimitMate_expand_cr') && g:delimitMate_expand_cr == 1))
echom "delimitMate: There seems to be some incompatibility with your settings that may interfer with the expansion of <CR>. See :help 'delimitMate_expand_cr' for details."
endif
call s:option_init("expand_cr", 0)
" smart_matchpairs
call s:option_init("smart_matchpairs", '^\%(\w\|\!\|£\|\$\|_\|["'']\s*\S\)')
" smart_quotes
call s:option_init("smart_quotes", 1)
" apostrophes
call s:option_init("apostrophes", "")
call s:option_init("apostrophes_list", split(b:_l_delimitMate_apostrophes, ":\s*"))
" tab2exit
call s:option_init("tab2exit", 1)
" balance_matchpairs
call s:option_init("balance_matchpairs", 0)
let b:_l_delimitMate_buffer = []
endfunction "}}} Init()
"}}}
" Functions: {{{
function! s:Map() "{{{
" Set mappings:
try
let save_cpo = &cpo
let save_keymap = &keymap
let save_iminsert = &iminsert
let save_imsearch = &imsearch
set keymap=
set cpo&vim
if b:_l_delimitMate_autoclose
call s:AutoClose()
else
call s:NoAutoClose()
endif
call s:ExtraMappings()
finally
let &cpo = save_cpo
let &keymap = save_keymap
let &iminsert = save_iminsert
let &imsearch = save_imsearch
endtry
let b:delimitMate_enabled = 1
endfunction "}}} Map()
function! s:Unmap() " {{{
let imaps =
\ b:_l_delimitMate_right_delims +
\ b:_l_delimitMate_left_delims +
\ b:_l_delimitMate_quotes_list +
\ b:_l_delimitMate_apostrophes_list +
\ ['<BS>', '<S-BS>', '<Del>', '<CR>', '<Space>', '<S-Tab>', '<Esc>'] +
\ ['<Up>', '<Down>', '<Left>', '<Right>', '<LeftMouse>', '<RightMouse>'] +
\ ['<Home>', '<End>', '<PageUp>', '<PageDown>', '<S-Down>', '<S-Up>', '<C-G>g']
for map in imaps
if maparg(map, "i") =~? 'delimitMate'
if map == '|'
let map = '<Bar>'
endif
exec 'silent! iunmap <buffer> ' . map
endif
endfor
if !has('gui_running')
silent! iunmap <C-[>OC
endif
let b:delimitMate_enabled = 0
endfunction " }}} s:Unmap()
function! s:TestMappingsDo() "{{{
%d
if !exists("g:delimitMate_testing")
silent call delimitMate#TestMappings()
else
let temp_varsDM = [b:_l_delimitMate_expand_space, b:_l_delimitMate_expand_cr, b:_l_delimitMate_autoclose]
for i in [0,1]
let b:delimitMate_expand_space = i
let b:delimitMate_expand_cr = i
for a in [0,1]
let b:delimitMate_autoclose = a
call s:init()
call s:Unmap()
call s:Map()
call delimitMate#TestMappings()
call append(line('$'),'')
endfor
endfor
let b:delimitMate_expand_space = temp_varsDM[0]
let b:delimitMate_expand_cr = temp_varsDM[1]
let b:delimitMate_autoclose = temp_varsDM[2]
unlet temp_varsDM
endif
normal gg
g/\%^$/d
endfunction "}}}
function! s:DelimitMateDo(...) "{{{
" First, remove all magic, if needed:
if exists("b:delimitMate_enabled") && b:delimitMate_enabled == 1
call s:Unmap()
endif
" Check if this file type is excluded:
if exists("g:delimitMate_excluded_ft") &&
\ index(split(g:delimitMate_excluded_ft, ','), &filetype, 0, 1) >= 0
" Finish here:
return 1
endif
" Check if user tried to disable using b:loaded_delimitMate
if exists("b:loaded_delimitMate")
return 1
endif
" Initialize settings:
call s:init()
" Now, add magic:
call s:Map()
if a:0 > 0
echo "delimitMate has been reset."
endif
endfunction "}}}
function! s:DelimitMateSwitch() "{{{
if exists("b:delimitMate_enabled") && b:delimitMate_enabled
call s:Unmap()
echo "delimitMate has been disabled."
else
call s:Unmap()
call s:init()
call s:Map()
echo "delimitMate has been enabled."
endif
endfunction "}}}
function! s:Finish() " {{{
if exists('g:delimitMate_loaded')
return delimitMate#Finish(1)
endif
return ''
endfunction " }}}
function! s:FlushBuffer() " {{{
if exists('g:delimitMate_loaded')
return delimitMate#FlushBuffer()
endif
return ''
endfunction " }}}
"}}}
" Mappers: {{{
function! s:NoAutoClose() "{{{
" inoremap <buffer> ) <C-R>=delimitMate#SkipDelim('\)')<CR>
for delim in b:_l_delimitMate_right_delims + b:_l_delimitMate_quotes_list
if delim == '|'
let delim = '<Bar>'
endif
exec 'inoremap <silent> <Plug>delimitMate' . delim . ' <C-R>=delimitMate#SkipDelim("' . escape(delim,'"') . '")<CR>'
exec 'silent! imap <unique> <buffer> '.delim.' <Plug>delimitMate'.delim
endfor
endfunction "}}}
function! s:AutoClose() "{{{
" Add matching pair and jump to the midle:
" inoremap <silent> <buffer> ( ()<Left>
let i = 0
while i < len(b:_l_delimitMate_matchpairs_list)
let ld = b:_l_delimitMate_left_delims[i] == '|' ? '<bar>' : b:_l_delimitMate_left_delims[i]
let rd = b:_l_delimitMate_right_delims[i] == '|' ? '<bar>' : b:_l_delimitMate_right_delims[i]
exec 'inoremap <silent> <Plug>delimitMate' . ld . ' ' . ld . '<C-R>=delimitMate#ParenDelim("' . escape(rd, '|') . '")<CR>'
exec 'silent! imap <unique> <buffer> '.ld.' <Plug>delimitMate'.ld
let i += 1
endwhile
" Exit from inside the matching pair:
for delim in b:_l_delimitMate_right_delims
exec 'inoremap <silent> <Plug>delimitMate' . delim . ' <C-R>=delimitMate#JumpOut("\' . delim . '")<CR>'
exec 'silent! imap <unique> <buffer> ' . delim . ' <Plug>delimitMate'. delim
endfor
" Add matching quote and jump to the midle, or exit if inside a pair of matching quotes:
" inoremap <silent> <buffer> " <C-R>=delimitMate#QuoteDelim("\"")<CR>
for delim in b:_l_delimitMate_quotes_list
if delim == '|'
let delim = '<Bar>'
endif
exec 'inoremap <silent> <Plug>delimitMate' . delim . ' <C-R>=delimitMate#QuoteDelim("\' . delim . '")<CR>'
exec 'silent! imap <unique> <buffer> ' . delim . ' <Plug>delimitMate' . delim
endfor
" Try to fix the use of apostrophes (kept for backward compatibility):
" inoremap <silent> <buffer> n't n't
for map in b:_l_delimitMate_apostrophes_list
exec "inoremap <silent> " . map . " " . map
exec 'silent! imap <unique> <buffer> ' . map . ' <Plug>delimitMate' . map
endfor
endfunction "}}}
function! s:ExtraMappings() "{{{
" If pair is empty, delete both delimiters:
inoremap <silent> <Plug>delimitMateBS <C-R>=delimitMate#BS()<CR>
if !hasmapto('<Plug>delimitMateBS','i')
silent! imap <unique> <buffer> <BS> <Plug>delimitMateBS
endif
" If pair is empty, delete closing delimiter:
inoremap <silent> <expr> <Plug>delimitMateS-BS delimitMate#WithinEmptyPair() ? "\<C-R>=delimitMate#Del()\<CR>" : "\<S-BS>"
if !hasmapto('<Plug>delimitMateS-BS','i')
silent! imap <unique> <buffer> <S-BS> <Plug>delimitMateS-BS
endif
" Expand return if inside an empty pair:
inoremap <silent> <Plug>delimitMateCR <C-R>=delimitMate#ExpandReturn()<CR>
if b:_l_delimitMate_expand_cr != 0 && !hasmapto('<Plug>delimitMateCR', 'i')
silent! imap <unique> <buffer> <CR> <Plug>delimitMateCR
endif
" Expand space if inside an empty pair:
inoremap <silent> <Plug>delimitMateSpace <C-R>=delimitMate#ExpandSpace()<CR>
if b:_l_delimitMate_expand_space != 0 && !hasmapto('<Plug>delimitMateSpace', 'i')
silent! imap <unique> <buffer> <Space> <Plug>delimitMateSpace
endif
" Jump over any delimiter:
inoremap <silent> <Plug>delimitMateS-Tab <C-R>=delimitMate#JumpAny("\<S-Tab>")<CR>
if b:_l_delimitMate_tab2exit && !hasmapto('<Plug>delimitMateS-Tab', 'i')
silent! imap <unique> <buffer> <S-Tab> <Plug>delimitMateS-Tab
endif
" Change char buffer on Del:
inoremap <silent> <Plug>delimitMateDel <C-R>=delimitMate#Del()<CR>
if !hasmapto('<Plug>delimitMateDel', 'i')
silent! imap <unique> <buffer> <Del> <Plug>delimitMateDel
endif
" Flush the char buffer on movement keystrokes or when leaving insert mode:
for map in ['Esc', 'Left', 'Right', 'Home', 'End']
exec 'inoremap <silent> <Plug>delimitMate'.map.' <C-R>=<SID>Finish()<CR><'.map.'>'
if !hasmapto('<Plug>delimitMate'.map, 'i')
exec 'silent! imap <unique> <buffer> <'.map.'> <Plug>delimitMate'.map
endif
endfor
" Except when pop-up menu is active:
for map in ['Up', 'Down', 'PageUp', 'PageDown', 'S-Down', 'S-Up']
exec 'inoremap <silent> <expr> <Plug>delimitMate'.map.' pumvisible() ? "\<'.map.'>" : "\<C-R>=\<SID>Finish()\<CR>\<'.map.'>"'
if !hasmapto('<Plug>delimitMate'.map, 'i')
exec 'silent! imap <unique> <buffer> <'.map.'> <Plug>delimitMate'.map
endif
endfor
" Avoid ambiguous mappings:
for map in ['LeftMouse', 'RightMouse']
exec 'inoremap <silent> <Plug>delimitMateM'.map.' <C-R>=delimitMate#Finish(1)<CR><'.map.'>'
if !hasmapto('<Plug>delimitMate'.map, 'i')
exec 'silent! imap <unique> <buffer> <'.map.'> <Plug>delimitMateM'.map
endif
endfor
" Jump over next delimiters
inoremap <buffer> <Plug>delimitMateJumpMany <C-R>=len(b:_l_delimitMate_buffer) ? delimitMate#Finish(0) : delimitMate#JumpMany()<CR>
if !hasmapto('<Plug>delimitMateJumpMany')
imap <silent> <buffer> <C-G>g <Plug>delimitMateJumpMany
endif
" The following simply creates an ambiguous mapping so vim fully processes
" the escape sequence for terminal keys, see 'ttimeout' for a rough
" explanation, this just forces it to work
if !has('gui_running')
imap <silent> <C-[>OC <RIGHT>
endif
endfunction "}}}
"}}}
" Commands: {{{
call s:DelimitMateDo()
" Let me refresh without re-loading the buffer:
command! -bar DelimitMateReload call s:DelimitMateDo(1)
" Quick test:
command! -bar DelimitMateTest silent call s:TestMappingsDo()
" Switch On/Off:
command! -bar DelimitMateSwitch call s:DelimitMateSwitch()
"}}}
" Autocommands: {{{
augroup delimitMate
au!
" Run on file type change.
"autocmd VimEnter * autocmd FileType * call <SID>DelimitMateDo()
autocmd FileType * call <SID>DelimitMateDo()
" Run on new buffers.
autocmd BufNewFile,BufRead,BufEnter *
\ if !exists('b:delimitMate_was_here') |
\ call <SID>DelimitMateDo() |
\ let b:delimitMate_was_here = 1 |
\ endif
" Flush the char buffer:
autocmd InsertEnter * call <SID>FlushBuffer()
autocmd BufEnter *
\ if mode() == 'i' |
\ call <SID>FlushBuffer() |
\ endif
augroup END
"}}}
" GetLatestVimScripts: 2754 1 :AutoInstall: delimitMate.vim
" vim:foldmethod=marker:foldcolumn=4

132
vim/plugin/endwise.vim Normal file
View File

@@ -0,0 +1,132 @@
" endwise.vim - EndWise
" Author: Tim Pope <vimNOSPAM@tpope.info>
" Version: 1.0
" Distributable under the same terms as Vim itself (see :help license)
" Exit quickly when:
" - this plugin was already loaded (or disabled)
" - when 'compatible' is set
if (exists("g:loaded_endwise") && g:loaded_endwise) || &cp
finish
endif
let g:loaded_endwise = 1
let s:cpo_save = &cpo
set cpo&vim
augroup endwise " {{{1
au!
autocmd FileType ruby
\ let b:endwise_addition = '\=submatch(0)=="{" ? "}" : "end"' |
\ let b:endwise_words = 'module,class,def,if,unless,case,while,until,begin,do' |
\ let b:endwise_pattern = '^\s*\zs\%(module\|class\|def\|if\|unless\|case\|while\|until\|for\|\|begin\)\>\%(.*[^.:@$]\<end\>\)\@!\|\<do\ze\%(\s*|.*|\)\=\s*$' |
\ let b:endwise_syngroups = 'rubyModule,rubyClass,rubyDefine,rubyControl,rubyConditional,rubyRepeat'
autocmd FileType vb,vbnet,aspvbs
\ let b:endwise_addition = 'End &' |
\ let b:endwise_words = 'Function,Sub,Class,Module,Enum,Namespace' |
\ let b:endwise_pattern = '\%(\<End\>.*\)\@<!\<&\>' |
\ let b:endwise_syngroups = 'vbStatement,vbnetStorage,vbnetProcedure,vbnet.*Words,AspVBSStatement'
autocmd FileType vim
\ let b:endwise_addition = 'end&' |
\ let b:endwise_words = 'fu\%[nction],wh\%[ile],if,for,try' |
\ let b:endwise_syngroups = 'vimFuncKey,vimNotFunc,vimCommand'
augroup END " }}}1
" Maps {{{1
if maparg("<Plug>DiscretionaryEnd") == ""
inoremap <silent> <SID>DiscretionaryEnd <C-R>=<SID>crend(0)<CR>
inoremap <silent> <SID>AlwaysEnd <C-R>=<SID>crend(1)<CR>
imap <script> <Plug>DiscretionaryEnd <SID>DiscretionaryEnd
imap <script> <Plug>AlwaysEnd <SID>AlwaysEnd
endif
if maparg('<CR>','i') =~# '<C-R>=.*crend(.)<CR>\|<\%(Plug\|SID\)>.*End'
" Already mapped
elseif maparg('<CR>','i') =~ '<CR>'
exe "imap <script> <C-X><CR> ".maparg('<CR>','i')."<SID>AlwaysEnd"
exe "imap <script> <CR> ".maparg('<CR>','i')."<SID>DiscretionaryEnd"
else
imap <C-X><CR> <CR><Plug>AlwaysEnd
imap <CR> <CR><Plug>DiscretionaryEnd
endif
if maparg('<M-o>','i') == ''
inoremap <M-o> <C-O>o
endif
" }}}1
" Code {{{1
function! s:mysearchpair(beginpat,endpat,synpat)
let g:endwise_syntaxes = ""
let s:lastline = line('.')
call s:synname()
let line = searchpair(a:beginpat,'',a:endpat,'Wn','<SID>synname() !~# "^'.substitute(a:synpat,'\\','\\\\','g').'$"',line('.')+50)
return line
endfunction
function! s:crend(always)
let n = ""
if !exists("b:endwise_addition") || !exists("b:endwise_words") || !exists("b:endwise_syngroups")
return n
end
let synpat = '\%('.substitute(b:endwise_syngroups,',','\\|','g').'\)'
let wordchoice = '\%('.substitute(b:endwise_words,',','\\|','g').'\)'
if exists("b:endwise_pattern")
let beginpat = substitute(b:endwise_pattern,'&',substitute(wordchoice,'\\','\\&','g'),'g')
else
let beginpat = '\<'.wordchoice.'\>'
endif
let lnum = line('.') - 1
let space = matchstr(getline(lnum),'^\s*')
let col = match(getline(lnum),beginpat) + 1
let word = matchstr(getline(lnum),beginpat)
let endpat = substitute(word,'.*',b:endwise_addition,'')
let y = n.endpat."\<C-O>O"
let endpat = '\<'.substitute(wordchoice,'.*',b:endwise_addition,'').'\>'
if a:always
return y
elseif col <= 0 || synIDattr(synID(lnum,col,1),'name') !~ '^'.synpat.'$'
return n
elseif getline('.') !~ '^\s*#\=$'
return n
endif
let line = s:mysearchpair(beginpat,endpat,synpat)
" even is false if no end was found, or if the end found was less
" indented than the current line
let even = strlen(matchstr(getline(line),'^\s*')) >= strlen(space)
if line == 0
let even = 0
endif
let g:endwise_debug = line . "(" . even . ")"
if !even && line == line('.') + 1
return y
endif
if even
return n
endif
return y
endfunction
function! s:synname()
" Checking this helps to force things to stay in sync
while s:lastline < line('.')
let s = synIDattr(synID(s:lastline,indent(s:lastline)+1,1),'name')
let s:lastline = nextnonblank(s:lastline + 1)
endwhile
let s = synIDattr(synID(line('.'),col('.'),1),'name')
let g:endwise_syntaxes = g:endwise_syntaxes . line('.').','.col('.')."=".s."\n"
let s:lastline = line('.')
return s
endfunction
" }}}1
let &cpo = s:cpo_save
" vim:set ft=vim ff=unix ts=8 sw=4 sts=4:

42
vim/plugin/git-grep.vim Normal file
View File

@@ -0,0 +1,42 @@
let g:gitgrepprg="git\\ grep\\ -n"
function! GitGrep(args)
let grepprg_bak=&grepprg
exec "set grepprg=" . g:gitgrepprg
execute "silent! grep " . a:args
botright copen
let &grepprg=grepprg_bak
exec "redraw!"
endfunction
function! GitGrepAdd(args)
let grepprg_bak=&grepprg
exec "set grepprg=" . g:gitgrepprg
execute "silent! grepadd " . a:args
botright copen
let &grepprg=grepprg_bak
exec "redraw!"
endfunction
function! LGitGrep(args)
let grepprg_bak=&grepprg
exec "set grepprg=" . g:gitgrepprg
execute "silent! lgrep " . a:args
botright lopen
let &grepprg=grepprg_bak
exec "redraw!"
endfunction
function! LGitGrepAdd(args)
let grepprg_bak=&grepprg
exec "set grepprg=" . g:gitgrepprg
execute "silent! lgrepadd " . a:args
botright lopen
let &grepprg=grepprg_bak
exec "redraw!"
endfunction
command! -nargs=* -complete=file GitGrep call GitGrep(<q-args>)
command! -nargs=* -complete=file GitGrepAdd call GitGrepAdd(<q-args>)
command! -nargs=* -complete=file LGitGrep call LGitGrep(<q-args>)
command! -nargs=* -complete=file LGitGrepAdd call LGitGrepAdd(<q-args>)

310
vim/plugin/greplace.vim Executable file
View File

@@ -0,0 +1,310 @@
" File: greplace.vim
" Script to search and replace pattern across multiple files
" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
" Version: 1.0 Beta1
" Last Modified: March 3, 2007
"
if exists("loaded_greplace")
finish
endif
let loaded_greplace = 1
" Requires Vim 7.0 and above
if v:version < 700
finish
endif
" Line continuation used here
let s:cpo_save = &cpo
set cpo&vim
if &isfname =~ '['
let s:gRepl_bufname = '[Global\ Replace]'
else
let s:gRepl_bufname = '\[Global\ Replace\]'
endif
" Character to use to quote patterns
if !exists("Greplace_Shell_Quote_Char")
if has("win32") || has("win16") || has("win95")
let Greplace_Shell_Quote_Char = ''
else
let Greplace_Shell_Quote_Char = "'"
endif
endif
let s:save_qf_list = {}
function! s:warn_msg(msg)
echohl WarningMsg
echomsg a:msg
echohl None
endfunction
highlight GReplaceText term=reverse cterm=reverse gui=reverse
function! s:gReplace()
if empty(s:save_qf_list)
return
endif
let change_all = v:cmdbang
let changeset = {}
" Parse the replace buffer contents and get a List of changed lines
let lines = getbufline('%', 1, '$')
for l in lines
if l !~ '[^:]\+:\d\+:.*'
continue
endif
let match_l = matchlist(l, '\([^:]\+\):\(\d\+\):\(.*\)')
let fname = match_l[1]
let lnum = match_l[2]
let text = match_l[3]
let key = fname . ':' . lnum
if s:save_qf_list[key].text == text
" This line is not changed
continue
endif
let fname = s:save_qf_list[key].fname
if !has_key(changeset, fname)
let changeset[fname] = {}
endif
let changeset[fname][lnum] = text
endfor
if empty(changeset)
" The replace buffer is not changed by the user
call s:warn_msg('Error: No changes in the replace buffer')
return
endif
" Make the changes made by the user to the buffers
for f in keys(changeset)
let f_l = changeset[f]
if !filereadable(f)
continue
endif
silent! exe 'hide edit ' . f
let change_buf_all = 0 " Accept all the changes in this buffer
for lnum in keys(f_l)
exe lnum
let cur_ltext = getline(lnum)
let new_ltext = f_l[lnum]
let s_idx =0
while cur_ltext[s_idx] == new_ltext[s_idx]
let s_idx += 1
endwhile
let e_idx1 = strlen(cur_ltext) - 1
let e_idx2 = strlen(new_ltext) - 1
while e_idx1 >= 0 && cur_ltext[e_idx1] == new_ltext[e_idx2]
let e_idx1 -= 1
let e_idx2 -= 1
endwhile
let e_idx1 += 2
if (s_idx + 1) == e_idx1
" If there is nothing to highlight, then highlight the
" last character
let e_idx1 += 1
endif
let hl_pat = '/\%'.lnum.'l\%>'.s_idx.'v.*\%<'.e_idx1.'v/'
exe '2match GReplaceText ' . hl_pat
redraw!
try
let change_line = 0
if !change_all && !change_buf_all
let new_text_frag = strpart(new_ltext, s_idx,
\ e_idx2 - s_idx + 1)
echo "Replace with '" . new_text_frag . "' (y/n/a/b/q)?"
let ans = 'x'
while ans !~? '[ynab]'
let ans = nr2char(getchar())
if ans == 'q' || ans == "\<Esc>" " Quit
return
endif
endwhile
if ans == 'a' " Accept all
let change_all = 1
endif
if ans == 'b' " Accept changes in the current buffer
let change_buf_all = 1
endif
if ans == 'y' " Yes
let change_line = 1
endif
endif
if change_all || change_buf_all || change_line
call setline(lnum, f_l[lnum])
endif
finally
2match none
endtry
endfor
endfor
endfunction
function! s:gReplace_show_matches()
let qf = getqflist()
if empty(qf)
call s:warn_msg('Error: Quickfix list is empty')
return
endif
let new_qf = {}
" Populate the buffer with the current quickfix list
let lines = []
for l in qf
if l.valid && l.lnum > 0 && l.bufnr > 0
let fname = fnamemodify(bufname(l.bufnr), ':.')
let buf_text = fname . ':' . l.lnum . ':' . l.text
let k = fname . ':' . l.lnum
let new_qf[k] = {}
let new_qf[k].fname = fnamemodify(bufname(l.bufnr), ':p')
let new_qf[k].text = l.text
else
let buf_text = l.text
endif
call add(lines, buf_text)
endfor
if empty(lines)
" No valid matching lines
return
endif
let w = bufwinnr(s:gRepl_bufname)
if w == -1
" Create a new window
silent! exe 'new ' . s:gRepl_bufname
else
exe w . 'wincmd w'
" Discard the contents of the buffer
%d _
endif
call append(0, '#')
call append(1, '# Modify the contents of this buffer and then')
call append(2, '# use the ":Greplace" command to merge the changes.')
call append(3, '#')
call append(4, lines)
call cursor(5, 1)
setlocal buftype=nofile
setlocal bufhidden=wipe
setlocal nomodified
command! -buffer -nargs=0 -bang Greplace call s:gReplace()
let s:save_qf_list = new_qf
endfunction
" gSearch
" Search for a pattern in a group of files using ':grep'
function! s:gSearch(type, ...)
let grep_opt = '-r'
let pattern = ''
let filenames = ''
" Parse the arguments
" grep command-line flags are specified using the "-flag" format
" the next argument is assumed to be the pattern
" and the next arguments are assumed to be filenames or file patterns
let argcnt = 1
while argcnt <= a:0
if &grepprg =~ 'findstr' && a:{argcnt} =~ '^/'
let grep_opt = grep_opt . ' ' . a:{argcnt}
elseif a:{argcnt} =~ '^-'
let grep_opt = grep_opt . ' ' . a:{argcnt}
elseif pattern == ''
let pattern = a:{argcnt}
else
let filenames = filenames . ' ' . a:{argcnt}
endif
let argcnt += 1
endwhile
" If search pattern is not specified on command-line, ask for it
if pattern == ''
let pattern = input('Search pattern: ', expand('<cword>'))
if pattern == ''
return
endif
" Quote the supplied pattern
let pattern = g:Greplace_Shell_Quote_Char . pattern .
\ g:Greplace_Shell_Quote_Char
endif
if a:type == 'grep'
if filenames == ''
let filenames = input('Search in files: ', '*', 'file')
endif
elseif a:type == 'args'
" Search in all the filenames in the argument list
let arg_cnt = argc()
if arg_cnt == 0
call s:warn_msg('Error: Argument list is empty')
return
endif
let filenames = ''
for i in range(0, arg_cnt - 1)
let filenames .= ' ' . argv(i)
endfor
else
" Get a list of all the buffer names
let filenames = ''
for i in range(1, bufnr('$'))
let bname = bufname(i)
if bufexists(i) && buflisted(i) && filereadable(bname) &&
\ getbufvar(i, '&buftype') == ''
let filenames .= ' ' . bufname(i)
endif
endfor
endif
if filenames == ''
call s:warn_msg('Error: No valid file names')
return
endif
" Use ! after grep, so that Vim doesn't automatically jump to the
" first match
let grep_cmd = 'grep! ' . grep_opt . ' ' . pattern . ' ' . filenames
" Run the grep and get the matches
silent! exe grep_cmd
call s:gReplace_show_matches()
endfunction
command! -nargs=0 Gqfopen call s:gReplace_show_matches()
command! -nargs=* -complete=file Gsearch call s:gSearch('grep', <f-args>)
command! -nargs=* Gargsearch call s:gSearch('args', <f-args>)
command! -nargs=* Gbuffersearch call s:gSearch('buffer', <f-args>)
" restore 'cpo'
let &cpo = s:cpo_save
unlet s:cpo_save

2377
vim/plugin/lusty-explorer.vim Executable file

File diff suppressed because it is too large Load Diff

1143
vim/plugin/lusty-juggler.vim Normal file

File diff suppressed because it is too large Load Diff

44
vim/plugin/markdown-preview.css Executable file
View File

@@ -0,0 +1,44 @@
body div#content {
margin : 0 auto;
width : 920px;
background-color : #f8f8f8;
padding : .7em;
font-size : 13.34px;
font-family : verdana, sans-serif;
border : 1px #E0E0E0 solid;
}
body div#content h2, body div#content h3, body div#content h4 {
padding-top : 10px;
border-top : 4px solid #E0E0E0;
}
body div#content pre {
padding : 5px;
border-style : solid;
border-width : 1px;
border-color : #E0E0E0;
background-color : #F8F8FF;
}
body div#content pre code {
padding : 5px;
background-color : #F8F8FF;
border : none;
}
body div#content code {
font-family : courier, fixed;
display : inline-block;
padding : 0px 2px 0px 2px;
background-color : #F8F8FF;
border : 1px #E0E0E0 solid;
}
body h4#title {
font-family : verdana, sans-serif;
display : block;
margin : 0 auto;
width : 920px;
}

812
vim/plugin/matchit.vim Executable file
View File

@@ -0,0 +1,812 @@
" matchit.vim: (global plugin) Extended "%" matching
" Last Change: Fri Jan 25 10:00 AM 2008 EST
" Maintainer: Benji Fisher PhD <benji@member.AMS.org>
" Version: 1.13.2, for Vim 6.3+
" URL: http://www.vim.org/script.php?script_id=39
" Documentation:
" The documentation is in a separate file, matchit.txt .
" Credits:
" Vim editor by Bram Moolenaar (Thanks, Bram!)
" Original script and design by Raul Segura Acevedo
" Support for comments by Douglas Potts
" Support for back references and other improvements by Benji Fisher
" Support for many languages by Johannes Zellner
" Suggestions for improvement, bug reports, and support for additional
" languages by Jordi-Albert Batalla, Neil Bird, Servatius Brandt, Mark
" Collett, Stephen Wall, Dany St-Amant, Yuheng Xie, and Johannes Zellner.
" Debugging:
" If you'd like to try the built-in debugging commands...
" :MatchDebug to activate debugging for the current buffer
" This saves the values of several key script variables as buffer-local
" variables. See the MatchDebug() function, below, for details.
" TODO: I should think about multi-line patterns for b:match_words.
" This would require an option: how many lines to scan (default 1).
" This would be useful for Python, maybe also for *ML.
" TODO: Maybe I should add a menu so that people will actually use some of
" the features that I have implemented.
" TODO: Eliminate the MultiMatch function. Add yet another argument to
" Match_wrapper() instead.
" TODO: Allow :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
" TODO: Make backrefs safer by using '\V' (very no-magic).
" TODO: Add a level of indirection, so that custom % scripts can use my
" work but extend it.
" allow user to prevent loading
" and prevent duplicate loading
if exists("loaded_matchit") || &cp
finish
endif
let loaded_matchit = 1
let s:last_mps = ""
let s:last_words = ":"
let s:save_cpo = &cpo
set cpo&vim
nnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'n') <CR>
nnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'n') <CR>
vnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'v') <CR>m'gv``
vnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'v') <CR>m'gv``
onoremap <silent> % v:<C-U>call <SID>Match_wrapper('',1,'o') <CR>
onoremap <silent> g% v:<C-U>call <SID>Match_wrapper('',0,'o') <CR>
" Analogues of [{ and ]} using matching patterns:
nnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "n") <CR>
nnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "n") <CR>
vmap [% <Esc>[%m'gv``
vmap ]% <Esc>]%m'gv``
" vnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "v") <CR>m'gv``
" vnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "v") <CR>m'gv``
onoremap <silent> [% v:<C-U>call <SID>MultiMatch("bW", "o") <CR>
onoremap <silent> ]% v:<C-U>call <SID>MultiMatch("W", "o") <CR>
" text object:
vmap a% <Esc>[%v]%
" Auto-complete mappings: (not yet "ready for prime time")
" TODO Read :help write-plugin for the "right" way to let the user
" specify a key binding.
" let g:match_auto = '<C-]>'
" let g:match_autoCR = '<C-CR>'
" if exists("g:match_auto")
" execute "inoremap " . g:match_auto . ' x<Esc>"=<SID>Autocomplete()<CR>Pls'
" endif
" if exists("g:match_autoCR")
" execute "inoremap " . g:match_autoCR . ' <CR><C-R>=<SID>Autocomplete()<CR>'
" endif
" if exists("g:match_gthhoh")
" execute "inoremap " . g:match_gthhoh . ' <C-O>:call <SID>Gthhoh()<CR>'
" endif " gthhoh = "Get the heck out of here!"
let s:notslash = '\\\@<!\%(\\\\\)*'
function! s:Match_wrapper(word, forward, mode) range
" In s:CleanUp(), :execute "set" restore_options .
let restore_options = (&ic ? " " : " no") . "ignorecase"
if exists("b:match_ignorecase")
let &ignorecase = b:match_ignorecase
endif
let restore_options = " ve=" . &ve . restore_options
set ve=
" If this function was called from Visual mode, make sure that the cursor
" is at the correct end of the Visual range:
if a:mode == "v"
execute "normal! gv\<Esc>"
endif
" In s:CleanUp(), we may need to check whether the cursor moved forward.
let startline = line(".")
let startcol = col(".")
" Use default behavior if called with a count.
if v:count
exe "normal! " . v:count . "%"
return s:CleanUp(restore_options, a:mode, startline, startcol)
end
" First step: if not already done, set the script variables
" s:do_BR flag for whether there are backrefs
" s:pat parsed version of b:match_words
" s:all regexp based on s:pat and the default groups
"
if !exists("b:match_words") || b:match_words == ""
let match_words = ""
" Allow b:match_words = "GetVimMatchWords()" .
elseif b:match_words =~ ":"
let match_words = b:match_words
else
execute "let match_words =" b:match_words
endif
" Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion!
if (match_words != s:last_words) || (&mps != s:last_mps) ||
\ exists("b:match_debug")
let s:last_words = match_words
let s:last_mps = &mps
" The next several lines were here before
" BF started messing with this script.
" quote the special chars in 'matchpairs', replace [,:] with \| and then
" append the builtin pairs (/*, */, #if, #ifdef, #else, #elif, #endif)
" let default = substitute(escape(&mps, '[$^.*~\\/?]'), '[,:]\+',
" \ '\\|', 'g').'\|\/\*\|\*\/\|#if\>\|#ifdef\>\|#else\>\|#elif\>\|#endif\>'
let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
\ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
" s:all = pattern with all the keywords
let match_words = match_words . (strlen(match_words) ? "," : "") . default
if match_words !~ s:notslash . '\\\d'
let s:do_BR = 0
let s:pat = match_words
else
let s:do_BR = 1
let s:pat = s:ParseWords(match_words)
endif
let s:all = substitute(s:pat, s:notslash . '\zs[,:]\+', '\\|', 'g')
let s:all = '\%(' . s:all . '\)'
" let s:all = '\%(' . substitute(s:all, '\\\ze[,:]', '', 'g') . '\)'
if exists("b:match_debug")
let b:match_pat = s:pat
endif
endif
" Second step: set the following local variables:
" matchline = line on which the cursor started
" curcol = number of characters before match
" prefix = regexp for start of line to start of match
" suffix = regexp for end of match to end of line
" Require match to end on or after the cursor and prefer it to
" start on or before the cursor.
let matchline = getline(startline)
if a:word != ''
" word given
if a:word !~ s:all
echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE
return s:CleanUp(restore_options, a:mode, startline, startcol)
endif
let matchline = a:word
let curcol = 0
let prefix = '^\%('
let suffix = '\)$'
" Now the case when "word" is not given
else " Find the match that ends on or after the cursor and set curcol.
let regexp = s:Wholematch(matchline, s:all, startcol-1)
let curcol = match(matchline, regexp)
" If there is no match, give up.
if curcol == -1
return s:CleanUp(restore_options, a:mode, startline, startcol)
endif
let endcol = matchend(matchline, regexp)
let suf = strlen(matchline) - endcol
let prefix = (curcol ? '^.*\%' . (curcol + 1) . 'c\%(' : '^\%(')
let suffix = (suf ? '\)\%' . (endcol + 1) . 'c.*$' : '\)$')
endif
if exists("b:match_debug")
let b:match_match = matchstr(matchline, regexp)
let b:match_col = curcol+1
endif
" Third step: Find the group and single word that match, and the original
" (backref) versions of these. Then, resolve the backrefs.
" Set the following local variable:
" group = colon-separated list of patterns, one of which matches
" = ini:mid:fin or ini:fin
"
" Reconstruct the version with unresolved backrefs.
let patBR = substitute(match_words.',',
\ s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
let patBR = substitute(patBR, s:notslash.'\zs:\{2,}', ':', 'g')
" Now, set group and groupBR to the matching group: 'if:endif' or
" 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns
" group . "," . groupBR, and we pick it apart.
let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
let i = matchend(group, s:notslash . ",")
let groupBR = strpart(group, i)
let group = strpart(group, 0, i-1)
" Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
if s:do_BR " Do the hard part: resolve those backrefs!
let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
endif
if exists("b:match_debug")
let b:match_wholeBR = groupBR
let i = matchend(groupBR, s:notslash . ":")
let b:match_iniBR = strpart(groupBR, 0, i-1)
endif
" Fourth step: Set the arguments for searchpair().
let i = matchend(group, s:notslash . ":")
let j = matchend(group, '.*' . s:notslash . ":")
let ini = strpart(group, 0, i-1)
let mid = substitute(strpart(group, i,j-i-1), s:notslash.'\zs:', '\\|', 'g')
let fin = strpart(group, j)
"Un-escape the remaining , and : characters.
let ini = substitute(ini, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
let mid = substitute(mid, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
let fin = substitute(fin, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
" searchpair() requires that these patterns avoid \(\) groups.
let ini = substitute(ini, s:notslash . '\zs\\(', '\\%(', 'g')
let mid = substitute(mid, s:notslash . '\zs\\(', '\\%(', 'g')
let fin = substitute(fin, s:notslash . '\zs\\(', '\\%(', 'g')
" Set mid. This is optimized for readability, not micro-efficiency!
if a:forward && matchline =~ prefix . fin . suffix
\ || !a:forward && matchline =~ prefix . ini . suffix
let mid = ""
endif
" Set flag. This is optimized for readability, not micro-efficiency!
if a:forward && matchline =~ prefix . fin . suffix
\ || !a:forward && matchline !~ prefix . ini . suffix
let flag = "bW"
else
let flag = "W"
endif
" Set skip.
if exists("b:match_skip")
let skip = b:match_skip
elseif exists("b:match_comment") " backwards compatibility and testing!
let skip = "r:" . b:match_comment
else
let skip = 's:comment\|string'
endif
let skip = s:ParseSkip(skip)
if exists("b:match_debug")
let b:match_ini = ini
let b:match_tail = (strlen(mid) ? mid.'\|' : '') . fin
endif
" Fifth step: actually start moving the cursor and call searchpair().
" Later, :execute restore_cursor to get to the original screen.
let restore_cursor = virtcol(".") . "|"
normal! g0
let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
normal! H
let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
execute restore_cursor
call cursor(0, curcol + 1)
" normal! 0
" if curcol
" execute "normal!" . curcol . "l"
" endif
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
let skip = "0"
else
execute "if " . skip . "| let skip = '0' | endif"
endif
let sp_return = searchpair(ini, mid, fin, flag, skip)
let final_position = "call cursor(" . line(".") . "," . col(".") . ")"
" Restore cursor position and original screen.
execute restore_cursor
normal! m'
if sp_return > 0
execute final_position
endif
return s:CleanUp(restore_options, a:mode, startline, startcol, mid.'\|'.fin)
endfun
" Restore options and do some special handling for Operator-pending mode.
" The optional argument is the tail of the matching group.
fun! s:CleanUp(options, mode, startline, startcol, ...)
execute "set" a:options
" Open folds, if appropriate.
if a:mode != "o"
if &foldopen =~ "percent"
normal! zv
endif
" In Operator-pending mode, we want to include the whole match
" (for example, d%).
" This is only a problem if we end up moving in the forward direction.
elseif (a:startline < line(".")) ||
\ (a:startline == line(".") && a:startcol < col("."))
if a:0
" Check whether the match is a single character. If not, move to the
" end of the match.
let matchline = getline(".")
let currcol = col(".")
let regexp = s:Wholematch(matchline, a:1, currcol-1)
let endcol = matchend(matchline, regexp)
if endcol > currcol " This is NOT off by one!
execute "normal!" . (endcol - currcol) . "l"
endif
endif " a:0
endif " a:mode != "o" && etc.
return 0
endfun
" Example (simplified HTML patterns): if
" a:groupBR = '<\(\k\+\)>:</\1>'
" a:prefix = '^.\{3}\('
" a:group = '<\(\k\+\)>:</\(\k\+\)>'
" a:suffix = '\).\{2}$'
" a:matchline = "123<tag>12" or "123</tag>12"
" then extract "tag" from a:matchline and return "<tag>:</tag>" .
fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline)
if a:matchline !~ a:prefix .
\ substitute(a:group, s:notslash . '\zs:', '\\|', 'g') . a:suffix
return a:group
endif
let i = matchend(a:groupBR, s:notslash . ':')
let ini = strpart(a:groupBR, 0, i-1)
let tailBR = strpart(a:groupBR, i)
let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix,
\ a:groupBR)
let i = matchend(word, s:notslash . ":")
let wordBR = strpart(word, i)
let word = strpart(word, 0, i-1)
" Now, a:matchline =~ a:prefix . word . a:suffix
if wordBR != ini
let table = s:Resolve(ini, wordBR, "table")
else
" let table = "----------"
let table = ""
let d = 0
while d < 10
if tailBR =~ s:notslash . '\\' . d
" let table[d] = d
let table = table . d
else
let table = table . "-"
endif
let d = d + 1
endwhile
endif
let d = 9
while d
if table[d] != "-"
let backref = substitute(a:matchline, a:prefix.word.a:suffix,
\ '\'.table[d], "")
" Are there any other characters that should be escaped?
let backref = escape(backref, '*,:')
execute s:Ref(ini, d, "start", "len")
let ini = strpart(ini, 0, start) . backref . strpart(ini, start+len)
let tailBR = substitute(tailBR, s:notslash . '\zs\\' . d,
\ escape(backref, '\\'), 'g')
endif
let d = d-1
endwhile
if exists("b:match_debug")
if s:do_BR
let b:match_table = table
let b:match_word = word
else
let b:match_table = ""
let b:match_word = ""
endif
endif
return ini . ":" . tailBR
endfun
" Input a comma-separated list of groups with backrefs, such as
" a:groups = '\(foo\):end\1,\(bar\):end\1'
" and return a comma-separated list of groups with backrefs replaced:
" return '\(foo\):end\(foo\),\(bar\):end\(bar\)'
fun! s:ParseWords(groups)
let groups = substitute(a:groups.",", s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
let groups = substitute(groups, s:notslash . '\zs:\{2,}', ':', 'g')
let parsed = ""
while groups =~ '[^,:]'
let i = matchend(groups, s:notslash . ':')
let j = matchend(groups, s:notslash . ',')
let ini = strpart(groups, 0, i-1)
let tail = strpart(groups, i, j-i-1) . ":"
let groups = strpart(groups, j)
let parsed = parsed . ini
let i = matchend(tail, s:notslash . ':')
while i != -1
" In 'if:else:endif', ini='if' and word='else' and then word='endif'.
let word = strpart(tail, 0, i-1)
let tail = strpart(tail, i)
let i = matchend(tail, s:notslash . ':')
let parsed = parsed . ":" . s:Resolve(ini, word, "word")
endwhile " Now, tail has been used up.
let parsed = parsed . ","
endwhile " groups =~ '[^,:]'
let parsed = substitute(parsed, ',$', '', '')
return parsed
endfun
" TODO I think this can be simplified and/or made more efficient.
" TODO What should I do if a:start is out of range?
" Return a regexp that matches all of a:string, such that
" matchstr(a:string, regexp) represents the match for a:pat that starts
" as close to a:start as possible, before being preferred to after, and
" ends after a:start .
" Usage:
" let regexp = s:Wholematch(getline("."), 'foo\|bar', col(".")-1)
" let i = match(getline("."), regexp)
" let j = matchend(getline("."), regexp)
" let match = matchstr(getline("."), regexp)
fun! s:Wholematch(string, pat, start)
let group = '\%(' . a:pat . '\)'
let prefix = (a:start ? '\(^.*\%<' . (a:start + 2) . 'c\)\zs' : '^')
let len = strlen(a:string)
let suffix = (a:start+1 < len ? '\(\%>'.(a:start+1).'c.*$\)\@=' : '$')
if a:string !~ prefix . group . suffix
let prefix = ''
endif
return prefix . group . suffix
endfun
" No extra arguments: s:Ref(string, d) will
" find the d'th occurrence of '\(' and return it, along with everything up
" to and including the matching '\)'.
" One argument: s:Ref(string, d, "start") returns the index of the start
" of the d'th '\(' and any other argument returns the length of the group.
" Two arguments: s:Ref(string, d, "foo", "bar") returns a string to be
" executed, having the effect of
" :let foo = s:Ref(string, d, "start")
" :let bar = s:Ref(string, d, "len")
fun! s:Ref(string, d, ...)
let len = strlen(a:string)
if a:d == 0
let start = 0
else
let cnt = a:d
let match = a:string
while cnt
let cnt = cnt - 1
let index = matchend(match, s:notslash . '\\(')
if index == -1
return ""
endif
let match = strpart(match, index)
endwhile
let start = len - strlen(match)
if a:0 == 1 && a:1 == "start"
return start - 2
endif
let cnt = 1
while cnt
let index = matchend(match, s:notslash . '\\(\|\\)') - 1
if index == -2
return ""
endif
" Increment if an open, decrement if a ')':
let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')'
" let cnt = stridx('0(', match[index]) + cnt
let match = strpart(match, index+1)
endwhile
let start = start - 2
let len = len - start - strlen(match)
endif
if a:0 == 1
return len
elseif a:0 == 2
return "let " . a:1 . "=" . start . "| let " . a:2 . "=" . len
else
return strpart(a:string, start, len)
endif
endfun
" Count the number of disjoint copies of pattern in string.
" If the pattern is a literal string and contains no '0' or '1' characters
" then s:Count(string, pattern, '0', '1') should be faster than
" s:Count(string, pattern).
fun! s:Count(string, pattern, ...)
let pat = escape(a:pattern, '\\')
if a:0 > 1
let foo = substitute(a:string, '[^'.a:pattern.']', "a:1", "g")
let foo = substitute(a:string, pat, a:2, "g")
let foo = substitute(foo, '[^' . a:2 . ']', "", "g")
return strlen(foo)
endif
let result = 0
let foo = a:string
let index = matchend(foo, pat)
while index != -1
let result = result + 1
let foo = strpart(foo, index)
let index = matchend(foo, pat)
endwhile
return result
endfun
" s:Resolve('\(a\)\(b\)', '\(c\)\2\1\1\2') should return table.word, where
" word = '\(c\)\(b\)\(a\)\3\2' and table = '-32-------'. That is, the first
" '\1' in target is replaced by '\(a\)' in word, table[1] = 3, and this
" indicates that all other instances of '\1' in target are to be replaced
" by '\3'. The hard part is dealing with nesting...
" Note that ":" is an illegal character for source and target,
" unless it is preceded by "\".
fun! s:Resolve(source, target, output)
let word = a:target
let i = matchend(word, s:notslash . '\\\d') - 1
let table = "----------"
while i != -2 " There are back references to be replaced.
let d = word[i]
let backref = s:Ref(a:source, d)
" The idea is to replace '\d' with backref. Before we do this,
" replace any \(\) groups in backref with :1, :2, ... if they
" correspond to the first, second, ... group already inserted
" into backref. Later, replace :1 with \1 and so on. The group
" number w+b within backref corresponds to the group number
" s within a:source.
" w = number of '\(' in word before the current one
let w = s:Count(
\ substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1')
let b = 1 " number of the current '\(' in backref
let s = d " number of the current '\(' in a:source
while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1')
\ && s < 10
if table[s] == "-"
if w + b < 10
" let table[s] = w + b
let table = strpart(table, 0, s) . (w+b) . strpart(table, s+1)
endif
let b = b + 1
let s = s + 1
else
execute s:Ref(backref, b, "start", "len")
let ref = strpart(backref, start, len)
let backref = strpart(backref, 0, start) . ":". table[s]
\ . strpart(backref, start+len)
let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1')
endif
endwhile
let word = strpart(word, 0, i-1) . backref . strpart(word, i+1)
let i = matchend(word, s:notslash . '\\\d') - 1
endwhile
let word = substitute(word, s:notslash . '\zs:', '\\', 'g')
if a:output == "table"
return table
elseif a:output == "word"
return word
else
return table . word
endif
endfun
" Assume a:comma = ",". Then the format for a:patterns and a:1 is
" a:patterns = "<pat1>,<pat2>,..."
" a:1 = "<alt1>,<alt2>,..."
" If <patn> is the first pattern that matches a:string then return <patn>
" if no optional arguments are given; return <patn>,<altn> if a:1 is given.
fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...)
let tail = (a:patterns =~ a:comma."$" ? a:patterns : a:patterns . a:comma)
let i = matchend(tail, s:notslash . a:comma)
if a:0
let alttail = (a:1 =~ a:comma."$" ? a:1 : a:1 . a:comma)
let j = matchend(alttail, s:notslash . a:comma)
endif
let current = strpart(tail, 0, i-1)
if a:branch == ""
let currpat = current
else
let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g')
endif
while a:string !~ a:prefix . currpat . a:suffix
let tail = strpart(tail, i)
let i = matchend(tail, s:notslash . a:comma)
if i == -1
return -1
endif
let current = strpart(tail, 0, i-1)
if a:branch == ""
let currpat = current
else
let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g')
endif
if a:0
let alttail = strpart(alttail, j)
let j = matchend(alttail, s:notslash . a:comma)
endif
endwhile
if a:0
let current = current . a:comma . strpart(alttail, 0, j-1)
endif
return current
endfun
" Call this function to turn on debugging information. Every time the main
" script is run, buffer variables will be saved. These can be used directly
" or viewed using the menu items below.
if !exists(":MatchDebug")
command! -nargs=0 MatchDebug call s:Match_debug()
endif
fun! s:Match_debug()
let b:match_debug = 1 " Save debugging information.
" pat = all of b:match_words with backrefs parsed
amenu &Matchit.&pat :echo b:match_pat<CR>
" match = bit of text that is recognized as a match
amenu &Matchit.&match :echo b:match_match<CR>
" curcol = cursor column of the start of the matching text
amenu &Matchit.&curcol :echo b:match_col<CR>
" wholeBR = matching group, original version
amenu &Matchit.wh&oleBR :echo b:match_wholeBR<CR>
" iniBR = 'if' piece, original version
amenu &Matchit.ini&BR :echo b:match_iniBR<CR>
" ini = 'if' piece, with all backrefs resolved from match
amenu &Matchit.&ini :echo b:match_ini<CR>
" tail = 'else\|endif' piece, with all backrefs resolved from match
amenu &Matchit.&tail :echo b:match_tail<CR>
" fin = 'endif' piece, with all backrefs resolved from match
amenu &Matchit.&word :echo b:match_word<CR>
" '\'.d in ini refers to the same thing as '\'.table[d] in word.
amenu &Matchit.t&able :echo '0:' . b:match_table . ':9'<CR>
endfun
" Jump to the nearest unmatched "(" or "if" or "<tag>" if a:spflag == "bW"
" or the nearest unmatched "</tag>" or "endif" or ")" if a:spflag == "W".
" Return a "mark" for the original position, so that
" let m = MultiMatch("bW", "n") ... execute m
" will return to the original position. If there is a problem, do not
" move the cursor and return "", unless a count is given, in which case
" go up or down as many levels as possible and again return "".
" TODO This relies on the same patterns as % matching. It might be a good
" idea to give it its own matching patterns.
fun! s:MultiMatch(spflag, mode)
if !exists("b:match_words") || b:match_words == ""
return ""
end
let restore_options = (&ic ? "" : "no") . "ignorecase"
if exists("b:match_ignorecase")
let &ignorecase = b:match_ignorecase
endif
let startline = line(".")
let startcol = col(".")
" First step: if not already done, set the script variables
" s:do_BR flag for whether there are backrefs
" s:pat parsed version of b:match_words
" s:all regexp based on s:pat and the default groups
" This part is copied and slightly modified from s:Match_wrapper().
let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
\ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
" Allow b:match_words = "GetVimMatchWords()" .
if b:match_words =~ ":"
let match_words = b:match_words
else
execute "let match_words =" b:match_words
endif
if (match_words != s:last_words) || (&mps != s:last_mps) ||
\ exists("b:match_debug")
let s:last_words = match_words
let s:last_mps = &mps
if match_words !~ s:notslash . '\\\d'
let s:do_BR = 0
let s:pat = match_words
else
let s:do_BR = 1
let s:pat = s:ParseWords(match_words)
endif
let s:all = '\%(' . substitute(s:pat . (strlen(s:pat)?",":"") . default,
\ '[,:]\+','\\|','g') . '\)'
if exists("b:match_debug")
let b:match_pat = s:pat
endif
endif
" Second step: figure out the patterns for searchpair()
" and save the screen, cursor position, and 'ignorecase'.
" - TODO: A lot of this is copied from s:Match_wrapper().
" - maybe even more functionality should be split off
" - into separate functions!
let cdefault = (s:pat =~ '[^,]$' ? "," : "") . default
let open = substitute(s:pat . cdefault,
\ s:notslash . '\zs:.\{-}' . s:notslash . ',', '\\),\\(', 'g')
let open = '\(' . substitute(open, s:notslash . '\zs:.*$', '\\)', '')
let close = substitute(s:pat . cdefault,
\ s:notslash . '\zs,.\{-}' . s:notslash . ':', '\\),\\(', 'g')
let close = substitute(close, '^.\{-}' . s:notslash . ':', '\\(', '') . '\)'
if exists("b:match_skip")
let skip = b:match_skip
elseif exists("b:match_comment") " backwards compatibility and testing!
let skip = "r:" . b:match_comment
else
let skip = 's:comment\|string'
endif
let skip = s:ParseSkip(skip)
" let restore_cursor = line(".") . "G" . virtcol(".") . "|"
" normal! H
" let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
let restore_cursor = virtcol(".") . "|"
normal! g0
let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
normal! H
let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
execute restore_cursor
" Third step: call searchpair().
" Replace '\('--but not '\\('--with '\%(' and ',' with '\|'.
let openpat = substitute(open, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
let openpat = substitute(openpat, ',', '\\|', 'g')
let closepat = substitute(close, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
let closepat = substitute(closepat, ',', '\\|', 'g')
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
let skip = '0'
else
execute "if " . skip . "| let skip = '0' | endif"
endif
mark '
let level = v:count1
while level
if searchpair(openpat, '', closepat, a:spflag, skip) < 1
call s:CleanUp(restore_options, a:mode, startline, startcol)
return ""
endif
let level = level - 1
endwhile
" Restore options and return a string to restore the original position.
call s:CleanUp(restore_options, a:mode, startline, startcol)
return restore_cursor
endfun
" Search backwards for "if" or "while" or "<tag>" or ...
" and return "endif" or "endwhile" or "</tag>" or ... .
" For now, this uses b:match_words and the same script variables
" as s:Match_wrapper() . Later, it may get its own patterns,
" either from a buffer variable or passed as arguments.
" fun! s:Autocomplete()
" echo "autocomplete not yet implemented :-("
" if !exists("b:match_words") || b:match_words == ""
" return ""
" end
" let startpos = s:MultiMatch("bW")
"
" if startpos == ""
" return ""
" endif
" " - TODO: figure out whether 'if' or '<tag>' matched, and construct
" " - the appropriate closing.
" let matchline = getline(".")
" let curcol = col(".") - 1
" " - TODO: Change the s:all argument if there is a new set of match pats.
" let regexp = s:Wholematch(matchline, s:all, curcol)
" let suf = strlen(matchline) - matchend(matchline, regexp)
" let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(')
" let suffix = (suf ? '\).\{' . suf . '}$' : '\)$')
" " Reconstruct the version with unresolved backrefs.
" let patBR = substitute(b:match_words.',', '[,:]*,[,:]*', ',', 'g')
" let patBR = substitute(patBR, ':\{2,}', ':', "g")
" " Now, set group and groupBR to the matching group: 'if:endif' or
" " 'while:endwhile' or whatever.
" let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
" let i = matchend(group, s:notslash . ",")
" let groupBR = strpart(group, i)
" let group = strpart(group, 0, i-1)
" " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
" if s:do_BR
" let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
" endif
" " let g:group = group
"
" " - TODO: Construct the closing from group.
" let fake = "end" . expand("<cword>")
" execute startpos
" return fake
" endfun
" Close all open structures. "Get the heck out of here!"
" fun! s:Gthhoh()
" let close = s:Autocomplete()
" while strlen(close)
" put=close
" let close = s:Autocomplete()
" endwhile
" endfun
" Parse special strings as typical skip arguments for searchpair():
" s:foo becomes (current syntax item) =~ foo
" S:foo becomes (current syntax item) !~ foo
" r:foo becomes (line before cursor) =~ foo
" R:foo becomes (line before cursor) !~ foo
fun! s:ParseSkip(str)
let skip = a:str
if skip[1] == ":"
if skip[0] == "s"
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .
\ strpart(skip,2) . "'"
elseif skip[0] == "S"
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .
\ strpart(skip,2) . "'"
elseif skip[0] == "r"
let skip = "strpart(getline('.'),0,col('.'))=~'" . strpart(skip,2). "'"
elseif skip[0] == "R"
let skip = "strpart(getline('.'),0,col('.'))!~'" . strpart(skip,2). "'"
endif
endif
return skip
endfun
let &cpo = s:save_cpo
" vim:sts=2:sw=2:

537
vim/plugin/pastie.vim Normal file
View File

@@ -0,0 +1,537 @@
" pastie.vim: Vim plugin for pastie.caboo.se
" Maintainer: Tim Pope <vimNOSPAM@tpope.info>
" URL: http://www.vim.org/scripts/script.php?script_id=1624
" GetLatestVimScripts: 1624 1
" $Id: pastie.vim,v 1.15 2007-12-13 16:44:26 tpope Exp $
" Installation:
" Place in ~/.vim/plugin or vimfiles/plugin
" A working ruby install is required (Vim interface not necessary).
" Usage:
" :Pastie creates a new paste (example arguments shown below). Use :w to save
" it by posting it to the server (the parser used is derived from the Vim
" filetype). This updates the filename and stores the new url in the primary
" selection/clipboard when successful. :Pastie! creates a paste, saves, and
" closes the buffer, except when loading an existing paste.
" :Pastie Create a paste from all open windows
" :Pastie! Create a paste from all open windows and paste it
" :1,10Pastie Create a paste from the specified range
" :%Pastie Use the entire current file to create a new paste
" :Pastie foo.txt bar.txt Create a paste from foo.txt and bar.txt
" :Pastie! foo.txt Paste directly from foo.txt
" :Pastie a Create a paste from the "a register
" :Pastie @ Create a paste from the default (unnamed) register
" :Pastie * Create a paste from the primary selection/clipboard
" :Pastie _ Create a new, blank paste
" :768Pastie Load existing paste 768
" :0Pastie Load the newest paste
" :Pastie http://pastie.caboo.se/768 Load existing paste 768
" :Pastie http://pastie.caboo.se/123456?key=... Use login from pastie bot
" Regardless of the command used, on the first write, this script will create
" a new paste, and on subsequent writes, it will update the existing paste.
" If a bang is passed to a command that load an existing paste (:768), the
" first write will update as well. If the loaded paste was not created in the
" same vim session, or with an account extracted from your Firefox cookies,
" updates will almost certainly silently fail. (Advanced users can muck
" around with g:pastie_session_id if desired).
" As hinted at earlier, pastie.vim will snoop around in your Firefox cookies,
" and use an account cookie if one is found. The only way to create one of
" these account cookies is by talking to pastie on IRC.
" At the shell you can directly create a new pastie with a command like
" $ vim +Pastie
" or, assuming no other plugins conflict
" $ vim +Pa
" And, to read an existing paste
" $ vim +768Pa
" You could even paste a file directly
" $ vim '+Pa!~/.irbrc' +q
" You can even edit a pastie URL directly, but this is not recommended because
" netrw can sometimes interfere.
" Lines ending in #!! will be sent as lines beginning with !!. This alternate
" format is easier to read and is less likely to interfere with code
" execution. In Vim 7 highlighting is done with :2match (use ":2match none"
" to disable it) and in previous versions, :match (use ":match none" to
" disable).
"
" Known Issues:
" URL sometimes disappears with the bang (:Pastie!) variant. You can still
" retrieve it from the clipboard.
if exists("g:loaded_pastie") || &cp
finish
endif
let g:loaded_pastie = 1
augroup pastie
autocmd!
autocmd BufReadPre http://pastie.caboo.se/*[0-9]?key=* call s:extractcookies(expand("<amatch>"))
autocmd BufReadPost http://pastie.caboo.se/*[0-9]?key=* call s:PastieSwapout(expand("<amatch>"))
autocmd BufReadPost http://pastie.caboo.se/*[0-9] call s:PastieSwapout(expand("<amatch>"))
autocmd BufReadPost http://pastie.caboo.se/pastes/*[0-9]/download call s:PastieRead(expand("<amatch>"))
autocmd BufReadPost http://pastie.caboo.se/*[0-9].* call s:PastieRead(expand("<amatch>"))
autocmd BufWriteCmd http://pastie.caboo.se/pastes/*[0-9]/download call s:PastieWrite(expand("<amatch>"))
autocmd BufWriteCmd http://pastie.caboo.se/*[0-9].* call s:PastieWrite(expand("<amatch>"))
autocmd BufWriteCmd http://pastie.caboo.se/pastes/ call s:PastieWrite(expand("<amatch>"))
augroup END
let s:domain = "pastie.caboo.se"
let s:dl_suffix = ".txt" " Used only for :file
if !exists("g:pastie_destination")
if version >= 700
let g:pastie_destination = 'tab'
else
let g:pastie_destination = 'window'
endif
"let g:pastie_destination = 'buffer'
endif
command! -bar -bang -nargs=* -range=0 -complete=file Pastie :call s:Pastie(<bang>0,<line1>,<line2>,<count>,<f-args>)
function! s:Pastie(bang,line1,line2,count,...)
if exists(":tab")
let tabnr = tabpagenr()
endif
let newfile = "http://".s:domain."/pastes/"
let loggedin = 0
let ft = &ft
let num = 0
if a:0 == 0 && a:count == a:line1 && a:count > line('$')
let num = a:count
elseif a:0 == 0 && a:line1 == 0 && a:line2 == 0
let num = s:latestid()
if num == 0
return s:error("Could not determine latest paste")
endif
elseif !a:count && a:0 == 1
if a:1 == '*'
let numcheck = @*
elseif a:1 == '+'
let numcheck = @+
elseif a:1 == '@'
let numcheck = @@
else
let numcheck = a:1
endif
let numcheck = substitute(numcheck,'\n\+$','','')
let numcheck = substitute(numcheck,'^\n\+','','g')
if numcheck =~ '\n'
let numcheck = ''
endif
if numcheck =~ '^\d\d+$'
let num = numcheck
elseif numcheck =~ '\%(^\|/\)\d\+?key=\x\{8,\}'
if exists("b:pastie_fake_login")
unlet b:pastie_fake_login
else
call s:extractcookies('/'.matchstr(numcheck,'\%(^\|/\)\zs\d\+?.*'))
endif
if exists("g:pastie_account")
let loggedin = 1
endif
let num = matchstr(numcheck,'\%(^\|/\)\zs\d\+\ze?')
elseif numcheck =~ '\%(^\|^/\|^http://.*\)\d\+\%([/?]\|$\)'
let num = matchstr(numcheck,'\%(^\|/\)\zs\d\+')
endif
endif
if num
call s:newwindow()
let file = "http://".s:domain."/".num.s:dl_suffix
silent exe 'doautocmd BufReadPre '.file
silent exe 'read !ruby -rnet/http -e "r = Net::HTTP.get_response(\%{'.s:domain.'}, \%{/pastes/'.num.'/download}); if r.code == \%{200} then print r.body else exit 10+r.code.to_i/100 end"'
if v:shell_error && v:shell_error != 14 && v:shell_error !=15
return s:error("Something went wrong: shell returned ".v:shell_error)
else
let err = v:shell_error
silent exe "file ".file
1d_
set nomodified
call s:dobufreadpost()
if err
if loggedin
let b:pastie_update = 1
else
echohl WarningMsg
echo "Warning: Failed to retrieve existing paste"
echohl None
endif
endif
"call s:PastieRead(file)
if a:bang
" Instead of saving an identical paste, take ! to mean "do not
" create a new paste on first save"
let b:pastie_update = 1
endif
return
endif
elseif a:0 == 0 && !a:count && a:bang && expand("%") =~ '^http://'.s:domain.'/\d\+'
" If the :Pastie! form is used in an existing paste, switch to
" updating instead of creating.
"echohl Question
echo "Will update, not create"
echohl None
let b:pastie_update = 1
return
elseif a:0 == 1 && !a:count && a:1 =~ '^[&?]\x\{32,\}'
" Set session id with :Pastie&deadbeefcafebabe
let g:pastie_session_id = strpart(a:1,1)
elseif a:0 == 1 && !a:count && (a:1 == '&' || a:1 == '?')
" Extract session id with :Pastie&
call s:cookies()
if exists("g:pastie_session_id")
echo g:pastie_session_id
"silent! let @* = g:pastie_session_id
endif
elseif a:0 == 0 && !a:count && a:line1
let ft = 'conf'
let sum = ""
let cnt = 0
let keep = @"
windo let tmp = s:grabwin() | if tmp != "" | let cnt = cnt + 1 | let sum = sum . tmp | end
let sum = substitute(sum,'\n\+$',"\n",'')
if cnt == 1
let ft = matchstr(sum,'^##.\{-\} \[\zs\w*\ze\]')
if ft != ""
let sum = substitute(sum,'^##.\{-\} \[\w*\]\n','','')
endif
endif
call s:newwindow()
silent exe "file ".newfile
"silent exe "doautocmd BufReadPre ".newfile
if sum != ""
let @" = sum
silent $put
1d _
endif
if ft == 'plaintext' || ft == 'plain_text'
"set ft=conf
elseif ft != '' && sum != ""
let &ft = ft
endif
let @" = keep
call s:dobufreadpost()
else
let keep = @"
let args = ""
if a:0 > 0 && a:1 =~ '^[-"@0-9a-zA-Z:.%#*+~_/]$'
let i = 1
let register = a:1
else
let i = 0
let register = ""
endif
while i < a:0
let i = i+1
if strlen(a:{i})
let file = fnamemodify(expand(a:{i}),':~:.')
let args = args . file . "\n"
endif
endwhile
let range = ""
if a:count
silent exe a:line1.",".a:line2."yank"
let range = @"
let @" = keep
endif
call s:newwindow()
silent exe "file ".newfile
"silent exe "doautocmd BufReadPre ".newfile
if range != ""
let &ft = ft
let @" = range
silent $put
endif
if register != '' && register != '_'
"exe "let regvalue = @".register
silent exe "$put ".(register =~ '^[@"]$' ? '' : register)
endif
while args != ''
let file = matchstr(args,'^.\{-\}\ze\n')
let args = substitute(args,'^.\{-\}\n','','')
let @" = "## ".file." [".s:parser(file)."]\n"
if a:0 != 1 || a:count
silent $put
else
let &ft = s:filetype(file)
endif
silent exe "$read ".substitute(file,' ','\ ','g')
endwhile
let @" = keep
1d_
call s:dobufreadpost()
if (a:0 + (a:count > 0)) > 1
set ft=conf
endif
endif
1
call s:afterload()
if a:bang
write
let name = bufname('%')
" TODO: re-echo the URL in a way that doesn't disappear. Stupid Vim.
silent! bdel
if exists("tabnr")
silent exe "norm! ".tabnr."gt"
endif
endif
endfunction
function! s:dobufreadpost()
if expand("%") =~ '/\d\+\.\@!'
silent exe "doautocmd BufReadPost ".expand("%")
else
silent exe "doautocmd BufNewFile ".expand("%")
endif
endfunction
function! s:PastieSwapout(file)
if a:file =~ '?key='
let b:pastie_fake_login = 1
endif
exe "Pastie ".a:file
endfunction
function! s:PastieRead(file)
let lnum = line(".")
silent %s/^!!\(.*\)/\1 #!!/e
exe lnum
set nomodified
let num = matchstr(a:file,'/\@<!/\zs\d\+')
let url = "http://".s:domain."/pastes/".num
"let url = substitute(a:file,'\c/\%(download/\=\|text/\=\)\=$','','')
let url = url."/download"
let result = system('ruby -rnet/http -e "puts Net::HTTP.get_response(URI.parse(%{'.url.'}))[%{Content-Disposition}]"')
let fn = matchstr(result,'filename="\zs.*\ze"')
let &ft = s:filetype(fn)
if &ft =~ '^\%(html\|ruby\)$' && getline(1).getline(2).getline(3) =~ '<%'
set ft=eruby
endif
call s:afterload()
endfunction
function! s:afterload()
set commentstring=%s\ #!! "
hi def link pastieIgnore Ignore
hi def link pastieNonText NonText
if exists(":match")
hi def link pastieHighlight MatchParen
if version >= 700
2match pastieHighlight /^!!\s*.*\|^.\{-\}\ze\s*#!!\s*$/
else
match pastieHighlight /^!!\s*.*\|^.\{-\}\ze\s*#!!\s*$/
endif
else
hi def link pastieHighlight Search
syn match pastieHighlight '^.\{-\}\ze\s*#!!\s*$' nextgroup=pastieIgnore skipwhite
syn region pastieHighlight start='^!!\s*' end='$' contains=pastieNonText
endif
syn match pastieIgnore '#!!\ze\s*$' containedin=rubyComment,rubyString
syn match pastieNonText '^!!' containedin=rubyString
endfunction
function! s:PastieWrite(file)
let parser = s:parser(&ft)
let tmp = tempname()
let num = matchstr(a:file,'/\@<!/\zs\d\+')
if num == ''
let num = 'pastes'
endif
if exists("b:pastie_update") && s:cookies() != '' && num != ""
let url = "/pastes/".num
let method = "_method=put&"
else
let url = "/pastes"
let method = ""
endif
if exists("b:pastie_display_name")
let pdn = "&paste[display_name]=".s:urlencode(b:pastie_display_name)
elseif exists("g:pastie_display_name")
let pdn = "&paste[display_name]=".s:urlencode(g:pastie_display_name)
else
let pdn = ""
endif
silent exe "write ".tmp
let result = ""
let rubycmd = 'obj = Net::HTTP.start(%{'.s:domain.'}){|h|h.post(%{'.url.'}, %q{'.method.'paste[parser]='.parser.pdn.'&paste[authorization]=burger&paste[key]=&paste[body]=} + File.read(%q{'.tmp.'}).gsub(/^(.*?) *#\!\! *#{36.chr}/,%{!\!}+92.chr+%{1}).gsub(/[^a-zA-Z0-9_.-]/n) {|s| %{%%%02x} % s[0]},{%{Cookie} => %{'.s:cookies().'}})}; print obj[%{Location}].to_s+%{ }+obj[%{Set-Cookie}].to_s'
let result = system('ruby -rnet/http -e "'.rubycmd.'"')
let redirect = matchstr(result,'^[^ ]*')
let cookies = matchstr(result,'^[^ ]* \zs.*')
call s:extractcookiesfromheader(cookies)
call delete(tmp)
if redirect =~ '^\w\+://'
set nomodified
let b:pastie_update = 1
"silent! let @+ = result
silent! let @* = redirect
silent exe "file ".redirect.s:dl_suffix
" TODO: make a proper status message
echo '"'.redirect.'" written'
silent exe "doautocmd BufWritePost ".redirect.s:dl_suffix
else
if redirect == ''
let redirect = "Could not post to ".url
endif
let redirect = substitute(redirect,'^-e:1:\s*','','')
call s:error(redirect)
endif
endfunction
function! s:error(msg)
echohl Error
echo a:msg
echohl NONE
let v:errmsg = a:msg
endfunction
function! s:filetype(type)
" Accepts a filename, extension, pastie parser, or vim filetype
let type = tolower(substitute(a:type,'.*\.','',''))
if type =~ '^\%(x\=html\|asp\w*\)$'
return 'html'
elseif type =~ '^\%(eruby\|erb\|rhtml\)$'
return 'eruby'
elseif type =~ '^\%(ruby\|ruby_on_rails\|rb\|rake\|builder\|rjs\|irbrc\)'
return 'ruby'
elseif type == 'js' || type == 'javascript'
return 'javascript'
elseif type == 'c' || type == 'cpp' || type == 'c++'
return 'cpp'
elseif type =~ '^\%(css\|diff\|java\|php\|python\|sql\|sh\|shell-unix-generic\)$'
return type
else
return ''
endif
endfunction
function! s:parser(type)
let type = s:filetype(a:type)
if type == 'text' || type == ''
return 'plain_text'
elseif type == 'eruby'
return 'html_rails'
elseif type == 'ruby'
return 'ruby_on_rails'
elseif type == 'sh'
return 'shell-unix-generic'
elseif type == 'cpp'
return 'c++'
else
return type
endif
endfunction
function! s:grabwin()
let ft = (&ft == '' ? expand("%:e") : &ft)
let top = "## ".expand("%:~:.")." [".s:parser(ft)."]\n"
let keep = @"
silent %yank
let file = @"
let @" = keep
if file == "" || file == "\n"
return ""
else
return top.file."\n"
endif
endfunction
function! s:cookies()
if exists("g:pastie_session_id")
let cookies = "_pastie_session_id=".g:pastie_session_id
else
call s:extractcookies('/')
if !exists("g:pastie_session_id")
if !exists("s:session_warning")
echohl WarningMsg
echo "Warning: could not extract session id"
let s:session_warning = 1
echohl NONE
endif
let cookies = ""
else
let cookies = "_pastie_session_id=".g:pastie_session_id
endif
endif
if !exists("g:pastie_account")
let rubycmd = '%w(~/.mozilla/firefox ~/.firefox/default ~/.phoenix/default ~/Application\ Data/Mozilla/Firefox/Profiles ~/Library/Application\ Support/Firefox/Profiles)'
let rubycmd = rubycmd . '.each {|dir| Dir[File.join(File.expand_path(dir),%{*})].select {|p| File.exists?(File.join(p,%{cookies.txt}))}.each {|p| File.open(File.join(p,%{cookies.txt})).each_line { |l| a=l.split(9.chr); puts [a[4],a[6]].join(%{ }) if a[0] =~ /pastie\.caboo\.se#{36.chr}/ && Time.now.to_i < a[4].to_i && a[5] == %{account} }}}'
let output = ''
let output = system('ruby -e "'.rubycmd.'"')
if output =~ '\n' && output !~ '-e:'
let output = substitute(output,'\n.*','','')
let g:pastie_account = matchstr(output,' \zs.*')
let g:pastie_account_expires = matchstr(output,'.\{-\}\ze ')
else
let g:pastie_account = ''
endif
endif
if exists("g:pastie_account") && g:pastie_account != ""
" You cannot set this arbitrarily, it must be a valid cookie
let cookies = cookies . (cookies == "" ? "" : "; ")
let cookies = cookies . 'account='.substitute(g:pastie_account,':','%3A','g')
endif
return cookies
endfunction
function! s:extractcookies(path)
let path = substitute(a:path,'\c^http://'.s:domain,'','')
if path !~ '^/'
let path = '/'.path
endif
let cookie = system('ruby -rnet/http -e "print Net::HTTP.get_response(%{'.s:domain.'},%{'.path.'})[%{Set-Cookie}]"')
if exists("g:pastie_debug")
let g:pastie_cookies_path = path
let g:pastie_cookies = cookie
endif
return s:extractcookiesfromheader(cookie)
endfunction
function! s:extractcookiesfromheader(cookie)
let cookie = a:cookie
if cookie !~ '-e:'
let session_id = matchstr(cookie,'\<_pastie_session_id=\zs.\{-\}\ze\%([;,]\|$\)')
let account = matchstr(cookie,'\<account=\zs.\{-\}\ze\%([;,]\|$\)')
if session_id != ""
let g:pastie_session_id = session_id
endif
if account != ""
let g:pastie_account = account
let time = matchstr(cookie,'\<[Ee]xpires=\zs\w\w\w,.\{-\}\ze\%([;,]\|$\)')
if time != ""
let g:pastie_account_expires = system('ruby -e "print Time.parse(%{'.time.'}).to_i"')
endif
endif
endif
endfunction
function! s:latestid()
return system('ruby -rnet/http -e "print Net::HTTP.get_response(URI.parse(%{http://'.s:domain.'/all})).body.match(%r{<a href=.http://'.s:domain.'/(\d+).>View})[1]"')
endfunction
function! s:urlencode(str)
" Vim 6.2, how did we ever live with you?
return substitute(substitute(a:str,"[\001-\037%&?=\\\\]",'\="%".printf("%02X",char2nr(submatch(0)))','g'),' ','%20','g')
endfunction
function! s:newwindow()
if !(&modified) && (expand("%") == '' || (version >= 700 && winnr("$") == 1 && tabpagenr("$") == 1))
enew
else
if g:pastie_destination == 'tab'
tabnew
elseif g:pastie_destination == 'window'
new
else
enew
endif
endif
setlocal noswapfile
endfunction
" vim:set sw=4 sts=4 et:

44
vim/plugin/peepopen.vim Normal file
View File

@@ -0,0 +1,44 @@
" plugin/peepopen.vim
" Author: Geoffrey Grosenbach <boss@topfunky.com>
" License: MIT License
" Install this file as plugin/peepopen.vim.
" If you prefer Command-T, use this snippet in your .gvimrc:
" if has("gui_macvim")
" macmenu &File.New\ Tab key=<nop>
" map <D-t> <Plug>PeepOpen
" end
" ============================================================================
" Exit quickly when:
" - this plugin was already loaded (or disabled)
" - when 'compatible' is set
if &cp || exists("g:peepopen_loaded") && g:peepopen_loaded
finish
endif
let g:peepopen_loaded = 1
let s:save_cpo = &cpo
set cpo&vim
function s:LaunchPeepOpenViaVim()
let cwd = getcwd()
silent exe "!open -a PeepOpen " . shellescape(cwd)
endfunction
command! PeepOpen :call <SID>LaunchPeepOpenViaVim()
noremap <unique> <script> <Plug>PeepOpen <SID>Launch
noremap <SID>Launch :call <SID>LaunchPeepOpenViaVim()<CR>
if !hasmapto('<Plug>PeepOpen')
map <unique> <silent> <C-f> <Plug>PeepOpen
endif
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set sw=2 sts=2:

486
vim/plugin/ragtag.vim Normal file
View File

@@ -0,0 +1,486 @@
" ragtag.vim - Ghetto XML/HTML mappings (formerly allml.vim)
" Author: Tim Pope <vimNOSPAM@tpope.org>
" Version: 2.0
" GetLatestVimScripts: 1896 1 :AutoInstall: ragtag.vim
if exists("g:loaded_ragtag") || &cp
finish
endif
let g:loaded_ragtag = 1
if has("autocmd")
augroup ragtag
autocmd!
autocmd FileType *html*,wml,xml,xslt,xsd,jsp call s:Init()
autocmd FileType php,asp*,cf,mason,eruby call s:Init()
if version >= 700
autocmd InsertLeave * call s:Leave()
endif
autocmd CursorHold * if exists("b:loaded_ragtag") | call s:Leave() | endif
augroup END
endif
inoremap <silent> <Plug>ragtagHtmlComplete <C-R>=<SID>htmlEn()<CR><C-X><C-O><C-P><C-R>=<SID>htmlDis()<CR><C-N>
" Public interface, for if you have your own filetypes to activate on
function! RagtagInit()
call s:Init()
endfunction
function! AllmlInit()
call s:Init()
endfunction
function! s:Init()
let b:loaded_ragtag = 1
inoremap <silent> <buffer> <SID>xmlversion <?xml version="1.0" encoding="<C-R>=toupper(<SID>charset())<CR>"?>
inoremap <buffer> <SID>htmltrans <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
inoremap <buffer> <SID>xhtmltrans <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
if s:subtype() == "xml"
imap <script> <buffer> <SID>doctype <SID>xmlversion
elseif exists("+omnifunc")
inoremap <silent> <buffer> <SID>doctype <C-R>=<SID>htmlEn()<CR><!DOCTYPE<C-X><C-O><C-P><C-R>=<SID>htmlDis()<CR><C-N><C-R>=<SID>doctypeSeek()<CR>
elseif s:subtype() == "xhtml"
imap <script> <buffer> <SID>doctype <SID>xhtmltrans
else
imap <script> <buffer> <SID>doctype <SID>htmltrans
endif
imap <script> <buffer> <C-X>! <SID>doctype
imap <silent> <buffer> <C-X># <meta http-equiv="Content-Type" content="text/html; charset=<C-R>=<SID>charset()<CR>"<C-R>=<SID>closetag()<CR>
inoremap <silent> <buffer> <SID>HtmlComplete <C-R>=<SID>htmlEn()<CR><C-X><C-O><C-P><C-R>=<SID>htmlDis()<CR><C-N>
imap <buffer> <C-X>H <SID>HtmlComplete
inoremap <silent> <buffer> <C-X>$ <C-R>=<SID>javascriptIncludeTag()<CR>
inoremap <silent> <buffer> <C-X>@ <C-R>=<SID>stylesheetTag()<CR>
inoremap <silent> <buffer> <C-X><Space> <Esc>ciw<Lt><C-R>"<C-R>=<SID>tagextras()<CR>></<C-R>"><Esc>b2hi
inoremap <silent> <buffer> <C-X><CR> <Esc>ciw<Lt><C-R>"<C-R>=<SID>tagextras()<CR>><CR></<C-R>"><Esc>O
if exists("&omnifunc")
inoremap <silent> <buffer> <C-X>/ <Lt>/<C-R>=<SID>htmlEn()<CR><C-X><C-O><C-R>=<SID>htmlDis()<CR><C-F>
if exists(":XMLns")
XMLns xhtml10s
endif
else
inoremap <silent> <buffer> <C-X>/ <Lt>/><Left>
endif
let g:surround_{char2nr("p")} = "<p>\n\t\r\n</p>"
let g:surround_{char2nr("d")} = "<div\1div: \r^[^ ]\r &\1>\n\t\r\n</div>"
imap <buffer> <C-X><C-_> <C-X>/
imap <buffer> <SID>ragtagOopen <C-X><Lt><Space>
imap <buffer> <SID>ragtagOclose <Space><C-X>><Left><Left>
if &ft == "php"
inoremap <buffer> <C-X><Lt> <?php
inoremap <buffer> <C-X>> ?>
inoremap <buffer> <SID>ragtagOopen <?php<Space>print<Space>
let b:surround_45 = "<?php \r ?>"
let b:surround_61 = "<?php print \r ?>"
elseif &ft == "htmltt" || &ft == "tt2html"
inoremap <buffer> <C-X><Lt> [%
inoremap <buffer> <C-X>> %]
let b:surround_45 = "[% \r %]"
let b:surround_61 = "[% \r %]"
if !exists("b:surround_101")
let b:surround_101 = "[% \r %]\n[% END %]"
endif
elseif &ft =~ "django"
inoremap <buffer> <C-X><Lt> {{
inoremap <buffer> <C-X>> }}
let b:surround_45 = "{% \r %}"
let b:surround_61 = "{{ \r }}"
elseif &ft == "mason"
inoremap <buffer> <SID>ragtagOopen <&<Space>
inoremap <buffer> <SID>ragtagOclose <Space>&><Left><Left>
inoremap <buffer> <C-X><Lt> <%
inoremap <buffer> <C-X>> %>
let b:surround_45 = "<% \r %>"
let b:surround_61 = "<& \r &>"
elseif &ft == "cf"
inoremap <buffer> <SID>ragtagOopen <cfoutput>
inoremap <buffer> <SID>ragtagOclose </cfoutput><Left><C-Left><Left>
inoremap <buffer> <C-X><Lt> <cf
inoremap <buffer> <C-X>> >
let b:surround_45 = "<cf\r>"
let b:surround_61 = "<cfoutput>\r</cfoutput>"
else
inoremap <buffer> <SID>ragtagOopen <%=<Space>
inoremap <buffer> <C-X><Lt> <%
inoremap <buffer> <C-X>> %>
let b:surround_45 = "<% \r %>"
let b:surround_61 = "<%= \r %>"
endif
imap <buffer> <C-X>= <SID>ragtagOopen<SID>ragtagOclose<Left>
imap <buffer> <C-X>+ <C-V><NL><Esc>I<SID>ragtagOopen<Space><Esc>A<Space><SID>ragtagOclose<Esc>F<NL>s
" <%\n\n%>
if &ft == "cf"
inoremap <buffer> <C-X>] <cfscript><CR></cfscript><Esc>O
elseif &ft == "mason"
inoremap <buffer> <C-X>] <%perl><CR></%perl><Esc>O
elseif &ft == "html" || &ft == "xhtml" || &ft == "xml"
imap <buffer> <C-X>] <script<Space>type="text/javascript"><CR></script><Esc>O
else
imap <buffer> <C-X>] <C-X><Lt><CR><C-X>><Esc>O
endif
" <% %>
if &ft == "eruby"
inoremap <buffer> <C-X>- <%<Space><Space>-%><Esc>3hi
inoremap <buffer> <C-X>_ <C-V><NL><Esc>I<%<Space><Esc>A<Space>-%><Esc>F<NL>s
elseif &ft == "cf"
inoremap <buffer> <C-X>- <cf><Left>
inoremap <buffer> <C-X>_ <cfset ><Left>
else
imap <buffer> <C-X>- <C-X><Lt><Space><Space><C-X>><Esc>2hi
imap <buffer> <C-X>_ <C-V><NL><Esc>I<C-X><Lt><Space><Esc>A<Space><C-X>><Esc>F<NL>s
endif
" Comments
if &ft =~ '^asp'
imap <buffer> <C-X>' <C-X><Lt>'<Space><Space><C-X>><Esc>2hi
imap <buffer> <C-X>" <C-V><NL><Esc>I<C-X><Lt>'<Space><Esc>A<Space><C-X>><Esc>F<NL>s
let b:surround_35 = maparg("<C-X><Lt>","i")."' \r ".maparg("<C-X>>","i")
elseif &ft == "jsp"
inoremap <buffer> <C-X>' <Lt>%--<Space><Space>--%><Esc>4hi
inoremap <buffer> <C-X>" <C-V><NL><Esc>I<%--<Space><Esc>A<Space>--%><Esc>F<NL>s
let b:surround_35 = "<%-- \r --%>"
elseif &ft == "cf"
inoremap <buffer> <C-X>' <Lt>!---<Space><Space>---><Esc>4hi
inoremap <buffer> <C-X>" <C-V><NL><Esc>I<!---<Space><Esc>A<Space>---><Esc>F<NL>s
setlocal commentstring=<!---%s--->
let b:surround_35 = "<!--- \r --->"
elseif &ft == "html" || &ft == "xml" || &ft == "xhtml"
inoremap <buffer> <C-X>' <Lt>!--<Space><Space>--><Esc>3hi
inoremap <buffer> <C-X>" <C-V><NL><Esc>I<!--<Space><Esc>A<Space>--><Esc>F<NL>s
let b:surround_35 = "<!-- \r -->"
elseif &ft == "django"
inoremap <buffer> <C-X>' {#<Space><Space>#}<Esc>2hi
inoremap <buffer> <C-X>" <C-V><NL><Esc>I<C-X>{#<Space><Esc>A<Space>#}<Esc>F<NL>s
let b:surround_35 = "{# \r #}"
else
imap <buffer> <C-X>' <C-X><Lt>#<Space><Space><C-X>><Esc>2hi
imap <buffer> <C-X>" <C-V><NL><Esc>I<C-X><Lt>#<Space><Esc>A<Space><C-X>><Esc>F<NL>s
let b:surround_35 = maparg("<C-X><Lt>","i")."# \r ".maparg("<C-X>>","i")
endif
imap <buffer> <C-X>% <Plug>ragtagUrlEncode
imap <buffer> <C-X>& <Plug>ragtagXmlEncode
imap <buffer> <C-V>% <Plug>ragtagUrlV
imap <buffer> <C-V>& <Plug>ragtagXmlV
if !exists("b:did_indent")
if s:subtype() == "xml"
runtime! indent/xml.vim
else
runtime! indent/html.vim
endif
endif
" Pet peeve. Do people still not close their <p> and <li> tags?
if exists("g:html_indent_tags") && g:html_indent_tags !~ '\\|p\>'
let g:html_indent_tags = g:html_indent_tags.'\|p\|li\|dt\|dd'
endif
set indentkeys+=!^F
let b:surround_indent = 1
silent doautocmd User ragtag
silent doautocmd User allml
endfunction
function! s:Leave()
call s:disableescape()
endfunction
function! s:length(str)
return strlen(substitute(a:str,'.','.','g'))
endfunction
function! s:repeat(str,cnt)
let cnt = a:cnt
let str = ""
while cnt > 0
let str = str . a:str
let cnt = cnt - 1
endwhile
return str
endfunction
function! s:doctypeSeek()
if !exists("b:ragtag_doctype_index")
if exists("b:allml_doctype_index")
let b:ragtag_doctype_index = b:allml_doctype_index
elseif &ft == 'xhtml' || &ft == 'eruby'
let b:ragtag_doctype_index = 10
elseif &ft != 'xml'
let b:ragtag_doctype_index = 7
endif
endif
let index = b:ragtag_doctype_index - 1
return (index < 0 ? s:repeat("\<C-P>",-index) : s:repeat("\<C-N>",index))
endfunction
function! s:stylesheetTag()
if !exists("b:ragtag_stylesheet_link_tag")
if exists("b:allml_stylesheet_link_tag")
let b:ragtag_stylesheet_link_tag = b:allml_stylesheet_link_tag
else
let b:ragtag_stylesheet_link_tag = "<link rel=\"stylesheet\" type=\"text/css\" href=\"/stylesheets/\r.css\" />"
endif
endif
return s:insertTag(b:ragtag_stylesheet_link_tag)
endfunction
function! s:javascriptIncludeTag()
if !exists("b:ragtag_javascript_include_tag")
if exists("b:allml_javascript_include_tag")
let b:ragtag_javascript_include_tag = b:allml_javascript_include_tag
else
let b:ragtag_javascript_include_tag = "<script type=\"text/javascript\" src=\"/javascripts/\r.js\"></script>"
endif
endif
return s:insertTag(b:ragtag_javascript_include_tag)
endfunction
function! s:insertTag(tag)
let tag = a:tag
if s:subtype() == "html"
let tag = substitute(a:tag,'\s*/>','>','g')
endif
let before = matchstr(tag,'^.\{-\}\ze\r')
let after = matchstr(tag,'\r\zs\%(.*\r\)\@!.\{-\}$')
" middle isn't currently used
let middle = matchstr(tag,'\r\zs.\{-\}\ze\r')
return before.after.s:repeat("\<Left>",s:length(after))
endfunction
function! s:htmlEn()
let b:ragtag_omni = &l:omnifunc
let b:ragtag_isk = &l:isk
" : is for namespaced xml attributes
setlocal omnifunc=htmlcomplete#CompleteTags isk+=:
return ""
endfunction
function! s:htmlDis()
if exists("b:ragtag_omni")
let &l:omnifunc = b:ragtag_omni
unlet b:ragtag_omni
endif
if exists("b:ragtag_isk")
let &l:isk = b:ragtag_isk
unlet b:ragtag_isk
endif
return ""
endfunction
function! s:subtype()
let top = getline(1)."\n".getline(2)
if (top =~ '<?xml\>' && &ft !~? 'html') || &ft =~? '^\%(xml\|xsd\|xslt\)$'
return "xml"
elseif top =~? '\<xhtml\>'
return 'xhtml'
elseif top =~ '[^<]\<html\>'
return "html"
elseif &ft == "xhtml" || &ft == "eruby"
return "xhtml"
elseif exists("b:loaded_ragtag")
return "html"
else
return ""
endif
endfunction
function! s:closetagback()
if s:subtype() == "html"
return ">\<Left>"
else
return " />\<Left>\<Left>\<Left>"
endif
endfunction
function! s:closetag()
if s:subtype() == "html"
return ">"
else
return " />"
endif
endfunction
function! s:charset()
let enc = &fileencoding
if enc == ""
let enc = &encoding
endif
if enc == "latin1"
return "ISO-8859-1"
elseif enc == ""
return "US-ASCII"
else
return enc
endif
endfunction
function! s:tagextras()
if s:subtype() == "xml"
return ""
elseif @" == 'html' && s:subtype() == 'xhtml'
let lang = "en"
if exists("$LANG") && $LANG =~ '^..'
let lang = strpart($LANG,0,2)
endif
return ' xmlns="http://www.w3.org/1999/xhtml" lang="'.lang.'" xml:lang="'.lang.'"'
elseif @" == 'style'
return ' type="text/css"'
elseif @" == 'script'
return ' type="text/javascript"'
elseif @" == 'table'
return ' cellspacing="0"'
else
return ""
endif
endfunction
inoremap <silent> <SID>urlspace <C-R>=<SID>getinput()=~?'\%([?&]\<Bar>&amp;\)[%a-z0-9._~+-]*=[%a-z0-9._~+-]*$'?'+':'%20'<CR>
function! s:urltab(htmlesc)
let line = s:getinput()
let g:line = line
if line =~ '[^ <>"'."'".']\@<!\w\+$'
return ":"
elseif line =~ '[^ <>"'."'".']\@<!\w\+:/\=/\=[%a-z0-9._~+-]*$'
return "/"
elseif line =~? '\%([?&]\|&amp;\)[%a-z0-9._~+-]*$'
return "="
elseif line =~? '\%([?&]\|&amp;\)[%a-z0-9._~+-]*=[%a-z0-9._~+-]*$'
if a:htmlesc || synIDattr(synID(line('.'),col('.')-1,1),"name") =~ 'mlString$'
return "&amp;"
else
return "&"
endif
elseif line =~ '/$\|\.\w\+$'
return "?"
else
return "/"
endif
endfunction
function! s:toggleurlescape()
let htmllayer = 0
if exists("b:ragtag_escape_mode")
if b:ragtag_escape_mode == "url"
call s:disableescape()
return ""
elseif b:ragtag_escape_mode == "xml"
let htmllayer = 1
endif
call s:disableescape()
endif
let b:ragtag_escape_mode = "url"
imap <buffer> <BS> <Plug>ragtagBSUrl
inoremap <buffer> <CR> %0A
imap <script> <buffer> <Space> <SID>urlspace
inoremap <buffer> <Tab> &
inoremap <buffer> <Bar> %7C
if htmllayer
inoremap <silent> <buffer> <Tab> <C-R>=<SID>urltab(1)<CR>
else
inoremap <silent> <buffer> <Tab> <C-R>=<SID>urltab(0)<CR>
endif
let i = 33
while i < 127
" RFC3986: reserved = :/?#[]@ !$&'()*+,;=
if nr2char(i) =~# '[|=A-Za-z0-9_.~-]'
else
call s:urlmap(nr2char(i))
endif
let i = i + 1
endwhile
return ""
endfunction
function! s:urlencode(char)
let i = 0
let repl = ""
while i < strlen(a:char)
let repl = repl . printf("%%%02X",char2nr(strpart(a:char,i,1)))
let i = i + 1
endwhile
return repl
endfunction
function! s:urlmap(char)
let repl = s:urlencode(a:char)
exe "inoremap <buffer> ".a:char." ".repl
endfunction
function! s:urlv()
return s:urlencode(nr2char(getchar()))
endfunction
function! s:togglexmlescape()
if exists("b:ragtag_escape_mode")
if b:ragtag_escape_mode == "xml"
call s:disableescape()
return ""
endif
call s:disableescape()
endif
let b:ragtag_escape_mode = "xml"
imap <buffer> <BS> <Plug>ragtagBSXml
inoremap <buffer> <Lt> &lt;
inoremap <buffer> > &gt;
inoremap <buffer> & &amp;
inoremap <buffer> " &quot;
return ""
endfunction
function! s:disableescape()
if exists("b:ragtag_escape_mode")
if b:ragtag_escape_mode == "xml"
silent! iunmap <buffer> <BS>
silent! iunmap <buffer> <Lt>
silent! iunmap <buffer> >
silent! iunmap <buffer> &
silent! iunmap <buffer> "
elseif b:ragtag_escape_mode == "url"
silent! iunmap <buffer> <BS>
silent! iunmap <buffer> <Tab>
silent! iunmap <buffer> <CR>
silent! iunmap <buffer> <Space>
silent! iunmap <buffer> <Bar>
let i = 33
while i < 127
if nr2char(i) =~# '[|A-Za-z0-9_.~-]'
else
exe "silent! iunmap <buffer> ".nr2char(i)
endif
let i = i + 1
endwhile
endif
unlet b:ragtag_escape_mode
endif
endfunction
function! s:getinput()
return strpart(getline('.'),0,col('.')-1)
endfunction
function! s:bspattern(pattern)
let start = s:getinput()
let match = matchstr(start,'\%('.a:pattern.'\)$')
if match == ""
return "\<BS>"
else
return s:repeat("\<BS>",strlen(match))
endif
endfunction
inoremap <silent> <Plug>ragtagBSUrl <C-R>=<SID>bspattern('%\x\x\=\<Bar>&amp;')<CR>
inoremap <silent> <Plug>ragtagBSXml <C-R>=<SID>bspattern('&#\=\w*;\<Bar><[^><]*>\=')<CR>
inoremap <silent> <SID>ragtagUrlEncode <C-R>=<SID>toggleurlescape()<CR>
inoremap <silent> <SID>ragtagXmlEncode <C-R>=<SID>togglexmlescape()<CR>
inoremap <silent> <Plug>ragtagUrlEncode <C-R>=<SID>toggleurlescape()<CR>
inoremap <silent> <Plug>ragtagXmlEncode <C-R>=<SID>togglexmlescape()<CR>
inoremap <silent> <Plug>ragtagUrlV <C-R>=<SID>urlv()<CR>
inoremap <silent> <Plug>ragtagXmlV <C-R>="&#".getchar().";"<CR>
if exists("g:ragtag_global_maps")
imap <C-X>H <Plug>ragtagHtmlComplete
imap <C-X>/ </<Plug>ragtagHtmlComplete
imap <C-X>% <Plug>ragtagUrlEncode
imap <C-X>& <Plug>ragtagXmlEncode
imap <C-V>% <Plug>ragtagUrlV
imap <C-V>& <Plug>ragtagXmlV
endif

340
vim/plugin/rails.vim Executable file
View File

@@ -0,0 +1,340 @@
" rails.vim - Detect a rails application
" Author: Tim Pope <vimNOSPAM@tpope.org>
" GetLatestVimScripts: 1567 1 :AutoInstall: rails.vim
" URL: http://rails.vim.tpope.net/
" Install this file as plugin/rails.vim. See doc/rails.txt for details. (Grab
" it from the URL above if you don't have it.) To access it from Vim, see
" :help add-local-help (hint: :helptags ~/.vim/doc) Afterwards, you should be
" able to do :help rails
if exists('g:loaded_rails') || &cp || v:version < 700
finish
endif
let g:loaded_rails = 1
" Utility Functions {{{1
function! s:error(str)
echohl ErrorMsg
echomsg a:str
echohl None
let v:errmsg = a:str
endfunction
function! s:autoload(...)
if !exists("g:autoloaded_rails") && v:version >= 700
runtime! autoload/rails.vim
endif
if exists("g:autoloaded_rails")
if a:0
exe a:1
endif
return 1
endif
if !exists("g:rails_no_autoload_warning")
let g:rails_no_autoload_warning = 1
if v:version >= 700
call s:error("Disabling rails.vim: autoload/rails.vim is missing")
else
call s:error("Disabling rails.vim: Vim version 7 or higher required")
endif
endif
return ""
endfunction
" }}}1
" Configuration {{{
function! s:SetOptDefault(opt,val)
if !exists("g:".a:opt)
let g:{a:opt} = a:val
endif
endfunction
call s:SetOptDefault("rails_statusline",1)
call s:SetOptDefault("rails_syntax",1)
call s:SetOptDefault("rails_mappings",1)
call s:SetOptDefault("rails_abbreviations",1)
call s:SetOptDefault("rails_ctags_arguments","--exclude=\"*.js\"")
call s:SetOptDefault("rails_default_file","README")
call s:SetOptDefault("rails_root_url",'http://localhost:3000/')
call s:SetOptDefault("rails_modelines",0)
call s:SetOptDefault("rails_menu",!has('mac'))
call s:SetOptDefault("rails_gnu_screen",1)
call s:SetOptDefault("rails_history_size",5)
call s:SetOptDefault("rails_generators","controller\ngenerator\nhelper\nintegration_test\nmailer\nmetal\nmigration\nmodel\nobserver\nperformance_test\nplugin\nresource\nscaffold\nscaffold_controller\nsession_migration\nstylesheets")
if exists("g:loaded_dbext") && executable("sqlite3") && ! executable("sqlite")
" Since dbext can't find it by itself
call s:SetOptDefault("dbext_default_SQLITE_bin","sqlite3")
endif
" }}}1
" Detection {{{1
function! s:escvar(r)
let r = fnamemodify(a:r,':~')
let r = substitute(r,'\W','\="_".char2nr(submatch(0))."_"','g')
let r = substitute(r,'^\d','_&','')
return r
endfunction
function! s:Detect(filename)
let fn = substitute(fnamemodify(a:filename,":p"),'\c^file://','','')
let sep = matchstr(fn,'^[^\\/]\{3,\}\zs[\\/]')
if sep != ""
let fn = getcwd().sep.fn
endif
if fn =~ '[\/]config[\/]environment\.rb$'
return s:BufInit(strpart(fn,0,strlen(fn)-22))
endif
if isdirectory(fn)
let fn = fnamemodify(fn,':s?[\/]$??')
else
let fn = fnamemodify(fn,':s?\(.*\)[\/][^\/]*$?\1?')
endif
let ofn = ""
let nfn = fn
while nfn != ofn && nfn != ""
if exists("s:_".s:escvar(nfn))
return s:BufInit(nfn)
endif
let ofn = nfn
let nfn = fnamemodify(nfn,':h')
endwhile
let ofn = ""
while fn != ofn
if filereadable(fn . "/config/environment.rb")
return s:BufInit(fn)
endif
let ofn = fn
let fn = fnamemodify(ofn,':s?\(.*\)[\/]\(app\|config\|db\|doc\|features\|lib\|log\|public\|script\|spec\|stories\|test\|tmp\|vendor\)\($\|[\/].*$\)?\1?')
endwhile
return 0
endfunction
function! s:BufInit(path)
let s:_{s:escvar(a:path)} = 1
if s:autoload()
return RailsBufInit(a:path)
endif
endfunction
" }}}1
" Initialization {{{1
augroup railsPluginDetect
autocmd!
autocmd BufNewFile,BufRead * call s:Detect(expand("<afile>:p"))
autocmd VimEnter * if expand("<amatch>") == "" && !exists("b:rails_root") | call s:Detect(getcwd()) | endif | if exists("b:rails_root") | silent doau User BufEnterRails | endif
autocmd FileType netrw if !exists("b:rails_root") | call s:Detect(expand("<afile>:p")) | endif | if exists("b:rails_root") | silent doau User BufEnterRails | endif
autocmd BufEnter * if exists("b:rails_root")|silent doau User BufEnterRails|endif
autocmd BufLeave * if exists("b:rails_root")|silent doau User BufLeaveRails|endif
autocmd Syntax railslog if s:autoload()|call rails#log_syntax()|endif
augroup END
command! -bar -bang -nargs=* -complete=dir Rails :if s:autoload()|call rails#new_app_command(<bang>0,<f-args>)|endif
" }}}1
" abolish.vim support {{{1
function! s:function(name)
return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),''))
endfunction
augroup railsPluginAbolish
autocmd!
autocmd VimEnter * call s:abolish_setup()
augroup END
function! s:abolish_setup()
if exists('g:Abolish') && has_key(g:Abolish,'Coercions')
if !has_key(g:Abolish.Coercions,'l')
let g:Abolish.Coercions.l = s:function('s:abolish_l')
endif
if !has_key(g:Abolish.Coercions,'t')
let g:Abolish.Coercions.t = s:function('s:abolish_t')
endif
endif
endfunction
function! s:abolish_l(word)
let singular = rails#singularize(a:word)
return a:word ==? singular ? rails#pluralize(a:word) : singular
endfunction
function! s:abolish_t(word)
if a:word =~# '\u'
return rails#pluralize(rails#underscore(a:word))
else
return rails#singularize(rails#camelize(a:word))
endif
endfunction
" }}}1
" Menus {{{1
if !(g:rails_menu && has("menu"))
finish
endif
function! s:sub(str,pat,rep)
return substitute(a:str,'\v\C'.a:pat,a:rep,'')
endfunction
function! s:gsub(str,pat,rep)
return substitute(a:str,'\v\C'.a:pat,a:rep,'g')
endfunction
function! s:menucmd(priority)
return 'anoremenu <script> '.(exists("$CREAM") ? 87 : '').s:gsub(g:rails_installed_menu,'[^.]','').'.'.a:priority.' '
endfunction
function! s:CreateMenus() abort
if exists("g:rails_installed_menu") && g:rails_installed_menu != ""
exe "aunmenu ".s:gsub(g:rails_installed_menu,'\&','')
unlet g:rails_installed_menu
endif
if has("menu") && (exists("g:did_install_default_menus") || exists("$CREAM")) && g:rails_menu
if g:rails_menu > 1
let g:rails_installed_menu = '&Rails'
else
let g:rails_installed_menu = '&Plugin.&Rails'
endif
let dots = s:gsub(g:rails_installed_menu,'[^.]','')
let menucmd = s:menucmd(200)
if exists("$CREAM")
exe menucmd.g:rails_installed_menu.'.-PSep- :'
exe menucmd.g:rails_installed_menu.'.&Related\ file\ :R\ /\ Alt+] :R<CR>'
exe menucmd.g:rails_installed_menu.'.&Alternate\ file\ :A\ /\ Alt+[ :A<CR>'
exe menucmd.g:rails_installed_menu.'.&File\ under\ cursor\ Ctrl+Enter :Rfind<CR>'
else
exe menucmd.g:rails_installed_menu.'.-PSep- :'
exe menucmd.g:rails_installed_menu.'.&Related\ file\ :R\ /\ ]f :R<CR>'
exe menucmd.g:rails_installed_menu.'.&Alternate\ file\ :A\ /\ [f :A<CR>'
exe menucmd.g:rails_installed_menu.'.&File\ under\ cursor\ gf :Rfind<CR>'
endif
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Controller :find app/controllers/application.rb<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Helper :find app/helpers/application_helper.rb<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Javascript :find public/javascripts/application.js<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Layout :Rlayout application<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &README :find doc/README_FOR_APP<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.&Environment :find config/environment.rb<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.&Database\ Configuration :find config/database.yml<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.Database\ &Schema :Rmigration 0<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.R&outes :find config/routes.rb<CR>'
exe menucmd.g:rails_installed_menu.'.&Other\ files.&Test\ Helper :find test/test_helper.rb<CR>'
exe menucmd.g:rails_installed_menu.'.-FSep- :'
exe menucmd.g:rails_installed_menu.'.Ra&ke\ :Rake :Rake<CR>'
let menucmd = substitute(menucmd,'200 $','500 ','')
exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Start\ :Rserver :Rserver<CR>'
exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Force\ start\ :Rserver! :Rserver!<CR>'
exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Kill\ :Rserver!\ - :Rserver! -<CR>'
exe substitute(menucmd,'<script>','<script> <silent>','').g:rails_installed_menu.'.&Evaluate\ Ruby\.\.\.\ :Rp :call <SID>menuprompt("Rp","Code to execute and output: ")<CR>'
exe menucmd.g:rails_installed_menu.'.&Console\ :Rscript :Rscript console<CR>'
exe menucmd.g:rails_installed_menu.'.&Preview\ :Rpreview :Rpreview<CR>'
exe menucmd.g:rails_installed_menu.'.&Log\ file\ :Rlog :Rlog<CR>'
exe substitute(s:sub(menucmd,'anoremenu','vnoremenu'),'<script>','<script> <silent>','').g:rails_installed_menu.'.E&xtract\ as\ partial\ :Rextract :call <SID>menuprompt("'."'".'<,'."'".'>Rextract","Partial name (e.g., template or /controller/template): ")<CR>'
exe menucmd.g:rails_installed_menu.'.&Migration\ writer\ :Rinvert :Rinvert<CR>'
exe menucmd.' '.g:rails_installed_menu.'.-HSep- :'
exe substitute(menucmd,'<script>','<script> <silent>','').g:rails_installed_menu.'.&Help\ :help\ rails :if <SID>autoload()<Bar>exe RailsHelpCommand("")<Bar>endif<CR>'
exe substitute(menucmd,'<script>','<script> <silent>','').g:rails_installed_menu.'.Abo&ut\ :if <SID>autoload()<Bar>exe RailsHelpCommand("about")<Bar>endif<CR>'
let g:rails_did_menus = 1
call s:ProjectMenu()
call s:menuBufLeave()
if exists("b:rails_root")
call s:menuBufEnter()
endif
endif
endfunction
function! s:ProjectMenu()
if exists("g:rails_did_menus") && g:rails_history_size > 0
if !exists("g:RAILS_HISTORY")
let g:RAILS_HISTORY = ""
endif
let history = g:RAILS_HISTORY
let menu = s:gsub(g:rails_installed_menu,'\&','')
silent! exe "aunmenu <script> ".menu.".Projects"
let dots = s:gsub(menu,'[^.]','')
exe 'anoremenu <script> <silent> '.(exists("$CREAM") ? '87' : '').dots.'.100 '.menu.'.Pro&jects.&New\.\.\.\ :Rails :call <SID>menuprompt("Rails","New application path and additional arguments: ")<CR>'
exe 'anoremenu <script> '.menu.'.Pro&jects.-FSep- :'
while history =~ '\n'
let proj = matchstr(history,'^.\{-\}\ze\n')
let history = s:sub(history,'^.{-}\n','')
exe 'anoremenu <script> '.menu.'.Pro&jects.'.s:gsub(proj,'[.\\ ]','\\&').' :e '.s:gsub(proj."/".g:rails_default_file,'[ !%#]','\\&')."<CR>"
endwhile
endif
endfunction
function! s:menuBufEnter()
if exists("g:rails_installed_menu") && g:rails_installed_menu != ""
let menu = s:gsub(g:rails_installed_menu,'\&','')
exe 'amenu enable '.menu.'.*'
if RailsFileType() !~ '^view\>'
exe 'vmenu disable '.menu.'.Extract\ as\ partial'
endif
if RailsFileType() !~ '^\%(db-\)\=migration$' || RailsFilePath() =~ '\<db/schema\.rb$'
exe 'amenu disable '.menu.'.Migration\ writer'
endif
call s:ProjectMenu()
silent! exe 'aunmenu '.menu.'.Rake\ tasks'
silent! exe 'aunmenu '.menu.'.Generate'
silent! exe 'aunmenu '.menu.'.Destroy'
if rails#app().cache.needs('rake_tasks') || empty(rails#app().rake_tasks())
exe substitute(s:menucmd(300),'<script>','<script> <silent>','').g:rails_installed_menu.'.Rake\ &tasks\ :Rake.Fill\ this\ menu :call rails#app().rake_tasks()<Bar>call <SID>menuBufLeave()<Bar>call <SID>menuBufEnter()<CR>'
else
let i = 0
while i < len(rails#app().rake_tasks())
let task = rails#app().rake_tasks()[i]
exe s:menucmd(300).g:rails_installed_menu.'.Rake\ &tasks\ :Rake.'.s:sub(task,':',':.').' :Rake '.task.'<CR>'
let i += 1
endwhile
endif
let i = 0
let menucmd = substitute(s:menucmd(400),'<script>','<script> <silent>','').g:rails_installed_menu
while i < len(rails#app().generators())
let generator = rails#app().generators()[i]
exe menucmd.'.&Generate\ :Rgen.'.s:gsub(generator,'_','\\ ').' :call <SID>menuprompt("Rgenerate '.generator.'","Arguments for script/generate '.generator.': ")<CR>'
exe menucmd.'.&Destroy\ :Rdestroy.'.s:gsub(generator,'_','\\ ').' :call <SID>menuprompt("Rdestroy '.generator.'","Arguments for script/destroy '.generator.': ")<CR>'
let i += 1
endwhile
endif
endfunction
function! s:menuBufLeave()
if exists("g:rails_installed_menu") && g:rails_installed_menu != ""
let menu = s:gsub(g:rails_installed_menu,'\&','')
exe 'amenu disable '.menu.'.*'
exe 'amenu enable '.menu.'.Help\ '
exe 'amenu enable '.menu.'.About\ '
exe 'amenu enable '.menu.'.Projects'
silent! exe 'aunmenu '.menu.'.Rake\ tasks'
silent! exe 'aunmenu '.menu.'.Generate'
silent! exe 'aunmenu '.menu.'.Destroy'
exe s:menucmd(300).g:rails_installed_menu.'.Rake\ tasks\ :Rake.-TSep- :'
exe s:menucmd(400).g:rails_installed_menu.'.&Generate\ :Rgen.-GSep- :'
exe s:menucmd(400).g:rails_installed_menu.'.&Destroy\ :Rdestroy.-DSep- :'
endif
endfunction
function! s:menuprompt(vimcmd,prompt)
let res = inputdialog(a:prompt,'','!!!')
if res == '!!!'
return ""
endif
exe a:vimcmd." ".res
endfunction
call s:CreateMenus()
augroup railsPluginMenu
autocmd!
autocmd User BufEnterRails call s:menuBufEnter()
autocmd User BufLeaveRails call s:menuBufLeave()
" g:RAILS_HISTORY hasn't been set when s:InitPlugin() is called.
autocmd VimEnter * call s:ProjectMenu()
augroup END
" }}}1
" vim:set sw=2 sts=2:

72
vim/plugin/repeat.vim Normal file
View File

@@ -0,0 +1,72 @@
" repeat.vim - Let the repeat command repeat plugin maps
" Maintainer: Tim Pope
" Version: 1.0
" Installation:
" Place in either ~/.vim/plugin/repeat.vim (to load at start up) or
" ~/.vim/autoload/repeat.vim (to load automatically as needed).
"
" Developers:
" Basic usage is as follows:
"
" silent! call repeat#set("\<Plug>MappingToRepeatCommand",3)
"
" The first argument is the mapping that will be invoked when the |.| key is
" pressed. Typically, it will be the same as the mapping the user invoked.
" This sequence will be stuffed into the input queue literally. Thus you must
" encode special keys by prefixing them with a backslash inside double quotes.
"
" The second argument is the default count. This is the number that will be
" prefixed to the mapping if no explicit numeric argument was given. The
" value of the v:count variable is usually correct and it will be used if the
" second parameter is omitted. If your mapping doesn't accept a numeric
" argument and you never want to receive one, pass a value of -1.
"
" Make sure to call the repeat#set function _after_ making changes to the
" file.
if exists("g:loaded_repeat") || &cp || v:version < 700
finish
endif
let g:loaded_repeat = 1
let g:repeat_tick = -1
function! repeat#set(sequence,...)
silent exe "norm! \"=''\<CR>p"
let g:repeat_sequence = a:sequence
let g:repeat_count = a:0 ? a:1 : v:count
let g:repeat_tick = b:changedtick
endfunction
function! s:repeat(count)
if g:repeat_tick == b:changedtick
let c = g:repeat_count
let s = g:repeat_sequence
let cnt = c == -1 ? "" : (a:count ? a:count : (c ? c : ''))
call feedkeys(cnt . s)
else
call feedkeys((a:count ? a:count : '') . '.', 'n')
endif
endfunction
function! s:wrap(command,count)
let preserve = (g:repeat_tick == b:changedtick)
exe 'norm! '.(a:count ? a:count : '').a:command
if preserve
let g:repeat_tick = b:changedtick
endif
endfunction
nnoremap <silent> . :<C-U>call <SID>repeat(v:count)<CR>
nnoremap <silent> u :<C-U>call <SID>wrap('u',v:count)<CR>
nnoremap <silent> U :<C-U>call <SID>wrap('U',v:count)<CR>
nnoremap <silent> <C-R> :<C-U>call <SID>wrap("\<Lt>C-R>",v:count)<CR>
augroup repeatPlugin
autocmd!
autocmd BufLeave,BufWritePre,BufReadPre * let g:repeat_tick = (g:repeat_tick == b:changedtick || g:repeat_tick == 0) ? 0 : -1
autocmd BufEnter,BufWritePost * if g:repeat_tick == 0|let g:repeat_tick = b:changedtick|endif
augroup END
" vim:set ft=vim et sw=4 sts=4:

View File

@@ -0,0 +1,182 @@
if !has("ruby")
finish
end
command RunRubyFocusedUnitTest :call <SID>RunRubyFocusedUnitTest()
command RunRubyFocusedContext :call <SID>RunRubyFocusedContext()
command RunAllRubyTests :call <SID>RunAllRubyTests()
command RunLastRubyTest :call <SID>RunLastRubyTest()
function! s:RunRubyFocusedUnitTest()
ruby RubyFocusedUnitTest.new.run_test
endfunction
function! s:RunRubyFocusedContext()
ruby RubyFocusedUnitTest.new.run_context
endfunction
function! s:RunAllRubyTests()
ruby RubyFocusedUnitTest.new.run_all
endfunction
function! s:RunLastRubyTest()
ruby RubyFocusedUnitTest.new.run_last
endfunction
ruby << EOF
module VIM
class Buffer
class << self
include Enumerable
def each(&block)
(0...VIM::Buffer.count).each do |index|
yield self[index]
end
end
def create(name, opts={})
location = opts[:location] || :below
VIM.command("#{location} new #{name}")
buf = VIM::Buffer.current
if opts[:text]
buf.text = opts[:text]
end
buf
end
end
def text=(content)
content.split("\n").each_with_index do |line,index|
self.append index, line
end
end
def method_missing(method, *args, &block)
VIM.command "#{method} #{self.name}"
end
end
end
class RubyFocusedUnitTest
DEFAULT_OUTPUT_BUFFER = "rb_test_output"
SAVED_TEST_COMMAND_FILE = '/tmp/last_ruby_focused_unit_test'
def write_output_to_buffer(test_command)
save_test_command(test_command)
if buffer = VIM::Buffer.find { |b| b.name =~ /#{DEFAULT_OUTPUT_BUFFER}/ }
buffer.bdelete!
end
buffer = VIM::Buffer.create DEFAULT_OUTPUT_BUFFER, :location => :below, :text => "--- Run Focused Unit Test ---\n\n"
VIM.command("setlocal buftype=nowrite")
VIM.command "redraw"
IO.popen("#{test_command} 2>&1", "r") do |io|
begin
loop do
input = io.readpartial(10)
first, *rest = input.split(/\n/, -1)
buffer[buffer.length] = buffer[buffer.length] + first
rest.each {|l| buffer.append buffer.length, l }
VIM.command "redraw"
end
rescue EOFError
end
end
end
def save_test_command(test_command)
File.open(SAVED_TEST_COMMAND_FILE, 'w') { |f| f.write(test_command) }
end
def current_file
VIM::Buffer.current.name
end
def spec_file?
current_file =~ /spec_|_spec/
end
def line_number
VIM::Buffer.current.line_number
end
def run_spec
write_output_to_buffer("#{spec_command} '#{current_file}' -l #{line_number}")
end
def run_unit_test
method_name = nil
(line_number + 1).downto(1) do |line_number|
if VIM::Buffer.current[line_number] =~ /def (test_\w+)/
method_name = $1
break
elsif VIM::Buffer.current[line_number] =~ /test "([^"]+)"/ ||
VIM::Buffer.current[line_number] =~ /test '([^']+)'/
method_name = "test_" + $1.split(" ").join("_")
break
elsif VIM::Buffer.current[line_number] =~ /should "([^"]+)"/ ||
VIM::Buffer.current[line_number] =~ /should '([^']+)'/
method_name = "\"/#{Regexp.escape($1)}/\""
break
end
end
write_output_to_buffer("ruby #{current_file} -n #{method_name}") if method_name
end
def run_test
if spec_file?
run_spec
else
run_unit_test
end
end
def run_context
method_name = nil
context_line_number = nil
(line_number + 1).downto(1) do |line_number|
if VIM::Buffer.current[line_number] =~ /(context|describe) "([^"]+)"/ ||
VIM::Buffer.current[line_number] =~ /(context|describe) '([^']+)'/
method_name = $2
context_line_number = line_number
break
end
end
if method_name
if spec_file?
write_output_to_buffer("#{spec_command} #{current_file} -l #{context_line_number}")
else
method_name = "\"/#{Regexp.escape(method_name)}/\""
write_output_to_buffer("ruby #{current_file} -n #{method_name}")
end
end
end
def run_all
if spec_file?
write_output_to_buffer("#{spec_command} '#{current_file}'")
else
write_output_to_buffer("ruby '#{current_file}'")
end
end
def run_last
write_output_to_buffer(File.read(SAVED_TEST_COMMAND_FILE))
end
def spec_command
if File.exists?("Gemfile") && match = `bundle show rspec`.match(/(\d\.\d\.\d)$/)
match.to_a.last.to_f < 2 ? "bundle exec spec" : "bundle exec rspec"
else
system("rspec -v > /dev/null 2>&1") ? "rspec --no-color" : "spec"
end
end
end
EOF

293
vim/plugin/rubytest.vim Normal file
View File

@@ -0,0 +1,293 @@
" Vim plugin for running ruby tests
" Last Change: May 13 2009
" Maintainer: Jan <jan.h.xie@gmail.com>
" License: MIT License
if exists("rubytest_loaded")
finish
endif
let rubytest_loaded = 1
if !exists("g:rubytest_in_quickfix")
let g:rubytest_in_quickfix = 0
endif
if !exists("g:rubytest_spec_drb")
let g:rubytest_spec_drb = 0
endif
if !exists("g:rubytest_cmd_test")
let g:rubytest_cmd_test = "ruby %p"
endif
if !exists("g:rubytest_cmd_testcase")
let g:rubytest_cmd_testcase = "ruby %p -n '/%c/'"
endif
if !exists("g:rubytest_cmd_spec")
let g:rubytest_cmd_spec = "spec -f specdoc %p"
endif
if !exists("g:rubytest_cmd_example")
let g:rubytest_cmd_example = "spec -f specdoc %p -l %c"
endif
if !exists("g:rubytest_cmd_feature")
let g:rubytest_cmd_feature = "cucumber %p"
endif
if !exists("g:rubytest_cmd_story")
let g:rubytest_cmd_story = "cucumber %p -n '%c'"
endif
function s:FindCase(patterns)
let ln = a:firstline
while ln > 0
let line = getline(ln)
for pattern in keys(a:patterns)
if line =~ pattern
if s:pattern == 'spec'
return a:patterns[pattern](ln)
else
return a:patterns[pattern](line)
endif
endif
endfor
let ln -= 1
endwhile
return 'false'
endfunction
function s:EscapeBackSlash(str)
return substitute(a:str, '\', '\\\\', 'g')
endfunction
function s:RunTest()
if s:test_scope == 1
let cmd = g:rubytest_cmd_testcase
elseif s:test_scope == 2
let cmd = g:rubytest_cmd_test
end
let case = s:FindCase(s:test_case_patterns['test'])
if s:test_scope == 2 || case != 'false'
let case = substitute(case, "'\\|\"", '.', 'g')
let cmd = substitute(cmd, '%c', case, '')
let cmd = substitute(cmd, '%p', s:EscapeBackSlash(@%), '')
if @% =~ '^test'
let cmd = substitute(cmd, '^ruby ', 'ruby -Itest -rtest_helper ', '')
endif
if g:rubytest_in_quickfix > 0
let s:oldefm = &efm
let &efm = s:efm . s:efm_backtrace . ',' . s:efm_ruby . ',' . s:oldefm . ',%-G%.%#'
cex system(cmd)
cw
let &efm = s:oldefm
else
exe "!echo '" . cmd . "' && " . cmd
endif
else
echo 'No test case found.'
endif
endfunction
function s:RunSpec()
if s:test_scope == 1
let cmd = g:rubytest_cmd_example
elseif s:test_scope == 2
let cmd = g:rubytest_cmd_spec
endif
if g:rubytest_spec_drb > 0
let cmd = cmd . " --drb"
endif
let case = s:FindCase(s:test_case_patterns['spec'])
if s:test_scope == 2 || case != 'false'
let cmd = substitute(cmd, '%c', case, '')
let cmd = substitute(cmd, '%p', s:EscapeBackSlash(@%), '')
if g:rubytest_in_quickfix > 0
let s:oldefm = &efm
let &efm = s:efm . s:efm_backtrace . ',' . s:efm_ruby . ',' . s:oldefm . ',%-G%.%#'
cex system(cmd)
cw
let &efm = s:oldefm
else
exe "!echo '" . cmd . "' && " . cmd
endif
else
echo 'No spec found.'
endif
endfunction
function s:RunFeature()
let s:old_in_quickfix = g:rubytest_in_quickfix
let g:rubytest_in_quickfix = 0
if s:test_scope == 1
let cmd = g:rubytest_cmd_story
elseif s:test_scope == 2
let cmd = g:rubytest_cmd_feature
endif
let case = s:FindCase(s:test_case_patterns['feature'])
if s:test_scope == 2 || case != 'false'
let cmd = substitute(cmd, '%c', case, '')
let cmd = substitute(cmd, '%p', s:EscapeBackSlash(@%), '')
if g:rubytest_in_quickfix > 0
let s:oldefm = &efm
let &efm = s:efm . s:efm_backtrace . ',' . s:efm_ruby . ',' . s:oldefm . ',%-G%.%#'
cex system(cmd)
cw
let &efm = s:oldefm
else
exe "!echo '" . cmd . "' && " . cmd
endif
else
echo 'No story found.'
endif
let g:rubytest_in_quickfix = s:old_in_quickfix
endfunction
let s:test_patterns = {}
let s:test_patterns['test'] = function('s:RunTest')
let s:test_patterns['spec'] = function('s:RunSpec')
let s:test_patterns['\.feature$'] = function('s:RunFeature')
function s:GetTestCaseName1(str)
return split(a:str)[1]
endfunction
function s:GetTestCaseName2(str)
return "test_" . join(split(split(a:str, '"')[1]), '_')
endfunction
function s:GetTestCaseName3(str)
return split(a:str, '"')[1]
endfunction
function s:GetTestCaseName4(str)
return "test_" . join(split(split(a:str, "'")[1]), '_')
endfunction
function s:GetTestCaseName5(str)
return split(a:str, "'")[1]
endfunction
function s:GetSpecLine(str)
return a:str
endfunction
function s:GetStoryLine(str)
return join(split(split(a:str, "Scenario:")[1]))
endfunction
let s:test_case_patterns = {}
let s:test_case_patterns['test'] = {'^\s*def test':function('s:GetTestCaseName1'), '^\s*test \s*"':function('s:GetTestCaseName2'), "^\\s*test \\s*'":function('s:GetTestCaseName4'), '^\s*should \s*"':function('s:GetTestCaseName3'), "^\\s*should \\s*'":function('s:GetTestCaseName5')}
let s:test_case_patterns['spec'] = {'^\s*\(it\|example\|describe\|context\) \s*':function('s:GetSpecLine')}
let s:test_case_patterns['feature'] = {'^\s*Scenario:':function('s:GetStoryLine')}
let s:save_cpo = &cpo
set cpo&vim
if !hasmapto('<Plug>RubyTestRun')
map <unique> <Leader>rt <Plug>RubyTestRun
endif
if !hasmapto('<Plug>RubyFileRun')
map <unique> <Leader>rT <Plug>RubyFileRun
endif
function s:IsRubyTest()
for pattern in keys(s:test_patterns)
if @% =~ pattern
let s:pattern = pattern
return 1
endif
endfor
endfunction
function s:Run(scope)
if !s:IsRubyTest()
echo "This file doesn't contain ruby test."
else
" test scope define what to test
" 1: test case under cursor
" 2: all tests in file
let s:test_scope = a:scope
call s:test_patterns[s:pattern]()
endif
endfunction
noremap <unique> <script> <Plug>RubyTestRun <SID>Run
noremap <unique> <script> <Plug>RubyFileRun <SID>RunFile
noremap <SID>Run :call <SID>Run(1)<CR>
noremap <SID>RunFile :call <SID>Run(2)<CR>
let s:efm='%A%\\d%\\+)%.%#,'
" below errorformats are copied from rails.vim
" Current directory
let s:efm=s:efm . '%D(in\ %f),'
" Failure and Error headers, start a multiline message
let s:efm=s:efm
\.'%A\ %\\+%\\d%\\+)\ Failure:,'
\.'%A\ %\\+%\\d%\\+)\ Error:,'
\.'%+A'."'".'%.%#'."'".'\ FAILED,'
" Exclusions
let s:efm=s:efm
\.'%C%.%#(eval)%.%#,'
\.'%C-e:%.%#,'
\.'%C%.%#/lib/gems/%\\d.%\\d/gems/%.%#,'
\.'%C%.%#/lib/ruby/%\\d.%\\d/%.%#,'
\.'%C%.%#/vendor/rails/%.%#,'
" Specific to template errors
let s:efm=s:efm
\.'%C\ %\\+On\ line\ #%l\ of\ %f,'
\.'%CActionView::TemplateError:\ compile\ error,'
" stack backtrace is in brackets. if multiple lines, it starts on a new line.
let s:efm=s:efm
\.'%Ctest_%.%#(%.%#):%#,'
\.'%C%.%#\ [%f:%l]:,'
\.'%C\ \ \ \ [%f:%l:%.%#,'
\.'%C\ \ \ \ %f:%l:%.%#,'
\.'%C\ \ \ \ \ %f:%l:%.%#]:,'
\.'%C\ \ \ \ \ %f:%l:%.%#,'
" Catch all
let s:efm=s:efm
\.'%Z%f:%l:\ %#%m,'
\.'%Z%f:%l:,'
\.'%C%m,'
" Syntax errors in the test itself
let s:efm=s:efm
\.'%.%#.rb:%\\d%\\+:in\ `load'."'".':\ %f:%l:\ syntax\ error\\\, %m,'
\.'%.%#.rb:%\\d%\\+:in\ `load'."'".':\ %f:%l:\ %m,'
" And required files
let s:efm=s:efm
\.'%.%#:in\ `require'."'".':in\ `require'."'".':\ %f:%l:\ syntax\ error\\\, %m,'
\.'%.%#:in\ `require'."'".':in\ `require'."'".':\ %f:%l:\ %m,'
" Exclusions
let s:efm=s:efm
\.'%-G%.%#/lib/gems/%\\d.%\\d/gems/%.%#,'
\.'%-G%.%#/lib/ruby/%\\d.%\\d/%.%#,'
\.'%-G%.%#/vendor/rails/%.%#,'
\.'%-G%.%#%\\d%\\d:%\\d%\\d:%\\d%\\d%.%#,'
" Final catch all for one line errors
let s:efm=s:efm
\.'%-G%\\s%#from\ %.%#,'
\.'%f:%l:\ %#%m,'
let s:efm_backtrace='%D(in\ %f),'
\.'%\\s%#from\ %f:%l:%m,'
\.'%\\s%#from\ %f:%l:,'
\.'%\\s#{RAILS_ROOT}/%f:%l:\ %#%m,'
\.'%\\s%#[%f:%l:\ %#%m,'
\.'%\\s%#%f:%l:\ %#%m,'
\.'%\\s%#%f:%l:,'
\.'%m\ [%f:%l]:'
let s:efm_ruby='\%-E-e:%.%#,\%+E%f:%l:\ parse\ error,%W%f:%l:\ warning:\ %m,%E%f:%l:in\ %*[^:]:\ %m,%E%f:%l:\ %m,%-C%\tfrom\ %f:%l:in\ %.%#,%-Z%\tfrom\ %f:%l,%-Z%p^'
let &cpo = s:save_cpo

226
vim/plugin/snipMate.vim Normal file
View File

@@ -0,0 +1,226 @@
" File: snipMate.vim
" Author: Michael Sanders
" Version: 0.82
" Description: snipMate.vim implements some of TextMate's snippets features in
" Vim. A snippet is a piece of often-typed text that you can
" insert into your document using a trigger word followed by a "<tab>".
"
" For more help see snipMate.txt; you can do this by using:
" :helptags ~/.vim/doc
" :h snipMate.txt
if exists('loaded_snips') || &cp || version < 700
finish
endif
let loaded_snips = 1
if !exists('snips_author') | let snips_author = 'Me' | endif
au BufRead,BufNewFile *.snippets\= set ft=snippet
au FileType snippet setl noet fdm=indent
let s:snippets = {} | let s:multi_snips = {}
if !exists('snippets_dir')
let snippets_dir = substitute(globpath(&rtp, 'snippets/'), "\n", ',', 'g')
endif
fun! MakeSnip(scope, trigger, content, ...)
let multisnip = a:0 && a:1 != ''
let var = multisnip ? 's:multi_snips' : 's:snippets'
if !has_key({var}, a:scope) | let {var}[a:scope] = {} | endif
if !has_key({var}[a:scope], a:trigger)
let {var}[a:scope][a:trigger] = multisnip ? [[a:1, a:content]] : a:content
elseif multisnip | let {var}[a:scope][a:trigger] += [[a:1, a:content]]
else
"echom 'Warning in snipMate.vim: Snippet '.a:trigger.' is already defined.'
" \ .' See :h multi_snip for help on snippets with multiple matches.'
endif
endf
fun! ExtractSnips(dir, ft)
for path in split(globpath(a:dir, '*'), "\n")
if isdirectory(path)
let pathname = fnamemodify(path, ':t')
for snipFile in split(globpath(path, '*.snippet'), "\n")
call s:ProcessFile(snipFile, a:ft, pathname)
endfor
elseif fnamemodify(path, ':e') == 'snippet'
call s:ProcessFile(path, a:ft)
endif
endfor
endf
" Processes a single-snippet file; optionally add the name of the parent
" directory for a snippet with multiple matches.
fun s:ProcessFile(file, ft, ...)
let keyword = fnamemodify(a:file, ':t:r')
if keyword == '' | return | endif
try
let text = join(readfile(a:file), "\n")
catch /E484/
echom "Error in snipMate.vim: couldn't read file: ".a:file
endtry
return a:0 ? MakeSnip(a:ft, a:1, text, keyword)
\ : MakeSnip(a:ft, keyword, text)
endf
fun! ExtractSnipsFile(file, ft)
if !filereadable(a:file) | return | endif
let text = readfile(a:file)
let inSnip = 0
for line in text + ["\n"]
if inSnip && (line[0] == "\t" || line == '')
let content .= strpart(line, 1)."\n"
continue
elseif inSnip
call MakeSnip(a:ft, trigger, content[:-2], name)
let inSnip = 0
endif
if line[:6] == 'snippet'
let inSnip = 1
let trigger = strpart(line, 8)
let name = ''
let space = stridx(trigger, ' ') + 1
if space " Process multi snip
let name = strpart(trigger, space)
let trigger = strpart(trigger, 0, space - 1)
endif
let content = ''
endif
endfor
endf
fun! ResetSnippets()
let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {}
endf
let g:did_ft = {}
fun! GetSnippets(dir, filetypes)
for ft in split(a:filetypes, '\.')
if has_key(g:did_ft, ft) | continue | endif
call s:DefineSnips(a:dir, ft, ft)
if ft == 'objc' || ft == 'cpp' || ft == 'cs'
call s:DefineSnips(a:dir, 'c', ft)
elseif ft == 'xhtml'
call s:DefineSnips(a:dir, 'html', 'xhtml')
endif
let g:did_ft[ft] = 1
endfor
endf
" Define "aliasft" snippets for the filetype "realft".
fun s:DefineSnips(dir, aliasft, realft)
for path in split(globpath(a:dir, a:aliasft.'/')."\n".
\ globpath(a:dir, a:aliasft.'-*/'), "\n")
call ExtractSnips(path, a:realft)
endfor
for path in split(globpath(a:dir, a:aliasft.'.snippets')."\n".
\ globpath(a:dir, a:aliasft.'-*.snippets'), "\n")
call ExtractSnipsFile(path, a:realft)
endfor
endf
fun! TriggerSnippet()
if exists('g:SuperTabMappingForward')
if g:SuperTabMappingForward == "<tab>"
let SuperTabKey = "\<c-n>"
elseif g:SuperTabMappingBackward == "<tab>"
let SuperTabKey = "\<c-p>"
endif
endif
if pumvisible() " Update snippet if completion is used, or deal with supertab
if exists('SuperTabKey')
call feedkeys(SuperTabKey) | return ''
endif
call feedkeys("\<esc>a", 'n') " Close completion menu
call feedkeys("\<tab>") | return ''
endif
if exists('g:snipPos') | return snipMate#jumpTabStop() | endif
let word = matchstr(getline('.'), '\S\+\%'.col('.').'c')
for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
let [trigger, snippet] = s:GetSnippet(word, scope)
" If word is a trigger for a snippet, delete the trigger & expand
" the snippet.
if snippet != ''
let col = col('.') - len(trigger)
sil exe 's/\V'.escape(trigger, '/').'\%#//'
return snipMate#expandSnip(snippet, col)
endif
endfor
if exists('SuperTabKey')
call feedkeys(SuperTabKey)
return ''
endif
return "\<tab>"
endf
" Check if word under cursor is snippet trigger; if it isn't, try checking if
" the text after non-word characters is (e.g. check for "foo" in "bar.foo")
fun s:GetSnippet(word, scope)
let word = a:word | let snippet = ''
while snippet == ''
if exists('s:snippets["'.a:scope.'"]["'.escape(word, '\"').'"]')
let snippet = s:snippets[a:scope][word]
elseif exists('s:multi_snips["'.a:scope.'"]["'.escape(word, '\"').'"]')
let snippet = s:ChooseSnippet(a:scope, word)
if snippet == '' | break | endif
else
if match(word, '\W') == -1 | break | endif
let word = substitute(word, '.\{-}\W', '', '')
endif
endw
return [word, snippet]
endf
fun s:ChooseSnippet(scope, trigger)
let snippet = []
let i = 1
for snip in s:multi_snips[a:scope][a:trigger]
let snippet += [i.'. '.snip[0]]
let i += 1
endfor
if i == 2 | return s:multi_snips[a:scope][a:trigger][0][1] | endif
let num = inputlist(snippet) - 1
return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1]
endf
fun! ShowAvailableSnips()
let line = getline('.')
let col = col('.')
let word = matchstr(getline('.'), '\S\+\%'.col.'c')
let words = [word]
if stridx(word, '.')
let words += split(word, '\.', 1)
endif
let matchlen = 0
let matches = []
for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
let triggers = has_key(s:snippets, scope) ? keys(s:snippets[scope]) : []
if has_key(s:multi_snips, scope)
let triggers += keys(s:multi_snips[scope])
endif
for trigger in triggers
for word in words
if word == ''
let matches += [trigger] " Show all matches if word is empty
elseif trigger =~ '^'.word
let matches += [trigger]
let len = len(word)
if len > matchlen | let matchlen = len | endif
endif
endfor
endfor
endfor
" This is to avoid a bug with Vim when using complete(col - matchlen, matches)
" (Issue#46 on the Google Code snipMate issue tracker).
call setline(line('.'), substitute(line, repeat('.', matchlen).'\%'.col.'c', '', ''))
call complete(col, matches)
return ''
endf
" vim:noet:sw=4:ts=4:ft=vim

630
vim/plugin/surround.vim Normal file
View File

@@ -0,0 +1,630 @@
" surround.vim - Surroundings
" Author: Tim Pope <vimNOSPAM@tpope.info>
" GetLatestVimScripts: 1697 1 :AutoInstall: surround.vim
" $Id: surround.vim,v 1.33 2008-02-04 03:50:46 tpope Exp $
"
" See surround.txt for help. This can be accessed by doing
"
" :helptags ~/.vim/doc
" :help surround
"
" Licensed under the same terms as Vim itself.
" ============================================================================
" Exit quickly when:
" - this plugin was already loaded or disabled
" - when 'compatible' is set
if (exists("g:loaded_surround") && g:loaded_surround) || &cp
finish
endif
let g:loaded_surround = 1
let s:cpo_save = &cpo
set cpo&vim
" Input functions {{{1
function! s:getchar()
let c = getchar()
if c =~ '^\d\+$'
let c = nr2char(c)
endif
return c
endfunction
function! s:inputtarget()
let c = s:getchar()
while c =~ '^\d\+$'
let c = c . s:getchar()
endwhile
if c == " "
let c = c . s:getchar()
endif
if c =~ "\<Esc>\|\<C-C>\|\0"
return ""
else
return c
endif
endfunction
function! s:inputreplacement()
"echo '-- SURROUND --'
let c = s:getchar()
if c == " "
let c = c . s:getchar()
endif
if c =~ "\<Esc>" || c =~ "\<C-C>"
return ""
else
return c
endif
endfunction
function! s:beep()
exe "norm! \<Esc>"
return ""
endfunction
function! s:redraw()
redraw
return ""
endfunction
" }}}1
" Wrapping functions {{{1
function! s:extractbefore(str)
if a:str =~ '\r'
return matchstr(a:str,'.*\ze\r')
else
return matchstr(a:str,'.*\ze\n')
endif
endfunction
function! s:extractafter(str)
if a:str =~ '\r'
return matchstr(a:str,'\r\zs.*')
else
return matchstr(a:str,'\n\zs.*')
endif
endfunction
function! s:repeat(str,count)
let cnt = a:count
let str = ""
while cnt > 0
let str = str . a:str
let cnt = cnt - 1
endwhile
return str
endfunction
function! s:fixindent(str,spc)
let str = substitute(a:str,'\t',s:repeat(' ',&sw),'g')
let spc = substitute(a:spc,'\t',s:repeat(' ',&sw),'g')
let str = substitute(str,'\(\n\|\%^\).\@=','\1'.spc,'g')
if ! &et
let str = substitute(str,'\s\{'.&ts.'\}',"\t",'g')
endif
return str
endfunction
function! s:process(string)
let i = 0
while i < 7
let i = i + 1
let repl_{i} = ''
let m = matchstr(a:string,nr2char(i).'.\{-\}\ze'.nr2char(i))
if m != ''
let m = substitute(strpart(m,1),'\r.*','','')
let repl_{i} = input(substitute(m,':\s*$','','').': ')
endif
endwhile
let s = ""
let i = 0
while i < strlen(a:string)
let char = strpart(a:string,i,1)
if char2nr(char) < 8
let next = stridx(a:string,char,i+1)
if next == -1
let s = s . char
else
let insertion = repl_{char2nr(char)}
let subs = strpart(a:string,i+1,next-i-1)
let subs = matchstr(subs,'\r.*')
while subs =~ '^\r.*\r'
let sub = matchstr(subs,"^\r\\zs[^\r]*\r[^\r]*")
let subs = strpart(subs,strlen(sub)+1)
let r = stridx(sub,"\r")
let insertion = substitute(insertion,strpart(sub,0,r),strpart(sub,r+1),'')
endwhile
let s = s . insertion
let i = next
endif
else
let s = s . char
endif
let i = i + 1
endwhile
return s
endfunction
function! s:wrap(string,char,type,...)
let keeper = a:string
let newchar = a:char
let type = a:type
let linemode = type ==# 'V' ? 1 : 0
let special = a:0 ? a:1 : 0
let before = ""
let after = ""
if type == "V"
let initspaces = matchstr(keeper,'\%^\s*')
else
let initspaces = matchstr(getline('.'),'\%^\s*')
endif
" Duplicate b's are just placeholders (removed)
let pairs = "b()B{}r[]a<>"
let extraspace = ""
if newchar =~ '^ '
let newchar = strpart(newchar,1)
let extraspace = ' '
endif
let idx = stridx(pairs,newchar)
if newchar == ' '
let before = ''
let after = ''
elseif exists("b:surround_".char2nr(newchar))
let all = s:process(b:surround_{char2nr(newchar)})
let before = s:extractbefore(all)
let after = s:extractafter(all)
elseif exists("g:surround_".char2nr(newchar))
let all = s:process(g:surround_{char2nr(newchar)})
let before = s:extractbefore(all)
let after = s:extractafter(all)
elseif newchar ==# "p"
let before = "\n"
let after = "\n\n"
elseif newchar =~# "[tT\<C-T><,]"
let dounmapp = 0
let dounmapb = 0
if !maparg(">","c")
let dounmapb= 1
" Hide from AsNeeded
exe "cn"."oremap > <CR>"
exe "cn"."oremap % %<C-V>"
"cm ap > <C-R>=getcmdline() =~ '^[^%?].*[%?]$' ? "\026\076" : "\026\076\015"<CR>
endif
let default = ""
if !maparg("%","c")
" This is to help when typing things like
" <a href="/images/<%= @image.filename %>">
" The downside is it breaks backspace, so lets disable it for now
"let dounmapp= 1
"exe "cn"."oremap % %<C-V>"
endif
if newchar ==# "T"
if !exists("s:lastdel")
let s:lastdel = ""
endif
let default = matchstr(s:lastdel,'<\zs.\{-\}\ze>')
endif
let tag = input("<",default)
echo "<".substitute(tag,'>*$','>','')
"if dounmapr
"silent! cunmap <CR>
"endif
if dounmapb
silent! cunmap >
endif
if dounmapp
silent! cunmap %
endif
if tag != ""
let tag = substitute(tag,'>*$','','')
let before = '<'.tag.'>'
if tag =~ '/$'
let after = ''
else
let after = '</'.substitute(tag,' .*','','').'>'
endif
if newchar == "\<C-T>" || newchar == ","
if type ==# "v" || type ==# "V"
let before = before . "\n\t"
endif
if type ==# "v"
let after = "\n". after
endif
endif
endif
elseif newchar ==# 'l' || newchar == '\'
" LaTeX
let env = input('\begin{')
let env = '{' . env
let env = env . s:closematch(env)
echo '\begin'.env
if env != ""
let before = '\begin'.env
let after = '\end'.matchstr(env,'[^}]*').'}'
endif
"if type ==# 'v' || type ==# 'V'
"let before = before ."\n\t"
"endif
"if type ==# 'v'
"let after = "\n".initspaces.after
"endif
elseif newchar ==# 'f' || newchar ==# 'F'
let fnc = input('function: ')
if fnc != ""
let before = substitute(fnc,'($','','').'('
let after = ')'
if newchar ==# 'F'
let before = before . ' '
let after = ' ' . after
endif
endif
elseif idx >= 0
let spc = (idx % 3) == 1 ? " " : ""
let idx = idx / 3 * 3
let before = strpart(pairs,idx+1,1) . spc
let after = spc . strpart(pairs,idx+2,1)
elseif newchar == "\<C-[>" || newchar == "\<C-]>"
let before = "{\n\t"
let after = "\n}"
elseif newchar !~ '\a'
let before = newchar
let after = newchar
else
let before = ''
let after = ''
endif
"let before = substitute(before,'\n','\n'.initspaces,'g')
let after = substitute(after ,'\n','\n'.initspaces,'g')
"let after = substitute(after,"\n\\s*\<C-U>\\s*",'\n','g')
if type ==# 'V' || (special && type ==# "v")
let before = substitute(before,' \+$','','')
let after = substitute(after ,'^ \+','','')
if after !~ '^\n'
let after = initspaces.after
endif
if keeper !~ '\n$' && after !~ '^\n'
let keeper = keeper . "\n"
elseif keeper =~ '\n$' && after =~ '^\n'
let after = strpart(after,1)
endif
if before !~ '\n\s*$'
let before = before . "\n"
if special
let before = before . "\t"
endif
endif
endif
if type ==# 'V'
let before = initspaces.before
endif
if before =~ '\n\s*\%$'
if type ==# 'v'
let keeper = initspaces.keeper
endif
let padding = matchstr(before,'\n\zs\s\+\%$')
let before = substitute(before,'\n\s\+\%$','\n','')
let keeper = s:fixindent(keeper,padding)
endif
if type ==# 'V'
let keeper = before.keeper.after
elseif type =~ "^\<C-V>"
" Really we should be iterating over the buffer
let repl = substitute(before,'[\\~]','\\&','g').'\1'.substitute(after,'[\\~]','\\&','g')
let repl = substitute(repl,'\n',' ','g')
let keeper = substitute(keeper."\n",'\(.\{-\}\)\('.(special ? '\s\{-\}' : '').'\n\)',repl.'\n','g')
let keeper = substitute(keeper,'\n\%$','','')
else
let keeper = before.extraspace.keeper.extraspace.after
endif
return keeper
endfunction
function! s:wrapreg(reg,char,...)
let orig = getreg(a:reg)
let type = substitute(getregtype(a:reg),'\d\+$','','')
let special = a:0 ? a:1 : 0
let new = s:wrap(orig,a:char,type,special)
call setreg(a:reg,new,type)
endfunction
" }}}1
function! s:insert(...) " {{{1
" Optional argument causes the result to appear on 3 lines, not 1
"call inputsave()
let linemode = a:0 ? a:1 : 0
let char = s:inputreplacement()
while char == "\<CR>" || char == "\<C-S>"
" TODO: use total count for additional blank lines
let linemode = linemode + 1
let char = s:inputreplacement()
endwhile
"call inputrestore()
if char == ""
return ""
endif
"call inputsave()
let cb_save = &clipboard
let reg_save = @@
call setreg('"',"\r",'v')
call s:wrapreg('"',char,linemode)
" If line mode is used and the surrounding consists solely of a suffix,
" remove the initial newline. This fits a use case of mine but is a
" little inconsistent. Is there anyone that would prefer the simpler
" behavior of just inserting the newline?
if linemode && match(getreg('"'),'^\n\s*\zs.*') == 0
call setreg('"',matchstr(getreg('"'),'^\n\s*\zs.*'),getregtype('"'))
endif
" This can be used to append a placeholder to the end
if exists("g:surround_insert_tail")
call setreg('"',g:surround_insert_tail,"a".getregtype('"'))
endif
"if linemode
"call setreg('"',substitute(getreg('"'),'^\s\+','',''),'c')
"endif
if col('.') >= col('$')
norm! ""p
else
norm! ""P
endif
if linemode
call s:reindent()
endif
norm! `]
call search('\r','bW')
let @@ = reg_save
let &clipboard = cb_save
return "\<Del>"
endfunction " }}}1
function! s:reindent() " {{{1
if exists("b:surround_indent") ? b:surround_indent : (exists("g:surround_indent") && g:surround_indent)
silent norm! '[=']
endif
endfunction " }}}1
function! s:dosurround(...) " {{{1
let scount = v:count1
let char = (a:0 ? a:1 : s:inputtarget())
let spc = ""
if char =~ '^\d\+'
let scount = scount * matchstr(char,'^\d\+')
let char = substitute(char,'^\d\+','','')
endif
if char =~ '^ '
let char = strpart(char,1)
let spc = 1
endif
if char == 'a'
let char = '>'
endif
if char == 'r'
let char = ']'
endif
let newchar = ""
if a:0 > 1
let newchar = a:2
if newchar == "\<Esc>" || newchar == "\<C-C>" || newchar == ""
return s:beep()
endif
endif
let cb_save = &clipboard
set clipboard-=unnamed
let append = ""
let original = getreg('"')
let otype = getregtype('"')
call setreg('"',"")
let strcount = (scount == 1 ? "" : scount)
if char == '/'
exe 'norm '.strcount.'[/d'.strcount.']/'
else
exe 'norm d'.strcount.'i'.char
" One character backwards
if getreg('"') != ""
call search('.','bW')
endif
endif
let keeper = getreg('"')
let okeeper = keeper " for reindent below
if keeper == ""
call setreg('"',original,otype)
let &clipboard = cb_save
return ""
endif
let oldline = getline('.')
let oldlnum = line('.')
if char ==# "p"
call setreg('"','','V')
elseif char ==# "s" || char ==# "w" || char ==# "W"
" Do nothing
call setreg('"','')
elseif char =~ "[\"'`]"
exe "norm! a \<Esc>d2i".char
call setreg('"',substitute(getreg('"'),' ','',''))
elseif char == '/'
norm! "_x
call setreg('"','/**/',"c")
let keeper = substitute(substitute(keeper,'^/\*\s\=','',''),'\s\=\*$','','')
else
exe "norm da".char
endif
let removed = getreg('"')
let rem2 = substitute(removed,'\n.*','','')
let oldhead = strpart(oldline,0,strlen(oldline)-strlen(rem2))
let oldtail = strpart(oldline, strlen(oldline)-strlen(rem2))
let regtype = getregtype('"')
if char =~# '[\[({<T]' || spc
let keeper = substitute(keeper,'^\s\+','','')
let keeper = substitute(keeper,'\s\+$','','')
endif
if col("']") == col("$") && col('.') + 1 == col('$')
if oldhead =~# '^\s*$' && a:0 < 2
let keeper = substitute(keeper,'\%^\n'.oldhead.'\(\s*.\{-\}\)\n\s*\%$','\1','')
endif
let pcmd = "p"
else
let pcmd = "P"
endif
if line('.') < oldlnum && regtype ==# "V"
let pcmd = "p"
endif
call setreg('"',keeper,regtype)
if newchar != ""
call s:wrapreg('"',newchar)
endif
silent exe 'norm! ""'.pcmd.'`['
if removed =~ '\n' || okeeper =~ '\n' || getreg('"') =~ '\n'
call s:reindent()
endif
if getline('.') =~ '^\s\+$' && keeper =~ '^\s*\n'
silent norm! cc
endif
call setreg('"',removed,regtype)
let s:lastdel = removed
let &clipboard = cb_save
if newchar == ""
silent! call repeat#set("\<Plug>Dsurround".char,scount)
else
silent! call repeat#set("\<Plug>Csurround".char.newchar,scount)
endif
endfunction " }}}1
function! s:changesurround() " {{{1
let a = s:inputtarget()
if a == ""
return s:beep()
endif
let b = s:inputreplacement()
if b == ""
return s:beep()
endif
call s:dosurround(a,b)
endfunction " }}}1
function! s:opfunc(type,...) " {{{1
let char = s:inputreplacement()
if char == ""
return s:beep()
endif
let reg = '"'
let sel_save = &selection
let &selection = "inclusive"
let cb_save = &clipboard
set clipboard-=unnamed
let reg_save = getreg(reg)
let reg_type = getregtype(reg)
"call setreg(reg,"\n","c")
let type = a:type
if a:type == "char"
silent exe 'norm! v`[o`]"'.reg.'y'
let type = 'v'
elseif a:type == "line"
silent exe 'norm! `[V`]"'.reg.'y'
let type = 'V'
elseif a:type ==# "v" || a:type ==# "V" || a:type ==# "\<C-V>"
silent exe 'norm! gv"'.reg.'y'
elseif a:type =~ '^\d\+$'
let type = 'v'
silent exe 'norm! ^v'.a:type.'$h"'.reg.'y'
if mode() == 'v'
norm! v
return s:beep()
endif
else
let &selection = sel_save
let &clipboard = cb_save
return s:beep()
endif
let keeper = getreg(reg)
if type == "v" && a:type != "v"
let append = matchstr(keeper,'\_s\@<!\s*$')
let keeper = substitute(keeper,'\_s\@<!\s*$','','')
endif
call setreg(reg,keeper,type)
call s:wrapreg(reg,char,a:0)
if type == "v" && a:type != "v" && append != ""
call setreg(reg,append,"ac")
endif
silent exe 'norm! gv'.(reg == '"' ? '' : '"' . reg).'p`['
if type == 'V' || (getreg(reg) =~ '\n' && type == 'v')
call s:reindent()
endif
call setreg(reg,reg_save,reg_type)
let &selection = sel_save
let &clipboard = cb_save
if a:type =~ '^\d\+$'
silent! call repeat#set("\<Plug>Y".(a:0 ? "S" : "s")."surround".char,a:type)
endif
endfunction
function! s:opfunc2(arg)
call s:opfunc(a:arg,1)
endfunction " }}}1
function! s:closematch(str) " {{{1
" Close an open (, {, [, or < on the command line.
let tail = matchstr(a:str,'.[^\[\](){}<>]*$')
if tail =~ '^\[.\+'
return "]"
elseif tail =~ '^(.\+'
return ")"
elseif tail =~ '^{.\+'
return "}"
elseif tail =~ '^<.+'
return ">"
else
return ""
endif
endfunction " }}}1
nnoremap <silent> <Plug>Dsurround :<C-U>call <SID>dosurround(<SID>inputtarget())<CR>
nnoremap <silent> <Plug>Csurround :<C-U>call <SID>changesurround()<CR>
nnoremap <silent> <Plug>Yssurround :<C-U>call <SID>opfunc(v:count1)<CR>
nnoremap <silent> <Plug>YSsurround :<C-U>call <SID>opfunc2(v:count1)<CR>
" <C-U> discards the numerical argument but there's not much we can do with it
nnoremap <silent> <Plug>Ysurround :<C-U>set opfunc=<SID>opfunc<CR>g@
nnoremap <silent> <Plug>YSurround :<C-U>set opfunc=<SID>opfunc2<CR>g@
vnoremap <silent> <Plug>Vsurround :<C-U>call <SID>opfunc(visualmode())<CR>
vnoremap <silent> <Plug>VSurround :<C-U>call <SID>opfunc2(visualmode())<CR>
inoremap <silent> <Plug>Isurround <C-R>=<SID>insert()<CR>
inoremap <silent> <Plug>ISurround <C-R>=<SID>insert(1)<CR>
if !exists("g:surround_no_mappings") || ! g:surround_no_mappings
nmap ds <Plug>Dsurround
nmap cs <Plug>Csurround
nmap ys <Plug>Ysurround
nmap yS <Plug>YSurround
nmap yss <Plug>Yssurround
nmap ySs <Plug>YSsurround
nmap ySS <Plug>YSsurround
if !hasmapto("<Plug>Vsurround","v")
if exists(":xmap")
xmap s <Plug>Vsurround
else
vmap s <Plug>Vsurround
endif
endif
if !hasmapto("<Plug>VSurround","v")
if exists(":xmap")
xmap S <Plug>VSurround
else
vmap S <Plug>VSurround
endif
endif
if !hasmapto("<Plug>Isurround","i") && "" == mapcheck("<C-S>","i")
imap <C-S> <Plug>Isurround
endif
imap <C-G>s <Plug>Isurround
imap <C-G>S <Plug>ISurround
"Implemented internally instead
"imap <C-S><C-S> <Plug>ISurround
endif
let &cpo = s:cpo_save
" vim:set ft=vim sw=4 sts=4 et:

333
vim/plugin/syntastic.vim Executable file
View File

@@ -0,0 +1,333 @@
"============================================================================
"File: syntastic.vim
"Description: vim plugin for on the fly syntax checking
"Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
"Version: 1.2.0
"Last Change: 28 Oct, 2010
"License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
"============================================================================
if exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_plugin = 1
let s:running_windows = has("win16") || has("win32") || has("win64")
if !s:running_windows
let s:uname = system('uname')
endif
if !exists("g:syntastic_enable_signs") || !has('signs')
let g:syntastic_enable_signs = 0
endif
if !exists("g:syntastic_enable_balloons") || !has('balloon_eval')
let g:syntastic_enable_balloons = 0
endif
if !exists("g:syntastic_auto_loc_list")
let g:syntastic_auto_loc_list = 0
endif
if !exists("g:syntastic_auto_jump")
let syntastic_auto_jump=0
endif
if !exists("g:syntastic_quiet_warnings")
let g:syntastic_quiet_warnings = 0
endif
if !exists("g:syntastic_disabled_filetypes")
let g:syntastic_disabled_filetypes = []
endif
if !exists("g:syntastic_stl_format")
let g:syntastic_stl_format = '[Syntax: line:%F (%t)]'
endif
"refresh and redraw all the error info for this buf when saving or reading
autocmd bufreadpost,bufwritepost * call s:UpdateErrors()
function! s:UpdateErrors()
if &buftype == 'quickfix'
return
endif
call s:CacheErrors()
if g:syntastic_enable_balloons && has('balloon_eval')
let b:syntastic_balloons = {}
for i in b:syntastic_loclist
let b:syntastic_balloons[i['lnum']] = i['text']
endfor
set beval bexpr=syntastic#ErrorBalloonExpr()
endif
if g:syntastic_enable_signs
call s:RefreshSigns()
endif
if s:BufHasErrorsOrWarningsToDisplay()
call setloclist(0, b:syntastic_loclist)
if g:syntastic_auto_jump
silent!ll
endif
elseif g:syntastic_auto_loc_list == 2
lclose
endif
if g:syntastic_auto_loc_list == 1
if s:BufHasErrorsOrWarningsToDisplay()
call s:ShowLocList()
else
"TODO: this will close the loc list window if one was opened by
"something other than syntastic
lclose
endif
endif
endfunction
"detect and cache all syntax errors in this buffer
"
"depends on a function called SyntaxCheckers_{&ft}_GetLocList() existing
"elsewhere
function! s:CacheErrors()
let b:syntastic_loclist = []
if filereadable(expand("%"))
for ft in split(&ft, '\.')
if s:Checkable(ft)
let b:syntastic_loclist = extend(b:syntastic_loclist, SyntaxCheckers_{ft}_GetLocList())
endif
endfor
endif
endfunction
"return true if there are cached errors/warnings for this buf
function! s:BufHasErrorsOrWarnings()
return exists("b:syntastic_loclist") && !empty(b:syntastic_loclist)
endfunction
"return true if there are cached errors for this buf
function! s:BufHasErrors()
return len(s:ErrorsForType('E')) > 0
endfunction
function! s:BufHasErrorsOrWarningsToDisplay()
return s:BufHasErrors() || (!g:syntastic_quiet_warnings && s:BufHasErrorsOrWarnings())
endfunction
function! s:ErrorsForType(type)
if !exists("b:syntastic_loclist")
return []
endif
return filter(copy(b:syntastic_loclist), 'v:val["type"] ==? "' . a:type . '"')
endfunction
function s:Errors()
return extend(s:ErrorsForType("E"), s:ErrorsForType(''))
endfunction
function s:Warnings()
return s:ErrorsForType("W")
endfunction
if g:syntastic_enable_signs
"use >> to display syntax errors in the sign column
sign define SyntasticError text=>> texthl=error
sign define SyntasticWarning text=>> texthl=todo
endif
"start counting sign ids at 5000, start here to hopefully avoid conflicting
"with any other code that places signs (not sure if this precaution is
"actually needed)
let s:first_sign_id = 5000
let s:next_sign_id = s:first_sign_id
"place signs by all syntax errs in the buffer
function s:SignErrors()
if s:BufHasErrorsOrWarningsToDisplay()
for i in b:syntastic_loclist
if i['bufnr'] != bufnr("")
continue
endif
let sign_type = 'SyntasticError'
if i['type'] == 'W'
let sign_type = 'SyntasticWarning'
endif
exec "sign place ". s:next_sign_id ." line=". i['lnum'] ." name=". sign_type ." file=". expand("%:p")
call add(s:BufSignIds(), s:next_sign_id)
let s:next_sign_id += 1
endfor
endif
endfunction
"remove the signs with the given ids from this buffer
function! s:RemoveSigns(ids)
for i in a:ids
exec "sign unplace " . i
call remove(s:BufSignIds(), index(s:BufSignIds(), i))
endfor
endfunction
"get all the ids of the SyntaxError signs in the buffer
function! s:BufSignIds()
if !exists("b:syntastic_sign_ids")
let b:syntastic_sign_ids = []
endif
return b:syntastic_sign_ids
endfunction
"update the error signs
function! s:RefreshSigns()
let old_signs = copy(s:BufSignIds())
call s:SignErrors()
call s:RemoveSigns(old_signs)
let s:first_sign_id = s:next_sign_id
endfunction
"display the cached errors for this buf in the location list
function! s:ShowLocList()
if exists("b:syntastic_loclist")
let num = winnr()
lopen
if num != winnr()
wincmd p
endif
endif
endfunction
command Errors call s:ShowLocList()
"return a string representing the state of buffer according to
"g:syntastic_stl_format
"
"return '' if no errors are cached for the buffer
function! SyntasticStatuslineFlag()
if s:BufHasErrorsOrWarningsToDisplay()
let errors = s:Errors()
let warnings = s:Warnings()
let output = g:syntastic_stl_format
"hide stuff wrapped in %E(...) unless there are errors
let output = substitute(output, '\C%E{\([^}]*\)}', len(errors) ? '\1' : '' , 'g')
"hide stuff wrapped in %W(...) unless there are warnings
let output = substitute(output, '\C%W{\([^}]*\)}', len(warnings) ? '\1' : '' , 'g')
"hide stuff wrapped in %B(...) unless there are both errors and warnings
let output = substitute(output, '\C%B{\([^}]*\)}', (len(warnings) && len(errors)) ? '\1' : '' , 'g')
"sub in the total errors/warnings/both
let output = substitute(output, '\C%w', len(warnings), 'g')
let output = substitute(output, '\C%e', len(errors), 'g')
let output = substitute(output, '\C%t', len(b:syntastic_loclist), 'g')
"first error/warning line num
let output = substitute(output, '\C%F', b:syntastic_loclist[0]['lnum'], 'g')
"first error line num
let output = substitute(output, '\C%fe', len(errors) ? errors[0]['lnum'] : '', 'g')
"first warning line num
let output = substitute(output, '\C%fw', len(warnings) ? warnings[0]['lnum'] : '', 'g')
return output
else
return ''
endif
endfunction
"A wrapper for the :lmake command. Sets up the make environment according to
"the options given, runs make, resets the environment, returns the location
"list
"
"a:options can contain the following keys:
" 'makeprg'
" 'errorformat'
"
"The corresponding options are set for the duration of the function call. They
"are set with :let, so dont escape spaces.
function! SyntasticMake(options)
let old_loclist = getloclist(0)
let old_makeprg = &makeprg
let old_shellpipe = &shellpipe
let old_shell = &shell
let old_errorformat = &errorformat
if !s:running_windows && (s:uname !~ "FreeBSD")
"this is a hack to stop the screen needing to be ':redraw'n when
"when :lmake is run. Otherwise the screen flickers annoyingly
let &shellpipe='&>'
let &shell = '/bin/bash'
endif
if has_key(a:options, 'makeprg')
let &makeprg = a:options['makeprg']
endif
if has_key(a:options, 'errorformat')
let &errorformat = a:options['errorformat']
endif
silent lmake!
let errors = getloclist(0)
call setloclist(0, old_loclist)
let &makeprg = old_makeprg
let &errorformat = old_errorformat
let &shellpipe=old_shellpipe
let &shell=old_shell
return errors
endfunction
function! s:Checkable(ft)
if !exists("g:loaded_" . a:ft . "_syntax_checker")
exec "runtime syntax_checkers/" . a:ft . ".vim"
endif
return exists("*SyntaxCheckers_". a:ft ."_GetLocList") &&
\ index(g:syntastic_disabled_filetypes, a:ft) == -1
endfunction
command! -nargs=? SyntasticEnable call s:Enable(<f-args>)
command! -nargs=? SyntasticDisable call s:Disable(<f-args>)
"disable syntax checking for the given filetype (defaulting to current ft)
function! s:Disable(...)
let ft = a:0 ? a:1 : &filetype
if !empty(ft) && index(g:syntastic_disabled_filetypes, ft) == -1
call add(g:syntastic_disabled_filetypes, ft)
endif
"will cause existing errors to be cleared
call s:UpdateErrors()
endfunction
"enable syntax checking for the given filetype (defaulting to current ft)
function! s:Enable(...)
let ft = a:0 ? a:1 : &filetype
let i = index(g:syntastic_disabled_filetypes, ft)
if i != -1
call remove(g:syntastic_disabled_filetypes, i)
endif
if !&modified
call s:UpdateErrors()
redraw!
else
echom "Syntasic: enabled for the '" . ft . "' filetype. :write out to update errors"
endif
endfunction
" vim: set et sts=4 sw=4:

385
vim/plugin/tComment.vim Normal file
View File

@@ -0,0 +1,385 @@
" tComment.vim -- An easily extensible & universal comment plugin
" @Author: Tom Link (micathom AT gmail com)
" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
" @Created: 27-Dez-2004.
" @Last Change: 2009-08-07.
" @Revision: 1.9.671
"
" GetLatestVimScripts: 1173 1 tComment.vim
if &cp || exists('loaded_tcomment')
finish
endif
let loaded_tcomment = 109
" If true, comment blank lines too
if !exists("g:tcommentBlankLines")
let g:tcommentBlankLines = 1
endif
if !exists("g:tcommentMapLeader1")
let g:tcommentMapLeader1 = '<c-_>'
endif
if !exists("g:tcommentMapLeader2")
let g:tcommentMapLeader2 = '<Leader>_'
endif
if !exists("g:tcommentMapLeaderOp1")
let g:tcommentMapLeaderOp1 = 'gc'
endif
if !exists("g:tcommentMapLeaderOp2")
let g:tcommentMapLeaderOp2 = 'gC'
endif
if !exists("g:tcommentOpModeExtra")
let g:tcommentOpModeExtra = ''
endif
" Guess the file type based on syntax names always or for some fileformat only
if !exists("g:tcommentGuessFileType")
let g:tcommentGuessFileType = 0
endif
" In php documents, the php part is usually marked as phpRegion. We thus
" assume that the buffers default comment style isn't php but html
if !exists("g:tcommentGuessFileType_dsl")
let g:tcommentGuessFileType_dsl = 'xml'
endif
if !exists("g:tcommentGuessFileType_php")
let g:tcommentGuessFileType_php = 'html'
endif
if !exists("g:tcommentGuessFileType_html")
let g:tcommentGuessFileType_html = 1
endif
if !exists("g:tcommentGuessFileType_tskeleton")
let g:tcommentGuessFileType_tskeleton = 1
endif
if !exists("g:tcommentGuessFileType_vim")
let g:tcommentGuessFileType_vim = 1
endif
if !exists("g:tcommentIgnoreTypes_php")
let g:tcommentIgnoreTypes_php = 'sql'
endif
if !exists('g:tcommentSyntaxMap') "{{{2
let g:tcommentSyntaxMap = {
\ 'vimMzSchemeRegion': 'scheme',
\ 'vimPerlRegion': 'perl',
\ 'vimPythonRegion': 'python',
\ 'vimRubyRegion': 'ruby',
\ 'vimTclRegion': 'tcl',
\ }
endif
" If you don't define these variables, TComment will use &commentstring
" instead. We override the default values here in order to have a blank after
" the comment marker. Block comments work only if we explicitly define the
" markup.
" The format for block comments is similar to normal commentstrings with the
" exception that the format strings for blocks can contain a second line that
" defines how "middle lines" (see :h format-comments) should be displayed.
" I personally find this style rather irritating but here is an alternative
" definition that does this left-handed bar thing
if !exists("g:tcommentBlockC")
let g:tcommentBlockC = "/*%s */\n * "
endif
if !exists("g:tcommentBlockC2")
let g:tcommentBlockC2 = "/**%s */\n * "
endif
if !exists("g:tcommentInlineC")
let g:tcommentInlineC = "/* %s */"
endif
if !exists("g:tcommentBlockXML")
let g:tcommentBlockXML = "<!--%s-->\n "
endif
if !exists("g:tcommentInlineXML")
let g:tcommentInlineXML = "<!-- %s -->"
endif
let g:tcommentFileTypesDirty = 1
" Currently this function just sets a variable
function! TCommentDefineType(name, commentstring)
if !exists('g:tcomment_'. a:name)
let g:tcomment_{a:name} = a:commentstring
endif
let g:tcommentFileTypesDirty = 1
endf
function! TCommentTypeExists(name)
return exists('g:tcomment_'. a:name)
endf
call TCommentDefineType('aap', '# %s' )
call TCommentDefineType('ada', '-- %s' )
call TCommentDefineType('apache', '# %s' )
call TCommentDefineType('autoit', '; %s' )
call TCommentDefineType('asm', '; %s' )
call TCommentDefineType('awk', '# %s' )
call TCommentDefineType('catalog', '-- %s --' )
call TCommentDefineType('catalog_block', "--%s--\n " )
call TCommentDefineType('cpp', '// %s' )
call TCommentDefineType('cpp_inline', g:tcommentInlineC )
call TCommentDefineType('cpp_block', g:tcommentBlockC )
call TCommentDefineType('css', '/* %s */' )
call TCommentDefineType('css_inline', g:tcommentInlineC )
call TCommentDefineType('css_block', g:tcommentBlockC )
call TCommentDefineType('c', '/* %s */' )
call TCommentDefineType('c_inline', g:tcommentInlineC )
call TCommentDefineType('c_block', g:tcommentBlockC )
call TCommentDefineType('cfg', '# %s' )
call TCommentDefineType('conf', '# %s' )
call TCommentDefineType('crontab', '# %s' )
call TCommentDefineType('desktop', '# %s' )
call TCommentDefineType('docbk', '<!-- %s -->' )
call TCommentDefineType('docbk_inline', g:tcommentInlineXML)
call TCommentDefineType('docbk_block', g:tcommentBlockXML )
call TCommentDefineType('dosbatch', 'rem %s' )
call TCommentDefineType('dosini', '; %s' )
call TCommentDefineType('dsl', '; %s' )
call TCommentDefineType('dylan', '// %s' )
call TCommentDefineType('eiffel', '-- %s' )
call TCommentDefineType('eruby', '<%%# %s%%>' )
call TCommentDefineType('gtkrc', '# %s' )
call TCommentDefineType('gitcommit', '# %s' )
call TCommentDefineType('haskell', '-- %s' )
call TCommentDefineType('haskell_block', "{-%s-}\n " )
call TCommentDefineType('haskell_inline', '{- %s -}' )
call TCommentDefineType('html', '<!-- %s -->' )
call TCommentDefineType('html_inline', g:tcommentInlineXML)
call TCommentDefineType('html_block', g:tcommentBlockXML )
call TCommentDefineType('io', '// %s' )
call TCommentDefineType('javaScript', '// %s' )
call TCommentDefineType('javaScript_inline', g:tcommentInlineC )
call TCommentDefineType('javaScript_block', g:tcommentBlockC )
call TCommentDefineType('javascript', '// %s' )
call TCommentDefineType('javascript_inline', g:tcommentInlineC )
call TCommentDefineType('javascript_block', g:tcommentBlockC )
call TCommentDefineType('java', '/* %s */' )
call TCommentDefineType('java_inline', g:tcommentInlineC )
call TCommentDefineType('java_block', g:tcommentBlockC )
call TCommentDefineType('java_doc_block', g:tcommentBlockC2 )
call TCommentDefineType('jproperties', '# %s' )
call TCommentDefineType('lisp', '; %s' )
call TCommentDefineType('lynx', '# %s' )
call TCommentDefineType('m4', 'dnl %s' )
call TCommentDefineType('mail', '> %s' )
call TCommentDefineType('msidl', '// %s' )
call TCommentDefineType('msidl_block', g:tcommentBlockC )
call TCommentDefineType('nroff', '.\\" %s' )
call TCommentDefineType('nsis', '# %s' )
call TCommentDefineType('objc', '/* %s */' )
call TCommentDefineType('objc_inline', g:tcommentInlineC )
call TCommentDefineType('objc_block', g:tcommentBlockC )
call TCommentDefineType('ocaml', '(* %s *)' )
call TCommentDefineType('ocaml_inline', '(* %s *)' )
call TCommentDefineType('ocaml_block', "(*%s*)\n " )
call TCommentDefineType('pascal', '(* %s *)' )
call TCommentDefineType('pascal_inline', '(* %s *)' )
call TCommentDefineType('pascal_block', "(*%s*)\n " )
call TCommentDefineType('perl', '# %s' )
call TCommentDefineType('perl_block', "=cut%s=cut" )
call TCommentDefineType('php', '// %s' )
call TCommentDefineType('php_inline', g:tcommentInlineC )
call TCommentDefineType('php_block', g:tcommentBlockC )
call TCommentDefineType('php_2_block', g:tcommentBlockC2 )
call TCommentDefineType('po', '# %s' )
call TCommentDefineType('prolog', '%% %s' )
call TCommentDefineType('rc', '// %s' )
call TCommentDefineType('readline', '# %s' )
call TCommentDefineType('ruby', '# %s' )
call TCommentDefineType('ruby_3', '### %s' )
call TCommentDefineType('ruby_block', "=begin rdoc%s=end")
call TCommentDefineType('ruby_nodoc_block', "=begin%s=end" )
call TCommentDefineType('r', '# %s' )
call TCommentDefineType('sbs', "' %s" )
call TCommentDefineType('scheme', '; %s' )
call TCommentDefineType('sed', '# %s' )
call TCommentDefineType('sgml', '<!-- %s -->' )
call TCommentDefineType('sgml_inline', g:tcommentInlineXML)
call TCommentDefineType('sgml_block', g:tcommentBlockXML )
call TCommentDefineType('sh', '# %s' )
call TCommentDefineType('sql', '-- %s' )
call TCommentDefineType('spec', '# %s' )
call TCommentDefineType('sps', '* %s.' )
call TCommentDefineType('sps_block', "* %s." )
call TCommentDefineType('spss', '* %s.' )
call TCommentDefineType('spss_block', "* %s." )
call TCommentDefineType('tcl', '# %s' )
call TCommentDefineType('tex', '%% %s' )
call TCommentDefineType('tpl', '<!-- %s -->' )
call TCommentDefineType('viki', '%% %s' )
call TCommentDefineType('viki_3', '%%%%%% %s' )
call TCommentDefineType('viki_inline', '{cmt: %s}' )
call TCommentDefineType('vim', '" %s' )
call TCommentDefineType('vim_3', '""" %s' )
call TCommentDefineType('websec', '# %s' )
call TCommentDefineType('xml', '<!-- %s -->' )
call TCommentDefineType('xml_inline', g:tcommentInlineXML)
call TCommentDefineType('xml_block', g:tcommentBlockXML )
call TCommentDefineType('xs', '// %s' )
call TCommentDefineType('xs_block', g:tcommentBlockC )
call TCommentDefineType('xslt', '<!-- %s -->' )
call TCommentDefineType('xslt_inline', g:tcommentInlineXML)
call TCommentDefineType('xslt_block', g:tcommentBlockXML )
call TCommentDefineType('yaml', '# %s' )
" :line1,line2 TCommentAs commenttype
command! -bang -complete=customlist,tcomment#FileTypes -range -nargs=+ TCommentAs
\ call tcomment#CommentAs(<line1>, <line2>, "<bang>", <f-args>)
" :line1,line2 TComment ?commentBegin ?commentEnd
command! -bang -range -nargs=* TComment keepjumps call tcomment#Comment(<line1>, <line2>, 'G', "<bang>", <f-args>)
" :line1,line2 TCommentRight ?commentBegin ?commentEnd
command! -bang -range -nargs=* TCommentRight keepjumps call tcomment#Comment(<line1>, <line2>, 'R', "<bang>", <f-args>)
" :line1,line2 TCommentBlock ?commentBegin ?commentEnd
command! -bang -range -nargs=* TCommentBlock keepjumps call tcomment#Comment(<line1>, <line2>, 'B', "<bang>", <f-args>)
" :line1,line2 TCommentInline ?commentBegin ?commentEnd
command! -bang -range -nargs=* TCommentInline keepjumps call tcomment#Comment(<line1>, <line2>, 'I', "<bang>", <f-args>)
" :line1,line2 TCommentMaybeInline ?commentBegin ?commentEnd
command! -bang -range -nargs=* TCommentMaybeInline keepjumps call tcomment#Comment(<line1>, <line2>, 'i', "<bang>", <f-args>)
if (g:tcommentMapLeader1 != '')
exec 'noremap <silent> '. g:tcommentMapLeader1 .'<c-_> :TComment<cr>'
exec 'vnoremap <silent> '. g:tcommentMapLeader1 .'<c-_> :TCommentMaybeInline<cr>'
exec 'inoremap <silent> '. g:tcommentMapLeader1 .'<c-_> <c-o>:TComment<cr>'
exec 'noremap <silent> '. g:tcommentMapLeader1 .'p m`vip:TComment<cr>``'
exec 'inoremap <silent> '. g:tcommentMapLeader1 .'p <c-o>:norm! m`vip<cr>:TComment<cr><c-o>``'
exec 'noremap '. g:tcommentMapLeader1 .'<space> :TComment '
exec 'inoremap '. g:tcommentMapLeader1 .'<space> <c-o>:TComment '
exec 'inoremap <silent> '. g:tcommentMapLeader1 .'r <c-o>:TCommentRight<cr>'
exec 'noremap <silent> '. g:tcommentMapLeader1 .'r :TCommentRight<cr>'
exec 'vnoremap <silent> '. g:tcommentMapLeader1 .'i :TCommentInline<cr>'
exec 'vnoremap <silent> '. g:tcommentMapLeader1 .'r :TCommentRight<cr>'
exec 'noremap '. g:tcommentMapLeader1 .'b :TCommentBlock<cr>'
exec 'inoremap '. g:tcommentMapLeader1 .'b <c-o>:TCommentBlock<cr>'
exec 'noremap '. g:tcommentMapLeader1 .'a :TCommentAs '
exec 'inoremap '. g:tcommentMapLeader1 .'a <c-o>:TCommentAs '
exec 'noremap '. g:tcommentMapLeader1 .'n :TCommentAs <c-r>=&ft<cr> '
exec 'inoremap '. g:tcommentMapLeader1 .'n <c-o>:TCommentAs <c-r>=&ft<cr> '
exec 'noremap '. g:tcommentMapLeader1 .'s :TCommentAs <c-r>=&ft<cr>_'
exec 'inoremap '. g:tcommentMapLeader1 .'s <c-o>:TCommentAs <c-r>=&ft<cr>_'
endif
if (g:tcommentMapLeader2 != '')
exec 'noremap <silent> '. g:tcommentMapLeader2 .'_ :TComment<cr>'
exec 'vnoremap <silent> '. g:tcommentMapLeader2 .'_ :TCommentMaybeInline<cr>'
exec 'noremap <silent> '. g:tcommentMapLeader2 .'p vip:TComment<cr>'
exec 'noremap '. g:tcommentMapLeader2 .'<space> :TComment '
exec 'vnoremap <silent> '. g:tcommentMapLeader2 .'i :TCommentInline<cr>'
exec 'noremap <silent> '. g:tcommentMapLeader2 .'r :TCommentRight<cr>'
exec 'vnoremap <silent> '. g:tcommentMapLeader2 .'r :TCommentRight<cr>'
exec 'noremap '. g:tcommentMapLeader2 .'b :TCommentBlock<cr>'
exec 'noremap '. g:tcommentMapLeader2 .'a :TCommentAs '
exec 'noremap '. g:tcommentMapLeader2 .'n :TCommentAs <c-r>=&ft<cr> '
exec 'noremap '. g:tcommentMapLeader2 .'s :TCommentAs <c-r>=&ft<cr>_'
endif
if (g:tcommentMapLeaderOp1 != '')
exec 'nnoremap <silent> '. g:tcommentMapLeaderOp1 .' :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#Operator<cr>g@'
exec 'nnoremap <silent> '. g:tcommentMapLeaderOp1 .'c :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorLine<cr>g@$'
exec 'vnoremap <silent> '. g:tcommentMapLeaderOp1 .' :TCommentMaybeInline<cr>'
endif
if (g:tcommentMapLeaderOp2 != '')
exec 'nnoremap <silent> '. g:tcommentMapLeaderOp2 .' :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorAnyway<cr>g@'
exec 'nnoremap <silent> '. g:tcommentMapLeaderOp2 .'c :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorLineAnyway<cr>g@$'
exec 'vnoremap <silent> '. g:tcommentMapLeaderOp2 .' :TCommentMaybeInline<cr>'
endif
finish
-----------------------------------------------------------------------
History
0.1
- Initial release
0.2
- Fixed uncommenting of non-aligned comments
- improved support for block comments (with middle lines and indentation)
- using TCommentBlock for file types that don't have block comments creates
single line comments
- removed the TCommentAsBlock command (TCommentAs provides its functionality)
- removed g:tcommentSetCMS
- the default key bindings have slightly changed
1.3
- slightly improved recognition of embedded syntax
- if no commentstring is defined in whatever way, reconstruct one from
&comments
- The TComment... commands now have bang variants that don't act as toggles
but always comment out the selected text
- fixed problem with commentstrings containing backslashes
- comment as visual block (allows commenting text to the right of the main
text, i.e., this command doesn't work on whole lines but on the text to the
right of the cursor)
- enable multimode for dsl, vim filetypes
- added explicit support for some other file types I ran into
1.4
- Fixed problem when &commentstring was invalid (e.g. lua)
- perl_block by Kyosuke Takayama.
- <c-_>s mapped to :TCommentAs <c-r>=&ft<cr>
1.5
- "Inline" visual comments (uses the &filetype_inline style if
available; doesn't check if the filetype actually supports this kind of
comments); tComment can't currently deduce inline comment styles from
&comments or &commentstring (I personally hardly ever use them); default
map: <c-_>i or <c-_>I
- In visual mode: if the selection spans several lines, normal mode is
selected; if the selection covers only a part of one line, inline mode
is selected
- Fixed problem with lines containing ^M or ^@ characters.
- It's no longer necessary to call TCommentCollectFileTypes() after
defining a new filetype via TCommentDefineType()
- Disabled single <c-_> mappings
- Renamed TCommentVisualBlock to TCommentRight
- FIX: Forgot 'x' in ExtractCommentsPart() (thanks to Fredrik Acosta)
1.6
- Ignore sql when guessing the comment string in php files; tComment
sometimes chooses the wrong comment string because the use of sql syntax
is used too loosely in php files; if you want to comment embedded sql
code you have to use TCommentAs
- Use keepjumps in commands.
- Map <c-_>p & <L>_p to vip:TComment<cr>
- Made key maps configurable via g:tcommentMapLeader1 and
g:tcommentMapLeader2
1.7
- gc{motion} (see g:tcommentMapLeaderOp1) functions as a comment toggle
operator (i.e., something like gcl... works, mostly); gC{motion} (see
g:tcommentMapLeaderOp2) will unconditionally comment the text.
- TCommentAs takes an optional second argument (the comment level)
- New "n" map: TCommentAs &filetype [COUNT]
- Defined mail comments/citations
- g:tcommentSyntaxMap: Map syntax names to filetypes for buffers with
mixed syntax groups that don't match the filetypeEmbeddedsyntax scheme (e.g.
'vimRubyRegion', which should be commented as ruby syntax, not as vim
syntax)
- FIX: Comments in vim*Region
- TComment: The use of the type argument has slightly changed (IG -> i,
new: >)
1.8
- Definitly require vim7
- Split the plugin into autoload & plugin.
- g:TCommentFileTypes is a list
- Fixed some block comment strings
- Removed extraneous newline in some block comments.
- Maps for visal mode (thanks Krzysztof Goj)
1.9
- Fix left offset for inline comments (via operator binding)
1.10
- tcomment#Operator defines w:tcommentPos if invoked repeatedly
- s:GuessFileType: use len(getline()) instead of col()

4546
vim/plugin/taglist.vim Normal file

File diff suppressed because it is too large Load Diff

191
vim/plugin/themes.vim Normal file
View File

@@ -0,0 +1,191 @@
" Vim default schemes
amenu T&hemes.D&efault.Blue :colo blue<CR>
amenu T&hemes.D&efault.DarkBlue :colo darkblue<CR>
amenu T&hemes.D&efault.Default :colo default<CR>
amenu T&hemes.D&efault.Delek :colo delek<CR>
amenu T&hemes.D&efault.Desert :colo desert<CR>
amenu T&hemes.D&efault.ElfLord :colo elflord<CR>
amenu T&hemes.D&efault.Evening :colo evening<CR>
amenu T&hemes.D&efault.Koehler :colo koehler<CR>
amenu T&hemes.D&efault.Morning :colo morning<CR>
amenu T&hemes.D&efault.Murphy :colo murphy<CR>
amenu T&hemes.D&efault.Pablo :colo pablo<CR>
amenu T&hemes.D&efault.PeachPuff :colo peachpuff<CR>
amenu T&hemes.D&efault.Ron :colo ron<CR>
amenu T&hemes.D&efault.Shine :colo shine<CR>
amenu T&hemes.D&efault.Torte :colo torte<CR>
amenu T&hemes.-s1- :
" Recommended Themes
amenu T&hemes.&Recommendations.InkPot :colo inkpot<CR>
amenu T&hemes.&Recommendations.LingoDirector :colo lingodirector<CR>
amenu T&hemes.&Recommendations.MetaCosm :colo metacosm<CR>
amenu T&hemes.&Recommendations.MidNight2 :colo midnight2<CR>
amenu T&hemes.&Recommendations.PS_Warm :let psc_style='warm'<CR>:colo ps_color<CR>
amenu T&hemes.&Recommendations.SCite :colo scite<CR>
amenu T&hemes.-s2- :
" Schemes with pure Black background.
amenu T&hemes.Blac&k.Adrian :colo adrian<CR>
amenu T&hemes.Blac&k.BillW :colo billw<CR>
amenu T&hemes.Blac&k.BlackAngus :colo black_angus<CR>
amenu T&hemes.Blac&k.BlackBeauty :colo blackbeauty<CR>
amenu T&hemes.Blac&k.BlackSea :colo blacksea<CR>
amenu T&hemes.Blac&k.Brookstream :colo brookstream<CR>
amenu T&hemes.Blac&k.Candy :colo candy<CR>
amenu T&hemes.Blac&k.Colorer :colo colorer<CR>
amenu T&hemes.Blac&k.Dante :colo dante<CR>
" Vim Dark Default is hidden, this can be used to activate it.
amenu T&hemes.Blac&k.Dark_Default :let psc_style='defdark'<CR>:colo ps_color<CR>
amenu T&hemes.Blac&k.DarkBlack :colo darkblack<CR>
amenu T&hemes.Blac&k.DarkOcean :colo darkocean<CR>
amenu T&hemes.Blac&k.FnaqEvan :colo fnaqevan<CR>
amenu T&hemes.Blac&k.Golden :colo golden<CR>
amenu T&hemes.Blac&k.Gothic :colo gothic<CR>
amenu T&hemes.Blac&k.GreyBlue :colo greyblue<CR>
amenu T&hemes.Blac&k.HHd.blue :colo hhdblue<CR>
amenu T&hemes.Blac&k.HHd.cyan :colo hhdcyan<CR>
amenu T&hemes.Blac&k.HHd.gray :colo hhdgray<CR>
amenu T&hemes.Blac&k.HHd.green :colo hhdgreen<CR>
amenu T&hemes.Blac&k.HHd.magenta :colo hhdmagenta<CR>
amenu T&hemes.Blac&k.HHd.red :colo hhdred<CR>
amenu T&hemes.Blac&k.HHd.yellow :colo hhdyellow<CR>
amenu T&hemes.Blac&k.JHDark :colo jhdark<CR>
amenu T&hemes.Blac&k.Less :colo less<CR>
amenu T&hemes.Blac&k.Manxome :colo manxome<CR>
amenu T&hemes.Blac&k.Olive :colo olive<CR>
amenu T&hemes.Blac&k.OceanBlack :colo oceanblack<CR>
amenu T&hemes.Blac&k.PS_Cool :let psc_style='cool'<CR>:colo ps_color<CR>
amenu T&hemes.Blac&k.Putty :colo putty<CR>
amenu T&hemes.Blac&k.RedBlack :colo redblack<CR>
amenu T&hemes.Blac&k.Revolutions :colo revolutions<CR>
amenu T&hemes.Blac&k.RelaxedGreen :colo relaxedgreen<CR>
amenu T&hemes.Blac&k.Sean :colo sean<CR>
amenu T&hemes.Blac&k.WintersDay :colo wintersday<CR>
" Dark Blue, or Deep Blue
amenu T&hemes.&Blue.Adaryn :colo adaryn<CR>
amenu T&hemes.&Blue.Astronaut :colo astronaut<CR>
amenu T&hemes.&Blue.BlueGreen :colo bluegreen<CR>
amenu T&hemes.&Blue.Blugrine :colo blugrine<CR>
amenu T&hemes.&Blue.Borland :colo borland<CR>
amenu T&hemes.&Blue.BorlandTurbo :colo turbo<CR>
amenu T&hemes.&Blue.Cool :colo cool<CR>
amenu T&hemes.&Blue.DarkDot :colo darkdot<CR>
amenu T&hemes.&Blue.Denim :colo denim<CR>
amenu T&hemes.&Blue.IbmEdit :colo ibmedit<CR>
amenu T&hemes.&Blue.InkPot :colo inkpot<CR>
amenu T&hemes.&Blue.Midnight :colo midnight<CR>
amenu T&hemes.&Blue.Midnight2 :colo midnight2<CR>
amenu T&hemes.&Blue.Northsky :colo northsky<CR>
amenu T&hemes.&Blue.Sea :colo sea<CR>
amenu T&hemes.&Blue.Transparent :colo transparent<CR>
" A bit lighter Blue, or greenish blue
amenu T&hemes.&Blue.Adam :colo adam<CR>
amenu T&hemes.&Cyan.Aqua :colo aqua<CR>
amenu T&hemes.&Cyan.Breeze :colo breeze<CR>
amenu T&hemes.&Cyan.Darkblue2 :colo darkblue2<CR>
amenu T&hemes.&Cyan.DarkSlateGray :colo darkslategray<CR>
amenu T&hemes.&Cyan.Dusk :colo dusk<CR>
amenu T&hemes.&Cyan.Gor :colo gor<CR>
amenu T&hemes.&Cyan.HHazure :colo hhazure<CR>
amenu T&hemes.&Cyan.Navajo-Night :colo navajo-night<CR>
amenu T&hemes.&Cyan.NightShimmer :colo nightshimmer<CR>
amenu T&hemes.&Cyan.NightWish :colo nightwish<CR>
amenu T&hemes.&Cyan.OceanDeep :colo oceandeep<CR>
" A traditional Greenish look...
amenu T&hemes.&Green.Earth :colo earth<CR>
amenu T&hemes.&Green.HHteal :colo hhteal<CR>
amenu T&hemes.&Green.Matrix :colo matrix<CR>
amenu T&hemes.&Green.RobinHood :colo robinhood<CR>
" Looks Brown or not pure Black, this is the most popular category,
" The top-two on vim.sf.net are all here.
amenu T&hemes.&Grey_Brown.BlackDust :colo blackdust<CR>
amenu T&hemes.&Grey_Brown.Camo :colo camo<CR>
amenu T&hemes.&Grey_Brown.ChocolateLiquor :colo chocolateliquor<CR>
amenu T&hemes.&Grey_Brown.Coffee :colo coffee<CR>
amenu T&hemes.&Grey_Brown.Desert :colo desert<CR>
amenu T&hemes.&Grey_Brown.HHorange :colo hhorange<CR>
amenu T&hemes.&Grey_Brown.HHspring :colo hhspring<CR>
amenu T&hemes.&Grey_Brown.MetaCosm :colo metacosm<CR>
amenu T&hemes.&Grey_Brown.Navajo :colo navajo<CR>
amenu T&hemes.&Grey_Brown.Neon :colo neon<CR>
amenu T&hemes.&Grey_Brown.UmberGreen :colo umber-green<CR>
amenu T&hemes.&Grey_Brown.Zenburn :colo zenburn<CR>
amenu T&hemes.-s3- :
" Any scheme with Violet, Magenta, Reddish Blue, or Red
amenu T&hemes.&Violet_Red.Aiseered :colo aiseered<CR>
amenu T&hemes.&Violet_Red.Asu1Dark :colo asu1dark<CR>
amenu T&hemes.&Violet_Red.Caramel :colo caramel<CR>
amenu T&hemes.&Violet_Red.EdoSea :colo edo_sea<CR>
amenu T&hemes.&Violet_Red.HHpink :colo hhpink<CR>
amenu T&hemes.&Violet_Red.HHviolet :colo hhviolet<CR>
amenu T&hemes.&Violet_Red.Lilac :colo lilac<CR>
amenu T&hemes.&Violet_Red.Mars :colo mars<CR>
amenu T&hemes.&Violet_Red.Night :colo night<CR>
amenu T&hemes.&Violet_Red.Tibet :colo tibet<CR>
amenu T&hemes.&Violet_Red.TomatoSoup :colo tomatosoup<CR>
amenu T&hemes.&Violet_Red.Xian :colo xian<CR>
" Light backgrounds which are not pure white
amenu T&hemes.&OffWhite.Autumn :colo autumn2<CR>
amenu T&hemes.&OffWhite.Bog :colo bog<CR>
amenu T&hemes.&OffWhite.Brown :colo brown<CR>
amenu T&hemes.&OffWhite.ButterCream :colo buttercream<CR>
amenu T&hemes.&OffWhite.CleanPHP :colo cleanphp<CR>
amenu T&hemes.&OffWhite.JHLight :colo jhlight<CR>
amenu T&hemes.&OffWhite.OceanLight :colo oceanlight<CR>
amenu T&hemes.&OffWhite.PapayaWhip :colo papayawhip<CR>
amenu T&hemes.&OffWhite.Python :colo python<CR>
amenu T&hemes.&OffWhite.Sand :colo sand<CR>
amenu T&hemes.&OffWhite.SeaShell :colo seashell<CR>
amenu T&hemes.&OffWhite.SF :colo sf<CR>
" Note that on a well-adjusted monitor with 6500k temperature (standard),
" #ffffff is not pure white, pure white should be less than #e8e8e8.
amenu T&hemes.&OffWhite.TAqua :colo taqua<CR>
amenu T&hemes.&OffWhite.TCSoft :colo tcsoft<CR>
" Pure White with light background
amenu T&hemes.&White.Automation :colo automation<CR>
amenu T&hemes.&White.Autumn :colo autumn<CR>
amenu T&hemes.&White.AutumnLeaf :colo autumnleaf<CR>
amenu T&hemes.&White.BioGoo :colo biogoo<CR>
amenu T&hemes.&White.BMichaelsen :colo bmichaelsen<CR>
amenu T&hemes.&White.BW :colo bw<CR>
amenu T&hemes.&White.C :colo c<CR>
amenu T&hemes.&White.ChelaLight :colo chela_light<CR>
amenu T&hemes.&White.Dawn :colo dawn<CR>
amenu T&hemes.&White.Emacs :colo emacs<CR>
amenu T&hemes.&White.FineBlue :colo fine_blue<CR>
amenu T&hemes.&White.Fog :colo fog<CR>
amenu T&hemes.&White.Fruit :colo fruit<CR>
amenu T&hemes.&White.Gobo :colo gobo<CR>
amenu T&hemes.&White.IronMan :colo ironman<CR>
amenu T&hemes.&White.LingoDirector :colo lingodirector<CR>
amenu T&hemes.&White.ModTCSoft :colo mod_tcsoft<CR>
amenu T&hemes.&White.NEdit :colo nedit<CR>
amenu T&hemes.&White.NEdit2 :colo nedit2<CR>
amenu T&hemes.&White.Nuvola :colo nuvola<CR>
amenu T&hemes.&White.PS_Warm :let psc_style='warm'<CR>:colo ps_color<CR>
amenu T&hemes.&White.PrintBW :colo print_bw<CR>
amenu T&hemes.&White.SCite :colo scite<CR>
amenu T&hemes.&White.SimpleAndFriendly :colo simpleandfriendly<CR>
amenu T&hemes.&White.Tolerable :colo tolerable<CR>
amenu T&hemes.&White.VC :colo vc<CR>
amenu T&hemes.&White.VCBC :colo vcbc<CR>
amenu T&hemes.&White.White :colo white<CR>
amenu T&hemes.&White.WhiteDust :colo whitedust<CR>
amenu T&hemes.&White.Xemacs :colo xemacs<CR>
amenu T&hemes.-s4- :
amenu T&hemes.Broken.AF\ (changes\ status\ line) :colo af<CR>
amenu T&hemes.Broken.Potts\ (changes\ font) :colo potts<CR>
amenu T&hemes.Broken.ToothPik\ (changes\ font) :colo toothpik<CR>

View File

@@ -0,0 +1,24 @@
kramdown - fast, pure-Ruby Markdown-superset converter
Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
kramdown is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Some test cases and the benchmark files are based on test cases from
the MDTest test suite:
MDTest
Copyright (c) 2007 Michel Fortin
<http://www.michelf.com/>

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
# All the code in this file is backported from Ruby 1.8.7 sothat kramdown works under 1.8.5
if RUBY_VERSION == '1.8.5'
require 'rexml/parsers/baseparser'
module REXML
module Parsers
class BaseParser
UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
end
end
end
end

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
# == Converter Module
#
# This module contains all available converters, i.e. classes that take a document and convert the
# document tree to a specific output format, normally a string. For example, the Html module
# converts the document tree into HTML.
#
# Converters use the Base class for common functionality (like applying a template to the output)-
# see its API documentation for how to create a converter class.
module Converter
autoload :Base, 'kramdown/converter/base'
autoload :Html, 'kramdown/converter/html'
autoload :Latex, 'kramdown/converter/latex'
autoload :Kramdown, 'kramdown/converter/kramdown'
end
end

View File

@@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'erb'
module Kramdown
module Converter
# == Base class for converters
#
# This class serves as base class for all converters. It provides methods that can/should be
# used by all converters (like #generate_id) as well as common functionality that is
# automatically applied to the result (for example, embedding the output into a template).
#
# == Implementing a converter
#
# Implementing a new converter is rather easy: just create a new sub class from this class and
# put it in the Kramdown::Converter module (the latter is only needed if auto-detection should
# work properly). Then you need to implement the #convert(tree) method which takes a document
# tree and should return the converted output.
#
# The document instance is automatically set as @doc in Base#initialize. Furthermore, the
# document instance provides a hash called `conversion_infos` that is also automatically cleared
# and can be used to store information about the conversion process.
#
# The actual transformation of the document tree can be done in any way. However, writing one
# method per tree element type is a straight forward way to do it - this is how the Html and
# Latex converters do the transformation.
class Base
# Initialize the converter with the given Kramdown document +doc+.
def initialize(doc)
@doc = doc
@doc.conversion_infos.clear
end
private_class_method(:new, :allocate)
# Convert the Kramdown document +doc+ to the output format implemented by a subclass.
#
# Initializes a new instance of the calling class and then calls the #convert method that must
# be implemented by each subclass. If the +template+ option is specified and non-empty, the
# result is rendered into the specified template.
def self.convert(doc)
result = new(doc).convert(doc.tree)
result = apply_template(doc, result) if !doc.options[:template].empty?
result
end
# Apply the template specified in the +doc+ options, using +body+ as the body string.
def self.apply_template(doc, body)
erb = ERB.new(get_template(doc.options[:template]))
obj = Object.new
obj.instance_variable_set(:@doc, doc)
obj.instance_variable_set(:@body, body)
erb.result(obj.instance_eval{binding})
end
# Return the template specified by +template+.
def self.get_template(template)
format_ext = '.' + self.name.split(/::/).last.downcase
shipped = File.join(::Kramdown.data_dir, template + format_ext)
if File.exist?(template)
File.read(template)
elsif File.exist?(template + format_ext)
File.read(template + format_ext)
elsif File.exist?(shipped)
File.read(shipped)
else
raise "The specified template file #{template} does not exist"
end
end
# Generate an unique alpha-numeric ID from the the string +str+ for use as header ID.
def generate_id(str)
gen_id = str.gsub(/[^a-zA-Z0-9 -]/, '').gsub(/^[^a-zA-Z]*/, '').gsub(' ', '-').downcase
gen_id = 'section' if gen_id.length == 0
@used_ids ||= {}
if @used_ids.has_key?(gen_id)
gen_id += '-' + (@used_ids[gen_id] += 1).to_s
else
@used_ids[gen_id] = 0
end
@doc.options[:auto_id_prefix] + gen_id
end
end
end
end

View File

@@ -0,0 +1,391 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'rexml/parsers/baseparser'
module Kramdown
module Converter
# Converts a Kramdown::Document to HTML.
class Html < Base
include ::Kramdown::Utils::HTML
# DEPRECATED: use #html_attributes
def options_for_element(el)
warn("DEPRECATION WARNING: this method will be deprecated in the next release, use #html_attributes instead")
html_attributes(el)
end
# :stopdoc:
# Defines the amount of indentation used when nesting HTML tags.
INDENTATION = 2
begin
require 'coderay'
# Highlighting via coderay is available if this constant is +true+.
HIGHLIGHTING_AVAILABLE = true
rescue LoadError => e
HIGHLIGHTING_AVAILABLE = false
end
# Initialize the HTML converter with the given Kramdown document +doc+.
def initialize(doc)
super
@footnote_counter = @footnote_start = @doc.options[:footnote_nr]
@footnotes = []
@toc = []
@toc_code = nil
end
def convert(el, indent = -INDENTATION, opts = {})
send("convert_#{el.type}", el, indent, opts)
end
def inner(el, indent, opts)
result = ''
indent += INDENTATION
el.children.each do |inner_el|
result << send("convert_#{inner_el.type}", inner_el, indent, opts)
end
result
end
def convert_blank(el, indent, opts)
"\n"
end
def convert_text(el, indent, opts)
escape_html(el.value, :text)
end
def convert_p(el, indent, opts)
if el.options[:transparent]
"#{inner(el, indent, opts)}"
else
"#{' '*indent}<p#{html_attributes(el)}>#{inner(el, indent, opts)}</p>\n"
end
end
def convert_codeblock(el, indent, opts)
if el.options[:attr] && el.options[:attr]['lang'] && HIGHLIGHTING_AVAILABLE
el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
opts = {:wrap => @doc.options[:coderay_wrap], :line_numbers => @doc.options[:coderay_line_numbers],
:line_number_start => @doc.options[:coderay_line_number_start], :tab_width => @doc.options[:coderay_tab_width],
:bold_every => @doc.options[:coderay_bold_every], :css => @doc.options[:coderay_css]}
result = CodeRay.scan(el.value, el.options[:attr].delete('lang').to_sym).html(opts).chomp + "\n"
"#{' '*indent}<div#{html_attributes(el)}>#{result}#{' '*indent}</div>\n"
else
result = escape_html(el.value)
if el.options[:attr] && el.options[:attr].has_key?('class') && el.options[:attr]['class'] =~ /\bshow-whitespaces\b/
result.gsub!(/(?:(^[ \t]+)|([ \t]+$)|([ \t]+))/) do |m|
suffix = ($1 ? '-l' : ($2 ? '-r' : ''))
m.scan(/./).map do |c|
case c
when "\t" then "<span class=\"ws-tab#{suffix}\">\t</span>"
when " " then "<span class=\"ws-space#{suffix}\">&#8901;</span>"
end
end.join('')
end
end
"#{' '*indent}<pre#{html_attributes(el)}><code>#{result}#{result =~ /\n\Z/ ? '' : "\n"}</code></pre>\n"
end
end
def convert_blockquote(el, indent, opts)
"#{' '*indent}<blockquote#{html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</blockquote>\n"
end
def convert_header(el, indent, opts)
el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
if @doc.options[:auto_ids] && !(el.options[:attr] && el.options[:attr]['id'])
(el.options[:attr] ||= {})['id'] = generate_id(el.options[:raw_text])
end
@toc << [el.options[:level], el.options[:attr]['id'], el.children] if el.options[:attr] && el.options[:attr]['id'] && within_toc_depth?(el)
"#{' '*indent}<h#{el.options[:level]}#{html_attributes(el)}>#{inner(el, indent, opts)}</h#{el.options[:level]}>\n"
end
def within_toc_depth?(el)
@doc.options[:toc_depth] <= 0 || el.options[:level] <= @doc.options[:toc_depth]
end
def convert_hr(el, indent, opts)
"#{' '*indent}<hr />\n"
end
def convert_ul(el, indent, opts)
if !@toc_code && (el.options[:ial][:refs].include?('toc') rescue nil) && (el.type == :ul || el.type == :ol)
@toc_code = [el.type, el.options[:attr], (0..128).to_a.map{|a| rand(36).to_s(36)}.join]
@toc_code.last
else
"#{' '*indent}<#{el.type}#{html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</#{el.type}>\n"
end
end
alias :convert_ol :convert_ul
alias :convert_dl :convert_ul
def convert_li(el, indent, opts)
output = ' '*indent << "<#{el.type}" << html_attributes(el) << ">"
res = inner(el, indent, opts)
if el.children.empty? || (el.children.first.type == :p && el.children.first.options[:transparent])
output << res << (res =~ /\n\Z/ ? ' '*indent : '')
else
output << "\n" << res << ' '*indent
end
output << "</#{el.type}>\n"
end
alias :convert_dd :convert_li
def convert_dt(el, indent, opts)
"#{' '*indent}<dt#{html_attributes(el)}>#{inner(el, indent, opts)}</dt>\n"
end
HTML_TAGS_WITH_BODY=['div', 'script']
def convert_html_element(el, indent, opts)
res = inner(el, indent, opts)
if el.options[:category] == :span
"<#{el.value}#{html_attributes(el)}" << (!res.empty? ? ">#{res}</#{el.value}>" : " />")
else
output = ''
output << ' '*indent if !el.options[:parent_is_raw]
output << "<#{el.value}#{html_attributes(el)}"
if !res.empty? && el.options[:parse_type] != :block
output << ">#{res}</#{el.value}>"
elsif !res.empty?
output << ">\n#{res}" << ' '*indent << "</#{el.value}>"
elsif HTML_TAGS_WITH_BODY.include?(el.value)
output << "></#{el.value}>"
else
output << " />"
end
output << "\n" if el.options[:outer_element] || !el.options[:parent_is_raw]
output
end
end
def convert_xml_comment(el, indent, opts)
if el.options[:category] == :block && !el.options[:parent_is_raw]
' '*indent + el.value + "\n"
else
el.value
end
end
alias :convert_xml_pi :convert_xml_comment
alias :convert_html_doctype :convert_xml_comment
def convert_table(el, indent, opts)
if el.options[:alignment].all? {|a| a == :default}
alignment = ''
else
alignment = el.options[:alignment].map do |a|
"#{' '*(indent + INDENTATION)}" + (a == :default ? "<col />" : "<col align=\"#{a}\" />") + "\n"
end.join('')
end
"#{' '*indent}<table#{html_attributes(el)}>\n#{alignment}#{inner(el, indent, opts)}#{' '*indent}</table>\n"
end
def convert_thead(el, indent, opts)
"#{' '*indent}<#{el.type}#{html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</#{el.type}>\n"
end
alias :convert_tbody :convert_thead
alias :convert_tfoot :convert_thead
alias :convert_tr :convert_thead
def convert_td(el, indent, opts)
res = inner(el, indent, opts)
"#{' '*indent}<#{el.type}#{html_attributes(el)}>#{res.empty? ? "&nbsp;" : res}</#{el.type}>\n"
end
alias :convert_th :convert_td
def convert_comment(el, indent, opts)
if el.options[:category] == :block
"#{' '*indent}<!-- #{el.value} -->\n"
else
"<!-- #{el.value} -->"
end
end
def convert_br(el, indent, opts)
"<br />"
end
def convert_a(el, indent, opts)
do_obfuscation = el.options[:attr]['href'] =~ /^mailto:/
if do_obfuscation
el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
href = obfuscate(el.options[:attr]['href'].sub(/^mailto:/, ''))
mailto = obfuscate('mailto')
el.options[:attr]['href'] = "#{mailto}:#{href}"
end
res = inner(el, indent, opts)
res = obfuscate(res) if do_obfuscation
"<a#{html_attributes(el)}>#{res}</a>"
end
def convert_img(el, indent, opts)
"<img#{html_attributes(el)} />"
end
def convert_codespan(el, indent, opts)
"<code#{html_attributes(el)}>#{escape_html(el.value)}</code>"
end
def convert_footnote(el, indent, opts)
number = @footnote_counter
@footnote_counter += 1
@footnotes << [el.options[:name], @doc.parse_infos[:footnotes][el.options[:name]]]
"<sup id=\"fnref:#{el.options[:name]}\"><a href=\"#fn:#{el.options[:name]}\" rel=\"footnote\">#{number}</a></sup>"
end
def convert_raw(el, indent, opts)
el.value + (el.options[:category] == :block ? "\n" : '')
end
def convert_em(el, indent, opts)
"<#{el.type}#{html_attributes(el)}>#{inner(el, indent, opts)}</#{el.type}>"
end
alias :convert_strong :convert_em
def convert_entity(el, indent, opts)
entity_to_str(el.value)
end
TYPOGRAPHIC_SYMS = {
:mdash => [::Kramdown::Utils::Entities.entity('mdash')],
:ndash => [::Kramdown::Utils::Entities.entity('ndash')],
:hellip => [::Kramdown::Utils::Entities.entity('hellip')],
:laquo_space => [::Kramdown::Utils::Entities.entity('laquo'), ::Kramdown::Utils::Entities.entity('nbsp')],
:raquo_space => [::Kramdown::Utils::Entities.entity('nbsp'), ::Kramdown::Utils::Entities.entity('raquo')],
:laquo => [::Kramdown::Utils::Entities.entity('laquo')],
:raquo => [::Kramdown::Utils::Entities.entity('raquo')]
}
def convert_typographic_sym(el, indent, opts)
TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e)}.join('')
end
def convert_smart_quote(el, indent, opts)
entity_to_str(::Kramdown::Utils::Entities.entity(el.value.to_s))
end
def convert_math(el, indent, opts)
el = Marshal.load(Marshal.dump(el)) # so that the original is not changed
el.options[:attr] ||= {}
el.options[:attr]['class'] ||= ''
el.options[:attr]['class'] += (el.options[:attr]['class'].empty? ? '' : ' ') + 'math'
type = 'span'
type = 'div' if el.options[:category] == :block
"<#{type}#{html_attributes(el)}>#{escape_html(el.value)}</#{type}>#{type == 'div' ? "\n" : ''}"
end
def convert_abbreviation(el, indent, opts)
title = @doc.parse_infos[:abbrev_defs][el.value]
title = nil if title.empty?
"<abbr#{title ? " title=\"#{title}\"" : ''}>#{el.value}</abbr>"
end
def convert_root(el, indent, opts)
result = inner(el, indent, opts)
result << footnote_content
if @toc_code
toc_tree = generate_toc_tree(@toc, @toc_code[0], @toc_code[1] || {})
text = if toc_tree.children.size > 0
convert(toc_tree, 0)
else
''
end
result.sub!(/#{@toc_code.last}/, text)
end
result
end
def generate_toc_tree(toc, type, attr)
sections = Element.new(type, nil, {:attr => {'id' => 'markdown-toc'}.merge(attr)})
stack = []
toc.each do |level, id, children|
li = Element.new(:li, nil, {:level => level})
li.children << Element.new(:p, nil, {:transparent => true})
a = Element.new(:a, nil, {:attr => {:href => "##{id}"}})
a.children += children
li.children.last.children << a
li.children << Element.new(type)
success = false
while !success
if stack.empty?
sections.children << li
stack << li
success = true
elsif stack.last.options[:level] < li.options[:level]
stack.last.children.last.children << li
stack << li
success = true
else
item = stack.pop
item.children.pop unless item.children.last.children.size > 0
end
end
end
while !stack.empty?
item = stack.pop
item.children.pop unless item.children.last.children.size > 0
end
sections
end
# Helper method for obfuscating the +text+ by using HTML entities.
def obfuscate(text)
result = ""
text.each_byte do |b|
result += (b > 128 ? b.chr : "&#%03d;" % b)
end
result.force_encoding(text.encoding) if RUBY_VERSION >= '1.9'
result
end
# Return a HTML list with the footnote content for the used footnotes.
def footnote_content
ol = Element.new(:ol)
ol.options[:attr] = {'start' => @footnote_start} if @footnote_start != 1
@footnotes.each do |name, data|
li = Element.new(:li, nil, {:attr => {:id => "fn:#{name}"}, :first_is_block => true})
li.children = Marshal.load(Marshal.dump(data[:content].children)) #TODO: probably remove this!!!!
ol.children << li
ref = Element.new(:raw, "<a href=\"#fnref:#{name}\" rev=\"footnote\">&#8617;</a>")
if li.children.last.type == :p
para = li.children.last
else
li.children << (para = Element.new(:p))
end
para.children << ref
end
(ol.children.empty? ? '' : "<div class=\"footnotes\">\n#{convert(ol, 2)}</div>\n")
end
end
end
end

View File

@@ -0,0 +1,398 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'rexml/parsers/baseparser'
module Kramdown
module Converter
# Converts a Kramdown::Document to the kramdown format.
class Kramdown < Base
# :stopdoc:
include ::Kramdown::Utils::HTML
def initialize(doc)
super
@linkrefs = []
@footnotes = []
@abbrevs = []
@stack = []
end
def convert(el, opts = {})
res = send("convert_#{el.type}", el, opts)
if el.type != :html_element && el.type != :li && el.type != :dd && (ial = ial_for_element(el))
res << ial
res << "\n\n" if el.options[:category] == :block
end
res
end
def inner(el, opts = {})
@stack.push([el, opts])
result = ''
el.children.each_with_index do |inner_el, index|
options = opts.dup
#p [index, inner_el]
options[:index] = index
options[:prev] = (index == 0 ? nil : el.children[index-1])
options[:next] = (index == el.children.length - 1 ? nil : el.children[index+1])
result << convert(inner_el, options)
end
@stack.pop
result
end
def convert_blank(el, opts)
"\n"
end
ESCAPED_CHAR_RE = /(\$\$|[\\*_`\[\]\{\}"'])|^[ ]{0,3}(:)/
def convert_text(el, opts)
if opts[:raw_text]
el.value
else
nl = (el.value =~ /\n$/)
el.value.gsub(/\s+/, ' ').gsub(ESCAPED_CHAR_RE) { "\\#{$1 || $2}" } + (nl ? "\n" : '')
end
end
def convert_p(el, opts)
res = inner(el, opts).strip.gsub(/\A(?:([#|])|(\d+)\.|([+-]\s))/) do
$1 || $3 ? "\\#{$1 || $3}" : "#{$2}\\."
end + "\n"
if opts[:next] && opts[:next].type == :p && !ial_for_element(el)
res += "\n"
end
res
end
CODEBLOCK_PREV_EL = [:ul, :ol, :dl, :codeblock]
def convert_codeblock(el, opts)
res = ''
res << "^\n" if opts[:prev] && ((CODEBLOCK_PREV_EL.include?(opts[:prev].type) && !ial_for_element(opts[:prev])) ||
(opts[:prev].type == :blank &&
opts[:index]-2 >= 0 &&
(tmp = @stack.last.first.children[opts[:index]-2]) &&
CODEBLOCK_PREV_EL.include?(tmp.type) && !ial_for_element(tmp)))
res << el.value.split(/\n/).map {|l| l.empty? ? " " : " #{l}"}.join("\n") + "\n"
end
def convert_blockquote(el, opts)
res = ''
res << "\n" if opts[:prev] && opts[:prev].type == :blockquote
res << inner(el, opts).chomp.split(/\n/).map {|l| "> #{l}"}.join("\n") << "\n"
end
def convert_header(el, opts)
res = ''
res << "\n" if opts[:prev] && opts[:prev].type != :blank
res << "#{'#' * el.options[:level]} #{inner(el, opts)}"
res << " {##{el.options[:attr]['id']}}" if el.options[:attr] && el.options[:attr]['id']
res << "\n" if opts[:next] && opts[:next].type != :blank
res << "\n"
end
def convert_hr(el, opts)
"* * *\n"
end
def convert_ul(el, opts)
res = ''
res << "\n" if opts[:prev] && (opts[:prev].type == :p && !opts[:prev].options[:transparent])
res << "^\n" if opts[:prev] && ((opts[:prev].type == el.type && !ial_for_element(opts[:prev])) ||
(opts[:prev].type == :blank && opts[:index]-2 >= 0 &&
(tmp = @stack.last.first.children[opts[:index]-2]) &&
tmp.type == el.type && !ial_for_element(tmp)))
res + inner(el, opts).sub(/\n+\Z/, "\n")
end
alias :convert_ol :convert_ul
alias :convert_dl :convert_ul
def convert_li(el, opts)
sym, width = if @stack.last.first.type == :ul
['* ', el.children.first.type == :codeblock ? 4 : 2]
else
["#{opts[:index] + 1}.".ljust(4), 4]
end
if ial = ial_for_element(el)
sym += ial + " "
end
first, *last = inner(el, opts).chomp.split(/\n/)
last = last.map {|l| " "*width + l}.join("\n")
last = last.empty? ? "\n" : "\n#{last}\n"
if el.children.first.type == :p && !el.children.first.options[:transparent]
res = "#{sym}#{first}\n#{last}"
res << "^\n" if el.children.size == 1 && @stack.last.first.children.last == el &&
(@stack.last.first.children.any? {|c| c.children.first.type != :p} || @stack.last.first.children.size == 1)
res
elsif el.children.first.type == :codeblock
"#{sym}\n #{first}#{last}"
else
"#{sym}#{first}#{last}"
end
end
def convert_dd(el, opts)
sym, width = ": ", (el.children.first.type == :codeblock ? 4 : 2)
if ial = ial_for_element(el)
sym += ial + " "
end
first, *last = inner(el, opts).chomp.split(/\n/)
last = last.map {|l| " "*width + l}.join("\n")
text = first + (last.empty? ? '' : "\n" + last)
if el.children.first.type == :p && !el.children.first.options[:transparent]
"\n#{sym}#{text}\n"
elsif el.children.first.type == :codeblock
"#{sym}\n #{text}\n"
else
"#{sym}#{text}\n"
end
end
def convert_dt(el, opts)
res = ''
res << inner(el, opts) << "\n"
end
HTML_TAGS_WITH_BODY=['div', 'script']
def convert_html_element(el, opts)
markdown_attr = el.options[:category] == :block && el.children.any? do |c|
c.type != :html_element && (c.type != :p || !c.options[:transparent]) && c.options[:category] == :block
end
opts[:force_raw_text] = true if %w{script pre code}.include?(el.value)
opts[:raw_text] = opts[:force_raw_text] || opts[:block_raw_text] || (el.options[:category] != :span && !markdown_attr)
opts[:block_raw_text] = true if el.options[:category] == :block && opts[:raw_text]
res = inner(el, opts)
if el.options[:category] == :span
"<#{el.value}#{html_attributes(el)}" << (!res.empty? ? ">#{res}</#{el.value}>" : " />")
else
output = ''
output << "<#{el.value}#{html_attributes(el)}"
output << " markdown=\"1\"" if markdown_attr
if !res.empty? && el.options[:parse_type] != :block
output << ">#{res}</#{el.value}>"
elsif !res.empty?
output << ">\n#{res}" << "</#{el.value}>"
elsif HTML_TAGS_WITH_BODY.include?(el.value)
output << "></#{el.value}>"
else
output << " />"
end
output << "\n" if el.options[:outer_element] || !el.options[:parent_is_raw]
output
end
end
def convert_xml_comment(el, opts)
if el.options[:category] == :block && !el.options[:parent_is_raw]
el.value + "\n"
else
el.value
end
end
alias :convert_xml_pi :convert_xml_comment
alias :convert_html_doctype :convert_xml_comment
def convert_table(el, opts)
opts[:alignment] = el.options[:alignment]
inner(el, opts)
end
def convert_thead(el, opts)
rows = inner(el, opts)
if opts[:alignment].all? {|a| a == :default}
"#{rows}|" + "-"*10 + "\n"
else
"#{rows}| " + opts[:alignment].map do |a|
case a
when :left then ":-"
when :right then "-:"
when :center then ":-:"
when :default then "-"
end
end.join(' ') + "\n"
end
end
def convert_tbody(el, opts)
res = ''
res << inner(el, opts)
res << '|' << '-'*10 << "\n" if opts[:next] && opts[:next].type == :tbody
res
end
def convert_tfoot(el, opts)
"|" + "="*10 + "\n#{inner(el, opts)}"
end
def convert_tr(el, opts)
"| " + el.children.map {|c| convert(c, opts)}.join(" | ") + " |\n"
end
def convert_td(el, opts)
inner(el, opts).gsub(/\|/, '\\|')
end
alias :convert_th :convert_td
def convert_comment(el, opts)
if el.options[:category] == :block
"{::comment}\n#{el.value}\n{:/}\n"
else
"{::comment}#{el.value}{:/}"
end
end
def convert_br(el, opts)
" \n"
end
def convert_a(el, opts)
if el.options[:attr]['href'].empty?
"[#{inner(el, opts)}]()"
else
@linkrefs << el
"[#{inner(el, opts)}][#{@linkrefs.size}]"
end
end
def convert_img(el, opts)
title = (el.options[:attr]['title'] ? ' "' + el.options[:attr]['title'].gsub(/"/, "&quot;") + '"' : '')
"![#{el.options[:attr]['alt']}](<#{el.options[:attr]['src']}>#{title})"
end
def convert_codespan(el, opts)
delim = (el.value.scan(/`+/).max || '') + '`'
"#{delim}#{' ' if delim.size > 1}#{el.value}#{' ' if delim.size > 1}#{delim}"
end
def convert_footnote(el, opts)
@footnotes << [el.options[:name], @doc.parse_infos[:footnotes][el.options[:name]]]
"[^#{el.options[:name]}]"
end
def convert_raw(el, opts)
if @stack.last.first.type == :html_element
el.value
elsif el.options[:category] == :block
"{::nomarkdown}\n#{el.value}\n{:/}\n"
else
"{::nomarkdown}#{el.value}{:/}"
end
end
def convert_em(el, opts)
"*#{inner(el, opts)}*"
end
def convert_strong(el, opts)
"**#{inner(el, opts)}**"
end
def convert_entity(el, opts)
entity_to_str(el.value)
end
TYPOGRAPHIC_SYMS = {
:mdash => '---', :ndash => '--', :hellip => '...',
:laquo_space => '<< ', :raquo_space => ' >>',
:laquo => '<<', :raquo => '>>'
}
def convert_typographic_sym(el, opts)
TYPOGRAPHIC_SYMS[el.value]
end
def convert_smart_quote(el, opts)
el.value.to_s =~ /[rl]dquo/ ? "\"" : "'"
end
def convert_math(el, opts)
(@stack.last.first.type == :p && opts[:prev].nil? ? "\\" : '') + "$$#{el.value}$$" + (el.options[:category] == :block ? "\n" : '')
end
def convert_abbreviation(el, opts)
el.value
end
def convert_root(el, opts)
res = inner(el, opts)
res << create_link_defs
res << create_footnote_defs
res << create_abbrev_defs
res
end
def create_link_defs
res = ''
res << "\n\n" if @linkrefs.size > 0
@linkrefs.each_with_index do |el, i|
link = (el.type == :a ? el.options[:attr]['href'] : el.options[:attr]['src'])
link = "<#{link}>" if link =~ / /
title = el.options[:attr]['title']
res << "[#{i+1}]: #{link} #{title ? '"' + title.gsub(/"/, "&quot;") + '"' : ''}\n"
end
res
end
def create_footnote_defs
res = ''
res = "\n" if @footnotes.size > 0
@footnotes.each do |name, data|
res << "\n[^#{name}]:\n"
res << inner(data[:content]).chomp.split(/\n/).map {|l| " #{l}"}.join("\n")
end
res
end
def create_abbrev_defs
return '' unless @doc.parse_infos[:abbrev_defs]
res = ''
@doc.parse_infos[:abbrev_defs].each do |name, text|
res << "*[#{name}]: #{text}\n"
end
res
end
# Return the IAL containing the attributes of the element +el+.
def ial_for_element(el)
res = (el.options[:attr] || {}).map do |k,v|
next if [:img, :a].include?(el.type) && ['href', 'src', 'alt', 'title'].include?(k)
next if el.type == :header && k == 'id'
v.nil? ? '' : " #{k}=\"#{v.to_s}\""
end.compact.sort.join('')
res = "toc" + (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) &&
(el.options[:ial][:refs].include?('toc') rescue nil)
res.strip.empty? ? nil : "{:#{res}}"
end
end
end
end

View File

@@ -0,0 +1,553 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'set'
module Kramdown
module Converter
# Converts a Kramdown::Document to LaTeX. This converter uses ideas from other Markdown-to-LaTeX
# converters like Pandoc and Maruku.
class Latex < Base
# :stopdoc:
# Initialize the LaTeX converter with the given Kramdown document +doc+.
def initialize(doc)
super
#TODO: set the footnote counter at the beginning of the document
@doc.options[:footnote_nr]
@doc.conversion_infos[:packages] = Set.new
end
def convert(el, opts = {})
send("convert_#{el.type}", el, opts)
end
def inner(el, opts)
result = ''
el.children.each do |inner_el|
result << send("convert_#{inner_el.type}", inner_el, opts)
end
result
end
def convert_root(el, opts)
inner(el, opts)
end
def convert_blank(el, opts)
""
end
def convert_text(el, opts)
escape(el.value)
end
def convert_p(el, opts)
"#{inner(el, opts)}\n\n"
end
def convert_codeblock(el, opts)
show_whitespace = el.options[:attr] && el.options[:attr]['class'].to_s =~ /\bshow-whitespaces\b/
lang = el.options[:attr] && el.options[:attr]['lang']
if show_whitespace || lang
result = "\\lstset{showspaces=%s,showtabs=%s}\n" % (show_whitespace ? ['true', 'true'] : ['false', 'false'])
result += "\\lstset{language=#{lang}}\n" if lang
result += "\\lstset{basicstyle=\\ttfamily\\footnotesize}\\lstset{columns=fixed,frame=tlbr}\n"
"#{result}\\begin{lstlisting}#{attribute_list(el)}\n#{el.value}\n\\end{lstlisting}\n"
else
"\\begin{verbatim}#{el.value}\\end{verbatim}\n"
end
end
def latex_environment(type, el, text)
"\\begin{#{type}}#{attribute_list(el)}\n#{text}\n\\end{#{type}}\n"
end
def convert_blockquote(el, opts)
latex_environment('quote', el, inner(el, opts))
end
HEADER_TYPES = {
1 => 'section',
2 => 'subsection',
3 => 'subsubsection',
4 => 'paragraph',
5 => 'subparagraph',
6 => 'subparagraph'
}
def convert_header(el, opts)
type = HEADER_TYPES[el.options[:level]]
if ((el.options[:attr] && (id = el.options[:attr]['id'])) ||
(@doc.options[:auto_ids] && (id = generate_id(el.options[:raw_text])))) &&
(@doc.options[:toc_depth] <= 0 || el.options[:level] <= @doc.options[:toc_depth])
"\\hypertarget{#{id}}{}\\#{type}{#{inner(el, opts)}}\\label{#{id}}\n\n"
else
"\\#{type}*{#{inner(el, opts)}}\n\n"
end
end
def convert_hr(el, opts)
"\\begin{center}#{attribute_list(el)}\n\\rule{3in}{0.4pt}\n\\end{center}\n"
end
def convert_ul(el, opts)
if !@doc.conversion_infos[:has_toc] && (el.options[:ial][:refs].include?('toc') rescue nil)
@doc.conversion_infos[:has_toc] = true
'\tableofcontents'
else
latex_environment(el.type == :ul ? 'itemize' : 'enumerate', el, inner(el, opts))
end
end
alias :convert_ol :convert_ul
def convert_dl(el, opts)
latex_environment('description', el, inner(el, opts))
end
def convert_li(el, opts)
"\\item #{inner(el, opts).sub(/\n+\Z/, '')}\n"
end
def convert_dt(el, opts)
"\\item[#{inner(el, opts)}] "
end
def convert_dd(el, opts)
"#{inner(el, opts)}\n\n"
end
def convert_html_element(el, opts)
if el.value == 'i'
"\\emph{#{inner(el, opts)}}"
elsif el.value == 'b'
"\\emph{#{inner(el, opts)}}"
else
@doc.warnings << "Can't convert HTML element"
''
end
end
def convert_xml_comment(el, opts)
el.value.split(/\n/).map {|l| "% #{l}"}.join("\n") + "\n"
end
def convert_xml_pi(el, opts)
@doc.warnings << "Can't convert XML PI/HTML document type"
''
end
alias :convert_html_doctype :convert_xml_pi
TABLE_ALIGNMENT_CHAR = {:default => 'l', :left => 'l', :center => 'c', :right => 'r'}
def convert_table(el, opts)
align = el.options[:alignment].map {|a| TABLE_ALIGNMENT_CHAR[a]}.join('|')
"\\begin{tabular}{|#{align}|}#{attribute_list(el)}\n\\hline\n#{inner(el, opts)}\\hline\n\\end{tabular}\n\n"
end
def convert_thead(el, opts)
"#{inner(el, opts)}\\hline\n"
end
def convert_tbody(el, opts)
inner(el, opts)
end
def convert_tfoot(el, opts)
"\\hline \\hline \n#{inner(el, opts)}"
end
def convert_tr(el, opts)
el.children.map {|c| send("convert_#{c.type}", c, opts)}.join(' & ') + "\\\\\n"
end
def convert_td(el, opts)
inner(el, opts)
end
alias :convert_th :convert_td
def convert_comment(el, opts)
el.value.split(/\n/).map {|l| "% #{l}"}.join("\n") + "\n"
end
def convert_br(el, opts)
"\\newline\n"
end
def convert_a(el, opts)
url = el.options[:attr]['href']
if url =~ /^#/
"\\hyperlink{#{url[1..-1]}}{#{inner(el, opts)}}"
else
"\\href{#{url}}{#{inner(el, opts)}}"
end
end
def convert_img(el, opts)
if el.options[:attr]['src'] =~ /^(https?|ftps?):\/\//
@doc.warnings << "Cannot include non-local image"
''
elsif !el.options[:attr]['src'].empty?
@doc.conversion_infos[:packages] << 'graphicx'
"\\includegraphics{#{el.options[:attr]['src']}}"
else
@doc.warnings << "Cannot include image with empty path"
''
end
end
def convert_codespan(el, opts)
"{\\tt #{escape(el.value)}}"
end
def convert_footnote(el, opts)
@doc.conversion_infos[:packages] << 'fancyvrb'
"\\footnote{#{inner(@doc.parse_infos[:footnotes][el.options[:name]][:content], opts)}}"
end
def convert_raw(el, opts)
escape(el.value)
end
def convert_em(el, opts)
"\\emph{#{inner(el, opts)}}"
end
def convert_strong(el, opts)
"\\textbf{#{inner(el, opts)}}"
end
# Inspired by Maruku: entity conversion table based on the one from htmltolatex
# (http://sourceforge.net/projects/htmltolatex/), with some small adjustments/additions
ENTITY_CONV_TABLE = {
913 => ['$A$'],
914 => ['$B$'],
915 => ['$\Gamma$'],
916 => ['$\Delta$'],
917 => ['$E$'],
918 => ['$Z$'],
919 => ['$H$'],
920 => ['$\Theta$'],
921 => ['$I$'],
922 => ['$K$'],
923 => ['$\Lambda$'],
924 => ['$M$'],
925 => ['$N$'],
926 => ['$\Xi$'],
927 => ['$O$'],
928 => ['$\Pi$'],
929 => ['$P$'],
931 => ['$\Sigma$'],
932 => ['$T$'],
933 => ['$Y$'],
934 => ['$\Phi$'],
935 => ['$X$'],
936 => ['$\Psi$'],
937 => ['$\Omega$'],
945 => ['$\alpha$'],
946 => ['$\beta$'],
947 => ['$\gamma$'],
948 => ['$\delta$'],
949 => ['$\epsilon$'],
950 => ['$\zeta$'],
951 => ['$\eta$'],
952 => ['$\theta$'],
953 => ['$\iota$'],
954 => ['$\kappa$'],
955 => ['$\lambda$'],
956 => ['$\mu$'],
957 => ['$\nu$'],
958 => ['$\xi$'],
959 => ['$o$'],
960 => ['$\pi$'],
961 => ['$\rho$'],
963 => ['$\sigma$'],
964 => ['$\tau$'],
965 => ['$\upsilon$'],
966 => ['$\phi$'],
967 => ['$\chi$'],
968 => ['$\psi$'],
969 => ['$\omega$'],
962 => ['$\varsigma$'],
977 => ['$\vartheta$'],
982 => ['$\varpi$'],
8230 => ['\ldots'],
8242 => ['$\prime$'],
8254 => ['-'],
8260 => ['/'],
8472 => ['$\wp$'],
8465 => ['$\Im$'],
8476 => ['$\Re$'],
8501 => ['$\aleph$'],
8226 => ['$\bullet$'],
8482 => ['$^{\rm TM}$'],
8592 => ['$\leftarrow$'],
8594 => ['$\rightarrow$'],
8593 => ['$\uparrow$'],
8595 => ['$\downarrow$'],
8596 => ['$\leftrightarrow$'],
8629 => ['$\hookleftarrow$'],
8657 => ['$\Uparrow$'],
8659 => ['$\Downarrow$'],
8656 => ['$\Leftarrow$'],
8658 => ['$\Rightarrow$'],
8660 => ['$\Leftrightarrow$'],
8704 => ['$\forall$'],
8706 => ['$\partial$'],
8707 => ['$\exists$'],
8709 => ['$\emptyset$'],
8711 => ['$\nabla$'],
8712 => ['$\in$'],
8715 => ['$\ni$'],
8713 => ['$\notin$'],
8721 => ['$\sum$'],
8719 => ['$\prod$'],
8722 => ['$-$'],
8727 => ['$\ast$'],
8730 => ['$\surd$'],
8733 => ['$\propto$'],
8734 => ['$\infty$'],
8736 => ['$\angle$'],
8743 => ['$\wedge$'],
8744 => ['$\vee$'],
8745 => ['$\cup$'],
8746 => ['$\cap$'],
8747 => ['$\int$'],
8756 => ['$\therefore$', 'amssymb'],
8764 => ['$\sim$'],
8776 => ['$\approx$'],
8773 => ['$\cong$'],
8800 => ['$\neq$'],
8801 => ['$\equiv$'],
8804 => ['$\leq$'],
8805 => ['$\geq$'],
8834 => ['$\subset$'],
8835 => ['$\supset$'],
8838 => ['$\subseteq$'],
8839 => ['$\supseteq$'],
8836 => ['$\nsubset$', 'amssymb'],
8853 => ['$\oplus$'],
8855 => ['$\otimes$'],
8869 => ['$\perp$'],
8901 => ['$\cdot$'],
8968 => ['$\rceil$'],
8969 => ['$\lceil$'],
8970 => ['$\lfloor$'],
8971 => ['$\rfloor$'],
9001 => ['$\rangle$'],
9002 => ['$\langle$'],
9674 => ['$\lozenge$', 'amssymb'],
9824 => ['$\spadesuit$'],
9827 => ['$\clubsuit$'],
9829 => ['$\heartsuit$'],
9830 => ['$\diamondsuit$'],
38 => ['\&'],
34 => ['"'],
39 => ['\''],
169 => ['\copyright'],
60 => ['\textless{}'],
62 => ['\textgreater{}'],
338 => ['\OE'],
339 => ['\oe'],
352 => ['\v{S}'],
353 => ['\v{s}'],
376 => ['\"Y'],
710 => ['\textasciicircum'],
732 => ['\textasciitilde'],
8211 => ['--'],
8212 => ['---'],
8216 => ['`'],
8217 => ['\''],
8220 => ['``'],
8221 => ['\'\''],
8224 => ['\dag'],
8225 => ['\ddag'],
8240 => ['\permil', 'wasysym'],
8364 => ['\euro', 'eurosym'],
8249 => ['\guilsinglleft'],
8250 => ['\guilsinglright'],
8218 => ['\quotesinglbase', 'mathcomp'],
8222 => ['\quotedblbase', 'mathcomp'],
402 => ['\textflorin', 'mathcomp'],
381 => ['\v{Z}'],
382 => ['\v{z}'],
160 => ['\nolinebreak'],
161 => ['\textexclamdown'],
163 => ['\pounds'],
164 => ['\currency', 'wasysym'],
165 => ['\textyen', 'textcomp'],
166 => ['\brokenvert', 'wasysym'],
167 => ['\S'],
171 => ['\guillemotleft'],
187 => ['\guillemotright'],
174 => ['\textregistered'],
170 => ['\textordfeminine'],
172 => ['$\neg$'],
176 => ['$\degree$', 'mathabx'],
177 => ['$\pm$'],
180 => ['\''],
181 => ['$\mu$'],
182 => ['\P'],
183 => ['$\cdot$'],
186 => ['\textordmasculine'],
162 => ['\cent', 'wasysym'],
185 => ['$^1$'],
178 => ['$^2$'],
179 => ['$^3$'],
189 => ['$\frac{1}{2}$'],
188 => ['$\frac{1}{4}$'],
190 => ['$\frac{3}{4}'],
192 => ['\`A'],
193 => ['\\\'A'],
194 => ['\^A'],
195 => ['\~A'],
196 => ['\"A'],
197 => ['\AA'],
198 => ['\AE'],
199 => ['\cC'],
200 => ['\`E'],
201 => ['\\\'E'],
202 => ['\^E'],
203 => ['\"E'],
204 => ['\`I'],
205 => ['\\\'I'],
206 => ['\^I'],
207 => ['\"I'],
208 => ['$\eth$', 'amssymb'],
209 => ['\~N'],
210 => ['\`O'],
211 => ['\\\'O'],
212 => ['\^O'],
213 => ['\~O'],
214 => ['\"O'],
215 => ['$\times$'],
216 => ['\O'],
217 => ['\`U'],
218 => ['\\\'U'],
219 => ['\^U'],
220 => ['\"U'],
221 => ['\\\'Y'],
222 => ['\Thorn', 'wasysym'],
223 => ['\ss'],
224 => ['\`a'],
225 => ['\\\'a'],
226 => ['\^a'],
227 => ['\~a'],
228 => ['\"a'],
229 => ['\aa'],
230 => ['\ae'],
231 => ['\cc'],
232 => ['\`e'],
233 => ['\\\'e'],
234 => ['\^e'],
235 => ['\"e'],
236 => ['\`i'],
237 => ['\\\'i'],
238 => ['\^i'],
239 => ['\"i'],
240 => ['$\eth$'],
241 => ['\~n'],
242 => ['\`o'],
243 => ['\\\'o'],
244 => ['\^o'],
245 => ['\~o'],
246 => ['\"o'],
247 => ['$\divide$'],
248 => ['\o'],
249 => ['\`u'],
250 => ['\\\'u'],
251 => ['\^u'],
252 => ['\"u'],
253 => ['\\\'y'],
254 => ['\thorn', 'wasysym'],
255 => ['\"y'],
}
ENTITY_CONV_TABLE.each {|k,v| ENTITY_CONV_TABLE[k] = v.unshift(v.shift + '{}')}
def convert_entity(el, opts)
text, package = ENTITY_CONV_TABLE[el.value.code_point]
if text
@doc.conversion_infos[:packages] << package if package
text
else
@doc.warnings << "Couldn't find entity in substitution table!"
''
end
end
TYPOGRAPHIC_SYMS = {
:mdash => '---', :ndash => '--', :hellip => '\ldots{}',
:laquo_space => '\guillemotleft{}~', :raquo_space => '~\guillemotright{}',
:laquo => '\guillemotleft{}', :raquo => '\guillemotright{}'
}
def convert_typographic_sym(el, opts)
TYPOGRAPHIC_SYMS[el.value]
end
SMART_QUOTE_SYMS = {:lsquo => '`', :rsquo => '\'', :ldquo => '``', :rdquo => '\'\''}
def convert_smart_quote(el, opts)
SMART_QUOTE_SYMS[el.value]
end
def convert_math(el, opts)
@doc.conversion_infos[:packages] += %w[amssymb amsmath amsthm amsfonts]
if el.options[:category] == :block
if el.value =~ /\A\s*\\begin\{/
el.value
else
latex_environment('displaymath', el, el.value)
end
else
"$#{el.value}$"
end
end
def convert_abbreviation(el, opts)
el.value
end
ESCAPE_MAP = {
"^" => "\\^{}",
"\\" => "\\textbackslash{}",
"~" => "\\ensuremath{\\sim}",
"|" => "\\textbar{}",
"<" => "\\textless{}",
">" => "\\textgreater{}"
}.merge(Hash[*("{}$%&_#".scan(/./).map {|c| [c, "\\#{c}"]}.flatten)])
ESCAPE_RE = Regexp.union(*ESCAPE_MAP.collect {|k,v| k})
def escape(str)
str.gsub(ESCAPE_RE) {|m| ESCAPE_MAP[m]}
end
def attribute_list(el)
attrs = (el.options[:attr] || {}).map {|k,v| v.nil? ? '' : " #{k}=\"#{v.to_s}\""}.compact.sort.join('')
attrs = " % #{attrs}" if !attrs.empty?
attrs
end
end
end
end

View File

@@ -0,0 +1,166 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/compatibility'
require 'kramdown/version'
require 'kramdown/error'
require 'kramdown/parser'
require 'kramdown/converter'
require 'kramdown/options'
require 'kramdown/utils'
module Kramdown
# Return the data directory for kramdown.
def self.data_dir
unless defined?(@@data_dir)
require 'rbconfig'
@@data_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data', 'kramdown'))
@@data_dir = File.expand_path(File.join(Config::CONFIG["datadir"], "kramdown")) if !File.exists?(@@data_dir)
raise "kramdown data directory not found! This is a bug, please report it!" unless File.directory?(@@data_dir)
end
@@data_dir
end
# The main interface to kramdown.
#
# This class provides a one-stop-shop for using kramdown to convert text into various output
# formats. Use it like this:
#
# require 'kramdown'
# doc = Kramdown::Document.new('This *is* some kramdown text')
# puts doc.to_html
#
# The #to_html method is a shortcut for using the Converter::Html class.
#
# The second argument to the #new method is an options hash for customizing the behaviour of the
# used parser and the converter. See Document#new for more information!
class Document
# The element tree of the document. It is immediately available after the #new method has been
# called.
attr_accessor :tree
# The options hash which holds the options for parsing/converting the Kramdown document. It is
# possible that these values get changed during the parsing phase.
attr_reader :options
# An array of warning messages. It is filled with warnings during the parsing phase (i.e. in
# #new) and the conversion phase.
attr_reader :warnings
# Holds needed parse information which is dependent on the used parser, like ALDs, link
# definitions and so on. This information may be used by converters afterwards.
attr_reader :parse_infos
# Holds conversion information which is dependent on the used converter. A converter clears this
# variable before doing the conversion.
attr_reader :conversion_infos
# Create a new Kramdown document from the string +source+ and use the provided +options+. The
# options that can be used are defined in the Options module.
#
# The special options key <tt>:input</tt> can be used to select the parser that should parse the
# +source+. It has to be the name of a class in the Kramdown::Parser module. For example, to
# select the kramdown parser, one would set the <tt>:input</tt> key to +Kramdown+. If this key
# is not set, it defaults to +Kramdown+.
#
# The +source+ is immediately parsed by the selected parser so that the document tree is
# immediately available and the output can be generated.
def initialize(source, options = {})
@options = Options.merge(options)
@warnings = []
@parse_infos = {}
@parse_infos[:encoding] = source.encoding if RUBY_VERSION >= '1.9'
@conversion_infos = {}
parser = (options[:input] || 'kramdown').to_s
parser = parser[0..0].upcase + parser[1..-1]
if Parser.const_defined?(parser)
@tree = Parser.const_get(parser).parse(source, self)
else
raise Kramdown::Error.new("kramdown has no parser to handle the specified input format: #{options[:input]}")
end
end
# Check if a method is invoked that begins with +to_+ and if so, try to instantiate a converter
# class (i.e. a class in the Kramdown::Converter module) and use it for converting the document.
#
# For example, +to_html+ would instantiate the Kramdown::Converter::Html class.
def method_missing(id, *attr, &block)
if id.to_s =~ /^to_(\w+)$/
Converter.const_get($1[0..0].upcase + $1[1..-1]).convert(self)
else
super
end
end
def inspect #:nodoc:
"<KD:Document: options=#{@options.inspect} tree=#{@tree.inspect} warnings=#{@warnings.inspect}>"
end
end
# Represents all elements in the parse tree.
#
# kramdown only uses this one class for representing all available elements in a parse tree
# (paragraphs, headers, emphasis, ...). The type of element can be set via the #type accessor.
class Element
# A symbol representing the element type. For example, <tt>:p</tt> or <tt>:blockquote</tt>.
attr_accessor :type
# The value of the element. The interpretation of this field depends on the type of the element.
# Many elements don't use this field.
attr_accessor :value
# The options hash for the element. It is used for storing arbitray options as well as the
# following special contents:
#
# - *Attributes* of the element under the <tt>:attr</tt> key
# - Category of the element, either <tt>:block</tt> or <tt>:span</tt>, under the
# <tt>:category</tt> key. If this key is absent, it can be assumed that the element is in the
# <tt>:span</tt> category.
attr_accessor :options
# The child elements of this element.
attr_accessor :children
# Create a new Element object of type +type+. The optional parameters +value+ and +options+ can
# also be set in this constructor for convenience.
def initialize(type, value = nil, options = {})
@type, @value, @options = type, value, options
@children = []
end
def inspect #:nodoc:
"<kd:#{@type}#{@value.nil? ? '' : ' ' + @value.inspect}#{options.empty? ? '' : ' ' + @options.inspect}#{@children.empty? ? '' : ' ' + @children.inspect}>"
end
end
end

View File

@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
class Error < RuntimeError; end
end

View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/document'

View File

@@ -0,0 +1,283 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
# This module defines all options that are used by parsers and/or converters as well as providing
# methods to deal with the options.
module Options
# Helper class introducing a boolean type for specifying boolean values (+true+ and +false+) as
# option types.
class Boolean
# Return +true+ if +other+ is either +true+ or +false+
def self.===(other)
FalseClass === other || TrueClass === other
end
end
# ----------------------------
# :section: Option definitions
#
# This sections informs describes the methods that can be used on the Options module.
# ----------------------------
# Contains the definition of an option.
Definition = Struct.new(:name, :type, :default, :desc)
# Allowed option types.
ALLOWED_TYPES = [String, Integer, Float, Symbol, Boolean, Array, Object]
@options = {}
# Define a new option called +name+ (a Symbol) with the given +type+ (String, Integer, Float,
# Symbol, Boolean, Array, Object), default value +default+ and the description +desc+.
#
# The type 'Object' should only be used if none of the other types suffices because such an
# option will be opaque and cannot be used, for example, by CLI command!
def self.define(name, type, default, desc)
raise ArgumentError, "Option name #{name} is already used" if @options.has_key?(name)
raise ArgumentError, "Invalid option type #{type} specified" if !ALLOWED_TYPES.include?(type)
raise ArgumentError, "Invalid type for default value" if !(type === default) && !default.nil?
@options[name] = Definition.new(name, type, default, desc)
end
# Return all option definitions.
def self.definitions
@options
end
# Return +true+ if an option called +name+ is defined.
def self.defined?(name)
@options.has_key?(name)
end
# Return a Hash with the default values for all options.
def self.defaults
temp = {}
@options.each {|n, o| temp[o.name] = o.default}
temp
end
# Merge the #defaults Hash with the *parsed* options from the given Hash, i.e. only valid option
# names are considered and their value is run through the #parse method.
def self.merge(hash)
temp = defaults
hash.each do |k,v|
next unless @options.has_key?(k)
temp[k] = parse(k, v)
end
temp
end
# Parse the given value +data+ as if it was a value for the option +name+ and return the parsed
# value with the correct type.
#
# If +data+ already has the correct type, it is just returned. Otherwise it is converted to a
# String and then to the correct type.
def self.parse(name, data)
raise ArgumentError, "No option named #{name} defined" if !@options.has_key?(name)
return data if @options[name].type === data
data = data.to_s
if @options[name].type == String
data
elsif @options[name].type == Integer
Integer(data)
elsif @options[name].type == Float
Float(data)
elsif @options[name].type == Symbol
(data.strip.empty? ? nil : data.to_sym)
elsif @options[name].type == Boolean
data.downcase.strip != 'false' && !data.empty?
elsif @options[name].type == Array
data.split(/\s+/)
end
end
# ----------------------------
# :section: Option Definitions
#
# This sections contains all option definitions that are used by the included
# parsers/converters.
# ----------------------------
define(:template, String, '', <<EOF)
The name of an ERB template file that should be used to wrap the output
This is used to wrap the output in an environment so that the output can
be used as a stand-alone document. For example, an HTML template would
provide the needed header and body tags so that the whole output is a
valid HTML file. If no template is specified, the output will be just
the converted text.
When resolving the template file, the given template name is used first.
If such a file is not found, the converter extension is appended. If the
file still cannot be found, the templates name is interpreted as a
template name that is provided by kramdown (without the converter
extension).
kramdown provides a default template named 'default' for each converter.
Default: ''
Used by: all converters
EOF
define(:auto_ids, Boolean, true, <<EOF)
Use automatic header ID generation
If this option is `true`, ID values for all headers are automatically
generated if no ID is explicitly specified.
Default: true
Used by: HTML/Latex converter
EOF
define(:auto_id_prefix, String, '', <<EOF)
Prefix used for automatically generated heaer IDs
This option can be used to set a prefix for the automatically generated
header IDs so that there is no conflict when rendering multiple kramdown
documents into one output file separately. The prefix should only
contain characters that are valid in an ID!
Default: ''
Used by: HTML/Latex converter
EOF
define(:parse_block_html, Boolean, false, <<EOF)
Process kramdown syntax in block HTML tags
If this option is `true`, the kramdown parser processes the content of
block HTML tags as text containing block level elements. Since this is
not wanted normally, the default is `false`. It is normally better to
selectively enable kramdown processing via the markdown attribute.
Default: false
Used by: kramdown parser
EOF
define(:parse_span_html, Boolean, true, <<EOF)
Process kramdown syntax in span HTML tags
If this option is `true`, the kramdown parser processes the content of
span HTML tags as text containing span level elements.
Default: true
Used by: kramdown parser
EOF
define(:html_to_native, Boolean, false, <<EOF)
Convert HTML elements to native elements
If this option is `true`, the parser converts HTML elements to native
elements. For example, when parsing `<em>hallo</em>` the emphasis tag
would normally be converted to an `:html` element with tag type `:em`.
If `html_to_native` is `true`, then the emphasis would be converted to a
native `:em` element.
This is useful for converters that cannot deal with HTML elements.
Default: false
Used by: kramdown parser
EOF
define(:footnote_nr, Integer, 1, <<EOF)
The number of the first footnote
This option can be used to specify the number that is used for the first
footnote.
Default: 1
Used by: HTML converter
EOF
define(:coderay_wrap, Symbol, :div, <<EOF)
Defines how the highlighted code should be wrapped
The possible values are :span, :div or nil.
Default: :div
Used by: HTML converter
EOF
define(:coderay_line_numbers, Symbol, :inline, <<EOF)
Defines how and if line numbers should be shown
The possible values are :table, :inline, :list or nil. If this option is
nil, no line numbers are shown.
Default: :inline
Used by: HTML converter
EOF
define(:coderay_line_number_start, Integer, 1, <<EOF)
The start value for the line numbers
Default: 1
Used by: HTML converter
EOF
define(:coderay_tab_width, Integer, 8, <<EOF)
The tab width used in highlighted code
Used by: HTML converter
EOF
define(:coderay_bold_every, Integer, 10, <<EOF)
Defines how often a line number should be made bold
Default: 10
Used by: HTML converter
EOF
define(:coderay_css, Symbol, :style, <<EOF)
Defines how the highlighted code gets styled
Possible values are :class (CSS classes are applied to the code
elements, one must supply the needed CSS file) or :style (default CSS
styles are directly applied to the code elements).
Default: style
Used by: HTML converter
EOF
define(:numeric_entities, Boolean, false, <<EOF)
Defines whether entities are output using names or numeric values
Default: false
Used by: HTML converter, kramdown converter
EOF
define(:toc_depth, Integer, 0, <<EOF)
Defines the maximum level of headers which will be used to generate the table of
contents. For instance, with a value of 2, toc entries will be generated for h1
and h2 headers but not for h3, h4, etc. A value of 0 uses all header levels.
Default: 0
Used by: HTML/Latex converter
EOF
end
end

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
# == Parser Module
#
# This module contains all available parsers. Currently, there two parsers:
#
# * Kramdown for parsing documents in kramdown format
# * Html for parsing HTML documents
module Parser
autoload :Base, 'kramdown/parser/base'
autoload :Kramdown, 'kramdown/parser/kramdown'
autoload :Html, 'kramdown/parser/html'
end
end

View File

@@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
# == Base class for parsers
#
# This class serves as base class for parsers. It provides common methods that can/should be
# used by all parsers, especially by those using StringScanner for parsing.
#
class Base
# Initialize the parser with the given Kramdown document +doc+.
def initialize(doc)
@doc = doc
@text_type = :text
end
private_class_method(:new, :allocate)
# Parse the +source+ string into an element tree, using the information provided by the
# Kramdown document +doc+.
#
# Initializes a new instance of the calling class and then calls the #parse method that must
# be implemented by each subclass.
def self.parse(source, doc)
new(doc).parse(source)
end
# Add the given warning +text+ to the warning array of the Kramdown document.
def warning(text)
@doc.warnings << text
#TODO: add position information
end
# Modify the string +source+ to be usable by the parser.
def adapt_source(source)
source.gsub(/\r\n?/, "\n").chomp + "\n"
end
# This helper method adds the given +text+ either to the last element in the +tree+ if it is a
# +type+ element or creates a new text element with the given +type+.
def add_text(text, tree = @tree, type = @text_type)
if tree.children.last && tree.children.last.type == type
tree.children.last.value << text
elsif !text.empty?
tree.children << Element.new(type, text)
end
end
# Extract the part of the StringScanner +srcscan+ backed string specified by the +range+. This
# method also works correctly under Ruby 1.9.
def extract_string(range, strscan)
result = nil
if RUBY_VERSION >= '1.9'
begin
enc = strscan.string.encoding
strscan.string.force_encoding('ASCII-8BIT')
result = strscan.string[range].force_encoding(enc)
ensure
strscan.string.force_encoding(enc)
end
else
result = strscan.string[range]
end
result
end
end
end
end

View File

@@ -0,0 +1,482 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'rexml/parsers/baseparser'
require 'strscan'
module Kramdown
module Parser
# Used for parsing a HTML document.
class Html < Base
# Contains all constants that are used when parsing.
module Constants
#:stopdoc:
# The following regexps are based on the ones used by REXML, with some slight modifications.
HTML_DOCTYPE_RE = /<!DOCTYPE.*?>/m
HTML_COMMENT_RE = /<!--(.*?)-->/m
HTML_INSTRUCTION_RE = /<\?(.*?)\?>/m
HTML_ATTRIBUTE_RE = /\s*(#{REXML::Parsers::BaseParser::UNAME_STR})\s*=\s*(["'])(.*?)\2/m
HTML_TAG_RE = /<((?>#{REXML::Parsers::BaseParser::UNAME_STR}))\s*((?>\s+#{REXML::Parsers::BaseParser::UNAME_STR}\s*=\s*(["']).*?\3)*)\s*(\/)?>/m
HTML_TAG_CLOSE_RE = /<\/(#{REXML::Parsers::BaseParser::NAME_STR})\s*>/m
HTML_ENTITY_RE = /&([\w:][\-\w\d\.:]*);|&#(\d+);|&\#x([0-9a-fA-F]+);/
HTML_PARSE_AS_BLOCK = %w{applet button blockquote colgroup dd div dl fieldset form iframe li
map noscript object ol table tbody thead tfoot tr td ul}
HTML_PARSE_AS_SPAN = %w{a abbr acronym address b bdo big cite caption del dfn dt em
h1 h2 h3 h4 h5 h6 i ins kbd label legend optgroup p q rb rbc
rp rt rtc ruby samp select small span strong sub sup th tt var}
HTML_PARSE_AS_RAW = %w{script math option textarea pre code}
HTML_PARSE_AS = Hash.new {|h,k| h[k] = :raw}
HTML_PARSE_AS_BLOCK.each {|i| HTML_PARSE_AS[i] = :block}
HTML_PARSE_AS_SPAN.each {|i| HTML_PARSE_AS[i] = :span}
HTML_PARSE_AS_RAW.each {|i| HTML_PARSE_AS[i] = :raw}
# Some HTML elements like script belong to both categories (i.e. are valid in block and
# span HTML) and don't appear therefore!
HTML_SPAN_ELEMENTS = %w{a abbr acronym b big bdo br button cite code del dfn em i img input
ins kbd label option q rb rbc rp rt rtc ruby samp select small span
strong sub sup textarea tt var}
HTML_BLOCK_ELEMENTS = %w{address article aside applet body button blockquote caption col colgroup dd div dl dt fieldset
figcaption footer form h1 h2 h3 h4 h5 h6 header hgroup hr html head iframe legend listing menu
li map nav ol optgroup p pre section summary table tbody td th thead tfoot tr ul}
HTML_ELEMENTS_WITHOUT_BODY = %w{area base br col command embed hr img input keygen link meta param source track wbr}
end
# Contains the parsing methods. This module can be mixed into any parser to get HTML parsing
# functionality. The only thing that must be provided by the class are instance variable
# <tt>@stack</tt> for storing needed state and <tt>@src</tt> (instance of StringScanner) for
# the actual parsing.
module Parser
include Constants
# Process the HTML start tag that has already be scanned/checked. Does the common processing
# steps and then yields to the caller for further processing.
def handle_html_start_tag
name = @src[1]
closed = !@src[4].nil?
attrs = {}
@src[2].scan(HTML_ATTRIBUTE_RE).each {|attr,sep,val| attrs[attr] = val}
el = Element.new(:html_element, name, :attr => attrs, :category => :block)
@tree.children << el
if !closed && HTML_ELEMENTS_WITHOUT_BODY.include?(el.value)
warning("The HTML tag '#{el.value}' cannot have any content - auto-closing it")
closed = true
end
if name == 'script'
handle_html_script_tag
yield(el, true)
else
yield(el, closed)
end
end
def handle_html_script_tag
curpos = @src.pos
if result = @src.scan_until(/(?=<\/script\s*>)/m)
add_text(extract_string(curpos...@src.pos, @src), @tree.children.last, :raw)
@src.scan(HTML_TAG_CLOSE_RE)
else
add_text(@src.scan(/.*/m), @tree.children.last, :raw)
warning("Found no end tag for 'script' - auto-closing it")
end
end
HTML_RAW_START = /(?=<(#{REXML::Parsers::BaseParser::UNAME_STR}|\/|!--|\?))/
# Parse raw HTML from the current source position, storing the found elements in +el+.
# Parsing continues until one of the following criteria are fulfilled:
#
# - The end of the document is reached.
# - The matching end tag for the element +el+ is found (only used if +el+ is an HTML
# element).
#
# When an HTML start tag is found, processing is deferred to #handle_html_start_tag,
# providing the block given to this method.
def parse_raw_html(el, &block)
@stack.push(@tree)
@tree = el
done = false
while !@src.eos? && !done
if result = @src.scan_until(HTML_RAW_START)
add_text(result, @tree, :text)
if result = @src.scan(HTML_COMMENT_RE)
@tree.children << Element.new(:xml_comment, result, :category => :block, :parent_is_raw => true)
elsif result = @src.scan(HTML_INSTRUCTION_RE)
@tree.children << Element.new(:xml_pi, result, :category => :block, :parent_is_raw => true)
elsif @src.scan(HTML_TAG_RE)
handle_html_start_tag(&block)
elsif @src.scan(HTML_TAG_CLOSE_RE)
if @tree.value == @src[1]
done = true
else
warning("Found invalidly used HTML closing tag for '#{@src[1]}' - ignoring it")
end
else
add_text(@src.scan(/./), @tree, :text)
end
else
result = @src.scan(/.*/m)
add_text(result, @tree, :text)
warning("Found no end tag for '#{@tree.value}' - auto-closing it") if @tree.type == :html_element
done = true
end
end
@tree = @stack.pop
end
end
# Converts HTML elements to native elements if possible.
class ElementConverter
include Constants
include ::Kramdown::Utils::Entities
REMOVE_TEXT_CHILDREN = %w{html head hgroup ol ul dl table colgroup tbody thead tfoot tr select optgroup}
WRAP_TEXT_CHILDREN = %w{body section nav article aside header footer address div li dd blockquote figure
figcaption fieldset form}
REMOVE_WHITESPACE_CHILDREN = %w{body section nav article aside header footer address
div li dd blockquote figure figcaption td th fieldset form}
STRIP_WHITESPACE = %w{address article aside blockquote body caption dd div dl dt fieldset figcaption form footer
header h1 h2 h3 h4 h5 h6 legend li nav p section td th}
SIMPLE_ELEMENTS = %w{em strong blockquote hr br a img p thead tbody tfoot tr td th ul ol dl li dl dt dd}
def initialize(doc)
@doc = doc
end
# Convert the element +el+ and its children.
def process(el, do_conversion = true, preserve_text = false, parent = nil)
case el.type
when :xml_comment, :xml_pi, :html_doctype
ptype = if parent.nil?
'div'
else
case parent.type
when :html_element then parent.value
when :code_span then 'code'
when :code_block then 'pre'
when :header then 'h1'
else parent.type.to_s
end
end
el.options = {:category => HTML_PARSE_AS_SPAN.include?(ptype) ? :span : :block}
return
when :html_element
else return
end
type = el.value
remove_text_children(el) if REMOVE_TEXT_CHILDREN.include?(type)
mname = "convert_#{el.value}"
if do_conversion && self.class.method_defined?(mname)
send(mname, el)
elsif do_conversion && SIMPLE_ELEMENTS.include?(type)
set_basics(el, type.intern, HTML_SPAN_ELEMENTS.include?(type) ? :span : :block)
process_children(el, do_conversion, preserve_text)
else
process_html_element(el, do_conversion, preserve_text)
end
strip_whitespace(el) if STRIP_WHITESPACE.include?(type)
remove_whitespace_children(el) if REMOVE_WHITESPACE_CHILDREN.include?(type)
wrap_text_children(el) if WRAP_TEXT_CHILDREN.include?(type)
end
def process_children(el, do_conversion = true, preserve_text = false)
el.children.map! do |c|
if c.type == :text
process_text(c.value, preserve_text)
else
process(c, do_conversion, preserve_text, el)
c
end
end.flatten!
end
# Process the HTML text +raw+: compress whitespace (if +preserve+ is +false+) and convert
# entities in entity elements.
def process_text(raw, preserve = false)
raw.gsub!(/\s+/, ' ') unless preserve
src = StringScanner.new(raw)
result = []
while !src.eos?
if tmp = src.scan_until(/(?=#{HTML_ENTITY_RE})/)
result << Element.new(:text, tmp)
src.scan(HTML_ENTITY_RE)
val = src[1] || (src[2] && src[2].to_i) || src[3].hex
result << if %w{lsquo rsquo ldquo rdquo}.include?(val)
Element.new(:smart_quote, val.intern)
elsif %w{mdash ndash hellip laquo raquo}.include?(val)
Element.new(:typographic_sym, val.intern)
else
Element.new(:entity, entity(val))
end
else
result << Element.new(:text, src.scan(/.*/m))
end
end
result
end
def process_html_element(el, do_conversion = true, preserve_text = false)
el.options = {:category => HTML_SPAN_ELEMENTS.include?(el.value) ? :span : :block,
:parse_type => HTML_PARSE_AS[el.value],
:attr => el.options[:attr]
}
process_children(el, do_conversion, preserve_text)
end
def remove_text_children(el)
el.children.delete_if {|c| c.type == :text}
end
SPAN_ELEMENTS = [:em, :strong, :br, :a, :img, :codespan, :entity, :smart_quote, :typographic_sym, :math]
def wrap_text_children(el)
tmp = []
last_is_p = false
el.children.each do |c|
if c.options[:category] != :block || c.type == :text
if !last_is_p
tmp << Element.new(:p, nil, :transparent => true)
last_is_p = true
end
tmp.last.children << c
tmp
else
tmp << c
last_is_p = false
end
end
el.children = tmp
end
def strip_whitespace(el)
return if el.children.empty?
if el.children.first.type == :text
el.children.first.value.lstrip!
end
if el.children.last.type == :text
el.children.last.value.rstrip!
end
end
def remove_whitespace_children(el)
i = -1
el.children.delete_if do |c|
i += 1
c.type == :text && c.value.strip.empty? &&
(i == 0 || i == el.children.length - 1 || (el.children[i-1].options[:category] == :block &&
el.children[i+1].options[:category] == :block))
end
end
def set_basics(el, type, category, opts = {})
el.type = type
el.options = {:category => category, :attr => el.options[:attr]}.merge(opts)
el.value = nil
end
def extract_text(el, raw)
raw << el.value.to_s if el.type == :text
el.children.each {|c| extract_text(c, raw)}
end
def convert_h1(el)
set_basics(el, :header, :block, :level => el.value[1..1].to_i)
extract_text(el, el.options[:raw_text] = '')
process_children(el)
end
%w{h2 h3 h4 h5 h6}.each do |i|
alias_method("convert_#{i}".to_sym, :convert_h1)
end
def convert_code(el)
raw = ''
extract_text(el, raw)
result = process_text(raw, true)
begin
str = result.inject('') do |mem, c|
if c.type == :text
mem << c.value
elsif c.type == :entity
if RUBY_VERSION >= '1.9'
mem << c.value.char.encode(@doc.parse_infos[:encoding])
elsif [60, 62, 34, 38].include?(c.value.code_point)
mem << c.value.code_point.chr
end
elsif c.type == :smart_quote || c.type == :typographic_sym
mem << entity(c.value.to_s).char.encode(@doc.parse_infos[:encoding])
else
raise "Bug - please report"
end
end
result.clear
result << Element.new(:text, str)
rescue
end
if result.length > 1 || result.first.type != :text
process_html_element(el, false, true)
else
if el.value == 'code'
set_basics(el, :codespan, :span)
else
set_basics(el, :codeblock, :block)
end
el.value = result.first.value
end
end
alias :convert_pre :convert_code
def convert_table(el)
if !is_simple_table?(el)
process_html_element(el, false)
return
end
process_children(el)
set_basics(el, :table, :block)
el.options[:alignment] = []
calc_alignment = lambda do |c|
if c.type == :tr && el.options[:alignment].empty?
el.options[:alignment] = [:default] * c.children.length
break
else
c.children.each {|cc| calc_alignment.call(cc)}
end
end
calc_alignment.call(el)
if el.children.first.type == :tr
tbody = Element.new(:tbody, nil, :category => :block)
tbody.children = el.children
el.children = [tbody]
end
end
def is_simple_table?(el)
only_phrasing_content = lambda do |c|
c.children.all? do |cc|
(cc.type == :text || !HTML_BLOCK_ELEMENTS.include?(cc.value)) && only_phrasing_content.call(cc)
end
end
check_cells = Proc.new do |c|
if c.value == 'th' || c.value == 'td'
return false if !only_phrasing_content.call(c)
else
c.children.each {|cc| check_cells.call(cc)}
end
end
check_cells.call(el)
check_rows = lambda do |t, type|
t.children.all? {|r| (r.value == 'tr' || r.type == :text) && r.children.all? {|c| c.value == type || c.type == :text}}
end
check_rows.call(el, 'td') ||
(el.children.all? do |t|
t.type == :text || (t.value == 'thead' && check_rows.call(t, 'th')) ||
((t.value == 'tfoot' || t.value == 'tbody') && check_rows.call(t, 'td'))
end && el.children.any? {|t| t.value == 'tbody'})
end
def convert_div(el)
if !is_math_tag?(el)
process_html_element(el)
else
handle_math_tag(el)
end
end
alias :convert_span :convert_div
def is_math_tag?(el)
el.options[:attr] && el.options[:attr]['class'].to_s =~ /\bmath\b/ &&
el.children.size == 1 && el.children.first.type == :text
end
def handle_math_tag(el)
set_basics(el, :math, (el.value == 'div' ? :block : :span))
el.value = el.children.shift.value
if el.options[:attr]['class'] =~ /^\s*math\s*$/
el.options[:attr].delete('class')
else
el.options[:attr]['class'].sub!(/\s?math/, '')
end
el.value.gsub!(/&(amp|quot|gt|lt);/) do |m|
case m
when '&amp;' then '&'
when '&quot;' then '"'
when '&gt;' then '>'
when '&lt;' then '<'
end
end
end
end
include Parser
# Parse +source+ as HTML document and return the created +tree+.
def parse(source)
@stack = []
@tree = Element.new(:root)
@src = StringScanner.new(adapt_source(source))
while true
if result = @src.scan(/\s*#{HTML_INSTRUCTION_RE}/)
@tree.children << Element.new(:xml_pi, result.strip, :category => :block)
elsif result = @src.scan(/\s*#{HTML_DOCTYPE_RE}/)
@tree.children << Element.new(:html_doctype, result.strip, :category => :block)
elsif result = @src.scan(/\s*#{HTML_COMMENT_RE}/)
@tree.children << Element.new(:xml_comment, result.strip, :category => :block)
else
break
end
end
tag_handler = lambda do |c, closed|
parse_raw_html(c, &tag_handler) if !closed
end
parse_raw_html(@tree, &tag_handler)
ec = ElementConverter.new(@doc)
@tree.children.each {|c| ec.process(c)}
ec.remove_whitespace_children(@tree)
@tree
end
end
end
end

View File

@@ -0,0 +1,303 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'strscan'
require 'stringio'
#TODO: use [[:alpha:]] in all regexp to allow parsing of international values in 1.9.1
#NOTE: use @src.pre_match only before other check/match?/... operations, otherwise the content is changed
module Kramdown
module Parser
# Used for parsing a document in kramdown format.
#
# If you want to extend the functionality of the parser, you need to the following:
#
# * Create a new subclass
# * add the needed parser methods
# * modify the @block_parsers and @span_parsers variables and add the names of your parser
# methods
#
# Here is a small example for an extended parser class that parses ERB style tags as raw text if
# they are used as span level elements (an equivalent block level parser should probably also be
# made to handle the block case):
#
# require 'kramdown/parser/kramdown'
#
# class Kramdown::Parser::ERBKramdown < Kramdown::Parser::Kramdown
#
# def initialize(doc)
# super(doc)
# @span_parsers.unshift(:erb_tags)
# end
#
# ERB_TAGS_START = /<%.*?%>/
#
# def parse_erb_tags
# @src.pos += @src.matched_size
# @tree.children << Element.new(:raw, @src.matched)
# end
# define_parser(:erb_tags, ERB_TAGS_START, '<%')
#
# end
#
# The new parser can be used like this:
#
# require 'kramdown/document'
# # require the file with the above parser class
#
# Kramdown::Document.new(input_text, :input => 'ERBKramdown').to_html
#
class Kramdown < Base
include ::Kramdown
attr_reader :tree
attr_reader :doc
attr_reader :options
# Create a new Kramdown parser object for the Kramdown::Document +doc+.
def initialize(doc)
super(doc)
@src = nil
@tree = nil
@stack = []
@text_type = :raw_text
@block_ial = nil
@doc.parse_infos[:ald] = {}
@doc.parse_infos[:link_defs] = {}
@doc.parse_infos[:abbrev_defs] = {}
@doc.parse_infos[:footnotes] = {}
@block_parsers = [:blank_line, :codeblock, :codeblock_fenced, :blockquote, :table, :atx_header,
:setext_header, :horizontal_rule, :list, :definition_list, :link_definition, :block_html,
:footnote_definition, :abbrev_definition, :ald, :block_math,
:block_extension, :block_ial, :eob_marker, :paragraph]
@span_parsers = [:emphasis, :codespan, :autolink, :span_html, :footnote_marker, :link, :smart_quotes, :inline_math,
:span_extension, :span_ial, :html_entity, :typographic_syms, :line_break, :escaped_chars]
end
private_class_method(:new, :allocate)
# The source string provided on initialization is parsed and the created +tree+ is returned.
def parse(source)
configure_parser
tree = Element.new(:root)
parse_blocks(tree, adapt_source(source))
update_tree(tree)
replace_abbreviations(tree)
@doc.parse_infos[:footnotes].each do |name, data|
update_tree(data[:content])
end
tree
end
#######
protected
#######
# Adapt the object to allow parsing like specified in the options.
def configure_parser
@parsers = {}
(@block_parsers + @span_parsers).each do |name|
if self.class.has_parser?(name)
@parsers[name] = self.class.parser(name)
else
raise Kramdown::Error, "Unknown parser: #{name}"
end
end
@span_start, @span_start_re = span_parser_regexps
end
# Create the needed span parser regexps.
def span_parser_regexps(parsers = @span_parsers)
span_start = /#{parsers.map {|name| @parsers[name].span_start}.join('|')}/
[span_start, /(?=#{span_start})/]
end
# Parse all block level elements in +text+ into the element +el+.
def parse_blocks(el, text = nil)
@stack.push([@tree, @src])
@tree, @src = el, (text.nil? ? @src : StringScanner.new(text))
status = catch(:stop_block_parsing) do
while !@src.eos?
block_ial_set = @block_ial
@block_parsers.any? do |name|
if @src.check(@parsers[name].start_re)
send(@parsers[name].method)
else
false
end
end || begin
warning('Warning: this should not occur - no block parser handled the line')
add_text(@src.scan(/.*\n/))
end
@block_ial = nil if block_ial_set
end
end
@tree, @src = *@stack.pop
status
end
# Update the tree by parsing all <tt>:raw_text</tt> elements with the span level parser
# (resets +@tree+, +@src+ and the +@stack+) and by updating the attributes from the IALs.
def update_tree(element)
element.children.map! do |child|
if child.type == :raw_text
@stack, @tree, @text_type = [], nil, :text
@src = StringScanner.new(child.value)
parse_spans(child)
child.children
elsif child.type == :eob
[]
else
update_tree(child)
update_attr_with_ial(child.options[:attr] ||= {}, child.options[:ial]) if child.options[:ial]
child
end
end.flatten!
end
# Parse all span level elements in the source string.
def parse_spans(el, stop_re = nil, parsers = nil, text_type = @text_type)
@stack.push([@tree, @text_type]) unless @tree.nil?
@tree, @text_type = el, text_type
span_start = @span_start
span_start_re = @span_start_re
span_start, span_start_re = span_parser_regexps(parsers) if parsers
parsers = parsers || @span_parsers
used_re = (stop_re.nil? ? span_start_re : /(?=#{Regexp.union(stop_re, span_start)})/)
stop_re_found = false
while !@src.eos? && !stop_re_found
if result = @src.scan_until(used_re)
add_text(result)
if stop_re && (stop_re_matched = @src.check(stop_re))
stop_re_found = (block_given? ? yield : true)
end
processed = parsers.any? do |name|
if @src.check(@parsers[name].start_re)
send(@parsers[name].method)
true
else
false
end
end unless stop_re_found
add_text(@src.scan(/./)) if !processed && !stop_re_found
else
add_text(@src.scan(/.*/m)) unless stop_re
break
end
end
@tree, @text_type = @stack.pop
stop_re_found
end
# Update the attributes with the information from the inline attribute list and all referenced ALDs.
def update_attr_with_ial(attr, ial)
ial[:refs].each do |ref|
update_attr_with_ial(attr, ref) if ref = @doc.parse_infos[:ald][ref]
end if ial[:refs]
attr['class'] = ((attr['class'] || '') + " #{ial['class']}").lstrip if ial['class']
ial.each {|k,v| attr[k] = v if k.kind_of?(String) && k != 'class' }
end
# Create a new block level element, taking care of applying a preceding block IAL if it exists.
def new_block_el(*args)
el = Element.new(*args)
el.options[:category] ||= :block
el.options[:ial] = @block_ial if @block_ial && el.type != :blank && el.type != :eob
el
end
@@parsers = {}
# Holds all the needed data for one block/span level parser.
Data = Struct.new(:name, :start_re, :span_start, :method)
# Add a parser method
#
# * with the given +name+,
# * using +start_re+ as start regexp
# * and, for span parsers, +span_start+ as a String that can be used in a regexp and
# which identifies the starting character(s)
#
# to the registry. The method name is automatically derived from the +name+ or can explicitly
# be set by using the +meth_name+ parameter.
def self.define_parser(name, start_re, span_start = nil, meth_name = "parse_#{name}")
raise "A parser with the name #{name} already exists!" if @@parsers.has_key?(name)
@@parsers[name] = Data.new(name, start_re, span_start, meth_name)
end
# Return the Data structure for the parser +name+.
def self.parser(name = nil)
@@parsers[name]
end
# Return +true+ if there is a parser called +name+.
def self.has_parser?(name)
@@parsers.has_key?(name)
end
INDENT = /^(?:\t| {4})/
OPT_SPACE = / {0,3}/
require 'kramdown/parser/kramdown/blank_line'
require 'kramdown/parser/kramdown/eob'
require 'kramdown/parser/kramdown/paragraph'
require 'kramdown/parser/kramdown/header'
require 'kramdown/parser/kramdown/blockquote'
require 'kramdown/parser/kramdown/table'
require 'kramdown/parser/kramdown/codeblock'
require 'kramdown/parser/kramdown/horizontal_rule'
require 'kramdown/parser/kramdown/list'
require 'kramdown/parser/kramdown/link'
require 'kramdown/parser/kramdown/attribute_list'
require 'kramdown/parser/kramdown/extension'
require 'kramdown/parser/kramdown/footnote'
require 'kramdown/parser/kramdown/html'
require 'kramdown/parser/kramdown/escaped_chars'
require 'kramdown/parser/kramdown/html_entity'
require 'kramdown/parser/kramdown/line_break'
require 'kramdown/parser/kramdown/typographic_symbol'
require 'kramdown/parser/kramdown/autolink'
require 'kramdown/parser/kramdown/codespan'
require 'kramdown/parser/kramdown/emphasis'
require 'kramdown/parser/kramdown/smart_quotes'
require 'kramdown/parser/kramdown/math'
require 'kramdown/parser/kramdown/abbreviation'
end
end
end

View File

@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
ABBREV_DEFINITION_START = /^#{OPT_SPACE}\*\[(.+?)\]:(.*?)\n/
# Parse the link definition at the current location.
def parse_abbrev_definition
@src.pos += @src.matched_size
abbrev_id, abbrev_text = @src[1], @src[2].strip
warning("Duplicate abbreviation ID '#{abbrev_id}' - overwriting") if @doc.parse_infos[:abbrev_defs][abbrev_id]
@doc.parse_infos[:abbrev_defs][abbrev_id] = abbrev_text
true
end
define_parser(:abbrev_definition, ABBREV_DEFINITION_START)
# Replace the abbreviation text with elements.
def replace_abbreviations(el, regexps = nil)
return if @doc.parse_infos[:abbrev_defs].empty?
if !regexps
regexps = [Regexp.union(*@doc.parse_infos[:abbrev_defs].keys.map {|k| /#{Regexp.escape(k)}/})]
regexps << /(?=(?:\W|^)#{regexps.first}(?!\w))/ # regexp should only match on word boundaries
end
el.children.map! do |child|
if child.type == :text
result = []
strscan = StringScanner.new(child.value)
while temp = strscan.scan_until(regexps.last)
temp += strscan.scan(/\W|^/)
abbr = strscan.scan(regexps.first)
result += [Element.new(:text, temp), Element.new(:abbreviation, abbr)]
end
result + [Element.new(:text, extract_string(strscan.pos..-1, strscan))]
else
replace_abbreviations(child, regexps)
child
end
end.flatten!
end
end
end
end

View File

@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
# Parse the string +str+ and extract all attributes and add all found attributes to the hash
# +opts+.
def parse_attribute_list(str, opts)
str.scan(ALD_TYPE_ANY).each do |key, sep, val, id_attr, class_attr, ref|
if ref
(opts[:refs] ||= []) << ref
elsif class_attr
opts['class'] = ((opts['class'] || '') + " #{class_attr}").lstrip
elsif id_attr
opts['id'] = id_attr
else
opts[key] = val.gsub(/\\(\}|#{sep})/, "\\1")
end
end
end
# Update the +ial+ with the information from the inline attribute list +opts+.
def update_ial_with_ial(ial, opts)
(ial[:refs] ||= []) << opts[:refs]
ial['class'] = ((ial['class'] || '') + " #{opts['class']}").lstrip if opts['class']
opts.each {|k,v| ial[k] = v if k != :refs && k != 'class' }
end
ALD_ID_CHARS = /[\w\d-]/
ALD_ANY_CHARS = /\\\}|[^\}]/
ALD_ID_NAME = /(?:\w|\d)#{ALD_ID_CHARS}*/
ALD_TYPE_KEY_VALUE_PAIR = /(#{ALD_ID_NAME})=("|')((?:\\\}|\\\2|[^\}\2])*?)\2/
ALD_TYPE_CLASS_NAME = /\.(#{ALD_ID_NAME})/
ALD_TYPE_ID_NAME = /#(#{ALD_ID_NAME})/
ALD_TYPE_REF = /(#{ALD_ID_NAME})/
ALD_TYPE_ANY = /(?:\A|\s)(?:#{ALD_TYPE_KEY_VALUE_PAIR}|#{ALD_TYPE_ID_NAME}|#{ALD_TYPE_CLASS_NAME}|#{ALD_TYPE_REF})(?=\s|\Z)/
ALD_START = /^#{OPT_SPACE}\{:(#{ALD_ID_NAME}):(#{ALD_ANY_CHARS}+)\}\s*?\n/
# Parse the attribute list definition at the current location.
def parse_ald
@src.pos += @src.matched_size
parse_attribute_list(@src[2], @doc.parse_infos[:ald][@src[1]] ||= {})
@tree.children << Element.new(:eob)
true
end
define_parser(:ald, ALD_START)
IAL_BLOCK_START = /^#{OPT_SPACE}\{:(?!:)(#{ALD_ANY_CHARS}+)\}\s*?\n/
# Parse the inline attribute list at the current location.
def parse_block_ial
@src.pos += @src.matched_size
if @tree.children.last && @tree.children.last.type != :blank && @tree.children.last.type != :eob
parse_attribute_list(@src[1], @tree.children.last.options[:ial] ||= {})
else
parse_attribute_list(@src[1], @block_ial = {})
end
@tree.children << Element.new(:eob) unless @src.check(IAL_BLOCK_START)
true
end
define_parser(:block_ial, IAL_BLOCK_START)
IAL_SPAN_START = /\{:(#{ALD_ANY_CHARS}+)\}/
# Parse the inline attribute list at the current location.
def parse_span_ial
@src.pos += @src.matched_size
if @tree.children.last && @tree.children.last.type != :text
attr = {}
parse_attribute_list(@src[1], attr)
update_ial_with_ial(@tree.children.last.options[:ial] ||= {}, attr)
update_attr_with_ial(@tree.children.last.options[:attr] ||= {}, attr)
else
warning("Ignoring span IAL because preceding element is just text")
end
end
define_parser(:span_ial, IAL_SPAN_START, '\{:')
end
end
end

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
if RUBY_VERSION == '1.8.5'
ACHARS = '\x80-\xFF'
else
ACHARS = ''
end
AUTOLINK_START = /<((mailto|https?|ftps?):.+?|[-.\w#{ACHARS}]+@[-\w#{ACHARS}]+(\.[-\w#{ACHARS}]+)*\.[a-z]+)>/u
# Parse the autolink at the current location.
def parse_autolink
@src.pos += @src.matched_size
href = @src[1]
href= "mailto:#{href}" if @src[2].nil?
el = Element.new(:a, nil, {:attr => {'href' => href}})
add_text(@src[1].sub(/^mailto:/, ''), el)
@tree.children << el
end
define_parser(:autolink, AUTOLINK_START, '<')
end
end
end

View File

@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
BLANK_LINE = /(?:^\s*\n)+/
# Parse the blank line at the current postition.
def parse_blank_line
@src.pos += @src.matched_size
if @tree.children.last && @tree.children.last.type == :blank
@tree.children.last.value += @src.matched
else
@tree.children << new_block_el(:blank, @src.matched)
end
true
end
define_parser(:blank_line, BLANK_LINE)
end
end
end

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
BLOCKQUOTE_START = /^#{OPT_SPACE}> ?/
BLOCKQUOTE_MATCH = /(^#{OPT_SPACE}>.*?\n)+/
# Parse the blockquote at the current location.
def parse_blockquote
result = @src.scan(BLOCKQUOTE_MATCH).gsub(BLOCKQUOTE_START, '')
el = new_block_el(:blockquote)
@tree.children << el
parse_blocks(el, result)
true
end
define_parser(:blockquote, BLOCKQUOTE_START)
end
end
end

View File

@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/parser/kramdown/blank_line'
module Kramdown
module Parser
class Kramdown
CODEBLOCK_START = INDENT
CODEBLOCK_LINE = /(?:#{INDENT}.*?\S.*?\n)+/
CODEBLOCK_MATCH = /(?:#{BLANK_LINE}?#{CODEBLOCK_LINE})*/
# Parse the indented codeblock at the current location.
def parse_codeblock
@tree.children << new_block_el(:codeblock, @src.scan(CODEBLOCK_MATCH).gsub!(INDENT, ''))
true
end
define_parser(:codeblock, CODEBLOCK_START)
FENCED_CODEBLOCK_START = /^~{3,}/
FENCED_CODEBLOCK_MATCH = /^(~{3,})\s*?\n(.*?)^\1~*\s*?\n/m
# Parse the fenced codeblock at the current location.
def parse_codeblock_fenced
if @src.check(FENCED_CODEBLOCK_MATCH)
@src.pos += @src.matched_size
@tree.children << new_block_el(:codeblock, @src[2])
true
else
false
end
end
define_parser(:codeblock_fenced, FENCED_CODEBLOCK_START)
end
end
end

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
CODESPAN_DELIMITER = /`+/
# Parse the codespan at the current scanner location.
def parse_codespan
result = @src.scan(CODESPAN_DELIMITER)
simple = (result.length == 1)
reset_pos = @src.pos
if simple && @src.pre_match =~ /\s\Z/ && @src.match?(/\s/)
add_text(result)
return
end
text = @src.scan_until(/#{result}/)
if text
text.sub!(/#{result}\Z/, '')
if !simple
text = text[1..-1] if text[0..0] == ' '
text = text[0..-2] if text[-1..-1] == ' '
end
@tree.children << Element.new(:codespan, text)
else
@src.pos = reset_pos
add_text(result)
end
end
define_parser(:codespan, CODESPAN_DELIMITER, '`')
end
end
end

View File

@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
EMPHASIS_START = /(?:\*\*?|__?)/
# Parse the emphasis at the current location.
def parse_emphasis
result = @src.scan(EMPHASIS_START)
element = (result.length == 2 ? :strong : :em)
type = (result =~ /_/ ? '_' : '*')
reset_pos = @src.pos
if (type == '_' && @src.pre_match =~ /[[:alpha:]]\z/ && @src.check(/[[:alpha:]]/)) || @src.check(/\s/) ||
@tree.type == element || @stack.any? {|el, _| el.type == element}
add_text(result)
return
end
sub_parse = lambda do |delim, elem|
el = Element.new(elem)
stop_re = /#{Regexp.escape(delim)}/
found = parse_spans(el, stop_re) do
(@src.pre_match[-1, 1] !~ /\s/) &&
(elem != :em || !@src.match?(/#{Regexp.escape(delim*2)}(?!#{Regexp.escape(delim)})/)) &&
(type != '_' || !@src.match?(/#{Regexp.escape(delim)}[[:alpha:]]/)) && el.children.size > 0
end
[found, el, stop_re]
end
found, el, stop_re = sub_parse.call(result, element)
if !found && element == :strong && @tree.type != :em
@src.pos = reset_pos - 1
found, el, stop_re = sub_parse.call(type, :em)
end
if found
@src.scan(stop_re)
@tree.children << el
else
@src.pos = reset_pos
add_text(result)
end
end
define_parser(:emphasis, EMPHASIS_START, '\*|_')
end
end
end

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
EOB_MARKER = /^\^\s*?\n/
# Parse the EOB marker at the current location.
def parse_eob_marker
@src.pos += @src.matched_size
@tree.children << new_block_el(:eob)
true
end
define_parser(:eob_marker, EOB_MARKER)
end
end
end

View File

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
ESCAPED_CHARS = /\\([\\.*_+`()\[\]{}#!:|"'\$-])/
# Parse the backslash-escaped character at the current location.
def parse_escaped_chars
@src.pos += @src.matched_size
add_text(@src[1])
end
define_parser(:escaped_chars, ESCAPED_CHARS, '\\\\')
end
end
end

View File

@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/parser/kramdown/attribute_list'
module Kramdown
module Parser
class Kramdown
def parse_extension_start_tag(type)
@src.pos += @src.matched_size
if @src[4] || @src.matched == '{:/}'
name = (@src[4] ? "for '#{@src[4]}' " : '')
warning("Invalid extension stop tag #{name}found - ignoring it")
return
end
ext = @src[1]
opts = {}
body = nil
parse_attribute_list(@src[2] || '', opts)
if !@src[3]
stop_re = (type == :block ? /#{EXT_BLOCK_STOP_STR % ext}/ : /#{EXT_STOP_STR % ext}/)
if result = @src.scan_until(stop_re)
body = result.sub!(stop_re, '')
body.chomp! if type == :block
else
warning("No stop tag for extension '#{ext}' found - treating it as extension without body")
end
end
handle_extension(ext, opts, body, type)
end
def handle_extension(name, opts, body, type)
case name
when 'comment'
@tree.children << Element.new(:comment, body, :category => type) if body.kind_of?(String)
when 'nomarkdown'
@tree.children << Element.new(:raw, body, :category => type) if body.kind_of?(String)
when 'options'
opts.select do |k,v|
k = k.to_sym
if Kramdown::Options.defined?(k)
@doc.options[k] = Kramdown::Options.parse(k, v) rescue @doc.options[k]
false
else
true
end
end.each do |k,v|
warning("Unknown kramdown option '#{k}'")
end
else
warning("Invalid extension name '#{name}' specified - ignoring extension")
end
end
EXT_STOP_STR = "\\{:/(%s)?\\}"
EXT_START_STR = "\\{::(\\w+)(?:\\s(#{ALD_ANY_CHARS}*?)|)(\\/)?\\}"
EXT_SPAN_START = /#{EXT_START_STR}|#{EXT_STOP_STR % ALD_ID_NAME}/
EXT_BLOCK_START = /^#{OPT_SPACE}(?:#{EXT_START_STR}|#{EXT_STOP_STR % ALD_ID_NAME})\s*?\n/
EXT_BLOCK_STOP_STR = "^#{OPT_SPACE}#{EXT_STOP_STR}\s*?\n"
# Parse the extension block at the current location.
def parse_block_extension
parse_extension_start_tag(:block)
true
end
define_parser(:block_extension, EXT_BLOCK_START)
# Parse the extension span at the current location.
def parse_span_extension
parse_extension_start_tag(:span)
end
define_parser(:span_extension, EXT_SPAN_START, '\{:[:/]')
end
end
end

View File

@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/parser/kramdown/attribute_list'
require 'kramdown/parser/kramdown/blank_line'
require 'kramdown/parser/kramdown/codeblock'
module Kramdown
module Parser
class Kramdown
FOOTNOTE_DEFINITION_START = /^#{OPT_SPACE}\[\^(#{ALD_ID_NAME})\]:\s*?(.*?\n(?:#{BLANK_LINE}?#{CODEBLOCK_LINE})*)/
# Parse the foot note definition at the current location.
def parse_footnote_definition
@src.pos += @src.matched_size
el = Element.new(:footnote_def)
parse_blocks(el, @src[2].gsub(INDENT, ''))
warning("Duplicate footnote name '#{@src[1]}' - overwriting") if @doc.parse_infos[:footnotes][@src[1]]
(@doc.parse_infos[:footnotes][@src[1]] = {})[:content] = el
true
end
define_parser(:footnote_definition, FOOTNOTE_DEFINITION_START)
FOOTNOTE_MARKER_START = /\[\^(#{ALD_ID_NAME})\]/
# Parse the footnote marker at the current location.
def parse_footnote_marker
@src.pos += @src.matched_size
fn_def = @doc.parse_infos[:footnotes][@src[1]]
if fn_def
valid = fn_def[:marker] && fn_def[:marker].options[:stack][0..-2].zip(fn_def[:marker].options[:stack][1..-1]).all? do |par, child|
par.children.include?(child)
end
if !fn_def[:marker] || !valid
fn_def[:marker] = Element.new(:footnote, nil, :name => @src[1])
fn_def[:marker].options[:stack] = [@stack.map {|s| s.first}, @tree, fn_def[:marker]].flatten.compact
@tree.children << fn_def[:marker]
else
warning("Footnote marker '#{@src[1]}' already appeared in document, ignoring newly found marker")
add_text(@src.matched)
end
else
warning("Footnote definition for '#{@src[1]}' not found")
add_text(@src.matched)
end
end
define_parser(:footnote_marker, FOOTNOTE_MARKER_START, '\[')
end
end
end

View File

@@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
HEADER_ID=/(?:[ \t]\{#((?:\w|\d)[\w\d-]*)\})?/
SETEXT_HEADER_START = /^(#{OPT_SPACE}[^ \t].*?)#{HEADER_ID}[ \t]*?\n(-|=)+\s*?\n/
# Parse the Setext header at the current location.
def parse_setext_header
if @tree.children.last && @tree.children.last.type != :blank
return false
end
@src.pos += @src.matched_size
text, id, level = @src[1].strip, @src[2], @src[3]
el = new_block_el(:header, nil, :level => (level == '-' ? 2 : 1), :raw_text => text)
add_text(text, el)
el.options[:attr] = {'id' => id} if id
@tree.children << el
true
end
define_parser(:setext_header, SETEXT_HEADER_START)
ATX_HEADER_START = /^\#{1,6}/
ATX_HEADER_MATCH = /^(\#{1,6})(.+?)\s*?#*#{HEADER_ID}\s*?\n/
# Parse the Atx header at the current location.
def parse_atx_header
if @tree.children.last && @tree.children.last.type != :blank
return false
end
result = @src.scan(ATX_HEADER_MATCH)
level, text, id = @src[1], @src[2].strip, @src[3]
el = new_block_el(:header, nil, :level => level.length, :raw_text => text)
add_text(text, el)
el.options[:attr] = {'id' => id} if id
@tree.children << el
true
end
define_parser(:atx_header, ATX_HEADER_START)
end
end
end

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
HR_START = /^#{OPT_SPACE}(\*|-|_)[ \t]*\1[ \t]*\1[ \t]*(\1|[ \t])*\n/
# Parse the horizontal rule at the current location.
def parse_horizontal_rule
@src.pos += @src.matched_size
@tree.children << new_block_el(:hr)
true
end
define_parser(:horizontal_rule, HR_START)
end
end
end

View File

@@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/parser/html'
module Kramdown
module Parser
class Kramdown
include Kramdown::Parser::Html::Parser
def handle_kramdown_html_tag(el, closed)
parse_type = if @tree.type != :html_element || @tree.options[:parse_type] != :raw
(@doc.options[:parse_block_html] ? HTML_PARSE_AS[el.value] : :raw)
else
:raw
end
if val = html_parse_type(el.options[:attr].delete('markdown'))
parse_type = (val == :default ? HTML_PARSE_AS[el.value] : val)
end
@src.scan(/[ \t]*\n/) if parse_type == :block
el.options[:outer_element] = true if @tree.type != :html_element
el.options[:parent_is_raw] = true if @tree.type == :html_element && @tree.options[:parse_type] == :raw
el.options[:parse_type] = parse_type
if !closed
if parse_type == :block
end_tag_found = parse_blocks(el)
if !end_tag_found
warning("Found no end tag for '#{el.value}' - auto-closing it")
end
elsif parse_type == :span
curpos = @src.pos
if result = @src.scan_until(/(?=<\/#{el.value}\s*>)/m)
add_text(extract_string(curpos...@src.pos, @src), el)
@src.scan(HTML_TAG_CLOSE_RE)
else
add_text(@src.scan(/.*/m), el)
warning("Found no end tag for '#{el.value}' - auto-closing it")
end
else
parse_raw_html(el, &method(:handle_kramdown_html_tag))
end
@src.scan(/[ \t]*\n/) unless (@tree.type == :html_element && @tree.options[:parse_type] == :raw)
end
end
# Return the HTML parse type defined by the string +val+, i.e. raw when "0", default parsing
# (return value +nil+) when "1", span parsing when "span" and block parsing when "block". If
# +val+ is nil, then the default parsing mode is used.
def html_parse_type(val)
case val
when "0" then :raw
when "1" then :default
when "span" then :span
when "block" then :block
when NilClass then nil
else
warning("Invalid markdown attribute val '#{val}', using default")
nil
end
end
HTML_BLOCK_START = /^#{OPT_SPACE}<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/
# Parse the HTML at the current position as block level HTML.
def parse_block_html
if result = @src.scan(HTML_COMMENT_RE)
@tree.children << Element.new(:xml_comment, result, :category => :block)
@src.scan(/[ \t]*\n/)
true
elsif result = @src.scan(HTML_INSTRUCTION_RE)
@tree.children << Element.new(:xml_pi, result, :category => :block)
@src.scan(/[ \t]*\n/)
true
else
if result = @src.check(/^#{OPT_SPACE}#{HTML_TAG_RE}/) && !HTML_SPAN_ELEMENTS.include?(@src[1])
@src.pos += @src.matched_size
handle_html_start_tag(&method(:handle_kramdown_html_tag))
Kramdown::Parser::Html::ElementConverter.new(@doc).process(@tree.children.last) if @doc.options[:html_to_native]
true
elsif result = @src.check(/^#{OPT_SPACE}#{HTML_TAG_CLOSE_RE}/) && !HTML_SPAN_ELEMENTS.include?(@src[1])
@src.pos += @src.matched_size
name = @src[1]
if @tree.type == :html_element && @tree.value == name
throw :stop_block_parsing, :found
else
warning("Found invalidly used HTML closing tag for '#{name}' - ignoring it")
true
end
else
false
end
end
end
define_parser(:block_html, HTML_BLOCK_START)
HTML_SPAN_START = /<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/
# Parse the HTML at the current position as span level HTML.
def parse_span_html
if result = @src.scan(HTML_COMMENT_RE)
@tree.children << Element.new(:xml_comment, result, :category => :span)
elsif result = @src.scan(HTML_INSTRUCTION_RE)
@tree.children << Element.new(:xml_pi, result, :category => :span)
elsif result = @src.scan(HTML_TAG_CLOSE_RE)
warning("Found invalidly used HTML closing tag for '#{@src[1]}' - ignoring it")
elsif result = @src.scan(HTML_TAG_RE)
return if HTML_BLOCK_ELEMENTS.include?(@src[1])
reset_pos = @src.pos
attrs = {}
@src[2].scan(HTML_ATTRIBUTE_RE).each {|name,sep,val| attrs[name] = val.gsub(/\n+/, ' ')}
do_parsing = (HTML_PARSE_AS_RAW.include?(@src[1]) || @tree.options[:parse_type] == :raw ? false : @doc.options[:parse_span_html])
if val = html_parse_type(attrs.delete('markdown'))
if val == :block
warning("Cannot use block level parsing in span level HTML tag - using default mode")
elsif val == :span
do_parsing = true
elsif val == :default
do_parsing = !HTML_PARSE_AS_RAW.include?(@src[1])
elsif val == :raw
do_parsing = false
end
end
el = Element.new(:html_element, @src[1], :attr => attrs, :category => :span, :parse_type => (do_parsing ? :span : :raw))
@tree.children << el
stop_re = /<\/#{Regexp.escape(@src[1])}\s*>/
if !@src[4] && HTML_ELEMENTS_WITHOUT_BODY.include?(el.value)
warning("The HTML tag '#{el.value}' cannot have any content - auto-closing it")
elsif !@src[4]
if parse_spans(el, stop_re, (do_parsing ? nil : [:span_html]))
@src.scan(stop_re)
else
warning("Found no end tag for '#{el.value}' - auto-closing it")
add_text(@src.scan(/.*/m), el)
end
end
Kramdown::Parser::Html::ElementConverter.new(@doc).process(el) if @doc.options[:html_to_native]
else
add_text(@src.scan(/./))
end
end
define_parser(:span_html, HTML_SPAN_START, '<')
end
end
end

View File

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/parser/html'
module Kramdown
module Parser
class Kramdown
# Parse the HTML entity at the current location.
def parse_html_entity
@src.pos += @src.matched_size
@tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity(@src[1] || (@src[2] && @src[2].to_i) || @src[3].hex))
end
define_parser(:html_entity, Kramdown::Parser::Html::Constants::HTML_ENTITY_RE, '&')
end
end
end

View File

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
LINE_BREAK = /( |\\\\)(?=\n)/
# Parse the line break at the current location.
def parse_line_break
@src.pos += @src.matched_size
@tree.children << Element.new(:br)
end
define_parser(:line_break, LINE_BREAK, '( |\\\\)(?=\n)')
end
end
end

View File

@@ -0,0 +1,156 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
PUNCTUATION_CHARS = "_.:,;!?-"
LINK_ID_CHARS = /[a-zA-Z0-9 #{PUNCTUATION_CHARS}]/
LINK_ID_NON_CHARS = /[^a-zA-Z0-9 #{PUNCTUATION_CHARS}]/
LINK_DEFINITION_START = /^#{OPT_SPACE}\[(#{LINK_ID_CHARS}+)\]:[ \t]*(?:<(.*?)>|([^\s]+))[ \t]*?(?:\n?[ \t]*?(["'])(.+?)\4[ \t]*?)?\n/
# Parse the link definition at the current location.
def parse_link_definition
@src.pos += @src.matched_size
link_id, link_url, link_title = @src[1].downcase, @src[2] || @src[3], @src[5]
warning("Duplicate link ID '#{link_id}' - overwriting") if @doc.parse_infos[:link_defs][link_id]
@doc.parse_infos[:link_defs][link_id] = [link_url, link_title]
true
end
define_parser(:link_definition, LINK_DEFINITION_START)
# This helper methods adds the approriate attributes to the element +el+ of type +a+ or +img+
# and the element itself to the <tt>@tree</tt>.
def add_link(el, href, title, alt_text = nil)
el.options[:attr] ||= {}
el.options[:attr]['title'] = title if title
if el.type == :a
el.options[:attr]['href'] = href
else
el.options[:attr]['src'] = href
el.options[:attr]['alt'] = alt_text
el.children.clear
end
@tree.children << el
end
LINK_TEXT_BRACKET_RE = /\\\[|\\\]|\[|\]/
LINK_INLINE_ID_RE = /\s*?\[(#{LINK_ID_CHARS}+)?\]/
LINK_INLINE_TITLE_RE = /\s*?(["'])(.+?)\1\s*?\)/
LINK_START = /!?\[(?=[^^])/
# Parse the link at the current scanner position. This method is used to parse normal links as
# well as image links.
def parse_link
result = @src.scan(LINK_START)
reset_pos = @src.pos
link_type = (result =~ /^!/ ? :img : :a)
# no nested links allowed
if link_type == :a && (@tree.type == :img || @tree.type == :a || @stack.any? {|t,s| t && (t.type == :img || t.type == :a)})
add_text(result)
return
end
el = Element.new(link_type)
stop_re = /\]|!?\[/
count = 1
found = parse_spans(el, stop_re) do
case @src.matched
when "[", "!["
count += 1
when "]"
count -= 1
end
count - el.children.select {|c| c.type == :img}.size == 0
end
if !found || (link_type == :a && el.children.empty?)
@src.pos = reset_pos
add_text(result)
return
end
alt_text = extract_string(reset_pos...@src.pos, @src)
conv_link_id = alt_text.gsub(/(\s|\n)+/m, ' ').gsub(LINK_ID_NON_CHARS, '').downcase
@src.scan(stop_re)
# reference style link or no link url
if @src.scan(LINK_INLINE_ID_RE) || !@src.check(/\(/)
link_id = (@src[1] || conv_link_id).downcase
if link_id.empty?
@src.pos = reset_pos
add_text(result)
elsif @doc.parse_infos[:link_defs].has_key?(link_id)
add_link(el, @doc.parse_infos[:link_defs][link_id].first, @doc.parse_infos[:link_defs][link_id].last, alt_text)
else
warning("No link definition for link ID '#{link_id}' found")
@src.pos = reset_pos
add_text(result)
end
return
end
# link url in parentheses
if @src.scan(/\(<(.*?)>/)
link_url = @src[1]
if @src.scan(/\)/)
add_link(el, link_url, nil, alt_text)
return
end
else
link_url = ''
re = /\(|\)|\s/
nr_of_brackets = 0
while temp = @src.scan_until(re)
link_url += temp
case @src.matched
when /\s/
break
when '('
nr_of_brackets += 1
when ')'
nr_of_brackets -= 1
break if nr_of_brackets == 0
end
end
link_url = link_url[1..-2]
if nr_of_brackets == 0
add_link(el, link_url, nil, alt_text)
return
end
end
if @src.scan(LINK_INLINE_TITLE_RE)
add_link(el, link_url, @src[2], alt_text)
else
@src.pos = reset_pos
add_text(result)
end
end
define_parser(:link, LINK_START, '!?\[')
end
end
end

View File

@@ -0,0 +1,232 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/parser/kramdown/blank_line'
require 'kramdown/parser/kramdown/eob'
require 'kramdown/parser/kramdown/horizontal_rule'
require 'kramdown/parser/kramdown/attribute_list'
module Kramdown
module Parser
class Kramdown
# Used for parsing the first line of a list item or a definition, i.e. the line with list item
# marker or the definition marker.
def parse_first_list_line(indentation, content)
if content =~ /^\s*(#{IAL_SPAN_START})?\s*\n/
indentation = 4
else
while content =~ /^ *\t/
temp = content.scan(/^ */).first.length + indentation
content.sub!(/^( *)(\t+)/) {$1 + " "*(4 - (temp % 4)) + " "*($2.length - 1)*4}
end
indentation += content.scan(/^ */).first.length
end
content.sub!(/^\s*/, '')
indent_re = /^ {#{indentation}}/
content_re = /^(?:(?:\t| {4}){#{indentation / 4}} {#{indentation % 4}}|(?:\t| {4}){#{indentation / 4 + 1}}).*?\n/
[content, indentation, content_re, indent_re]
end
LIST_START_UL = /^(#{OPT_SPACE}[+*-])([\t| ].*?\n)/
LIST_START_OL = /^(#{OPT_SPACE}\d+\.)([\t| ].*?\n)/
LIST_START = /#{LIST_START_UL}|#{LIST_START_OL}/
# Parse the ordered or unordered list at the current location.
def parse_list
if @tree.children.last && @tree.children.last.type == :p # last element must not be a paragraph
return false
end
type, list_start_re = (@src.check(LIST_START_UL) ? [:ul, LIST_START_UL] : [:ol, LIST_START_OL])
list = new_block_el(type)
item = nil
indent_re = nil
content_re = nil
eob_found = false
nested_list_found = false
while !@src.eos?
if @src.check(HR_START)
break
elsif @src.scan(list_start_re)
item = Element.new(:li)
item.value, indentation, content_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
list.children << item
item.value.sub!(/^#{IAL_SPAN_START}\s*/) do |match|
parse_attribute_list($~[1], item.options[:ial] ||= {})
''
end
list_start_re = (type == :ul ? /^( {0,#{[3, indentation - 1].min}}[+*-])([\t| ].*?\n)/ :
/^( {0,#{[3, indentation - 1].min}}\d+\.)([\t| ].*?\n)/)
nested_list_found = false
elsif result = @src.scan(content_re)
result.sub!(/^(\t+)/) { " "*4*($1 ? $1.length : 0) }
result.sub!(indent_re, '')
if !nested_list_found && result =~ LIST_START
parse_blocks(item, item.value)
if item.children.length == 1 && item.children.first.type == :p
item.value = ''
else
item.children.clear
end
nested_list_found = true
end
item.value << result
elsif result = @src.scan(BLANK_LINE)
nested_list_found = true
item.value << result
elsif @src.scan(EOB_MARKER)
eob_found = true
break
else
break
end
end
@tree.children << list
last = nil
list.children.each do |it|
temp = Element.new(:temp)
parse_blocks(temp, it.value)
it.children += temp.children
it.value = nil
next if it.children.size == 0
if it.children.first.type == :p && (it.children.length < 2 || it.children[1].type != :blank ||
(it == list.children.last && it.children.length == 2 && !eob_found)) &&
(list.children.last != it || list.children.size == 1 ||
list.children[0..-2].any? {|cit| cit.children.first.type != :p || cit.children.first.options[:transparent]})
it.children.first.children.first.value += "\n" if it.children.size > 1 && it.children[1].type != :blank
it.children.first.options[:transparent] = true
end
if it.children.last.type == :blank
last = it.children.pop
else
last = nil
end
end
@tree.children << last if !last.nil? && !eob_found
true
end
define_parser(:list, LIST_START)
DEFINITION_LIST_START = /^(#{OPT_SPACE}:)([\t| ].*?\n)/
# Parse the ordered or unordered list at the current location.
def parse_definition_list
children = @tree.children
if !children.last || (children.length == 1 && children.last.type != :p ) ||
(children.length >= 2 && children[-1].type != :p && (children[-1].type != :blank || children[-1].value != "\n" || children[-2].type != :p))
return false
end
first_as_para = false
deflist = new_block_el(:dl)
para = @tree.children.pop
if para.type == :blank
para = @tree.children.pop
first_as_para = true
end
para.children.first.value.split("\n").each do |term|
el = Element.new(:dt)
el.children << Element.new(:raw_text, term)
deflist.children << el
end
item = nil
indent_re = nil
content_re = nil
def_start_re = DEFINITION_LIST_START
while !@src.eos?
if @src.scan(def_start_re)
item = Element.new(:dd)
item.options[:first_as_para] = first_as_para
item.value, indentation, content_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
deflist.children << item
item.value.sub!(/^#{IAL_SPAN_START}\s*/) do |match|
parse_attribute_list($~[1], item.options[:ial] ||= {})
''
end
def_start_re = /^( {0,#{[3, indentation - 1].min}}:)([\t| ].*?\n)/
first_as_para = false
elsif result = @src.scan(content_re)
result.sub!(/^(\t+)/) { " "*4*($1 ? $1.length : 0) }
result.sub!(indent_re, '')
item.value << result
first_as_para = false
elsif result = @src.scan(BLANK_LINE)
first_as_para = true
item.value << result
else
break
end
end
last = nil
deflist.children.each do |it|
next if it.type == :dt
parse_blocks(it, it.value)
it.value = nil
next if it.children.size == 0
if it.children.last.type == :blank
last = it.children.pop
else
last = nil
end
if it.children.first.type == :p && !it.options.delete(:first_as_para)
it.children.first.children.first.value += "\n" if it.children.size > 1
it.children.first.options[:transparent] = true
end
end
if @tree.children.length >= 1 && @tree.children.last.type == :dl
@tree.children[-1].children += deflist.children
elsif @tree.children.length >= 2 && @tree.children[-1].type == :blank && @tree.children[-2].type == :dl
@tree.children.pop
@tree.children[-1].children += deflist.children
else
@tree.children << deflist
end
@tree.children << last if !last.nil?
true
end
define_parser(:definition_list, DEFINITION_LIST_START)
end
end
end

View File

@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
BLOCK_MATH_START = /^#{OPT_SPACE}(\\)?\$\$(.*?)\$\$\s*?\n/m
# Parse the math block at the current location.
def parse_block_math
if @src[1]
@src.scan(/^#{OPT_SPACE}\\/)
return false
end
@src.pos += @src.matched_size
@tree.children << new_block_el(:math, @src[2], :category => :block)
true
end
define_parser(:block_math, BLOCK_MATH_START)
INLINE_MATH_START = /\$\$(.*?)\$\$/
# Parse the inline math at the current location.
def parse_inline_math
@src.pos += @src.matched_size
@tree.children << Element.new(:math, @src[1], :category => :span)
end
define_parser(:inline_math, INLINE_MATH_START, '\$')
end
end
end

View File

@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
PARAGRAPH_START = /^#{OPT_SPACE}[^ \t].*?\n/
# Parse the paragraph at the current location.
def parse_paragraph
@src.pos += @src.matched_size
if @tree.children.last && @tree.children.last.type == :p
@tree.children.last.children.first.value << "\n" << @src.matched.chomp
else
@tree.children << new_block_el(:p)
add_text(@src.matched.lstrip.chomp, @tree.children.last)
end
true
end
define_parser(:paragraph, PARAGRAPH_START)
end
end
end

View File

@@ -0,0 +1,214 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
#--
# Parts of this file are based on code from Maruku by Andrea Censi.
# The needed license statements follow:
#
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
#
# Maruku is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Maruku is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Maruku; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# NOTA BENE:
#
# The following algorithm is a rip-off of RubyPants written by
# Christian Neukirchen.
#
# RubyPants is a Ruby port of SmartyPants written by John Gruber.
#
# This file is distributed under the GPL, which I guess is compatible
# with the terms of the RubyPants license.
#
# -- Andrea Censi
#
# = RubyPants -- SmartyPants ported to Ruby
#
# Ported by Christian Neukirchen <mailto:chneukirchen@gmail.com>
# Copyright (C) 2004 Christian Neukirchen
#
# Incooporates ideas, comments and documentation by Chad Miller
# Copyright (C) 2004 Chad Miller
#
# Original SmartyPants by John Gruber
# Copyright (C) 2003 John Gruber
#
#
# = RubyPants -- SmartyPants ported to Ruby
#
#
# [snip]
#
# == Authors
#
# John Gruber did all of the hard work of writing this software in
# Perl for Movable Type and almost all of this useful documentation.
# Chad Miller ported it to Python to use with Pyblosxom.
#
# Christian Neukirchen provided the Ruby port, as a general-purpose
# library that follows the *Cloth API.
#
#
# == Copyright and License
#
# === SmartyPants license:
#
# Copyright (c) 2003 John Gruber
# (http://daringfireball.net)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name "SmartyPants" nor the names of its contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# This software is provided by the copyright holders and contributors
# "as is" and any express or implied warranties, including, but not
# limited to, the implied warranties of merchantability and fitness
# for a particular purpose are disclaimed. In no event shall the
# copyright owner or contributors be liable for any direct, indirect,
# incidental, special, exemplary, or consequential damages (including,
# but not limited to, procurement of substitute goods or services;
# loss of use, data, or profits; or business interruption) however
# caused and on any theory of liability, whether in contract, strict
# liability, or tort (including negligence or otherwise) arising in
# any way out of the use of this software, even if advised of the
# possibility of such damage.
#
# === RubyPants license
#
# RubyPants is a derivative work of SmartyPants and smartypants.py.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# This software is provided by the copyright holders and contributors
# "as is" and any express or implied warranties, including, but not
# limited to, the implied warranties of merchantability and fitness
# for a particular purpose are disclaimed. In no event shall the
# copyright owner or contributors be liable for any direct, indirect,
# incidental, special, exemplary, or consequential damages (including,
# but not limited to, procurement of substitute goods or services;
# loss of use, data, or profits; or business interruption) however
# caused and on any theory of liability, whether in contract, strict
# liability, or tort (including negligence or otherwise) arising in
# any way out of the use of this software, even if advised of the
# possibility of such damage.
#
# == Links
#
# John Gruber:: http://daringfireball.net
# SmartyPants:: http://daringfireball.net/projects/smartypants
#
# Chad Miller:: http://web.chad.org
#
# Christian Neukirchen:: http://kronavita.de/chris
#
#++
#
module Kramdown
module Parser
class Kramdown
SQ_PUNCT = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'
SQ_CLOSE = %![^\ \\\\\t\r\n\\[{(-]!
SQ_RULES = [
[/("|')(?=#{SQ_PUNCT}\B)/, [:rquote1]],
# Special case for double sets of quotes, e.g.:
# <p>He said, "'Quoted' words in a larger quote."</p>
[/(\s?)"'(?=\w)/, [1, :ldquo, :lsquo]],
[/(\s?)'"(?=\w)/, [1, :lsquo, :ldquo]],
# Special case for decade abbreviations (the '80s):
[/(\s?)'(?=\d\ds)/, [1, :rsquo]],
# Get most opening single/double quotes:
[/(\s)('|")(?=\w)/, [1, :lquote2]],
# Single/double closing quotes:
[/(#{SQ_CLOSE})('|")/, [1, :rquote2]],
# Special case for e.g. "<i>Custer</i>'s Last Stand."
[/("|')(\s|s\b|$)/, [:rquote1, 2]],
# Any remaining single quotes should be opening ones:
[/(.?)'/m, [1, :lsquo]],
[/(.?)"/m, [1, :ldquo]],
] #'"
SQ_SUBSTS = {
[:rquote1, '"'] => :rdquo,
[:rquote1, "'"] => :rsquo,
[:rquote2, '"'] => :rdquo,
[:rquote2, "'"] => :rsquo,
[:lquote1, '"'] => :ldquo,
[:lquote1, "'"] => :lsquo,
[:lquote2, '"'] => :ldquo,
[:lquote2, "'"] => :lsquo,
}
SMART_QUOTES_RE = /[^\\]?["']/
# Parse the smart quotes at current location.
def parse_smart_quotes
regexp, substs = SQ_RULES.find {|reg, subst| @src.scan(reg)}
substs.each do |subst|
if subst.kind_of?(Integer)
add_text(@src[subst].to_s)
else
val = SQ_SUBSTS[[subst, @src[subst.to_s[-1,1].to_i]]] || subst
@tree.children << Element.new(:smart_quote, val)
end
end
end
define_parser(:smart_quotes, SMART_QUOTES_RE, '[^\\\\]?["\']')
end
end
end

View File

@@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
require 'kramdown/parser/kramdown/blank_line'
require 'kramdown/parser/kramdown/eob'
require 'kramdown/parser/kramdown/horizontal_rule'
module Kramdown
module Parser
class Kramdown
TABLE_SEP_LINE = /^#{OPT_SPACE}(?:\||\+)([ ]?:?-[+|: -]*)[ \t]*\n/
TABLE_HSEP_ALIGN = /[ ]?(:?)-+(:?)[ ]?/
TABLE_FSEP_LINE = /^#{OPT_SPACE}(\||\+)[ ]?:?=[+|: =]*[ \t]*\n/
TABLE_ROW_LINE = /^#{OPT_SPACE}\|(.*?)[ \t]*\n/
TABLE_START = /^#{OPT_SPACE}\|(?:-|(?!=))/
# Parse the table at the current location.
def parse_table
orig_pos = @src.pos
table = new_block_el(:table, nil, :alignment => [])
@src.scan(TABLE_SEP_LINE)
rows = []
has_footer = false
columns = 0
add_container = lambda do |type, force|
if force || type != :tbody || !has_footer
cont = Element.new(type)
cont.children, rows = rows, []
table.children << cont
end
end
while !@src.eos?
if @src.scan(TABLE_SEP_LINE) && !rows.empty?
if table.options[:alignment].empty? && !has_footer
add_container.call(:thead, false)
table.options[:alignment] = @src[1].scan(TABLE_HSEP_ALIGN).map do |left, right|
(left.empty? && right.empty? && :default) || (right.empty? && :left) || (left.empty? && :right) || :center
end
else # treat as normal separator line
add_container.call(:tbody, false)
end
elsif @src.scan(TABLE_FSEP_LINE)
add_container.call(:tbody, true) if !rows.empty?
has_footer = true
elsif @src.scan(TABLE_ROW_LINE)
trow = Element.new(:tr)
cells = (@src[1] + ' ').split(/\|/)
i = 0
while i < cells.length - 1
backslashes = cells[i].scan(/\\+$/).first
if backslashes && backslashes.length % 2 == 1
cells[i] = cells[i].chop + '|' + cells[i+1]
cells.delete_at(i+1)
else
i += 1
end
end
cells.pop if cells.last.strip.empty?
cells.each do |cell_text|
tcell = Element.new(:td)
tcell.children << Element.new(:raw_text, cell_text.strip)
trow.children << tcell
end
columns = [columns, cells.length].max
rows << trow
else
break
end
end
add_container.call(has_footer ? :tfoot : :tbody, false) if !rows.empty?
if !table.children.any? {|c| c.type == :tbody}
warning("Found table without body - ignoring it")
@src.pos = orig_pos
return false
end
# adjust all table rows to have equal number of columns, same for alignment defs
table.children.each do |kind|
kind.children.each do |row|
(columns - row.children.length).times do
row.children << Element.new(:td)
end
row.children.each {|el| el.type = :th} if kind.type == :thead
end
end
if table.options[:alignment].length > columns
table.options[:alignment] = table.options[:alignment][0...columns]
else
table.options[:alignment] += [:default] * (columns - table.options[:alignment].length)
end
@tree.children << table
true
end
define_parser(:table, TABLE_START)
end
end
end

View File

@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Parser
class Kramdown
TYPOGRAPHIC_SYMS = [['---', :mdash], ['--', :ndash], ['...', :hellip],
['\\<<', '&lt;&lt;'], ['\\>>', '&gt;&gt;'],
['<< ', :laquo_space], [' >>', :raquo_space],
['<<', :laquo], ['>>', :raquo]]
TYPOGRAPHIC_SYMS_SUBST = Hash[*TYPOGRAPHIC_SYMS.flatten]
TYPOGRAPHIC_SYMS_RE = /#{TYPOGRAPHIC_SYMS.map {|k,v| Regexp.escape(k)}.join('|')}/
# Parse the typographic symbols at the current location.
def parse_typographic_syms
@src.pos += @src.matched_size
val = TYPOGRAPHIC_SYMS_SUBST[@src.matched]
if val.kind_of?(Symbol)
@tree.children << Element.new(:typographic_sym, val)
elsif @src.matched == '\\<<'
@tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'))
@tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'))
else
@tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'))
@tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'))
end
end
define_parser(:typographic_syms, TYPOGRAPHIC_SYMS_RE, '--|\\.\\.\\.|(?:\\\\| )?(?:<<|>>)')
end
end
end

View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
# == Utils Module
#
# This module contains utility class/modules/methods that can be used by both parsers and
# converters.
module Utils
autoload :Entities, 'kramdown/utils/entities'
autoload :HTML, 'kramdown/utils/html'
end
end

View File

@@ -0,0 +1,338 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Utils
module Entities
class Entity < Struct.new(:code_point, :name)
def char
[code_point].pack('U*') rescue nil
end
end
ENTITY_TABLE = [
[913, 'Alpha'],
[914, 'Beta'],
[915, 'Gamma'],
[916, 'Delta'],
[917, 'Epsilon'],
[918, 'Zeta'],
[919, 'Eta'],
[920, 'Theta'],
[921, 'Iota'],
[922, 'Kappa'],
[923, 'Lambda'],
[924, 'Mu'],
[925, 'Nu'],
[926, 'Xi'],
[927, 'Omicron'],
[928, 'Pi'],
[929, 'Rho'],
[931, 'Sigma'],
[932, 'Tau'],
[933, 'Upsilon'],
[934, 'Phi'],
[935, 'Chi'],
[936, 'Psi'],
[937, 'Omega'],
[945, 'alpha'],
[946, 'beta'],
[947, 'gamma'],
[948, 'delta'],
[949, 'epsilon'],
[950, 'zeta'],
[951, 'eta'],
[952, 'theta'],
[953, 'iota'],
[954, 'kappa'],
[955, 'lambda'],
[956, 'mu'],
[957, 'nu'],
[958, 'xi'],
[959, 'omicron'],
[960, 'pi'],
[961, 'rho'],
[963, 'sigma'],
[964, 'tau'],
[965, 'upsilon'],
[966, 'phi'],
[967, 'chi'],
[968, 'psi'],
[969, 'omega'],
[962, 'sigmaf'],
[977, 'thetasym'],
[982, 'piv'],
[8230, 'hellip'],
[8242, 'prime'],
[8254, 'oline'],
[8260, 'frasl'],
[8472, 'weierp'],
[8465, 'image'],
[8476, 'real'],
[8501, 'alefsym'],
[8226, 'bull'],
[8482, 'trade'],
[8592, 'larr'],
[8594, 'rarr'],
[8593, 'uarr'],
[8595, 'darr'],
[8596, 'harr'],
[8629, 'crarr'],
[8657, 'uArr'],
[8659, 'dArr'],
[8656, 'lArr'],
[8658, 'rArr'],
[8660, 'hArr'],
[8704, 'forall'],
[8706, 'part'],
[8707, 'exist'],
[8709, 'empty'],
[8711, 'nabla'],
[8712, 'isin'],
[8715, 'ni'],
[8713, 'notin'],
[8721, 'sum'],
[8719, 'prod'],
[8722, 'minus'],
[8727, 'lowast'],
[8730, 'radic'],
[8733, 'prop'],
[8734, 'infin'],
[8736, 'ang'],
[8743, 'and'],
[8744, 'or'],
[8745, 'cup'],
[8746, 'cap'],
[8747, 'int'],
[8756, 'there4'],
[8764, 'sim'],
[8776, 'asymp'],
[8773, 'cong'],
[8800, 'ne'],
[8801, 'equiv'],
[8804, 'le'],
[8805, 'ge'],
[8834, 'sub'],
[8835, 'sup'],
[8838, 'sube'],
[8839, 'supe'],
[8836, 'nsub'],
[8853, 'oplus'],
[8855, 'otimes'],
[8869, 'perp'],
[8901, 'sdot'],
[8968, 'rceil'],
[8969, 'lceil'],
[8970, 'lfloor'],
[8971, 'rfloor'],
[9001, 'rang'],
[9002, 'lang'],
[9674, 'loz'],
[9824, 'spades'],
[9827, 'clubs'],
[9829, 'hearts'],
[9830, 'diams'],
[38, 'amp'],
[34, 'quot'],
[39, 'apos'],
[169, 'copy'],
[60, 'lt'],
[62, 'gt'],
[338, 'OElig'],
[339, 'oelig'],
[352, 'Scaron'],
[353, 'scaron'],
[376, 'Yuml'],
[710, 'circ'],
[732, 'tilde'],
[8211, 'ndash'],
[8212, 'mdash'],
[8216, 'lsquo'],
[8217, 'rsquo'],
[8220, 'ldquo'],
[8221, 'rdquo'],
[8224, 'dagger'],
[8225, 'Dagger'],
[8240, 'permil'],
[8364, 'euro'],
[8249, 'lsaquo'],
[8250, 'rsaquo'],
[160, 'nbsp'],
[161, 'iexcl'],
[163, 'pound'],
[164, 'curren'],
[165, 'yen'],
[166, 'brvbar'],
[167, 'sect'],
[171, 'laquo'],
[187, 'raquo'],
[174, 'reg'],
[170, 'ordf'],
[172, 'not'],
[176, 'deg'],
[177, 'plusmn'],
[180, 'acute'],
[181, 'micro'],
[182, 'para'],
[183, 'middot'],
[186, 'ordm'],
[162, 'cent'],
[185, 'sup1'],
[178, 'sup2'],
[179, 'sup3'],
[189, 'frac12'],
[188, 'frac14'],
[190, 'frac34'],
[192, 'Agrave'],
[193, 'Aacute'],
[194, 'Acirc'],
[195, 'Atilde'],
[196, 'Auml'],
[197, 'Aring'],
[198, 'AElig'],
[199, 'Ccedil'],
[200, 'Egrave'],
[201, 'Eacute'],
[202, 'Ecirc'],
[203, 'Euml'],
[204, 'Igrave'],
[205, 'Iacute'],
[206, 'Icirc'],
[207, 'Iuml'],
[208, 'ETH'],
[209, 'Ntilde'],
[210, 'Ograve'],
[211, 'Oacute'],
[212, 'Ocirc'],
[213, 'Otilde'],
[214, 'Ouml'],
[215, 'times'],
[216, 'Oslash'],
[217, 'Ugrave'],
[218, 'Uacute'],
[219, 'Ucirc'],
[220, 'Uuml'],
[221, 'Yacute'],
[222, 'THORN'],
[223, 'szlig'],
[224, 'agrave'],
[225, 'aacute'],
[226, 'acirc'],
[227, 'atilde'],
[228, 'auml'],
[229, 'aring'],
[230, 'aelig'],
[231, 'ccedil'],
[232, 'egrave'],
[233, 'eacute'],
[234, 'ecirc'],
[235, 'euml'],
[236, 'igrave'],
[237, 'iacute'],
[238, 'icirc'],
[239, 'iuml'],
[240, 'eth'],
[241, 'ntilde'],
[242, 'ograve'],
[243, 'oacute'],
[244, 'ocirc'],
[245, 'otilde'],
[246, 'ouml'],
[247, 'divide'],
[248, 'oslash'],
[249, 'ugrave'],
[250, 'uacute'],
[251, 'ucirc'],
[252, 'uuml'],
[253, 'yacute'],
[254, 'thorn'],
[255, 'yuml'],
[8218, 'sbquo'],
[402, 'fnof'],
[8222, 'bdquo'],
[381, 'Zcaron'],
[382, 'zcaron'],
[128, 8364],
[130, 8218],
[131, 402],
[132, 8222],
[133, 8230],
[134, 8224],
[135, 8225],
[136, 710],
[137, 8240],
[138, 352],
[139, 8249],
[140, 338],
[142, 381],
[145, 8216],
[146, 8217],
[147, 8220],
[148, 8221],
[149, 8226],
[150, 8211],
[151, 8212],
[152, 732],
[153, 8482],
[154, 353],
[155, 8250],
[156, 339],
[158, 382],
[159, 376],
]
ENTITY_MAP = Hash.new do |h,k|
if k.kind_of?(Integer)
h[k] = Entity.new(k, nil)
else
raise Kramdown::Error, "Can't handle generic non-integer character reference '#{k}'"
end
end
ENTITY_TABLE.each do |code_point, data|
if data.kind_of?(String)
ENTITY_MAP[code_point] = ENTITY_MAP[data] = Entity.new(code_point, data)
else
raise "No entity object for code point #{data} found" unless ENTITY_MAP.has_key?(data)
ENTITY_MAP[code_point] = ENTITY_MAP[data]
end
end
# Return the entity for the given +point_or_name+.
def entity(point_or_name)
ENTITY_MAP[point_or_name]
end
module_function :entity
end
end
end

View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
module Utils
module HTML
# Convert the +entity+ to a string.
def entity_to_str(e)
if RUBY_VERSION >= '1.9' && (c = e.char.encode(@doc.parse_infos[:encoding]) rescue nil) && !ESCAPE_MAP.has_key?(c)
c
elsif @doc.options[:numeric_entities] || e.name.nil?
"&##{e.code_point};"
else
"&#{e.name};"
end
end
# Return the string with the attributes of the element +el+.
def html_attributes(el)
(el.options[:attr] || {}).map {|k,v| v.nil? ? '' : " #{k}=\"#{escape_html(v.to_s, :no_entities)}\"" }.sort.join('')
end
ESCAPE_MAP = {
'<' => '&lt;',
'>' => '&gt;',
'&' => '&amp;',
'"' => '&quot;'
}
ESCAPE_ALL_RE = Regexp.union(*ESCAPE_MAP.collect {|k,v| k})
ESCAPE_NO_ENTITIES_RE = Regexp.union(REXML::Parsers::BaseParser::REFERENCE_RE, ESCAPE_ALL_RE)
ESCAPE_NORMAL = Regexp.union(REXML::Parsers::BaseParser::REFERENCE_RE, /<|>|&/)
ESCAPE_RE_FROM_TYPE = {
:all => ESCAPE_ALL_RE,
:no_entities => ESCAPE_NO_ENTITIES_RE,
:text => ESCAPE_NORMAL
}
# Escape the special HTML characters in the string +str+. The parameter +type+ specifies what
# is escaped: <tt>:all</tt> - all special HTML characters as well as entities,
# <tt>:no_entities</tt> - all special HTML characters but no entities, <tt>:text</tt> - all
# special HTML characters except the quotation mark but no entities.
def escape_html(str, type = :all)
str.gsub(ESCAPE_RE_FROM_TYPE[type]) {|m| ESCAPE_MAP[m] || m}
end
end
end
end

View File

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown.
#
# kramdown is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
#
module Kramdown
# The kramdown version.
VERSION = '0.9.0'
end

View File

@@ -0,0 +1,44 @@
body div#container {
margin : 0 auto;
max-width : 920px;
background-color : #f8f8f8;
padding : .7em;
font-size : 13.34px;
font-family : verdana, sans-serif;
border : 1px #E0E0E0 solid;
}
body div#container h2, body div#container h3, body div#content h4 {
padding-top : 10px;
border-top : 4px solid #E0E0E0;
}
body div#container pre {
padding : 5px;
border-style : solid;
border-width : 1px;
border-color : #E0E0E0;
background-color : #F8F8FF;
}
body div#container pre code {
padding : 5px;
background-color : #F8F8FF;
border : none;
}
body div#container code {
font-family : courier, fixed;
display : inline-block;
padding : 0px 2px 0px 2px;
background-color : #F8F8FF;
border : 1px #E0E0E0 solid;
}
body h4#title {
font-family : verdana, sans-serif;
display : block;
margin : 0 auto;
width : 920px;
}

View File

@@ -0,0 +1,487 @@
@media print {
/* print.css from blueprint CSS framework */
.page {
margin-left: 0.1in;
margin-right: 0.1in;
margin-top: 2in;
}
body {
line-height:1.5;
font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;
font-family: Georgia, Times, serif;
color:#000;
background:none;
font-size:12pt;
}
.container {
background:none;
}
hr {
background:#ccc;
color:#ccc;
width:100%;
height:2px;
margin:2em 0;
padding:0;
border:none;
}
hr.space {
background:#fff;
color:#fff;
visibility:hidden;
}
h1, h2, h3, h4, h5, h6 {
font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;
}
code {
font:.9em "Courier New", Monaco, Courier, monospace;
}
pre {
line-height:0.8;
}
a img {
border:none;
}
p img.top {
margin-top:0;
}
blockquote {
margin:1.5em;
padding:1em;
font-style:italic;
font-size:.9em;
}
.small {
font-size:.9em;
}
.large {
font-size:1.1em;
}
.quiet {
color:#999;
}
.hide {display:none;}
a:link, a:visited {
background:transparent;font-weight:700;text-decoration:underline;
}
a:link:after, a:visited:after {
content:" (" attr(href) ")";font-size:90%;
}
table {
page-break-inside: avoid;
}
}
@media screen {
/* screen.css from Safari Reader */
h1.title {
font-family: Palatino, Georgia, Times, "Times New Roman", serif;
font-weight: bold;
font-size: 1.33em;
line-height: 1.25em;
}
h1 {
font-size: 1.25em;
}
h2 {
font-size: 1.125em;
}
h3 {
font-size: 1.05em;
}
.page a {
text-decoration: none;
color: rgb(32, 0, 127);
}
.page a:visited {
color: rgb(32, 0, 127);
}
#article img {
/* Float images to the left, so that text will nicely flow around them. */
float: left;
margin-right: 12px;
}
#article img.reader-image-tiny {
/* Don't float very small images -- let them display where they occur in the text. */
float: none;
margin: 0;
}
#article img.reader-image-large {
float: none;
margin: auto;
display: block;
}
.float {
margin: 8px 0;
font-size: 65%;
line-height: 1.4;
text-align: left;
}
.float.left {
float: left;
margin-right: 20px;
}
.float.right {
float: right;
margin-left: 20px;
}
.float.full-width {
float: none;
display: block;
}
.page {
font: 20px Palatino, Georgia, Times, "Times New Roman", serif;
line-height: 160%;
text-align: justify;
}
.page:first-of-type .title {
display: block;
}
.page table {
font-size: 0.9em;
text-align: left;
}
.page.rtl table {
text-align: right;
}
.page-number {
display: none;
}
.title {
display: none;
}
body {
margin: 0;
padding: 0;
background-color: transparent;
-webkit-user-select: none;
}
.cached embed, .cached applet, .cached object {
display: none !important;
}
#background {
background-color: rgba(0, 0, 0, 0.8);
-webkit-transform: translateZ(0);
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#container {
margin-left: -431px;
left: 50%;
width: 862px;
height: 100%;
position: absolute;
pointer-events: none;
}
#centered {
position: absolute;
top: 0;
width: 100%;
height: 100%;
z-index: 0;
}
.preloading #background {
opacity: 0;
}
.preloading #centered {
-webkit-transform: translate3d(0, 100%, 0);
}
.activating #background {
-webkit-transition: opacity 0.40s ease-out;
opacity: 1.0;
}
.activating #fade-top {
-webkit-animation-name: fadeTopActivationFadeIn;
-webkit-animation-duration: 0.40s;
-webkit-animation-timing-function: ease-out;
}
.activating.skip-transition #fade-top {
-webkit-animation: none !important;
}
@-webkit-keyframes fadeTopActivationFadeIn {
0% {
opacity: 0;
}
80% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.activating.skip-transition #background {
-webkit-transition: none !important;
}
.activating #centered {
-webkit-transition: -webkit-transform 0.40s ease-out;
-webkit-transform: translate3d(0, 0, 0);
}
.activating.skip-transition #centered {
-webkit-transition: none !important;
}
.deactivating #background {
-webkit-transition: opacity 0.40s ease-in;
opacity: 0;
}
.deactivating #fade-top {
opacity: 0;
}
.deactivating #fade-bottom {
-webkit-transition: opacity 0.40s ease-in;
opacity: 0;
}
.deactivating #centered {
-webkit-transition: -webkit-transform 0.40s ease-in;
-webkit-transform: translate3d(0, 100%, 0);
}
.deactivating #hud {
-webkit-transition: opacity 0.25s ease-in;
opacity: 0 !important;
}
#drop-shadow {
position: absolute;
top: 0;
bottom: 0;
width: 800px;
left: 10px;
border-width: 24px 24px;
-webkit-border-image: url(safari-resource:/ReaderDropShadow.png) 24 24 24 24 stretch stretch;
opacity: 0;
}
#hud {
position: fixed;
width: 314px;
height: 72px;
left: 50%;
margin-left: -157px;
bottom: 30px;
background: rgba(0, 0, 0, 0.75);
-webkit-border-radius: 12px;
z-index: 100;
opacity: 0;
-webkit-transition: opacity 0.75s;
pointer-events: auto;
zoom: reset;
}
#hud button {
display: block;
float: left;
width: 48px;
height: 48px;
padding: 0;
border: none;
margin: 12px 5px;
}
#hud button:first-of-type {
margin-left: 12px;
}
#hud button:last-of-type {
margin-right: 12px;
}
#hud-zoom-out {
background: url(safari-resource:/ReaderHUDZoomOutInactive.png) no-repeat;
}
#hud-zoom-out:active {
background: url(safari-resource:/ReaderHUDZoomOutActive.png) no-repeat;
}
#hud-zoom-in {
background: url(safari-resource:/ReaderHUDZoomInInactive.png) no-repeat;
}
#hud-zoom-in:active {
background: url(safari-resource:/ReaderHUDZoomInActive.png) no-repeat;
}
#hud-mail {
background: url(safari-resource:/ReaderHUDMailContentsInactive.png) no-repeat;
}
#hud-mail:active {
background: url(safari-resource:/ReaderHUDMailContentsActive.png) no-repeat;
}
#hud-print {
background: url(safari-resource:/ReaderHUDPrintInactive.png) no-repeat;
}
#hud-print:active {
background: url(safari-resource:/ReaderHUDPrintActive.png) no-repeat;
}
#hud-exit {
background: url(safari-resource:/ReaderHUDCloseInactive.png) no-repeat;
}
#hud-exit:active {
background: url(safari-resource:/ReaderHUDCloseActive.png) no-repeat;
}
#article {
/* The width of 819px here includes 19px for the WebKit scrollbar's width. */
/* The padding-right of 8px separates the scrollbar from the article itself. */
position: absolute;
height: 100%;
left: 34px;
width: 819px;
padding-right: 8px;
overflow: scroll;
z-index: 0;
outline: none;
pointer-events: auto;
-webkit-user-select: auto;
-webkit-transform: translateZ(0);
}
.article-fade {
position: absolute;
left: 34px;
height: 36px;
width: 800px;
z-index: 10;
pointer-events: none;
}
#fade-top {
top: 0;
background: url(safari-resource:/ReaderFadeTop.png) repeat-x;
}
#fade-bottom {
bottom: 0;
background: url(safari-resource:/ReaderFadeBottom.png) repeat-x;
}
#resize-indicator {
position: fixed;
bottom: 0;
right: 0;
width: 12px;
height: 12px;
background: url(safari-resource:/TopSitesCornerResize.png);
}
.page:only-of-type .page-number {
display: none;
}
.page-number {
display: block;
font: bold 11px Helvetica, sans-serif;
margin-left: 12px;
color: #B2B2B2;
position: absolute;
right: 10px;
top: 10px;
-webkit-user-select: none;
}
.page:first-of-type {
margin-top: 22px;
}
.page:last-of-type {
margin-bottom: 22px;
}
.page {
width: 658px;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
padding: 45px 70px;
color: black;
background: white;
border: 1px solid #c3c3c3;
position: relative;
overflow: hidden;
-webkit-transition: height .5s ease-out;
}
.page.rtl {
direction: rtl;
}
#incoming-page-placeholder {
height: 30px;
margin-bottom: 0;
}
#incoming-page-corner {
position: absolute;
right: 10px;
top: 8px;
}
#incoming-page-spinner {
width: 16px;
height: 16px;
float: right;
background: url(safari-resource:/ReaderSpinner.png);
}
#incoming-page-text {
float: right;
margin-top: 2px;
margin-left: 8px;
color: #B2B2B2;
font: bold 11px Helvetica, sans-serif;
-webkit-user-select: none;
}
#next-page-container {
position:absolute;
display: none;
}
.no-transition {
-webkit-transition: none !important;
}
}

View File

@@ -0,0 +1,50 @@
body {
font-size:13px;
font-family:verdana, sans-serif;
line-height:1.5em;
}
h1 { font-size:1.6em; }
h2 { font-size:1.5em; }
h3 { font-size:1.4em; font-weight:300; }
h4 { font-size:1em; }
h1, h2, h3, h4 {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin-top:20px;
}
h2 {
padding-top:5px;
border-top:1px solid #AAA;
margin-top:40px;
}
p {
margin:15px 15px;
}
pre {
padding:5px;
border:1px solid #EEEEEE;
background-color:#F6F6F6;
margin:0 25px;
}
pre code {
padding:5px;
background-color:#F6F6F6;
border:none;
}
code {
font-family:courier, fixed;
display:inline-block;
padding:0px 2px 0px 2px;
background-color: #F6F6F6;
border:1px #E0E0E0 solid;
}
ul li {
margin:2px 0 0 0;
}

96
vim/plugin/vmp.vim Executable file
View File

@@ -0,0 +1,96 @@
if !exists('g:VMPoutputformat')
let g:VMPoutputformat = 'html'
endif
if !exists('g:VMPoutputdirectory')
let g:VMPoutputdirectory = '/tmp'
endif
if !exists('g:VMPhtmlreader')
if has('mac')
let g:VMPhtmlreader = 'open'
elseif has('win32') || has('win64')
let g:VMPhtmlreader = 'start'
elseif has('unix') && executable('xdg-open')
let g:VMPhtmlreader = 'xdg-open'
else
let g:VMPhtmlreader = ''
end
endif
if !exists('g:VMPstylesheet')
let g:VMPstylesheet = 'github.css'
endif
function! PreviewMKD()
ruby << RUBY
runtime = Vim.evaluate('&runtimepath').split(',')
runtime.each { |path| $LOAD_PATH.unshift(File.join(path, 'plugin', 'vim-markdown-preview')) }
css_base = runtime.detect { |path| File.exists? File.join(path, 'plugin', 'vmp.vim') }
stylesheet = File.join(css_base, 'plugin', 'vim-markdown-preview', 'stylesheets',
Vim.evaluate('g:VMPstylesheet'))
name = Vim::Buffer.current.name.nil? ? 'Untitled' : File.basename(Vim::Buffer.current.name)
output_dir = Vim.evaluate('g:VMPoutputdirectory')
contents = Array.new(VIM::Buffer.current.count) { |i| VIM::Buffer.current[i + 1] }.join("\n")
require('kramdown/kramdown')
layout = <<-LAYOUT
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet"
href="#{stylesheet}">
</link>
<title> #{name} </title>
</head>
<body>
<div id="container">
<div id="centered">
<div id="article">
<div class="page">
#{Kramdown::Document.new(contents).to_html}
</div>
</div>
</div>
</div>
</body>
</html>
LAYOUT
case Vim.evaluate('g:VMPoutputformat')
when 'html'
reader = Vim.evaluate('g:VMPhtmlreader')
if reader == ''
Vim.message('No suitable HTML reader found! Please set g:VMPhtmlreader.')
else
file = File.join(output_dir, name + '.html')
File.open(file, 'w') { |f| f.write(layout) }
Vim.command("silent ! #{reader} '%s'" % [ file ])
Vim.command 'redraw!'
end
when 'pdf'
Vim.message('output format not implemented yet.')
else
Vim.message('Unrecongized output format! Check g:VMPoutputformat.')
end
RUBY
endfunction
:command! Mm :call PreviewMKD()