" Vimball Archiver by Charles E. Campbell, Jr., Ph.D. UseVimball finish doc/tskeleton.txt [[[1 1178 *tskeleton.txt* tskeleton -- File Templates and Code Skeletons Author: Tom Link, micathom AT gmail com?subject=vim tskeleton provides file templates and code skeletons ("snippets" or "bits"). These templates may contain special tags that are replaced with some computed value (e.g., variables, user input ...), vimscript code, or place holders/jump positions (see |tskeleton-jump-positions|). Basic usage: Type `:new filename.ext`. If a skeleton for the respective filetype is defined (see |tskeleton-skeletons|), it will be read into the buffer. Type a partial name of a snippet (at least the first letter) and press (in insert mode) (see |tskeleton-key-bindings| for alternative key maps). If the name identifies a snippet/bit, it will be replaced with its expansion text. If there are several snippets beginning with that "name", you will be asked to select one from a list of matching snippets. can be configured to expand snippets but also (albeit disabled by default) abbreviations, functions (VIM script only), tags, word, 'completefunc' and 'omnifunc' items (see |g:tskelTypes| and |g:tskelHyperComplete| for details.) Press to jump to the next place holder (see |tskeleton#GoToNextTag()|). Demo -- tskeleton and the stakeholders (vimscript #3326) plugin: http://vimsomnia.blogspot.com/2010/11/tskeleton-and-stakeholders-vim-plugins.html Git: https://github.com/tomtom/tskeleton_vim For similar plugins see: http://vim.wikia.com/wiki/Snippet_Plugin_Comparison Limitations of tskeleton: - Place holders cannot be nested. - tskeleton was originally written for vim 6.0. I'd expect it to be less snappy than more modern and simpler plugins, although it tries to provide acceptable performance on slower computers by caching frequently reused data. Advantages of tskeleton with respect to some other plugins: - tskeleton provides for more complex templates (see |tskeleton-place-holder|) including conditional expansion, loops, inclusion of other templates, user queries etc. - Easy creation of camel case, all upper/lower case letter names etc. (see |tskeleton-modifiers|). It depends: - A place holder is some text in the buffer, i.e. tskeleton uses less magic when handling jump positions. As long as users don't replace all place holders, the buffer's contents most likely isn't valid code and an interpreter/compiler will most likely refuse to load it even if the code is never executed. ----------------------------------------------------------------------- *tskeleton-install* Install~ Edit the vba file and type: :so % See :help vimball for details. It is recommended to use tskeleton in conjunction with the stakeholders plugin (vimscript #3326): http://www.vim.org/scripts/script.php?script_id=3326 https://github.com/tomtom/stakeholders_vim If you don't already have some skeletons, you may want to download tskeleton-Samples.zip from: http://www.vim.org/scripts/script.php?script_id=1160 or from https://github.com/tomtom/tskeletons Copy the files to your local vimfiles directory (see also |add-global-plugin|). The directory structure should look like this: ~/.vim/skeletons/ FILE TEMPLATES ... map/ MAP FILES FOR CONDITIONAL EXPANSION bits/ &filetype.txt (single line templates) general/ GENERAL CODE SKELETONS ... &filetype/ FILETYPE SPECIFIC CODE SKELETONS: ONE SKELETON PER FILE ... *tskeleton-snippets* tskeleton also provides partial support for snipMate snippets (see https://github.com/honza/snipmate-snippets). The following limitations apply: - tskeleton cannot handle nested tags/place holders *tskeleton-cache* In order to speed up things, tskeleton caches intermediate results. Those files are created in |g:tlib_cache|. By default, the old files will be removed from the cache every |g:tlib#cache#purge_every_days| days. In order to disable purging (e.g. if you purge the cache directory by means of a cron script), set |g:tlib#cache#purge_every_days| to -1. ----------------------------------------------------------------------- *tskeleton-usage* *tskeleton-skeletons* File templates~ The file skeletons are stored in the skeletons subdirectory. Which template is used for which new file is controlled by |:autocmd|s. This provides greater flexibility than a &filetype based approach as you can select templates on the basis of a filename pattern or a specific directory. Currently, the following file types are supported by default: - batch.bat - deplate.txt - latex.tex - php.inc.php - php.php - plugin.vim - ruby.rb - shell.sh - text.txt In order to add support for a new filetype, save a skeleton file to ~/.vim/skeletons/file.suffix and add something like this to your .vimrc file: > autocmd BufNewFile *.suffix TSkeletonSetup template.suffix autocmd BufNewFile /here/*.suffix TSkeletonSetup othertemplate.suffix Alternatively, you can store templates as: > ~/.vim/skeletons/templates/GROUP/FILETYPE PATTERN where GROUP is an arbitrary name for a collection of auto templates, FILETYPE is a know vim filetype, and the pattern is an encoded pattern (# == *, %XX=Char XXh) for auto-generated autocmds. Example: Templates file names for some vim-related files: > ~/.vim/skeletons/templates/vim/help #%2fvimfiles%2fdoc%2f#.txt ~/.vim/skeletons/templates/vim/vim #%2fvimfiles#%2fftplugin%2f#.vim ~/.vim/skeletons/templates/vim/vim #%2fvimfiles#%2fsyntax%2f#.vim < *tskeleton-place-holder* Tags (which look like <+...+>) serve two purposes: - marker for jump positions (see |tskeleton#GoToNextTag()|) - dynamic content expansion You can use tags to define cursor jump positions. tskeleton also supports some special tags that are expanded when inserting the skeleton. A list of special tags: *tSkeletion-<+FILE NAME ROOT+>* <+FILE NAME ROOT+> The file name root *tSkeletion-<+FILE NAME+>* <+FILE NAME+> The file name *tSkeletion-<+FILE SUFFIX+>* <+FILE SUFFIX+> The file suffix *tSkeletion-<+FILE DIRNAME+>* <+FILE DIRNAME+> The file's directory *tSkeletion-<+NOTE+>* <+NOTE+> A note *tSkeletion-<+DATE+>* <+DATE+> The current date (the format is controlled via g:tskelDateFormat) *tSkeletion-<+AUTHOR+>* <+AUTHOR+> The author's name (g:tskelUserName) *tSkeletion-<+EMAIL+>* <+EMAIL+> The author's e-mail (g:tskelUserEmail) *tSkeletion-<+COMPANY+>* <+COMPANY+> The author's company (g:tskelUserCompany) *tSkeletion-<+WEBSITE+>* <+WEBSITE+> The author's homepage (g:tskelUserWWW) *tSkeletion-<+LICENSE+>* <+LICENSE+> The name of the license this file is released under (g:tskelLicense) In order to define your own tag, you have to define a function called TSkeleton_TAGNAME() that returns the text to be filled in. *tskeleton-tags* tskeleton also supports the following pseudo-tags: <+CURSOR+> *tSkeletion-<+CURSOR+>* Where to place the cursor after insertion <+&NAME+> *tSkeletion-<+&+>* A vim option <+g:NAME+> *tSkeletion-<+g:+>* A global variable <+b:NAME+> *tSkeletion-<+b:+>* A buffer local variable <+?QUERY?+> *tSkeletion-<+?+>* Query[1] the user <+?VAR|QUERY?+> Query[1] the user and propose some choices from the variable VAR *tSkeletion-<+bit+>* <+bit:BIT+>, <+bit:BIT|"DEFAULT"+>, <+bit:BIT|COMMANDS+> Insert a bit; if the bit isn't defined for the current filetype, use DEFAULT; if DEFAULT matches ".*" insert it as a string; otherwise interpret it as a command sequence to be fed to normal <+tskel:TSKELETON+> *tSkeletion-<+tskel+>* Same as the above <+call:FUNCTION(ARGS)+> *tSkeletion-<+call+>* Insert the result value of some function <+include(TSKELETON)+> *tSkeletion-<+include+>* Another synonym for the above. <+execute(EX COMMAND)+> *tSkeletion-<+execute+>* Run a vim command. [1] If the query ends with a colon, the second question mark will be removed. Up to verson 2.4 VAR is a string, separating the items by an "\n". From 3.0 on, VAR is a list. NOTE: Flow control and loop tags are experimental and it's more than just likely that the output doesn't meet your expectations. Flow control: *tSkeletion-<+if+>* <+if(CONDITION)+> <+elseif(CONDITION)+> <+else+> <+endif+> Loops: *tSkeletion-<+for+>* <+for(VAR in LIST)+> <+endfor+>, <+endfor(VAR)+> If you nest for loops, you have to add the variable name to the endfor tag. And no, this isn't the most clever way to do this. Variables: *tSkeletion-<+let+>* <+let(VAR=VALUE)+> The variable will be unset or restored to its original value after processing the current template. VAR may have some modifiers attached: VAR? ... Set only if undefined VAR& ... Don't restore original variable Interaction: *tSkeletion-<+input+>* <+input(VAR, QUERY, [DEFAULT], [COMPLETION])+> This will insert the user input and set the variable VAR (unless empty), which can be used throughout the template. The variable will be removed after finishing the current template. If the variable was previously defined, the original value will be restored. If VAR ends with '!', no text will be inserted in the buffer. In this case any whitespace (including one newline) after the tag will be removed. See also the notes on |tSkeletion-<+input+>|. *tSkeletion-<+select+>* <+select(VAR, LIST, [TYPE='s'], [SEPARATOR=', '])+> Let the user select an item from a list. VAR is a string. TYPE is either 's' (single selection) or 'm' (multiple selection) -- see also |tlib#input#List()|. If TYPE is 'm', the results are joined with SEPARATOR. Example: > before(<+select("s:type", [":all", ":each"])+>) before(<+select("s:type", ["A", "B", "C", "D"], "m", "-")+>) < Other: *tSkeletion-<+nl+>* <+nl+> Insert a newline <+joinline+> *tSkeletion-<+joinline+>* Join with next line. Delete any whitespace. <+nop+> *tSkeletion-<+nop+>* Insert nothing (could be necessary in conjunction with the "for" tag) A wiki like table could then be constructed using a skeleton like this: > let s:my_rows = input('Rows: ') let s:my_cols = input('Columns: ') unlet! s:my_rows s:my_cols <+CURSOR+><+for(i in range(s:my_rows))+> |<+for(j in range(s:my_cols))+> <+CELL+> |<+endfor(j)+><+nop+> <+endfor(i)+> or: > <+input('s:my_rows?!', 'Rows: ')+> <+input('s:my_cols?!', 'Cols: ')+> <+for(i in range(s:my_rows))+> |<+for(j in range(s:my_cols))+> <+CURSOR+> |<+endfor(j)+><+nop+> <+endfor(i)+> NOTE: The <+nop+> is necessary in order to prevent the <+endfor+> tag to "eat" the newline. If we include this bit from another bit that already sets s:my_rows and/or s:my_cols, the user won't be queried again (because of the "?" in the input statement). E.g. > <+let(s:my_rows = 3)+> <+let(s:my_cols = 3)+> <+include(table)+> *tSkeletion-backslash* Any special tag can be preceded with a backslash in order to prevent expansion. Examples: > <+\if(foo=1)+> surprisingly expands to > <+if(foo=1)+> It's best to use global variables with "if" and "for" tags as the body is most likely evaluated in a different buffer in a hypothetically unknown context. *tskeleton-jump-positions* Unknown tags are kept in the expanded skeleton. These tags can be used as cursor jump marks. This syntax was originally used by imap (vimscript #244 or vimscript #475). If you don't want to install imap, you can also use |TSkeletonMapGoToNextTag()|. Nameless tags (<++>) will disappear when they are selected. Example:> case <+CURSOR+> in <+PATTERN+>) <+BODY+> ;; *) <+DEFAULT+> ;; esac <++> When you insert this skeleton, the cursor will be placed at "<+CURSOR+>". If you press , the cursor will jump to "<+PATTERN+>" (the tag will remain selected). If you press three times, the cursor will jump to "<++>" (the tag will be deleted). Check out the "test_tskeleton" skeleton for examples. *tskeleton-modifiers* Tags can be modified using modifiers, like in: > <+TAG NAME:MODIFIER+> Known modifiers: l :: lower case u :: upper case c :: capitalize C :: transform to CamelCase s/FROM/TO/ :: replace text (actually a s//g); this has to be the last modifier; the pattern separator can be selected arbitrarily Example for a ruby class template: > class <+FILE NAME ROOT:cs*\W*_*+> <+CURSOR+> end <++> ----------------------------------------------------------------------- *tskeleton-code-skeletons* *tskeleton-bits* Bits/Code Skeletons~ Smaller skeleton bits are stored in SKELETONS/bits/FILETYPE/ or SKELETONS/bits/general/. I.e., code skeletons can be filetype specific or generally available. The filenames of the bits may be grouped in submenus as in: ../tex/&Define.%5Cnew&command ../tex/&Define.%5Cnew&environment This will create skeletons for \newcommand and \newenvironment but will group the skeletons under the TSkel.Define. menu with the respective accelerators. *tskeleton-Types* *g:tskelTypes* *tskeleton#Initialize()* tskeleton supports several types of code templates: - skeleton (standard tskeleton functionality) - abbreviations (VIM abbreviations) - functions (VIM script functions extracted from :function) - mini ("mini" bits, one-liners etc.) - tags (tags-based code templates, requires ctags, I presume) Not all types are enabled by default. User have to select, which types they want to use, by setting the g:tskelTypes at start-up. When changing the variable, users might have to call tskeleton#Initialize(). *tskeleton-Skeleton* Smaller skeleton bits are stored in SKELETONS/bits/FILETYPE/ or SKELETONS/bits/general/. I.e., code skeletons can be filetype specific or generally available. Skeleton bits can be filled in by typing: > :TSkeletonBit NAME For this command, command line completion is implemented. Calling this command will insert the contents of the respective file below the current line. NOTE: Bit names should not contain ampersand (as these are interpreted as menu accelerators) and periods (which are used to construct submenus). Other special characters can be included by encoding them in hex form as %XX as it is done in URLs. Example: "%5Csection" becomes "\section". *tskeleton-key-bindings* The default key bindings for inserting code skeletons are: ... In insert mode, expand name before the cursor ## ... Expand name under cursor #t ... Insert code skeleton via command line ... In insert mode, expand the bit before the cursor (on a German keyboard this happens to be ) *g:tskelKeyword_{&filetype}* A bit name usually is the |word| under the cursor. If this doesn't fit your needs, you can define g:tskelKeyword_{&filetype} to define what makes up a skeleton name. Example: > let g:tskelKeyword_viki = '\(#\|{\)\?[^#{[:blank:]]\{-}' *tskeleton-embedded-code* Code skeletons may contain vim code that is evaluated before or after expanding the tags. The before/after blocks are fed to |:exec| and must not contain function definitions. NOTE: The "parser" is quite primitive. These tags have to start as single statement in a line at column 1, and they have to appear in the following order: ** Display an explanatory message after template expansion ** Execute code before template expansion in the target buffer ** Execute code after template expansion in the target buffer ** Execute code before template expansion in the template buffer ** Execute code after template expansion in the template buffer ** Make the bit available via |:abbreviate| under the enclosed name. ** Use this menu name instead of the default one. ** An expression that checks whether a bit is eligible in the current context. BibTeX example: > Insert a collection entry let b:tskelArticleID = input("ID of bibentry: ") if b:tskelArticleID == "" | let b:tskelArticleID = "<+CURSOR+>" | endif unlet b:tskelArticleID @INCOLLECTION{<+b:tskelArticleID+>, author = {<+CURSOR+>}, title = {<+ARTICLE TITLE+>}, crossref = {<+CROSSREF+>}, pages = {<+PAGES+>}, abstract = {[[~/Docs/Abstracts/<+b:tskelArticleID+>.txt]]}, } <++> In the above example, we query the user for an ID and insert this ID as entry key and as an abstract's file name. The before/after blocks are evaluated in the destination buffer. The variants here_before/here_after are evaluated in the scratch buffer for the current code skeleton. *tskeleton-groups* *g:tskelBitGroup_{&filetype}* Groups~ Some filetype's bits might be of use for other filetypes too. You can make them accessible by defining a g:tskelBitGroup_{&filetype} variable. E.g., in php mode all html bits are made accessible by setting this variable (the default): > let g:tskelBitGroup_php = ['php', 'html'] Bits of type "general" are always available. *tskeleton-context* *tskeleton-map* Maps -- Context-sensitive expansion~ To some extent, tskeleton is capable of offering the user only a small selection of eligible bits for a specific context if a map file ($VIMFILES/skeletons/map/{&filetype}) is provided. Such a map file is made up of regular expressions matching a specific context (before the cursor only) and a blank-separated list of eligible bits. The regexp and the list are separated by whitespace: > REGEXP BIT1 BIT2 ... BITn Example: > ]\\|\\n\\)* name= action= method= If an eligible bit is undefined, the name is inserted as is. I.e. you don't have to define skeletons for all these options and argument names. *tskeleton-minibits* Minibits~ Mini bits are kept in the files: - $CWD/.tskelmini - $VIMFILES/skeletons/bits/{&filetype}.txt These files contain whitespace-separated pairs of bit names and their expansions. These files are meant to keep expansions of accronyms and abbreviations and the like. Example: > IMHO In my humble opinion AFAIK As far as I know *tskeleton-menu* *g:tskelMenuPrefix* Menu~ If g:tskelMenuPrefix is non-empty, tskeleton will display a menu containing all eligible bits for a certain filetype. The menu can be hierarchical and certain entries may have shortcuts by properly naming the bits. Example: > &Environment.&Quote &Environment.Q&uotation This will create the submenu "Environment" that can be selected by typing "e" (on Windows) and two entries, the first of which can be selected by typing "q" and the second by typing "u". Be aware that the actual bit names are Quote and Quotation (i.e. the submenu and the ampersand are stripped off). ----------------------------------------------------------------------- *tskeleton-utilities* Utilities~ *tskeleton#IncreaseRevisionNumber()* The function tskeleton#IncreaseRevisionNumber() provides a way to automatically update a revision number in the form > @Revision: 1.0.393 In order to use this function, add something like this to your |vimrc| file: > autocmd BufWritePre * call tskeleton#IncreaseRevisionNumber() *:TSkeletonCleanUpBibEntry* The TSkeletonCleanUpBibEntry command can be used to purge the current bibtex entry from expendable fields (i.e., lines matching <+.\{-}+>). For bibtex files, this command is bound to: tc *TSkeletonMapGoToNextTag()* *tskeleton#GoToNextTag()* If g:tskelMapGoToNextTag is true, the map will be enabled. (That is the key that was also used by the imaps.vim plugin.) Press to jump between tags. This function provides one or two extras over the version of imaps.vim. An explanation: - ###, +++, ???, !!! are used as markers too. - If a marker is empty (e.g. <++>), the marker will be removed (as imaps.vim does). - If a marker matches <+NAME/DEFAULT+>, the marker will be replaced with DEFAULT. - If a snippet contains numbered placeholders (e.g. <+1+>), these will be selected first in increasing number. ======================================================================== Contents~ tskeleton#abbreviations#Reset .............. |tskeleton#abbreviations#Reset()| tskeleton#abbreviations#Initialize ......... |tskeleton#abbreviations#Initialize()| tskeleton#abbreviations#GetAbbreviations ... |tskeleton#abbreviations#GetAbbreviations()| tskeleton#abbreviations#BufferBits ......... |tskeleton#abbreviations#BufferBits()| tskeleton#abbreviations#Retrieve ........... |tskeleton#abbreviations#Retrieve()| tskeleton#functions#Initialize ............. |tskeleton#functions#Initialize()| tskeleton#functions#FiletypeBits_vim ....... |tskeleton#functions#FiletypeBits_vim()| tskeleton#mini#Initialize .................. |tskeleton#mini#Initialize()| tskeleton#mini#FiletypeBits ................ |tskeleton#mini#FiletypeBits()| tskeleton#skeleton#Initialize .............. |tskeleton#skeleton#Initialize()| tskeleton#skeleton#FiletypeBits ............ |tskeleton#skeleton#FiletypeBits()| tskeleton#skeleton#BufferBits .............. |tskeleton#skeleton#BufferBits()| tskeleton#skeleton#Generator ............... |tskeleton#skeleton#Generator()| tskeleton#tags#Initialize .................. |tskeleton#tags#Initialize()| tskeleton#tags#BufferBits .................. |tskeleton#tags#BufferBits()| tskeleton#tags#Process_vim ................. |tskeleton#tags#Process_vim()| tskeleton#tags#Process_ruby ................ |tskeleton#tags#Process_ruby()| tskeleton#tags#Process_c ................... |tskeleton#tags#Process_c()| tskeleton#tags#Process_java ................ |tskeleton#tags#Process_java()| tskeleton#completefunc#Initialize .......... |tskeleton#completefunc#Initialize()| tskeleton#completefunc#FiletypeBits ........ |tskeleton#completefunc#FiletypeBits()| tskeleton#omnicomplete#Initialize .......... |tskeleton#omnicomplete#Initialize()| tskeleton#omnicomplete#FiletypeBits ........ |tskeleton#omnicomplete#FiletypeBits()| g:tskelBitsIgnore .......................... |g:tskelBitsIgnore| g:tskelNewBufferIsDirty .................... |g:tskelNewBufferIsDirty| g:tskeleton#enable_stakeholders ............ |g:tskeleton#enable_stakeholders| g:tskeleton#max_basename ................... |g:tskeleton#max_basename| g:tskeleton#conceal_cchar .................. |g:tskeleton#conceal_cchar| TSkeleton_FILE_DIRNAME ..................... |TSkeleton_FILE_DIRNAME()| TSkeleton_FILE_SUFFIX ...................... |TSkeleton_FILE_SUFFIX()| TSkeleton_FILE_NAME_ROOT ................... |TSkeleton_FILE_NAME_ROOT()| TSkeleton_FILE_NAME ........................ |TSkeleton_FILE_NAME()| TSkeleton_NOTE ............................. |TSkeleton_NOTE()| TSkeleton_DATE ............................. |TSkeleton_DATE()| TSkeleton_TIME ............................. |TSkeleton_TIME()| TSkeleton_AUTHOR ........................... |TSkeleton_AUTHOR()| TSkeleton_EMAIL ............................ |TSkeleton_EMAIL()| TSkeleton_COMPANY .......................... |TSkeleton_COMPANY()| TSkeleton_WEBSITE .......................... |TSkeleton_WEBSITE()| TSkeleton_LICENSE .......................... |TSkeleton_LICENSE()| TSkeletonCB_FILENAME ....................... |TSkeletonCB_FILENAME()| TSkeletonCB_DIRNAME ........................ |TSkeletonCB_DIRNAME()| TSkelNewScratchHook_viki ................... |TSkelNewScratchHook_viki()| tskeleton#WrapMarker ....................... |tskeleton#WrapMarker()| tskeleton#CursorMarker ..................... |tskeleton#CursorMarker()| tskeleton#TagRx ............................ |tskeleton#TagRx()| tskeleton#ExpandedAbbreviationTemplate ..... |tskeleton#ExpandedAbbreviationTemplate()| tskeleton#FillIn ........................... |tskeleton#FillIn()| tskeleton#ExtractMeta ...................... |tskeleton#ExtractMeta()| tskeleton#SetCursor ........................ |tskeleton#SetCursor()| tskeleton#GetVar ........................... |tskeleton#GetVar()| tskeleton#GetDestBuffer .................... |tskeleton#GetDestBuffer()| tskeleton#EvalInDestBuffer ................. |tskeleton#EvalInDestBuffer()| tskeleton#ExecInDestBuffer ................. |tskeleton#ExecInDestBuffer()| tskeleton#FindTemplate ..................... |tskeleton#FindTemplate()| tskeleton#CollectTemplates ................. |tskeleton#CollectTemplates()| tskeleton#Setup ............................ |tskeleton#Setup()| tskeleton#SelectTemplate ................... |tskeleton#SelectTemplate()| tskeleton#EditBitCompletion ................ |tskeleton#EditBitCompletion()| tskeleton#Edit ............................. |tskeleton#Edit()| tskeleton#BitsPath ......................... |tskeleton#BitsPath()| tskeleton#EditBit .......................... |tskeleton#EditBit()| tskeleton#NewFile .......................... |tskeleton#NewFile()| tskeleton#NewBufferMenuItem ................ |tskeleton#NewBufferMenuItem()| tskeleton#FetchMiniBits .................... |tskeleton#FetchMiniBits()| tskeleton#MaybePathshorten ................. |tskeleton#MaybePathshorten()| tskeleton#FetchMiniBitsGenerator ........... |tskeleton#FetchMiniBitsGenerator()| tskeleton#ReplacePrototypeArgs ............. |tskeleton#ReplacePrototypeArgs()| tskeleton#PurifyBit ........................ |tskeleton#PurifyBit()| tskeleton#BitDef ........................... |tskeleton#BitDef()| tskeleton#BuildBufferMenu .................. |tskeleton#BuildBufferMenu()| tskeleton#PrepareBits ...................... |tskeleton#PrepareBits()| tskeleton#ResetBits ........................ |tskeleton#ResetBits()| tskeleton#SelectBit ........................ |tskeleton#SelectBit()| tskeleton#IsScratchBuffer .................. |tskeleton#IsScratchBuffer()| tskeleton#Retrieve ......................... |tskeleton#Retrieve()| tskeleton#Bit .............................. |tskeleton#Bit()| tskeleton#ExpandBitUnderCursor ............. |tskeleton#ExpandBitUnderCursor()| tskeleton#WithSelection .................... |tskeleton#WithSelection()| tskeleton#Complete_use_omnifunc ............ |tskeleton#Complete_use_omnifunc()| tskeleton#Complete_use_completefunc ........ |tskeleton#Complete_use_completefunc()| tskeleton#Complete_scan_words .............. |tskeleton#Complete_scan_words()| tskeleton#Complete_scan_tags ............... |tskeleton#Complete_scan_tags()| tskeleton#GetCompletions ................... |tskeleton#GetCompletions()| tskeleton#Complete ......................... |tskeleton#Complete()| tskeleton#Placeholders ..................... |tskeleton#Placeholders()| tskeleton#LateExpand ....................... |tskeleton#LateExpand()| tskeleton#Repeat ........................... |tskeleton#Repeat()| tskeleton#InsertTable ...................... |tskeleton#InsertTable()| tskeleton#HyperComplete_query .............. |tskeleton#HyperComplete_query()| tskeleton#HyperComplete_pum ................ |tskeleton#HyperComplete_pum()| g:tskelGlobalBitsPath ...................... |g:tskelGlobalBitsPath| g:tskelLocalBitsDirs ....................... |g:tskelLocalBitsDirs| g:tskelMapLeader ........................... |g:tskelMapLeader| g:tskelMapInsert ........................... |g:tskelMapInsert| g:tskelAddMapInsert ........................ |g:tskelAddMapInsert| g:tskelMenuCache ........................... |g:tskelMenuCache| g:tskelMapGoToNextTag ...................... |g:tskelMapGoToNextTag| g:tskelMapHyperComplete .................... |g:tskelMapHyperComplete| g:tskelHyperComplete ....................... |g:tskelHyperComplete| g:tskelHyperType ........................... |g:tskelHyperType| TSkeletonMapHyperComplete .................. |TSkeletonMapHyperComplete()| :TSkeletonSetup ............................ |:TSkeletonSetup| :TSkeletonEdit ............................. |:TSkeletonEdit| :TSkeletonEditBit .......................... |:TSkeletonEditBit| :TSkeletonNewFile .......................... |:TSkeletonNewFile| :TSkeletonBitReset ......................... |:TSkeletonBitReset| :TSkeletonBit .............................. |:TSkeletonBit| ======================================================================== autoload/tskeleton/abbreviations.vim~ *tskeleton#abbreviations#Reset()* tskeleton#abbreviations#Reset() *tskeleton#abbreviations#Initialize()* tskeleton#abbreviations#Initialize() *tskeleton#abbreviations#GetAbbreviations()* tskeleton#abbreviations#GetAbbreviations() *tskeleton#abbreviations#BufferBits()* tskeleton#abbreviations#BufferBits(dict, filetype) *tskeleton#abbreviations#Retrieve()* tskeleton#abbreviations#Retrieve(bit, indent, ft) ======================================================================== autoload/tskeleton/functions.vim~ *tskeleton#functions#Initialize()* tskeleton#functions#Initialize() *tskeleton#functions#FiletypeBits_vim()* tskeleton#functions#FiletypeBits_vim(dict, filetype) ======================================================================== autoload/tskeleton/mini.vim~ *tskeleton#mini#Initialize()* tskeleton#mini#Initialize() *tskeleton#mini#FiletypeBits()* tskeleton#mini#FiletypeBits(dict, type) ======================================================================== autoload/tskeleton/skeleton.vim~ *tskeleton#skeleton#Initialize()* tskeleton#skeleton#Initialize() *tskeleton#skeleton#FiletypeBits()* tskeleton#skeleton#FiletypeBits(dict, type) *tskeleton#skeleton#BufferBits()* tskeleton#skeleton#BufferBits(dict, type) *tskeleton#skeleton#Generator()* tskeleton#skeleton#Generator(filename) ======================================================================== autoload/tskeleton/tags.vim~ *tskeleton#tags#Initialize()* tskeleton#tags#Initialize() *tskeleton#tags#BufferBits()* tskeleton#tags#BufferBits(dict, filetype) *tskeleton#tags#Process_vim()* tskeleton#tags#Process_vim(dict, tag) *tskeleton#tags#Process_ruby()* tskeleton#tags#Process_ruby(dict, tag) *tskeleton#tags#Process_c()* tskeleton#tags#Process_c(dict, tag) *tskeleton#tags#Process_java()* tskeleton#tags#Process_java(dict, tag) ======================================================================== autoload/tskeleton/completefunc.vim~ *tskeleton#completefunc#Initialize()* tskeleton#completefunc#Initialize() *tskeleton#completefunc#FiletypeBits()* tskeleton#completefunc#FiletypeBits(dict, type) ======================================================================== autoload/tskeleton/omnicomplete.vim~ *tskeleton#omnicomplete#Initialize()* tskeleton#omnicomplete#Initialize() *tskeleton#omnicomplete#FiletypeBits()* tskeleton#omnicomplete#FiletypeBits(dict, type) ======================================================================== autoload/tskeleton.vim~ *g:tskelBitsIgnore* g:tskelBitsIgnore (default: tlib#rx#Suffixes()) *g:tskelNewBufferIsDirty* g:tskelNewBufferIsDirty (default: ! &hidden) If true, a new file that was filled with a template is marked as 'modified'. *g:tskeleton#enable_stakeholders* g:tskeleton#enable_stakeholders (default: exists('g:loaded_stakeholders') && g:loaded_stakeholders) *g:tskeleton#max_basename* g:tskeleton#max_basename (default: 255 - len(tlib#cache#Filename('tskeleton', '.'))) *g:tskeleton#conceal_cchar* g:tskeleton#conceal_cchar (default: has('conceal') ? {'utf-8': '⬚', '_': '#'} : {}) With |+conceal|, show this character for placeholders. If empty, don't use |:syn-conceal|. *TSkeleton_FILE_DIRNAME()* TSkeleton_FILE_DIRNAME() *TSkeleton_FILE_SUFFIX()* TSkeleton_FILE_SUFFIX() *TSkeleton_FILE_NAME_ROOT()* TSkeleton_FILE_NAME_ROOT() *TSkeleton_FILE_NAME()* TSkeleton_FILE_NAME() *TSkeleton_NOTE()* TSkeleton_NOTE() *TSkeleton_DATE()* TSkeleton_DATE() *TSkeleton_TIME()* TSkeleton_TIME() *TSkeleton_AUTHOR()* TSkeleton_AUTHOR() *TSkeleton_EMAIL()* TSkeleton_EMAIL() *TSkeleton_COMPANY()* TSkeleton_COMPANY() *TSkeleton_WEBSITE()* TSkeleton_WEBSITE() *TSkeleton_LICENSE()* TSkeleton_LICENSE() *TSkeletonCB_FILENAME()* TSkeletonCB_FILENAME() *TSkeletonCB_DIRNAME()* TSkeletonCB_DIRNAME() *TSkelNewScratchHook_viki()* TSkelNewScratchHook_viki() *tskeleton#WrapMarker()* tskeleton#WrapMarker(text, ...) *tskeleton#CursorMarker()* tskeleton#CursorMarker(...) *tskeleton#TagRx()* tskeleton#TagRx() *tskeleton#ExpandedAbbreviationTemplate()* tskeleton#ExpandedAbbreviationTemplate() *tskeleton#FillIn()* tskeleton#FillIn(bit, ?filetype='', ?meta={}) Expand special tags. *tskeleton#ExtractMeta()* tskeleton#ExtractMeta(text) *tskeleton#SetCursor()* tskeleton#SetCursor(from, to, ...) tskeleton#SetCursor(from, to, ?findAny=0, ?findOnly) *tskeleton#GetVar()* tskeleton#GetVar(name, ?default=g:name) Get the value of variable name from the destination buffer. *tskeleton#GetDestBuffer()* tskeleton#GetDestBuffer() *tskeleton#EvalInDestBuffer()* tskeleton#EvalInDestBuffer(code) Evaluate code in the destination buffer. *tskeleton#ExecInDestBuffer()* tskeleton#ExecInDestBuffer(code) Execute code in the destination buffer. *tskeleton#FindTemplate()* tskeleton#FindTemplate(template) *tskeleton#CollectTemplates()* tskeleton#CollectTemplates() *tskeleton#Setup()* tskeleton#Setup(template, ?unconditionally=0) Fill in a file template. *tskeleton#SelectTemplate()* tskeleton#SelectTemplate(ArgLead, CmdLine, CursorPos) Command line completion. *tskeleton#EditBitCompletion()* tskeleton#EditBitCompletion(ArgLead, CmdLine, CursorPos) Command line completion. *tskeleton#Edit()* tskeleton#Edit(?dir) Edit a file template. *tskeleton#BitsPath()* tskeleton#BitsPath(...) *tskeleton#EditBit()* tskeleton#EditBit(bit) Edit a skeleton bit. *tskeleton#NewFile()* tskeleton#NewFile(?template, ?dir, ?fileName) Create a new file template. *tskeleton#NewBufferMenuItem()* tskeleton#NewBufferMenuItem(menu, bit, ...) *tskeleton#FetchMiniBits()* tskeleton#FetchMiniBits(dict, path, pattern, buildmenu) *tskeleton#MaybePathshorten()* tskeleton#MaybePathshorten(filename) *tskeleton#FetchMiniBitsGenerator()* tskeleton#FetchMiniBitsGenerator(filename, buildmenu) *tskeleton#ReplacePrototypeArgs()* tskeleton#ReplacePrototypeArgs(text, rest) *tskeleton#PurifyBit()* tskeleton#PurifyBit(bit) *tskeleton#BitDef()* tskeleton#BitDef(name, ...) *tskeleton#BuildBufferMenu()* tskeleton#BuildBufferMenu(prepareBits) *tskeleton#PrepareBits()* tskeleton#PrepareBits(?filetype=&filetype, ?reset=0) Prepare the buffer for use with tskeleton. *tskeleton#ResetBits()* tskeleton#ResetBits(filetype) *tskeleton#SelectBit()* tskeleton#SelectBit(ArgLead, CmdLine, CursorPos) *tskeleton#IsScratchBuffer()* tskeleton#IsScratchBuffer() *tskeleton#Retrieve()* tskeleton#Retrieve(name) *tskeleton#Bit()* tskeleton#Bit(bit, ...) tskeleton#Bit(bit, ?mode='n') *tskeleton#ExpandBitUnderCursor()* tskeleton#ExpandBitUnderCursor(mode, ...) tskeleton#ExpandBitUnderCursor(mode, ?bit="", ?default={}) See also |g:tskelHyperComplete|. *tskeleton#WithSelection()* tskeleton#WithSelection(pre) *tskeleton#Complete_use_omnifunc()* tskeleton#Complete_use_omnifunc(bit, completions) *tskeleton#Complete_use_completefunc()* tskeleton#Complete_use_completefunc(bit, completions) *tskeleton#Complete_scan_words()* tskeleton#Complete_scan_words(bit, completions) *tskeleton#Complete_scan_tags()* tskeleton#Complete_scan_tags(bit, completions) *tskeleton#GetCompletions()* tskeleton#GetCompletions(func, bit) *tskeleton#Complete()* tskeleton#Complete(findstart, base, ?default={}) A function suitable for use as 'completefunc' or 'omnifunc'. You have to accept a match with in order to trigger skeleton expansion. See |popupmenu-keys|. *tskeleton#Placeholders()* tskeleton#Placeholders(line1, line2) *tskeleton#LateExpand()* tskeleton#LateExpand() *tskeleton#Repeat()* tskeleton#Repeat(n, string, ?sep="\n") *tskeleton#InsertTable()* tskeleton#InsertTable(rows, cols, rowbeg, rowend, celljoin) *tskeleton#HyperComplete_query()* tskeleton#HyperComplete_query(mode, default) *tskeleton#HyperComplete_pum()* tskeleton#HyperComplete_pum(mode, default) ======================================================================== plugin/tskeleton.vim~ *g:tskelGlobalBitsPath* g:tskelGlobalBitsPath (default: exists('g:tskelBitsDir') ? g:tskelBitsDir : '') A comma-separated list of directories (see |globpath()|) for globally available bits. If empty, use all "skeletons/bits/" subdirectories in 'runtimepath'. *g:tskelLocalBitsDirs* g:tskelLocalBitsDirs (default: ['.tskel', '_tskel']) A list of directories that contains buffer-local bits. *g:tskelMapLeader* g:tskelMapLeader (default: "#") Map leader for maps in normal mode. *g:tskelMapInsert* g:tskelMapInsert (default: '') Map leader for maps in insert mode. *g:tskelAddMapInsert* g:tskelAddMapInsert (default: 0) If true, insert |g:tskelMapInsert| after expanding a bit. This could be useful if you plan to map |g:tskelMapInsert| to something like . *g:tskelMenuCache* g:tskelMenuCache (default: '.tskelmenu') If non-empty, cache menu items. *g:tskelMapGoToNextTag* g:tskelMapGoToNextTag (default: '') If non-empty, create maps for "go to next place holder" feature. This map should work in normal, visual, selection, and insert mode. *g:tskelMapHyperComplete* g:tskelMapHyperComplete (default: '') Key to invoke hyper completion (see |g:tskelHyperComplete|). *g:tskelHyperComplete* g:tskelHyperComplete (default: {'use_completefunc': 1, 'scan_words': 1, 'scan_tags': 1}) A dictionary of items that should be offered on "hyper complete". *g:tskelHyperType* g:tskelHyperType (default: 'query') Either query or pum. If you set the variable to "pum", you have to accept completions with . This variable must be set in your |vimrc| file before loading the tskeleton plugin. *TSkeletonMapHyperComplete()* TSkeletonMapHyperComplete(key, ...) In the current buffer, map a:key so that - If the cursor is located at the beginning of the line or if the the cursor is over a whitespace character, indent the current line - otherwise expand the bit under the cursor or (if not suitable bit was found) use &omnifunc, &completefunc, tags, and (as fallback strategy) the words in the buffer as possible completions. *:TSkeletonSetup* :TSkeletonSetup Fill in a file template. *:TSkeletonEdit* :TSkeletonEdit Edit a file template. *:TSkeletonEditBit* :TSkeletonEditBit Edit a bit. *:TSkeletonNewFile* :TSkeletonNewFile Create a new file template. *:TSkeletonBitReset* :TSkeletonBitReset Reset a buffer's bits. Use this command if the list of bits known in a buffer is outdated. *:TSkeletonBit* :TSkeletonBit Insert a bit/snippet. vim:tw=78:fo=tcq2:isk=!-~,^*,^|,^":ts=8:ft=help:norl: skeletons/README_tskeleton.txt [[[1 17 Skeletons for the tSkeleton vim plugin: http://www.vim.org/scripts/script.php?script_id=1160 By default, this is the directory where tskeleton searches for skeletons. This directory may contain three types of files: 1. Manually configured skeletons, loaded from an autocommand. Example: This will load a file plain.txt from this directory when creating new files whose extension is "txt": autocmd BufNewFile *.txt TSkeletonSetup plain.txt 2. Automatically configured skeletons are kept in the "templates" subdirectory. tskeleton will automatically define suitable autocommands for you. The effect of the above example could also be achieved by saving the template as ".../templates/text/text #.vim" 3. "Bits" are skeletons for small portions of code. These are saved in the "bits" subdirectory. Example: The bits for, say, vimscript files are kept in ".../bits/vim/" plugin/tskeleton.vim [[[1 249 " tSkeleton.vim " @Author: Tom Link (micathom AT gmail com?subject=vim) " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 21-Sep-2004. " @Last Change: 2012-10-25. " @Revision: 3957 " " GetLatestVimScripts: 1160 1 tskeleton.vim " http://www.vim.org/scripts/script.php?script_id=1160 if &cp || exists("loaded_tskeleton") "{{{2 finish endif if !exists('loaded_tlib') || loaded_tlib < 110 runtime plugin/02tlib.vim if !exists('loaded_tlib') || loaded_tlib < 110 echoerr "tSkeleton requires tlib >= 1.10" finish endif endif let loaded_tskeleton = 501 if !exists("g:tskelDir") "{{{2 let g:tskelDir = get(split(globpath(&rtp, 'skeletons/'), '\n'), 0, '') endif if !isdirectory(g:tskelDir) "{{{2 echoerr 'tSkeleton: g:tskelDir ('. g:tskelDir .') isn''t readable. See :help tSkeleton-install for details!' finish endif let g:tskelDir = tlib#dir#CanonicName(g:tskelDir) if !exists('g:tskelGlobalBitsPath') "{{{2 " A comma-separated list of directories (see |globpath()|) for " globally available bits. If empty, use all "skeletons/bits/" " subdirectories in 'runtimepath'. let g:tskelGlobalBitsPath = exists('g:tskelBitsDir') ? g:tskelBitsDir : '' "{{{2 endif if !exists('g:tskelLocalBitsDirs') "{{{2 " A list of directories that contains buffer-local bits. let g:tskelLocalBitsDirs = ['.tskel', '_tskel'] "{{{2 endif let g:tskeleton_SetFiletype = 1 if !exists("g:tskelMapLeader") " Map leader for maps in normal mode. let g:tskelMapLeader = "#" "{{{2 endif if !exists("g:tskelMapInsert") " Map leader for maps in insert mode. let g:tskelMapInsert = '' "{{{2 endif if !exists("g:tskelAddMapInsert") " If true, insert |g:tskelMapInsert| after expanding a bit. This " could be useful if you plan to map |g:tskelMapInsert| to something " like . let g:tskelAddMapInsert = 0 "{{{2 endif if !exists("g:tskelMenuCache") " If non-empty, cache menu items. let g:tskelMenuCache = '.tskelmenu' "{{{2 endif if !exists("g:tskelMenuPrefix") " :nodoc: " Prefix for menu items. let g:tskelMenuPrefix = 'TSke&l' "{{{2 endif if !exists("g:tskelMapGoToNextTag") " If non-empty, create maps for "go to next place holder" feature. " This map should work in normal, visual, selection, and insert " mode. let g:tskelMapGoToNextTag = '' "{{{2 endif if !exists("g:tskelMapHyperComplete") "{{{2 if empty(maparg('') . maparg('', 'i')) " Key to invoke hyper completion (see |g:tskelHyperComplete|). let g:tskelMapHyperComplete = '' "{{{2 else let g:tskelMapHyperComplete = '' endif endif if !exists("g:tskelHyperComplete") "{{{2 " A dictionary of items that should be offered on "hyper complete". let g:tskelHyperComplete = {'use_completefunc': 1, 'scan_words': 1, 'scan_tags': 1} "{{{2 endif if !exists('g:tskelHyperType') " Either query or pum. " If you set the variable to "pum", you have to accept completions " with . " This variable must be set in your |vimrc| file before loading the " tskeleton plugin. let g:tskelHyperType = 'query' "{{{2 endif " :nodoc: " Create maps for the "go to next placeholder" functionality (see g:tskelMapGoToNextTag|). function! TSkeletonMapGoToNextTag() "{{{3 let map = type(g:tskelMapGoToNextTag) == 0 ? '' : g:tskelMapGoToNextTag exec 'nnoremap ' map ':call tskeleton#GoToNextTag()' exec 'vnoremap ' map ':call tskeleton#GoToNextTag()' exec 'inoremap ' map ':call tskeleton#GoToNextTag()' endf if !empty(g:tskelMapGoToNextTag) call TSkeletonMapGoToNextTag() endif " In the current buffer, map a:key so that " - If the cursor is located at the beginning of the line or if the " the cursor is over a whitespace character, indent the current " line " - otherwise expand the bit under the cursor or (if not suitable bit " was found) use &omnifunc, &completefunc, tags, and (as fallback " strategy) the words in the buffer as possible completions. function! TSkeletonMapHyperComplete(key, ...) "{{{3 let default = a:0 >= 1 ? a:1 : '==' if g:tskelHyperType == 'pum' exec 'inoremap '. a:key .' =tskeleton#HyperComplete_'. g:tskelHyperType .'("i", '. string(default) .')' elseif g:tskelHyperType == 'query' exec 'inoremap '. a:key .' :call tskeleton#HyperComplete_'. g:tskelHyperType .'("i", '. string(default) .')' else echoerr "tSkeleton: Unknown type for g:tskelHyperType: "+ g:tskelHyperType endif exec 'noremap '. a:key .' :call tskeleton#HyperComplete_query("n", '. string(default) .')' endf if !empty(g:tskelMapHyperComplete) call TSkeletonMapHyperComplete(g:tskelMapHyperComplete) endif " Fill in a file template. command! -bang -nargs=* -complete=custom,tskeleton#SelectTemplate TSkeletonSetup \ call tskeleton#Setup(, !empty("")) " Edit a file template. command! -nargs=? -complete=custom,tskeleton#SelectTemplate TSkeletonEdit \ call tskeleton#Edit() " Edit a bit. command! -nargs=? -complete=customlist,tskeleton#EditBitCompletion TSkeletonEditBit \ call tskeleton#EditBit() " Create a new file template. command! -nargs=* -complete=custom,tskeleton#SelectTemplate TSkeletonNewFile \ call tskeleton#NewFile() " Reset a buffer's bits. Use this command if the list of bits known in a " buffer is outdated. command! -bar -nargs=? TSkeletonBitReset call tskeleton#ResetBits() " Insert a bit/snippet. command! -nargs=? -complete=custom,tskeleton#SelectBit TSkeletonBit \ call tskeleton#Bit() " :nodoc: " Remove lines containing placeholders from a bibtex entry. command! TSkeletonCleanUpBibEntry call tskeleton#CleanUpBibEntry() if !empty(g:tskelMapLeader) " noremap tt ""diw:TSkeletonBit " exec "noremap ". g:tskelMapLeader ."t :TSkeletonBit " exec "nnoremap ". g:tskelMapLeader ."# :call tskeleton#ExpandBitUnderCursor('n')" if g:tskelAddMapInsert exec "inoremap ". g:tskelMapInsert ." :call tskeleton#ExpandBitUnderCursor('i','', {'string':". string(g:tskelMapInsert) ."})" else exec "inoremap ". g:tskelMapInsert ." :call tskeleton#ExpandBitUnderCursor('i')" endif exec "vnoremap ". g:tskelMapLeader ."# d:call tskeleton#WithSelection('')" exec "vnoremap ". g:tskelMapLeader ." d:call tskeleton#WithSelection(' ')" exec "nnoremap ". g:tskelMapLeader ."x :call tskeleton#LateExpand()" exec "vnoremap ". g:tskelMapLeader ."x `<:call tskeleton#LateExpand()" endif augroup tSkeleton autocmd! if !exists("g:tskelDontSetup") "{{{2 function! s:DefineAutoCmd(template) "{{{3 " TLogVAR a:template " let sfx = fnamemodify(a:template, ':e') let tpl = fnamemodify(a:template, ':t') " TLogVAR tpl let filetype = tlib#url#Decode(matchstr(tpl, '^\S\+')) let pattern = matchstr(tpl, '^\S\+ \+\zs.*$') if !empty(filetype) && !empty(pattern) " TLogVAR pattern let pattern = substitute(pattern, '#', '*', 'g') " TLogVAR pattern let pattern = tlib#url#Decode(pattern) " TLogVAR pattern exec 'autocmd BufNewFile' escape(pattern, ' ') 'set ft='. escape(filetype, ' ') '| TSkeletonSetup' a:template endif endf call map(split(glob(tlib#file#Join([g:tskelDir, 'templates', '**'], 1)), '\n'), 'isdirectory(v:val) || s:DefineAutoCmd(v:val)') delfunction s:DefineAutoCmd for [s:pat, s:tpl] in [ \ ["*.bat", "batch.bat"], \ ["*.tex", "latex.tex"], \ ["tc-*.rb", "tc-ruby.rb"], \ ["*.rb", "ruby.rb"], \ ["*.rbx", "ruby.rb"], \ ["*.sh", "shell.sh"], \ ["*.txt", "text.txt"], \ ["*.vim", "plugin.vim"], \ ["*.inc.php", "php.inc.php"], \ ["*.class.php", "php.class.php"], \ ["*.php", "php.php"], \ ["*.tpl", "smarty.tpl"], \ ["*.html", "html.html"] \ ] if filereadable(tlib#file#Join([g:tskelDir, s:tpl])) exec 'autocmd BufNewFile' s:pat 'TSkeletonSetup' s:tpl endif endfor endif exec 'autocmd BufNewFile,BufRead '. escape(g:tskelDir, ' ') .'* if g:tskeleton_SetFiletype | set ft=tskeleton | endif' autocmd FileType * call tskeleton#PrepareBits(&filetype) autocmd SessionLoadPost,BufEnter * if (g:tskelMenuPrefix != '' && g:tskelMenuCache != '' && !tskeleton#IsScratchBuffer()) | call tskeleton#BuildBufferMenu(1) | endif autocmd FileType bib if !hasmapto(":TSkeletonCleanUpBibEntry") | exec "noremap ". g:tskelMapLeader ."c :TSkeletonCleanUpBibEntry" | endif augroup END " call tskeleton#PrepareBits('general') autoload/tskeleton.vim [[[1 3220 " tskeleton.vim " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 2007-09-03. " @Last Change: 2013-01-16. " @Revision: 2210 " call tlog#Log('Load: '. expand('')) " vimtlib-sfile if !exists('g:tskelMapsDir') "{{{2 let g:tskelMapsDir = g:tskelDir .'map/' endif let g:tskelMapsDir = tlib#dir#CanonicName(g:tskelDir) if !exists('g:tskelBitsIgnore') let g:tskelBitsIgnore = tlib#rx#Suffixes() "{{{2 endif if !exists('g:tskelNewBufferIsDirty') " If true, a new file that was filled with a template is marked as " 'modified'. let g:tskelNewBufferIsDirty = ! &hidden "{{{2 endif if !exists("g:tskelTypes") "{{{2 " 'skeleton' (standard tSkeleton functionality) " 'abbreviations' (VIM abbreviations) " 'functions' (VIM script functions extracted from :function) " 'mini' ("mini" bits, one-liners etc.) " 'tags' (tags-based code templates, requires ctags, I presume) let g:tskelTypes = ['skeleton', 'mini', 'snippets'] endif if !exists('g:tskelLicense') "{{{2 let g:tskelLicense = 'GPL (see http://www.gnu.org/licenses/gpl.txt)' endif if !exists("g:tskelMarkerHiGroup") | let g:tskelMarkerHiGroup = 'Special' | endif "{{{2 if !exists("g:tskelMarkerLeft") | let g:tskelMarkerLeft = "<+" | endif "{{{2 if !exists("g:tskelMarkerRight") | let g:tskelMarkerRight = "+>" | endif "{{{2 if !exists('g:tskelMarkerExtra') | let g:tskelMarkerExtra = '???\|+++\|!!!\|###' | endif if !exists("g:tskelMarkerCursor_mark") | let g:tskelMarkerCursor_mark = "CURSOR" | endif "{{{2 if !exists("g:tskelMarkerCursor_volatile") | let g:tskelMarkerCursor_volatile = "/CURSOR" | endif "{{{2 if !exists("g:tskelMarkerCursor_rx") | let g:tskelMarkerCursor_rx = 'CURSOR\(/\(.\{-}\)\)\?' | endif "{{{2 if !exists("g:tskelDateFormat") | let g:tskelDateFormat = '%Y-%m-%d' | endif "{{{2 if !exists("g:tskelUserName") | let g:tskelUserName = g:tskelMarkerLeft."NAME".g:tskelMarkerRight | endif "{{{2 if !exists("g:tskelUserAddr") | let g:tskelUserAddr = g:tskelMarkerLeft."ADDRESS".g:tskelMarkerRight | endif "{{{2 if !exists("g:tskelUserEmail") | let g:tskelUserEmail = g:tskelMarkerLeft."EMAIL".g:tskelMarkerRight | endif "{{{2 if !exists("g:tskelUserWWW") | let g:tskelUserWWW = g:tskelMarkerLeft."WWW".g:tskelMarkerRight | endif "{{{2 if !exists("g:tskelUserCompany") | let g:tskelUserCompany = g:tskelMarkerLeft."COMPANY".g:tskelMarkerRight | endif "{{{2 if !exists("g:tskelRevisionMarkerRx") | let g:tskelRevisionMarkerRx = '@Revision:\s\+' | endif "{{{2 if !exists("g:tskelRevisionVerRx") | let g:tskelRevisionVerRx = '\(RC\d*\|pre\d*\|p\d\+\|-\?\d\+\)\.' | endif "{{{2 if !exists("g:tskelRevisionGrpIdx") | let g:tskelRevisionGrpIdx = 3 | endif "{{{2 if !exists("g:tskelMaxRecDepth") | let g:tskelMaxRecDepth = 10 | endif "{{{2 if !exists("g:tskelChangeDir") | let g:tskelChangeDir = 1 | endif "{{{2 if !exists("g:tskelMenuPriority") | let g:tskelMenuPriority = 90 | endif "{{{2 if !exists("g:tskelMenuMiniPrefix") | let g:tskelMenuMiniPrefix = 'etc.' | endif "{{{2 if !exists("g:tskelAutoAbbrevs") | let g:tskelAutoAbbrevs = 0 | endif "{{{2 if !exists("g:tskelAbbrevPostfix") | let g:tskelAbbrevPostfix = '#' | endif "{{{2 " By default bit names are case sensitive. " 1 ... case sensitive " -1 ... default (see 'smartcase') " 0 ... case insensitive if !exists("g:tskelCaseSensitive") | let g:tskelCaseSensitive = 1 | endif "{{{2 if !exists("g:tskelCaseSensitive_html") | let g:tskelCaseSensitive_html = 0 | endif "{{{2 if !exists("g:tskelCaseSensitive_bbcode") | let g:tskelCaseSensitive_bbcode = 0 | endif "{{{2 if !exists("g:tskelUseBufferCache") | let g:tskelUseBufferCache = 0 | endif "{{{2 if !exists("g:tskelMenuPrefix_tags") | let g:tskelMenuPrefix_tags = 'Tags.' | endif "{{{2 if !exists("g:tskelQueryType") "{{{2 let g:tskelQueryType = 'query' endif if !exists("g:tskelPopupNumbered") | let g:tskelPopupNumbered = 1 | endif "{{{2 " set this to v for using visual mode when calling TSkeletonGoToNextTag() if !exists("g:tskelSelectTagMode") | let g:tskelSelectTagMode = 's' | endif "{{{2 " \Q will be replaced with a quantifier if !exists("g:tskelKeyword_bbcode") | let g:tskelKeyword_bbcode = '\(\[\*\|[\[\\][*[:alnum:]]\Q\)' | endif "{{{2 if !exists("g:tskelKeyword_bib") | let g:tskelKeyword_bib = '[@[:alnum:]]\Q' | endif "{{{2 if !exists("g:tskelKeyword_java") | let g:tskelKeyword_java = '[[:alnum:]_@<&]\Q' | endif "{{{2 if !exists("g:tskelKeyword_php") | let g:tskelKeyword_java = '[[:alnum:]_@<&$]\Q' | endif "{{{2 if !exists("g:tskelKeyword_html") | let g:tskelKeyword_html = '<\?[^>[:blank:]]\Q' | endif "{{{2 if !exists("g:tskelKeyword_sh") | let g:tskelKeyword_sh = '[\[@${([:alpha:]]\Q' | endif "{{{2 if !exists("g:tskelKeyword_tex") | let g:tskelKeyword_tex = '\\\?\k\Q' | endif "{{{2 if !exists("g:tskelKeyword_viki") | let g:tskelKeyword_viki = '\(#\|{\|\\\)\?[^#{[:blank:][:punct:]-]\Q' | endif "{{{2 " if !exists("g:tskelKeyword_viki") | let g:tskelKeyword_viki = '\(#\|{\)\?[^#{[:blank:]]\{-}' | endif "{{{2 if !exists("g:tskelBitGroup_html") "{{{2 let g:tskelBitGroup_html = ['html', 'html_common'] endif if !exists("g:tskelBitGroup_bbcode") "{{{2 let g:tskelBitGroup_bbcode = ['bbcode', 'tex'] endif if !exists("g:tskelBitGroup_php") "{{{2 let g:tskelBitGroup_php = ['php', 'html', 'html_common'] endif if !exists("g:tskelBitGroup_java") "{{{2 let g:tskelBitGroup_java = ['java', 'html_common'] endif if !exists("g:tskelBitGroup_viki") "{{{2 let g:tskelBitGroup_viki = ['tex', 'viki'] endif if !exists("g:tskelBitGroup_xslt") "{{{2 let g:tskelBitGroup_xslt = ['xslt', 'xml'] endif if !exists("g:tskel_completions") "{{{2 let g:tskel_completions = { \ 'use_omnifunc': 'tskeleton#Complete_use_omnifunc', \ 'use_completefunc': 'tskeleton#Complete_use_completefunc', \ 'scan_words': 'tskeleton#Complete_scan_words', \ 'scan_tags': 'tskeleton#Complete_scan_tags', \ } endif if !exists('g:tskeleton#enable_stakeholders') let g:tskeleton#enable_stakeholders = exists('g:loaded_stakeholders') && g:loaded_stakeholders "{{{2 endif if !exists('g:tskeleton#max_basename') let g:tskeleton#max_basename = 255 - len(tlib#cache#Filename('tskeleton', '.')) "{{{2 endif if !exists('g:tskeleton#conceal_cchar') " With |+conceal|, show this character for placeholders. " If empty, don't use |:syn-conceal|. let g:tskeleton#conceal_cchar = has('conceal') ? {'utf-8': '⬚', '_': '#'} : {} "{{{2 endif if !exists('*TSkeleton_FILE_DIRNAME') "{{{2 function! TSkeleton_FILE_DIRNAME() "{{{3 return tskeleton#EvalInDestBuffer('expand("%:p:h")') endf endif if !exists('*TSkeleton_FILE_SUFFIX') "{{{2 function! TSkeleton_FILE_SUFFIX() "{{{3 return tskeleton#EvalInDestBuffer('expand("%:e")') endf endif if !exists('*TSkeleton_FILE_NAME_ROOT') "{{{2 function! TSkeleton_FILE_NAME_ROOT() "{{{3 return tskeleton#EvalInDestBuffer('expand("%:t:r")') endf endif if !exists('*TSkeleton_FILE_NAME') "{{{2 function! TSkeleton_FILE_NAME() "{{{3 return tskeleton#EvalInDestBuffer('expand("%:t")') endf endif if !exists('*TSkeleton_NOTE') "{{{2 function! TSkeleton_NOTE() "{{{3 let title = tskeleton#GetVar("tskelTitle", 'input("Please describe the project: ")', '') let note = title != "" ? " -- ".title : "" return note endf endif if !exists('*TSkeleton_DATE') "{{{2 function! TSkeleton_DATE() "{{{3 return strftime(tskeleton#GetVar('tskelDateFormat')) endf endif if !exists('*TSkeleton_TIME') "{{{2 function! TSkeleton_TIME() "{{{3 return strftime('%X') endf endif if !exists('*TSkeleton_AUTHOR') "{{{2 function! TSkeleton_AUTHOR() "{{{3 return tskeleton#GetVar('tskelUserName') endf endif if !exists('*TSkeleton_EMAIL') "{{{2 function! TSkeleton_EMAIL() "{{{3 let email = tskeleton#GetVar('tskelUserEmail') " return substitute(email, "@"," AT ", "g") return email endf endif if !exists('*TSkeleton_COMPANY') "{{{2 function! TSkeleton_COMPANY() "{{{3 let company = tskeleton#GetVar('tskelUserCompany') return company endf endif if !exists('*TSkeleton_WEBSITE') "{{{2 function! TSkeleton_WEBSITE() "{{{3 return tskeleton#GetVar('tskelUserWWW') endf endif if !exists('*TSkeleton_LICENSE') "{{{2 function! TSkeleton_LICENSE() "{{{3 return tskeleton#GetVar('tskelLicense') endf endif function! TSkeletonCB_FILENAME() "{{{3 return input('File name: ', '', 'file') endf function! TSkeletonCB_DIRNAME() "{{{3 return input('Directory name: ', '', 'dir') endf function! TSkelNewScratchHook_viki() let b:vikiMarkInexistent = 0 endf " let s:tskelScratchVars = ['tskelMarkerCursor', 'tskelMarkerLeft', 'tskelMarkerRight'] let s:tskelScratchVars = [] let s:tskelScratchIdx = 0 let s:tskelScratchMax = 0 let s:tskelDestBufNr = -1 let s:tskelBuiltMenu = 0 let s:tskelLine = 0 let s:tskelCol = 0 let s:tskelProcessing = 0 let s:tskelConditions = [] let s:tskelLoops = [] let s:initialized = [] " :nodoc: function! tskeleton#Initialize(...) "{{{3 TVarArg ['types', g:tskelTypes] " TLogVAR types for type in types if index(s:initialized, type) == -1 " TLogVAR type call {'tskeleton#'. type .'#Initialize'}() call add(s:initialized, type) endif endfor endf function! tskeleton#WrapMarker(text, ...) "{{{3 TVarArg 'type' let left = tlib#var#Get('tskelMarkerLeft', 'bg') let right = tlib#var#Get('tskelMarkerRight', 'bg') if type == 'rx' return tlib#rx#Escape(left) . a:text . tlib#rx#Escape(right) else return left . a:text . right endif endf function! tskeleton#CursorMarker(...) "{{{3 TVarArg ['type', 'mark'] let cursor = tlib#var#Get('tskelMarkerCursor_'.type, 'bg') return tskeleton#WrapMarker(cursor, type) endf function! tskeleton#TagRx() "{{{3 " let text = '\('. tskeleton#WrapMarker('.\{-}') .'\|.\)\{-}' let text = '.\{-}' return tskeleton#WrapMarker('\(' \ .'\$[a-zA-Z0-9_]\+\|[\&].\{-}\|[gbws]:.\{-}\|\%(bit\|tskel\):.\{-}' \ .'\|call:\%(''[^'']*''\|\"\%(\\\"\|[^\"]\)*\"\|[bgs]:\|.\)\{-1,}' \ .'\|[a-zA-Z0-9_ -]*\%(/'. text .'\)\?' \ .'\|\%(if\|elseif\|for\|input\|select\|let\|\include\|execute\)(.\{-})' \ .'\|?.\{-}?' \ .'\)\(: *'. text .' *\)\?' \ , 'rx') endf function! tskeleton#ExpandedAbbreviationTemplate() "{{{3 return ':call tskeleton#ExpandBitUnderCursor("n", %s)' endf " :def: function! tskeleton#FillIn(bit, ?filetype='', ?meta={}) " Expand special tags. function! tskeleton#FillIn(bit, ...) "{{{3 " TLogVAR a:bit let filetype = a:0 >= 1 && a:1 != '' ? a:1 : s:Filetype() " TLogVAR filetype call tskeleton#PrepareBits(filetype) let b:tskelTemporaryVariables = [] if a:0 >= 2 let meta = a:2 else let bitdef = tskeleton#BitDef(a:bit) " TLogVAR bitdef let meta = get(bitdef, 'meta', {}) endif " TLogVAR meta if !empty(meta) let msg = get(meta, 'msg', '') if !empty(msg) echom msg endif call s:EvalBitProcess(get(meta, 'before'), 1) call s:EvalBitProcess(get(meta, 'here_before'), 0) endif let foldenable = &l:foldenable let selection = &l:selection setlocal nofoldenable setlocal selection=exclusive try silent norm! gg0 " call tlog#Debug(tskeleton#TagRx()) " call tlog#Debug(s:tskelScratchIdx) let s:tskelLine_{s:tskelScratchIdx} = search(tskeleton#TagRx(), 'cW') while s:tskelLine_{s:tskelScratchIdx} > 0 " TLogDBG string(getpos('.')) " TLogDBG string(getline(1, '$')) let s:tskelPos0 = getpos('.') " call tlog#Debug(s:tskelLine_{s:tskelScratchIdx}) " let col = virtcol(".") let col = col('.') " TLogVAR col let line = strpart(getline('.'), col - 1) let mlst = matchlist(line, tskeleton#TagRx()) " TLogVAR mlst " TLogVAR getline('.'), col, line let text0 = matchstr(line, tskeleton#TagRx()) " TLogVAR text0 " let text = substitute(line, tskeleton#TagRx() .'.*$', '\1', '') let text = mlst[1] " TLogVAR text let s:tskelPostExpand = '' let [postprocess, repl] = s:HandleTag(text, b:tskelFiletype) " postprocess " -1 .. " 1 .. " 2 .. No substitutions were made " TLogVAR postprocess, repl if postprocess == -1 call s:ReplaceLine(col, repl) exec 'norm! '. len(repl) .'l' elseif postprocess >= 1 if repl != '' && line =~ '\V\^'. escape(repl, '\') norm! l else let mod = mlst[2] " TLogVAR mod let repl = s:Modify(repl, mod) " TLogVAR repl call s:ReplaceLine(col, repl) endif endif if s:tskelPostExpand != '' " call tlog#Debug(s:tskelPostExpand) exec s:tskelPostExpand let s:tskelPostExpand = '' end if s:tskelLine_{s:tskelScratchIdx} > 0 " call tlog#Debug('search(tskeleton#TagRx(), "W")') let s:tskelLine_{s:tskelScratchIdx} = search(tskeleton#TagRx(), 'cW') endif endwh " TLogDBG "endwhile" finally let &l:foldenable = foldenable let &l:selection = selection endtry if !empty(meta) call s:EvalBitProcess(get(meta, 'here_after'), 0) call s:EvalBitProcess(get(meta, 'after'), 1) endif " TLogVAR b:tskelTemporaryVariables for def in b:tskelTemporaryVariables let var = get(def, 0) " TLogVAR def, var if len(def) == 1 exec 'unlet! '. var else call s:SetVar(var, get(def, 1)) endif endfor if empty(a:bit) " TLogDBG "tskeleton#SetCursor" call tskeleton#SetCursor('%', '') endif " TLogDBG "done" endf function! s:ReplaceLine(col, repl) "{{{3 " TLogVAR a:col, a:repl let tagrx = escape(tskeleton#TagRx(), '/') " TLogVAR tagrx exec 'silent! s/\%'. a:col .'c'. tagrx .'//' call tlib#buffer#InsertText0(a:repl, { \ 'pos': 's', \ 'col': a:col, \ 'indent': 1, \ }) endf function! tskeleton#ExtractMeta(text) " TLogVAR a:text let meta = {'type': 'tskeleton'} let [text, meta.msg] = s:GetBitProcess(a:text, 'msg', 2) let [text, meta.before] = s:GetBitProcess(text, 'before', 1) " TLogVAR meta.before let [text, meta.after] = s:GetBitProcess(text, 'after', 1) " TLogVAR meta.after let [text, meta.here_before] = s:GetBitProcess(text, 'here_before', 0) " TLogVAR meta.here_before let [text, meta.here_after] = s:GetBitProcess(text, 'here_after', 0) " TLogVAR meta.here_after let [text, meta.abbrev] = s:GetBitProcess(text, 'abbrev', 0) " TLogVAR meta.abbrev let [text, meta.menu] = s:GetBitProcess(text, 'menu', 0) let [text, meta.condition] = s:GetBitProcess(text, 'condition', 0) if empty(meta.condition) let meta.condition = 1 endif " TLogVAR meta.condition " TLogVAR text return [text, meta] endf function! s:HandleTag(match, filetype) "{{{3 " TLogVAR a:match, a:filetype let s:tskel_use_placeholders = 1 " TLogDBG a:match =~# '^[bgsw]:' if a:match =~# '^[bgsw]:' return [1, s:Var(a:match)] elseif a:match =~# '^\$[a-zA-Z_]\+$' return [1, exists(a:match) ? eval(a:match) : ''] elseif a:match =~# '^nl$' return [1, "\n"] elseif a:match =~# '^nop$' return [1, ""] elseif a:match =~# '^joinline$' call s:JoinLine() return [1, ""] elseif a:match =~# '^input(' return s:Input(strpart(a:match, 5)) elseif a:match =~# '^select(' return s:Select(strpart(a:match, 6)) elseif a:match =~# '^if(' return [0, s:SwitchIf(strpart(a:match, 2))] elseif a:match =~# '^elseif(' return [0, s:SwitchElseif(strpart(a:match, 6))] elseif a:match =~# '^else$' return [0, s:SwitchElse()] elseif a:match =~# '^endif$' return [0, s:SwitchEndif()] elseif a:match =~# '^for(' return [0, s:LoopFor(strpart(a:match, 3))] elseif a:match =~# '^let(' return [0, s:LetVar(strpart(a:match, 3))] elseif a:match =~# '^include(' return [1, s:Expand(matchstr(a:match, '(\zs.\{-}\ze)$'), a:filetype)] elseif a:match =~# '^execute(' return [0, s:Execute(matchstr(a:match, '(\zs.\{-}\ze)$'))] elseif a:match =~# '^\([A-Z ]\+\)' return s:Dispatch(a:match) elseif a:match[0] == '&' return [1, s:Exec(a:match)] elseif a:match[0] == '\' return [-1, tskeleton#WrapMarker(strpart(a:match, 1))] elseif a:match[0] == '?' return [1, s:Query(strpart(a:match, 1, strlen(a:match) - 2))] elseif strpart(a:match, 0, 4) =~# '\(bit\|tskel\):' " return [1, s:Expand(strpart(a:match, 4), a:filetype)] return [1, s:Expand(matchstr(a:match, ':\zs.*'), a:filetype)] " elseif strpart(a:match, 0, 6) =~# 'tskel:' " return [1, s:Expand(strpart(a:match, 6), a:filetype)] " elseif strpart(a:match, 0, 6) =~# 'include:' " return [1, s:Expand(strpart(a:match, 8), a:filetype)] elseif strpart(a:match, 0, 5) =~# 'call:' return [1, s:Call(strpart(a:match, 5))] else return [2, tskeleton#WrapMarker(a:match)] end endf " tskeleton#SetCursor(from, to, ?findAny=0, ?findOnly) function! tskeleton#SetCursor(from, to, ...) "{{{3 " TLogVAR a:from, a:to let findAny = a:0 >= 1 ? a:1 : 0 let findOnly = a:0 >= 2 ? a:2 : (s:tskelScratchIdx > 1) " TLogVAR findAny, findOnly let c = col('.') let l = line('.') if a:to == '' if a:from == '%' silent norm! gg0 else exec a:from endif else exec a:to norm! 0 end let cursor_rx = tskeleton#CursorMarker('rx') let l = search(cursor_rx, 'Wc') " TLogVAR l, findOnly, findAny if l == 0 && findAny let cursor_rx = tskeleton#TagRx() let l = -search(cursor_rx, 'Wc') endif if l == 0 call cursor(l, c) return 0 elseif !findOnly if g:tskeleton#enable_stakeholders call stakeholders#CursorMoved('n') endif let c = col('.') " TLogDBG getline('.') if !findAny && l > 0 let smarttaglen = len(get(matchlist(getline('.')[c - 1 :], cursor_rx), 2, '')) silent exec 's/'. escape(cursor_rx, '/') .'/\2/e' else let smarttaglen = len(matchstr(getline('.')[c - 1 :], cursor_rx)) endif call cursor(0, c) if smarttaglen > 0 exec 'norm! v'. (smarttaglen - s:InclusiveSelection()) .'l' call s:SelectTagMode() endif " TLogVAR findAny, cursor_rx, l, smarttaglen " TLogDBG getline('.') endif " TLogVAR l return l endf function! s:JoinLine() let s:tskelPostExpand = 'silent norm! d/\S ' endf function! s:Input(text) "{{{3 " TLogVAR a:text let args = eval('['. matchstr(a:text, '^(\zs.*\ze)$') .']') " TLogVAR args let var = get(args, 0, '') let vdef = s:VarName(var) if var[-1:-1] == '!' call s:DelTo('input(.\{-}', 1) let s:tskelPostExpand = "call setpos('.', ". string(s:tskelPos0) .")" " TLogDBG string(getline(1, '$')) let reval = 0 let var = var[0:-2] else let reval = 1 endif if s:SkipVar(vdef) let val = s:GetVar(vdef.name) else let val = call('input', args[1:-1]) call s:TemporaryLet(var, val) endif return [reval, val] endf function! s:Select(text) "{{{3 let args = eval('['. matchstr(a:text, '^(\zs.*\ze)$') .']') " TLogVAR args let var = get(args, 0, '') let type = get(args, 2, 's') let join = get(args, 3, ', ') let vdef = s:VarName(var) if var[-1:-1] == '!' call s:DelTo('select(.\{-}', 1) let s:tskelPostExpand = "call setpos('.', ". string(s:tskelPos0) .")" " TLogDBG string(getline(1, '$')) let reval = 0 let var = var[0:-2] else let reval = 1 endif if s:SkipVar(vdef) let val = s:GetVar(vdef.name) else let val0 = tlib#input#List(type, 'Select item:', get(args, 1, ['Malformed arguments'])) if type =~# 'm' let val = join(val0, join) else let val = val0 endif call s:TemporaryLet(var, val) endif return [reval, val] endf function! s:TemporaryLet(var, val) "{{{3 if !empty(a:var) " TLogVAR a:var let var = s:VarName(a:var) if s:SkipVar(var) return endif if var.mod !~ '&' if exists(var.name) call insert(b:tskelTemporaryVariables, [var.name, s:GetVar(var.name)]) else call insert(b:tskelTemporaryVariables, [var.name]) endif endif call s:SetVar(var.name, a:val) endif endf function! s:VarName(var) "{{{3 let [match, var, mod; rest] = matchlist(a:var, '^\(.\{-}\)\([!?&]*\)$') return {'match': match, 'name': var, 'mod': mod} endf function! s:SkipVar(var) "{{{3 return a:var.mod =~ '?' && exists(a:var.name) endf function! s:GetVar(var) "{{{3 return eval(a:var) endf function! s:SetVar(var, val) "{{{3 exec 'let '. a:var .'= a:val' return endf function! s:SwitchIf(text) " TLogDBG 'if' " TLogVAR a:text if empty(s:tskelConditions) || s:LastCondition() if eval(a:text) " TLogDBG 'true' call add(s:tskelConditions, 1) call s:DelTo('if(.\{-}', 1) else " TLogDBG 'false' call add(s:tskelConditions, 0) call s:DelTo('\(if(.\{-}\|elseif(.\{-}\|else\|endif\)', 0) endif else call add(s:tskelConditions, 0) call s:DelTo('\(if(.\{-}\|endif\)', 0) endif return '' endf function! s:SwitchElseif(text) " TLogDBG 'elseif' " TLogVAR a:text " TLogDBG string(getline(1, '$')) if s:LastCondition() " TLogDBG 'elseif obsolete' call s:DelTo('endif', 1) elseif eval(a:text) " TLogDBG 'elseif true' call add(s:tskelConditions, 1) call s:DelTo('elseif(.\{-}', 1) else " TLogDBG 'elseif false' call s:DelTo('\(elseif(.\{-}\|else\|endif\)', 0) endif return '' endf function! s:SwitchElse() " TLogDBG 'else' if s:LastCondition() " TLogDBG 'else false' call s:DelTo('endif', 1) else " TLogDBG 'else true' let s:tskelConditions[-1] = 1 call s:DelTo('else', 1) endif return '' endf function! s:SwitchEndif() " TLogDBG 'endif' if empty(s:tskelConditions) echoerr 'tSkeleton: "endif" without "if"' endif call remove(s:tskelConditions, -1) call s:DelTo('endif', 1) return '' endf function! s:LastCondition() "{{{3 if !empty(s:tskelConditions) return s:tskelConditions[-1] endif echoerr 'tSkeleton: "else/elseif/endif" without "if"' return 0 endf function! s:LetVar(text) "{{{3 let var = matchstr(a:text, '^(\s*\zs[^=]\{-}\ze\s*=') let val = matchstr(a:text, '=\s*\zs.\{-}\ze)$') " TLogVAR var, val call s:TemporaryLet(var, eval(val)) call s:DelTo('let.\{-}', 1) return '' endf function! s:LoopFor(text) "{{{3 " TLogDBG 'for' " TLogVAR a:text let var = matchstr(a:text, '^(\zs\S\+') let endrx = 'endfor\(('.var.')\)\?' " TLogVAR var, endrx let lists = matchstr(a:text, '\sin\s\+\zs.\{-}\ze)$') " TLogVAR var, lists let t = @t try call s:DoVisual('for(.\{-}', 1, '"ty') let head = @t " TLogVAR head call s:DelTo('for(.\{-}', 1) call s:DoVisual(endrx, 0, '"ty') let body = @t " TLogVAR body call s:DelTo(endrx, 1) finally let @t = t endtry let acc = [] for e in eval(lists) call add(acc, tskeleton#WrapMarker(printf('let(%s=%s)', var, string(e)))) call add(acc, body) endfor " TLogVAR acc call s:InsertBitText('gil', join(acc, '')) let s:tskelPostExpand = "call setpos('.', ". string(s:tskelPos0) .")" return '' endf function! s:DoVisual(pattern, inclusive, cmd) "{{{3 let rx = tskeleton#WrapMarker(a:pattern, 'rx') " TLogVAR rx exec 'silent! norm! v/'. escape(rx, '/') .(a:inclusive ? '/e1' : '') ."\". a:cmd endf function! s:DelTo(pattern, inclusive) call s:DoVisual(a:pattern, a:inclusive, 'd') endf function! s:Var(arg) "{{{3 " TLogVAR a:arg if exists(a:arg) " TLogVAR {a:arg} return {a:arg} else return tskeleton#EvalInDestBuffer(printf('exists("%s") ? %s : "%s"', a:arg, a:arg, a:arg)) endif endf function! s:Execute(text) "{{{3 " TLogDBG string(getline(1, '$')) call s:DelTo('execute(.\{-}', 1) exec a:text " TLogDBG string(getline(1, '$')) return '' endf function! s:Exec(arg) "{{{3 return tskeleton#EvalInDestBuffer(a:arg) endf function! s:Query(arg) "{{{3 let sepx = stridx(a:arg, '|') let var = strpart(a:arg, 0, sepx) let text = strpart(a:arg, sepx + 1) let tsep = stridx(text, '|') if tsep == -1 let repl = '' else let repl = strpart(text, tsep + 1) let text = strpart(text, 0, tsep) endif if var != '' if !tskeleton#EvalInDestBuffer('exists('. string(var) .')') echom 'Unknown choice variable: '. var else let val0 = tskeleton#EvalInDestBuffer(var) if type(val0) == 3 let val = val0 else let val = split(val0, '\n') endif " TAssert IsList(val) let val = sort(copy(val)) " TLogVAR val let rv = tlib#input#List('s', 'Choices:', val) " TLogVAR rv if repl != '' && rv != '' let rv = s:sprintf1(repl, rv) endif " TLogVAR rv return rv endif endif let rv = input(text. ' ', '') if rv != '' && repl != '' let rv = s:sprintf1(repl, rv) endif return rv endf function! s:GetVarName(name, global) "{{{3 if a:global == 2 return 's:tskelBitProcess_'. a:name elseif a:global == 1 return 's:tskelBitProcess_'. s:tskelScratchIdx .'_'. a:name else return 'b:tskelBitProcess_'. a:name endif endf function! s:SaveBitProcess(name, match, global) "{{{3 let s:tskelGetBit = a:match return '' endf function! s:GetBitProcess(text, name, global) "{{{3 let s:tskelGetBit = '' let text = substitute(a:text, '^\s*\s*\n\(\(.\{-}\n\)\{-}\)\s*<\/tskel:'. a:name .'>\s*\n', '\=s:SaveBitProcess("'. a:name .'", submatch(1), '. a:global .')', '') " call tlog#Debug(s:tskelGetBit) return [text, tlib#string#Chomp(s:tskelGetBit)] endf function! s:EvalBitProcess(eval, global) "{{{3 " TLogVAR a:global, a:eval if !empty(a:eval) let eval = substitute(a:eval, '\(^\|\n\)\s*".*\n', '', 'g') " TLogVAR eval if a:global call tskeleton#ExecInDestBuffer(eval) else exec eval endif endif " TLogVAR 'done' endf function! s:Modify(text, modifier) "{{{3 " TLogVAR a:text, a:modifier let rv = a:text let premod = '^[:ulcCs]\{-}\zs' if a:modifier =~# premod.'u' " TLogVAR "u", rv let rv = toupper(rv) endif if a:modifier =~# premod.'l' " TLogVAR "l", rv let rv = tolower(rv) endif if a:modifier =~# premod.'c' " TLogVAR "c", rv let rv = toupper(rv[0]) . tolower(strpart(rv, 1)) endif if a:modifier =~# premod.'C' " TLogVAR "C", rv let rv = substitute(rv, '\(^\|[^a-zA-Z0-9]\)\(.\)', '\u\2', 'g') endif if a:modifier =~# premod.'s' " TLogVAR "s", rv let mod = matchstr(a:modifier, 's\zs.*\ze$') let rxm = '' let sep = mod[0] let esep = escape(sep, '\') let pat = '\(\[^'. sep .']\*\)' let rx = '\V\^'. esep . pat . esep . pat . esep .'\$' let from = matchlist(mod, rx)[1] let to = matchlist(mod, rx)[2] let rv = substitute(rv, rxm . from, to, 'g') endif return rv endf function! s:Dispatch(name) "{{{3 let name = matchstr(a:name, '^ *\zs.\{-}\ze *$') let name = substitute(name, ' ', '_', 'g') " TLogVAR name if exists('*TSkeleton_'. name) let rv = [1, TSkeleton_{name}()] " TLogVAR rv else let rv = [2, tskeleton#WrapMarker(a:name)] endif return rv endf function! s:Call(fn) "{{{3 " TLogVAR a:fn return tskeleton#EvalInDestBuffer(a:fn) endf function! s:Expand(bit, ...) "{{{3 " TLogVAR a:bit let filetype = a:0 >= 1 && a:0 != '' ? a:1 : &filetype " TLogVAR filetype " TLogVAR b:tskelFiletype call tskeleton#PrepareBits(filetype) let sepx = match(a:bit, '|') if sepx == -1 let name = a:bit let default = '' else let name = strpart(a:bit, 0, sepx) let default = strpart(a:bit, sepx + 1) endif let bittext = '' " TLogVAR name, default " TLogDBG string(keys(b:tskelBitDefs)) let indent = s:GetIndent(getline('.')) if s:IsDefined(name) let [setCursor, bittext] = s:RetrieveBit('text', name, indent, filetype) " TLogVAR setCursor, bittext endif " TLogVAR bittext if empty(bittext) if default =~ '".*"' let bittext = matchstr(default, '^"\ze.*\ze"$') elseif default != '' let s:tskelPostExpand = s:tskelPostExpand .'|norm '. default else let bittext = tskeleton#WrapMarker('bit:'.a:bit) endif endif " TLogVAR bittext return bittext endf " :def: function! tskeleton#GetVar(name, ?default=g:name) " Get the value of variable name from the destination buffer. function! tskeleton#GetVar(name, ...) "{{{3 if tskeleton#EvalInDestBuffer('exists("b:'. a:name .'")') return tskeleton#EvalInDestBuffer('b:'. a:name) elseif a:0 >= 1 exec 'return '. a:1 else exec 'return g:'. a:name endif endf function! tskeleton#GetDestBuffer() "{{{3 return s:tskelDestBufNr endf " Evaluate code in the destination buffer. function! tskeleton#EvalInDestBuffer(code) "{{{3 return tskeleton#ExecInDestBuffer('return '. a:code) endf " Execute code in the destination buffer. function! tskeleton#ExecInDestBuffer(code) "{{{3 let cb = bufnr('%') let wb = bufwinnr('%') " TLogVAR cb let sb = s:tskelDestBufNr >= 0 && s:tskelDestBufNr != cb let lazyredraw = &lazyredraw set lazyredraw if sb let ws = bufwinnr(s:tskelDestBufNr) if ws != -1 try exec 'noautocmd' ws.'wincmd w' let code = substitute("\n". a:code ."\n", '\n\s*".\{-}\ze\n', "", "g") " TLogVAR a:code exec 'noautocmd' a:code finally exec 'noautocmd' wb.'wincmd w' endtry else try silent exec 'noautocmd sbuffer! '. s:tskelDestBufNr exec a:code finally noautocmd wincmd c endtry endif else exec a:code endif let &lazyredraw = lazyredraw " TLogDBG 'done' endf function! tskeleton#FindTemplate(template) "{{{3 "<+BODY+> endf function! tskeleton#CollectTemplates() "{{{3 "<+BODY+> endf " :def: function! tskeleton#Setup(template, ?unconditionally=0) " Fill in a file template. function! tskeleton#Setup(template, ...) "{{{3 let anyway = a:0 >= 1 ? a:1 : 0 " TLogVAR a:template, anyway if anyway || !exists('b:tskelDidFillIn') || !b:tskelDidFillIn if filereadable(g:tskelDir . a:template) let tf = g:tskelDir . a:template elseif filereadable(a:template) let tf = a:template else echoerr 'Unknown skeleton: '. a:template return endif let unset_ft = !exists('g:tskelFiletype') if unset_ft let g:tskelFiletype = &filetype endif try let meta = s:ReadSkeleton(tf) let s:tskel_use_placeholders = 0 call tskeleton#FillIn('', &filetype, meta) call tskeleton#Placeholders(0, 0) if g:tskelChangeDir let cd = substitute(expand('%:p:h'), '\', '/', 'g') let cd = substitute(cd, '^\@= 1 && !empty(a:1) ? a:1 : s:Browse(0, "Template", g:tskelDir, "") if !empty(tpl) let tf = tlib#arg#Ex(g:tskelDir . tpl) " TLogVAR tf exe 'edit '. tf end endf function! tskeleton#BitsPath(...) "{{{3 if !exists('s:bits_path') if !empty(g:tskelGlobalBitsPath) let s:bits_path = g:tskelGlobalBitsPath else let s:bits_path = globpath(&rtp, 'skeletons/bits') endif endif if a:0 >= 1 let bits_paths = split(s:bits_path, ',') " TLogVAR bits_paths return get(bits_paths, a:1, '') else return s:bits_path endif endf " Edit a skeleton bit. function! tskeleton#EditBit(bit) "{{{3 if !empty(a:bit) let f = findfile(a:bit, tskeleton#BitsPath()) " TLogVAR f if empty(f) let f = tlib#file#Join([tskeleton#BitsPath(0), a:bit]) " TLogVAR f endif if !empty(f) let tf = tlib#arg#Ex(f) " TLogVAR tf exe 'edit '. tf let filetype = get(split(a:bit, '[\/]'), 0) " if !empty(filetype) && filetype != 'general' " exec 'setf' filetype " endif setf tskeleton exec 'autocmd tSkeleton BufWritePost TSkeletonBitReset '. filetype endif endif endf " :def: function! tskeleton#NewFile(?template, ?dir, ?fileName) " Create a new file template. function! tskeleton#NewFile(...) "{{{3 if a:0 >= 1 && a:1 != "" let tpl = g:tskelDir. a:1 else let tpl = s:Browse(0, "Template", g:tskelDir, "") if tpl == "" return else let tpl = fnamemodify(tpl, ":p") endif endif if a:0 >= 2 && a:2 != "" let dir = a:2 else let dir = getcwd() endif if a:0 >= 3 let fn = a:3 else let fn = s:Browse(1, "New File", dir, "new.".fnamemodify(tpl, ":e")) if fn == "" return else let fn = fnamemodify(fn, ":p") endif endif if fn != "" && tpl != "" " TLogVAR tpl exe 'edit '. tpl exe 'saveas '. fn let s:tskel_use_placeholders = 0 call tskeleton#FillIn('', &filetype) call tskeleton#Placeholders(0, 0) exe "bdelete ". tpl endif endf function! s:PrepareMiniBit(dict, def, buildmenu) "{{{3 " TAssert IsDictionary(a:dict) " TAssert IsString(a:def) if !empty(a:def) " TLogVAR a:def if a:def =~ '\S\+\s' let bit = matchstr(a:def, '^\S\+\ze\s') let exp = matchstr(a:def, '\s\zs.\+$') else let bit = a:def let exp = a:def endif " TAssert IsString(exp) let a:dict[bit] = {'text': exp, 'menu': g:tskelMenuMiniPrefix . bit, 'type': 'tskeleton'} if a:buildmenu call tskeleton#NewBufferMenuItem(b:tskelBufferMenu, bit) endif " TAssert IsNotEmpty(a:dict[bit]) endif endf function! tskeleton#NewBufferMenuItem(menu, bit, ...) TVarArg ['subpriority', 10] " TLogVAR a:menu " TLogVAR a:bit " TLogVAR subpriority let min = s:PrepareMenuEntry(a:bit, subpriority, "n") " TLogVAR min call add(a:menu, min) let mii = s:PrepareMenuEntry(a:bit, subpriority, "i") " TLogVAR mii call add(a:menu, mii) if tlib#var#Get('tskelAutoAbbrevs', 'bg') let mia = s:PrepareAbbreviation(a:bit) " TLogVAR mia if !empty(mia) call add(a:menu, mia) endif endif " TLogDBG 'tskeleton#NewBufferMenuItem end' endf function! tskeleton#FetchMiniBits(dict, path, pattern, buildmenu) "{{{3 " TAssert IsDictionary(a:dict) " TLogVAR a:filename, a:buildmenu " TLogVAR keys(a:dict) if empty(a:path) let filenames = [a:pattern] else let filenames = split(globpath(a:path, a:pattern), '\n') endif for filename in filenames let cache_name = tskeleton#MaybePathshorten(filename) let cfile = tlib#cache#Filename('tskel_mbits', tlib#url#Encode(cache_name), 1) let ftime = getftime(filename) let mbits = tlib#cache#Value(cfile, 'tskeleton#FetchMiniBitsGenerator', ftime, [filename, a:buildmenu]) " TAssert IsDictionary(mbits) " TLogVAR mbits call extend(a:dict, mbits) endfor return a:dict endf function! tskeleton#MaybePathshorten(filename) "{{{3 if strlen(a:filename) > g:tskeleton#max_basename return pathshorten(a:filename) else return a:filename endif endf function! tskeleton#FetchMiniBitsGenerator(filename, buildmenu) let dict = {} let c = s:ReadFile(a:filename) if c =~ '\S' for line in sort(split(c, "\n")) call s:PrepareMiniBit(dict, line, a:buildmenu) endfor endif return dict endf function! tskeleton#ReplacePrototypeArgs(text, rest) let args = split(a:text, ',\s\+') if empty(args) return '()' . tskeleton#CursorMarker() else let max = len(args) - 1 let rv = map(range(0, max), '!empty(a:rest) && args[v:val] =~# a:rest ? tskeleton#WrapMarker("") : (v:val == 0 ? "" : ", ") . printf(tskeleton#WrapMarker("%s"), s:CleanArgument(args[v:val]))') return printf('(%s%s)%s', tskeleton#CursorMarker(), join(rv, ''), tskeleton#WrapMarker('')) endif endf function! s:CleanArgument(arg) "{{{3 return substitute(a:arg, '[?&:|()<>]', ' ', 'g') endf function! s:ExpandMiniBit(bit) "{{{3 let rv = '' if s:IsDefined(a:bit) let rv = tskeleton#BitDef(a:bit, 'text') endif " TAssert IsString(rv) return rv endf function! s:sprintf1(string, arg) "{{{3 let rv = substitute(a:string, '\C\(^\|%%\|[^%]\)\zs%s', escape(a:arg, '"\'), 'g') let rv = substitute(rv, '%%', '%', 'g') return rv endf function! s:GetBitGroup(filetype, ...) "{{{3 let general_first = a:0 >= 1 ? a:1 : 0 let filetype = substitute(a:filetype, '\W', '_', 'g') let bg = tlib#var#Get('tskelBitGroup_'. filetype, 'bg') if !empty(bg) if type(bg) == 1 echom 'tSkeleton: [bg]:tskelBitGroup_'. filetype .' should be a list' let rv = split(bg, "\n") else let rv = copy(bg) endif else let rv = [filetype] endif " TAssert IsList(rv) if filetype != 'general' if general_first call insert(rv, 'general') else call add(rv, 'general') endif endif return rv endf function! tskeleton#PurifyBit(bit) "{{{3 let mname = tlib#url#Decode(a:bit) let cname = a:bit let cname = substitute(cname, '^.\{-}\.\ze[^.]\+$', '', '') let cname = tlib#url#Decode(substitute(cname, '&', '', 'g')) return [cname, mname] endf function! s:DidSetup(filetype) "{{{3 return exists('g:tskelBits_'. a:filetype) endf function! s:ToBeInitialized(list, filetype) "{{{3 return index(a:list, a:filetype) != -1 endf function! s:FiletypesToBeInitialized(ftgroup, explicit_reset) "{{{3 if a:explicit_reset return a:ftgroup endif return filter(copy(a:ftgroup), 's:FiletypeToBeInitialized(v:val)') endf function! s:FiletypeToBeInitialized(filetype) "{{{3 if !s:DidSetup(a:filetype) return 1 else let ftm = s:GetMenuCacheFilename(a:filetype) if empty(ftm) return 0 else return !filereadable(ftm) endif endif endf " s:PrepareMenu(type, ?menuprefix='') function! s:PrepareMenu(filetype, ...) "{{{3 if g:tskelMenuCache == '' || g:tskelMenuPrefix == '' return endif " TLogVAR a:filetype let menu_file = s:GetMenuCacheFilename(a:filetype) " TLogVAR menu_file if menu_file != '' let sub = a:0 >= 1 ? a:1 : '' let tskelMenuPrefix = g:tskelMenuPrefix let verbose = &verbose let lazyredraw = &lazyredraw let backup = &backup let patchmode = &patchmode let g:tskeleton_SetFiletype = 0 set lazyredraw set nobackup set patchmode= set verbose& try let menu = s:MakeMenuEntry(keys(g:tskelBits_{a:filetype}), sub) if !empty(menu) exec 'redir! > '. menu_file if exists('*TSkelMenuCacheEditHook') silent! call TSkelMenuCacheEditHook() endif silent! echo join(menu, "\n") if exists('*TSkelMenuCachePostWriteHook') silent! call TSkelMenuCachePostWriteHook() endif redir END endif catch echohl Error echom "Exception" v:exception "from" v:throwpoint echom v:errmsg echohl NONE finally let &verbose = verbose let &lazyredraw = lazyredraw let &backup = backup let &patchmode = patchmode let g:tskeleton_SetFiletype = 1 let g:tskelMenuPrefix = tskelMenuPrefix endtry endif endf function! s:MakeMenuEntry(items, ...) let sub = a:0 >= 1 ? a:1 : '' " TLogVAR a:items " TAssert IsList(a:items) if sub != '' let g:tskelMenuPrefix = g:tskelMenuPrefix .'.'. sub let subpriority = 10 else let subpriority = 20 endif let menu = [] call filter(sort(copy(a:items)), 'tskeleton#NewBufferMenuItem(menu, v:val, subpriority)') " TLogVAR menu return menu endf function! s:GetCacheFilename(filetype, what) "{{{3 " TLogVAR a:filetype if a:filetype == '' return '' endif let cfn = tlib#cache#Filename(a:what, a:filetype, 1) " TLogVAR cfn return cfn endf function! s:GetMenuCacheFilename(filetype) "{{{3 return s:GetCacheFilename(a:filetype, 'tskel_menu') endf function! s:GetFiletypeBitsCacheFilename(filetype) "{{{3 return s:GetCacheFilename(a:filetype, 'tskel_bits') endf function! s:ResetBufferCacheForFiletype(filetype) "{{{3 let dir = s:GetCacheFilename(a:filetype, 'tskel_bbits') if !empty(dir) let files = split(globpath(dir, '**'), '\n') for fname in files if !isdirectory(fname) " TLogVAR fname call delete(fname) endif endfor endif endf function! s:GetBufferCacheFilename(filetype, ...) "{{{3 if g:tskelUseBufferCache let fname = expand('%:t') " TLogVAR fname if !empty(fname) let create_dir = a:0 >= 1 ? a:1 : 0 let dir = s:GetCacheFilename(a:filetype, 'tskel_bbits') if !empty(dir) let dir = tlib#file#Join([ \ dir, \ substitute(expand('%:p:h'), '[:&<>]\|//\+\|\\\\\+', '_', 'g') \ ]) " TLogVAR dir if create_dir && !isdirectory(dir) call tlib#dir#Ensure(dir) endif " let fname = expand('%:t') .'.'. a:filetype let cname = tlib#file#Join([dir, fname]) " TLogVAR cname return cname endif endif endif return '' endf function! tskeleton#BitDef(name, ...) "{{{3 TVarArg 'field', 'default' " TLogVAR a:name, field, default let def = get(s:GetBitDefs(), a:name, {}) " TLogVAR def if empty(field) return def else let rv = get(def, field, default) if field == 'text' if has_key(def, 'preprocess') let rv = call(def.preprocess, [rv]) endif endif return rv endif endf function! s:PrepareAbbreviation(name) "{{{3 if a:name =~ '\S' " TLogVAR a:name let bit = tskeleton#BitDef(a:name) if !(has_key(bit, 'abbrev') && empty(bit.abbrev)) let abb = a:name. tlib#var#Get('tskelAbbrevPostfix', 'bg') if abb =~ '\W\W$' echom 'tSkeleton: Invalid name for an abbreviation: '. abb else if !empty(bit) let meta = get(bit, 'meta', {}) let abbr = get(meta, 'abbrev', get(bit, 'abbrev', '')) let abbr = substitute(abbr, '\s', '', 'g') if !empty(abbr) let abb = abbr endif endif " TLogVAR abb if !empty(abb) return 'iabbrev '. abb .' '. printf(tskeleton#ExpandedAbbreviationTemplate(), string(a:name)) endif endif endif endif return '' endf function! s:PrepareMenuEntry(name, subpriority, mode) "{{{3 " TLogVAR a:name if a:name =~ '\S' " TLogVAR a:mode let bit = tskeleton#BitDef(a:name) " TLogVAR bit let mname = escape(a:name, '\.') if !empty(bit) let mname = get(bit, 'menu', mname) endif let mname = escape(mname, ' |') " TLogVAR mname let acc = [] for menu_name in split(mname, "\n") " TLogVAR menu_name let spri = stridx(menu_name, '.') >= 0 ? a:subpriority - 1 : a:subpriority " TLogVAR spri let pri = g:tskelMenuPriority .'.'. spri " TLogVAR pri let subst = string(escape(a:name, '|')) if s:IsInsertMode(a:mode) call add(acc, 'imenu '. pri .' '. g:tskelMenuPrefix .'.'. menu_name . \ ' :call tskeleton#ExpandBitUnderCursor("i", '. subst .')') else call add(acc, 'menu '. pri .' '. g:tskelMenuPrefix .'.'. menu_name . \ ' :call tskeleton#ExpandBitUnderCursor("n", '. subst .')') endif endfor return join(acc, "\n") else return '' endif endf function! s:InitBufferMenu() if !exists('b:tskelBufferMenu') let b:tskelBufferMenu = [] endif endf function! tskeleton#BuildBufferMenu(prepareBits) "{{{3 " TLogVAR a:prepareBits if !s:tskelProcessing && &filetype != '' && g:tskelMenuCache != '' && g:tskelMenuPrefix != '' if a:prepareBits call tskeleton#PrepareBits() endif if s:tskelBuiltMenu == 1 try silent exec 'aunmenu '. g:tskelMenuPrefix finally endtry endif let pri = g:tskelMenuPriority .'.'. 5 exec 'amenu '. pri .' '. g:tskelMenuPrefix .'.Reset :TSkeletonBitReset' exec 'amenu '. pri .' '. g:tskelMenuPrefix .'.-tskel1- :' let bg = s:GetBitGroup(&filetype, 1) " TLogVAR bg call map(bg, 's:GetMenuCache(v:val)') if exists('b:tskelBufferMenu') " TLogVAR b:tskelBufferMenu for m in b:tskelBufferMenu exec m endfor endif let s:tskelBuiltMenu = 1 endif endf function! s:GetMenuCache(filetype) "{{{3 let pg = s:GetMenuCacheFilename(a:filetype) " TLogVAR pg if filereadable(pg) exec 'source '. pg endif endf " :def: function! tskeleton#PrepareBits(?filetype=&filetype, ?reset=0) " Prepare the buffer for use with tskeleton. function! tskeleton#PrepareBits(...) "{{{3 if a:0 >= 1 && !empty(a:1) let filetype = a:1 " TLogVAR 'a:1', filetype else let filetype = s:Filetype() endif " TLogVAR a:0, filetype, &filetype call tskeleton#Initialize() let explicit_reset = a:0 >= 2 ? a:2 : 0 if explicit_reset for idx in range(1, s:tskelScratchMax) let ibn = bufnr(s:tskelScratchNr{idx}) if bufloaded(ibn) exec 'noautocmd bdelete! '. ibn endif endfor let s:tskelScratchMax = 0 if g:tskelUseBufferCache call s:ResetBufferCacheForFiletype(filetype) endif endif " TLogVAR explicit_reset let init_buffer = !exists('b:tskelFiletype') || b:tskelFiletype != filetype " TLogVAR init_buffer if !explicit_reset && !init_buffer return endif " TLogVAR filetype let ft_group = s:GetBitGroup(filetype) " TAssert IsList(ft_group) " TLogVAR ft_group let to_be_initialized = s:FiletypesToBeInitialized(ft_group, explicit_reset) " TAssert IsList(to_be_initialized) " TLogVAR to_be_initialized if init_buffer || !empty(to_be_initialized) if !explicit_reset && g:tskelUseBufferCache && s:HasCachedBufferBits(filetype) " TLogDBG 'PrepareBufferFromCache' call s:PrepareBufferFromCache(filetype) else call s:InitBufferMenu() let b:tskelBitDefs = {} for gfiletype in ft_group " TLogVAR gfiletype let reset = s:ToBeInitialized(to_be_initialized, gfiletype) let resetcache = explicit_reset || !s:FiletypeInCache(gfiletype) " TLogVAR reset, resetcache if reset if resetcache call s:PrepareFiletype(gfiletype, reset) else call s:PrepareFiletypeFromCache(gfiletype) endif endif " TLogDBG 'ExtendBitDefs' call s:ExtendBitDefs(b:tskelBitDefs, gfiletype) " TLogDBG 'PrepareFiletypeMap' call s:PrepareFiletypeMap(gfiletype, reset) if reset if resetcache " TLogDBG 'CacheFiletypeBits' call s:CacheFiletypeBits(gfiletype) endif if !tskeleton#IsScratchBuffer() " TLogDBG 'PrepareFiletypeMenu' call s:PrepareFiletypeMenu(gfiletype) endif endif endfor " if s:PrepareBuffer(gfiletype) && empty(&buftype) if s:PrepareBuffer(gfiletype) && g:tskelUseBufferCache " TLogDBG 'CacheBufferBits' call s:CacheBufferBits(gfiletype) endif endif " TAssert IsDictionary(b:tskelBitDefs) " TLogDBG 'tskeleton#BuildBufferMenu' call tskeleton#BuildBufferMenu(0) let b:tskelFiletype = filetype endif endf function! s:HasCachedBufferBits(filetype) "{{{3 let cname = s:GetBufferCacheFilename(a:filetype) return filereadable(cname) endf function! s:CacheBufferBits(filetype) "{{{3 let cname = s:GetBufferCacheFilename(a:filetype, 1) if !empty(cname) " TLogVAR cname call writefile([string(s:GetBitDefs())], cname, 'b') endif endf function! s:PrepareBufferFromCache(filetype) "{{{3 let cname = s:GetBufferCacheFilename(a:filetype) let b:tskelBitDefs = eval(join(readfile(cname, 'b'), "\n")) endf function! s:FiletypeInCache(filetype) "{{{3 let cache = s:GetFiletypeBitsCacheFilename(a:filetype) let filereadable = filereadable(cache) " TLogVAR cache, filereadable return filereadable endf function! s:PrepareFiletypeFromCache(filetype) "{{{3 let cache = s:GetFiletypeBitsCacheFilename(a:filetype) if !empty(cache) let g:tskelBits_{a:filetype} = eval(join(readfile(cache, 'b'), "\n")) " TLogVAR cache, len(g:tskelBits_{a:filetype}) endif endf function! s:CacheFiletypeBits(filetype) "{{{3 let cache = s:GetFiletypeBitsCacheFilename(a:filetype) if !empty(cache) call writefile([string(g:tskelBits_{a:filetype})], cache, 'b') " TLogVAR cache, len(g:tskelBits_{a:filetype}) endif endf function! s:PrepareFiletype(filetype, reset) " TLogVAR a:filetype " TLogVAR a:reset let g:tskelBits_{a:filetype} = {} let fns = s:CollectFunctions('tskeleton#%s#FiletypeBits') \ + s:CollectFunctions('tskeleton#%s#FiletypeBits_'. a:filetype) " TLogVAR fns for fn in fns " TLogDBG 'PrepareFiletype '.fn call {fn}(g:tskelBits_{a:filetype}, a:filetype) " TLogVAR fn, len(g:tskelBits_{a:filetype}) endfor " TLogDBG 'bits for '. a:filetype .'='. string(keys(g:tskelBits_{a:filetype})) endf function! s:PrepareBuffer(filetype) " TLogDBG bufname('%') let fns = s:CollectFunctions('tskeleton#%s#BufferBits') \ + s:CollectFunctions('tskeleton#%s#BufferBits_'. a:filetype) " TLogVAR fns for fn in fns " TLogDBG 'PrepareBuffer '.fn call {fn}(s:GetBitDefs(), a:filetype) endfor " TLogDBG string(keys(b:tskelBitDefs)) return !empty(fns) endf function! s:CollectFunctions(pattern) " TLogVAR a:pattern let rv = [] let ts = tlib#var#Get('tskelTypes', 'bg') " TLogVAR ts call tskeleton#Initialize(ts) for t in ts let f = printf(a:pattern, t) " TLogVAR f " TLogDBG exists('*'. f) if exists('*'. f) call add(rv, f) endif endfor return rv endf function! s:ReadFile(filename) "{{{3 " TAssert IsString(a:filename) if filereadable(a:filename) return join(readfile(a:filename), "\n") endif return '' endf function! s:ReadSkeleton(filename) "{{{3 let lines = readfile(a:filename) let [text, meta] = tskeleton#ExtractMeta(join(lines, "\n")) " echom "DBG" text string(meta) call tlib#buffer#InsertText(text) return meta endf function! s:PrepareFiletypeMap(filetype, anyway) "{{{3 if !exists('g:tskelBitMap_'. a:filetype) || a:anyway let fn = g:tskelMapsDir . a:filetype let c = s:ReadFile(fn) if c =~ '\S' let g:tskelBitMap_{a:filetype} = {} for line in split(c, "\n") let pattern = matchstr(line, '^.\{-}\ze\t') if !empty(pattern) let bits = matchstr(line, '\t\zs.*$') let g:tskelBitMap_{a:filetype}[pattern] = split(bits, '\s\+') endif endfor endif endif endf function! s:PrepareFiletypeMenu(filetype) "{{{3 " TLogVAR a:filetype if a:filetype == 'general' call s:PrepareMenu('general', 'General') else call s:PrepareMenu(a:filetype) endif endf function! s:ExtendBitDefs(dict, filetype) "{{{3 " TAssert IsDictionary(a:dict) if s:DidSetup(a:filetype) let bm = g:tskelBits_{a:filetype} " TAssert IsDictionary(bm) if !empty(bm) call extend(a:dict, bm) endif endif endf function! tskeleton#ResetBits(filetype) "{{{3 let filetype = empty(a:filetype) ? &filetype : a:filetype for bn in range(1, bufnr('$')) if bufloaded(bn) && (filetype == 'general' || getbufvar(bn, 'tskelFiletype') == filetype) call setbufvar(bn, 'tskelFiletype', '') endif endfor call tskeleton#PrepareBits(filetype, 1) endf function! tskeleton#SelectBit(ArgLead, CmdLine, CursorPos) "{{{3 call tskeleton#PrepareBits() return join(s:EligibleBits(&filetype), "\n") endf function! s:SetLine(mode) "{{{3 let s:tskelLine = line('.') let s:tskelCol = col('.') endf function! s:UnsetLine() "{{{3 let s:tskelLine = 0 let s:tskelCol = 0 endf function! s:GetEligibleBits(filetype) "{{{3 let pos = '\\%'. s:tskelLine .'l\\%'. s:tskelCol .'c' for pattern in keys(g:tskelBitMap_{a:filetype}) if search(pattern.pos, 'W') return g:tskelBitMap_{a:filetype}[pattern] endif endfor return [] endf function! s:EligibleBits(filetype) "{{{3 if s:tskelLine && exists('g:tskelBitMap_'. a:filetype) norm! { let eligible = s:GetEligibleBits(a:filetype) " TAssert IsList(eligible) call cursor(s:tskelLine, s:tskelCol) if !empty(eligible) " TLogDBG a:filetype.': '. string(eligible) return eligible endif endif let ok = filter(items(s:GetBitDefs()), 'eval(get(get(get(v:val, 1, {}), "meta", {}), "condition", 1))') return map(ok, 'v:val[0]') endf function! s:EditScratchBuffer(filetype, ...) "{{{3 let idx = a:0 >= 1 ? a:1 : s:tskelScratchIdx if exists("s:tskelScratchNr". idx) && s:tskelScratchNr{idx} >= 0 let tsbnr = bufnr(s:tskelScratchNr{idx}) else let tsbnr = -1 endif let vars = map(copy(s:tskelScratchVars), 'exists("b:".v:val) ? ["b:".v:val, b:{v:val}] : ["", ""]') let tskel_bitDefs = b:tskelBitDefs let tskelFiletype = b:tskelFiletype if tsbnr >= 0 " TLogVAR tsbnr silent exec "noautocmd sbuffer ". tsbnr else silent noautocmd split " TLogVAR idx " TLogDBG 'edit __TSkeletonScratch_'. idx .'__' silent exec 'noautocmd edit __TSkeletonScratch_'. idx .'__' " TLogDBG 1 let s:tskelScratchNr{idx} = bufnr("%") endif for [var, val] in vars if !empty(var) && !exists(var) let {var} = val endif endfor " TLogDBG 2 setlocal buftype=nofile setlocal bufhidden=hide setlocal noswapfile setlocal nobuflisted setlocal foldlevel=99 setlocal foldmethod=manual silent norm! ggdG " TLogVAR a:filetype, tskelFiletype " TLogDBG 3 " Let's assume the bits get inherited from the parent buffer let b:tskelFiletype = tskelFiletype let b:tskelBitDefs = copy(tskel_bitDefs) " TLogDBG 4 if exists('*TSkelNewScratchHook_'. a:filetype) call TSkelNewScratchHook_{a:filetype}() endif " TLogDBG 'exit' endf function! tskeleton#IsScratchBuffer() return bufname('%') =~ '\V__TSkeletonScratch_\d\+__' endf function! tskeleton#Retrieve(name) "{{{3 let [setCursor, bittext] = s:RetrieveBit('text', a:name) return bittext endf function! s:Filetype() "{{{3 if exists('b:tskelFiletype') let filetype = b:tskelFiletype elseif exists('g:tskelFiletype') let filetype = g:tskelFiletype else let filetype = &filetype endif " TLogVAR filetype return filetype endf " s:RetrieveBit(agent, bit, ?indent, ?filetype) => setCursor?; @t=expanded template bit function! s:RetrieveBit(agent, bit, ...) "{{{3 if s:tskelScratchIdx >= g:tskelMaxRecDepth return 0 endif " TLogVAR a:agent, a:bit let indent = a:0 >= 1 ? a:1 : '' let filetype = a:0 >= 2 ? a:2 : s:Filetype() " TLogVAR filetype let rv = '' if s:tskelScratchIdx == 0 let s:tskelDestBufNr = bufnr("%") endif let s:tskelScratchIdx = s:tskelScratchIdx + 1 if s:tskelScratchIdx > s:tskelScratchMax let s:tskelScratchMax = s:tskelScratchIdx let s:tskelScratchNr{s:tskelScratchIdx} = -1 endif let setCursor = 0 let pos = getpos('.') let processing = s:SetProcessing() let t = @t try call s:EditScratchBuffer(filetype) if filetype != "" call tskeleton#PrepareBits(filetype) endif let type = tskeleton#BitDef(a:bit, 'type', 'tskeleton') " TLogVAR type " TLogExec sleep 3 | redraw if type != 'tskeleton' let retriever = printf('tskeleton#%s#Retrieve', type) " TLogVAR retriever let setCursor = {retriever}(a:bit, indent, filetype) else if s:RetrieveAgent_{a:agent}(a:bit) " TLogDBG string(getline(1, '$')) " TLogDBG string(getline(1, '$')) silent norm! gg call tskeleton#FillIn(a:bit, filetype) " TLogDBG string(getline(1, '$')) let setCursor = tskeleton#SetCursor('%', '', 1, 1) " TLogDBG string(getline(1, '$')) else echoerr "Internal error" endif endif " TLogVAR setCursor " TLogExec sleep 3 | redraw let bot = line('$') let rv = join(getline(1, bot), "\n") " TLogVAR rv let rv = tlib#string#Chomp(rv, 1) " TLogVAR rv finally let @t = t call s:SetProcessing(processing) noautocmd wincmd c let s:tskelScratchIdx = s:tskelScratchIdx - 1 if s:tskelScratchIdx == 0 silent exec 'noautocmd buffer '. s:tskelDestBufNr let s:tskelDestBufNr = -1 else silent exec 'noautocmd buffer '. s:tskelScratchNr{s:tskelScratchIdx} endif call setpos('.', pos) endtry " TLogVAR rv return [setCursor, rv] endf function! s:SetProcessing(...) "{{{3 if a:0 >= 1 let s:tskelProcessing = a:1 return a:1 else let rv = s:tskelProcessing let s:tskelProcessing = 1 return rv endif endf function! s:RetrieveAgent_text(bit) "{{{3 " TLogVAR a:bit if s:IsDefined(a:bit) let text = tskeleton#BitDef(a:bit, 'text') " TLogVAR text let lines = split(text, '\n', 1) " TLogVAR lines call append(0, lines) " TLogVAR line('$'), len(lines) if line('$') > len(lines) norm! Gdd endif return 1 else " TLogDBG "Undefined bit: ". a:bit echoerr "Undefined bit: ". a:bit return 0 endif " TLogDBG string(getline(1, '$')) endf function! s:InsertBit(agent, bit, mode) "{{{3 " TLogVAR a:agent, a:bit, a:mode let c = col(".") let e = col("$") let l = line(".") let li = getline(l) let sli = s:Subline(li, c, a:mode) let by = line2byte(l) + c " Adjust for vim idiosyncrasy " TLogVAR "orig", li, sli, c, e, l, by if c == e - 1 && li[c - 1] == " " let e = e - 1 endif " TLogVAR "adj", li, sli, c, e, l, by let i = s:GetIndent(sli) let [setCursor, bittext] = s:RetrieveBit(a:agent, a:bit, i) " TLogVAR setCursor, bittext " TLogVAR getpos('.') call cursor(0, c) " TLogVAR getpos('.') let shift = s:InsertBitText(a:mode, bittext) " TLogVAR shift, getpos('.') if setCursor let ll = l + abs(setCursor) - 1 " TLogVAR ll call tskeleton#SetCursor(l, ll, setCursor < 0) else let byte = by + len(bittext) - 1 + shift " TLogVAR byte, by, len(bittext) if s:IsInsertMode(a:mode) && s:IsEOL(a:mode) && len(li) > 0 let byte += 1 end exec 'go '. byte " TLogVAR getpos('.') endif endf function! s:InsertBitText(mode, bittext) "{{{3 " TLogVAR a:mode, a:bittext let s:bit_lines = len(split(a:bittext, '\n', 1)) let rv = tlib#buffer#InsertText(a:bittext, { \ 'shift': s:IsEOL(a:mode) ? 0 : -1, \ 'pos': 's', \ 'indent': a:mode =~# 'l' ? 0 : 1, \ }) if s:tskelScratchIdx == 0 let lnum = line('.') call s:UseStakeholders(lnum, lnum + s:bit_lines) endif if !s:IsInsertMode(a:mode) && !s:IsEOL(a:mode) let rv -= 1 endif return rv endf function! s:GetIndent(line) "{{{3 return matchstr(a:line, '^\(\s*\)') endf function! s:IndentLines(from, to, indent) "{{{3 " TLogVAR a:indent silent exec a:from.",".a:to.'s/^/'. escape(a:indent, '/\') .'/g' endf function! s:CharRx(char) "{{{3 let rv = '&\?' if a:char == '\\' return rv .'\('. tlib#url#EncodeChar('\') .'\|\\\)' elseif a:char =~ '[/*#<>|:"?{}~]' return rv .'\('. tlib#url#EncodeChar(a:char) .'\|'. a:char .'\)' else return rv . a:char endif endf function! s:BitRx(bit, escapebs) "{{{3 let rv = substitute(escape(a:bit, '\'), '\(\\\\\|.\)', '\=s:CharRx(submatch(1))', 'g') return rv endf function! s:FindValue(list, function, ...) " TLogDBG "function=". a:function " TLogDBG "list=". string(a:list) for elt in a:list try let fn = printf(a:function, escape(string(elt), '\')) " TLogDBG "fn=". fn let val = eval(fn) " TLogDBG "val=". val if !empty(val) " TLogDBG "rv=". val return val endif catch echohl Error echom "Exception" v:exception "from" v:throwpoint echom v:errmsg echohl NONE endtry unlet elt endfor return a:0 >= 1 ? a:1 : 0 endf function! s:IsDefined(bit) "{{{3 " TLogVAR bufname('%'), !empty(a:bit), exists('b:tskelBitDefs') " call tlog#Log("has_key(b:tskelBitDefs, a:bit) = ". has_key(b:tskelBitDefs, a:bit)) return !empty(a:bit) && exists('b:tskelBitDefs') && has_key(b:tskelBitDefs, a:bit) endf function! s:GetBitDefs() "{{{3 if !exists('b:tskelBitDefs') call tskeleton#PrepareBits() endif return exists('b:tskelBitDefs') ? b:tskelBitDefs : {} endf function! s:SelectAndInsert(bit, mode) "{{{3 " TLogVAR a:bit if s:IsDefined(a:bit) call s:InsertBit('text', a:bit, a:mode) return 1 endif return 0 endf " tskeleton#Bit(bit, ?mode='n') function! tskeleton#Bit(bit, ...) "{{{3 " TLogVAR a:bit " TAssert IsNotEmpty(a:bit) call tskeleton#PrepareBits() let mode = a:0 >= 1 ? a:1 : 'n' let processing = s:SetProcessing() let wlayout = tlib#win#GetLayout() let s:tskel_use_placeholders = 0 let s:bit_lines = 0 try if empty(a:bit) call s:BitMenu(a:bit, mode, s:Filetype()) elseif s:SelectAndInsert(a:bit, mode) " call tlog#Debug('s:SelectAndInsert ok') return 1 else " call tlog#Debug("TSkeletonBit: Unknown bit '". a:bit ."'") if s:IsPopup(mode) call s:InsertBitText(mode, a:bit) return 1 endif return 0 endif finally let lnum = line('.') call tskeleton#Placeholders(lnum, lnum + s:bit_lines - 1) call tlib#win#SetLayout(wlayout) call s:SetProcessing(processing) endtry endf function! s:IsInsertMode(mode) "{{{3 return a:mode =~? 'i' endf function! s:IsEOL(mode) "{{{3 if a:mode =~ 'g' let mode = a:mode . s:Eol(a:mode, col('.')) else let mode = a:mode endif " TLogVAR a:mode, mode return mode =~? '1' endf function! s:IsPopup(mode) "{{{3 return a:mode =~? 'p' endf function! s:Subline(line, col, mode) "{{{3 " TLogVAR a:line, a:col, a:mode let e = a:col - 1 if s:IsEOL(a:mode) let e += 1 endif if e < 0 let e = 0 endif let rv = strpart(a:line, 0, e) " TLogVAR rv return rv endf function! s:BitMenu(bit, mode, filetype) "{{{3 " TLogVAR a:bit if has("menu") && g:tskelQueryType == 'popup' return s:BitMenu_menu(a:bit, a:mode, a:filetype) else return s:BitMenu_query(a:bit, a:mode, a:filetype) endif endf function! s:BitMenuEligible(agent, bit, mode, filetype) "{{{3 " TLogVAR a:agent, a:bit, a:mode, a:filetype call s:SetLine(a:mode) let t = copy(s:EligibleBits(a:filetype)) " TLogVAR len(t) " TAssert IsList(t) let s:tskelMenuEligibleIdx = 0 let s:tskelMenuEligibleRx = '^'. s:BitRx(a:bit, 0) call filter(t, 'v:val =~ ''\S'' && s:MatchBit(v:val, s:tskelMenuEligibleRx)') " TLogVAR len(t) if g:tskelPopupNumbered call sort(t) endif let e = map(t, 's:BitMenuEligible_'. a:agent .'_cb(v:val, '. string(a:mode) .')') " TAssert IsList(e) " TLogDBG 'e='. string(e) return tlib#list#Compact(e) endf function! s:MatchBit(value, rx) "{{{3 let case_sensitive = tlib#var#Get('tskelCaseSensitive_'. s:Filetype(), 'bg', tlib#var#Get('tskelCaseSensitive', 'bg')) if case_sensitive == 1 return a:value =~# a:rx elseif case_sensitive == -1 return a:value =~ a:rx elseif case_sensitive == 0 return a:value =~? a:rx else echoerr 'tskelCaseSensitive: Must be one of: 1, -1, 0' endif endf function! s:BitMenuEligible_complete_cb(bit, mode) "{{{3 return s:BitMenuEligible_query_cb(a:bit, a:mode) endf function! s:BitMenu_query(bit, mode, filetype) "{{{3 let s:tskelQueryAcc = s:BitMenuEligible('query', a:bit, a:mode, a:filetype) if len(s:tskelQueryAcc) <= 1 let rv = get(s:tskelQueryAcc, 0, a:bit) let rv = get(s:tskelQueryAcc, 0, '') else let qu = "s:tskelQueryAcc|Select bit:" let rv = s:Query(qu) endif " TLogVAR rv if rv != '' call tskeleton#Bit(rv, a:mode .'p') return 1 endif return 0 endf function! s:BitMenuEligible_query_cb(bit, mode) "{{{3 return tlib#url#Decode(a:bit) endf function! s:BitMenu_menu(bit, mode, filetype) "{{{3 silent! aunmenu ]TSkeleton " TLogDBG 'bit='. a:bit let rv = s:BitMenuEligible('menu', a:bit, a:mode, a:filetype) " TAssert IsList(rv) let j = len(rv) if j == 1 exec s:tskelMenuEligibleEntry return 1 elseif j > 0 popup ]TSkeleton return 1 endif return 0 endf function! s:BitMenuEligible_menu_cb(bit, mode) "{{{3 " TAssert IsString(a:bit) " TLogDBG 'bit='. a:bit " call tlog#Debug('tskelMenuEligibleRx=~'. a:bit =~ s:tskelMenuEligibleRx) let s:tskelMenuEligibleIdx = s:tskelMenuEligibleIdx + 1 if g:tskelPopupNumbered if stridx(a:bit, '&') == -1 let x = substitute(s:tskelMenuEligibleIdx, '\(.\)$', '\&\1', '') else let x = s:tskelMenuEligibleIdx end let x .= '\ ' let m = a:bit else let x = '' let m = escape(tskeleton#BitDef(a:bit, 'menu'), '"\ ') endif let s:tskelMenuEligibleEntry = 'call tskeleton#Bit('. string(a:bit) .', "'. a:mode .'p")' " call tlog#Debug(s:tskelMenuEligibleEntry) exec 'amenu ]TSkeleton.'. x . m .' :'. s:tskelMenuEligibleEntry .'' return 1 endf function! s:Eol(mode, col) "{{{3 " TLogVAR a:mode, a:col, col('$'), a:col >= col('$') return a:col >= col('$') && &virtualedit =~ '^\(block\|onemore\)\?$' endf " tskeleton#ExpandBitUnderCursor(mode, ?bit="", ?default={}) " See also |g:tskelHyperComplete|. function! tskeleton#ExpandBitUnderCursor(mode, ...) "{{{3 let bit = a:0 >= 1 && a:1 != '' ? a:1 : '' let default = a:0 >= 2 && !empty(a:2) ? a:2 : {} let line = line('.') let l = getline(line) let col0 = col('.') " TLogVAR 1, col('.') " TLogDBG 'ExpandBit saveview '. line('w0') let view = winsaveview() " TLogVAR line, col0, l " TLogVAR bit call tskeleton#PrepareBits() let t = @t let lazyredraw = &lazyredraw set lazyredraw let unset_ft = !exists('g:tskelFiletype') if unset_ft let g:tskelFiletype = &filetype endif " TLogVAR g:tskelFiletype " TLogVAR 2, col('.') try let @t = '' let filetype = s:Filetype() let imode = s:IsInsertMode(a:mode) " TLogVAR a:mode, imode, col0 let col = col0 if imode if s:Eol(a:mode, col) let eol_adjustment = 1 else let col -= 1 let eol_adjustment = 0 endif else let eol_adjustment = (col + 1 >= col('$')) endif " TLogVAR imode, eol_adjustment let mode = a:mode . eol_adjustment " TLogVAR 3, col('.') " TLogVAR mode " TLogDBG string(getline(line)) if bit != '' let @t = bit else let c = l[col - 1] let pos = '\%#' if c =~ '\s' let @t = '' " TLogDBG " 0 @t=". @t if !imode && !eol_adjustment norm! l endif elseif s:SearchKeyword(filetype, pos) if imode && eol_adjustment let d = col - col('.') else let d = col - col('.') + 1 endif " TLogVAR imode, eol_adjustment, d, col, col('.') if d > 0 exec 'silent norm! "td'. d .'l' else exec 'silent norm! "tdl' endif " TLogDBG " 1 @t='". @t ."'" elseif imode && !eol_adjustment silent norm! h"tdiw " TLogDBG " 2 @t='". @t ."'" else silent norm! "tdiw " TLogDBG " 3 @t='". @t ."'" endif endif " TLogDBG "#1". getline(line) let bit = @t if bit =~ '^\s\+$' let bit = '' endif " TLogDBG " 4 bit='". bit ."'" " TLogDBG string(getline(line)) if bit != '' && tskeleton#Bit(bit, mode) == 1 " call tlog#Debug("TSkeletonBit succeeded!") return 1 elseif (bit != '' || empty(default)) && s:BitMenu(bit, mode, filetype) " call tlog#Debug("s:BitMenu succeeded!") " TLogVAR mode, bit, default return 0 endif " TLogDBG "#2". getline(line) " TLogVAR bit " TLogVAR default let s:got_default_string = 0 " TLogDBG 'ExpandBit w0='. line('w0') " TLogDBG string(getline(line)) if s:InsertDefault(mode, bit, default) " TLogDBG 's:InsertDefault succeeded! '. line('w0') return 1 else " TLogDBG "#3". getline(line) " TLogDBG 'Last ressort' if s:got_default_string " TLogDBG 'got_default_string' " TLogDBG string(getline(line)) call s:InsertBitText(mode, bit) let success = 0 else " TLogDBG 'GetDefaultString' let [success, default_string] = s:GetDefaultString(bit, default) " TLogVAR success, default_string " TLogDBG string(getline(line)) call s:InsertBitText(mode, default_string) endif if !success echom "TSkeletonBit: Unknown bit '". bit ."'" endif " TLogVAR line, col0 " TLogDBG col('.') call winrestview(view) " TLogDBG 'ExpandBit restview '. line('w0') return success endif finally let @t = t call s:UnsetLine() let lazyredraw = &lazyredraw if unset_ft unlet g:tskelFiletype endif endtry endf function! s:KeywordRx(...) "{{{3 TVarArg ['quantifier', '\{-}'], ['filetype', ''] " TLogVAR filetype if empty(filetype) let filetype = s:Filetype() endif let rx = tlib#var#Get('tskelKeyword_'. filetype, 'bg', '\k\Q') " TLogVAR filetype, rx let rx = substitute(rx, '\(\\\)\@' call setpos('.', pos) if search('<+CURSOR+>', 'W') norm! cf> endif else let left = len(default_string) if col('.') == 1 let left -= 1 endif exec 'norm! '. left .'l' endif if s:IsInsertMode(a:mode) call cursor(line('.'), col('.') + 1) endif endif return success else return 0 endif endf function! s:AddDefaultCompletions(completions, bit, default) "{{{3 " TLogVAR a:default for [name, fn] in items(tlib#var#Get('tskel_completions', 'bg', {})) if has_key(a:default, name) call call(fn, [a:bit, a:completions]) " TLogVAR name, fn, len(a:completions) endif endfor return a:completions endf function! s:GetDefaultString(bit, default) "{{{3 " TLogVAR a:bit, a:default " Don't call this function twice in one go -- see tskeleton#ExpandBitUnderCursor(). let s:got_default_string = 1 let completions = {} call s:AddDefaultCompletions(completions, a:bit, a:default) if !empty(completions) " TLogDBG 'Process completions' let s:tskelQueryAcc = keys(completions) " call tlog#Debug(string(s:tskelQueryAcc)) let rv = s:Query("s:tskelQueryAcc|Select bit:") " TLogVAR rv return [!empty(rv), rv] endif if has_key(a:default, 'string') " TLogDBG 'Process string' " TLogVAR a:default.string return [1, a:bit . a:default.string] endif " TLogDBG "Fall back" " TLogVAR a:bit return [0, a:bit] endf function! tskeleton#Complete_use_omnifunc(bit, completions) "{{{3 " TLogDBG 'use_omnifunc' if !empty(&omnifunc) " TLogDBG 'use_omnicomplete' for w in tskeleton#GetCompletions(&omnifunc, a:bit) let [cname, mname] = tskeleton#PurifyBit(w) let a:completions[w] = {'text': w, 'menu': 'OmniComplete.'. mname, 'type': 'tskeleton'} endfor endif endf function! tskeleton#Complete_use_completefunc(bit, completions) "{{{3 if !empty(&completefunc) " TLogDBG 'use_completefunc' for w in tskeleton#GetCompletions(&completefunc, a:bit) let [cname, mname] = tskeleton#PurifyBit(w) let a:completions[w] = {'text': w, 'menu': 'CompleteFunc.'. mname, 'type': 'tskeleton'} endfor endif endfun function! tskeleton#Complete_scan_words(bit, completions) "{{{3 " TLogVAR a:bit " TLogDBG 'scan_tags saveview '. line('w0') let view = winsaveview() if !empty(a:bit) let kw = '\k\+' let rx = tlib#rx#Escape(a:bit) . kw " TLogVAR kw, rx norm! G$ let [lnum, col] = searchpos(rx, 'w') " TLogVAR lnum, col while lnum > 0 let subline = getline(lnum)[col - 1 : -1] let match = matchstr(subline, '^'. rx) if !empty(match) " TLogVAR subline, match let a:completions[match] = {'text': match, 'type': 'tskeleton'} endif norm! w " TLogVAR lnum, col, match, subline let [lnum, col] = searchpos(rx, 'W') endwh call winrestview(view) endif " TLogDBG 'scan_tags restview '. line('w0') endf function! tskeleton#Complete_scan_tags(bit, completions) "{{{3 " TLogDBG 'scan_tags' let tags = taglist('^'. tlib#rx#Escape(a:bit)) if !empty(tags) for tag in tags let a:completions[tag.name] = {'text': tag.name, 'type': 'tskeleton'} endfor endif endf function! tskeleton#GetCompletions(func, bit) "{{{3 let b:compl_context = getline('.')[0 : col('.')] . a:bit let completions = call(a:func, [0, a:bit]) " TLogVAR a:func, completions call map(completions, 'substitute(type(v:val) == 4 ? v:val.word : v:val, "($", "", "")') call filter(completions, 'v:val != a:bit') return completions endf " :display: tskeleton#Complete(findstart, base, ?default={}) " A function suitable for use as 'completefunc' or 'omnifunc'. " You have to accept a match with in order to trigger skeleton " expansion. See |popupmenu-keys|. function! tskeleton#Complete(findstart, base, ...) " TLogVAR a:findstart, a:base if a:findstart let pattern = s:KeywordRx() let line = strpart(getline('.'), 0, col('.') - 1) let start = match(line, pattern.'$') " TLogVAR pattern, line, start return start == -1 ? col('.') - 1 : start else let default = a:0 >= 1 ? a:1 : {} " TAssertType default, 'dictionary' let filetype = s:Filetype() let t = s:BitMenuEligible('complete', a:base, 'i', filetype) let setup_done = s:DidSetup(filetype) " TLogVAR len(t), setup_done if setup_done let completions = copy(g:tskelBits_{filetype}) " TLogVAR len(completions) call filter(completions, 'strpart(v:val.text, 0, len(a:base)) ==# a:base') " TLogVAR len(completions) if !empty(default) call s:AddDefaultCompletions(completions, a:base, default) endif " TLogVAR len(completions), completions for [bit, def] in items(completions) " TLogVAR bit, def " TAssert IsDictionary(def) call add(t, {'word': def['text'], 'abbr': bit}) endfor endif if len(t) > 0 let s:pum_complete_args = { \ 'pos': getpos('.'), \ 'eol': col('.') >= col('$'), \ 'view': winsaveview(), \ 'eligible': t, \ } " call tlog#Debug("s:pum_complete_args: ". string(s:pum_complete_args)) autocmd! tSkeleton CursorMoved,CursorMovedI,CursorHold,CursorHoldI autocmd tSkeleton CursorMoved,CursorMovedI,CursorHold,CursorHoldI call s:ExpandCompletion(s:pum_complete_args) endif " TAssert IsList(t) return t endif endf function! s:ExpandCompletion(args) "{{{3 " TLogVAR pumvisible() if !pumvisible() autocmd! tSkeleton CursorMoved,CursorMovedI,CursorHold,CursorHoldI " TLogVAR a:args.pos, bufnr('%'), col('.') if a:args.pos[0] == 0 || a:args.pos[0] == bufnr('%') let line = getline('.') let beg = a:args.pos[2] - 1 let end = col('.') - 1 let bit = strpart(line, beg, end) " TLogVAR line, beg, end, bit if index(a:args.eligible, bit) != -1 call tskeleton#ExpandBitUnderCursor("i") redraw endif endif endif endf function! s:TagSelect(chars, mode, tag_i) "{{{3 " TLogVAR a:chars, a:mode let chars = a:chars - s:InclusiveSelection() " TLogVAR chars if a:mode == 'd' let cp = col('.') + chars " TLogDBG 'col.='. col('.') .' colp='. cp .' col$='. col('$') if cp >= col('$') if &ve =~ 'all' let correction = '$l' else let correction = '$' endif else let correction = '' endif " TLogVAR correction exec 'norm! d'. chars .'l'.correction call s:SetLastTagInfo(a:tag_i) else " TLogDBG 'norm! v'. chars .'l' exec 'norm! v'. chars .'l' call s:SetLastTagInfo(a:tag_i) call s:SelectTagMode() endif endf function! s:InclusiveSelection() "{{{3 return &selection =~ '^[io]' ? 1 : 0 endf function! s:SelectTagMode() "{{{3 if g:tskelSelectTagMode[0] == 's' exec "norm! \" endif endf " :nodoc: function! tskeleton#GoToNextTag() "{{{3 let [rx, x, tag_i] = s:SearchNextTagRx() " TLogVAR rx, x if x > 0 let lc = exists('b:tskelLastCol') ? b:tskelLastCol : col('.') " TLogVAR lc let l = strpart(getline(x), lc - 1) " TLogVAR l let ms = matchstr(l, rx) " TLogVAR ms let ml = len(ms) " TLogVAR ml if ms =~# printf('^\(%s\)$', g:tskelMarkerExtra) " TLogVAR "extra" call s:TagSelect(ml, 'v', 0) else if ml == 4 " TLogVAR "4" call s:TagSelect(ml + s:InclusiveSelection(), 'd', 0) else let defrx = tskeleton#WrapMarker('.\{-}/\zs.\{-}\ze', 'rx') " TLogVAR ms, defrx if ms =~ defrx let default = matchstr(ms, defrx) let ldefault = len(default) " TLogVAR default, ldefault " TLogVAR col('.'), getline('.') let vcol = virtcol('.') call s:TagSelect(ml + s:InclusiveSelection(), 'd', 0) " TLogVAR col('.'), getline('.') let shift = s:Eol('i', lc) ? 0 : -1 " TLogVAR getline('.'), ms, ml, lc, col('.'), col('$'), shift call tlib#buffer#InsertText(default, {'pos': 's', 'shift': shift}) " TLogVAR col('.'), getline('.') " TLogVAR vcol, col('.'), ldefault exec 'norm!' vcol .'|v'. ldefault .'l' call s:SetLastTagInfo(tag_i) call s:SelectTagMode() else call s:TagSelect(ml, 'v', tag_i) endif endif endif endif endf function! s:SearchNextTagRx() "{{{3 try let rx = tskeleton#WrapMarker('[1-9]\(/.\{-}\)\?', 'rx') if search(rx, 'cnw') if exists('w:tskel_last_tag') let is = range(w:tskel_last_tag.i + 1, 9) + range(1, w:tskel_last_tag.i) else let is = range(1, 9) endif " TLogVAR is norm! gg0 for i in is let rxi = tskeleton#WrapMarker(i .'\(/.\{-}\)\?', 'rx') let x = search(rxi, 'c') if x " TLogVAR i, rx let rx = rxi return [rx, x, i] endif endfor endif let rx = '\('. g:tskelMarkerExtra .'\|'. tskeleton#WrapMarker('') .'\|'. tskeleton#TagRx() .'\)' let x = search(rx, 'c') " TLogVAR rx return [rx, x, 0] finally if exists('#stakeholders') silent! doau stakeholders CursorMoved endif endtry endf function! s:SetLastTagInfo(tag_i) "{{{3 if a:tag_i > 0 let w:tskel_last_tag = {'pos': getpos('.'), 'i': a:tag_i} augroup tSkeleton_last_tag autocmd! autocmd CursorMoved,CursorMovedI call s:RemoveLastTagInfo() augroup END elseif exists('w:tskel_last_tag') unlet! w:tskel_last_tag endif endf function! s:RemoveLastTagInfo() "{{{3 unlet! w:tskel_last_tag autocmd! tSkeleton_last_tag CursorMoved,CursorMovedI endf let s:syn_clusters = {} function! tskeleton#Placeholders(line1, line2) "{{{3 if s:tskel_use_placeholders if !exists("b:tskelHighlight") if !empty(g:tskelMarkerHiGroup) let cchar = get(g:tskeleton#conceal_cchar, &enc, get(g:tskeleton#conceal_cchar, '_', '')) let conceal = empty(cchar) ? '' : (' conceal cchar='. cchar) " TLogVAR &enc, cchar, conceal exec 'syntax match TSkelPlaceHolder /'. escape(tskeleton#WrapMarker('.\{-}', 'rx'), '/') .'/'. conceal exec 'hi def link TSkelPlaceHolder '. g:tskelMarkerHiGroup if has_key(s:syn_clusters, &filetype) let syn = s:syn_clusters[&filetype] else let syn = tlib#cmd#OutputAsList('syn list') call filter(syn, 'v:val =~ ''^\w\+\s\+cluster=''') " TLogVAR syn call map(syn, 'matchstr(v:val, ''^\w\+'')') let filetype = empty(&filetype) ? "no filetype" : &filetype let s:syn_clusters[filetype] = syn endif " TLogVAR syn for syncluster in syn exec 'syn cluster' syncluster 'add=TSkelPlaceHolder' endfor endif let b:tskelHighlight = 1 endif " call s:UseStakeholders(a:line1, a:line2) endif endf function! s:UseStakeholders(line1, line2) "{{{3 if g:tskeleton#enable_stakeholders " TLogVAR a:line1, a:line2 if a:line1 > 0 && a:line2 >= a:line1 call stakeholders#EnableInRange(a:line1, a:line2) else call stakeholders#EnableBuffer() endif endif endf function! tskeleton#LateExpand() "{{{3 let l = getline('.') let lc = col('.') - 1 let left = tlib#var#Get('tskelMarkerLeft', 'bg') let right = tlib#var#Get('tskelMarkerRight', 'bg') while strpart(l, lc, len(left)) != left " TLogVAR lc " TLogDBG strpart(l, lc, 2) let lc -= 1 if lc <= -1 || strpart(l, lc, len(right)) == right throw "TSkeleton: No tag under cursor" endif endwh let l = strpart(l, lc) let me = matchend(l, tskeleton#WrapMarker('.\{-}', 'rx')) if me < 0 throw "TSkeleton: No tag under cursor" else let lp = substitute(strpart(l, 2, me - 4), '\W', '_', 'g') let v = '' if exists('*TSkeletonCB_'. lp) let v = TSkeletonCB_{lp}() elseif exists('*TSkeleton_'. lp) let v = TSkeleton_{lp}() else throw 'TSkeleton: No callback defined for '. lp .' (TSkeletonCB_'. lp .')' endif if v != '' call cursor(0, lc + 1) exec 'norm! d'. me .'li'. v return endif endif endf " :nodoc: function! tskeleton#IncreaseRevisionNumber() "{{{3 let rev = exists("b:revisionRx") ? b:revisionRx : g:tskelRevisionMarkerRx let ver = exists("b:versionRx") ? b:versionRx : g:tskelRevisionVerRx let pos = getpos('.') let rs = @/ exec '%s/'.rev.'\('.ver.'\)*\zs\(-\?\d\+\)/\=(submatch(g:tskelRevisionGrpIdx) + 1)/e' let @/ = rs call setpos('.', pos) endf " :nodoc: function! tskeleton#CleanUpBibEntry() "{{{3 exec printf('''{,''}s/^.*%s.*\n//e', tskeleton#WrapMarker('.\{-}', 'rx')) if exists('*TSkeletonCleanUpBibEntry_User') call TSkeletonCleanUpBibEntry_User() endif endf " :display: tskeleton#Repeat(n, string, ?sep="\n") function! tskeleton#Repeat(n, string, ...) "{{{3 let sep = a:0 >= 1 ? a:1 : "\n" let rv = a:string let n = a:n - 1 while n > 0 let rv = rv . sep . a:string let n = n - 1 endwh return rv endf function! tskeleton#InsertTable(rows, cols, rowbeg, rowend, celljoin) "{{{3 let y = a:rows let r = '' while y > 0 let x = a:cols let r = r . a:rowbeg while x > 0 if x == a:cols let r = r .tskeleton#WrapMarker('CELL') else let r = r . a:celljoin .tskeleton#WrapMarker('CELL') end let x = x - 1 endwh let r = r. a:rowend if y > 1 let r = r ."\n" endif let y = y - 1 endwh return r endf function! tskeleton#HyperComplete_query(mode, default) "{{{3 let col = col('.') - 1 if s:IsInsertMode(a:mode) && col > 0 let col -= 1 endif let pre = getline('.')[0 : col] " TLogVAR col, pre if empty(pre) || pre =~ '\s$' " TLogVAR a:default let view = winsaveview() exec 'norm! '. a:default call winrestview(view) else " TLogVAR a:mode let w:tskeleton_hypercomplete = 1 try let filetype = s:Filetype() call tskeleton#ExpandBitUnderCursor(a:mode, '', tlib#var#Get('tskelHyperComplete_'. filetype, 'bg', tlib#var#Get('tskelHyperComplete', 'bg', {}))) finally unlet! w:tskeleton_hypercomplete endtry endif endf function! tskeleton#HyperComplete_pum(mode, default) "{{{3 let start = tskeleton#Complete(1, "") let pos = getpos('.') let line = pos[1] let col = pos[2] let text0 = getline(line) let base0 = strpart(text0, start) let kwrx = s:KeywordRx('\+') let kwrx = substitute(kwrx, '\(\\\)\@''') for f in sort(fnl) let fn = matchstr(f, '^.\{-}\ze(') let fr = substitute(f, '(\(.\{-}\))$', '\=tskeleton#ReplacePrototypeArgs(submatch(1), ''\V...'')', "g") " TLogDBG fn ." -> ". fr " let a:dict[fn] = {'text': fr, 'menu': 'Function.'. fn, 'type': 'tskeleton'} let a:dict[fn] = {'text': fr, 'type': 'tskeleton'} endfor endf autoload/tskeleton/snippets.vim [[[1 186 " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Revision: 84 if &cp || exists("loaded_tskeleton_snippets_autoload") finish endif let loaded_tskeleton_snippets_autoload = 1 if !exists('g:tskeleton#snippets#force') " If true, allow snippets to overwrite other skeletons. let g:tskeleton#snippets#force = 0 "{{{2 endif function! tskeleton#snippets#Initialize() "{{{3 if !exists('#tSkeleton#BufWritePost#*/snippets/*.snippets') autocmd tSkeleton BufWritePost */snippets/*.snippets call s:UpdateSnippetDef(expand('%:t:r')) endif endf function! tskeleton#snippets#FiletypeBits(dict, type) "{{{3 " TLogVAR a:type " TAssert IsDictionary(a:dict) " TAssert IsString(a:type) let type = a:type == 'general' ? '_' : a:type let bf = split(globpath(&rtp, 'snippets/'. type .'.snippets'), '\n') let bf = map(bf, 'fnamemodify(v:val, ":p")') if exists('g:snippets_dir') " TLogVAR g:snippets_dir let sfiles = split(globpath(g:snippets_dir, 'snippets/'. type .'.snippets'), '\n') " TLogVAR sfiles for sfile in sfiles let sfile = fnamemodify(sfile, ':p') if index(bf, sfile) == -1 call add(bf, sfile) endif endfor endif " let cx = tskeleton#CursorMarker('rx') " let cm = tskeleton#CursorMarker() for f in bf " TLogVAR f if !isdirectory(f) && filereadable(f) let cache_name = tskeleton#MaybePathshorten(f) let cfile = tlib#cache#Filename('tskel_snip', tlib#url#Encode(cache_name), 1) let ftime = getftime(f) let snippets = tlib#cache#Value(cfile, 'tskeleton#snippets#Generator', ftime, [f]) " TLogVAR snippets call extend(a:dict, snippets, g:tskeleton#snippets#force ? 'force' : 'keep') endif endfor endf function! tskeleton#snippets#Generator(filename) "{{{3 let snippets = {} let lines = readfile(a:filename) let def = {} let indent = '' let state = 'find' let max = len(lines) let lnum = 0 while lnum < max let line = lines[lnum] " TLogVAR state, lnum, line if state == 'find' if line =~ '^#' " ignore elseif line =~ '^snippet\s' let name = matchstr(line, '^snippet\s\+\zs.\+$') " let mname = escape(name, '. \') let mname = escape(name, '.') let def = { \ 'cname': name, \ 'menu': 'Snippets.'. mname, \ 'mname': mname, \ 'text': '', \ 'type': 'tskeleton', \ 'meta': {}, \ 'preprocess': 'tskeleton#snippets#Preprocess', \ 'bitfile': a:filename \ } let state = 'PARSE' else " shouldn't be here endif elseif state ==? 'parse' if line =~ '^\s' || empty(line) if state ==# 'PARSE' " let s:first_pos = 1 let state = 'parse' let indent = matchstr(line, '^\s\+') endif let pre = empty(def.text) ? '' : "\n" let body = s:ConvertSnippet(strpart(line, strlen(indent))) let def.text .= pre . body else if !empty(def) " TLogVAR def let snippets[def.cname] = def endif let state = 'find' let lnum -= 1 endif endif let lnum += 1 endwh if !empty(def) " TLogVAR def let snippets[def.cname] = def endif " TLogVAR snippets return snippets endf function! s:ConvertSnippet(line) "{{{3 " TLogVAR a:line let line = substitute(a:line, \ '\$\(\([1-9]\)$\|\([1-9]\)\|{\([1-9]\)}$\|{\([1-9]\)}\|{\([1-9]:[^}]\+\)}$\|{\([1-9]:[^}]\+\)}\)', \ '\=s:ConvertPos(a:line, submatch(2), submatch(3), submatch(4), submatch(5), submatch(6), submatch(7))', \ 'g') return line endf function! s:ConvertEval(arg) "{{{3 return printf('<+call:eval(%s)+>', string(a:arg)) endf function! Filename(...) "{{{3 let bufnr = tskeleton#GetDestBuffer() let rv = bufnr == -1 ? expand('%:t:r') : fnamemodify(bufname(bufnr), ':t:r') if a:0 > 0 if !empty(a:1) let rv = substitute(a:1, '\$1', escape(rv, '\&~'), 'g') elseif a:0 >= 2 let rv = a:2 endif endif return rv endf function! s:ConvertPos(line, simpleeol, simple, exteol, ext, extnoteeol, extnote) "{{{3 " TLogVAR a:simpleeol, a:simple, a:exteol, a:ext, a:extnoteeol, a:extnote if !empty(a:simpleeol) " return '<++>' return printf('<+%s+>', s:Name(a:simple)) elseif !empty(a:simple) return printf('<+%s+>', s:Name(a:simple)) elseif !empty(a:exteol) " return '<++>' return printf('<+%s+>', s:Name(a:exteol)) elseif !empty(a:ext) return printf('<+%s+>', s:Name(a:ext)) elseif !empty(a:extnoteeol) " return printf('<+/%s+>', matchstr(a:extnoteeol, '^\d\+:\zs.*$')) return printf('<+%s/%s+>', s:Name(matchstr(a:extnoteeol, '^\d\+')), matchstr(a:extnoteeol, '^\d\+:\zs.*$')) elseif !empty(a:extnote) return printf('<+%s/%s+>', s:Name(matchstr(a:extnote, '^\d\+')), matchstr(a:extnote, '^\d\+:\zs.*$')) else throw "tskeleton/Snippets: Internal error when parsing ". a:line endif endf function! s:Name(num) "{{{3 if a:num == 1 return 'CURSOR' else return a:num endif endf function! tskeleton#snippets#Preprocess(text) "{{{3 sandbox let text = substitute(a:text, '`\([^`]\+\)`', '\=eval(submatch(1))', 'g') return text endf autoload/tskeleton/tags.vim [[[1 129 " tags.vim " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 2007-09-15. " @Last Change: 2012-10-25. " @Revision: 0.0.17 if &cp || exists("loaded_tskeleton_tags_autoload") finish endif let loaded_tskeleton_tags_autoload = 1 let s:tag_defs = {} function! tskeleton#tags#Initialize() "{{{3 endf function! s:SortBySource(a, b) let ta = s:sort_tag_defs[a:a] let tb = s:sort_tag_defs[a:b] let fa = ta.source let fb = tb.source if fa == fb return ta.menu == tb.menu ? 0 : ta.menu > tb.menu ? 1 : -1 else return fa > fb ? 1 : -1 endif endf function! s:SortByFilename(tag1, tag2) let f1 = a:tag1['filename'] let f2 = a:tag2['filename'] return f1 == f2 ? 0 : f1 > f2 ? 1 : -1 endf function! tskeleton#tags#BufferBits(dict, filetype) "{{{3 " TAssert IsDictionary(a:dict) " TAssert IsString(a:filetype) " TLogVAR a:filetype if exists('*tskeleton#tags#Process_'. a:filetype) let td_id = join(map(tagfiles(), 'fnamemodify(v:val, ":p")'), '\n') " TLogVAR td_id if !empty(td_id) let tag_defs = get(s:tag_defs, td_id, {}) " TLogDBG len(tag_defs) if empty(tag_defs) echom 'tSkeleton: Building tags menu for '. expand('%') let tags = taglist('.') call sort(tags, 's:SortByFilename') call filter(tags, 'tskeleton#tags#Process_{a:filetype}(tag_defs, v:val)') let s:tag_defs[td_id] = tag_defs echo redraw endif call extend(a:dict, tag_defs, 'keep') let menu_prefix = tlib#var#Get('tskelMenuPrefix_tags', 'bg') if !empty(menu_prefix) let s:sort_tag_defs = tag_defs let tagnames = sort(keys(tag_defs), 's:SortBySource') " TLogVAR tagnames " call filter(tagnames, 'tskeleton#NewBufferMenuItem(b:tskelBufferMenu, v:val)') call filter(tagnames, 'tskeleton#NewBufferMenuItem(b:tskelBufferMenu, v:val)') endif endif endif endf function! tskeleton#tags#Process_vim(dict, tag) return s:ProcessTag_functions_with_parentheses('f', a:dict, a:tag, '\V...') endf function! tskeleton#tags#Process_ruby(dict, tag) return s:ProcessTag_functions_with_parentheses('f', a:dict, a:tag, '\*\a\+\s*$') endf function! tskeleton#tags#Process_c(dict, tag) return s:ProcessTag_functions_with_parentheses('f', a:dict, a:tag, '') endf function! tskeleton#tags#Process_java(dict, tag) return s:ProcessTag_functions_with_parentheses('f', a:dict, a:tag, '\V...') endf function! s:ProcessTag_functions_with_parentheses(kinds, dict, tag, restargs) if empty(a:kinds) || stridx(a:kinds, a:tag['kind']) != -1 let source0 = fnamemodify(a:tag['filename'], ':p') let source = source0 let xname = a:tag['name'] if has_key(a:tag, 'signature') let args0 = a:tag.signature else let args0 = matchstr(a:tag['cmd'], '(.\{-})') endif let args = matchstr(args0, '(\zs.\{-}\ze)') let bname0 = xname . args0 .'@' let bname = bname0 . fnamemodify(source, ':t') if has_key(a:dict, bname) if fnamemodify(get(a:dict[bname], 'source', ''), ':p') == source0 return '' else let bname = bname0 . source endif endif let xname .= tskeleton#ReplacePrototypeArgs(args, a:restargs) let a:dict[bname] = {'text': xname, 'source': source, 'type': 'tskeleton'} let menu_prefix = tlib#var#Get('tskelMenuPrefix_tags', 'bg') if !empty(menu_prefix) let smenu = join(map(split(source, '[\/]'), 'escape(v:val, ".")'), '.') let mname = menu_prefix . smenu .'.'. escape(bname, '.') " TLogDBG xname .' -- '. xname let a:dict[bname]['menu'] = mname endif return bname endif return '' endf autoload/tskeleton/mini.vim [[[1 29 " mini.vim " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 2007-09-15. " @Last Change: 2012-10-24. " @Revision: 0.0.18 if &cp || exists("loaded_tskeleton_mini_autoload") "{{{2 finish endif let loaded_tskeleton_mini_autoload = 1 function! tskeleton#mini#Initialize() "{{{3 endf function! tskeleton#mini#FiletypeBits(dict, type) "{{{3 " TLogVAR a:dict, a:type let files = findfile('.tskelmini', expand('%:p:h') .';', -1) " TLogVAR files for file in reverse(files) " TLogVAR file call tskeleton#FetchMiniBits(a:dict, '', file, 1) endfor endf autoload/tskeleton/abbreviations.vim [[[1 71 " abbreviations.vim " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 2007-09-15. " @Last Change: 2009-08-11. " @Revision: 0.0.62 if &cp || exists("loaded_tskeleton_abbreviations_autoload") finish endif let loaded_tskeleton_abbreviations_autoload = 1 function! tskeleton#abbreviations#Reset() "{{{3 let s:abbrevs = tlib#cmd#OutputAsList('abbrev') endf function! tskeleton#abbreviations#Initialize() "{{{3 call tskeleton#abbreviations#Reset() endf function! tskeleton#abbreviations#GetAbbreviations() "{{{3 if !exists('s:abbrev') call tskeleton#abbreviations#Reset() endif return s:abbrev endf function! tskeleton#abbreviations#BufferBits(dict, filetype) "{{{3 call filter(s:abbrevs, 'v:val =~ ''^[i!]''') let rx = '^\(.\)\s\+\(\S\+\)\s\+\(.\+\)$' for abbr in sort(s:abbrevs) let matches = matchlist(abbr, rx) " TLogVAR abbr, rx, matches let name = matches[2] " TLogVAR name " TLogDBG has_key(a:dict, name.g:tskelAbbrevPostfix) let text = matches[3] if text !~ printf(tlib#rx#Escape(tskeleton#ExpandedAbbreviationTemplate()), '.\{-}') let a:dict[name] = { \ 'text': text, \ 'abbrev_type': matches[1], \ 'abbrev': '', \ 'menu': 'Abbreviation.'. escape(name, '.\'), \ 'type': 'abbreviations' \ } endif endfor endf function! tskeleton#abbreviations#Retrieve(bit, indent, ft) "{{{3 let def = tskeleton#BitDef(a:bit) let text = def.text " let text .= tskeleton#CursorMarker() " TLogVAR a:bit, a:def " if text[0] == '@' " exec 'norm! i'. text[1:-1] " else " exec 'norm! i'. text " endif exec 'norm i'. a:bit call tlib#buffer#InsertText0(tskeleton#CursorMarker()) return line('.') endf autoload/tskeleton/omnicomplete.vim [[[1 26 " omnicomplete.vim " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 2009-08-23. " @Last Change: 2010-02-26. " @Revision: 0.0.15 let s:save_cpo = &cpo set cpo&vim function! tskeleton#omnicomplete#Initialize() "{{{3 endf function! tskeleton#omnicomplete#FiletypeBits(dict, type) "{{{3 " TAssert IsDictionary(a:dict) " TAssert IsString(a:type) call tskeleton#Complete_use_omnifunc('', a:dict) endf let &cpo = s:save_cpo unlet s:save_cpo autoload/tskeleton/skeleton.vim [[[1 106 " skeleton.vim " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 2007-09-15. " @Last Change: 2012-10-24. " @Revision: 0.0.58 if &cp || exists("loaded_tskeleton_skeleton_autoload") finish endif let loaded_tskeleton_skeleton_autoload = 1 function! tskeleton#skeleton#Initialize() "{{{3 endf function! tskeleton#skeleton#FiletypeBits(dict, type) "{{{3 " TLogVAR a:type " TAssert IsDictionary(a:dict) " TAssert IsString(a:type) call tskeleton#FetchMiniBits(a:dict, tskeleton#BitsPath(), a:type .'.txt', 0) call s:ScanPath(a:dict, a:type, tskeleton#BitsPath()) endf function! tskeleton#skeleton#BufferBits(dict, type) "{{{3 " TLogVAR a:type if !exists('b:tskel_bufferbits_path') let b:tskel_bufferbits_path = '' for dir0 in g:tskelLocalBitsDirs let dirs1 = finddir(dir0, '.;', -1) " TLogVAR dirs1 let dirs1 = map(dirs1, 'escape(fnamemodify(v:val, ":p"), ",")') let dirs = join(dirs1, ',') if empty(b:tskel_bufferbits_path) let b:tskel_bufferbits_path = dirs else let b:tskel_bufferbits_path .= ','. dirs endif endfor endif if !empty(b:tskel_bufferbits_path) call s:ScanPath(a:dict, a:type, b:tskel_bufferbits_path) endif endf function! s:ScanPath(dict, type, path) "{{{3 let bf = s:GlobBits(a:path, a:type, 2) " let cx = tskeleton#CursorMarker('rx') " let cm = tskeleton#CursorMarker() for f in bf " TLogVAR f if !isdirectory(f) && filereadable(f) let cache_name = tskeleton#MaybePathshorten(f) let cfile = tlib#cache#Filename('tskel_skel', tlib#url#Encode(cache_name), 1) let ftime = getftime(f) let bitdef = tlib#cache#Value(cfile, 'tskeleton#skeleton#Generator', ftime, [f]) " TLogVAR bitdef let a:dict[bitdef.cname] = bitdef endif endfor endf function! tskeleton#skeleton#Generator(filename) "{{{3 let fname = fnamemodify(a:filename, ":t") let [cname, mname] = tskeleton#PurifyBit(fname) " TLogVAR cname let body = join(readfile(a:filename), "\n") let [body, meta] = tskeleton#ExtractMeta(body) " if body !~ cx " let body .= cm " endif if has_key(meta, 'menu') && !empty(meta.menu) let mname = meta.menu endif return {'cname': cname, 'text': body, 'menu': mname, 'meta': meta, 'bitfile': a:filename, 'type': 'tskeleton'} endf " s:GlobBits(path, ?mode=1) function! s:GlobBits(path, type, ...) "{{{3 let mode = a:0 >= 1 ? a:1 : 1 let pt = a:type .'/*' let rvs = globpath(a:path, pt) let rvs = substitute(rvs, '\\', '/', 'g') let rv = sort(split(rvs, "\n")) let stop_rx = tlib#var#Get('tskelBitsIgnore', 'bg') if !empty(stop_rx) call filter(rv, 'v:val !~ stop_rx') endif if mode == 0 call map(rv, 'fnamemodify(v:val, ":t")') elseif mode == 1 call map(rv, 'tskeleton#PurifyBit(fnamemodify(v:val, ":t"))[0]') elseif mode == 2 else echoerr 'tSkeleton: Unknown mode: '. mode endif " TAssert IsList(rv) return rv endf autoload/tskeleton/completefunc.vim [[[1 26 " completefunc.vim " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 2009-08-23. " @Last Change: 2010-02-26. " @Revision: 0.0.12 let s:save_cpo = &cpo set cpo&vim function! tskeleton#completefunc#Initialize() "{{{3 endf function! tskeleton#completefunc#FiletypeBits(dict, type) "{{{3 " TAssert IsDictionary(a:dict) " TAssert IsString(a:type) call tskeleton#Complete_use_completefunc('', a:dict) endf let &cpo = s:save_cpo unlet s:save_cpo syntax/tskeleton.vim [[[1 52 " tskeleton.vim " @Author: Tom Link (micathom AT gmail com?subject=vim) " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 30-Dez-2003. " @Last Change: 2009-02-15. " @Revision: 0.493 if version < 600 syntax clear elseif exists("b:current_syntax") finish endif let s:tskel_filetype=expand("%:p:h:t") if s:tskel_filetype != 'tskeleton' try exec "runtime! syntax/". s:tskel_filetype .".vim" unlet b:current_syntax catch endtry endif if s:tskel_filetype == 'vim' syn region tskeletonProcess matchgroup=tskeletonProcessMarker \ start='^\s*<\z(tskel:[a-z_:]\+\)>\s*$' end='^\s*\s*$' else syntax include @Vim syntax/vim.vim syn region tskeletonProcess matchgroup=tskeletonProcessMarker \ start='^\s*<\z(tskel:[a-z_:]\+\)>\s*$' end='^\s*\s*$' \ contains=@Vim endif unlet s:tskel_filetype " 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_tskeleton_syntax_inits") if version < 508 let did_tskeleton_syntax_inits = 1 " :nodoc: command! -nargs=+ HiLink hi link else " :nodoc: command! -nargs=+ HiLink hi def link endif HiLink tskeletonProcessMarker Statement delcommand HiLink endif