[SCM] Lisaac compiler branch, master, updated. a6ea11745086a163c36945f4592c146a27486d6b
Xavier Oswald
x.oswald at free.fr
Mon Nov 10 20:39:20 UTC 2008
The following commit has been merged in the master branch:
commit 6003ff2ba05d0cb0a05cf94834744a7a0ed3350e
Author: Xavier Oswald <x.oswald at free.fr>
Date: Mon Nov 10 21:38:43 2008 +0100
* Add JPTemplate support for vim
diff --git a/Changelog b/Changelog
index e3d94fb..9f79308 100644
--- a/Changelog
+++ b/Changelog
@@ -3,6 +3,7 @@ Version 0.14 :
[Xavier Oswald]
* New vim syntax coloration file (2008/11/07)
* Update default vimrc (2008/11/06)
+ * Add JPTemplate support for vim (2008/11/10)
[Benoit Sonntag]
* Lip project path Makefile
diff --git a/editor/vim/jptemplate/lisaac/do_while b/editor/vim/jptemplate/lisaac/do_while
new file mode 100644
index 0000000..a5ba3ce
--- /dev/null
+++ b/editor/vim/jptemplate/lisaac/do_while
@@ -0,0 +1,3 @@
+{
+ ${cursor}
+}.do_while {${test expression}};
diff --git a/editor/vim/jptemplate/lisaac/for b/editor/vim/jptemplate/lisaac/for
new file mode 100644
index 0000000..9dfcf4b
--- /dev/null
+++ b/editor/vim/jptemplate/lisaac/for
@@ -0,0 +1,3 @@
+${initializer expression:0}.to (${loop test expression}) do { ${iterator:i}:INTEGER;
+ ${cursor}
+};
diff --git a/editor/vim/jptemplate/lisaac/for_step b/editor/vim/jptemplate/lisaac/for_step
new file mode 100644
index 0000000..eadea7a
--- /dev/null
+++ b/editor/vim/jptemplate/lisaac/for_step
@@ -0,0 +1,3 @@
+${initializer expression:0}.to (${loop test expression}) by(${step}) do { ${iterator:i}:INTEGER;
+ ${cursor}
+};
diff --git a/editor/vim/jptemplate/lisaac/if b/editor/vim/jptemplate/lisaac/if
new file mode 100644
index 0000000..f05210d
--- /dev/null
+++ b/editor/vim/jptemplate/lisaac/if
@@ -0,0 +1,3 @@
+(${test expression}).if {
+ ${cursor}
+};
diff --git a/editor/vim/jptemplate/lisaac/if_else b/editor/vim/jptemplate/lisaac/if_else
new file mode 100644
index 0000000..3660a1a
--- /dev/null
+++ b/editor/vim/jptemplate/lisaac/if_else
@@ -0,0 +1,5 @@
+(${test expression}).if {
+ ${cursor}
+} else {
+
+};
diff --git a/editor/vim/jptemplate/lisaac/if_elseif b/editor/vim/jptemplate/lisaac/if_elseif
new file mode 100644
index 0000000..b0d7a48
--- /dev/null
+++ b/editor/vim/jptemplate/lisaac/if_elseif
@@ -0,0 +1,5 @@
+(${test expression1}).if {
+ ${cursor}
+}.elseif {${test expression2}} then {
+
+};
diff --git a/editor/vim/jptemplate/lisaac/while_do b/editor/vim/jptemplate/lisaac/while_do
new file mode 100644
index 0000000..7edb921
--- /dev/null
+++ b/editor/vim/jptemplate/lisaac/while_do
@@ -0,0 +1,3 @@
+{${test expression}}.while_do {
+ ${cursor}
+};
diff --git a/editor/vim/plugin/jptemplate.vim b/editor/vim/plugin/jptemplate.vim
new file mode 100644
index 0000000..9833ab2
--- /dev/null
+++ b/editor/vim/plugin/jptemplate.vim
@@ -0,0 +1,369 @@
+" jptemplate.vim:
+"
+" A simple yet powerful interactive templating system for VIM.
+"
+" Version 1.5 (released 2008-07-08).
+"
+" Copyright (c) 2008 Jannis Pohlmann <jannis at xfce.org>.
+"
+" This program is free software; you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation; either version 2 of the License, or (at
+" your option) any later version.
+"
+" This program is distributed in the hope that it will be useful, but
+" WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+" General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program; if not, write to the Free Software
+" Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+" MA 02111-1307 USA
+
+
+" Reserved variable names
+let s:reservedVariables = ['date','shell','interactive_shell']
+
+" Variable value history
+let s:rememberedValues = {}
+
+" Characters to be escaped before the substitute() call
+let s:escapeCharacters = '&~\'
+
+
+function! jp:Initialize ()
+
+ " List for default configuration
+ let defaults = []
+
+ " Default configuration values
+ call add (defaults, ['g:jpTemplateDir', $HOME . '/.vim/jptemplate'])
+ call add (defaults, ['g:jpTemplateKey', '<C-Tab>'])
+ call add (defaults, ['g:jpTemplateDateFormat', '%Y-%m-%d'])
+ call add (defaults, ['g:jpTemplateDefaults', {}])
+ call add (defaults, ['g:jpTemplateVerbose', 0])
+
+ " Set default configuration for non-existent variables
+ for var in filter (defaults, '!exists (v:val[0])')
+ exec 'let ' . var[0] . ' = ' . string (var[1])
+ endfor
+
+endfunction
+
+
+function! jp:GetTemplateInfo ()
+
+ " Prepare info dictionary
+ let info = {}
+
+ " Get part of the line before the cursor
+ let part = getline ('.')[0 : getpos ('.')[2]-1]
+
+ " Get start and end position of the template name
+ let info['start'] = match (part, '\(\w*\)$')
+ let info['end'] = matchend (part, '\(\w*\)$')
+
+ " Get template name
+ let info['name'] = part[info['start'] : info['end']]
+
+ " Throw exception if no template name could be found
+ if empty (info['name'])
+ throw 'No template name found at cursor'
+ endif
+
+ " Determine directory to load the template from (skip empty directories;
+ " each directory may override the ones before)
+ for dir in filter ([ 'general', &ft ], '!empty (v:val)')
+ let filename = g:jpTemplateDir .'/'. dir .'/'. info['name']
+ if filereadable (filename)
+ let info['filename'] = filename
+ endif
+ endfor
+
+ " Throw exception if the template file does not exist in any of these
+ " directories (or is not readable)
+ if !has_key (info, 'filename')
+ throw 'Template file not found'
+ endif
+
+ " Determine indentation
+ let info['indent'] = matchstr (part, '^\s\+')
+
+ " Return template name information
+ return info
+
+endfunction
+
+
+function! jp:ReadTemplate (name, filename)
+
+ " Try to read the template file and throw exception if that fails
+ try
+ return readfile (a:filename)
+ catch
+ throw 'Template "' . a:name . '" could not be found.'
+ endtry
+
+endfunction
+
+
+function! jp:UpdateCursorPosition (lines, endColumn)
+
+ " Define cursorPosition as the column to which the cursor is moved
+ let cursorPosition = -1
+
+ for cnt in range (0, a:lines)
+ " Search for ${cursor} in the current line
+ let str = getline (line ('.') + cnt)
+ let start = match (str, '${cursor}')
+ let end = matchend (str, '${cursor}')
+ let before = strpart (str, 0, start)
+ let after = strpart (str, end)
+
+ if start >= 0
+ " Remove ${cursor} and move the cursor to the desired position
+ call setline (line ('.') + cnt, before . after)
+ call cursor (line ('.') + cnt, start+1)
+
+ let cursorPosition = start
+
+ " We're done
+ break
+ endif
+ endfor
+
+ " Update cursor position in case no ${cursor} was found in the template
+ " and the resulting template was not empty
+ if cursorPosition == -1 && a:lines >= 0
+ if a:lines == 0
+ call cursor (line ('.'), a:endColumn + 1)
+ else
+ call cursor (line ('.') + a:lines, a:endColumn + 1)
+ endif
+ endif
+
+ " Return to insert mode (distinguish between 'in the middle of the line' and
+ " 'at the end of the line')
+ if col ('.') == len (getline ('.'))
+ startinsert!
+ else
+ startinsert
+ endif
+
+endfunction
+
+
+function! jp:ParseExpression (expr)
+
+ " Determine position of the separator between name and value
+ let valuepos = match (a:expr, ':')
+
+ " Extract name and value strings
+ let name = valuepos >= 0 ? strpart (a:expr, 0, valuepos) : a:expr
+ let value = valuepos >= 0 ? strpart (a:expr, valuepos + 1) : ''
+
+ " Return list with both strings
+ return [name, value]
+
+endfunction
+
+
+function! jp:EvaluateReservedVariable (name, value, variables)
+
+ let result = ''
+
+ if a:name == 'date'
+ let result = strftime (empty (a:value) ? g:jpTemplateDateFormat : a:value)
+ elseif a:name == 'shell'
+ if !empty (a:value)
+ let result = system (a:value)
+ endif
+ elseif a:name == 'interactive_shell'
+ let command = input ('interactive_shell: ', a:value)
+ if !empty (command)
+ let result = system (command)
+ endif
+ endif
+
+ return result
+
+endfunction
+
+
+function! jp:ExpandTemplate (info, template)
+
+ " Backup content before and after the template name
+ let before = strpart (getline ('.'), 0, a:info['start'])
+ let after = strpart (getline ('.'), a:info['end'])
+
+ " Merge lines of the template and then split them up again.
+ " This makes multi-line variable values possible
+ let mergedTemplate = split (join (a:template, "\n"), "\n")
+
+ " Define cnt as the number of inserted lines
+ let cnt = 0
+
+ " Remove template string if the resulting template is empty
+ if empty (mergedTemplate)
+ call setline (line ('.'), before . after)
+ call cursor (line ('.'), len (before) + 1)
+ let cnt = -1
+ else
+ " Insert template between before and after
+ for cnt in range (0, len (mergedTemplate) - 1)
+ if cnt == 0
+ call setline (line ('.'), before . mergedTemplate[cnt])
+ else
+ call append (line ('.') + cnt - 1, a:info['indent'] . mergedTemplate[cnt])
+ endif
+ if cnt == len (mergedTemplate) - 1
+ call setline (line ('.') + cnt, getline (line ('.') + cnt) . after)
+ endif
+ endfor
+ endif
+
+ " Define start and end columns of the template
+ let startColumn = len (before)
+ if empty (mergedTemplate)
+ let endColumn = startColumn
+ else
+ if cnt == 0
+ let endColumn = startColumn + len (mergedTemplate[0])
+ else
+ let endColumn = len (a:info['indent'] . mergedTemplate[len (mergedTemplate) - 1])
+ endif
+ endif
+
+ " Return number of inserted lines, start and end columns
+ return [cnt, startColumn, endColumn]
+
+endfunction
+
+
+function! jp:ProcessTemplate (info, template)
+
+ let matchpos = 0
+ let expressions = []
+ let variables = {}
+ let reserved = {}
+
+ " Make a string out of the template lines
+ let s:str = join (a:template, ' ')
+
+ " Detect all variable names of the template
+ while 1
+ " Find next variable start and end position
+ let start = match (s:str, '${[^{}]\+}', matchpos)
+ let end = matchend (s:str, '${[^{}]\+}', matchpos)
+
+ if start < 0
+ " Stop search if there is no variable left
+ break
+ else
+ " Extract variable expression (remove '${' and '}')
+ let expr = s:str[start+2 : end-2]
+
+ " Extract variable name and default value */
+ let [name, value] = jp:ParseExpression (expr)
+
+ if name == 'cursor'
+ " Skip the ${cursor} variable
+ elseif count (s:reservedVariables, name) > 0
+ let reserved[expr] = ''
+ else
+ " Only insert variables on their first appearance
+ if !has_key (variables, name)
+ " Add expression to the expression list
+ call add (expressions, expr)
+
+ " Set variable value to ''
+ let variables[name] = ''
+ endif
+
+ " Check whether local default value is defined or not
+ if empty (value)
+ " If not, check if variable value is empty
+ if empty (variables[name])
+ " If so, either set it to the last remembered value or the global
+ " default if it exists
+ if has_key (s:rememberedValues, name)
+ let variables[name] = s:rememberedValues[name]
+ elseif has_key (g:jpTemplateDefaults, name)
+ let variables[name] = g:jpTemplateDefaults[name]
+ endif
+ endif
+ else
+ " Use local default (first occurence in the template only)
+ let variables[name] = value
+ endif
+ endif
+
+ " Start next search at the end position of this expression
+ let matchpos = end
+ endif
+ endwhile
+
+ " Ask the user to enter values for all variables
+ for expr in expressions
+ let [name, value] = jp:ParseExpression (expr)
+ let variables[name] = input (name . ': ', variables[name])
+ let s:rememberedValues[name] = variables[name]
+ endfor
+
+ " Evaluate reserved variables
+ for expr in keys (reserved)
+ let [name, value] = jp:ParseExpression (expr)
+ let replacement = jp:EvaluateReservedVariable (name, value, variables)
+ let reserved[expr] = replacement
+ endfor
+
+ " Expand all variables (custom and reserved)
+ for index in range (len (a:template))
+ for expr in expressions
+ let [name, value] = jp:ParseExpression (expr)
+ let expr = '${' . name . '\(:[^{}]\+\)\?}'
+ let value = escape(variables[name], s:escapeCharacters)
+ let a:template[index] = substitute (a:template[index], expr, value, 'g')
+ endfor
+
+ for [expr, value] in items (reserved)
+ let expr = '${' . expr . '}'
+ let value = escape(value, s:escapeCharacters)
+ let a:template[index] = substitute (a:template[index], expr, value, 'g')
+ endfor
+ endfor
+
+ " Insert template into the code line by line
+ let [insertedLines, startColumn, endColumn] = jp:ExpandTemplate (a:info, a:template)
+
+ " Update the cursor position and return to insert mode
+ call jp:UpdateCursorPosition (insertedLines, endColumn)
+
+endfunction
+
+
+function! jp:InsertTemplate ()
+
+ try
+ " Detect bounds of the template name as well as the name itself
+ let info = jp:GetTemplateInfo ()
+
+ " Load the template file
+ let template = jp:ReadTemplate (info['name'], info['filename'])
+
+ " Do the hard work: Process the template
+ call jp:ProcessTemplate (info, template)
+ catch
+ " Inform the user about errors
+ echo g:jpTemplateVerbose ? v:exception . " (in " . v:throwpoint . ")" : v:exception
+ endtry
+
+endfunction
+
+
+" Initialize jptemplate configuration
+call jp:Initialize ()
+
+" Map keyboard shortcut to the template system
+exec 'imap ' . g:jpTemplateKey . ' <Esc>:call jp:InsertTemplate()<CR>'
diff --git a/install_lisaac.li b/install_lisaac.li
index c26d154..763d2d4 100644
--- a/install_lisaac.li
+++ b/install_lisaac.li
@@ -467,6 +467,8 @@ Section Private
} else {
ENVIRONMENT.execute_command "mkdir -p ~/.vim/syntax";
ENVIRONMENT.execute_command "mkdir -p ~/.vim/indent";
+ ENVIRONMENT.execute_command "mkdir -p ~/.vim/plugin";
+ ENVIRONMENT.execute_command "mkdir -p ~/.vim/jptemplate/lisaac";
// Syntax hilightning support
string_tmp.copy "cp -f editor/vim/syntax/lisaac.vim ~/.vim/syntax/";
@@ -492,6 +494,30 @@ Section Private
"OK.\n".print;
};
+ // JPTemplate plugin - A simple yet powerful interactive template system for VIM v1.5
+ string_tmp.copy "cp -f editor/vim/plugin/lisaac.vim ~/.vim/plugin/";
+ " `".print;
+ string_tmp.print;
+ "'\t".print;
+ (ENVIRONMENT.execute_command string_tmp != 0).if {
+ "\n Sorry, auto-install fail !\n\
+ \ You can read the `editor/vim/install_vim_plugin.sh' file.\n".print;
+ } else {
+ "OK.\n".print;
+ };
+
+ string_tmp.copy "cp -f editor/vim/jptemplate/lisaac/* ~/.vim/jptemplate/lisaac/";
+ " `".print;
+ string_tmp.print;
+ "'\t".print;
+ (ENVIRONMENT.execute_command string_tmp != 0).if {
+ "\n Sorry, auto-install fail !\n\
+ \ You can read the `editor/vim/install_vim_plugin.sh' file.\n".print;
+ } else {
+ "OK.\n".print;
+ };
+
+
// Install ~/.vimrc file
char := question
"\n Do you want to install the default configuration provided by lisaac \n\
--
Lisaac compiler
More information about the Lisaac-commits
mailing list