Commit af7a6adb authored by Taddeüs Kroes's avatar Taddeüs Kroes

First version

parents
# ~/.bashrc: executed by bash(1) for non-login shells.
#
# Bash history and shell options
#
# if not running interactively, don't do anything
[ -z "$PS1" ] && return
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
. /etc/bash_completion
fi
#
# Setting PS1
#
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# comment for uncolored terminal
color_prompt=yes
if [ $UID -eq 0 ]; then
USERCOLOR="\[\e[01;31m\]" # Red if running as root
INDICATOR="#"
else
USERCOLOR="\[\e[01;32m\]" # Green otherwise
INDICATOR="$"
fi
if [ "$color_prompt" = yes ]; then
PS1="${debian_chroot:+($debian_chroot)}$USERCOLOR\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$INDICATOR "
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$INDICATOR '
fi
unset color_prompt
#
# Aliases
#
# enable color support of ls and grep
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# ls shortcuts
alias ll='ls -alFh'
alias la='ls -A'
alias l='ls -CF'
# ssh shortcuts for multivac
alias smv='ssh mv -tt screen -Uxr'
alias mvv='mosh mv -p 8215 -- screen -Uxr'
# more alias fancyness
alias cdhere='cd $(realpath $(pwd))'
alias ocaml='rlwrap ocaml'
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
#
# Environment
#
export TERM="xterm-256color"
export LC_ALL="en_US.UTF-8"
export LANG="$LC_ALL"
export EDITOR=vim
export PATH=$PATH:$HOME/.local/bin
#
# local, installation-specific config
#
[ -f ~/.bashrc_local ] && . ~/.bashrc_local
awesome vim vim-gui-common vim-nox git tig radiotray chromium-browser thunar
gmail-notify numlockx htop mosh mupdf
ranger gimp meld imagemagick curl bpython gparted tree graphviz realpath
python-tornado pyflakes pep8 feh python-numpy python-scipy python-pygame
python-cairo python-setuptools python-coverage python-gtk2 python-mysqldb
python-sqlalchemy python-pip python-matplotlib python-docutils
mpi-default-dev build-essential subversion gettext liblua5.1-dev libsdl1.2-dev
libsigc++-2.0-dev binutils-dev nasm libasound2 ocaml ocaml-native-compilers
opam camlp4-extra menhir g++-multilib bison flex mysql-server mysql-workbench
ruby-sass
texlive-base texlive-latex-extra texlive-fonts-recommended texlive-extra-utils
texlive-bibtex-extra kbibtex
gstreamer0.10-plugins-bad gstreamer0.10-plugins-ugly gstreamer0.10-plugins-good
gconf-editor
libncurses5-dev openjdk-7-jdk ant libnotify-bin
command-t-1.8.vba: call delete('/home/taddeus/.vim/ruby/command-t/controller.rb')|call delete('/home/taddeus/.vim/ruby/command-t/extconf.rb')|call delete('/home/taddeus/.vim/ruby/command-t/finder/buffer_finder.rb')|call delete('/home/taddeus/.vim/ruby/command-t/finder/file_finder.rb')|call delete('/home/taddeus/.vim/ruby/command-t/finder/jump_finder.rb')|call delete('/home/taddeus/.vim/ruby/command-t/finder/tag_finder.rb')|call delete('/home/taddeus/.vim/ruby/command-t/finder.rb')|call delete('/home/taddeus/.vim/ruby/command-t/match_window.rb')|call delete('/home/taddeus/.vim/ruby/command-t/prompt.rb')|call delete('/home/taddeus/.vim/ruby/command-t/scanner/buffer_scanner.rb')|call delete('/home/taddeus/.vim/ruby/command-t/scanner/file_scanner/find_file_scanner.rb')|call delete('/home/taddeus/.vim/ruby/command-t/scanner/file_scanner/ruby_file_scanner.rb')|call delete('/home/taddeus/.vim/ruby/command-t/scanner/file_scanner/watchman_file_scanner.rb')|call delete('/home/taddeus/.vim/ruby/command-t/scanner/file_scanner.rb')|call delete('/home/taddeus/.vim/ruby/command-t/scanner/jump_scanner.rb')|call delete('/home/taddeus/.vim/ruby/command-t/scanner/tag_scanner.rb')|call delete('/home/taddeus/.vim/ruby/command-t/scanner.rb')|call delete('/home/taddeus/.vim/ruby/command-t/settings.rb')|call delete('/home/taddeus/.vim/ruby/command-t/stub.rb')|call delete('/home/taddeus/.vim/ruby/command-t/util.rb')|call delete('/home/taddeus/.vim/ruby/command-t/vim/path_utilities.rb')|call delete('/home/taddeus/.vim/ruby/command-t/vim/screen.rb')|call delete('/home/taddeus/.vim/ruby/command-t/vim/window.rb')|call delete('/home/taddeus/.vim/ruby/command-t/vim.rb')|call delete('/home/taddeus/.vim/ruby/command-t/ext.c')|call delete('/home/taddeus/.vim/ruby/command-t/match.c')|call delete('/home/taddeus/.vim/ruby/command-t/matcher.c')|call delete('/home/taddeus/.vim/ruby/command-t/watchman.c')|call delete('/home/taddeus/.vim/ruby/command-t/ext.h')|call delete('/home/taddeus/.vim/ruby/command-t/match.h')|call delete('/home/taddeus/.vim/ruby/command-t/matcher.h')|call delete('/home/taddeus/.vim/ruby/command-t/ruby_compat.h')|call delete('/home/taddeus/.vim/ruby/command-t/watchman.h')|call delete('/home/taddeus/.vim/ruby/command-t/depend')|call delete('/home/taddeus/.vim/doc/command-t.txt')|call delete('/home/taddeus/.vim/plugin/command-t.vim')
let g:netrw_dirhistmax =10
let g:netrw_dirhist_cnt =5
let g:netrw_dirhist_1='/home/taddeus/programming/s2e/s2e/qemu/s2e'
let g:netrw_dirhist_2='/home/taddeus/programming/s2e/s2e/qemu'
let g:netrw_dirhist_3='/home/taddeus/programming/s2e/s2e/qemu/s2e'
let g:netrw_dirhist_4='/home/taddeus/programming/s2e/s2e/qemu/s2e/Plugins/thesis'
let g:netrw_dirhist_5='/etc/wpa_supplicant'
" These are the mappings for snipMate.vim. Putting it here ensures that it
" will be mapped after other plugins such as supertab.vim.
if !exists('loaded_snips') || exists('s:did_snips_mappings')
finish
endif
let s:did_snips_mappings = 1
ino <silent> <tab> <c-r>=TriggerSnippet()<cr>
snor <silent> <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
ino <silent> <s-tab> <c-r>=BackwardsSnippet()<cr>
snor <silent> <s-tab> <esc>i<right><c-r>=BackwardsSnippet()<cr>
ino <silent> <c-r><tab> <c-r>=ShowAvailableSnips()<cr>
" The default mappings for these are annoying & sometimes break snipMate.
" You can change them back if you want, I've put them here for convenience.
snor <bs> b<bs>
snor <right> <esc>a
snor <left> <esc>bi
snor ' b<bs>'
snor ` b<bs>`
snor % b<bs>%
snor U b<bs>U
snor ^ b<bs>^
snor \ b<bs>\
snor <c-x> b<bs><c-x>
" By default load snippets in snippets_dir
if empty(snippets_dir)
finish
endif
call GetSnippets(snippets_dir, '_') " Get global snippets
au FileType * if &ft != 'help' | call GetSnippets(snippets_dir, &ft) | endif
" vim:noet:sw=4:ts=4:ft=vim
" Language: CoffeeScript
" Maintainer: Sven Felix Oberquelle <Svelix.Github@gmail.com>
" URL: http://github.com/kchmck/vim-coffee-script
" License: WTFPL
" Inherit coffee from html so coffeeComment isn't redefined and given higher
" priority than hamlInterpolation.
syn cluster hamlCoffeescript contains=@htmlCoffeeScript
syn region hamlCoffeescriptFilter matchgroup=hamlFilter start="^\z(\s*\):coffeescript\s*$" end="^\%(\z1 \| *$\)\@!" contains=@hamlCoffeeScript,hamlInterpolation keepend
" Language: CoffeeScript
" Maintainer: Mick Koch <kchmck@gmail.com>
" URL: http://github.com/kchmck/vim-coffee-script
" License: WTFPL
" Syntax highlighting for text/coffeescript script tags
syn include @htmlCoffeeScript syntax/coffee.vim
syn region coffeeScript start=+<script [^>]*type *=[^>]*text/coffeescript[^>]*>+
\ end=+</script>+me=s-1 keepend
\ contains=@htmlCoffeeScript,htmlScriptTag,@htmlPreproc
\ containedin=htmlHead
fun! Filename(...)
let filename = expand('%:t:r')
if filename == '' | return a:0 == 2 ? a:2 : '' | endif
return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g')
endf
fun s:RemoveSnippet()
unl! g:snipPos s:curPos s:snipLen s:endCol s:endLine s:prevLen
\ s:lastBuf s:oldWord
if exists('s:update')
unl s:startCol s:origWordLen s:update
if exists('s:oldVars') | unl s:oldVars s:oldEndCol | endif
endif
aug! snipMateAutocmds
endf
fun snipMate#expandSnip(snip, col)
let lnum = line('.') | let col = a:col
let snippet = s:ProcessSnippet(a:snip)
" Avoid error if eval evaluates to nothing
if snippet == '' | return '' | endif
" Expand snippet onto current position with the tab stops removed
let snipLines = split(substitute(snippet, '$\d\+\|${\d\+.\{-}}', '', 'g'), "\n", 1)
let line = getline(lnum)
let afterCursor = strpart(line, col - 1)
" Keep text after the cursor
if afterCursor != "\t" && afterCursor != ' '
let line = strpart(line, 0, col - 1)
let snipLines[-1] .= afterCursor
else
let afterCursor = ''
" For some reason the cursor needs to move one right after this
if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore'
let col += 1
endif
endif
call setline(lnum, line.snipLines[0])
" Autoindent snippet according to previous indentation
let indent = matchend(line, '^.\{-}\ze\(\S\|$\)') + 1
call append(lnum, map(snipLines[1:], "'".strpart(line, 0, indent - 1)."'.v:val"))
" Open any folds snippet expands into
if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif
let [g:snipPos, s:snipLen] = s:BuildTabStops(snippet, lnum, col - indent, indent)
if s:snipLen
aug snipMateAutocmds
au CursorMovedI * call s:UpdateChangedSnip(0)
au InsertEnter * call s:UpdateChangedSnip(1)
aug END
let s:lastBuf = bufnr(0) " Only expand snippet while in current buffer
let s:curPos = 0
let s:endCol = g:snipPos[s:curPos][1]
let s:endLine = g:snipPos[s:curPos][0]
call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1])
let s:prevLen = [line('$'), col('$')]
if g:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif
else
unl g:snipPos s:snipLen
" Place cursor at end of snippet if no tab stop is given
let newlines = len(snipLines) - 1
call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor)
\ + (newlines ? 0: col - 1))
endif
return ''
endf
" Prepare snippet to be processed by s:BuildTabStops
fun s:ProcessSnippet(snip)
let snippet = a:snip
" Evaluate eval (`...`) expressions.
" Backquotes prefixed with a backslash "\" are ignored.
" Using a loop here instead of a regex fixes a bug with nested "\=".
if stridx(snippet, '`') != -1
while match(snippet, '\(^\|[^\\]\)`.\{-}[^\\]`') != -1
let snippet = substitute(snippet, '\(^\|[^\\]\)\zs`.\{-}[^\\]`\ze',
\ substitute(eval(matchstr(snippet, '\(^\|[^\\]\)`\zs.\{-}[^\\]\ze`')),
\ "\n\\%$", '', ''), '')
endw
let snippet = substitute(snippet, "\r", "\n", 'g')
let snippet = substitute(snippet, '\\`', '`', 'g')
endif
" Place all text after a colon in a tab stop after the tab stop
" (e.g. "${#:foo}" becomes "${:foo}foo").
" This helps tell the position of the tab stops later.
let snippet = substitute(snippet, '${\d\+:\(.\{-}\)}', '&\1', 'g')
" Update the a:snip so that all the $# become the text after
" the colon in their associated ${#}.
" (e.g. "${1:foo}" turns all "$1"'s into "foo")
let i = 1
while stridx(snippet, '${'.i) != -1
let s = matchstr(snippet, '${'.i.':\zs.\{-}\ze}')
if s != ''
let snippet = substitute(snippet, '$'.i, s.'&', 'g')
endif
let i += 1
endw
if &et " Expand tabs to spaces if 'expandtab' is set.
return substitute(snippet, '\t', repeat(' ', &sts ? &sts : &sw), 'g')
endif
return snippet
endf
" Counts occurences of haystack in needle
fun s:Count(haystack, needle)
let counter = 0
let index = stridx(a:haystack, a:needle)
while index != -1
let index = stridx(a:haystack, a:needle, index+1)
let counter += 1
endw
return counter
endf
" Builds a list of a list of each tab stop in the snippet containing:
" 1.) The tab stop's line number.
" 2.) The tab stop's column number
" (by getting the length of the string between the last "\n" and the
" tab stop).
" 3.) The length of the text after the colon for the current tab stop
" (e.g. "${1:foo}" would return 3). If there is no text, -1 is returned.
" 4.) If the "${#:}" construct is given, another list containing all
" the matches of "$#", to be replaced with the placeholder. This list is
" composed the same way as the parent; the first item is the line number,
" and the second is the column.
fun s:BuildTabStops(snip, lnum, col, indent)
let snipPos = []
let i = 1
let withoutVars = substitute(a:snip, '$\d\+', '', 'g')
while stridx(a:snip, '${'.i) != -1
let beforeTabStop = matchstr(withoutVars, '^.*\ze${'.i.'\D')
let withoutOthers = substitute(withoutVars, '${\('.i.'\D\)\@!\d\+.\{-}}', '', 'g')
let j = i - 1
call add(snipPos, [0, 0, -1])
let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n")
let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze${'.i.'\D'))
if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif
" Get all $# matches in another list, if ${#:name} is given
if stridx(withoutVars, '${'.i.':') != -1
let snipPos[j][2] = len(matchstr(withoutVars, '${'.i.':\zs.\{-}\ze}'))
let dots = repeat('.', snipPos[j][2])
call add(snipPos[j], [])
let withoutOthers = substitute(a:snip, '${\d\+.\{-}}\|$'.i.'\@!\d\+', '', 'g')
while match(withoutOthers, '$'.i.'\(\D\|$\)') != -1
let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.'$'.i.'\(\D\|$\)')
call add(snipPos[j][3], [0, 0])
let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n")
let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum
\ ? len(matchstr(beforeMark, '.*\n\zs.*'))
\ : a:col + len(beforeMark))
let withoutOthers = substitute(withoutOthers, '$'.i.'\ze\(\D\|$\)', '', '')
endw
endif
let i += 1
endw
return [snipPos, i - 1]
endf
fun snipMate#jumpTabStop(backwards)
let leftPlaceholder = exists('s:origWordLen')
\ && s:origWordLen != g:snipPos[s:curPos][2]
if leftPlaceholder && exists('s:oldEndCol')
let startPlaceholder = s:oldEndCol + 1
endif
if exists('s:update')
call s:UpdatePlaceholderTabStops()
else
call s:UpdateTabStops()
endif
" Don't reselect placeholder if it has been modified
if leftPlaceholder && g:snipPos[s:curPos][2] != -1
if exists('startPlaceholder')
let g:snipPos[s:curPos][1] = startPlaceholder
else
let g:snipPos[s:curPos][1] = col('.')
let g:snipPos[s:curPos][2] = 0
endif
endif
let s:curPos += a:backwards ? -1 : 1
" Loop over the snippet when going backwards from the beginning
if s:curPos < 0 | let s:curPos = s:snipLen - 1 | endif
if s:curPos == s:snipLen
let sMode = s:endCol == g:snipPos[s:curPos-1][1]+g:snipPos[s:curPos-1][2]
call s:RemoveSnippet()
return sMode ? "\<tab>" : TriggerSnippet()
endif
call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1])
let s:endLine = g:snipPos[s:curPos][0]
let s:endCol = g:snipPos[s:curPos][1]
let s:prevLen = [line('$'), col('$')]
return g:snipPos[s:curPos][2] == -1 ? '' : s:SelectWord()
endf
fun s:UpdatePlaceholderTabStops()
let changeLen = s:origWordLen - g:snipPos[s:curPos][2]
unl s:startCol s:origWordLen s:update
if !exists('s:oldVars') | return | endif
" Update tab stops in snippet if text has been added via "$#"
" (e.g., in "${1:foo}bar$1${2}").
if changeLen != 0
let curLine = line('.')
for pos in g:snipPos
if pos == g:snipPos[s:curPos] | continue | endif
let changed = pos[0] == curLine && pos[1] > s:oldEndCol
let changedVars = 0
let endPlaceholder = pos[2] - 1 + pos[1]
" Subtract changeLen from each tab stop that was after any of
" the current tab stop's placeholders.
for [lnum, col] in s:oldVars
if lnum > pos[0] | break | endif
if pos[0] == lnum
if pos[1] > col || (pos[2] == -1 && pos[1] == col)
let changed += 1
elseif col < endPlaceholder
let changedVars += 1
endif
endif
endfor
let pos[1] -= changeLen * changed
let pos[2] -= changeLen * changedVars " Parse variables within placeholders
" e.g., "${1:foo} ${2:$1bar}"
if pos[2] == -1 | continue | endif
" Do the same to any placeholders in the other tab stops.
for nPos in pos[3]
let changed = nPos[0] == curLine && nPos[1] > s:oldEndCol
for [lnum, col] in s:oldVars
if lnum > nPos[0] | break | endif
if nPos[0] == lnum && nPos[1] > col
let changed += 1
endif
endfor
let nPos[1] -= changeLen * changed
endfor
endfor
endif
unl s:endCol s:oldVars s:oldEndCol
endf
fun s:UpdateTabStops()
let changeLine = s:endLine - g:snipPos[s:curPos][0]
let changeCol = s:endCol - g:snipPos[s:curPos][1]
if exists('s:origWordLen')
let changeCol -= s:origWordLen
unl s:origWordLen
endif
let lnum = g:snipPos[s:curPos][0]
let col = g:snipPos[s:curPos][1]
" Update the line number of all proceeding tab stops if <cr> has
" been inserted.
if changeLine != 0
let changeLine -= 1
for pos in g:snipPos
if pos[0] >= lnum
if pos[0] == lnum | let pos[1] += changeCol | endif
let pos[0] += changeLine
endif
if pos[2] == -1 | continue | endif
for nPos in pos[3]
if nPos[0] >= lnum
if nPos[0] == lnum | let nPos[1] += changeCol | endif
let nPos[0] += changeLine
endif
endfor
endfor
elseif changeCol != 0
" Update the column of all proceeding tab stops if text has
" been inserted/deleted in the current line.
for pos in g:snipPos
if pos[1] >= col && pos[0] == lnum
let pos[1] += changeCol
endif
if pos[2] == -1 | continue | endif
for nPos in pos[3]
if nPos[0] > lnum | break | endif
if nPos[0] == lnum && nPos[1] >= col
let nPos[1] += changeCol
endif
endfor
endfor
endif
endf
fun s:SelectWord()
let s:origWordLen = g:snipPos[s:curPos][2]
let s:oldWord = strpart(getline('.'), g:snipPos[s:curPos][1] - 1,
\ s:origWordLen)
let s:prevLen[1] -= s:origWordLen
if !empty(g:snipPos[s:curPos][3])
let s:update = 1
let s:endCol = -1
let s:startCol = g:snipPos[s:curPos][1] - 1
endif
if !s:origWordLen | return '' | endif
let l = col('.') != 1 ? 'l' : ''
if &sel == 'exclusive'
return "\<esc>".l.'v'.s:origWordLen."l\<c-g>"
endif
return s:origWordLen == 1 ? "\<esc>".l.'gh'
\ : "\<esc>".l.'v'.(s:origWordLen - 1)."l\<c-g>"
endf
" This updates the snippet as you type when text needs to be inserted
" into multiple places (e.g. in "${1:default text}foo$1bar$1",
" "default text" would be highlighted, and if the user types something,
" UpdateChangedSnip() would be called so that the text after "foo" & "bar"
" are updated accordingly)
"
" It also automatically quits the snippet if the cursor is moved out of it
" while in insert mode.
fun s:UpdateChangedSnip(entering)
if exists('g:snipPos') && bufnr(0) != s:lastBuf
call s:RemoveSnippet()
elseif exists('s:update') " If modifying a placeholder
if !exists('s:oldVars') && s:curPos + 1 < s:snipLen
" Save the old snippet & word length before it's updated
" s:startCol must be saved too, in case text is added
" before the snippet (e.g. in "foo$1${2}bar${1:foo}").
let s:oldEndCol = s:startCol
let s:oldVars = deepcopy(g:snipPos[s:curPos][3])
endif
let col = col('.') - 1
if s:endCol != -1
let changeLen = col('$') - s:prevLen[1]
let s:endCol += changeLen
else " When being updated the first time, after leaving select mode
if a:entering | return | endif
let s:endCol = col - 1
endif
" If the cursor moves outside the snippet, quit it
if line('.') != g:snipPos[s:curPos][0] || col < s:startCol ||
\ col - 1 > s:endCol
unl! s:startCol s:origWordLen s:oldVars s:update
return s:RemoveSnippet()
endif
call s:UpdateVars()
let s:prevLen[1] = col('$')
elseif exists('g:snipPos')
if !a:entering && g:snipPos[s:curPos][2] != -1
let g:snipPos[s:curPos][2] = -2
endif
let col = col('.')
let lnum = line('.')
let changeLine = line('$') - s:prevLen[0]
if lnum == s:endLine
let s:endCol += col('$') - s:prevLen[1]
let s:prevLen = [line('$'), col('$')]
endif
if changeLine != 0
let s:endLine += changeLine
let s:endCol = col
endif
" Delete snippet if cursor moves out of it in insert mode
if (lnum == s:endLine && (col > s:endCol || col < g:snipPos[s:curPos][1]))
\ || lnum > s:endLine || lnum < g:snipPos[s:curPos][0]
call s:RemoveSnippet()
endif
endif
endf
" This updates the variables in a snippet when a placeholder has been edited.
" (e.g., each "$1" in "${1:foo} $1bar $1bar")
fun s:UpdateVars()
let newWordLen = s:endCol - s:startCol + 1
let newWord = strpart(getline('.'), s:startCol, newWordLen)
if newWord == s:oldWord || empty(g:snipPos[s:curPos][3])
return
endif
let changeLen = g:snipPos[s:curPos][2] - newWordLen
let curLine = line('.')
let startCol = col('.')
let oldStartSnip = s:startCol
let updateTabStops = changeLen != 0
let i = 0
for [lnum, col] in g:snipPos[s:curPos][3]
if updateTabStops
let start = s:startCol
if lnum == curLine && col <= start
let s:startCol -= changeLen
let s:endCol -= changeLen
endif
for nPos in g:snipPos[s:curPos][3][(i):]
" This list is in ascending order, so quit if we've gone too far.
if nPos[0] > lnum | break | endif
if nPos[0] == lnum && nPos[1] > col
let nPos[1] -= changeLen
endif
endfor
if lnum == curLine && col > start
let col -= changeLen
let g:snipPos[s:curPos][3][i][1] = col
endif
let i += 1
endif
" "Very nomagic" is used here to allow special characters.
call setline(lnum, substitute(getline(lnum), '\%'.col.'c\V'.
\ escape(s:oldWord, '\'), escape(newWord, '\&'), ''))
endfor
if oldStartSnip != s:startCol
call cursor(0, startCol + s:startCol - oldStartSnip)
endif
let s:oldWord = newWord
let g:snipPos[s:curPos][2] = newWordLen
endf
" vim:noet:sw=4:ts=4:ft=vim
" Vim color file
"
" Author: Brian Mock <mock.brian@gmail.com>
" Author: Sander Mathijs van Veen <smvv@kompiler.org>
"
" Note: Based on Oblivion color scheme for gedit (gtk-source-view)
" and based on Brian Mock's darkspectrum color theme.
"
" cool help screens
" :he group-name
" :he highlight-groups
" :he cterm-colors
hi clear
if version > 580
" no guarantees for version 5.8 and below, but this makes it stop
" complaining
hi clear
if exists("syntax_on")
syntax reset
endif
endif
set background=dark
let g:colors_name="darkspectrum"
hi Normal guifg=#efefef guibg=#000000 ctermbg=none gui=none
" highlight groups
hi Cursor guibg=#ffffff guifg=#000000
hi CursorLine guibg=#000000
"hi CursorColumn guibg=#464646
"hi diffText guibg=#4e9a06 guifg=#FFFFFF gui=bold
"hi diffChange guibg=#4e9a06 guifg=#FFFFFF gui=bold
"hi diffAdd guibg=#204a87 guifg=#FFFFFF gui=bold
"hi diffDelete guibg=#5c3566 guifg=#FFFFFF gui=bold
hi diffFile guifg=#aaaaaa gui=none
hi diffNewFile guifg=#aaaaaa gui=none
""hi DiffAdd guifg=#ffcc7f guibg=#a67429 gui=none
hi diffAdded guifg=#44cc44 gui=none
hi diffChange guifg=#7fbdff gui=none
hi diffRemoved guifg=#aa2723 gui=none
"hi DiffAdd gui=none guifg=#ffcc7f guibg=none
"hi DiffChange gui=none guifg=bg guibg=none
"hi DiffDelete gui=none guifg=bg guibg=none
"hi DiffText gui=none guifg=bg guibg=none
hi Number guifg=#fce94f
hi Folded guibg=#000000 guifg=#FFFFFF gui=bold
hi vimFold guibg=#000000 guifg=#FFFFFF gui=bold
hi FoldColumn guibg=#000000 guifg=#FFFFFF gui=bold
hi LineNr guifg=#636363
hi NonText guifg=#636363
hi Folded guifg=#666666 gui=bold
hi FoldeColumn guifg=#636363 gui=bold
"hi VertSplit guibg=#ffffff gui=none
hi VertSplit guifg=#3C3C3C gui=none
hi StatusLine guifg=#FFFFFF gui=none
hi StatusLineNC guifg=#808080 gui=none
hi ModeMsg guifg=#fce94f
hi MoreMsg guifg=#fce94f
hi Visual guifg=#FFFFFF guibg=#3465a4 gui=none
hi VisualNOS guifg=#FFFFFF guibg=#204a87 gui=none
"hi IncSearch guibg=#FFFFFF guifg=#5f6400
hi IncSearch guibg=#FFFFFF guifg=#ef5939
"hi Search guibg=#ad7fa8 guifg=#FFFFFF
hi Search guibg=#818800 guifg=#FFFFFF
hi SpecialKey guifg=#8ae234
hi Title guifg=#ef5939
hi WarningMsg guifg=#ef5939
hi Number guifg=#fcaf3e
hi MatchParen guibg=#ad7fa8 guifg=#FFFFFF
hi Comment guifg=#b3b3b3
hi Constant guifg=#ef5939 gui=none
hi String guifg=#fce94f
hi Identifier guifg=#729fcf
hi Statement guifg=#ffffff gui=bold
hi PreProc guifg=#ffffff gui=bold
hi Type guifg=#8ae234 gui=bold
hi Special guifg=#e9b96e
hi Underlined guifg=#ad7fa8 gui=underline
hi Directory guifg=#729fcf
hi Ignore guifg=#555753
hi Todo guifg=#FFFFFF guibg=#ef5939 gui=bold
hi Function guifg=#ad7fa8
"hi WildMenu guibg=#2e3436 guifg=#ffffff gui=bold
"hi WildMenu guifg=#7fbdff guibg=#425c78 gui=none
hi WildMenu guifg=#ffffff guibg=#3465a4 gui=none
hi Pmenu guibg=#000000 guifg=#c0c0c0
hi PmenuSel guibg=#3465a4 guifg=#ffffff
hi PmenuSbar guibg=#444444 guifg=#444444
hi PmenuThumb guibg=#888888 guifg=#888888
hi cppSTLType guifg=#729fcf gui=bold
"hi SpellBad guifg=#fcaf3e
hi SpellBad gui=underline
hi SpellCap guifg=#73d216
hi SpellRare guifg=#ad7fa8
hi SpellLocal guifg=#729fcf
hi link cppSTL Function
hi link Error Todo
hi link Character Number
hi link rubySymbol Number
hi link htmlTag htmlEndTag
"hi link htmlTagName htmlTag
hi link htmlLink Underlined
hi link pythonFunction Identifier
hi link Question Type
hi link CursorIM Cursor
hi link VisualNOS Visual
hi link xmlTag Identifier
hi link xmlTagName Identifier
hi link shDeref Identifier
hi link shVariable Function
hi link rubySharpBang Special
hi link perlSharpBang Special
hi link schemeFunc Statement
"hi link shSpecialVariables Constant
"hi link bashSpecialVariables Constant
" tabs (non gui)
hi TabLine guifg=#A3A3A3 guibg=#202020 gui=none
hi TabLineFill guifg=#535353 guibg=#202020 gui=none
hi TabLineSel guifg=#FFFFFF gui=bold
" Pyflakes warning and errors
hi pyflakes guifg=#ccaa00 gui=underline
" vim: sw=4 ts=4
" Language: CoffeeScript
" Maintainer: Mick Koch <kchmck@gmail.com>
" URL: http://github.com/kchmck/vim-coffee-script
" License: WTFPL
if exists('current_compiler')
finish
endif
let current_compiler = 'coffee'
" Pattern to check if coffee is the compiler
let s:pat = '^' . current_compiler
" Extra options passed to CoffeeMake
if !exists("coffee_make_options")
let coffee_make_options = ""
endif
" Get a `makeprg` for the current filename. This is needed to support filenames
" with spaces and quotes, but also not break generic `make`.
function! s:GetMakePrg()
return 'coffee -c ' . g:coffee_make_options . ' $* ' . fnameescape(expand('%'))
endfunction
" Set `makeprg` and return 1 if coffee is still the compiler, else return 0.
function! s:SetMakePrg()
if &l:makeprg =~ s:pat
let &l:makeprg = s:GetMakePrg()
elseif &g:makeprg =~ s:pat
let &g:makeprg = s:GetMakePrg()
else
return 0
endif
return 1
endfunction
" Set a dummy compiler so we can check whether to set locally or globally.
CompilerSet makeprg=coffee
call s:SetMakePrg()
CompilerSet errorformat=Error:\ In\ %f\\,\ %m\ on\ line\ %l,
\Error:\ In\ %f\\,\ Parse\ error\ on\ line\ %l:\ %m,
\SyntaxError:\ In\ %f\\,\ %m,
\%-G%.%#
" Compile the current file.
command! -bang -bar -nargs=* CoffeeMake make<bang> <args>
" Set `makeprg` on rename since we embed the filename in the setting.
augroup CoffeeUpdateMakePrg
autocmd!
" Update `makeprg` if coffee is still the compiler, else stop running this
" function.
function! s:UpdateMakePrg()
if !s:SetMakePrg()
autocmd! CoffeeUpdateMakePrg
endif
endfunction
" Set autocmd locally if compiler was set locally.
if &l:makeprg =~ s:pat
autocmd BufFilePost,BufWritePost <buffer> call s:UpdateMakePrg()
else
autocmd BufFilePost,BufWritePost call s:UpdateMakePrg()
endif
augroup END
*CSApprox.txt* Bringing GVim colorschemes to the terminal!
*csapprox* *csapprox.vim*
_____ ____ ___ ~
/ ___// __// _ | ___ ___ ____ ___ __ __ ~
/ /__ _\ \ / __ | / _ \ / _ \ / __// _ \ \ \ / ~
\___//___//_/ |_|/ .__// .__//_/ \___//_\_\ ~
/_/ /_/ ~
For Vim version 7.0 or newer
Last changed 01 Apr 2009
By Matt Wozniski
mjw@drexel.edu
Reference Manual~
*csapprox-toc*
1. Introduction |csapprox-intro|
2. Requirements |csapprox-requirements|
3. Configuration |csapprox-configure|
4. Rationale/Design |csapprox-design|
5. Known Bugs and Limitations |csapprox-limitations|
6. Appendix - Terminals and Palettes |csapprox-terminal-list|
7. Changelog |csapprox-changelog|
8. Contact Info |csapprox-author|
The functionality mentioned here is a plugin, see |add-plugin|.
You can avoid loading this plugin by setting the "CSApprox_loaded" global
variable in your |vimrc| file: >
:let g:CSApprox_loaded = 1
==============================================================================
1. Introduction *csapprox-intro*
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.
If for some reason this transparent method isn't suitable to you (for instance
if your environment can't be configured to meet the |csapprox-requirements|,
or you need to work in Vim 6), another option is also available: using the
|:CSApproxSnapshot| command to create a new GUI/88-/256-color terminal
colorscheme. To use this command, a user would generally start GVim, choose a
colorscheme that sets up the desired colors, and then use |:CSApproxSnapshot|
to create a new colorscheme based on those colors that works in high color
terminals. This method is more flexible than the transparent mode and works
in more places, but also requires more user intervention, and makes it harder
to deal with colorschemes being updated and such.
*:CSApproxSnapshot*
The full syntax for the command is: >
:CSApproxSnapshot[!] /path/to/new/colorscheme
< For example: >
:CSApproxSnapshot ~/.vim/colors/foobar.vim
<
NOTE: The generated colorscheme will only work in 88- and 256-color terminals,
and in GVim. It will not work at all in a terminal with 16 or fewer
colors. There's just no reliable way to approximate down from
16,777,216 colors to 16 colors, especially without there being any
standard for what those 16 colors look like other than 'orange-ish',
'red-ish', etc.
NOTE: Although :CSApproxSnapshot can be used in both GVim and terminal Vim,
the resulting colors might be slightly off when run from terminal Vim.
I can find no way around this; Vim internally sets different colors when
running in a terminal than running in the GUI, and there's no way for
terminal Vim to figure out what color would have been used in GVim.
==============================================================================
2. Requirements *csapprox-requirements*
For CSApprox to work, there are 2 major requirements that must be met.
a) GUI support *csapprox-gui-support* *csapprox-+gui*
If CSApprox is being used to adjust a scheme's colors transparently, then the
terminal "vim" binary that is being run must be built with GUI support (see
|csapprox-limitations| for an explanation). If |:CSApproxSnapshot| is being
used to create a terminal colorscheme for high color terminals, then the
"vim" binary being used to create the scheme must be built with +gui, but the
scheme can be used in terminal "vim" binaries that weren't built with +gui.
NOTE that creating snapshots with GVim will work better than making them with
Vim, and (obviously) all "gvim" binaries are built with +gui.
Unfortunately, several Linux distributions only include GUI support in their
"gvim" binary, and not in their "vim" binary. You can check if GUI support is
available with the following command:
:echo has('gui')
If that prints 0, the first thing to try would be searching for a larger vim
package provided by your distribution, like "vim-enhanced" on RedHat/CentOS
or "vim-gtk" or "vim-gnome" on Debian/Ubuntu.
If you are unable to obtain a "vim" binary that includes GUI support, but
have a "gvim" binary available, you can probably launch Vim with GUI support
anyway by calling gvim with the |-v| flag in the shell: >
gvim -v
If the above works, you can remove the need to call "gvim -v" instead of "vim"
all the time by creating a symbolic link from your "gvim" binary to "vim"
somewhere in your $PATH, for example:
sudo ln -s $(which gvim) $(which vim)
If launching as "gvim -v" doesn"t work, and no package with GUI support is
available, you will need to compile Vim yourself and ensure that GUI support
is included to use CSApprox in its transparent mode, or create a snapshotted
scheme from GVim to use its snapshot mode. If this is inconvenient for you,
make sure that the Vim maintainer for your distribution knows it; they made a
conscious decision to build "vim" without +gui and "gvim" without terminal
support.
b) Properly configured terminal *csapprox-terminal*
As said above, many modern terminals support 88 or 256 colors, but most of
these default to setting $TERM to something generic (usually "xterm"). Since
Vim uses the value of the "colors" attribute for the current $TERM in terminfo
to figure out the number of colors used internally as 't_Co', this plugin will
either need for 't_Co' to be set to 88 or 256 in |vimrc|, or for $TERM to be
set to something that implies high color support. Possible choices include
"xterm-256color" for 256 color support and "rxvt-unicode" for 88 color
support.
*csapprox-palettes*
Also, there are three different 256 color cube palettes available and CSApprox
has no way to tell which you're using unless $TERM is set to something that is
specific to the terminal, like "konsole-256color" or "Eterm". Because of this, the
most sane behavior is assuming the user is using the most popular palette,
which is used by all but Konsole and Eterm, whenever $TERM is set to something
generic like "xterm" or "screen". You can override this default, however -
see |csapprox-configure|.
*csapprox-terminal-example*
To turn on high color support without fixing $TERM, you can change t_Co in
your .vimrc, and set either CSApprox_konsole or CSApprox_eterm if appropriate.
One way would be to put something like this into your |vimrc|:
>
if (&term == 'xterm' || &term =~? '^screen') && hostname() == 'my-machine'
" On my machine, I use Konsole with 256 color support
set t_Co=256
let g:CSApprox_konsole = 1
endif
Gnome Terminal, as of the time that I am writing this, doesn't support having
the terminal emulator set $TERM to something adequately descriptive. In cases
like this, something like the following would be appropriate:
>
if &term =~ '^\(xterm\|screen\)$' && $COLORTERM == 'gnome-terminal'
set t_Co=256
endif
==============================================================================
3. Configuration *csapprox-configure*
There are several global variables that can be set to configure the behavior
of CSApprox. They are listed roughly based on the likelihood that the end
user might want to know about them.
g:CSApprox_loaded *g:CSApprox_loaded*
If set in your |vimrc|, CSApprox is not loaded. Has no effect on
snapshotted schemes.
g:CSApprox_verbose_level *g:CSApprox_verbose_level*
When CSApprox is run, the 'verbose' option will be temporarily raised to
the value held in this variable unless it is already greater. The default
value is 1, which allows CSApprox to default to warning whenever something
is wrong, even if it is recoverable, but allows the user to quiet us if he
wants by changing this variable to 0. The most important messages will be
shown at verbosity level 1; some less important ones will be shown at
higher verbosity levels. Has no effect on snapshotted schemes.
g:CSApprox_eterm *g:CSApprox_eterm*
If set to a non-zero number, CSApprox will use the Eterm palette when
'term' is set to "xterm" or begins with "screen". Otherwise, the xterm
palette would be used. This also affects snapshotted schemes.
g:CSApprox_konsole *g:CSApprox_konsole*
If set to a non-zero number, CSApprox will use the Konsole palette when
'term' is set to "xterm" or begins with "screen". Otherwise, the xterm
palette would be used. This also affects snapshotted schemes.
g:CSApprox_attr_map *g:CSApprox_attr_map*
Since some attributes (like 'guisp') can't be used in a terminal, and
others (like 'italic') are often very ugly in terminals, a generic way to
map between a requested attribute and another attribute is included. This
variable should be set to a Dictionary, where the keys are strings
representing the attributes the author wanted set, and the values are the
strings that the user wants set instead. If a value is '', it means the
attribute should just be ignored. The default is to replace 'italic' with
'underline', and to use 'fg' instead of 'sp': >
let g:CSApprox_attr_map = { 'italic' : 'underline', 'sp' : 'fg' }
<
Your author prefers disabling bold and italic entirely, so uses this: >
let g:CSApprox_attr_map = { 'bold' : '', 'italic' : '', 'sp' : 'fg' }
<
Note: This transformation is considered at the time a snapshotted scheme
is created, rather than when it is used.
Note: You can only map an attribute representing a color to another
attribute representing a color; likewise with boolean attributes.
After all, sp -> bold and italic -> fg would be nonsensical.
*g:CSApprox_hook_pre* *g:CSApprox_hook_{scheme}_pre*
*g:CSApprox_hook_post* *g:CSApprox_hook_{scheme}_post*
g:CSApprox_hook_pre
g:CSApprox_hook_post
g:CSApprox_hook_{scheme}_pre
g:CSApprox_hook_{scheme}_post *csapprox-hooks*
These variables provide a method for adjusting tweaking the approximation
algorithm, either for all schemes, or on a per scheme basis. For
snapshotted schemes, these will only take effect when the snapshotted
scheme is created, rather than when it is used. Each of these variables
may be set to either a String containing a command to be :execute'd, or a
List of such Strings. The _pre hooks are executed before any
approximations have been done. In order to affect the approximation at
this stage, you would need to change the gui colors for a group; the cterm
colors will then be approximated from those gui colors. Example:
>
let g:CSApprox_hook_pre = 'hi Comment guibg=#ffddff'
<
The advantage to tweaking the colors at this stage is that CSApprox will
handle approximating the given gui colors to the proper cterm colors,
regardless of the number of colors the terminal supports. The
disadvantage is that certain things aren't possible, including clearing
the background or foreground color for a group, selecting a precise cterm
color to be used, and overriding the mappings made by g:CSApprox_attr_map.
Another notable disadvantage is that overriding things at this level will
actually affect the gui colors, in case the :gui is used to start gvim
from the running vim instance.
To overcome these disadvantages, the _post hooks are provided. These
hooks will be executed only after all approximations have been completed.
At this stage, in order to have changes appear the cterm* colors must be
modified. For example:
*csapprox-transparency*
>
let g:CSApprox_hook_post = ['hi Normal ctermbg=NONE ctermfg=NONE',
\ 'hi NonText ctermbg=NONE ctermfg=NONE' ]
<
Setting g:CSApprox_hook_post as shown above will clear the background of
the Normal and NonText groups, forcing the terminal's default background
color to be used instead, including any pseudotransparency done by that
terminal emulator. As noted, though, the _post functions do not allow
CSApprox to approximate the colors. This may be desired, but if this is
an inconvenience the function named by g:CSApprox_approximator_function
can still be called manually. For example:
>
let g:CSApprox_hook_post = 'exe "hi Comment ctermbg="'
\ . '. g:CSApprox_approximator_function(0xA0,0x50,0x35)'
<
The _{scheme}_ versions are exactly like their counterparts, except that
they will only be executed if the value of g:colors_name matches the
scheme name embedded in the variable name. They will be executed after
the corresponding hook without _{scheme}_, which provides a way to
override a less specific hook with a more specific one. For example, to
clear the Normal and NonText groups, but only for the colorscheme
"desert", one could do the following:
>
let g:CSApprox_hook_desert_post = ['hi Normal ctermbg=NONE ctermfg=NONE',
\ 'hi NonText ctermbg=NONE ctermfg=NONE' ]
<
One final example: If you want CSApprox to be active for nearly all
colorschemes, but want one or two particular schemes to be ignored, you
can take advantage of the CSApprox logic that skips over any color scheme
that is already high color by setting a color to a number above 255. Note
that most colors greater than 15 will work, but some will not - 256 should
always work. For instance, you can prevent CSApprox from modifying the
colors of the zellner colorscheme like this:
>
let g:CSApprox_hook_zellner_pre = 'hi _FakeGroup ctermbg=256'
<
NOTE: Any characters that would stop the string stored in g:colors_name
from being a valid variable name will be removed before the
_{scheme}_ hook is searched. Basically, this means that first all
characters that are neither alphanumeric nor underscore will be
removed, then any leading digits will be removed. So, for a
colorscheme named "123 foo_bar-baz456.vim", the hook searched for
will be, eg, g:CSApprox_hook_foo_barbaz456_post
g:CSApprox_use_showrgb *g:CSApprox_use_showrgb*
By default, CSApprox will use a built in mapping of color names to values.
This optimization greatly helps speed, but means that colors addressed by
name might not match up perfectly between gvim (which uses the system's
real rgb database) and CSApprox (which uses the builtin database). To
force CSApprox to try the systemwide database first, and only fall back on
the builtin database if it isn't available, set this variable non-zero.
g:CSApprox_approximator_function *g:CSApprox_approximator_function*
If the default approximation function doesn't work well enough, the user
(or another author wishing to extend this plugin) can write another
approximation function. This function should take three numbers,
representing r, g, and b in decimal, and return the index on the color
cube that best matches those colors. Assigning a |Funcref| to this
variable will override the default approximator with the one the Funcref
references. This option will take effect at the time a snapshotted scheme
is created, rather than when it's used.
g:CSApprox_redirfallback *g:CSApprox_redirfallback*
Until Vim 7.2.052, there was a bug in the Vim function synIDattr() that
made it impossible to determine syntax information about the |guisp|
attribute. CSApprox includes a workaround for this problem, as well as a
test that ought to disable this workaround if synIDattr() works properly.
If this test should happen to give improper results somehow, the user can
force the behavior with this variable. When set to 1, the workaround will
always be used, and when set to 0, synIDattr() is blindly used. Needless
to say, if this automatic detection should ever fail, the author would
like to be notified! This option will take effect at the time a
snapshotted scheme is created, rather than when it's used.
==============================================================================
4. Rationale/Design *csapprox-design*
There is a wealth of colorschemes available for Vim. Unfortunately, since
traditional terminal emulators have only supported 2, 8 or 16 colors,
colorscheme authors have tended to avoid writing colorschemes for terminal
Vim, sticking instead to GVim. Even now that nearly every popular terminal
supports either 88 or 256 colors, few colorschemes are written to support
them. This may be because the terminal color codes are just numbers from 0 to
87 or 255 with no semantic meaning, or because the same number doesn't yield
the same color in all terminals, or simply because the colorscheme author
doesn't use the terminal and doesn't want to take the time to support
terminals.
Whatever the reason, this leaves users of many modern terminal emulators in
the awkward position of having a terminal emulator that supports many colors,
but having very few colorschemes that were written to utilize those colors.
This is where CSApprox comes in. It attempts to fill this void allowing GVim
colorschemes to be used in terminal Vim. CSApprox has two distinct modes of
operation. In the first mode, it attempts to make GVim colorschemes
transparently backwards compatible with terminal Vim in a high color terminal.
Basically, whenever a colorscheme is run it should set some colors for the
GUI, and this script will then run and attempt to figure out the closest color
available in the terminal's color palette to the color the scheme author asked
for. Unfortunately, this does not work well all the time, and it has some
limitations (see |csapprox-limitations|). Most of the time, however, this
gives a very close approximation to the GVim colors without requiring any
changes to the colorscheme, or any user interaction. It only requires that
the plugin be installed on the machine where Vim is being run, and that the
user's environment meets the needs specified at |csapprox-requirements|. In
the event that this doesn't work, a second option - using :CSApproxSnapshot
to create a new, 88-/256-color capable colorscheme - is available.
Ideally, the aim is for CSApprox to be completely transparent to the user.
This is why the approach I take is entirely different from the GuiColorScheme
script, which will break on any but the simplest colorschemes. Unfortunately,
given the difficulty of determining exactly which terminal emulator the user
is running, and what features it supports, and which color palette it's using,
perfect transparency is difficult. So, to this end, I've attempted to default
to settings that make it unlikely that this script ever makes things worse
(this is why I chose not to override t_Co to 256 myself), and I've attempted
to make it easy to override my choice of defaults when necessary (through
g:CSApprox_approximator_function, g:CSApprox_konsole, g:CSApprox_eterm,
g:CSApprox_attr_map, etc).
In the event that the transparent solution is undesirable, or that the user's
environment can't be configured to allow it (no GVim and no Vim with +gui, for
instance), |:CSApproxSnapshot| should provide a workable alternative - less
cool, and less flexible, but it will work in more environments, and the
snapshotted colorscheme will even work in Vim 6.
If any of my design choices seem to be causing extra work with no real
advantages, though, I'd like to hear about it. Feel free to email me with any
improvements or complaints.
==============================================================================
5. Known Bugs and Limitations *csapprox-limitations*
GUI support is required for transparently adapting schemes.
There is nothing I can do about this given my chosen design. CSApprox works
by being notified every time a colorscheme sets some GUI colors, then
approximating those colors to similar terminal colors. Unfortunately, when
Vim is not built with GUI support, it doesn't bother to store the GUI
colors, so querying for them fails. This leaves me completely unable to
tell what the colorscheme was trying to do. See |csapprox-+gui| for some
potential workarounds if your distribution doesn't provide a Vim with +gui.
User intervention is sometimes required for information about the terminal.
This is really an insurmountable problem. Unfortunately, most terminal
emulators default to setting $TERM to 'xterm', even when they're not really
compatible with an xterm. $TERM is really the only reliable way to
find anything at all out about the terminal you're running in, so there's no
way to know if the terminal supports 88 or 256 colors without either the
terminal telling me (using $TERM) or the user telling me (using 't_Co').
Similarly, unless $TERM is set to something that implies a certain color
palette ought to be used, there's no way for me to know, so I'm forced to
default to the most common, xterm's palette, and allow the user to override
my choice with |g:CSApprox_konsole| or |g:CSApprox_eterm|. An example of
configuring Vim to work around a terminal where $TERM is set to something
generic without configuring the terminal properly is shown at
|csapprox-terminal-example|.
Some colorschemes could fail to be converted if they try to be too smart.
A colorscheme could decide to only set colors for the mode Vim is running
in. If a scheme only sets GUI colors when the GUI is running, instead of
using the usual approach of setting all colors and letting Vim choose which
to use, my approach falls apart. My method for figuring out what the scheme
author wants the scheme to look like absolutely depends upon him setting the
GUI colors in all modes. Fortunately, the few colorschemes that do this
seem to be, by and large, intended for 256 color terminals already, meaning
that skipping them is the proper behavior. Note that this will only affect
transparently adapted schemes and snapshots made from terminal Vim;
snapshots made from GVim are immune to this problem.
Transparently adapting schemes is slow.
For me, it takes Vim's startup time from 0.15 seconds to 0.35 seconds. This
is probably still acceptable, but it is definitely worth trying to cut down
on this time in future versions. Snapshotted schemes are faster to use,
since all of the hard evaluations are made when they're made instead of when
they're used.
NOTE: As of CSApprox 3.50, the overhead is down to about 0.10 seconds on my
test machine.
==============================================================================
6. Appendix - Terminals and Palettes *csapprox-terminal-list*
What follows is a list of terminals known to have and known not to have high
color support. This list is certainly incomplete; feel free to contact me
with more to add to either list.
*csapprox-terminals-good*
------------------------------- Good Terminals -------------------------------
The most recent versions of each of these terminals can be compiled with
either 88 or 256 color support.
*csapprox-xterm*
xterm:
256 color palette
Colors composed of: [ 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF ]
Greys composed of: [ 0x08, 0x12, 0x1C, 0x26, 0x30, 0x3A, 0x44, 0x4E,
0x58, 0x62, 0x6C, 0x76, 0x80, 0x8A, 0x94, 0x9E,
0xA8, 0xB2, 0xBC, 0xC6, 0xD0, 0xDA, 0xE4, 0xEE ]
*csapprox-urxvt*
rxvt-unicode (urxvt):
88 colors by default (but a patch is available to use xterm's palette)
Colors composed of: [ 0x00, 0x8B, 0xCD, 0xFF ]
Greys composed of: [ 0x2E, 0x5C, 0x73, 0x8B, 0xA2, 0xB9, 0xD0, 0xE7 ]
*csapprox-pterm* *csapprox-putty*
PuTTY (pterm; putty.exe):
256 colors; same palette as xterm
*csapprox-mrxvt*
Mrxvt (mrxvt):
256 colors; same palette as xterm
*csapprox-gnome-terminal*
GNOME Terminal (gnome-terminal):
256 colors; same palette as xterm
*csapprox-roxterm*
ROXTerm (roxterm):
256 colors; same palette as xterm
*csapprox-xfce4-terminal*
Terminal (xfce4-terminal):
256 colors; same palette as xterm
*csapprox-iterm.app*
iTerm (iTerm.app):
256 colors; same palette as xterm
*csapprox-konsole*
Konsole (konsole):
256 color palette
Colors composed of: [ 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF ]
Same greyscales as xterm
You should set the g:CSApprox_konsole variable unless $TERM begins with
'konsole', case insensitive
*csapprox-eterm*
eterm (Eterm):
256 color palette
Colors composed of: [ 0x00, 0x2A, 0x55, 0x7F, 0xAA, 0xD4 ]
Same greyscales as xterm
You should set the g:CSApprox_eterm variable unless $TERM begins with
'eterm', case insensitive
*csapprox-screen*
GNU Screen (screen):
256 color support. Internally, uses the xterm palette, but this is only
relevant when running screen inside a terminal with fewer than 256 colors,
in which case screen will attempt to map between its own 256 color cube
and the colors supported by the real terminal to the best of its ability,
in much the same way as CSApprox maps between GUI and terminal colors.
*csapprox-terminals-bad*
-------------------------------- Bad Terminals -------------------------------
This is a list of terminals known _not_ to have high color support. If any of
these terminals have high color support added at some point in the future,
please tell me and I'll update this information.
*csapprox-terminal.app*
Terminal.app (as of OS X 10.5.2)
*csapprox-aterm*
aterm (as of version 1.00.01)
*csapprox-xiterm*
xiterm (as of version 0.5)
*csapprox-wterm*
wterm (as of version 6.2.9)
*csapprox-mlterm*
mlterm (as of version 2.9.4)
*csapprox-kterm*
kterm (as of version 6.2.0)
==============================================================================
7. Changelog *csapprox-changelog*
3.50 01 Apr 2009 Fix a major regression that prevented the Eterm and
Konsole colors from being correctly snapshotted
Fix a related bug causing incorrect terminal colors
after calling :CSApproxSnapshot
Fix a bug causing black to be used instead of dark grey
Have snapshots calculate g:colors_name programmatically
Introduce many tweaks for better speed
Clarify some things at :help csapprox-terminal-example
Default to using our own list of rgb.txt colors rather
than searching, for performance. Add a new variable,
g:CSApprox_use_showrgb, which forces us to try finding
the colors using the "showrgb" program instead, and fall
back on our own list if it isn't available
Remove g:CSApprox_extra_rgb_txt_dirs - not needed in
light of the above change
3.05 31 Jan 2009 Fix a harmless "Undefined variable" error in
:CSApproxSnapshot
Fix a behavioral bug when dumping out colors defined
external to the scheme.
3.00 21 Jan 2009 Update the docs for better info on :CSApproxSnapshot
Allow snapshotted schemes to work on Vim 6, and work
properly in Konsole and Eterm (thanks David Majnemer!)
Fix a bug causing a syntax error when using GVim while
CSApprox was loaded. (thanks again, David Majnemer!)
2.00 14 Dec 2008 Add a hooks system, allowing users to specify a command
to run, either before or after the approximation
algorithm is run, for all schemes or one specific one.
Also rewrite :CSApproxSnapshot to be more maintainable
and less of a hack, and fix several bugs that it
contained.
1.50 19 Nov 2008 Add CSApproxSnapshot command, as an alternative solution
when the user has gvim or a vim with gui support, but
sometimes needs to use a vim without gui support.
1.10 28 Oct 2008 Enable running on systems with no rgb.txt (Penn Su)
Begin distributing a copy of rgb.txt with CSApprox
1.00 04 Oct 2008 First public release
0.90 14 Sep 2008 Initial beta release
==============================================================================
8. Contact Info *csapprox-author*
Your author, a Vim nerd with some free time, was sick of seeing terminals
always get the short end of the stick. He'd like to be notified of any
problems you find - after all, he took the time to write all this lovely
documentation, and this plugin, which took more time than you could possibly
imagine to get working transparently for every colorscheme he could get his
hands on. You can contact him with any problems or praises at mjw@drexel.edu
==============================================================================
vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
*coffee-script.txt* For Vim version 7.3
=============================================================================
Author: Mick Koch <kchmck@gmail.com> *coffee-script-author*
License: WTFPL (see |coffee-script-license|)
=============================================================================
CONTENTS *coffee-script-contents*
|coffee-script-introduction| Introduction and Feature Summary
|coffee-script-commands| Commands
|coffee-script-settings| Settings
{Vi does not have any of this}
=============================================================================
INTRODUCTION *coffee-script*
*coffee-script-introduction*
This plugin adds support for CoffeeScript syntax, indenting, and compiling.
Also included is an eco syntax and support for CoffeeScript in Haml and HTML.
COMMANDS *coffee-script-commands*
*:CoffeeMake*
:CoffeeMake[!] {opts} Wrapper around |:make| that also passes options in
|g:coffee_make_options| to the compiler. Use |:silent|
to hide compiler output. See |:make| for more
information about the bang and other helpful commands.
*:CoffeeCompile*
:[range]CoffeeCompile [vertical] [{win-size}]
Shows how the current file or [range] is compiled
to JavaScript. [vertical] (or vert) splits the
compile buffer vertically instead of horizontally, and
{win-size} sets the initial size of the buffer. It can
be closed quickly with the "q" key.
:CoffeeCompile {watch} [vertical] [{win-size}]
The watch mode of :CoffeeCompile emulates the "Try
CoffeeScript" live preview on the CoffeeScript web
site. After making changes to the source file,
exiting insert mode will cause the preview buffer to
update automatically. {watch} should be given as
"watch" or "unwatch," where the latter will stop the
automatic updating. [vertical] is recommended, and
'scrollbind' is useful.
*:CoffeeRun*
:[range]CoffeeRun Compiles the file or [range] and runs the resulting
JavaScript, displaying the output.
SETTINGS *coffee-script-settings*
You can configure plugin behavior using global variables and syntax commands
in your |vimrc|.
Global Settings~
*g:coffee_make_options*
Set default options |CoffeeMake| should pass to the compiler.
>
let coffee_make_options = '--bare'
<
*g:coffee_compile_vert*
Split the CoffeeCompile buffer vertically by default.
>
let coffee_compile_vert = 1
Syntax Highlighting~
*ft-coffee-script-syntax*
Trailing whitespace is highlighted as an error by default. This can be
disabled with:
>
hi link coffeeSpaceError NONE
Trailing semicolons are also considered an error (for help transitioning from
JavaScript.) This can be disabled with:
>
hi link coffeeSemicolonError NONE
Reserved words like {function} and {var} are highlighted where they're not
allowed in CoffeeScript. This can be disabled with:
>
hi link coffeeReservedError NONE
COMPILER *compiler-coffee-script*
A CoffeeScript compiler is provided as a wrapper around {coffee} and can be
loaded with;
>
compiler coffee
This is done automatically when a CoffeeScript file is opened if no other
compiler is loaded.
=============================================================================
LICENSE *coffee-script-license*
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2010 to 2011 Mick Koch <kchmck@gmail.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
vim:tw=78:ts=8:ft=help:norl:
*command-t.txt* Command-T plug-in for Vim *command-t*
CONTENTS *command-t-contents*
1. Introduction |command-t-intro|
2. Requirements |command-t-requirements|
3. Installation |command-t-installation|
3. Managing using Pathogen |command-t-pathogen|
4. Trouble-shooting |command-t-trouble-shooting|
5. Usage |command-t-usage|
6. Commands |command-t-commands|
7. Mappings |command-t-mappings|
8. Options |command-t-options|
9. FAQ |command-t-faq|
10. Tips |command-t-tips|
11. Authors |command-t-authors|
12. Development |command-t-development|
13. Website |command-t-website|
14. Donations |command-t-donations|
15. License |command-t-license|
16. History |command-t-history|
INTRODUCTION *command-t-intro*
The Command-T plug-in provides an extremely fast, intuitive mechanism for
opening files and buffers with a minimal number of keystrokes. It's named
"Command-T" because it is inspired by the "Go to File" window bound to
Command-T in TextMate.
Files are selected by typing characters that appear in their paths, and are
ordered by an algorithm which knows that characters that appear in certain
locations (for example, immediately after a path separator) should be given
more weight.
To search efficiently, especially in large projects, you should adopt a
"path-centric" rather than a "filename-centric" mentality. That is you should
think more about where the desired file is found rather than what it is
called. This means narrowing your search down by including some characters
from the upper path components rather than just entering characters from the
filename itself.
Screencasts demonstrating the plug-in can be viewed at:
https://wincent.com/products/command-t
REQUIREMENTS *command-t-requirements*
The plug-in requires Vim compiled with Ruby support, a compatible Ruby
installation at the operating system level, and a C compiler to build
the Ruby extension.
1. Vim compiled with Ruby support ~
You can check for Ruby support by launching Vim with the --version switch:
vim --version
If "+ruby" appears in the version information then your version of Vim has
Ruby support.
Another way to check is to simply try using the :ruby command from within Vim
itself:
:ruby 1
If your Vim lacks support you'll see an error message like this:
E319: Sorry, the command is not available in this version
The version of Vim distributed with OS X may not include Ruby support (for
example, Snow Leopard, which was the current version of OS X when Command-T
was first released, did not support Ruby in the system Vim, but the current
version of OS X at the time of writing, Mavericks, does). All recent versions
of MacVim come with Ruby support; it is available from:
http://github.com/b4winckler/macvim/downloads
For Windows users, the Vim 7.2 executable available from www.vim.org does
include Ruby support, and is recommended over version 7.3 (which links against
Ruby 1.9, but apparently has some bugs that need to be resolved).
2. Ruby ~
In addition to having Ruby support in Vim, your system itself must have a
compatible Ruby install. "Compatible" means the same version as Vim itself
links against. If you use a different version then Command-T is unlikely
to work (see |command-t-trouble-shooting| below).
On OS X Snow Leopard, Lion and Mountain Lion, the system comes with Ruby 1.8.7
and all recent versions of MacVim (the 7.2 snapshots and 7.3) are linked
against it.
On OS X Mavericks, the default system ruby is 2.0, but MacVim continues to
link against 1.8.7, which is also present on the system at:
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
On Linux and similar platforms, the linked version of Ruby will depend on
your distribution. You can usually find this out by examining the
compilation and linking flags displayed by the |:version| command in Vim, and
by looking at the output of:
:ruby puts "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
A suitable Ruby environment for Windows can be installed using the Ruby
1.8.7-p299 RubyInstaller available at:
http://rubyinstaller.org/downloads/archives
If using RubyInstaller be sure to download the installer executable, not the
7-zip archive. When installing mark the checkbox "Add Ruby executables to your
PATH" so that Vim can find them.
3. C compiler ~
Part of Command-T is implemented in C as a Ruby extension for speed, allowing
it to work responsively even on directory hierarchies containing enormous
numbers of files. As such, a C compiler is required in order to build the
extension and complete the installation.
On OS X, this can be obtained by installing the Xcode Tools from the App
Store.
On Windows, the RubyInstaller Development Kit can be used to conveniently
install the necessary tool chain:
http://rubyinstaller.org/downloads/archives
At the time of writing, the appropriate development kit for use with Ruby
1.8.7 is DevKit-3.4.5r3-20091110.
To use the Development Kit extract the archive contents to your C:\Ruby
folder.
INSTALLATION *command-t-installation*
You can install Command-T by obtaining the source files and building the C
extension. The recommended way to get the source is by using a plug-in
management system such as Pathogen (see |command-t-pathogen|).
Command-T is also distributed as a "vimball" which means that it can be
installed by opening it in Vim and then sourcing it:
:e command-t.vba
:so %
The files will be installed in your |'runtimepath'|. To check where this is
you can issue:
:echo &rtp
The C extension must then be built, which can be done from the shell. If you
use a typical |'runtimepath'| then the files were installed inside ~/.vim and
you can build the extension with:
cd ~/.vim/ruby/command-t
ruby extconf.rb
make
Note: If you are an RVM or rbenv user, you must perform the build using the
same version of Ruby that Vim itself is linked against. This will often be the
system Ruby, which can be selected before issuing the "make" command with one
of the following commands:
rvm use system
rbenv local system
Note: If you are on OS X Mavericks and compiling against MacVim, the default
system Ruby is 2.0 but MacVim still links against the older 1.8.7 Ruby that is
also bundled with the system; in this case the build command becomes:
cd ~/.vim/ruby/command-t
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb
make
Note: Make sure you compile targeting the same architecture Vim was built for.
For instance, MacVim binaries are built for i386, but sometimes GCC compiles
for x86_64. First you have to check the platform Vim was built for:
vim --version
...
Compilation: gcc ... -arch i386 ...
...
and make sure you use the correct ARCHFLAGS during compilation:
export ARCHFLAGS="-arch i386"
make
Note: If you are on Fedora 17+, you can install Command-T from the system
repository with:
su -c 'yum install vim-command-t'
MANAGING USING PATHOGEN *command-t-pathogen*
Pathogen is a plugin that allows you to maintain plugin installations in
separate, isolated subdirectories under the "bundle" directory in your
|'runtimepath'|. The following examples assume that you already have
Pathogen installed and configured, and that you are installing into
~/.vim/bundle. For more information about Pathogen, see:
http://www.vim.org/scripts/script.php?script_id=2332
If you manage your entire ~/.vim folder using Git then you can add the
Command-T repository as a submodule:
cd ~/.vim
git submodule add git://git.wincent.com/command-t.git bundle/command-t
git submodule init
Or if you just wish to do a simple clone instead of using submodules:
cd ~/.vim
git clone git://git.wincent.com/command-t.git bundle/command-t
Once you have a local copy of the repository you can update it at any time
with:
cd ~/.vim/bundle/command-t
git pull
Or you can switch to a specific release with:
cd ~/.vim/bundle/command-t
git checkout 0.8b
After installing or updating you must build the extension:
cd ~/.vim/bundle/command-t/ruby/command-t
ruby extconf.rb
make
While the Vimball installation automatically generates the help tags, under
Pathogen it is necessary to do so explicitly from inside Vim:
:call pathogen#helptags()
TROUBLE-SHOOTING *command-t-trouble-shooting*
Most installation problems are caused by a mismatch between the version of
Ruby on the host operating system, and the version of Ruby that Vim itself
linked against at compile time. For example, if one is 32-bit and the other is
64-bit, or one is from the Ruby 1.9 series and the other is from the 1.8
series, then the plug-in is not likely to work.
As such, on OS X, I recommend using the standard Ruby that comes with the
system (currently 1.8.7) along with the latest version of MacVim (currently
version 7.3). If you wish to use custom builds of Ruby or of MacVim (not
recommmended) then you will have to take extra care to ensure that the exact
same Ruby environment is in effect when building Ruby, Vim and the Command-T
extension.
For Windows, the following combination is known to work:
- Vim 7.2 from http://www.vim.org/download.php:
ftp://ftp.vim.org/pub/vim/pc/gvim72.exe
- Ruby 1.8.7-p299 from http://rubyinstaller.org/downloads/archives:
http://rubyforge.org/frs/download.php/71492/rubyinstaller-1.8.7-p299.exe
- DevKit 3.4.5r3-20091110 from http://rubyinstaller.org/downloads/archives:
http://rubyforge.org/frs/download.php/66888/devkit-3.4.5r3-20091110.7z
If a problem occurs the first thing you should do is inspect the output of:
ruby extconf.rb
make
During the installation, and:
vim --version
And compare the compilation and linker flags that were passed to the
extension and to Vim itself when they were built. If the Ruby-related
flags or architecture flags are different then it is likely that something
has changed in your Ruby environment and the extension may not work until
you eliminate the discrepancy.
USAGE *command-t-usage*
Bring up the Command-T file window by typing:
<Leader>t
This mapping is set up automatically for you, provided you do not already have
a mapping for <Leader>t or |:CommandT|. You can also bring up the file window
by issuing the command:
:CommandT
A prompt will appear at the bottom of the screen along with a file window
showing all of the files in the current directory (as returned by the
|:pwd| command).
For the most efficient file navigation within a project it's recommended that
you |:cd| into the root directory of your project when starting to work on it.
If you wish to open a file from outside of the project folder you can pass in
an optional path argument (relative or absolute) to |:CommandT|:
:CommandT ../path/to/other/files
Type letters in the prompt to narrow down the selection, showing only the
files whose paths contain those letters in the specified order. Letters do not
need to appear consecutively in a path in order for it to be classified as a
match.
Once the desired file has been selected it can be opened by pressing <CR>.
(By default files are opened in the current window, but there are other
mappings that you can use to open in a vertical or horizontal split, or in
a new tab.) Note that if you have |'nohidden'| set and there are unsaved
changes in the current window when you press <CR> then opening in the current
window would fail; in this case Command-T will open the file in a new split.
The following mappings are active when the prompt has focus:
<BS> delete the character to the left of the cursor
<Del> delete the character at the cursor
<Left> move the cursor one character to the left
<C-h> move the cursor one character to the left
<Right> move the cursor one character to the right
<C-l> move the cursor one character to the right
<C-a> move the cursor to the start (left)
<C-e> move the cursor to the end (right)
<C-u> clear the contents of the prompt
<Tab> change focus to the file listing
The following mappings are active when the file listing has focus:
<Tab> change focus to the prompt
The following mappings are active when either the prompt or the file listing
has focus:
<CR> open the selected file
<C-CR> open the selected file in a new split window
<C-s> open the selected file in a new split window
<C-v> open the selected file in a new vertical split window
<C-t> open the selected file in a new tab
<C-j> select next file in the file listing
<C-n> select next file in the file listing
<Down> select next file in the file listing
<C-k> select previous file in the file listing
<C-p> select previous file in the file listing
<Up> select previous file in the file listing
<C-f> flush the cache (see |:CommandTFlush| for details)
<C-q> place the current matches in the quickfix window
<C-c> cancel (dismisses file listing)
The following is also available on terminals which support it:
<Esc> cancel (dismisses file listing)
Note that the default mappings can be overriden by setting options in your
~/.vimrc file (see the OPTIONS section for a full list of available options).
In addition, when the file listing has focus, typing a character will cause
the selection to jump to the first path which begins with that character.
Typing multiple characters consecutively can be used to distinguish between
paths which begin with the same prefix.
COMMANDS *command-t-commands*
*:CommandT*
|:CommandT| Brings up the Command-T file window, starting in the
current working directory as returned by the|:pwd|
command.
*:CommandTBuffer*
|:CommandTBuffer|Brings up the Command-T buffer window.
This works exactly like the standard file window,
except that the selection is limited to files that
you already have open in buffers.
*:CommandTJumps*
|:CommandTJump| Brings up the Command-T jumplist window.
This works exactly like the standard file window,
except that the selection is limited to files that
you already have in the jumplist. Note that jumps
can persist across Vim sessions (see Vim's |jumplist|
documentation for more info).
*:CommandTTag*
|:CommandTTag| Brings up the Command-T window tags window, which can
be used to select from the tags, if any, returned by
Vim's |taglist()| function. See Vim's |tag| documentation
for general info on tags.
*:CommandTFlush*
|:CommandTFlush|Instructs the plug-in to flush its path cache, causing
the directory to be rescanned for new or deleted paths
the next time the file window is shown (pressing <C-f> when
a match listing is visible flushes the cache immediately; this
mapping is configurable via the |g:CommandTRefreshMap|
setting). In addition, all configuration settings are
re-evaluated, causing any changes made to settings via the
|:let| command to be picked up.
MAPPINGS *command-t-mappings*
By default Command-T comes with only two mappings:
<Leader>t bring up the Command-T file window
<Leader>b bring up the Command-T buffer window
However, Command-T won't overwrite a pre-existing mapping so if you prefer
to define different mappings use lines like these in your ~/.vimrc:
nnoremap <silent> <Leader>t :CommandT<CR>
nnoremap <silent> <Leader>b :CommandTBuffer<CR>
Replacing "<Leader>t" or "<Leader>b" with your mapping of choice.
Note that in the case of MacVim you actually can map to Command-T (written
as <D-t> in Vim) in your ~/.gvimrc file if you first unmap the existing menu
binding of Command-T to "New Tab":
if has("gui_macvim")
macmenu &File.New\ Tab key=<nop>
map <D-t> :CommandT<CR>
endif
When the Command-T window is active a number of other additional mappings
become available for doing things like moving between and selecting matches.
These are fully described above in the USAGE section, and settings for
overriding the mappings are listed below under OPTIONS.
OPTIONS *command-t-options*
A number of options may be set in your ~/.vimrc to influence the behaviour of
the plug-in. To set an option, you include a line like this in your ~/.vimrc:
let g:CommandTMaxFiles=20000
To have Command-T pick up new settings immediately (that is, without having
to restart Vim) you can issue the |:CommandTFlush| command after making
changes via |:let|.
Following is a list of all available options:
*g:CommandTMaxFiles*
|g:CommandTMaxFiles| number (default 30000)
The maximum number of files that will be considered when scanning the
current directory. Upon reaching this number scanning stops. This
limit applies only to file listings and is ignored for buffer
listings.
*g:CommandTMaxDepth*
|g:CommandTMaxDepth| number (default 15)
The maximum depth (levels of recursion) to be explored when scanning the
current directory. Any directories at levels beyond this depth will be
skipped.
*g:CommandTMaxCachedDirectories*
|g:CommandTMaxCachedDirectories| number (default 1)
The maximum number of directories whose contents should be cached when
recursively scanning. With the default value of 1, each time you change
directories the cache will be emptied and Command-T will have to
rescan. Higher values will make Command-T hold more directories in the
cache, bringing performance at the cost of memory usage. If set to 0,
there is no limit on the number of cached directories.
*g:CommandTMaxHeight*
|g:CommandTMaxHeight| number (default: 0)
The maximum height in lines the match window is allowed to expand to.
If set to 0, the window will occupy as much of the available space as
needed to show matching entries.
*g:CommandTInputDebounce*
|g:CommandTInputDebounce| number (default: 50)
The number of milliseconds to wait before updating the match listing
following a key-press. This can be used to avoid wasteful recomputation
when making a rapid series of key-presses in a directory with many tens
(or hundreds) of thousands of files.
*g:CommandTFileScanner*
|g:CommandTFileScanner| string (default: 'ruby')
The underlying scanner implementation that should be used to explore the
filesystem. Possible values are:
- "ruby": uses built-in Ruby and should work everywhere, albeit slowly
on large (many tens of thousands of files) hierarchies.
- "find": uses the command-line tool of the same name, which can be much
faster on large projects because it is written in pure C, but may not
work on systems without the tool or with an incompatible version of
the tool.
- "watchman": uses Watchman (https://github.com/facebook/watchman) if
available; otherwise falls back to "find". Note that this scanner is
intended for use with very large hierarchies (hundreds of thousands of
files) and so the task of deciding which files should be included is
entirely delegated to Watchman; this means that settings which
Command-T would usually consult, such as 'wildignore' and
|g:CommandTScanDotDirectories| are ignored.
*g:CommandTMinHeight*
|g:CommandTMinHeight| number (default: 0)
The minimum height in lines the match window is allowed to shrink to.
If set to 0, will default to a single line. If set above the max height,
will default to |g:CommandTMaxHeight|.
*g:CommandTAlwaysShowDotFiles*
|g:CommandTAlwaysShowDotFiles| boolean (default: 0)
When showing the file listing Command-T will by default show dot-files
only if the entered search string contains a dot that could cause a
dot-file to match. When set to a non-zero value, this setting instructs
Command-T to always include matching dot-files in the match list
regardless of whether the search string contains a dot. See also
|g:CommandTNeverShowDotFiles|. Note that this setting only influences
the file listing; the buffer listing treats dot-files like any other
file.
*g:CommandTNeverShowDotFiles*
|g:CommandTNeverShowDotFiles| boolean (default: 0)
In the file listing, Command-T will by default show dot-files if the
entered search string contains a dot that could cause a dot-file to
match. When set to a non-zero value, this setting instructs Command-T to
never show dot-files under any circumstances. Note that it is
contradictory to set both this setting and
|g:CommandTAlwaysShowDotFiles| to true, and if you do so Vim will suffer
from headaches, nervous twitches, and sudden mood swings. This setting
has no effect in buffer listings, where dot files are treated like any
other file.
*g:CommandTScanDotDirectories*
|g:CommandTScanDotDirectories| boolean (default: 0)
Normally Command-T will not recurse into "dot-directories" (directories
whose names begin with a dot) while performing its initial scan. Set
this setting to a non-zero value to override this behavior and recurse.
Note that this setting is completely independent of the
|g:CommandTAlwaysShowDotFiles| and |g:CommandTNeverShowDotFiles|
settings; those apply only to the selection and display of matches
(after scanning has been performed), whereas
|g:CommandTScanDotDirectories| affects the behaviour at scan-time.
Note also that even with this setting off you can still use Command-T to
open files inside a "dot-directory" such as ~/.vim, but you have to use
the |:cd| command to change into that directory first. For example:
:cd ~/.vim
:CommandT
*g:CommandTMatchWindowAtTop*
|g:CommandTMatchWindowAtTop| boolean (default: 0)
When this setting is off (the default) the match window will appear at
the bottom so as to keep it near to the prompt. Turning it on causes the
match window to appear at the top instead. This may be preferable if you
want the best match (usually the first one) to appear in a fixed location
on the screen rather than moving as the number of matches changes during
typing.
*g:CommandTMatchWindowReverse*
|g:CommandTMatchWindowReverse| boolean (default: 0)
When this setting is off (the default) the matches will appear from
top to bottom with the topmost being selected. Turning it on causes the
matches to be reversed so the best match is at the bottom and the
initially selected match is the bottom most. This may be preferable if
you want the best match to appear in a fixed location on the screen
but still be near the prompt at the bottom.
*g:CommandTTagIncludeFilenames*
|g:CommandTTagIncludeFilenames| boolean (default: 0)
When this setting is off (the default) the matches in the |:CommandTTag|
listing do not include filenames.
*g:CommandTHighlightColor*
|g:CommandTHighlightColor| string (default: 'PmenuSel')
Specifies the highlight color that will be used to show the currently
selected item in the match listing window.
*g:CommandTWildIgnore*
|g:CommandTWildIgnore| string (default: none)
Optionally override Vim's global |'wildignore'| setting during Command-T
searches. If you wish to supplement rather than replace the global
setting, you can use a syntax like:
let g:CommandTWildIgnore=&wildignore . ",**/bower_components/*"
See also |command-t-wildignore|.
As well as the basic options listed above, there are a number of settings that
can be used to override the default key mappings used by Command-T. For
example, to set <C-x> as the mapping for cancelling (dismissing) the Command-T
window, you would add the following to your ~/.vimrc:
let g:CommandTCancelMap='<C-x>'
Multiple, alternative mappings may be specified using list syntax:
let g:CommandTCancelMap=['<C-x>', '<C-c>']
Following is a list of all map settings and their defaults:
Setting Default mapping(s)
*g:CommandTBackspaceMap*
|g:CommandTBackspaceMap| <BS>
*g:CommandTDeleteMap*
|g:CommandTDeleteMap| <Del>
*g:CommandTAcceptSelectionMap*
|g:CommandTAcceptSelectionMap| <CR>
*g:CommandTAcceptSelectionSplitMap*
|g:CommandTAcceptSelectionSplitMap| <C-CR>
<C-s>
*g:CommandTAcceptSelectionTabMap*
|g:CommandTAcceptSelectionTabMap| <C-t>
*g:CommandTAcceptSelectionVSplitMap*
|g:CommandTAcceptSelectionVSplitMap| <C-v>
*g:CommandTToggleFocusMap*
|g:CommandTToggleFocusMap| <Tab>
*g:CommandTCancelMap*
|g:CommandTCancelMap| <C-c>
<Esc> (not on all terminals)
*g:CommandTSelectNextMap*
|g:CommandTSelectNextMap| <C-n>
<C-j>
<Down>
*g:CommandTSelectPrevMap*
|g:CommandTSelectPrevMap| <C-p>
<C-k>
<Up>
*g:CommandTClearMap*
|g:CommandTClearMap| <C-u>
*g:CommandTRefreshMap*
|g:CommandTRefreshMap| <C-f>
*g:CommandTQuickfixMap*
|g:CommandTQuickfixMap| <C-q>
*g:CommandTCursorLeftMap*
|g:CommandTCursorLeftMap| <Left>
<C-h>
*g:CommandTCursorRightMap*
|g:CommandTCursorRightMap| <Right>
<C-l>
*g:CommandTCursorEndMap*
|g:CommandTCursorEndMap| <C-e>
*g:CommandTCursorStartMap*
|g:CommandTCursorStartMap| <C-a>
In addition to the options provided by Command-T itself, some of Vim's own
settings can be used to control behavior:
*command-t-wildignore*
|'wildignore'| string (default: '')
Vim's |'wildignore'| setting is used to determine which files should be
excluded from listings. This is a comma-separated list of glob patterns.
It defaults to the empty string, but common settings include "*.o,*.obj"
(to exclude object files) or ".git,.svn" (to exclude SCM metadata
directories). For example:
:set wildignore+=*.o,*.obj,.git
A pattern such as "vendor/rails/**" would exclude all files and
subdirectories inside the "vendor/rails" directory (relative to
directory Command-T starts in).
See the |'wildignore'| documentation for more information.
If you want to influence Command-T's file exclusion behavior without
changing your global |'wildignore'| setting, you can use the
|g:CommandTWildIgnore| setting to apply an override that takes effect
only during Command-T searches.
FAQ *command-t-faq*
Why does my build fail with "unknown argument -multiply_definedsuppress"? ~
You may see this on OS X Mavericks when building with the Clang compiler
against the system Ruby. This is an unfortunate Apple bug that breaks
compilation of many Ruby gems with native extensions on Mavericks. It has been
worked around in the upstream Ruby version, but won't be fixed in OS X until
Apple updates their supplied version of Ruby (most likely this won't be until
the next major release):
https://bugs.ruby-lang.org/issues/9624
Workarounds include building your own Ruby (and then your own Vim and
Command-T), or more simply, building with the following `ARCHFLAGS` set:
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future ruby extconf.rb
make
Why can't I open in a split with <C-CR> and <C-s> in the terminal? ~
It's likely that <C-CR> won't work in most terminals, because the keycode that
is sent to processes running inside them is identical to <CR>; when you type
<C-CR>, terminal Vim literally "sees" <CR>. Unfortunately, there is no
workaround for this.
If you find that <C-s> also doesn't work the most likely explanation is that
XON/XOFF flow control is enabled; this is the default in many environments.
This means that when you press <C-s> all input to the terminal is suspended
until you release it by hitting <C-q>. While input is suspended you may think
your terminal has frozen, but it hasn't.
To disable flow control, add the following to your `.zshrc` or
`.bash_profile`:
stty -ixon
See the `stty` man page for more details.
TIPS *command-t-tips*
Working with very large repositories ~
One of the primary motivations for writing Command-T was to get fast, robust
high-quality matches even on large hierarchies. The larger the hierarchy, the
more important having good file navigation becomes. This is why Command-T's
performance-critical sections are written in C. This requires a compilation
step and makes Command-T harder to install than similar plug-ins which are
written in pure Vimscript, and can be a disincentive against use. This is a
conscious trade-off; the goal isn't to have as many users as possible, but
rather to provide the best performance at the highest quality.
The speed of the core is high enough that Command-T can afford to burn a bunch
of extra cycles -- using its recursive matching algorithm -- looking for a
higher-quality, more intuitive ranking of search results. Again, the larger
the hierarchy, the more important the quality of result ranking becomes.
Nevertheless, for extremely large hierarchies (of the order of 500,000 files)
some tuning is required in order to get useful and usable performance levels.
Here are some useful example settings:
let g:CommandTMaxHeight = 30
You want the match listing window to be large enough that you can get useful
feedback about how your search query is going; in large hierarchies there may
be many, many matches for a given query. At the same time, you don't want Vim
wasting valuable cycles repainting a large portion of the screen area,
especially on a large display. Setting the limit to 30 or similar is a
reasonable compromise.
let g:CommandTMaxFiles = 500000
The default limit of 30,000 files prevents Command-T from "seeing" many of the
files in a large directory hierarchy so you need to increase this limit.
let g:CommandTInputDebounce = 200
Wait for 200ms of keyboard inactivity before computing search results. For
example, if you are enter "foobar" quickly (ie. within 1 second), there is
little sense in fetching the results for "f", "fo", "foo", "foob", "fooba" and
finally "foobar". Instead, we can just fetch the results for "foobar". This
setting trades off some immediate responsiveness at the micro level for
better performance (real and perceived) and a better search experience
overall.
let g:CommandTFileScanner = 'watchman'
On a large hierarchy with of the order of 500,000 files, scanning a directory
tree with a tool like the `find` executable may take literally minutes with a
cold cache. Once the cache is warm, the same `find` run may take only a second
or two. Command-T provides a "find" scanner to leverage this performance, but
there is still massive overhead in passing the results through Vim internal
functions that apply 'wildignore' settings and such, so for truly immense
repos the "watchman" scanner is the tool of choice.
This scanner delegates the task of finding files to Facebook's `watchman` tool
(https://github.com/facebook/watchman), which can return results for a 500,000
file hierarchy within about a second.
Note that Watchman has a range of configuration options that can be applied by
files such as `/etc/watchman.json` or per-direcory `.watchmanconfig` files and
which may affect how Command-T works. For example, if your configuration has a
`root_restrict_files` setting that makes Watchman only work with roots that
look like Git or Mercurial repos, then Command-T will fall back to using the
"find" scanner any time you invoke it on a non-repo directory. For
simplicity's sake, it is probably a good idea to use Vim and Command-T
anchored at the root level of your repository in any case.
let g:CommandTMaxCachedDirectories = 10
Command-T will internally cache up to 10 different directories, so even if you
|cd| repeatedly, it should only need to scan each directory once.
It's advisable to keep a long-running Vim instance in place and let it cache
the directory listings rather than repeatedly closing and re-opening Vim in
order to edit every file. On those occasions when you do need to flush the
cache (ie. with |CommandTFlush| or <C-f> in the match listing window), use of
the Watchman scanner should make the delay barely noticeable.
As noted in the introduction, Command-T works best when you adopt a
"path-centric" mentality. This is especially true on very large hierarchies.
For example, if you're looking for a file at:
lib/third-party/adapters/restful-services/foobar/foobar-manager.js
you'll be able to narrow your search results down more narrowly if you search
with a query like "librestfoofooman" than "foobar-manager.js". This evidently
requires that you know where the file you're wanting to open exists, but
again, this is a concious design decision: Command-T is made to enable people
who know what they want to open and where it is to open it as quickly as
possible; other tools such as NERDTree exist for visually exploring an unknown
hierarchy.
Over time, you will get a feel for how economical you can afford to be with
your search queries in a given repo. In the example above, if "foo" is not a
very common pattern in your hierarchy, then you may find that you can find
what you need with a very concise query such as "foomanjs". With time, this
kind of ongoing calibration will come quite naturally.
Finally, it is important to be on a relatively recent version of Command-T to
fully benefit from the available performance enhancements:
- version 1.8 (March 2013) sped up the Watchman file scanner by switching its
communication from the JSON to the binary Watchman protocol
- version 1.7 (February 2014) added the |g:CommandTInputDebounce| and
|g:CommandTFileScanner| settings, along with support for the Watchman file
scanner
- version 1.6 (December 2013) added parallelized search
- version 1.5 (September 2013) added memoization to the matching algorithm,
improving general performance on large hierarchies, but delivering
spectacular gains on hierarchies with "pathological" characteristics that
lead the algorithm to exhibit degenerate behavior
AUTHORS *command-t-authors*
Command-T is written and maintained by Wincent Colaiuta <win@wincent.com>.
Other contributors that have submitted patches include (in alphabetical
order):
Andy Waite Mike Lundy Shlomi Fish
Anthony Panozzo Nadav Samet Steven Moazami
Daniel Hahler Nate Kane Sung Pae
Felix Tjandrawibawa Nicholas Alpi Thomas Pelletier
Gary Bernhardt Noon Silk Victor Hugo Borja
Ivan Ukhov Paul Jolly Vít Ondruch
Jeff Kreeftmeijer Pavel Sergeev Woody Peterson
Lucas de Vries Rainux Luo Yan Pritzker
Marcus Brito Roland Puntaier Yiding Jia
Marian Schubert Scott Bronson Zak Johnson
Matthew Todd Seth Fowler
As this was the first Vim plug-in I had ever written I was heavily influenced
by the design of the LustyExplorer plug-in by Stephen Bach, which I understand
was one of the largest Ruby-based Vim plug-ins at the time.
While the Command-T codebase doesn't contain any code directly copied from
LustyExplorer, I did use it as a reference for answers to basic questions (like
"How do you do 'X' in a Ruby-based Vim plug-in?"), and also copied some basic
architectural decisions (like the division of the code into Prompt, Settings
and MatchWindow classes).
LustyExplorer is available from:
http://www.vim.org/scripts/script.php?script_id=1890
DEVELOPMENT *command-t-development*
Development in progress can be inspected via the project's Git web-based
repository browser at:
https://wincent.com/repos/command-t
the clone URL for which is:
git://git.wincent.com/command-t.git
Mirrors exist on GitHub and Gitorious; these are automatically updated once
per hour from the authoritative repository:
https://github.com/wincent/command-t
https://gitorious.org/command-t/command-t
Patches are welcome via the usual mechanisms (pull requests, email, posting to
the project issue tracker etc).
As many users choose to track Command-T using Pathogen, which often means
running a version later than the last official release, the intention is that
the "master" branch should be kept in a stable and reliable state as much as
possible.
Riskier changes are first cooked on the "next" branch for a period before
being merged into master. You can track this branch if you're feeling wild and
experimental, but note that the "next" branch may periodically be rewound
(force-updated) to keep it in sync with the "master" branch after each
official release.
WEBSITE *command-t-website*
The official website for Command-T is:
https://wincent.com/products/command-t
The latest release will always be available from there.
A copy of each release is also available from the official Vim scripts site
at:
http://www.vim.org/scripts/script.php?script_id=3025
Bug reports should be submitted to the issue tracker at:
https://wincent.com/issues
DONATIONS *command-t-donations*
Command-T itself is free software released under the terms of the BSD license.
If you would like to support further development you can make a donation via
PayPal to win@wincent.com:
https://wincent.com/products/command-t/donations
LICENSE *command-t-license*
Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. 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 HOLDERS 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.
HISTORY *command-t-history*
1.8 (31 March 2014)
- taught Watchman file scanner to use the binary protocol instead of JSON,
roughly doubling its speed
- build changes to accommodate MinGW (patch from Roland Puntaier)
1.7 (9 March 2014)
- added |g:CommandTInputDebounce|, which can be used to improve responsiveness
in large file hierarchies (based on patch from Yiding Jia)
- added a potentially faster file scanner which uses the `find` executable
(based on patch from Yiding Jia)
- added a file scanner that knows how to talk to Watchman
(https://github.com/facebook/watchman)
- added |g:CommandTFileScanner|, which can be used to switch file scanners
- fix processor count detection on some platforms (patch from Pavel Sergeev)
1.6.1 (22 December 2013)
- defer processor count detection until runtime (makes it possible to sensibly
build Command-T on one machine and use it on another)
1.6 (16 December 2013)
- on systems with POSIX threads (such as OS X and Linux), Command-T will use
threads to compute match results in parallel, resulting in a large speed
boost that is especially noticeable when navigating large projects
1.5.1 (23 September 2013)
- exclude large benchmark fixture file from source exports (patch from Vít
Ondruch)
1.5 (18 September 2013)
- don't scan "pathological" filesystem structures (ie. circular or
self-referential symlinks; patch from Marcus Brito)
- gracefully handle files starting with "+" (patch from Ivan Ukhov)
- switch default selection highlight color for better readability (suggestion
from André Arko), but make it possible to configure via the
|g:CommandTHighlightColor| setting
- added a mapping to take the current matches and put then in the quickfix
window
- performance improvements, particularly noticeable with large file
hierarchies
- added |g:CommandTWildIgnore| setting (patch from Paul Jolly)
1.4 (20 June 2012)
- added |:CommandTTag| command (patches from Noon Silk)
- turn off |'colorcolumn'| and |'relativenumber'| in the match window (patch
from Jeff Kreeftmeijer)
- documentation update (patch from Nicholas Alpi)
- added |:CommandTMinHeight| option (patch from Nate Kane)
- highlight (by underlining) matched characters in the match listing (requires
Vim to have been compiled with the +conceal feature, which is available in
Vim 7.3 or later; patch from Steven Moazami)
- added the ability to flush the cache while the match window is open using
<C-f>
1.3.1 (18 December 2011)
- fix jumplist navigation under Ruby 1.9.x (patch from Woody Peterson)
1.3 (27 November 2011)
- added the option to maintain multiple caches when changing among
directories; see the accompanying |g:CommandTMaxCachedDirectories| setting
- added the ability to navigate using the Vim jumplist (patch from Marian
Schubert)
1.2.1 (30 April 2011)
- Remove duplicate copy of the documentation that was causing "Duplicate tag"
errors
- Mitigate issue with distracting blinking cursor in non-GUI versions of Vim
(patch from Steven Moazami)
1.2 (30 April 2011)
- added |g:CommandTMatchWindowReverse| option, to reverse the order of items
in the match listing (patch from Steven Moazami)
1.1b2 (26 March 2011)
- fix a glitch in the release process; the plugin itself is unchanged since
1.1b
1.1b (26 March 2011)
- add |:CommandTBuffer| command for quickly selecting among open buffers
1.0.1 (5 January 2011)
- work around bug when mapping |:CommandTFlush|, wherein the default mapping
for |:CommandT| would not be set up
- clean up when leaving the Command-T buffer via unexpected means (such as
with <C-W k> or similar)
1.0 (26 November 2010)
- make relative path simplification work on Windows
1.0b (5 November 2010)
- work around platform-specific Vim 7.3 bug seen by some users (wherein
Vim always falsely reports to Ruby that the buffer numbers is 0)
- re-use the buffer that is used to show the match listing, rather than
throwing it away and recreating it each time Command-T is shown; this
stops the buffer numbers from creeping up needlessly
0.9 (8 October 2010)
- use relative paths when opening files inside the current working directory
in order to keep buffer listings as brief as possible (patch from Matthew
Todd)
0.8.1 (14 September 2010)
- fix mapping issues for users who have set |'notimeout'| (patch from Sung
Pae)
0.8 (19 August 2010)
- overrides for the default mappings can now be lists of strings, allowing
multiple mappings to be defined for any given action
- <Leader>t mapping only set up if no other map for |:CommandT| exists
(patch from Scott Bronson)
- prevent folds from appearing in the match listing
- tweaks to avoid the likelihood of "Not enough room" errors when trying to
open files
- watch out for "nil" windows when restoring window dimensions
- optimizations (avoid some repeated downcasing)
- move all Ruby files under the "command-t" subdirectory and avoid polluting
the "Vim" module namespace
0.8b (11 July 2010)
- large overhaul of the scoring algorithm to make the ordering of returned
results more intuitive; given the scope of the changes and room for
optimization of the new algorithm, this release is labelled as "beta"
0.7 (10 June 2010)
- handle more |'wildignore'| patterns by delegating to Vim's own |expand()|
function; with this change it is now viable to exclude patterns such as
'vendor/rails/**' in addition to filename-only patterns like '*.o' and
'.git' (patch from Mike Lundy)
- always sort results alphabetically for empty search strings; this eliminates
filesystem-specific variations (patch from Mike Lundy)
0.6 (28 April 2010)
- |:CommandT| now accepts an optional parameter to specify the starting
directory, temporarily overriding the usual default of Vim's |:pwd|
- fix truncated paths when operating from root directory
0.5.1 (11 April 2010)
- fix for Ruby 1.9 compatibility regression introduced in 0.5
- documentation enhancements, specifically targetted at Windows users
0.5 (3 April 2010)
- |:CommandTFlush| now re-evaluates settings, allowing changes made via |let|
to be picked up without having to restart Vim
- fix premature abort when scanning very deep directory hierarchies
- remove broken |<Esc>| key mapping on vt100 and xterm terminals
- provide settings for overriding default mappings
- minor performance optimization
0.4 (27 March 2010)
- add |g:CommandTMatchWindowAtTop| setting (patch from Zak Johnson)
- documentation fixes and enhancements
- internal refactoring and simplification
0.3 (24 March 2010)
- add |g:CommandTMaxHeight| setting for controlling the maximum height of the
match window (patch from Lucas de Vries)
- fix bug where |'list'| setting might be inappropriately set after dismissing
Command-T
- compatibility fix for different behaviour of "autoload" under Ruby 1.9.1
- avoid "highlight group not found" warning when run under a version of Vim
that does not have syntax highlighting support
- open in split when opening normally would fail due to |'hidden'| and
|'modified'| values
0.2 (23 March 2010)
- compatibility fixes for compilation under Ruby 1.9 series
- compatibility fixes for compilation under Ruby 1.8.5
- compatibility fixes for Windows and other non-UNIX platforms
- suppress "mapping already exists" message if <Leader>t mapping is already
defined when plug-in is loaded
- exclude paths based on |'wildignore'| setting rather than a hardcoded
regular expression
0.1 (22 March 2010)
- initial public release
------------------------------------------------------------------------------
vim:tw=78:ft=help:
*snipMate.txt* Plugin for using TextMate-style snippets in Vim.
snipMate *snippet* *snippets* *snipMate*
Last Change: July 13, 2009
|snipMate-description| Description
|snipMate-syntax| Snippet syntax
|snipMate-usage| Usage
|snipMate-settings| Settings
|snipMate-features| Features
|snipMate-disadvantages| Disadvantages to TextMate
|snipMate-contact| Contact
For Vim version 7.0 or later.
This plugin only works if 'compatible' is not set.
{Vi does not have any of these features.}
==============================================================================
DESCRIPTION *snipMate-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 instance, in a C file using the default installation of snipMate.vim, if
you type "for<tab>" in insert mode, it will expand a typical for loop in C: >
for (i = 0; i < count; i++) {
}
To go to the next item in the loop, simply <tab> over to it; if there is
repeated code, such as the "i" variable in this example, you can simply
start typing once it's highlighted and all the matches specified in the
snippet will be updated. To go in reverse, use <shift-tab>.
==============================================================================
SYNTAX *snippet-syntax*
Snippets can be defined in two ways. They can be in their own file, named
after their trigger in 'snippets/<filetype>/<trigger>.snippet', or they can be
defined together in a 'snippets/<filetype>.snippets' file. Note that dotted
'filetype' syntax is supported -- e.g., you can use >
:set ft=html.eruby
to activate snippets for both HTML and eRuby for the current file.
The syntax for snippets in *.snippets files is the following: >
snippet trigger
expanded text
more expanded text
Note that the first hard tab after the snippet trigger is required, and not
expanded in the actual snippet. The syntax for *.snippet files is the same,
only without the trigger declaration and starting indentation.
Also note that snippets must be defined using hard tabs. They can be expanded
to spaces later if desired (see |snipMate-indenting|).
"#" is used as a line-comment character in *.snippets files; however, they can
only be used outside of a snippet declaration. E.g.: >
# this is a correct comment
snippet trigger
expanded text
snippet another_trigger
# this isn't a comment!
expanded text
<
This should hopefully be obvious with the included syntax highlighting.
*snipMate-${#}*
Tab stops ~
By default, the cursor is placed at the end of a snippet. To specify where the
cursor is to be placed next, use "${#}", where the # is the number of the tab
stop. E.g., to place the cursor first on the id of a <div> tag, and then allow
the user to press <tab> to go to the middle of it:
>
snippet div
<div id="${1}">
${2}
</div>
<
*snipMate-placeholders* *snipMate-${#:}* *snipMate-$#*
Placeholders ~
Placeholder text can be supplied using "${#:text}", where # is the number of
the tab stop. This text then can be copied throughout the snippet using "$#",
given # is the same number as used before. So, to make a C for loop: >
snippet for
for (${2:i}; $2 < ${1:count}; $1++) {
${4}
}
This will cause "count" to first be selected and change if the user starts
typing. When <tab> is pressed, the "i" in ${2}'s position will be selected;
all $2 variables will default to "i" and automatically be updated if the user
starts typing.
NOTE: "$#" syntax is used only for variables, not for tab stops as in TextMate.
Variables within variables are also possible. For instance: >
snippet opt
<option value="${1:option}">${2:$1}</option>
Will, as usual, cause "option" to first be selected and update all the $1
variables if the user starts typing. Since one of these variables is inside of
${2}, this text will then be used as a placeholder for the next tab stop,
allowing the user to change it if he wishes.
To copy a value throughout a snippet without supplying default text, simply
use the "${#:}" construct without the text; e.g.: >
snippet foo
${1:}bar$1
< *snipMate-commands*
Interpolated Vim Script ~
Snippets can also contain Vim script commands that are executed (via |eval()|)
when the snippet is inserted. Commands are given inside backticks (`...`); for
TextMates's functionality, use the |system()| function. E.g.: >
snippet date
`system("date +%Y-%m-%d")`
will insert the current date, assuming you are on a Unix system. Note that you
can also (and should) use |strftime()| for this example.
Filename([{expr}] [, {defaultText}]) *snipMate-filename* *Filename()*
Since the current filename is used often in snippets, a default function
has been defined for it in snipMate.vim, appropriately called Filename().
With no arguments, the default filename without an extension is returned;
the first argument specifies what to place before or after the filename,
and the second argument supplies the default text to be used if the file
has not been named. "$1" in the first argument is replaced with the filename;
if you only want the filename to be returned, the first argument can be left
blank. Examples: >
snippet filename
`Filename()`
snippet filename_with_default
`Filename('', 'name')`
snippet filename_foo
`filename('$1_foo')`
The first example returns the filename if it the file has been named, and an
empty string if it hasn't. The second returns the filename if it's been named,
and "name" if it hasn't. The third returns the filename followed by "_foo" if
it has been named, and an empty string if it hasn't.
*multi_snip*
To specify that a snippet can have multiple matches in a *.snippets file, use
this syntax: >
snippet trigger A description of snippet #1
expand this text
snippet trigger A description of snippet #2
expand THIS text!
In this example, when "trigger<tab>" is typed, a numbered menu containing all
of the descriptions of the "trigger" will be shown; when the user presses the
corresponding number, that snippet will then be expanded.
To create a snippet with multiple matches using *.snippet files,
simply place all the snippets in a subdirectory with the trigger name:
'snippets/<filetype>/<trigger>/<name>.snippet'.
==============================================================================
USAGE *snipMate-usage*
*'snippets'* *g:snippets_dir*
Snippets are by default looked for any 'snippets' directory in your
'runtimepath'. Typically, it is located at '~/.vim/snippets/' on *nix or
'$HOME\vimfiles\snippets\' on Windows. To change that location or add another
one, change the g:snippets_dir variable in your |.vimrc| to your preferred
directory, or use the |ExtractSnips()|function. This will be used by the
|globpath()| function, and so accepts the same syntax as it (e.g.,
comma-separated paths).
ExtractSnipsFile({directory}, {filetype}) *ExtractSnipsFile()* *.snippets*
ExtractSnipsFile() extracts the specified *.snippets file for the given
filetype. A .snippets file contains multiple snippet declarations for the
filetype. It is further explained above, in |snippet-syntax|.
ExtractSnips({directory}, {filetype}) *ExtractSnips()* *.snippet*
ExtractSnips() extracts *.snippet files from the specified directory and
defines them as snippets for the given filetype. The directory tree should
look like this: 'snippets/<filetype>/<trigger>.snippet'. If the snippet has
multiple matches, it should look like this:
'snippets/<filetype>/<trigger>/<name>.snippet' (see |multi_snip|).
*ResetSnippets()*
The ResetSnippets() function removes all snippets from memory. This is useful
to put at the top of a snippet setup file for if you would like to |:source|
it multiple times.
*list-snippets* *i_CTRL-R_<Tab>*
If you would like to see what snippets are available, simply type <c-r><tab>
in the current buffer to show a list via |popupmenu-completion|.
==============================================================================
SETTINGS *snipMate-settings* *g:snips_author*
The g:snips_author string (similar to $TM_FULLNAME in TextMate) should be set
to your name; it can then be used in snippets to automatically add it. E.g.: >
let g:snips_author = 'Hubert Farnsworth'
snippet name
`g:snips_author`
<
*snipMate-expandtab* *snipMate-indenting*
If you would like your snippets to be expanded using spaces instead of tabs,
just enable 'expandtab' and set 'softtabstop' to your preferred amount of
spaces. If 'softtabstop' is not set, 'shiftwidth' is used instead.
*snipMate-remap*
snipMate does not come with a setting to customize the trigger key, but you
can remap it easily in the two lines it's defined in the 'after' directory
under 'plugin/snipMate.vim'. For instance, to change the trigger key
to CTRL-J, just change this: >
ino <tab> <c-r>=TriggerSnippet()<cr>
snor <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
to this: >
ino <c-j> <c-r>=TriggerSnippet()<cr>
snor <c-j> <esc>i<right><c-r>=TriggerSnippet()<cr>
==============================================================================
FEATURES *snipMate-features*
snipMate.vim has the following features among others:
- The syntax of snippets is very similar to TextMate's, allowing
easy conversion.
- The position of the snippet is kept transparently (i.e. it does not use
markers/placeholders written to the buffer), which allows you to escape
out of an incomplete snippet, something particularly useful in Vim.
- Variables in snippets are updated as-you-type.
- Snippets can have multiple matches.
- Snippets can be out of order. For instance, in a do...while loop, the
condition can be added before the code.
- [New] File-based snippets are supported.
- [New] Triggers after non-word delimiters are expanded, e.g. "foo"
in "bar.foo".
- [New] <shift-tab> can now be used to jump tab stops in reverse order.
==============================================================================
DISADVANTAGES *snipMate-disadvantages*
snipMate.vim currently has the following disadvantages to TextMate's snippets:
- There is no $0; the order of tab stops must be explicitly stated.
- Placeholders within placeholders are not possible. E.g.: >
'<div${1: id="${2:some_id}}">${3}</div>'
<
In TextMate this would first highlight ' id="some_id"', and if
you hit delete it would automatically skip ${2} and go to ${3}
on the next <tab>, but if you didn't delete it it would highlight
"some_id" first. You cannot do this in snipMate.vim.
- Regex cannot be performed on variables, such as "${1/.*/\U&}"
- Placeholders cannot span multiple lines.
- Activating snippets in different scopes of the same file is
not possible.
Perhaps some of these features will be added in a later release.
==============================================================================
CONTACT *snipMate-contact* *snipMate-author*
To contact the author (Michael Sanders), please email:
msanders42+snipmate <at> gmail <dot> com
I greatly appreciate any suggestions or improvements offered for the script.
==============================================================================
vim:tw=78:ts=8:ft=help:norl:
:CSApproxSnapshot CSApprox.txt /*:CSApproxSnapshot*
:CoffeeCompile coffee-script.txt /*:CoffeeCompile*
:CoffeeMake coffee-script.txt /*:CoffeeMake*
:CoffeeRun coffee-script.txt /*:CoffeeRun*
:CommandT command-t.txt /*:CommandT*
:CommandTBuffer command-t.txt /*:CommandTBuffer*
:CommandTFlush command-t.txt /*:CommandTFlush*
:CommandTJumps command-t.txt /*:CommandTJumps*
:CommandTTag command-t.txt /*:CommandTTag*
CSApprox.txt CSApprox.txt /*CSApprox.txt*
coffee-script coffee-script.txt /*coffee-script*
coffee-script-author coffee-script.txt /*coffee-script-author*
coffee-script-commands coffee-script.txt /*coffee-script-commands*
coffee-script-contents coffee-script.txt /*coffee-script-contents*
coffee-script-introduction coffee-script.txt /*coffee-script-introduction*
coffee-script-license coffee-script.txt /*coffee-script-license*
coffee-script-settings coffee-script.txt /*coffee-script-settings*
coffee-script.txt coffee-script.txt /*coffee-script.txt*
command-t command-t.txt /*command-t*
command-t-authors command-t.txt /*command-t-authors*
command-t-commands command-t.txt /*command-t-commands*
command-t-contents command-t.txt /*command-t-contents*
command-t-development command-t.txt /*command-t-development*
command-t-donations command-t.txt /*command-t-donations*
command-t-faq command-t.txt /*command-t-faq*
command-t-history command-t.txt /*command-t-history*
command-t-installation command-t.txt /*command-t-installation*
command-t-intro command-t.txt /*command-t-intro*
command-t-license command-t.txt /*command-t-license*
command-t-mappings command-t.txt /*command-t-mappings*
command-t-options command-t.txt /*command-t-options*
command-t-pathogen command-t.txt /*command-t-pathogen*
command-t-requirements command-t.txt /*command-t-requirements*
command-t-tips command-t.txt /*command-t-tips*
command-t-trouble-shooting command-t.txt /*command-t-trouble-shooting*
command-t-usage command-t.txt /*command-t-usage*
command-t-website command-t.txt /*command-t-website*
command-t-wildignore command-t.txt /*command-t-wildignore*
command-t.txt command-t.txt /*command-t.txt*
compiler-coffee-script coffee-script.txt /*compiler-coffee-script*
csapprox CSApprox.txt /*csapprox*
csapprox-+gui CSApprox.txt /*csapprox-+gui*
csapprox-aterm CSApprox.txt /*csapprox-aterm*
csapprox-author CSApprox.txt /*csapprox-author*
csapprox-changelog CSApprox.txt /*csapprox-changelog*
csapprox-configure CSApprox.txt /*csapprox-configure*
csapprox-design CSApprox.txt /*csapprox-design*
csapprox-eterm CSApprox.txt /*csapprox-eterm*
csapprox-gnome-terminal CSApprox.txt /*csapprox-gnome-terminal*
csapprox-gui-support CSApprox.txt /*csapprox-gui-support*
csapprox-hooks CSApprox.txt /*csapprox-hooks*
csapprox-intro CSApprox.txt /*csapprox-intro*
csapprox-iterm.app CSApprox.txt /*csapprox-iterm.app*
csapprox-konsole CSApprox.txt /*csapprox-konsole*
csapprox-kterm CSApprox.txt /*csapprox-kterm*
csapprox-limitations CSApprox.txt /*csapprox-limitations*
csapprox-mlterm CSApprox.txt /*csapprox-mlterm*
csapprox-mrxvt CSApprox.txt /*csapprox-mrxvt*
csapprox-palettes CSApprox.txt /*csapprox-palettes*
csapprox-pterm CSApprox.txt /*csapprox-pterm*
csapprox-putty CSApprox.txt /*csapprox-putty*
csapprox-requirements CSApprox.txt /*csapprox-requirements*
csapprox-roxterm CSApprox.txt /*csapprox-roxterm*
csapprox-screen CSApprox.txt /*csapprox-screen*
csapprox-terminal CSApprox.txt /*csapprox-terminal*
csapprox-terminal-example CSApprox.txt /*csapprox-terminal-example*
csapprox-terminal-list CSApprox.txt /*csapprox-terminal-list*
csapprox-terminal.app CSApprox.txt /*csapprox-terminal.app*
csapprox-terminals-bad CSApprox.txt /*csapprox-terminals-bad*
csapprox-terminals-good CSApprox.txt /*csapprox-terminals-good*
csapprox-toc CSApprox.txt /*csapprox-toc*
csapprox-transparency CSApprox.txt /*csapprox-transparency*
csapprox-urxvt CSApprox.txt /*csapprox-urxvt*
csapprox-wterm CSApprox.txt /*csapprox-wterm*
csapprox-xfce4-terminal CSApprox.txt /*csapprox-xfce4-terminal*
csapprox-xiterm CSApprox.txt /*csapprox-xiterm*
csapprox-xterm CSApprox.txt /*csapprox-xterm*
csapprox.vim CSApprox.txt /*csapprox.vim*
ft-coffee-script-syntax coffee-script.txt /*ft-coffee-script-syntax*
g:CSApprox_approximator_function CSApprox.txt /*g:CSApprox_approximator_function*
g:CSApprox_attr_map CSApprox.txt /*g:CSApprox_attr_map*
g:CSApprox_eterm CSApprox.txt /*g:CSApprox_eterm*
g:CSApprox_hook_post CSApprox.txt /*g:CSApprox_hook_post*
g:CSApprox_hook_pre CSApprox.txt /*g:CSApprox_hook_pre*
g:CSApprox_hook_{scheme}_post CSApprox.txt /*g:CSApprox_hook_{scheme}_post*
g:CSApprox_hook_{scheme}_pre CSApprox.txt /*g:CSApprox_hook_{scheme}_pre*
g:CSApprox_konsole CSApprox.txt /*g:CSApprox_konsole*
g:CSApprox_loaded CSApprox.txt /*g:CSApprox_loaded*
g:CSApprox_redirfallback CSApprox.txt /*g:CSApprox_redirfallback*
g:CSApprox_use_showrgb CSApprox.txt /*g:CSApprox_use_showrgb*
g:CSApprox_verbose_level CSApprox.txt /*g:CSApprox_verbose_level*
g:CommandTAcceptSelectionMap command-t.txt /*g:CommandTAcceptSelectionMap*
g:CommandTAcceptSelectionSplitMap command-t.txt /*g:CommandTAcceptSelectionSplitMap*
g:CommandTAcceptSelectionTabMap command-t.txt /*g:CommandTAcceptSelectionTabMap*
g:CommandTAcceptSelectionVSplitMap command-t.txt /*g:CommandTAcceptSelectionVSplitMap*
g:CommandTAlwaysShowDotFiles command-t.txt /*g:CommandTAlwaysShowDotFiles*
g:CommandTBackspaceMap command-t.txt /*g:CommandTBackspaceMap*
g:CommandTCancelMap command-t.txt /*g:CommandTCancelMap*
g:CommandTClearMap command-t.txt /*g:CommandTClearMap*
g:CommandTCursorEndMap command-t.txt /*g:CommandTCursorEndMap*
g:CommandTCursorLeftMap command-t.txt /*g:CommandTCursorLeftMap*
g:CommandTCursorRightMap command-t.txt /*g:CommandTCursorRightMap*
g:CommandTCursorStartMap command-t.txt /*g:CommandTCursorStartMap*
g:CommandTDeleteMap command-t.txt /*g:CommandTDeleteMap*
g:CommandTFileScanner command-t.txt /*g:CommandTFileScanner*
g:CommandTHighlightColor command-t.txt /*g:CommandTHighlightColor*
g:CommandTInputDebounce command-t.txt /*g:CommandTInputDebounce*
g:CommandTMatchWindowAtTop command-t.txt /*g:CommandTMatchWindowAtTop*
g:CommandTMatchWindowReverse command-t.txt /*g:CommandTMatchWindowReverse*
g:CommandTMaxCachedDirectories command-t.txt /*g:CommandTMaxCachedDirectories*
g:CommandTMaxDepth command-t.txt /*g:CommandTMaxDepth*
g:CommandTMaxFiles command-t.txt /*g:CommandTMaxFiles*
g:CommandTMaxHeight command-t.txt /*g:CommandTMaxHeight*
g:CommandTMinHeight command-t.txt /*g:CommandTMinHeight*
g:CommandTNeverShowDotFiles command-t.txt /*g:CommandTNeverShowDotFiles*
g:CommandTQuickfixMap command-t.txt /*g:CommandTQuickfixMap*
g:CommandTRefreshMap command-t.txt /*g:CommandTRefreshMap*
g:CommandTScanDotDirectories command-t.txt /*g:CommandTScanDotDirectories*
g:CommandTSelectNextMap command-t.txt /*g:CommandTSelectNextMap*
g:CommandTSelectPrevMap command-t.txt /*g:CommandTSelectPrevMap*
g:CommandTTagIncludeFilenames command-t.txt /*g:CommandTTagIncludeFilenames*
g:CommandTToggleFocusMap command-t.txt /*g:CommandTToggleFocusMap*
g:CommandTWildIgnore command-t.txt /*g:CommandTWildIgnore*
g:coffee_compile_vert coffee-script.txt /*g:coffee_compile_vert*
g:coffee_make_options coffee-script.txt /*g:coffee_make_options*
" Language: CoffeeScript
" Maintainer: Mick Koch <kchmck@gmail.com>
" URL: http://github.com/kchmck/vim-coffee-script
" License: WTFPL
autocmd BufNewFile,BufRead *.coffee set filetype=coffee
autocmd BufNewFile,BufRead *Cakefile set filetype=coffee
autocmd BufNewFile,BufRead *.coffeekup set filetype=coffee
autocmd BufNewFile,BufRead *.eco set filetype=eco
" Language: CoffeeScript
" Maintainer: Mick Koch <kchmck@gmail.com>
" URL: http://github.com/kchmck/vim-coffee-script
" License: WTFPL
if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1
setlocal formatoptions-=t formatoptions+=croql
setlocal comments=:#
setlocal commentstring=#\ %s
setlocal omnifunc=javascriptcomplete#CompleteJS
" Enable CoffeeMake if it won't overwrite any settings.
if !len(&l:makeprg)
compiler coffee
endif
" Reset the global variables used by CoffeeCompile.
function! s:CoffeeCompileResetVars()
" Position in the source buffer
let s:coffee_compile_src_buf = -1
let s:coffee_compile_src_pos = []
" Position in the CoffeeCompile buffer
let s:coffee_compile_buf = -1
let s:coffee_compile_win = -1
let s:coffee_compile_pos = []
" If CoffeeCompile is watching a buffer
let s:coffee_compile_watch = 0
endfunction
" Save the cursor position when moving to and from the CoffeeCompile buffer.
function! s:CoffeeCompileSavePos()
let buf = bufnr('%')
let pos = getpos('.')
if buf == s:coffee_compile_buf
let s:coffee_compile_pos = pos
else
let s:coffee_compile_src_buf = buf
let s:coffee_compile_src_pos = pos
endif
endfunction
" Restore the cursor to the source buffer.
function! s:CoffeeCompileRestorePos()
let win = bufwinnr(s:coffee_compile_src_buf)
if win != -1
exec win 'wincmd w'
call setpos('.', s:coffee_compile_src_pos)
endif
endfunction
" Close the CoffeeCompile buffer and clean things up.
function! s:CoffeeCompileClose()
silent! autocmd! CoffeeCompileAuPos
silent! autocmd! CoffeeCompileAuWatch
call s:CoffeeCompileRestorePos()
call s:CoffeeCompileResetVars()
endfunction
" Update the CoffeeCompile buffer given some input lines.
function! s:CoffeeCompileUpdate(startline, endline)
let input = join(getline(a:startline, a:endline), "\n")
" Coffee doesn't like empty input.
if !len(input)
return
endif
" Compile input.
let output = system('coffee -scb 2>&1', input)
" Move to the CoffeeCompile buffer.
exec s:coffee_compile_win 'wincmd w'
" Replace buffer contents with new output and delete the last empty line.
setlocal modifiable
exec '% delete _'
put! =output
exec '$ delete _'
setlocal nomodifiable
" Highlight as JavaScript if there is no compile error.
if v:shell_error
setlocal filetype=
else
setlocal filetype=javascript
endif
" Restore the cursor in the compiled output.
call setpos('.', s:coffee_compile_pos)
endfunction
" Update the CoffeeCompile buffer with the whole source buffer and restore the
" cursor.
function! s:CoffeeCompileWatchUpdate()
call s:CoffeeCompileSavePos()
call s:CoffeeCompileUpdate(1, '$')
call s:CoffeeCompileRestorePos()
endfunction
" Peek at compiled CoffeeScript in a scratch buffer. We handle ranges like this
" to prevent the cursor from being moved (and its position saved) before the
" function is called.
function! s:CoffeeCompile(startline, endline, args)
" Don't compile the CoffeeCompile buffer.
if bufnr('%') == s:coffee_compile_buf
return
endif
" Parse arguments.
let watch = a:args =~ '\<watch\>'
let unwatch = a:args =~ '\<unwatch\>'
let size = str2nr(matchstr(a:args, '\<\d\+\>'))
" Determine default split direction.
if exists("g:coffee_compile_vert")
let vert = 1
else
let vert = a:args =~ '\<vert\%[ical]\>'
endif
" Remove any watch listeners.
silent! autocmd! CoffeeCompileAuWatch
" If just unwatching, don't compile.
if unwatch
let s:coffee_compile_watch = 0
return
endif
if watch
let s:coffee_compile_watch = 1
endif
call s:CoffeeCompileSavePos()
" Build the CoffeeCompile buffer if it doesn't exist.
if s:coffee_compile_buf == -1
let src_win = bufwinnr(s:coffee_compile_src_buf)
" Create the new window and resize it.
if vert
let width = size ? size : winwidth(src_win) / 2
vertical new
exec 'vertical resize' width
else
" Try to guess the compiled output's height.
let height = size ? size : min([winheight(src_win) / 2,
\ a:endline - a:startline + 2])
botright new
exec 'resize' height
endif
" Set up scratch buffer.
setlocal bufhidden=wipe buftype=nofile
setlocal nobuflisted nomodifiable noswapfile nowrap
autocmd BufWipeout <buffer> call s:CoffeeCompileClose()
nnoremap <buffer> <silent> q :hide<CR>
" Save the cursor position on each buffer switch.
augroup CoffeeCompileAuPos
autocmd BufEnter,BufLeave * call s:CoffeeCompileSavePos()
augroup END
let s:coffee_compile_buf = bufnr('%')
let s:coffee_compile_win = bufwinnr(s:coffee_compile_buf)
endif
" Go back to the source buffer and do the initial compile.
call s:CoffeeCompileRestorePos()
if s:coffee_compile_watch
call s:CoffeeCompileWatchUpdate()
augroup CoffeeCompileAuWatch
autocmd InsertLeave <buffer> call s:CoffeeCompileWatchUpdate()
augroup END
else
call s:CoffeeCompileUpdate(a:startline, a:endline)
endif
endfunction
" Complete arguments for the CoffeeCompile command.
function! s:CoffeeCompileComplete(arg, cmdline, cursor)
let args = ['unwatch', 'vertical', 'watch']
if !len(a:arg)
return args
endif
let match = '^' . a:arg
for arg in args
if arg =~ match
return [arg]
endif
endfor
endfunction
" Don't let new windows overwrite the CoffeeCompile variables.
if !exists("s:coffee_compile_buf")
call s:CoffeeCompileResetVars()
endif
" Peek at compiled CoffeeScript.
command! -range=% -bar -nargs=* -complete=customlist,s:CoffeeCompileComplete
\ CoffeeCompile call s:CoffeeCompile(<line1>, <line2>, <q-args>)
" Run some CoffeeScript.
command! -range=% -bar CoffeeRun <line1>,<line2>:w !coffee -s
" Helper function for (x)html snippets
if exists('s:did_snip_helper') || &cp || !exists('loaded_snips')
finish
endif
let s:did_snip_helper = 1
" Automatically closes tag if in xhtml
fun! Close()
return stridx(&ft, 'xhtml') == -1 ? '' : ' /'
endf
" Language: CoffeeScript
" Maintainer: Mick Koch <kchmck@gmail.com>
" URL: http://github.com/kchmck/vim-coffee-script
" License: WTFPL
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
setlocal autoindent
setlocal indentexpr=GetCoffeeIndent(v:lnum)
" Make sure GetCoffeeIndent is run when these are typed so they can be
" indented or outdented.
setlocal indentkeys+=0],0),0.,=else,=when,=catch,=finally
" Only define the function once.
if exists("*GetCoffeeIndent")
finish
endif
" Keywords to indent after
let s:INDENT_AFTER_KEYWORD = '^\%(if\|unless\|else\|for\|while\|until\|'
\ . 'loop\|switch\|when\|try\|catch\|finally\|'
\ . 'class\)\>'
" Operators to indent after
let s:INDENT_AFTER_OPERATOR = '\%([([{:=]\|[-=]>\)$'
" Keywords and operators that continue a line
let s:CONTINUATION = '\<\%(is\|isnt\|and\|or\)\>$'
\ . '\|'
\ . '\%(-\@<!-\|+\@<!+\|<\|[-=]\@<!>\|\*\|/\@<!/\|%\||\|'
\ . '&\|,\|\.\@<!\.\)$'
" Operators that block continuation indenting
let s:CONTINUATION_BLOCK = '[([{:=]$'
" A continuation dot access
let s:DOT_ACCESS = '^\.'
" Keywords to outdent after
let s:OUTDENT_AFTER = '^\%(return\|break\|continue\|throw\)\>'
" A compound assignment like `... = if ...`
let s:COMPOUND_ASSIGNMENT = '[:=]\s*\%(if\|unless\|for\|while\|until\|'
\ . 'switch\|try\|class\)\>'
" A postfix condition like `return ... if ...`.
let s:POSTFIX_CONDITION = '\S\s\+\zs\<\%(if\|unless\)\>'
" A single-line else statement like `else ...` but not `else if ...
let s:SINGLE_LINE_ELSE = '^else\s\+\%(\<\%(if\|unless\)\>\)\@!'
" Max lines to look back for a match
let s:MAX_LOOKBACK = 50
" Syntax names for strings
let s:SYNTAX_STRING = 'coffee\%(String\|AssignString\|Embed\|Regex\|Heregex\|'
\ . 'Heredoc\)'
" Syntax names for comments
let s:SYNTAX_COMMENT = 'coffee\%(Comment\|BlockComment\|HeregexComment\)'
" Syntax names for strings and comments
let s:SYNTAX_STRING_COMMENT = s:SYNTAX_STRING . '\|' . s:SYNTAX_COMMENT
" Get the linked syntax name of a character.
function! s:SyntaxName(linenum, col)
return synIDattr(synID(a:linenum, a:col, 1), 'name')
endfunction
" Check if a character is in a comment.
function! s:IsComment(linenum, col)
return s:SyntaxName(a:linenum, a:col) =~ s:SYNTAX_COMMENT
endfunction
" Check if a character is in a string.
function! s:IsString(linenum, col)
return s:SyntaxName(a:linenum, a:col) =~ s:SYNTAX_STRING
endfunction
" Check if a character is in a comment or string.
function! s:IsCommentOrString(linenum, col)
return s:SyntaxName(a:linenum, a:col) =~ s:SYNTAX_STRING_COMMENT
endfunction
" Check if a whole line is a comment.
function! s:IsCommentLine(linenum)
" Check the first non-whitespace character.
return s:IsComment(a:linenum, indent(a:linenum) + 1)
endfunction
" Repeatedly search a line for a regex until one is found outside a string or
" comment.
function! s:SmartSearch(linenum, regex)
" Start at the first column.
let col = 0
" Search until there are no more matches, unless a good match is found.
while 1
call cursor(a:linenum, col + 1)
let [_, col] = searchpos(a:regex, 'cn', a:linenum)
" No more matches.
if !col
break
endif
if !s:IsCommentOrString(a:linenum, col)
return 1
endif
endwhile
" No good match found.
return 0
endfunction
" Skip a match if it's in a comment or string, is a single-line statement that
" isn't adjacent, or is a postfix condition.
function! s:ShouldSkip(startlinenum, linenum, col)
if s:IsCommentOrString(a:linenum, a:col)
return 1
endif
" Check for a single-line statement that isn't adjacent.
if s:SmartSearch(a:linenum, '\<then\>') && a:startlinenum - a:linenum > 1
return 1
endif
if s:SmartSearch(a:linenum, s:POSTFIX_CONDITION) &&
\ !s:SmartSearch(a:linenum, s:COMPOUND_ASSIGNMENT)
return 1
endif
return 0
endfunction
" Find the farthest line to look back to, capped to line 1 (zero and negative
" numbers cause bad things).
function! s:MaxLookback(startlinenum)
return max([1, a:startlinenum - s:MAX_LOOKBACK])
endfunction
" Get the skip expression for searchpair().
function! s:SkipExpr(startlinenum)
return "s:ShouldSkip(" . a:startlinenum . ", line('.'), col('.'))"
endfunction
" Search for pairs of text.
function! s:SearchPair(start, end)
" The cursor must be in the first column for regexes to match.
call cursor(0, 1)
let startlinenum = line('.')
" Don't need the W flag since MaxLookback caps the search to line 1.
return searchpair(a:start, '', a:end, 'bcn',
\ s:SkipExpr(startlinenum),
\ s:MaxLookback(startlinenum))
endfunction
" Try to find a previous matching line.
function! s:GetMatch(curline)
let firstchar = a:curline[0]
if firstchar == '}'
return s:SearchPair('{', '}')
elseif firstchar == ')'
return s:SearchPair('(', ')')
elseif firstchar == ']'
return s:SearchPair('\[', '\]')
elseif a:curline =~ '^else\>'
return s:SearchPair('\<\%(if\|unless\|when\)\>', '\<else\>')
elseif a:curline =~ '^catch\>'
return s:SearchPair('\<try\>', '\<catch\>')
elseif a:curline =~ '^finally\>'
return s:SearchPair('\<try\>', '\<finally\>')
endif
return 0
endfunction
" Get the nearest previous line that isn't a comment.
function! s:GetPrevNormalLine(startlinenum)
let curlinenum = a:startlinenum
while curlinenum > 0
let curlinenum = prevnonblank(curlinenum - 1)
if !s:IsCommentLine(curlinenum)
return curlinenum
endif
endwhile
return 0
endfunction
" Try to find a comment in a line.
function! s:FindComment(linenum)
let col = 0
while 1
call cursor(a:linenum, col + 1)
let [_, col] = searchpos('#', 'cn', a:linenum)
if !col
break
endif
if s:IsComment(a:linenum, col)
return col
endif
endwhile
return 0
endfunction
" Get a line without comments or surrounding whitespace.
function! s:GetTrimmedLine(linenum)
let comment = s:FindComment(a:linenum)
let line = getline(a:linenum)
if comment
" Subtract 1 to get to the column before the comment and another 1 for
" zero-based indexing.
let line = line[:comment - 2]
endif
return substitute(substitute(line, '^\s\+', '', ''),
\ '\s\+$', '', '')
endfunction
function! s:GetCoffeeIndent(curlinenum)
let prevlinenum = s:GetPrevNormalLine(a:curlinenum)
" Don't do anything if there's no previous line.
if !prevlinenum
return -1
endif
let curline = s:GetTrimmedLine(a:curlinenum)
" Try to find a previous matching statement. This handles outdenting.
let matchlinenum = s:GetMatch(curline)
if matchlinenum
return indent(matchlinenum)
endif
" Try to find a matching `when`.
if curline =~ '^when\>' && !s:SmartSearch(prevlinenum, '\<switch\>')
let linenum = a:curlinenum
while linenum > 0
let linenum = s:GetPrevNormalLine(linenum)
if getline(linenum) =~ '^\s*when\>'
return indent(linenum)
endif
endwhile
return -1
endif
let prevline = s:GetTrimmedLine(prevlinenum)
let previndent = indent(prevlinenum)
" Always indent after these operators.
if prevline =~ s:INDENT_AFTER_OPERATOR
return previndent + &shiftwidth
endif
" Indent after a continuation if it's the first.
if prevline =~ s:CONTINUATION
" If the line ends in a slash, make sure it isn't a regex.
if prevline =~ '/$'
" Move to the line so we can get the last column.
call cursor(prevlinenum)
if s:IsString(prevlinenum, col('$') - 1)
return -1
endif
endif
let prevprevlinenum = s:GetPrevNormalLine(prevlinenum)
" If the continuation is the first in the file, don't run the other checks.
if !prevprevlinenum
return previndent + &shiftwidth
endif
let prevprevline = s:GetTrimmedLine(prevprevlinenum)
if prevprevline !~ s:CONTINUATION && prevprevline !~ s:CONTINUATION_BLOCK
return previndent + &shiftwidth
endif
return -1
endif
" Indent after these keywords and compound assignments if they aren't a
" single-line statement.
if prevline =~ s:INDENT_AFTER_KEYWORD || prevline =~ s:COMPOUND_ASSIGNMENT
if !s:SmartSearch(prevlinenum, '\<then\>') && prevline !~ s:SINGLE_LINE_ELSE
return previndent + &shiftwidth
endif
return -1
endif
" Indent a dot access if it's the first.
if curline =~ s:DOT_ACCESS && prevline !~ s:DOT_ACCESS
return previndent + &shiftwidth
endif
" Outdent after these keywords if they don't have a postfix condition or are
" a single-line statement.
if prevline =~ s:OUTDENT_AFTER
if !s:SmartSearch(prevlinenum, s:POSTFIX_CONDITION) ||
\ s:SmartSearch(prevlinenum, '\<then\>')
return previndent - &shiftwidth
endif
endif
" No indenting or outdenting is needed.
return -1
endfunction
" Wrap s:GetCoffeeIndent to keep the cursor position.
function! GetCoffeeIndent(curlinenum)
let oldcursor = getpos('.')
let indent = s:GetCoffeeIndent(a:curlinenum)
call setpos('.', oldcursor)
return indent
endfunction
" Vim indent file
" Language: OCaml
" Maintainers: Jean-Francois Yuen <jfyuen@happycoders.org>
" Mike Leary <leary@nwlink.com>
" Markus Mottl <markus.mottl@gmail.com>
" URL: http://www.ocaml.info/vim/indent/ocaml.vim
" Last Change: 2010 Sep 04 - Added an indentation improvement by Mark Weber
" 2005 Jun 25 - Fixed multiple bugs due to 'else\nreturn ind' working
" 2005 May 09 - Added an option to not indent OCaml-indents specially (MM)
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
setlocal expandtab
setlocal indentexpr=GetOCamlIndent()
setlocal indentkeys+=0=and,0=class,0=constraint,0=done,0=else,0=end,0=exception,0=external,0=if,0=in,0=include,0=inherit,0=initializer,0=let,0=method,0=open,0=then,0=type,0=val,0=with,0;;,0>\],0\|\],0>},0\|,0},0\],0)
setlocal nolisp
setlocal nosmartindent
setlocal textwidth=80
setlocal shiftwidth=2
" Comment formatting
if !exists("no_ocaml_comments")
if (has("comments"))
setlocal comments=sr:(**,mb:\ ,ex:*),sr:(*,m:*,ex:*)
setlocal fo=cqort
endif
endif
" Only define the function once.
if exists("*GetOCamlIndent")
finish
endif
" Define some patterns:
let s:beflet = '^\s*\(initializer\|method\|try\)\|\(\<\(begin\|do\|else\|in\|then\|try\)\|->\|<-\|=\|;\|(\)\s*$'
let s:letpat = '^\s*\(let\|type\|module\|class\|open\|exception\|val\|include\|external\)\>'
let s:letlim = '\(\<\(sig\|struct\)\|;;\)\s*$'
let s:lim = '^\s*\(exception\|external\|include\|let\|module\|open\|type\|val\)\>'
let s:module = '\<\%(begin\|sig\|struct\|object\)\>'
let s:obj = '^\s*\(constraint\|inherit\|initializer\|method\|val\)\>\|\<\(object\|object\s*(.*)\)\s*$'
let s:type = '^\s*\%(class\|let\|type\)\>.*='
" Skipping pattern, for comments
function! s:GetLineWithoutFullComment(lnum)
let lnum = prevnonblank(a:lnum - 1)
let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '')
while lline =~ '^\s*$' && lnum > 0
let lnum = prevnonblank(lnum - 1)
let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '')
endwhile
return lnum
endfunction
" Indent for ';;' to match multiple 'let'
function! s:GetInd(lnum, pat, lim)
let llet = search(a:pat, 'bW')
let old = indent(a:lnum)
while llet > 0
let old = indent(llet)
let nb = s:GetLineWithoutFullComment(llet)
if getline(nb) =~ a:lim
return old
endif
let llet = search(a:pat, 'bW')
endwhile
return old
endfunction
" Indent pairs
function! s:FindPair(pstart, pmid, pend)
call search(a:pend, 'bW')
return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"'))
endfunction
" Indent 'let'
function! s:FindLet(pstart, pmid, pend)
call search(a:pend, 'bW')
return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") =~ "^\\s*let\\>.*=.*\\<in\\s*$" || getline(prevnonblank(".") - 1) =~ s:beflet'))
endfunction
function! GetOCamlIndent()
" Find a non-commented line above the current line.
let lnum = s:GetLineWithoutFullComment(v:lnum)
" At the start of the file use zero indent.
if lnum == 0
return 0
endif
let ind = indent(lnum)
let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '')
" Return double 'shiftwidth' after lines matching:
"if lline =~ '^\s*|.*->\s*$'
" return ind + &sw + &sw
"endif
let line = getline(v:lnum)
" Indent if line ends with 'match ... with':
"if lline =~ '\<match\>.*\<with\s*$'
" return ind + &sw
" Indent if current line begins with 'end':
if line =~ '^\s*end\>'
return s:FindPair(s:module, '','\<end\>')
" Indent if current line begins with 'done' for 'do':
elseif line =~ '^\s*done\>'
return s:FindPair('\<do\>', '','\<done\>')
" Indent if current line begins with '}' or '>}':
elseif line =~ '^\s*\(\|>\)}'
return s:FindPair('{', '','}')
" Indent if current line begins with ']', '|]' or '>]':
elseif line =~ '^\s*\(\||\|>\)\]'
return s:FindPair('\[', '','\]')
" Indent if current line begins with ')':
elseif line =~ '^\s*)'
return s:FindPair('(', '',')')
" Indent if current line begins with 'let':
elseif line =~ '^\s*let\>'
if lline !~ s:lim . '\|' . s:letlim . '\|' . s:beflet
return s:FindLet(s:type, '','\<let\s*$')
endif
" Indent if current line begins with 'class' or 'type':
elseif line =~ '^\s*\(class\|type\)\>'
if lline !~ s:lim . '\|\<and\s*$\|' . s:letlim
return s:FindLet(s:type, '','\<\(class\|type\)\s*$')
endif
" Indent for pattern matching:
elseif line =~ '^\s*|'
if lline !~ '^\s*\(|[^\]]\|\(match\|type\|with\)\>\)\|\<\(function\|parser\|private\|with\)\s*$'
call search('|', 'bW')
return indent(searchpair('^\s*\(match\|type\)\>\|\<\(function\|parser\|private\|with\)\s*$', '', '^\s*|', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") !~ "^\\s*|.*->"'))
endif
" Indent if current line begins with ';;':
elseif line =~ '^\s*;;'
if lline !~ ';;\s*$'
return s:GetInd(v:lnum, s:letpat, s:letlim)
endif
" Indent if current line begins with 'in':
elseif line =~ '^\s*in\>'
if lline !~ '^\s*\(let\|and\)\>'
return s:FindPair('\<let\>', '', '\<in\>')
endif
" Indent if current line begins with 'else':
elseif line =~ '^\s*else\>'
if lline !~ '^\s*\(if\|then\)\>'
return s:FindPair('\<if\>', '', '\<else\>')
endif
" Indent if current line begins with 'then':
elseif line =~ '^\s*then\>'
if lline !~ '^\s*\(if\|else\)\>'
return s:FindPair('\<if\>', '', '\<then\>')
endif
" Indent if current line begins with 'and':
elseif line =~ '^\s*and\>'
if lline !~ '^\s*\(and\|let\|type\)\>\|\<end\s*$'
return ind - &sw
endif
" Indent if current line begins with 'with':
elseif line =~ '^\s*with\>'
if lline !~ '^\s*\(match\|try\)\>'
return s:FindPair('\<\%(match\|try\)\>', '','\<with\>')
endif
" Indent if current line begins with 'exception', 'external', 'include' or
" 'open':
elseif line =~ '^\s*\(exception\|external\|include\|open\)\>'
if lline !~ s:lim . '\|' . s:letlim
call search(line)
return indent(search('^\s*\(\(exception\|external\|include\|open\|type\)\>\|val\>.*:\)', 'bW'))
endif
" Indent if current line begins with 'val':
elseif line =~ '^\s*val\>'
if lline !~ '^\s*\(exception\|external\|include\|open\)\>\|' . s:obj . '\|' . s:letlim
return indent(search('^\s*\(\(exception\|include\|initializer\|method\|open\|type\|val\)\>\|external\>.*:\)', 'bW'))
endif
" Indent if current line begins with 'constraint', 'inherit', 'initializer'
" or 'method':
elseif line =~ '^\s*\(constraint\|inherit\|initializer\|method\)\>'
if lline !~ s:obj
return indent(search('\<\(object\|object\s*(.*)\)\s*$', 'bW')) + &sw
endif
endif
" Add a 'shiftwidth' after lines ending with:
if lline =~ '\(:\|=\|->\|<-\|(\|\[\|{\|{<\|\[|\|\[<\|\<\(begin\|do\|else\|fun\|function\|functor\|if\|initializer\|object\|parser\|private\|sig\|struct\|then\|try\)\|\<object\s*(.*)\)\s*$'
let ind = ind + &sw
" Back to normal indent after lines ending with ';;':
elseif lline =~ ';;\s*$' && lline !~ '^\s*;;'
let ind = s:GetInd(v:lnum, s:letpat, s:letlim)
" Back to normal indent after lines ending with 'end':
elseif lline =~ '\<end\s*$'
let ind = s:FindPair(s:module, '','\<end\>')
" Back to normal indent after lines ending with 'in':
elseif lline =~ '\<in\s*$' && lline !~ '^\s*in\>'
let ind = s:FindPair('\<let\>', '', '\<in\>')
" Back to normal indent after lines ending with 'done':
elseif lline =~ '\<done\s*$'
let ind = s:FindPair('\<do\>', '','\<done\>')
" Back to normal indent after lines ending with '}' or '>}':
elseif lline =~ '\(\|>\)}\s*$'
let ind = s:FindPair('{', '', '}')
" Back to normal indent after lines ending with ']', '|]' or '>]':
elseif lline =~ '\(\||\|>\)\]\s*$'
let ind = s:FindPair('\[', '', '\]')
" Back to normal indent after comments:
elseif lline =~ '\*)\s*$'
call search('\*)', 'bW')
let ind = indent(searchpair('(\*', '', '\*)', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"'))
" Back to normal indent after lines ending with ')':
elseif lline =~ ')\s*$'
let ind = s:FindPair('(', '', ')')
" Indent closing brachet for ocamldoc comment properly
"elseif lline =~ '^\s*(\*\*' && line =~ '^\s*\*)'
" let ind = s:FindPair('(\*\*', '', '\*)') + 1
" If this is an ocamldoc comment then indent with 4 spaces
elseif lline =~ '^\s*(\*\*'
let ind = 4
" If this is a multiline comment then align '*':
"elseif lline =~ '^\s*(\*' && line =~ '^\s*\*'
" let ind = ind + 1
" String with continuation character -> indent continuation on next line
elseif lline =~ '\\\s*$'
call search('\\', 'bW')
let ind = searchpairpos('"', '', '"', 'bWn', 'getline(".")[col(".")-2] =~ "\\"')[1]
" Return to original indent when string ends
elseif lline =~ '"\s*$'
call search('"', 'bW')
let ind = indent(searchpair('"', '', '"', 'bWn', 'getline(".")[col(".")-2] =~ "\\"'))
"let ind = searchpairpos('"', '', '"', 'bWn', 'getline(".")[col(".")-2] =~ "\\"')[1] - 1
else
" Don't change indentation of this line
" for new lines (indent==0) use indentation of previous line
" This is for preventing removing indentation of these args:
" let f x =
" let y = x + 1 in
" Printf.printf
" "o" << here
" "oeuth" << don't touch indentation
let i = indent(v:lnum)
return i == 0 ? ind : i
endif
" Subtract a 'shiftwidth' after lines matching 'match ... with parser':
if lline =~ '\<match\>.*\<with\>\s*\<parser\s*$'
let ind = ind - &sw
endif
return ind
endfunction
" vim:sw=2
"
" File: clang_complete.vim
" Author: Xavier Deguillard <deguilx@gmail.com>
"
" Description: Use of clang to complete in C/C++.
"
" Configuration: Each project can have a .clang_complete at his root,
" containing the compiler options. This is useful if
" you're using some non-standard include paths.
" For simplicity, please don't put relative and
" absolute include path on the same line. It is not
" currently correctly handled.
"
" Options:
" - g:clang_complete_auto:
" if equal to 1, automatically complete after ->, ., ::
" Default: 1
"
" - g:clang_complete_copen:
" if equal to 1, open quickfix window on error.
" Default: 0
"
" - g:clang_hl_errors:
" if equal to 1, it will highlight the warnings and errors the
" same way clang does it.
" Default: 1
"
" - g:clang_periodic_quickfix:
" if equal to 1, it will periodically update the quickfix window
" Note: You could use the g:ClangUpdateQuickFix() to do the same
" with a mapping.
" Default: 0
"
" - g:clang_snippets:
" if equal to 1, it will do some snippets magic after a ( or a ,
" inside function call. Not currently fully working.
" Default: 0
"
" - g:clang_conceal_snippets:
" if equal to 1, vim will use vim 7.3 conceal feature to hide <#
" and #> which delimit a snippets.
" Note: See concealcursor and conceallevel for conceal configuration.
" Default: 1 (0 if conceal not available)
"
" - g:clang_exec:
" Name or path of clang executable.
" Note: Use this if clang has a non-standard name, or isn't in the
" path.
" Default: 'clang'
"
" - g:clang_user_options:
" Option added at the end of clang command. Useful if you want to
" filter the result, or if you want to ignore the error code
" returned by clang: on error, the completion is not shown.
" Default: ''
" Example: '|| exit 0' (it will discard clang return value)
"
" Todo: - Fix bugs
" - Parse fix-its and do something useful with it.
" - -code-completion-macros -code-completion-patterns
"
au FileType c,cpp,objc,objcpp call s:ClangCompleteInit()
let b:clang_parameters = ''
let b:clang_user_options = ''
let b:my_changedtick = 0
function s:ClangCompleteInit()
let l:local_conf = findfile(".clang_complete", '.;')
let b:clang_user_options = ''
if l:local_conf != ""
let l:opts = readfile(l:local_conf)
for l:opt in l:opts
" Better handling of absolute path
" I don't know if those pattern will work on windows
" platform
if matchstr(l:opt, '\C-I\s*/') != ""
let l:opt = substitute(l:opt, '\C-I\s*\(/\%(\w\|\\\s\)*\)',
\ '-I' . '\1', "g")
else
let l:opt = substitute(l:opt, '\C-I\s*\(\%(\w\|\\\s\)*\)',
\ '-I' . l:local_conf[:-16] . '\1', "g")
endif
let b:clang_user_options .= " " . l:opt
endfor
endif
if !exists('g:clang_complete_auto')
let g:clang_complete_auto = 1
endif
if !exists('g:clang_complete_copen')
let g:clang_complete_copen = 0
endif
if !exists('g:clang_hl_errors')
let g:clang_hl_errors = 1
endif
if !exists('g:clang_periodic_quickfix')
let g:clang_periodic_quickfix = 0
endif
if !exists('g:clang_snippets')
let g:clang_snippets = 0
endif
if !exists('g:clang_conceal_snippets')
let g:clang_conceal_snippets = has("conceal")
endif
if !exists('g:clang_exec')
let g:clang_exec = 'clang'
endif
if !exists('g:clang_user_options')
let g:clang_user_options = ''
endif
let b:clang_user_options .= ' ' . g:clang_user_options
if g:clang_complete_auto == 1
inoremap <expr> <buffer> <C-X><C-U> LaunchCompletion()
inoremap <expr> <buffer> . CompleteDot()
inoremap <expr> <buffer> > CompleteArrow()
inoremap <expr> <buffer> : CompleteColon()
endif
if g:clang_snippets == 1
noremap <expr> <buffer> <tab> UpdateSnips()
snoremap <expr> <buffer> <tab> UpdateSnips()
if g:clang_conceal_snippets == 1
syntax match Conceal /<#/ conceal
syntax match Conceal /#>/ conceal
endif
endif
" Disable every autocmd that could have been set.
augroup ClangComplete
autocmd!
augroup end
let b:should_overload = 0
let b:my_changedtick = b:changedtick
let b:clang_parameters = '-x c'
if &filetype == 'objc'
let b:clang_parameters = '-x objective-c'
endif
if &filetype == 'cpp' || &filetype == 'objcpp'
let b:clang_parameters .= '++'
endif
if expand('%:e') =~ 'h*'
let b:clang_parameters .= '-header'
endif
setlocal completefunc=ClangComplete
if g:clang_periodic_quickfix == 1
augroup ClangComplete
au CursorHold,CursorHoldI <buffer> call s:DoPeriodicQuickFix()
augroup end
endif
endfunction
function s:GetKind(proto)
if a:proto == ""
return 't'
endif
let l:ret = match(a:proto, '^\[#')
let l:params = match(a:proto, '(')
if l:ret == -1 && l:params == -1
return 't'
endif
if l:ret != -1 && l:params == -1
return 'v'
endif
if l:params != -1
return 'f'
endif
return 'm'
endfunction
function s:DoPeriodicQuickFix()
" Don't do any superfluous reparsing.
if b:my_changedtick == b:changedtick
return
endif
let b:my_changedtick = b:changedtick
let l:buf = getline(1, '$')
let l:tempfile = expand('%:p:h') . '/' . localtime() . expand('%:t')
try
call writefile(l:buf, l:tempfile)
catch /^Vim\%((\a\+)\)\=:E482/
return
endtry
let l:escaped_tempfile = shellescape(l:tempfile)
let l:command = g:clang_exec . " -cc1 -fsyntax-only"
\ . " -fno-caret-diagnostics -fdiagnostics-print-source-range-info"
\ . " " . l:escaped_tempfile
\ . " " . b:clang_parameters . " " . b:clang_user_options
let l:clang_output = split(system(l:command), "\n")
call delete(l:tempfile)
call s:ClangQuickFix(l:clang_output, l:tempfile)
endfunction
function s:ClangQuickFix(clang_output, tempfname)
" Clear the bad spell, the user may have corrected them.
syntax clear SpellBad
syntax clear SpellLocal
let l:list = []
for l:line in a:clang_output
let l:erridx = match(l:line, '\%(error\|warning\): ')
if l:erridx == -1
" Error are always at the beginning.
if l:line[:11] == 'COMPLETION: ' || l:line[:9] == 'OVERLOAD: '
break
endif
continue
endif
let l:pattern = '^\(.*\):\(\d*\):\(\d*\):\(\%({\d\+:\d\+-\d\+:\d\+}\)*\)'
let l:tmp = matchstr(l:line, l:pattern)
let l:fname = substitute(l:tmp, l:pattern, '\1', '')
if l:fname == a:tempfname
let l:fname = "%"
endif
let l:bufnr = bufnr(l:fname, 1)
let l:lnum = substitute(l:tmp, l:pattern, '\2', '')
let l:col = substitute(l:tmp, l:pattern, '\3', '')
let l:errors = substitute(l:tmp, l:pattern, '\4', '')
if l:line[l:erridx] == 'e'
let l:text = l:line[l:erridx + 7:]
let l:type = 'E'
let l:hlgroup = " SpellBad "
else
let l:text = l:line[l:erridx + 9:]
let l:type = 'W'
let l:hlgroup = " SpellLocal "
endif
let l:item = {
\ "bufnr": l:bufnr,
\ "lnum": l:lnum,
\ "col": l:col,
\ "text": l:text,
\ "type": l:type }
let l:list = add(l:list, l:item)
if g:clang_hl_errors == 0 || l:fname != "%"
continue
endif
" Highlighting the ^
let l:pat = '/\%' . l:lnum . 'l' . '\%' . l:col . 'c./'
exe "syntax match" . l:hlgroup . l:pat
if l:errors == ""
continue
endif
let l:ranges = split(l:errors, '}')
for l:range in l:ranges
" Doing precise error and warning handling.
" The highlight will be the same as clang's carets.
let l:pattern = '{\%(\d\+\):\(\d\+\)-\%(\d\+\):\(\d\+\)'
let l:tmp = matchstr(l:range, l:pattern)
let l:startcol = substitute(l:tmp, l:pattern, '\1', '')
let l:endcol = substitute(l:tmp, l:pattern, '\2', '')
" Highlighting the ~~~~
let l:pat = '/\%' . l:lnum . 'l'
\ . '\%' . l:startcol . 'c'
\ . '.*'
\ . '\%' . l:endcol . 'c/'
exe "syntax match" . l:hlgroup . l:pat
endfor
endfor
call setqflist(l:list)
doautocmd QuickFixCmdPost make
if g:clang_complete_copen == 1
" We should get back to the original buffer
let l:bufnr = bufnr("%")
cwindow
let l:winbufnr = bufwinnr(l:bufnr)
exe l:winbufnr . "wincmd w"
endif
endfunction
function s:DemangleProto(prototype)
let l:proto = substitute(a:prototype, '[#', "", "g")
let l:proto = substitute(l:proto, '#]', ' ', "g")
let l:proto = substitute(l:proto, '#>', "", "g")
let l:proto = substitute(l:proto, '<#', "", "g")
" TODO: add a candidate for each optional parameter
let l:proto = substitute(l:proto, '{#', "", "g")
let l:proto = substitute(l:proto, '#}', "", "g")
return l:proto
endfunction
let b:col = 0
function ClangComplete(findstart, base)
if a:findstart
let l:line = getline('.')
let l:start = col('.') - 1
let l:wsstart = l:start
if l:line[l:wsstart - 1] =~ '\s'
while l:wsstart > 0 && l:line[l:wsstart - 1] =~ '\s'
let l:wsstart -= 1
endwhile
endif
if l:line[l:wsstart - 1] =~ '[(,]'
let b:should_overload = 1
let b:col = l:wsstart + 1
return l:wsstart
endif
let b:should_overload = 0
while l:start > 0 && l:line[l:start - 1] =~ '\i'
let l:start -= 1
endwhile
let b:col = l:start + 1
return l:start
else
let l:buf = getline(1, '$')
let l:tempfile = expand('%:p:h') . '/' . localtime() . expand('%:t')
try
call writefile(l:buf, l:tempfile)
catch /^Vim\%((\a\+)\)\=:E482/
return {}
endtry
let l:escaped_tempfile = shellescape(l:tempfile)
let l:command = g:clang_exec . " -cc1 -fsyntax-only"
\ . " -fno-caret-diagnostics -fdiagnostics-print-source-range-info"
\ . " -code-completion-at=" . l:escaped_tempfile . ":"
\ . line('.') . ":" . b:col . " " . l:escaped_tempfile
\ . " " . b:clang_parameters . " " . b:clang_user_options
let l:clang_output = split(system(l:command), "\n")
call delete(l:tempfile)
call s:ClangQuickFix(l:clang_output, l:tempfile)
if v:shell_error
return {}
endif
if l:clang_output == []
return {}
endif
let l:res = []
for l:line in l:clang_output
if l:line[:11] == 'COMPLETION: ' && b:should_overload != 1
let l:value = l:line[12:]
if l:value =~ 'Pattern'
if g:clang_snippets != 1
continue
endif
let l:value = l:value[10:]
endif
if l:value !~ '^' . a:base
continue
endif
let l:colonidx = stridx(l:value, " : ")
if l:colonidx == -1
let l:wabbr = s:DemangleProto(l:value)
let l:word = l:value
let l:proto = l:value
else
let l:word = l:value[:l:colonidx - 1]
" WTF is that?
if l:word =~ '(Hidden)'
let l:word = l:word[:-10]
endif
let l:wabbr = l:word
let l:proto = l:value[l:colonidx + 3:]
endif
let l:kind = s:GetKind(l:proto)
if g:clang_snippets == 1
let l:word = substitute(l:proto, '\[#[^#]*#\]', "", "g")
else
let l:word = l:wabbr
endif
let l:proto = s:DemangleProto(l:proto)
elseif l:line[:9] == 'OVERLOAD: ' && b:should_overload == 1
\ && g:clang_snippets == 1
let l:value = l:line[10:]
if match(l:value, '<#') == -1
continue
endif
" TODO: handle optionnal parameters correctly.
let l:word = substitute(l:value, '.*<#', '<#', "g")
let l:word = substitute(l:word, '#>.*', '#>', "g")
let l:wabbr = substitute(l:word, '<#\([^#]*\)#>', '\1', "g")
let l:proto = s:DemangleProto(l:value)
let l:kind = ""
else
continue
endif
let l:item = {
\ "word": l:word,
\ "abbr": l:wabbr,
\ "menu": l:proto,
\ "info": l:proto,
\ "dup": 1,
\ "kind": l:kind }
call add(l:res, l:item)
endfor
if g:clang_snippets == 1
augroup ClangComplete
au CursorMovedI <buffer> call BeginSnips()
augroup end
endif
return l:res
endif
endfunction
function ShouldComplete()
if (getline(".") =~ '#\s*\(include\|import\)')
return 0
else
return match(synIDattr(synID(line("."), col(".") - 1, 1), "name"),
\'\C\<cComment\|\<cCppString\|\<cString\|\<cNumber') == -1
endfunction
function LaunchCompletion()
if ShouldComplete()
return "\<C-X>\<C-U>"
else
return ""
endif
endfunction
function CompleteDot()
return '.' . LaunchCompletion()
endfunction
function CompleteArrow()
if getline('.')[col('.') - 2] != '-'
return '>'
endif
return '>' . LaunchCompletion()
endfunction
function CompleteColon()
if getline('.')[col('.') - 2] != ':'
return ':'
endif
return ':' . LaunchCompletion()
endfunction
function UpdateSnips()
let l:line = getline(".")
let l:pattern = '<#[^#]*#>'
if match(l:line, l:pattern) == -1
return ""
endif
" Is it possible to use f/t/F/T on multiple chars?
"return "\<esc>f<va>\<C-G>"
return "\<esc>/<#\<CR>v/#>\<CR>l\<C-G>"
endfunction
function BeginSnips()
if pumvisible() != 0
return ""
endif
augroup ClangComplete
au! CursorMovedI <buffer>
augroup end
" Do we need to launch UpdateSnippets()?
let l:line = getline(".")
let l:pattern = '<#[^#]*#>'
if match(l:line, l:pattern) == -1
return ""
endif
call feedkeys("\<esc>^\<tab>")
return ""
endfunction
" May be used in a mapping to update the quickfix window.
function g:ClangUpdateQuickFix()
call s:DoPeriodicQuickFix()
return ""
endfunction
" command-t.vim
" Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
"
" 1. Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
" 2. 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 HOLDERS 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.
if exists("g:command_t_loaded") || &cp
finish
endif
let g:command_t_loaded = 1
command CommandTBuffer call <SID>CommandTShowBufferFinder()
command CommandTJump call <SID>CommandTShowJumpFinder()
command CommandTTag call <SID>CommandTShowTagFinder()
command -nargs=? -complete=dir CommandT call <SID>CommandTShowFileFinder(<q-args>)
command CommandTFlush call <SID>CommandTFlush()
if !hasmapto(':CommandT<CR>')
silent! nnoremap <unique> <silent> <Leader>t :CommandT<CR>
endif
if !hasmapto(':CommandTBuffer<CR>')
silent! nnoremap <unique> <silent> <Leader>b :CommandTBuffer<CR>
endif
function s:CommandTRubyWarning()
echohl WarningMsg
echo "command-t.vim requires Vim to be compiled with Ruby support"
echo "For more information type: :help command-t"
echohl none
endfunction
function s:CommandTShowBufferFinder()
if has('ruby')
ruby $command_t.show_buffer_finder
else
call s:CommandTRubyWarning()
endif
endfunction
function s:CommandTShowFileFinder(arg)
if has('ruby')
ruby $command_t.show_file_finder
else
call s:CommandTRubyWarning()
endif
endfunction
function s:CommandTShowJumpFinder()
if has('ruby')
ruby $command_t.show_jump_finder
else
call s:CommandTRubyWarning()
endif
endfunction
function s:CommandTShowTagFinder()
if has('ruby')
ruby $command_t.show_tag_finder
else
call s:CommandTRubyWarning()
endif
endfunction
function s:CommandTFlush()
if has('ruby')
ruby $command_t.flush
else
call s:CommandTRubyWarning()
endif
endfunction
if !has('ruby')
finish
endif
function CommandTListMatches()
ruby $command_t.list_matches
endfunction
function CommandTHandleKey(arg)
ruby $command_t.handle_key
endfunction
function CommandTBackspace()
ruby $command_t.backspace
endfunction
function CommandTDelete()
ruby $command_t.delete
endfunction
function CommandTAcceptSelection()
ruby $command_t.accept_selection
endfunction
function CommandTAcceptSelectionTab()
ruby $command_t.accept_selection :command => 'tabe'
endfunction
function CommandTAcceptSelectionSplit()
ruby $command_t.accept_selection :command => 'sp'
endfunction
function CommandTAcceptSelectionVSplit()
ruby $command_t.accept_selection :command => 'vs'
endfunction
function CommandTQuickfix()
ruby $command_t.quickfix
endfunction
function CommandTRefresh()
ruby $command_t.refresh
endfunction
function CommandTToggleFocus()
ruby $command_t.toggle_focus
endfunction
function CommandTCancel()
ruby $command_t.cancel
endfunction
function CommandTSelectNext()
ruby $command_t.select_next
endfunction
function CommandTSelectPrev()
ruby $command_t.select_prev
endfunction
function CommandTClear()
ruby $command_t.clear
endfunction
function CommandTCursorLeft()
ruby $command_t.cursor_left
endfunction
function CommandTCursorRight()
ruby $command_t.cursor_right
endfunction
function CommandTCursorEnd()
ruby $command_t.cursor_end
endfunction
function CommandTCursorStart()
ruby $command_t.cursor_start
endfunction
ruby << EOF
# require Ruby files
begin
# prepare controller
require 'command-t/vim'
require 'command-t/controller'
$command_t = CommandT::Controller.new
rescue LoadError
load_path_modified = false
::VIM::evaluate('&runtimepath').to_s.split(',').each do |path|
lib = "#{path}/ruby"
if !$LOAD_PATH.include?(lib) and File.exist?(lib)
$LOAD_PATH << lib
load_path_modified = true
end
end
retry if load_path_modified
# could get here if C extension was not compiled, or was compiled
# for the wrong architecture or Ruby version
require 'command-t/stub'
$command_t = CommandT::Stub.new
end
EOF
" fugitive.vim - A Git wrapper so awesome, it should be illegal
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" Version: 1.1
" GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim
if exists('g:loaded_fugitive') || &cp
finish
endif
let g:loaded_fugitive = 1
if !exists('g:fugitive_git_executable')
let g:fugitive_git_executable = 'git'
endif
" Utility {{{1
function! s:function(name) abort
return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),''))
endfunction
function! s:sub(str,pat,rep) abort
return substitute(a:str,'\v\C'.a:pat,a:rep,'')
endfunction
function! s:gsub(str,pat,rep) abort
return substitute(a:str,'\v\C'.a:pat,a:rep,'g')
endfunction
function! s:shellesc(arg) abort
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
return a:arg
elseif &shell =~# 'cmd' && a:arg !~# '"'
return '"'.a:arg.'"'
else
return shellescape(a:arg)
endif
endfunction
function! s:fnameescape(file) abort
if exists('*fnameescape')
return fnameescape(a:file)
else
return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
endif
endfunction
function! s:throw(string) abort
let v:errmsg = 'fugitive: '.a:string
throw v:errmsg
endfunction
function! s:warn(str)
echohl WarningMsg
echomsg a:str
echohl None
let v:warningmsg = a:str
endfunction
function! s:shellslash(path)
if exists('+shellslash') && !&shellslash
return s:gsub(a:path,'\\','/')
else
return a:path
endif
endfunction
function! s:add_methods(namespace, method_names) abort
for name in a:method_names
let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name)
endfor
endfunction
let s:commands = []
function! s:command(definition) abort
let s:commands += [a:definition]
endfunction
function! s:define_commands()
for command in s:commands
exe 'command! -buffer '.command
endfor
endfunction
function! s:compatibility_check()
if exists('b:git_dir') && exists('*GitBranchInfoCheckGitDir') && !exists('g:fugitive_did_compatibility_warning')
let g:fugitive_did_compatibility_warning = 1
call s:warn("See http://github.com/tpope/vim-fugitive/issues#issue/1 for why you should remove git-branch-info.vim")
endif
endfunction
augroup fugitive_utility
autocmd!
autocmd User Fugitive call s:define_commands()
autocmd VimEnter * call s:compatibility_check()
augroup END
let s:abstract_prototype = {}
" }}}1
" Initialization {{{1
function! s:ExtractGitDir(path) abort
let path = s:shellslash(a:path)
if path =~? '^fugitive://.*//'
return matchstr(path,'fugitive://\zs.\{-\}\ze//')
endif
let fn = fnamemodify(path,':s?[\/]$??')
let ofn = ""
let nfn = fn
while fn != ofn
if isdirectory(fn . '/.git')
return s:sub(simplify(fnamemodify(fn . '/.git',':p')),'\W$','')
elseif fn =~ '\.git$' && filereadable(fn . '/HEAD')
return s:sub(simplify(fnamemodify(fn,':p')),'\W$','')
endif
let ofn = fn
let fn = fnamemodify(ofn,':h')
endwhile
return ''
endfunction
function! s:Detect(path)
if exists('b:git_dir') && b:git_dir ==# ''
unlet b:git_dir
endif
if !exists('b:git_dir')
let dir = s:ExtractGitDir(a:path)
if dir != ''
let b:git_dir = dir
endif
endif
if exists('b:git_dir')
silent doautocmd User Fugitive
cnoremap <expr> <buffer> <C-R><C-G> fugitive#buffer().rev()
let buffer = fugitive#buffer()
if expand('%:p') =~# '//'
call buffer.setvar('&path',s:sub(buffer.getvar('&path'),'^\.%(,|$)',''))
endif
if b:git_dir !~# ',' && stridx(buffer.getvar('&tags'),b:git_dir.'/tags') == -1
call buffer.setvar('&tags',buffer.getvar('&tags').','.b:git_dir.'/tags')
endif
endif
endfunction
augroup fugitive
autocmd!
autocmd BufNewFile,BufReadPost * call s:Detect(expand('<amatch>:p'))
autocmd FileType netrw call s:Detect(expand('<afile>:p'))
autocmd VimEnter * if expand('<amatch>')==''|call s:Detect(getcwd())|endif
autocmd BufWinLeave * execute getwinvar(+winnr(), 'fugitive_restore')
augroup END
" }}}1
" Repository {{{1
let s:repo_prototype = {}
let s:repos = {}
function! s:repo(...) abort
let dir = a:0 ? a:1 : (exists('b:git_dir') && b:git_dir !=# '' ? b:git_dir : s:ExtractGitDir(expand('%:p')))
if dir !=# ''
if has_key(s:repos,dir)
let repo = get(s:repos,dir)
else
let repo = {'git_dir': dir}
let s:repos[dir] = repo
endif
return extend(extend(repo,s:repo_prototype,'keep'),s:abstract_prototype,'keep')
endif
call s:throw('not a git repository: '.expand('%:p'))
endfunction
function! s:repo_dir(...) dict abort
return join([self.git_dir]+a:000,'/')
endfunction
function! s:repo_tree(...) dict abort
if !self.bare()
let dir = fnamemodify(self.git_dir,':h')
return join([dir]+a:000,'/')
endif
call s:throw('no work tree')
endfunction
function! s:repo_bare() dict abort
return self.dir() !~# '/\.git$'
endfunction
function! s:repo_translate(spec) dict abort
if a:spec ==# '.' || a:spec ==# '/.'
return self.bare() ? self.dir() : self.tree()
elseif a:spec =~# '^/'
return fnamemodify(self.dir(),':h').a:spec
elseif a:spec =~# '^:[0-3]:'
return 'fugitive://'.self.dir().'//'.a:spec[1].'/'.a:spec[3:-1]
elseif a:spec ==# ':'
if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(s:repo().dir())] ==# s:repo().dir('') && filereadable($GIT_INDEX_FILE)
return fnamemodify($GIT_INDEX_FILE,':p')
else
return self.dir('index')
endif
elseif a:spec =~# '^:/'
let ref = self.rev_parse(matchstr(a:spec,'.[^:]*'))
return 'fugitive://'.self.dir().'//'.ref
elseif a:spec =~# '^:'
return 'fugitive://'.self.dir().'//0/'.a:spec[1:-1]
elseif a:spec =~# 'HEAD\|^refs/' && a:spec !~ ':' && filereadable(self.dir(a:spec))
return self.dir(a:spec)
elseif filereadable(s:repo().dir('refs/'.a:spec))
return self.dir('refs/'.a:spec)
elseif filereadable(s:repo().dir('refs/tags/'.a:spec))
return self.dir('refs/tags/'.a:spec)
elseif filereadable(s:repo().dir('refs/heads/'.a:spec))
return self.dir('refs/heads/'.a:spec)
elseif filereadable(s:repo().dir('refs/remotes/'.a:spec))
return self.dir('refs/remotes/'.a:spec)
elseif filereadable(s:repo().dir('refs/remotes/'.a:spec.'/HEAD'))
return self.dir('refs/remotes/'.a:spec,'/HEAD')
else
try
let ref = self.rev_parse(matchstr(a:spec,'[^:]*'))
let path = s:sub(matchstr(a:spec,':.*'),'^:','/')
return 'fugitive://'.self.dir().'//'.ref.path
catch /^fugitive:/
return self.tree(a:spec)
endtry
endif
endfunction
call s:add_methods('repo',['dir','tree','bare','translate'])
function! s:repo_git_command(...) dict abort
let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir)
return git.join(map(copy(a:000),'" ".s:shellesc(v:val)'),'')
endfunction
function! s:repo_git_chomp(...) dict abort
return s:sub(system(call(self.git_command,a:000,self)),'\n$','')
endfunction
function! s:repo_git_chomp_in_tree(...) dict abort
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
return call(s:repo().git_chomp, a:000, s:repo())
finally
execute cd.'`=dir`'
endtry
endfunction
function! s:repo_rev_parse(rev) dict abort
let hash = self.git_chomp('rev-parse','--verify',a:rev)
if hash =~ '^\x\{40\}$'
return hash
endif
call s:throw('rev-parse '.a:rev.': '.hash)
endfunction
call s:add_methods('repo',['git_command','git_chomp','git_chomp_in_tree','rev_parse'])
function! s:repo_dirglob(base) dict abort
let base = s:sub(a:base,'^/','')
let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*/')),"\n")
call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]')
return matches
endfunction
function! s:repo_superglob(base) dict abort
if a:base =~# '^/' || a:base !~# ':'
let results = []
if a:base !~# '^/'
let heads = ["HEAD","ORIG_HEAD","FETCH_HEAD","MERGE_HEAD"]
let heads += sort(split(s:repo().git_chomp("rev-parse","--symbolic","--branches","--tags","--remotes"),"\n"))
call filter(heads,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
let results += heads
endif
if !self.bare()
let base = s:sub(a:base,'^/','')
let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*')),"\n")
call map(matches,'s:shellslash(v:val)')
call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val')
call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]')
let results += matches
endif
return results
elseif a:base =~# '^:'
let entries = split(self.git_chomp('ls-files','--stage'),"\n")
call map(entries,'s:sub(v:val,".*(\\d)\\t(.*)",":\\1:\\2")')
if a:base !~# '^:[0-3]\%(:\|$\)'
call filter(entries,'v:val[1] == "0"')
call map(entries,'v:val[2:-1]')
endif
call filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
return entries
else
let tree = matchstr(a:base,'.*[:/]')
let entries = split(self.git_chomp('ls-tree',tree),"\n")
call map(entries,'s:sub(v:val,"^04.*\\zs$","/")')
call map(entries,'tree.s:sub(v:val,".*\t","")')
return filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
endif
endfunction
call s:add_methods('repo',['dirglob','superglob'])
function! s:repo_keywordprg() dict abort
let args = ' --git-dir='.escape(self.dir(),"\\\"' ").' show'
if has('gui_running') && !has('win32')
return g:fugitive_git_executable . ' --no-pager' . args
else
return g:fugitive_git_executable . args
endif
endfunction
call s:add_methods('repo',['keywordprg'])
" }}}1
" Buffer {{{1
let s:buffer_prototype = {}
function! s:buffer(...) abort
let buffer = {'#': bufnr(a:0 ? a:1 : '%')}
call extend(extend(buffer,s:buffer_prototype,'keep'),s:abstract_prototype,'keep')
if buffer.getvar('git_dir') !=# ''
return buffer
endif
call s:throw('not a git repository: '.expand('%:p'))
endfunction
function! fugitive#buffer(...) abort
return s:buffer(a:0 ? a:1 : '%')
endfunction
function! s:buffer_getvar(var) dict abort
return getbufvar(self['#'],a:var)
endfunction
function! s:buffer_setvar(var,value) dict abort
return setbufvar(self['#'],a:var,a:value)
endfunction
function! s:buffer_getline(lnum) dict abort
return getbufline(self['#'],a:lnum)[0]
endfunction
function! s:buffer_repo() dict abort
return s:repo(self.getvar('git_dir'))
endfunction
function! s:buffer_type(...) dict abort
if self.getvar('fugitive_type') != ''
let type = self.getvar('fugitive_type')
elseif fnamemodify(self.spec(),':p') =~# '.\git/refs/\|\.git/\w*HEAD$'
let type = 'head'
elseif self.getline(1) =~ '^tree \x\{40\}$' && self.getline(2) == ''
let type = 'tree'
elseif self.getline(1) =~ '^\d\{6\} \w\{4\} \x\{40\}\>\t'
let type = 'tree'
elseif self.getline(1) =~ '^\d\{6\} \x\{40\}\> \d\t'
let type = 'index'
elseif isdirectory(self.spec())
let type = 'directory'
elseif self.spec() == ''
let type = 'null'
elseif filereadable(self.spec())
let type = 'file'
else
let type = ''
endif
if a:0
return !empty(filter(copy(a:000),'v:val ==# type'))
else
return type
endif
endfunction
function! s:buffer_spec() dict abort
let bufname = bufname(self['#'])
return s:shellslash(bufname == '' ? '' : fnamemodify(bufname,':p'))
endfunction
function! s:buffer_name() dict abort
return self.spec()
endfunction
function! s:buffer_commit() dict abort
return matchstr(self.spec(),'^fugitive://.\{-\}//\zs\w*')
endfunction
function! s:buffer_path(...) dict abort
let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*')
if rev != ''
let rev = s:sub(rev,'\w*','')
else
let rev = self.spec()[strlen(self.repo().tree()) : -1]
endif
return s:sub(rev,'^/',a:0 ? a:1 : '')
endfunction
function! s:buffer_rev() dict abort
let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*')
if rev =~ '^\x/'
return ':'.rev[0].':'.rev[2:-1]
elseif rev =~ '.'
return s:sub(rev,'/',':')
elseif self.spec() =~ '\.git/index$'
return ':'
elseif self.spec() =~ '\.git/refs/\|\.git/.*HEAD$'
return self.spec()[strlen(self.repo().dir())+1 : -1]
else
return self.path()
endif
endfunction
function! s:buffer_sha1() dict abort
if self.spec() =~ '^fugitive://' || self.spec() =~ '\.git/refs/\|\.git/.*HEAD$'
return self.repo().rev_parse(self.rev())
else
return ''
endif
endfunction
function! s:buffer_expand(rev) dict abort
if a:rev =~# '^:[0-3]$'
let file = a:rev.self.path(':')
elseif a:rev =~# '^-'
let file = 'HEAD^{}'.a:rev[1:-1].self.path(':')
elseif a:rev =~# '^@{'
let file = 'HEAD'.a:rev.self.path(':')
elseif a:rev =~# '^[~^]'
let commit = s:sub(self.commit(),'^\d=$','HEAD')
let file = commit.a:rev.self.path(':')
else
let file = a:rev
endif
return s:sub(file,'\%$',self.path())
endfunction
function! s:buffer_containing_commit() dict abort
if self.commit() =~# '^\d$'
return ':'
elseif self.commit() =~# '.'
return self.commit()
else
return 'HEAD'
endif
endfunction
call s:add_methods('buffer',['getvar','setvar','getline','repo','type','spec','name','commit','path','rev','sha1','expand','containing_commit'])
" }}}1
" Git {{{1
call s:command("-bang -nargs=? -complete=customlist,s:GitComplete Git :execute s:Git(<bang>0,<q-args>)")
function! s:ExecuteInTree(cmd) abort
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
execute a:cmd
finally
execute cd.'`=dir`'
endtry
endfunction
function! s:Git(bang,cmd) abort
let git = s:repo().git_command()
if has('gui_running') && !has('win32')
let git .= ' --no-pager'
endif
let cmd = matchstr(a:cmd,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=')
call s:ExecuteInTree('!'.git.' '.cmd)
call fugitive#reload_status()
return matchstr(a:cmd,'\v\C\\@<!%(\\\\)*\|\zs.*')
endfunction
function! s:GitComplete(A,L,P) abort
if !exists('s:exec_path')
let s:exec_path = s:sub(system(g:fugitive_git_executable.' --exec-path'),'\n$','')
endif
let cmds = map(split(glob(s:exec_path.'/git-*'),"\n"),'s:sub(v:val[strlen(s:exec_path)+5 : -1],"\\.exe$","")')
if a:L =~ ' [[:alnum:]-]\+ '
return s:repo().superglob(a:A)
elseif a:A == ''
return cmds
else
return filter(cmds,'v:val[0 : strlen(a:A)-1] ==# a:A')
endif
endfunction
" }}}1
" Gcd, Glcd {{{1
function! s:DirComplete(A,L,P) abort
let matches = s:repo().dirglob(a:A)
return matches
endfunction
call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Gcd :cd<bang> `=s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>)`")
call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :lcd<bang> `=s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>)`")
" }}}1
" Gstatus {{{1
call s:command("-bar Gstatus :execute s:Status()")
function! s:Status() abort
try
Gpedit :
wincmd P
nnoremap <buffer> <silent> q :<C-U>bdelete<CR>
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
return ''
endfunction
function! fugitive#reload_status() abort
let mytab = tabpagenr()
for tab in [mytab] + range(1,tabpagenr('$'))
for winnr in range(1,tabpagewinnr(tab,'$'))
if getbufvar(tabpagebuflist(tab)[winnr-1],'fugitive_type') ==# 'index'
execute 'tabnext '.tab
if winnr != winnr()
execute winnr.'wincmd w'
let restorewinnr = 1
endif
try
if !&modified
call s:BufReadIndex()
endif
finally
if exists('restorewinnr')
wincmd p
endif
execute 'tabnext '.mytab
endtry
endif
endfor
endfor
endfunction
function! s:StageDiff(bang) abort
let section = getline(search('^# .*:$','bnW'))
let line = getline('.')
let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*')
if filename ==# '' && section == '# Changes to be committed:'
return 'Git diff --cached'
elseif filename ==# ''
return 'Git diff'
elseif line =~# '^#\trenamed:' && filename =~ ' -> '
let [old, new] = split(filename,' -> ')
execute 'Gedit '.s:fnameescape(':0:'.new)
return 'Gdiff'.a:bang.' HEAD:'.s:fnameescape(old)
elseif section == '# Changes to be committed:'
execute 'Gedit '.s:fnameescape(':0:'.filename)
return 'Gdiff'.a:bang.' -'
else
execute 'Gedit '.s:fnameescape('/'.filename)
return 'Gdiff'.a:bang
endif
endfunction
function! s:StageToggle(lnum1,lnum2) abort
try
let output = ''
for lnum in range(a:lnum1,a:lnum2)
let line = getline(lnum)
if getline('.') == '# Changes to be committed:'
return 'Gcommit'
endif
let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*')
if filename ==# ''
continue
endif
if !exists('first_filename')
let first_filename = filename
endif
execute lnum
let section = getline(search('^# .*:$','bnW'))
if line =~# '^#\trenamed:' && filename =~ ' -> '
let cmd = ['mv','--'] + reverse(split(filename,' -> '))
let filename = cmd[-1]
elseif section =~? ' to be '
let cmd = ['reset','-q','--',filename]
elseif line =~# '^#\tdeleted:'
let cmd = ['rm','--',filename]
else
let cmd = ['add','--',filename]
endif
let output .= call(s:repo().git_chomp_in_tree,cmd,s:repo())."\n"
endfor
if exists('first_filename')
let jump = first_filename
let f = matchstr(getline(a:lnum1-1),'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*')
if f !=# '' | let jump = f | endif
let f = matchstr(getline(a:lnum2+1),'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*')
if f !=# '' | let jump = f | endif
silent! edit!
1
redraw
call search('^#\t\%([[:alpha:] ]\+: *\)\=\V'.jump.'\$','W')
endif
echo s:sub(s:gsub(output,'\n+','\n'),'\n$','')
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
return 'checktime'
endfunction
function! s:StagePatch(lnum1,lnum2) abort
let add = []
let reset = []
for lnum in range(a:lnum1,a:lnum2)
let line = getline(lnum)
if line == '# Changes to be committed:'
return 'Git reset --patch'
elseif line == '# Changed but not updated:'
return 'Git add --patch'
endif
let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*')
if filename ==# ''
continue
endif
if !exists('first_filename')
let first_filename = filename
endif
execute lnum
let section = getline(search('^# .*:$','bnW'))
if line =~# '^#\trenamed:' && filename =~ ' -> '
let reset += [split(filename,' -> ')[1]]
elseif section =~? ' to be '
let reset += [filename]
elseif line !~# '^#\tdeleted:'
let add += [filename]
endif
endfor
try
if !empty(add)
execute "Git add --patch -- ".join(map(add,'s:shellesc(v:val)'))
endif
if !empty(reset)
execute "Git reset --patch -- ".join(map(add,'s:shellesc(v:val)'))
endif
if exists('first_filename')
silent! edit!
1
redraw
call search('^#\t\%([[:alpha:] ]\+: *\)\=\V'.first_filename.'\$','W')
endif
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
return 'checktime'
endfunction
" }}}1
" Gcommit {{{1
call s:command("-nargs=? -complete=customlist,s:CommitComplete Gcommit :execute s:Commit(<q-args>)")
function! s:Commit(args) abort
let old_type = s:buffer().type()
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
let msgfile = s:repo().dir('COMMIT_EDITMSG')
let outfile = tempname()
let errorfile = tempname()
try
execute cd.'`=s:repo().tree()`'
let command = ''
if &shell =~# 'cmd'
let old_editor = $GIT_EDITOR
let $GIT_EDITOR = 'false'
elseif &shell !~# 'csh'
let command = 'GIT_EDITOR=false '
endif
let command .= s:repo().git_command('commit').' '.a:args
if &shell =~# 'csh'
silent execute '!setenv GIT_EDITOR false; ('.command.' > '.outfile.') >& '.errorfile
elseif a:args =~# '\%(^\| \)--interactive\>'
execute '!'.command.' 2> '.errorfile
else
silent execute '!'.command.' > '.outfile.' 2> '.errorfile
endif
if !v:shell_error
if filereadable(outfile)
for line in readfile(outfile)
echo line
endfor
endif
return ''
else
let errors = readfile(errorfile)
let error = get(errors,-2,get(errors,-1,'!'))
if error =~# "'false'\\.$"
let args = a:args
let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-[se]|--edit|--interactive)%($| )','')
let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-F|--file|-m|--message)%(\s+|\=)%(''[^'']*''|"%(\\.|[^"])*"|\\.|\S)*','')
let args = s:gsub(args,'%(^| )@<=[%#]%(:\w)*','\=expand(submatch(0))')
let args = '-F '.s:shellesc(msgfile).' '.args
if args !~# '\%(^\| \)--cleanup\>'
let args = '--cleanup=strip '.args
endif
if bufname('%') == '' && line('$') == 1 && getline(1) == '' && !&mod
edit `=msgfile`
else
split `=msgfile`
endif
if old_type ==# 'index'
bdelete #
endif
let b:fugitive_commit_arguments = args
setlocal bufhidden=delete filetype=gitcommit
return '1'
elseif error ==# '!'
return s:Status()
else
call s:throw(error)
endif
endif
catch /^fugitive:/
return 'echoerr v:errmsg'
finally
if exists('old_editor')
let $GIT_EDITOR = old_editor
endif
call delete(outfile)
call delete(errorfile)
execute cd.'`=dir`'
call fugitive#reload_status()
endtry
endfunction
function! s:CommitComplete(A,L,P) abort
if a:A =~ '^-' || type(a:A) == type(0) " a:A is 0 on :Gcommit -<Tab>
let args = ['-C', '-F', '-a', '-c', '-e', '-i', '-m', '-n', '-o', '-q', '-s', '-t', '-u', '-v', '--all', '--allow-empty', '--amend', '--author=', '--cleanup=', '--dry-run', '--edit', '--file=', '--include', '--interactive', '--message=', '--no-verify', '--only', '--quiet', '--reedit-message=', '--reuse-message=', '--signoff', '--template=', '--untracked-files', '--verbose']
return filter(args,'v:val[0 : strlen(a:A)-1] ==# a:A')
else
return s:repo().superglob(a:A)
endif
endfunction
function! s:FinishCommit()
let args = getbufvar(+expand('<abuf>'),'fugitive_commit_arguments')
if !empty(args)
call setbufvar(+expand('<abuf>'),'fugitive_commit_arguments','')
return s:Commit(args)
endif
return ''
endfunction
augroup fugitive_commit
autocmd!
autocmd VimLeavePre,BufDelete *.git/COMMIT_EDITMSG execute s:sub(s:FinishCommit(), '^echoerr (.*)', 'echohl ErrorMsg|echo \1|echohl NONE')
augroup END
" }}}1
" Ggrep, Glog {{{1
if !exists('g:fugitive_summary_format')
let g:fugitive_summary_format = '%s'
endif
call s:command("-bang -nargs=? -complete=customlist,s:EditComplete Ggrep :execute s:Grep(<bang>0,<q-args>)")
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Glog :execute s:Log('grep<bang>',<f-args>)")
function! s:Grep(bang,arg) abort
let grepprg = &grepprg
let grepformat = &grepformat
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n')
let &grepformat = '%f:%l:%m'
exe 'grep! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|')
let list = getqflist()
for entry in list
if bufname(entry.bufnr) =~ ':'
let entry.filename = s:repo().translate(bufname(entry.bufnr))
unlet! entry.bufnr
elseif a:arg =~# '\%(^\| \)--cached\>'
let entry.filename = s:repo().translate(':0:'.bufname(entry.bufnr))
unlet! entry.bufnr
endif
endfor
call setqflist(list,'r')
if !a:bang && !empty(list)
return 'cfirst'.matchstr(a:arg,'\v\C[''" ]\zs\|.*')
else
return matchstr(a:arg,'\v\C[''" ]\|\zs.*')
endif
finally
let &grepprg = grepprg
let &grepformat = grepformat
execute cd.'`=dir`'
endtry
endfunction
function! s:Log(cmd,...)
let path = s:buffer().path('/')
if path =~# '^/\.git\%(/\|$\)' || index(a:000,'--') != -1
let path = ''
endif
let cmd = ['--no-pager', 'log', '--no-color']
let cmd += [escape('--pretty=format:fugitive://'.s:repo().dir().'//%H'.path.'::'.g:fugitive_summary_format,'%')]
if empty(filter(a:000[0 : index(a:000,'--')],'v:val !~# "^-"'))
if s:buffer().commit() =~# '\x\{40\}'
let cmd += [s:buffer().commit()]
elseif s:buffer().path() =~# '^\.git/refs/\|^\.git/.*HEAD$'
let cmd += [s:buffer().path()[5:-1]]
endif
end
let cmd += map(copy(a:000),'s:sub(v:val,"^\\%(%(:\\w)*)","\\=fnamemodify(s:buffer().path(),submatch(1))")')
if path =~# '/.'
let cmd += ['--',path[1:-1]]
endif
let grepformat = &grepformat
let grepprg = &grepprg
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
let &grepprg = call(s:repo().git_command,cmd,s:repo())
let &grepformat = '%f::%m'
exe a:cmd
finally
let &grepformat = grepformat
let &grepprg = grepprg
execute cd.'`=dir`'
endtry
endfunction
" }}}1
" Gedit, Gpedit, Gsplit, Gvsplit, Gtabedit, Gread {{{1
function! s:Edit(cmd,...) abort
if a:0 && a:1 == ''
return ''
elseif a:0
let file = s:buffer().expand(a:1)
elseif s:buffer().commit() ==# '' && s:buffer().path('/') !~# '^/.git\>'
let file = s:buffer().path(':')
else
let file = s:buffer().path('/')
endif
try
let file = s:repo().translate(file)
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
if a:cmd =~# 'read!$' || a:cmd ==# 'read'
if a:cmd =~# '!$'
call s:warn(':Gread! is deprecated. Use :Gread')
endif
return 'silent %delete|read '.s:fnameescape(file).'|silent 1delete_|diffupdate|'.line('.')
else
if &previewwindow && getbufvar('','fugitive_type') ==# 'index'
wincmd p
endif
return a:cmd.' '.s:fnameescape(file)
endif
endfunction
function! s:EditComplete(A,L,P) abort
return s:repo().superglob(a:A)
endfunction
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Ge :execute s:Edit('edit<bang>',<f-args>)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gedit :execute s:Edit('edit<bang>',<f-args>)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gpedit :execute s:Edit('pedit<bang>',<f-args>)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gsplit :execute s:Edit('split<bang>',<f-args>)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gvsplit :execute s:Edit('vsplit<bang>',<f-args>)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gtabedit :execute s:Edit('tabedit<bang>',<f-args>)")
call s:command("-bar -bang -nargs=? -count -complete=customlist,s:EditComplete Gread :execute s:Edit((!<count> && <line1> ? '' : <count>).'read<bang>',<f-args>)")
" }}}1
" Gwrite {{{1
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gwrite :execute s:Write(<bang>0,<f-args>)")
function! s:Write(force,...) abort
if exists('b:fugitive_commit_arguments')
return 'write|bdelete'
elseif expand('%:t') == 'COMMIT_EDITMSG' && $GIT_INDEX_FILE != ''
return 'wq'
elseif s:buffer().type() == 'index'
return 'Gcommit'
endif
let mytab = tabpagenr()
let mybufnr = bufnr('')
let path = a:0 ? a:1 : s:buffer().path()
if path =~# '^:\d\>'
return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:repo().translate(s:buffer().expand(path)))
endif
let always_permitted = (s:buffer().path() ==# path && s:buffer().commit() =~# '^0\=$')
if !always_permitted && !a:force && s:repo().git_chomp_in_tree('diff','--name-status','HEAD','--',path) . s:repo().git_chomp_in_tree('ls-files','--others','--',path) !=# ''
let v:errmsg = 'fugitive: file has uncommitted changes (use ! to override)'
return 'echoerr v:errmsg'
endif
let file = s:repo().translate(path)
let treebufnr = 0
for nr in range(1,bufnr('$'))
if fnamemodify(bufname(nr),':p') ==# file
let treebufnr = nr
endif
endfor
if treebufnr > 0 && treebufnr != bufnr('')
let temp = tempname()
silent execute '%write '.temp
for tab in [mytab] + range(1,tabpagenr('$'))
for winnr in range(1,tabpagewinnr(tab,'$'))
if tabpagebuflist(tab)[winnr-1] == treebufnr
execute 'tabnext '.tab
if winnr != winnr()
execute winnr.'wincmd w'
let restorewinnr = 1
endif
try
let lnum = line('.')
let last = line('$')
silent execute '$read '.temp
silent execute '1,'.last.'delete_'
silent write!
silent execute lnum
let did = 1
finally
if exists('restorewinnr')
wincmd p
endif
execute 'tabnext '.mytab
endtry
endif
endfor
endfor
if !exists('did')
call writefile(readfile(temp,'b'),file,'b')
endif
else
execute 'write! '.s:fnameescape(s:repo().translate(path))
endif
if a:force
let error = s:repo().git_chomp_in_tree('add', '--force', file)
else
let error = s:repo().git_chomp_in_tree('add', file)
endif
if v:shell_error
let v:errmsg = 'fugitive: '.error
return 'echoerr v:errmsg'
endif
if s:buffer().path() ==# path && s:buffer().commit() =~# '^\d$'
set nomodified
endif
let one = s:repo().translate(':1:'.path)
let two = s:repo().translate(':2:'.path)
let three = s:repo().translate(':3:'.path)
for nr in range(1,bufnr('$'))
if bufloaded(nr) && !getbufvar(nr,'&modified') && (bufname(nr) == one || bufname(nr) == two || bufname(nr) == three)
execute nr.'bdelete'
endif
endfor
unlet! restorewinnr
let zero = s:repo().translate(':0:'.path)
for tab in range(1,tabpagenr('$'))
for winnr in range(1,tabpagewinnr(tab,'$'))
let bufnr = tabpagebuflist(tab)[winnr-1]
let bufname = bufname(bufnr)
if bufname ==# zero && bufnr != mybufnr
execute 'tabnext '.tab
if winnr != winnr()
execute winnr.'wincmd w'
let restorewinnr = 1
endif
try
let lnum = line('.')
let last = line('$')
silent $read `=file`
silent execute '1,'.last.'delete_'
silent execute lnum
set nomodified
diffupdate
finally
if exists('restorewinnr')
wincmd p
endif
execute 'tabnext '.mytab
endtry
break
endif
endfor
endfor
call fugitive#reload_status()
return 'checktime'
endfunction
" }}}1
" Gdiff {{{1
call s:command("-bang -bar -nargs=? -complete=customlist,s:EditComplete Gdiff :execute s:Diff(<bang>0,<f-args>)")
call s:command("-bar -nargs=? -complete=customlist,s:EditComplete Gvdiff :execute s:Diff(0,<f-args>)")
call s:command("-bar -nargs=? -complete=customlist,s:EditComplete Gsdiff :execute s:Diff(1,<f-args>)")
augroup fugitive_diff
autocmd!
autocmd BufWinLeave * if s:diff_window_count() == 2 && &diff && getbufvar(+expand('<abuf>'), 'git_dir') !=# '' | call s:diff_off_all(getbufvar(+expand('<abuf>'), 'git_dir')) | endif
autocmd BufWinEnter * if s:diff_window_count() == 1 && &diff && getbufvar(+expand('<abuf>'), 'git_dir') !=# '' | diffoff | endif
augroup END
function! s:diff_window_count()
let c = 0
for nr in range(1,winnr('$'))
let c += getwinvar(nr,'&diff')
endfor
return c
endfunction
function! s:diff_off_all(dir)
for nr in range(1,winnr('$'))
if getwinvar(nr,'&diff')
if nr != winnr()
execute nr.'wincmd w'
let restorewinnr = 1
endif
if exists('b:git_dir') && b:git_dir ==# a:dir
diffoff
endif
if exists('restorewinnr')
wincmd p
endif
endif
endfor
endfunction
function! s:buffer_compare_age(commit) dict abort
let scores = {':0': 1, ':1': 2, ':2': 3, ':': 4, ':3': 5}
let my_score = get(scores,':'.self.commit(),0)
let their_score = get(scores,':'.a:commit,0)
if my_score || their_score
return my_score < their_score ? -1 : my_score != their_score
elseif self.commit() ==# a:commit
return 0
endif
let base = self.repo().git_chomp('merge-base',self.commit(),a:commit)
if base ==# self.commit()
return -1
elseif base ==# a:commit
return 1
endif
let my_time = +self.repo().git_chomp('log','--max-count=1','--pretty=format:%at',self.commit())
let their_time = +self.repo().git_chomp('log','--max-count=1','--pretty=format:%at',a:commit)
return my_time < their_time ? -1 : my_time != their_time
endfunction
call s:add_methods('buffer',['compare_age'])
function! s:Diff(bang,...) abort
let split = a:bang ? 'split' : 'vsplit'
if exists(':DiffGitCached')
return 'DiffGitCached'
elseif (!a:0 || a:1 == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# ''
execute 'leftabove '.split.' `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`'
diffthis
wincmd p
execute 'rightbelow '.split.' `=fugitive#buffer().repo().translate(s:buffer().expand('':3''))`'
diffthis
wincmd p
diffthis
return ''
elseif a:0
if a:1 ==# ''
return ''
elseif a:1 ==# '/'
let file = s:buffer().path('/')
elseif a:1 ==# ':'
let file = s:buffer().path(':0:')
elseif a:1 =~# '^:/'
try
let file = s:repo().rev_parse(a:1).s:buffer().path(':')
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
else
let file = s:buffer().expand(a:1)
endif
if file !~# ':' && file !~# '^/' && s:repo().git_chomp('cat-file','-t',file) =~# '^\%(tag\|commit\)$'
let file = file.s:buffer().path(':')
endif
else
let file = s:buffer().path(s:buffer().commit() == '' ? ':0:' : '/')
endif
try
let spec = s:repo().translate(file)
let commit = matchstr(spec,'\C[^:/]//\zs\x\+')
if s:buffer().compare_age(commit) < 0
execute 'rightbelow '.split.' `=spec`'
else
execute 'leftabove '.split.' `=spec`'
endif
diffthis
wincmd p
diffthis
return ''
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
endfunction
" }}}1
" Gmove, Gremove {{{1
function! s:Move(force,destination)
if a:destination =~# '^/'
let destination = a:destination[1:-1]
else
let destination = fnamemodify(s:sub(a:destination,'[%#]%(:\w)*','\=expand(submatch(0))'),':p')
if destination[0:strlen(s:repo().tree())] ==# s:repo().tree('')
let destination = destination[strlen(s:repo().tree('')):-1]
endif
endif
let message = call(s:repo().git_chomp_in_tree,['mv']+(a:force ? ['-f'] : [])+['--', s:buffer().path(), destination], s:repo())
if v:shell_error
let v:errmsg = 'fugitive: '.message
return 'echoerr v:errmsg'
endif
let destination = s:repo().tree(destination)
if isdirectory(destination)
let destination = fnamemodify(s:sub(destination,'/$','').'/'.expand('%:t'),':.')
endif
call fugitive#reload_status()
if s:buffer().commit() == ''
return 'saveas! '.s:fnameescape(destination)
else
return 'file '.s:fnameescape(s:repo().translate(':0:'.destination)
endif
endfunction
function! s:MoveComplete(A,L,P)
if a:A =~ '^/'
return s:repo().superglob(a:A)
else
let matches = split(glob(a:A.'*'),"\n")
call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val')
return matches
endif
endfunction
function! s:Remove(force)
if s:buffer().commit() ==# ''
let cmd = ['rm']
elseif s:buffer().commit() ==# '0'
let cmd = ['rm','--cached']
else
let v:errmsg = 'fugitive: rm not supported here'
return 'echoerr v:errmsg'
endif
if a:force
let cmd += ['--force']
endif
let message = call(s:repo().git_chomp_in_tree,cmd+['--',s:buffer().path()],s:repo())
if v:shell_error
let v:errmsg = 'fugitive: '.s:sub(message,'error:.*\zs\n\(.*-f.*',' (add ! to force)')
return 'echoerr '.string(v:errmsg)
else
call fugitive#reload_status()
return 'bdelete'.(a:force ? '!' : '')
endif
endfunction
augroup fugitive_remove
autocmd!
autocmd User Fugitive if s:buffer().commit() =~# '^0\=$' |
\ exe "command! -buffer -bar -bang -nargs=1 -complete=customlist,s:MoveComplete Gmove :execute s:Move(<bang>0,<q-args>)" |
\ exe "command! -buffer -bar -bang Gremove :execute s:Remove(<bang>0)" |
\ endif
augroup END
" }}}1
" Gblame {{{1
augroup fugitive_blame
autocmd!
autocmd BufReadPost *.fugitiveblame setfiletype fugitiveblame
autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:repo().keywordprg() | endif
autocmd Syntax fugitiveblame call s:BlameSyntax()
autocmd User Fugitive if s:buffer().type('file', 'blob') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(<bang>0,<line1>,<line2>,<count>,[<f-args>])" | endif
augroup END
function! s:Blame(bang,line1,line2,count,args) abort
try
if s:buffer().path() == ''
call s:throw('file or blob required')
endif
if filter(copy(a:args),'v:val !~# "^\\%(--root\|--show-name\\|-\\=\\%([ltwfs]\\|[MC]\\d*\\)\\+\\)$"') != []
call s:throw('unsupported option')
endif
call map(a:args,'s:sub(v:val,"^\\ze[^-]","-")')
let git_dir = s:repo().dir()
let cmd = ['--no-pager', 'blame', '--show-number'] + a:args
if s:buffer().commit() =~# '\D\|..'
let cmd += [s:buffer().commit()]
else
let cmd += ['--contents', '-']
endif
let basecmd = call(s:repo().git_command,cmd+['--',s:buffer().path()],s:repo())
try
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
if !s:repo().bare()
let dir = getcwd()
execute cd.'`=s:repo().tree()`'
endif
if a:count
execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g')
else
let error = tempname()
let temp = error.'.fugitiveblame'
if &shell =~# 'csh'
silent! execute '%write !('.basecmd.' > '.temp.') >& '.error
else
silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error
endif
if exists('l:dir')
execute cd.'`=dir`'
unlet dir
endif
if v:shell_error
call s:throw(join(readfile(error),"\n"))
endif
let bufnr = bufnr('')
let restore = 'call setwinvar(bufwinnr('.bufnr.'),"&scrollbind",0)'
if &l:wrap
let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&wrap",1)'
endif
if &l:foldenable
let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&foldenable",1)'
endif
let winnr = winnr()
windo set noscrollbind
exe winnr.'wincmd w'
setlocal scrollbind nowrap nofoldenable
let top = line('w0') + &scrolloff
let current = line('.')
exe 'leftabove vsplit '.temp
let b:git_dir = git_dir
let b:fugitive_type = 'blame'
let b:fugitive_blamed_bufnr = bufnr
let w:fugitive_restore = restore
let b:fugitive_blame_arguments = join(a:args,' ')
call s:Detect(expand('%:p'))
execute top
normal! zt
execute current
execute "vertical resize ".(match(getline('.'),'\s\+\d\+)')+1)
setlocal nomodified nomodifiable bufhidden=delete nonumber scrollbind nowrap foldcolumn=0 nofoldenable filetype=fugitiveblame
nnoremap <buffer> <silent> q :<C-U>bdelete<CR>
nnoremap <buffer> <silent> <CR> :<C-U>exe <SID>BlameJump('')<CR>
nnoremap <buffer> <silent> P :<C-U>exe <SID>BlameJump('^'.v:count1)<CR>
nnoremap <buffer> <silent> ~ :<C-U>exe <SID>BlameJump('~'.v:count1)<CR>
nnoremap <buffer> <silent> o :<C-U>exe <SID>Edit((&splitbelow ? "botright" : "topleft")." split", matchstr(getline('.'),'\x\+'))<CR>
nnoremap <buffer> <silent> O :<C-U>exe <SID>Edit("tabedit", matchstr(getline('.'),'\x\+'))<CR>
syncbind
endif
finally
if exists('l:dir')
execute cd.'`=dir`'
endif
endtry
return ''
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
endfunction
function! s:BlameJump(suffix) abort
let commit = matchstr(getline('.'),'^\^\=\zs\x\+')
if commit =~# '^0\+$'
let commit = ':0'
endif
let lnum = matchstr(getline('.'),'\d\+\ze\s\+[([:digit:]]')
let path = matchstr(getline('.'),'^\^\=\zs\x\+\s\+\zs.\{-\}\ze\s*\d\+ ')
if path ==# ''
let path = s:buffer(b:fugitive_blamed_bufnr).path()
endif
let args = b:fugitive_blame_arguments
let offset = line('.') - line('w0')
let bufnr = bufnr('%')
let winnr = bufwinnr(b:fugitive_blamed_bufnr)
if winnr > 0
exe winnr.'wincmd w'
endif
execute s:Edit('edit',commit.a:suffix.':'.path)
if winnr > 0
exe bufnr.'bdelete'
endif
execute 'Gblame '.args
execute lnum
let delta = line('.') - line('w0') - offset
if delta > 0
execute 'norm! 'delta."\<C-E>"
elseif delta < 0
execute 'norm! '(-delta)."\<C-Y>"
endif
syncbind
return ''
endfunction
function! s:BlameSyntax() abort
let b:current_syntax = 'fugitiveblame'
syn match FugitiveblameBoundary "^\^"
syn match FugitiveblameBlank "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite
syn match FugitiveblameHash "\%(^\^\=\)\@<=\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline
syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation
syn match FugitiveblameLineNumber " \@<=\d\+)\@=" contained containedin=FugitiveblameAnnotation
syn match FugitiveblameOriginalFile " \%(\f\+\D\@<=\|\D\@=\f\+\)\%(\%(\s\+\d\+\)\=\s\%((\|\s*\d\+)\)\)\@=" contained nextgroup=FugitiveblameOriginalLineNumber,FugitiveblameAnnotation skipwhite
syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%(\s(\)\@=" contained nextgroup=FugitiveblameAnnotation skipwhite
syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%(\s\+\d\+)\)\@=" contained nextgroup=FugitiveblameShort skipwhite
syn match FugitiveblameShort "\d\+)" contained contains=FugitiveblameLineNumber
syn match FugitiveblameNotCommittedYet "(\@<=Not Committed Yet\>" contained containedin=FugitiveblameAnnotation
hi def link FugitiveblameBoundary Keyword
hi def link FugitiveblameHash Identifier
hi def link FugitiveblameUncommitted Function
hi def link FugitiveblameTime PreProc
hi def link FugitiveblameLineNumber Number
hi def link FugitiveblameOriginalFile String
hi def link FugitiveblameOriginalLineNumber Float
hi def link FugitiveblameShort FugitiveblameDelimiter
hi def link FugitiveblameDelimiter Delimiter
hi def link FugitiveblameNotCommittedYet Comment
endfunction
" }}}1
" File access {{{1
function! s:ReplaceCmd(cmd,...) abort
let fn = bufname('')
let tmp = tempname()
let aw = &autowrite
let prefix = ''
try
if a:0 && a:1 != ''
if &shell =~# 'cmd'
let old_index = $GIT_INDEX_FILE
let $GIT_INDEX_FILE = a:1
elseif &shell =~# 'csh'
let prefix = 'setenv GIT_INDEX_FILE '.s:shellesc(a:1).'; '
else
let prefix = 'GIT_INDEX_FILE='.s:shellesc(a:1).' '
endif
endif
set noautowrite
silent exe '!'.escape(prefix.a:cmd,'%#').' > '.tmp
finally
let &autowrite = aw
if exists('old_index')
let $GIT_INDEX_FILE = old_index
endif
endtry
silent exe 'keepalt file '.tmp
silent edit!
silent exe 'keepalt file '.s:fnameescape(fn)
call delete(tmp)
silent exe 'doau BufReadPost '.s:fnameescape(fn)
endfunction
function! s:BufReadIndex()
if !exists('b:fugitive_display_format')
let b:fugitive_display_format = filereadable(expand('%').'.lock')
endif
let b:fugitive_display_format = b:fugitive_display_format % 2
let b:fugitive_type = 'index'
try
let b:git_dir = s:repo().dir()
setlocal noro ma
if fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : b:git_dir . '/index', ':p') ==# expand('%:p')
let index = ''
else
let index = expand('%:p')
endif
if b:fugitive_display_format
call s:ReplaceCmd(s:repo().git_command('ls-files','--stage'),index)
set ft=git nospell
else
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
call s:ReplaceCmd(s:repo().git_command('status'),index)
finally
execute cd.'`=dir`'
endtry
set ft=gitcommit
endif
setlocal ro noma nomod nomodeline bufhidden=delete
nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += 1<Bar>exe <SID>BufReadIndex()<CR>
nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= 1<Bar>exe <SID>BufReadIndex()<CR>
nnoremap <buffer> <silent> D :<C-U>execute <SID>StageDiff('')<CR>
nnoremap <buffer> <silent> dd :<C-U>execute <SID>StageDiff('')<CR>
nnoremap <buffer> <silent> dh :<C-U>execute <SID>StageDiff('!')<CR>
nnoremap <buffer> <silent> - :<C-U>execute <SID>StageToggle(line('.'),line('.')+v:count1-1)<CR>
xnoremap <buffer> <silent> - :<C-U>execute <SID>StageToggle(line("'<"),line("'>"))<CR>
nnoremap <buffer> <silent> p :<C-U>execute <SID>StagePatch(line('.'),line('.')+v:count1-1)<CR>
xnoremap <buffer> <silent> p :<C-U>execute <SID>StagePatch(line("'<"),line("'>"))<CR>
nnoremap <buffer> <silent> <C-N> :call search('^#\t.*','W')<Bar>.<CR>
nnoremap <buffer> <silent> <C-P> :call search('^#\t.*','Wbe')<Bar>.<CR>
call s:JumpInit()
nunmap <buffer> P
nunmap <buffer> ~
nnoremap <buffer> <silent> C :<C-U>Gcommit<CR>
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
endfunction
function! s:FileRead()
try
let repo = s:repo(s:ExtractGitDir(expand('<amatch>')))
let path = s:sub(s:sub(matchstr(expand('<amatch>'),'fugitive://.\{-\}//\zs.*'),'/',':'),'^\d:',':&')
let hash = repo.rev_parse(path)
if path =~ '^:'
let type = 'blob'
else
let type = repo.git_chomp('cat-file','-t',hash)
endif
" TODO: use count, if possible
return "read !".escape(repo.git_command('cat-file',type,hash),'%#\')
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
endfunction
function! s:BufReadIndexFile()
try
let b:fugitive_type = 'blob'
let b:git_dir = s:repo().dir()
call s:ReplaceCmd(s:repo().git_command('cat-file','blob',s:buffer().sha1()))
return ''
catch /^fugitive: rev-parse/
silent exe 'doau BufNewFile '.s:fnameescape(bufname(''))
return ''
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
endfunction
function! s:BufWriteIndexFile()
let tmp = tempname()
try
let path = matchstr(expand('<amatch>'),'//\d/\zs.*')
let stage = matchstr(expand('<amatch>'),'//\zs\d')
silent execute 'write !'.s:repo().git_command('hash-object','-w','--stdin').' > '.tmp
let sha1 = readfile(tmp)[0]
let old_mode = matchstr(s:repo().git_chomp('ls-files','--stage',path),'^\d\+')
if old_mode == ''
let old_mode = executable(s:repo().tree(path)) ? '100755' : '100644'
endif
let info = old_mode.' '.sha1.' '.stage."\t".path
call writefile([info],tmp)
if has('win32')
let error = system('type '.tmp.'|'.s:repo().git_command('update-index','--index-info'))
else
let error = system(s:repo().git_command('update-index','--index-info').' < '.tmp)
endif
if v:shell_error == 0
setlocal nomodified
silent execute 'doautocmd BufWritePost '.s:fnameescape(expand('%:p'))
call fugitive#reload_status()
return ''
else
return 'echoerr '.string('fugitive: '.error)
endif
finally
call delete(tmp)
endtry
endfunction
function! s:BufReadObject()
try
setlocal noro ma
let b:git_dir = s:repo().dir()
let hash = s:buffer().sha1()
if !exists("b:fugitive_type")
let b:fugitive_type = s:repo().git_chomp('cat-file','-t',hash)
endif
if b:fugitive_type !~# '^\%(tag\|commit\|tree\|blob\)$'
return "echoerr 'fugitive: unrecognized git type'"
endif
let firstline = getline('.')
if !exists('b:fugitive_display_format') && b:fugitive_type != 'blob'
let b:fugitive_display_format = +getbufvar('#','fugitive_display_format')
endif
let pos = getpos('.')
silent %delete
setlocal endofline
if b:fugitive_type == 'tree'
let b:fugitive_display_format = b:fugitive_display_format % 2
if b:fugitive_display_format
call s:ReplaceCmd(s:repo().git_command('ls-tree',hash))
else
call s:ReplaceCmd(s:repo().git_command('show',hash))
endif
elseif b:fugitive_type == 'tag'
let b:fugitive_display_format = b:fugitive_display_format % 2
if b:fugitive_display_format
call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
else
call s:ReplaceCmd(s:repo().git_command('cat-file','-p',hash))
endif
elseif b:fugitive_type == 'commit'
let b:fugitive_display_format = b:fugitive_display_format % 2
if b:fugitive_display_format
call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
else
call s:ReplaceCmd(s:repo().git_command('show','--pretty=format:tree %T%nparent %P%nauthor %an <%ae> %ad%ncommitter %cn <%ce> %cd%nencoding %e%n%n%s%n%n%b',hash))
call search('^parent ')
if getline('.') ==# 'parent '
silent delete_
else
silent s/\%(^parent\)\@<! /\rparent /ge
endif
if search('^encoding \%(<unknown>\)\=$','W',line('.')+3)
silent delete_
end
1
endif
elseif b:fugitive_type ==# 'blob'
call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
endif
call setpos('.',pos)
setlocal ro noma nomod nomodeline
if b:fugitive_type !=# 'blob'
set filetype=git
nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += v:count1<Bar>exe <SID>BufReadObject()<CR>
nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= v:count1<Bar>exe <SID>BufReadObject()<CR>
else
call s:JumpInit()
endif
return ''
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
endfunction
augroup fugitive_files
autocmd!
autocmd BufReadCmd *.git/index exe s:BufReadIndex()
autocmd BufReadCmd *.git/*index*.lock exe s:BufReadIndex()
autocmd FileReadCmd fugitive://**//[0-3]/** exe s:FileRead()
autocmd BufReadCmd fugitive://**//[0-3]/** exe s:BufReadIndexFile()
autocmd BufWriteCmd fugitive://**//[0-3]/** exe s:BufWriteIndexFile()
autocmd BufReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe s:BufReadObject()
autocmd FileReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe s:FileRead()
autocmd FileType git call s:JumpInit()
augroup END
" }}}1
" Go to file {{{1
function! s:JumpInit() abort
nnoremap <buffer> <silent> <CR> :<C-U>exe <SID>GF("edit")<CR>
if !&modifiable
nnoremap <buffer> <silent> o :<C-U>exe <SID>GF("split")<CR>
nnoremap <buffer> <silent> O :<C-U>exe <SID>GF("tabedit")<CR>
nnoremap <buffer> <silent> P :<C-U>exe <SID>Edit('edit',<SID>buffer().commit().'^'.v:count1.<SID>buffer().path(':'))<CR>
nnoremap <buffer> <silent> ~ :<C-U>exe <SID>Edit('edit',<SID>buffer().commit().'~'.v:count1.<SID>buffer().path(':'))<CR>
nnoremap <buffer> <silent> C :<C-U>exe <SID>Edit('edit',<SID>buffer().containing_commit())<CR>
nnoremap <buffer> <silent> cc :<C-U>exe <SID>Edit('edit',<SID>buffer().containing_commit())<CR>
nnoremap <buffer> <silent> co :<C-U>exe <SID>Edit('split',<SID>buffer().containing_commit())<CR>
nnoremap <buffer> <silent> cO :<C-U>exe <SID>Edit('tabedit',<SID>buffer().containing_commit())<CR>
nnoremap <buffer> <silent> cp :<C-U>exe <SID>Edit('pedit',<SID>buffer().containing_commit())<CR>
endif
endfunction
function! s:GF(mode) abort
try
let buffer = s:buffer()
let myhash = buffer.sha1()
if buffer.type('tree')
let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
if showtree && line('.') == 1
return ""
elseif showtree && line('.') > 2
return s:Edit(a:mode,buffer.commit().':'.(buffer.path() == '' ? '' : buffer.path().'/').s:sub(getline('.'),'/$',''))
elseif getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t'
return s:Edit(a:mode,buffer.commit().':'.(buffer.path() == '' ? '' : buffer.path().'/').s:sub(matchstr(getline('.'),'\t\zs.*'),'/$',''))
endif
elseif buffer.type('blob')
let ref = expand("<cfile>")
try
let sha1 = buffer.repo().rev_parse(ref)
catch /^fugitive:/
endtry
if exists('sha1')
return s:Edit(a:mode,ref)
endif
else
" Index
if getline('.') =~# '^\d\{6\} \x\{40\} \d\t'
let ref = matchstr(getline('.'),'\x\{40\}')
let file = ':'.s:sub(matchstr(getline('.'),'\d\t.*'),'\t',':')
return s:Edit(a:mode,file)
elseif getline('.') =~# '^#\trenamed:.* -> '
let file = '/'.matchstr(getline('.'),' -> \zs.*')
return s:Edit(a:mode,file)
elseif getline('.') =~# '^#\t[[:alpha:] ]\+: *.'
let file = '/'.matchstr(getline('.'),': *\zs.*')
return s:Edit(a:mode,file)
elseif getline('.') =~# '^#\t.'
let file = '/'.matchstr(getline('.'),'#\t\zs.*')
return s:Edit(a:mode,file)
elseif getline('.') =~# ': needs merge$'
let file = '/'.matchstr(getline('.'),'.*\ze: needs merge$')
return s:Edit(a:mode,file).'|Gdiff'
elseif getline('.') ==# '# Not currently on any branch.'
return s:Edit(a:mode,'HEAD')
elseif getline('.') =~# '^# On branch '
let file = 'refs/heads/'.getline('.')[12:]
return s:Edit(a:mode,file)
elseif getline('.') =~# "^# Your branch .*'"
let file = matchstr(getline('.'),"'\\zs\\S\\+\\ze'")
return s:Edit(a:mode,file)
endif
let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
if getline('.') =~# '^ref: '
let ref = strpart(getline('.'),5)
elseif getline('.') =~# '^parent \x\{40\}\>'
let ref = matchstr(getline('.'),'\x\{40\}')
let line = line('.')
let parent = 0
while getline(line) =~# '^parent '
let parent += 1
let line -= 1
endwhile
return s:Edit(a:mode,ref)
elseif getline('.') =~ '^tree \x\{40\}$'
let ref = matchstr(getline('.'),'\x\{40\}')
if s:repo().rev_parse(myhash.':') == ref
let ref = myhash.':'
endif
return s:Edit(a:mode,ref)
elseif getline('.') =~# '^object \x\{40\}$' && getline(line('.')+1) =~ '^type \%(commit\|tree\|blob\)$'
let ref = matchstr(getline('.'),'\x\{40\}')
let type = matchstr(getline(line('.')+1),'type \zs.*')
elseif getline('.') =~# '^\l\{3,8\} '.myhash.'$'
return ''
elseif getline('.') =~# '^\l\{3,8\} \x\{40\}\>'
let ref = matchstr(getline('.'),'\x\{40\}')
echoerr "warning: unknown context ".matchstr(getline('.'),'^\l*')
elseif getline('.') =~# '^[+-]\{3\} [ab/]'
let ref = getline('.')[4:]
elseif getline('.') =~# '^rename from '
let ref = 'a/'.getline('.')[12:]
elseif getline('.') =~# '^rename to '
let ref = 'b/'.getline('.')[10:]
elseif getline('.') =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
let dref = matchstr(getline('.'),'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
let ref = matchstr(getline('.'),'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
let dcmd = 'Gdiff'
elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
let line = getline(line('.')-1)
let dref = matchstr(line,'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
let ref = matchstr(line,'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
let dcmd = 'Gdiff!'
elseif line('$') == 1 && getline('.') =~ '^\x\{40\}$'
let ref = getline('.')
else
let ref = ''
endif
if myhash ==# ''
let ref = s:sub(ref,'^a/','HEAD:')
let ref = s:sub(ref,'^b/',':0:')
if exists('dref')
let dref = s:sub(dref,'^a/','HEAD:')
endif
else
let ref = s:sub(ref,'^a/',myhash.'^:')
let ref = s:sub(ref,'^b/',myhash.':')
if exists('dref')
let dref = s:sub(dref,'^a/',myhash.'^:')
endif
endif
if ref ==# '/dev/null'
" Empty blob
let ref = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'
endif
if exists('dref')
return s:Edit(a:mode,ref) . '|'.dcmd.' '.s:fnameescape(dref)
elseif ref != ""
return s:Edit(a:mode,ref)
endif
endif
return ''
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
endfunction
" }}}1
" Statusline {{{1
function! s:repo_head_ref() dict abort
return readfile(s:repo().dir('HEAD'))[0]
endfunction
call s:add_methods('repo',['head_ref'])
function! fugitive#statusline(...)
if !exists('b:git_dir')
return ''
endif
let status = ''
if s:buffer().commit() != ''
let status .= ':' . s:buffer().commit()[0:7]
endif
let head = s:repo().head_ref()
if head =~# '^ref: '
let status .= s:sub(head,'^ref: %(refs/%(heads/|remotes/|tags/)=)=','(').')'
elseif head =~# '^\x\{40\}$'
let status .= '('.head[0:7].')'
endif
if &statusline =~# '%[MRHWY]' && &statusline !~# '%[mrhwy]'
return ',GIT'.status
else
return '[Git'.status.']'
endif
endfunction
function! s:repo_config(conf) dict abort
return matchstr(system(s:repo().git_command('config').' '.a:conf),"[^\r\n]*")
endfun
function! s:repo_user() dict abort
let username = s:repo().config('user.name')
let useremail = s:repo().config('user.email')
return username.' <'.useremail.'>'
endfun
call s:add_methods('repo',['config', 'user'])
" }}}1
" vim:set ft=vim ts=8 sw=2 sts=2:
" guicolorscheme.vim: Convert GUI only color schems
"
" Maintainer: Aaron Griffin <aaron@archlinux.org>
" Last Modified: Mon Feb 26 22:52:34 UTC 2007
" Version: 1.2
" URL: http://www.vim.org/script.php?script_id=39
"
" Convert a GUI-only colorscheme to support 88 and 256 color terminals
" This should also work on the GUI, so using it 100% of the time, assuming
" you always have a non 8/16 color terminal should work fine
" conversion functions {{{
" canibalized from desert256.vim
function! s:greynum(x) "{{{
if &t_Co == 88
if a:x < 23
return 0
elseif a:x < 69
return 1
elseif a:x < 103
return 2
elseif a:x < 127
return 3
elseif a:x < 150
return 4
elseif a:x < 173
return 5
elseif a:x < 196
return 6
elseif a:x < 219
return 7
elseif a:x < 243
return 8
else
return 9
endif
else
if a:x < 14
return 0
else
let l:n = (a:x - 8) / 10
let l:m = (a:x - 8) % 10
if l:m < 5
return l:n
else
return l:n + 1
endif
endif
endif
endfunction "}}}
function! s:greylvl(n) "{{{
if &t_Co == 88
if a:n == 0
return 0
elseif a:n == 1
return 46
elseif a:n == 2
return 92
elseif a:n == 3
return 115
elseif a:n == 4
return 139
elseif a:n == 5
return 162
elseif a:n == 6
return 185
elseif a:n == 7
return 208
elseif a:n == 8
return 231
else
return 255
endif
else
if a:n == 0
return 0
else
return 8 + (a:n * 10)
endif
endif
endfunction "}}}
function! s:grey(n) "{{{
if &t_Co == 88
if a:n == 0
return 16
elseif a:n == 9
return 79
else
return 79 + a:n
endif
else
if a:n == 0
return 16
elseif a:n == 25
return 231
else
return 231 + a:n
endif
endif
endfunction "}}}
function! s:rgbnum(x) "{{{
if &t_Co == 88
if a:x < 69
return 0
elseif a:x < 172
return 1
elseif a:x < 230
return 2
else
return 3
endif
else
if a:x < 75
return 0
else
let l:n = (a:x - 55) / 40
let l:m = (a:x - 55) % 40
if l:m < 20
return l:n
else
return l:n + 1
endif
endif
endif
endfunction "}}}
function! s:rgblvl(n) "{{{
if &t_Co == 88
if a:n == 0
return 0
elseif a:n == 1
return 139
elseif a:n == 2
return 205
else
return 255
endif
else
if a:n == 0
return 0
else
return 55 + (a:n * 40)
endif
endif
endfunction "}}}
function! s:rgb(r, g, b) "{{{
if &t_Co == 88
return 16 + (a:r * 16) + (a:g * 4) + a:b
else
return 16 + (a:r * 36) + (a:g * 6) + a:b
endif
endfunction "}}}
function! s:color(r, g, b) "{{{
" get the closest grey
let l:gx = s:greynum(a:r)
let l:gy = s:greynum(a:g)
let l:gz = s:greynum(a:b)
" get the closest color
let l:x = s:rgbnum(a:r)
let l:y = s:rgbnum(a:g)
let l:z = s:rgbnum(a:b)
let l:level = (a:r * a:r) + (a:g * a:g) + (a:b * a:b)
if l:gx == l:gy && l:gy == l:gz
" there are two possibilities
let l:dgr = s:greylvl(l:gx)
let l:dgg = s:greylvl(l:gy)
let l:dgb = s:greylvl(l:gz)
let l:dgrey = (l:dgr * l:dgr) + (l:dgg * l:dgg) + (l:dgb * l:dgb) - l:level
let l:dr = s:rgblvl(l:gx)
let l:dg = s:rgblvl(l:gy)
let l:db = s:rgblvl(l:gz)
let l:drgb = (l:dr * l:dr) + (l:dg * l:dg) + (l:db * l:db) - l:level
if l:dgrey < l:drgb
" use the grey
return s:grey(l:gx)
else
" use the color
return s:rgb(l:x, l:y, l:z)
endif
else
" only one possibility
return s:rgb(l:x, l:y, l:z)
endif
endfunction "}}}
function! s:cindex(rgb) "{{{
"convert RRGGBB to a terminal (numeric) index
let l:r = ("0x" . strpart(a:rgb, 0, 2)) + 0
let l:g = ("0x" . strpart(a:rgb, 2, 2)) + 0
let l:b = ("0x" . strpart(a:rgb, 4, 2)) + 0
return s:color(l:r, l:g, l:b)
endfunction "}}}
function! s:HL(group, fg, bg, attr) "{{{
"The main highlight (HL) function
exec "hi clear " . a:group
if a:fg != ""
exec "hi " . a:group . " guifg=#" . a:fg . " ctermfg=" . s:cindex(a:fg)
endif
if a:bg != ""
exec "hi " . a:group . " guibg=#" . a:bg . " ctermbg=" . s:cindex(a:bg)
endif
if a:attr != ""
exec "hi " . a:group . " gui=" . a:attr . " cterm=" . a:attr
endif
endfunction "}}}
"}}}
" Completion Helpers {{{
function! s:Colorscheme_Complete(A,L,P)
let l:files = split(globpath(&runtimepath, "colors/" . a:A . "*"), "\n")
let l:retlist = []
for file in l:files
let l:basename = substitute(file, ".*/", "", "")
let l:basename = substitute(l:basename, "\.vim", "", "")
call add(l:retlist, l:basename)
endfor
return l:retlist
endfunction
function! s:GetColorschemeFile(fname)
let l:files = split(globpath(&runtimepath, "colors/" . a:fname . ".vim"), "\n")
if len(l:files) == 0
echoerr "Colorscheme ".a:fname." not found"
return ""
else
return l:files[0]
endif
endfunction
command! -complete=customlist,s:Colorscheme_Complete -nargs=1 GuiColorScheme :call s:GuiColorScheme("<args>")
" }}}
function! s:GuiColorScheme(fname)
let l:file = s:GetColorschemeFile(a:fname)
if l:file == ""
return 1
endif
if has("gui_running")
exec "colorscheme " . l:file
return 0
endif
for line in readfile(l:file)
if line =~ '\s*hi'
let l:name = ""
let l:fg = ""
let l:bg = ""
let l:attr = ""
" get highlight name
let l:start = match(line, "hi")
let l:end = match(line, "[ \t]", l:start)
let l:start = l:end +1
let l:end = match(line, "[ \t]", l:start)
let l:name = strpart(line, l:start, l:end - l:start)
" strip foreground color
let l:start = match(line, "guifg=")
if l:start != -1
let l:start = l:start + 6 "strlen(guifg=)
let l:end = match(line, "[ \t]", l:start)
if l:end == -1
let l:fg = strpart(line, l:start)
else
let l:fg = strpart(line, l:start, l:end - l:start)
endif
if strpart(l:fg, 0, 1) == "#"
let l:fg = strpart(l:fg, 1)
endif
endif
" strip background color
let l:start = match(line, "guibg=")
if l:start != -1
let l:start = l:start + 6 "strlen(guibg=)
let l:end = match(line, "[ \t]", l:start)
if l:end == -1
let l:bg = strpart(line, l:start)
else
let l:bg = strpart(line, l:start, l:end - l:start)
endif
if strpart(l:bg, 0, 1) == "#"
let l:bg = strpart(l:bg, 1)
endif
endif
" strip attribute
let l:start = match(line, "gui=")
if l:start != -1
let l:start = l:start + 4 "strlen(gui=)
let l:end = match(line, "[ \t]", l:start)
if l:end == -1
let l:attr = strpart(line, l:start)
else
let l:attr = strpart(line, l:start, l:end - l:start)
endif
endif
call s:HL(l:name, l:fg, l:bg, l:attr)
endif
endfor
endfunction
" vim:ft=vim:fdl=0:fdm=marker:ts=4:sw=4
" File: snipMate.vim
" Author: Michael Sanders
" Version: 0.84
" 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
" Reset snippets for filetype.
fun! ResetSnippets(ft)
let ft = a:ft == '' ? '_' : a:ft
for dict in [s:snippets, s:multi_snips, g:did_ft]
if has_key(dict, ft)
unlet dict[ft]
endif
endfor
endf
" Reset snippets for all filetypes.
fun! ResetAllSnippets()
let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {}
endf
" Reload snippets for filetype.
fun! ReloadSnippets(ft)
let ft = a:ft == '' ? '_' : a:ft
call ResetSnippets(ft)
call GetSnippets(g:snippets_dir, ft)
endf
" Reload snippets for all filetypes.
fun! ReloadAllSnippets()
for ft in keys(g:did_ft)
call ReloadSnippets(ft)
endfor
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(0) | 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
fun! BackwardsSnippet()
if exists('g:snipPos') | return snipMate#jumpTabStop(1) | endif
if exists('g:SuperTabMappingForward')
if g:SuperTabMappingBackward == "<s-tab>"
let SuperTabKey = "\<c-p>"
elseif g:SuperTabMappingForward == "<s-tab>"
let SuperTabKey = "\<c-n>"
endif
endif
if exists('SuperTabKey')
call feedkeys(SuperTabKey)
return ''
endif
return "\<s-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
if word == '' && a:word != '.' && stridx(a:word, '.') != -1
let [word, snippet] = s:GetSnippet('.', a:scope)
endif
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
" unimpaired.vim - Pairs of handy bracket mappings
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" Version: 1.1
if exists("g:loaded_unimpaired") || &cp || v:version < 700
finish
endif
let g:loaded_unimpaired = 1
let s:cpo_save = &cpo
set cpo&vim
" Next and previous {{{1
function! s:MapNextFamily(map,cmd)
let map = '<Plug>unimpaired'.toupper(a:map)
let end = ' ".(v:count ? v:count : "")<CR>'
execute 'nmap <silent> '.map.'Previous :<C-U>exe "'.a:cmd.'previous'.end
execute 'nmap <silent> '.map.'Next :<C-U>exe "'.a:cmd.'next'.end
execute 'nmap <silent> '.map.'First :<C-U>exe "'.a:cmd.'first'.end
execute 'nmap <silent> '.map.'Last :<C-U>exe "'.a:cmd.'last'.end
execute 'nmap <silent> ['. a:map .' '.map.'Previous'
execute 'nmap <silent> ]'. a:map .' '.map.'Next'
execute 'nmap <silent> ['.toupper(a:map).' '.map.'First'
execute 'nmap <silent> ]'.toupper(a:map).' '.map.'Last'
endfunction
call s:MapNextFamily('a','')
call s:MapNextFamily('b','b')
call s:MapNextFamily('l','l')
call s:MapNextFamily('q','c')
function! s:entries(path)
let path = substitute(a:path,'[\\/]$','','')
let files = split(glob(path."/.*"),"\n")
let files += split(glob(path."/*"),"\n")
call map(files,'substitute(v:val,"[\\/]$","","")')
call filter(files,'v:val !~# "[\\\\/]\\.\\.\\=$"')
call filter(files,'v:val[-4:-1] !=# ".swp" && v:val[-1:-1] !=# "~"')
return files
endfunction
function! s:FileByOffset(num)
let file = expand('%:p')
let num = a:num
while num
let files = s:entries(fnamemodify(file,':h'))
if a:num < 0
call reverse(sort(filter(files,'v:val < file')))
else
call sort(filter(files,'v:val > file'))
endif
let temp = get(files,0,'')
if temp == ''
let file = fnamemodify(file,':h')
else
let file = temp
while isdirectory(file)
let files = s:entries(file)
if files == []
" TODO: walk back up the tree and continue
break
endif
let file = files[num > 0 ? 0 : -1]
endwhile
let num += num > 0 ? -1 : 1
endif
endwhile
return file
endfunction
nnoremap <silent> <Plug>unimpairedONext :<C-U>edit `=<SID>FileByOffset(v:count1)`<CR>
nnoremap <silent> <Plug>unimpairedOPrevious :<C-U>edit `=<SID>FileByOffset(-v:count1)`<CR>
nmap ]o <Plug>unimpairedONext
nmap [o <Plug>unimpairedOPrevious
" }}}1
" Line operations {{{1
nnoremap <silent> <Plug>unimpairedBlankUp :<C-U>put!=repeat(nr2char(10),v:count)<Bar>']+1<CR>
nnoremap <silent> <Plug>unimpairedBlankDown :<C-U>put =repeat(nr2char(10),v:count)<Bar>'[-1<CR>
nmap [<Space> <Plug>unimpairedBlankUp
nmap ]<Space> <Plug>unimpairedBlankDown
nnoremap <silent> <Plug>unimpairedMoveUp :<C-U>exe 'norm m`'<Bar>exe 'move--'.v:count1<CR>``
nnoremap <silent> <Plug>unimpairedMoveDown :<C-U>exe 'norm m`'<Bar>exe 'move+'.v:count1<CR>``
xnoremap <silent> <Plug>unimpairedMoveUp :<C-U>exe 'norm m`'<Bar>exe '''<,''>move--'.v:count1<CR>``
xnoremap <silent> <Plug>unimpairedMoveDown :<C-U>exe 'norm m`'<Bar>exe '''<,''>move''>+'.v:count1<CR>``
nmap [e <Plug>unimpairedMoveUp
nmap ]e <Plug>unimpairedMoveDown
xmap [e <Plug>unimpairedMoveUp
xmap ]e <Plug>unimpairedMoveDown
" }}}1
" Encoding and decoding {{{1
function! s:StringEncode(str)
let map = {"\n": 'n', "\r": 'r', "\t": 't', "\b": 'b', "\f": '\f', '"': '"', '\': '\'}
return substitute(a:str,"[\001-\033\\\\\"]",'\="\\".get(map,submatch(0),printf("%03o",char2nr(submatch(0))))','g')
endfunction
function! s:StringDecode(str)
let map = {'n': "\n", 'r': "\r", 't': "\t", 'b': "\b", 'f': "\f", 'e': "\e", 'a': "\001", 'v': "\013", '"': '"', '\': '\', "'": "'"}
let str = a:str
if str =~ '^\s*".\{-\}\\\@<!\%(\\\\\)*"\s*\n\=$'
let str = substitute(substitute(str,'^\s*\zs"','',''),'"\ze\s*\n\=$','','')
endif
let str = substitute(str,'\\n\%(\n$\)\=','\n','g')
return substitute(str,'\\\(\o\{1,3\}\|x\x\{1,2\}\|u\x\{1,4\}\|.\)','\=get(map,submatch(1),nr2char("0".substitute(submatch(1),"^[Uu]","x","")))','g')
endfunction
function! s:UrlEncode(str)
return substitute(a:str,'[^A-Za-z0-9_.~-]','\="%".printf("%02X",char2nr(submatch(0)))','g')
endfunction
function! s:UrlDecode(str)
let str = substitute(substitute(substitute(a:str,'%0[Aa]\n$','%0A',''),'%0[Aa]','\n','g'),'+',' ','g')
return substitute(str,'%\(\x\x\)','\=nr2char("0x".submatch(1))','g')
endfunction
" HTML entities {{{2
let g:unimpaired_html_entities = {
\ 'nbsp': 160, 'iexcl': 161, 'cent': 162, 'pound': 163,
\ 'curren': 164, 'yen': 165, 'brvbar': 166, 'sect': 167,
\ 'uml': 168, 'copy': 169, 'ordf': 170, 'laquo': 171,
\ 'not': 172, 'shy': 173, 'reg': 174, 'macr': 175,
\ 'deg': 176, 'plusmn': 177, 'sup2': 178, 'sup3': 179,
\ 'acute': 180, 'micro': 181, 'para': 182, 'middot': 183,
\ 'cedil': 184, 'sup1': 185, 'ordm': 186, 'raquo': 187,
\ 'frac14': 188, 'frac12': 189, 'frac34': 190, 'iquest': 191,
\ 'Agrave': 192, 'Aacute': 193, 'Acirc': 194, 'Atilde': 195,
\ 'Auml': 196, 'Aring': 197, 'AElig': 198, 'Ccedil': 199,
\ 'Egrave': 200, 'Eacute': 201, 'Ecirc': 202, 'Euml': 203,
\ 'Igrave': 204, 'Iacute': 205, 'Icirc': 206, 'Iuml': 207,
\ 'ETH': 208, 'Ntilde': 209, 'Ograve': 210, 'Oacute': 211,
\ 'Ocirc': 212, 'Otilde': 213, 'Ouml': 214, 'times': 215,
\ 'Oslash': 216, 'Ugrave': 217, 'Uacute': 218, 'Ucirc': 219,
\ 'Uuml': 220, 'Yacute': 221, 'THORN': 222, 'szlig': 223,
\ 'agrave': 224, 'aacute': 225, 'acirc': 226, 'atilde': 227,
\ 'auml': 228, 'aring': 229, 'aelig': 230, 'ccedil': 231,
\ 'egrave': 232, 'eacute': 233, 'ecirc': 234, 'euml': 235,
\ 'igrave': 236, 'iacute': 237, 'icirc': 238, 'iuml': 239,
\ 'eth': 240, 'ntilde': 241, 'ograve': 242, 'oacute': 243,
\ 'ocirc': 244, 'otilde': 245, 'ouml': 246, 'divide': 247,
\ 'oslash': 248, 'ugrave': 249, 'uacute': 250, 'ucirc': 251,
\ 'uuml': 252, 'yacute': 253, 'thorn': 254, 'yuml': 255,
\ 'OElig': 338, 'oelig': 339, 'Scaron': 352, 'scaron': 353,
\ 'Yuml': 376, 'circ': 710, 'tilde': 732, 'ensp': 8194,
\ 'emsp': 8195, 'thinsp': 8201, 'zwnj': 8204, 'zwj': 8205,
\ 'lrm': 8206, 'rlm': 8207, 'ndash': 8211, 'mdash': 8212,
\ 'lsquo': 8216, 'rsquo': 8217, 'sbquo': 8218, 'ldquo': 8220,
\ 'rdquo': 8221, 'bdquo': 8222, 'dagger': 8224, 'Dagger': 8225,
\ 'permil': 8240, 'lsaquo': 8249, 'rsaquo': 8250, 'euro': 8364,
\ 'fnof': 402, 'Alpha': 913, 'Beta': 914, 'Gamma': 915,
\ 'Delta': 916, 'Epsilon': 917, 'Zeta': 918, 'Eta': 919,
\ 'Theta': 920, 'Iota': 921, 'Kappa': 922, 'Lambda': 923,
\ 'Mu': 924, 'Nu': 925, 'Xi': 926, 'Omicron': 927,
\ 'Pi': 928, 'Rho': 929, 'Sigma': 931, 'Tau': 932,
\ 'Upsilon': 933, 'Phi': 934, 'Chi': 935, 'Psi': 936,
\ 'Omega': 937, 'alpha': 945, 'beta': 946, 'gamma': 947,
\ 'delta': 948, 'epsilon': 949, 'zeta': 950, 'eta': 951,
\ 'theta': 952, 'iota': 953, 'kappa': 954, 'lambda': 955,
\ 'mu': 956, 'nu': 957, 'xi': 958, 'omicron': 959,
\ 'pi': 960, 'rho': 961, 'sigmaf': 962, 'sigma': 963,
\ 'tau': 964, 'upsilon': 965, 'phi': 966, 'chi': 967,
\ 'psi': 968, 'omega': 969, 'thetasym': 977, 'upsih': 978,
\ 'piv': 982, 'bull': 8226, 'hellip': 8230, 'prime': 8242,
\ 'Prime': 8243, 'oline': 8254, 'frasl': 8260, 'weierp': 8472,
\ 'image': 8465, 'real': 8476, 'trade': 8482, 'alefsym': 8501,
\ 'larr': 8592, 'uarr': 8593, 'rarr': 8594, 'darr': 8595,
\ 'harr': 8596, 'crarr': 8629, 'lArr': 8656, 'uArr': 8657,
\ 'rArr': 8658, 'dArr': 8659, 'hArr': 8660, 'forall': 8704,
\ 'part': 8706, 'exist': 8707, 'empty': 8709, 'nabla': 8711,
\ 'isin': 8712, 'notin': 8713, 'ni': 8715, 'prod': 8719,
\ 'sum': 8721, 'minus': 8722, 'lowast': 8727, 'radic': 8730,
\ 'prop': 8733, 'infin': 8734, 'ang': 8736, 'and': 8743,
\ 'or': 8744, 'cap': 8745, 'cup': 8746, 'int': 8747,
\ 'there4': 8756, 'sim': 8764, 'cong': 8773, 'asymp': 8776,
\ 'ne': 8800, 'equiv': 8801, 'le': 8804, 'ge': 8805,
\ 'sub': 8834, 'sup': 8835, 'nsub': 8836, 'sube': 8838,
\ 'supe': 8839, 'oplus': 8853, 'otimes': 8855, 'perp': 8869,
\ 'sdot': 8901, 'lceil': 8968, 'rceil': 8969, 'lfloor': 8970,
\ 'rfloor': 8971, 'lang': 9001, 'rang': 9002, 'loz': 9674,
\ 'spades': 9824, 'clubs': 9827, 'hearts': 9829, 'diams': 9830,
\ 'apos': 39}
" }}}2
function! s:XmlEncode(str)
let str = a:str
let str = substitute(str,'&','\&amp;','g')
let str = substitute(str,'<','\&lt;','g')
let str = substitute(str,'>','\&gt;','g')
let str = substitute(str,'"','\&quot;','g')
return str
endfunction
function! s:XmlEntityDecode(str)
let str = substitute(a:str,'\c&#\%(0*38\|x0*26\);','&amp;','g')
let str = substitute(str,'\c&#\(\d\+\);','\=nr2char(submatch(1))','g')
let str = substitute(str,'\c&#\(x\x\+\);','\=nr2char("0".submatch(1))','g')
let str = substitute(str,'\c&apos;',"'",'g')
let str = substitute(str,'\c&quot;','"','g')
let str = substitute(str,'\c&gt;','>','g')
let str = substitute(str,'\c&lt;','<','g')
let str = substitute(str,'\C&\(\%(amp;\)\@!\w*\);','\=nr2char(get(g:unimpaired_html_entities,submatch(1),63))','g')
return substitute(str,'\c&amp;','\&','g')
endfunction
function! s:XmlDecode(str)
let str = substitute(a:str,'<\%([[:alnum:]-]\+=\%("[^"]*"\|''[^'']*''\)\|.\)\{-\}>','','g')
return s:XmlEntityDecode(str)
endfunction
function! s:Transform(algorithm,type)
let sel_save = &selection
let cb_save = &clipboard
set selection=inclusive clipboard-=unnamed
let reg_save = @@
if a:type =~ '^\d\+$'
silent exe 'norm! ^v'.a:type.'$hy'
elseif a:type =~ '^.$'
silent exe "normal! `<" . a:type . "`>y"
elseif a:type == 'line'
silent exe "normal! '[V']y"
elseif a:type == 'block'
silent exe "normal! `[\<C-V>`]y"
else
silent exe "normal! `[v`]y"
endif
let @@ = s:{a:algorithm}(@@)
norm! gvp
let @@ = reg_save
let &selection = sel_save
let &clipboard = cb_save
if a:type =~ '^\d\+$'
silent! call repeat#set("\<Plug>unimpairedLine".a:algorithm,a:type)
endif
endfunction
function! s:TransformOpfunc(type)
return s:Transform(s:encode_algorithm, a:type)
endfunction
function! s:TransformSetup(algorithm)
let s:encode_algorithm = a:algorithm
let &opfunc = matchstr(expand('<sfile>'), '<SNR>\d\+_').'TransformOpfunc'
endfunction
function! s:MapTransform(algorithm, key)
exe 'nnoremap <silent> <Plug>unimpaired' .a:algorithm.' :<C-U>call <SID>TransformSetup("'.a:algorithm.'")<CR>g@'
exe 'xnoremap <silent> <Plug>unimpaired' .a:algorithm.' :<C-U>call <SID>Transform("'.a:algorithm.'",visualmode())<CR>'
exe 'nnoremap <silent> <Plug>unimpairedLine'.a:algorithm.' :<C-U>call <SID>Transform("'.a:algorithm.'",v:count1)<CR>'
exe 'nmap '.a:key.' <Plug>unimpaired'.a:algorithm
exe 'xmap '.a:key.' <Plug>unimpaired'.a:algorithm
exe 'nmap '.a:key.a:key[strlen(a:key)-1].' <Plug>unimpairedLine'.a:algorithm
endfunction
call s:MapTransform('StringEncode','[y')
call s:MapTransform('StringDecode',']y')
call s:MapTransform('UrlEncode','[u')
call s:MapTransform('UrlDecode',']u')
call s:MapTransform('XmlEncode','[x')
call s:MapTransform('XmlDecode',']x')
" }}}1
let &cpo = s:cpo_save
" vim:set ft=vim ts=8 sw=2 sts=2:
SHELL = /bin/sh
#### Start of system configuration section. ####
srcdir = .
topdir = /usr/lib/ruby/1.8/i686-linux
hdrdir = $(topdir)
VPATH = $(srcdir):$(topdir):$(hdrdir)
prefix = $(DESTDIR)/usr
exec_prefix = $(prefix)
oldincludedir = $(DESTDIR)/usr/include
localstatedir = $(DESTDIR)/var
localedir = $(datarootdir)/locale
pdfdir = $(docdir)
libdir = $(exec_prefix)/lib
sbindir = $(exec_prefix)/sbin
sitearchdir = $(sitelibdir)/$(sitearch)
vendorlibdir = $(vendordir)/$(ruby_version)
datarootdir = $(prefix)/share
docdir = $(datarootdir)/doc/$(PACKAGE)
sitelibdir = $(sitedir)/$(ruby_version)
sitedir = $(DESTDIR)/usr/local/lib/site_ruby
sharedstatedir = $(prefix)/com
dvidir = $(docdir)
psdir = $(docdir)
libexecdir = $(prefix)/lib/ruby1.8
archdir = $(rubylibdir)/$(arch)
includedir = $(prefix)/include
vendorarchdir = $(vendorlibdir)/$(sitearch)
sysconfdir = $(DESTDIR)/etc
bindir = $(exec_prefix)/bin
htmldir = $(docdir)
mandir = $(prefix)/share/man
datadir = $(datarootdir)
rubylibdir = $(libdir)/ruby/$(ruby_version)
vendordir = $(libdir)/ruby/vendor_ruby
infodir = $(prefix)/share/info
CC = gcc
LIBRUBY = $(LIBRUBY_SO)
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
RUBY_EXTCONF_H =
CFLAGS = -fPIC -fno-strict-aliasing -g -g -O2 -fPIC $(cflags)
INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
DEFS = -D_FILE_OFFSET_BITS=64 -DWATCHMAN_BUILD
CPPFLAGS = -DHAVE_FCNTL_H -DHAVE_SYS_ERRNO_H -DHAVE_SYS_SOCKET_H -DHAVE_ST_H -D_FORTIFY_SOURCE=2 $(DEFS) $(cppflags)
CXXFLAGS = $(CFLAGS)
ldflags = -L. -Wl,-Bsymbolic-functions -Wl,-z,relro -rdynamic -Wl,-export-dynamic
dldflags =
archflag =
DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
LDSHARED = $(CC) -shared
AR = ar
EXEEXT =
RUBY_INSTALL_NAME = ruby1.8
RUBY_SO_NAME = ruby1.8
arch = i686-linux
sitearch = i686-linux
ruby_version = 1.8
ruby = /usr/bin/ruby1.8
RUBY = $(ruby)
RM = rm -f
MAKEDIRS = mkdir -p
INSTALL = /usr/bin/install -c
INSTALL_PROG = $(INSTALL) -m 0755
INSTALL_DATA = $(INSTALL) -m 644
COPY = cp
#### End of system configuration section. ####
preload =
libpath = . $(libdir)
LIBPATH = -L. -L$(libdir)
DEFFILE =
CLEANFILES = mkmf.log
DISTCLEANFILES =
extout =
extout_prefix =
target_prefix =
LOCAL_LIBS =
LIBS = $(LIBRUBYARG_SHARED) -lpthread -lrt -ldl -lcrypt -lm -lc
SRCS = watchman.c match.c matcher.c ext.c
OBJS = watchman.o match.o matcher.o ext.o
TARGET = ext
DLLIB = $(TARGET).so
EXTSTATIC =
STATIC_LIB =
BINDIR = $(bindir)
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
TARGET_SO = $(DLLIB)
CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map
CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
all: $(DLLIB)
static: $(STATIC_LIB)
clean:
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
distclean: clean
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
realclean: distclean
install: install-so install-rb
install-so: $(RUBYARCHDIR)
install-so: $(RUBYARCHDIR)/$(DLLIB)
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
install-rb: pre-install-rb install-rb-default
install-rb-default: pre-install-rb-default
pre-install-rb: Makefile
pre-install-rb-default: Makefile
$(RUBYARCHDIR):
$(MAKEDIRS) $@
site-install: site-install-so site-install-rb
site-install-so: install-so
site-install-rb: install-rb
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
.cc.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cxx.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cpp.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.C.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.c.o:
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
$(DLLIB): $(OBJS) Makefile
@-$(RM) $@
$(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
###
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
CFLAGS += -Wall -Wextra -Wno-unused-parameter
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/finder/buffer_finder'
require 'command-t/finder/jump_finder'
require 'command-t/finder/file_finder'
require 'command-t/finder/tag_finder'
require 'command-t/match_window'
require 'command-t/prompt'
require 'command-t/vim/path_utilities'
require 'command-t/util'
module CommandT
class Controller
include VIM::PathUtilities
def initialize
@prompt = Prompt.new
end
def show_buffer_finder
@path = VIM::pwd
@active_finder = buffer_finder
show
end
def show_jump_finder
@path = VIM::pwd
@active_finder = jump_finder
show
end
def show_tag_finder
@path = VIM::pwd
@active_finder = tag_finder
show
end
def show_file_finder
# optional parameter will be desired starting directory, or ""
@path = File.expand_path(::VIM::evaluate('a:arg'), VIM::pwd)
@active_finder = file_finder
file_finder.path = @path
show
rescue Errno::ENOENT
# probably a problem with the optional parameter
@match_window.print_no_such_file_or_directory
end
def hide
@match_window.close
if VIM::Window.select @initial_window
if @initial_buffer.number == 0
# upstream bug: buffer number misreported as 0
# see: https://wincent.com/issues/1617
::VIM::command "silent b #{@initial_buffer.name}"
else
::VIM::command "silent b #{@initial_buffer.number}"
end
end
end
# Take current matches and stick them in the quickfix window.
def quickfix
hide
matches = @matches.map do |match|
"{ 'filename': '#{VIM::escape_for_single_quotes match}' }"
end.join(', ')
::VIM::command 'call setqflist([' + matches + '])'
::VIM::command 'cope'
end
def refresh
return unless @active_finder && @active_finder.respond_to?(:flush)
@active_finder.flush
list_matches!
end
def flush
@max_height = nil
@min_height = nil
@file_finder = nil
@tag_finder = nil
end
def handle_key
key = ::VIM::evaluate('a:arg').to_i.chr
if @focus == @prompt
@prompt.add! key
@needs_update = true
else
@match_window.find key
end
end
def backspace
if @focus == @prompt
@prompt.backspace!
@needs_update = true
end
end
def delete
if @focus == @prompt
@prompt.delete!
@needs_update = true
end
end
def accept_selection options = {}
selection = @match_window.selection
hide
open_selection(selection, options) unless selection.nil?
end
def toggle_focus
@focus.unfocus # old focus
@focus = @focus == @prompt ? @match_window : @prompt
@focus.focus # new focus
end
def cancel
hide
end
def select_next
@match_window.select_next
end
def select_prev
@match_window.select_prev
end
def clear
@prompt.clear!
list_matches!
end
def cursor_left
@prompt.cursor_left if @focus == @prompt
end
def cursor_right
@prompt.cursor_right if @focus == @prompt
end
def cursor_end
@prompt.cursor_end if @focus == @prompt
end
def cursor_start
@prompt.cursor_start if @focus == @prompt
end
def leave
@match_window.leave
end
def unload
@match_window.unload
end
def list_matches(options = {})
return unless @needs_update || options[:force]
@matches = @active_finder.sorted_matches_for(
@prompt.abbrev,
:limit => match_limit,
:threads => CommandT::Util.processor_count
)
@match_window.matches = @matches
@needs_update = false
end
private
def list_matches!
list_matches(:force => true)
end
def show
@initial_window = $curwin
@initial_buffer = $curbuf
@match_window = MatchWindow.new \
:highlight_color => get_string('g:CommandTHighlightColor'),
:match_window_at_top => get_bool('g:CommandTMatchWindowAtTop'),
:match_window_reverse => get_bool('g:CommandTMatchWindowReverse'),
:min_height => min_height,
:debounce_interval => get_number('g:CommandTInputDebounce', 50),
:prompt => @prompt
@focus = @prompt
@prompt.focus
register_for_key_presses
set_up_autocmds
clear # clears prompt and lists matches
end
def max_height
@max_height ||= get_number('g:CommandTMaxHeight', 0)
end
def min_height
@min_height ||= begin
min_height = get_number('g:CommandTMinHeight', 0)
min_height = max_height if max_height != 0 && min_height > max_height
min_height
end
end
def get_number(name, default = nil)
VIM::exists?(name) ? ::VIM::evaluate("#{name}").to_i : default
end
def get_bool(name)
VIM::exists?(name) ? ::VIM::evaluate("#{name}").to_i != 0 : nil
end
def get_string(name)
VIM::exists?(name) ? ::VIM::evaluate("#{name}").to_s : nil
end
# expect a string or a list of strings
def get_list_or_string name
return nil unless VIM::exists?(name)
list_or_string = ::VIM::evaluate("#{name}")
if list_or_string.kind_of?(Array)
list_or_string.map { |item| item.to_s }
else
list_or_string.to_s
end
end
# Backslash-escape space, \, |, %, #, "
def sanitize_path_string str
# for details on escaping command-line mode arguments see: :h :
# (that is, help on ":") in the Vim documentation.
str.gsub(/[ \\|%#"]/, '\\\\\0')
end
def default_open_command
if !get_bool('&hidden') && get_bool('&modified')
'sp'
else
'e'
end
end
def ensure_appropriate_window_selection
# normally we try to open the selection in the current window, but there
# is one exception:
#
# - we don't touch any "unlisted" buffer with buftype "nofile" (such as
# NERDTree or MiniBufExplorer); this is to avoid things like the "Not
# enough room" error which occurs when trying to open in a split in a
# shallow (potentially 1-line) buffer like MiniBufExplorer is current
#
# Other "unlisted" buffers, such as those with buftype "help" are treated
# normally.
initial = $curwin
while true do
break unless ::VIM::evaluate('&buflisted').to_i == 0 &&
::VIM::evaluate('&buftype').to_s == 'nofile'
::VIM::command 'wincmd w' # try next window
break if $curwin == initial # have already tried all
end
end
def open_selection selection, options = {}
command = options[:command] || default_open_command
selection = File.expand_path selection, @path
selection = relative_path_under_working_directory selection
selection = sanitize_path_string selection
selection = File.join('.', selection) if selection =~ /^\+/
ensure_appropriate_window_selection
@active_finder.open_selection command, selection, options
end
def map key, function, param = nil
::VIM::command "noremap <silent> <buffer> #{key} " \
":call CommandT#{function}(#{param})<CR>"
end
def term
@term ||= ::VIM::evaluate('&term')
end
def register_for_key_presses
# "normal" keys (interpreted literally)
numbers = ('0'..'9').to_a.join
lowercase = ('a'..'z').to_a.join
uppercase = lowercase.upcase
punctuation = '<>`@#~!"$%&/()=+*-_.,;:?\\\'{}[] ' # and space
(numbers + lowercase + uppercase + punctuation).each_byte do |b|
map "<Char-#{b}>", 'HandleKey', b
end
# "special" keys (overridable by settings)
{
'AcceptSelection' => '<CR>',
'AcceptSelectionSplit' => ['<C-CR>', '<C-s>'],
'AcceptSelectionTab' => '<C-t>',
'AcceptSelectionVSplit' => '<C-v>',
'Backspace' => '<BS>',
'Cancel' => ['<C-c>', '<Esc>'],
'Clear' => '<C-u>',
'CursorEnd' => '<C-e>',
'CursorLeft' => ['<Left>', '<C-h>'],
'CursorRight' => ['<Right>', '<C-l>'],
'CursorStart' => '<C-a>',
'Delete' => '<Del>',
'Quickfix' => '<C-q>',
'Refresh' => '<C-f>',
'SelectNext' => ['<C-n>', '<C-j>', '<Down>'],
'SelectPrev' => ['<C-p>', '<C-k>', '<Up>'],
'ToggleFocus' => '<Tab>',
}.each do |key, value|
if override = get_list_or_string("g:CommandT#{key}Map")
Array(override).each do |mapping|
map mapping, key
end
else
Array(value).each do |mapping|
unless mapping == '<Esc>' && term =~ /\A(screen|xterm|vt100)/
map mapping, key
end
end
end
end
end
def set_up_autocmds
::VIM::command 'augroup Command-T'
::VIM::command 'au!'
::VIM::command 'autocmd CursorHold <buffer> :call CommandTListMatches()'
::VIM::command 'augroup END'
end
# Returns the desired maximum number of matches, based on available
# vertical space and the g:CommandTMaxHeight option.
def match_limit
limit = VIM::Screen.lines - 5
limit = 1 if limit < 0
limit = [limit, max_height].min if max_height > 0
limit
end
def buffer_finder
@buffer_finder ||= CommandT::BufferFinder.new
end
def file_finder
@file_finder ||= CommandT::FileFinder.new nil,
:max_depth => get_number('g:CommandTMaxDepth'),
:max_files => get_number('g:CommandTMaxFiles'),
:max_caches => get_number('g:CommandTMaxCachedDirectories'),
:always_show_dot_files => get_bool('g:CommandTAlwaysShowDotFiles'),
:never_show_dot_files => get_bool('g:CommandTNeverShowDotFiles'),
:scan_dot_directories => get_bool('g:CommandTScanDotDirectories'),
:wild_ignore => get_string('g:CommandTWildIgnore'),
:scanner => get_string('g:CommandTFileScanner')
end
def jump_finder
@jump_finder ||= CommandT::JumpFinder.new
end
def tag_finder
@tag_finder ||= CommandT::TagFinder.new \
:include_filenames => get_bool('g:CommandTTagIncludeFilenames')
end
end # class Controller
end # module commandT
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
CFLAGS += -Wall -Wextra -Wno-unused-parameter
// Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include "matcher.h"
#include "watchman.h"
VALUE mCommandT = 0; // module CommandT
VALUE cCommandTMatcher = 0; // class CommandT::Matcher
VALUE mCommandTWatchman = 0; // module CommandT::Watchman
VALUE mCommandTWatchmanUtils = 0; // module CommandT::Watchman::Utils
VALUE CommandT_option_from_hash(const char *option, VALUE hash)
{
VALUE key;
if (NIL_P(hash))
return Qnil;
key = ID2SYM(rb_intern(option));
if (rb_funcall(hash, rb_intern("has_key?"), 1, key) == Qtrue)
return rb_hash_aref(hash, key);
else
return Qnil;
}
void Init_ext()
{
// module CommandT
mCommandT = rb_define_module("CommandT");
// class CommandT::Matcher
cCommandTMatcher = rb_define_class_under(mCommandT, "Matcher", rb_cObject);
rb_define_method(cCommandTMatcher, "initialize", CommandTMatcher_initialize, -1);
rb_define_method(cCommandTMatcher, "sorted_matches_for", CommandTMatcher_sorted_matches_for, -1);
// module CommandT::Watchman::Utils
mCommandTWatchman = rb_define_module_under(mCommandT, "Watchman");
mCommandTWatchmanUtils = rb_define_module_under(mCommandTWatchman, "Utils");
rb_define_singleton_method(mCommandTWatchmanUtils, "load", CommandTWatchmanUtils_load, 1);
rb_define_singleton_method(mCommandTWatchmanUtils, "dump", CommandTWatchmanUtils_dump, 1);
rb_define_singleton_method(mCommandTWatchmanUtils, "query", CommandTWatchmanUtils_query, 2);
}
// Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include <ruby.h>
extern VALUE mCommandT; // module CommandT
extern VALUE cCommandTMatcher; // class CommandT::Matcher
extern VALUE mCommandTWatchman; // module CommandT::Watchman
extern VALUE mCommandTWatchmanUtils; // module CommandT::Watchman::Utils
// Encapsulates common pattern of checking for an option in an optional
// options hash. The hash itself may be nil, but an exception will be
// raised if it is not nil and not a hash.
VALUE CommandT_option_from_hash(const char *option, VALUE hash);
// Debugging macro.
#define ruby_inspect(obj) rb_funcall(rb_mKernel, rb_intern("p"), 1, obj)
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'mkmf'
def header(item)
unless find_header(item)
puts "couldn't find #{item} (required)"
exit 1
end
end
# mandatory headers
header('float.h')
header('ruby.h')
header('stdlib.h')
header('string.h')
# optional headers (for CommandT::Watchman::Utils)
if have_header('fcntl.h') &&
have_header('sys/errno.h') &&
have_header('sys/socket.h')
RbConfig::MAKEFILE_CONFIG['DEFS'] += ' -DWATCHMAN_BUILD'
have_header('ruby/st.h') # >= 1.9; sets HAVE_RUBY_ST_H
have_header('st.h') # 1.8; sets HAVE_ST_H
end
# optional
if RbConfig::CONFIG['THREAD_MODEL'] == 'pthread'
have_library('pthread', 'pthread_create') # sets HAVE_PTHREAD_H if found
end
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
create_makefile('ext')
# Copyright 2010-2012 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/ext' # CommandT::Matcher
module CommandT
# Encapsulates a Scanner instance (which builds up a list of available files
# in a directory) and a Matcher instance (which selects from that list based
# on a search string).
#
# Specialized subclasses use different kinds of scanners adapted for
# different kinds of search (files, buffers).
class Finder
include VIM::PathUtilities
def initialize path = Dir.pwd, options = {}
raise RuntimeError, 'Subclass responsibility'
end
# Options:
# :limit (integer): limit the number of returned matches
def sorted_matches_for str, options = {}
@matcher.sorted_matches_for str, options
end
def open_selection command, selection, options = {}
::VIM::command "silent #{command} #{selection}"
end
def path= path
@scanner.path = path
end
end # class Finder
end # CommandT
# Copyright 2010-2011 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/ext' # CommandT::Matcher
require 'command-t/scanner/buffer_scanner'
require 'command-t/finder'
module CommandT
class BufferFinder < Finder
def initialize
@scanner = BufferScanner.new
@matcher = Matcher.new @scanner, :always_show_dot_files => true
end
end # class BufferFinder
end # CommandT
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/ext' # CommandT::Matcher
require 'command-t/finder'
require 'command-t/scanner/file_scanner/ruby_file_scanner'
require 'command-t/scanner/file_scanner/find_file_scanner'
require 'command-t/scanner/file_scanner/watchman_file_scanner'
module CommandT
class FileFinder < Finder
def initialize(path = Dir.pwd, options = {})
case options.delete(:scanner)
when 'ruby', nil # ruby is the default
@scanner = FileScanner::RubyFileScanner.new(path, options)
when 'find'
@scanner = FileScanner::FindFileScanner.new(path, options)
when 'watchman'
@scanner = FileScanner::WatchmanFileScanner.new(path, options)
else
raise ArgumentError, "unknown scanner type '#{options[:scanner]}'"
end
@matcher = Matcher.new @scanner, options
end
def flush
@scanner.flush
end
end # class FileFinder
end # module CommandT
# Copyright 2011 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/ext' # CommandT::Matcher
require 'command-t/scanner/jump_scanner'
require 'command-t/finder'
module CommandT
class JumpFinder < Finder
def initialize
@scanner = JumpScanner.new
@matcher = Matcher.new @scanner, :always_show_dot_files => true
end
end # class JumpFinder
end # module CommandT
# Copyright 2011-2012 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/ext' # CommandT::Matcher
require 'command-t/scanner/tag_scanner'
require 'command-t/finder'
module CommandT
class TagFinder < Finder
def initialize options = {}
@scanner = TagScanner.new options
@matcher = Matcher.new @scanner, :always_show_dot_files => true
end
def open_selection command, selection, options = {}
if @scanner.include_filenames
selection = selection[0, selection.index(':')]
end
# open the tag and center the screen on it
::VIM::command "silent! tag #{selection} | :normal zz"
end
end # class TagFinder
end # module CommandT
// Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include <float.h> /* for DBL_MAX */
#include "match.h"
#include "ext.h"
#include "ruby_compat.h"
// use a struct to make passing params during recursion easier
typedef struct {
char *haystack_p; // pointer to the path string to be searched
long haystack_len; // length of same
char *needle_p; // pointer to search string (needle)
long needle_len; // length of same
double max_score_per_char;
int dot_file; // boolean: true if str is a dot-file
int always_show_dot_files; // boolean
int never_show_dot_files; // boolean
double *memo; // memoization
} matchinfo_t;
double recursive_match(matchinfo_t *m, // sharable meta-data
long haystack_idx, // where in the path string to start
long needle_idx, // where in the needle string to start
long last_idx, // location of last matched character
double score) // cumulative score so far
{
double seen_score = 0; // remember best score seen via recursion
int dot_file_match = 0; // true if needle matches a dot-file
int dot_search = 0; // true if searching for a dot
long i, j, distance;
int found;
double score_for_char;
// do we have a memoized result we can return?
double memoized = m->memo[needle_idx * m->needle_len + haystack_idx];
if (memoized != DBL_MAX)
return memoized;
// bail early if not enough room (left) in haystack for (rest of) needle
if (m->haystack_len - haystack_idx < m->needle_len - needle_idx) {
score = 0.0;
goto memoize;
}
for (i = needle_idx; i < m->needle_len; i++) {
char c = m->needle_p[i];
if (c == '.')
dot_search = 1;
found = 0;
// similar to above, we'll stop iterating when we know we're too close
// to the end of the string to possibly match
for (j = haystack_idx;
j <= m->haystack_len - (m->needle_len - i);
j++, haystack_idx++) {
char d = m->haystack_p[j];
if (d == '.') {
if (j == 0 || m->haystack_p[j - 1] == '/') {
m->dot_file = 1; // this is a dot-file
if (dot_search) // and we are searching for a dot
dot_file_match = 1; // so this must be a match
}
} else if (d >= 'A' && d <= 'Z') {
d += 'a' - 'A'; // add 32 to downcase
}
if (c == d) {
found = 1;
dot_search = 0;
// calculate score
score_for_char = m->max_score_per_char;
distance = j - last_idx;
if (distance > 1) {
double factor = 1.0;
char last = m->haystack_p[j - 1];
char curr = m->haystack_p[j]; // case matters, so get again
if (last == '/')
factor = 0.9;
else if (last == '-' ||
last == '_' ||
last == ' ' ||
(last >= '0' && last <= '9'))
factor = 0.8;
else if (last >= 'a' && last <= 'z' &&
curr >= 'A' && curr <= 'Z')
factor = 0.8;
else if (last == '.')
factor = 0.7;
else
// if no "special" chars behind char, factor diminishes
// as distance from last matched char increases
factor = (1.0 / distance) * 0.75;
score_for_char *= factor;
}
if (++j < m->haystack_len) {
// bump cursor one char to the right and
// use recursion to try and find a better match
double sub_score = recursive_match(m, j, i, last_idx, score);
if (sub_score > seen_score)
seen_score = sub_score;
}
score += score_for_char;
last_idx = haystack_idx + 1;
break;
}
}
if (!found) {
score = 0.0;
goto memoize;
}
}
if (m->dot_file &&
(m->never_show_dot_files ||
(!dot_file_match && !m->always_show_dot_files))) {
score = 0.0;
goto memoize;
}
score = score > seen_score ? score : seen_score;
memoize:
m->memo[needle_idx * m->needle_len + haystack_idx] = score;
return score;
}
void calculate_match(VALUE str,
VALUE needle,
VALUE always_show_dot_files,
VALUE never_show_dot_files,
match_t *out)
{
long i, max;
double score;
matchinfo_t m;
m.haystack_p = RSTRING_PTR(str);
m.haystack_len = RSTRING_LEN(str);
m.needle_p = RSTRING_PTR(needle);
m.needle_len = RSTRING_LEN(needle);
m.max_score_per_char = (1.0 / m.haystack_len + 1.0 / m.needle_len) / 2;
m.dot_file = 0;
m.always_show_dot_files = always_show_dot_files == Qtrue;
m.never_show_dot_files = never_show_dot_files == Qtrue;
// calculate score
score = 1.0;
// special case for zero-length search string
if (m.needle_len == 0) {
// filter out dot files
if (!m.always_show_dot_files) {
for (i = 0; i < m.haystack_len; i++) {
char c = m.haystack_p[i];
if (c == '.' && (i == 0 || m.haystack_p[i - 1] == '/')) {
score = 0.0;
break;
}
}
}
} else if (m.haystack_len > 0) { // normal case
// prepare for memoization
double memo[m.haystack_len * m.needle_len];
for (i = 0, max = m.haystack_len * m.needle_len; i < max; i++)
memo[i] = DBL_MAX;
m.memo = memo;
score = recursive_match(&m, 0, 0, 0, 0.0);
}
// final book-keeping
out->path = str;
out->score = score;
}
// Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include <ruby.h>
// struct for representing an individual match
typedef struct {
VALUE path;
double score;
} match_t;
extern void calculate_match(VALUE str,
VALUE needle,
VALUE always_show_dot_files,
VALUE never_show_dot_files,
match_t *out);
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'ostruct'
require 'command-t/settings'
module CommandT
class MatchWindow
SELECTION_MARKER = '> '
MARKER_LENGTH = SELECTION_MARKER.length
UNSELECTED_MARKER = ' ' * MARKER_LENGTH
MH_START = '<commandt>'
MH_END = '</commandt>'
@@buffer = nil
def initialize options = {}
@highlight_color = options[:highlight_color] || 'PmenuSel'
@min_height = options[:min_height]
@prompt = options[:prompt]
@reverse_list = options[:match_window_reverse]
# save existing window dimensions so we can restore them later
@windows = []
(0..(::VIM::Window.count - 1)).each do |i|
@windows << OpenStruct.new(:index => i,
:height => ::VIM::Window[i].height,
:width => ::VIM::Window[i].width)
end
set 'timeout', true # ensure mappings timeout
set 'hlsearch', false # don't highlight search strings
set 'insertmode', false # don't make Insert mode the default
set 'showcmd', false # don't show command info on last line
set 'equalalways', false # don't auto-balance window sizes
set 'timeoutlen', 0 # respond immediately to mappings
set 'report', 9999 # don't show "X lines changed" reports
set 'sidescroll', 0 # don't sidescroll in jumps
set 'sidescrolloff', 0 # don't sidescroll automatically
set 'updatetime', options[:debounce_interval]
# show match window
split_location = options[:match_window_at_top] ? 'topleft' : 'botright'
if @@buffer # still have buffer from last time
::VIM::command "silent! #{split_location} #{@@buffer.number}sbuffer"
raise "Can't re-open GoToFile buffer" unless $curbuf.number == @@buffer.number
$curwin.height = 1
else # creating match window for first time and set it up
::VIM::command "silent! #{split_location} 1split GoToFile"
set 'bufhidden', 'unload' # unload buf when no longer displayed
set 'buftype', 'nofile' # buffer is not related to any file
set 'modifiable', false # prevent manual edits
set 'swapfile', false # don't create a swapfile
set 'wrap', false # don't soft-wrap
set 'number', false # don't show line numbers
set 'list', false # don't use List mode (visible tabs etc)
set 'foldcolumn', 0 # don't show a fold column at side
set 'foldlevel', 99 # don't fold anything
set 'cursorline', false # don't highlight line cursor is on
set 'spell', false # spell-checking off
set 'buflisted', false # don't show up in the buffer list
set 'textwidth', 0 # don't hard-wrap (break long lines)
# don't show the color column
set 'colorcolumn', 0 if VIM::exists?('+colorcolumn')
# don't show relative line numbers
set 'relativenumber', false if VIM::exists?('+relativenumber')
# sanity check: make sure the buffer really was created
raise "Can't find GoToFile buffer" unless $curbuf.name.match /GoToFile\z/
@@buffer = $curbuf
end
# syntax coloring
if VIM::has_syntax?
::VIM::command "syntax match CommandTSelection \"^#{SELECTION_MARKER}.\\+$\""
::VIM::command 'syntax match CommandTNoEntries "^-- NO MATCHES --$"'
::VIM::command 'syntax match CommandTNoEntries "^-- NO SUCH FILE OR DIRECTORY --$"'
set 'synmaxcol', 9999
if VIM::has_conceal?
set 'conceallevel', 2
set 'concealcursor', 'nvic'
::VIM::command 'syntax region CommandTCharMatched ' \
"matchgroup=CommandTCharMatched start=+#{MH_START}+ " \
"matchgroup=CommandTCharMatchedEnd end=+#{MH_END}+ concealends"
::VIM::command 'highlight def CommandTCharMatched ' \
'term=bold,underline cterm=bold,underline ' \
'gui=bold,underline'
end
::VIM::command "highlight link CommandTSelection #{@highlight_color}"
::VIM::command 'highlight link CommandTNoEntries Error'
# hide cursor
@cursor_highlight = get_cursor_highlight
hide_cursor
end
# perform cleanup using an autocmd to ensure we don't get caught out
# by some unexpected means of dismissing or leaving the Command-T window
# (eg. <C-W q>, <C-W k> etc)
::VIM::command 'autocmd! * <buffer>'
::VIM::command 'autocmd BufLeave <buffer> silent! ruby $command_t.leave'
::VIM::command 'autocmd BufUnload <buffer> silent! ruby $command_t.unload'
@has_focus = false
@selection = nil
@abbrev = ''
@window = $curwin
end
def close
# Unlisted buffers like those provided by Netrw, NERDTree and Vim's help
# don't actually appear in the buffer list; if they are the only such
# buffers present when Command-T is invoked (for example, when invoked
# immediately after starting Vim with a directory argument, like `vim .`)
# then performing the normal clean-up will yield an "E90: Cannot unload
# last buffer" error. We can work around that by doing a :quit first.
if ::VIM::Buffer.count == 0
::VIM::command 'silent quit'
end
# Workaround for upstream bug in Vim 7.3 on some platforms
#
# On some platforms, $curbuf.number always returns 0. One workaround is
# to build Vim with --disable-largefile, but as this is producing lots of
# support requests, implement the following fallback to the buffer name
# instead, at least until upstream gets fixed.
#
# For more details, see: https://wincent.com/issues/1617
if $curbuf.number == 0
# use bwipeout as bunload fails if passed the name of a hidden buffer
::VIM::command 'silent! bwipeout! GoToFile'
@@buffer = nil
else
::VIM::command "silent! bunload! #{@@buffer.number}"
end
end
def leave
close
unload
end
def unload
restore_window_dimensions
@settings.restore
@prompt.dispose
show_cursor
end
def add! char
@abbrev += char
end
def backspace!
@abbrev.chop!
end
def select_next
if @selection < @matches.length - 1
@selection += 1
print_match(@selection - 1) # redraw old selection (removes marker)
print_match(@selection) # redraw new selection (adds marker)
move_cursor_to_selected_line
else
# (possibly) loop or scroll
end
end
def select_prev
if @selection > 0
@selection -= 1
print_match(@selection + 1) # redraw old selection (removes marker)
print_match(@selection) # redraw new selection (adds marker)
move_cursor_to_selected_line
else
# (possibly) loop or scroll
end
end
def matches= matches
matches = matches.reverse if @reverse_list
if matches != @matches
@matches = matches
@selection = @reverse_list ? @matches.length - 1 : 0
print_matches
move_cursor_to_selected_line
end
end
def focus
unless @has_focus
@has_focus = true
if VIM::has_syntax?
::VIM::command 'highlight link CommandTSelection Search'
end
end
end
def unfocus
if @has_focus
@has_focus = false
if VIM::has_syntax?
::VIM::command "highlight link CommandTSelection #{@highlight_color}"
end
end
end
def find char
# is this a new search or the continuation of a previous one?
now = Time.now
if @last_key_time.nil? or @last_key_time < (now - 0.5)
@find_string = char
else
@find_string += char
end
@last_key_time = now
# see if there's anything up ahead that matches
@matches.each_with_index do |match, idx|
if match[0, @find_string.length].casecmp(@find_string) == 0
old_selection = @selection
@selection = idx
print_match(old_selection) # redraw old selection (removes marker)
print_match(@selection) # redraw new selection (adds marker)
break
end
end
end
# Returns the currently selected item as a String.
def selection
@matches[@selection]
end
def print_no_such_file_or_directory
print_error 'NO SUCH FILE OR DIRECTORY'
end
private
def set(setting, value)
@settings ||= Settings.new
@settings.set(setting, value)
end
def move_cursor_to_selected_line
# on some non-GUI terminals, the cursor doesn't hide properly
# so we move the cursor to prevent it from blinking away in the
# upper-left corner in a distracting fashion
@window.cursor = [@selection + 1, 0]
end
def print_error msg
return unless VIM::Window.select(@window)
unlock
clear
@window.height = @min_height > 0 ? @min_height : 1
@@buffer[1] = "-- #{msg} --"
lock
end
def restore_window_dimensions
# sort from tallest to shortest, tie-breaking on window width
@windows.sort! do |a, b|
order = b.height <=> a.height
if order.zero?
b.width <=> a.width
else
order
end
end
# starting with the tallest ensures that there are no constraints
# preventing windows on the side of vertical splits from regaining
# their original full size
@windows.each do |w|
# beware: window may be nil
if window = ::VIM::Window[w.index]
window.height = w.height
window.width = w.width
end
end
end
def match_text_for_idx idx
match = truncated_match @matches[idx].to_s
if idx == @selection
prefix = SELECTION_MARKER
suffix = padding_for_selected_match match
else
if VIM::has_syntax? && VIM::has_conceal?
match = match_with_syntax_highlight match
end
prefix = UNSELECTED_MARKER
suffix = ''
end
prefix + match + suffix
end
# Highlight matching characters within the matched string.
#
# Note that this is only approximate; it will highlight the first matching
# instances within the string, which may not actually be the instances that
# were used by the matching/scoring algorithm to determine the best score
# for the match.
#
def match_with_syntax_highlight match
highlight_chars = @prompt.abbrev.downcase.chars.to_a
match.chars.inject([]) do |output, char|
if char.downcase == highlight_chars.first
highlight_chars.shift
output.concat [MH_START, char, MH_END]
else
output << char
end
end.join
end
# Print just the specified match.
def print_match idx
return unless VIM::Window.select(@window)
unlock
@@buffer[idx + 1] = match_text_for_idx idx
lock
end
# Print all matches.
def print_matches
match_count = @matches.length
if match_count == 0
print_error 'NO MATCHES'
else
return unless VIM::Window.select(@window)
unlock
clear
actual_lines = 1
@window_width = @window.width # update cached value
max_lines = VIM::Screen.lines - 5
max_lines = 1 if max_lines < 0
actual_lines = match_count < @min_height ? @min_height : match_count
actual_lines = max_lines if actual_lines > max_lines
@window.height = actual_lines
(1..actual_lines).each do |line|
idx = line - 1
if @@buffer.count >= line
@@buffer[line] = match_text_for_idx idx
else
@@buffer.append line - 1, match_text_for_idx(idx)
end
end
lock
end
end
# Prepare padding for match text (trailing spaces) so that selection
# highlighting extends all the way to the right edge of the window.
def padding_for_selected_match str
len = str.length
if len >= @window_width - MARKER_LENGTH
''
else
' ' * (@window_width - MARKER_LENGTH - len)
end
end
# Convert "really/long/path" into "really...path" based on available
# window width.
def truncated_match str
len = str.length
available_width = @window_width - MARKER_LENGTH
return str if len <= available_width
left = (available_width / 2) - 1
right = (available_width / 2) - 2 + (available_width % 2)
str[0, left] + '...' + str[-right, right]
end
def clear
# range = % (whole buffer)
# action = d (delete)
# register = _ (black hole register, don't record deleted text)
::VIM::command 'silent %d _'
end
def get_cursor_highlight
# there are 3 possible formats to check for, each needing to be
# transformed in a certain way in order to reapply the highlight:
# Cursor xxx guifg=bg guibg=fg -> :hi! Cursor guifg=bg guibg=fg
# Cursor xxx links to SomethingElse -> :hi! link Cursor SomethingElse
# Cursor xxx cleared -> :hi! clear Cursor
highlight = VIM::capture 'silent! 0verbose highlight Cursor'
if highlight =~ /^Cursor\s+xxx\s+links to (\w+)/
"link Cursor #{$~[1]}"
elsif highlight =~ /^Cursor\s+xxx\s+cleared/
'clear Cursor'
elsif highlight =~ /Cursor\s+xxx\s+(.+)/
"Cursor #{$~[1]}"
else # likely cause E411 Cursor highlight group not found
nil
end
end
def hide_cursor
if @cursor_highlight
::VIM::command 'highlight Cursor NONE'
end
end
def show_cursor
if @cursor_highlight
::VIM::command "highlight #{@cursor_highlight}"
end
end
def lock
set 'modifiable', false
end
def unlock
set 'modifiable', true
end
end
end
// Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include <stdlib.h> /* for qsort() */
#include <string.h> /* for strncmp() */
#include "matcher.h"
#include "match.h"
#include "ext.h"
#include "ruby_compat.h"
// order matters; we want this to be evaluated only after ruby.h
#ifdef HAVE_PTHREAD_H
#include <pthread.h> /* for pthread_create, pthread_join etc */
#endif
// comparison function for use with qsort
int cmp_alpha(const void *a, const void *b)
{
match_t a_match = *(match_t *)a;
match_t b_match = *(match_t *)b;
VALUE a_str = a_match.path;
VALUE b_str = b_match.path;
char *a_p = RSTRING_PTR(a_str);
long a_len = RSTRING_LEN(a_str);
char *b_p = RSTRING_PTR(b_str);
long b_len = RSTRING_LEN(b_str);
int order = 0;
if (a_len > b_len) {
order = strncmp(a_p, b_p, b_len);
if (order == 0)
order = 1; // shorter string (b) wins
} else if (a_len < b_len) {
order = strncmp(a_p, b_p, a_len);
if (order == 0)
order = -1; // shorter string (a) wins
} else {
order = strncmp(a_p, b_p, a_len);
}
return order;
}
// comparison function for use with qsort
int cmp_score(const void *a, const void *b)
{
match_t a_match = *(match_t *)a;
match_t b_match = *(match_t *)b;
if (a_match.score > b_match.score)
return -1; // a scores higher, a should appear sooner
else if (a_match.score < b_match.score)
return 1; // b scores higher, a should appear later
else
return cmp_alpha(a, b);
}
VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE always_show_dot_files;
VALUE never_show_dot_files;
VALUE options;
VALUE scanner;
// process arguments: 1 mandatory, 1 optional
if (rb_scan_args(argc, argv, "11", &scanner, &options) == 1)
options = Qnil;
if (NIL_P(scanner))
rb_raise(rb_eArgError, "nil scanner");
rb_iv_set(self, "@scanner", scanner);
// check optional options hash for overrides
always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options);
never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options);
rb_iv_set(self, "@always_show_dot_files", always_show_dot_files);
rb_iv_set(self, "@never_show_dot_files", never_show_dot_files);
return Qnil;
}
typedef struct {
int thread_count;
int thread_index;
match_t *matches;
long path_count;
VALUE paths;
VALUE abbrev;
VALUE always_show_dot_files;
VALUE never_show_dot_files;
} thread_args_t;
void *match_thread(void *thread_args)
{
long i;
thread_args_t *args = (thread_args_t *)thread_args;
for (i = args->thread_index; i < args->path_count; i += args->thread_count) {
VALUE path = RARRAY_PTR(args->paths)[i];
calculate_match(path,
args->abbrev,
args->always_show_dot_files,
args->never_show_dot_files,
&args->matches[i]);
}
return NULL;
}
VALUE CommandTMatcher_sorted_matches_for(int argc, VALUE *argv, VALUE self)
{
long i, limit, path_count, thread_count;
#ifdef HAVE_PTHREAD_H
long err;
#endif
match_t *matches;
thread_args_t *thread_args;
VALUE abbrev;
VALUE always_show_dot_files;
VALUE limit_option;
VALUE never_show_dot_files;
VALUE options;
VALUE paths;
VALUE results;
VALUE scanner;
VALUE threads_option;
// process arguments: 1 mandatory, 1 optional
if (rb_scan_args(argc, argv, "11", &abbrev, &options) == 1)
options = Qnil;
if (NIL_P(abbrev))
rb_raise(rb_eArgError, "nil abbrev");
abbrev = StringValue(abbrev);
abbrev = rb_funcall(abbrev, rb_intern("downcase"), 0);
// check optional options has for overrides
limit_option = CommandT_option_from_hash("limit", options);
threads_option = CommandT_option_from_hash("threads", options);
// get unsorted matches
scanner = rb_iv_get(self, "@scanner");
paths = rb_funcall(scanner, rb_intern("paths"), 0);
always_show_dot_files = rb_iv_get(self, "@always_show_dot_files");
never_show_dot_files = rb_iv_get(self, "@never_show_dot_files");
path_count = RARRAY_LEN(paths);
matches = malloc(path_count * sizeof(match_t));
if (!matches)
rb_raise(rb_eNoMemError, "memory allocation failed");
thread_count = NIL_P(threads_option) ? 1 : NUM2LONG(threads_option);
#ifdef HAVE_PTHREAD_H
#define THREAD_THRESHOLD 1000 /* avoid the overhead of threading when search space is small */
if (path_count < THREAD_THRESHOLD)
thread_count = 1;
pthread_t *threads = malloc(sizeof(pthread_t) * thread_count);
if (!threads)
rb_raise(rb_eNoMemError, "memory allocation failed");
#endif
thread_args = malloc(sizeof(thread_args_t) * thread_count);
if (!thread_args)
rb_raise(rb_eNoMemError, "memory allocation failed");
for (i = 0; i < thread_count; i++) {
thread_args[i].thread_count = thread_count;
thread_args[i].thread_index = i;
thread_args[i].matches = matches;
thread_args[i].path_count = path_count;
thread_args[i].paths = paths;
thread_args[i].abbrev = abbrev;
thread_args[i].always_show_dot_files = always_show_dot_files;
thread_args[i].never_show_dot_files = never_show_dot_files;
#ifdef HAVE_PTHREAD_H
if (i == thread_count - 1) {
#endif
// for the last "worker", we'll just use the main thread
(void)match_thread(&thread_args[i]);
#ifdef HAVE_PTHREAD_H
} else {
err = pthread_create(&threads[i], NULL, match_thread, (void *)&thread_args[i]);
if (err != 0)
rb_raise(rb_eSystemCallError, "pthread_create() failure (%d)", (int)err);
}
#endif
}
#ifdef HAVE_PTHREAD_H
for (i = 0; i < thread_count - 1; i++) {
err = pthread_join(threads[i], NULL);
if (err != 0)
rb_raise(rb_eSystemCallError, "pthread_join() failure (%d)", (int)err);
}
free(threads);
#endif
if (RSTRING_LEN(abbrev) == 0 ||
(RSTRING_LEN(abbrev) == 1 && RSTRING_PTR(abbrev)[0] == '.'))
// alphabetic order if search string is only "" or "."
qsort(matches, path_count, sizeof(match_t), cmp_alpha);
else
// for all other non-empty search strings, sort by score
qsort(matches, path_count, sizeof(match_t), cmp_score);
results = rb_ary_new();
limit = NIL_P(limit_option) ? 0 : NUM2LONG(limit_option);
if (limit == 0)
limit = path_count;
for (i = 0; i < path_count && limit > 0; i++) {
if (matches[i].score > 0.0) {
rb_funcall(results, rb_intern("push"), 1, matches[i].path);
limit--;
}
}
free(matches);
return results;
}
// Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include <ruby.h>
extern VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self);
extern VALUE CommandTMatcher_sorted_matches_for(int argc, VALUE *argv, VALUE self);
find_header: checking for float.h... -------------------- yes
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <float.h>
/* end */
--------------------
find_header: checking for ruby.h... -------------------- yes
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <ruby.h>
/* end */
--------------------
find_header: checking for stdlib.h... -------------------- yes
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <stdlib.h>
/* end */
--------------------
find_header: checking for string.h... -------------------- yes
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <string.h>
/* end */
--------------------
have_header: checking for fcntl.h... -------------------- yes
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <fcntl.h>
/* end */
--------------------
have_header: checking for sys/errno.h... -------------------- yes
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <sys/errno.h>
/* end */
--------------------
have_header: checking for sys/socket.h... -------------------- yes
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <sys/socket.h>
/* end */
--------------------
have_header: checking for ruby/st.h... -------------------- no
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
conftest.c:1:21: fatal error: ruby/st.h: No such file or directory
compilation terminated.
checked program was:
/* begin */
1: #include <ruby/st.h>
/* end */
--------------------
have_header: checking for st.h... -------------------- yes
"gcc -E -I. -I/usr/lib/ruby/1.8/i686-linux -I. -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -g -g -O2 -fPIC conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <st.h>
/* end */
--------------------
# Copyright 2010 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
module CommandT
# Abuse the status line as a prompt.
class Prompt
attr_accessor :abbrev
def initialize
@abbrev = '' # abbreviation entered so far
@col = 0 # cursor position
@has_focus = false
end
# Erase whatever is displayed in the prompt line,
# effectively disposing of the prompt
def dispose
::VIM::command 'echo'
::VIM::command 'redraw'
end
# Clear any entered text.
def clear!
@abbrev = ''
@col = 0
redraw
end
# Insert a character at (before) the current cursor position.
def add! char
left, cursor, right = abbrev_segments
@abbrev = left + char + cursor + right
@col += 1
redraw
end
# Delete a character to the left of the current cursor position.
def backspace!
if @col > 0
left, cursor, right = abbrev_segments
@abbrev = left.chop! + cursor + right
@col -= 1
redraw
end
end
# Delete a character at the current cursor position.
def delete!
if @col < @abbrev.length
left, cursor, right = abbrev_segments
@abbrev = left + right
redraw
end
end
def cursor_left
if @col > 0
@col -= 1
redraw
end
end
def cursor_right
if @col < @abbrev.length
@col += 1
redraw
end
end
def cursor_end
if @col < @abbrev.length
@col = @abbrev.length
redraw
end
end
def cursor_start
if @col != 0
@col = 0
redraw
end
end
def redraw
if @has_focus
prompt_highlight = 'Comment'
normal_highlight = 'None'
cursor_highlight = 'Underlined'
else
prompt_highlight = 'NonText'
normal_highlight = 'NonText'
cursor_highlight = 'NonText'
end
left, cursor, right = abbrev_segments
components = [prompt_highlight, '>>', 'None', ' ']
components += [normal_highlight, left] unless left.empty?
components += [cursor_highlight, cursor] unless cursor.empty?
components += [normal_highlight, right] unless right.empty?
components += [cursor_highlight, ' '] if cursor.empty?
set_status *components
end
def focus
unless @has_focus
@has_focus = true
redraw
end
end
def unfocus
if @has_focus
@has_focus = false
redraw
end
end
private
# Returns the @abbrev string divided up into three sections, any of
# which may actually be zero width, depending on the location of the
# cursor:
# - left segment (to left of cursor)
# - cursor segment (character at cursor)
# - right segment (to right of cursor)
def abbrev_segments
left = @abbrev[0, @col]
cursor = @abbrev[@col, 1]
right = @abbrev[(@col + 1)..-1] || ''
[left, cursor, right]
end
def set_status *args
# see ':help :echo' for why forcing a redraw here helps
# prevent the status line from getting inadvertantly cleared
# after our echo commands
::VIM::command 'redraw'
while (highlight = args.shift) and (text = args.shift) do
text = VIM::escape_for_single_quotes text
::VIM::command "echohl #{highlight}"
::VIM::command "echon '#{text}'"
end
::VIM::command 'echohl None'
end
end # class Prompt
end # module CommandT
// Copyright 2010 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include <ruby.h>
// for compatibility with older versions of Ruby which don't declare RSTRING_PTR
#ifndef RSTRING_PTR
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
#endif
// for compatibility with older versions of Ruby which don't declare RSTRING_LEN
#ifndef RSTRING_LEN
#define RSTRING_LEN(s) (RSTRING(s)->len)
#endif
// for compatibility with older versions of Ruby which don't declare RARRAY_PTR
#ifndef RARRAY_PTR
#define RARRAY_PTR(a) (RARRAY(a)->ptr)
#endif
// for compatibility with older versions of Ruby which don't declare RARRAY_LEN
#ifndef RARRAY_LEN
#define RARRAY_LEN(a) (RARRAY(a)->len)
#endif
// for compatibility with older versions of Ruby which don't declare RFLOAT_VALUE
#ifndef RFLOAT_VALUE
#define RFLOAT_VALUE(f) (RFLOAT(f)->value)
#endif
# Copyright 2010-2011 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/vim'
module CommandT
class Scanner; end
end # module CommandT
# Copyright 2010-2011 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/vim'
require 'command-t/vim/path_utilities'
require 'command-t/scanner'
module CommandT
# Returns a list of all open buffers.
class BufferScanner < Scanner
include VIM::PathUtilities
def paths
(0..(::VIM::Buffer.count - 1)).map do |n|
buffer = ::VIM::Buffer[n]
if buffer.name # beware, may be nil
relative_path_under_working_directory buffer.name
end
end.compact
end
end # class BufferScanner
end # module CommandT
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/vim'
require 'command-t/scanner'
module CommandT
# Reads the current directory recursively for the paths to all regular files.
#
# This is an abstract superclass; the real work is done by subclasses which
# obtain file listings via different strategies (for examples, see the
# RubyFileScanner and FindFileScanner subclasses).
class FileScanner < Scanner
class FileLimitExceeded < ::RuntimeError; end
attr_accessor :path
def initialize(path = Dir.pwd, options = {})
@paths = {}
@paths_keys = []
@path = path
@max_depth = options[:max_depth] || 15
@max_files = options[:max_files] || 30_000
@max_caches = options[:max_caches] || 1
@scan_dot_directories = options[:scan_dot_directories] || false
@wild_ignore = options[:wild_ignore]
@base_wild_ignore = VIM::wild_ignore
end
def paths
@paths[@path] || begin
ensure_cache_under_limit
@prefix_len = @path.chomp('/').length
nil
end
end
def flush
@paths = {}
end
private
def ensure_cache_under_limit
# Ruby 1.8 doesn't have an ordered hash, so use a separate stack to
# track and expire the oldest entry in the cache
if @max_caches > 0 && @paths_keys.length >= @max_caches
@paths.delete @paths_keys.shift
end
@paths_keys << @path
end
def path_excluded?(path)
# first strip common prefix (@path) from path to match VIM's behavior
path = path[(@prefix_len + 1)..-1]
path = VIM::escape_for_single_quotes path
::VIM::evaluate("empty(expand(fnameescape('#{path}')))").to_i == 1
end
def set_wild_ignore(ignore)
::VIM::command("set wildignore=#{ignore}") if @wild_ignore
end
end # class FileScanner
end # module CommandT
# Copyright 2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'open3'
require 'command-t/vim'
require 'command-t/vim/path_utilities'
require 'command-t/scanner/file_scanner'
module CommandT
class FileScanner
# A FileScanner which shells out to the `find` executable in order to scan.
class FindFileScanner < FileScanner
include VIM::PathUtilities
def paths
super || begin
set_wild_ignore(@wild_ignore)
# temporarily set field separator to NUL byte; this setting is
# respected by both `readlines` and `chomp!` below, and makes it easier
# to parse the output of `find -print0`
separator = $/
$/ = "\x00"
unless @scan_dot_directories
dot_directory_filter = [
'-not', '-path', "#{@path}/.*/*", # top-level dot dir
'-and', '-not', '-path', "#{@path}/*/.*/*" # lower-level dot dir
]
end
Open3.popen3(*([
'find', '-L', # follow symlinks
@path, # anchor search here
'-maxdepth', @max_depth.to_s, # limit depth of DFS
'-type', 'f', # only show regular files (not dirs etc)
dot_directory_filter, # possibly skip out dot directories
'-print0' # NUL-terminate results
].flatten.compact)) do |stdin, stdout, stderr|
counter = 1
paths = []
stdout.readlines.each do |line|
next if path_excluded?(line.chomp!)
paths << line[@prefix_len + 1..-1]
break if (counter += 1) > @max_files
end
@paths[@path] = paths
end
ensure
$/ = separator
set_wild_ignore(@base_wild_ignore)
end
@paths[@path]
end
end # class FindFileScanner
end # class FileScanner
end # module CommandT
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/vim'
require 'command-t/scanner/file_scanner'
module CommandT
class FileScanner
# Pure Ruby implementation of a file scanner.
class RubyFileScanner < FileScanner
def paths
super || begin
@paths[@path] = []
@depth = 0
@files = 0
set_wild_ignore(@wild_ignore)
add_paths_for_directory @path, @paths[@path]
rescue FileLimitExceeded
ensure
set_wild_ignore(@base_wild_ignore)
end
@paths[@path]
end
private
def looped_symlink? path
if File.symlink?(path)
target = File.expand_path(File.readlink(path), File.dirname(path))
target.include?(@path) || @path.include?(target)
end
end
def add_paths_for_directory dir, accumulator
Dir.foreach(dir) do |entry|
next if ['.', '..'].include?(entry)
path = File.join(dir, entry)
unless path_excluded?(path)
if File.file?(path)
@files += 1
raise FileLimitExceeded if @files > @max_files
accumulator << path[@prefix_len + 1..-1]
elsif File.directory?(path)
next if @depth >= @max_depth
next if (entry.match(/\A\./) && !@scan_dot_directories)
next if looped_symlink?(path)
@depth += 1
add_paths_for_directory path, accumulator
@depth -= 1
end
end
end
rescue Errno::EACCES
# skip over directories for which we don't have access
end
end # class RubyFileScanner
end # class FileScanner
end # module CommandT
# Copyright 2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'pathname'
require 'socket'
require 'command-t/vim'
require 'command-t/vim/path_utilities'
require 'command-t/scanner/file_scanner'
require 'command-t/scanner/file_scanner/find_file_scanner'
module CommandT
class FileScanner
# A FileScanner which delegates the heavy lifting to Watchman
# (https://github.com/facebook/watchman); useful for very large hierarchies.
#
# Inherits from FindFileScanner so that it can fall back to it in the event
# that Watchman isn't available or able to fulfil the request.
class WatchmanFileScanner < FindFileScanner
# Exception raised when Watchman is unavailable or unable to process the
# requested path.
class WatchmanUnavailable < RuntimeError; end
def paths
@paths[@path] ||= begin
ensure_cache_under_limit
sockname = Watchman::Utils.load(
%x{watchman --output-encoding=bser get-sockname}
)['sockname']
raise WatchmanUnavailable unless $?.exitstatus.zero?
UNIXSocket.open(sockname) do |socket|
root = Pathname.new(@path).realpath.to_s
roots = Watchman::Utils.query(['watch-list'], socket)['roots']
if !roots.include?(root)
# this path isn't being watched yet; try to set up watch
result = Watchman::Utils.query(['watch', root], socket)
# root_restrict_files setting may prevent Watchman from working
raise WatchmanUnavailable if result.has_key?('error')
end
query = ['query', root, {
'expression' => ['type', 'f'],
'fields' => ['name'],
}]
paths = Watchman::Utils.query(query, socket)
# could return error if watch is removed
raise WatchmanUnavailable if paths.has_key?('error')
@paths[@path] = paths['files']
end
end
@paths[@path]
rescue Errno::ENOENT, WatchmanUnavailable
# watchman executable not present, or unable to fulfil request
super
end
end # class WatchmanFileScanner
end # class FileScanner
end # module CommandT
# Copyright 2011 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/vim'
require 'command-t/vim/path_utilities'
require 'command-t/scanner'
module CommandT
# Returns a list of files in the jumplist.
class JumpScanner < Scanner
include VIM::PathUtilities
def paths
jumps_with_filename = jumps.lines.select do |line|
line_contains_filename?(line)
end
filenames = jumps_with_filename[1..-2].map do |line|
relative_path_under_working_directory line.split[3]
end
filenames.sort.uniq
end
private
def line_contains_filename? line
line.split.count > 3
end
def jumps
VIM::capture 'silent jumps'
end
end # class JumpScanner
end # module CommandT
# Copyright 2011-2012 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/vim'
require 'command-t/scanner'
module CommandT
class TagScanner < Scanner
attr_reader :include_filenames
def initialize options = {}
@include_filenames = options[:include_filenames] || false
end
def paths
taglist.map do |tag|
path = tag['name']
path << ":#{tag['filename']}" if @include_filenames
path
end.uniq.sort
end
private
def taglist
::VIM::evaluate 'taglist(".")'
end
end # class TagScanner
end # module CommandT
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
module CommandT
# Convenience class for saving and restoring global settings.
class Settings
# Settings which apply globally and so must be manually saved and restored
GLOBAL_SETTINGS = %w[
equalalways
hlsearch
insertmode
report
showcmd
sidescroll
sidescrolloff
timeout
timeoutlen
updatetime
]
# Settings which can be made locally to the Command-T buffer or window
LOCAL_SETTINGS = %w[
bufhidden
buflisted
buftype
colorcolumn
concealcursor
conceallevel
cursorline
foldcolumn
foldlevel
list
modifiable
number
relativenumber
spell
swapfile
synmaxcol
textwidth
wrap
]
KNOWN_SETTINGS = GLOBAL_SETTINGS + LOCAL_SETTINGS
def initialize
@settings = []
end
def set(setting, value)
raise "Unknown setting #{setting}" unless KNOWN_SETTINGS.include?(setting)
case value
when TrueClass, FalseClass
@settings.push([setting, get_bool(setting)]) if global?(setting)
set_bool setting, value
when Numeric
@settings.push([setting, get_number(setting)]) if global?(setting)
set_number setting, value
when String
@settings.push([setting, get_string(setting)]) if global?(setting)
set_string setting, value
end
end
def restore
@settings.each do |setting, value|
case value
when TrueClass, FalseClass
set_bool setting, value
when Numeric
set_number setting, value
when String
set_string setting, value
end
end
end
private
def global?(setting)
GLOBAL_SETTINGS.include?(setting)
end
def get_bool(setting)
::VIM::evaluate("&#{setting}").to_i == 1
end
def get_number(setting)
::VIM::evaluate("&#{setting}").to_i
end
def get_string(name)
::VIM::evaluate("&#{name}").to_s
end
def set_bool(setting, value)
command = global?(setting) ? 'set' : 'setlocal'
setting = value ? setting : "no#{setting}"
::VIM::command "#{command} #{setting}"
end
def set_number(setting, value)
command = global?(setting) ? 'set' : 'setlocal'
::VIM::command "#{command} #{setting}=#{value}"
end
alias set_string set_number
end # class Settings
end # module CommandT
# Copyright 2010-2011 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
module CommandT
class Stub
@@load_error = ['command-t.vim could not load the C extension',
'Please see INSTALLATION and TROUBLE-SHOOTING in the help',
'For more information type: :help command-t']
[:flush, :show_buffer_finder, :show_file_finder, :show_tag_finder].each do |method|
define_method(method.to_sym) { warn *@@load_error }
end
private
def warn *msg
::VIM::command 'echohl WarningMsg'
msg.each { |m| ::VIM::command "echo '#{m}'" }
::VIM::command 'echohl none'
end
end # class Stub
end # module CommandT
# Copyright 2013-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'rbconfig'
module CommandT
module Util
class << self
def processor_count
@processor_count ||= begin
count = processor_count!
count = 1 if count < 1 # sanity check
count = 32 if count > 32 # sanity check
count
end
end
private
# This method derived from:
#
# https://github.com/grosser/parallel/blob/d11e4a3c8c1a/lib/parallel.rb
#
# Number of processors seen by the OS and used for process scheduling.
#
# * AIX: /usr/sbin/pmcycles (AIX 5+), /usr/sbin/lsdev
# * BSD: /sbin/sysctl
# * Cygwin: /proc/cpuinfo
# * Darwin: /usr/bin/hwprefs, /usr/sbin/sysctl
# * HP-UX: /usr/sbin/ioscan
# * IRIX: /usr/sbin/sysconf
# * Linux: /proc/cpuinfo
# * Minix 3+: /proc/cpuinfo
# * Solaris: /usr/sbin/psrinfo
# * Tru64 UNIX: /usr/sbin/psrinfo
# * UnixWare: /usr/sbin/psrinfo
#
# Copyright (C) 2013 Michael Grosser <michael@grosser.it>
#
# 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.
#
def processor_count!
os_name = RbConfig::CONFIG['target_os']
if os_name =~ /mingw|mswin/
require 'win32ole'
result = WIN32OLE.connect('winmgmts://').ExecQuery(
'select NumberOfLogicalProcessors from Win32_Processor')
result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
elsif File.readable?('/proc/cpuinfo')
IO.read('/proc/cpuinfo').scan(/^processor/).size
elsif File.executable?('/usr/bin/hwprefs')
IO.popen(%w[/usr/bin/hwprefs thread_count]).read.to_i
elsif File.executable?('/usr/sbin/psrinfo')
IO.popen('/usr/sbin/psrinfo').read.scan(/^.*on-*line/).size
elsif File.executable?('/usr/sbin/ioscan')
IO.popen(%w[/usr/sbin/ioscan -kC processor]) do |out|
out.read.scan(/^.*processor/).size
end
elsif File.executable?('/usr/sbin/pmcycles')
IO.popen(%w[/usr/sbin/pmcycles -m]).read.count("\n")
elsif File.executable?('/usr/sbin/lsdev')
IO.popen(%w[/usr/sbin/lsdev -Cc processor -S 1]).read.count("\n")
elsif File.executable?('/usr/sbin/sysconf') and os_name =~ /irix/i
IO.popen(%w[/usr/sbin/sysconf NPROC_ONLN]).read.to_i
elsif File.executable?('/usr/sbin/sysctl')
IO.popen(%w[/usr/sbin/sysctl -n hw.ncpu]).read.to_i
elsif File.executable?('/sbin/sysctl')
IO.popen(%w[/sbin/sysctl -n hw.ncpu]).read.to_i
else # unknown platform
1
end
rescue
1
end
end
end # module Util
end # module commandT
# Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/vim/screen'
require 'command-t/vim/window'
module CommandT
module VIM
def self.has_syntax?
::VIM::evaluate('has("syntax")').to_i != 0
end
def self.exists? str
::VIM::evaluate(%{exists("#{str}")}).to_i != 0
end
def self.has_conceal?
::VIM::evaluate('has("conceal")').to_i != 0
end
def self.pwd
::VIM::evaluate 'getcwd()'
end
def self.wild_ignore
exists?('&wildignore') && ::VIM::evaluate('&wildignore').to_s
end
# Execute cmd, capturing the output into a variable and returning it.
def self.capture cmd
::VIM::command 'silent redir => g:command_t_captured_output'
::VIM::command cmd
::VIM::command 'silent redir END'
::VIM::evaluate 'g:command_t_captured_output'
end
# Escape a string for safe inclusion in a Vim single-quoted string
# (single quotes escaped by doubling, everything else is literal)
def self.escape_for_single_quotes str
str.gsub "'", "''"
end
end # module VIM
end # module CommandT
# Copyright 2010-2011 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
require 'command-t/vim'
module CommandT
module VIM
module PathUtilities
private
def relative_path_under_working_directory path
# any path under the working directory will be specified as a relative
# path to improve the readability of the buffer list etc
pwd = File.expand_path(VIM::pwd) + '/'
path.index(pwd) == 0 ? path[pwd.length..-1] : path
end
end # module PathUtilities
end # module VIM
end # module CommandT
# Copyright 2010 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
module CommandT
module VIM
module Screen
def self.lines
::VIM::evaluate('&lines').to_i
end
end # module Screen
end # module VIM
end # module CommandT
# Copyright 2010 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. 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 HOLDERS 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.
module CommandT
module VIM
class Window
def self.select window
return true if $curwin == window
initial = $curwin
while true do
::VIM::command 'wincmd w' # cycle through windows
return true if $curwin == window # have selected desired window
return false if $curwin == initial # have already looped through all
end
end
end # class Window
end # module VIM
end # module CommandT
// Copyright 2014 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include "watchman.h"
#ifdef WATCHMAN_BUILD
#if defined(HAVE_RUBY_ST_H)
#include <ruby/st.h>
#elif defined(HAVE_ST_H)
#include <st.h>
#else
#error no st.h header found
#endif
#include <fcntl.h> /* for fcntl() */
#include <sys/errno.h> /* for errno */
#include <sys/socket.h> /* for recv(), MSG_PEEK */
typedef struct {
uint8_t *data; // payload
size_t cap; // total capacity
size_t len; // current length
} watchman_t;
// Forward declarations:
VALUE watchman_load(char **ptr, char *end);
void watchman_dump(watchman_t *w, VALUE serializable);
/**
* Inspect a ruby object (debugging aid)
*/
#define ruby_inspect(obj) rb_funcall(rb_mKernel, rb_intern("p"), 1, obj)
/**
* Print `count` bytes of memory at `address` (debugging aid)
*/
#define dump(address, count) \
do { \
for (int i = 0; i < count; i++) { \
printf("%02x ", ((unsigned char *)address)[i]); printf("\n"); \
} \
} while(0)
#define WATCHMAN_DEFAULT_STORAGE 4096
#define WATCHMAN_BINARY_MARKER "\x00\x01"
#define WATCHMAN_ARRAY_MARKER 0x00
#define WATCHMAN_HASH_MARKER 0x01
#define WATCHMAN_STRING_MARKER 0x02
#define WATCHMAN_INT8_MARKER 0x03
#define WATCHMAN_INT16_MARKER 0x04
#define WATCHMAN_INT32_MARKER 0x05
#define WATCHMAN_INT64_MARKER 0x06
#define WATCHMAN_FLOAT_MARKER 0x07
#define WATCHMAN_TRUE 0x08
#define WATCHMAN_FALSE 0x09
#define WATCHMAN_NIL 0x0a
#define WATCHMAN_TEMPLATE_MARKER 0x0b
#define WATCHMAN_SKIP_MARKER 0x0c
#define WATCHMAN_HEADER \
WATCHMAN_BINARY_MARKER \
"\x06" \
"\x00\x00\x00\x00\x00\x00\x00\x00"
static const char watchman_array_marker = WATCHMAN_ARRAY_MARKER;
static const char watchman_hash_marker = WATCHMAN_HASH_MARKER;
static const char watchman_string_marker = WATCHMAN_STRING_MARKER;
static const char watchman_true = WATCHMAN_TRUE;
static const char watchman_false = WATCHMAN_FALSE;
static const char watchman_nil = WATCHMAN_NIL;
/**
* Appends `len` bytes, starting at `data`, to the watchman_t struct `w`
*
* Will attempt to reallocate the underlying storage if it is not sufficient.
*/
void watchman_append(watchman_t *w, const char *data, size_t len) {
if (w->len + len > w->cap) {
w->cap += w->len + WATCHMAN_DEFAULT_STORAGE;
REALLOC_N(w->data, uint8_t, w->cap);
}
memcpy(w->data + w->len, data, len);
w->len += len;
}
/**
* Allocate a new watchman_t struct
*
* The struct has a small amount of extra capacity preallocated, and a blank
* header that can be filled in later to describe the PDU.
*/
watchman_t *watchman_init() {
watchman_t *w = ALLOC(watchman_t);
w->cap = WATCHMAN_DEFAULT_STORAGE;
w->len = 0;
w->data = ALLOC_N(uint8_t, WATCHMAN_DEFAULT_STORAGE);
watchman_append(w, WATCHMAN_HEADER, sizeof(WATCHMAN_HEADER) - 1);
return w;
}
/**
* Free a watchman_t struct `w` that was previously allocated with
* `watchman_init`
*/
void watchman_free(watchman_t *w) {
xfree(w->data);
xfree(w);
}
/**
* Encodes and appends the integer `num` to `w`
*/
void watchman_dump_int(watchman_t *w, int64_t num) {
char encoded[1 + sizeof(int64_t)];
if (num == (int8_t)num) {
encoded[0] = WATCHMAN_INT8_MARKER;
encoded[1] = (int8_t)num;
watchman_append(w, encoded, 1 + sizeof(int8_t));
} else if (num == (int16_t)num) {
encoded[0] = WATCHMAN_INT16_MARKER;
*(int16_t *)(encoded + 1) = (int16_t)num;
watchman_append(w, encoded, 1 + sizeof(int16_t));
} else if (num == (int32_t)num) {
encoded[0] = WATCHMAN_INT32_MARKER;
*(int32_t *)(encoded + 1) = (int32_t)num;
watchman_append(w, encoded, 1 + sizeof(int32_t));
} else {
encoded[0] = WATCHMAN_INT64_MARKER;
*(int64_t *)(encoded + 1) = (int64_t)num;
watchman_append(w, encoded, 1 + sizeof(int64_t));
}
}
/**
* Encodes and appends the string `string` to `w`
*/
void watchman_dump_string(watchman_t *w, VALUE string) {
watchman_append(w, &watchman_string_marker, sizeof(watchman_string_marker));
watchman_dump_int(w, RSTRING_LEN(string));
watchman_append(w, RSTRING_PTR(string), RSTRING_LEN(string));
}
/**
* Encodes and appends the double `num` to `w`
*/
void watchman_dump_double(watchman_t *w, double num) {
char encoded[1 + sizeof(double)];
encoded[0] = WATCHMAN_FLOAT_MARKER;
*(double *)(encoded + 1) = num;
watchman_append(w, encoded, sizeof(encoded));
}
/**
* Encodes and appends the array `array` to `w`
*/
void watchman_dump_array(watchman_t *w, VALUE array) {
long i;
watchman_append(w, &watchman_array_marker, sizeof(watchman_array_marker));
watchman_dump_int(w, RARRAY_LEN(array));
for (i = 0; i < RARRAY_LEN(array); i++) {
watchman_dump(w, rb_ary_entry(array, i));
}
}
/**
* Helper method that encodes and appends a key/value pair (`key`, `value`) from
* a hash to the watchman_t struct passed in via `data`
*/
int watchman_dump_hash_iterator(VALUE key, VALUE value, VALUE data) {
watchman_t *w = (watchman_t *)data;
watchman_dump_string(w, StringValue(key));
watchman_dump(w, value);
return ST_CONTINUE;
}
/**
* Encodes and appends the hash `hash` to `w`
*/
void watchman_dump_hash(watchman_t *w, VALUE hash) {
watchman_append(w, &watchman_hash_marker, sizeof(watchman_hash_marker));
watchman_dump_int(w, RHASH_SIZE(hash));
rb_hash_foreach(hash, watchman_dump_hash_iterator, (VALUE)w);
}
/**
* Encodes and appends the serialized Ruby object `serializable` to `w`
*
* Examples of serializable objects include arrays, hashes, strings, numbers
* (integers, floats), booleans, and nil.
*/
void watchman_dump(watchman_t *w, VALUE serializable) {
switch (TYPE(serializable)) {
case T_ARRAY:
return watchman_dump_array(w, serializable);
case T_HASH:
return watchman_dump_hash(w, serializable);
case T_STRING:
return watchman_dump_string(w, serializable);
case T_FIXNUM: // up to 63 bits
return watchman_dump_int(w, FIX2LONG(serializable));
case T_BIGNUM:
return watchman_dump_int(w, NUM2LL(serializable));
case T_FLOAT:
return watchman_dump_double(w, NUM2DBL(serializable));
case T_TRUE:
return watchman_append(w, &watchman_true, sizeof(watchman_true));
case T_FALSE:
return watchman_append(w, &watchman_false, sizeof(watchman_false));
case T_NIL:
return watchman_append(w, &watchman_nil, sizeof(watchman_nil));
default:
rb_raise(rb_eTypeError, "unsupported type");
}
}
/**
* Extract and return the int encoded at `ptr`
*
* Moves `ptr` past the extracted int.
*
* Will raise an ArgumentError if extracting the int would take us beyond the
* end of the buffer indicated by `end`, or if there is no int encoded at `ptr`.
*
* @returns The extracted int
*/
int64_t watchman_load_int(char **ptr, char *end) {
char *val_ptr = *ptr + sizeof(int8_t);
int64_t val = 0;
if (val_ptr >= end) {
rb_raise(rb_eArgError, "insufficient int storage");
}
switch (*ptr[0]) {
case WATCHMAN_INT8_MARKER:
if (val_ptr + sizeof(int8_t) > end) {
rb_raise(rb_eArgError, "overrun extracting int8_t");
}
val = *(int8_t *)val_ptr;
*ptr = val_ptr + sizeof(int8_t);
break;
case WATCHMAN_INT16_MARKER:
if (val_ptr + sizeof(int16_t) > end) {
rb_raise(rb_eArgError, "overrun extracting int16_t");
}
val = *(int16_t *)val_ptr;
*ptr = val_ptr + sizeof(int16_t);
break;
case WATCHMAN_INT32_MARKER:
if (val_ptr + sizeof(int32_t) > end) {
rb_raise(rb_eArgError, "overrun extracting int32_t");
}
val = *(int32_t *)val_ptr;
*ptr = val_ptr + sizeof(int32_t);
break;
case WATCHMAN_INT64_MARKER:
if (val_ptr + sizeof(int64_t) > end) {
rb_raise(rb_eArgError, "overrun extracting int64_t");
}
val = *(int64_t *)val_ptr;
*ptr = val_ptr + sizeof(int64_t);
break;
default:
rb_raise(rb_eArgError, "bad integer marker 0x%02x", (unsigned int)*ptr[0]);
break;
}
return val;
}
/**
* Reads and returns a string encoded in the Watchman binary protocol format,
* starting at `ptr` and finishing at or before `end`
*/
VALUE watchman_load_string(char **ptr, char *end) {
if (*ptr >= end) {
rb_raise(rb_eArgError, "unexpected end of input");
}
if (*ptr[0] != WATCHMAN_STRING_MARKER) {
rb_raise(rb_eArgError, "not a number");
}
*ptr += sizeof(int8_t);
if (*ptr >= end) {
rb_raise(rb_eArgError, "invalid string header");
}
int64_t len = watchman_load_int(ptr, end);
if (len == 0) { // special case for zero-length strings
return rb_str_new2("");
} else if (*ptr + len > end) {
rb_raise(rb_eArgError, "insufficient string storage");
}
VALUE string = rb_str_new(*ptr, len);
*ptr += len;
return string;
}
/**
* Reads and returns a double encoded in the Watchman binary protocol format,
* starting at `ptr` and finishing at or before `end`
*/
double watchman_load_double(char **ptr, char *end) {
*ptr += sizeof(int8_t); // caller has already verified the marker
if (*ptr + sizeof(double) > end) {
rb_raise(rb_eArgError, "insufficient double storage");
}
double val = *(double *)*ptr;
*ptr += sizeof(double);
return val;
}
/**
* Helper method which returns length of the array encoded in the Watchman
* binary protocol format, starting at `ptr` and finishing at or before `end`
*/
int64_t watchman_load_array_header(char **ptr, char *end) {
if (*ptr >= end) {
rb_raise(rb_eArgError, "unexpected end of input");
}
// verify and consume marker
if (*ptr[0] != WATCHMAN_ARRAY_MARKER) {
rb_raise(rb_eArgError, "not an array");
}
*ptr += sizeof(int8_t);
// expect a count
if (*ptr + sizeof(int8_t) * 2 > end) {
rb_raise(rb_eArgError, "incomplete array header");
}
return watchman_load_int(ptr, end);
}
/**
* Reads and returns an array encoded in the Watchman binary protocol format,
* starting at `ptr` and finishing at or before `end`
*/
VALUE watchman_load_array(char **ptr, char *end) {
int64_t count, i;
VALUE array;
count = watchman_load_array_header(ptr, end);
array = rb_ary_new2(count);
for (i = 0; i < count; i++) {
rb_ary_push(array, watchman_load(ptr, end));
}
return array;
}
/**
* Reads and returns a hash encoded in the Watchman binary protocol format,
* starting at `ptr` and finishing at or before `end`
*/
VALUE watchman_load_hash(char **ptr, char *end) {
int64_t count, i;
VALUE hash, key, value;
*ptr += sizeof(int8_t); // caller has already verified the marker
// expect a count
if (*ptr + sizeof(int8_t) * 2 > end) {
rb_raise(rb_eArgError, "incomplete hash header");
}
count = watchman_load_int(ptr, end);
hash = rb_hash_new();
for (i = 0; i < count; i++) {
key = watchman_load_string(ptr, end);
value = watchman_load(ptr, end);
rb_hash_aset(hash, key, value);
}
return hash;
}
/**
* Reads and returns a templated array encoded in the Watchman binary protocol
* format, starting at `ptr` and finishing at or before `end`
*
* Templated arrays are arrays of hashes which have repetitive key information
* pulled out into a separate "headers" prefix.
*
* @see https://github.com/facebook/watchman/blob/master/BSER.markdown
*/
VALUE watchman_load_template(char **ptr, char *end) {
int64_t header_items_count, i, row_count;
VALUE array, hash, header, key, value;
*ptr += sizeof(int8_t); // caller has already verified the marker
// process template header array
header_items_count = watchman_load_array_header(ptr, end);
header = rb_ary_new2(header_items_count);
for (i = 0; i < header_items_count; i++) {
rb_ary_push(header, watchman_load_string(ptr, end));
}
// process row items
row_count = watchman_load_int(ptr, end);
array = rb_ary_new2(header_items_count);
while (row_count--) {
hash = rb_hash_new();
for (i = 0; i < header_items_count; i++) {
if (*ptr >= end) {
rb_raise(rb_eArgError, "unexpected end of input");
}
if (*ptr[0] == WATCHMAN_SKIP_MARKER) {
*ptr += sizeof(uint8_t);
} else {
value = watchman_load(ptr, end);
key = rb_ary_entry(header, i);
rb_hash_aset(hash, key, value);
}
}
rb_ary_push(array, hash);
}
return array;
}
/**
* Reads and returns an object encoded in the Watchman binary protocol format,
* starting at `ptr` and finishing at or before `end`
*/
VALUE watchman_load(char **ptr, char *end) {
if (*ptr >= end) {
rb_raise(rb_eArgError, "unexpected end of input");
}
switch (*ptr[0]) {
case WATCHMAN_ARRAY_MARKER:
return watchman_load_array(ptr, end);
case WATCHMAN_HASH_MARKER:
return watchman_load_hash(ptr, end);
case WATCHMAN_STRING_MARKER:
return watchman_load_string(ptr, end);
case WATCHMAN_INT8_MARKER:
case WATCHMAN_INT16_MARKER:
case WATCHMAN_INT32_MARKER:
case WATCHMAN_INT64_MARKER:
return LL2NUM(watchman_load_int(ptr, end));
case WATCHMAN_FLOAT_MARKER:
return rb_float_new(watchman_load_double(ptr, end));
case WATCHMAN_TRUE:
*ptr += 1;
return Qtrue;
case WATCHMAN_FALSE:
*ptr += 1;
return Qfalse;
case WATCHMAN_NIL:
*ptr += 1;
return Qnil;
case WATCHMAN_TEMPLATE_MARKER:
return watchman_load_template(ptr, end);
default:
rb_raise(rb_eTypeError, "unsupported type");
}
return Qnil; // keep the compiler happy
}
/**
* CommandT::Watchman::Utils.load(serialized)
*
* Converts the binary object, `serialized`, from the Watchman binary protocol
* format into a normal Ruby object.
*/
VALUE CommandTWatchmanUtils_load(VALUE self, VALUE serialized) {
serialized = StringValue(serialized);
long len = RSTRING_LEN(serialized);
char *ptr = RSTRING_PTR(serialized);
char *end = ptr + len;
// expect at least the binary marker and a int8_t length counter
if ((size_t)len < sizeof(WATCHMAN_BINARY_MARKER) - 1 + sizeof(int8_t) * 2) {
rb_raise(rb_eArgError, "undersized header");
}
if (memcmp(ptr, WATCHMAN_BINARY_MARKER, sizeof(WATCHMAN_BINARY_MARKER) - 1)) {
rb_raise(rb_eArgError, "missing binary marker");
}
// get size marker
ptr += sizeof(WATCHMAN_BINARY_MARKER) - 1;
uint64_t payload_size = watchman_load_int(&ptr, end);
if (!payload_size) {
rb_raise(rb_eArgError, "empty payload");
}
// sanity check length
if (ptr + payload_size != end) {
rb_raise(rb_eArgError, "payload size mismatch (%lu)", end - (ptr + payload_size));
}
VALUE loaded = watchman_load(&ptr, end);
// one more sanity check
if (ptr != end) {
rb_raise(rb_eArgError, "payload termination mismatch (%lu)", end - ptr);
}
return loaded;
}
/**
* CommandT::Watchman::Utils.dump(serializable)
*
* Converts the Ruby object, `serializable`, into a binary string in the
* Watchman binary protocol format.
*
* Examples of serializable objects include arrays, hashes, strings, numbers
* (integers, floats), booleans, and nil.
*/
VALUE CommandTWatchmanUtils_dump(VALUE self, VALUE serializable) {
watchman_t *w = watchman_init();
watchman_dump(w, serializable);
// update header with final length information
uint64_t *len = (uint64_t *)(w->data + sizeof(WATCHMAN_HEADER) - sizeof(uint64_t) - 1);
*len = w->len - sizeof(WATCHMAN_HEADER) + 1;
// prepare final return value
VALUE serialized = rb_str_buf_new(w->len);
rb_str_buf_cat(serialized, (const char*)w->data, w->len);
watchman_free(w);
return serialized;
}
/**
* Helper method for raising a SystemCallError wrapping a lower-level error code
* coming from the `errno` global variable.
*/
void watchman_raise_system_call_error(int number) {
VALUE error = INT2FIX(number);
rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
}
// How far we have to look to figure out the size of the PDU header
#define WATCHMAN_SNIFF_BUFFER_SIZE sizeof(WATCHMAN_BINARY_MARKER) - 1 + sizeof(int8_t)
// How far we have to peek, at most, to figure out the size of the PDU itself
#define WATCHMAN_PEEK_BUFFER_SIZE \
sizeof(WATCHMAN_BINARY_MARKER) - 1 + \
sizeof(WATCHMAN_INT64_MARKER) + \
sizeof(int64_t)
/**
* CommandT::Watchman::Utils.query(query, socket)
*
* Converts `query`, a Watchman query comprising Ruby objects, into the Watchman
* binary protocol format, transmits it over socket, and unserializes and
* returns the result.
*/
VALUE CommandTWatchmanUtils_query(VALUE self, VALUE query, VALUE socket) {
int fileno = NUM2INT(rb_funcall(socket, rb_intern("fileno"), 0));
// do blocking I/O to simplify the following logic
int flags = fcntl(fileno, F_GETFL);
if (fcntl(fileno, F_SETFL, flags & ~O_NONBLOCK) == -1) {
rb_raise(rb_eRuntimeError, "unable to clear O_NONBLOCK flag");
}
// send the message
VALUE serialized = CommandTWatchmanUtils_dump(self, query);
long query_len = RSTRING_LEN(serialized);
ssize_t sent = send(fileno, RSTRING_PTR(serialized), query_len, 0);
if (sent == -1) {
watchman_raise_system_call_error(errno);
} else if (sent != query_len) {
rb_raise(rb_eRuntimeError, "expected to send %ld bytes but sent %ld",
query_len, sent);
}
// sniff to see how large the header is
int8_t peek[WATCHMAN_PEEK_BUFFER_SIZE];
ssize_t received = recv(fileno, peek, WATCHMAN_SNIFF_BUFFER_SIZE, MSG_PEEK | MSG_WAITALL);
if (received == -1) {
watchman_raise_system_call_error(errno);
} else if (received != WATCHMAN_SNIFF_BUFFER_SIZE) {
rb_raise(rb_eRuntimeError, "failed to sniff PDU header");
}
// peek at size of PDU
int8_t sizes[] = { 0, 0, 0, 1, 2, 4, 8 };
ssize_t peek_size = sizeof(WATCHMAN_BINARY_MARKER) - 1 + sizeof(int8_t) +
sizes[peek[sizeof(WATCHMAN_BINARY_MARKER) - 1]];
received = recv(fileno, peek, peek_size, MSG_PEEK);
if (received == -1) {
watchman_raise_system_call_error(errno);
} else if (received != peek_size) {
rb_raise(rb_eRuntimeError, "failed to peek at PDU header");
}
int8_t *pdu_size_ptr = peek + sizeof(WATCHMAN_BINARY_MARKER) - sizeof(int8_t);
int64_t payload_size =
peek_size +
watchman_load_int((char **)&pdu_size_ptr, (char *)peek + peek_size);
// actually read the PDU
void *buffer = xmalloc(payload_size);
if (!buffer) {
rb_raise(rb_eNoMemError, "failed to allocate %lld bytes", payload_size);
}
received = recv(fileno, buffer, payload_size, MSG_WAITALL);
if (received == -1) {
watchman_raise_system_call_error(errno);
} else if (received != payload_size) {
rb_raise(rb_eRuntimeError, "failed to load PDU");
}
char *payload = buffer + peek_size;
VALUE loaded = watchman_load(&payload, payload + payload_size);
free(buffer);
return loaded;
}
#else /* don't build Watchman utils; supply stubs only*/
VALUE CommandTWatchmanUtils_load(VALUE self, VALUE serialized) {
rb_raise(rb_eRuntimeError, "unsupported operation");
}
VALUE CommandTWatchmanUtils_dump(VALUE self, VALUE serializable) {
rb_raise(rb_eRuntimeError, "unsupported operation");
}
VALUE CommandTWatchmanUtils_query(VALUE self, VALUE query, VALUE socket) {
rb_raise(rb_eRuntimeError, "unsupported operation");
}
#endif
// Copyright 2014 Wincent Colaiuta. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. 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 HOLDERS 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.
#include <ruby.h>
/**
* @module CommandT::Watchman::Utils
*
* Methods for working with the Watchman binary protocol
*
* @see https://github.com/facebook/watchman/blob/master/BSER.markdown
*/
/**
* Convert an object serialized using the Watchman binary protocol[0] into an
* unpacked Ruby object
*/
extern VALUE CommandTWatchmanUtils_load(VALUE self, VALUE serialized);
/**
* Serialize a Ruby object into the Watchman binary protocol format
*/
extern VALUE CommandTWatchmanUtils_dump(VALUE self, VALUE serializable);
/**
* Issue `query` to the Watchman instance listening on `socket` (a `UNIXSocket`
* instance) and return the result
*
* The query is serialized following the Watchman binary protocol and the
* result is converted to native Ruby objects before returning to the caller.
*/
extern VALUE CommandTWatchmanUtils_query(VALUE self, VALUE query, VALUE socket);
# Global snippets
# (c) holds no legal value ;)
snippet c)
`&enc[:2] == "utf" ? "©" : "(c)"` Copyright `strftime("%Y")` ${1:`g:snips_author`}. All Rights Reserved.${2}
snippet date
`strftime("%Y-%m-%d")`
snippet if
If ${1:condition} Then
${2:; True code}
EndIf
snippet el
Else
${1}
snippet elif
ElseIf ${1:condition} Then
${2:; True code}
# If/Else block
snippet ifel
If ${1:condition} Then
${2:; True code}
Else
${3:; Else code}
EndIf
# If/ElseIf/Else block
snippet ifelif
If ${1:condition 1} Then
${2:; True code}
ElseIf ${3:condition 2} Then
${4:; True code}
Else
${5:; Else code}
EndIf
# Switch block
snippet switch
Switch (${1:condition})
Case {$2:case1}:
{$3:; Case 1 code}
Case Else:
{$4:; Else code}
EndSwitch
# Select block
snippet select
Select (${1:condition})
Case {$2:case1}:
{$3:; Case 1 code}
Case Else:
{$4:; Else code}
EndSelect
# While loop
snippet while
While (${1:condition})
${2:; code...}
WEnd
# For loop
snippet for
For ${1:n} = ${3:1} to ${2:count}
${4:; code...}
Next
# New Function
snippet func
Func ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
${4:Return}
EndFunc
# Message box
snippet msg
MsgBox(${3:MsgType}, ${1:"Title"}, ${2:"Message Text"})
# Debug Message
snippet debug
MsgBox(0, "Debug", ${1:"Debug Message"})
# Show Variable Debug Message
snippet showvar
MsgBox(0, "${1:VarName}", $1)
# main()
snippet main
int main(int argc, const char *argv[])
{
${1}
return 0;
}
# #include <...>
snippet inc
#include <${1:stdio}.h>${2}
# #include "..."
snippet Inc
#include "${1:`Filename("$1.h")`}"${2}
# #ifndef ... #define ... #endif
snippet Def
#ifndef $1
#define ${1:SYMBOL} ${2:value}
#endif${3}
snippet def
#define
snippet ifdef
#ifdef ${1:FOO}
${2:#define }
#endif
snippet #if
#if ${1:FOO}
${2}
#endif
# Header Include-Guard
# (the randomizer code is taken directly from TextMate; it could probably be
# cleaner, I don't know how to do it in vim script)
snippet once
#ifndef ${1:`toupper(Filename('', 'UNTITLED').'_'.system("/usr/bin/ruby -e 'print (rand * 2821109907455).round.to_s(36)'"))`}
#define $1
${2}
#endif /* end of include guard: $1 */
# If Condition
snippet if
if (${1:/* condition */}) {
${2:/* code */}
}
snippet el
else {
${1}
}
# Tertiary conditional
snippet t
${1:/* condition */} ? ${2:a} : ${3:b}
# Do While Loop
snippet do
do {
${2:/* code */}
} while (${1:/* condition */});
# While Loop
snippet wh
while (${1:/* condition */}) {
${2:/* code */}
}
# For Loop
snippet for
for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) {
${4:/* code */}
}
# Custom For Loop
snippet forr
for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) {
${5:/* code */}
}
# Function
snippet fun
${1:void} ${2:function_name}(${3})
{
${4:/* code */}
}
# Function Declaration
snippet fund
${1:void} ${2:function_name}(${3});${4}
# Typedef
snippet td
typedef ${1:int} ${2:MyCustomType};${3}
# Struct
snippet st
struct ${1:`Filename('$1_t', 'name')`} {
${2:/* data */}
}${3: /* optional variable list */};${4}
# Typedef struct
snippet tds
typedef struct ${2:_$1 }{
${3:/* data */}
} ${1:`Filename('$1_t', 'name')`};
# Typdef enum
snippet tde
typedef enum {
${1:/* data */}
} ${2:foo};
# printf
# unfortunately version this isn't as nice as TextMates's, given the lack of a
# dynamic `...`
snippet pr
printf("${1:%s}\n"${2});${3}
# fprintf (again, this isn't as nice as TextMate's version, but it works)
snippet fpr
fprintf(${1:stderr}, "${2:%s}\n"${3});${4}
snippet .
[${1}]${2}
snippet un
unsigned
# Read File Into Vector
snippet readfile
std::vector<char> v;
if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) {
char buf[1024];
while (size_t len = fread(buf, 1, sizeof(buf), $2))
v.insert(v.end(), buf, buf + len);
fclose($2);
}${3}
# std::map
snippet map
std::map<${1:key}, ${2:value}> map${3};
# std::vector
snippet vector
std::vector<${1:char}> v${2};
# Namespace
snippet ns
namespace ${1:`Filename('', 'my')`} {
${2}
} /* $1 */
# Class
snippet cl
class ${1:`Filename('$1_t', 'name')`} {
public:
$1 (${2:arguments});
virtual ~$1 ();
private:
${3:/* data */}
};
# Some useful Unicode entities
# Non-Breaking Space
snippet nbs
&nbsp;
# ←
snippet left
&#x2190;
# →
snippet right
&#x2192;
# ↑
snippet up
&#x2191;
# ↓
snippet down
&#x2193;
# ↩
snippet return
&#x21A9;
# ⇤
snippet backtab
&#x21E4;
# ⇥
snippet tab
&#x21E5;
# ⇧
snippet shift
&#x21E7;
# ⌃
snippet control
&#x2303;
# ⌅
snippet enter
&#x2305;
# ⌘
snippet command
&#x2318;
# ⌥
snippet option
&#x2325;
# ⌦
snippet delete
&#x2326;
# ⌫
snippet backspace
&#x232B;
# ⎋
snippet escape
&#x238B;
# Generic Doctype
snippet doctype HTML 4.01 Strict
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
"http://www.w3.org/TR/html4/strict.dtd">
snippet doctype HTML 4.01 Transitional
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""
"http://www.w3.org/TR/html4/loose.dtd">
snippet doctype HTML 5
<!DOCTYPE HTML>
snippet doctype XHTML 1.0 Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
snippet doctype XHTML 1.0 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
snippet doctype XHTML 1.0 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
snippet doctype XHTML 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
# HTML Doctype 4.01 Strict
snippet docts
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
"http://www.w3.org/TR/html4/strict.dtd">
# HTML Doctype 4.01 Transitional
snippet doct
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""
"http://www.w3.org/TR/html4/loose.dtd">
# HTML Doctype 5
snippet doct5
<!DOCTYPE HTML>
# XHTML Doctype 1.0 Frameset
snippet docxf
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
# XHTML Doctype 1.0 Strict
snippet docxs
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
# XHTML Doctype 1.0 Transitional
snippet docxt
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
# XHTML Doctype 1.1
snippet docx
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
snippet html
<html>
${1}
</html>
snippet xhtml
<html xmlns="http://www.w3.org/1999/xhtml">
${1}
</html>
snippet body
<body>
${1}
</body>
snippet head
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"`Close()`>
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>
${2}
</head>
snippet title
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>${2}
snippet script
<script type="text/javascript" charset="utf-8">
${1}
</script>${2}
snippet scriptsrc
<script src="${1}.js" type="text/javascript" charset="utf-8"></script>${2}
snippet style
<style type="text/css" media="${1:screen}">
${2}
</style>${3}
snippet base
<base href="${1}" target="${2}"`Close()`>
snippet r
<br`Close()[1:]`>
snippet div
<div id="${1:name}">
${2}
</div>
# Embed QT Movie
snippet movie
<object width="$2" height="$3" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab">
<param name="src" value="$1"`Close()`>
<param name="controller" value="$4"`Close()`>
<param name="autoplay" value="$5"`Close()`>
<embed src="${1:movie.mov}"
width="${2:320}" height="${3:240}"
controller="${4:true}" autoplay="${5:true}"
scale="tofit" cache="true"
pluginspage="http://www.apple.com/quicktime/download/"
`Close()[1:]`>
</object>${6}
snippet fieldset
<fieldset id="$1">
<legend>${1:name}</legend>
${3}
</fieldset>
snippet form
<form action="${1:`Filename('$1_submit')`}" method="${2:get}" accept-charset="utf-8">
${3}
<p><input type="submit" value="Continue &rarr;"`Close()`></p>
</form>
snippet h1
<h1 id="${1:heading}">${2:$1}</h1>
snippet input
<input type="${1:text/submit/hidden/button}" name="${2:some_name}" value="${3}"`Close()`>${4}
snippet label
<label for="${2:$1}">${1:name}</label><input type="${3:text/submit/hidden/button}" name="${4:$2}" value="${5}" id="${6:$2}"`Close()`>${7}
snippet link
<link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" charset="utf-8"`Close()`>${4}
snippet mailto
<a href="mailto:${1:joe@example.com}?subject=${2:feedback}">${3:email me}</a>
snippet meta
<meta name="${1:name}" content="${2:content}"`Close()`>${3}
snippet opt
<option value="${1:option}">${2:$1}</option>${3}
snippet optt
<option>${1:option}</option>${2}
snippet select
<select name="${1:some_name}" id="${2:$1}">
<option value="${3:option}">${4:$3}</option>
</select>${5}
snippet table
<table border="${1:0}">
<tr><th>${2:Header}</th></tr>
<tr><th>${3:Data}</th></tr>
</table>${4}
snippet textarea
<textarea name="${1:Name}" rows="${2:8}" cols="${3:40}">${4}</textarea>${5}
snippet main
public static void main (String [] args)
{
${1:/* code */}
}
snippet pu
public
snippet po
protected
snippet pr
private
snippet st
static
snippet fi
final
snippet ab
abstract
snippet re
return
snippet br
break;
snippet de
default:
${1}
snippet ca
catch(${1:Exception} ${2:e}) ${3}
snippet th
throw
snippet sy
synchronized
snippet im
import
snippet j.u
java.util
snippet j.i
java.io.
snippet j.b
java.beans.
snippet j.n
java.net.
snippet j.m
java.math.
snippet if
if (${1}) ${2}
snippet el
else
snippet elif
else if (${1}) ${2}
snippet wh
while (${1}) ${2}
snippet for
for (${1}; ${2}; ${3}) ${4}
snippet fore
for (${1} : ${2}) ${3}
snippet sw
switch (${1}) ${2}
snippet cs
case ${1}:
${2}
${3}
snippet tc
public class ${1:`Filename()`} extends ${2:TestCase}
snippet t
public void test${1:Name}() throws Exception ${2}
snippet cl
class ${1:`Filename("", "untitled")`} ${2}
snippet in
interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3}
snippet m
${1:void} ${2:method}(${3}) ${4:throws }${5}
snippet v
${1:String} ${2:var}${3: = null}${4};${5}
snippet co
static public final ${1:String} ${2:var} = ${3};${4}
snippet cos
static public final String ${1:var} = "${2}";${3}
snippet as
assert ${1:test} : "${2:Failure message}";${3}
# Prototype
snippet proto
${1:class_name}.prototype.${2:method_name} =
function(${3:first_argument}) {
${4:// body...}
};
# Function
snippet fun
function ${1:function_name} (${2:argument}) {
${3:// body...}
}
# Anonymous Function
snippet f
function(${1}) {${2}};
# if
snippet if
if (${1:true}) {${2}};
# if ... else
snippet ife
if (${1:true}) {${2}}
else{${3}};
# tertiary conditional
snippet t
${1:/* condition */} ? ${2:a} : ${3:b}
# switch
snippet switch
switch(${1:expression}) {
case '${3:case}':
${4:// code}
break;
${5}
default:
${2:// code}
}
# case
snippet case
case '${1:case}':
${2:// code}
break;
${3}
# for (...) {...}
snippet for
for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) {
${4:$1[$2]}
};
# for (...) {...} (Improved Native For-Loop)
snippet forr
for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) {
${4:$1[$2]}
};
# while (...) {...}
snippet wh
while (${1:/* condition */}) {
${2:/* code */}
}
# do...while
snippet do
do {
${2:/* code */}
} while (${1:/* condition */});
# Object Method
snippet :f
${1:method_name}: function(${2:attribute}) {
${4}
}${3:,}
# setTimeout function
snippet timeout
setTimeout(function() {${3}}${2}, ${1:10};
# Get Elements
snippet get
getElementsBy${1:TagName}('${2}')${3}
# Get Element
snippet gett
getElementBy${1:Id}('${2}')${3}
snippet def
<%def name="${1:name}">
${2:}
</%def>
snippet call
<%call expr="${1:name}">
${2:}
</%call>
snippet doc
<%doc>
${1:}
</%doc>
snippet text
<%text>
${1:}
</%text>
snippet for
% for ${1:i} in ${2:iter}:
${3:}
% endfor
snippet if if
% if ${1:condition}:
${2:}
% endif
snippet if if/else
% if ${1:condition}:
${2:}
% else:
${3:}
% endif
snippet try
% try:
${1:}
% except${2:}:
${3:pass}
% endtry
snippet wh
% while ${1:}:
${2:}
% endwhile
snippet $
${ ${1:} }
snippet <%
<% ${1:} %>
snippet <!%
<!% ${1:} %>
snippet inherit
<%inherit file="${1:filename}" />
snippet include
<%include file="${1:filename}" />
snippet namespace
<%namespace file="${1:name}" />
snippet page
<%page args="${1:}" />
# #import <...>
snippet Imp
#import <${1:Cocoa/Cocoa.h}>${2}
# #import "..."
snippet imp
#import "${1:`Filename()`.h}"${2}
# @selector(...)
snippet sel
@selector(${1:method}:)${3}
# @"..." string
snippet s
@"${1}"${2}
# Object
snippet o
${1:NSObject} *${2:foo} = [${3:$1 alloc}]${4};${5}
# NSLog(...)
snippet log
NSLog(@"${1:%@}"${2});${3}
# Class
snippet objc
@interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
{
}
@end
@implementation $1
${3}
@end
# Class Interface
snippet int
@interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
{${3}
}
${4}
@end
# Class Implementation
snippet impl
@implementation ${1:`Filename('', 'someClass')`}
${2}
@end
snippet init
- (id)init
{
[super init];
return self;
}
snippet ifself
if (self = [super init]) {
${1:/* code */}
}
return self;
snippet ibo
IBOutlet ${1:NSSomeClass} *${2:$1};${3}
# Category
snippet cat
@interface ${1:NSObject} (${2:Category})
@end
@implementation $1 ($2)
${3}
@end
# Category Interface
snippet cath
@interface ${1:NSObject} (${2:Category})
${3}
@end
# NSArray
snippet array
NSMutableArray *${1:array} = [NSMutable array];${2}
# NSDictionary
snippet dict
NSMutableDictionary *${1:dict} = [NSMutableDictionary dictionary];${2}
# NSBezierPath
snippet bez
NSBezierPath *${1:path} = [NSBezierPath bezierPath];${2}
# Method
snippet m
- (${1:id})${2:method}
{
${3}
}
# Method declaration
snippet md
- (${1:id})${2:method};${3}
# IBAction declaration
snippet ibad
- (IBAction)${1:method}:(${2:id})sender;${3}
# IBAction method
snippet iba
- (IBAction)${1:method}:(${2:id})sender
{
${3}
}
# awakeFromNib method
snippet wake
- (void)awakeFromNib
{
${1}
}
# Class Method
snippet M
+ (${1:id})${2:method}
{${3}
return nil;
}
# Sub-method (Call super)
snippet sm
- (${1:id})${2:method}
{
[super $2];${3}
return self;
}
# Method: Initialize
snippet I
+ (void) initialize
{
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWIthObjectsAndKeys:
${1}@"value", @"key",
nil]];
}
# Accessor Methods For:
# Object
snippet objacc
- (${1:id})${2:thing}
{
return $2;
}
- (void)set$2:($1)${3:new$2}
{
[$3 retain];
[$2 release];
$2 = $3;
}${4}
# for (object in array)
snippet forin
for (${1:Class} *${2:some$1} in ${3:array}) {
${4}
}
snippet forarray
unsigned int ${1:object}Count = [${2:array} count];
for (unsigned int index = 0; index < $1Count; index++) {
${3:id} $1 = [$2 $1AtIndex:index];
${4}
}
# IBOutlet
# @property (Objective-C 2.0)
snippet prop
@property (${1:retain}) ${2:NSSomeClass} ${3:*$2};${4}
# @synthesize (Objective-C 2.0)
snippet syn
@synthesize ${1:property};${2}
# [[ alloc] init]
snippet alloc
[[${1:foo} alloc] init${2}];${3}
# retain
snippet ret
[${1:foo} retain];${2}
# release
snippet rel
[${1:foo} release];
${2:$1 = nil;}
# autorelease
snippet arel
[${1:foo} autorelease];
# autorelease pool
snippet pool
NSAutoreleasePool *${1:pool} = [[NSAutoreleasePool alloc] init];
${2:/* code */}
[$1 drain];
# Throw an exception
snippet except
NSException *${1:badness};
$1 = [NSException exceptionWithName:@"${2:$1Name}"
reason:@"${3}"
userInfo:nil];
[$1 raise];
snippet prag
#pragma mark ${1:foo}
snippet cl
@class ${1:Foo};${2}
snippet color
[[NSColor ${1:blackColor}] set];
# #!/usr/bin/perl
snippet #!
#!/usr/bin/perl
# Hash Pointer
snippet .
=>
# Function
snippet sub
sub ${1:function_name} {
${2:#body ...}
}
# Conditional
snippet if
if (${1}) {
${2:# body...}
}
# Conditional if..else
snippet ife
if (${1}) {
${2:# body...}
} else {
${3:# else...}
}
# Conditional if..elsif..else
snippet ifee
if (${1}) {
${2:# body...}
} elsif (${3}) {
${4:# elsif...}
} else {
${5:# else...}
}
# Conditional One-line
snippet xif
${1:expression} if ${2:condition};${3}
# Unless conditional
snippet unless
unless (${1}) {
${2:# body...}
}
# Unless conditional One-line
snippet xunless
${1:expression} unless ${2:condition};${3}
# Try/Except
snippet eval
eval {
${1:# do something risky...}
};
if ($@) {
${2:# handle failure...}
}
# While Loop
snippet wh
while (${1}) {
${2:# body...}
}
# While Loop One-line
snippet xwh
${1:expression} while ${2:condition};${3}
# For Loop
snippet for
for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) {
${4:# body...}
}
# Foreach Loop
snippet fore
foreach my $${1:x} (@${2:array}) {
${3:# body...}
}
# Foreach Loop One-line
snippet xfore
${1:expression} foreach @${2:array};${3}
# Package
snippet cl
package ${1:ClassName};
use base qw(${2:ParentClass});
sub new {
my $class = shift;
$class = ref $class if ref $class;
my $self = bless {}, $class;
$self;
}
1;${3}
# Read File
snippet slurp
my $${1:var};
{ local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = <FILE>; close FILE }${3}
snippet php
<?php
${1}
?>
snippet ec
echo "${1:string}"${2};
snippet inc
include '${1:file}';${2}
snippet inc1
include_once '${1:file}';${2}
snippet req
require '${1:file}';${2}
snippet req1
require_once '${1:file}';${2}
# $GLOBALS['...']
snippet globals
$GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5}
snippet $_ COOKIE['...']
$_COOKIE['${1:variable}']${2}
snippet $_ ENV['...']
$_ENV['${1:variable}']${2}
snippet $_ FILES['...']
$_FILES['${1:variable}']${2}
snippet $_ Get['...']
$_GET['${1:variable}']${2}
snippet $_ POST['...']
$_POST['${1:variable}']${2}
snippet $_ REQUEST['...']
$_REQUEST['${1:variable}']${2}
snippet $_ SERVER['...']
$_SERVER['${1:variable}']${2}
snippet $_ SESSION['...']
$_SESSION['${1:variable}']${2}
# Start Docblock
snippet /*
/**
* ${1}
**/
# Class - post doc
snippet doc_cp
/**
* ${1:undocumented class}
*
* @package ${2:default}
* @author ${3:`g:snips_author`}
**/${4}
# Class Variable - post doc
snippet doc_vp
/**
* ${1:undocumented class variable}
*
* @var ${2:string}
**/${3}
# Class Variable
snippet doc_v
/**
* ${3:undocumented class variable}
*
* @var ${4:string}
**/
${1:var} $${2};${5}
# Class
snippet doc_c
/**
* ${3:undocumented class}
*
* @packaged ${4:default}
* @author ${5:`g:snips_author`}
**/
${1:}class ${2:}
{${6}
} // END $1class $2
# Constant Definition - post doc
snippet doc_dp
/**
* ${1:undocumented constant}
**/${2}
# Constant Definition
snippet doc_d
/**
* ${3:undocumented constant}
**/
define(${1}, ${2});${4}
# Function - post doc
snippet doc_fp
/**
* ${1:undocumented function}
*
* @return ${2:void}
* @author ${3:`g:snips_author`}
**/${4}
# Function signature
snippet doc_s
/**
* ${4:undocumented function}
*
* @return ${5:void}
* @author ${6:`g:snips_author`}
**/
${1}function ${2}(${3});${7}
# Function
snippet doc_f
/**
* ${4:undocumented function}
*
* @return ${5:void}
* @author ${6:`g:snips_author`}
**/
${1}function ${2}(${3})
{${7}
}
# Header
snippet doc_h
/**
* ${1}
*
* @author ${2:`g:snips_author`}
* @version ${3:$Id$}
* @copyright ${4:$2}, `strftime('%d %B, %Y')`
* @package ${5:default}
**/
/**
* Define DocBlock
*//
# Interface
snippet doc_i
/**
* ${2:undocumented class}
*
* @package ${3:default}
* @author ${4:`g:snips_author`}
**/
interface ${1:}
{${5}
} // END interface $1
# class ...
snippet class
/**
* ${1}
**/
class ${2:ClassName}
{
${3}
function ${4:__construct}(${5:argument})
{
${6:// code...}
}
}
# define(...)
snippet def
define('${1}'${2});${3}
# defined(...)
snippet def?
${1}defined('${2}')${3}
snippet wh
while (${1:/* condition */}) {
${2:// code...}
}
# do ... while
snippet do
do {
${2:// code... }
} while (${1:/* condition */});
snippet if
if (${1:/* condition */}) {
${2:// code...}
}
snippet ife
if (${1:/* condition */}) {
${2:// code...}
} else {
${3:// code...}
}
${4}
snippet else
else {
${1:// code...}
}
snippet elseif
elseif (${1:/* condition */}) {
${2:// code...}
}
# Tertiary conditional
snippet t
$${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5}
snippet switch
switch ($${1:variable}) {
case '${2:value}':
${3:// code...}
break;
${5}
default:
${4:// code...}
break;
}
snippet case
case '${1:value}':
${2:// code...}
break;${3}
snippet for
for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) {
${4: // code...}
}
snippet foreach
foreach ($${1:variable} as $${2:key}) {
${3:// code...}
}
snippet fun
${1:public }function ${2:FunctionName}(${3})
{
${4:// code...}
}
# $... = array (...)
snippet array
$${1:arrayName} = array('${2}' => ${3});${4}
snippet #!
#!/usr/bin/python
snippet imp
import ${1:module}
# Module Docstring
snippet docs
'''
File: ${1:`Filename('$1.py', 'foo.py')`}
Author: ${2:`g:snips_author`}
Description: ${3}
'''
snippet wh
while ${1:condition}:
${2:# code...}
snippet for
for ${1:needle} in ${2:haystack}:
${3:# code...}
# New Class
snippet cl
class ${1:ClassName}(${2:object}):
"""${3:docstring for $1}"""
def __init__(self, ${4:arg}):
${5:super($1, self).__init__()}
self.$4 = $4
${6}
# New Function
snippet def
def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
"""${3:docstring for $1}"""
${4:pass}
snippet deff
def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
${3}
# New Method
snippet defs
def ${1:mname}(self, ${2:arg}):
${3:pass}
# New Property
snippet property
def ${1:foo}():
doc = "${2:The $1 property.}"
def fget(self):
${3:return self._$1}
def fset(self, value):
${4:self._$1 = value}
# Lambda
snippet ld
${1:var} = lambda ${2:vars} : ${3:action}
snippet .
self.
snippet try Try/Except
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
snippet try Try/Except/Else
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
else:
${5:pass}
snippet try Try/Except/Finally
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
finally:
${5:pass}
snippet try Try/Except/Else/Finally
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
else:
${5:pass}
finally:
${6:pass}
# if __name__ == '__main__':
snippet ifmain
if __name__ == '__main__':
${1:main()}
# __magic__
snippet _
__${1:init}__${2}
# #!/usr/bin/ruby
snippet #!
#!/usr/bin/ruby
# New Block
snippet =b
=begin rdoc
${1}
=end
snippet y
:yields: ${1:arguments}
snippet rb
#!/usr/bin/env ruby -wKU
snippet req
require "${1}"${2}
snippet #
# =>
snippet end
__END__
snippet case
case ${1:object}
when ${2:condition}
${3}
end
snippet when
when ${1:condition}
${2}
snippet def
def ${1:method_name}
${2}
end
snippet deft
def test_${1:case_name}
${2}
end
snippet if
if ${1:condition}
${2}
end
snippet ife
if ${1:condition}
${2}
else
${3}
end
snippet elsif
elsif ${1:condition}
${2}
snippet unless
unless ${1:condition}
${2}
end
snippet while
while ${1:condition}
${2}
end
snippet until
until ${1:condition}
${2}
end
snippet cla class .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`}
${2}
end
snippet cla class .. initialize .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`}
def initialize(${2:args})
${3}
end
end
snippet cla class .. < ParentClass .. initialize .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass}
def initialize(${3:args})
${4}
end
end
snippet cla ClassName = Struct .. do .. end
${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do
def ${3:method_name}
${4}
end
end
snippet cla class BlankSlate .. initialize .. end
class ${1:BlankSlate}
instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ }
snippet cla class << self .. end
class << ${1:self}
${2}
end
# class .. < DelegateClass .. initialize .. end
snippet cla-
class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass})
def initialize(${3:args})
super(${4:del_obj})
${5}
end
end
snippet mod module .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
${2}
end
snippet mod module .. module_function .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
module_function
${2}
end
snippet mod module .. ClassMethods .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
module ClassMethods
${2}
end
module InstanceMethods
end
def self.included(receiver)
receiver.extend ClassMethods
receiver.send :include, InstanceMethods
end
end
# attr_reader
snippet r
attr_reader :${1:attr_names}
# attr_writer
snippet w
attr_writer :${1:attr_names}
# attr_accessor
snippet rw
attr_accessor :${1:attr_names}
# include Enumerable
snippet Enum
include Enumerable
def each(&block)
${1}
end
# include Comparable
snippet Comp
include Comparable
def <=>(other)
${1}
end
# extend Forwardable
snippet Forw-
extend Forwardable
# def self
snippet defs
def self.${1:class_method_name}
${2}
end
# def method_missing
snippet defmm
def method_missing(meth, *args, &blk)
${1}
end
snippet defd
def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name}
snippet defds
def_delegators :${1:@del_obj}, :${2:del_methods}
snippet am
alias_method :${1:new_name}, :${2:old_name}
snippet app
if __FILE__ == $PROGRAM_NAME
${1}
end
# usage_if()
snippet usai
if ARGV.${1}
abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
end
# usage_unless()
snippet usau
unless ARGV.${1}
abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
end
snippet array
Array.new(${1:10}) { |${2:i}| ${3} }
snippet hash
Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} }
snippet file File.foreach() { |line| .. }
File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} }
snippet file File.read()
File.read(${1:"path/to/file"})${2}
snippet Dir Dir.global() { |file| .. }
Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} }
snippet Dir Dir[".."]
Dir[${1:"glob/**/*.rb"}]${2}
snippet dir
Filename.dirname(__FILE__)
snippet deli
delete_if { |${1:e}| ${2} }
snippet fil
fill(${1:range}) { |${2:i}| ${3} }
# flatten_once()
snippet flao
inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3}
snippet zip
zip(${1:enums}) { |${2:row}| ${3} }
# downto(0) { |n| .. }
snippet dow
downto(${1:0}) { |${2:n}| ${3} }
snippet ste
step(${1:2}) { |${2:n}| ${3} }
snippet tim
times { |${1:n}| ${2} }
snippet upt
upto(${1:1.0/0.0}) { |${2:n}| ${3} }
snippet loo
loop { ${1} }
snippet ea
each { |${1:e}| ${2} }
snippet eab
each_byte { |${1:byte}| ${2} }
snippet eac- each_char { |chr| .. }
each_char { |${1:chr}| ${2} }
snippet eac- each_cons(..) { |group| .. }
each_cons(${1:2}) { |${2:group}| ${3} }
snippet eai
each_index { |${1:i}| ${2} }
snippet eak
each_key { |${1:key}| ${2} }
snippet eal
each_line { |${1:line}| ${2} }
snippet eap
each_pair { |${1:name}, ${2:val}| ${3} }
snippet eas-
each_slice(${1:2}) { |${2:group}| ${3} }
snippet eav
each_value { |${1:val}| ${2} }
snippet eawi
each_with_index { |${1:e}, ${2:i}| ${3} }
snippet reve
reverse_each { |${1:e}| ${2} }
snippet inj
inject(${1:init}) { |${2:mem}, ${3:var}| ${4} }
snippet map
map { |${1:e}| ${2} }
snippet mapwi-
enum_with_index.map { |${1:e}, ${2:i}| ${3} }
snippet sor
sort { |a, b| ${1} }
snippet sorb
sort_by { |${1:e}| ${2} }
snippet ran
sort_by { rand }
snippet all
all? { |${1:e}| ${2} }
snippet any
any? { |${1:e}| ${2} }
snippet cl
classify { |${1:e}| ${2} }
snippet col
collect { |${1:e}| ${2} }
snippet det
detect { |${1:e}| ${2} }
snippet fet
fetch(${1:name}) { |${2:key}| ${3} }
snippet fin
find { |${1:e}| ${2} }
snippet fina
find_all { |${1:e}| ${2} }
snippet gre
grep(${1:/pattern/}) { |${2:match}| ${3} }
snippet sub
${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} }
snippet sca
scan(${1:/pattern/}) { |${2:match}| ${3} }
snippet max
max { |a, b|, ${1} }
snippet min
min { |a, b|, ${1} }
snippet par
partition { |${1:e}|, ${2} }
snippet rej
reject { |${1:e}|, ${2} }
snippet sel
select { |${1:e}|, ${2} }
snippet lam
lambda { |${1:args}| ${2} }
snippet do
do |${1:variable}|
${2}
end
snippet :
:${1:key} => ${2:"value"}${3}
snippet ope
open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} }
# path_from_here()
snippet patfh
File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2}
# unix_filter {}
snippet unif
ARGF.each_line${1} do |${2:line}|
${3}
end
# option_parse {}
snippet optp
require "optparse"
options = {${1:default => "args"}}
ARGV.options do |opts|
opts.banner = "Usage: #{File.basename($PROGRAM_NAME)}
snippet opt
opts.on( "-${1:o}", "--${2:long-option-name}", ${3:String},
"${4:Option description.}") do |${5:opt}|
${6}
end
snippet tc
require "test/unit"
require "${1:library_file_name}"
class Test${2:$1} < Test::Unit::TestCase
def test_${3:case_name}
${4}
end
end
snippet ts
require "test/unit"
require "tc_${1:test_case_file}"
require "tc_${2:test_case_file}"${3}
snippet as
assert(${1:test}, "${2:Failure message.}")${3}
snippet ase
assert_equal(${1:expected}, ${2:actual})${3}
snippet asne
assert_not_equal(${1:unexpected}, ${2:actual})${3}
snippet asid
assert_in_delta(${1:expected_float}, ${2:actual_float}, ${3:2 ** -20})${4}
snippet asio
assert_instance_of(${1:ExpectedClass}, ${2:actual_instance})${3}
snippet asko
assert_kind_of(${1:ExpectedKind}, ${2:actual_instance})${3}
snippet asn
assert_nil(${1:instance})${2}
snippet asnn
assert_not_nil(${1:instance})${2}
snippet asm
assert_match(/${1:expected_pattern}/, ${2:actual_string})${3}
snippet asnm
assert_no_match(/${1:unexpected_pattern}/, ${2:actual_string})${3}
snippet aso
assert_operator(${1:left}, :${2:operator}, ${3:right})${4}
snippet asr
assert_raise(${1:Exception}) { ${2} }
snippet asnr
assert_nothing_raised(${1:Exception}) { ${2} }
snippet asrt
assert_respond_to(${1:object}, :${2:method})${3}
snippet ass assert_same(..)
assert_same(${1:expected}, ${2:actual})${3}
snippet ass assert_send(..)
assert_send([${1:object}, :${2:message}, ${3:args}])${4}
snippet asns
assert_not_same(${1:unexpected}, ${2:actual})${3}
snippet ast
assert_throws(:${1:expected}) { ${2} }
snippet asnt
assert_nothing_thrown { ${1} }
snippet fl
flunk("${1:Failure message.}")${2}
# Benchmark.bmbm do .. end
snippet bm-
TESTS = ${1:10_000}
Benchmark.bmbm do |results|
${2}
end
snippet rep
results.report("${1:name}:") { TESTS.times { ${2} }}
# Marshal.dump(.., file)
snippet Md
File.open(${1:"path/to/file.dump"}, "wb") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4}
# Mashal.load(obj)
snippet Ml
File.open(${1:"path/to/file.dump"}, "rb") { |${2:file}| Marshal.load($2) }${3}
# deep_copy(..)
snippet deec
Marshal.load(Marshal.dump(${1:obj_to_copy}))${2}
snippet Pn-
PStore.new(${1:"file_name.pstore"})${2}
snippet tra
transaction(${1:true}) { ${2} }
# xmlread(..)
snippet xml-
REXML::Document.new(File.read(${1:"path/to/file"}))${2}
# xpath(..) { .. }
snippet xpa
elements.each(${1:"//Xpath"}) do |${2:node}|
${3}
end
# class_from_name()
snippet clafn
split("::").inject(Object) { |par, const| par.const_get(const) }
# singleton_class()
snippet sinc
class << self; self end
snippet nam
namespace :${1:`Filename()`} do
${2}
end
snippet tas
desc "${1:Task description\}"
task :${2:task_name => [:dependent, :tasks]} do
${3}
end
# #!/bin/bash
snippet #!
#!/bin/bash
snippet if
if [[ ${1:condition} ]]; then
${2:#statements}
fi
snippet elif
elif [[ ${1:condition} ]]; then
${2:#statements}
snippet for
for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
${3:#statements}
done
snippet wh
while [[ ${1:condition} ]]; do
${2:#statements}
done
snippet until
until [[ ${1:condition} ]]; do
${2:#statements}
done
snippet case
case ${1:word} in
${2:pattern})
${3};;
esac
# snippets for making snippets :)
snippet snip
snippet ${1:trigger}
${2}
snippet msnip
snippet ${1:trigger} ${2:description}
${3}
# #!/usr/bin/tclsh
snippet #!
#!/usr/bin/tclsh
# Process
snippet pro
proc ${1:function_name} {${2:args}} {
${3:#body ...}
}
#xif
snippet xif
${1:expr}? ${2:true} : ${3:false}
# Conditional
snippet if
if {${1}} {
${2:# body...}
}
# Conditional if..else
snippet ife
if {${1}} {
${2:# body...}
} else {
${3:# else...}
}
# Conditional if..elsif..else
snippet ifee
if {${1}} {
${2:# body...}
} elseif {${3}} {
${4:# elsif...}
} else {
${5:# else...}
}
# If catch then
snippet ifc
if { [catch {${1:#do something...}} ${2:err}] } {
${3:# handle failure...}
}
# Catch
snippet catch
catch {${1}} ${2:err} ${3:options}
# While Loop
snippet wh
while {${1}} {
${2:# body...}
}
# For Loop
snippet for
for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} {
${4:# body...}
}
# Foreach Loop
snippet fore
foreach ${1:x} {${2:#list}} {
${3:# body...}
}
# after ms script...
snippet af
after ${1:ms} ${2:#do something}
# after cancel id
snippet afc
after cancel ${1:id or script}
# after idle
snippet afi
after idle ${1:script}
# after info id
snippet afin
after info ${1:id}
# Expr
snippet exp
expr {${1:#expression here}}
# Switch
snippet sw
switch ${1:var} {
${3:pattern 1} {
${4:#do something}
}
default {
${2:#do something}
}
}
# Case
snippet ca
${1:pattern} {
${2:#do something}
}${3}
# Namespace eval
snippet ns
namespace eval ${1:path} {${2:#script...}}
# Namespace current
snippet nsc
namespace current
# \begin{}...\end{}
snippet begin
\begin{${1:env}}
${2}
\end{$1}
# Tabular
snippet tab
\begin{${1:tabular}}{${2:c}}
${3}
\end{$1}
# Align(ed)
snippet ali
\begin{align${1:ed}}
${2}
\end{align$1}
# Gather(ed)
snippet gat
\begin{gather${1:ed}}
${2}
\end{gather$1}
# Equation
snippet eq
\begin{equation}
${1}
\end{equation}
# Unnumbered Equation
snippet \
\\[
${1}
\\]
# Enumerate
snippet enum
\begin{enumerate}
\item ${1}
\end{enumerate}
# Itemize
snippet item
\begin{itemize}
\item ${1}
\end{itemize}
# Description
snippet desc
\begin{description}
\item[${1}] ${2}
\end{description}
# Matrix
snippet mat
\begin{${1:p/b/v/V/B/small}matrix}
${2}
\end{$1matrix}
# Cases
snippet cas
\begin{cases}
${1:equation}, &\text{ if }${2:case}\\
${3}
\end{cases}
# Split
snippet spl
\begin{split}
${1}
\end{split}
# Part
snippet part
\part{${1:part name}} % (fold)
\label{prt:${2:$1}}
${3}
% part $2 (end)
# Chapter
snippet cha
\chapter{${1:chapter name}} % (fold)
\label{cha:${2:$1}}
${3}
% chapter $2 (end)
# Section
snippet sec
\section{${1:section name}} % (fold)
\label{sec:${2:$1}}
${3}
% section $2 (end)
# Sub Section
snippet sub
\subsection{${1:subsection name}} % (fold)
\label{sub:${2:$1}}
${3}
% subsection $2 (end)
# Sub Sub Section
snippet subs
\subsubsection{${1:subsubsection name}} % (fold)
\label{ssub:${2:$1}}
${3}
% subsubsection $2 (end)
# Paragraph
snippet par
\paragraph{${1:paragraph name}} % (fold)
\label{par:${2:$1}}
${3}
% paragraph $2 (end)
# Sub Paragraph
snippet subp
\subparagraph{${1:subparagraph name}} % (fold)
\label{subp:${2:$1}}
${3}
% subparagraph $2 (end)
snippet itd
\item[${1:description}] ${2:item}
snippet figure
${1:Figure}~\ref{${2:fig:}}${3}
snippet table
${1:Table}~\ref{${2:tab:}}${3}
snippet listing
${1:Listing}~\ref{${2:list}}${3}
snippet section
${1:Section}~\ref{${2:sec:}}${3}
snippet page
${1:page}~\pageref{${2}}${3}
snippet header
" File: ${1:`expand('%:t')`}
" Author: ${2:`g:snips_author`}
" Description: ${3}
${4:" Last Modified: `strftime("%B %d, %Y")`}
snippet guard
if exists('${1:did_`Filename()`}') || &cp${2: || version < 700}
finish
endif
let $1 = 1${3}
snippet f
fun ${1:function_name}(${2})
${3:" code}
endf
snippet for
for ${1:needle} in ${2:haystack}
${3:" code}
endfor
snippet wh
while ${1:condition}
${2:" code}
endw
snippet if
if ${1:condition}
${2:" code}
endif
snippet ife
if ${1:condition}
${2}
else
${3}
endif
# #!/bin/zsh
snippet #!
#!/bin/zsh
snippet if
if ${1:condition}; then
${2:# statements}
fi
snippet ife
if ${1:condition}; then
${2:# statements}
else
${3:# statements}
fi
snippet elif
elif ${1:condition} ; then
${2:# statements}
snippet for
for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
${3:# statements}
done
snippet fore
for ${1:item} in ${2:list}; do
${3:# statements}
done
snippet wh
while ${1:condition}; do
${2:# statements}
done
snippet until
until ${1:condition}; do
${2:# statements}
done
snippet repeat
repeat ${1:integer}; do
${2:# statements}
done
snippet case
case ${1:word} in
${2:pattern})
${3};;
esac
snippet select
select ${1:answer} in ${2:choices}; do
${3:# statements}
done
snippet (
( ${1:#statements} )
snippet {
{ ${1:#statements} }
snippet [
[[ ${1:test} ]]
snippet always
{ ${1:try} } always { ${2:always} }
snippet fun
function ${1:name} (${2:args}) {
${3:# body}
}
y
fiducials
API
TUIO
API's
interactor
extendable
smartphones
smartphone
webcams
Screenshot
draggable
timestamp
preforked
interpenetrate
LockFreeTree
CoarseGrainedList
FineGrainedList
LockFreeList
CoarseGrainedTree
FineGrainedTree
runtimes
pseudocode
parallelizable
MPI
serializable
virtualized
virtualization
leaderboard
base64
deobfuscation
Warshall
Grayscale
grayscale
Malware
bytecode
malware
unobfuscated
VPC
obfuscator
subtrace
equational
obfuscators
deobfuscated
Concolic
concolic
deobfuscate
deobfuscating
plugin
stylesheet
" Language: CoffeeScript
" Maintainer: Mick Koch <kchmck@gmail.com>
" URL: http://github.com/kchmck/vim-coffee-script
" License: WTFPL
" Bail if our syntax is already loaded.
if exists('b:current_syntax') && b:current_syntax == 'coffee'
finish
endif
" Include JavaScript for coffeeEmbed.
syn include @coffeeJS syntax/javascript.vim
" Highlight long strings.
syn sync minlines=100
" CoffeeScript identifiers can have dollar signs.
setlocal isident+=$
" These are `matches` instead of `keywords` because vim's highlighting
" priority for keywords is higher than matches. This causes keywords to be
" highlighted inside matches, even if a match says it shouldn't contain them --
" like with coffeeAssign and coffeeDot.
syn match coffeeStatement /\<\%(return\|break\|continue\|throw\)\>/ display
hi def link coffeeStatement Statement
syn match coffeeRepeat /\<\%(for\|while\|until\|loop\)\>/ display
hi def link coffeeRepeat Repeat
syn match coffeeConditional /\<\%(if\|else\|unless\|switch\|when\|then\)\>/
\ display
hi def link coffeeConditional Conditional
syn match coffeeException /\<\%(try\|catch\|finally\)\>/ display
hi def link coffeeException Exception
syn match coffeeKeyword /\<\%(new\|in\|of\|by\|and\|or\|not\|is\|isnt\|class\|extends\|super\|do\)\>/
\ display
" The `own` keyword is only a keyword after `for`.
syn match coffeeKeyword /\<for\s\+own\>/ contained containedin=coffeeRepeat
\ display
hi def link coffeeKeyword Keyword
syn match coffeeOperator /\<\%(instanceof\|typeof\|delete\)\>/ display
hi def link coffeeOperator Operator
" The first case matches symbol operators only if they have an operand before.
syn match coffeeExtendedOp /\%(\S\s*\)\@<=[+\-*/%&|\^=!<>?.]\+\|[-=]>\|--\|++\|:/
\ display
syn match coffeeExtendedOp /\<\%(and\|or\)=/ display
hi def link coffeeExtendedOp coffeeOperator
" This is separate from `coffeeExtendedOp` to help differentiate commas from
" dots.
syn match coffeeSpecialOp /[,;]/ display
hi def link coffeeSpecialOp SpecialChar
syn match coffeeBoolean /\<\%(true\|on\|yes\|false\|off\|no\)\>/ display
hi def link coffeeBoolean Boolean
syn match coffeeGlobal /\<\%(null\|undefined\)\>/ display
hi def link coffeeGlobal Type
" A special variable
syn match coffeeSpecialVar /\<\%(this\|prototype\|arguments\)\>/ display
" An @-variable
syn match coffeeSpecialVar /@\%(\I\i*\)\?/ display
hi def link coffeeSpecialVar Special
" A class-like name that starts with a capital letter
syn match coffeeObject /\<\u\w*\>/ display
hi def link coffeeObject Structure
" A constant-like name in SCREAMING_CAPS
syn match coffeeConstant /\<\u[A-Z0-9_]\+\>/ display
hi def link coffeeConstant Constant
" A variable name
syn cluster coffeeIdentifier contains=coffeeSpecialVar,coffeeObject,
\ coffeeConstant
" A non-interpolated string
syn cluster coffeeBasicString contains=@Spell,coffeeEscape
" An interpolated string
syn cluster coffeeInterpString contains=@coffeeBasicString,coffeeInterp
" Regular strings
syn region coffeeString start=/"/ skip=/\\\\\|\\"/ end=/"/
\ contains=@coffeeInterpString
syn region coffeeString start=/'/ skip=/\\\\\|\\'/ end=/'/
\ contains=@coffeeBasicString
hi def link coffeeString String
" A integer, including a leading plus or minus
syn match coffeeNumber /\i\@<![-+]\?\d\+\%([eE][+-]\?\d\+\)\?/ display
" A hex number
syn match coffeeNumber /\<0[xX]\x\+\>/ display
syn match coffeeNumber /\<0b[01]\+\>/ display
hi def link coffeeNumber Number
" A floating-point number, including a leading plus or minus
syn match coffeeFloat /\i\@<![-+]\?\d*\.\@<!\.\d\+\%([eE][+-]\?\d\+\)\?/
\ display
hi def link coffeeFloat Float
" An error for reserved keywords
if !exists("coffee_no_reserved_words_error")
syn match coffeeReservedError /\<\%(case\|default\|function\|var\|void\|with\|const\|let\|enum\|export\|import\|native\|__hasProp\|__extends\|__slice\|__bind\|__indexOf\)\>/
\ display
hi def link coffeeReservedError Error
endif
" A normal object assignment
syn match coffeeObjAssign /@\?\I\i*\s*\ze::\@!/ contains=@coffeeIdentifier display
hi def link coffeeObjAssign Identifier
syn keyword coffeeTodo TODO FIXME XXX contained
hi def link coffeeTodo Todo
syn match coffeeComment /#.*/ contains=@Spell,coffeeTodo
hi def link coffeeComment Comment
syn region coffeeBlockComment start=/####\@!/ end=/###/
\ contains=@Spell,coffeeTodo
hi def link coffeeBlockComment coffeeComment
" A comment in a heregex
syn region coffeeHeregexComment start=/#/ end=/\ze\/\/\/\|$/ contained
\ contains=@Spell,coffeeTodo
hi def link coffeeHeregexComment coffeeComment
" Embedded JavaScript
syn region coffeeEmbed matchgroup=coffeeEmbedDelim
\ start=/`/ skip=/\\\\\|\\`/ end=/`/
\ contains=@coffeeJS
hi def link coffeeEmbedDelim Delimiter
syn region coffeeInterp matchgroup=coffeeInterpDelim start=/#{/ end=/}/ contained
\ contains=@coffeeAll
hi def link coffeeInterpDelim PreProc
" A string escape sequence
syn match coffeeEscape /\\\d\d\d\|\\x\x\{2\}\|\\u\x\{4\}\|\\./ contained display
hi def link coffeeEscape SpecialChar
" A regex -- must not follow a parenthesis, number, or identifier, and must not
" be followed by a number
syn region coffeeRegex start=/\%(\%()\|\i\@<!\d\)\s*\|\i\)\@<!\/=\@!\s\@!/
\ skip=/\[[^\]]\{-}\/[^\]]\{-}\]/
\ end=/\/[gimy]\{,4}\d\@!/
\ oneline contains=@coffeeBasicString
hi def link coffeeRegex String
" A heregex
syn region coffeeHeregex start=/\/\/\// end=/\/\/\/[gimy]\{,4}/
\ contains=@coffeeInterpString,coffeeHeregexComment
\ fold
hi def link coffeeHeregex coffeeRegex
" Heredoc strings
syn region coffeeHeredoc start=/"""/ end=/"""/ contains=@coffeeInterpString
\ fold
syn region coffeeHeredoc start=/'''/ end=/'''/ contains=@coffeeBasicString
\ fold
hi def link coffeeHeredoc String
" An error for trailing whitespace, as long as the line isn't just whitespace
if !exists("coffee_no_trailing_space_error")
syn match coffeeSpaceError /\S\@<=\s\+$/ display
hi def link coffeeSpaceError Error
endif
" An error for trailing semicolons, for help transitioning from JavaScript
if !exists("coffee_no_trailing_semicolon_error")
syn match coffeeSemicolonError /;$/ display
hi def link coffeeSemicolonError Error
endif
" Ignore reserved words in dot accesses.
syn match coffeeDotAccess /\.\@<!\.\s*\I\i*/he=s+1 contains=@coffeeIdentifier
hi def link coffeeDotAccess coffeeExtendedOp
" Ignore reserved words in prototype accesses.
syn match coffeeProtoAccess /::\s*\I\i*/he=s+2 contains=@coffeeIdentifier
hi def link coffeeProtoAccess coffeeExtendedOp
" This is required for interpolations to work.
syn region coffeeCurlies matchgroup=coffeeCurly start=/{/ end=/}/
\ contains=@coffeeAll
syn region coffeeBrackets matchgroup=coffeeBracket start=/\[/ end=/\]/
\ contains=@coffeeAll
syn region coffeeParens matchgroup=coffeeParen start=/(/ end=/)/
\ contains=@coffeeAll
" These are highlighted the same as commas since they tend to go together.
hi def link coffeeBlock coffeeSpecialOp
hi def link coffeeBracket coffeeBlock
hi def link coffeeCurly coffeeBlock
hi def link coffeeParen coffeeBlock
" This is used instead of TOP to keep things coffee-specific for good
" embedding. `contained` groups aren't included.
syn cluster coffeeAll contains=coffeeStatement,coffeeRepeat,coffeeConditional,
\ coffeeException,coffeeKeyword,coffeeOperator,
\ coffeeExtendedOp,coffeeSpecialOp,coffeeBoolean,
\ coffeeGlobal,coffeeSpecialVar,coffeeObject,
\ coffeeConstant,coffeeString,coffeeNumber,
\ coffeeFloat,coffeeReservedError,coffeeObjAssign,
\ coffeeComment,coffeeBlockComment,coffeeEmbed,
\ coffeeRegex,coffeeHeregex,coffeeHeredoc,
\ coffeeSpaceError,coffeeSemicolonError,
\ coffeeDotAccess,coffeeProtoAccess,
\ coffeeCurlies,coffeeBrackets,coffeeParens
if !exists('b:current_syntax')
let b:current_syntax = 'coffee'
endif
" Vim syntax file
" Language: eco
" Maintainer: Jay Adkisson
" Mostly stolen from eruby.vim
if !exists("g:eco_default_subtype")
let g:eco_default_subtype = "html"
endif
if !exists("b:eco_subtype")
let s:lines = getline(1)."\n".getline(2)."\n".getline(3)."\n".getline(4)."\n".getline(5)."\n".getline("$")
let b:eco_subtype = matchstr(s:lines,'eco_subtype=\zs\w\+')
if b:eco_subtype == ''
let b:eco_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.eco\)\+$','',''),'\.\zs\w\+$')
endif
if b:eco_subtype == 'rhtml'
let b:eco_subtype = 'html'
elseif b:eco_subtype == 'jst'
let b:eco_subtype = 'html'
elseif b:eco_subtype == 'rb'
let b:eco_subtype = 'ruby'
elseif b:eco_subtype == 'yml'
let b:eco_subtype = 'yaml'
elseif b:eco_subtype == 'js' || b:eco_subtype == 'json'
let b:eco_subtype = 'javascript'
elseif b:eco_subtype == 'txt'
" Conventional; not a real file type
let b:eco_subtype = 'text'
elseif b:eco_subtype == ''
if exists('b:current_syntax') && b:current_syntax != ''
let b:eco_subtype = b:current_syntax
else
let b:eco_subtype = g:eco_default_subtype
endif
endif
endif
if exists("b:eco_subtype") && b:eco_subtype != '' && b:eco_subtype != 'eco'
exec "runtime! syntax/".b:eco_subtype.".vim"
syn include @coffeeTop syntax/coffee.vim
endif
syn cluster ecoRegions contains=ecoBlock,ecoExpression,ecoComment
syn region ecoBlock matchgroup=ecoDelimiter start=/<%/ end=/%>/ contains=@coffeeTop containedin=ALLBUT,@ecoRegions keepend
syn region ecoExpression matchgroup=ecoDelimiter start=/<%[=\-]/ end=/%>/ contains=@coffeeTop containedin=ALLBUT,@ecoRegions keepend
syn region ecoComment matchgroup=ecoComment start=/<%#/ end=/%>/ contains=@coffeeTodo,@Spell containedin=ALLBUT,@ecoRegions keepend
" eco features not in coffeescript proper
syn keyword ecoEnd end containedin=@ecoRegions
syn match ecoIndentColon /\s+\w+:/ containedin=@ecoRegions
" Define the default highlighting.
hi def link ecoDelimiter Delimiter
hi def link ecoComment Comment
hi def link ecoEnd coffeeConditional
hi def link ecoIndentColon None
let b:current_syntax = 'eco'
" vim: nowrap sw=2 sts=2 ts=8:
" Vim syntax file
" Language: LESS Cascading Style Sheets
" Maintainer: Leaf Corcoran <leafot@gmail.com>
" Modifier: Bryan J Swift <bryan@bryanjswift.com>
" URL: http://leafo.net/lessphp/vim/less.vim
" URL: http://gist.github.com/161047
" Last Change: 2009 August 4
" LESS by Leaf Corcoran
" CSS2 by Nikolai Weibull
" Full CSS2, HTML4 support by Yeti
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
if !exists("main_syntax")
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
let main_syntax = 'less'
endif
syn case ignore
syn keyword cssTagName abbr acronym address applet area a b base
syn keyword cssTagName basefont bdo big blockquote body br button
syn keyword cssTagName caption center cite code col colgroup dd del
syn keyword cssTagName dfn dir div dl dt em fieldset font form frame
syn keyword cssTagName frameset h1 h2 h3 h4 h5 h6 head hr html img i
syn keyword cssTagName iframe img input ins isindex kbd label legend li
syn keyword cssTagName link map menu meta noframes noscript ol optgroup
syn keyword cssTagName option p param pre q s samp script select small
syn keyword cssTagName span strike strong style sub sup tbody td
syn keyword cssTagName textarea tfoot th thead title tr tt ul u var
syn match cssTagName "\<table\>"
syn match cssTagName "\*"
syn match cssTagName "@page\>" nextgroup=cssDefinition
syn match cssSelectorOp "[+>.]"
syn match cssSelectorOp2 "[~|]\?=" contained
syn region cssAttributeSelector matchgroup=cssSelectorOp start="\[" end="]" transparent contains=cssUnicodeEscape,cssSelectorOp2,cssStringQ,cssStringQQ
try
syn match cssIdentifier "#[A-Za-zÀ-ÿ_@][A-Za-zÀ-ÿ0-9_@-]*"
catch /^.*/
syn match cssIdentifier "#[A-Za-z_@][A-Za-z0-9_@-]*"
endtry
syn match cssMedia "@media\>" nextgroup=cssMediaType skipwhite skipnl
syn keyword cssMediaType contained screen print aural braile embosed handheld projection ty tv all nextgroup=cssMediaComma,cssMediaBlock skipwhite skipnl
syn match cssMediaComma "," nextgroup=cssMediaType skipwhite skipnl
syn region cssMediaBlock transparent matchgroup=cssBraces start='{' end='}' contains=cssTagName,cssError,cssComment,cssDefinition,cssURL,cssUnicodeEscape,cssIdentifier
syn match cssValueInteger "[-+]\=\d\+"
syn match cssValueNumber "[-+]\=\d\+\(\.\d*\)\="
syn match cssValueLength "[-+]\=\d\+\(\.\d*\)\=\(%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\)"
syn match cssValueAngle contained "[-+]\=\d\+\(\.\d*\)\=\(deg\|grad\|rad\)"
syn match cssValueTime contained "+\=\d\+\(\.\d*\)\=\(ms\|s\)"
syn match cssValueFrequency contained "+\=\d\+\(\.\d*\)\=\(Hz\|kHz\)"
syn match cssFontDescriptor "@font-face\>" nextgroup=cssFontDescriptorBlock skipwhite skipnl
syn region cssFontDescriptorBlock contained transparent matchgroup=cssBraces start="{" end="}" contains=cssComment,cssError,cssUnicodeEscape,cssFontProp,cssFontAttr,cssCommonAttr,cssStringQ,cssStringQQ,cssFontDescriptorProp,cssValue.*,cssFontDescriptorFunction,cssUnicodeRange,cssFontDescriptorAttr
syn match cssFontDescriptorProp contained "\<\(unicode-range\|unit-per-em\|panose-1\|cap-height\|x-height\|definition-src\)\>"
syn keyword cssFontDescriptorProp contained src stemv stemh slope ascent descent widths bbox baseline centerline mathline topline
syn keyword cssFontDescriptorAttr contained all
syn region cssFontDescriptorFunction contained matchgroup=cssFunctionName start="\<\(uri\|url\|local\|format\)\s*(" end=")" contains=cssStringQ,cssStringQQ oneline keepend
syn match cssUnicodeRange contained "U+[0-9A-Fa-f?]\+"
syn match cssUnicodeRange contained "U+\x\+-\x\+"
syn keyword cssColor contained aqua black blue fuchsia gray green lime maroon navy olive purple red silver teal yellow
" FIXME: These are actually case-insentivie too, but (a) specs recommend using
" mixed-case (b) it's hard to highlight the word `Background' correctly in
" all situations
syn case match
syn keyword cssColor contained ActiveBorder ActiveCaption AppWorkspace ButtonFace ButtonHighlight ButtonShadow ButtonText CaptionText GrayText Highlight HighlightText InactiveBorder InactiveCaption InactiveCaptionText InfoBackground InfoText Menu MenuText Scrollbar ThreeDDarkShadow ThreeDFace ThreeDHighlight ThreeDLightShadow ThreeDShadow Window WindowFrame WindowText Background
syn case ignore
syn match cssColor contained "\<transparent\>"
syn match cssColor contained "\<white\>"
syn match cssColor contained "#[0-9A-Fa-f]\{3\}\>"
syn match cssColor contained "#[0-9A-Fa-f]\{6\}\>"
"syn match cssColor contained "\<rgb\s*(\s*\d\+\(\.\d*\)\=%\=\s*,\s*\d\+\(\.\d*\)\=%\=\s*,\s*\d\+\(\.\d*\)\=%\=\s*)"
syn region cssURL contained matchgroup=cssFunctionName start="\<url\s*(" end=")" oneline keepend
syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgb\|clip\|attr\|counter\|rect\)\s*(" end=")" oneline keepend
syn match cssImportant contained "!\s*important\>"
syn keyword cssCommonAttr contained auto none inherit
syn keyword cssCommonAttr contained top bottom
syn keyword cssCommonAttr contained medium normal
syn match cssFontProp contained "\<font\>\(-\(family\|style\|variant\|weight\|size\(-adjust\)\=\|stretch\)\>\)\="
syn match cssFontAttr contained "\<\(sans-\)\=\<serif\>"
syn match cssFontAttr contained "\<small\>\(-\(caps\|caption\)\>\)\="
syn match cssFontAttr contained "\<x\{1,2\}-\(large\|small\)\>"
syn match cssFontAttr contained "\<message-box\>"
syn match cssFontAttr contained "\<status-bar\>"
syn match cssFontAttr contained "\<\(\(ultra\|extra\|semi\|status-bar\)-\)\=\(condensed\|expanded\)\>"
syn keyword cssFontAttr contained cursive fantasy monospace italic oblique
syn keyword cssFontAttr contained bold bolder lighter larger smaller
syn keyword cssFontAttr contained icon menu
syn match cssFontAttr contained "\<caption\>"
syn keyword cssFontAttr contained large smaller larger
syn keyword cssFontAttr contained narrower wider
syn keyword cssColorProp contained color
syn match cssColorProp contained "\<background\(-\(color\|image\|attachment\|position\)\)\="
syn keyword cssColorAttr contained center scroll fixed
syn match cssColorAttr contained "\<repeat\(-[xy]\)\=\>"
syn match cssColorAttr contained "\<no-repeat\>"
syn match cssTextProp "\<\(\(word\|letter\)-spacing\|text\(-\(decoration\|transform\|align\|index\|shadow\)\)\=\|vertical-align\|unicode-bidi\|line-height\)\>"
syn match cssTextAttr contained "\<line-through\>"
syn match cssTextAttr contained "\<text-indent\>"
syn match cssTextAttr contained "\<\(text-\)\=\(top\|bottom\)\>"
syn keyword cssTextAttr contained underline overline blink sub super middle
syn keyword cssTextAttr contained capitalize uppercase lowercase center justify baseline sub super
syn match cssBoxProp contained "\<\(margin\|padding\|border\)\(-\(top\|right\|bottom\|left\)\)\=\>"
syn match cssBoxProp contained "\<border-\(\(\(top\|right\|bottom\|left\)-\)\=\(width\|color\|style\)\)\=\>"
syn match cssBoxProp contained "\<\(width\|z-index\)\>"
syn match cssBoxProp contained "\<\(min\|max\)-\(width\|height\)\>"
syn keyword cssBoxProp contained width height float clear overflow clip visibility
syn keyword cssBoxAttr contained thin thick both
syn keyword cssBoxAttr contained dotted dashed solid double groove ridge inset outset
syn keyword cssBoxAttr contained hidden visible scroll collapse
syn keyword cssGeneratedContentProp contained content quotes
syn match cssGeneratedContentProp contained "\<counter-\(reset\|increment\)\>"
syn match cssGeneratedContentProp contained "\<list-style\(-\(type\|position\|image\)\)\=\>"
syn match cssGeneratedContentAttr contained "\<\(no-\)\=\(open\|close\)-quote\>"
syn match cssAuralAttr contained "\<lower\>"
syn match cssGeneratedContentAttr contained "\<\(lower\|upper\)-\(roman\|alpha\|greek\|latin\)\>"
syn match cssGeneratedContentAttr contained "\<\(hiragana\|katakana\)\(-iroha\)\=\>"
syn match cssGeneratedContentAttr contained "\<\(decimal\(-leading-zero\)\=\|cjk-ideographic\)\>"
syn keyword cssGeneratedContentAttr contained disc circle square hebrew armenian georgian
syn keyword cssGeneratedContentAttr contained inside outside
syn match cssPagingProp contained "\<page\(-break-\(before\|after\|inside\)\)\=\>"
syn keyword cssPagingProp contained size marks inside orphans widows
syn keyword cssPagingAttr contained landscape portrait crop cross always avoid
syn keyword cssUIProp contained cursor
syn match cssUIProp contained "\<outline\(-\(width\|style\|color\)\)\=\>"
syn match cssUIAttr contained "\<[ns]\=[ew]\=-resize\>"
syn keyword cssUIAttr contained default crosshair pointer move wait help
syn keyword cssUIAttr contained thin thick
syn keyword cssUIAttr contained dotted dashed solid double groove ridge inset outset
syn keyword cssUIAttr contained invert
syn match cssRenderAttr contained "\<marker\>"
syn match cssRenderProp contained "\<\(display\|marker-offset\|unicode-bidi\|white-space\|list-item\|run-in\|inline-table\)\>"
syn keyword cssRenderProp contained position top bottom direction
syn match cssRenderProp contained "\<\(left\|right\)\>"
syn keyword cssRenderAttr contained block inline compact
syn match cssRenderAttr contained "\<table\(-\(row-gorup\|\(header\|footer\)-group\|row\|column\(-group\)\=\|cell\|caption\)\)\=\>"
syn keyword cssRenderAttr contained static relative absolute fixed
syn keyword cssRenderAttr contained ltr rtl embed bidi-override pre nowrap
syn match cssRenderAttr contained "\<bidi-override\>"
syn match cssAuralProp contained "\<\(pause\|cue\)\(-\(before\|after\)\)\=\>"
syn match cssAuralProp contained "\<\(play-during\|speech-rate\|voice-family\|pitch\(-range\)\=\|speak\(-\(punctuation\|numerals\)\)\=\)\>"
syn keyword cssAuralProp contained volume during azimuth elevation stress richness
syn match cssAuralAttr contained "\<\(x-\)\=\(soft\|loud\)\>"
syn keyword cssAuralAttr contained silent
syn match cssAuralAttr contained "\<spell-out\>"
syn keyword cssAuralAttr contained non mix
syn match cssAuralAttr contained "\<\(left\|right\)-side\>"
syn match cssAuralAttr contained "\<\(far\|center\)-\(left\|center\|right\)\>"
syn keyword cssAuralAttr contained leftwards rightwards behind
syn keyword cssAuralAttr contained below level above higher
syn match cssAuralAttr contained "\<\(x-\)\=\(slow\|fast\)\>"
syn keyword cssAuralAttr contained faster slower
syn keyword cssAuralAttr contained male female child code digits continuous
syn match cssTableProp contained "\<\(caption-side\|table-layout\|border-collapse\|border-spacing\|empty-cells\|speak-header\)\>"
syn keyword cssTableAttr contained fixed collapse separate show hide once always
syn match lessComment "//.*$" contains=@Spell
syn match lessVariable "@[A-Za-z_-][A-Za-z0-9_-]*" contained
syn region lessVariableDefinition start="^@" end=";" contains=css.*Attr,css.*Prop,cssComment,cssValue.*,cssColor,cssURL,cssImportant,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssDefinition,cssClassName,cssTagName,cssIdentifier,lessComment,lessVariable,lessFunction
" captures both the definition and the call
syn region lessFunction matchgroup=lessFuncDef start="@[A-Za-z_-][A-Za-z0-9_-]*(" end=")" contains=css.*Attr,css.*Prop,cssComment,cssValue.*,cssColor,cssURL,cssImportant,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssDefinition,cssClassName,cssTagName,cssIdentifier,lessComment,lessVariable,lessFunction
" FIXME: This allows cssMediaBlock before the semicolon, which is wrong.
syn region cssInclude start="@import" end=";" contains=cssComment,cssURL,cssUnicodeEscape,cssMediaType
syn match cssBraces contained "[{}]"
syn match cssError contained "{@<>"
syn region cssDefinition transparent matchgroup=cssBraces start='{' end='}' contains=css.*Attr,css.*Prop,cssComment,cssValue.*,cssColor,cssURL,cssImportant,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssDefinition,cssClassName,cssTagName,cssIdentifier,lessComment,lessVariable,lessFunction
" syn match cssBraceError "}"
syn match cssPseudoClass ":\S*" contains=cssPseudoClassId,cssUnicodeEscape
syn keyword cssPseudoClassId contained link visited active hover focus before after left right
syn match cssPseudoClassId contained "\<first\(-\(line\|letter\|child\)\)\=\>"
syn region cssPseudoClassLang matchgroup=cssPseudoClassId start=":lang(" end=")" oneline
syn region cssComment start="/\*" end="\*/" contains=@Spell
syn match cssUnicodeEscape "\\\x\{1,6}\s\?"
syn match cssSpecialCharQQ +\\"+ contained
syn match cssSpecialCharQ +\\'+ contained
syn region cssStringQQ start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=cssUnicodeEscape,cssSpecialCharQQ
syn region cssStringQ start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=cssUnicodeEscape,cssSpecialCharQ
syn match cssClassName "\.[A-Za-z][A-Za-z0-9_-]\+"
if main_syntax == "css"
syn sync minlines=10
endif
" Define the default highlighting.
" For version 5.7 and earlier: only when not done already
" For version 5.8 and later: only when an item doesn't have highlighting yet
if version >= 508 || !exists("did_less_syn_inits")
if version < 508
let did_less_syn_inits = 1
command -nargs=+ HiLink hi link <args>
else
command -nargs=+ HiLink hi def link <args>
endif
HiLink lessComment Comment
HiLink lessVariable Special
HiLink lessFuncDef Function
HiLink cssComment Comment
HiLink cssTagName Statement
HiLink cssSelectorOp Special
HiLink cssSelectorOp2 Special
HiLink cssFontProp StorageClass
HiLink cssColorProp storageClass
HiLink cssTextProp StorageClass
HiLink cssBoxProp StorageClass
HiLink cssRenderProp StorageClass
HiLink cssAuralProp StorageClass
HiLink cssRenderProp StorageClass
HiLink cssGeneratedContentProp StorageClass
HiLink cssPagingProp StorageClass
HiLink cssTableProp StorageClass
HiLink cssUIProp StorageClass
HiLink cssFontAttr Type
HiLink cssColorAttr Type
HiLink cssTextAttr Type
HiLink cssBoxAttr Type
HiLink cssRenderAttr Type
HiLink cssAuralAttr Type
HiLink cssGeneratedContentAttr Type
HiLink cssPagingAttr Type
HiLink cssTableAttr Type
HiLink cssUIAttr Type
HiLink cssCommonAttr Type
HiLink cssPseudoClassId PreProc
HiLink cssPseudoClassLang Constant
HiLink cssValueLength Number
HiLink cssValueInteger Number
HiLink cssValueNumber Number
HiLink cssValueAngle Number
HiLink cssValueTime Number
HiLink cssValueFrequency Number
HiLink cssFunction Constant
HiLink cssURL String
HiLink cssFunctionName Function
HiLink cssColor Constant
HiLink cssIdentifier Function
HiLink cssInclude Include
HiLink cssImportant Special
HiLink cssBraces SpecialChar
HiLink cssBraceError Error
HiLink cssError Error
HiLink cssInclude Include
HiLink cssUnicodeEscape Special
HiLink cssStringQQ String
HiLink cssStringQ String
HiLink cssMedia Special
HiLink cssMediaType Special
HiLink cssMediaComma Normal
HiLink cssFontDescriptor Special
HiLink cssFontDescriptorFunction Constant
HiLink cssFontDescriptorProp StorageClass
HiLink cssFontDescriptorAttr Type
HiLink cssUnicodeRange Constant
HiLink cssClassName Function
delcommand HiLink
endif
let b:current_syntax = "less"
if main_syntax == 'less'
unlet main_syntax
endif
" vim: ts=8
" Vim syntax file
" Language: OCaml
" Filenames: *.ml *.mli *.mll *.mly
" Maintainers: Markus Mottl <markus.mottl@gmail.com>
" Karl-Heinz Sylla <Karl-Heinz.Sylla@gmd.de>
" Issac Trotts <ijtrotts@ucdavis.edu>
" URL: http://www.ocaml.info/vim/syntax/ocaml.vim
" Last Change: 2010 Oct 11 - Added highlighting of lnot (MM, thanks to Erick Matsen)
" 2010 Sep 03 - Fixed escaping bug (MM, thanks to Florent Monnier)
" 2010 Aug 07 - Fixed module type bug (MM)
" A minor patch was applied to the official version so that object/end
" can be distinguished from begin/end, which is used for indentation,
" and folding. (David Baelde)
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
if version < 600
syntax clear
elseif exists("b:current_syntax") && b:current_syntax == "ocaml"
finish
endif
" OCaml is case sensitive.
syn case match
" Access to the method of an object
syn match ocamlMethod "#"
" Script headers highlighted like comments
syn match ocamlComment "^#!.*"
" Scripting directives
syn match ocamlScript "^#\<\(quit\|labels\|warnings\|directory\|cd\|load\|use\|install_printer\|remove_printer\|require\|thread\|trace\|untrace\|untrace_all\|print_depth\|print_length\|camlp4o\)\>"
" lowercase identifier - the standard way to match
syn match ocamlLCIdentifier /\<\(\l\|_\)\(\w\|'\)*\>/
syn match ocamlKeyChar "|"
" Errors
syn match ocamlBraceErr "}"
syn match ocamlBrackErr "\]"
syn match ocamlParenErr ")"
syn match ocamlArrErr "|]"
syn match ocamlCommentErr "\*)"
syn match ocamlCountErr "\<downto\>"
syn match ocamlCountErr "\<to\>"
if !exists("ocaml_revised")
syn match ocamlDoErr "\<do\>"
endif
syn match ocamlDoneErr "\<done\>"
syn match ocamlThenErr "\<then\>"
" Error-highlighting of "end" without synchronization:
" as keyword or as error (default)
if exists("ocaml_noend_error")
syn match ocamlKeyword "\<end\>"
else
syn match ocamlEndErr "\<end\>"
endif
" Some convenient clusters
syn cluster ocamlAllErrs contains=ocamlBraceErr,ocamlBrackErr,ocamlParenErr,ocamlCommentErr,ocamlCountErr,ocamlDoErr,ocamlDoneErr,ocamlEndErr,ocamlThenErr
syn cluster ocamlAENoParen contains=ocamlBraceErr,ocamlBrackErr,ocamlCommentErr,ocamlCountErr,ocamlDoErr,ocamlDoneErr,ocamlEndErr,ocamlThenErr
syn cluster ocamlContained contains=ocamlTodo,ocamlPreDef,ocamlModParam,ocamlModParam1,ocamlPreMPRestr,ocamlMPRestr,ocamlMPRestr1,ocamlMPRestr2,ocamlMPRestr3,ocamlModRHS,ocamlFuncWith,ocamlFuncStruct,ocamlModTypeRestr,ocamlModTRWith,ocamlWith,ocamlWithRest,ocamlModType,ocamlFullMod,ocamlVal
" Enclosing delimiters
syn region ocamlEncl transparent matchgroup=ocamlKeyword start="(" matchgroup=ocamlKeyword end=")" contains=ALLBUT,@ocamlContained,ocamlParenErr
syn region ocamlEncl transparent matchgroup=ocamlKeyword start="{" matchgroup=ocamlKeyword end="}" contains=ALLBUT,@ocamlContained,ocamlBraceErr
syn region ocamlEncl transparent matchgroup=ocamlKeyword start="\[" matchgroup=ocamlKeyword end="\]" contains=ALLBUT,@ocamlContained,ocamlBrackErr
syn region ocamlEncl transparent matchgroup=ocamlKeyword start="\[|" matchgroup=ocamlKeyword end="|\]" contains=ALLBUT,@ocamlContained,ocamlArrErr
" Comments
syn region ocamlComment start="(\*" end="\*)" contains=ocamlComment,ocamlTodo
syn keyword ocamlTodo contained TODO FIXME XXX NOTE
" Objects
syn region ocamlEnd matchgroup=ocamlObject start="\<object\>" matchgroup=ocamlObject end="\<end\>" contains=ALLBUT,@ocamlContained,ocamlEndErr
" Blocks
if !exists("ocaml_revised")
syn region ocamlEnd matchgroup=ocamlKeyword start="\<begin\>" matchgroup=ocamlKeyword end="\<end\>" contains=ALLBUT,@ocamlContained,ocamlEndErr
endif
" "for"
syn region ocamlNone matchgroup=ocamlKeyword start="\<for\>" matchgroup=ocamlKeyword end="\<\(to\|downto\)\>" contains=ALLBUT,@ocamlContained,ocamlCountErr
" "do"
if !exists("ocaml_revised")
syn region ocamlDo matchgroup=ocamlKeyword start="\<do\>" matchgroup=ocamlKeyword end="\<done\>" contains=ALLBUT,@ocamlContained,ocamlDoneErr
endif
" "if"
syn region ocamlNone matchgroup=ocamlKeyword start="\<if\>" matchgroup=ocamlKeyword end="\<then\>" contains=ALLBUT,@ocamlContained,ocamlThenErr
"" Modules
" "sig"
syn region ocamlSig matchgroup=ocamlModule start="\<sig\>" matchgroup=ocamlModule end="\<end\>" contains=ALLBUT,@ocamlContained,ocamlEndErr,ocamlModule
syn region ocamlModSpec matchgroup=ocamlKeyword start="\<module\>" matchgroup=ocamlModule end="\<\u\(\w\|'\)*\>" contained contains=@ocamlAllErrs,ocamlComment skipwhite skipempty nextgroup=ocamlModTRWith,ocamlMPRestr
" "open"
syn region ocamlNone matchgroup=ocamlKeyword start="\<open\>" matchgroup=ocamlModule end="\<\u\(\w\|'\)*\(\.\u\(\w\|'\)*\)*\>" contains=@ocamlAllErrs,ocamlComment
" "include"
syn match ocamlKeyword "\<include\>" skipwhite skipempty nextgroup=ocamlModParam,ocamlFullMod
" "module" - somewhat complicated stuff ;-)
syn region ocamlModule matchgroup=ocamlKeyword start="\<module\>" matchgroup=ocamlModule end="\<\u\(\w\|'\)*\>" contains=@ocamlAllErrs,ocamlComment skipwhite skipempty nextgroup=ocamlPreDef
syn region ocamlPreDef start="."me=e-1 matchgroup=ocamlKeyword end="\l\|=\|)"me=e-1 contained contains=@ocamlAllErrs,ocamlComment,ocamlModParam,ocamlModTypeRestr,ocamlModTRWith nextgroup=ocamlModPreRHS
syn region ocamlModParam start="([^*]" end=")" contained contains=@ocamlAENoParen,ocamlModParam1,ocamlVal
syn match ocamlModParam1 "\<\u\(\w\|'\)*\>" contained skipwhite skipempty nextgroup=ocamlPreMPRestr
syn region ocamlPreMPRestr start="."me=e-1 end=")"me=e-1 contained contains=@ocamlAllErrs,ocamlComment,ocamlMPRestr,ocamlModTypeRestr
syn region ocamlMPRestr start=":" end="."me=e-1 contained contains=@ocamlComment skipwhite skipempty nextgroup=ocamlMPRestr1,ocamlMPRestr2,ocamlMPRestr3
syn region ocamlMPRestr1 matchgroup=ocamlModule start="\ssig\s\=" matchgroup=ocamlModule end="\<end\>" contained contains=ALLBUT,@ocamlContained,ocamlEndErr,ocamlModule
syn region ocamlMPRestr2 start="\sfunctor\(\s\|(\)\="me=e-1 matchgroup=ocamlKeyword end="->" contained contains=@ocamlAllErrs,ocamlComment,ocamlModParam skipwhite skipempty nextgroup=ocamlFuncWith,ocamlMPRestr2
syn match ocamlMPRestr3 "\w\(\w\|'\)*\(\.\w\(\w\|'\)*\)*" contained
syn match ocamlModPreRHS "=" contained skipwhite skipempty nextgroup=ocamlModParam,ocamlFullMod
syn keyword ocamlKeyword val
syn region ocamlVal matchgroup=ocamlKeyword start="\<val\>" matchgroup=ocamlLCIdentifier end="\<\l\(\w\|'\)*\>" contains=@ocamlAllErrs,ocamlComment skipwhite skipempty nextgroup=ocamlMPRestr
syn region ocamlModRHS start="." end=".\w\|([^*]"me=e-2 contained contains=ocamlComment skipwhite skipempty nextgroup=ocamlModParam,ocamlFullMod
syn match ocamlFullMod "\<\u\(\w\|'\)*\(\.\u\(\w\|'\)*\)*" contained skipwhite skipempty nextgroup=ocamlFuncWith
syn region ocamlFuncWith start="([^*]"me=e-1 end=")" contained contains=ocamlComment,ocamlWith,ocamlFuncStruct skipwhite skipempty nextgroup=ocamlFuncWith
syn region ocamlFuncStruct matchgroup=ocamlModule start="[^a-zA-Z]struct\>"hs=s+1 matchgroup=ocamlModule end="\<end\>" contains=ALLBUT,@ocamlContained,ocamlEndErr
syn match ocamlModTypeRestr "\<\w\(\w\|'\)*\(\.\w\(\w\|'\)*\)*\>" contained
syn region ocamlModTRWith start=":\s*("hs=s+1 end=")" contained contains=@ocamlAENoParen,ocamlWith
syn match ocamlWith "\<\(\u\(\w\|'\)*\.\)*\w\(\w\|'\)*\>" contained skipwhite skipempty nextgroup=ocamlWithRest
syn region ocamlWithRest start="[^)]" end=")"me=e-1 contained contains=ALLBUT,@ocamlContained
" "struct"
syn region ocamlStruct matchgroup=ocamlModule start="\<\(module\s\+\)\=struct\>" matchgroup=ocamlModule end="\<end\>" contains=ALLBUT,@ocamlContained,ocamlEndErr
" "module type"
syn region ocamlKeyword start="\<module\>\s*\<type\>\(\s*\<of\>\)\=" matchgroup=ocamlModule end="\<\w\(\w\|'\)*\>" contains=ocamlComment skipwhite skipempty nextgroup=ocamlMTDef
syn match ocamlMTDef "=\s*\w\(\w\|'\)*\>"hs=s+1,me=s
syn keyword ocamlKeyword and as assert class
syn keyword ocamlKeyword constraint else
syn keyword ocamlKeyword exception external fun
syn keyword ocamlKeyword in inherit initializer
syn keyword ocamlKeyword land lazy let match
syn keyword ocamlKeyword method mutable new of
syn keyword ocamlKeyword parser private raise rec
syn keyword ocamlKeyword try type
syn keyword ocamlKeyword virtual when while with
if exists("ocaml_revised")
syn keyword ocamlKeyword do value
syn keyword ocamlBoolean True False
else
syn keyword ocamlKeyword function
syn keyword ocamlBoolean true false
syn match ocamlKeyChar "!"
endif
syn keyword ocamlType array bool char exn float format format4
syn keyword ocamlType int int32 int64 lazy_t list nativeint option
syn keyword ocamlType string unit
syn keyword ocamlOperator asr lnot lor lsl lsr lxor mod not
syn match ocamlConstructor "(\s*)"
syn match ocamlConstructor "\[\s*\]"
syn match ocamlConstructor "\[|\s*>|]"
syn match ocamlConstructor "\[<\s*>\]"
syn match ocamlConstructor "\u\(\w\|'\)*\>"
" Polymorphic variants
syn match ocamlConstructor "`\w\(\w\|'\)*\>"
" Module prefix
syn match ocamlModPath "\u\(\w\|'\)*\."he=e-1
syn match ocamlCharacter "'\\\d\d\d'\|'\\[\'ntbr]'\|'.'"
syn match ocamlCharacter "'\\x\x\x'"
syn match ocamlCharErr "'\\\d\d'\|'\\\d'"
syn match ocamlCharErr "'\\[^\'ntbr]'"
syn region ocamlString start=+"+ skip=+\\\\\|\\"+ end=+"+
syn match ocamlFunDef "->"
syn match ocamlRefAssign ":="
syn match ocamlTopStop ";;"
syn match ocamlOperator "\^"
syn match ocamlOperator "::"
syn match ocamlOperator "&&"
syn match ocamlOperator "<"
syn match ocamlOperator ">"
syn match ocamlAnyVar "\<_\>"
syn match ocamlKeyChar "|[^\]]"me=e-1
syn match ocamlKeyChar ";"
syn match ocamlKeyChar "\~"
syn match ocamlKeyChar "?"
syn match ocamlKeyChar "\*"
syn match ocamlKeyChar "="
if exists("ocaml_revised")
syn match ocamlErr "<-"
else
syn match ocamlOperator "<-"
endif
syn match ocamlNumber "\<-\=\d\(_\|\d\)*[l|L|n]\?\>"
syn match ocamlNumber "\<-\=0[x|X]\(\x\|_\)\+[l|L|n]\?\>"
syn match ocamlNumber "\<-\=0[o|O]\(\o\|_\)\+[l|L|n]\?\>"
syn match ocamlNumber "\<-\=0[b|B]\([01]\|_\)\+[l|L|n]\?\>"
syn match ocamlFloat "\<-\=\d\(_\|\d\)*\.\?\(_\|\d\)*\([eE][-+]\=\d\(_\|\d\)*\)\=\>"
" Labels
syn match ocamlLabel "\~\(\l\|_\)\(\w\|'\)*"lc=1
syn match ocamlLabel "?\(\l\|_\)\(\w\|'\)*"lc=1
syn region ocamlLabel transparent matchgroup=ocamlLabel start="?(\(\l\|_\)\(\w\|'\)*"lc=2 end=")"me=e-1 contains=ALLBUT,@ocamlContained,ocamlParenErr
" Synchronization
syn sync minlines=50
syn sync maxlines=500
if !exists("ocaml_revised")
syn sync match ocamlDoSync grouphere ocamlDo "\<do\>"
syn sync match ocamlDoSync groupthere ocamlDo "\<done\>"
endif
if exists("ocaml_revised")
syn sync match ocamlEndSync grouphere ocamlEnd "\<\(object\)\>"
else
syn sync match ocamlEndSync grouphere ocamlEnd "\<\(begin\|object\)\>"
endif
syn sync match ocamlEndSync groupthere ocamlEnd "\<end\>"
syn sync match ocamlStructSync grouphere ocamlStruct "\<struct\>"
syn sync match ocamlStructSync groupthere ocamlStruct "\<end\>"
syn sync match ocamlSigSync grouphere ocamlSig "\<sig\>"
syn sync match ocamlSigSync groupthere ocamlSig "\<end\>"
" Define the default highlighting.
" For version 5.7 and earlier: only when not done already
" For version 5.8 and later: only when an item doesn't have highlighting yet
if version >= 508 || !exists("did_ocaml_syntax_inits")
if version < 508
let did_ocaml_syntax_inits = 1
command -nargs=+ HiLink hi link <args>
else
command -nargs=+ HiLink hi def link <args>
endif
HiLink ocamlBraceErr Error
HiLink ocamlBrackErr Error
HiLink ocamlParenErr Error
HiLink ocamlArrErr Error
HiLink ocamlCommentErr Error
HiLink ocamlCountErr Error
HiLink ocamlDoErr Error
HiLink ocamlDoneErr Error
HiLink ocamlEndErr Error
HiLink ocamlThenErr Error
HiLink ocamlCharErr Error
HiLink ocamlErr Error
HiLink ocamlComment Comment
HiLink ocamlModPath Include
HiLink ocamlObject Include
HiLink ocamlModule Include
HiLink ocamlModParam1 Include
HiLink ocamlModType Include
HiLink ocamlMPRestr3 Include
HiLink ocamlFullMod Include
HiLink ocamlModTypeRestr Include
HiLink ocamlWith Include
HiLink ocamlMTDef Include
HiLink ocamlScript Include
HiLink ocamlConstructor Constant
HiLink ocamlVal Keyword
HiLink ocamlModPreRHS Keyword
HiLink ocamlMPRestr2 Keyword
HiLink ocamlKeyword Keyword
HiLink ocamlMethod Include
HiLink ocamlFunDef Keyword
HiLink ocamlRefAssign Keyword
HiLink ocamlKeyChar Keyword
HiLink ocamlAnyVar Keyword
HiLink ocamlTopStop Keyword
HiLink ocamlOperator Keyword
HiLink ocamlBoolean Boolean
HiLink ocamlCharacter Character
HiLink ocamlNumber Number
HiLink ocamlFloat Float
HiLink ocamlString String
HiLink ocamlLabel Identifier
HiLink ocamlType Type
HiLink ocamlTodo Todo
HiLink ocamlEncl Keyword
delcommand HiLink
endif
let b:current_syntax = "ocaml"
" vim: ts=8
" Syntax highlighting for snippet files (used for snipMate.vim)
" Hopefully this should make snippets a bit nicer to write!
syn match snipComment '^#.*'
syn match placeHolder '\${\d\+\(:.\{-}\)\=}' contains=snipCommand
syn match tabStop '\$\d\+'
syn match snipCommand '[^\\]`.\{-}`'
syn match snippet '^snippet.*' transparent contains=multiSnipText,snipKeyword
syn match multiSnipText '\S\+ \zs.*' contained
syn match snipKeyword '^snippet'me=s+8 contained
syn match snipError "^[^#s\t].*$"
hi link snipComment Comment
hi link multiSnipText String
hi link snipKeyword Keyword
hi link snipComment Comment
hi link placeHolder Special
hi link tabStop Special
hi link snipCommand String
hi link snipError Error
set ruler
hi SpellBad guisp=#fcaf3e cterm=underline
set expandtab
set modeline
set tabstop=4 " a tab is four spaces
set backspace=indent,eol,start
" allow backspacing over everything in insert mode
set autoindent " always set autoindenting on
set copyindent " copy the previous indentation on autoindenting
set number " always show line numbers
set shiftwidth=4 " number of spaces to use for autoindenting
set shiftround " use multiple of shiftwidth when indenting with '<' and '>'
set ignorecase " ignore case when searching
set smartcase " ignore case if search pattern is all lowercase,
" case-sensitive otherwise
set smarttab " insert tabs on the start of a line according to
" shiftwidth, not tabstop
set hlsearch " highlight search terms
set incsearch " show search matches as you type
set history=1000 " remember more commands and search history
set undolevels=1000 " use many muchos levels of undo
set wildignore=*.swp,*.bak,*.pyc,*.class,*.old
set textwidth=79
set vb t_vb=
set ls=2 " always display filename
" IMPORTANT: Uncomment one of the following lines to force
" using 256 colors (or 88 colors) if your terminal supports it,
" but does not automatically use 256 colors by default.
" -- run in gnome-terminal: --
" export TERM="xterm-256color"
"
set t_Co=88
if $TERM == 'xterm-256color'
set t_Co=256
endif
" ,rl = run pdflatex (on current file)
map ,rl :!pdflatex -src -shell-escape -interaction=nonstopmode %
" trigger pdflatex (above) on FileWritePost event
":autocmd BufWritePost *.tex :!pdflatex -src -shell-escape -interaction=nonstopmode % | grep -A 4 -i "error"
:autocmd BufNewFile,BufRead *.tex :set spell
"augroup vimrc_autocmds
" autocmd BufEnter * highlight OverLength ctermbg=darkgrey guibg=#592929
" autocmd BufEnter * match OverLength /\%81v.*/
"augroup END
" configure tags - add additional tags here or comment out not-used ones
" cd /usr/include
" ctags -R --sort=yes --fields=+iaS -f ~/.vim/tags/stdc stdio.h stdlib.h \
" pthread.h math.h assert.h errno.h malloc.h strings.h fcntl.h unistd.h
" ctags -R --sort=yes --fields=+iaS -f ~/.vim/tags/gl GL/
"set tags+=~/.vim/tags/stdc
"set tags+=~/.vim/tags/gl
" build tags of your own project with CTRL+F12
"map <C-F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<CR>
"noremap <F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<cr>
"inoremap <F12> <Esc>:!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<cr>
"" OmniCppComplete
"let OmniCpp_NamespaceSearch = 1
"let OmniCpp_GlobalScopeSearch = 1
"let OmniCpp_ShowAccess = 1
"let OmniCpp_MayCompleteDot = 1
"let OmniCpp_MayCompleteArrow = 1
"let OmniCpp_MayCompleteScope = 1
"let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"]
"" automatically open and close the popup menu / preview window
"au CursorMovedI,InsertLeave * if pumvisible() == 0|silent! pclose|endif
""set completeopt=menuone,menu,longest,preview
"set completeopt=menuone,menu " ,longest,preview
"set nocp
filetype plugin on
"set background=dark
"colorscheme darkspectrum
runtime! plugin/guicolorscheme.vim
GuiColorScheme darkspectrum
" Wildmenu
set wildmenu " use wildmenu
set wildcharm=<TAB> " autocomplete
set wildignore=*.swp,*.bak,*.pyc,*.class,*.old
" ------------------
" Various vim tweaks
" ------------------
set title " change the terminal's title
set visualbell " don't beep
set noerrorbells " don't beep
set nocp " Disable Vi-compatibility
" syntax detection and filetype indention
filetype plugin indent on
syntax enable
autocmd BufReadPre *.pdf set ro nowrap
autocmd BufReadPost *.pdf silent %!pdftotext "%" -nopgbrk -layout -q -eol unix -
" C syntax highlighting for CiviC files
au BufNewFile,BufRead *.cvc set filetype=c
" Automatically remove all trailing spaces
autocmd BufWritePre * :%s/\s\+$//e
" -----------------
" Source completion
" -----------------
au CursorMovedI,InsertLeave * if pumvisible() == 0|silent! pclose|endif
"set completeopt=menuone,menu
" --------------
" Source folding
" --------------
"set foldmethod=indent
" -------------
" File explorer
" -------------
let g:netrw_liststyle=3 " Use tree-mode as default view
"let g:netrw_browse_split=4 " Open file in previous buffer
let g:netrw_preview=1 " Preview window shown in a vertically split
" ------------
" Key bindings
" ------------
" skip the press and hold 'shift' + press ';' + release 'shift'.
" Now you can simply use ';' instead of ':'.
nnoremap ; :
" Use Q for formatting the current paragraph (or selection)
vmap Q gq
nmap Q gqap
" Unbind Shift + up/down
vmap <s-up> <up>
nmap <s-up> <up>
vmap <s-down> <down>
nmap <s-down> <down>
" If you like long lines with line wrapping enabled, this solves the problem
" that pressing down jumpes your cursor “over” the current line to the next
" line. It changes behaviour so that it jumps to the next row in the editor.
nnoremap j gj
nnoremap k gk
" Easy window navigation
map <C-h> <C-w>h
map <C-j> <C-w>j
map <C-k> <C-w>k
map <C-l> <C-w>l
" It clears the search buffer (and highlighting) when you press ,/
nmap <silent> ,/ :nohlsearch<CR>
nmap <silent> ,mt :!make check<CR>
nmap <silent> ,mc :!make coverage<CR>
nmap <silent> ,ml :!make clean<CR>
nmap <silent> ,mm :!make<CR>
nmap <silent> ,mM :!make && make<CR>
nmap <silent> ,md :!make doc<CR>
nmap <silent> ,mb :!make -B<CR>
nmap <silent> ,a :!ant<CR>
" when you forgot to sudo before editing a file that requires root privileges.
" This lets you use w!! to do that after you opened the file already:
cmap w!! w !sudo tee % >/dev/null
" Status line highlight
:hi StatusLine ctermbg=black ctermfg=grey
" Syntax highlighting for .less files
au BufNewFile,BufRead *.less set filetype=less
set fileformats=unix
let mapleader=","
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment