" Vim OMNI completion script for SQL
" Language: SQL
" Maintainer: David Fishburn <dfishburn dot vim at gmail dot com>
-" Version: 10.0
-" Last Change: 2010 Jun 11
+" Version: 12.0
+" Last Change: 2012 Feb 08
" Usage: For detailed help
-" ":help sql.txt"
-" or ":help ft-sql-omni"
+" ":help sql.txt"
+" or ":help ft-sql-omni"
" or read $VIMRUNTIME/doc/sql.txt
" History
+" Version 12.0
+" - Partial column name completion did not work when a table
+" name or table alias was provided (Jonas Enberg).
+" - Improved the handling of column completion. First we match any
+" columns from a previous completion. If not matches are found, we
+" consider the partial name to be a table or table alias for the
+" query and attempt to match on it.
+"
+" Version 11.0
+" Added g:omni_sql_default_compl_type variable
+" - You can specify which type of completion to default to
+" when pressing <C-X><C-O>. The entire list of available
+" choices can be found in the calls to sqlcomplete#Map in:
+" ftplugin/sql.vim
+"
" Version 10.0
-" Updated PreCacheSyntax()
+" Updated PreCacheSyntax()
" - Now returns a List of the syntax items it finds.
" This allows other plugins / scripts to use this list for their own
" purposes. In this case XPTemplate can use them for a Choose list.
" warning if not.
" - Verifies the parameters are the correct type and displays a
" warning if not.
-" Updated SQLCWarningMsg()
+" Updated SQLCWarningMsg()
" - Prepends warning message with SQLComplete so you know who issued
" the warning.
-" Updated SQLCErrorMsg()
+" Updated SQLCErrorMsg()
" - Prepends error message with SQLComplete so you know who issued
" the error.
-"
+"
" Version 9.0
" This change removes some of the support for tables with spaces in their
-" names in order to simplify the regexes used to pull out query table
+" names in order to simplify the regexes used to pull out query table
" aliases for more robust table name and column name code completion.
" Full support for "table names with spaces" can be added in again
" after 7.3.
"
" Version 8.0
-" Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left
+" Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left
" when drilling in and out of a column list for a table.
"
" Version 7.0
"
" Set completion with CTRL-X CTRL-O to autoloaded function.
" This check is in place in case this script is
-" sourced directly instead of using the autoload feature.
+" sourced directly instead of using the autoload feature.
if exists('&omnifunc')
" Do not set the option if already set since this
" results in an E117 warning.
endif
if exists('g:loaded_sql_completion')
- finish
+ finish
endif
-let g:loaded_sql_completion = 100
+let g:loaded_sql_completion = 120
" Maintains filename of dictionary
let s:sql_file_table = ""
let s:tbl_cols = []
let s:syn_list = []
let s:syn_value = []
-
+
" Used in conjunction with the syntaxcomplete plugin
let s:save_inc = ""
let s:save_exc = ""
if exists('g:omni_syntax_group_exclude_sql')
let s:save_exc = g:omni_syntax_group_exclude_sql
endif
-
+
" Used with the column list
let s:save_prev_table = ""
if g:loaded_dbext >= 300
" New to dbext 3.00, by default the table lists include the owner
" name of the table. This is used when determining how much of
- " whatever has been typed should be replaced as part of the
+ " whatever has been typed should be replaced as part of the
" code replacement.
let g:omni_sql_include_owner = 1
endif
endif
endif
+" Default type of completion used when <C-X><C-O> is pressed
+if !exists('g:omni_sql_default_compl_type')
+ let g:omni_sql_default_compl_type = 'table'
+endif
" This function is used for the 'omnifunc' option.
function! sqlcomplete#Complete(findstart, base)
let begindot = 1
endif
while start > 0
- " Additional code was required to handle objects which
+ " Additional code was required to handle objects which
" can contain spaces like "my table name".
if line[start - 1] !~ '\(\w\|\.\)'
" If the previous character is not a period or word character
elseif line[start - 1] =~ '\w'
" If the previous character is word character continue back
let start -= 1
- elseif line[start - 1] =~ '\.' &&
+ elseif line[start - 1] =~ '\.' &&
\ compl_type =~ 'column\|table\|view\|procedure'
" If the previous character is a period and we are completing
" an object which can be specified with a period like this:
" If lastword has already been set for column completion
" break from the loop, since we do not also want to pickup
" a table name if it was also supplied.
- if lastword != -1 && compl_type == 'column'
+ if lastword != -1 && compl_type == 'column'
break
endif
" If column completion was specified stop at the "." if
endif
" If omni_sql_include_owner = 0, do not include the table
" name as part of the substitution, so break here
- if lastword == -1 &&
- \ compl_type =~ 'table\|view\|procedure\column_csv' &&
+ if lastword == -1 &&
+ \ compl_type =~ 'table\|view\|procedure\column_csv' &&
\ g:omni_sql_include_owner == 0
let lastword = start
break
let compl_list = []
" Default to table name completion
- let compl_type = 'table'
+ let compl_type = g:omni_sql_default_compl_type
" Allow maps to specify what type of object completion they want
if exists('b:sql_compl_type')
let compl_type = b:sql_compl_type
if compl_type == 'table' ||
\ compl_type == 'procedure' ||
- \ compl_type == 'view'
+ \ compl_type == 'view'
" This type of completion relies upon the dbext.vim plugin
if s:SQLCCheck4dbext() == -1
if base == ""
" The last time we displayed a column list we stored
- " the table name. If the user selects a column list
+ " the table name. If the user selects a column list
" without a table name of alias present, assume they want
" the previous column list displayed.
let base = s:save_prev_table
" has entered:
" owner.table
" table.column_prefix
- " So there are a couple of things we can do to mitigate
+ " So there are a couple of things we can do to mitigate
" this issue.
" 1. Check if the dbext plugin has the option turned
" on to even allow owners
" 2. Based on 1, if the user is showing a table list
- " and the DrillIntoTable (using <Right>) then
+ " and the DrillIntoTable (using <Right>) then
" this will be owner.table. In this case, we can
- " check to see the table.column exists in the
+ " check to see the table.column exists in the
" cached table list. If it does, then we have
- " determined the user has actually chosen
+ " determined the user has actually chosen
" owner.table, not table.column_prefix.
let found = -1
if g:omni_sql_include_owner == 1 && owner == ''
" If the user has indicated not to use table owners at all and
" the base ends in a '.' we know they are not providing a column
" name, so we can shift the items appropriately.
- if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$')
- let owner = table
- let table = column
- let column = ''
- endif
+ " if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$')
+ " let owner = table
+ " let table = column
+ " let column = ''
+ " endif
else
+ " If no "." was provided and the user asked for
+ " column level completion, first attempt the match
+ " on any previous column lists. If the user asked
+ " for a list of columns comma separated, continue as usual.
+ if compl_type == 'column' && s:save_prev_table != ''
+ " The last time we displayed a column list we stored
+ " the table name. If the user selects a column list
+ " without a table name of alias present, assume they want
+ " the previous column list displayed.
+ let table = s:save_prev_table
+ let list_type = ''
+
+ let compl_list = s:SQLCGetColumns(table, list_type)
+ if ! empty(compl_list)
+ " If no column prefix has been provided and the table
+ " name was provided, append it to each of the items
+ " returned.
+ let compl_list = filter(deepcopy(compl_list), 'v:val=~"^'.base.'"' )
+
+ " If not empty, we have a match on columns
+ " return the list
+ if ! empty(compl_list)
+ return compl_list
+ endif
+ endif
+ endif
+ " Since no columns were found to match the base supplied
+ " assume the user is trying to complete the column list
+ " for a table (and or an alias to a table).
let table = base
endif
" Get anything after the . and consider this the table name
- " If an owner has been specified, then we must consider the
+ " If an owner has been specified, then we must consider the
" base to be a partial column name
" let base = matchstr( base, '^\(.*\.\)\?\zs.*' )
" If no column prefix has been provided and the table
" name was provided, append it to each of the items
" returned.
- let compl_list = map(compl_list, "table.'.'.v:val")
+ let compl_list = map(compl_list, 'table.".".v:val')
if owner != ''
" If an owner has been provided append it to each of the
" items returned.
- let compl_list = map(compl_list, "owner.'.'.v:val")
+ let compl_list = map(compl_list, 'owner.".".v:val')
endif
else
let base = ''
if base != ''
" Filter the list based on the first few characters the user entered.
- " Check if the text matches at the beginning
- " or
+ " Check if the text matches at the beginning
+ " \\(^.base.'\\)
+ " or
" Match to a owner.table or alias.column type match
+ " ^\\(\\w\\+\\.\\)\\?'.base.'\\)
" or
" Handle names with spaces "my table name"
+ " "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"'
+ "
let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"'
" let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\)"'
" let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\(\\.\\)\\?'.base.'\\)"'
let syn_group_arr = []
let syn_items = []
- if a:0 > 0
+ if a:0 > 0
if type(a:1) != 3
call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']")
return ''
function! sqlcomplete#ResetCacheSyntax(...)
let syn_group_arr = []
- if a:0 > 0
+ if a:0 > 0
if type(a:1) != 3
call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']")
return ''
" If the popup is not visible, simple perform the normal
" key behaviour.
" Must use exec since they key must be preceeded by "\"
- " or feedkeys will simply push each character of the string
+ " or feedkeys will simply push each character of the string
" rather than the "key press".
exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_right.'", "n")'
endif
" If the popup is not visible, simple perform the normal
" key behaviour.
" Must use exec since they key must be preceeded by "\"
- " or feedkeys will simply push each character of the string
+ " or feedkeys will simply push each character of the string
" rather than the "key press".
exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_left.'", "n")'
endif
function! s:SQLCWarningMsg(msg)
echohl WarningMsg
- echomsg 'SQLComplete:'.a:msg
+ echomsg 'SQLComplete:'.a:msg
echohl None
endfunction
-
+
function! s:SQLCErrorMsg(msg)
echohl ErrorMsg
- echomsg 'SQLComplete:'.a:msg
+ echomsg 'SQLComplete:'.a:msg
echohl None
endfunction
-
+
function! s:SQLCGetSyntaxList(syn_group)
let syn_group = a:syn_group
let compl_list = []
" Return previously cached value
let compl_list = s:syn_value[list_idx]
else
- " Request the syntax list items from the
+ " Request the syntax list items from the
" syntax completion plugin
if syn_group == 'syntax'
" Handle this special case. This allows the user
let table_alias = a:table_alias
let cols = a:cols
- if g:omni_sql_use_tbl_alias != 'n'
+ if g:omni_sql_use_tbl_alias != 'n'
if table_alias == ''
if 'da' =~? g:omni_sql_use_tbl_alias
if table_name =~ '_'
setlocal iskeyword-=_
" Get the first letter of each word
- " [[:alpha:]] is used instead of \w
+ " [[:alpha:]] is used instead of \w
" to catch extended accented characters
"
- let table_alias = substitute(
- \ table_name,
- \ '\<[[:alpha:]]\+\>_\?',
- \ '\=strpart(submatch(0), 0, 1)',
+ let table_alias = substitute(
+ \ table_name,
+ \ '\<[[:alpha:]]\+\>_\?',
+ \ '\=strpart(submatch(0), 0, 1)',
\ 'g'
\ )
" Restore original value
return cols
endfunction
-function! s:SQLCGetObjectOwner(object)
+function! s:SQLCGetObjectOwner(object)
" The owner regex matches a word at the start of the string which is
" followed by a dot, but doesn't include the dot in the result.
" ^ - from beginning of line
" let owner = matchstr( a:object, '^\s*\zs.*\ze\.' )
let owner = matchstr( a:object, '^\("\|\[\)\?\zs\.\{-}\ze\("\|\]\)\?\.' )
return owner
-endfunction
+endfunction
function! s:SQLCGetColumns(table_name, list_type)
" Check if the table name was provided as part of the column name
if list_idx > -1
let table_cols = split(s:tbl_cols[list_idx], '\n')
else
- " Check if we have already cached the column list for this table
+ " Check if we have already cached the column list for this table
" by its alias, assuming the table_name provided was actually
" the alias for the table instead
" select *
" And the table ends in a "." or we are looking for a column list
" if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column')
" if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv')
- if list_idx == -1
+ if list_idx == -1
let saveY = @y
let saveSearch = @/
let saveWScan = &wrapscan
setlocal nowrapscan
" If . was entered, look at the word just before the .
" We are looking for something like this:
- " select *
+ " select *
" from customer c
" where c.
" So when . is pressed, we need to find 'c'
" if query =~? '^\c\(select\)'
if query =~? '^\(select\|update\|delete\)'
let found = 1
- " \(\(\<\w\+\>\)\.\)\? -
+ " \(\(\<\w\+\>\)\.\)\? -
" '\c\(from\|join\|,\).\{-}' - Starting at the from clause (case insensitive)
" '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional)
- " '\<\w\+\>\ze' - Get the table name
+ " '\<\w\+\>\ze' - Get the table name
" '\s\+\<'.table_name.'\>' - Followed by the alias
" '\s*\.\@!.*' - Cannot be followed by a .
" '\(\<where\>\|$\)' - Must be followed by a WHERE clause
" '.*' - Exclude the rest of the line in the match
- " let table_name_new = matchstr(@y,
+ " let table_name_new = matchstr(@y,
" \ '\c\(from\|join\|,\).\{-}'.
" \ '\zs\(\("\|\[\)\?.\{-}\("\|\]\)\.\)\?'.
" \ '\("\|\[\)\?.\{-}\("\|\]\)\?\ze'.
" \ '\(\<where\>\|$\)'.
" \ '.*'
" \ )
- let table_name_new = matchstr(@y,
+ "
+ "
+ " ''\c\(\<from\>\|\<join\>\|,\)\s*' - Starting at the from clause (case insensitive)
+ " '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?' - Get the owner name (optional)
+ " '\("\|\[\)\?\w\+\("\|\]\)\?\ze' - Get the table name
+ " '\s\+\%(as\s\+\)\?\<'.matchstr(table_name, '.\{-}\ze\.\?$').'\>' - Followed by the alias
+ " '\s*\.\@!.*' - Cannot be followed by a .
+ " '\(\<where\>\|$\)' - Must be followed by a WHERE clause
+ " '.*' - Exclude the rest of the line in the match
+ let table_name_new = matchstr(@y,
\ '\c\(\<from\>\|\<join\>\|,\)\s*'.
\ '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?'.
\ '\("\|\[\)\?\w\+\("\|\]\)\?\ze'.
" Return to previous location
call cursor(curline, curcol)
-
+
if found == 0
if g:loaded_dbext > 300
exec 'DBSetOption use_tbl_alias='.saveSettingAlias
" Not a SQL statement, do not display a list
return []
endif
- endif
+ endif
if empty(table_cols)
" Specify silent mode, no messages to the user (tbl, 1)
" Vim syntax file
" Language: Reva Forth
-" Version: 7.1
-" Last Change: 2008/01/11
+" Version: 2011.2
+" Last Change: 2012/02/13
" Maintainer: Ron Aaron <ron@ronware.org>
" URL: http://ronware.org/reva/
-" Filetypes: *.rf *.frt
+" Filetypes: *.rf *.frt
" NOTE: You should also have the ftplugin/reva.vim file to set 'isk'
" For version 5.x: Clear all syntax items and don't load
finish
endif
+let s:cpo_save = &cpo
+set cpo&vim
+
syn clear
" Synchronization method
-syn sync ccomment
+syn sync ccomment
syn sync maxlines=100
syn case match
" basic mathematical and logical operators
syn keyword revaoperators + - * / mod /mod negate abs min max umin umax
-syn keyword revaoperators and or xor not invert 1+ 1-
+syn keyword revaoperators and or xor not invert 1+ 1-
syn keyword revaoperators m+ */ */mod m* um* m*/ um/mod fm/mod sm/rem
syn keyword revaoperators d+ d- dnegate dabs dmin dmax > < = >> << u< <>
" address operations
syn keyword revamemory @ ! +! c@ c! 2@ 2! align aligned allot allocate here free resize
syn keyword revaadrarith chars char+ cells cell+ cell cell- 2cell+ 2cell- 3cell+ 4cell+
-syn keyword revamemblks move fill
+syn keyword revamemblks move fill
" conditionals
-syn keyword revacond if else then =if >if <if <>if if0 ;; catch throw
+syn keyword revacond if else then =if >if <if <>if if0 ;; catch throw
" iterations
syn keyword revaloop while repeat until again
syn match revaColonDef '\<noname:\|\<:\s+' contains=revaComment
syn keyword revaEndOfColonDef ; ;inline
syn keyword revadefine constant constant, variable create variable,
-syn keyword revadefine user value to +to defer! defer@ defer is does> immediate
+syn keyword revadefine user value to +to defer! defer@ defer is does> immediate
syn keyword revadefine compile literal ' [']
" Built in words
com! -nargs=+ Builtin syn keyword revaBuiltin <args>
Builtin execute ahead interp bye >body here pad words make
Builtin accept close cr creat delete ekey emit fsize ioerr key?
-Builtin mtime open/r open/rw read rename seek space spaces stat
+Builtin mtime open/r open/rw read rename seek space spaces stat
Builtin tell type type_ write (seek) (argv) (save) 0; 0drop;
Builtin >class >lz >name >xt alias alias: appname argc asciiz, asciizl,
Builtin body> clamp depth disassemble findprev fnvhash getenv here,
-Builtin iterate last! last@ later link lz> lzmax os parse/ peek
+Builtin iterate last! last@ later link lz> lzmax os parse/ peek
Builtin peek-n pop prior push put rp@ rpick save setenv slurp
Builtin stack-empty? stack-iterate stack-size stack: THROW_BADFUNC
Builtin THROW_BADLIB THROW_GENERIC used xt>size z,
Builtin (-lib) (bye) (call) (else) (find) (func) (here) (if (lib) (s0) (s^)
Builtin (to~) (while) >in >rel ?literal appstart cold compiling? context? d0 default_class
Builtin defer? dict dolstr dostr find-word h0 if) interp isa onexit
-Builtin onstartup pdoes pop>ebx prompt rel> rp0 s0 src srcstr state str0 then,> then> tib
+Builtin onstartup pdoes pop>ebx prompt rel> rp0 s0 src srcstr state str0 then,> then> tib
Builtin tp vector vector! word? xt? .ver revaver revaver# && '' 'constant 'context
Builtin 'create 'defer 'does 'forth 'inline 'macro 'macront 'notail 'value 'variable
Builtin (.r) (context) (create) (header) (hide) (inline) (p.r) (words~) (xfind)
Builtin ++ -- , -2drop -2nip -link -swap . .2x .classes .contexts .funcs .libs .needs .r
Builtin .rs .x 00; 0do 0if 1, 2, 3, 2* 2/ 2constant 2variable 3dup 4dup ;then >base >defer
Builtin >rr ? ?do @execute @rem appdir argv as back base base! between chain cleanup-libs
-Builtin cmove> context?? ctrl-c ctx>name data: defer: defer@def dictgone do_cr eleave
-Builtin endcase endof eval exception exec false find func: header heapgone help help/
+Builtin cmove> context?? ctrl-c ctx>name data: defer: defer@def dictgone do_cr eleave
+Builtin endcase endof eval exception exec false find func: header heapgone help help/
Builtin hex# hide inline{ last lastxt lib libdir literal, makeexename mnotail ms ms@
-Builtin newclass noop nosavedict notail nul of off on p: padchar parse parseln
-Builtin parsews rangeof rdepth remains reset reva revaused rol8 rr> scratch setclass sp
+Builtin newclass noop nosavedict notail nul of off on p: padchar parse parseln
+Builtin parsews rangeof rdepth remains reset reva revaused rol8 rr> scratch setclass sp
Builtin strof super> temp time&date true turnkey? undo vfunc: w! w@
Builtin xchg xchg2 xfind xt>name xwords { {{ }} } _+ _1+ _1- pathsep case \||
-" p[ [''] [ [']
+" p[ [''] [ [']
" debugging
" syn region revaCharOps start=+."\s+ skip=+\\"+ end=+"+
" char-number conversion
-syn keyword revaconversion s>d >digit digit> >single >double >number >float
+syn keyword revaconversion s>d >digit digit> >single >double >number >float
" contexts
-syn keyword revavocs forth macro inline
-syn keyword revavocs context:
+syn keyword revavocs forth macro inline
+syn keyword revavocs context:
syn match revavocs /\<\~[^~ ]*/
syn match revavocs /[^~ ]*\~\>/
" Strings
" syn region revaString start=+\.\?\"+ end=+"+ end=+$+
-syn region revaString start=/"/ skip=/\\"/ end=/"/
+syn region revaString start=/"/ skip=/\\"/ end=/"/
" Comments
syn region revaComment start='\\S\s' end='.*' contains=revaTodo
endif
let b:current_syntax = "reva"
+let &cpo = s:cpo_save
+unlet s:cpo_save
" vim: ts=8:sw=4:nocindent:smartindent: