diff options
| author | Anton Bobov <abobov@gmail.com> | 2013-10-10 22:55:51 +0600 |
|---|---|---|
| committer | Anton Bobov <abobov@gmail.com> | 2013-10-10 22:55:51 +0600 |
| commit | 9356a267f4ff70ed2c41996a248f1ca90552bd89 (patch) | |
| tree | 81692c3e25b01cc877b6827bfb76caf79043806e | |
| parent | 758071194a0adf8a6ec2e83130f8677d7ca7b70c (diff) | |
| parent | a909de07c5f982968cb8cd0f2101ac052f4a0034 (diff) | |
Merge branch 'master' of github.com:abobov/dotfiles
Conflicts:
.gitmodules
28 files changed, 36 insertions, 26244 deletions
@@ -1,7 +1,8 @@ +/files/.aria2/dht.dat /files/.mutt/aliases /files/.mutt/certificates +/files/.mutt/secret /files/.vim/.netrwhist +/files/.vim/doc/tags /files/.vim/spell /files/.zsh/cache -files/.mutt/secret -files/.aria2/dht.dat diff --git a/.gitmodules b/.gitmodules index fdc6093..4caa8d3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,30 +1,37 @@ +[submodule "files/bin"] + path = files/bin + url = https://github.com/abobov/bin.git +[submodule "zsh-completions"] + path = files/.zsh/zsh-completions + url = https://github.com/zsh-users/zsh-completions.git +# Vim bundles +[submodule "vim-pathogen"] + path = files/.vim/bundle/vim-pathogen + url = https://github.com/tpope/vim-pathogen [submodule "surround"] path = files/.vim/bundle/surround - url = git://github.com/tpope/vim-surround.git + url = https://github.com/tpope/vim-surround.git [submodule "repeat"] path = files/.vim/bundle/repeat - url = git://github.com/tpope/vim-repeat.git -[submodule "files/bin"] - path = files/bin - url = git://github.com/abobov/bin.git -[submodule "files/.vim/bundle/nginx-vim-syntax"] - path = files/.vim/bundle/nginx-vim-syntax - url = git://github.com/evanmiller/nginx-vim-syntax.git -[submodule "files/.vim/bundle/nerdcommenter"] + url = https://github.com/tpope/vim-repeat.git +[submodule "nerdcommenter"] path = files/.vim/bundle/nerdcommenter - url = http://github.com/scrooloose/nerdcommenter.git -[submodule "files/.vim/bundle/vim-markdown"] + url = https://github.com/scrooloose/nerdcommenter.git +[submodule "nerdtree"] + path = files/.vim/bundle/nerdtree + url = https://github.com/scrooloose/nerdtree +[submodule "vim-markdown"] path = files/.vim/bundle/vim-markdown url = https://github.com/plasticboy/vim-markdown.git -[submodule "files/.zsh/zsh-completions"] - path = files/.zsh/zsh-completions - url = https://github.com/zsh-users/zsh-completions.git -[submodule "files/.vim/bundle/vim-jade"] +[submodule "vim-jade"] path = files/.vim/bundle/vim-jade url = git://github.com/digitaltoad/vim-jade.git -[submodule "files/.vim/bundle/vim-pathogen"] - path = files/.vim/bundle/vim-pathogen - url = https://github.com/tpope/vim-pathogen -[submodule "files/.vim/bundle/nerdtree"] - path = files/.vim/bundle/nerdtree - url = https://github.com/scrooloose/nerdtree +[submodule "xml.vim"] + path = files/.vim/bundle/xml.vim + url = https://github.com/othree/xml.vim +[submodule "vim-yaml"] + path = files/.vim/bundle/vim-yaml + url = https://github.com/avakhov/vim-yaml +[submodule "nginx-vim-syntax"] + path = files/.vim/bundle/nginx-vim-syntax + url = https://github.com/evanmiller/nginx-vim-syntax.git diff --git a/files/.vim/after/syntax/help.vim b/files/.vim/after/syntax/help.vim deleted file mode 100644 index 5215867..0000000 --- a/files/.vim/after/syntax/help.vim +++ /dev/null @@ -1,24 +0,0 @@ -" Help extensions for luarefvim -" This is somewhat based on CRefVim -" Maintainer: Luis Carvalho <lexcarvalho@gmail.com> -" Last Change: May, 26, 2005 -" Version: 0.1 - -" add three syntax classes: bold, emph (italic) and code -- similarly to html -syn match helpIgnoreBold "#[a-zA-Z0-9&()\`\'\"\-\+\*=\[\]\{\}\.,;: ]\+#" contains=helpMatchBold -syn match helpMatchBold "[a-zA-Z0-9&()\`\'\"\-\+\*=\[\]\{\}\.,;: ]\+" contained -syn match helpIgnoreEmph "@[a-zA-Z0-9&()\`\'\"\-\+\*=\[\]\{\}\.,;: ]\+@" contains=helpMatchEmph -syn match helpMatchEmph "[a-zA-Z0-9&()\`\'\"\-\+\*=\[\]\{\}\.,;: ]\+" contained -" this match is the same as in CRefVim's help.vim (that is, uses $$): -" the idea is to keep some degree of portability. -syn match helpIgnoreCode "\$[a-zA-Z0-9@\\\*/\._=()\-+%<>&\^|!~\?:,\[\];{}#\`\'\" ]\+\$" contains=helpMatchCode -syn match helpMatchCode "[a-zA-Z0-9@\\\*/\._=()\-+%<>&\^|!~\?:,\[\];{}#\`\'\" ]\+" contained - -" syn high links -hi def link helpIgnoreBold Ignore -hi def link helpIgnoreEmph Ignore -hi def link helpIgnoreCode Ignore -hi def link helpMatchBold Function -hi def link helpMatchEmph Special -hi def link helpMatchCode Comment - diff --git a/files/.vim/autoload/Reflection.java b/files/.vim/autoload/Reflection.java deleted file mode 100644 index 5452b0f..0000000 --- a/files/.vim/autoload/Reflection.java +++ /dev/null @@ -1,670 +0,0 @@ -/** - * Reflection.java - * - * A utility class for javacomplete mainly for reading class or package information. - * Version: 0.77 - * Maintainer: cheng fang <fangread@yahoo.com.cn> - * Last Change: 2007-09-16 - * Copyright: Copyright (C) 2007 cheng fang. All rights reserved. - * License: Vim License (see vim's :help license) - * - */ - -import java.lang.reflect.*; -import java.io.*; -import java.util.*; -import java.util.zip.*; - -class Reflection { - static final String VERSION = "0.77"; - - static final int OPTION_FIELD = 1; - static final int OPTION_METHOD = 2; - static final int OPTION_STATIC_FIELD = 4; - static final int OPTION_STATIC_METHOD = 8; - static final int OPTION_CONSTRUCTOR = 16; - static final int OPTION_STATIC = 12; // compound static - static final int OPTION_INSTANCE = 15; // compound instance - static final int OPTION_ALL = 31; // compound all - static final int OPTION_SUPER = 32; - static final int OPTION_SAME_PACKAGE = 64; - - static final int STRATEGY_ALPHABETIC = 128; - static final int STRATEGY_HIERARCHY = 256; - static final int STRATEGY_DEFAULT = 512; - - static final int RETURN_ALL_PACKAGE_INFO = 0x1000; - - static final String KEY_NAME = "'n':"; // "'name':"; - static final String KEY_TYPE = "'t':"; // "'type':"; - static final String KEY_MODIFIER = "'m':"; // "'modifier':"; - static final String KEY_PARAMETERTYPES = "'p':"; // "'parameterTypes':"; - static final String KEY_RETURNTYPE = "'r':"; // "'returnType':"; - static final String KEY_DESCRIPTION = "'d':"; // "'description':"; - static final String KEY_DECLARING_CLASS = "'c':"; // "'declaringclass':"; - - static final String NEWLINE = ""; // "\r\n" - - static boolean debug_mode = false; - - static Hashtable htClasspath = new Hashtable(); - - public static boolean existed(String fqn) { - boolean result = false; - try { - Class.forName(fqn); - result = true; - } - catch (Exception ex) { - } - return result; - } - - public static String existedAndRead(String fqns) { - Hashtable mapPackages = new Hashtable(); // qualified name --> StringBuffer - Hashtable mapClasses = new Hashtable(); // qualified name --> StringBuffer - - for (StringTokenizer st = new StringTokenizer(fqns, ","); st.hasMoreTokens(); ) { - String fqn = st.nextToken(); - try { - Class clazz = Class.forName(fqn); - putClassInfo(mapClasses, clazz); - } - catch (Exception ex) { - String binaryName = fqn; - boolean found = false; - while (true) { - try { - int lastDotPos = binaryName.lastIndexOf('.'); - if (lastDotPos == -1) - break; - binaryName = binaryName.substring(0, lastDotPos) + '$' + binaryName.substring(lastDotPos+1, binaryName.length()); - Class clazz = Class.forName(binaryName); - putClassInfo(mapClasses, clazz); - found = true; - break; - } - catch (Exception e) { - } - } - if (!found) - putPackageInfo(mapPackages, fqn); - } - } - - if (mapPackages.size() > 0 || mapClasses.size() > 0) { - StringBuffer sb = new StringBuffer(4096); - sb.append("{"); - for (Enumeration e = mapPackages.keys(); e.hasMoreElements(); ) { - String s = (String)e.nextElement(); - sb.append("'").append( s.replace('$', '.') ).append("':").append(mapPackages.get(s)).append(","); - } - for (Enumeration e = mapClasses.keys(); e.hasMoreElements(); ) { - String s = (String)e.nextElement(); - sb.append("'").append( s.replace('$', '.') ).append("':").append(mapClasses.get(s)).append(","); - } - sb.append("}"); - return sb.toString(); - } - else - return ""; - } - - private static String getPackageList(String fqn) { - Hashtable mapPackages = new Hashtable(); - putPackageInfo(mapPackages, fqn); - return mapPackages.size() > 0 ? mapPackages.get(fqn).toString() : ""; - } - - private static Hashtable collectClassPath() { - if (!htClasspath.isEmpty()) - return htClasspath; - - // runtime classes - if ("Kaffe".equals(System.getProperty("java.vm.name"))) { - addClasspathesFromDir(System.getProperty("java.home") + File.separator + "share" + File.separator + "kaffe" + File.separator); - } - else if ("GNU libgcj".equals(System.getProperty("java.vm.name"))) { - if (new File(System.getProperty("sun.boot.class.path")).exists()) - htClasspath.put(System.getProperty("sun.boot.class.path"), ""); - } - - if (System.getProperty("java.vendor").toLowerCase(Locale.US).indexOf("microsoft") >= 0) { - // `*.ZIP` files in `Packages` directory - addClasspathesFromDir(System.getProperty("java.home") + File.separator + "Packages" + File.separator); - } - else { - // the following code works for several kinds of JDK - // - JDK1.1: classes.zip - // - JDK1.2+: rt.jar - // - JDK1.4+ of Sun and Apple: rt.jar + jce.jar + jsse.jar - // - JDK1.4 of IBM split rt.jar into core.jar, graphics.jar, server.jar - // combined jce.jar and jsse.jar into security.jar - // - JDK for MacOS X split rt.jar into classes.jar, ui.jar in Classes directory - addClasspathesFromDir(System.getProperty("java.home") + File.separator + "lib" + File.separator); - addClasspathesFromDir(System.getProperty("java.home") + File.separator + "jre" + File.separator + "lib" + File.separator); - addClasspathesFromDir(System.getProperty("java.home") + File.separator + ".." + File.separator + "Classes" + File.separator); - } - - // ext - String extdirs = System.getProperty("java.ext.dirs"); - for (StringTokenizer st = new StringTokenizer(extdirs, File.pathSeparator); st.hasMoreTokens(); ) { - addClasspathesFromDir(st.nextToken() + File.separator); - } - - // user classpath - String classPath = System.getProperty("java.class.path"); - StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator); - while (st.hasMoreTokens()) { - String path = st.nextToken(); - File f = new File(path); - if (!f.exists()) - continue; - - if (path.endsWith(".jar") || path.endsWith(".zip")) - htClasspath.put(f.toString(), ""); - else { - if (f.isDirectory()) - htClasspath.put(f.toString(), ""); - } - } - - return htClasspath; - } - - private static void addClasspathesFromDir(String dirpath) { - File dir = new File(dirpath); - if (dir.isDirectory()) { - String[] items = dir.list(); // use list() instead of listFiles() since the latter are introduced in 1.2 - for (int i = 0; i < items.length; i++) { - File f = new File(dirpath + items[i]); - if (!f.exists()) - continue; - - if (items[i].endsWith(".jar") || items[i].endsWith(".zip") || items[i].endsWith(".ZIP")) { - htClasspath.put(f.toString(), ""); - } - else if (items.equals("classes")) { - if (f.isDirectory()) - htClasspath.put(f.toString(), ""); - } - } - } - } - - - /** - * If name is empty, put all loadable package info into map once. - */ - private static void putPackageInfo(Hashtable map, String name) { - String prefix = name.replace('.', '/') + "/"; - Hashtable subpackages = new Hashtable(); - Hashtable classes = new Hashtable(); - for (Enumeration e = collectClassPath().keys(); e.hasMoreElements(); ) { - String path = (String)e.nextElement(); - if (path.endsWith(".jar") || path.endsWith(".zip")) - appendListFromJar(subpackages, classes, path, prefix); - else - appendListFromFolder(subpackages, classes, path, prefix); - } - - if (subpackages.size() > 0 || classes.size() > 0) { - StringBuffer sb = new StringBuffer(1024); - sb.append("{'tag':'PACKAGE','subpackages':["); - for (Enumeration e = subpackages.keys(); e.hasMoreElements(); ) { - sb.append("'").append(e.nextElement()).append("',"); - } - sb.append("],'classes':["); - for (Enumeration e = classes.keys(); e.hasMoreElements(); ) { - sb.append("'").append(e.nextElement()).append("',"); - } - sb.append("]}"); - map.put(name, sb.toString()); - } - } - - public static void appendListFromJar(Hashtable subpackages, Hashtable classes, String path, String prefix) { - try { - for (Enumeration entries = new ZipFile(path).entries(); entries.hasMoreElements(); ) { - String entry = entries.nextElement().toString(); - int len = entry.length(); - if (entry.endsWith(".class") && entry.indexOf('$') == -1 - && entry.startsWith(prefix)) { - int splitPos = entry.indexOf('/', prefix.length()); - String shortname = entry.substring(prefix.length(), splitPos == -1 ? entry.length()-6 : splitPos); - if (splitPos == -1) { - if (!classes.containsKey(shortname)) - classes.put(shortname, ""); //classes.put(shortname, "{'tag':'CLASSDEF','name':'"+shortname+"'}"); - } - else { - if (!subpackages.containsKey(shortname)) - subpackages.put(shortname, ""); //subpackages.put(shortname, "{'tag':'PACKAGE','name':'" +shortname+"'}"); - } - } - } - } - catch (Throwable e) { - //e.printStackTrace(); - } - } - - public static void appendListFromFolder(Hashtable subpackages, Hashtable classes, String path, String prefix) { - try { - String fullPath = path + "/" + prefix; - File file = new File(fullPath); - if (file.isDirectory()) { - String[] descents = file.list(); - for (int i = 0; i < descents.length; i++) { - if (descents[i].indexOf('$') == -1) { - if (descents[i].endsWith(".class")) { - String shortname = descents[i].substring(0, descents[i].length()-6); - if (!classes.containsKey(shortname)) - classes.put(shortname, ""); - } - else if ((new File(fullPath + "/" + descents[i])).isDirectory()) { - if (!subpackages.containsKey(descents[i])) - subpackages.put(descents[i], ""); - } - } - } - } - } - catch (Throwable e) { - } - } - - private static int INDEX_PACKAGE = 0; - private static int INDEX_CLASS = 1; - - // generate information of all packages in jar files. - public static String getPackageList() { - Hashtable map = new Hashtable(); - - for (Enumeration e = collectClassPath().keys(); e.hasMoreElements(); ) { - String path = (String)e.nextElement(); - if (path.endsWith(".jar") || path.endsWith(".zip")) - appendListFromJar(path, map); - } - - StringBuffer sb = new StringBuffer(4096); - sb.append("{"); - //sb.append("'*':'").append( map.remove("") ).append("',"); // default package - for (Enumeration e = map.keys(); e.hasMoreElements(); ) { - String s = (String)e.nextElement(); - StringBuffer[] sbs = (StringBuffer[])map.get(s); - sb.append("'").append( s.replace('/', '.') ).append("':") - .append("{'tag':'PACKAGE'"); - if (sbs[INDEX_PACKAGE].length() > 0) - sb.append(",'subpackages':[").append(sbs[INDEX_PACKAGE]).append("]"); - if (sbs[INDEX_CLASS].length() > 0) - sb.append(",'classes':[").append(sbs[INDEX_CLASS]).append("]"); - sb.append("},"); - } - sb.append("}"); - return sb.toString(); - - } - - public static void appendListFromJar(String path, Hashtable map) { - try { - for (Enumeration entries = new ZipFile(path).entries(); entries.hasMoreElements(); ) { - String entry = entries.nextElement().toString(); - int len = entry.length(); - if (entry.endsWith(".class") && entry.indexOf('$') == -1) { - int slashpos = entry.lastIndexOf('/'); - String parent = entry.substring(0, slashpos); - String child = entry.substring(slashpos+1, len-6); - putItem(map, parent, child, INDEX_CLASS); - - slashpos = parent.lastIndexOf('/'); - if (slashpos != -1) { - AddToParent(map, parent.substring(0, slashpos), parent.substring(slashpos+1)); - } - } - } - } - catch (Throwable e) { - //e.printStackTrace(); - } - } - - public static void putItem(Hashtable map, String parent, String child, int index) { - StringBuffer[] sbs = (StringBuffer[])map.get(parent); - if (sbs == null) { - sbs = new StringBuffer[] { new StringBuffer(256), // packages - new StringBuffer(256) // classes - }; - } - if (sbs[index].toString().indexOf("'" + child + "',") == -1) - sbs[index].append("'").append(child).append("',"); - map.put(parent, sbs); - } - - public static void AddToParent(Hashtable map, String parent, String child) { - putItem(map, parent, child, INDEX_PACKAGE); - - int slashpos = parent.lastIndexOf('/'); - if (slashpos != -1) { - AddToParent(map, parent.substring(0, slashpos), parent.substring(slashpos+1)); - } - } - - - public static String getClassInfo(String className) { - Hashtable mapClasses = new Hashtable(); - try { - Class clazz = Class.forName(className); - putClassInfo(mapClasses, clazz); - } - catch (Exception ex) { - } - - if (mapClasses.size() == 1) { - return mapClasses.get(className).toString(); // return {...} - } - else if (mapClasses.size() > 1) { - StringBuffer sb = new StringBuffer(4096); - sb.append("["); - for (Enumeration e = mapClasses.keys(); e.hasMoreElements(); ) { - String s = (String)e.nextElement(); - sb.append(mapClasses.get(s)).append(","); - } - sb.append("]"); - return sb.toString(); // return [...] - } - else - return ""; - } - - private static void putClassInfo(Hashtable map, Class clazz) { - if (map.containsKey(clazz.getName())) - return ; - - try { - StringBuffer sb = new StringBuffer(1024); - sb.append("{") - .append("'tag':'CLASSDEF',").append(NEWLINE) - .append("'flags':'").append(Integer.toString(clazz.getModifiers(), 2)).append("',").append(NEWLINE) - .append("'name':'").append(clazz.getName().replace('$', '.')).append("',").append(NEWLINE) - //.append("'package':'").append(clazz.getPackage().getName()).append("',").append(NEWLINE) // no getPackage() in JDK1.1 - .append("'classpath':'1',").append(NEWLINE) - .append("'fqn':'").append(clazz.getName().replace('$', '.')).append("',").append(NEWLINE); - - Class[] interfaces = clazz.getInterfaces(); - if (clazz.isInterface()) { - sb.append("'extends':["); - } else { - Class superclass = clazz.getSuperclass(); - if (superclass != null && !"java.lang.Object".equals(superclass.getName())) { - sb.append("'extends':['").append(superclass.getName().replace('$', '.')).append("'],").append(NEWLINE); - putClassInfo(map, superclass); // !! - } - sb.append("'implements':["); - } - for (int i = 0, n = interfaces.length; i < n; i++) { - sb.append("'").append(interfaces[i].getName().replace('$', '.')).append("',"); - putClassInfo(map, interfaces[i]); // !! - } - sb.append("],").append(NEWLINE);; - - Constructor[] ctors = clazz.getConstructors(); - sb.append("'ctors':["); - for (int i = 0, n = ctors.length; i < n; i++) { - Constructor ctor = ctors[i]; - sb.append("{"); - appendModifier(sb, ctor.getModifiers()); - appendParameterTypes(sb, ctor.getParameterTypes()); - sb.append(KEY_DESCRIPTION).append("'").append(ctors[i].toString()).append("'"); - sb.append("},").append(NEWLINE); - } - sb.append("], ").append(NEWLINE); - - Field[] fields = clazz.getFields(); - //java.util.Arrays.sort(fields, comparator); - sb.append("'fields':["); - for (int i = 0, n = fields.length; i < n; i++) { - Field f = fields[i]; - int modifier = f.getModifiers(); - sb.append("{"); - sb.append(KEY_NAME).append("'").append(f.getName()).append("',"); - if (!f.getDeclaringClass().getName().equals(clazz.getName())) - sb.append(KEY_DECLARING_CLASS).append("'").append(f.getDeclaringClass().getName()).append("',"); - appendModifier(sb, modifier); - sb.append(KEY_TYPE).append("'").append(f.getType().getName()).append("'"); - sb.append("},").append(NEWLINE); - } - sb.append("], ").append(NEWLINE); - - Method[] methods = clazz.getMethods(); - //java.util.Arrays.sort(methods, comparator); - sb.append("'methods':["); - for (int i = 0, n = methods.length; i < n; i++) { - Method m = methods[i]; - int modifier = m.getModifiers(); - sb.append("{"); - sb.append(KEY_NAME).append("'").append(m.getName()).append("',"); - if (!m.getDeclaringClass().getName().equals(clazz.getName())) - sb.append(KEY_DECLARING_CLASS).append("'").append(m.getDeclaringClass().getName()).append("',"); - appendModifier(sb, modifier); - sb.append(KEY_RETURNTYPE).append("'").append(m.getReturnType().getName()).append("',"); - appendParameterTypes(sb, m.getParameterTypes()); - sb.append(KEY_DESCRIPTION).append("'").append(m.toString()).append("'"); - sb.append("},").append(NEWLINE); - } - sb.append("], ").append(NEWLINE); - - Class[] classes = clazz.getClasses(); - sb.append("'classes': ["); - for (int i = 0, n = classes.length; i < n; i++) { - Class c = classes[i]; - sb.append("'").append(c.getName().replace('$', '.')).append("',"); - putClassInfo(map, c); // !! - } - sb.append("], ").append(NEWLINE); - - appendDeclaredMembers(map, clazz, sb); - - sb.append("}"); - map.put(clazz.getName(), sb); - } - catch (Exception ex) { - //ex.printStackTrace(); - } - } - - private static void appendDeclaredMembers(Hashtable map, Class clazz, StringBuffer sb) { - Constructor[] ctors = clazz.getDeclaredConstructors(); - sb.append("'declared_ctors':["); - for (int i = 0, n = ctors.length; i < n; i++) { - Constructor ctor = ctors[i]; - if (!Modifier.isPublic(ctor.getModifiers())) { - sb.append("{"); - appendModifier(sb, ctor.getModifiers()); - appendParameterTypes(sb, ctor.getParameterTypes()); - sb.append(KEY_DESCRIPTION).append("'").append(ctors[i].toString()).append("'"); - sb.append("},").append(NEWLINE); - } - } - sb.append("], ").append(NEWLINE); - - Field[] fields = clazz.getDeclaredFields(); - sb.append("'declared_fields':["); - for (int i = 0, n = fields.length; i < n; i++) { - Field f = fields[i]; - int modifier = f.getModifiers(); - if (!Modifier.isPublic(modifier)) { - sb.append("{"); - sb.append(KEY_NAME).append("'").append(f.getName()).append("',"); - if (!f.getDeclaringClass().getName().equals(clazz.getName())) - sb.append(KEY_DECLARING_CLASS).append("'").append(f.getDeclaringClass().getName()).append("',"); - appendModifier(sb, modifier); - sb.append(KEY_TYPE).append("'").append(f.getType().getName()).append("'"); - sb.append("},").append(NEWLINE); - } - } - sb.append("], ").append(NEWLINE); - - Method[] methods = clazz.getDeclaredMethods(); - sb.append("'declared_methods':["); - for (int i = 0, n = methods.length; i < n; i++) { - Method m = methods[i]; - int modifier = m.getModifiers(); - if (!Modifier.isPublic(modifier)) { - sb.append("{"); - sb.append(KEY_NAME).append("'").append(m.getName()).append("',"); - if (!m.getDeclaringClass().getName().equals(clazz.getName())) - sb.append(KEY_DECLARING_CLASS).append("'").append(m.getDeclaringClass().getName()).append("',"); - appendModifier(sb, modifier); - sb.append(KEY_RETURNTYPE).append("'").append(m.getReturnType().getName()).append("',"); - appendParameterTypes(sb, m.getParameterTypes()); - sb.append(KEY_DESCRIPTION).append("'").append(m.toString()).append("'"); - sb.append("},").append(NEWLINE); - } - } - sb.append("], ").append(NEWLINE); - - Class[] classes = clazz.getDeclaredClasses(); - sb.append("'declared_classes': ["); - for (int i = 0, n = classes.length; i < n; i++) { - Class c = classes[i]; - if (!Modifier.isPublic(c.getModifiers())) { - sb.append("'").append(c.getName().replace('$', '.')).append("',"); - putClassInfo(map, c); // !! - } - } - sb.append("], ").append(NEWLINE); - } - - private static void appendModifier(StringBuffer sb, int modifier) { - sb.append(KEY_MODIFIER).append("'").append(Integer.toString(modifier, 2)).append("', "); - } - - private static void appendParameterTypes(StringBuffer sb, Class[] paramTypes) { - if (paramTypes.length == 0) return ; - - sb.append(KEY_PARAMETERTYPES).append("["); - for (int j = 0; j < paramTypes.length; j++) { - sb.append("'").append(paramTypes[j].getName()).append("',"); - } - sb.append("],"); - } - - private static boolean isBlank(String str) { - int len; - if (str == null || (len = str.length()) == 0) - return true; - for (int i = 0; i < len; i++) - if ((Character.isWhitespace(str.charAt(i)) == false)) - return false; - return true; - } - - // test methods - - static void debug(String s) { - if (debug_mode) - System.out.println(s); - } - static void output(String s) { - if (!debug_mode) - System.out.print(s); - } - - - private static void usage() { - System.out.println("Reflection for javacomplete (" + VERSION + ")"); - System.out.println(" java [-classpath] Reflection [-c] [-d] [-e] [-h] [-v] [-p] [-s] name[,comma_separated_name_list]"); - System.out.println("Options:"); - System.out.println(" -a list all members in alphabetic order"); - System.out.println(" -c list constructors"); - System.out.println(" -C return class info"); - System.out.println(" -d default strategy, i.e. instance fields, instance methods, static fields, static methods"); - System.out.println(" -e check class existed"); - System.out.println(" -E check class existed and read class information"); - System.out.println(" -D debug mode"); - System.out.println(" -p list package content"); - System.out.println(" -P print all package info in the Vim dictionary format"); - System.out.println(" -s list static fields and methods"); - System.out.println(" -h help"); - System.out.println(" -v version"); - } - - public static void main(String[] args) { - String className = null; - int option = 0x0; - boolean wholeClassInfo = false; - boolean onlyStatic = false; - boolean onlyConstructor = false; - boolean listPackageContent = false; - boolean checkExisted = false; - boolean checkExistedAndRead = false; - boolean allPackageInfo = false; - - for (int i = 0, n = args.length; i < n && !isBlank(args[i]); i++) { - //debug(args[i]); - if (args[i].charAt(0) == '-') { - if (args[i].length() > 1) { - switch (args[i].charAt(1)) { - case 'a': - break; - case 'c': // request constructors - option = option | OPTION_CONSTRUCTOR; - onlyConstructor = true; - break; - case 'C': // class info - wholeClassInfo = true; - break; - case 'd': // default strategy - option = option | STRATEGY_DEFAULT; - break; - case 'D': // debug mode - debug_mode = true; - break; - case 'e': // class existed - checkExisted = true; - break; - case 'E': // check existed and read class information - checkExistedAndRead = true; - break; - case 'h': // help - usage(); - return ; - case 'v': // version - System.out.println("Reflection for javacomplete (" + VERSION + ")"); - break; - case 'p': - listPackageContent = true; - break; - case 'P': - option = RETURN_ALL_PACKAGE_INFO; - break; - case 's': // request static members - option = option | OPTION_STATIC_METHOD | OPTION_STATIC_FIELD; - onlyStatic = true; - break; - default: - } - } - } - else { - className = args[i]; - } - } - if (className == null && (option & RETURN_ALL_PACKAGE_INFO) != RETURN_ALL_PACKAGE_INFO) { - return; - } - if (option == 0x0) - option = OPTION_INSTANCE; - - if (wholeClassInfo) - output( getClassInfo(className) ); - else if ((option & RETURN_ALL_PACKAGE_INFO) == RETURN_ALL_PACKAGE_INFO) - output( getPackageList() ); - else if (checkExistedAndRead) - output( existedAndRead(className) ); - else if (checkExisted) - output( String.valueOf(existed(className)) ); - else if (listPackageContent) - output( getPackageList(className) ); - } -} diff --git a/files/.vim/autoload/java_parser.vim b/files/.vim/autoload/java_parser.vim deleted file mode 100644 index 5e1ec38..0000000 --- a/files/.vim/autoload/java_parser.vim +++ /dev/null @@ -1,3500 +0,0 @@ -" Vim autoload script for a JAVA PARSER and more. -" Language: Java -" Maintainer: cheng fang <fangread@yahoo.com.cn> -" Last Changed: 2007-09-16 -" Version: 0.67 -" Copyright: Copyright (C) 2007 cheng fang. All rights reserved. -" License: Vim License (see vim's :help license) - - -if exists("g:loaded_javaparser") || version < 700 || &cp - finish -endif -let g:loaded_javaparser = 'v0.67' - - -" Constants used by scanner and parser {{{1 -let s:EOI = '' - -let s:keywords = {'+': 'PLUS', '-': 'SUB', '!': 'BANG', '%': 'PERCENT', '^': 'CARET', '&': 'AMP', '*': 'STAR', '|': 'BAR', '~': 'TILDE', '/': 'SLASH', '>': 'GT', '<': 'LT', '?': 'QUES', ':': 'COLON', '=': 'EQ', '++': 'PLUSPLUS', '--': 'SUBSUB', '==': 'EQEQ', '<=': 'LTEQ', '>=': 'GTEQ', '!=': 'BANGEQ', '<<': 'LTLT', '>>': 'GTGT', '>>>': 'GTGTGT', '+=': 'PLUSEQ', '-=': 'SUBEQ', '*=': 'STAREQ', '/=': 'SLASHEQ', '&=': 'AMPEQ', '|=': 'BAREQ', '^=': 'CARETEQ', '%=': 'PERCENTEQ', '<<=': 'LTLTEQ', '>>=': 'GTGTEQ', '>>>=': 'GTGTGTEQ', '||': 'BARBAR', '&&': 'AMPAMP', 'abstract': 'ABSTRACT', 'assert': 'ASSERT', 'boolean': 'BOOLEAN', 'break': 'BREAK', 'byte': 'BYTE', 'case': 'CASE', 'catch': 'CATCH', 'char': 'CHAR', 'class': 'CLASS', 'const': 'CONST', 'continue': 'CONTINUE', 'default': 'DEFAULT', 'do': 'DO', 'double': 'DOUBLE', 'else': 'ELSE', 'extends': 'EXTENDS', 'final': 'FINAL', 'finally': 'FINALLY', 'float': 'FLOAT', 'for': 'FOR', 'goto': 'GOTO', 'if': 'IF', 'implements': 'IMPLEMENTS', 'import': 'IMPORT', 'instanceof': 'INSTANCEOF', 'int': 'INT', 'interface': 'INTERFACE', 'long': 'LONG', 'native': 'NATIVE', 'new': 'NEW', 'package': 'PACKAGE', 'private': 'PRIVATE', 'protected': 'PROTECTED', 'public': 'PUBLIC', 'return': 'RETURN', 'short': 'SHORT', 'static': 'STATIC', 'strictfp': 'STRICTFP', 'super': 'SUPER', 'switch': 'SWITCH', 'synchronized': 'SYNCHRONIZED', 'this': 'THIS', 'throw': 'THROW', 'throws': 'THROWS', 'transient': 'TRANSIENT', 'try': 'TRY', 'void': 'VOID', 'volatile': 'VOLATILE', 'while': 'WHILE', 'true': 'TRUE', 'false': 'FALSE', 'null': 'NULL', '(': 'LPAREN', ')': 'RPAREN', '{': 'LBRACE', '}': 'RBRACE', '[': 'LBRACKET', ']': 'RBRACKET', ';': 'SEMI', ',': 'COMMA', '.': 'DOT', 'enum': 'ENUM', '...': 'ELLIPSIS', '@': 'MONKEYS_AT'} - -let s:Flags = {'PUBLIC': 0x1, 'PRIVATE': 0x2, 'PROTECTED': 0x4, 'STATIC': 0x8, 'FINAL': 0x10, 'SYNCHRONIZED': 0x20, 'VOLATILE': 0x40, 'TRANSIENT': 0x80, 'NATIVE': 0x100, 'INTERFACE': 0x200, 'ABSTRACT': 0x400, 'STRICTFP': 0x800, 'SYNTHETIC': 0x1000, 'ANNOTATION': 0x2000, 'ENUM': 0x4000, 'StandardFlags':0x0fff, 'ACC_SUPER': 0x20, 'ACC_BRIDGE': 0x40, 'ACC_VARARGS': 0x80, 'DEPRECATED': 0x20000, 'HASINIT': 0x40000, 'BLOCK': 0x100000, 'IPROXY': 0x200000, 'NOOUTERTHIS': 0x400000, 'EXISTS': 0x800000, 'COMPOUND': 0x1000000, 'CLASS_SEEN': 0x2000000, 'SOURCE_SEEN': 0x4000000, 'LOCKED': 0x8000000, 'UNATTRIBUTED': 0x10000000, 'ANONCONSTR': 0x20000000, 'ACYCLIC': 0x40000000, 'BRIDGE': 1.repeat('0', 31), 'PARAMETER': 1.repeat('0', 33), 'VARARGS': 1.repeat('0', 34), 'ACYCLIC_ANN': 1.repeat('0', 35), 'GENERATEDCONSTR': 1.repeat('0', 36), 'HYPOTHETICAL': 1.repeat('0', 37), 'PROPRIETARY': 1.repeat('0', 38)} - -let s:RE_ANYTHING_AND_NEWLINE = '\(\(.\|\n\)*\)' -let s:RE_LINE_COMMENT = '//.*$' -let s:RE_COMMENT_SP = '/\*\*/' -let s:RE_COMMENT = '' -let s:RE_BRACKETS = '\(\s*\[\s*\]\)' - -let s:RE_IDENTIFIER = '[a-zA-Z_$][a-zA-Z0-9_$]*' -let s:RE_QUALID = s:RE_IDENTIFIER. '\(\s*\.\s*' .s:RE_IDENTIFIER. '\)*' -let s:RE_TYPE_NAME = s:RE_QUALID -let s:RE_REFERENCE_TYPE = s:RE_QUALID . s:RE_BRACKETS . '*' " TypeName || Type[] -let s:RE_TYPE = s:RE_REFERENCE_TYPE " PrimitiveType || ReferenceType -let s:RE_TYPE_VARIABLE = s:RE_IDENTIFIER -let s:RE_VAR_DECL_ID = s:RE_IDENTIFIER . s:RE_BRACKETS . '*' - -let s:RE_TYPE_PARAMS = '' - -let s:RE_THROWS = 'throws\s\+' . s:RE_TYPE_NAME . '\(\s*,\s*' . s:RE_TYPE_NAME . '\)*' -let s:RE_FORMAL_PARAM = '\(final\s*\)\='. s:RE_TYPE . '\s\+' . s:RE_VAR_DECL_ID -let s:RE_FORMAL_PARAM_LIST = s:RE_FORMAL_PARAM . '\(\s*,\s*' . s:RE_FORMAL_PARAM . '\)*' -let s:RE_FORMAL_PARAM2 = '^\s*\(final\s*\)\=\('. s:RE_TYPE . '\)\s\+\(' . s:RE_IDENTIFIER . '\)' . s:RE_BRACKETS . '*' - -let s:RE_MEMBER_MODS = '\%(PUBLIC\|PROTECTED\|PRIVATE\|ABSTRACT\|STATIC\|FINAL\|TRANSIENT\|VOLATILE\|SYNCHRONIZED\|NATIVE\|STRICTFP\)' -let s:RE_MEMBER_HEADER = '\s*\(\%(' .s:RE_MEMBER_MODS. '\s\+\)\+\)\(' .s:RE_IDENTIFIER. '\%(\s*\.\s*' .s:RE_IDENTIFIER. '\)*\%(\s*\[\s*\]\)*\)\s\+\(' .s:RE_IDENTIFIER. '\)' - -" API {{{1 - -let s:PROTOTYPE = {'s:options': {}, 'b:buf': '', 'b:buflen': 0, 'b:lines': [], 'b:idxes': [0], 'b:bp': -1, 'b:ch': '', 'b:line': 0, 'b:col': 0, 'b:pos': 0, 'b:endPos': 0, 'b:prevEndPos': 0, 'b:errPos': -1, 'b:errorEndPos': -1, 'b:sbuf': '', 'b:name': '', 'b:token': '', 'b:docComment': '', 'b:radix': 0, 'b:unicodeConversionBp': -1, 'b:scanStrategy': 0, 'b:allowGenerics': 1, 'b:allowVarargs': 1, 'b:allowAsserts': 1, 'b:allowEnums': 1, 'b:allowForeach': 1, 'b:allowStaticImport': 1, 'b:allowAnnotations': 1, 'b:keepDocComments': 1, 'b:mode': 0, 'b:lastmode': 0, 'b:log': [], 'b:et_perf': '', 'b:et_nextToken_count': 0} - -" Function to initialize the parser -" parameters: -" - lines List of code text -" - options A set of options -fu! java_parser#InitParser(lines, ...) - let s:options = a:0 == 0 ? {} : a:1 - - " internal variables for scanning -" let b:buf = '' " The input buffer - let b:buflen = 0 " index of one past last character in buffer. also eofPos - let b:lines = a:lines " The input buffer - let b:idxes = [0] " Begin index of every lines - let b:bp = -1 " index of next character to be read. - let b:ch = '' " The current character. - let b:line = 0 " The line number position of the current character. - let b:col = 0 " The column number position of the current character. - let b:pos = 0 " The token's position, 0-based offset from beginning of text. - let b:endPos = 0 " Character position just after the last character of the token. - let b:prevEndPos = 0 " The last character position of the previous token. - let b:errPos = -1 " The position where a lexical error occurred - let b:errorEndPos = -1 " - let b:sbuf = '' " A character buffer for literals. - let b:name = '' " The name of an identifier or token: - let b:token = 0 " The token, set by s:nextToken(). - let b:docComment = '' - let b:radix = 0 " The radix of a numeric literal token. - let b:unicodeConversionBp =-1 " The buffer index of the last converted unicode character - - let b:scanStrategy = get(s:options, 'scanStrategy', -1) " 0 - only class members when parse full file; - " 1 - keep statement as a whole string; - " 2 - all - " -1 - enable quick recognition of declarations in common form. - - " language feature options. - let b:allowGenerics = get(s:options, 'allowGenerics', 1) - let b:allowVarargs = get(s:options, 'allowVarargs', 1) - let b:allowAsserts = get(s:options, 'allowAsserts', 1) - let b:allowEnums = get(s:options, 'allowEnums', 1) - let b:allowForeach = get(s:options, 'allowForeach', 1) - let b:allowStaticImport = get(s:options, 'allowStaticImport', 1) - let b:allowAnnotations = get(s:options, 'allowAnnotations', 1) - let b:keepDocComments = get(s:options, 'keepDocComments', 1) - - let b:mode = 0 " The current mode. - let b:lastmode = 0 " The mode of the term that was parsed last. - - - let b:log = [] - - let b:et_perf = '' - let b:et_nextToken_count = 0 - -" let b:buf = join(a:lines, "\r") -" let b:buflen = strlen(b:buf) - for line in a:lines - let b:buflen += strlen(line) + 1 - call add(b:idxes, b:buflen) - endfor - call add(b:lines, s:EOI) " avoid 'list index out of range' error from lines[] in java_scanChar - " if b:bp >= b:buflen - " return s:EOI - " endif - - " initialize scanner - call s:scanChar() " be ready for scanning - call s:nextToken() " prime the pump -endfu - -fu! java_parser#FreeParser() - for varname in keys(s:PROTOTYPE) - exe "if exists(" . string(varname) . ") | unlet " . varname . " | endif" - endfor -endfu - -fu! java_parser#GetSnapshot() - let snapshot = {} - for varname in keys(s:PROTOTYPE) - exe "let snapshot[" . string(varname) . "] = " . varname - endfor - return snapshot -endfu - -fu! java_parser#Restore(snapshot) - for key in keys(a:snapshot) - exe "let " . key . "=" . string(a:snapshot[key]) - endfor -endfu - -" move b:bp and b:pos to the specified position -fu! java_parser#GotoPosition(pos) - let b:bp = a:pos-1 - let b:pos = a:pos - let p = java_parser#DecodePos(b:bp) - let b:line = p.line - let b:col = p.col - call s:scanChar() - call s:nextToken() -endfu - -fu! java_parser#compilationUnit() - return s:compilationUnit() -endfu - -fu! java_parser#block() - return s:block() -endfu - -fu! java_parser#statement() - return s:blockStatements() -endfu - -fu! java_parser#expression() - return s:expression() -endfu - -fu! java_parser#nextToken() - return s:nextToken() -endfu - - -" Tree {{{1 -let s:TTree = {'tag': '', 'pos': 0} " Root class for AST nodes. - -" Tree maker functions {{{2 -fu! s:ClassDef(pos, mods, ...) - return {'tag': 'CLASSDEF', 'pos': a:pos, 'mods': a:mods, 'name': ''} -endfu - -fu! s:VarDef(pos, mods, name, vartype) - return {'tag': 'VARDEF', 'pos': a:pos, 'mods': a:mods, 'name': a:name, 'vartype': a:vartype} -endfu - -fu! s:Unary(pos, opcode, arg) - return {'tag': a:opcode, 'pos': a:pos, 'arg': a:arg} -endfu - -fu! s:Binary(pos, opcode, lhs, rhs, ...) - return {'tag': a:opcode, 'pos': a:pos, 'lhs': a:lhs, 'rhs': a:rhs} -endfu - -fu! s:TypeCast(pos, clazz, expr) - return {'tag': 'TYPECAST', 'pos': a:pos, 'clazz': a:clazz, 'expr': a:expr} -endfu - -fu! s:Select(pos, selected, name) - return {'tag': 'SELECT', 'pos': a:pos, 'selected': a:selected, 'name': a:name} -endfu - -fu! s:Ident(pos, name) - return {'tag': 'IDENT', 'pos': a:pos, 'name': a:name} -endfu - -fu! s:TypeArray(pos, elementtype) - return {'tag': 'TYPEARRAY', 'pos': a:pos, 'elementtype': a:elementtype} -endfu - -fu! s:Modifiers(pos, flags, annotations) - let noFlags = s:BitAnd(a:flags, s:Flags.StandardFlags) == 0 - let mods = {'tag': 'MODIFIERS', 'flags': a:flags} - let mods.pos = noFlags && empty(a:annotations) ? -1 : a:pos - if !empty(a:annotations) - let mods.annotations = a:annotations - endif - return mods -endfu - - -" {{{2 -fu! java_parser#IsStatement(tree) - return has_key(a:tree, 'tag') && a:tree.tag =~# '^\(CLASSDEF\|VARDEF\|BLOCK\|IF\|DOLOOP\|WHILELOOP\|FORLOOP\|FOREACHLOOP\|SWITCH\|TRY\|EXEC\|LABELLED\|SYNCHRONIZED\|CASE\|BREAK\|RETURN\|SKIP\|THROW\|ASSERT\|CONTINUE\)$' -endfu - -" Tree Helper {{{1 -fu! java_parser#type2Str(type) - if type(a:type) == type("") - return a:type - endif - - let t = a:type - if t.tag == 'IDENTIFIER' - return t.value - elseif t.tag == 'IDENT' - return t.name - elseif t.tag == 'TYPEIDENT' - return t.typetag - elseif t.tag == 'SELECT' - return java_parser#type2Str(t.selected) . '.' . t.name - elseif t.tag == 'TYPEARRAY' - return java_parser#type2Str(t.elementtype) . '[]' - elseif t.tag == 'TYPEAPPLY' - return t.clazz.name - elseif t.tag == 'TEMPLATE' - let s = t.clazz.value . '<' - for arg in t.arguments - let s .= arg.value - endfor - let s .= '>' - return s - endif -endfu - -fu! s:vardef2Str(vardef) - return java_parser#type2Str(a:vardef.vartype) . ' ' . a:vardef.name -endfu - -fu! s:method2Str(methoddef) - let m = a:methoddef - let desc = m.r . ' ' . m.n . '(' - for item in m.params - let desc .= s:vardef2Str(item) . ',' - endfor - let desc = substitute(desc, ',$', '', '') - let desc .= ')' - return desc -endfu - -" Scanner {{{1 - -" nextToken() {{{2 -fu! s:nextToken() - let b:prevEndPos = b:endPos - let b:et_nextToken_count += 1 - let b:sbuf = '' - while 1 - let b:pos = b:bp - if b:ch =~ '[ \t\r\n]' " - FF - " OAO optimized code: skip spaces - let b:col = match(b:lines[b:line], '[^ \t\r\n]\|$', b:col) - let b:bp = b:idxes[b:line] + b:col - call s:scanChar() - let b:endPos = b:bp - continue - - elseif b:ch =~ '[a-zA-Z$_]' - " read a identifier - call s:scanIdent() - return - - elseif b:ch == '0' - call s:scanChar() - " hex - if b:ch == 'x' || b:ch == 'X' - call s:scanChar() - if b:ch == '.' - call s:scanHexFractionAndSuffix(0) - elseif s:isDigit(16) - call s:scanNumber(16) - else - call s:LexError("invalid.hex.number") - endif - " oct - else - let b:sbuf .= '0' - call s:scanNumber(8) - endif - return - - elseif b:ch =~ '[1-9]' - " read number - call s:scanNumber(10) - return - - elseif b:ch == '.' - call s:scanChar() - if b:ch =~ '[0-9]' - let b:sbuf .= '.' - call s:scanFractionAndSuffix() - " JAVA5 ELLIPSIS - elseif b:ch == '.' - let b:sbuf .= '..' - call s:scanChar() - if b:ch == '.' - call s:scanChar() - let b:sbuf .= '.' - let b:token = 'ELLIPSIS' - else - call s:LexError('malformed.fp.lit') - endif - else - let b:token = 'DOT' - endif - return - - elseif b:ch =~ '[,;(){}[\]]' - let b:token = s:keywords[b:ch] - call s:scanChar() - return - - elseif b:ch == '/' - let status = s:scanComment() - if status == 1 - continue - elseif status == 2 - return - elseif b:ch == '=' - let b:name = '/=' - let b:token = 'SLASHEQ' - call s:scanChar() - else - let b:name = '/' - let b:token = 'SLASH' - endif - return - - - elseif b:ch == "'" - call s:scanSingleQuote() - return - - elseif b:ch == '"' - call s:scanDoubleQuote() - return - - else - if s:IsSpecial(b:ch) - call s:scanOperator() - elseif b:ch =~ '[a-zA-Z_]' - call s:scanIdent() - elseif b:bp >= b:buflen - let b:token = 'EOF' - else - call s:LexError("illegal.char '" . b:ch . "'") - call s:scanChar() - endif - return - endif - endwhile -endfu - -" scanChar() Read next character. {{{2 -" one buf version -"fu! s:scanChar() -" let b:bp += 1 -" if b:bp % 256 == 0 -" let b:buf2 = strpart(b:buf, b:bp, 256) -" endif -" let b:ch = b:buf2[b:bp % 256] -"" let b:ch = b:buf[b:bp] " it will be extremely slow when buf is large -" "call s:Trace( "'" . b:ch . "'" ) -" -" if b:ch == "\r" -" let b:line += 1 -" let b:col = 0 -" elseif b:ch == "\n" -" if b:bp == 0 || b:buf[b:bp-1] == "\r" -" let b:line += 1 -" let b:col = 0 -" endif -" else -" let b:col += 1 -" endif -"endfu - -" Read next character. multiple lines version -fu! s:scanChar() - let b:bp+=1 - let b:ch=b:lines[b:line][b:col] - let b:col+=1 - if b:ch=='' - let b:ch="\r" - let b:line+=1 - let b:col=0 - endif - - if b:ch == '\' - call s:convertUnicode() - endif -endfu - -fu! java_parser#CharAt(line, col) - let ch=b:lines[a:line][a:col] - if ch == '' - let ch = "\r" - endif - return ch -endfu - -fu! s:convertUnicode() - if b:ch == '\' && b:unicodeConversionBp != b:bp - "if java_parser#CharAt(b:bp+1) == 'u' - "call s:scanChar() - "endif - endif -endfu - -" putChar() is substituted with -" let b:sbuf .= '.' - -" scanIdent() {{{2 -" OAO optimized code -fu! s:scanIdent() - let col_old = b:col - let b:col = match(b:lines[b:line], '[^a-zA-Z0-9$_]\|$', b:col) - let b:name = strpart(b:lines[b:line], col_old-1, b:col-col_old+1) - let b:token = get(s:keywords, b:name, 'IDENTIFIER') - call s:Debug('name: "' . b:name . '" of token type ' . b:token ) - let b:bp = b:idxes[b:line] + b:col - call s:scanChar() -endfu - -" Standard implementation -fu! s:scanIdent_old() - " do ... while () - let b:sbuf .= b:ch - call s:scanChar() - if b:ch !~ '[a-zA-Z0-9$_]' || b:bp >= b:buflen - let b:name = b:sbuf - let b:token = has_key(s:keywords, b:name) ? s:keywords[b:name] : 'IDENTIFIER' - call s:Debug('name: "' . b:name . '" of token type ' . b:token ) - return - endif - - while (1) - let b:sbuf .= b:ch - call s:scanChar() - if b:ch !~ '[a-zA-Z0-9$_]' || b:bp >= b:buflen - let b:name = b:sbuf - let b:token = has_key(s:keywords, b:name) ? s:keywords[b:name] : 'IDENTIFIER' - call s:Debug('name: "' . b:name . '" of token type ' . b:token ) - break - endif - endwhile -endfu - -" digit() {{{2 -" Convert an ASCII digit from its base (8, 10, or 16) to its value. -" NOTE: This only implement isdigit() check -fu! s:digit(base) - let c = b:ch - "let result = -endfu - -fu! s:isDigit(base) - if a:base == 8 - return b:ch =~ '[0-7]' - elseif a:base == 16 - return b:ch =~ '[0-9a-fA-F]' - elseif a:base == 10 - return b:ch =~ '[0-9]' - endif -endfu - -" scanNumber() {{{2 -fu! s:scanNumber(radix) - let b:radix = a:radix - let digitRadix = a:radix <= 10 ? 10 : 16 - let seendigit = 0 - while s:isDigit(a:radix) - let seendigit = 1 - let b:sbuf .= b:ch - call s:scanChar() - endwhile - if a:radix == 16 && b:ch == '.' - call s:scanHexFractionAndSuffix(seendigit) - elseif seendigit && a:radix == 16 && (b:ch == 'p' || b:ch == 'P') - call s:scanHexExponentAndSuffix() - elseif a:radix <= 10 && b:ch == '.' - let b:sbuf .= b:ch - call s:scanChar() - call s:scanFractionAndSuffix() - elseif a:radix <= 10 && b:ch =~ '[eEfFdD]' - call s:scanFractionAndSuffix() - else - if b:ch == 'l' || b:ch == 'L' - call s:scanChar() - let b:token = 'LONGLITERAL' - else - let b:token = 'INTLITERAL' - endif - endif -endfu - -fu! s:scanHexExponentAndSuffix() - if b:ch == 'p' || b:ch == 'P' - let b:sbuf .= b:ch - call s:scanChar() - if b:ch == '+' || b:ch == '-' - let b:sbuf .= b:ch - call s:scanChar() - endif - - if '0' <= b:ch && b:ch <= '9' - let b:sbuf .= b:ch - call s:scanChar() - while '0' <= b:ch && b:ch <= '9' - let b:sbuf .= b:ch - call s:scanChar() - endwhile - - "if !b:allowHexFloats - "elseif !b:hexFloatsWork - " call s:LexError("unsupported.cross.fp.lit") - "endif - else - call s:LexError("malformed.fp.lit") - endif - else - call s:LexError("malformed.fp.lit") - endif - - if b:ch == 'f' || b:ch == 'F' - let b:sbuf .= b:ch - call s:scanChar() - let b:token = 'FLOATLITERAL' - else - if b:ch == 'f' || b:ch == 'F' - let b:sbuf .= b:ch - call s:scanChar() - endif - let b:token = 'DOUBLELITERAL' - endif -endfu - -fu! s:scanFraction() - " scan fraction - while b:ch =~ '[0-9]' - let b:sbuf .= b:ch - call s:scanChar() - endwhile - - " floating point number - if b:ch == 'e' || b:ch == 'E' - let b:sbuf .= b:ch - call s:scanChar() - - if b:ch == '+' || b:ch == '-' - let b:sbuf .= b:ch - call s:scanChar() - endif - - if b:ch =~ '[0-9]' - let b:sbuf .= b:ch - call s:scanChar() - while b:ch =~ '[0-9]' - let b:sbuf .= b:ch - call s:scanChar() - endwhile - return - endif - - call s:LexError("malformed.fp.lit") - endif -endfu - -" Read fractional part and 'd' or 'f' suffix of floating point number. -fu! s:scanFractionAndSuffix() - call s:scanFraction() - if b:ch == 'f' || b:ch == 'F' - let b:sbuf .= b:ch - call s:scanChar() - let b:token = 'FLOATLITERAL' - else - if b:ch == 'd' || b:ch == 'D' - let b:sbuf .= b:ch - call s:scanChar() - endif - let b:token = 'DOUBLELITERAL' - endif -endfu - -fu! s:scanHexFractionAndSuffix(seendigit) - let seendigit = a:seendigit - let b:radix = 16 - if b:ch != '.' | echoerr "b:ch != '.'" | endif - - let b:sbuf .= b:ch - call s:scanChar() - while s:isDigit(16) - let seendigit = 1 - let b:sbuf .= b:ch - call s:scanChar() - endwhile - - if !seendigit - call s:LexError("invalid.hex.number") - else - call s:scanHexExponentAndSuffix() - endif -endfu - -" scanLitChar() {{{2 -fu! s:scanLitChar() - if b:ch == '\' - call s:scanChar() - if b:ch =~ '[0-7]' - let leadch = b:ch - let oct = b:ch - call s:scanChar() - if b:ch =~ '[0-7]' - let oct = oct * 8 + b:ch - call s:scanChar() - if leadch <= '3' && '0' <= b:ch && b:ch <= '7' - let oct = oct * 8 + b:ch - call s:scanChar() - endif - endif - let b:sbuf .= oct - - elseif b:ch == "'" || b:ch =~ '[btnfr"\\]' - let b:sbuf .= b:ch - call s:scanChar() - - " unicode escape - elseif b:ch == 'u' - while b:ch =~ '[a-zA-Z0-9]' - call s:scanChar() - endwhile - - else - call s:LexError("illegal.esc.char") - endif - - elseif b:bp < b:buflen - let b:sbuf .= b:ch - call s:scanChar() - endif -endfu - -" scanOperator() {{{2 -fu! s:scanOperator() - while 1 - if !has_key(s:keywords, b:sbuf . b:ch) - break - endif - - let b:sbuf .= b:ch - let b:token = get(s:keywords, b:sbuf, 'IDENTIFIER') - call s:Debug('sbuf: "' . b:sbuf . '" of token type ' . b:token ) - call s:scanChar() - if !s:IsSpecial(b:ch) - break - endif - endwhile -endfu - -" NOTE: add @ for JAVA5 -fu! s:IsSpecial(ch) - return a:ch =~ '[!%&*?+-:<=>^|~@]' -endfu - -" scan comment {{{2 -" return 0 - not comment, 1 - succeeded to scan comment, 2 - unclosed comment -fu! s:scanComment() - call s:scanChar() - " line comment - if b:ch == '/' - let b:token = 'LINECOMMENT' - call s:Info('line comment') - call s:SkipLineComment() - let b:endPos = b:bp - return 1 - - " classic comment - " test cases: /**/, /***/, /*******/, /*** astatement; /***/, /*/ - elseif b:ch == '*' - let b:token = 'BLOCKCOMMENT' - call s:Info('block comment') - call s:scanChar() - let time = reltime() - " javadoc - if b:ch == '*' - let b:docComment = s:scanDocComment() - " normal comment - else - call s:skipComment() - endif - let b:et_perf .= "\r" . 'comment ' . reltimestr(reltime(time)) - - if b:ch == '/' - call s:Info('end block comment') - call s:scanChar() - let b:endPos = b:bp - return 1 - else - call s:LexError('unclosed.comment') - return 2 - endif - endif - return 0 -endfu - -fu! s:SkipLineComment() - " OAO optimized code - let b:ch = "\r" - let b:line += 1 - let b:col = 0 - let b:bp = b:idxes[b:line] + b:col - - " OLD - "call s:scanChar() - "while (b:ch != "\r") - " call s:scanChar() - "endwhile -endfu - -fu! s:skipComment() - if b:ch == '*' - call s:scanChar() - if b:ch == '/' - return - else " NOTE: go back - let b:ch = '*' - let b:bp -= 1 - let b:col -= 1 - endif - endif - - " OAO optimized code - if s:Stridx('*/') > -1 - call s:scanChar() - endif - -" " Standard implementation -" while b:bp < b:buflen -" if b:ch == '*' -" call s:scanChar() -" if b:ch == '/' -" break -" endif -" else -" call s:scanChar() -" endif -" endwhile -endfu - -fu! s:scanDocComment() - call s:Info('It is javadoc') - return s:skipComment() - - " skip star '*' - while (b:bp < b:buflen && b:ch == '*') - call s:scanChar() - endwhile - - if b:bp < b:buflen && b:ch == '/' - return '' - endif - - let result = '' - while b:bp < b:buflen - if b:ch == '*' - call s:scanChar() - if b:ch == '/' - break - else - let result .= b:ch - endif - else - call s:scanChar() - let result .= b:ch - endif - endwhile - - return result -endfu - -" scan single quote {{{2 -fu! s:scanSingleQuote() - call s:scanChar() - if (b:ch == "'") - call s:LexError("empty.char.lit") - else - if (b:ch =~ '[\r\n]') - call s:LexError("illegal.line.end.in.char.lit") - endif - - call s:scanLitChar() - if b:ch == "'" - call s:scanChar() - let b:token = 'CHARLITERAL' - else - call s:LexError("unclosed.char.lit") - endif - endif -endfu - -" scan double quote {{{2 -" test cases: -" 'a"";' -" 'a"b,c";' -" 'a"b,\"c";' -" 'a"b,\\"c";' -" 'a"b,\\\"c";' -" 'a"b,\\\\"c";' -" 'a"b,\\\"c;' " NOTE: cannot handle -fu! s:scanDoubleQuote() - if match(b:lines[b:line], '\\"', b:col) == -1 - let idx = matchend(b:lines[b:line], '\(\\\(["\\''ntbrf]\)\|[^"]\)*"', b:col) - if idx != -1 - let b:sbuf = strpart(b:lines[b:line], b:col, idx-b:col-1) - let b:col = idx-1 " back to the end - let b:bp = b:idxes[b:line] + b:col - call s:scanChar() - let b:token = 'STRINGLITERAL' - else - call s:LexError("unclosed.str.lit") - endif - call s:scanChar() - return - endif - - - call s:scanChar() - while b:ch !~ '["\r\n]' && b:bp < b:buflen - call s:scanLitChar() - endwhile - - if b:ch == '"' - let b:token = 'STRINGLITERAL' - call s:scanChar() - else - call s:LexError("unclosed.str.lit") - endif -endfu - -" lex errors {{{2 -fu! s:LexError(key, ...) - let pos = a:0 == 0 ? b:pos : a:1 - let b:token = 'ERROR' - let b:errPos = pos - call s:Log(4, b:pos, '[lex error]:' . s:Pos2Str(pos) . ': ' . a:key) -endfu - -" Scanner Helper {{{1 -" gotoMatchEnd {{{2 -fu! s:gotoMatchEnd(one, another, ...) - while b:bp < b:buflen - if b:ch == a:another - call s:scanChar() - if has_key(s:keywords, a:another) - let b:token = s:keywords[a:another] - else - echoerr '<strange>' - endif - break - - elseif b:ch == a:one - call s:scanChar() - call s:gotoMatchEnd(a:one, a:another) - - " skip commment - elseif b:ch == '/' - call s:scanComment() - - " skip literal character - elseif b:ch == "'" - call s:scanSingleQuote() - - " skip literal string - elseif b:ch == '"' - call s:scanDoubleQuote() - - else - " OAO - call s:Match('[' . a:one . a:another . '/"'']') - " OLD - "call s:scanChar() - endif - endwhile - - " For such situation: after accept one token, the next token is just the same. - let nextTokenIsLBRACE = a:0 == 0 ? 0 : a:1 - if nextTokenIsLBRACE - call s:gotoMatchEnd(a:one, a:another) - endif - - return b:bp -endfu - -" gotoSemi {{{2 -fu! s:gotoSemi() - while b:bp < b:buflen - if b:ch == ';' - let b:pos = b:bp - call s:scanChar() - let b:token = 'SEMI' - return - - " skip commment - elseif b:ch == '/' - call s:scanComment() - - " skip literal character - elseif b:ch == "'" - call s:scanSingleQuote() - - " skip literal string - elseif b:ch == '"' - call s:scanDoubleQuote() - - elseif b:ch == '{' - call s:scanChar() - call s:gotoMatchEnd('{', '}') - - elseif b:ch == '(' - call s:scanChar() - call s:gotoMatchEnd('(', ')') - - elseif b:ch == '[' - call s:scanChar() - call s:gotoMatchEnd('[', ']') - - else - " OAO - call s:Match('[;({[/"'']') - " OLD - "call s:scanChar() - endif - endwhile -endfu - -" s:Strpart(), s:Stridx(), s:Match() {{{2 -fu! Strpart(start, len) - let startline = java_parser#DecodePos(a:start).line - let endline = java_parser#DecodePos(a:start + a:len).line - let str = join(b:lines[startline:endline-1]) . b:lines[endline] - return strpart(str, a:start-b:idxes[startline], a:len) -endfu - -fu! s:Stridx(needle) - let found = 0 - while b:line < len(b:lines)-1 - let idx = stridx(b:lines[b:line], a:needle, b:col) - if idx > -1 - let found = 1 - let b:col = idx - break - endif - let b:line += 1 - let b:col = 0 - endwhile - - if found - let b:bp = b:idxes[b:line] + b:col - call s:scanChar() - return b:bp - else - let b:bp = b:buflen - let b:ch = s:EOI - return -1 - endif -endfu - -fu! s:Match(pat) - let bp_old = b:bp - let line_old = b:line - let col_old = b:col - - let found = 0 - while b:line < len(b:lines)-1 - let idx = match(b:lines[b:line], a:pat, b:col) - if idx > -1 - let found = 1 - let b:col = idx - break - endif - let b:line += 1 - let b:col = 0 - endwhile - - if found - let b:bp = b:idxes[b:line] + b:col-1 - call s:scanChar() - return b:bp - else - let b:bp = bp_old - let b:line = line_old - let b:col = col_old - call s:scanChar() - return -1 - endif -endfu - - -" conversion between position and (line, col) {{{2 -fu! java_parser#MakePos(line, col) - return b:idxes[a:line] + a:col -endfu - -fu! java_parser#DecodePos(pos) - let line = -1 - for idx in b:idxes - if idx > a:pos - break - endif - let line += 1 - endfor - let col = a:pos - b:idxes[line] - return {'line': line, 'col': col} -endfu - -fu! s:Pos2Str(pos) - let o = java_parser#DecodePos(a:pos) - return '(' . (o.line+1) . ',' . (o.col+1) . ')' -endfu - -" Bitwise operator emulators {{{1 -" NOTE: For more than 32 bit number, use the string bits form. - -" bit operator ~ -fu! s:BitNot(v) - return s:Bits2Number( s:BitNot_binary(s:Number2Bits(a:v)) ) -endfu - -fu! s:BitNot_binary(v) - let v = substitute(a:v, '^0*\([01]\+\)', '\1', 'g') - let v = substitute(v, '1', '2', 'g') - let v = substitute(v, '0', '1', 'g') - let v = substitute(v, '2', '0', 'g') - return v -endfu - -" bit operator & -fu! s:BitAnd(n1, n2) - if a:n1 == 0 || a:n2 == 0 | return 0 | endif - if a:n1 == a:n2 | return 1 | endif - return s:Bits2Number( s:BitOperator_binary(s:Number2Bits(a:n1), s:Number2Bits(a:n2), 'n1[i] == "1" && n2[i] == "1"') ) -endfu - -" bit operator | -fu! s:BitOr(n1, n2, ...) - if a:0 == 0 - if a:n1 == 0 - return a:n2 - elseif a:n2 == 0 - return a:n1 - endif - endif - let result = s:BitOperator_binary(s:Number2Bits(a:n1), s:Number2Bits(a:n2), 'n1[i] == "1" || n2[i] == "1"') - for a in a:000 - let result = s:BitOperator_binary(result, s:Number2Bits(a), 'n1[i] == "1" || n2[i] == "1"') - endfor - return s:Bits2Number( result ) -endfu - -" bit operator ^ -fu! s:BitXor(n1, n2) - if a:n1 == a:n2 | return 0 | endif - return s:Bits2Number( s:BitOperator_binary(s:Number2Bits(a:n1), s:Number2Bits(a:n2), 'n1[i] != n2[i]') ) -endfu - -fu! s:BitOperator_binary(n1, n2, comparator) - let n1 = a:n1 - let n2 = a:n2 - - let len1 = len(n1) - let len2 = len(n2) - let len = len1 - if len1 > len2 - let n2 = repeat('0', len1-len2) . n2 - else - let len = len2 - let n1 = repeat('0', len2-len1) . n1 - endif - - let i = 0 - let bits = '' - while i < len - let bits .= eval(a:comparator) ? '1' : '0' - let i += 1 - endwhile - return bits -endfu - -" bit operator << -fu! s:BitMoveLeft() -endfu - -" bit operator >> -fu! s:BitMoveRight() -endfu - -" helper function: convert a number to a string consisted of '0' or '1' indicating number -fu! s:Number2Bits(n, ...) - if type(a:n) == type("") | return a:n | endif - if a:n == 0 | return '0' | endif - - let n = a:n - let bits = '' - while n != 0 - let bit = n % 2 - "echo 'n: ' . n . ' bit: ' . bit - let bits = bit . bits - let n = (n-bit)/ 2 - endwhile - if a:0 > 0 - let bits = repeat(a:1 - len(bits)) . bits - endif - return bits -endfu - -" helper function: convert a string consisted of '0' or '1' indicating number to a number -" precondition: bits must not be empty string -fu! s:Bits2Number(bits) - let len = len(a:bits) - let n = a:bits[0] - let i = 1 - while i < len - let n = n * 2 + a:bits[i] - let i += 1 - endwhile - return n -endfu - - -let s:modifier_keywords = ['strictfp', 'abstract', 'interface', 'native', 'transient', 'volatile', 'synchronized', 'final', 'static', 'protected', 'private', 'public'] -fu! s:String2Flags(str) - let mod = [0,0,0,0,0,0,0,0,0,0,0,0,] - for item in split(a:str, '\s\+') - if index(s:modifier_keywords, item) != -1 - let mod[index(s:modifier_keywords, item)] = '1' - endif - endfor - return join(mod[index(mod, '1'):], '') -endfu - -" Log utilities {{{1 -" level -" 5 off/fatal -" 4 error -" 3 warn -" 2 info -" 1 debug -" 0 trace -fu! java_parser#SetLogLevel(level) - let b:loglevel = a:level -endfu - -fu! java_parser#GetLogLevel() - return exists('b:loglevel') ? b:loglevel : 3 -endfu - -fu! java_parser#GetLogContent() - return b:log -endfu - -fu! s:Trace(msg) - call s:Log(0, b:pos, a:msg) -endfu - -fu! s:Debug(msg) - call s:Log(1, b:pos, a:msg) -endfu - -fu! s:Info(msg) - call s:Log(2, b:pos, a:msg) -endfu - -fu! s:Log(level, pos, key, ...) - if a:level >= java_parser#GetLogLevel() - echo a:key - call add(b:log, a:key) - endif -endfu - -fu! s:ShowWatch(...) - let at = a:0 > 0 ? a:1 : '' - echo '-- b:bp ' . b:bp . string(java_parser#DecodePos(b:bp)) . ' b:ch "' . b:ch . '" b:name ' . b:name . ' b:token ' . b:token . ' b:pos ' .b:pos . ' endPos ' . b:endPos . ' prevEndPos ' . b:prevEndPos . ' errPos ' . b:errPos . ' errorEndPos ' . b:errorEndPos . at -endfu - -fu! java_parser#Exe(cmd) - exe a:cmd -endfu - -" Parser {{{1 -" skip() Skip forward until a suitable stop token is found. {{{2 -fu! s:skip(stopAtImport, stopAtMemberDecl, stopAtIdentifier, stopAtStatement) - while 1 - if b:token == 'SEMI' - call s:nextToken() - return - elseif b:token =~# '^\(PUBLIC\|FINAL\|ABSTRACT\|MONKEYS_AT\|EOF\|CLASS\|INTERFACE\|ENUM\)$' - return - elseif b:token == 'IMPORT' - if a:stopAtImport - return - endif - elseif b:token =~# '^\(LBRACE\|RBRACE\|PRIVATE\|PROTECTED\|STATIC\|TRANSIENT\|NATIVE\|VOLATILE\|SYNCHRONIZED\|STRICTFP\|LT\|BYTE\|SHORT\|CHAR\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\|VOID\)$' - if a:stopAtMemberDecl - return - endif - elseif b:token == 'IDENTIFIER' - if a:stopAtIdentifier - return - endif - elseif b:token =~# '^\(CASE\|DEFAULT\|IF\|FOR\|WHILE\|DO\|TRY\|SWITCH\|RETURN\|THROW\|BREAK\|CONTINUE\|ELSE\|FINALLY\|CATCH\)$' - if a:stopAtStatement - return - endif - endif - call s:nextToken() - endwhile -endfu - -" syntax errors {{{2 -fu! s:SyntaxError(key, ...) - let pos = a:0 == 0 ? b:pos : a:1 - let errs = a:0 > 1 ? a:2 : [] - call s:setErrorEndPos(pos) - call s:ReportSyntaxError(pos, a:key) - return {'tag': 'ERRONEOUS', 'pos': pos, 'errs': errs} -endfu - -fu! s:ReportSyntaxError(pos, key, ...) - if a:pos > b:errPos || a:pos == -1 - let key = a:key . (b:token == 'EOF' ? ' and premature.eof' : '') - call s:Log(4, a:pos, '[syntax error]' . s:Pos2Str(a:pos) . ': ' . key) - endif - let b:errPos = a:pos -endfu - -" accept() {{{2 -fu! s:accept(token_type) - "call s:Debug(b:token . ' == ' . a:token_type . (b:token == a:token_type)) - if b:token == a:token_type - call s:nextToken() - else - call s:setErrorEndPos(b:pos) - call s:ReportSyntaxError(b:prevEndPos, s:token2string(a:token_type) . " expected") - "call s:nextToken() - endif -endfu - -fu! s:token2string(token) - if a:token =~# '^\(DOT\|COMMA\|SEMI\|LPAREN\|RPAREN\|LBRACKET\|RBRACKET\|LBRACE\|RBRACE\)$' - return "'" . a:token . "'" - endif - return a:token -endfu - - -" illegal() {{{2 -fu! s:illegal(...) - call s:setErrorEndPos(b:pos) - return s:SyntaxError(s:modeAndEXPR() ? 'illegal.start.of.expr' : 'illegal.start.of.type', a:0 == 0 ? b:pos : a:1) -endfu - -" setErrorEndPos() {{{2 -fu! s:setErrorEndPos(errPos) - if a:errPos > b:errorEndPos - let b:errorEndPos = a:errPos - endif -endfu - -" ident() {{{2 -" Ident = IDENTIFIER -fu! s:ident() - call s:Trace('s:ident ' . b:token) - - if b:token == 'IDENTIFIER' - let name = b:name - call s:nextToken() - return name - - elseif b:token == 'ASSERT' - if s:allowAsserts - call s:Log(4, b:pos, 'assert.as.identifier') - call s:nextToken() - return '<error>' - else - call s:Log(3, b:pos, 'assert.as.identifier') - let name = b:name - call s:nextToken() - return name - endif - - elseif b:token == 'ENUM' - if b:allowEnums - call s:Log(4, b:pos, 'enum.as.identifier') - call s:nextToken() - return '<error>' - else - call s:Log(3, b:pos, 'enum.as.identifier') - let name = b:name - call s:nextToken() - return name - endif - - else - call s:accept('IDENTIFIER') - return '<error>' - endif -endfu - -" qualident() {{{2 -" Qualident = Ident { DOT Ident } -fu! s:qualident() - let t = s:Ident(b:pos, s:ident()) - while b:token == 'DOT' - let pos = b:pos - call s:nextToken() - let t = s:Select(b:pos, t, s:ident()) - "let t.name .= '.' . s:ident() " FIXME - endwhile - return t -endfu - -" literal() {{{2 -" Literal = INTLITERAL | LONGLITERAL | FLOATLITERAL | DOUBLELITERAL | CHARLITERAL | STRINGLITERAL | TRUE | FALSE | NULL -fu! s:literal(prefix) - let t = {'tag': 'LITERAL', 'pos': b:pos} - if b:token == 'INTLITERAL' - let t.typetag = 'INT' - let t.value = b:sbuf - elseif b:token == 'LONGLITERAL' - let t.typetag = 'LONG' - let t.value = b:sbuf - elseif b:token == 'FLOATLITERAL' - let t.typetag = 'FLOAT' - let t.value = b:sbuf - elseif b:token == 'DOUBLELITERAL' - let t.typetag = 'DOUBLE' - let t.value = b:sbuf - elseif b:token == 'CHARLITERAL' - let t.typetag = 'CHAR' - let t.value = b:sbuf - elseif b:token == 'STRINGLITERAL' - let t.typetag = 'CLASS' - let t.value = b:sbuf - elseif b:token == 'TRUE' - let t.typetag = 'BOOLEAN' - let t.value = 1 - elseif b:token == 'FALSE' - let t.typetag = 'BOOLEAN' - let t.value = 0 - elseif b:token == 'NULL' - let t.typetag = 'BOT' - let t.value = 'null' - else - echoerr 'can not reach here' - endif - call s:nextToken() - return t -endfu - -" {{{2 -" terms, expression, type {{{2 -" When terms are parsed, the mode determines which is expected: -" mode = EXPR : an expression -" mode = TYPE : a type -" mode = NOPARAMS : no parameters allowed for type -" mode = TYPEARG : type argument -let s:EXPR = 1 -let s:TYPE = 2 -let s:NOPARAMS = 4 -let s:TYPEARG = 8 -let s:EXPR_OR_TYPE = 3 -let s:EXPR_OR_TYPE_OR_NOPARAMS = 7 -let s:TYPEARG_OR_NOPARAMS = 12 - -fu! s:modeAndEXPR() - return b:mode % 2 -endfu - -fu! s:modeAndTYPE() - return s:BitAnd(b:mode, s:TYPE) -endfu - -" terms can be either expressions or types. -fu! s:expression() - return s:term(s:EXPR) -endfu - -fu! s:type() - return s:term(s:TYPE) -endfu - -fu! s:typeList() - let ts = [] - call add(ts, s:type()) - while b:token == 'COMMA' - call s:nextToken() - call add(ts, s:type()) - endwhile - return ts -endfu - -" Expression = Expression1 [ExpressionRest] -" ExpressionRest = [AssignmentOperator Expression1] -" AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "&=" | "|=" | "^=" | -" "%=" | "<<=" | ">>=" | ">>>=" -" Type = Type1 -" TypeNoParams = TypeNoParams1 -" StatementExpression = Expression -" ConstantExpression = Expression -fu! s:term(...) - let prevmode = b:mode - let b:mode = a:0 == 0 ? b:mode : a:1 - - let t = s:term1() - if s:modeAndEXPR() && b:token == 'EQ' || b:token =~# '^\(PLUSEQ\|SUBEQ\|STAREQ\|SLASHEQ\|AMPEQ\|BAREQ\|CARETEQ\|PERCENTEQ\|LTLTEQ\|GTGTEQ\|GTGTGTEQ\)$' - let t = s:termRest(t) - endif - - let b:lastmode = b:mode - let b:mode = prevmode - return t -endfu - -fu! s:termRest(t) - if b:token == 'EQ' - let pos = b:pos - call s:nextToken() - let b:mode = s:EXPR - return {'tag': 'ASSIGN', 'pos': pos, 'lhs': a:t, 'rhs': s:term()} - - elseif b:token =~# '^\(PLUSEQ\|SUBEQ\|STAREQ\|SLASHEQ\|PERCENTEQ\|AMPEQ\|BAREQ\|CARETEQ\|LTLTEQ\|GTGTEQ\|GTGTGTEQ\)$' - let pos = b:pos - let token = b:token - call s:nextToken() - let b:mode = s:EXPR - return {'tag': s:optag(token), 'pos': pos, 'lhs': a:t, 'rhs': s:term()} - - else - return a:t - endif -endfu - -" Expression1 = Expression2 [Expression1Rest] -" Type1 = Type2 -" TypeNoParams1 = TypeNoParams2 -fu! s:term1() - let t = s:term2() - if s:modeAndEXPR() && b:token == 'QUES' - let b:mode = s:EXPR - return s:term1Rest(t) - else - return t - endif -endfu - -" Expression1Rest = ["?" Expression ":" Expression1] -fu! s:term1Rest(t) - if b:token == 'QUES' - let t = {'tag': 'CONDEXPR', 'pos': b:pos, 'cond': a:t} - call s:nextToken() - let t.truepart = s:term() - call s:accept('COLON') - let t.falsepart = s:term1() - return t - else - return a:t - endif -endfu - -" Expression2 = Expression3 [Expression2Rest] -" Type2 = Type3 -" TypeNoParams2 = TypeNoParams3 -fu! s:term2() - let t = s:term3() - if s:modeAndEXPR() && s:prec(b:token) >= s:opprecedences.orPrec - let b:mode = s:EXPR - return s:term2Rest(t, s:opprecedences.orPrec) - else - return t - endif -endfu - -" Expression2Rest = {infixop Expression3} -"" | Expression3 instanceof Type -" infixop = "||" -" | "&&" -" | "|" -" | "^" -" | "&" -" | "==" | "!=" -" | "<" | ">" | "<=" | ">=" -" | "<<" | ">>" | ">>>" -" | "+" | "-" -" | "*" | "/" | "%" -fu! s:term2Rest(t, minprec) - let odStack = [a:t] " for expressions - let opStack = [] " for tokens - let top = 0 - let startPos = b:pos - let topOp = 'ERROR' - while s:prec(b:token) >= a:minprec - call add(opStack, topOp) - let top += 1 - let topOp = b:token - let pos = b:pos - call s:nextToken() - call add(odStack, topOp == 'INSTANCEOF' ? s:type() : s:term3()) - while top > 0 && s:prec(topOp) >= s:prec(b:token) - let odStack[top-1] = s:makeOp(pos, topOp, odStack[top-1], odStack[top]) - let top -= 1 - let topOp = opStack[top] - endwhile - endwhile - "assert top == 0 - let t = odStack[0] - - if t.tag == 'PLUS' - let buf = s:foldStrings(t) - if buf != '' - let t = {'tag': 'LITERAL', 'pos': startPos, 'typetag': 'CLASS', 'value': t} - endif - endif - return t -endfu - -fu! s:makeOp(pos, topOp, od1, od2) - if a:topOp == 'INSTANCEOF' - return {'tag': 'TYPETEST', 'pos': a:pos, 'expr': a:od1, 'clazz': a:od2} - else - return s:Binary(a:pos, s:optag(a:topOp), a:od1, a:od2) - endif -endfu - -fu! s:foldStrings(tree) - let tree = a:tree - let buf = '' - while 1 - if tree.tag == 'LITERAL' - let lit = tree - if lit.typetag == 'CLASS' - let sbuf = lit.value - if buf != '' - let sbuf .= buf - endif - return sbuf - endif - elseif tree.tag == 'PLUS' - let op = tree - if op.rhs.tag == 'LITERAL' - let lit = op.rhs - if lit.typetag == 'CLASS' - let buf = lit.value . buf - let tree = op.lhs - continue - endif - endif - endif - return '' - endwhile -endfu - -" Expression3 = PrefixOp Expression3 {{{2 -" | "(" Expr | TypeNoParams ")" Expression3 -" | Primary {Selector} {PostfixOp} -" Primary = "(" Expression ")" -" | Literal -" | [TypeArguments] THIS [Arguments] -" | [TypeArguments] SUPER SuperSuffix -" | NEW [TypeArguments] Creator -" | Ident { "." Ident } -" [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) -" | Arguments -" | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) -" ] -" | BasicType BracketsOpt "." CLASS -" PrefixOp = "++" | "--" | "!" | "~" | "+" | "-" -" PostfixOp = "++" | "--" -" Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt -" | BasicType -" TypeNoParams3 = Ident { "." Ident } BracketsOpt -" Selector = "." [TypeArguments] Ident [Arguments] -" | "." THIS -" | "." [TypeArguments] SUPER SuperSuffix -" | "." NEW [TypeArguments] InnerCreator -" | "[" Expression "]" -" TypeSelector = "." Ident [TypeArguments] -" SuperSuffix = Arguments | "." Ident [Arguments] -" NOTE: We need only type expression. -fu! s:term3() - let pos = b:pos - let t = copy(s:TTree) - - call s:Debug('term3() b:token is ' . b:token) - let typeArgs = s:typeArgumentsOpt(s:EXPR) - - if b:token == 'QUES' - if s:modeAndTYPE() && s:BitAnd(b:mode, s:TYPEARG_OR_NOPARAMS) == s:TYPEARG - let b:mode = s:TYPE - return s:typeArgument() - else - return s:illegal() - endif - - elseif b:token =~# '^\(PLUSPLUS\|SUBSUB\|BANG\|TILDE\|PLUS\|SUB\)$' - if typeArgs == [] && s:modeAndEXPR() - let token = b:token - call s:nextToken() - let b:mode = s:EXPR - if token == 'SUB' && (b:token == 'INTLITERAL' || b:token == 'LONGLITERAL') && b:radix == 10 - let b:mode = s:EXPR - let t = s:literal('-') - else - let t = s:term3() - return s:Unary(pos, s:unoptag(token), t) - endif - else - return s:illegal() - endif - - elseif b:token == 'LPAREN' - if typeArgs == [] && s:modeAndEXPR() - call s:nextToken() - let b:mode = s:EXPR_OR_TYPE_OR_NOPARAMS - let t = s:term3() - if s:modeAndEXPR() && b:token == 'LT' - let op = 'LT' - let pos1 = b:pos - call s:nextToken() - let b:mode = s:BitAnd(b:mode, s:EXPR_OR_TYPE) - let b:mode = s:BitOr(b:mode, s:TYPEARG) - let t1 = s:term3() - if s:modeAndTYPE() && (b:token == 'COMMA' || b:token == 'GT') - let b:mode = s:TYPE - let args = [] - call add(args, t1) - while b:token == 'COMMA' - call s:nextToken() - call add(args, s:typeArgument()) - endwhile - call s:accept('GT') - let t = {'tag': 'TYPEAPPLY', 'pos': pos1, 'clazz': t, 'arguments': args} - " checkGenerics - let t = s:bracketsOpt(t) - elseif s:modeAndEXPR() - let b:mode = s:EXPR - let t = s:Binary(pos1, op, t, s:term2Rest(t1, s:opprecedences.shiftPrec)) - let t = s:termRest(s:term1Rest(s:term2Rest(t, s:opprecedences.orPrec))) - else - call s:accept('GT') - endif - else - let t = s:termRest(s:term1Rest(s:term2Rest(t, s:opprecedences.orPrec))) - endif - call s:accept('RPAREN') - let b:lastmode = b:mode - let b:mode = s:EXPR - if s:BitAnd(b:lastmode, s:EXPR) == 0 - return s:TypeCast(pos, t, s:term3()) - elseif s:BitAnd(b:lastmode, s:TYPE) != 0 - if b:token =~# '^\(BANG\|TILDE\|LPAREN\|THIS\|SUPER\|INTLITERAL\|LONGLITERAL\|FLOATLITERAL\|DOUBLELITERAL\|CHARLITERAL\|STRINGLITERAL\|TRUE\|FALSE\|NULL\|NEW\|IDENTIFIER\|ASSERT\|ENUM\|BYTE\|SHORT\|CHAR\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\|VOID\)$' - return s:TypeCast(pos, t, s:term3()) - endif - endif - else - return s:illegal() - endif - let t = {'tag': 'PARENS', 'pos': pos, 'expr': t} - - elseif b:token == 'THIS' - if s:modeAndEXPR() - let b:mode = s:EXPR - let t = s:Ident(pos, 'this') - call s:nextToken() - if typeArgs == [] - let t = s:argumentsOpt([], t) - else - let t = s:arguments(typeArgs, t) - endif - let typeArgs = [] - else - return s:illegal() - endif - - elseif b:token == 'SUPER' - if s:modeAndEXPR() - let b:mode = s:EXPR - let t = s:superSuffix(typeArgs, s:Ident(pos, 'super')) - let typeArgs = [] - else - return s:illegal() - endif - - elseif b:token =~# '^\(INTLITERAL\|LONGLITERAL\|FLOATLITERAL\|DOUBLELITERAL\|CHARLITERAL\|STRINGLITERAL\|TRUE\|FALSE\|NULL\)$' - if typeArgs == [] && s:modeAndEXPR() - let b:mode = s:EXPR - let t = s:literal('') - else - return s:illegal() - endif - - elseif b:token == 'NEW' - if typeArgs != [] - return s:illegal() - endif - - if s:modeAndEXPR() - let b:mode = s:EXPR - call s:nextToken() - if b:token == 'LT' - let typeArgs = s:typeArguments() - endif - let t = s:creator(pos, typeArgs) - let typeArgs = [] - else - return s:illegal() - endif - - elseif b:token =~# '^\(IDENTIFIER\|ASSERT\|ENUM\)$' - if typeArgs != [] - return s:illegal() - endif - - let t = s:Ident(pos, s:ident()) - while 1 - if b:token == 'LBRACKET' - "let t.value = '[' " FIXME - call s:nextToken() - if b:token == 'RBRACKET' - "let t.value .= ']' - call s:nextToken() - let t = s:bracketsSuffix(s:TypeArray(pos, s:bracketsOpt(t))) - else - if s:modeAndEXPR() - let b:mode = s:EXPR - let t = {'tag': 'INDEXED', 'pos': pos, 'indexed': t, 'index': s:term()} - endif - call s:accept('RBRACKET') - "let t.value .= ']' - endif - break - - elseif b:token == 'LPAREN' - if s:modeAndEXPR() - let b:mode = s:EXPR - let t = s:arguments(typeArgs, t) - let typeArgs = [] - "call s:accept('LPAREN') - "call s:gotoMatchEnd('(', ')', b:token == 'LPAREN') - "call s:accept('RPAREN') - endif - break - - elseif b:token == 'DOT' - call s:nextToken() - let typeArgs = s:typeArgumentsOpt(s:EXPR) - if s:modeAndEXPR() - if b:token == 'CLASS' || b:token == 'THIS' - if typeArgs != [] - return s:illegal() - endif - let b:mode = s:EXPR - let t = s:Select(pos, t, b:token == 'CLASS' ? 'class' : 'this') - call s:nextToken() - break - elseif b:token == 'SUPER' - let b:mode = s:EXPR - let t = s:Select(pos, t, 'super') - let t = s:superSuffix(typeArgs, t) - let typeArgs = [] - break - elseif b:token == 'NEW' - if typeArgs != [] - return s:illegal() - endif - let b:mode = s:EXPR - let pos1 = b:pos - call s:nextToken() - if b:token == 'LT' - let typeArgs = s:typeArguments() - endif - let t = s:innerCreator(pos1, typeArgs, t) - let typeArgs = [] - break - endif - endif - let t = s:Select(pos, t, s:ident()) - else - break - endif - endwhile - if typeArgs != [] | call s:illegal() | endif - let t = s:typeArgumentsOpt2(t) - - elseif b:token =~# '^\(BYTE\|SHORT\|CHAR\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\)$' - if typeArgs != [] | call s:illegal() | endif - let t = s:bracketsSuffix(s:bracketsOpt(s:basicType())) - - elseif b:token == 'VOID' - if typeArgs != [] | call s:illegal() | endif - if s:modeAndEXPR() - call s:nextToken() - if b:token == 'DOT' - let ti = {'tag': 'TYPEIDENT', 'pos': pos, 'typetag': 'void'} " FIXME - let t = s:bracketsSuffix(ti) - else - return s:illegal(pos) - endif - else - return s:illegal() - endif - - else - return s:illegal() - endif - - if typeArgs != [] - return s:illegal() - endif - - while 1 - let pos1 = b:pos - if b:token == 'LBRACKET' - call s:nextToken() - if s:modeAndEXPR() - let oldmode = b:mode - let b:mode = s:TYPE - if b:token == 'RBRACKET' - call s:nextToken() - let t = s:bracketsOpt(t) - let t = s:TypeArray(pos1, t) - return t - endif - let b:mode = oldmode - endif - if s:modeAndEXPR() - let b:mode = s:EXPR - let t = {'tag': 'INDEXED', 'pos': pos1, 'indexed': t, 'index': s:term()} - endif - call s:accept('RBRACKET') - - elseif b:token == 'DOT' - call s:nextToken() - let typeArgs = s:typeArgumentsOpt(s:EXPR) - if b:token == 'SUPER' && s:modeAndEXPR() - let b:mode = s:EXPR - let t = s:Select(pos1, t, 'super') - call s:nextToken() - let t = s:arguments(typeArgs, t) - let typeArgs = [] - elseif b:token == 'NEW' && s:modeAndEXPR() - if typeArgs != [] - return s:illegal() - endif - let b:mode = s:EXPR - let pos2 = b:pos - call s:nextToken() - if b:token == 'LT' - let typeArgs = s:typeArguments() - endif - let t = s:innerCreator(pos2, typeArgs, t) - let typeArgs = [] - else - let t = s:Select(pos1, t, s:ident()) - let t = s:argumentsOpt(typeArgs, s:typeArgumentsOpt2(t)) - let typeArgs = [] - endif - else - break - endif - endwhile - - - while (b:token == 'PLUSPLUS' || b:token == 'SUBSUB') && s:modeAndEXPR() - let b:mode = s:EXPR - let t = s:Unary(b:pos, b:token == 'PLUSPLUS' ? 'POSTINC' : 'POSTDEC', t) - call s:nextToken() - endwhile - return t -endfu - -fu! s:superSuffix(typeArgs, t) - let typeArgs = a:typeArgs - let t = a:t - call s:nextToken() - if b:token == 'LPAREN' || typeArgs != [] - let t = s:arguments(typeArgs, t) - else - let pos = b:pos - call s:accept('DOT') - let typeArgs = b:token == 'LT' ? s:typeArguments() : [] - let t = s:Select(pos, t, s:ident()) - let t = s:argumentsOpt(typeArgs, t) - endif - return t -endfu - -" BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN {{{2 -fu! s:basicType() - let t = {'tag': 'TYPEIDENT', 'pos': b:pos, 'typetag': s:typetag(b:token)} - call s:nextToken() - return t -endfu - -" ArgumentsOpt = [ Arguments ] {{{2 -fu! s:argumentsOpt(typeArgs, t) - if s:modeAndEXPR() && b:token == 'LPAREN' || a:typeArgs != [] - let b:mode = s:EXPR - return s:arguments(a:typeArgs, a:t) - else - return a:t - endif -endfu - -" Arguments = "(" [Expression { COMMA Expression }] ")" -fu! s:arguments(...) - let pos = b:pos - let args = [] - if b:token == 'LPAREN' - call s:nextToken() - if b:token != 'RPAREN' - call add(args, s:expression()) - while b:token == 'COMMA' - call s:nextToken() - call add(args, s:expression()) - endwhile - endif - call s:accept('RPAREN') - else - call s:SyntaxError(') expected') - endif - - if a:0 == 0 - return args - else - let typeArgs = a:1 - let t = a:2 - return {'tag': 'APPLY', 'pos': pos, 'typeargs': typeArgs, 'meth': t, 'args': args} - endif -endfu - -" typeArgument generic type {{{2 -fu! s:typeArgumentsOpt2(t) - if b:token == 'LT' && s:modeAndTYPE() && s:BitAnd(b:mode, s:NOPARAMS) == 0 - let b:mode = s:TYPE - " checkGenerics() - return s:typeArguments(a:t) - else - return a:t - endif -endfu - -fu! s:typeArgumentsOpt(...) - let useMode = a:0 == 0 ? s:TYPE : a:1 - - if b:token == 'LT' - " checkGenerics() - if s:BitAnd(b:mode, useMode) == 0 || s:BitAnd(b:mode, s:NOPARAMS) != 0 - return s:illegal() - endif - let b:mode = useMode - return s:typeArguments() - endif - return [] -endfu - -" TypeArguments = "<" TypeArgument {"," TypeArgument} ">" -fu! s:typeArguments(...) - let pos = b:pos - - let args = [] - if b:token == 'LT' - call s:nextToken() - call add(args, s:modeAndEXPR() ? s:type() : s:typeArgument()) - while b:token == 'COMMA' - call s:nextToken() - call add(args, s:modeAndEXPR() ? s:type() : s:typeArgument()) - endwhile - - if b:token == 'GTGTGTEQ' - let b:token = 'GTGTEQ' - elseif b:token == 'GTGTEQ' - let b:token = 'GTEQ' - elseif b:token == 'GTEQ' - let b:token = 'EQ' - elseif b:token == 'GTGTGT' - let b:token = 'GTGT' - elseif b:token == 'GTGT' - let b:token = 'GT' - else - call s:accept('GT') - endif - else - call s:SyntaxError("LT expected") - endif - - if a:0 == 0 - return args - else - return {'tag': 'TYPEAPPLY', 'pos': pos, 'clazz': a:1, 'arguments': args} - endif -endfu - -" TypeArgument = Type -" | "?" -" | "?" EXTENDS Type {"&" Type} -" | "?" SUPER Type -fu! s:typeArgument() - if b:token != 'QUES' - return s:type() - endif - - call s:nextToken() - if b:token == 'EXTENDS' - call s:nextToken() - return s:type() - elseif b:token == 'SUPER' - call s:nextToken() - return s:type() - elseif b:token == 'IDENTIFIER' - let id = ident() - else - endif -endfu - - -" BracketsOpt = {"[" "]"} {{{2 -fu! s:bracketsOpt(t) - let t = a:t - while b:token == 'LBRACKET' - let pos = b:pos - call s:nextToken() - let t = s:bracketsOptCont(t, pos) - endwhile - return t -endfu - -fu! s:bracketsOptCont(t, pos) - let t = a:t - call s:accept('RBRACKET') - let t = s:bracketsOpt(t) - return s:TypeArray(a:pos, t) -endfu - -" BracketsSuffixExpr = "." CLASS -" BracketsSuffixType = -fu! s:bracketsSuffix(t) - let t = a:t - if s:modeAndEXPR() && b:token == 'DOT' - let b:mode = s:EXPR - let pos = b:pos - call s:nextToken() - call s:accept('CLASS') - if b:pos == b:errorEndPos - let name = '' - if b:token == 'IDENTIFIER' - let name = b:name - call s:nextToken() - else - let name = '<error>' - endif - let t = {'tag': 'ERRONEOUS', 'pos': pos, 'errs': [s:Select(pos, t, name)]} - else - let t = s:Select(pos, t, 'class') - endif - elseif s:modeAndTYPE() - let b:mode = s:TYPE - else - call s:SyntaxError('dot.class.expected') - endif - return t -endfu - -" creator {{{2 -fu! s:creator(newpos, typeArgs) - if b:token =~# '^\(BYTE\|SHORT\|CHAR\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\)$' - if a:typeArgs == [] - return s:arrayCreatorRest(a:newpos, s:basicType()) - endif - endif - - let t = s:qualident() - let oldmode = b:mode - let b:mode = s:TYPE - if b:token == 'LT' - "checkGenerics - let t = s:typeArguments(t) - endif - let b:mode = oldmode - - if b:token == 'LBRACKET' - return s:arrayCreatorRest(a:newpos, t) - elseif b:token == 'LPAREN' - return s:classCreatorRest(a:newpos, {}, a:typeArgs, t) - else - call s:ReportSyntaxError(b:pos, '( or [ expected') - let t = {'tag': 'NEWCLASS', 'encl': {}, 'typeargs': a:typeArgs, 'clazz': t, 'args': [], 'def': {}} - return {'tag': 'ERRONEOUS', 'pos': a:newpos, 'errs': [t]} - endif -endfu - -fu! s:innerCreator(newpos, typeArgs, encl) - let t = s:Ident(b:pos, s:ident()) - if b:token == 'LT' - " checkGenerics - let t = TypeArguments(t) - endif - return s:classCreatorRest(a:newpos, a:encl, a:typeArgs, t) -endfu - -fu! s:arrayCreatorRest(newpos, elemtype) - let elemtype = a:elemtype - call s:accept('LBRACKET') - if b:token == 'RBRACKET' - call s:accept('RBRACKET') - let elemtype = s:bracketsOpt(elemtype) - if b:token == 'LBRACE' - return s:arrayInitializer(a:newpos, elemtype) - else - return s:SyntaxError('array.dimension.missing') - endif - else - let dims = [s:expression()] - call s:accept('RBRACKET') - while b:token == 'LBRACKET' - let pos = b:pos - call s:nextToken() - if b:token == 'RBRACKET' - let elemtype = s:bracketsOptCont(elemtype, pos) - else - call add(dims, s:expression()) - call s:accept('RBRACKET') - endif - endwhile - return {'tag': 'NEWARRAY', 'pos': a:newpos, 'elemtype': elemtype, 'dims': dims, 'elems': {}} - endif -endfu - -fu! s:classCreatorRest(newpos, encl, typeArgs, t) - let args = s:arguments() - let body = {} - if b:token == 'LBRACE' - let body = s:ClassDef(b:pos, {}) - let body.defs = s:classOrInterfaceBody('', 0) - let body.endpos = b:pos - endif - return {'tag': 'NEWCLASS', 'encl': a:encl, 'typeargs': a:typeArgs, 'clazz': a:t, 'args': args, 'def': body} -endfu - -" ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" {{{2 -fu! s:arrayInitializer(newpos, t) - call s:accept('LBRACE') - let elems = [] - if b:token == 'COMMA' - call s:nextToken() - elseif b:token != 'RBRACE' - call add(elems, s:variableInitializer()) - while b:token == 'COMMA' - call s:nextToken() - if b:token == 'RBRACE' - break - endif - call add(elems, s:variableInitializer()) - endwhile - endif - call s:accept('RBRACE') - return {'tag': 'NEWARRAY', 'pos': a:newpos, 'elemtype': a:t, 'dims': [], 'elems': elems} -endfu - -" VariableInitializer = ArrayInitializer | Expression {{{2 -fu! s:variableInitializer() - return b:token == 'LBRACE' ? s:arrayInitializer(b:pos, {}) : s:expression() -endfu - -" ParExpression = "(" Expression ")" {{{2 -fu! s:parExpression() - call s:accept('LPAREN') - let t = s:expression() - call s:accept('RPAREN') - return t -endfu - -" {{{2 -" Block = "{" BlockStatements "}" {{{2 -fu! s:block(...) - let t = {'tag': 'BLOCK', 'stats': []} - let t.pos = a:0 > 0 ? a:1 : b:pos - let t.flags = a:0 > 1 ? a:2 : 0 - - call s:accept('LBRACE') - - " scan strategy: ignore statements? - if a:0 > 2 && a:3 - if b:token !=# 'RBRACE' - let b:pos = s:gotoMatchEnd('{', '}', b:token == 'LBRACE') - endif - "let t.stats = Strpart(t.pos, t.endpos-t.pos-1) - else - let t.stats = s:blockStatements() - while b:token == 'CASE' || b:token == 'DEFAULT' - call s:SyntaxError("orphaned") - call s:switchBlockStatementGroups() - endwhile - endif - - let t.endpos = b:pos - call s:accept('RBRACE') - return t -endfu - -" BlockStatements = { BlockStatement } {{{2 -" BlockStatement = LocalVariableDeclarationStatement -" | ClassOrInterfaceOrEnumDeclaration -" | [Ident ":"] Statement -" LocalVariableDeclarationStatement -" = { FINAL | '@' Annotation } Type VariableDeclarators ";" -fu! s:blockStatements() - let lastErrPos = -1 - let stats = [] - while 1 - let pos = b:pos - if b:token =~# '^\(RBRACE\|CASE\|DEFAULT\|EOF\)$' - return stats - elseif b:token =~# '^\(LBRACE\|IF\|FOR\|WHILE\|DO\|TRY\|SWITCH\|SYNCHRONIZED\|RETURN\|THROW\|BREAK\|CONTINUE\|SEMI\|ELSE\|FINALLY\|CATCH\)$' - call add(stats, s:statement()) - elseif b:token =~# '^\(MONKEYS_AT\|FINAL\)' - let dc = b:docComment - let mods = s:modifiersOpt() - if b:token =~# '^\(INTERFACE\|CLASS\|ENUM\)$' - call add(stats, s:classOrInterfaceOrEnumDeclaration(mods, dc)) - else - let t = s:type() - let stats = stats + s:variableDeclarators(mods, t, []) - call s:accept('SEMI') - endif - elseif b:token =~# '^\(ABSTRACT\|STRICTFP\|CLASS\|INTERFACE\|ENUM\)$' - if b:token == 'ENUM' - call s:Log(4, b:pos, 'local.enum') - endif - call add(stats, s:classOrInterfaceOrEnumDeclaration(s:modifiersOpt(), b:docComment)) - elseif b:token == 'ASSERT' - call add(stats, s:statement()) - else - let name = b:name - let t = s:term(s:EXPR_OR_TYPE) - if b:token == 'COLON' && t.tag == 'IDENT' - call s:nextToken() - let stat = s:statement() - call add(stats, {'tag': 'LABELLED', 'pos': b:pos, 'label': name, 'body': stat}) - elseif s:BitAnd(b:lastmode, s:TYPE) && b:token =~# '^\(IDENTIFIER\|ASSERT\|ENUM\)$' - let pos = b:pos - let mods = {} " {'tag': 'MODIFIERS', 'pos': -1, 'flags': 0} - let stats = stats + s:variableDeclarators(mods, t, []) - call s:accept('SEMI') - else - call add(stats, {'tag': 'EXEC', 'pos': pos, 'expr': s:checkExprStat(t)}) " TODO - call s:accept('SEMI') - endif - endif - - if b:pos == lastErrPos - return stats - endif - if b:pos <= b:errorEndPos - call s:skip(0, 1, 1, 1) - let lastErrPos = b:pos - endif - - " resetDeprecatedFlag() - endwhile -endfu - -" Statement = Block {{{2 -" | IF ParExpression Statement [ELSE Statement] -" | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement -" | FOR "(" FormalParameter : Expression ")" Statement -" | WHILE ParExpression Statement -" | DO Statement WHILE ParExpression ";" -" | TRY Block ( Catches | [Catches] FinallyPart ) -" | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" -" | SYNCHRONIZED ParExpression Block -" | RETURN [Expression] ";" -" | THROW Expression ";" -" | BREAK [Ident] ";" -" | CONTINUE [Ident] ";" -" | ASSERT Expression [ ":" Expression ] ";" -" | ";" -" | ExpressionStatement -" | Ident ":" Statement -" called only by BlockStatements or self -fu! s:statement() - let pos = b:pos - if b:token == 'LBRACE' - return s:block() - elseif b:token == 'IF' - call s:nextToken() - let t = {'tag': 'IF', 'pos': pos, 'cond': s:parExpression(), 'thenpart': s:statement()} - if b:token == 'ELSE' - call s:nextToken() - let t.elsepart = s:statement() - endif - let t.endpos = b:pos - return t - - elseif b:token == 'FOR' - call s:nextToken() - call s:accept('LPAREN') - let inits = b:token == 'SEMI' ? [] : s:forInit() - " foreach - if len(inits) == 1 && inits[0].tag == 'VARDEF' && (!has_key(inits[0], 'init') || inits[0].init == {}) && b:token == 'COLON' - " checkForeach - let var = inits[0] - call s:accept('COLON') - let expr = s:expression() - call s:accept('RPAREN') - let body = s:statement() - return {'tag': 'FOREACHLOOP', 'pos': pos, 'endpos': b:pos, 'var': var, 'expr': expr, 'body': body} - else - call s:accept('SEMI') - let cond = b:token == 'SEMI' ? {} : s:expression() - call s:accept('SEMI') - let steps = b:token == 'RPAREN' ? [] : s:forUpdate() - call s:accept('RPAREN') - let body = s:statement() - return {'tag': 'FORLOOP', 'pos': pos, 'endpos': b:pos, 'init': inits, 'cond': cond, 'step': steps, 'body': body} - endif - - elseif b:token == 'WHILE' - call s:nextToken() - let cond = s:parExpression() - let body = s:statement() - return {'tag': 'WHILELOOP', 'pos': pos, 'endpos': b:pos, 'cond': cond, 'body': body} - - elseif b:token == 'DO' - call s:nextToken() - let body = s:statement() - call s:accept('WHILE') - let cond = s:parExpression() - let t = {'tag': 'DOLOOP', 'pos': pos, 'endpos': b:pos, 'cond': cond, 'body': body} - call s:accept('SEMI') - return t - - elseif b:token == 'TRY' - call s:nextToken() - let body = s:block() - let catchers = [] - let finalizer = {} - if b:token == 'CATCH' || b:token == 'FINALLY' - while b:token == 'CATCH' - call add(catchers, s:catchClause()) - endwhile - if b:token == 'FINALLY' - call s:nextToken() - let finalizer = s:block() - endif - else - call s:Log(4, b:pos, 'try.without.catch.or.finally') - endif - return {'tag': 'TRY', 'pos': pos, 'endpos': b:pos, 'body': body, 'catchers': catchers, 'finalizer': finalizer} - - elseif b:token == 'SWITCH' - call s:nextToken() - let selector = s:parExpression() - call s:accept('LBRACE') - let cases = s:switchBlockStatementGroups() - call s:accept('RBRACE') - return {'tag': 'SWITCH', 'pos': pos, 'endpos': b:pos, 'selector': selector, 'cases': cases} - - elseif b:token == 'SYNCHRONIZED' - call s:nextToken() - let lock = s:parExpression() - let body = s:block() - return {'tag': 'SYNCHRONIZED', 'pos': pos, 'endpos': b:pos, 'lock': lock, 'cases': body} - - elseif b:token == 'RETURN' - call s:nextToken() - let result = b:token == 'SEMI' ? {} : s:expression() - call s:accept('SEMI') - return {'tag': 'RETURN', 'pos': pos, 'endpos': b:pos, 'expr': result} - - elseif b:token == 'THROW' - call s:nextToken() - let exc = s:expression() - call s:accept('SEMI') - return {'tag': 'THROW', 'pos': pos, 'endpos': b:pos, 'expr': exc} - - elseif b:token == 'BREAK' || b:token == 'CONTINUE' - let token = b:token - call s:nextToken() - let label = b:token =~# '^\(IDENTIFIER\|ASSERT\|ENUM\)$' ? s:ident() : '' - call s:accept('SEMI') - return {'tag': token, 'pos': pos, 'endpos': b:pos, 'label': label} - - elseif b:token == 'SEMI' - call s:nextToken() - return {'tag': 'SKIP', 'pos': pos} - - elseif b:token == 'ELSE' - return s:SyntaxError("else.without.if") - elseif b:token == 'FINALLY' - return s:SyntaxError("finally.without.try") - elseif b:token == 'CATCH' - return s:SyntaxError("catch.without.try") - - elseif b:token == 'ASSERT' - "if b:allowAsserts && b:token == 'ASSERT' - call s:nextToken() - let t = {'tag': 'ASSERT', 'pos': pos, 'cond': s:expression()} - if b:token == 'COLON' - call s:nextToken() - let t.detail = s:expression() - endif - call s:accept('SEMI') - let t.endpos = b:pos - return t - "endif - - else " also ENUM - let name = b:name - let expr = s:expression() - if b:token == 'COLON' && expr.tag == 'IDENT' - call s:nextToken() - let stat = s:statement() - return {'tag': 'LABELLED', 'pos': pos, 'endpos': b:pos, 'label': name, 'body': stat} - else - let stat = {'tag': 'EXEC', 'pos': pos, 'endpos': b:pos, 'expr': s:checkExprStat(expr)} - call s:accept('SEMI') - return stat - endif - endif -endfu - -" CatchClause = CATCH "(" FormalParameter ")" Block -fu! s:catchClause() - let pos = b:pos - call s:accept('CATCH') - call s:accept('LPAREN') - let formal = s:variableDeclaratorId(s:optFinalParameter(), s:qualident()) - call s:accept('RPAREN') - let body = s:block() - return {'tag': 'CATCH', 'pos': pos, 'endpos': b:pos, 'param': formal, 'body': body} -endfu - -" SwitchBlockStatementGroups = { SwitchBlockStatementGroup } -" SwitchBlockStatementGroup = SwitchLabel BlockStatements -" SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" -fu! s:switchBlockStatementGroups() - let cases = [] - while 1 - let pos = b:pos - if b:token == 'CASE' || b:token == 'DEFAULT' - let token = b:token - call s:nextToken() - let pat = token == 'CASE' ? s:expression() : {} - call s:accept('COLON') - let stats = s:blockStatements() - call add(cases, {'tag': 'CASE', 'pos': pos, 'pat': pat, 'stats': stats}) - elseif b:token == 'RBRACE' || b:token == 'EOF' - return cases - else - call s:nextToken() - call s:SyntaxError('case.default.rbrace.expected') - endif - endwhile -endfu - -" MoreStatementExpressions = { COMMA StatementExpression } -fu! s:moreStatementExpressions(pos, first, stats) - call add(a:stats, {'tag': 'EXEC', 'pos': a:pos, 'expr': s:checkExprStat(a:first)}) - while b:token == 'COMMA' - call s:nextToken() - let pos = b:pos - let t = s:expression() - call add(a:stats, {'tag': 'EXEC', 'pos': pos, 'expr': s:checkExprStat(t)}) - endwhile - return a:stats -endfu - -" ForInit = StatementExpression MoreStatementExpressions -" | { FINAL | '@' Annotation } Type VariableDeclarators -fu! s:forInit() - let stats = [] - let pos = b:pos - if b:token == 'FINAL' || b:token == 'MONKEYS_AT' - return s:variableDeclarators(s:optFinal(0), s:type(), stats) - else - let t = s:term(s:EXPR_OR_TYPE) - if s:BitAnd(b:lastmode, s:TYPE) && b:token =~# '^\(IDENTIFIER\|ASSERT\|ENUM\)$' - return s:variableDeclarators(s:modifiersOpt(), t, stats) - else - return s:moreStatementExpressions(pos, t, stats) - endif - endif -endfu - -" ForUpdate = StatementExpression MoreStatementExpressions -fu! s:forUpdate() - return s:moreStatementExpressions(b:pos, s:expression(), []) -endfu - -" ModifiersOpt = { Modifier } {{{2 -" Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL -" | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" -" | "@" Annotation -" NOTE: flags is a string, not a long number -fu! s:modifiersOpt(...) - let partial = a:0 == 0 ? {} : a:1 - - let flags = partial == {} ? 0 : partial.flags - let annotations = partial == {} ? [] : partial.annotations - " TODO: deprecatedFlag - - let pos = b:pos - let lastPos = -1 - while 1 - let flag = 0 - if b:token =~# '^\(PUBLIC\|PROTECTED\|PRIVATE\|STATIC\|ABSTRACT\|FINAL\|NATIVE\|SYNCHRONIZED\|TRANSIENT\|VOLATILE\|STRICTFP\|MONKEYS_AT\)$' - let flag = b:token == 'MONKEYS_AT' ? s:Flags.ANNOTATION : get(s:Flags, b:token, 0) - else - break - endif - "if s:BitAnd(flags, flag) != 0 - " "log.error(S.pos(), "repeated.modifier") - "endif - - let lastPos = b:pos - call s:nextToken() - - if flag == s:Flags.ANNOTATION - "call s:checkAnnotations() - if b:token != 'INTERFACE' - let ann = s:annotation(lastPos) - if flags == 0 && annotations == [] - let pos = ann.pos - endif - call add(annotations, ann) - let lastPos = ann.pos - let flag = 0 - endif - endif - let flags = s:BitOr(flags, flag) - endwhile - - if b:token == 'ENUM' - let flags = s:BitOr(flags, s:Flags.ENUM) - elseif b:token == 'INTERFACE' - let flags = s:BitOr(flags, s:Flags.INTERFACE) - endif - - if flags == 0 && empty(annotations) - let pos = -1 - endif - - return {'tag': 'MODIFIERS', 'pos': pos, 'flags': flags, 'annotations': annotations} -endfu - -" Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] {{{2 -fu! s:annotation(pos) - "call s:checkAnnotations() - let ident = s:qualident() - "let endPos = b:prevEndPos - let fieldValues = s:annotationFieldValuesOpt() - - return {'tag': 'ANNOTATION', 'pos': a:pos, 'annotationType': ident, 'args': fieldValues} -endfu - -fu! s:annotationFieldValuesOpt() - return b:token == 'LPAREN' ? s:annotationFieldValues() : [] -endfu - -" AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" -fu! s:annotationFieldValues() - let buf = [] - call s:accept('LPAREN') - if b:token != 'RPAREN' - call add(buf, s:annotationFieldValue()) - while b:token == 'COMMA' - call s:nextToken() - call add(buf, s:annotationFieldValue()) - endwhile - endif - call s:accept('RPAREN') - return buf -endfu - -" AnnotationFieldValue = AnnotationValue | Identifier "=" AnnotationValue -fu! s:annotationFieldValue() - call s:Trace('s:annotationFieldValue ' . b:token) - if b:token == 'IDENTIFIER' - let b:mode = s:EXPR - let t1 = s:term1() - if t1.tag == 'IDENT' && b:token == 'EQ' - let pos = b:pos - call s:accept('EQ') - return {'tag': 'ASSIGN', 'pos': pos, 'lhs': t1, 'rhs': s:annotationValue()} - else - return t1 - endif - endif - return s:annotationValue() -endfu - -" AnnotationValue = ConditionalExpression | Annotation | "{" [ AnnotationValue { "," AnnotationValue } ] "}" -fu! s:annotationValue() - let pos = 0 - if b:token == 'MONKEYS_AT' - let pos = b:bp - call s:nextToken() - return s:annotation(pos) - elseif b:token == 'LBRACE' - let pos = b:pos - call s:accept('LBRACE') - let buf = [] - if b:token != 'RBRACE' - call add(buf, s:annotationValue()) - while b:token == 'COMMA' - call s:nextToken() - if b:token == 'RPAREN' - break - endif - call add(buf, s:annotationValue()) - endwhile - endif - call s:accept('RBRACE') - return buf - else - let b:mode = s:EXPR - return s:term1() - endif -endfu - -" AnnotationsOpt = { '@' Annotation } -fu! s:annotationsOpt() - if b:token != 'MONKEYS_AT' - return [] - endif - - let buf = [] - while b:token != 'MONKEYS_AT' - let pos = b:pos - call s:nextToken() - call add(buf, s:annotation(pos)) - endwhile - return buf -endfu - -" {{{2 -" CompilationUnit {{{2 -" CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} -fu! s:compilationUnit() - let unit = {'tag': 'TOPLEVEL', 'pos': b:pos} - - let mods = {} - if b:token == 'MONKEYS_AT' - let mods = s:modifiersOpt() - endif - - if b:token == 'PACKAGE' - if mods != {} - " checkNoMods(mods.flags) - let unit.packageAnnotations = mods.annotations - let mods = {} - endif - call s:nextToken() - let unit.pid = s:qualident() - let unit.package = java_parser#type2Str(unit.pid) - call s:accept('SEMI') - endif - - let imports = [] - let s:types = [] - let checkForImports = 1 - while b:token != 'EOF' - if b:pos <= b:errorEndPos - call s:skip(checkForImports, 0, 0, 0) - if b:token == 'EOF' - break - endif - endif - if checkForImports && mods == {} && b:token == 'IMPORT' - call add(imports, s:importDeclaration()) - else - let def = s:typeDeclaration(mods) - "if (def instanceof JCExpressionStatement) - " def = ((JCExpressionStatement)def).expr - "endif - call add(s:types, def) - if def.tag == 'CLASSDEF' - let checkForImports = 0 - endif - let mods = {} - endif - endwhile - let unit.imports = imports - let unit.types = s:types - unlet s:types - - return unit -endfu - -" ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" {{{2 -" return fqn -fu! s:importDeclaration() - " OAO: Usualy it is in one line. - if b:scanStrategy < 0 - let idx = matchend(b:lines[b:line], '\(\s\+static\>\)\?\s\+\([_$a-zA-Z][_$a-zA-Z0-9_]*\)\(\s*\.\s*[_$a-zA-Z][_$a-zA-Z0-9_]*\)*\(\s*\.\s*\*\)\?;') - if idx != -1 - let fqn = strpart(b:lines[b:line], b:col, idx-b:col-1) - let b:col = idx - let b:bp = b:idxes[b:line] + b:col - call s:nextToken() - return fqn - endif - endif - - - call s:Info('==import==') - let pos = b:pos - call s:nextToken() - - let importStatic = 0 - if b:token == 'STATIC' - " checkStaticImports() - let importStatic = 1 - call s:nextToken() - endif - - let pid = s:Ident(b:pos, s:ident()) - - " - let pos1 = b:pos - call s:accept('DOT') - if b:token == 'STAR' - let pid = s:Select(pos1, pid, '*') - call s:nextToken() - else - let pid = s:Select(pos1, pid, s:ident()) - endif - while b:token == 'DOT' - let pos1 = b:pos - call s:accept('DOT') - if b:token == 'STAR' - let pid = s:Select(pos1, pid, '*') - call s:nextToken() - break - else - let pid = s:Select(pos1, pid, s:ident()) - endif - endwhile - let fqn = java_parser#type2Str(pid) - if b:token != 'SEMI' - let fqn .= '<SEMI expected>' - endif - call s:accept('SEMI') - "return {'tag': 'IMPORT', 'pos': b:pos, 'qualid': pid, 'staticImport': importStatic} - return fqn -endfu - -" TypeDeclaration = ClassOrInterfaceOrEnumDeclaration | ";" {{{2 -fu! s:typeDeclaration(mods) - let pos = b:pos - if a:mods == {} && b:token == 'SEMI' - call s:nextToken() - return {'tag': 'SKIP', 'pos': pos} - else - let dc = b:docComment - let mods = s:modifiersOpt(a:mods) - return s:classOrInterfaceOrEnumDeclaration(mods, dc) - endif -endfu - -fu! s:classOrInterfaceOrEnumDeclaration(mods, dc) - call s:Info('== type ==') - if b:token == 'CLASS' - return s:classDeclaration(a:mods, a:dc) - elseif b:token == 'INTERFACE' - return s:interfaceDeclaration(a:mods, a:dc) - elseif b:token == 'ENUM' - "if !exists('b:allowEnums') || !b:allowEnums - " call s:SyntaxError("enums.not.supported.in.source") - "endif - return s:enumDeclaration(a:mods, a:dc) - else - let pos = b:pos - let errs = [] - if b:token == 'IDENTIFIER' - call add(errs, s:ident()) - call s:setErrorEndPos(b:bp) - endif - return s:SyntaxError("class.or.intf.or.enum.expected", pos, errs) - endif -endfu - -" ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] [IMPLEMENTS TypeList] ClassBody {{{2 -fu! s:classDeclaration(mods, dc) - let type = s:ClassDef(b:pos, a:mods) - - call s:accept('CLASS') - let type.name = s:ident() - - let type.typarams = s:typeParametersOpt() - - " extends - if b:token == 'EXTENDS' - call s:nextToken() - let type.extends = [s:type()] - endif - - " implements - if b:token == 'IMPLEMENTS' - call s:nextToken() - let type.implements = s:typeList() - endif - - let type.defs = s:classOrInterfaceBody(type.name, 0) - let type.endpos = b:pos - return type -endfu - -" InterfaceDeclaration = INTERFACE Ident TypeParametersOpt [EXTENDS TypeList] InterfaceBody {{{2 -fu! s:interfaceDeclaration(mods, dc) - let type = s:ClassDef(b:pos, a:mods) - - call s:accept('INTERFACE') - let type.name = s:ident() - - let type.typarams = s:typeParametersOpt() - - " extends - if b:token == 'EXTENDS' - call s:nextToken() - let type.extends = s:typeList() - endif - - let type.defs = s:classOrInterfaceBody(type.name, 1) - let type.endpos = b:pos - return type -endfu - -" EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody {{{2 -fu! s:enumDeclaration(mods, dc) - let type = s:ClassDef(b:pos, a:mods) - - call s:accept('ENUM') - let type.name = s:ident() - - if b:token == 'IMPLEMENTS' - call s:nextToken() - let type.implements = s:typeList() - endif - - let type.defs = s:enumBody(type.name) - let type.endpos = b:pos - return type -endfu - -" EnumBody = "{" { EnumeratorDeclarationList } [","] -" [ ";" {ClassBodyDeclaration} ] "}" -fu! s:enumBody(enumName) - let defs = [] - call s:accept('LBRACE') - - if b:token == 'COMMA' - call s:nextToken() - elseif b:token != 'RBRACE' && b:token != 'SEMI' - call add(defs, s:enumeratorDeclaration(a:enumName)) - while b:token == 'COMMA' - call s:nextToken() - if b:token == 'RBRACE' || b:token == 'SEMI' - break - endif - call add(defs, s:enumeratorDeclaration(a:enumName)) - endwhile - if b:token != 'RBRACE' && b:token != 'SEMI' - call s:SyntaxError('comma.or.rbrace.or.semi. expected') - call s:nextToken() - endif - endif - - if b:token == 'SEMI' - call s:nextToken() - while b:token != 'RBRACE' && b:token != 'EOF' - call add(defs, s:classOrInterfaceBodyDeclaration(a:enumName, 0)) - if b:pos <= b:errorEndPos - call s:skip(0, 1, 1, 0) - endif - endwhile - endif - - call s:accept('RBRACE') - return defs -endfu - -" EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] -fu! s:enumeratorDeclaration(enumName) - let vardef = {'tag': 'VARDEF', 'pos': b:pos} - - let dc = b:docComment - let flags = 16409 " s:BitOr(s:Flags.PUBLIC, s:Flags.STATIC, s:Flags.FINAL, s:Flags.ENUM) - " if b:deprecatedFlag - " let flags = 147481 " s:BitOr(flags, s:Flags.DEPRECATED) - " let b:deprecatedFlag = 1 - " endif - let pos = b:pos - let annotations = s:annotationsOpt() - let vardef.mods = s:Modifiers(pos, flags, annotations) - let vardef.mods.pos = empty(annotations) ? -1 : pos - let vardef.m = s:Number2Bits(flags) - - let typeArgs = s:typeArgumentsOpt() - let identPos = b:pos - let vardef.name = s:ident() - let vardef.n = vardef.name - - let args = b:token == 'LPAREN' ? s:arguments() : [] - - " NOTE: It may be either a class body or a method body. I dont care, just record it - if b:token == 'LBRACE' - "call s:accept('LBRACE') - "if b:token !=# 'RBRACE' - " call s:gotoMatchEnd('{', '}') - "endif - "call s:accept('RBRACE') - - "let mods1 = s:Modifiers(-1, s:BitOr(s:Flags.ENUM, s:Flags.STATIC), []) - let defs = s:classOrInterfaceBody('', 0) - "let body = s:ClassDef(identPos, mods1) - "let body.defs = defs - endif - let vardef.endpos = b:bp - - " TODO: create new class - - return vardef -endfu - -" classOrInterfaceBody {{{2 -" ClassBody = "{" {ClassBodyDeclaration} "}" -" InterfaceBody = "{" {InterfaceBodyDeclaration} "}" -fu! s:classOrInterfaceBody(classname, isInterface) - call s:Info('== type definition body ==') - call s:accept('LBRACE') - - if b:pos <= b:errorEndPos - call s:skip(0, 1, 0, 0) - if b:token == 'LBRACE' - call s:nextToken() - endif - endif - - let defs = [] - while b:token != 'RBRACE' && b:token != 'EOF' - let defs += s:classOrInterfaceBodyDeclaration(a:classname, a:isInterface) - - if b:pos <= b:errorEndPos - call s:skip(0, 1, 1, 0) - endif - endwhile - call s:accept('RBRACE') - return defs -endfu - -" classOrInterfaceBodyDeclaration {{{2 -" ClassBodyDeclaration = -" ";" -" | [STATIC] Block -" | ModifiersOpt -" ( Type Ident -" ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) -" | VOID Ident MethodDeclaratorRest -" | TypeParameters (Type | VOID) Ident MethodDeclaratorRest -" | Ident ConstructorDeclaratorRest -" | TypeParameters Ident ConstructorDeclaratorRest -" | ClassOrInterfaceOrEnumDeclaration -" ) -" InterfaceBodyDeclaration = -" ";" -" | ModifiersOpt Type Ident -" ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) -fu! s:classOrInterfaceBodyDeclaration(classname, isInterface) - call s:Info('s:classOrInterfaceBodyDeclaration') - if b:token == 'SEMI' - call s:nextToken() - return [{'tag': 'BLOCK', 'pos': -1, 'endpos': -1, 'stats': []}] - else - if b:scanStrategy < 0 - let result = s:classOrInterfaceBodyDeclaration_opt(a:classname, a:isInterface) - if !empty(result) - return result - endif - endif - - - let dc = b:docComment - let pos = b:bp - let mods = s:modifiersOpt() - - if b:token =~# '^\(CLASS\|INTERFACE\|ENUM\)$' - return [s:classOrInterfaceOrEnumDeclaration(mods, dc)] - - " [STATIC] block - elseif b:token == 'LBRACE' && !a:isInterface - return [s:block(pos, mods.flags, b:scanStrategy < 1)] - - else - let typarams = s:typeParametersOpt() - - let token = b:token - let name = b:name - - let type = copy(s:TTree) - let isVoid = b:token == 'VOID' - if isVoid - let type = {'tag': 'TYPEIDENT', 'pos': pos, 'typetag': 'void'} " FIXME - let type.value = '' - call s:nextToken() - else - let time = reltime() - let type = s:type() - let b:et_perf .= "\r" . reltimestr(reltime(time)) . ' s:type() ' - endif - - - " ctor - if b:token == 'LPAREN' && !a:isInterface && type.tag == 'IDENT' - if a:isInterface || name != a:classname - call s:SyntaxError('invalid.meth.decl.ret.type.req') - endif - return [s:methodDeclaratorRest(pos, mods, type, name, typarams, a:isInterface, 1, dc)] - else - let name = s:ident() - " method - if b:token == 'LPAREN' - return [s:methodDeclaratorRest(pos, mods, type, name, typarams, a:isInterface, isVoid, dc)] - " field - elseif !isVoid && len(typarams) == 0 - let defs = s:variableDeclaratorsRest(pos, mods, type, name, a:isInterface, dc, copy([])) - call s:accept('SEMI') - return defs - else - call s:SyntaxError("LPAREN expected") - return [{}] - endif - endif - endif - endif -endfu - -" OAO: short way for common declaration of field or method, not for generic type yet. -fu! s:classOrInterfaceBodyDeclaration_opt(classname, isInterface) - let str = b:lines[b:line] - let idx = matchend(str, s:RE_MEMBER_HEADER) - if idx != -1 - let subs = split(substitute(strpart(str, 0, idx), s:RE_MEMBER_HEADER, '\1;\2;\3', ''), ';') - let name_ = subs[2] - let type_ = subs[1] - let flag_ = s:String2Flags(subs[0]) - -" if type_ =~# '^\(class\|interface\|enum\)$' -" return [s:classOrInterfaceOrEnumDeclaration(mods, dc)] -" else - " methodDeclarator - let idx = matchend(str, '^\s*[,=;(]', idx)-1 - if str[idx] == '(' - let methoddef = s:methodDeclaratorRest_opt(b:pos, flag_, type_, name_, [], a:isInterface, type_ == 'void', '', str, idx) - if !empty(methoddef) - return [methoddef] - endif - - " variableDeclarator - elseif str[idx] =~ '[=;]' - let vardef = {'tag': 'VARDEF', 'pos': b:pos, 'name': name_, 'n': name_, 'vartype': type_, 't': type_, 'm': flag_} - call s:gotoSemi() - call s:accept('SEMI') - let vardef.pos_end = b:pos - return [vardef] - - " variableDeclarators - elseif str[idx] == ',' - let ie = matchend(str, '^\(,\s*'. s:RE_IDENTIFIER .'\s*\)*;', idx) - if ie != -1 - let vardef = {'tag': 'VARDEF', 'pos': b:pos, 'name': name_, 'n': name_, 'vartype': type_, 't': type_, 'm': flag_} - let vars = [vardef] - for item in split(substitute(strpart(str, idx+1, ie-idx-2), '\s', '', 'g'), ',') - let vardef = copy(vardef) - let vardef.name = item - let vardef.n = item - call add(vars, vardef) - endfor - let b:col = ie - let b:bp = b:idxes[b:line] + b:col - call s:nextToken() - return vars - endif - endif -" endif - endif - - let RE_CTOR_HEADER = '^\s*\(\(public\|protected\|private\)\s\+\)\=\C' .a:classname. '\s*(' - let ie = matchend(str, RE_CTOR_HEADER) - if ie != -1 && !a:isInterface - let flag_ = s:String2Flags(substitute(strpart(str, 0, ie), RE_CTOR_HEADER, '\1', '')) - let methoddef = s:methodDeclaratorRest_opt(b:pos, flag_, a:classname, a:classname, [], a:isInterface, 1, '', str, ie-1) - if !empty(methoddef) - return [methoddef] - endif - endif - - let RE_METHOD_HEADER = '^\s*\(' .s:RE_IDENTIFIER. '\%(\s*\.\s*' .s:RE_IDENTIFIER. '\)*\%(\s*\[\s*\]\)\=\)\s\+\(' .s:RE_IDENTIFIER. '\)\s*(' - let ie = matchend(str, RE_METHOD_HEADER) - if ie != -1 - let subs = split(substitute(strpart(str, 0, ie), RE_METHOD_HEADER, '\1;\2', ''), ';') - let methoddef = s:methodDeclaratorRest_opt(b:pos, 0, subs[0], subs[1], [], a:isInterface, subs[0] == 'void', '', str, ie-1) - if !empty(methoddef) - return [methoddef] - endif - endif -endfu - - -" MethodDeclaratorRest = {{{2 -" FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") -" VoidMethodDeclaratorRest = FormalParameters [Throws TypeList] ( MethodBody | ";") -" InterfaceMethodDeclaratorRest = FormalParameters BracketsOpt [THROWS TypeList] ";" -" VoidInterfaceMethodDeclaratorRest = FormalParameters [THROWS TypeList] ";" -" ConstructorDeclaratorRest = "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody -fu! s:methodDeclaratorRest(pos, mods, type, name, typarams, isInterface, isVoid, dc) - let time = reltime() - let methoddef = {'tag': 'METHODDEF', 'pos': a:pos, 'name': a:name, 'mods': a:mods, 'restype': a:type, 'typarams': a:typarams} - let methoddef.n = a:name - let methoddef.m = s:Number2Bits(a:mods.flags) - let methoddef.r = java_parser#type2Str(a:type) - - " parameters - let methoddef.params = s:formalParameters() - - " BracketsOpt - if !a:isVoid - let methoddef.r = java_parser#type2Str(s:bracketsOpt(a:type)) - endif - - - " throws - if b:token == 'THROWS' - call s:nextToken() - - " thrown = qualidentList() - let ts = [s:qualident()] - while b:token == 'COMMA' - call s:nextToken() - call add(ts, s:qualident()) - endwhile - let methoddef.throws = ts - endif - - " method body - if b:token == 'LBRACE' - let methoddef.body = s:block(b:pos, 0, b:scanStrategy < 1) - else - if b:token == 'DEFAULT' - call s:accept('DEFAULT') - let methoddef.defaultValue = s:annotationValue() - endif - call s:accept('SEMI') - - if b:pos <= b:errorEndPos - call s:skip(0, 1, 0, 0) - if b:token == 'LBRACE' - let methoddef.body = s:block(b:pos, 0, b:scanStrategy < 1) - endif - endif - endif - - let methoddef.d = s:method2Str(methoddef) - let b:et_perf .= "\r" . reltimestr(reltime(time)) . ' methodrest() ' - return methoddef -endfu - -" method header declared in one line, -" NOTE: RE_FORMAL_PARAM_LIST do not recognize varargs and nested comments -fu! s:methodDeclaratorRest_opt(pos, mods, type, name, typarams, isInterface, isVoid, dc, str, idx) - let str = a:str - let idx = a:idx - - " params - let idxend = matchend(str, '^(\s*)', idx) " no params - if idxend == -1 - let idxend = matchend(str, '^(\s*' . s:RE_FORMAL_PARAM_LIST . '\s*)', idx) - endif - if idxend == -1 - return - endif - - let methoddef = {'tag': 'METHODDEF', 'pos': a:pos, 'name': a:name, 'n': a:name, 'm': a:mods, 'r': a:type} - - " params - let methoddef.params = [] - let s = strpart(str, idx+1, idxend-idx-2) - if s !~ '^\s*$' - for item in split(s, ',') - let subs = split(substitute(item, s:RE_FORMAL_PARAM2, '\2;\5', ''), ';') - let param = {'tag': 'VARDEF', 'pos': -1} - let param.name = subs[1] - let param.vartype = substitute(subs[0], ' ', '', 'g') - let param.m = s:Flags.PARAMETER - call add(methoddef.params, param) - endfor - endif - - " throws - let idx2 = matchend(str, '^\s*' . s:RE_THROWS, idxend) - let idx = idx2 == -1 ? idxend : idx2 - if idx2 != -1 - "let throws = strpart(str, idxend, idx-idxend) - endif - - " in interface - if a:isInterface - let idx = matchend(str, '^\s*;', idx) - if idx != -1 - let b:token = 'SEMI' - let b:col = idx - let b:bp = b:idxes[b:line] + b:col - let b:pos = b:bp - 1 - let methoddef.d = substitute(str, '^\s*\([^{]*\)\s*;\=$', '\1', '') - return methoddef - endif - endif - - let idx = matchend(str, '^\s*{', idx) - if idx == -1 - let idx = matchend(b:lines[b:line+1], '^\s*{') - if idx != -1 - let b:line += 1 - endif - endif - if idx != -1 - let b:token = 'LBRACE' - let b:col = idx - let b:bp = b:idxes[b:line] + b:col - let b:pos = b:bp - 1 - let methoddef.d = substitute(str, '^\s*\([^{]*\)\s*{\=$', '\1', '') - let methoddef.body = s:block(b:pos, 0, b:scanStrategy < 1) - return methoddef - endif -endfu - -" VariableDeclarators = VariableDeclarator { "," VariableDeclarator } {{{2 -fu! s:variableDeclarators(mods, type, vdefs) - return s:variableDeclaratorsRest(b:pos, a:mods, a:type, s:ident(), 0, '', a:vdefs) -endfu - -" VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } -" ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } -fu! s:variableDeclaratorsRest(pos, mods, type, name, reqInit, dc, vdefs) - call add(a:vdefs, s:variableDeclaratorRest(a:pos, a:mods, a:type, a:name, a:reqInit, a:dc)) - while b:token == 'COMMA' - call s:nextToken() - call add(a:vdefs, s:variableDeclarator(a:mods, a:type, a:reqInit, a:dc)) - endwhile - return a:vdefs -endfu - -" VariableDeclarator = Ident VariableDeclaratorRest -" ConstantDeclarator = Ident ConstantDeclaratorRest -fu! s:variableDeclarator(mods, type, reqInit, dc) - return s:variableDeclaratorRest(b:pos, a:mods, a:type, s:ident(), a:reqInit, a:dc) -endfu - -" VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] -" ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer -fu! s:variableDeclaratorRest(pos, mods, type, name, reqInit, dc) - let vardef = s:VarDef(a:pos, a:mods, a:name, s:bracketsOpt(a:type)) - let vardef.n = vardef.name - let vardef.m = a:mods == {} ? '0' : s:Number2Bits(a:mods.flags) - let vardef.t = java_parser#type2Str(vardef.vartype) - - if b:token == 'EQ' - call s:nextToken() - call s:Info('field init ' . b:token) - let vardef.init = s:variableInitializer() - elseif a:reqInit - echo '[syntax error]:' . s:token2string('EQ') . " expected" - endif - - let vardef.endpos = b:pos - return vardef -endfu - -fu! s:variableDeclaratorId(mods, type) - let vardef = s:VarDef(b:pos, a:mods, s:ident(), a:type) - if len(a:mods.flags) <= 34 " (a:mods.flags & s:Flags.VARARGS) == 0 - let vardef.type = s:bracketsOpt(vardef.vartype) - endif - return vardef -endfu - -" {{{2 -" TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] {{{2 -fu! s:typeParametersOpt() - if b:token == 'LT' - "call checkGenerics() - let typarams = [] - call s:nextToken() - call add(typarams, s:typeParameter()) - while b:token == 'COMMA' - call s:nextToken() - call add(typarams, s:typeParameter()) - endwhile - call s:accept('GT') - return typarams - else - return [] - endif -endfu - -" TypeParameter = TypeVariable [TypeParameterBound] {{{2 -" TypeParameterBound = EXTENDS Type {"&" Type} -" TypeVariable = Ident -fu! s:typeParameter() - let pos = b:pos - let name = s:ident() - let bounds = [] - if b:token == 'EXTENDS' - call s:nextToken() - call add(bounds, s:type()) - while b:token == 'AMP' - call s:nextToken() - call add(bounds, s:type()) - endwhile - endif - - return {'tag': 'TYPEPARAMETER', 'pos': pos, 'name': name, 'bounds': bounds} -endfu - -" FormalParameters = "(" [ FormalParameterList ] ")" {{{2 -" FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter -" FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter -fu! s:formalParameters() - let params = [] - let lastParam = {} - call s:accept('LPAREN') - if b:token != 'RPAREN' - let lastParam = s:formalParameter() - call add(params, lastParam) - while b:token == 'COMMA' && len(lastParam.mods.flags) <= 34 " (lastParam.mods.flags & s:Flags.VARARGS) == 0 - call s:nextToken() - let lastParam = s:formalParameter() - call add(params, lastParam) - endwhile - endif - call s:accept('RPAREN') - return params -endfu - -" FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId {{{2 -" LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter -fu! s:optFinal(flags) - let mods = s:modifiersOpt() - " checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)) - let mods.flags = s:BitOr(mods.flags, a:flags) - return mods -endfu - -" OAO: optional FINAL for parameter -fu! s:optFinalParameter() - let mods = {'tag': 'MODIFIERS', 'pos': b:pos, 'flags': s:Flags.PARAMETER, 'annotations': []} - if b:token == 'FINAL' - let mods.flags = '1000000000000000000000000000010000' - call s:nextToken() - endif - return mods -endfu - -fu! s:formalParameter() - let mods = s:optFinalParameter() - let type = s:type() - - if b:token == 'ELLIPSIS' - " checkVarargs() - let mods.flags = '1' . mods.flags " s:BitOr_binary(mods.flags, s:Flags.VARARGS) - let type = s:TypeArray(b:pos, type) - call s:nextToken() - endif - - return s:variableDeclaratorId(mods, type) -endfu - -" {{{2 -" auxiliary methods {{{2 -let s:MapToken2Tag = {'BARBAR': 'OR', 'AMPAMP': 'AND', 'BAR': 'BITOR', 'BAREQ': 'BITOR_ASG', 'CARET': 'BITXOR', 'CARETEQ': 'BITXOR_ASG', 'AMP': 'BITAND', 'AMPEQ': 'BITAND_ASG', 'EQEQ': 'EQ', 'BANGEQ': 'NE', 'LT': 'LT', 'GT': 'GT', 'LTEQ': 'LE', 'GTEQ': 'GE', 'LTLT': 'SL', 'LTLTEQ': 'SL_ASG', 'GTGT': 'SR', 'GTGTEQ': 'SR_ASG', 'GTGTGT': 'USR', 'GTGTGTEQ': 'USR_ASG', 'PLUS': 'PLUS', 'PLUSEQ': 'PLUS_ASG', 'SUB': 'MINUS', 'SUBEQ': 'MINUS_ASG', 'STAR': 'MUL', 'STAREQ': 'MUL_ASG', 'SLASH': 'DIV', 'SLASHEQ': 'DIV_ASG', 'PERCENT': 'MOD', 'PERCENTEQ': 'MOD_ASG', 'INSTANCEOF': 'TYPETEST'} -let s:opprecedences = {'notExpression': -1, 'noPrec': 0, 'assignPrec': 1, 'assignopPrec': 2, 'condPrec': 3, 'orPrec': 4, 'andPrec': 5, 'bitorPrec': 6, 'bitxorPrec': 7, 'bitandPrec': 8, 'eqPrec': 9, 'ordPrec': 10, 'shiftPrec': 11, 'addPrec': 12, 'mulPrec': 13, 'prefixPrec': 14, 'postfixPrec': 15, 'precCount': 16} - -fu! s:checkExprStat(t) - if a:t.tag =~# '^\(PREINC\|PREDEC\|POSTINC\|POSTDEC\|ASSIGN\|BITOR_ASG\|BITXOR_ASG\|BITAND_ASG\|SL_ASG\|SR_ASG\|USR_ASG\|PLUS_ASG\|MINUS_ASG\|MUL_ASG\|DIV_ASG\|MOD_ASG\|APPLY\|NEWCLASS\|ERRONEOUS\)$' - return a:t - else - call s:SyntaxError('not.stmt') - return {'tag': 'ERRONEOUS', 'pos': b:pos, 'errs': [a:t]} - endif -endfu - -fu! s:prec(token) - let oc = s:optag(a:token) - return oc == -1 ? -1 : s:opPrec(oc) -endfu - -fu! s:opPrec(tag) - if a:tag =~# '^\(POS\|NEG\|NOT\|COMPL\|PREINC\|PREDEC\)$' - return s:opprecedences.prefixPrec - elseif a:tag =~# '^\(POSTINC\|POSTDEC\|NULLCHK\)$' - return s:opprecedences.postfixPrec - elseif a:tag == 'ASSIGN' - return s:opprecedences.assignPrec - elseif a:tag =~# '^\(BITOR_ASG\|BITXOR_ASG\|BITAND_ASG\|SL_ASG\|SR_ASG\|USR_ASG\|PLUS_ASG\|MINUS_ASG\|MUL_ASG\|DIV_ASG\|MOD_ASG\)$' - return s:opprecedences.assignopPrec - elseif a:tag == 'OR' - return s:opprecedences.orPrec - elseif a:tag == 'AND' - return s:opprecedences.andPrec - elseif a:tag =~# '^\(EQ\|NE\)$' - return s:opprecedences.eqPrec - elseif a:tag =~# '^\(LT\|GT\|LE\|GE\)$' - return s:opprecedences.ordPrec - elseif a:tag == 'BITOR' - return s:opprecedences.bitorPrec - elseif a:tag == 'BITXOR' - return s:opprecedences.bitxorPrec - elseif a:tag == 'BITAND' - return s:opprecedences.bitandPrec - elseif a:tag =~# '^\(SL\|SR\|USR\)$' - return s:opprecedences.shiftPrec - elseif a:tag =~# '^\(PLUS\|MINUS\)$' - return s:opprecedences.addPrec - elseif a:tag =~# '^\(MUL\|DIV\|MOD\)$' - return s:opprecedences.mulPrec - elseif a:tag == 'TYPETEST' - return s:opprecedences.ordPrec - else - return -1 - endif -endfu - -fu! s:optag(token) - return get(s:MapToken2Tag, a:token, -1) -endfu - -fu! s:unoptag(token) - if a:token == 'PLUS' - return 'POS' - elseif a:token == 'SUB' - return 'NEG' - elseif a:token == 'BANG' - return 'NOT' - elseif a:token == 'TILDE' - return 'COMPL' - elseif a:token == 'PLUSPLUS' - return 'PREINC' - elseif a:token == 'SUBSUB' - return 'PREDEC' - else - return -1 - endif -endfu - -fu! s:typetag(token) - if a:token =~# '\(BYTE\|CHAR\|SHORT\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\)' - return tolower(a:token) - else - return -1 - endif -endfu - -"}}}1 -" vim:set fdm=marker sw=2 nowrap: diff --git a/files/.vim/autoload/javacomplete.vim b/files/.vim/autoload/javacomplete.vim deleted file mode 100644 index becef53..0000000 --- a/files/.vim/autoload/javacomplete.vim +++ /dev/null @@ -1,2918 +0,0 @@ -" Vim completion script - hit 80% complete tasks -" Version: 0.77.1 -" Language: Java -" Maintainer: cheng fang <fangread@yahoo.com.cn> -" Last Change: 2007-09-26 -" Copyright: Copyright (C) 2006-2007 cheng fang. All rights reserved. -" License: Vim License (see vim's :help license) - - -" constants {{{1 -" input context type -let s:CONTEXT_AFTER_DOT = 1 -let s:CONTEXT_METHOD_PARAM = 2 -let s:CONTEXT_IMPORT = 3 -let s:CONTEXT_IMPORT_STATIC = 4 -let s:CONTEXT_PACKAGE_DECL = 6 -let s:CONTEXT_NEED_TYPE = 7 -let s:CONTEXT_OTHER = 0 - - -let s:ARRAY_TYPE_MEMBERS = [ -\ {'kind': 'm', 'word': 'clone(', 'abbr': 'clone()', 'menu': 'Object clone()', }, -\ {'kind': 'm', 'word': 'equals(', 'abbr': 'equals()', 'menu': 'boolean equals(Object)', }, -\ {'kind': 'm', 'word': 'getClass(', 'abbr': 'getClass()', 'menu': 'Class Object.getClass()', }, -\ {'kind': 'm', 'word': 'hashCode(', 'abbr': 'hashCode()', 'menu': 'int hashCode()', }, -\ {'kind': 'f', 'word': 'length', 'menu': 'int'}, -\ {'kind': 'm', 'word': 'notify(', 'abbr': 'notify()', 'menu': 'void Object.notify()', }, -\ {'kind': 'm', 'word': 'notifyAll(', 'abbr': 'notifyAll()', 'menu': 'void Object.notifyAll()', }, -\ {'kind': 'm', 'word': 'toString(', 'abbr': 'toString()', 'menu': 'String toString()', }, -\ {'kind': 'm', 'word': 'wait(', 'abbr': 'wait()', 'menu': 'void Object.wait() throws InterruptedException', }, -\ {'kind': 'm', 'dup': 1, 'word': 'wait(', 'abbr': 'wait()', 'menu': 'void Object.wait(long timeout) throws InterruptedException', }, -\ {'kind': 'm', 'dup': 1, 'word': 'wait(', 'abbr': 'wait()', 'menu': 'void Object.wait(long timeout, int nanos) throws InterruptedException', }] - -let s:ARRAY_TYPE_INFO = {'tag': 'CLASSDEF', 'name': '[', 'ctors': [], -\ 'fields': [{'n': 'length', 'm': '1', 't': 'int'}], -\ 'methods':[ -\ {'n': 'clone', 'm': '1', 'r': 'Object', 'p': [], 'd': 'Object clone()'}, -\ {'n': 'equals', 'm': '1', 'r': 'boolean', 'p': ['Object'], 'd': 'boolean Object.equals(Object obj)'}, -\ {'n': 'getClass', 'm': '100010001', 'r': 'Class', 'p': [], 'd': 'Class Object.getClass()'}, -\ {'n': 'hashCode', 'm': '100000001', 'r': 'int', 'p': [], 'd': 'int Object.hashCode()'}, -\ {'n': 'notify', 'm': '100010001', 'r': 'void', 'p': [], 'd': 'void Object.notify()'}, -\ {'n': 'notifyAll','m': '100010001', 'r': 'void', 'p': [], 'd': 'void Object.notifyAll()'}, -\ {'n': 'toString', 'm': '1', 'r': 'String', 'p': [], 'd': 'String Object.toString()'}, -\ {'n': 'wait', 'm': '10001', 'r': 'void', 'p': [], 'd': 'void Object.wait() throws InterruptedException'}, -\ {'n': 'wait', 'm': '100010001', 'r': 'void', 'p': ['long'], 'd': 'void Object.wait(long timeout) throws InterruptedException'}, -\ {'n': 'wait', 'm': '10001', 'r': 'void', 'p': ['long','int'], 'd': 'void Object.wait(long timeout, int nanos) throws InterruptedException'}, -\ ]} - -let s:PRIMITIVE_TYPE_INFO = {'tag': 'CLASSDEF', 'name': '!', 'fields': [{'n': 'class','m': '1','t': 'Class'}]} - -let s:JSP_BUILTIN_OBJECTS = {'session': 'javax.servlet.http.HttpSession', -\ 'request': 'javax.servlet.http.HttpServletRequest', -\ 'response': 'javax.servlet.http.HttpServletResponse', -\ 'pageContext': 'javax.servlet.jsp.PageContext', -\ 'application': 'javax.servlet.ServletContext', -\ 'config': 'javax.servlet.ServletConfig', -\ 'out': 'javax.servlet.jsp.JspWriter', -\ 'page': 'javax.servlet.jsp.HttpJspPage', } - - -let s:PRIMITIVE_TYPES = ['boolean', 'byte', 'char', 'int', 'short', 'long', 'float', 'double'] -let s:KEYWORDS_MODS = ['public', 'private', 'protected', 'static', 'final', 'synchronized', 'volatile', 'transient', 'native', 'strictfp', 'abstract'] -let s:KEYWORDS_TYPE = ['class', 'interface', 'enum'] -let s:KEYWORDS = s:PRIMITIVE_TYPES + s:KEYWORDS_MODS + s:KEYWORDS_TYPE + ['super', 'this', 'void'] + ['assert', 'break', 'case', 'catch', 'const', 'continue', 'default', 'do', 'else', 'extends', 'finally', 'for', 'goto', 'if', 'implements', 'import', 'instanceof', 'interface', 'new', 'package', 'return', 'switch', 'throw', 'throws', 'try', 'while', 'true', 'false', 'null'] - -let s:PATH_SEP = ':' -let s:FILE_SEP = '/' -if has("win32") || has("win64") || has("win16") || has("dos32") || has("dos16") - let s:PATH_SEP = ';' - let s:FILE_SEP = '\' -endif - -let s:RE_BRACKETS = '\%(\s*\[\s*\]\)' -let s:RE_IDENTIFIER = '[a-zA-Z_$][a-zA-Z0-9_$]*' -let s:RE_QUALID = s:RE_IDENTIFIER. '\%(\s*\.\s*' .s:RE_IDENTIFIER. '\)*' - -let s:RE_REFERENCE_TYPE = s:RE_QUALID . s:RE_BRACKETS . '*' -let s:RE_TYPE = s:RE_REFERENCE_TYPE - -let s:RE_TYPE_ARGUMENT = '\%(?\s\+\%(extends\|super\)\s\+\)\=' . s:RE_TYPE -let s:RE_TYPE_ARGUMENTS = '<' . s:RE_TYPE_ARGUMENT . '\%(\s*,\s*' . s:RE_TYPE_ARGUMENT . '\)*>' -let s:RE_TYPE_WITH_ARGUMENTS_I = s:RE_IDENTIFIER . '\s*' . s:RE_TYPE_ARGUMENTS -let s:RE_TYPE_WITH_ARGUMENTS = s:RE_TYPE_WITH_ARGUMENTS_I . '\%(\s*' . s:RE_TYPE_WITH_ARGUMENTS_I . '\)*' - -let s:RE_TYPE_MODS = '\%(public\|protected\|private\|abstract\|static\|final\|strictfp\)' -let s:RE_TYPE_DECL_HEAD = '\(class\|interface\|enum\)[ \t\n\r]\+' -let s:RE_TYPE_DECL = '\<\C\(\%(' .s:RE_TYPE_MODS. '\s\+\)*\)' .s:RE_TYPE_DECL_HEAD. '\(' .s:RE_IDENTIFIER. '\)[< \t\n\r]' - -let s:RE_ARRAY_TYPE = '^\s*\(' .s:RE_QUALID . '\)\(' . s:RE_BRACKETS . '\+\)\s*$' -let s:RE_SELECT_OR_ACCESS = '^\s*\(' . s:RE_IDENTIFIER . '\)\s*\(\[.*\]\)\=\s*$' -let s:RE_ARRAY_ACCESS = '^\s*\(' . s:RE_IDENTIFIER . '\)\s*\(\[.*\]\)\+\s*$' -let s:RE_CASTING = '^\s*(\(' .s:RE_QUALID. '\))\s*\(' . s:RE_IDENTIFIER . '\)\>' - -let s:RE_KEYWORDS = '\<\%(' . join(s:KEYWORDS, '\|') . '\)\>' - - -" local variables {{{1 -let b:context_type = s:CONTEXT_OTHER -"let b:statement = '' " statement before cursor -let b:dotexpr = '' " expression ends with '.' -let b:incomplete = '' " incomplete word: 1. dotexpr.method(|) 2. new classname(|) 3. dotexpr.ab|, 4. ja|, 5. method(| -let b:errormsg = '' - -" script variables {{{1 -let s:cache = {} " FQN -> member list, e.g. {'java.lang.StringBuffer': classinfo, 'java.util': packageinfo, '/dir/TopLevelClass.java': compilationUnit} -let s:files = {} " srouce file path -> properties, e.g. {filekey: {'unit': compilationUnit, 'changedtick': tick, }} -let s:history = {} " - - -" This function is used for the 'omnifunc' option. {{{1 -function! javacomplete#Complete(findstart, base) - if a:findstart - let s:et_whole = reltime() - let start = col('.') - 1 - let s:log = [] - - " reset enviroment - let b:dotexpr = '' - let b:incomplete = '' - let b:context_type = s:CONTEXT_OTHER - - let statement = s:GetStatement() - call s:WatchVariant('statement: "' . statement . '"') - - if statement =~ '[.0-9A-Za-z_]\s*$' - let valid = 1 - if statement =~ '\.\s*$' - let valid = statement =~ '[")0-9A-Za-z_\]]\s*\.\s*$' && statement !~ '\<\H\w\+\.\s*$' && statement !~ '\<\(abstract\|assert\|break\|case\|catch\|const\|continue\|default\|do\|else\|enum\|extends\|final\|finally\|for\|goto\|if\|implements\|import\|instanceof\|interface\|native\|new\|package\|private\|protected\|public\|return\|static\|strictfp\|switch\|synchronized\|throw\|throws\|transient\|try\|volatile\|while\|true\|false\|null\)\.\s*$' - endif - if !valid - return -1 - endif - - let b:context_type = s:CONTEXT_AFTER_DOT - - " import or package declaration - if statement =~# '^\s*\(import\|package\)\s\+' - let statement = substitute(statement, '\s\+\.', '.', 'g') - let statement = substitute(statement, '\.\s\+', '.', 'g') - if statement =~ '^\s*import\s\+' - let b:context_type = statement =~# '\<static\s\+' ? s:CONTEXT_IMPORT_STATIC : s:CONTEXT_IMPORT - let b:dotexpr = substitute(statement, '^\s*import\s\+\(static\s\+\)\?', '', '') - else - let b:context_type = s:CONTEXT_PACKAGE_DECL - let b:dotexpr = substitute(statement, '\s*package\s\+', '', '') - endif - - " String literal - elseif statement =~ '"\s*\.\s*$' - let b:dotexpr = substitute(statement, '\s*\.\s*$', '\.', '') - return start - strlen(b:incomplete) - - else - " type declaration NOTE: not supported generic yet. - let idx_type = matchend(statement, '^\s*' . s:RE_TYPE_DECL) - if idx_type != -1 - let b:dotexpr = strpart(statement, idx_type) - " return if not after extends or implements - if b:dotexpr !~ '^\(extends\|implements\)\s\+' - return -1 - endif - let b:context_type = s:CONTEXT_NEED_TYPE - endif - - let b:dotexpr = s:ExtractCleanExpr(statement) - endif - - " all cases: " java.ut|" or " java.util.|" or "ja|" - let b:incomplete = strpart(b:dotexpr, strridx(b:dotexpr, '.')+1) - let b:dotexpr = strpart(b:dotexpr, 0, strridx(b:dotexpr, '.')+1) - return start - strlen(b:incomplete) - - - " method parameters, treat methodname or 'new' as an incomplete word - elseif statement =~ '(\s*$' - " TODO: Need to exclude method declaration? - let b:context_type = s:CONTEXT_METHOD_PARAM - let pos = strridx(statement, '(') - let s:padding = strpart(statement, pos+1) - let start = start - (len(statement) - pos) - - let statement = substitute(statement, '\s*(\s*$', '', '') - - " new ClassName? - let str = matchstr(statement, '\<new\s\+' . s:RE_QUALID . '$') - if str != '' - let str = substitute(str, '^new\s\+', '', '') - if !s:IsKeyword(str) - let b:incomplete = '+' - let b:dotexpr = str - return start - len(b:dotexpr) - endif - - " normal method invocations - else - let pos = match(statement, '\s*' . s:RE_IDENTIFIER . '$') - " case: "method(|)", "this(|)", "super(|)" - if pos == 0 - let statement = substitute(statement, '^\s*', '', '') - " treat "this" or "super" as a type name. - if statement == 'this' || statement == 'super' - let b:dotexpr = statement - let b:incomplete = '+' - return start - len(b:dotexpr) - - elseif !s:IsKeyword(statement) - let b:incomplete = statement - return start - strlen(b:incomplete) - endif - - " case: "expr.method(|)" - elseif statement[pos-1] == '.' && !s:IsKeyword(strpart(statement, pos)) - let b:dotexpr = s:ExtractCleanExpr(strpart(statement, 0, pos)) - let b:incomplete = strpart(statement, pos) - return start - strlen(b:incomplete) - endif - endif - endif - - return -1 - endif - - - " Return list of matches. - - call s:WatchVariant('b:context_type: "' . b:context_type . '" b:incomplete: "' . b:incomplete . '" b:dotexpr: "' . b:dotexpr . '"') - if b:dotexpr =~ '^\s*$' && b:incomplete =~ '^\s*$' - return [] - endif - - - let result = [] - if b:dotexpr !~ '^\s*$' - if b:context_type == s:CONTEXT_AFTER_DOT - let result = s:CompleteAfterDot(b:dotexpr) - elseif b:context_type == s:CONTEXT_IMPORT || b:context_type == s:CONTEXT_IMPORT_STATIC || b:context_type == s:CONTEXT_PACKAGE_DECL || b:context_type == s:CONTEXT_NEED_TYPE - let result = s:GetMembers(b:dotexpr[:-2]) - elseif b:context_type == s:CONTEXT_METHOD_PARAM - if b:incomplete == '+' - let result = s:GetConstructorList(b:dotexpr) - else - let result = s:CompleteAfterDot(b:dotexpr) - endif - endif - - " only incomplete word - elseif b:incomplete !~ '^\s*$' - " only need methods - if b:context_type == s:CONTEXT_METHOD_PARAM - let methods = s:SearchForName(b:incomplete, 0, 1)[1] - call extend(result, eval('[' . s:DoGetMethodList(methods) . ']')) - - else - let result = s:CompleteAfterWord(b:incomplete) - endif - - " then no filter needed - let b:incomplete = '' - endif - - - if len(result) > 0 - " filter according to b:incomplete - if len(b:incomplete) > 0 && b:incomplete != '+' - let result = filter(result, "type(v:val) == type('') ? v:val =~ '^" . b:incomplete . "' : v:val['word'] =~ '^" . b:incomplete . "'") - endif - - if exists('s:padding') && !empty(s:padding) - for item in result - if type(item) == type("") - let item .= s:padding - else - let item.word .= s:padding - endif - endfor - unlet s:padding - endif - - call s:Debug('finish completion' . reltimestr(reltime(s:et_whole)) . 's') - return result - endif - - if strlen(b:errormsg) > 0 - echoerr 'javacomplete error: ' . b:errormsg - let b:errormsg = '' - endif -endfunction - -" Precondition: incomplete must be a word without '.'. -" return all the matched, variables, fields, methods, types, packages -fu! s:CompleteAfterWord(incomplete) - " packages in jar files - if !exists('s:all_packages_in_jars_loaded') - call s:DoGetInfoByReflection('-', '-P') - let s:all_packages_in_jars_loaded = 1 - endif - - let pkgs = [] - let types = [] - for key in keys(s:cache) - if key =~# '^' . a:incomplete - if type(s:cache[key]) == type('') || get(s:cache[key], 'tag', '') == 'PACKAGE' - call add(pkgs, {'kind': 'P', 'word': key}) - - " filter out type info - elseif b:context_type != s:CONTEXT_PACKAGE_DECL && b:context_type != s:CONTEXT_IMPORT && b:context_type != s:CONTEXT_IMPORT_STATIC - call add(types, {'kind': 'C', 'word': key}) - endif - endif - endfor - - let pkgs += s:DoGetPackageInfoInDirs(a:incomplete, b:context_type == s:CONTEXT_PACKAGE_DECL, 1) - - - " add accessible types which name beginning with the incomplete in source files - " TODO: remove the inaccessible - if b:context_type != s:CONTEXT_PACKAGE_DECL - " single type import - for fqn in s:GetImports('imports_fqn') - let name = fqn[strridx(fqn, ".")+1:] - if name =~ '^' . a:incomplete - call add(types, {'kind': 'C', 'word': name}) - endif - endfor - - " current file - let lnum_old = line('.') - let col_old = col('.') - call cursor(1, 1) - while 1 - let lnum = search('\<\C\(class\|interface\|enum\)[ \t\n\r]\+' . a:incomplete . '[a-zA-Z0-9_$]*[< \t\n\r]', 'W') - if lnum == 0 - break - elseif s:InCommentOrLiteral(line('.'), col('.')) - continue - else - normal w - call add(types, {'kind': 'C', 'word': matchstr(getline(line('.'))[col('.')-1:], s:RE_IDENTIFIER)}) - endif - endwhile - call cursor(lnum_old, col_old) - - " other files - let filepatterns = '' - for dirpath in s:GetSourceDirs(expand('%:p')) - let filepatterns .= escape(dirpath, ' \') . '/*.java ' - endfor - exe 'vimgrep /\s*' . s:RE_TYPE_DECL . '/jg ' . filepatterns - for item in getqflist() - if item.text !~ '^\s*\*\s\+' - let text = matchstr(s:Prune(item.text, -1), '\s*' . s:RE_TYPE_DECL) - if text != '' - let subs = split(substitute(text, '\s*' . s:RE_TYPE_DECL, '\1;\2;\3', ''), ';', 1) - if subs[2] =~# '^' . a:incomplete && (subs[0] =~ '\C\<public\>' || fnamemodify(bufname(item.bufnr), ':p:h') == expand('%:p:h')) - call add(types, {'kind': 'C', 'word': subs[2]}) - endif - endif - endif - endfor - endif - - - let result = [] - - " add variables and members in source files - if b:context_type == s:CONTEXT_AFTER_DOT - let matches = s:SearchForName(a:incomplete, 0, 0) - let result += sort(eval('[' . s:DoGetFieldList(matches[2]) . ']')) - let result += sort(eval('[' . s:DoGetMethodList(matches[1]) . ']')) - endif - let result += sort(pkgs) - let result += sort(types) - - return result -endfu - - -" Precondition: expr must end with '.' -" return members of the value of expression -function! s:CompleteAfterDot(expr) - let items = s:ParseExpr(a:expr) " TODO: return a dict containing more than items - if empty(items) - return [] - endif - - - " 0. String literal - call s:Info('P0. "str".|') - if items[-1] =~ '"$' - return s:GetMemberList("java.lang.String") - endif - - - let ti = {} - let ii = 1 " item index - let itemkind = 0 - - " - " optimized process - " - " search the longest expr consisting of ident - let i = 1 - let k = i - while i < len(items) && items[i] =~ '^\s*' . s:RE_IDENTIFIER . '\s*$' - let ident = substitute(items[i], '\s', '', 'g') - if ident == 'class' || ident == 'this' || ident == 'super' - let k = i - " return when found other keywords - elseif s:IsKeyword(ident) - return [] - endif - let items[i] = substitute(items[i], '\s', '', 'g') - let i += 1 - endwhile - - if i > 1 - " cases: "this.|", "super.|", "ClassName.this.|", "ClassName.super.|", "TypeName.class.|" - if items[k] ==# 'class' || items[k] ==# 'this' || items[k] ==# 'super' - call s:Info('O1. ' . items[k] . ' ' . join(items[:k-1], '.')) - let ti = s:DoGetClassInfo(items[k] == 'class' ? 'java.lang.Class' : join(items[:k-1], '.')) - if !empty(ti) - let itemkind = items[k] ==# 'this' ? 1 : items[k] ==# 'super' ? 2 : 0 - let ii = k+1 - else - return [] - endif - - " case: "java.io.File.|" - else - let fqn = join(items[:i-1], '.') - let srcpath = join(s:GetSourceDirs(expand('%:p'), s:GetPackageName()), ',') - call s:Info('O2. ' . fqn) - call s:DoGetTypeInfoForFQN([fqn], srcpath) - if get(get(s:cache, fqn, {}), 'tag', '') == 'CLASSDEF' - let ti = s:cache[fqn] - let itemkind = 11 - let ii = i - endif - endif - endif - - - " - " first item - " - if empty(ti) - " cases: - " 1) "int.|", "void.|" - primitive type or pseudo-type, return `class` - " 2) "this.|", "super.|" - special reference - " 3) "var.|" - variable or field - " 4) "String.|" - type imported or defined locally - " 5) "java.|" - package - if items[0] =~ '^\s*' . s:RE_IDENTIFIER . '\s*$' - let ident = substitute(items[0], '\s', '', 'g') - - if s:IsKeyword(ident) - " 1) - call s:Info('F1. "' . ident . '.|"') - if ident ==# 'void' || s:IsBuiltinType(ident) - let ti = s:PRIMITIVE_TYPE_INFO - let itemkind = 11 - - " 2) - call s:Info('F2. "' . ident . '.|"') - elseif ident ==# 'this' || ident ==# 'super' - let itemkind = ident ==# 'this' ? 1 : ident ==# 'super' ? 2 : 0 - let ti = s:DoGetClassInfo(ident) - endif - - else - " 3) - let typename = s:GetDeclaredClassName(ident) - call s:Info('F3. "' . ident . '.|" typename: "' . typename . '"') - if (typename != '') - if typename[0] == '[' || typename[-1:] == ']' - let ti = s:ARRAY_TYPE_INFO - elseif typename != 'void' && !s:IsBuiltinType(typename) - let ti = s:DoGetClassInfo(typename) - endif - - else - " 4) - call s:Info('F4. "TypeName.|"') - let ti = s:DoGetClassInfo(ident) - let itemkind = 11 - - if get(ti, 'tag', '') != 'CLASSDEF' - let ti = {} - endif - - " 5) - if empty(ti) - call s:Info('F5. "package.|"') - unlet ti - let ti = s:GetMembers(ident) " s:DoGetPackegInfo(ident) - let itemkind = 20 - endif - endif - endif - - " method invocation: "method().|" - "this.method().|" - elseif items[0] =~ '^\s*' . s:RE_IDENTIFIER . '\s*(' - let ti = s:MethodInvocation(items[0], ti, itemkind) - - " array type, return `class`: "int[] [].|", "java.lang.String[].|", "NestedClass[].|" - elseif items[0] =~# s:RE_ARRAY_TYPE - call s:Info('array type. "' . items[0] . '"') - let qid = substitute(items[0], s:RE_ARRAY_TYPE, '\1', '') - if s:IsBuiltinType(qid) || (!s:HasKeyword(qid) && !empty(s:DoGetClassInfo(qid))) - let ti = s:PRIMITIVE_TYPE_INFO - let itemkind = 11 - endif - - " class instance creation expr: "new String().|", "new NonLoadableClass().|" - " array creation expr: "new int[i=1] [val()].|", "new java.lang.String[].|" - elseif items[0] =~ '^\s*new\s\+' - call s:Info('creation expr. "' . items[0] . '"') - let subs = split(substitute(items[0], '^\s*new\s\+\(' .s:RE_QUALID. '\)\s*\([([]\)', '\1;\2', ''), ';') - if subs[1][0] == '[' - let ti = s:ARRAY_TYPE_INFO - elseif subs[1][0] == '(' - let ti = s:DoGetClassInfo(subs[0]) - " exclude interfaces and abstract class. TODO: exclude the inaccessible - if get(ti, 'flags', '')[-10:-10] || get(ti, 'flags', '')[-11:-11] - echo 'cannot instantiate the type ' . subs[0] - let ti = {} - return [] - endif - endif - - " casting conversion: "(Object)o.|" - elseif items[0] =~ s:RE_CASTING - call s:Info('Casting conversion. "' . items[0] . '"') - let subs = split(substitute(items[0], s:RE_CASTING, '\1;\2', ''), ';') - let ti = s:DoGetClassInfo(subs[0]) - - " array access: "var[i][j].|" Note: "var[i][]" is incorrect - elseif items[0] =~# s:RE_ARRAY_ACCESS - let subs = split(substitute(items[0], s:RE_ARRAY_ACCESS, '\1;\2', ''), ';') - if get(subs, 1, '') !~ s:RE_BRACKETS - let typename = s:GetDeclaredClassName(subs[0]) - call s:Info('ArrayAccess. "' .items[0]. '.|" typename: "' . typename . '"') - if (typename != '') - let ti = s:ArrayAccess(typename, items[0]) - endif - endif - endif - endif - - - " - " next items - " - while !empty(ti) && ii < len(items) - " method invocation: "PrimaryExpr.method(parameters)[].|" - if items[ii] =~ '^\s*' . s:RE_IDENTIFIER . '\s*(' - let ti = s:MethodInvocation(items[ii], ti, itemkind) - let itemkind = 0 - let ii += 1 - continue - - - " expression of selection, field access, array access - elseif items[ii] =~ s:RE_SELECT_OR_ACCESS - let subs = split(substitute(items[ii], s:RE_SELECT_OR_ACCESS, '\1;\2', ''), ';') - let ident = subs[0] - let brackets = get(subs, 1, '') - - " package members - if itemkind/10 == 2 && empty(brackets) && !s:IsKeyword(ident) - let qn = join(items[:ii], '.') - if type(ti) == type([]) - let idx = s:Index(ti, ident, 'word') - if idx >= 0 - if ti[idx].kind == 'P' - unlet ti - let ti = s:GetMembers(qn) - let ii += 1 - continue - elseif ti[idx].kind == 'C' - unlet ti - let ti = s:DoGetClassInfo(qn) - let itemkind = 11 - let ii += 1 - continue - endif - endif - endif - - - " type members - elseif itemkind/10 == 1 && empty(brackets) - if ident ==# 'class' || ident ==# 'this' || ident ==# 'super' - let ti = s:DoGetClassInfo(ident == 'class' ? 'java.lang.Class' : join(items[:ii-1], '.')) - let itemkind = ident ==# 'this' ? 1 : ident ==# 'super' ? 2 : 0 - let ii += 1 - continue - - elseif !s:IsKeyword(ident) && type(ti) == type({}) && get(ti, 'tag', '') == 'CLASSDEF' - " accessible static field - "let idx = s:Index(get(ti, 'fields', []), ident, 'n') - "if idx >= 0 && s:IsStatic(ti.fields[idx].m) - " let ti = s:ArrayAccess(ti.fields[idx].t, items[ii]) - let members = s:SearchMember(ti, ident, 1, itemkind, 1, 0) - if !empty(members[2]) - let ti = s:ArrayAccess(members[2][0].t, items[ii]) - let itemkind = 0 - let ii += 1 - continue - endif - - " accessible nested type - "if !empty(filter(copy(get(ti, 'classes', [])), 'strpart(v:val, strridx(v:val, ".")) ==# "' . ident . '"')) - if !empty(members[0]) - let ti = s:DoGetClassInfo(join(items[:ii], '.')) - let ii += 1 - continue - endif - endif - - - " instance members - elseif itemkind/10 == 0 && !s:IsKeyword(ident) - if type(ti) == type({}) && get(ti, 'tag', '') == 'CLASSDEF' - "let idx = s:Index(get(ti, 'fields', []), ident, 'n') - "if idx >= 0 - " let ti = s:ArrayAccess(ti.fields[idx].t, items[ii]) - let members = s:SearchMember(ti, ident, 1, itemkind, 1, 0) - let itemkind = 0 - if !empty(members[2]) - let ti = s:ArrayAccess(members[2][0].t, items[ii]) - let ii += 1 - continue - endif - endif - endif - endif - - return [] - endwhile - - - " type info or package info --> members - if !empty(ti) - if type(ti) == type({}) - if get(ti, 'tag', '') == 'CLASSDEF' - if get(ti, 'name', '') == '!' - return [{'kind': 'f', 'word': 'class', 'menu': 'Class'}] - elseif get(ti, 'name', '') == '[' - return s:ARRAY_TYPE_MEMBERS - elseif itemkind < 20 - return s:DoGetMemberList(ti, itemkind) - endif - elseif get(ti, 'tag', '') == 'PACKAGE' - " TODO: ti -> members, in addition to packages in dirs - return s:GetMembers( substitute(join(items, '.'), '\s', '', 'g') ) - endif - elseif type(ti) == type([]) - return ti - endif - endif - - return [] -endfunction - - -fu! s:MethodInvocation(expr, ti, itemkind) - let subs = split(substitute(a:expr, '\s*\(' . s:RE_IDENTIFIER . '\)\s*\((.*\)', '\1;\2', ''), ';') - - " all methods matched - if empty(a:ti) - let methods = s:SearchForName(subs[0], 0, 1)[1] - elseif type(a:ti) == type({}) && get(a:ti, 'tag', '') == 'CLASSDEF' - let methods = s:SearchMember(a:ti, subs[0], 1, a:itemkind, 1, 0, a:itemkind == 2)[1] -" let methods = s:filter(get(a:ti, 'methods', []), 'item.n == "' . subs[0] . '"') -" if a:itemkind == 1 || a:itemkind == 2 -" let methods += s:filter(get(a:ti, 'declared_methods', []), 'item.n == "' . subs[0] . '"') -" endif - else - let methods = [] - endif - - let method = s:DetermineMethod(methods, subs[1]) - if !empty(method) - return s:ArrayAccess(method.r, a:expr) - endif - return {} -endfu - -fu! s:ArrayAccess(arraytype, expr) - if a:expr =~ s:RE_BRACKETS | return {} | endif - let typename = a:arraytype - - let dims = 0 - if typename[0] == '[' || typename[-1:] == ']' || a:expr[-1:] == ']' - let dims = s:CountDims(a:expr) - s:CountDims(typename) - if dims == 0 - let typename = matchstr(typename, s:RE_IDENTIFIER) - elseif dims < 0 - return s:ARRAY_TYPE_INFO - else - "echoerr 'dims exceeds' - endif - endif - if dims == 0 - if typename != 'void' && !s:IsBuiltinType(typename) - return s:DoGetClassInfo(typename) - endif - endif - return {} -endfu - - -" Quick information {{{1 -function! MyBalloonExpr() - if (searchdecl(v:beval_text, 1, 0) == 0) - return s:GetVariableDeclaration() - endif - return '' -" return 'Cursor is at line ' . v:beval_lnum . -" \', column ' . v:beval_col . -" \ ' of file ' . bufname(v:beval_bufnr) . -" \ ' on word "' . v:beval_text . '"' -endfunction -"set bexpr=MyBalloonExpr() -"set ballooneval - -" parameters information {{{1 -fu! javacomplete#CompleteParamsInfo(findstart, base) - if a:findstart - return col('.') - 1 - endif - - - let mi = s:GetMethodInvocationExpr(s:GetStatement()) - if empty(mi.method) - return [] - endif - - " TODO: how to determine overloaded functions - "let mi.params = s:EvalParams(mi.params) - if empty(mi.expr) - let methods = s:SearchForName(mi.method, 0, 1)[1] - let result = eval('[' . s:DoGetMethodList(methods) . ']') - elseif mi.method == '+' - let result = s:GetConstructorList(mi.expr) - else - let result = s:CompleteAfterDot(mi.expr) - endif - - if !empty(result) - if !empty(mi.method) && mi.method != '+' - let result = filter(result, "type(v:val) == type('') ? v:val ==# '" . mi.method . "' : v:val['word'] ==# '" . mi.method . "('") - endif - return result - endif -endfu - -" scanning and parsing {{{1 - -" Search back from the cursor position till meeting '{' or ';'. -" '{' means statement start, ';' means end of a previous statement. -" Return: statement before cursor -" Note: It's the base for parsing. And It's OK for most cases. -function! s:GetStatement() - if getline('.') =~ '^\s*\(import\|package\)\s\+' - return strpart(getline('.'), match(getline('.'), '\(import\|package\)'), col('.')-1) - endif - - let lnum_old = line('.') - let col_old = col('.') - - while 1 - if search('[{};]\|<%\|<%!', 'bW') == 0 - let lnum = 1 - let col = 1 - else - if s:InCommentOrLiteral(line('.'), col('.')) - continue - endif - - normal w - let lnum = line('.') - let col = col('.') - endif - break - endwhile - - silent call cursor(lnum_old, col_old) - return s:MergeLines(lnum, col, lnum_old, col_old) -endfunction - -fu! s:MergeLines(lnum, col, lnum_old, col_old) - let lnum = a:lnum - let col = a:col - - let str = '' - if lnum < a:lnum_old - let str = s:Prune(strpart(getline(lnum), a:col-1)) - let lnum += 1 - while lnum < a:lnum_old - let str .= s:Prune(getline(lnum)) - let lnum += 1 - endwhile - let col = 1 - endif - let lastline = strpart(getline(a:lnum_old), col-1, a:col_old-col) - let str .= s:Prune(lastline, col) - let str = s:RemoveBlockComments(str) - " generic in JAVA 5+ - while match(str, s:RE_TYPE_ARGUMENTS) != -1 - let str = substitute(str, '\(' . s:RE_TYPE_ARGUMENTS . '\)', '\=repeat(" ", len(submatch(1)))', 'g') - endwhile - let str = substitute(str, '\s\s\+', ' ', 'g') - let str = substitute(str, '\([.()]\)[ \t]\+', '\1', 'g') - let str = substitute(str, '[ \t]\+\([.()]\)', '\1', 'g') - return s:Trim(str) . matchstr(lastline, '\s*$') -endfu - -" Extract a clean expr, removing some non-necessary characters. -fu! s:ExtractCleanExpr(expr) - let cmd = substitute(a:expr, '[ \t\r\n]\+\([.()[\]]\)', '\1', 'g') - let cmd = substitute(cmd, '\([.()[\]]\)[ \t\r\n]\+', '\1', 'g') - - let pos = strlen(cmd)-1 - while pos >= 0 && cmd[pos] =~ '[a-zA-Z0-9_.)\]]' - if cmd[pos] == ')' - let pos = s:SearchPairBackward(cmd, pos, '(', ')') - elseif cmd[pos] == ']' - let pos = s:SearchPairBackward(cmd, pos, '[', ']') - endif - let pos -= 1 - endwhile - - " try looking back for "new" - let idx = match(strpart(cmd, 0, pos+1), '\<new[ \t\r\n]*$') - - return strpart(cmd, idx != -1 ? idx : pos+1) -endfu - -fu! s:ParseExpr(expr) - let items = [] - let s = 0 - " recognize ClassInstanceCreationExpr as a whole - let e = matchend(a:expr, '^\s*new\s\+' . s:RE_QUALID . '\s*[([]')-1 - if e < 0 - let e = match(a:expr, '[.([]') - endif - let isparen = 0 - while e >= 0 - if a:expr[e] == '.' - let subexpr = strpart(a:expr, s, e-s) - call extend(items, isparen ? s:ProcessParentheses(subexpr) : [subexpr]) - let isparen = 0 - let s = e + 1 - elseif a:expr[e] == '(' - let e = s:GetMatchedIndexEx(a:expr, e, '(', ')') - let isparen = 1 - if e < 0 - break - else - let e = matchend(a:expr, '^\s*[.[]', e+1)-1 - continue - endif - elseif a:expr[e] == '[' - let e = s:GetMatchedIndexEx(a:expr, e, '[', ']') - if e < 0 - break - else - let e = matchend(a:expr, '^\s*[.[]', e+1)-1 - continue - endif - endif - let e = match(a:expr, '[.([]', s) - endwhile - let tail = strpart(a:expr, s) - if tail !~ '^\s*$' - call extend(items, isparen ? s:ProcessParentheses(tail) : [tail]) - endif - - return items -endfu - -" Given optional argument, call s:ParseExpr() to parser the nonparentheses expr -fu! s:ProcessParentheses(expr, ...) - let s = matchend(a:expr, '^\s*(') - if s != -1 - let e = s:GetMatchedIndexEx(a:expr, s-1, '(', ')') - if e >= 0 - let tail = strpart(a:expr, e+1) - if tail =~ '^\s*[\=$' - return s:ProcessParentheses(strpart(a:expr, s, e-s), 1) - elseif tail =~ '^\s*\w' - return [strpart(a:expr, 0, e+1) . 'obj.'] - endif - endif - - " multi-dot-expr except for new expr - elseif a:0 > 0 && stridx(a:expr, '.') != match(a:expr, '\.\s*$') && a:expr !~ '^\s*new\s\+' - return s:ParseExpr(a:expr) - endif - return [a:expr] -endfu - -" return {'expr': , 'method': , 'params': } -fu! s:GetMethodInvocationExpr(expr) - let idx = strlen(a:expr)-1 - while idx >= 0 - if a:expr[idx] == '(' - break - elseif a:expr[idx] == ')' - let idx = s:SearchPairBackward(a:expr, idx, '(', ')') - elseif a:expr[idx] == ']' - let idx = s:SearchPairBackward(a:expr, idx, '[', ']') - endif - let idx -= 1 - endwhile - - let mi = {'expr': strpart(a:expr, 0, idx+1), 'method': '', 'params': strpart(a:expr, idx+1)} - let idx = match(mi.expr, '\<new\s\+' . s:RE_QUALID . '\s*(\s*$') - if idx >= 0 - let mi.method = '+' - let mi.expr = substitute(matchstr(strpart(mi.expr, idx+4), s:RE_QUALID), '\s', '', 'g') - else - let idx = match(mi.expr, '\<' . s:RE_IDENTIFIER . '\s*(\s*$') - if idx >= 0 - let subs = s:SplitAt(mi.expr, idx-1) - let mi.method = substitute(subs[1], '\s*(\s*$', '', '') - let mi.expr = s:ExtractCleanExpr(subs[0]) - endif - endif - return mi -endfu - -" imports {{{1 -function! s:GenerateImports() - let imports = [] - - let lnum_old = line('.') - let col_old = col('.') - call cursor(1, 1) - - if &ft == 'jsp' - while 1 - let lnum = search('\<import\s*=[''"]', 'W') - if (lnum == 0) - break - endif - - let str = getline(lnum) - if str =~ '<%\s*@\s*page\>' || str =~ '<jsp:\s*directive.page\>' - let str = substitute(str, '.*import=[''"]\([a-zA-Z0-9_$.*, \t]\+\)[''"].*', '\1', '') - for item in split(str, ',') - call add(imports, substitute(item, '\s', '', 'g')) - endfor - endif - endwhile - else - while 1 - let lnum = search('\<import\>', 'W') - if (lnum == 0) - break - elseif !s:InComment(line("."), col(".")-1) - normal w - " TODO: search semicolon or import keyword, excluding comment - let stat = matchstr(getline(lnum)[col('.')-1:], '\(static\s\+\)\?\(' .s:RE_QUALID. '\%(\s*\.\s*\*\)\?\)\s*;') - if !empty(stat) - call add(imports, stat[:-2]) - endif - endif - endwhile - endif - - call cursor(lnum_old, col_old) - return imports -endfunction - -fu! s:GetImports(kind, ...) - let filekey = a:0 > 0 && !empty(a:1) ? a:1 : s:GetCurrentFileKey() - let props = get(s:files, filekey, {}) - if !has_key(props, a:kind) - let props['imports'] = filekey == s:GetCurrentFileKey() ? s:GenerateImports() : props.unit.imports - let props['imports_static'] = [] - let props['imports_fqn'] = [] - let props['imports_star'] = ['java.lang.'] - if &ft == 'jsp' || filekey =~ '\.jsp$' - let props.imports_star += ['javax.servlet.', 'javax.servlet.http.', 'javax.servlet.jsp.'] - endif - - for import in props.imports - let subs = split(substitute(import, '^\s*\(static\s\+\)\?\(' .s:RE_QUALID. '\%(\s*\.\s*\*\)\?\)\s*$', '\1;\2', ''), ';', 1) - let qid = substitute(subs[1] , '\s', '', 'g') - if !empty(subs[0]) - call add(props.imports_static, qid) - elseif qid[-1:] == '*' - call add(props.imports_star, qid[:-2]) - else - call add(props.imports_fqn, qid) - endif - endfor - let s:files[filekey] = props - endif - return get(props, a:kind, []) -endfu - -" search for name in -" return the fqn matched -fu! s:SearchSingleTypeImport(name, fqns) - let matches = s:filter(a:fqns, 'item =~# ''\<' . a:name . '$''') - if len(matches) == 1 - return matches[0] - elseif !empty(matches) - echoerr 'Name "' . a:name . '" conflicts between ' . join(matches, ' and ') - return matches[0] - endif - return '' -endfu - -" search for name in static imports, return list of members with the same name -" return [types, methods, fields] -fu! s:SearchStaticImports(name, fullmatch) - let result = [[], [], []] - let candidates = [] " list of the canonical name - for item in s:GetImports('imports_static') - if item[-1:] == '*' " static import on demand - call add(candidates, item[:-3]) - elseif item[strridx(item, '.')+1:] ==# a:name - \ || (!a:fullmatch && item[strridx(item, '.')+1:] =~ '^' . a:name) - call add(candidates, item[:strridx(item, '.')]) - endif - endfor - if empty(candidates) - return result - endif - - - " read type info which are not in cache - let commalist = '' - for typename in candidates - if !has_key(s:cache, typename) - let commalist .= typename . ',' - endif - endfor - if commalist != '' - let res = s:RunReflection('-E', commalist, 's:SearchStaticImports in Batch') - if res =~ "^{'" - let dict = eval(res) - for key in keys(dict) - let s:cache[key] = s:Sort(dict[key]) - endfor - endif - endif - - " search in all candidates - for typename in candidates - let ti = get(s:cache, typename, 0) - if type(ti) == type({}) && get(ti, 'tag', '') == 'CLASSDEF' - let members = s:SearchMember(ti, a:name, a:fullmatch, 12, 1, 0) - let result[1] += members[1] - let result[2] += members[2] - "let pattern = 'item.n ' . (a:fullmatch ? '==# ''' : '=~# ''^') . a:name . ''' && s:IsStatic(item.m)' - "let result[1] += s:filter(get(ti, 'methods', []), pattern) - "let result[2] += s:filter(get(ti, 'fields', []), pattern) - else - " TODO: mark the wrong import declaration. - endif - endfor - return result -endfu - - -" search decl {{{1 -" Return: The declaration of identifier under the cursor -" Note: The type of a variable must be imported or a fqn. -function! s:GetVariableDeclaration() - let lnum_old = line('.') - let col_old = col('.') - - silent call search('[^a-zA-Z0-9$_.,?<>[\] \t\r\n]', 'bW') " call search('[{};(,]', 'b') - normal w - let lnum = line('.') - let col = col('.') - if (lnum == lnum_old && col == col_old) - return '' - endif - -" silent call search('[;){]') -" let lnum_end = line('.') -" let col_end = col('.') -" let declaration = '' -" while (lnum <= lnum_end) -" let declaration = declaration . getline(lnum) -" let lnum = lnum + 1 -" endwhile -" let declaration = strpart(declaration, col-1) -" let declaration = substitute(declaration, '\.[ \t]\+', '.', 'g') - - silent call cursor(lnum_old, col_old) - return s:MergeLines(lnum, col, lnum_old, col_old) -endfunction - -function! s:FoundClassDeclaration(type) - let lnum_old = line('.') - let col_old = col('.') - call cursor(1, 1) - while 1 - let lnum = search('\<\C\(class\|interface\|enum\)[ \t\n\r]\+' . a:type . '[< \t\n\r]', 'W') - if lnum == 0 || !s:InCommentOrLiteral(line('.'), col('.')) - break - endif - endwhile - - " search mainly for the cases: " class /* block comment */ Ident" - " " class // comment \n Ident " - if lnum == 0 - let found = 0 - while !found - let lnum = search('\<\C\(class\|interface\|enum\)[ \t\n\r]\+', 'W') - if lnum == 0 - break - elseif s:InCommentOrLiteral(line('.'), col('.')) - continue - else - normal w - " skip empty line - while getline(line('.'))[col('.')-1] == '' - normal w - endwhile - let lnum = line('.') - let col = col('.') - while 1 - if match(getline(lnum)[col-1:], '^[ \t\n\r]*' . a:type . '[< \t\n\r]') >= 0 - let found = 1 - " meets comment - elseif match(getline(lnum)[col-1:], '^[ \t\n\r]*\(//\|/\*\)') >= 0 - if getline(lnum)[col-1:col] == '//' - normal $eb - else - let lnum = search('\*\/', 'W') - if lnum == 0 - break - endif - normal web - endif - let lnum = line('.') - let col = col('.') - continue - endif - break - endwhile - endif - endwhile - endif - - silent call cursor(lnum_old, col_old) - return lnum -endfu - -fu! s:FoundClassLocally(type) - " current path - if globpath(expand('%:p:h'), a:type . '.java') != '' - return 1 - endif - - " - let srcpath = javacomplete#GetSourcePath(1) - let file = globpath(srcpath, substitute(fqn, '\.', '/', 'g') . '.java') - if file != '' - return 1 - endif - - return 0 -endfu - -" regexp samples: -" echo search('\(\(public\|protected|private\)[ \t\n\r]\+\)\?\(\(static\)[ \t\n\r]\+\)\?\(\<class\>\|\<interface\>\)[ \t\n\r]\+HelloWorld[^a-zA-Z0-9_$]', 'W') -" echo substitute(getline('.'), '.*\(\(public\|protected\|private\)[ \t\n\r]\+\)\?\(\(static\)[ \t\n\r]\+\)\?\(\<class\>\|\<interface\>\)\s\+\([a-zA-Z0-9_]\+\)\s\+\(\(implements\|extends\)\s\+\([^{]\+\)\)\?\s*{.*', '["\1", "\2", "\3", "\4", "\5", "\6", "\8", "\9"]', '') -" code sample: -function! s:GetClassDeclarationOf(type) - call cursor(1, 1) - let decl = [] - - let lnum = search('\(\<class\>\|\<interface\>\)[ \t\n\r]\+' . a:type . '[^a-zA-Z0-9_$]', 'W') - if (lnum != 0) - " TODO: search back for optional 'public | private' and 'static' - " join lines till to '{' - let lnum_end = search('{') - if (lnum_end != 0) - let str = '' - while (lnum <= lnum_end) - let str = str . getline(lnum) - let lnum = lnum + 1 - endwhile - - exe "let decl = " . substitute(str, '.*\(\<class\>\|\<interface\>\)\s\+\([a-zA-Z0-9_]\+\)\s\+\(\(implements\|extends\)\s\+\([^{]\+\)\)\?\s*{.*', '["\1", "\2", "\4", "\5"]', '') - endif - endif - - return decl -endfunction - -" return list -" 0 class | interface -" 1 name -" [2 implements | extends ] -" [3 parent list ] -function! s:GetThisClassDeclaration() - let lnum_old = line('.') - let col_old = col('.') - - while (1) - call search('\(\<class\C\>\|\<interface\C\>\|\<enum\C\>\)[ \t\r\n]\+', 'bW') - if !s:InComment(line("."), col(".")-1) - if getline('.')[col('.')-2] !~ '\S' - break - endif - end - endwhile - - " join lines till to '{' - let str = '' - let lnum = line('.') - call search('{') - let lnum_end = line('.') - while (lnum <= lnum_end) - let str = str . getline(lnum) - let lnum = lnum + 1 - endwhile - - - let declaration = substitute(str, '.*\(\<class\>\|\<interface\>\)\s\+\([a-zA-Z0-9_]\+\)\(\s\+\(implements\|extends\)\s\+\([^{]\+\)\)\?\s*{.*', '["\1", "\2", "\4", "\5"]', '') - call cursor(lnum_old, col_old) - if declaration !~ '^[' - echoerr 'Some error occurs when recognizing this class:' . declaration - return ['', ''] - endif - exe "let list = " . declaration - return list -endfunction - -" searches for name of a var or a field and determines the meaning {{{1 - -" The standard search order of a variable or field is as follows: -" 1. Local variables declared in the code block, for loop, or catch clause -" from current scope up to the most outer block, a method or an initialization block -" 2. Parameters if the code is in a method or ctor -" 3. Fields of the type -" 4. Accessible inherited fields. -" 5. If the type is a nested type, -" local variables of the enclosing block or fields of the enclosing class. -" Note that if the type is a static nested type, only static members of an enclosing block or class are searched -" Reapply this rule to the upper block and class enclosing the enclosing type recursively -" 6. Accessible static fields imported. -" It is allowed that several fields with the same name. - -" The standard search order of a method is as follows: -" 1. Methods of the type -" 2. Accessible inherited methods. -" 3. Methods of the enclosing class if the type is a nested type. -" 4. Accessible static methods imported. -" It is allowed that several methods with the same name and signature. - -" first return at once if found one. -" fullmatch 1 - equal, 0 - match beginning -" return [types, methods, fields, vars] -fu! s:SearchForName(name, first, fullmatch) - let result = [[], [], [], []] - if s:IsKeyword(a:name) - return result - endif - - " use java_parser.vim - if javacomplete#GetSearchdeclMethod() == 4 - " declared in current file - let unit = javacomplete#parse() - let targetPos = java_parser#MakePos(line('.')-1, col('.')-1) - let trees = s:SearchNameInAST(unit, a:name, targetPos, a:fullmatch) - for tree in trees - if tree.tag == 'VARDEF' - call add(result[2], tree) - elseif tree.tag == 'METHODDEF' - call add(result[1], tree) - elseif tree.tag == 'CLASSDEF' - call add(result[0], tree.name) - endif - endfor - - if a:first && result != [[], [], [], []] | return result | endif - - " Accessible inherited members - let type = get(s:SearchTypeAt(unit, targetPos), -1, {}) - if !empty(type) - let members = s:SearchMember(type, a:name, a:fullmatch, 2, 1, 0, 1) - let result[0] += members[0] - let result[1] += members[1] - let result[2] += members[2] -" "let ti = s:AddInheritedClassInfo({}, type) -" if !empty(ti) -" let comparator = a:fullmatch ? "=~# '^" : "==# '" -" let result[0] += s:filter(get(ti, 'classes', []), 'item ' . comparator . a:name . "'") -" let result[1] += s:filter(get(ti, 'methods', []), 'item.n ' . comparator . a:name . "'") -" let result[2] += s:filter(get(ti, 'fields', []), 'item.n ' . comparator . a:name . "'") -" if a:0 > 0 -" let result[1] += s:filter(get(ti, 'declared_methods', []), 'item.n ' . comparator . a:name . "'") -" let result[2] += s:filter(get(ti, 'declared_fields', []), 'item.n ' . comparator . a:name . "'") -" endif -" if a:first && result != [[], [], [], []] | return result | endif -" endif - endif - - " static import - let si = s:SearchStaticImports(a:name, a:fullmatch) - let result[1] += si[1] - let result[2] += si[2] - endif - return result -endfu - -" TODO: how to determine overloaded functions -fu! s:DetermineMethod(methods, parameters) - return get(a:methods, 0, {}) -endfu - -" Parser.GetType() in insenvim -function! s:GetDeclaredClassName(var) - let var = s:Trim(a:var) - call s:Trace('GetDeclaredClassName for "' . var . '"') - if var =~# '^\(this\|super\)$' - return var - endif - - - " Special handling for builtin objects in JSP - if &ft == 'jsp' - if get(s:JSP_BUILTIN_OBJECTS, a:var, '') != '' - return s:JSP_BUILTIN_OBJECTS[a:var] - endif - endif - - " use java_parser.vim - if javacomplete#GetSearchdeclMethod() == 4 - let variable = get(s:SearchForName(var, 1, 1)[2], -1, {}) - return get(variable, 'tag', '') == 'VARDEF' ? java_parser#type2Str(variable.vartype) : get(variable, 't', '') - endif - - - let ic = &ignorecase - setlocal noignorecase - - let searched = javacomplete#GetSearchdeclMethod() == 2 ? s:Searchdecl(var, 1, 0) : searchdecl(var, 1, 0) - if (searched == 0) - " code sample: - " String tmp; java. - " lang. String str, value; - " for (int i = 0, j = 0; i < 10; i++) { - " j = 0; - " } - let declaration = s:GetVariableDeclaration() - " Assume it a class member, and remove modifiers - let class = substitute(declaration, '^\(public\s\+\|protected\s\+\|private\s\+\|abstract\s\+\|static\s\+\|final\s\+\|native\s\+\)*', '', '') - let class = substitute(class, '\s*\([a-zA-Z0-9_.]\+\)\(\[\]\)\?\s\+.*', '\1\2', '') - let class = substitute(class, '\([a-zA-Z0-9_.]\)<.*', '\1', '') - call s:Info('class: "' . class . '" declaration: "' . declaration . '" for ' . a:var) - let &ignorecase = ic - if class != '' && class !=# a:var && class !=# 'import' && class !=# 'class' - return class - endif - endif - - let &ignorecase = ic - call s:Trace('GetDeclaredClassName: cannot find') - return '' -endfunction - -" using java_parser.vim {{{1 -" javacomplete#parse() {{{2 -fu! javacomplete#parse(...) - let filename = a:0 == 0 ? '%' : a:1 - - let changed = 0 - if filename == '%' - let filename = s:GetCurrentFileKey() - let props = get(s:files, filename, {}) - if get(props, 'changedtick', -1) != b:changedtick - let changed = 1 - let props.changedtick = b:changedtick - let lines = getline('^', '$') - endif - else - let props = get(s:files, filename, {}) - if get(props, 'modifiedtime', 0) != getftime(filename) - let changed = 1 - let props.modifiedtime = getftime(filename) - let lines = readfile(filename) - endif - endif - - if changed - call java_parser#InitParser(lines) - call java_parser#SetLogLevel(5) - let props.unit = java_parser#compilationUnit() - - let package = has_key(props.unit, 'package') ? props.unit.package . '.' : '' - call s:UpdateFQN(props.unit, package) - endif - let s:files[filename] = props - return props.unit -endfu - -" update fqn for toplevel types or nested types. -" not for local type or anonymous type -fu! s:UpdateFQN(tree, qn) - if a:tree.tag == 'TOPLEVEL' - for def in a:tree.types - call s:UpdateFQN(def, a:qn) - endfor - elseif a:tree.tag == 'CLASSDEF' - let a:tree.fqn = a:qn . a:tree.name - for def in a:tree.defs - if def.tag == 'CLASSDEF' - call s:UpdateFQN(def, a:tree.fqn . '.') - endif - endfor - endif -endfu - -" TreeVisitor {{{2 -fu! s:visitTree(tree, param) dict - if type(a:tree) == type({}) - exe get(self, get(a:tree, 'tag', ''), '') - elseif type(a:tree) == type([]) - for tree in a:tree - call self.visit(tree, a:param) - endfor - endif -endfu - -let s:TreeVisitor = {'visit': function('s:visitTree'), - \ 'TOPLEVEL' : 'call self.visit(a:tree.types, a:param)', - \ 'BLOCK' : 'let stats = a:tree.stats | if stats == [] | call java_parser#GotoPosition(a:tree.pos) | let stats = java_parser#block().stats | endif | call self.visit(stats, a:param)', - \ 'DOLOOP' : 'call self.visit(a:tree.body, a:param) | call self.visit(a:tree.cond, a:param)', - \ 'WHILELOOP' : 'call self.visit(a:tree.cond, a:param) | call self.visit(a:tree.body, a:param)', - \ 'FORLOOP' : 'call self.visit(a:tree.init, a:param) | call self.visit(a:tree.cond, a:param) | call self.visit(a:tree.step, a:param) | call self.visit(a:tree.body, a:param)', - \ 'FOREACHLOOP' : 'call self.visit(a:tree.var, a:param) | call self.visit(a:tree.expr, a:param) | call self.visit(a:tree.body, a:param)', - \ 'LABELLED' : 'call self.visit(a:tree.body, a:param)', - \ 'SWITCH' : 'call self.visit(a:tree.selector, a:param) | call self.visit(a:tree.cases, a:param)', - \ 'CASE' : 'call self.visit(a:tree.pat, a:param) | call self.visit(a:tree.stats, a:param)', - \ 'SYNCHRONIZED': 'call self.visit(a:tree.lock, a:param) | call self.visit(a:tree.body, a:param)', - \ 'TRY' : 'call self.visit(a:tree.body, a:param) | call self.visit(a:tree.catchers, a:param) | call self.visit(a:tree.finalizer, a:param) ', - \ 'CATCH' : 'call self.visit(a:tree.param,a:param) | call self.visit(a:tree.body, a:param)', - \ 'CONDEXPR' : 'call self.visit(a:tree.cond, a:param) | call self.visit(a:tree.truepart, a:param) | call self.visit(a:tree.falsepart, a:param)', - \ 'IF' : 'call self.visit(a:tree.cond, a:param) | call self.visit(a:tree.thenpart, a:param) | if has_key(a:tree, "elsepart") | call self.visit(a:tree.elsepart, a:param) | endif', - \ 'EXEC' : 'call self.visit(a:tree.expr, a:param)', - \ 'APPLY' : 'call self.visit(a:tree.meth, a:param) | call self.visit(a:tree.args, a:param)', - \ 'NEWCLASS' : 'call self.visit(a:tree.def, a:param)' - \} - -let s:TV_CMP_POS = 'a:tree.pos <= a:param.pos && a:param.pos <= get(a:tree, "endpos", -1)' -let s:TV_CMP_POS_BODY = 'has_key(a:tree, "body") && a:tree.body.pos <= a:param.pos && a:param.pos <= get(a:tree.body, "endpos", -1)' - -" Return a stack of enclosing types (including local or anonymous classes). -" Given the optional argument, return all (toplevel or static member) types besides enclosing types. -fu! s:SearchTypeAt(tree, targetPos, ...) - let s:TreeVisitor.CLASSDEF = 'if a:param.allNonLocal || ' . s:TV_CMP_POS . ' | call add(a:param.result, a:tree) | call self.visit(a:tree.defs, a:param) | endif' - let s:TreeVisitor.METHODDEF = 'if ' . s:TV_CMP_POS_BODY . ' | call self.visit(a:tree.body, a:param) | endif' - let s:TreeVisitor.VARDEF = 'if has_key(a:tree, "init") && !a:param.allNonLocal && ' . s:TV_CMP_POS . ' | call self.visit(a:tree.init, a:param) | endif' - - let result = [] - call s:TreeVisitor.visit(a:tree, {'result': result, 'pos': a:targetPos, 'allNonLocal': a:0 == 0 ? 0 : 1}) - return result -endfu - -" a:1 match beginning -" return a stack of matching name -fu! s:SearchNameInAST(tree, name, targetPos, fullmatch) - let comparator = a:fullmatch ? '==#' : '=~# "^" .' - let cmd = 'if a:tree.name ' .comparator. ' a:param.name | call add(a:param.result, a:tree) | endif' - let s:TreeVisitor.CLASSDEF = 'if ' . s:TV_CMP_POS . ' | ' . cmd . ' | call self.visit(a:tree.defs, a:param) | endif' - let s:TreeVisitor.METHODDEF = cmd . ' | if ' . s:TV_CMP_POS_BODY . ' | call self.visit(a:tree.params, a:param) | call self.visit(a:tree.body, a:param) | endif' - let s:TreeVisitor.VARDEF = cmd . ' | if has_key(a:tree, "init") && ' . s:TV_CMP_POS . ' | call self.visit(a:tree.init, a:param) | endif' - - let result = [] - call s:TreeVisitor.visit(a:tree, {'result': result, 'pos': a:targetPos, 'name': a:name}) - "call s:Info(a:name . ' ' . string(result) . ' line: ' . line('.') . ' col: ' . col('.')) . ' ' . a:targetPos - return result -endfu - - -" javacomplete#Searchdecl {{{2 -" TODO: -fu! javacomplete#Searchdecl() - let var = expand('<cword>') - - let line = line('.')-1 - let col = col('.')-1 - - - if var =~# '^\(this\|super\)$' - if &ft == 'jsp' - return '' - endif - - let matchs = s:SearchTypeAt(javacomplete#parse(), java_parser#MakePos(line, col)) - - let stat = s:GetStatement() - for t in matchs - if stat =~ t.name - let coor = java_parser#DecodePos(t.pos) - return var . '(' . (coor.line+1) . ',' . (coor.col) . ') ' . getline(coor.line+1) - endif - endfor - if len(matchs) > 0 - let coor = java_parser#DecodePos(matchs[len(matchs)-1].pos) - return var . '(' . (coor.line+1) . ',' . (coor.col) . ') ' . getline(coor.line+1) - endif - return '' - endif - - " Type.this. - " new Type() - " new Type(param1, param2) - " this.field - " super.field - - let s:log = [] - - - " It may be an imported class. - let imports = [] - for fqn in s:GetImports('imports_fqn') - if fqn =~# '\<' . var . '\>$' - call add(imports, fqn) - endif - endfor - if len(imports) > 1 - echoerr 'Imports conflicts between ' . join(imports, ' and ') - endif - - - " Search in this buffer - let matchs = s:SearchNameInAST(javacomplete#parse(), var, java_parser#MakePos(line, col), 1) - - - let hint = var . ' ' - if !empty(matchs) - let tree = matchs[len(matchs)-1] - let coor = java_parser#DecodePos(tree.pos) - let hint .= '(' . (coor.line+1) . ',' . (coor.col) . ') ' - let hint .= getline(coor.line+1) "string(tree) - else - for fqn in imports - let ci = s:DoGetClassInfo(fqn) - if !empty(ci) - let hint .= ' ' . fqn - endif - " TODO: get javadoc - endfor - - endif - return hint -endfu - - -" java {{{1 - -fu! s:IsBuiltinType(name) - return index(s:PRIMITIVE_TYPES, a:name) >= 0 -endfu - -fu! s:IsKeyword(name) - return index(s:KEYWORDS, a:name) >= 0 -endfu - -fu! s:HasKeyword(name) - return a:name =~# s:RE_KEYWORDS -endfu - -fu! s:TailOfQN(qn) - return a:qn[strridx(a:qn, '.')+1:] -endfu - -" options {{{1 -" Methods to search declaration {{{2 -" 1 - by builtin searchdecl() -" 2 - by special Searchdecl() -" 4 - by java_parser -fu! javacomplete#GetSearchdeclMethod() - if &ft == 'jsp' - return 1 - endif - return exists('s:searchdecl') ? s:searchdecl : 4 -endfu - -fu! javacomplete#SetSearchdeclMethod(method) - let s:searchdecl = a:method -endfu - -" JDK1.1 {{{2 -fu! javacomplete#UseJDK11() - let s:isjdk11 = 1 -endfu - -" java compiler {{{2 -fu! javacomplete#GetCompiler() - return exists('s:compiler') && s:compiler !~ '^\s*$' ? s:compiler : 'javac' -endfu - -fu! javacomplete#SetCompiler(compiler) - let s:compiler = a:compiler -endfu - -" jvm launcher {{{2 -fu! javacomplete#GetJVMLauncher() - return exists('s:interpreter') && s:interpreter !~ '^\s*$' ? s:interpreter : 'java' -endfu - -fu! javacomplete#SetJVMLauncher(interpreter) - if javacomplete#GetJVMLauncher() != a:interpreter - let s:cache = {} - endif - let s:interpreter = a:interpreter -endfu - -" sourcepath {{{2 -fu! javacomplete#AddSourcePath(s) - if !isdirectory(a:s) - echoerr 'invalid source path: ' . a:s - return - endif - let path = fnamemodify(a:s, ':p:h') - if !exists('s:sourcepath') - let s:sourcepath = [path] - elseif index(s:sourcepath, path) == -1 - call add(s:sourcepath, path) - endif -endfu - -fu! javacomplete#DelSourcePath(s) - if !exists('s:sourcepath') || !isdirectory(a:s)| return | endif - let idx = index(s:sourcepath, a:s) - if idx != -1 - call remove(s:sourcepath, idx) - endif -endfu - -fu! javacomplete#SetSourcePath(s) - let paths = type(a:s) == type([]) ? a:s : split(a:s, javacomplete#GetClassPathSep()) - let s:sourcepath = [] - for path in paths - if isdirectory(path) - call add(s:sourcepath, fnamemodify(path, ':p:h')) - endif - endfor -endfu - -" return the sourcepath. Given argument, add current path or default package root path -" NOTE: Avoid path duplicate, otherwise globpath() will return duplicate result. -fu! javacomplete#GetSourcePath(...) - return join(s:GetSourceDirs(a:0 > 0 && a:1 ? expand('%:p') : ''), s:PATH_SEP) -endfu - -fu! s:GetSourceDirs(filepath, ...) - let dirs = exists('s:sourcepath') ? s:sourcepath : [] - - if !empty(a:filepath) - let filepath = fnamemodify(a:filepath, ':p:h') - - " get source path according to file path and package name - let packageName = a:0 > 0 ? a:1 : s:GetPackageName() - if packageName != '' - let path = fnamemodify(substitute(filepath, packageName, '', 'g'), ':p:h') - if index(dirs, path) < 0 - call add(dirs, path) - endif - endif - - " Consider current path as a sourcepath - if index(dirs, filepath) < 0 - call add(dirs, filepath) - endif - endif - return dirs -endfu - -" classpath {{{2 -fu! javacomplete#AddClassPath(s) - if !isdirectory(a:s) - echoerr 'invalid classpath: ' . a:s - return - endif - - if !exists('s:classpath') - let s:classpath = [a:s] - elseif index(s:classpath, a:s) == -1 - call add(s:classpath, a:s) - endif - let s:cache = {} -endfu - -fu! javacomplete#DelClassPath(s) - if !exists('s:classpath') | return | endif - let idx = index(s:classpath, a:s) - if idx != -1 - call remove(s:classpath, idx) - endif -endfu - -fu! javacomplete#SetClassPath(s) - if type(a:s) == type("") - let s:classpath = split(a:s, javacomplete#GetClassPathSep()) - elseif type(a:s) == type([]) - let s:classpath = a:s - endif - let s:cache = {} -endfu - -fu! javacomplete#GetClassPathSep() - return s:PATH_SEP -endfu - -fu! javacomplete#GetClassPath() - return exists('s:classpath') ? join(s:classpath, javacomplete#GetClassPathSep()) : '' -endfu - -" s:GetClassPath() {{{2 -fu! s:GetClassPath() - let path = s:GetJavaCompleteClassPath() . javacomplete#GetClassPathSep() - - if &ft == 'jsp' - let path .= s:GetClassPathOfJsp() - endif - - if exists('b:classpath') && b:classpath !~ '^\s*$' - return path . b:classpath - endif - - if exists('s:classpath') - return path . javacomplete#GetClassPath() - endif - - if exists('g:java_classpath') && g:java_classpath !~ '^\s*$' - return path . g:java_classpath - endif - - return path . $CLASSPATH -endfu - -fu! s:GetJavaCompleteClassPath() - let classfile = globpath(&rtp, 'autoload/Reflection.class') - if classfile == '' - let classfile = globpath($HOME, 'Reflection.class') - endif - if classfile == '' - " try to find source file and compile to $HOME - let srcfile = globpath(&rtp, 'autoload/Reflection.java') - if srcfile != '' - exe '!' . javacomplete#GetCompiler() . ' -d "' . $HOME . '" "' . srcfile . '"' - let classfile = globpath($HOME, 'Reflection.class') - if classfile == '' - echo srcfile . ' can not be compiled. Please check it' - endif - else - echo 'No Reflection.class found in $HOME or any autoload directory of the &rtp. And no Reflection.java found in any autoload directory of the &rtp to compile.' - endif - endif - return fnamemodify(classfile, ':p:h') -endfu - -fu! s:GetClassPathOfJsp() - if exists('b:classpath_jsp') - return b:classpath_jsp - endif - - let b:classpath_jsp = '' - let path = expand('%:p:h') - while 1 - if isdirectory(path . '/WEB-INF' ) - if isdirectory(path . '/WEB-INF/classes') - let b:classpath_jsp .= s:PATH_SEP . path . '/WEB-INF/classes' - endif - if isdirectory(path . '/WEB-INF/lib') - let libs = globpath(path . '/WEB-INF/lib', '*.jar') - if libs != '' - let b:classpath_jsp .= s:PATH_SEP . substitute(libs, "\n", s:PATH_SEP, 'g') - endif - endif - return b:classpath_jsp - endif - - let prev = path - let path = fnamemodify(path, ":p:h:h") - if path == prev - break - endif - endwhile - return '' -endfu - -" return only classpath which are directories -fu! s:GetClassDirs() - let dirs = [] - for path in split(s:GetClassPath(), s:PATH_SEP) - if isdirectory(path) - call add(dirs, fnamemodify(path, ':p:h')) - endif - endfor - return dirs -endfu - -" s:GetPackageName() {{{2 -fu! s:GetPackageName() - let lnum_old = line('.') - let col_old = col('.') - - call cursor(1, 1) - let lnum = search('^\s*package[ \t\r\n]\+\([a-zA-Z][a-zA-Z0-9.]*\);', 'w') - let packageName = substitute(getline(lnum), '^\s*package\s\+\([a-zA-Z][a-zA-Z0-9.]*\);', '\1', '') - - call cursor(lnum_old, col_old) - return packageName -endfu - -fu! s:IsStatic(modifier) - return a:modifier[strlen(a:modifier)-4] -endfu - -" utilities {{{1 -" Convert a file name into the unique form. -" Similar with fnamemodify(). NOTE that ':gs' should not be used. -fu! s:fnamecanonize(fname, mods) - return fnamemodify(a:fname, a:mods . ':gs?[\\/]\+?/?') -endfu - -" Similar with filter(), but returns a new list instead of operating in-place. -" `item` has the value of the current item. -fu! s:filter(expr, string) - if type(a:expr) == type([]) - let result = [] - for item in a:expr - if eval(a:string) - call add(result, item) - endif - endfor - return result - else - let result = {} - for item in items(a:expr) - if eval(a:string) - let result[item[0]] = item[1] - endif - endfor - return result - endif -endfu - -fu! s:Index(list, expr, key) - let i = 0 - while i < len(a:list) - if get(a:list[i], a:key, '') == a:expr - return i - endif - let i += 1 - endwhile - return -1 -endfu - -fu! s:Match(list, expr, key) - let i = 0 - while i < len(a:list) - if get(a:list[i], a:key, '') =~ a:expr - return i - endif - let i += 1 - endwhile - return -1 -endfu - -fu! s:KeepCursor(cmd) - let lnum_old = line('.') - let col_old = col('.') - exe a:cmd - call cursor(lnum_old, col_old) -endfu - -fu! s:InCommentOrLiteral(line, col) - if has("syntax") && &ft != 'jsp' - return synIDattr(synID(a:line, a:col, 1), "name") =~? '\(Comment\|String\|Character\)' - endif -endfu - -function! s:InComment(line, col) - if has("syntax") && &ft != 'jsp' - return synIDattr(synID(a:line, a:col, 1), "name") =~? 'comment' - endif -" if getline(a:line) =~ '\s*\*' -" return 1 -" endif -" let idx = strridx(getline(a:line), '//') -" if idx >= 0 && idx < a:col -" return 1 -" endif -" return 0 -endfunction - -" set string literal empty, remove comments, trim begining or ending spaces -" test case: ' sb. /* block comment*/ append( "stringliteral" ) // comment ' -function! s:Prune(str, ...) - if a:str =~ '^\s*$' | return '' | endif - - let str = substitute(a:str, '"\(\\\(["\\''ntbrf]\)\|[^"]\)*"', '""', 'g') - let str = substitute(str, '\/\/.*', '', 'g') - let str = s:RemoveBlockComments(str) - return a:0 > 0 ? str : str . ' ' -endfunction - -" Given argument, replace block comments with spaces of same number -fu! s:RemoveBlockComments(str, ...) - let result = a:str - let ib = match(result, '\/\*') - let ie = match(result, '\*\/') - while ib != -1 && ie != -1 && ib < ie - let result = strpart(result, 0, ib) . (a:0 == 0 ? ' ' : repeat(' ', ie-ib+2)) . result[ie+2: ] - let ib = match(result, '\/\*') - let ie = match(result, '\*\/') - endwhile - return result -endfu - -fu! s:Trim(str) - let str = substitute(a:str, '^\s*', '', '') - return substitute(str, '\s*$', '', '') -endfu - -fu! s:SplitAt(str, index) - return [strpart(a:str, 0, a:index+1), strpart(a:str, a:index+1)] -endfu - -" TODO: search pair used in string, like -" 'create(ao.fox("("), new String).foo().' -function! s:GetMatchedIndexEx(str, idx, one, another) - let pos = a:idx - while 0 <= pos && pos < len(a:str) - let pos = match(a:str, '['. a:one . escape(a:another, ']') .']', pos+1) - if pos != -1 - if a:str[pos] == a:one - let pos = s:GetMatchedIndexEx(a:str, pos, a:one, a:another) - elseif a:str[pos] == a:another - break - endif - endif - endwhile - return 0 <= pos && pos < len(a:str) ? pos : -3 -endfunction - -function! s:SearchPairBackward(str, idx, one, another) - let idx = a:idx - let n = 0 - while idx >= 0 - let idx -= 1 - if a:str[idx] == a:one - if n == 0 - break - endif - let n -= 1 - elseif a:str[idx] == a:another " nested - let n += 1 - endif - endwhile - return idx -endfunction - -fu! s:CountDims(str) - if match(a:str, '[[\]]') == -1 - return 0 - endif - - " int[] -> [I, String[] -> - let dims = len(matchstr(a:str, '^[\+')) - if dims == 0 - let idx = len(a:str)-1 - while idx >= 0 && a:str[idx] == ']' - let dims += 1 - let idx = s:SearchPairBackward(a:str, idx, '[', ']')-1 - endwhile - endif - return dims -endfu - -fu! s:GotoUpperBracket() - let searched = 0 - while (!searched) - call search('[{}]', 'bW') - if getline('.')[col('.')-1] == '}' - normal % - else - let searched = 1 - endif - endwhile -endfu - -" Improve recognition of variable declaration using my version of searchdecl() for accuracy reason. -" TODO: -fu! s:Searchdecl(name, ...) - let global = a:0 > 0 ? a:1 : 0 - let thisblock = a:0 > 1 ? a:2 : 1 - - call search('\<' . a:name . '\>', 'bW') - let lnum_old = line('.') - let col_old = col('.') - - call s:GotoUpperBracket() - let lnum_bracket = line('.') - let col_bracket = col('.') - call search('\<' . a:name . '\>', 'W', lnum_old) - if line('.') != lnum_old || col('.') != col_old - return 0 - endif - - " search globally - if global - call cursor(lnum_bracket, col_bracket) - " search backward - while (1) - if search('\([{}]\|\<' . a:name . '\>\)', 'bW') == 0 - break - endif - if s:InComment(line('.'), col('.')) "|| s:InStringLiteral() - continue - endif - let cword = expand('<cword>') - if cword == a:name - return 0 - endif - if getline('.')[col('.')-1] == '}' - normal % - endif - endwhile - - call cursor(lnum_old, col_old) - " search forward - call search('[{};]', 'W') - while (1) - if search('\([{}]\|\<' . a:name . '\>\)', 'W') == 0 - break - endif - if s:InComment(line('.'), col('.')) "|| s:InStringLiteral() - continue - endif - let cword = expand('<cword>') - if cword == a:name - return 0 - endif - if getline('.')[col('.')-1] == '{' - normal % - endif - endwhile - endif - return 1 -endfu -"nmap <F8> :call <SID>Searchdecl(expand('<cword>'))<CR> - -fu! javacomplete#Exe(cmd) - exe a:cmd -endfu - -" cache utilities {{{1 - -" key of s:files for current buffer. It may be the full path of current file or the bufnr of unnamed buffer, and is updated when BufEnter, BufLeave. -fu! s:GetCurrentFileKey() - return has("autocmd") ? s:curfilekey : empty(expand('%')) ? bufnr('%') : expand('%:p') -endfu - -fu! s:SetCurrentFileKey() - let s:curfilekey = empty(expand('%')) ? bufnr('%') : expand('%:p') -endfu - -call s:SetCurrentFileKey() -if has("autocmd") - autocmd BufEnter *.java call s:SetCurrentFileKey() - autocmd FileType java call s:SetCurrentFileKey() -endif - - -" Log utilities {{{1 -fu! s:WatchVariant(variant) - "echoerr a:variant -endfu - -" level -" 5 off/fatal -" 4 error -" 3 warn -" 2 info -" 1 debug -" 0 trace -fu! javacomplete#SetLogLevel(level) - let s:loglevel = a:level -endfu - -fu! javacomplete#GetLogLevel() - return exists('s:loglevel') ? s:loglevel : 3 -endfu - -fu! javacomplete#GetLogContent() - return s:log -endfu - -fu! s:Trace(msg) - call s:Log(0, a:msg) -endfu - -fu! s:Debug(msg) - call s:Log(1, a:msg) -endfu - -fu! s:Info(msg) - call s:Log(2, a:msg) -endfu - -fu! s:Log(level, key, ...) - if a:level >= javacomplete#GetLogLevel() - echo a:key - call add(s:log, a:key) - endif -endfu - -fu! s:System(cmd, caller) - call s:WatchVariant(a:cmd) - let t = reltime() - let res = system(a:cmd) - call s:Debug(reltimestr(reltime(t)) . 's to exec "' . a:cmd . '" by ' . a:caller) - return res -endfu - -" functions to get information {{{1 -" utilities {{{2 -fu! s:MemberCompare(m1, m2) - return a:m1['n'] == a:m2['n'] ? 0 : a:m1['n'] > a:m2['n'] ? 1 : -1 -endfu - -fu! s:Sort(ci) - let ci = a:ci - if has_key(ci, 'fields') - call sort(ci['fields'], 's:MemberCompare') - endif - if has_key(ci, 'methods') - call sort(ci['methods'], 's:MemberCompare') - endif - return ci -endfu - -" Function to run Reflection {{{2 -fu! s:RunReflection(option, args, log) - let classpath = '' - if !exists('s:isjdk11') - let classpath = ' -classpath "' . s:GetClassPath() . '" ' - endif - - let cmd = javacomplete#GetJVMLauncher() . classpath . ' Reflection ' . a:option . ' "' . a:args . '"' - return s:System(cmd, a:log) -endfu -" class information {{{2 - - -" The standard search order of a FQN is as follows: -" 1. a file-name toplevel type or static member type accessed by the file-name type declared in source files -" 2. other types declared in source files -" 3. an accessible loadable type. -" parameters: -" fqns - list of fqn -" srcpaths - a comma-separated list of directory names. -" a:1 - search all. -" return a dict of fqn -> type info -" precondition: -" NOTE: call expand() to convert path to standard form -fu! s:DoGetTypeInfoForFQN(fqns, srcpath, ...) - if empty(a:fqns) || empty(a:srcpath) - return - endif - - " 1 - let files = {} " fqn -> java file path - for fqn in a:fqns - " toplevel type - let filepath = globpath(a:srcpath, substitute(fqn, '\.', '/', 'g') . '.java') - if filepath != '' - let files[fqn] = expand(filepath) - - " nested type - elseif stridx(fqn, '.') >= 0 - let idents = split(fqn, '\.') - let i = len(idents)-2 - while i >= 0 - let filepath = globpath(a:srcpath, join(idents[:i], '/') . '.java') - if filepath != '' - let files[fqn] = expand(filepath) - break - endif - let i -= 1 - endwhile - endif - endfor - - - " 2 - let dirs = {} " dir.idents -> names of nested type - " dir.qfitems -> items of quick fix - " dir.fqn -> fqn - for fqn in a:fqns - if !has_key(files, fqn) - for path in split(a:srcpath, ',') - let idents = split(fqn, '\.') - let i = len(idents)-2 - while i >= 0 - let dirpath = path . '/' . join(idents[:i], '/') - " it is a package - if isdirectory(dirpath) - let dirs[fnamemodify(dirpath, ':p:h:gs?[\\/]\+?/?')] = {'fqn': fqn, 'idents': idents[i+1:]} - break - endif - let i -= 1 - endwhile - endfor - endif - endfor - - if !empty(dirs) - let items = {} " dir -> items of quick fix - - let filepatterns = '' - for dirpath in keys(dirs) - let filepatterns .= escape(dirpath, ' \') . '/*.java ' - endfor - - let cwd = fnamemodify(expand('%:p:h'), ':p:h:gs?[\\/]\+?/?') - exe 'vimgrep /\s*' . s:RE_TYPE_DECL . '/jg ' . filepatterns - for item in getqflist() - if item.text !~ '^\s*\*\s\+' - let text = matchstr(s:Prune(item.text, -1), '\s*' . s:RE_TYPE_DECL) - if text != '' - let subs = split(substitute(text, '\s*' . s:RE_TYPE_DECL, '\1;\2;\3', ''), ';', 1) - let dirpath = fnamemodify(bufname(item.bufnr), ':p:h:gs?[\\/]\+?/?') - let idents = dirs[dirpath].idents - if index(idents, subs[2]) >= 0 && (subs[0] =~ '\C\<public\>' || dirpath == cwd) " FIXME? - let item.subs = subs - let dirs[dirpath].qfitems = get(dirs[dirpath], 'qfitems', []) + [item] - endif - endif - endif - endfor - - for dirpath in keys(dirs) - " a. names of nested type must be existed in the same file - " PackageName.NonFileNameTypeName.NestedType.NestedNestedType - let qfitems = get(dirs[dirpath], 'qfitems', []) - let nr = 0 - for ident in dirs[dirpath].idents - for item in qfitems - if item.subs[2] == ident - let nr += 1 - endif - endfor - endfor - if nr == len(dirs[dirpath].idents) - " b. TODO: Check whether one enclosed another is correct - let files[fqn] = expand(bufname(qfitems[0].bufnr)) - endif - endfor - endif - - - call s:Info('FQN1&2: ' . string(keys(files))) - for fqn in keys(files) - if !has_key(s:cache, fqn) || get(get(s:files, files[fqn], {}), 'modifiedtime', 0) != getftime(files[fqn]) - let ti = s:GetClassInfoFromSource(fqn[strridx(fqn, '.')+1:], files[fqn]) - if !empty(ti) - let s:cache[fqn] = s:Sort(ti) - endif - endif - if (a:0 == 0 || !a:1) - return - endif - endfor - - - " 3 - let commalist = '' - for fqn in a:fqns - if has_key(s:cache, fqn) && (a:0 == 0 || !a:1) - return - else "if stridx(fqn, '.') >= 0 - let commalist .= fqn . ',' - endif - endfor - if !empty(commalist) - let res = s:RunReflection('-E', commalist, 'DoGetTypeInfoForFQN in Batch') - if res =~ "^{'" - let dict = eval(res) - for key in keys(dict) - if !has_key(s:cache, key) - if type(dict[key]) == type({}) - let s:cache[key] = s:Sort(dict[key]) - elseif type(dict[key]) == type([]) - let s:cache[key] = sort(dict[key]) - endif - endif - endfor - endif - endif -endfu - -" a:1 filepath -" a:2 package name -fu! s:DoGetClassInfo(class, ...) - if has_key(s:cache, a:class) - return s:cache[a:class] - endif - - " array type: TypeName[] or '[I' or '[[Ljava.lang.String;' - if a:class[-1:] == ']' || a:class[0] == '[' - return s:ARRAY_TYPE_INFO - endif - - " either this or super is not qualified - if a:class == 'this' || a:class == 'super' - if &ft == 'jsp' - let ci = s:DoGetReflectionClassInfo('javax.servlet.jsp.HttpJspPage') - if a:class == 'this' - " TODO: search methods defined in <%! [declarations] %> - " search methods defined in other jsp files included - " avoid including self directly or indirectly - endif - return ci - endif - - call s:Info('A0. ' . a:class) - " this can be a local class or anonymous class as well as static type - let t = get(s:SearchTypeAt(javacomplete#parse(), java_parser#MakePos(line('.')-1, col('.')-1)), -1, {}) - if !empty(t) - " What will be returned for super? - " - the protected or public inherited fields and methods. No ctors. - " - the (public static) fields of interfaces. - " - the methods of the Object class. - " What will be returned for this? - " - besides the above, all fields and methods of current class. No ctors. - return s:Sort(s:Tree2ClassInfo(t)) - "return s:Sort(s:AddInheritedClassInfo(a:class == 'this' ? s:Tree2ClassInfo(t) : {}, t, 1)) - endif - - return {} - endif - - - if a:class !~ '^\s*' . s:RE_QUALID . '\s*$' || s:HasKeyword(a:class) - return {} - endif - - - let typename = substitute(a:class, '\s', '', 'g') - let filekey = a:0 > 0 ? a:1 : s:GetCurrentFileKey() - let packagename = a:0 > 1 ? a:2 : s:GetPackageName() - let srcpath = join(s:GetSourceDirs(a:0 > 0 && a:1 != bufnr('%') ? a:1 : expand('%:p'), packagename), ',') - - let names = split(typename, '\.') - " remove the package name if in the same packge - if len(names) > 1 - if packagename == join(names[:-2], '.') - let names = names[-1:] - endif - endif - - " a FQN - if len(names) > 1 - call s:DoGetTypeInfoForFQN([typename], srcpath) - let ci = get(s:cache, typename, {}) - if get(ci, 'tag', '') == 'CLASSDEF' - return s:cache[typename] - elseif get(ci, 'tag', '') == 'PACKAGE' - return {} - endif - endif - - - " The standard search order of a simple type name is as follows: - " 1. The current type including inherited types. - " 2. A nested type of the current type. - " 3. Explicitly named imported types (single type import). - " 4. Other types declared in the same package. Not only current directory. - " 5. Implicitly named imported types (import on demand). - - " 1 & 2. - " NOTE: inherited types are treated as normal - if filekey == s:GetCurrentFileKey() - let simplename = typename[strridx(typename, '.')+1:] - if s:FoundClassDeclaration(simplename) != 0 - call s:Info('A1&2') - let ci = s:GetClassInfoFromSource(simplename, '%') - " do not cache it - if !empty(ci) - return ci - endif - endif - else - let ci = s:GetClassInfoFromSource(typename, filekey) - if !empty(ci) - return ci - endif - endif - - " 3. - " NOTE: PackageName.Ident, TypeName.Ident - let fqn = s:SearchSingleTypeImport(typename, s:GetImports('imports_fqn', filekey)) - if !empty(fqn) - call s:Info('A3') - call s:DoGetTypeInfoForFQN([fqn], srcpath) - let ti = get(s:cache, fqn, {}) - if get(ti, 'tag', '') != 'CLASSDEF' - " TODO: mark the wrong import declaration. - endif - return ti - endif - - " 4 & 5 - " NOTE: Keeps the fqn of the same package first!! - call s:Info('A4&5') - let fqns = [empty(packagename) ? typename : packagename . '.' . typename] - for p in s:GetImports('imports_star', filekey) - call add(fqns, p . typename) - endfor - call s:DoGetTypeInfoForFQN(fqns, srcpath) - for fqn in fqns - if has_key(s:cache, fqn) - return get(s:cache[fqn], 'tag', '') == 'CLASSDEF' ? s:cache[fqn] : {} - endif - endfor - - return {} -endfu - -" Rules of overriding and hiding: -" 1. Fields cannot be overridden; they can only be hidden. -" In the subclass, the hidden field of superclass can no longer be accessed -" directly by its simple name. `super` or another reference must be used. -" 2. A method can be overriden only if it is accessible. -" When overriding methods, both the signature and return type must be the -" same as in the superclass. -" 3. Static members cannot be overridden; they can only be hidden -" -- whether a field or a method. But hiding static members has little effect, -" because static should be accessed via the name of its declaring class. -" Given optional argument, add protected, default (package) access, private members. -"fu! s:MergeClassInfo(ci, another, ...) -" if empty(a:another) | return a:ci | endif -" -" if empty(a:ci) -" let ci = copy(a:another) -"" if a:0 > 0 && a:1 -"" call extend(ci.fields, get(a:another, 'declared_fields', [])) -"" call extend(ci.methods, get(a:another, 'declared_methods', [])) -"" endif -" return ci -" endif -" -" call extend(a:ci.methods, a:another.methods) -" -" for f in a:another.fields -" if s:Index(a:ci.fields, f.n, 'n') < 0 -" call add(a:ci.fields, f) -" endif -" endfor -" return a:ci -"endfu - - -" Parameters: -" class the qualified class name -" Return: TClassInfo or {} when not found -" See ClassInfoFactory.getClassInfo() in insenvim. -function! s:DoGetReflectionClassInfo(fqn) - if !has_key(s:cache, a:fqn) - let res = s:RunReflection('-C', a:fqn, 's:DoGetReflectionClassInfo') - if res =~ '^{' - let s:cache[a:fqn] = s:Sort(eval(res)) - elseif res =~ '^[' - for type in eval(res) - if get(type, 'name', '') != '' - let s:cache[type.name] = s:Sort(type) - endif - endfor - else - let b:errormsg = res - endif - endif - return get(s:cache, a:fqn, {}) -endfunction - -fu! s:GetClassInfoFromSource(class, filename) - let ci = {} - if len(tagfiles()) > 0 - let ci = s:DoGetClassInfoFromTags(a:class) - endif - - if empty(ci) - call s:Info('Use java_parser.vim to generate class information') - let unit = javacomplete#parse(a:filename) - let targetPos = a:filename == '%' ? java_parser#MakePos(line('.')-1, col('.')-1) : -1 - for t in s:SearchTypeAt(unit, targetPos, 1) - if t.name == a:class - let t.filepath = a:filename == '%' ? s:GetCurrentFileKey() : expand(a:filename) - return s:Tree2ClassInfo(t) - "return s:AddInheritedClassInfo(s:Tree2ClassInfo(t), t) - endif - endfor - endif - return ci -endfu - -fu! s:Tree2ClassInfo(t) - let t = a:t - - " fill fields and methods - let t.fields = [] - let t.methods = [] - let t.ctors = [] - let t.classes = [] - for def in t.defs - if def.tag == 'METHODDEF' - call add(def.n == t.name ? t.ctors : t.methods, def) - elseif def.tag == 'VARDEF' - call add(t.fields, def) - elseif def.tag == 'CLASSDEF' - call add(t.classes, t.fqn . '.' . def.name) - endif - endfor - - " convert type name in extends to fqn for class defined in source files - if !has_key(a:t, 'classpath') && has_key(a:t, 'extends') - if has_key(a:t, 'filepath') && a:t.filepath != s:GetCurrentFileKey() - let filepath = a:t.filepath - let packagename = get(s:files[filepath].unit, 'package', '') - else - let filepath = expand('%:p') - let packagename = s:GetPackageName() - endif - - let extends = a:t.extends - let i = 0 - while i < len(extends) - let ci = s:DoGetClassInfo(java_parser#type2Str(extends[i]), filepath, packagename) - if has_key(ci, 'fqn') - let extends[i] = ci.fqn - endif - let i += 1 - endwhile - endif - - return t -endfu - -"fu! s:AddInheritedClassInfo(ci, t, ...) -" let ci = a:ci -" " add inherited fields and methods -" let list = [] -" for i in get(a:t, 'extends', []) -" call add(list, java_parser#type2Str(i)) -" endfor -" -" if has_key(a:t, 'filepath') && a:t.filepath != expand('%:p') -" let filepath = a:t.filepath -" let props = get(s:files, a:t.filepath, {}) -" let packagename = get(props.unit, 'package', '') -" else -" let filepath = expand('%:p') -" let packagename = s:GetPackageName() -" endif -" -" for id in list -" let ci = s:MergeClassInfo(ci, s:DoGetClassInfo(id, filepath, packagename), a:0 > 0 && a:1) -" endfor -" return ci -"endfu - -" To obtain information of the class in current file or current folder, or -" even in current project. -function! s:DoGetClassInfoFromTags(class) - " find tag of a:class declaration - let tags = taglist('^' . a:class) - let filename = '' - let cmd = '' - for tag in tags - if has_key(tag, 'kind') - if tag['kind'] == 'c' - let filename = tag['filename'] - let cmd = tag['cmd'] - break - endif - endif - endfor - - let tags = taglist('^' . (empty(b:incomplete) ? '.*' : b:incomplete) ) - if filename != '' - call filter(tags, "v:val['filename'] == '" . filename . "' && has_key(v:val, 'class') ? v:val['class'] == '" . a:class . "' : 1") - endif - - let ci = {'name': a:class} - " extends and implements - let ci['ctors'] = [] - let ci['fields'] = [] - let ci['methods'] = [] - - " members - for tag in tags - let member = {'n': tag['name']} - - " determine kind - let kind = 'm' - if has_key(tag, 'kind') - let kind = tag['kind'] - endif - - let cmd = tag['cmd'] - if cmd =~ '\<static\>' - let member['m'] = '1000' - else - let member['m'] = '' - endif - - let desc = substitute(cmd, '/^\s*', '', '') - let desc = substitute(desc, '\s*{\?\s*$/$', '', '') - - if kind == 'm' - " description - if cmd =~ '\<static\>' - let desc = substitute(desc, '\s\+static\s\+', ' ', '') - endif - let member['d'] = desc - - let member['p'] = '' - let member['r'] = '' - if tag['name'] == a:class - call add(ci['ctors'], member) - else - call add(ci['methods'], member) - endif - elseif kind == 'f' - let member['t'] = substitute(desc, '\([a-zA-Z0-9_[\]]\)\s\+\<' . tag['name'] . '\>.*$', '\1', '') - call add(ci['fields'], member) - endif - endfor - return ci -endfu - -" package information {{{2 - -fu! s:DoGetInfoByReflection(class, option) - if has_key(s:cache, a:class) - return s:cache[a:class] - endif - - let res = s:RunReflection(a:option, a:class, 's:DoGetInfoByReflection') - if res =~ '^[{\[]' - let v = eval(res) - if type(v) == type([]) - let s:cache[a:class] = sort(v) - elseif type(v) == type({}) - if get(v, 'tag', '') =~# '^\(PACKAGE\|CLASSDEF\)$' - let s:cache[a:class] = v - else - call extend(s:cache, v, 'force') - endif - endif - unlet v - else - let b:errormsg = res - endif - - return get(s:cache, a:class, {}) -endfu - -" search in members {{{2 -" TODO: what about default access? -" public for all -" protected for this or super -" private for this -fu! s:CanAccess(mods, kind) - return (a:mods[-4:-4] || a:kind/10 == 0) - \ && (a:kind == 1 || a:mods[-1:] - \ || (a:mods[-3:-3] && (a:kind == 1 || a:kind == 2)) - \ || (a:mods[-2:-2] && a:kind == 1)) -endfu - -fu! s:SearchMember(ci, name, fullmatch, kind, returnAll, memberkind, ...) - let result = [[], [], []] - - if a:kind != 13 - for m in (a:0 > 0 && a:1 ? [] : get(a:ci, 'fields', [])) + ((a:kind == 1 || a:kind == 2) ? get(a:ci, 'declared_fields', []) : []) - if empty(a:name) || (a:fullmatch ? m.n ==# a:name : m.n =~# '^' . a:name) - if s:CanAccess(m.m, a:kind) - call add(result[2], m) - endif - endif - endfor - - for m in (a:0 > 0 && a:1 ? [] : get(a:ci, 'methods', [])) + ((a:kind == 1 || a:kind == 2) ? get(a:ci, 'declared_methods', []) : []) - if empty(a:name) || (a:fullmatch ? m.n ==# a:name : m.n =~# '^' . a:name) - if s:CanAccess(m.m, a:kind) - call add(result[1], m) - endif - endif - endfor - endif - - if a:kind/10 != 0 - let types = get(a:ci, 'classes', []) - for t in types - if empty(a:name) || (a:fullmatch ? t[strridx(t, '.')+1:] ==# a:name : t[strridx(t, '.')+1:] =~# '^' . a:name) - if !has_key(s:cache, t) || !has_key(s:cache[t], 'flags') || a:kind == 1 || s:cache[t].flags[-1:] - call add(result[0], t) - endif - endif - endfor - endif - - " key `classpath` indicates it is a loaded class from classpath - " All public members of a loaded class are stored in current ci - if !has_key(a:ci, 'classpath') || (a:kind == 1 || a:kind == 2) - for i in get(a:ci, 'extends', []) - let ci = s:DoGetClassInfo(java_parser#type2Str(i)) - let members = s:SearchMember(ci, a:name, a:fullmatch, a:kind == 1 ? 2 : a:kind, a:returnAll, a:memberkind) - let result[0] += members[0] - let result[1] += members[1] - let result[2] += members[2] - endfor - endif - return result -endfu - - -" generate member list {{{2 - -fu! s:DoGetFieldList(fields) - let s = '' - for field in a:fields - let s .= "{'kind':'" . (s:IsStatic(field.m) ? "F" : "f") . "','word':'" . field.n . "','menu':'" . field.t . "','dup':1}," - endfor - return s -endfu - -fu! s:DoGetMethodList(methods, ...) - let paren = a:0 == 0 || !a:1 ? '(' : '' - let s = '' - for method in a:methods - let s .= "{'kind':'" . (s:IsStatic(method.m) ? "M" : "m") . "','word':'" . method.n . paren . "','abbr':'" . method.n . "()','menu':'" . method.d . "','dup':'1'}," - endfor - return s -endfu - -" kind: -" 0 - for instance, 1 - this, 2 - super, 3 - class, 4 - array, 5 - method result, 6 - primitive type -" 11 - for type, with `class` and static member and nested types. -" 12 - for import static, no lparen for static methods -" 13 - for import or extends or implements, only nested types -" 20 - for package -fu! s:DoGetMemberList(ci, kind) - if type(a:ci) != type({}) || a:ci == {} - return [] - endif - - let s = a:kind == 11 ? "{'kind': 'C', 'word': 'class', 'menu': 'Class'}," : '' - - let members = s:SearchMember(a:ci, '', 1, a:kind, 1, 0, a:kind == 2) - - " add accessible member types - if a:kind / 10 != 0 - " Use dup here for member type can share name with field. - for class in members[0] - "for class in get(a:ci, 'classes', []) - let v = get(s:cache, class, {}) - if v == {} || v.flags[-1:] - let s .= "{'kind': 'C', 'word': '" . substitute(class, a:ci.name . '\.', '\1', '') . "','dup':1}," - endif - endfor - endif - - if a:kind != 13 - let fieldlist = [] - let sfieldlist = [] - for field in members[2] - "for field in get(a:ci, 'fields', []) - if s:IsStatic(field['m']) - call add(sfieldlist, field) - elseif a:kind / 10 == 0 - call add(fieldlist, field) - endif - endfor - - let methodlist = [] - let smethodlist = [] - for method in members[1] - if s:IsStatic(method['m']) - call add(smethodlist, method) - elseif a:kind / 10 == 0 - call add(methodlist, method) - endif - endfor - - if a:kind / 10 == 0 - let s .= s:DoGetFieldList(fieldlist) - let s .= s:DoGetMethodList(methodlist) - endif - let s .= s:DoGetFieldList(sfieldlist) - let s .= s:DoGetMethodList(smethodlist, a:kind == 12) - - let s = substitute(s, '\<' . a:ci.name . '\.', '', 'g') - let s = substitute(s, '\<java\.lang\.', '', 'g') - let s = substitute(s, '\<\(public\|static\|synchronized\|transient\|volatile\|final\|strictfp\|serializable\|native\)\s\+', '', 'g') - endif - return eval('[' . s . ']') -endfu - -" interface {{{2 - -function! s:GetMemberList(class) - if s:IsBuiltinType(a:class) - return [] - endif - - return s:DoGetMemberList(s:DoGetClassInfo(a:class), 0) -endfunction - -fu! s:GetStaticMemberList(class) - return s:DoGetMemberList(s:DoGetClassInfo(a:class), 11) -endfu - -function! s:GetConstructorList(class) - let ci = s:DoGetClassInfo(a:class) - if empty(ci) - return [] - endif - - let s = '' - for ctor in get(ci, 'ctors', []) - let s .= "{'kind': '+', 'word':'". a:class . "(','abbr':'" . ctor.d . "','dup':1}," - endfor - - let s = substitute(s, '\<java\.lang\.', '', 'g') - let s = substitute(s, '\<public\s\+', '', 'g') - return eval('[' . s . ']') -endfunction - -" Name can be a (simple or qualified) package name, or a (simple or qualified) -" type name. -fu! s:GetMembers(fqn, ...) - let list = [] - let isClass = 0 - - let v = s:DoGetInfoByReflection(a:fqn, '-E') - if type(v) == type([]) - let list = v - elseif type(v) == type({}) && v != {} - if get(v, 'tag', '') == 'PACKAGE' - if b:context_type == s:CONTEXT_IMPORT_STATIC || b:context_type == s:CONTEXT_IMPORT - call add(list, {'kind': 'P', 'word': '*;'}) - endif - if b:context_type != s:CONTEXT_PACKAGE_DECL - for c in sort(get(v, 'classes', [])) - call add(list, {'kind': 'C', 'word': c}) - endfor - endif - for p in sort(get(v, 'subpackages', [])) - call add(list, {'kind': 'P', 'word': p}) - endfor - else " elseif get(v, 'tag', '') == 'CLASSDEF' - let isClass = 1 - let list += s:DoGetMemberList(v, b:context_type == s:CONTEXT_IMPORT || b:context_type == s:CONTEXT_NEED_TYPE ? 13 : b:context_type == s:CONTEXT_IMPORT_STATIC ? 12 : 11) - endif - endif - - if !isClass - let list += s:DoGetPackageInfoInDirs(a:fqn, b:context_type == s:CONTEXT_PACKAGE_DECL) - endif - - return list -endfu - -" a:1 incomplete mode -" return packages in classes directories or source pathes -fu! s:DoGetPackageInfoInDirs(package, onlyPackages, ...) - let list = [] - - let pathes = s:GetSourceDirs(expand('%:p')) - for path in s:GetClassDirs() - if index(pathes, path) <= 0 - call add(pathes, path) - endif - endfor - - let globpattern = a:0 > 0 ? a:package . '*' : substitute(a:package, '\.', '/', 'g') . '/*' - let matchpattern = a:0 > 0 ? a:package : a:package . '[\\/]' - for f in split(globpath(join(pathes, ','), globpattern), "\n") - for path in pathes - let idx = matchend(f, escape(path, ' \') . '[\\/]\?\C' . matchpattern) - if idx != -1 - let name = (a:0 > 0 ? a:package : '') . strpart(f, idx) - if f[-5:] == '.java' - if !a:onlyPackages - call add(list, {'kind': 'C', 'word': name[:-6]}) - endif - elseif name =~ '^' . s:RE_IDENTIFIER . '$' && isdirectory(f) && f !~# 'CVS$' - call add(list, {'kind': 'P', 'word': name}) - endif - endif - endfor - endfor - return list -endfu -" }}} -"}}} -" vim:set fdm=marker sw=2 nowrap: diff --git a/files/.vim/bundle/vim-yaml b/files/.vim/bundle/vim-yaml new file mode 160000 +Subproject 4b37a4fa8a91c44b517e3fb6de3ebba5e02ec9f diff --git a/files/.vim/bundle/xml.vim b/files/.vim/bundle/xml.vim new file mode 160000 +Subproject b878689de5f2ccf2b9c2593165dc810d53cbe4e diff --git a/files/.vim/doc/javacomplete.txt b/files/.vim/doc/javacomplete.txt deleted file mode 100644 index ae39ffb..0000000 --- a/files/.vim/doc/javacomplete.txt +++ /dev/null @@ -1,558 +0,0 @@ -*javacomplete.txt* For Vim version 7.0 and above. Last change: 2007 Sep 26 - - JAVACOMPLETE REFERENCE MANUAL by cheng fang~ - fangread@yahoo.com.cn~ - - -1. Overview |javacomplete-overview| - 1.1 Features |javacomplete-features| - 1.2 Requirements |javacomplete-requirements| - 1.3 Download |javacomplete-download| - 1.4 Install |javacomplete-install| -2. Usage |javacomplete-usage| - 2.1 Input contexts |javacomplete-contexts| - 2.2 Kind letter |javacomplete-kindletter| - 2.3 Options |javacomplete-options| - 2.4 Commands |javacomplete-commands| -3. Java parser in Vim |javacomplete-parser| - 3.1 Abstract Syntax Tree |javacomplete-ast| - 3.2 Global Constants |javacomplete-constants| - 3.3 Parsing Functions |javacomplete-functions| - 3.4 Sample |javacomplete-sample| -4. FAQ |javacomplete-faq| -5. Limitations |javacomplete-limitations| -6. History - 6.1 javacomplete |javacomplete-history| - 6.2 Parser |java-parser-history| - 6.2 Reflection.java |javacomplete-reflection| -7. Todo |javacomplete-todo| -8. Thanks |javacomplete-thanks| - -============================================================================== -1. Overview *javacomplete-overview* - -This is javacomplete, an omni-completion script of JAVA language for vim 7 and -above. It includes javacomplete.vim, java_parser.vim, Reflection.java, and -javacomplete.txt. - -1.1 Features *javacomplete-features* - -- List members of a class, including (static) fields, (static) methods and ctors. -- List classes or subpackages of a package. -- Provide parameters information of a method, list all overload methods. -- Complete an incomplete word. -- Provide a complete JAVA parser written in Vim script language. -- Use the JVM to obtain most information. -- Use the embedded parser to obtain the class information from source files. -- Tags generated by ctags can also be used. -- JSP is supported, Builtin objects such as request, session can be recognized. - The classes and jar files in the WEB-INF will be appended automatically to the classpath. - -1.2 Requirements *javacomplete-requirements* - -It works on all the platforms wherever -- Vim version 7.0 and above, -- JDK version 1.1 and above, -existed. - -1.3 Download *javacomplete-download* - -You can download the lastest version from this url: - http://www.vim.org/scripts/script.php?script_id=1785 - -1.4 Install *javacomplete-install* - -1. Unzip javacomplete.zip to a directory of 'runtimepath', e.g. -$HOME/.vim (unix/linux), $VIM/vimfiles (windows). > - > unzip javacomplete.zip -d ~/.vim - -< To update Vim help tags, run vim and run command: > - :helptags $HOME/.vim/doc -< or > - :helptags $VIM/vimfiles/doc - -NOTE: javacomplete.vim, java_parser.vim and Reflection.java should be in one -autoload directory of 'runtimepath'. -javacomplete.txt should be in one doc directory of 'runtimepath'. - -2. Set 'omnifunc' option. e.g. > - :setlocal omnifunc=javacomplete#Complete -< Or, use autocmd: > - :" Only do this part when compiled with support for autocommands. - :if has("autocmd") - : autocmd Filetype java setlocal omnifunc=javacomplete#Complete - :endif -You can add this command to your .vimrc or _vimrc. - -3. Set 'completefunc' option to show parameters information IF YOU LIKE. e.g. > - :setlocal completefunc=javacomplete#CompleteParamsInfo -You can map as follows for better display: > - :inoremap <buffer> <C-X><C-U> <C-X><C-U><C-P> - :inoremap <buffer> <C-S-Space> <C-X><C-U><C-P> - -4. Reflection.java will be automatcally compiled and placed to $HOME when you -use first time. Assure that Reflection.java is in the same directory with -javacomplete.vim to be searched in autoload subdirectory of &rtp. -If no Reflection.class is generated, check that you have the write permission -in $HOME directory. -If a previous Reflection.java is not compatible with the new version -javacomplete.vim, please compile Reflection.java manually. - -============================================================================== -2. Usage *javacomplete-usage* - -You can use it like other omni-completion script. Many samples of input context -are gived in the following section. - -Make sure a JVM launcher (default 'java') can be searched in the PATH enviroment -variable, otherwise Use javacomplete#SetJVMLauncher() to specify one. See option -`javacomplete-launcher`. - -See FAQ in time if some problem occurs. When meeting other problems not -described in FAQ, you can contact with the auther by the following e-mail: -fangread@yahoo.com.cn - -2.1 Input contexts |javacomplete-contexts| -It recognize nearly all kinds of Primary Expressions (see langspec-3.0) -except for "Primary.new Indentifier". Casting conversion is also supported. - -Samples of input contexts are as following: (Note that '|' indicates cursor) - (1). after '.', list members of a class or a package - - package.| subpackages and classes of a package - - Type.| static members of the 'Type' class and "class" - - var.| or field.| members of a variable or a field - - method().| members of result of method() - - this.| members of the current class - - ClassName.this.| members of the qualified class - - super.| members of the super class - - array.| members of an array object - - array[i].| array access, return members of the element of array - - "String".| String literal, return members of java.lang.String - - int.| or void.| primitive type or pseudo-type, return "class" - - int[].| array type, return members of a array type and "class" - - java.lang.String[].| - - new int[].| members of the new array instance - - new java.lang.String[i=1][].| - - new Type().| members of the new class instance - - Type.class.| class literal, return members of java.lang.Class - - void.class.| or int.class.| - - ((Type)var).| cast var as Type, return members of Type. - - (var.method()).| same with "var.|" - - (new Class()).| same with "new Class().|" - - (2). after '(', list matching methods with parameters information. - - method(|) methods matched - - var.method(|) methods matched - - new ClassName(|) constructors matched - - this(|) constructors of current class matched - - super(|) constructors of super class matched - Any place between '(' and ')' will be supported soon. - Help information of javadoc is not supported yet. - - (3). after an incomplete word, list all the matched beginning with it. - - var.ab| subset of members of var beginning with `ab` - - ab| list of all maybes - - (4). import statement - - " import java.util.|" - - " import java.ut|" - - " import ja|" - - " import java.lang.Character.|" e.g. "Subset" - - " import static java.lang.Math.|" e.g. "PI, abs" - - (5). package declaration - - " package com.|" - - The above are in simple expression. - (6). after compound expression: - - PrimaryExpr.var.| - - PrimaryExpr.method().| - - PrimaryExpr.method(|) - - PrimaryExpr.var.ab| - e.g. - - "java.lang . System.in .|" - - "java.lang.System.getenv().|" - - "int.class.toString().|" - - "list.toArray().|" - - "new ZipFile(path).|" - - "new ZipFile(path).entries().|" - - (7). Nested expression: - - "System.out.println( str.| )" - - "System.out.println(str.charAt(| )" - - "for (int i = 0; i < str.|; i++)" - - "for ( Object o : a.getCollect| )" - - -2.2 Kind letter *javacomplete-kindletter* - -A single letter indicates the kind of compeltion item. These kinds are: - + ctor - v local variable or parameter - f nonstatic field - F static field - m nonstatic method - M static method - P package - C class type - I interface type - -2.3 Options *javacomplete-options* - -1. Set java compiler (default 'javac') using the following function: - javacomplete#SetCompiler('javac') *javacomplete-compiler* - -2. Set java launcher (default 'java') using the following function: - javacomplete#SetJVMLauncher('java') *javacomplete-launcher* - -3. Set classpath using the following function: > - javacomplete#AddClassPath('jarfile_or_classes_path') - javacomplete#DelClassPath('jarfile_or_classes_path') - javacomplete#SetClassPath('semicolon_separated_string') -< - Another two variables will be used if they are existing: - |g:java_classpath| global classpath - |b:classpath| associated with current buffer - In one sense, s:classpath is like a classpath option for a PROJECT. - If some of them are body set, the priority of these variables is: - first, b:classpath first, - second, s:classpath - third, g:java_classpath - last, $CLASSPATH - -4. Set sourcepath using the following function: > - javacomplete#AddSourcePath('sources_file_path') - javacomplete#DelSourcePath('sources_file_path') - javacomplete#SetSourcePath('sources_file_path') - -5. Set option for using JDK1.1 if you meet the problem described in FAQ 3: > - javacomplete#UseJDK11() - -6. Set methods to search declaration: > - " 1 - by builtin searchdecl(), quickest but inaccurate in many cases. - " 2 - by special Searchdecl(), work NOT WELL YET. - " 4 - by java_parser, slowest but accurate in most cases. Not for JSP. - javacomplete#SetSearchdeclMethod() - -2.4 Commands *javacomplete-commands* - -============================================================================== -3. Java parser in Vim *javacomplete-parser* - -3.1 Abstract Syntax Tree *javacomplete-ast* - -3.2 Global Constants *javacomplete-constants* - -3.3 Parsing Functions *javacomplete-functions* - -3.4 Sample Codes *javacomplete-sample* -This parser can be a good candidate for anyone who needs a java parser to get -a abstract syntax tree for many use. The following are sample codes: > - - " NOTE: The script contains a single parser instance. You cannot create - " another parser! The only way to parse another JAVA code is reset the - " parser by calling java_parser#InitParser(). - - " 1. Initialize the parser - " for a code snippet, - call java_parser#InitParser(['for (int i = 0; i < N; i++) {', '', '}']) - " or for the current buffer, - call java_parser#InitParser(getline('^', '$')) - " or for a whole source file - call java_parser#InitParser(readfile('java/util/Arrays.java')) - - " 2. Get the result tree - call java_parser#compilationUnit() - " or others according to the input code - call java_parser#expression() - call java_parser#block() - call java_parser#statement() - - " 3. Use the tree as you like - - " 4. The default scan strategy is scanning only sklenton. - " You can change it by set the option 'scanStrategy'. - " The values for 'scanStrategy' option are: - " 0 - only class members when parse full file; - " 1 - keep statement as a whole string; - " 2 - all - call java_parser#InitParser(getline('^', '$'), {'scanStrategy': 2}) - - " 5. I recommend that keeping scanStrategy as default. - " If you want to parse a code snippet such as a method body of the whole - " file, you can call java_parser#GotoPosition() to go to what you are going - " to start parsing. - " Then, call java_parser#block(), java_parser#statement() or - " java_parser#expression() to parse the smaller snippet. - " NOTE: This way will keep the result tree reserved. - call java_parser#GotoPosition(def.body.pos) - call java_parser#block() - -============================================================================== -4. FAQ *javacomplete-faq* - -(1). When you meets the following problem: > - omni-completion error: Exception in thread "main" - java.lang.NoClassDefFoundError: Reflection -It is Reflection.class not found in autoload directory or $HOME that cause -this problem. -There are several reasons causing this problem: - o No compiler. Use javacomplete#SetCompiler() to specify one. - o No write permission for $HOME directory. - -(2). Reflection.java should be searched in autoload subdirectory of &rtp. -Reflection.class should be searched in $HOME or autoload subdirectory of &rtp. -If not found, javacomplete try to compile it and place the generated class -file in $HOME. - -(3). A error when using JDK1.1: - Unable to initialize threads: cannot find class java/lang/Thread -When I tested JDK1.1.8 on Windows XP, I found -classpath options cause it. -There are two way to avoid it is: - o Add the runtime classes to classpath, like - "${JDK118}\classes;${JDK118}\lib\classes.zip;${JDK118}\lib\classes.jar;" - o Add Reflection.class and others to the CLASSPATH enviroment variable. - And call javacomplete#UseJDK11() to set option. - -============================================================================== -5. Limitations *javacomplete-limitations* - -The embedded parser works a bit slower than expected. - -============================================================================== -6. History - -6.1 javacomplete *javacomplete-history* - -v0.77.1 - 2007-09-19 Supported showing method parameters information in any place - between parenthesises. - -v0.77 - 2007-09-19 bug fix - 2007-09-18 Added GetCurrentFileKey() avoid empty key of s:files for current buffer. - 2007-09-16 Use a new strategy for searching inherited members. - 2007-09-11 - - Supported new contexts "jav|", "var|", just after an incomplete word. - - Supported new context "abs(|)", a imported static method. - 2007-09-10 - - Improved FoundClassDeclaration() - - Fixed bug calling cursor(0, 0) - 2007-09-09 Rewrote DoGetClassInfo(), GetFQN() and IsFQN() - 2007-09-08 Fixed a bug when merging superclass's members - 2007-09-05 -- 07 - - Improved s:MergeLines() and s:ExtractCleanExpr(). - - Rewrote CompleteAfterDot(). Added ParseExpr(). Removed s:GetNextSubexprType() - - Supported accessible static imported members. - - Supported accessible inherited members. - - 2007-09-04 Used b:changedtick and getftime() to check buffer (or other file) for changing. - 2007-09-01 Supported not-file-name toplevel or static member class in source files. - -v0.76.8 - 2007-08-30 - - Created the s:TreeVisitor to search type or symbol names. - - Supported local and anonymous class. - - 2007-08-29 - - Supported appending automatically classpath under WEB-INF for jsp files. - -v0.76.7 - 2007-08-28 - - Fixed case of "new java.util.zip.ZipFile().|" - - Improved process of type arguments and method parameters. JAVA5+ - - Reorganize codes in javacomplete#Complete() - - Added CONTEXT_NEED_TYPE, removed CONTEXT_INCOMPLETE_WORD - - 2007-08-24 Add Context types for type declaration: CONTEXT_NEED_TYPE - -v0.76.6 - 2007-08-23 Improved GetStatement() and related. Bug fixed. - -v0.76.5 - 2007-08-21 - - Fixed bug: "foo().|", "getFoo().foo().|", - "for (Enumeration entries = ; entries.|; )". - - Supported input contexts: "((Object)o).|", "((Object)o).getClass().|", - "new ZipFile(path).|", "(new String().)|". - -v0.76.4 - 2007-08-17 - - Improved input contexts: "int.class.toString().|", "list.toArray().|". - - Fixed recognizing "this(|)", "method1(|)" - - Added the 'kind' letter to distinguish between classes and packages. - 2007-08-14 - - Support accessible nested classes. - - Support import static members and import accessible nested classes. - 2007-08-11 - - Fixed a bug when Reflection.java is in the path which contains space. - - Improved process of this and super in JSP. - - Fixed an severe bug parsing current jsp file. - -v0.76.3 - 2007-08-10 - - Add an option 'searchdecl' set by javacomplete#SetSearchdeclMethod(). - - Make an improvement for jsp file. - - Clear cache when set options affecting classpath. - - Improved DoGetPackageList() and s:GenerateImports(). - - Replace codes searching list of string with index(). - -v0.76.2 - 2007-08-08 - - Fix failing to list members of nested class. - - Combine members of local packages and loadable packages. - - Add quick recognition of package or import. - 2007-08-06 Add inherited fields and methods to local class. - -v0.76.1 - 2007-08-04 - - Fix using a: in javacomplete#SetClassPath() - - Fix a bug in javacomplete#GetClassPath() - -v0.76 2007-08-04 - 2007-08-04 - - Fix a infinite loop bug in s:GetMatchedIndexEx() - - Fix that array type not recognised in compound expression. - - Add a option for JDK1.1. See FAQ 3. - 2007-08-03 - - Improve for 'this' or 'super'. - - Support searching toplevel class in sourcepath. - - Clean - 2007-08-02 - - Improve the process of checking a class in one of packages. - 2007-08-01 - - Add Searchdecl() using java_parser.vim to provide quick information. - - Supports input context: "StringLiteral".|, "int.|", "void.|" - 2007-07-28 - - Automatcally compile Reflection.java and place it to $HOME. - - Add option 'javacompiler', default 'javac' - - Add option 'java', default 'java' - -v0.75 2007-02-13 - - Add java_parser.vim. - - Add b:sourcepath option. - - Improve recognition of classes defined in current buffer or in source path. - - Support generating class information from tags instead of returning list directly. - -v0.74 2007-02-03 - - Support jre1.2 (and above). - - Support input context like "boolean.class.|" - - Handle java primitive types like 'int'. - -v0.73 2007-02-01 - - Fix bug that CLASSPATH not used when b:classpath or g:java_classpath not set. - - Fix bug that call filter() without making a copy for incomplete. - - Improve recognition of declaration of this class - -v0.72 2007-01-31 Handle nested expression. -v0.71 2007-01-28 Add Basic support for class in current folder. -v0.70 2007-01-27 Complete the reflection part. -v0.60 2007-01-25 Design TClassInfo, etc. -v0.50 2007-01-21 Use java and Reflection.class directly. - - -6.2 Parser *java-parser-history* - -v0.67 - 2007-09-11 Append a error string to imported qid when error occurs. - 2007-09-10 Improved regexp constants. - 2007-09-07 Fixed type2Str(). Removed qualident2Str(). - -v0.66.1 08-30 Changed classCreatorRest(). -v0.66 08-27 Minor changes - -v0.65 - 2007-08-23 - - Improved s:scanComment(), s:Strpart(), s:String2Flags(). - - Improved recognizing methods, ctors, and variable declarators declared in most common form. - - Added s:optFinalParameter(), s:methodDeclaratorRest_opt(). - - Removed s:GetLine() and s:GetCol(). - - Rewrote binary functions. - -v0.64 - 2007-08-21 - - Added quick recognizing fields or methods declared in most common form. - - Optimized code: s:modeAndEXPR(), formalParameter(), and others. - -v0.63 - 2007-08-10 - - Removed the unclear s:tokens and s:modifier_keywords. - - Add java_parser#GetSnapshot() and java_parser#Restore(). - 2007-08-09 Fixed a bug when no top level class defined - -v0.62 2007-08-08 - 2007-08-08 Fix values in s:Flags and s:modifiersOpt() and the related. - 2007-08-07 Optimize code of scanDoubleQuote() and importDeclaration(). - -v0.61 2007-08-04 - 2007-08-01 Fix a bug typetag(). return a:token -> return tolower(a:token) - 2007-07-31 - - Rename all script functions matching "s:Java_\(\i\+\)" to "s:\1". - - Change s:EOI = '' - - Use get() instead of s:GetOption(). Remove it. - - Use repeat() instead of s:PrependChar(). Remove it. - - Improve scanChar() - -v0.60 2007-07-31 Now it nearly is a complete parser and support Java5,6. - And tested correctly on all java files in jdk6 src.zip. - 2007-07-19 Support new language features in java 5 and above. - 2007-07-25 Add supports for parsing statement, block or expression - 2007-07-28 Place it to autoload directory. - 2007-07-30 Clean this script. - -v0.51 2007-02-13 Optimize several scan function. -v0.50 2007-02-10 Complete the skeleton. - - -6.3 Reflection.java *javacomplete-reflection* - -v0.77 - 2007-09-14 Improved generating information of all packages in jar files. - 2007-09-06 - - Improved getting paths of all system jar files for different JDKs - in different platforms. - 2007-08-14 Major improvement. Support nontoplevel classes. - -v0.76.3 - 2007-08-09 Redefined '-P' option for returning all packages and subpackages info in one time. - -v0.76.2 - 2007-08-06 Return a modifier value as a string because it more than 32bit. - -v0.76 - 2007-08-04 Support checking and reading package members for '-E'. - 2007-08-02 - - Add an option '-E'. - - Use ZipFile and ZipEntry instead of JarFile and JarEntry, - so that it can be compiled by and run on JDK1.1 and above. -v0.7 2007-02-17 - -============================================================================== -7. Todo *javacomplete-todo* - -- Improve performance of the embedded parser. Incremental parser. -- Add quick information using balloonexpr, ballooneval, balloondelay. -- Add javadoc -- Give a hint for class name conflict in different packages. -- Support parameter information for template - -============================================================================== -8. Thanks *javacomplete-thanks* - * Bram Moolenaar and all Vim contributors for Vim - * The insenvim project - * The javac and gjc sources - * All of you for using this script :) - - * For help, documentation, bug report : - Martin Stubenschrott author of IComplete - Vissale NEANG author of OmniCppComplete - David Fishburn author of SQLComplete and others - Nico Weber testing on the Mac - Thomas Link testing on cygwin+bash - Zhixing Yu - -FeedBack: -Any problem, bug or suggest are welcome to send to fangread@yahoo.com.cn - -============================================================================== - vim:tw=78:ts=8:ft=help:norl: diff --git a/files/.vim/doc/lua51refvim.txt b/files/.vim/doc/lua51refvim.txt deleted file mode 100644 index e80d613..0000000 --- a/files/.vim/doc/lua51refvim.txt +++ /dev/null @@ -1,5617 +0,0 @@ -*luarefvim.txt* Lua 5.1 Reference Manual for Vim - Vim version 7.0 - - - *luaref* *Lua-Reference* - Lua Reference for Vim - ========================= - Version 0.2.0 - November, 25th, 2006 - - (c) 2006 by Luis Carvalho - <lexcarvalho at gmail dot com> - - Adapted from "Lua: 5.1 reference manual" - R. Ierusalimschy, L. H. de Figueiredo, W. Celes - Copyright (c) 2006 Lua.org, PUC-Rio. - - - See |lrv-doc| for information on this manual. - See |lrv-copyright| for copyright and licenses. - - - CONTENTS - ============ - - 1 INTRODUCTION........................|lrv-intro| - - 2 THE LANGUAGE........................|lrv-language| - 2.1 Lexical Conventions...............|lrv-langLexConv| - 2.2 Values and Types..................|lrv-langValTypes| - 2.2.1 Coercion........................|lrv-langCoercion| - 2.3 Variables.........................|lrv-langVariables| - 2.4 Statements........................|lrv-langStats| - 2.4.1 Chunks..........................|lrv-langChunks| - 2.4.2 Blocks..........................|lrv-langBlocks| - 2.4.3 Assignment......................|lrv-langAssign| - 2.4.4 Control Structures..............|lrv-langContStructs| - 2.4.5 For Statement...................|lrv-langForStat| - 2.4.6 Function Calls as Statements....|lrv-langFuncStat| - 2.4.7 Local Declarations..............|lrv-langLocalDec| - 2.5 Expressions.......................|lrv-langExpressions| - 2.5.1 Arithmetic Operators............|lrv-langArithOp| - 2.5.2 Relational Operators............|lrv-langRelOp| - 2.5.3 Logical Operators...............|lrv-langLogOp| - 2.5.4 Concatenation...................|lrv-langConcat| - 2.5.5 The Length Operator.............|lrv-langLength| - 2.5.6 Precedence......................|lrv-langPrec| - 2.5.7 Table Constructors..............|lrv-langTableConst| - 2.5.8 Function Calls..................|lrv-langFuncCalls| - 2.5.9 Function Definitions............|lrv-langFuncDefs| - 2.6 Visibility Rules..................|lrv-langVisibRules| - 2.7 Error Handling....................|lrv-langError| - 2.8 Metatables........................|lrv-langMetatables| - 2.9 Environments......................|lrv-langEnvironments| - 2.10 Garbage Collection...............|lrv-langGC| - 2.10.1 Garbage-Collection Metamethods.|lrv-langGCMeta| - 2.10.2 Weak Tables....................|lrv-langWeaktables| - 2.11 Coroutines.......................|lrv-langCoro| - - 3 THE APPLICATION PROGRAM INTERFACE...|lrv-api| - 3.1 The Stack.........................|lrv-apiStack| - 3.2 Stack Size........................|lrv-apiStackSize| - 3.3 Pseudo-Indices....................|lrv-apiPseudoIndices| - 3.4 C Closures........................|lrv-apiCClosures| - 3.5 Registry..........................|lrv-apiRegistry| - 3.6 Error Handling in C...............|lrv-apiError| - 3.7 Functions and Types...............|lrv-apiFunctions| - 3.8 The Debug Interface...............|lrv-apiDebug| - - 4 THE AUXILIARY LIBRARY...............|lrv-aux| - 4.1 Functions and Types...............|lrv-auxFunctions| - - 5 STANDARD LIBRARIES..................|lrv-lib| - 5.1 Basic Functions...................|lrv-libBasic| - 5.2 Coroutine Manipulation............|lrv-libCoro| - 5.3 Modules...........................|lrv-libModule| - 5.4 String Manipulation...............|lrv-libString| - 5.4.1 Patterns........................|lrv-libStringPat| - 5.5 Table Manipulation................|lrv-libTable| - 5.6 Mathematical Functions............|lrv-libMath| - 5.7 Input and Output Facilities.......|lrv-libIO| - 5.8 Operating System Facilities.......|lrv-libOS| - 5.9 The Debug Library.................|lrv-libDebug| - - 6 LUA STAND-ALONE.....................|lrv-LuaSA| - - A INDEX...............................|lrv-index| - B BIBLIOGRAPHY........................|lrv-bibliography| - C COPYRIGHT & LICENSES................|lrv-copyright| - D LUAREFVIM DOC.......................|lrv-doc| - D.1 Installation.......................|lrv-docInstall| - D.2 Usage..............................|lrv-docUsage| - - -============================================================================== -1 INTRODUCTION *lrv-intro* -============================================================================== - -Lua is an extension programming language designed to support general -procedural programming with data description facilities. It also offers good -support for object-oriented programming, functional programming, and -data-driven programming. Lua is intended to be used as a powerful, -light-weight scripting language for any program that needs one. Lua is -implemented as a library, written in@clean@C (that is, in the common subset -of ANSI C and C++). - -Being an extension language, Lua has no notion of a "main" program: it only -works@embedded@in a host client, called the@embedding program@or simply -the@host@. This host program can invoke functions to execute a piece of Lua -code, can write and read Lua variables, and can register C functions to be -called by Lua code. Through the use of C functions, Lua can be augmented to -cope with a wide range of different domains, thus creating customized -programming languages sharing a syntactical framework. - -The Lua distribution includes a sample host program called$lua$, which uses -the Lua library to offer a complete, stand-alone Lua interpreter. - -Lua is free software, and is provided as usual with no guarantees, as stated -in its license. The implementation described in this manual is available at -Lua's official web site,$www.lua.org$. - -Like any other reference manual, this document is dry in places. For a -discussion of the decisions behind the design of Lua, see references at -|lrv-bibliography|. For a detailed introduction to programming in Lua, see -Roberto's book,@Programming in Lua@. - -Lua means "moon" in Portuguese and is pronounced LOO-ah. - - -============================================================================== -2 THE LANGUAGE *lrv-language* -============================================================================== - -This section describes the lexis, the syntax, and the semantics of Lua. In -other words, this section describes which tokens are valid, how they can be -combined, and what their combinations mean. - -The language constructs will be explained using the usual extended BNF -notation, in which {@a@} means 0 or more@a@'s, and [@a@] means an optional@a@. -Non-terminals are shown in@italics@, keywords are shown in#bold#, and other -terminal symbols are shown in$typewriter$color, enclosed in single quotes. - - -============================================================================== -2.1 Lexical Conventions *lrv-langLexConv* - - - *lrv-names* *lrv-identifiers* -@Names@(also called@identifiers@) in Lua can be any string of letters, digits, -and underscores, not beginning with a digit. This coincides with the -definition of identifiers in most languages. (The definition of letter depends -on the current locale: any character considered alphabetic by the current -locale can be used in an identifier.) Identifiers are used to name variables -and table fields. - -The following@keywords@are reserved and cannot be used as names: -> - and break do else elseif - end false for function if - in local nil not or - repeat return then true until while -< -Lua is a case-sensitive language:$and$is a reserved word, but$And$and$AND$are -two different, valid names. As a convention, names starting with an underscore -followed by uppercase letters (such as$_VERSION$) are reserved for internal -global variables used by Lua. - -The following strings denote other tokens: -> - + - * / % ^ # - == ~= <= >= < > = - ( ) { } [ ] - ; : , . .. ... -> - *lrv-literal* -@Literal strings@can be delimited by matching single or double quotes, and can -contain the following C-like escape sequences: - - #o#$\a$: bell - #o#$\b$: backspace - #o#$\f$: form feed - #o#$\n$: newline - #o#$\r$: carriage return - #o#$\t$: horizontal tab - #o#$\v$: vertical tab - #o#$\\$: backslash - #o#$\"$: quotation mark (double quote) - #o#$\'$: apostrophe (single quote) - -Moreover, a backslash followed by a real newline results in a newline in the -string. A character in a string may also be specified by its numerical value -using the escape sequence$`\ddd'$, where@ddd@is a sequence of up to three -decimal digits. (Note that if a numerical escape is to be followed by a digit, -it must be expressed using exactly three digits.) Strings in Lua may contain -any 8-bit value, including embedded zeros, which can be specified as$`\0'$. - -To put a double (single) quote, a newline, a backslash, or an embedded zero -inside a literal string enclosed by double (single) quotes you must use an -escape sequence. Any other character may be directly inserted into the -literal. (Some control characters may cause problems for the file system, but -Lua has no problem with them.) - -Literal strings can also be defined using a long format enclosed by -@long brackets@. We define an@opening long bracket of level n@as an opening -square bracket followed by@n@ equal signs followed by another opening square -bracket. So, an opening long bracket of level 0 is written as$[[$, an opening -long bracket of level 1 is written as$[=[$, and so on. -A@closing long bracket@is defined similarly; for instance, a closing long -bracket of level 4 is written as$]====]$. A long string starts with an opening -long bracket of any level and ends at the first closing long bracket of the -same level. Literals in this bracketed form may run for several lines, do not -interpret any escape sequences, and ignore long brackets of any other level. -They may contain anything except a closing bracket of the proper level. - -For convenience, when the opening long bracket is immediately followed by a -newline, the newline is not included in the string. As an example, in a system -using ASCII (in which$`a'$is coded as 97, newline is coded as 10, and $`1'$is -coded as 49), the five literals below denote the same string: -> - a = 'alo\n123"' - a = "alo\n123\"" - a = '\97lo\10\04923"' - a = [[alo - 123"]] - a = [==[ - alo - 123"]==] -> - *lrv-numconstant* -A@numerical constant@may be written with an optional decimal part and an -optional decimal exponent. Lua also accepts integer hexadecimal constants, by -prefixing them with$0x$. Examples of valid numerical constants are -> - 3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56 -> - *lrv-comment* -A@comment@starts with a double hyphen ($--$) anywhere outside a string. If the -text immediately after$--$is not an opening long bracket, the comment is -a@short comment@, which runs until the end of the line. Otherwise, it is -a@long comment@, which runs until the corresponding closing long bracket. Long -comments are frequently used to disable code temporarily. - -============================================================================== -2.2 Values and Types *lrv-langValTypes* - - -Lua is a@dynamically typed language@. This means that variables do not have -types; only values do. There are no type definitions in the language. All -values carry their own type. - -All values in Lua are@first-class values@. This means that all values can be -stored in variables, passed as arguments to other functions, and returned as -results. - - *lrv-types* *lrv-nil* *lrv-true* *lrv-false* *lrv-number* *lrv-string* -There are eight basic types in Lua:@nil@,@boolean@,@number@,@string@, -@function@,@userdata@,@thread@, and@table@.@Nil@is the type of the value#nil#, -whose main property is to be different from any other value; it usually -represents the absence of a useful value.@Boolean@is the type of the -values#false#and#true#. Both#nil#and#false#make a condition false; any other -value makes it true.@Number@represents real (double-precision floating-point) -numbers. (It is easy to build Lua interpreters that use other internal -representations for numbers, such as single-precision float or long -integers; see file$luaconf.h$.)@String@represents arrays of characters. Lua is -8-bit clean: strings may contain any 8-bit character, including embedded zeros -($'\0'$) (see |lrv-literal|). - -Lua can call (and manipulate) functions written in Lua and functions written -in C (see |lrv-langFuncCalls|). - - *lrv-userdatatype* -The type@userdata@is provided to allow arbitrary C data to be stored in Lua -variables. This type corresponds to a block of raw memory and has no -pre-defined operations in Lua, except assignment and identity test. However, -by using@metatables@, the programmer can define operations for userdata values -(see |lrv-langMetatables|). Userdata values cannot be created or modified in -Lua, only through the C API. This guarantees the integrity of data owned by -the host program. - - *lrv-thread* -The type@thread@represents independent threads of execution and it is used to -implement coroutines (see |lrv-langCoro|). Do not confuse Lua threads with -operating-system threads. Lua supports coroutines on all systems, even those -that do not support threads. - - *lrv-table* -The type@table@implements associative arrays, that is, arrays that can be -indexed not only with numbers, but with any value (except#nil#). Tables can -be@heterogeneous@; that is, they can contain values of all types -(except#nil#). Tables are the sole data structuring mechanism in Lua; they may -be used to represent ordinary arrays, symbol tables, sets, records, graphs, -trees, etc. To represent records, Lua uses the field name as an index. The -language supports this representation by providing$a.name$as syntactic sugar -for$a["name"]$. There are several convenient ways to create tables in Lua (see -|lrv-langTableConst|). - -Like indices, the value of a table field can be of any type (except#nil#). In -particular, because functions are first-class values, table fields may contain -functions. Thus tables may also carry@methods@(see |lrv-langFuncDefs|). - -Tables, functions, threads and (full) userdata values are@objects@: variables -do not actually@contain@these values, only@references@to them. Assignment, -parameter passing, and function returns always manipulate references to such -values; these operations do not imply any kind of copy. - -The library function$type$returns a string describing the type of a given -value (see |lrv-type|). - - ------------------------------------------------------------------------------- -2.2.1 Coercion *lrv-langCoercion* - -Lua provides automatic conversion between string and number values at run -time. Any arithmetic operation applied to a string tries to convert that -string to a number, following the usual conversion rules. Conversely, whenever -a number is used where a string is expected, the number is converted to a -string, in a reasonable format. For complete control of how numbers are -converted to strings, use the$format$function from the string library (see -|lrv-string.format|). - - -============================================================================== -2.3 Variables *lrv-langVariables* - - -Variables are places that store values. There are three kinds of variables in -Lua: global variables, local variables, and table fields. - -A single name can denote a global variable or a local variable (or a -function's formal parameter, which is a particular form of local variable): -> - var ::= Name -> -Name denotes identifiers, as defined in |lrv-langLexConv|. - -Any variable is assumed to be global unless explicitly declared as a local -(see |lrv-langLocalDec|). Local variables are@lexically scoped@: local -variables can be freely accessed by functions defined inside their scope (see -|lrv-langVisibRules|). - -Before the first assignment to a variable, its value is#nil#. - -Square brackets are used to index a table: - - $var ::= prefixexp$#`['#$exp$#`]'# - -The first expression (@prefixexp@) should result in a table value; the second -expression (@exp@) identifies a specific entry inside that table. The -expression denoting the table to be indexed has a restricted syntax; see -|lrv-langExpressions| for details. - -The syntax$var.NAME$is just syntactic sugar for$var["NAME"]$: - - $var ::= prefixexp$#`.'#$Name$ - -All global variables live as fields in ordinary Lua tables, called -@environment tables@or simply@environments@(see |lrv-langEnvironments|). -Each function has its own reference to an environment, so that all global -variables in this function will refer to this environment table. When a -function is created, it inherits the environment from the function that -created it. To get the environment table of a Lua function, you -call$getfenv$(see |lrv-getfenv|). To replace it, you call$setfenv$(see -|lrv-setfenv|). (You can only manipulate the environment of C functions -through the debug library; see |lrv-libDebug|.) - -An access to a global variable$x$is equivalent to$_env.x$, which in turn is -equivalent to -> - gettable_event(_env, "x") -> -where$_env$is the environment of the running function. (The$_env$variable is -not defined in Lua. We use it here only for explanatory purposes.) - -The meaning of accesses to global variables and table fields can be changed -via metatables. An access to an indexed variable$t[i]$is equivalent to a -call$gettable_event(t,i)$. (See |lrv-langMetatables| for a complete -description of the$gettable_event$function. This function is not defined or -callable in Lua. We use it here only for explanatory purposes.) - - -============================================================================== -2.4 Statements *lrv-langStats* - - -Lua supports an almost conventional set of statements, similar to those in -Pascal or C. This set includes assignment, control structures, function -calls, and variable declarations. - - ------------------------------------------------------------------------------- -2.4.1 Chunks *lrv-chunk* *lrv-langChunks* - - -The unit of execution of Lua is called a@chunk@. A chunk is simply a sequence -of statements, which are executed sequentially. Each statement can be -optionally followed by a semicolon: - - $chunk ::= {stat [$#`;'#$]}$ - -There are no empty statements and thus$`;;'$is not legal. - -Lua handles a chunk as the body of an anonymous function with a variable -number of arguments (see |lrv-langFuncDefs|). As such, chunks can define local -variables, receive arguments, and return values. - -A chunk may be stored in a file or in a string inside the host program. When a -chunk is executed, first it is pre-compiled into instructions for a virtual -machine, and then the compiled code is executed by an interpreter for the -virtual machine. - -Chunks may also be pre-compiled into binary form; see program$luac$for -details. Programs in source and compiled forms are interchangeable; Lua -automatically detects the file type and acts accordingly. - - ------------------------------------------------------------------------------- -2.4.2 Blocks *lrv-block* *lrv-langBlocks* - - -A block is a list of statements; syntactically, a block is the same as a -chunk: -> - block ::= chunk -> - *lrv-do* *lrv-end* -A block may be explicitly delimited to produce a single statement: - - $stat ::=$#do#$block$#end# - -Explicit blocks are useful to control the scope of variable declarations. -Explicit blocks are also sometimes used to add a#return#or#break#statement in -the middle of another block (see |lrv-langContStructs|). - - ------------------------------------------------------------------------------- -2.4.3 Assignment *lrv-langAssign* - - -Lua allows multiple assignment. Therefore, the syntax for assignment defines a -list of variables on the left side and a list of expressions on the right -side. The elements in both lists are separated by commas: - - $stat ::= varlist1$#`='#$explist1$ - $varlist1 ::= var {$#`,'#$var }$ - $explist1 ::= exp {$#`,'#$exp }$ - -Expressions are discussed in |lrv-langExpressions|. - -Before the assignment, the list of values is@adjusted@to the length of the -list of variables. If there are more values than needed, the excess values are -thrown away. If there are fewer values than needed, the list is extended with -as many#nil#'s as needed. If the list of expressions ends with a function -call, then all values returned by this call enter in the list of values, -before the adjustment (except when the call is enclosed in parentheses; see -|lrv-langExpressions|). - -The assignment statement first evaluates all its expressions and only then are -the assignments performed. Thus the code -> - i = 3 - i, a[i] = i+1, 20 -> -sets$a[3]$to 20, without affecting$a[4]$because the$i$in$a[i]$is evaluated (to -3) before it is assigned 4. Similarly, the line -> - x, y = y, x -> -exchanges the values of$x$and$y$. - -The meaning of assignments to global variables and table fields can be changed -via metatables. An assignment to an indexed variable$t[i] = val$is equivalent -to$settable_event(t,i,val)$. (See |lrv-langMetatables| for a complete -description of the$settable_event$function. This function is not defined or -callable in Lua. We use it here only for explanatory purposes.) - -An assignment to a global variable$x = val$is equivalent to the -assignment$_env.x = val$, which in turn is equivalent to -> - settable_event(_env, "x", val) -> -where$_env$is the environment of the running function. (The$_env$variable is -not defined in Lua. We use it here only for explanatory purposes.) - - ------------------------------------------------------------------------------- -2.4.4 Control Structures *lrv-langContStructs* - - *lrv-if* *lrv-then* *lrv-else* *lrv-elseif* - *lrv-while* *lrv-repeat* *lrv-until* -The control structures#if#,#while#, and#repeat#have the usual meaning and -familiar syntax: - - $stat ::=$#while#$exp$#do#$block$#end# - $stat ::=$#repeat#$block$#until#$exp$ - $stat ::=$#if#$exp$#then#$block {$#elseif#$exp$#then#$block }$ - $[$#else#$block ]$#end# - -Lua also has a#for#statement, in two flavors (see |lrv-langForStat|). - -The condition expression of a control structure may return any value. -Both#false#and#nil#are considered false. All values different -from#nil#and#false#are considered true (in particular, the number 0 and the -empty string are also true). - -In the#repeat-until#loop, the inner block does not end at the#until#keyword, -but only after the condition. So, the condition can refer to local variables -declared inside the loop block. - - *lrv-return* -The#return#statement is used to return values from a function or a chunk -(which is just a function). Functions and chunks may return more than one -value, so the syntax for the#return#statement is - - $stat ::=$#return#$[explist1]$ - - *lrv-break* -The#break#statement is used to terminate the execution of a#while#,#repeat#, -or#for#loop, skipping to the next statement after the loop: - - $stat ::=$#break# - -A#break#ends the innermost enclosing loop. - -The#return#and#break#statements can only be written as the@last@statement of a -block. If it is really necessary to#return#or#break#in the middle of a block, -then an explicit inner block can be used, as in the idioms -$`do return end'$and$`do break end'$, because now#return#and#break#are the -last statements in their (inner) blocks. - - ------------------------------------------------------------------------------- -2.4.5 For Statement *lrv-for* *lrv-langForStat* - - -The#for#statement has two forms: one numeric and one generic. - -The numeric#for#loop repeats a block of code while a control variable runs -through an arithmetic progression. It has the following syntax: - - $stat ::=$#for#$Name$#`='#$exp$#`,'#$exp [$#`,'#$exp ]$#do#$block$#end# - -The@block@is repeated for@name@starting at the value of the first@exp@, until -it passes the second@exp@by steps of the third@exp@. More precisely, -a#for#statement like - - $for var =$@e1, e2, e3@$do$@block@$end$ - -is equivalent to the code: - - $do$ - $local$@var, limit, step@$= tonumber(e1), tonumber(e2), tonumber(e3)$ - $if not ($@var@$and$@limit@$and$@step@$) then error() end$ - $while ($@step@$>0 and$@var@$<=$@limit@$)$ - $or ($@step@$<=0 and$@var@$>=$@limit@$) do$ - $block$ - @var@$=$@var@$+$@step@ - $end$ - $end$ - -Note the following: - - #o#All three control expressions are evaluated only once, before the loop - starts. They must all result in numbers. - #o#@var@,@limit@and@step@are invisible variables. The names are here for - explanatory purposes only. - #o#If the third expression (the step) is absent, then a step of 1 is used. - #o#You can use#break#to exit a#for#loop. - #o#The loop variable$var$is local to the loop; you cannot use its value - after the#for#ends or is broken. If you need this value, assign it to - another variable before breaking or exiting the loop. - - *lrv-in* -The generic#for#statement works over functions, called@iterators@. On each -iteration, the iterator function is called to produce a new value, stopping -when this new value is#nil#. The generic#for#loop has the following syntax: - - $stat ::=$#for#$namelist$#in#$explist1$#do#$block$#end# - $namelist ::= Name {$#`,'#$Name }$ - -A#for#statement like - - $for$@var1, ..., varn@$in$@explist@$do$@block@$end$ - -is equivalent to the code: - - $do$ - $local$@f, s, var@$=$@explist@ - $while true do$ - $local$@var1, ..., varn@$=$@f(s, var)@ - @var@$=$@var1@ - $if$@var@$== nil then break end$ - @block@ - $end$ - $end$ - -Note the following: - - #o#@explist@is evaluated only once. Its results are an@iterator@function, - a@state@, and an initial value for the first@iterator variable@. - #o#@f@,@s@, and@var@are invisible variables. The names are here for - explanatory purposes only. - #o#You can use#break#to exit a#for#loop. - #o#The loop variables@var1, ..., varn@are local to the loop; you cannot use - their values after the#for#ends. If you need these values, then assign - them to other variables before breaking or exiting the loop. - - ------------------------------------------------------------------------------- -2.4.6 Function Calls as Statements *lrv-langFuncStat* - - -To allow possible side-effects, function calls can be executed as statements: -> - stat ::= functioncall -> -In this case, all returned values are thrown away. Function calls are -explained in |lrv-langFuncCalls|. - - ------------------------------------------------------------------------------- -2.4.7 Local Declarations *lrv-local* *lrv-langLocalDec* - - -Local variables may be declared anywhere inside a block. The declaration may -include an initial assignment: - - $stat ::=$#local#$namelist [$#`='#$explist1 ]$ - $namelist ::= Name {$#`,'#$Name }$ - -If present, an initial assignment has the same semantics of a multiple -assignment (see |lrv-langAssign|). Otherwise, all variables are initialized -with#nil#. - -A chunk is also a block (see |lrv-langChunks|), and so local variables can be -declared in a chunk outside any explicit block. The scope of such local -variables extends until the end of the chunk. - -The visibility rules for local variables are explained in -|lrv-langVisibRules|. - - -============================================================================== -2.5 Expressions *lrv-langExpressions* - - -The basic expressions in Lua are the following: - - $exp ::= prefixexp$ - $exp ::=$#nil#$|$#false#$|$#true# - $exp ::= Number$ - $exp ::= String$ - $exp ::= function$ - $exp ::= tableconstructor$ - $exp ::=$#`...'# - $exp ::= exp binop exp$ - $exp ::= unop exp$ - $prefixexp ::= var | functioncall |$#`('#$exp$#`)'# - -Numbers and literal strings are explained in |lrv-langLexConv|; variables are -explained in |lrv-langVariables|; function definitions are explained in -|lrv-langFuncDefs|; function calls are explained in |lrv-langFuncCalls|; -table constructors are explained in |lrv-langTableConst|. Vararg expressions, -denoted by three dots ($`...'$), can only be used inside vararg functions; -they are explained in |lrv-langFuncDefs|. - -Binary operators comprise arithmetic operators (see |lrv-langArithOp|), -relational operators (see |lrv-langRelOp|), logical operators (see -|lrv-langLogOp|), and the concatenation operator (see |lrv-langConcat|). -Unary operators comprise the unary minus (see |lrv-labgArithOp|), the unary -#not# (see |lrv-langLogOp|), and the unary@length operator@(see -|lrv-langLength|). - -Both function calls and vararg expressions may result in multiple values. If -the expression is used as a statement (see |lrv-langFuncStat|) -(only possible for function calls), then its return list is adjusted to zero -elements, thus discarding all returned values. If the expression is used as -the last (or the only) element of a list of expressions, then no adjustment is -made (unless the call is enclosed in parentheses). In all other contexts, Lua -adjusts the result list to one element, discarding all values except the first -one. - -Here are some examples: -> - f() -- adjusted to 0 results - g(f(), x) -- f() is adjusted to 1 result - g(x, f()) -- g gets x plus all results from f() - a,b,c = f(), x -- f() is adjusted to 1 result (c gets nil) - a,b = ... -- a gets the first vararg parameter, b gets - -- the second (both a and b may get nil if there - -- is no corresponding vararg parameter) - - a,b,c = x, f() -- f() is adjusted to 2 results - a,b,c = f() -- f() is adjusted to 3 results - return f() -- returns all results from f() - return ... -- returns all received vararg parameters - return x,y,f() -- returns x, y, and all results from f() - {f()} -- creates a list with all results from f() - {...} -- creates a list with all vararg parameters - {f(), nil} -- f() is adjusted to 1 result -> -An expression enclosed in parentheses always results in only one value. Thus, -$(f(x,y,z))$is always a single value, even if$f$returns several values. -(The value of$(f(x,y,z))$is the first value returned by$f$or#nil#if$f$does not -return any values.) - - ------------------------------------------------------------------------------- -2.5.1 Arithmetic Operators *lrv-langArithOp* - - -Lua supports the usual arithmetic operators: the binary$+$(addition), -$-$(subtraction),$*$(multiplication),$/$(division),$%$(modulo) -and$^$(exponentiation); and unary$-$(negation). If the operands are numbers, -or strings that can be converted to numbers (see |lrv-langCoercion|), then all -operations have the usual meaning. Exponentiation works for any exponent. For -instance,$x^(-0.5)$computes the inverse of the square root of$x$. Modulo is -defined as -> - a % b == a - math.floor(a/b)*b -> -That is, it is the remainder of a division that rounds the quotient towards -minus infinity. - - ------------------------------------------------------------------------------- -2.5.2 Relational Operators *lrv-langRelOp* - - -The relational operators in Lua are -> - == ~= < > <= >= -> -These operators always result in#false#or#true#. - -Equality ($==$) first compares the type of its operands. If the types are -different, then the result is#false#. Otherwise, the values of the operands -are compared. Numbers and strings are compared in the usual way. Objects -(tables, userdata, threads, and functions) are compared by@reference@: two -objects are considered equal only if they are the@same@object. Every time you -create a new object (a table, userdata, or function), this new object is -different from any previously existing object. - -You can change the way that Lua compares tables and userdata using the "eq" -metamethod (see |lrv-langMetatables|). - -The conversion rules of coercion |lrv-langCoercion|@do not@apply to equality -comparisons. Thus,$"0"==0$evaluates to#false#, and$t[0]$and$t["0"]$denote -different entries in a table. - -The operator$~=$is exactly the negation of equality ($==$). - -The order operators work as follows. If both arguments are numbers, then they -are compared as such. Otherwise, if both arguments are strings, then their -values are compared according to the current locale. Otherwise, Lua tries to -call the "lt" or the "le" metamethod (see |lrv-langMetatables|). - - ------------------------------------------------------------------------------- -2.5.3 Logical Operators *lrv-langLogOp* - - -The logical operators in Lua are -> - and or not -> -Like the control structures (see |lrv-langContStructs|), all logical operators -consider both#false#and#nil#as false and anything else as true. - - *lrv-not* *lrv-and* *lrv-or* -The negation operator#not#always returns#false#or#true#. The conjunction -operator#and#returns its first argument if this value is#false#or#nil#; -otherwise,#and#returns its second argument. The disjunction -operator#or#returns its first argument if this value is different -from#nil#and#false#; otherwise,#or#returns its second argument. -Both#and#and#or#use short-cut evaluation, that is, the second operand is -evaluated only if necessary. Here are some examples: -> - 10 or 20 --> 10 - 10 or error() --> 10 - nil or "a" --> "a" - nil and 10 --> nil - false and error() --> false - false and nil --> false - false or nil --> nil - 10 and 20 --> 20 -> -(In this manual,$-->$indicates the result of the preceding expression.) - - ------------------------------------------------------------------------------- -2.5.4 Concatenation *lrv-langConcat* - - -The string concatenation operator in Lua is denoted by two dots ($`..'$). -If both operands are strings or numbers, then they are converted to strings -according to the rules mentioned in |lrv-langCoercion|. Otherwise, the -"concat" metamethod is called (see |lrv-langMetatables|). - - ------------------------------------------------------------------------------- -2.5.5 The Length Operator *lrv-langLength* - - -The length operator is denoted by the unary operator$#$. The length of a -string is its number of bytes (that is, the usual meaning of string length -when each character is one byte). - -The length of a table$t$is defined to be any integer index$n$such that$t[n]$is -not#nil#and$t[n+1]$is#nil#; moreover, if$t[1]$is#nil#,$n$may be zero. For a -regular array, with non-nil values from 1 to a given$n$, its length is exactly -that$n$, the index of its last value. If the array has "holes" (that -is,#nil#values between other non-nil values), then$#t$may be any of the -indices that directly precedes a#nil#value (that is, it may consider any -such#nil#value as the end of the array). - - ------------------------------------------------------------------------------- -2.5.6 Precedence *lrv-langPrec* - - -Operator precedence in Lua follows the table below, from lower to higher -priority: -> - or - and - < > <= >= ~= == - .. - + - - * / - not # - (unary) - ^ -> -As usual, you can use parentheses to change the precedences in an expression. -The concatenation ($`..'$) and exponentiation ($`^'$) operators are right -associative. All other binary operators are left associative. - - ------------------------------------------------------------------------------- -2.5.7 Table Constructors *lrv-langTableConst* - - -Table constructors are expressions that create tables. Every time a -constructor is evaluated, a new table is created. Constructors can be used to -create empty tables, or to create a table and initialize some of its fields. -The general syntax for constructors is - - $tableconstructor ::=$#`{'#$[ fieldlist ]$#`}'# - $fieldlist ::= field { fieldsep field } [ fieldsep ]$ - $field ::=$#`['#$exp$#`]' `='#$exp | Name$#`='#$exp | exp$ - $fieldsep ::=$ #`,'#$|$ #`;'# - -Each field of the form$[exp1] = exp2$adds to the new table an entry with -key$exp1$and value$exp2$. A field of the form$name = exp$is equivalent to -$["name"] = exp$. Finally, fields of the form$exp$are equivalent to -$[i] = exp$, where$i$are consecutive numerical integers, starting with 1. -Fields in the other formats do not affect this counting. For example, -> - a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 } -> -is equivalent to -> - do - local t = {} - t[f(1)] = g - t[1] = "x" -- 1st exp - t[2] = "y" -- 2nd exp - t.x = 1 -- temp["x"] = 1 - t[3] = f(x) -- 3rd exp - t[30] = 23 - t[4] = 45 -- 4th exp - a = t - end -> -If the last field in the list has the form$exp$and the expression is a -function call, then all values returned by the call enter the list -consecutively (see |lrv-langFuncCalls|). To avoid this, enclose the function -call in parentheses (see |lrv-langExpressions|). - -The field list may have an optional trailing separator, as a convenience for -machine-generated code. - - ------------------------------------------------------------------------------- -2.5.8 Function Calls *lrv-function* *lrv-langFuncCalls* - - -A function call in Lua has the following syntax: -> - functioncall ::= prefixexp args -> -In a function call, first@prefixexp@and@args@are evaluated. If the value -of@prefixexp@has type@function@, then this function is called with the given -arguments. Otherwise, the@prefixexp@"call" metamethod is called, having as -first parameter the value of@prefixexp@, followed by the original call -arguments (see |lrv-langMetatables|). - -The form - - $functioncall ::= prefixexp$#`:'#$Name args$ - -can be used to call "methods". A call$v:name($@args@$)$is syntactic sugar -for$v.name(v,$@args@$)$, except that$v$is evaluated only once. - -Arguments have the following syntax: - - $args ::= $#`('#$[ explist1 ]$#`)'# - $args ::= tableconstructor$ - $args ::= String$ - -All argument expressions are evaluated before the call. A call of the -form$f{$@fields@$}$is syntactic sugar for $f({$@fields@$})$, that is, the -argument list is a single new table. A call of the form$f'$@string@$'$ -(or$f"$@string@$"$or$f[[$@string@$]]$) is syntactic sugar for -$f('$@string@$')$, that is, the argument list is a single literal string. - -As an exception to the free-format syntax of Lua, you cannot put a line break -before the$'('$ in a function call. This restriction avoids some ambiguities -in the language. If you write -> - a = f - (g).x(a) -> -Lua would see that as a single statement,$a = f(g).x(a)$. So, if you want two -statements, you must add a semi-colon between them. If you actually want to -call$f$, you must remove the line break before$(g)$. - - *lrv-tailcall* -A call of the form$return$@functioncall@is called a@tail call@. Lua -implements@proper tail calls@(or@proper tail recursion@): in a tail call, the -called function reuses the stack entry of the calling function. Therefore, -there is no limit on the number of nested tail calls that a program can -execute. However, a tail call erases any debug information about the calling -function. Note that a tail call only happens with a particular syntax, where -the#return#has one single function call as argument; this syntax makes the -calling function return exactly the returns of the called function. So, none -of the following examples are tail calls: -> - return (f(x)) -- results adjusted to 1 - return 2 * f(x) - return x, f(x) -- additional results - f(x); return -- results discarded - return x or f(x) -- results adjusted to 1 -> - ------------------------------------------------------------------------------- -2.5.9 Function Definitions *lrv-langFuncDefs* - - -The syntax for function definition is - - $function ::=$#function#$funcbody$ - $funcbody ::=$#`('#$[ parlist1 ]$#`)'#$block$#end# - -The following syntactic sugar simplifies function definitions: - - $stat ::=$#function#$funcname funcbody$ - $stat ::=$#local function#$Name funcbody$ - $funcname ::= Name {$#`.'#$Name } [$#`:'#$Name ]$ - -The statement - - $function f ()$@body@$end$ - -translates to - - $f = function ()$@body@$end$ - -The statement - - $function t.a.b.c.f ()$@body@$end$ - -translates to - - $t.a.b.c.f = function ()$@body@$end$ - -The statement - - $local function f ()$@body@$end$ - -translates to - - $local f; f = function f ()$@body@$end$ - -@not@to - - $local f = function f ()$@body@$end$ - -(This only makes a difference when the body of the function contains -references to$f$.) - - *lrv-closure* -A function definition is an executable expression, whose value has -type@function@. When Lua pre-compiles a chunk, all its function bodies are -pre-compiled too. Then, whenever Lua executes the function definition, the -function is@instantiated@(or@closed@). This function instance (or@closure@) -is the final value of the expression. Different instances of the same -function may refer to different external local variables and may have -different environment tables. - -Parameters act as local variables that are initialized with the argument -values: - - $parlist1 ::= namelist [$#`,' `...'#$] |$#`...'# - - *lrv-vararg* -When a function is called, the list of arguments is adjusted to the length of -the list of parameters, unless the function is a variadic or@vararg function@, -which is indicated by three dots ($`...'$) at the end of its parameter list. -A vararg function does not adjust its argument list; instead, it collects all -extra arguments and supplies them to the function through a@vararg expression@, -which is also written as three dots. The value of this expression is a list of -all actual extra arguments, similar to a function with multiple results. If a -vararg expression is used inside another expression or in the middle of a list -of expressions, then its return list is adjusted to one element. If the -expression is used as the last element of a list of expressions, then no -adjustment is made (unless the call is enclosed in parentheses). - -As an example, consider the following definitions: -> - function f(a, b) end - function g(a, b, ...) end - function r() return 1,2,3 end -> -Then, we have the following mapping from arguments to parameters and to the -vararg expression: -> - CALL PARAMETERS - - f(3) a=3, b=nil - f(3, 4) a=3, b=4 - f(3, 4, 5) a=3, b=4 - f(r(), 10) a=1, b=10 - f(r()) a=1, b=2 - - g(3) a=3, b=nil, ... --> (nothing) - g(3, 4) a=3, b=4, ... --> (nothing) - g(3, 4, 5, 8) a=3, b=4, ... --> 5 8 - g(5, r()) a=5, b=1, ... --> 2 3 -> -Results are returned using the#return#statement (see |lrv-langContStructs|). -If control reaches the end of a function without encountering -a#return#statement, then the function returns with no results. - - *lrv-colonsyntax* -The@colon@syntax is used for defining@methods@, that is, functions that have -an implicit extra parameter$self$. Thus, the statement - - $function t.a.b.c:f ($@params@$)$@body@$end$ - -is syntactic sugar for - - $t.a.b.c:f = function (self, ($@params@$)$@body@$end$ - - -============================================================================== -2.6 Visibility Rules *lrv-langVisibRules* - - -Lua is a lexically scoped language. The scope of variables begins at the -first statement@after@their declaration and lasts until the end of the -innermost block that includes the declaration. Consider the following example: -> - x = 10 -- global variable - do -- new block - local x = x -- new `x', with value 10 - print(x) --> 10 - x = x+1 - do -- another block - local x = x+1 -- another `x' - print(x) --> 12 - end - print(x) --> 11 - end - print(x) --> 10 (the global one) -> -Notice that, in a declaration like$local x = x$, the new$x$being declared is -not in scope yet, and so the second$x$refers to the outside variable. - - *lrv-upvalue* -Because of the lexical scoping rules, local variables can be freely accessed -by functions defined inside their scope. A local variable used by an inner -function is called an@upvalue@, or@external local variable@, inside the inner -function. - -Notice that each execution of a#local#statement defines new local variables. -Consider the following example: -> - a = {} - local x = 20 - for i=1,10 do - local y = 0 - a[i] = function () y=y+1; return x+y end - end -> -The loop creates ten closures (that is, ten instances of the anonymous -function). Each of these closures uses a different$y$variable, while all of -them share the same$x$. - - -============================================================================== -2.7 Error Handling *lrv-langError* - - -Because Lua is an embedded extension language, all Lua actions start from -C code in the host program calling a function from the Lua library (see -|lrv-lua_pcall|). Whenever an error occurs during Lua compilation or -execution, control returns to C, which can take appropriate measures (such as -print an error message). - -Lua code can explicitly generate an error by calling the$error$function (see -|lrv-error|). If you need to catch errors in Lua, you can use -the$pcall$function (see |lrv-pcall|). - - -============================================================================== -2.8 Metatables *lrv-metatable* *lrv-langMetatables* - - -Every value in Lua may have a@metatable@. This@metatable@is an ordinary Lua -table that defines the behavior of the original table and userdata under -certain special operations. You can change several aspects of the behavior of -an object by setting specific fields in its metatable. For instance, when a -non-numeric value is the operand of an addition, Lua checks for a function in -the field$"__add"$in its metatable. If it finds one, Lua calls that function -to perform the addition. - -We call the keys in a metatable@events@and the values@metamethods@. In the -previous example, the event is$"add"$and the metamethod is the function that -performs the addition. - -You can query the metatable of any value through the$getmetatable$function -(see |lrv-getmetatable|). - -You can replace the metatable of tables through the$setmetatable$function (see -|lrv-setmetatable|). You cannot change the metatable of other types from Lua -(except using the debug library); you must use the C API for that. - -Tables and userdata have individual metatables (although multiple tables and -userdata can share a same table as their metatable); values of all other types -share one single metatable per type. So, there is one single metatable for all -numbers, and for all strings, etc. - -A metatable may control how an object behaves in arithmetic operations, order -comparisons, concatenation, length operation, and indexing. A metatable can -also define a function to be called when a userdata is garbage collected. For -each of those operations Lua associates a specific key called an@event@. When -Lua performs one of those operations over a value, it checks whether this -value has a metatable with the corresponding event. If so, the value -associated with that key (the@metamethod@) controls how Lua will perform the -operation. - -Metatables control the operations listed next. Each operation is identified by -its corresponding name. The key for each operation is a string with its name -prefixed by two underscores,$'__'$; for instance, the key for operation "add" -is the string$"__add"$. The semantics of these operations is better explained -by a Lua function describing how the interpreter executes that operation. - -The code shown here in Lua is only illustrative; the real behavior is hard -coded in the interpreter and it is much more efficient than this simulation. -All functions used in these descriptions ($rawget$,$tonumber$, etc.) are -described in |lrv-libBasic|. In particular, to retrieve the metamethod of a -given object, we use the expression -> - metatable(obj)[event] -> -This should be read as -> - rawget(metatable(obj) or {}, event) -> -That is, the access to a metamethod does not invoke other metamethods, and the -access to objects with no metatables does not fail (it simply results -in#nil#). - -$"add":$ *lrv-__add* --------- -the$+$operation. - -The function$getbinhandler$below defines how Lua chooses a handler for a -binary operation. First, Lua tries the first operand. If its type does not -define a handler for the operation, then Lua tries the second operand. -> - function getbinhandler (op1, op2, event) - return metatable(op1)[event] or metatable(op2)[event] - end -> -By using this function, the behavior of the$op1 + op2$is -> - function add_event (op1, op2) - local o1, o2 = tonumber(op1), tonumber(op2) - if o1 and o2 then -- both operands are numeric? - return o1 + o2 -- `+' here is the primitive `add' - else -- at least one of the operands is not numeric - local h = getbinhandler(op1, op2, "__add") - if h then - -- call the handler with both operands - return h(op1, op2) - else -- no handler available: default behavior - error(...) - end - end - end -> -$"sub":$ *lrv-__sub* --------- -the$-$operation. Behavior similar to the "add" operation. - -$"mul":$ *lrv-__mul* --------- -the$*$operation. Behavior similar to the "add" operation. - -$"div":$ *lrv-__div* --------- -the$/$operation. Behavior similar to the "add" operation. - -$"mod":$ *lrv-__mod* --------- -the$%$operation. Behavior similar to the "add" operation, with the -operation$o1 - floor(o1/o2)*o2$as the primitive operation. - -$"pow":$ *lrv-__pow* --------- -the$^$(exponentiation) operation. Behavior similar to the "add" operation, -with the function$pow$(from the C math library) as the primitive operation. - -$"unm":$ *lrv-__unm* --------- -the unary$-$operation. -> - function unm_event (op) - local o = tonumber(op) - if o then -- operand is numeric? - return -o -- '-' here is the primitive 'unm' - else -- the operand is not numeric. - -- Try to get a handler from the operand - local h = metatable(op).__unm - if h then - -- call the handler with the operand - return h(op) - else -- no handler available: default behavior - error(...) - end - end - end -> -$"concat":$ *lrv-__concat* ------------ -the$..$(concatenation) operation. -> - function concat_event (op1, op2) - if (type(op1) == "string" or type(op1) == "number") and - (type(op2) == "string" or type(op2) == "number") then - return op1 .. op2 -- primitive string concatenation - else - local h = getbinhandler(op1, op2, "__concat") - if h then - return h(op1, op2) - else - error(...) - end - end - end -> -$"len":$ *lrv-__len* ------------ -the$#$operation. -> - function len_event (op) - if type(op) == "string" then - return strlen(op) -- primitive string length - elseif type(op) == "table" then - return #op -- primitive table length - else - local h = metatable(op).__len - if h then - -- call the handler with the operand - return h(op) - else -- no handler available: default behavior - error(...) - end - end - end -> -$"eq":$ *lrv-__eq* -------- -the$==$operation. - -The function$getcomphandler$defines how Lua chooses a metamethod for -comparison operators. A metamethod only is selected when both objects being -compared have the same type and the same metamethod for the selected -operation. -> - function getcomphandler (op1, op2, event) - if type(op1) ~= type(op2) then return nil end - local mm1 = metatable(op1)[event] - local mm2 = metatable(op2)[event] - if mm1 == mm2 then return mm1 else return nil end - end -> -The "eq" event is defined as follows: -> - function eq_event (op1, op2) - if type(op1) ~= type(op2) then -- different types? - return false -- different objects - end - if op1 == op2 then -- primitive equal? - return true -- objects are equal - end - -- try metamethod - local h = getcomphandler(op1, op2, "__eq") - if h then - return h(op1, op2) - else - return false - end - end -> -$a ~= b$is equivalent to$not (a == b)$. - -$"lt":$ *lrv-__lt* -------- -the$<$operation. -> - function lt_event (op1, op2) - if type(op1) == "number" and type(op2) == "number" then - return op1 < op2 -- numeric comparison - elseif type(op1) == "string" and type(op2) == "string" then - return op1 < op2 -- lexicographic comparison - else - local h = getcomphandler(op1, op2, "__lt") - if h then - return h(op1, op2) - else - error(...); - end - end - end -> -$a > b$is equivalent to$b < a$. - -$"le":$ *lrv-__le* -------- -the$<=$operation. -> - function le_event (op1, op2) - if type(op1) == "number" and type(op2) == "number" then - return op1 <= op2 -- numeric comparison - elseif type(op1) == "string" and type(op2) == "string" then - return op1 <= op2 -- lexicographic comparison - else - local h = getcomphandler(op1, op2, "__le") - if h then - return h(op1, op2) - else - h = getcomphandler(op1, op2, "__lt") - if h then - return not h(op2, op1) - else - error(...); - end - end - end - end -> -$a >= b$is equivalent to$b <= a$. Note that, in the absence of a "le" -metamethod, Lua tries the "lt", assuming that$a <= b$is equivalent -to$not (b < a)$. - -$"index":$ *lrv-__index* ----------- -The indexing access$table[key]$. -> - function gettable_event (table, key) - local h - if type(table) == "table" then - local v = rawget(table, key) - if v ~= nil then return v end - h = metatable(table).__index - if h == nil then return nil end - else - h = metatable(table).__index - if h == nil then - error(...); - end - end - if type(h) == "function" then - return h(table, key) -- call the handler - else return h[key] -- or repeat operation on it - end -> -$"newindex":$ *lrv-__newindex* -------------- -The indexing assignment$table[key] = value$. -> - function settable_event (table, key, value) - local h - if type(table) == "table" then - local v = rawget(table, key) - if v ~= nil then rawset(table, key, value); return end - h = metatable(table).__newindex - if h == nil then rawset(table, key, value); return end - else - h = metatable(table).__newindex - if h == nil then - error(...); - end - end - if type(h) == "function" then - return h(table, key,value) -- call the handler - else h[key] = value -- or repeat operation on it - end -> -$"call":$ *lrv-__call* ---------- -called when Lua calls a value. -> - function function_event (func, ...) - if type(func) == "function" then - return func(...) -- primitive call - else - local h = metatable(func).__call - if h then - return h(func, ...) - else - error(...) - end - end - end -> - -============================================================================== -2.9 Environments *lrv-environment* *lrv-langEnvironments* - - -Besides metatables, objects of types thread, function, and userdata have -another table associated with them, called their@environment@. Like -metatables, environments are regular tables and multiple objects can share the -same environment. - -Environments associated with userdata have no meaning for Lua. It is only a -convenience feature for programmers to associate a table to a userdata. - -Environments associated with threads are called@global environments@. They are -used as the default environment for their threads and non-nested functions -created by the thread (through$loadfile$|lrv-loadfile|, -$loadstring$|lrv-loadstring| or$load$|lrv-load|) and can be directly accessed -by C code (see |lrv-apiPseudoIndices|). - - -Environments associated with C functions can be directly accessed by C code -(see |lrv-apiPseudoIndices|). They are used as the default environment for -other C functions created by the function. - -Environments associated with Lua functions are used to resolve all accesses to -global variables within the function (see |lrv-langVariables|). They are used -as the default environment for other Lua functions created by the function. - -You can change the environment of a Lua function or the running thread by -calling$setfenv$(see |lrv-setenv|). You can get the environment of a Lua -function or the running thread by calling$getfenv$(see |lrv-getfenv|). To -manipulate the environment of other objects (userdata, C functions, other -threads) you must use the C API. - - -============================================================================== -2.10 Garbage Collection *lrv-langGC* - - -Lua performs automatic memory management. This means that you do not have to -worry neither about allocating memory for new objects nor about freeing it -when the objects are no longer needed. Lua manages memory automatically by -running a@garbage collector@from time to time to collect all@dead objects@ -(that is, these objects that are no longer accessible from Lua). All objects -in Lua are subject to automatic management: tables, userdata, functions, -threads, and strings. - -Lua implements an incremental mark-and-sweep collector. It uses two numbers to -control its garbage-collection cycles: the@garbage-collector pause@and the -@garbage-collector step multiplier@. - -The garbage-collector pause controls how long the collector waits before -starting a new cycle. Larger values make the collector less aggressive. Values -smaller than 1 mean the collector will not wait to start a new cycle. A value -of 2 means that the collector waits for the total memory in use to double -before starting a new cycle. - -The step multiplier controls the relative speed of the collector relative to -memory allocation. Larger values make the collector more aggressive but also -increase the size of each incremental step. Values smaller than 1 make the -collector too slow and may result in the collector never finishing a cycle. -The default, 2, means that the collector runs at "twice" the speed of memory -allocation. - -You can change these numbers by calling$lua_gc$(see |lrv-lua_gc|) in C or -$collectgarbage$(see |lrv-collectgarbage|) in Lua. Both get percentage points -as arguments (so an argument of 100 means a real value of 1). With these -functions you can also control the collector directly (e.g., stop and restart -it). - - ------------------------------------------------------------------------------- -2.10.1 Garbage-Collection Metamethods *lrv-langGCMeta* - - -Using the C API, you can set garbage-collector metamethods for userdata (see -|lrv-langMetatables|). These metamethods are also called@finalizers@. -Finalizers allow you to coordinate Lua's garbage collection with external -resource management (such as closing files, network or database connections, -or freeing your own memory). - - *lrv-__gc* -Garbage userdata with a field$__gc$in their metatables are not collected -immediately by the garbage collector. Instead, Lua puts them in a list. After -the collection, Lua does the equivalent of the following function for each -userdata in that list: -> - function gc_event (udata) - local h = metatable(udata).__gc - if h then - h(udata) - end - end -> -At the end of each garbage-collection cycle, the finalizers for userdata are -called in@reverse@order of their creation, among these collected in that -cycle. That is, the first finalizer to be called is the one associated with -the userdata created last in the program. - - ------------------------------------------------------------------------------- -2.10.2 - Weak Tables *lrv-weaktable* *lrv-langWeaktables* - - -A@weak table@is a table whose elements are@weak references@. A weak reference -is ignored by the garbage collector. In other words, if the only references to -an object are weak references, then the garbage collector will collect this -object. - - *lrv-__mode* -A weak table can have weak keys, weak values, or both. A table with weak keys -allows the collection of its keys, but prevents the collection of its values. -A table with both weak keys and weak values allows the collection of both keys -and values. In any case, if either the key or the value is collected, the -whole pair is removed from the table. The weakness of a table is controlled by -the value of the$__mode$field of its metatable. If the$__mode$field is a -string containing the character$'k'$, the keys in the table are weak. -If$__mode$contains$'v'$, the values in the table are weak. - -After you use a table as a metatable, you should not change the value of its -field$__mode$. Otherwise, the weak behavior of the tables controlled by this -metatable is undefined. - - -============================================================================== -2.11 Coroutines *lrv-coroutine* *lrv-langCoro* - - -Lua supports coroutines, also called@collaborative multithreading@. -A coroutine in Lua represents an independent thread of execution. Unlike -threads in multithread systems, however, a coroutine only suspends its -execution by explicitly calling a yield function. - -You create a coroutine with a call to$coroutine.create$(see -|lrv-coroutine.create|). Its sole argument is a function that is the main -function of the coroutine. The$create$function only creates a new coroutine -and returns a handle to it (an object of type@thread@); it does not start the -coroutine execution. - -When you first call$coroutine.resume$(see |lrv-coroutine.resume|), passing as -its first argument the thread returned by$coroutine.create$, the coroutine -starts its execution, at the first line of its main function. Extra arguments -passed to$coroutine.resume$are passed on to the coroutine main function. After -the coroutine starts running, it runs until it terminates or@yields@. - -A coroutine can terminate its execution in two ways: normally, when its main -function returns (explicitly or implicitly, after the last instruction); and -abnormally, if there is an unprotected error. In the first case, -$coroutine.resume$returns#true#, plus any values returned by the coroutine -main function. In case of errors,$coroutine.resume$returns#false#plus an error -message. - -A coroutine yields by calling$coroutine.yield$(see |lrv-coroutine.yield|). -When a coroutine yields, the corresponding$coroutine.resume$returns -immediately, even if the yield happens inside nested function calls (that is, -not in the main function, but in a function directly or indirectly called by -the main function). In the case of a yield,$coroutine.resume$also -returns#true#, plus any values passed to$coroutine.yield$. The next time you -resume the same coroutine, it continues its execution from the point where it -yielded, with the call to$coroutine.yield$returning any extra arguments passed -to$coroutine.resume$. - -Like$coroutine.create$, the$coroutine.wrap$function (see |lrv-coroutine.wrap|) -also creates a coroutine, but instead of returning the coroutine itself, it -returns a function that, when called, resumes the coroutine. Any arguments -passed to this function go as extra arguments to$coroutine.resume$. -$coroutine.wrap$returns all the values returned by$coroutine.resume$, except -the first one (the boolean error code). Unlike$coroutine.resume$, -$coroutine.wrap$does not catch errors; any error is propagated to the caller. - -As an example, consider the next code: -> - function foo1 (a) - print("foo", a) - return coroutine.yield(2*a) - end - - co = coroutine.create(function (a,b) - print("co-body", a, b) - local r = foo1(a+1) - print("co-body", r) - local r, s = coroutine.yield(a+b, a-b) - print("co-body", r, s) - return b, "end" - end) - - print("main", coroutine.resume(co, 1, 10)) - print("main", coroutine.resume(co, "r")) - print("main", coroutine.resume(co, "x", "y")) - print("main", coroutine.resume(co, "x", "y")) -> -When you run it, it produces the following output: -> - co-body 1 10 - foo 2 - main true 4 - co-body r - main true 11 -9 - co-body x y - main true 10 end - main false cannot resume dead coroutine -> - -============================================================================== -3 THE APPLICATION PROGRAM INTERFACE *lrv-API* -============================================================================== - - -This section describes the C API for Lua, that is, the set of C functions -available to the host program to communicate with Lua. All API functions and -related types and constants are declared in the header file$lua.h$. - -Even when we use the term "function", any facility in the API may be provided -as a@macro@instead. All such macros use each of its arguments exactly once -(except for the first argument, which is always a Lua state), and so do not -generate hidden side-effects. - -As in most C libraries, the Lua API functions do not check their arguments for -validity or consistency. However, you can change this behavior by compiling -Lua with a proper definition for the macro$luai_apicheck$,in file$luaconf.h$. - - -============================================================================== -3.1 The Stack *lrv-stack* *lrv-apiStack* - - -Lua uses a@virtual stack@to pass values to and from C. Each element in this -stack represents a Lua value (#nil#, number, string, etc.). - -Whenever Lua calls C, the called function gets a new stack, which is -independent of previous stacks and of stacks of C functions that are still -active. This stack initially contains any arguments to the C function and it -is where the C function pushes its results to be returned to the caller (see -|lrv-lua_CFunction|). - - *lrv-stackindex* -For convenience, most query operations in the API do not follow a strict stack -discipline. Instead, they can refer to any element in the stack by using an -@index@: a positive index represents an@absolute@stack position (starting -at 1); a negative index represents an@offset@from the top of the stack. -More specifically, if the stack has@n@elements, then index 1 represents the -first element (that is, the element that was pushed onto the stack first) and -index@n@represents the last element; index@-1@also represents the last element -(that is, the element at the top) and index@-n@represents the first element. -We say that an index is@valid@if it lies between 1 and the stack top (that is, -if$1 <= abs(index) <= top$). - - -============================================================================== -3.2 Stack Size *lrv-apiStackSize* - - -When you interact with Lua API, you are responsible for ensuring consistency. -In particular, @you are responsible for controlling stack overflow@. You can -use the function$lua_checkstack$to grow the stack size (see -|lrv-lua_checkstack|). - -Whenever Lua calls C, it ensures that at least$LUA_MINSTACK$stack positions -are available.$LUA_MINSTACK$is defined as 20, so that usually you do not have -to worry about stack space unless your code has loops pushing elements onto -the stack. - -Most query functions accept as indices any value inside the available stack -space, that is, indices up to the maximum stack size you have set -through$lua_checkstack$. Such indices are called@acceptable indices@. More -formally, we define an@acceptable index@as follows: -> - (index < 0 && abs(index) <= top) || (index > 0 && index <= stackspace) -> -Note that 0 is never an acceptable index. - - -============================================================================== -3.3 Pseudo-Indices *lrv-pseudoindex* *lrv-apiPseudoIndices* - - -Unless otherwise noted, any function that accepts valid indices can also be -called with@pseudo-indices@, which represent some Lua values that are -accessible to the C code but which are not in the stack. Pseudo-indices are -used to access the thread environment, the function environment, the registry, -and the upvalues of a C function (see |lrv-apiCClosures|). - -The thread environment (where global variables live) is always at pseudo-index -$LUA_GLOBALSINDEX$. The environment of the running C function is always at -pseudo-index$LUA_ENVIRONINDEX$. - -To access and change the value of global variables, you can use regular table -operations over an environment table. For instance, to access the value of a -global variable, do -> - lua_getfield(L, LUA_GLOBALSINDEX, varname); -> - -============================================================================== -3.4 C Closures *lrv-cclosure* *lrv-apiCClosures* - - -When a C function is created, it is possible to associate some values with it, -thus creating a@C closure@; these values are called@upvalues@and are -accessible to the function whenever it is called (see |lrv-lua_pushcclosure|). - - -Whenever a C function is called, its upvalues are located at specific -pseudo-indices. These pseudo-indices are produced by the macro -$lua_upvalueindex$(see |lrv-lua_upvalueindex|). The first value associated -with a function is at position$lua_upvalueindex(1)$, and so on. Any access to -$lua_upvalueindex($@n@$)$, where@n@is greater than the number of upvalues of -the current function, produces an acceptable (but invalid) index. - - -============================================================================== -3.5 Registry *lrv-registry* *lrv-apiRegistry* - - -Lua provides a@registry@, a pre-defined table that can be used by any -C code to store whatever Lua value it needs to store. This table is always -located at pseudo-index$LUA_REGISTRYINDEX$. Any C library can store data into -this table, but it should take care to choose keys different from those used -by other libraries, to avoid collisions. Typically, you should use as key a -string containing your library name or a light userdata with the address of a -C object in your code. - -The integer keys in the registry are used by the reference mechanism, -implemented by the auxiliary library, and therefore should not be used for -other purposes. - - -============================================================================== -3.6 Error Handling in C *lrv-apiError* - - -Internally, Lua uses the C$longjmp$facility to handle errors. (You can also -choose to use exceptions if you use C++; see file$luaconf.h$.) When Lua faces -any error (such as memory allocation errors, type errors, syntax errors, and -runtime errors) it@raises@an error; that is, it does a long jump. -A@protected environment@uses$setjmp$to set a recover point; any error jumps to -the most recent active recover point. - -Almost any function in the API may raise an error, for instance due to a -memory allocation error. The following functions run in protected mode (that -is, they create a protected environment to run), so they never raise an error: -$lua_newstate$,$lua_close$,$lua_load$,$lua_pcall$, and$lua_cpcall$(see -|lrv-lua_newstate|, |lrv-lua_close|, |lrv-lua_load|, |lrv-lua_pcall|, and -|lrv-lua_cpcall|). - -Inside a C function you can raise an error by calling$lua_error$ (see -|lrv-lua_error|). - - -============================================================================== -3.7 Functions and Types *lrv-apiFunctions* - - -Here we list all functions and types from the C API in alphabetical order. - - -$lua_Alloc$ *lrv-lua_Alloc* ------------ -> - typedef void * (*lua_Alloc) (void *ud, - void *ptr, - size_t osize, - size_t nsize); -> -The type of the memory-allocation function used by Lua states. The allocator -function must provide a functionality similar to$realloc$, but not exactly the -same. Its arguments are$ud$, an opaque pointer passed to$lua_newstate$ -(see |lrv-lua_newstate|);$ptr$, a pointer to the block being -allocated/reallocated/freed;$osize$, the original size of the block; -$nsize$, the new size of the block.$ptr$is$NULL$if and only if$osize$is zero. -When$nsize$is zero, the allocator must return$NULL$; if$osize$is not zero, -it should free the block pointed to by$ptr$. When$nsize$is not zero, the -allocator returns$NULL$if and only if it cannot fill the request. -When$nsize$is not zero and$osize$is zero, the allocator should behave -like$malloc$. When$nsize$and$osize$are not zero, the allocator behaves like -$realloc$. Lua assumes that the allocator never fails when$osize >= nsize$. - -Here is a simple implementation for the allocator function. It is used in the -auxiliary library by$luaL_newstate$(see |lrv-luaL_newstate|). -> - static void *l_alloc (void *ud, void *ptr, size_t osize, - size_t nsize) { - (void)ud; (void)osize; /* not used */ - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); - } -> -This code assumes that$free(NULL)$has no effect and that -$realloc(NULL, size)$is equivalent to$malloc(size)$. ANSI C ensures both -behaviors. - - -$lua_atpanic$ *lrv-lua_atpanic* -------------- -> - lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); -> -Sets a new panic function and returns the old one. - -If an error happens outside any protected environment, Lua calls a@panic@ -@function@and then calls$exit(EXIT_FAILURE)$, thus exiting the host -application. Your panic function may avoid this exit by never returning (e.g., -doing a long jump). - -The panic function can access the error message at the top of the stack. - - -$lua_call$ *lrv-lua_call* ----------- -> - void lua_call (lua_State *L, int nargs, int nresults); -> -Calls a function. - -To call a function you must use the following protocol: first, the function to -be called is pushed onto the stack; then, the arguments to the function are -pushed in direct order; that is, the first argument is pushed first. Finally -you call$lua_call$;$nargs$is the number of arguments that you pushed onto the -stack. All arguments and the function value are popped from the stack when the -function is called. The function results are pushed onto the stack when the -function returns. The number of results is adjusted to$nresults$, unless -$nresults$is$LUA_MULTRET$. In this case,@all@results from the function are -pushed. Lua takes care that the returned values fit into the stack space. The -function results are pushed onto the stack in direct order (the first result -is pushed first), so that after the call the last result is on the top of the -stack. - -Any error inside the called function is propagated upwards (with a$longjmp$). - -The following example shows how the host program may do the equivalent to this -Lua code: -> - a = f("how", t.x, 14) -> -Here it is in C: -> - lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* function to be called */ - lua_pushstring(L, "how"); /* 1st argument */ - lua_getfield(L, LUA_GLOBALSINDEX, "t"); /* table to be indexed */ - lua_getfield(L, -1, "x"); /* push result of t.x (2nd arg) */ - lua_remove(L, -2); /* remove 't' from the stack */ - lua_pushinteger(L, 14); /* 3rd argument */ - lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */ - lua_setfield(L, LUA_GLOBALSINDEX, "a"); /* set global 'a' */ -> -Note that the code above is "balanced": at its end, the stack is back to its -original configuration. This is considered good programming practice. - - -$lua_CFunction$ *lrv-cfunction* *lrv-lua_CFunction* ---------------- -> - typedef int (*lua_CFunction) (lua_State *L); -> -Type for C functions. - -In order to communicate properly with Lua, a C function must use the following -protocol, which defines the way parameters and results are passed: a C -function receives its arguments from Lua in its stack in direct order (the -first argument is pushed first). So, when the function starts,$lua_gettop(L)$ -(see |lrv-lua_gettop|) returns the number of arguments received by the -function. The first argument (if any) is at index 1 and its last argument is -at index$lua_gettop(L)$. To return values to Lua, a C function just pushes -them onto the stack, in direct order (the first result is pushed first), and -returns the number of results. Any other value in the stack below the results -will be properly discarded by Lua. Like a Lua function, a C function called by -Lua can also return many results. - - *lrv-cfunctionexample* -As an example, the following function receives a variable number of numerical -arguments and returns their average and sum: -> - static int foo (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number sum = 0; - int i; - for (i = 1; i <= n; i++) { - if (!lua_isnumber(L, i)) { - lua_pushstring(L, "incorrect argument"); - lua_error(L); - } - sum += lua_tonumber(L, i); - } - lua_pushnumber(L, sum/n); /* first result */ - lua_pushnumber(L, sum); /* second result */ - return 2; /* number of results */ - } -> - -$lua_checkstack$ *lrv-lua_checkstack* ----------------- -> - int lua_checkstack (lua_State *L, int extra); -> -Ensures that there are at least$extra$free stack slots in the stack. It -returns false if it cannot grow the stack to that size. This function never -shrinks the stack; if the stack is already larger than the new size, it is -left unchanged. - - -$lua_close$ *lrv-lua_close* ------------ -> - void lua_close (lua_State *L); -> -Destroys all objects in the given Lua state (calling the corresponding -garbage-collection metamethods, if any) and frees all dynamic memory used by -this state. On several platforms, you may not need to call this function, -because all resources are naturally released when the host program ends. On -the other hand, long-running programs, such as a daemon or a web server, might -need to release states as soon as they are not needed, to avoid growing too -large. - - -$lua_concat$ *lrv-lua_concat* ------------- -> - void lua_concat (lua_State *L, int n); -> -Concatenates the$n$values at the top of the stack, pops them, and leaves the -result at the top. If$n$is 1, the result is the single string on the stack -(that is, the function does nothing); if$n$is 0, the result is the empty -string. Concatenation is done following the usual semantics of Lua (see -|lrv-langConcat|). - - -$lua_cpcall$ *lrv-lua_cpcall* ------------- -> - int lua_cpcall (lua_State *L, lua_CFunction func, void *ud); -> -Calls the C function$func$in protected mode.$func$starts with only one element -in its stack, a light userdata containing$ud$. In case of errors, -$lua_cpcall$returns the same error codes as$lua_pcall$(see |lrv-lua_pcall|), -plus the error object on the top of the stack; otherwise, it returns zero, and -does not change the stack. All values returned by$func$are discarded. - - -$lua_createtable$ *lrv-lua_createtable* ------------------ -> - void lua_createtable (lua_State *L, int narr, int nrec); -> -Creates a new empty table and pushes it onto the stack. The new table has -space pre-allocated for$narr$array elements and$nrec$non-array elements. This -pre-allocation is useful when you know exactly how many elements the table -will have. Otherwise you can use the function$lua_newtable$ (see -|lrv-lua_newtable|). - - -$lua_dump$ *lrv-lua_dump* ----------- -> - int lua_dump (lua_State *L, lua_Writer writer, void *data); -> -Dumps a function as a binary chunk. Receives a Lua function on the top of the -stack and produces a binary chunk that, if loaded again, results in a function -equivalent to the one dumped. As it produces parts of the chunk,$lua_dump$ -calls function$writer$(see |lrv-lua_Writer|) with the given$data$to write -them. - -The value returned is the error code returned by the last call to the writer; -0 means no errors. - -This function does not pop the Lua function from the stack. - - -$lua_equal$ *lrv-lua_equal* ------------ -> - int lua_equal (lua_State *L, int index1, int index2); -> -Returns 1 if the two values in acceptable indices$index1$and$index2$are equal, -following the semantics of the Lua$==$operator (that is, may call -metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non -valid. - - -$lua_error$ *lrv-lua_error* ------------ -> - int lua_error (lua_State *L); -> -Generates a Lua error. The error message (which can actually be a Lua value of -any type) must be on the stack top. This function does a long jump, and -therefore never returns (see |lrv-luaL_error|). - - -$lua_gc$ *lrv-lua_gc* --------- -> - int lua_gc (lua_State *L, int what, int data); -> -Controls the garbage collector. - -This function performs several tasks, according to the value of the parameter -$what$: - - #o#$LUA_GCSTOP$: stops the garbage collector. - #o#$LUA_GCRESTART$: restarts the garbage collector. - #o#$LUA_GCCOLLECT$: performs a full garbage-collection cycle. - #o#$LUA_GCCOUNT$: returns the current amount of memory (in Kbytes) in use by - Lua. - #o#$LUA_GCCOUNTB$: returns the remainder of dividing the current amount of - bytes of memory in use by Lua by 1024. - #o#$LUA_GCSTEP$: performs an incremental step of garbage collection. The - step "size" is controlled by$data$(larger values mean more steps) in a - non-specified way. If you want to control the step size you must - experimentally tune the value of$data$. The function returns 1 if the - step finished a garbage-collection cycle. - #o#$LUA_GCSETPAUSE$: sets$data$/100 as the new value for the@pause@of the - collector (see |lrv-langGC|). The function returns the previous value of - the pause. - #o#$LUA_GCSETSTEPMUL$: sets$data$/100 as the new value for the@step@ - @multiplier@ of the collector (see |lrv-langGC|). The function returns - the previous value of the step multiplier. - - -$lua_getallocf$ *lrv-lua_getallocf* ---------------- -> - lua_Alloc lua_getallocf (lua_State *L, void **ud); -> -Returns the memory-allocation function of a given state. If$ud$is not$NULL$, -Lua stores in$*ud$the opaque pointer passed to$lua_newstate$(see -|lrv-lua_newstate|). - - -$lua_getfenv$ *lrv-lua_getfenv* -------------- -> - void lua_getfenv (lua_State *L, int index); -> -Pushes onto the stack the environment table of the value at the given index. - - -$lua_getfield$ *lrv-lua_getfield* --------------- -> - void lua_getfield (lua_State *L, int index, const char *k); -> -Pushes onto the stack the value$t[k]$, where$t$is the value at the given valid -index$index$. As in Lua, this function may trigger a metamethod for the -"index" event (see |lrv-langMetatables|). - - -$lua_getglobal$ *lrv-lua_getglobal* ---------------- -> - void lua_getglobal (lua_State *L, const char *name); -> -Pushes onto the stack the value of the global$name$. It is defined as a macro: -> - #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s) -> - -$lua_getmetatable$ *lrv-lua_getmetatable* ------------------- -> - int lua_getmetatable (lua_State *L, int index); -> -Pushes onto the stack the metatable of the value at the given acceptable -index. If the index is not valid, or if the value does not have a metatable, -the function returns 0 and pushes nothing on the stack. - - -$lua_gettable$ *lrv-lua_gettable* --------------- -> - void lua_gettable (lua_State *L, int index); -> -Pushes onto the stack the value$t[k]$, where$t$is the value at the given valid -index$index$and$k$is the value at the top of the stack. - -This function pops the key from the stack (putting the resulting value in its -place). As in Lua, this function may trigger a metamethod for the "index" -event (see |lrv-langMetatables|). - - -$lua_gettop$ *lrv-lua_gettop* ------------- -> - int lua_gettop (lua_State *L); -> -Returns the index of the top element in the stack. Because indices start -at 1, this result is equal to the number of elements in the stack (and so -0 means an empty stack). - - -$lua_insert$ *lrv-lua_insert* ------------- -> - void lua_insert (lua_State *L, int index); -> -Moves the top element into the given valid index, shifting up the elements -above this index to open space. Cannot be called with a pseudo-index, because -a pseudo-index is not an actual stack position. - - -$lua_Integer$ *lrv-lua_Integer* -------------- -> - typedef ptrdiff_t lua_Integer; -> -The type used by the Lua API to represent integral values. - -By default it is a$ptrdiff_t$, which is usually the largest integral type the -machine handles "comfortably". - - -$lua_isboolean$ *lrv-lua_isboolean* ---------------- -> - int lua_isboolean (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index has type boolean, and -0 otherwise. - - -$lua_iscfunction$ *lrv-lua_iscfunction* ------------------ -> - int lua_iscfunction (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is a C function, and -0 otherwise. - - -$lua_isfunction$ *lrv-lua_isfunction* ----------------- -> - int lua_isfunction (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is a function (either -C or Lua), and 0 otherwise. - - -$lua_islightuserdata$ *lrv-lua_islightuserdata* ---------------------- -> - int lua_islightuserdata (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is a light userdata, and -0 otherwise. - - -$lua_isnil$ *lrv-lua_isnil* ------------ -> - int lua_isnil (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is#nil#, and 0 otherwise. - - -$lua_isnumber$ *lrv-lua_isnumber* --------------- -> - int lua_isnumber (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is a number or a string -convertible to a number, and 0 otherwise. - - -$lua_isstring$ *lrv-lua_isstring* --------------- -> - int lua_isstring (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is a string or a number -(which is always convertible to a string), and 0 otherwise. - - -$lua_istable$ *lrv-lua_istable* -------------- -> - int lua_istable (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is a table, and -0 otherwise. - - -$lua_isthread$ *lrv-lua_isthread* --------------- -> - int lua_isthread (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is a thread, and -0 otherwise. - - -$lua_isuserdata$ *lrv-lua_isuserdata* ----------------- -> - int lua_isuserdata (lua_State *L, int index); -> -Returns 1 if the value at the given acceptable index is a userdata (either -full or light), and 0 otherwise. - - -$lua_lessthan$ *lrv-lua_lessthan* --------------- -> - int lua_lessthan (lua_State *L, int index1, int index2); -> -Returns 1 if the value at acceptable index$index1$is smaller than the value at -acceptable index$index2$, following the semantics of the Lua$<$operator (that -is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the -indices is non valid. - - -$lua_load$ *lrv-lua_load* ----------- -> - int lua_load (lua_State *L, - lua_Reader reader, - void *data, - const char *chunkname); -> -Loads a Lua chunk. If there are no errors,$lua_load$pushes the compiled chunk -as a Lua function on top of the stack. Otherwise, it pushes an error message. -The return values of$lua_load$are: - - #o##0#: no errors; - #o#$LUA_ERRSYNTAX$: syntax error during pre-compilation; - #o#$LUA_ERRMEM$: memory allocation error. - -This function only loads a chunk; it does not run it. - -$lua_load$automatically detects whether the chunk is text or binary, and loads -it accordingly (see program$luac$, |lrv-luac|). - -The$lua_load$function uses a user-supplied$reader$function to read the chunk -(see |lrv-lua_Reader|). The$data$argument is an opaque value passed to the -reader function. - -The$chunkname$argument gives a name to the chunk, which is used for error -messages and in debug information (see |lrv-apiDebug|). - - -$lua_newstate$ *lrv-lua_newstate* --------------- -> - lua_State *lua_newstate (lua_Alloc f, void *ud); -> -Creates a new, independent state. Returns$NULL$if cannot create the state (due -to lack of memory). The argument$f$is the allocator function; Lua does all -memory allocation for this state through this function. The second argument, -$ud$, is an opaque pointer that Lua simply passes to the allocator in every -call. - - -$lua_newtable$ *lrv-lua_newtable* --------------- -> - void lua_newtable (lua_State *L); -> -Creates a new empty table and pushes it onto the stack. It is equivalent to -$lua_createtable(L, 0, 0)$(see |lrv-lua_createtable|). - - -$lua_newthread$ *lrv-lua_newthread* ---------------- -> - lua_State *lua_newthread (lua_State *L); -> -Creates a new thread, pushes it on the stack, and returns a pointer to a -$lua_State$ (see |lrv-lua_State|) that represents this new thread. The new -state returned by this function shares with the original state all global -objects (such as tables), but has an independent execution stack. - -There is no explicit function to close or to destroy a thread. Threads are -subject to garbage collection, like any Lua object. - - -$lua_newuserdata$ *lrv-lua_newuserdata* ------------------ -> - void *lua_newuserdata (lua_State *L, size_t size); -> -This function allocates a new block of memory with the given size, pushes onto -the stack a new full userdata with the block address, and returns this -address. - - *lrv-userdata* -Userdata represents C values in Lua. A@full userdata@represents a block of -memory. It is an object (like a table): you must create it, it can have its -own metatable, and you can detect when it is being collected. A full userdata -is only equal to itself (under raw equality). - -When Lua collects a full userdata with a$gc$metamethod, Lua calls the -metamethod and marks the userdata as finalized. When this userdata is -collected again then Lua frees its corresponding memory. - - -$lua_next$ *lrv-lua_next* ----------- -> - int lua_next (lua_State *L, int index); -> -Pops a key from the stack, and pushes a key-value pair from the table at the -given index (the "next" pair after the given key). If there are no more -elements in the table, then$lua_next$returns 0 (and pushes nothing). - - *lrv-tabletraversal* -A typical traversal looks like this: -> - /* table is in the stack at index 't' */ - lua_pushnil(L); /* first key */ - while (lua_next(L, t) != 0) { - /* uses 'key' (at index -2) and 'value' (at index -1) */ - printf("%s - %s\n", - lua_typename(L, lua_type(L, -2)), - lua_typename(L, lua_type(L, -1))); - /* removes 'value'; keeps 'key' for next iteration */ - lua_pop(L, 1); - } -> -While traversing a table, do not call$lua_tolstring$(see |lrv-lua_tolstring|) -directly on a key, unless you know that the key is actually a string. Recall -that$lua_tolstring$@changes@the value at the given index; this confuses the -next call to$lua_next$. - - -$lua_Number$ *lrv-lua_Number* ------------- -> - typedef double lua_Number; -> -The type of numbers in Lua. By default, it is double, but that can be changed -in$luaconf.h$. - -Through the configuration file you can change Lua to operate with another type -for numbers (e.g., float or long). - - -$lua_objlen$ *lrv-lua_objlen* ------------- -> - size_t lua_objlen (lua_State *L, int index); -> -Returns the "length" of the value at the given acceptable index: for strings, -this is the string length; for tables, this is the result of the length -operator ($'#'$); for userdata, this is the size of the block of memory -allocated for the userdata; for other values, it is 0. - - -$lua_pcall$ *lrv-lua_pcall* ------------ -> - lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); -> -Calls a function in protected mode. - -Both$nargs$and$nresults$have the same meaning as in$lua_call$(see -|lrv-lua_call|). If there are no errors during the call,$lua_pcall$behaves -exactly like $lua_call$. However, if there is any error,$lua_pcall$catches it, -pushes a single value on the stack (the error message), and returns an error -code. Like $lua_call$,$lua_pcall$always removes the function and its arguments -from the stack. - -If$errfunc$is 0, then the error message returned on the stack is exactly the -original error message. Otherwise,$errfunc$is the stack index of an@error@ -@handler function@. (In the current implementation, this index cannot be a -pseudo-index.) In case of runtime errors, this function will be called with -the error message and its return value will be the message returned on the -stack by$lua_pcall$. - -Typically, the error handler function is used to add more debug information to -the error message, such as a stack traceback. Such information cannot be -gathered after the return of$lua_pcall$, since by then the stack has unwound. - -The$lua_pcall$function returns 0 in case of success or one of the following -error codes (defined in$lua.h$): - - #o#$LUA_ERRRUN$: a runtime error. - #o#$LUA_ERRMEM$: memory allocation error. For such errors, Lua does not call - the error handler function. - #o#$LUA_ERRERR$: error while running the error handler function. - - -$lua_pop$ *lrv-lua_pop* ---------- -> - void lua_pop (lua_State *L, int n); -> -Pops$n$elements from the stack. - - -$lua_pushboolean$ *lrv-lua_pushboolean* ------------------ -> - void lua_pushboolean (lua_State *L, int b); -> -Pushes a boolean value with value$b$onto the stack. - - -$lua_pushcclosure$ *lrv-lua_pushcclosure* ------------------- -> - void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); -> -Pushes a new C closure onto the stack. - -When a C function is created, it is possible to associate some values with it, -thus creating a C closure (see |lrv-apiCClosures|); these values are then -accessible to the function whenever it is called. To associate values with a -C function, first these values should be pushed onto the stack (when there are -multiple values, the first value is pushed first). Then$lua_pushcclosure$is -called to create and push the C function onto the stack, with the argument -$n$telling how many values should be associated with the function. -$lua_pushcclosure$also pops these values from the stack. - - -$lua_pushcfunction$ *lrv-lua_pushcfunction* -------------------- -> - void lua_pushcfunction (lua_State *L, lua_CFunction f); -> -Pushes a C function onto the stack. This function receives a pointer to a C -function and pushes onto the stack a Lua value of type$function$that, when -called, invokes the corresponding C function. - -Any function to be registered in Lua must follow the correct protocol to -receive its parameters and return its results (see |lrv-lua_CFunction|). - -$lua_pushcfunction$is defined as a macro: -> - #define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0) -> - -$lua_pushfstring$ *lrv-lua_pushfstring* ------------------ -> - const char *lua_pushfstring (lua_State *L, const char *fmt, ...); -> -Pushes onto the stack a formatted string and returns a pointer to this string. -It is similar to the C function$sprintf$, but has some important differences: - - #o# You do not have to allocate space for the result: the result is a Lua - string and Lua takes care of memory allocation (and deallocation, - through garbage collection). - #o# The conversion specifiers are quite restricted. There are no flags, - widths, or precisions. The conversion specifiers can only be$'%%'$ - (inserts a$'%'$in the string),$'%s'$(inserts a zero-terminated string, - with no size restrictions),$'%f'$(inserts a$lua_Number$),$'%p'$(inserts - a pointer as a hexadecimal numeral),$'%d'$(inserts an$int$), and$'%c'$ - (inserts an$int$as a character). - - -$lua_pushinteger$ *lrv-lua_pushinteger* ------------------ -> - void lua_pushinteger (lua_State *L, lua_Integer n); -> -Pushes a number with value$n$onto the stack. - - -$lua_pushlightuserdata$ *lrv-lua_pushlightuserdata* ------------------------ -> - void lua_pushlightuserdata (lua_State *L, void *p); -> -Pushes a light userdata onto the stack. - - *lrv-lightuserdata* -Userdata represents C values in Lua. A@light userdata@represents a pointer. It -is a value (like a number): you do not create it, it has no individual -metatable, and it is not collected (as it was never created). A light userdata -is equal to "any" light userdata with the same C address. - - -$lua_pushlstring$ *lrv-lua_pushlstring* ------------------ -> - void lua_pushlstring (lua_State *L, const char *s, size_t len); -> -Pushes the string pointed to by$s$with size$len$onto the stack. Lua makes (or -reuses) an internal copy of the given string, so the memory at$s$can be freed -or reused immediately after the function returns. The string can contain -embedded zeros. - - -$lua_pushnil$ *lrv-lua_pushnil* -------------- -> - void lua_pushnil (lua_State *L); -> -Pushes a nil value onto the stack. - - -$lua_pushnumber$ *lrv-lua_pushnumber* ----------------- -> - void lua_pushnumber (lua_State *L, lua_Number n); -> -Pushes a number with value$n$onto the stack. - - -$lua_pushstring$ *lrv-lua_pushstring* ----------------- -> - void lua_pushstring (lua_State *L, const char *s); -> -Pushes the zero-terminated string pointed to by$s$onto the stack. Lua makes -(or reuses) an internal copy of the given string, so the memory at$s$can be -freed or reused immediately after the function returns. The string cannot -contain embedded zeros; it is assumed to end at the first zero. - - -$lua_pushthread$ *lrv-lua_pushthread* ----------------- -> - int lua_pushthread (lua_State *L); -> -Pushes the thread represented by$L$onto the stack. Returns 1 if this thread is -the main thread of its state. - - -$lua_pushvalue$ *lrv-lua_pushvalue* ---------------- -> - void lua_pushvalue (lua_State *L, int index); -> -Pushes a copy of the element at the given valid index onto the stack. - - -$lua_pushvfstring$ *lrv-lua_pushvfstring* ------------------- -> - const char *lua_pushvfstring (lua_State *L, - const char *fmt, - va_list argp); -> -Equivalent to$lua_pushfstring$(see |lrv-pushfstring|), except that it -receives a$va_list$instead of a variable number of arguments. - - -$lua_rawequal$ *lrv-lua_rawequal* --------------- -> - int lua_rawequal (lua_State *L, int index1, int index2); -> -Returns 1 if the two values in acceptable indices$index1$and$index2$are -primitively equal (that is, without calling metamethods). Otherwise -returns 0. Also returns 0 if any of the indices are non valid. - - -$lua_rawget$ *lrv-lua_rawget* ------------- -> - void lua_rawget (lua_State *L, int index); -> -Similar to$lua_gettable$(see |lrv-lua_gettable|), but does a raw access -(i.e., without metamethods). - - -$lua_rawgeti$ *lrv-lua_rawgeti* -------------- -> - void lua_rawgeti (lua_State *L, int index, int n); -> -Pushes onto the stack the value$t[n]$, where$t$is the value at the given valid -index$index$. The access is raw; that is, it does not invoke metamethods. - - -$lua_rawset$ *lrv-lua_rawset* ------------- -> - void lua_rawset (lua_State *L, int index); -> -Similar to$lua_settable$(see |lrv-lua_settable|), but does a raw assignment -(i.e., without metamethods). - - -$lua_rawseti$ *lrv-lua_rawseti* -------------- -> - void lua_rawseti (lua_State *L, int index, int n); -> -Does the equivalent of$t[n] = v$, where$t$is the value at the given valid -index$index$and$v$is the value at the top of the stack. - -This function pops the value from the stack. The assignment is raw; that is, -it does not invoke metamethods. - - -$lua_Reader$ *lrv-lua_Reader* ------------- -> - typedef const char * (*lua_Reader) (lua_State *L, - void *data, - size_t *size); -> -The reader function used by$lua_load$(see |lrv-lua_load|). Every time it needs -another piece of the chunk,$lua_load$calls the reader, passing along its$data$ -parameter. The reader must return a pointer to a block of memory with a new -piece of the chunk and set$size$to the block size. The block must exist until -the reader function is called again. To signal the end of the chunk, the -reader must return$NULL$. The reader function may return pieces of any size -greater than zero. - - -$lua_register$ *lrv-lua_register* --------------- -> - void lua_register (lua_State *L, - const char *name, - lua_CFunction f); -> -Sets the C function$f$as the new value of global$name$. It is defined as a -macro: -> - #define lua_register(L,n,f) \ - (lua_pushcfunction(L, f), lua_setglobal(L, n)) -> - -$lua_remove$ *lrv-lua_remove* ------------- -> - void lua_remove (lua_State *L, int index); -> -Removes the element at the given valid index, shifting down the elements above -this index to fill the gap. Cannot be called with a pseudo-index, because a -pseudo-index is not an actual stack position. - - -$lua_replace$ *lrv-lua_replace* -------------- -> - void lua_replace (lua_State *L, int index); -> -Moves the top element into the given position (and pops it), without shifting -any element (therefore replacing the value at the given position). - - -$lua_resume$ *lrv-lua_resume* ------------- -> - int lua_resume (lua_State *L, int narg); -> -Starts and resumes a coroutine in a given thread. - -To start a coroutine, you first create a new thread (see |lrv-lua_newthread|); -then you push onto its stack the main function plus any arguments; then you -call$lua_resume$(see |lrv-lua_resume|) with$narg$being the number of -arguments. This call returns when the coroutine suspends or finishes its -execution. When it returns, the stack contains all values passed to$lua_yield$ -(see |lrv-lua_yield|), or all values returned by the body function. -$lua_resume$returns$LUA_YIELD$if the coroutine yields, 0 if the coroutine -finishes its execution without errors, or an error code in case of errors (see -|lrv-lua_pcall|). In case of errors, the stack is not unwound, so you can use -the debug API over it. The error message is on the top of the stack. To -restart a coroutine, you put on its stack only the values to be passed as -results from$lua_yield$, and then call$lua_resume$. - - -$lua_setallocf$ *lrv-lua_setallocf* ---------------- -> - void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); -> -Changes the allocator function of a given state to$f$with user data$ud$. - - -$lua_setfenv$ *lrv-lua_setfenv* -------------- -> - int lua_setfenv (lua_State *L, int index); -> -Pops a table from the stack and sets it as the new environment for the value -at the given index. If the value at the given index is neither a function nor -a thread nor a userdata,$lua_setfenv$returns 0. Otherwise it returns 1. - - -$lua_setfield$ *lrv-lua_setfield* --------------- -> - void lua_setfield (lua_State *L, int index, const char *k); -> -Does the equivalent to$t[k] = v$, where$t$is the value at the given valid -index$index$and$v$is the value at the top of the stack. - -This function pops the value from the stack. As in Lua, this function may -trigger a metamethod for the "newindex" event (see |lrv-langMetatables|). - - -$lua_setglobal$ *lrv-lua_setglobal* ---------------- -> - void lua_setglobal (lua_State *L, const char *name); -> -Pops a value from the stack and sets it as the new value of global$name$. -It is defined as a macro: -> - #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, s) -> - -$lua_setmetatable$ *lrv-lua_setmetatable* ------------------- -> - int lua_setmetatable (lua_State *L, int index); -> -Pops a table from the stack and sets it as the new metatable for the value at -the given acceptable index. - - -$lua_settable$ *lrv-lua_settable* --------------- -> - void lua_settable (lua_State *L, int index); -> -Does the equivalent to$t[k] = v$, where$t$is the value at the given valid -index$index$,$v$is the value at the top of the stack, and$k$is the value just -below the top. - -This function pops both the key and the value from the stack. As in Lua, this -function may trigger a metamethod for the "newindex" event (see -|lrv-langMetatables|). - - -$lua_settop$ *lrv-lua_settop* ------------- -> - void lua_settop (lua_State *L, int index); -> -Accepts any acceptable index, or 0, and sets the stack top to this index. If -the new top is larger than the old one, then the new elements are filled with -#nil#. If$index$is 0, then all stack elements are removed. - - -$lua_State$ *lrv-lua_State* ------------ -> - typedef struct lua_State lua_State; -> -Opaque structure that keeps the whole state of a Lua interpreter. The Lua -library is fully reentrant: it has no global variables. All information about -a state is kept in this structure. - -A pointer to this state must be passed as the first argument to every function -in the library, except to$lua_newstate$(see |lrv-lua_newstate|), which -creates a Lua state from scratch. - - -$lua_status$ *lrv-lua_status* ------------- -> - int lua_status (lua_State *L); -> -Returns the status of the thread$L$. - -The status can be 0 for a normal thread, an error code if the thread finished -its execution with an error, or$LUA_YIELD$if the thread is suspended. - - -$lua_toboolean$ *lrv-lua_toboolean* ---------------- -> - int lua_toboolean (lua_State *L, int index); -> -Converts the Lua value at the given acceptable index to a C boolean value -(0 or 1). Like all tests in Lua,$lua_toboolean$returns 1 for any Lua value -different from#false#and#nil#; otherwise it returns 0. It also returns 0 when -called with a non-valid index. (If you want to accept only actual boolean -values, use$lua_isboolean$|lrv-lua_isboolean| to test the value's type.) - - -$lua_tocfunction$ *lrv-lua_tocfunction* ------------------ -> - lua_CFunction lua_tocfunction (lua_State *L, int index); -> -Converts a value at the given acceptable index to a C function. That value -must be a C function; otherwise it returns$NULL$. - - -$lua_tointeger$ *lrv-lua_tointeger* ---------------- -> - lua_Integer lua_tointeger (lua_State *L, int idx); -> -Converts the Lua value at the given acceptable index to the signed integral -type$lua_Integer$(see |lrv-lua_Integer|). The Lua value must be a number or a -string convertible to a number (see |lrv-langCoercion|); otherwise, -$lua_tointeger$returns 0. - -If the number is not an integer, it is truncated in some non-specified way. - - -$lua_tolstring$ *lrv-lua_tolstring* ---------------- -> - const char *lua_tolstring (lua_State *L, int index, size_t *len); -> -Converts the Lua value at the given acceptable index to a C string. If$len$is -not$NULL$, it also sets$*len$with the string length. The Lua value must be a -string or a number; otherwise, the function returns$NULL$. If the value is a -number, then$lua_tolstring$ also@changes the actual value in the stack to a@ -@string@. (This change confuses$lua_next$|lrv-lua_next| when$lua_tolstring$is -applied to keys during a table traversal.) - -$lua_tolstring$returns a fully aligned pointer to a string inside the Lua -state. This string always has a zero ($'\0'$) after its last character (as -in C), but may contain other zeros in its body. Because Lua has garbage -collection, there is no guarantee that the pointer returned by$lua_tolstring$ -will be valid after the corresponding value is removed from the stack. - - -$lua_tonumber$ *lrv-lua_tonumber* --------------- -> - lua_Number lua_tonumber (lua_State *L, int index); -> -Converts the Lua value at the given acceptable index to the C type$lua_Number$ -(see |lrv-lua_Number|). The Lua value must be a number or a string convertible -to a number (see |lrv-langCoercion|); otherwise,$lua_tonumber$returns 0. - - -$lua_topointer$ *lrv-lua_topointer* ---------------- -> - const void *lua_topointer (lua_State *L, int index); -> -Converts the value at the given acceptable index to a generic C pointer -($void*$). The value may be a userdata, a table, a thread, or a function; -otherwise,$lua_topointer$returns$NULL$. Different objects will give different -pointers. There is no way to convert the pointer back to its original value. - -Typically this function is used only for debug information. - - -$lua_tostring$ *lrv-lua_tostring* --------------- -> - const char *lua_tostring (lua_State *L, int index); -> -Equivalent to$lua_tolstring$(see |lrv-lua_tolstring|) with$len$equal to$NULL$. - - -$lua_tothread$ *lrv-lua_tothread* --------------- -> - lua_State *lua_tothread (lua_State *L, int index); -> -Converts the value at the given acceptable index to a Lua thread (represented -as$lua_State*$|lrv-lua_State|). This value must be a thread; otherwise, the -function returns$NULL$. - - -$lua_touserdata$ *lrv-lua_touserdata* ----------------- -> - void *lua_touserdata (lua_State *L, int index); -> -If the value at the given acceptable index is a full userdata, returns its -block address. If the value is a light userdata, returns its pointer. -Otherwise, it returns$NULL$. - - -$lua_type$ *lrv-lua_type* ----------- -> - int lua_type (lua_State *L, int index); -> -Returns the type of the value in the given acceptable index, or$LUA_TNONE$for -a non-valid index (that is, an index to an "empty" stack position). The types -returned by$lua_type$are coded by the following constants defined in$lua.h$: -$LUA_TNIL$,$LUA_TNUMBER$,$LUA_TBOOLEAN$,$LUA_TSTRING$,$LUA_TTABLE$, -$LUA_TFUNCTION$,$LUA_TUSERDATA$,$LUA_TTHREAD$, and$LUA_TLIGHTUSERDATA$. - - -$lua_typename$ *lrv-lua_typename* --------------- -> - const char *lua_typename (lua_State *L, int tp); -> -Returns the name of the type encoded by the value$tp$, which must be one the -values returned by$lua_type$. - - -$lua_Writer$ *lrv-lua_Writer* ------------- -> - typedef int (*lua_Writer) (lua_State *L, - const void* p, - size_t sz, - void* ud); -> -The writer function used by$lua_dump$(see |lrv-lua_dump|). Every time it -produces another piece of chunk,$lua_dump$calls the writer, passing along the -buffer to be written ($p$), its size ($sz$), and the$data$parameter supplied -to$lua_dump$. - -The writer returns an error code: 0 means no errors; any other value means an -error and stops$lua_dump$from calling the writer again. - - -$lua_xmove$ *lrv-lua_xmove* ------------ -> - void lua_xmove (lua_State *from, lua_State *to, int n); -> -Exchange values between different threads of the@same@global state. - -This function pops$n$values from the stack$from$, and pushes them onto the -stack$to$. - - -$lua_yield$ *lrv-lua_yield* ------------ -> - int lua_yield (lua_State *L, int nresults); -> -Yields a coroutine. - -This function should only be called as the return expression of a C function, -as follows: -> - return lua_yield (L, nresults); -> -When a C function calls$lua_yield$in that way, the running coroutine suspends -its execution, and the call to$lua_resume$(see |lrv-lua_resume|) that started -this coroutine returns. The parameter$nresults$is the number of values from -the stack that are passed as results to$lua_resume$. - - - *lrv-stackexample* -As an example of stack manipulation, if the stack starts as -$10 20 30 40 50*$(from bottom to top; the $'*'$marks the top), then -> - lua_pushvalue(L, 3) --> 10 20 30 40 50 30* - lua_pushvalue(L, -1) --> 10 20 30 40 50 30 30* - lua_remove(L, -3) --> 10 20 30 40 30 30* - lua_remove(L, 6) --> 10 20 30 40 30* - lua_insert(L, 1) --> 30 10 20 30 40* - lua_insert(L, -1) --> 30 10 20 30 40* (no effect) - lua_replace(L, 2) --> 30 40 20 30* - lua_settop(L, -3) --> 30 40* - lua_settop(L, 6) --> 30 40 nil nil nil nil* -> - -============================================================================== -3.8 The Debug Interface *lrv-apiDebug* - - -Lua has no built-in debugging facilities. Instead, it offers a special -interface by means of functions and@hooks@. This interface allows the -construction of different kinds of debuggers, profilers, and other tools that -need "inside information" from the interpreter. - - -$lua_Debug$ *lrv-lua_Debug* ------------ - - $typedef struct lua_Debug {$ - $int event;$ - $const char *name; /* (n) */$ - $const char *namewhat; /* (n) */$ - $const char *what; /* (S) */$ - $const char *source; /* (S) */$ - $int currentline; /* (l) */$ - $int nups; /* (u) number of upvalues */$ - $int linedefined; /* (S) */$ - $int lastlinedefined; /* (S) */$ - $char short_src[LUA_IDSIZE]; /* (S) */$ - $/* private part */$ - @other fields@ - $} lua_Debug;$ - - -A structure used to carry different pieces of information about an active -function.$lua_getstack$(see |lrv-lua_getstack|) fills only the private part -of this structure, for later use. To fill the other fields of$lua_Debug$with -useful information, call$lua_getinfo$(see |lrv-lua_getinfo|). - -The fields of$lua_Debug$ have the following meaning: - - #o#$source$: If the function was defined in a string, then$source$is that - string. If the function was defined in a file, then$source$starts with a - $'@'$followed by the file name. - #o#$short_src$: a "printable" version of$source$, to be used in error - messages. - #o#$linedefined$: the line number where the definition of the function - starts. - #o#$lastlinedefined$: the line number where the definition of the function - ends. - #o#$what$: the string$"Lua"$if the function is a Lua function,$"C"$if it is - a C function,$"main"$if it is the main part of a chunk, and$"tail"$if it - was a function that did a tail call. In the latter case, Lua has no - other information about the function. - #o#$currentline$: the current line where the given function is executing. - When no line information is available,$currentline$is set to -1. - #o#$name$: a reasonable name for the given function. Because functions in - Lua are first-class values, they do not have a fixed name: some - functions may be the value of multiple global variables, while others - may be stored only in a table field. The$lua_getinfo$function checks how - the function was called to find a suitable name. If it cannot find a - name, then$name$is set to$NULL$. - #o#$namewhat$: explains the$name$field. The value of$namewhat$can be - $"global"$,$"local"$,$"method"$,$"field"$,$"upvalue"$, or$""$(the empty - string), according to how the function was called. (Lua uses the empty - string when no other option seems to apply.) - #o#$nups$: the number of upvalues of the function. - - -$lua_gethook$ *lrv-lua_gethook* -------------- -> - lua_Hook lua_gethook (lua_State *L); -> -Returns the current hook function. - - -$lua_gethookcount$ *lrv-lua_gethookcount* ------------------- -> - int lua_gethookcount (lua_State *L); -> -Returns the current hook count. - - -$lua_gethookmask$ *lrv-lua_gethookmask* -> - int lua_gethookmask (lua_State *L); -> -Returns the current hook mask. - - -$lua_getinfo$ *lrv-lua_getinfo* -------------- -> - int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); -> -Returns information about a specific function or function invocation. - -To get information about a function invocation, the parameter$ar$must be a -valid activation record that was filled by a previous call to$lua_getstack$ -(see |lrv-lua_getstack|) or given as argument to a hook (see |lrv-lua_Hook|). - -To get information about a function you push it onto the stack and start the -$what$string with the character $'>'$. (In that case,$lua_getinfo$pops the -function in the top of the stack.) For instance, to know in which line a -function$f$was defined, you can write the following code: -> - lua_Debug ar; - lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* get global 'f' */ - lua_getinfo(L, ">S", &ar); - printf("%d\n", ar.linedefined); -> -Each character in the string$what$selects some fields of the structure$ar$to -be filled or a value to be pushed on the stack: - - #o#$'n'$: fills in the field$name$and$namewhat$; - #o#$'S'$: fills in the fields$source$,$short_src$,$linedefined$, - $lastlinedefined$, and$what$; - #o#$'l'$: fills in the field$currentline$; - #o#$'u'$: fills in the field$nups$; - #o#$'f'$: pushes onto the stack the function that is running at the given - level; - #o#$'L'$: pushes onto the stack a table whose indices are the numbers of the - lines that are valid on the function. (A@valid line@is a line with some - associated code, that is, a line where you can put a break point. - Non-valid lines include empty lines and comments.) - -This function returns 0 on error (for instance, an invalid option in$what$). - - -$lua_getlocal$ *lrv-lua_getlocal* --------------- -> - const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n); -> -Gets information about a local variable of a given activation record. The -parameter$ar$must be a valid activation record that was filled by a previous -call to$lua_getstack$(see |lrv-lua_getstack|) or given as argument to a hook -(see |lrv-lua_Hook|). The index$n$selects which local variable to inspect (1 -is the first parameter or active local variable, and so on, until the last -active local variable).$lua_getlocal$pushes the variable's value onto the -stack and returns its name. - -Variable names starting with$'('$(open parentheses) represent internal -variables (loop control variables, temporaries, and C function locals). - -Returns$NULL$(and pushes nothing) when the index is greater than the number of -active local variables. - - -$lua_getstack$ *lrv-lua_getstack* --------------- -> - int lua_getstack (lua_State *L, int level, lua_Debug *ar); -> -Gets information about the interpreter runtime stack. - -This function fills parts of a$lua_Debug$(see |lrv-lua_Debug|) structure with -an identification of the@activation record@of the function executing at a -given level. Level 0 is the current running function, whereas level@n+1@is the -function that has called level@n@. When there are no errors,$lua_getstack$ -returns 1; when called with a level greater than the stack depth, it -returns 0. - - -$lua_getupvalue$ *lrv-lua_getupvalue* ----------------- -> - const char *lua_getupvalue (lua_State *L, int funcindex, int n); -> -Gets information about a closure's upvalue. (For Lua functions, upvalues are -the external local variables that the function uses, and that are consequently -included in its closure.)$lua_getupvalue$gets the index$n$of an upvalue, -pushes the upvalue's value onto the stack, and returns its name.$funcindex$ -points to the closure in the stack. (Upvalues have no particular order, as -they are active through the whole function. So, they are numbered in an -arbitrary order.) - -Returns$NULL$(and pushes nothing) when the index is greater than the number of -upvalues. For C functions, this function uses the empty string$""$as a name -for all upvalues. - - -$lua_Hook$ *lrv-lua_Hook* ----------- -> - typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); -> -Type for debugging hook functions. - - -Whenever a hook is called, its$ar$argument has its field$event$set to the -specific event that triggered the hook. Lua identifies these events with the -following constants:$LUA_HOOKCALL$,$LUA_HOOKRET$,$LUA_HOOKTAILRET$, -$LUA_HOOKLINE$, and$LUA_HOOKCOUNT$. Moreover, for line events, the field -$currentline$is also set. To get the value of any other field in$ar$, the hook -must call$lua_getinfo$(see |lrv-lua_getinfo|). For return events,$event$may be -$LUA_HOOKRET$, the normal value, or$LUA_HOOKTAILRET$. In the latter case, Lua -is simulating a return from a function that did a tail call; in this case, it -is useless to call$lua_getinfo$. - -While Lua is running a hook, it disables other calls to hooks. Therefore, if a -hook calls back Lua to execute a function or a chunk, this execution occurs -without any calls to hooks. - - -$lua_sethook$ *lrv-lua_sethook* -------------- -> - int lua_sethook (lua_State *L, lua_Hook f, int mask, int count); -> -Sets the debugging hook function. - -Argument$f$is the hook function.$mask$specifies on which events the hook will -be called: it is formed by a bitwise@or@of the constants$LUA_MASKCALL$, -$LUA_MASKRET$,$LUA_MASKLINE$, and$LUA_MASKCOUNT$. The$count$argument is only -meaningful when the mask includes$LUA_MASKCOUNT$. For each event, the hook is -called as explained below: - - #o##The call hook#: is called when the interpreter calls a function. The - hook is called just after Lua enters the new function, before the - function gets its arguments. - #o##The return hook#: is called when the interpreter returns from a - function. The hook is called just before Lua leaves the function. You - have no access to the values to be returned by the function. - #o##The line hook#: is called when the interpreter is about to start the - execution of a new line of code, or when it jumps back in the code (even - to the same line). (This event only happens while Lua is executing a Lua - function.) - #o##The count hook#: is called after the interpreter executes every$count$ - instructions. (This event only happens while Lua is executing a Lua - function.) - -A hook is disabled by setting$mask$to zero. - - -$lua_setlocal$ *lrv-lua_setlocal* --------------- -> - const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n); -> -Sets the value of a local variable of a given activation record. Parameters$ar$ -and$n$are as in$lua_getlocal$(see |lrv-lua_getlocal|).$lua_setlocal$assigns -the value at the top of the stack to the variable and returns its name. It -also pops the value from the stack. - -Returns$NULL$(and pops nothing) when the index is greater than the number of -active local variables. - - -$lua_setupvalue$ *lrv-lua_setupvalue* ----------------- -> - const char *lua_setupvalue (lua_State *L, int funcindex, int n); -> -Sets the value of a closure's upvalue. It assigns the value at the top of the -stack to the upvalue and returns its name. It also pops the value from the -stack. Parameters$funcindex$and$n$are as in the$lua_getupvalue$(see -|lrv-lua_getupvalue|). - -Returns$NULL$(and pops nothing) when the index is greater than the number of -upvalues. - - - *lrv-debugexample* -As an example, the following function lists the names of all local variables -and upvalues for a function at a given level of the stack: -> - int listvars (lua_State *L, int level) { - lua_Debug ar; - int i; - const char *name; - if (lua_getstack(L, level, &ar) == 0) - return 0; /* failure: no such level in the stack */ - i = 1; - while ((name = lua_getlocal(L, &ar, i++)) != NULL) { - printf("local %d %s\n", i-1, name); - lua_pop(L, 1); /* remove variable value */ - } - lua_getinfo(L, "f", &ar); /* retrieves function */ - i = 1; - while ((name = lua_getupvalue(L, -1, i++)) != NULL) { - printf("upvalue %d %s\n", i-1, name); - lua_pop(L, 1); /* remove upvalue value */ - } - return 1; - } -> - -============================================================================== -4 THE AUXILIARY LIBRARY *lrv-aux* -============================================================================== - - -The@auxiliary library@provides several convenient functions to interface C -with Lua. While the basic API provides the primitive functions for all -interactions between C and Lua, the auxiliary library provides higher-level -functions for some common tasks. - -All functions from the auxiliary library are defined in header file$lauxlib.h$ -and have a prefix$luaL_$. - -All functions in the auxiliary library are built on top of the basic API, and -so they provide nothing that cannot be done with this API. - -Several functions in the auxiliary library are used to check C function -arguments. Their names are always$luaL_check*$or$luaL_opt*$. All of these -functions raise an error if the check is not satisfied. Because the error -message is formatted for arguments (e.g.,$"bad argument #1"$), you should not -use these functions for other stack values. - - -============================================================================== -4.1 Functions and Types *lrv-auxFunctions* - - -Here we list all functions and types from the auxiliary library in -alphabetical order. - - -$luaL_addchar$ *lrv-luaL_addchar* --------------- -> - void luaL_addchar (luaL_Buffer *B, char c); -> -Adds the character$c$to the buffer$B$(see |lrv-luaL_Buffer|). - - -$luaL_addlstring$ *lrv-luaL_addlstring* ------------------ -> - void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); -> -Adds the string pointed to by$s$with length$l$to the buffer$B$(see -|lrv-luaL_Buffer|). The string may contain embedded zeros. - - -$luaL_addsize$ *lrv-luaL_addsize* --------------- -> - void luaL_addsize (luaL_Buffer *B, size_t n); -> -Adds to the buffer$B$(see |lrv-luaL_Buffer|) a string of length$n$previously -copied to the buffer area (see |lrv-luaL_prepbuffer|). - - -$luaL_addstring$ *lrv-luaL_addstring* ----------------- -> - void luaL_addstring (luaL_Buffer *B, const char *s); -> -Adds the zero-terminated string pointed to by$s$to the buffer$B$(see -|lrv-luaL_Buffer|). The string may not contain embedded zeros. - - -$luaL_addvalue$ *lrv-luaL_addvalue* ---------------- -> - void luaL_addvalue (luaL_Buffer *B); -> -Adds the value at the top of the stack to the buffer$B$(see -|lrv-luaL_Buffer|). Pops the value. - -This is the only function on string buffers that can (and must) be called with -an extra element on the stack, which is the value to be added to the buffer. - - -$luaL_argcheck$ *lrv-luaL_argcheck* ---------------- -> - void luaL_argcheck (lua_State *L, - int cond, - int narg, - const char *extramsg); -> -Checks whether$cond$is true. If not, raises an error with the following -message, where$func$is retrieved from the call stack: -> - bad argument #<narg> to <func> (<extramsg>) -> - -$luaL_argerror$ *lrv-luaL_argerror* ---------------- -> - int luaL_argerror (lua_State *L, int narg, const char *extramsg); -> -Raises an error with the following message, where$func$is retrieved from the -call stack: -> - bad argument #<narg> to <func> (<extramsg>) -> -This function never returns, but it is an idiom to use it in C functions as -$return luaL_argerror($@args@$)$. - - -$luaL_Buffer$ *lrv-luaL_Buffer* -------------- -> - typedef struct luaL_Buffer luaL_Buffer; -> -Type for a@string buffer@. - -A string buffer allows C code to build Lua strings piecemeal. Its pattern of -use is as follows: - - #o# First you declare a variable$b$of type$luaL_Buffer$. - #o# Then you initialize it with a call$luaL_buffinit(L, &b)$(see - |lrv-luaL_buffinit|). - #o# Then you add string pieces to the buffer calling any of the$luaL_add*$ - functions. - #o# You finish by calling$luaL_pushresult(&b)$(see |lrv-luaL_pushresult|). - This call leaves the final string on the top of the stack. - -During its normal operation, a string buffer uses a variable number of stack -slots. So, while using a buffer, you cannot assume that you know where the top -of the stack is. You can use the stack between successive calls to buffer -operations as long as that use is balanced; that is, when you call a buffer -operation, the stack is at the same level it was immediately after the -previous buffer operation. (The only exception to this rule is -$luaL_addvalue$|lrv-luaL_addvalue|.) After calling$luaL_pushresult$the stack -is back to its level when the buffer was initialized, plus the final string on -its top. - - -$luaL_buffinit$ *lrv-luaL_buffinit* ---------------- -> - void luaL_buffinit (lua_State *L, luaL_Buffer *B); -> -Initializes a buffer$B$. This function does not allocate any space; the buffer -must be declared as a variable (see |lrv-luaL_Buffer|). - - -$luaL_callmeta$ *lrv-luaL_callmeta* ---------------- -> - int luaL_callmeta (lua_State *L, int obj, const char *e); -> -Calls a metamethod. - -If the object at index$obj$has a metatable and this metatable has a field$e$, -this function calls this field and passes the object as its only argument. In -this case this function returns 1 and pushes onto the stack the value returned -by the call. If there is no metatable or no metamethod, this function returns -0 (without pushing any value on the stack). - - -$luaL_checkany$ *lrv-luaL_checkany* ---------------- -> - void luaL_checkany (lua_State *L, int narg); -> -Checks whether the function has an argument of any type (including#nil#) at -position$narg$. - - -$luaL_checkint$ *lrv-luaL_checkint* ---------------- -> - int luaL_checkint (lua_State *L, int narg); -> -Checks whether the function argument$narg$is a number and returns this number -cast to an$int$. - - -$luaL_checkinteger$ *lrv-luaL_checkinteger* -------------------- -> - lua_Integer luaL_checkinteger (lua_State *L, int narg); -> -Checks whether the function argument$narg$is a number and returns this number -cast to a$lua_Integer$(see |lrv-lua_Integer|). - - -$luaL_checklong$ *lrv-luaL_checklong* ----------------- -> - long luaL_checklong (lua_State *L, int narg); -> -Checks whether the function argument$narg$is a number and returns this number -cast to a$long$. - - -$luaL_checklstring$ *lrv-luaL_checklstring* -------------------- -> - const char *luaL_checklstring (lua_State *L, int narg, size_t *l); -> -Checks whether the function argument$narg$is a string and returns this string; -if$l$is not$NULL$fills$*l$with the string's length. - - -$luaL_checknumber$ *lrv-luaL_checknumber* ------------------- -> - lua_Number luaL_checknumber (lua_State *L, int narg); -> -Checks whether the function argument$narg$is a number and returns this number -(see |lrv-lua_Number|). - - -$luaL_checkoption$ *lrv-luaL_checkoption* ------------------- -> - int luaL_checkoption (lua_State *L, - int narg, - const char *def, - const char *const lst[]); -> -Checks whether the function argument$narg$is a string and searches for this -string in the array$lst$(which must be NULL-terminated). Returns the index in -the array where the string was found. Raises an error if the argument is not a -string or if the string cannot be found. - -If$def$is not$NULL$, the function uses$def$as a default value when there is no -argument$narg$or if this argument is#nil#. - -This is a useful function for mapping strings to C enums. (The usual -convention in Lua libraries is to use strings instead of numbers to select -options.) - - -$luaL_checkstack$ *lrv-luaL_checkstack* ------------------ -> - void luaL_checkstack (lua_State *L, int sz, const char *msg); -> -Grows the stack size to$top + sz$elements, raising an error if the stack -cannot grow to that size.$msg$is an additional text to go into the error -message. - - -$luaL_checkstring$ *lrv-luaL_checkstring* ------------------- -> - const char *luaL_checkstring (lua_State *L, int narg); -> -Checks whether the function argument$narg$is a string and returns this string. - - -$luaL_checktype$ *lrv-luaL_checktype* ----------------- -> - void luaL_checktype (lua_State *L, int narg, int t); -> -Checks whether the function argument$narg$has type$t$(see |lrv-lua_type|). - - -$luaL_checkudata$ *lrv-luaL_checkudata* ------------------ -> - void *luaL_checkudata (lua_State *L, int narg, const char *tname); -> -Checks whether the function argument$narg$is a userdata of the type$tname$ -(see |lrv-luaL_newmetatable|). - - -$luaL_dofile$ *lrv-luaL_dofile* -------------- -> - int luaL_dofile (lua_State *L, const char *filename); -> -Loads and runs the given file. It is defined as the following macro: -> - (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0)) -> -It returns 0 if there are no errors or 1 in case of errors. - - -$luaL_dostring$ *lrv-luaL_dostring* ---------------- -> - int luaL_dostring (lua_State *L, const char *str); -> -Loads and runs the given string. It is defined as the following macro: -> - (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0)) -> -It returns 0 if there are no errors or 1 in case of errors. - - -$luaL_error$ *lrv-luaL_error* ------------- -> - int luaL_error (lua_State *L, const char *fmt, ...); -> -Raises an error. The error message format is given by$fmt$plus any extra -arguments, following the same rules of$lua_pushfstring$(see -|lrv-lua_pushfstring|). It also adds at the beginning of the message the file -name and the line number where the error occurred, if this information is -available. - -This function never returns, but it is an idiom to use it in C functions as -$return luaL_error($@args@$)$. - - -$luaL_getmetafield$ *lrv-luaL_getmetafield* -------------------- -> - int luaL_getmetafield (lua_State *L, int obj, const char *e); -> -Pushes onto the stack the field$e$from the metatable of the object at index -$obj$. If the object does not have a metatable, or if the metatable does not -have this field, returns 0 and pushes nothing. - - -$luaL_getmetatable$ *lrv-luaL_getmetatable* -------------------- -> - void luaL_getmetatable (lua_State *L, const char *tname); -> -Pushes onto the stack the metatable associated with name$tname$in the registry -(see |lrv-luaL_newmetatable|). - - -$luaL_gsub$ *lrv-luaL_gsub* ------------ -> - const char *luaL_gsub (lua_State *L, - const char *s, - const char *p, - const char *r); -> -Creates a copy of string$s$by replacing any occurrence of the string$p$with -the string$r$. Pushes the resulting string on the stack and returns it. - - -$luaL_loadbuffer$ *lrv-luaL_loadbuffer* ------------------ -> - int luaL_loadbuffer (lua_State *L, - const char *buff, - size_t sz, - const char *name); -> -Loads a buffer as a Lua chunk. This function uses$lua_load$(see -|lrv-lua_load|) to load the chunk in the buffer pointed to by$buff$with size -$sz$. - -This function returns the same results as$lua_load$.$name$is the chunk name, -used for debug information and error messages. - - -$luaL_loadfile$ *lrv-luaL_loadfile* ---------------- -> - int luaL_loadfile (lua_State *L, const char *filename); -> -Loads a file as a Lua chunk. This function uses$lua_load$(see |lrv-lua_load|) -to load the chunk in the file named$filename$. If$filename$is$NULL$, then it -loads from the standard input. The first line in the file is ignored if it -starts with a$#$. - -This function returns the same results as$lua_load$, but it has an extra error -code$LUA_ERRFILE$if it cannot open/read the file. - -As$lua_load$, this function only loads the chunk; it does not run it. - - -$luaL_loadstring$ *lrv-luaL_loadstring* ------------------ -> - int luaL_loadstring (lua_State *L, const char *s); -> -Loads a string as a Lua chunk. This function uses$lua_load$(see -|lrv-lua_load|) to load the chunk in the zero-terminated string$s$. - -This function returns the same results as$lua_load$. - -Also as$lua_load$, this function only loads the chunk; it does not run it. - - -$luaL_newmetatable$ *lrv-luaL_newmetatable* -------------------- -> - int luaL_newmetatable (lua_State *L, const char *tname); -> -If the registry already has the key$tname$, returns 0. Otherwise, creates a -new table to be used as a metatable for userdata, adds it to the registry with -key$tname$, and returns 1. - -In both cases pushes onto the stack the final value associated with$tname$in -the registry. - - -$luaL_newstate$ *lrv-luaL_newstate* ---------------- -> - lua_State *luaL_newstate (void); -> -Creates a new Lua state. It calls$lua_newstate$(see |lrv-lua_newstate|) with an -allocator based on the standard C$realloc$function and then sets a panic -function (see |lrv-lua_atpanic|) that prints an error message to the standard -error output in case of fatal errors. - -Returns the new state, or$NULL$if there is a memory allocation error. - - -$luaL_openlibs$ *lrv-luaL_openlibs* ---------------- -> - void luaL_openlibs (lua_State *L); -> -Opens all standard Lua libraries into the given state. See also -|lrv-openlibs| for details on how to open individual libraries. - - -$luaL_optint$ *lrv-luaL_optint* -------------- -> - int luaL_optint (lua_State *L, int narg, int d); -> -If the function argument$narg$is a number, returns this number cast to an -$int$. If this argument is absent or is#nil#, returns$d$. Otherwise, raises an -error. - - -$luaL_optinteger$ *lrv-luaL_optinteger* ------------------ -> - lua_Integer luaL_optinteger (lua_State *L, - int narg, - lua_Integer d); -> -If the function argument$narg$is a number, returns this number cast to a -$lua_Integer$(see |lrv-lua_Integer|). If this argument is absent or is#nil#, -returns$d$. Otherwise, raises an error. - - -$luaL_optlong$ *lrv-luaL_optlong* --------------- -> - long luaL_optlong (lua_State *L, int narg, long d); -> -If the function argument$narg$is a number, returns this number cast to a -$long$. If this argument is absent or is#nil#, returns$d$. Otherwise, raises -an error. - - -$luaL_optlstring$ *lrv-luaL_optlstring* ------------------ -> - const char *luaL_optlstring (lua_State *L, - int narg, - const char *d, - size_t *l); -> -If the function argument$narg$is a string, returns this string. If this -argument is absent or is#nil#, returns$d$. Otherwise, raises an error. - -If$l$is not$NULL$, fills the position$*l$with the results's length. - - -$luaL_optnumber$ *lrv-luaL_optnumber* ----------------- -> - lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d); -> -If the function argument$narg$is a number, returns this number. If this -argument is absent or is#nil#, returns$d$. Otherwise, raises an error. - - -$luaL_optstring$ *lrv-luaL_optstring* ----------------- -> - const char *luaL_optstring (lua_State *L, - int narg, - const char *d); -> -If the function argument$narg$is a string, returns this string. If this -argument is absent or is#nil#, returns$d$. Otherwise, raises an error. - - -$luaL_prepbuffer$ *lrv-luaL_prepbuffer* ------------------ -> - char *luaL_prepbuffer (luaL_Buffer *B); -> -Returns an address to a space of size$LUAL_BUFFERSIZE$where you can copy a -string to be added to buffer$B$(see |lrv-luaL_Buffer|). After copying the -string into this space you must call$luaL_addsize$(see |lrv-luaL_addsize|) -with the size of the string to actually add it to the buffer. - - -$luaL_pushresult$ *lrv-luaL_pushresult* ------------------ -> - void luaL_pushresult (luaL_Buffer *B); -> -Finishes the use of buffer$B$leaving the final string on the top of the stack. - - -$luaL_ref$ *lrv-luaL_ref* ----------- -> - int luaL_ref (lua_State *L, int t); -> -Creates and returns a@reference@, in the table at index$t$, for the object at -the top of the stack (and pops the object). - -A reference is a unique integer key. As long as you do not manually add -integer keys into table$t$,$luaL_ref$ensures the uniqueness of the key it -returns. You can retrieve an object referred by reference$r$by calling -$lua_rawgeti(L, t, r)$(see |lrv-lua_rawgeti|). Function$luaL_unref$(see -|lrv-luaL_unref|) frees a reference and its associated object. - -If the object at the top of the stack is#nil#,$luaL_ref$returns the constant -$LUA_REFNIL$. The constant$LUA_NOREF$is guaranteed to be different from any -reference returned by$luaL_ref$. - - -$luaL_Reg$ *lrv-luaL_Reg* ----------- -> - typedef struct luaL_Reg { - const char *name; - lua_CFunction func; - } luaL_Reg; -> -Type for arrays of functions to be registered by$luaL_register$ (see -|lrv-luaL_register|).$name$is the function name and$func$is a pointer to the -function. Any array of$luaL_Reg$must end with a sentinel entry in which both -$name$and$func$are$NULL$. - - -$luaL_register$ *lrv-luaL_register* ---------------- -> - void luaL_register (lua_State *L, - const char *libname, - const luaL_Reg *l); -> -Opens a library. - -When called with$libname$equal to$NULL$, it simply registers all functions in -the list$l$(see |lrv-luaL_Reg|) into the table on the top of the stack. - -When called with a non-null$libname$,$luaL_register$creates a new table$t$, -sets it as the value of the global variable$libname$, sets it as the value of -$package.loaded[libname]$, and registers on it all functions in the list$l$. -If there is a table in$package.loaded[libname]$or in variable$libname$, reuses -this table instead of creating a new one. - -In any case the function leaves the table on the top of the stack. - - -$luaL_typename$ *lrv-luaL_typename* ---------------- -> - const char *luaL_typename (lua_State *L, int idx); -> -Returns the name of the type of the value at index$idx$. - - -$luaL_typerror$ *lrv-luaL_typerror* ---------------- -> - int luaL_typerror (lua_State *L, int narg, const char *tname); -> -Generates an error with a message like the following: - - @location@$: bad argument$@narg@$to$@'func'@$($@tname@$expected, got$@rt@$)$ - -where@location@is produced by$luaL_where$ (see |lrv-luaL_where|),@func@is the -name of the current function, and@rt@is the type name of the actual argument. - - -$luaL_unref$ *lrv-luaL_unref* ------------- -> - void luaL_unref (lua_State *L, int t, int ref); -> -Releases reference$ref$from the table at index$t$(see |lrv-luaL_ref|). -The entry is removed from the table, so that the referred object can be -collected. The reference$ref$is also freed to be used again. - -If$ref$is$LUA_NOREF$or$LUA_REFNIL$,$luaL_unref$does nothing. - - -$luaL_where$ *lrv-luaL_where* ------------- -> - void luaL_where (lua_State *L, int lvl); -> -Pushes onto the stack a string identifying the current position of the control -at level$lvl$in the call stack. Typically this string has the following -format: - - @chunkname:currentline:@ - -Level 0 is the running function, level 1 is the function that called the -running function, etc. - -This function is used to build a prefix for error messages. - - -============================================================================== -5 STANDARD LIBRARIES *lrv-Lib* -============================================================================== - - -The standard libraries provide useful functions that are implemented directly -through the C API. Some of these functions provide essential services to the -language (e.g.,$type$and$getmetatable$); others provide access to "outside" -services (e.g., I/O); and others could be implemented in Lua itself, but are -quite useful or have critical performance requirements that deserve an -implementation in C (e.g.,$sort$). - -All libraries are implemented through the official C API and are provided as -separate C modules. Currently, Lua has the following standard libraries: - - #o# basic library; - #o# package library; - #o# string manipulation; - #o# table manipulation; - #o# mathematical functions (sin, log, etc.); - #o# input and output; - #o# operating system facilities; - #o# debug facilities. - -Except for the basic and package libraries, each library provides all its -functions as fields of a global table or as methods of its objects. - - *lrv-openlibs* -To have access to these libraries, the C host program should call the -$luaL_openlibs$function, which opens all standard libraries (see -|lrv-luaL_openlibs|). Alternatively, the host program can open the libraries -individually by calling$luaopen_base$(for the basic library), -$luaopen_package$(for the package library),$luaopen_string$(for the string -library),$luaopen_table$(for the table library),$luaopen_math$(for the -mathematical library),$luaopen_io$(for the I/O and the Operating System -libraries), and$luaopen_debug$(for the debug library). These functions are -declared in$lualib.h$and should not be called directly: you must call them -like any other Lua C function, e.g., by using$lua_call$(see |lrv-lua_call|). - - -============================================================================== -5.1 Basic Functions *lrv-libBasic* - - -The basic library provides some core functions to Lua. If you do not include -this library in your application, you should check carefully whether you need -to provide implementations for some of its facilities. - - -$assert (v [, message])$ *lrv-assert* ------------------------- -Issues an error when the value of its argument$v$is false (i.e.,#nil#or -#false#); otherwise, returns all its arguments.$message$is an error message; -when absent, it defaults to "assertion failed!" - - -$collectgarbage (opt [, arg])$ *lrv-collectgarbage* ------------------------------- -This function is a generic interface to the garbage collector. It performs -different functions according to its first argument,$opt$: - - #o##"stop"#: stops the garbage collector. - #o##"restart"#: restarts the garbage collector. - #o##"collect"#: performs a full garbage-collection cycle. - #o##"count"#: returns the total memory in use by Lua (in Kbytes). - #o##"step"#: performs a garbage-collection step. The step "size" is - controlled by$arg$(larger values mean more steps) in a non-specified - way. If you want to control the step size you must experimentally tune - the value of$arg$. Returns#true#if the step finished a collection cycle. - #o##"setpause"#: sets$arg$/100 as the new value for the@pause@of the - collector (see |lrv-langGC|). - #o##"setstepmul"#: sets$arg$/100 as the new value for the@step multiplier@of - the collector (see |lrv-langGC|). - - -$dofile (filename)$ *lrv-dofile* -------------------- -Opens the named file and executes its contents as a Lua chunk. When called -without arguments,$dofile$executes the contents of the standard input -($stdin$). Returns all values returned by the chunk. In case of -errors,$dofile$propagates the error to its caller (that is,$dofile$does not -run in protected mode). - - -$error (message [, level])$ *lrv-error* ---------------------------- -Terminates the last protected function called and returns$message$as the error -message. Function$error$never returns. - -Usually,$error$adds some information about the error position at the beginning -of the message. The$level$argument specifies how to get the error position. -With level 1 (the default), the error position is where the$error$function was -called. Level 2 points the error to where the function that called$error$was -called; and so on. Passing a level 0 avoids the addition of error position -information to the message. - - -$_G$ *lrv-_G* ------ -A global variable (not a function) that holds the global environment (that -is,$_G._G = _G$). Lua itself does not use this variable; changing its value -does not affect any environment, nor vice-versa. (Use$setfenv$to change -environments.) - - -$getfenv (f)$ *lrv-getfenv* -------------- -Returns the current environment in use by the function.$f$can be a Lua -function or a number that specifies the function at that stack level: -Level 1 is the function calling$getfenv$. If the given function is not a Lua -function, or if$f$is 0,$getfenv$returns the global environment. The default -for$f$is 1. - - -$getmetatable (object)$ *lrv-getmetatable* ------------------------ -If$object$does not have a metatable, returns#nil#. Otherwise, if the object's -metatable has a$"__metatable"$field, returns the associated value. Otherwise, -returns the metatable of the given object. - - -$ipairs (t)$ *lrv-ipairs* ------------- -Returns three values: an iterator function, the table$t$, and 0, so that the -construction - - $for i,v in ipairs(t) do$@body@$end$ - -will iterate over the pairs ($1,t[1]$), ($2,t[2]$), ..., up to the first -integer key absent from the table. - - -$load (func [, chunkname])$ *lrv-load* ---------------------------- -Loads a chunk using function$func$to get its pieces. Each call to$func$must -return a string that concatenates with previous results. A return of#nil#(or -no value) signals the end of the chunk. - -If there are no errors, returns the compiled chunk as a function; otherwise, -returns#nil#plus the error message. The environment of the returned function -is the global environment. - -$chunkname$is used as the chunk name for error messages and debug information. - - -$loadfile ([filename])$ *lrv-loadfile* ------------------------ -Similar to$load$(see |lrv-load|), but gets the chunk from file$filename$or -from the standard input, if no file name is given. - - -$loadstring (string [, chunkname])$ *lrv-loadstring* ------------------------------------ -Similar to$load$(see |lrv-load|), but gets the chunk from the given string. - -To load and run a given string, use the idiom -> - assert(loadstring(s))() -> - -$next (table [, index])$ *lrv-next* ------------------------- -Allows a program to traverse all fields of a table. Its first argument is a -table and its second argument is an index in this table.$next$returns the next -index of the table and its associated value. When called with#nil#as its -second argument,$next$returns an initial index and its associated value. When -called with the last index, or with#nil#in an empty table,$next$returns#nil#. -If the second argument is absent, then it is interpreted as#nil#. In -particular, you can use$next(t)$to check whether a table is empty. - -The order in which the indices are enumerated is not specified,@even for@ -@numeric indices@. (To traverse a table in numeric order, use a numerical#for# -or the$ipairs$|lrv-ipairs| function.) - -The behavior of$next$is@undefined@if, during the traversal, you assign any -value to a non-existent field in the table. You may however modify existing -fields. In particular, you may clear existing fields. - - -$pairs (t)$ *lrv-pairs* ------------ -Returns three values: the$next$|lrv-next| function, the table$t$, and#nil#, so -that the construction - - $for k,v in pairs(t) do$@body@$end$ - -will iterate over all key-value pairs of table$t$. - - -$pcall (f, arg1, ...)$ *lrv-pcall* ----------------------- -Calls function$f$with the given arguments in@protected mode@. This means that -any error inside$f$is not propagated; instead,$pcall$catches the error and -returns a status code. Its first result is the status code (a boolean), which -is#true#if the call succeeds without errors. In such case,$pcall$also returns -all results from the call, after this first result. In case of any error, -$pcall$returns#false#plus the error message. - - -$print (...)$ *lrv-print* -------------- -Receives any number of arguments, and prints their values to$stdout$, using -the$tostring$|lrv-tostring| function to convert them to strings.$print$is not -intended for formatted output, but only as a quick way to show a value, -typically for debugging. For formatted output, use$string.format$(see -|lrv-string.format|). - - -$rawequal (v1, v2)$ *lrv-rawequal* -------------------- -Checks whether$v1$is equal to$v2$, without invoking any metamethod. Returns a -boolean. - - -$rawget (table, index)$ *lrv-rawget* ------------------------ -Gets the real value of$table[index]$, without invoking any metamethod.$table$ -must be a table;$index$may be any value. - - -$rawset (table, index, value)$ *lrv-rawset* ------------------------------- -Sets the real value of$table[index]$to$value$, without invoking any -metamethod.$table$must be a table,$index$any value different from#nil#, -and$value$any Lua value. - -This function returns$table$. - - -$select (index, ...)$ *lrv-select* ---------------------- -If$index$is a number, returns all arguments after argument number$index$. -Otherwise,$index$must be the string$"#"$, and$select$returns the total number -of extra arguments it received. - - -$setfenv (f, table)$ *lrv-setfenv* --------------------- -Sets the environment to be used by the given function.$f$can be a Lua function -or a number that specifies the function at that stack level: Level 1 is the -function calling$setfenv$.$setfenv$returns the given function. - -As a special case, when$f$is 0$setfenv$changes the environment of the running -thread. In this case,$setfenv$returns no values. - - -$setmetatable (table, metatable)$ *lrv-setmetatable* ---------------------------------- -Sets the metatable for the given table. (You cannot change the metatable of -other types from Lua, only from C.) If$metatable$is#nil#, removes the -metatable of the given table. If the original metatable has -a$"__metatable"$field, raises an error. - -This function returns$table$. - - -$tonumber (e [, base])$ *lrv-tonumber* ------------------------ -Tries to convert its argument to a number. If the argument is already a number -or a string convertible to a number, then$tonumber$returns this number; -otherwise, it returns#nil#. - -An optional argument specifies the base to interpret the numeral. The base may -be any integer between 2 and 36, inclusive. In bases above 10, the -letter$'A'$(in either upper or lower case) represents 10,$'B'$represents 11, -and so forth, with$'Z'$representing 35. In base 10 (the default), the number -may have a decimal part, as well as an optional exponent part (see -|lrv-langLexConv|). In other bases, only unsigned integers are accepted. - - -$tostring (e)$ *lrv-tostring* --------------- -Receives an argument of any type and converts it to a string in a reasonable -format. For complete control of how numbers are converted, use$string.format$ -(see |lrv-string.format|). - - *lrv-__tostring* -If the metatable of$e$has a$"__tostring"$field,$tostring$calls the -corresponding value with$e$as argument, and uses the result of the call as its -result. - - -$type (v)$ *lrv-type* ----------- -Returns the type of its only argument, coded as a string. The possible results -of this function are$"nil"$(a string, not the value#nil#),$"number"$, -$"string"$,$"boolean$,$"table"$,$"function"$,$"thread"$, and$"userdata"$. - - -$unpack (list [, i [, j]])$ *lrv-unpack* ---------------------------- -Returns the elements from the given table. This function is equivalent to -> - return list[i], list[i+1], ..., list[j] -> -except that the above code can be written only for a fixed number of elements. -By default,$i$is 1 and$j$is the length of the list, as defined by the length -operator (see |lrv-langLength|). - - -$_VERSION$ *lrv-_VERSION* ----------- -A global variable (not a function) that holds a string containing the current -interpreter version. The current contents of this string is$"Lua 5.1"$. - - -$xpcall (f, err)$ *lrv-xpcall* ------------------ -This function is similar to$pcall$(see |lrv-pcall|), except that you can set a -new error handler. - -$xpcall$calls function$f$in protected mode, using$err$as the error handler. -Any error inside$f$is not propagated; instead,$xpcall$catches the error, calls -the$err$function with the original error object, and returns a status code. -Its first result is the status code (a boolean), which is true if the call -succeeds without errors. In this case,$xpcall$also returns all results from -the call, after this first result. In case of any error,$xpcall$returns#false# -plus the result from$err$. - - -============================================================================== -5.2 Coroutine Manipulation *lrv-libCoro* - - -The operations related to coroutines comprise a sub-library of the basic -library and come inside the table$coroutine$. See |lrv-langCoro| for a general -description of coroutines. - - -$coroutine.create (f)$ *lrv-coroutine.create* ----------------------- -Creates a new coroutine, with body$f$.$f$must be a Lua function. Returns this -new coroutine, an object with type$"thread"$. - - -$coroutine.resume (co [, val1, ...])$ *lrv-coroutine.resume* -------------------------------------- -Starts or continues the execution of coroutine$co$. The first time you resume -a coroutine, it starts running its body. The values$val1$, ... are passed as -arguments to the body function. If the coroutine has yielded,$resume$restarts -it; the values$val1$, ... are passed as the results from the yield. - -If the coroutine runs without any errors,$resume$returns#true#plus any values -passed to$yield$(if the coroutine yields) or any values returned by the body -function (if the coroutine terminates). If there is any error,$resume$returns -#false#plus the error message. - - -$coroutine.running ()$ *lrv-coroutine.running* ----------------------- -Returns the running coroutine, or#nil#when called by the main thread. - - -$coroutine.status (co)$ *lrv-coroutine.status* ------------------------ -Returns the status of coroutine$co$, as a string:$"running"$, if the coroutine -is running (that is, it called$status$);$"suspended"$, if the coroutine is -suspended in a call to$yield$, or if it has not started running yet; -$"normal"$if the coroutine is active but not running (that is, it has resumed -another coroutine); and$"dead"$if the coroutine has finished its body -function, or if it has stopped with an error. - - -$coroutine.wrap (f)$ *lrv-coroutine.wrap* --------------------- -Creates a new coroutine, with body$f$.$f$must be a Lua function. Returns a -function that resumes the coroutine each time it is called. Any arguments -passed to the function behave as the extra arguments to$resume$. Returns the -same values returned by$resume$, except the first boolean. In case of error, -propagates the error. - - -$coroutine.yield (...)$ *lrv-coroutine.yield* ------------------------ -Suspends the execution of the calling coroutine. The coroutine cannot be -running a C function, a metamethod, or an iterator. Any arguments to$yield$are -passed as extra results to$resume$. - - -============================================================================== -5.3 - Modules *lrv-libModule* - - -The package library provides basic facilities for loading and building modules -in Lua. It exports two of its functions directly in the global environment: -$require$and$module$(see |lrv-require| and |lrv-module|). Everything else is -exported in a table$package$. - - -$module (name [, ...])$ *lrv-module* ------------------------ -Creates a module. If there is a table in$package.loaded[name]$, this table is -the module. Otherwise, if there is a global table$t$with the given name, this -table is the module. Otherwise creates a new table$t$and sets it as the value -of the global$name$and the value of$package.loaded[name]$. This function also -initializes$t._NAME$with the given name,$t._M$with the module ($t$itself), and -$t._PACKAGE$with the package name (the full module name minus last component; -see below). Finally,$module$sets$t$as the new environment of the current -function and the new value of$package.loaded[name]$, so that$require$(see -|lrv-require|) returns$t$. - -If$name$is a compound name (that is, one with components separated by dots), -$module$creates (or reuses, if they already exist) tables for each component. -For instance, if$name$is$a.b.c$, then$module$stores the module table in field -$c$of field$b$of global$a$. - -This function may receive optional@options@after the module name, where each -option is a function to be applied over the module. - - -$require (modname)$ *lrv-require* -------------------- -Loads the given module. The function starts by looking into the -$package.loaded$table to determine whether$modname$is already loaded. If it -is, then$require$returns the value stored at$package.loaded[modname]$. -Otherwise, it tries to find a@loader@for the module. - -To find a loader, first$require$queries$package.preload[modname]$. If it has a -value, this value (which should be a function) is the loader. Otherwise -$require$searches for a Lua loader using the path stored in$package.path$. -If that also fails, it searches for a C loader using the path stored in -$package.cpath$. If that also fails, it tries an@all-in-one@loader (see -below). - -When loading a C library,$require$first uses a dynamic link facility to link -the application with the library. Then it tries to find a C function inside -this library to be used as the loader. The name of this C function is the -string$"luaopen_"$concatenated with a copy of the module name where each dot -is replaced by an underscore. Moreover, if the module name has a hyphen, its -prefix up to (and including) the first hyphen is removed. For instance, if the -module name is$a.v1-b.c$, the function name will be$luaopen_b_c$. - -If$require$finds neither a Lua library nor a C library for a module, it calls -the@all-in-one loader@. This loader searches the C path for a library for the -root name of the given module. For instance, when requiring$a.b.c$, it will -search for a C library for$a$. If found, it looks into it for an open function -for the submodule; in our example, that would be$luaopen_a_b_c$. With this -facility, a package can pack several C submodules into one single library, -with each submodule keeping its original open function. - -Once a loader is found,$require$calls the loader with a single argument, -$modname$. If the loader returns any value,$require$assigns the returned value -to$package.loaded[modname]$. If the loader returns no value and has not -assigned any value to$package.loaded[modname]$, then$require$assigns#true#to -this entry. In any case,$require$returns the final value of -$package.loaded[modname]$. - -If there is any error loading or running the module, or if it cannot find any -loader for the module, then$require$signals an error. - - -$package.cpath$ *lrv-package.cpath* ---------------- -The path used by$require$to search for a C loader. - -Lua initializes the C path$package.cpath$in the same way it initializes the -Lua path$package.path$, using the environment variable$LUA_CPATH$(plus another -default path defined in$luaconf.h$). - - -$package.loaded$ *lrv-package.loaded* ----------------- -A table used by$require$to control which modules are already loaded. When you -require a module$modname$and$package.loaded[modname]$is not false,$require$ -simply returns the value stored there. - - -$package.loadlib (libname, funcname)$ *lrv-package.loadlib* -------------------------------------- -Dynamically links the host program with the C library$libname$. Inside this -library, looks for a function$funcname$and returns this function as a -C function. (So,$funcname$must follow the protocol (see |lrv-lua_CFunction|)). - -This is a low-level function. It completely bypasses the package and module -system. Unlike$require$, it does not perform any path searching and does not -automatically adds extensions.$libname$must be the complete file name of the -C library, including if necessary a path and extension.$funcname$must be the -exact name exported by the C library (which may depend on the C compiler and -linker used). - -This function is not supported by ANSI C. As such, it is only available on -some platforms (Windows, Linux, Mac OS X, Solaris, BSD, plus other Unix -systems that support the$dlfcn$standard). - - -$package.path$ *lrv-package.path* --------------- -The path used by$require$to search for a Lua loader. - -At start-up, Lua initializes this variable with the value of the environment -variable$LUA_PATH$or with a default path defined in$luaconf.h$, if the -environment variable is not defined. Any$";;"$in the value of the environment -variable is replaced by the default path. - -A path is a sequence of@templates@separated by semicolons. For each template, -$require$will change each interrogation mark in the template by$filename$, -which is$modname$with each dot replaced by a "directory separator" (such as -$"/"$ in Unix); then it will try to load the resulting file name. So, for -instance, if the Lua path is -> - "./?.lua;./?.lc;/usr/local/?/init.lua" -> -the search for a Lua loader for module$foo$will try to load the files -$./foo.lua$,$./foo.lc$, and$/usr/local/foo/init.lua$, in that order. - - -$package.preload$ *lrv-package.preload* ------------------ -A table to store loaders for specific modules (see |lrv-require|). - - -$package.seeall (module)$ *lrv-package.seeall* -------------------------- -Sets a metatable for$module$with its$__index$field referring to the global -environment, so that this module inherits values from the global environment. -To be used as an option to function$module$. - - -============================================================================== -5.4 - String Manipulation *lrv-libString* - - -This library provides generic functions for string manipulation, such as -finding and extracting substrings, and pattern matching. When indexing a -string in Lua, the first character is at position 1 (not at 0, as in C). -Indices are allowed to be negative and are interpreted as indexing backwards, -from the end of the string. Thus, the last character is at position -1, and -so on. - -The string library provides all its functions inside the table$string$. -It also sets a metatable for strings where the$__index$field points to the -$string$table. Therefore, you can use the string functions in object-oriented -style. For instance,$string.byte(s, i)$can be written as$s:byte(i)$. - - - -$string.byte (s [, i [, j]])$ *lrv-string.byte* ------------------------------ -Returns the internal numerical codes of the characters$s[i]$,$s[i+1]$,..., -$s[j]$. The default value for$i$is 1; the default value for$j$is$i$. - -Note that numerical codes are not necessarily portable across platforms. - - -$string.char (...)$ *lrv-string.char* -------------------- -Receives zero or more integers. Returns a string with length equal to the -number of arguments, in which each character has the internal numerical code -equal to its correspondent argument. - -Note that numerical codes are not necessarily portable across platforms. - - -$string.dump (function)$ *lrv-string.dump* ------------------------- -Returns a string containing a binary representation of the given function, so -that a later$loadstring$on this string returns a copy of the function. -$function$must be a Lua function without upvalues. - - -$string.find (s, pattern [, init [, plain]])$ *lrv-string.find* ---------------------------------------------- -Looks for the first match of$pattern$in the string$s$. If it finds a match, -then$find$returns the indices of$s$where this occurrence starts and ends; -otherwise, it returns#nil#. A third, optional numerical argument$init$ -specifies where to start the search; its default value is 1 and may be -negative. A value of#true#as a fourth, optional argument$plain$turns off the -pattern matching facilities, so the function does a plain "find substring" -operation, with no characters in$pattern$being considered "magic". Note that -if$plain$is given, then$init$must be given as well. - - -If the pattern has captures, then in a successful match the captured values -are also returned, after the two indices. - - -$string.format (formatstring, ...)$ *lrv-string.format* ------------------------------------ -Returns a formatted version of its variable number of arguments following the -description given in its first argument (which must be a string). The format -string follows the same rules as the$printf$family of standard C functions. -The only differences are that the options/modifiers$*$,$l$,$L$,$n$,$p$, and$h$ -are not supported and that there is an extra option,$q$. The$q$option formats -a string in a form suitable to be safely read back by the Lua interpreter: the -string is written between double quotes, and all double quotes, newlines, -embedded zeros, and backslashes in the string are correctly escaped when -written. For instance, the call -> - string.format('%q', 'a string with "quotes" and \n new line') -> -will produce the string: -> - "a string with \"quotes\" and \ - new line" -> -The options$c$,$d$,$E$,$e$,$f$,$g$,$G$,$i$,$o$,$u$,$X$, and$x$all expect a -number as argument, whereas$q$and$s$expect a string. - -This function does not accept string values containing embedded zeros. - - -$string.gmatch (s, pattern)$ *lrv-string.gmatch* ----------------------------- -Returns an iterator function that, each time it is called, returns the next -captures from$pattern$over string$s$. - -If$pattern$specifies no captures, then the whole match is produced in each -call. - -As an example, the following loop -> - s = "hello world from Lua" - for w in string.gmatch(s, "%a+") do - print(w) - end -> -will iterate over all the words from string$s$, printing one per line. -The next example collects all pairs$key=value$from the given string into a -table: -> - t = {} - s = "from=world, to=Lua" - for k, v in string.gmatch(s, "(%w+)=(%w+)") do - t[k] = v - end -> - -$string.gsub (s, pattern, repl [, n])$ *lrv-string.gsub* --------------------------------------- -Returns a copy of$s$in which all occurrences of the$pattern$have been replaced -by a replacement string specified by$repl$, which may be a string, a table, or -a function.$gsub$also returns, as its second value, the total number of -substitutions made. - -If$repl$is a string, then its value is used for replacement. The character$%$ -works as an escape character: any sequence in$repl$of the form$%n$, with@n@ -between 1 and 9, stands for the value of the@n@-th captured substring (see -below). The sequence$%0$stands for the whole match. The sequence$%%$stands for -a single$%$. - -If$repl$is a table, then the table is queried for every match, using the first -capture as the key; if the pattern specifies no captures, then the whole match -is used as the key. - -If$repl$is a function, then this function is called every time a match occurs, -with all captured substrings passed as arguments, in order; if the pattern -specifies no captures, then the whole match is passed as a sole argument. - -If the value returned by the table query or by the function call is a string -or a number, then it is used as the replacement string; otherwise, if it is -#false#or#nil#, then there is no replacement (that is, the original match is -kept in the string). - -The optional last parameter$n$limits the maximum number of substitutions to -occur. For instance, when$n$is 1 only the first occurrence of$pattern$is -replaced. - -Here are some examples: -> - x = string.gsub("hello world", "(%w+)", "%1 %1") - --> x="hello hello world world" - - x = string.gsub("hello world", "%w+", "%0 %0", 1) - --> x="hello hello world" - - x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") - --> x="world hello Lua from" - - x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) - --> x="home = /home/roberto, user = roberto" - - x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) - return loadstring(s)() - end) - --> x="4+5 = 9" - - local t = {name="lua", version="5.1"} - x = string.gsub("$name%-$version.tar.gz", "%$(%w+)", t) - --> x="lua-5.1.tar.gz" -> - -$string.len (s)$ *lrv-string.len* ----------------- -Receives a string and returns its length. The empty string$""$has length 0. -Embedded zeros are counted, so$"a\000b\000c"$has length 5. - - -$string.lower (s)$ *lrv-string.lower* ------------------- -Receives a string and returns a copy of this string with all uppercase letters -changed to lowercase. All other characters are left unchanged. The definition -of what an uppercase letter is depends on the current locale. - - -$string.match (s, pattern [, init])$ *lrv-string.match* ------------------------------------- -Looks for the first@match@of$pattern$in the string$s$. If it finds one, then -$match$returns the captures from the pattern; otherwise it returns#nil#. -If$pattern$specifies no captures, then the whole match is returned. A third, -optional numerical argument$init$specifies where to start the search; its -default value is 1 and may be negative. - - -$string.rep (s, n)$ *lrv-string.rep* -------------------- -Returns a string that is the concatenation of$n$copies of the string$s$. - - -$string.reverse (s)$ *lrv-string.reverse* --------------------- -Returns a string that is the string$s$reversed. - - -$string.sub (s, i [, j])$ *lrv-string.sub* -------------------------- -Returns the substring of$s$that starts at$i$and continues until$j$;$i$and$j$ -may be negative. If$j$is absent, then it is assumed to be equal to@-1@(which -is the same as the string length). In particular, the call$string.sub(s,1,j)$ -returns a prefix of$s$with length$j$, and$string.sub(s,-i)$returns a suffix -of$s$with length$i$. - - -$string.upper (s)$ *lrv-string.upper* ------------------- -Receives a string and returns a copy of that string with all lowercase letters -changed to uppercase. All other characters are left unchanged. The definition -of what a lowercase letter is depends on the current locale. - - ------------------------------------------------------------------------------- -5.4.1 Patterns *lrv-patterns* *lrv-libStringPat* - - -A@character class@is used to represent a set of characters. The following -combinations are allowed in describing a character class: - - #o#@x@: (where@x@is not one of@the magic characters@ ^$()%.[]*+-? ) - represents the character@x@itself. - #o#$.$: (a dot) represents all characters. - #o#$%a$: represents all letters. - #o#$%c$: represents all control characters. - #o#$%d$: represents all digits. - #o#$%l$: represents all lowercase letters. - #o#$%p$: represents all punctuation characters. - #o#$%s$: represents all space characters. - #o#$%u$: represents all uppercase letters. - #o#$%w$: represents all alphanumeric characters. - #o#$%x$: represents all hexadecimal digits. - #o#$%z$: represents the character with representation 0. - #o#$%x$(where@x@is any non-alphanumeric character) represents the - character@x@. This is the standard way to escape the magic characters. - Any punctuation character (even the non-magic) can be preceded by a - $'%'$when used to represent itself in a pattern. - - #o#$[set]$: represents the class which is the union of all characters in - @set@. A range of characters may be specified by separating the end - characters of the range with a$'-'$. All classes$%x$described above may - also be used as components in@set@. All other characters in@set@ - represent themselves. For example,$[%w_]$(or$[_%w]$) represents all - alphanumeric characters plus the underscore,$[0-7]$represents the octal - digits, and$[0-7%l%-]$represents the octal digits plus the lowercase - letters plus the$'-'$character. - - The interaction between ranges and classes is not defined. Therefore, - patterns like$[%a-z]$or$[a-%%]$have no meaning. - - #o#$[^set]$: represents the complement of@set@, where@set@is interpreted - as above. - -For all classes represented by single letters ($%a$,$%c$, etc.), the -corresponding uppercase letter represents the complement of the class. For -instance,$%S$represents all non-space characters. - -The definitions of letter, space, and other character groups depend on the -current locale. In particular, the class$[a-z]$may not be equivalent to$%l$. - - *lrv-patternitem* -Pattern Item:~ -------------- -A@pattern item@may be - - #o# a single character class, which matches any single character in the - class; - #o# a single character class followed by$'*'$, which matches 0 or more - repetitions of characters in the class. These repetition items will - always match the longest possible sequence; - #o# a single character class followed by$'+'$, which matches 1 or more - repetitions of characters in the class. These repetition items will - always match the longest possible sequence; - #o# a single character class followed by$'-'$, which also matches 0 or - more repetitions of characters in the class. Unlike$'*'$, these - repetition items will always match the@shortest@possible sequence; - #o# a single character class followed by$'?'$, which matches 0 or 1 - occurrences of a character in the class; - #o#$%n$, for@n@between 1 and 9; such item matches a substring equal to the - @n@-th captured string (see below); - #o#$%bxy$, where@x@and@y@are two distinct characters; such item matches - strings that start with@x@, end with@y@, and where the@x@and@y@ - are@balanced@. This means that, if one reads the string from left to - right, counting@+1@for an@x@and@-1@for a@y@, the ending@y@is the first - @y@where the count reaches 0. For instance, the item$%b()$matches - expressions with balanced parentheses. - - *lrv-pattern* -Pattern:~ --------- -A@pattern@is a sequence of pattern items. A$'^'$at the beginning of a pattern -anchors the match at the beginning of the subject string. A '$' at the end of -a pattern anchors the match at the end of the subject string. At other -positions,$'^'$and '$' have no special meaning and represent themselves. - - *lrv-capture* -Captures:~ ---------- -A pattern may contain sub-patterns enclosed in parentheses; they describe -@captures@. When a match succeeds, the substrings of the subject string that -match captures are stored (@captured@) for future use. Captures are numbered -according to their left parentheses. For instance, in the pattern -$"(a*(.)%w(%s*))"$, the part of the string matching$"a*(.)%w(%s*)"$is -stored as the first capture (and therefore has number 1); the character -matching$.$is captured with number 2, and the part matching$%s*$has number 3. - -As a special case, the empty capture$()$captures the current string position -(a number). For instance, if we apply the pattern$"()aa()"$on the -string$"flaaap"$, there will be two captures: 3 and 5. - -A pattern cannot contain embedded zeros. Use$%z$instead. - - -============================================================================== -5.5 Table Manipulation *lrv-libTable* - - -This library provides generic functions for table manipulation. It provides -all its functions inside the table$table$. - -Most functions in the table library assume that the table represents an array -or a list. For those functions, when we talk about the "length" of a table we -mean the result of the length operator. - - -$table.concat (table [, sep [, i [, j]]])$ *lrv-table.concat* ------------------------------------------- -Given an array where all elements are strings or numbers, returns -$table[i]..sep..table[i+1] ... sep..table[j]$. The default value for$sep$is -the empty string, the default for$i$is 1, and the default for$j$is the length -of the table. If$i$is greater than$j$, returns the empty string. - - -$table.foreach (table, f)$ *lrv-table.foreach* --------------------------- -Executes the given$f$over all elements of$table$. For each element,$f$is -called with the index and respective value as arguments. If$f$returns a -non-#nil#value, then the loop is broken, and this value is returned as the -final value of$table.foreach$. - -See |lrv-next| for extra information about table traversals. - - -$table.foreachi (table, f)$ *lrv-table.foreachi* ---------------------------- -Executes the given$f$over the numerical indices of$table$. For each -index,$f$is called with the index and respective value as arguments. Indices -are visited in sequential order, from 1 to$n$, where$n$is the length of the -table. If$f$returns a non-#nil#value, then the loop is broken and this value -is returned as the result of$table.foreachi$. - - -$table.insert (table, [pos,] value)$ *lrv-table.insert* ------------------------------------- -Inserts element$value$at position$pos$in$table$, shifting up other elements to -open space, if necessary. The default value for$pos$is$n+1$, where$n$is the -length of the table (see |lrv-langLength|), so that a call$table.insert(t,x)$ -inserts$x$at the end of table$t$. - - -$table.maxn (table)$ *lrv-table.maxn* --------------------- -Returns the largest positive numerical index of the given table, or zero if -the table has no positive numerical indices. (To do its job this function does -a linear traversal of the whole table.) - - -$table.remove (table [, pos])$ *lrv-table.remove* ------------------------------- -Removes from$table$the element at position$pos$, shifting down other elements -to close the space, if necessary. Returns the value of the removed element. -The default value for$pos$is$n$, where$n$is the length of the table (see -|lrv-langLength|), so that a call$table.remove(t)$removes the last element of -table$t$. - - -$table.sort (table [, comp])$ *lrv-table.sort* ------------------------------ -Sorts table elements in a given order,@in-place@, from$table[1]$to$table[n]$, -where$n$is the length of the table (see |lrv-langLength|). If$comp$is given, -then it must be a function that receives two table elements, and returns true -when the first is less than the second (so that$not comp(a[i+1],a[i])$will be -true after the sort). If$comp$is not given, then the standard Lua -operator$<$is used instead. - -The sort algorithm is@not@stable, that is, elements considered equal by the -given order may have their relative positions changed by the sort. - - -============================================================================== -5.6 Mathematical Functions *lrv-libMath* - - -This library is an interface to most of the functions of the standard C math -library. It provides all its functions inside the table$math$. - - -$math.abs (x)$ *lrv-math.abs* --------------- -Returns the absolute value of$x$. - - -$math.acos (x)$ *lrv-math.acos* ---------------- -Returns the arc cosine of$x$(in radians). - - -$math.asin (x)$ *lrv-math.asin* ---------------- -Returns the arc sine of$x$(in radians). - - -$math.atan (x)$ *lrv-math.atan* ---------------- -Returns the arc tangent of$x$(in radians). - - -$math.atan2 (x, y)$ *lrv-math.atan2* -------------------- -Returns the arc tangent of$x/y$(in radians), but uses the signs of both -parameters to find the quadrant of the result. (It also handles correctly the -case of$y$being zero.) - - -$math.ceil (x)$ *lrv-math.ceil* ---------------- -Returns the smallest integer larger than or equal to$x$. - - -$math.cos (x)$ *lrv-math.cos* --------------- -Returns the cosine of$x$(assumed to be in radians). - - -$math.cosh (x)$ *lrv-math.cosh* ---------------- -Returns the hyperbolic cosine of$x$. - - -$math.deg (x)$ *lrv-math.deg* --------------- -Returns the angle$x$(given in radians) in degrees. - - -$math.exp (x)$ *lrv-math.exp* --------------- -Returns the value$e^x$. - - -$math.floor (x)$ *lrv-math.floor* ----------------- -Returns the largest integer smaller than or equal to$x$. - - -$math.fmod (x, y)$ *lrv-math.fmod* ------------------- -Returns the remainder of the division of$x$by$y$. - - -$math.frexp (x)$ *lrv-math.frexp* ----------------- -Returns$m$and$e$such that$x = m * 2^e$,$e$is an integer and the absolute value -of$m$is in the range@[0.5, 1)@(or zero when$x$is zero). - - -$math.huge$ *lrv-math.huge* ------------ -The value$HUGE_VAL$, a value larger than or equal to any other numerical -value. - - -$math.ldexp (m, e)$ *lrv-math.ldexp* -------------------- -Returns$m * 2^e$($e$should be an integer). - - -$math.log (x)$ *lrv-math.log* --------------- -Returns the natural logarithm of$x$. - - -$math.log10 (x)$ *lrv-math.log10* ----------------- -Returns the base-10 logarithm of$x$. - - -$math.max (x, ...)$ *lrv-math.max* -------------------- -Returns the maximum value among its arguments. - - -$math.min (x, ...)$ *lrv-math.min* -------------------- -Returns the minimum value among its arguments. - - -$math.modf (x)$ *lrv-math.modf* ---------------- -Returns two numbers, the integral part of$x$and the fractional part of$x$. - - -$math.pi$ *lrv-math.pi* ---------- -The value of@pi@. - - -$math.pow (x, y)$ *lrv-math.pow* ------------------ -Returns$x^y$. (You can also use the expression$x^y$to compute this value.) - - -$math.rad (x)$ *lrv-math.rad* --------------- -Returns the angle$x$(given in degrees) in radians. - - -$math.random ([m [, n]])$ *lrv-math.random* -------------------------- -This function is an interface to the simple pseudo-random generator function -$rand$provided by ANSI C. (No guarantees can be given for its statistical -properties.) - -When called without arguments, returns a pseudo-random real number in the -range@[0,1)@. When called with a number$m$,$math.random$returns a -pseudo-random integer in the range@[1, m]@. When called with two numbers$m$ -and$n$,$math.random$returns a pseudo-random integer in the range@[m, n]@. - - -$math.randomseed (x)$ *lrv-math.randomseed* ---------------------- -Sets$x$as the "seed" for the pseudo-random generator: equal seeds produce -equal sequences of numbers. - - -$math.sin (x)$ *lrv-math.sin* --------------- -Returns the sine of$x$(assumed to be in radians). - - -$math.sinh (x)$ *lrv-math.sinh* ---------------- -Returns the hyperbolic sine of$x$. - - -$math.sqrt (x)$ *lrv-math.sqrt* ---------------- -Returns the square root of$x$. (You can also use the expression$x^0.5$to -compute this value.) - - -$math.tan (x)$ *lrv-math.tan* --------------- -Returns the tangent of$x$(assumed to be in radians). - - -$math.tanh (x)$ *lrv-math.tanh* ---------------- -Returns the hyperbolic tangent of$x$. - - -============================================================================== -5.6 Input and Output Facilities *lrv-libIO* - - -The I/O library provides two different styles for file manipulation. The first -one uses implicit file descriptors; that is, there are operations to set a -default input file and a default output file, and all input/output operations -are over these default files. The second style uses explicit file -descriptors. - -When using implicit file descriptors, all operations are supplied by -table$io$. When using explicit file descriptors, the operation$io.open$returns -a file descriptor and then all operations are supplied as methods of the file -descriptor. - -The table$io$also provides three predefined file descriptors with their usual -meanings from C:$io.stdin$,$io.stdout$, and$io.stderr$. - -Unless otherwise stated, all I/O functions return#nil#on failure (plus an -error message as a second result) and some value different from#nil#on -success. - - -$io.close ([file])$ *lrv-io.close* -------------------- -Equivalent to$file:close$. Without a$file$, closes the default output file. - - -$io.flush ()$ *lrv-io.flush* -------------- -Equivalent to$file:flush$over the default output file. - - -$io.input ([file])$ *lrv-io.input* -------------------- -When called with a file name, it opens the named file (in text mode), and sets -its handle as the default input file. When called with a file handle, it -simply sets this file handle as the default input file. When called without -parameters, it returns the current default input file. - -In case of errors this function raises the error, instead of returning an -error code. - - -$io.lines ([filename])$ *lrv-io.lines* ------------------------ -Opens the given file name in read mode and returns an iterator function that, -each time it is called, returns a new line from the file. Therefore, the -construction - - $for line in io.lines(filename) do$@body@$end$ - -will iterate over all lines of the file. When the iterator function detects -the end of file, it returns#nil#(to finish the loop) and automatically closes -the file. - -The call$io.lines()$(without a file name) is equivalent to -$io.input():lines()$; that is, it iterates over the lines of the default input -file. In this case it does not close the file when the loop ends. - - -$io.open (filename [, mode])$ *lrv-io.open* ------------------------------ -This function opens a file, in the mode specified in the string$mode$. It -returns a new file handle, or, in case of errors,#nil#plus an error message. - -The$mode$string can be any of the following: - - #o#@"r"@: read mode (the default); - #o#@"w"@: write mode; - #o#@"a"@: append mode; - #o#@"r+"@: update mode, all previous data is preserved; - #o#@"w+"@: update mode, all previous data is erased; - #o#@"a+"@: append update mode, previous data is preserved, writing is only - allowed at the end of file. - -The$mode$string may also have a$'b'$at the end, which is needed in some -systems to open the file in binary mode. This string is exactly what is used -in the standard C function$fopen$. - - -$io.output ([file])$ *lrv-io.output* --------------------- -Similar to$io.input$, but operates over the default output file. - - -$io.popen (prog [, mode])$ *lrv-io.popen* --------------------------- -Starts program$prog$in a separated process and returns a file handle that you -can use to read data from this program (if$mode$is$"r"$, the default) or to -write data to this program (if$mode$is$"w"$). - -This function is system dependent and is not available on all platforms. - - -$io.read (...)$ *lrv-io.read* ---------------- -Equivalent to$io.input():read$. - - -$io.tmpfile ()$ *lrv-io.tmpfile* ---------------- -Returns a handle for a temporary file. This file is opened in update mode and -it is automatically removed when the program ends. - - -$io.type (obj)$ *lrv-io.type* ---------------- -Checks whether$obj$is a valid file handle. Returns the string$"file"$if$obj$is -an open file handle,$"closed file"$if$obj$is a closed file handle, or#nil#if -$obj$is not a file handle. - - -$io.write (...)$ *lrv-io.write* ----------------- -Equivalent to$io.output():write$. - - -$file:close ()$ *lrv-file:close* ---------------- -Closes$file$. Note that files are automatically closed when their handles are -garbage collected, but that takes an unpredictable amount of time to happen. - - -$file:flush ()$ *lrv-file:flush* ---------------- -Saves any written data to$file$. - - -$file:lines ()$ *lrv-file:lines* ---------------- -Returns an iterator function that, each time it is called, returns a new line -from the file. Therefore, the construction - - $for line in file:lines() do$@body@$end$ - -will iterate over all lines of the file. (Unlike$io.lines$, this function does -not close the file when the loop ends.) - - -$file:read (...)$ *lrv-file:read* ------------------ -Reads the file$file$, according to the given formats, which specify what to -read. For each format, the function returns a string (or a number) with the -characters read, or#nil#if it cannot read data with the specified format. When -called without formats, it uses a default format that reads the entire next -line (see below). - -The available formats are - - #o##"*n"#: reads a number; this is the only format that returns a number - instead of a string. - #o##"*a"#: reads the whole file, starting at the current position. On end of - file, it returns the empty string. - #o##"*l"#: reads the next line (skipping the end of line), returning#nil#on - end of file. This is the default format. - #o#@number@: reads a string with up to that number of characters, returning - #nil#on end of file. If number is zero, it reads nothing and returns an - empty string, or#nil#on end of file. - - -$file:seek ([whence] [, offset])$ *lrv-file:seek* ---------------------------------- -Sets and gets the file position, measured from the beginning of the file, to -the position given by$offset$plus a base specified by the string$whence$, as -follows: - - #o##"set"#: base is position 0 (beginning of the file); - #o##"cur"#: base is current position; - #o##"end"#: base is end of file; - -In case of success, function$seek$returns the final file position, measured in -bytes from the beginning of the file. If this function fails, it returns#nil#, -plus a string describing the error. - -The default value for$whence$is$"cur"$, and for$offset$is 0. Therefore, the -call$file:seek()$returns the current file position, without changing it; the -call$file:seek("set")$sets the position to the beginning of the file (and -returns 0); and the call$file:seek("end")$sets the position to the end of the -file, and returns its size. - - -$file:setvbuf (mode [, size])$ *lrv-file:setvbuf* ------------------------------- -Sets the buffering mode for an output file. There are three available modes: - - #o##"no"#: no buffering; the result of any output operation appears - immediately. - #o##"full"#: full buffering; output operation is performed only when the - buffer is full (or when you explicitly$flush$the file (see - |lrv-io.flush|). - #o##"line"#: line buffering; output is buffered until a newline is output or - there is any input from some special files (such as a terminal device). - -For the last two cases,$size$specifies the size of the buffer, in bytes. -The default is an appropriate size. - - -$file:write (...)$ *lrv-file:write* ------------------- -Writes the value of each of its arguments to$file$. The arguments must be -strings or numbers. To write other values, use$tostring$|lrv-tostring| or -$string.format$|lrv-string.format| before$write$. - - -============================================================================== -5.8 Operating System Facilities *lrv-libOS* - - -This library is implemented through table$os$. - - -$os.clock ()$ *lrv-os.clock* -------------- -Returns an approximation of the amount in seconds of CPU time used by the -program. - - -$os.date ([format [, time]])$ *lrv-os.date* ------------------------------ -Returns a string or a table containing date and time, formatted according to -the given string$format$. - -If the$time$argument is present, this is the time to be formatted (see the -$os.time$function |lrv-os.time| for a description of this value). Otherwise, -$date$formats the current time. - -If$format$starts with$'!'$,then the date is formatted in Coordinated Universal -Time. After this optional character, if$format$is the string$"*t"$, then$date$ -returns a table with the following fields:$year$(four digits),$month$(1-12), -$day$(1-31),$hour$(0-23),$min$(0-59),$sec$(0-61),$wday$(weekday, Sunday is 1), -$yday$(day of the year), and$isdst$(daylight saving flag, a boolean). - -If$format$is not$"*t"$, then$date$returns the date as a string, formatted -according to the same rules as the C function$strftime$. - -When called without arguments,$date$returns a reasonable date and time -representation that depends on the host system and on the current locale (that -is,$os.date()$is equivalent to$os.date("%c")$). - - -$os.difftime (t2, t1)$ *lrv-os.difftime* ----------------------- -Returns the number of seconds from time$t1$to time$t2$. In POSIX, Windows, and -some other systems, this value is exactly$t2 - t1$. - - -$os.execute ([command])$ *lrv-os.execute* ----------------------- -This function is equivalent to the C function$system$. It passes$command$to be -executed by an operating system shell. It returns a status code, which is -system-dependent. If$command$is absent, then it returns nonzero if a shell is -available and zero otherwise. - - -$os.exit ([code])$ *lrv-os.exit* ------------------- -Calls the C function$exit$, with an optional$code$, to terminate the host -program. The default value for$code$is the success code. - - -$os.getenv (varname)$ *lrv-os.getenv* ---------------------- -Returns the value of the process environment variable$varname$, or#nil#if the -variable is not defined. - - -$os.remove (filename)$ *lrv-os.remove* ----------------------- -Deletes the file with the given name. Directories must be empty to be removed. -If this function fails, it returns#nil#, plus a string describing the error. - - -$os.rename (oldname, newname)$ *lrv-os.rename* ------------------------------- -Renames file named$oldname$to$newname$. If this function fails, it returns -#nil#, plus a string describing the error. - - -$os.setlocale (locale [, category])$ *lrv-os.setlocale* ------------------------------------- -Sets the current locale of the program.$locale$is a string specifying a -locale;$category$is an optional string describing which category to change: -$"all"$,$"collate"$,$"ctype"$,$"monetary"$,$"numeric"$, or$"time"$; the -default category is$"all"$. The function returns the name of the new locale, -or#nil#if the request cannot be honored. - - -$os.time ([table])$ *lrv-os.time* -------------------- -Returns the current time when called without arguments, or a time representing -the date and time specified by the given table. This table must have fields -$year$,$month$, and$day$, and may have fields$hour$,$min$,$sec$, and$isdst$ -(for a description of these fields, see the$os.date$function |lrv-os.date|). - -The returned value is a number, whose meaning depends on your system. In -POSIX, Windows, and some other systems, this number counts the number of -seconds since some given start time (the "epoch"). In other systems, the -meaning is not specified, and the number returned by$time$can be used only as -an argument to$date$and$difftime$. - - -$os.tmpname ()$ *lrv-os.tmpname* ---------------- -Returns a string with a file name that can be used for a temporary file. The -file must be explicitly opened before its use and explicitly removed when no -longer needed. - - -============================================================================== -5.9 The Debug Library *lrv-libDebug* - - -This library provides the functionality of the debug interface to Lua -programs. You should exert care when using this library. The functions -provided here should be used exclusively for debugging and similar tasks, such -as profiling. Please resist the temptation to use them as a usual programming -tool: they can be very slow. Moreover, several of its functions violate some -assumptions about Lua code (e.g., that variables local to a function cannot be -accessed from outside or that userdata metatables cannot be changed by Lua -code) and therefore can compromise otherwise secure code. - -All functions in this library are provided inside the$debug$table. All -functions that operate over a thread have an optional first argument which is -the thread to operate over. The default is always the current thread. - - -$debug.debug ()$ *lrv-debug.debug* ----------------- -Enters an interactive mode with the user, running each string that the user -enters. Using simple commands and other debug facilities, the user can inspect -global and local variables, change their values, evaluate expressions, and so -on. A line containing only the word$cont$finishes this function, so that the -caller continues its execution. - -Note that commands for$debug.debug$are not lexically nested within any -function, and so have no direct access to local variables. - - -$debug.getfenv (o)$ *lrv-debug.getfenv* -------------------- -Returns the environment of object$o$. - - -$debug.gethook ([thread])$ *lrv-debug.gethook* --------------------------- -Returns the current hook settings of the thread, as three values: the current -hook function, the current hook mask, and the current hook count (as set by -the$debug.sethook$function). - - -$debug.getinfo ([thread,] function [, what])$ *lrv-debug.getinfo* ---------------------------------------------- -Returns a table with information about a function. You can give the function -directly, or you can give a number as the value of$function$, which means the -function running at level$function$of the call stack of the given thread: -level 0 is the current function ($getinfo$itself); level 1 is the function -that called$getinfo$; and so on. If$function$is a number larger than the -number of active functions, then$getinfo$returns#nil#. - -The returned table may contain all the fields returned by$lua_getinfo$(see -|lrv-lua_getinfo|), with the string$what$describing which fields to fill in. -The default for$what$is to get all information available, except the table of -valid lines. If present, the option$'f'$adds a field named$func$with the -function itself. If present, the option$'L'$adds a field named$activelines$ -with the table of valid lines. - -For instance, the expression$debug.getinfo(1,"n").name$returns the name of the -current function, if a reasonable name can be found, and$debug.getinfo(print)$ -returns a table with all available information about the$print$function. - - -$debug.getlocal ([thread,] level, local)$ *lrv-debug.getlocal* ------------------------------------------ -This function returns the name and the value of the local variable with index -$local$of the function at level$level$of the stack. (The first parameter or -local variable has index 1, and so on, until the last active local variable.) -The function returns#nil#if there is no local variable with the given index, -and raises an error when called with a$level$out of range. (You can call -$debug.getinfo$|lrv-debug.getinfo| to check whether the level is valid.) - -Variable names starting with$'('$(open parentheses) represent internal -variables (loop control variables, temporaries, and C function locals). - - -$debug.getmetatable (object)$ *lrv-debug.getmetatable* ------------------------------ -Returns the metatable of the given$object$or#nil#if it does not have a -metatable. - - -$debug.getregistry ()$ *lrv-debug.getregistry* ----------------------- -Returns the registry table (see |lrv-apiRegistry|). - - -$debug.getupvalue (func, up)$ *lrv-debug.getupvalue* ------------------------------ -This function returns the name and the value of the upvalue with index$up$of -the function$func$. The function returns#nil#if there is no upvalue with the -given index. - - -$debug.setfenv (object, table)$ *lrv-debug.setfenv* -------------------------------- -Sets the environment of the given$object$to the given$table$. Returns$object$. - - -$debug.sethook ([thread,] hook, mask [, count])$ *lrv-debug.sethook* ------------------------------------------------- -Sets the given function as a hook. The string$mask$and the number$count$ -describe when the hook will be called. The string mask may have the following -characters, with the given meaning: - - #o#@"c"@: The hook is called every time Lua calls a function; - #o#@"r"@: The hook is called every time Lua returns from a function; - #o#@"l"@: The hook is called every time Lua enters a new line of code. - -With a$count$different from zero, the hook is called after every$count$ -instructions. - -When called without arguments, the$debug.sethook$turns off the hook. - -When the hook is called, its first parameter is a string describing the -event that triggered its call:$"call"$,$"return"$(or$"tail return"$),$"line"$, -and$"count"$. For line events, the hook also gets the new line number as its -second parameter. Inside a hook, you can call$getinfo$with level 2 to get -more information about the running function (level 0 is the$getinfo$function, -and level 1 is the hook function), unless the event is$"tail return"$. In this -case, Lua is only simulating the return, and a call to$getinfo$will return -invalid data. - - -$debug.setlocal ([thread,] level, local, value)$ *lrv-debug.setlocal* ------------------------------------------------- -This function assigns the value$value$to the local variable with index$local$ -of the function at level$level$of the stack. The function returns#nil#if there -is no local variable with the given index, and raises an error when called -with a$level$out of range. (You can call$getinfo$to check whether the level is -valid.) Otherwise, it returns the name of the local variable. - - -$debug.setmetatable (object, table)$ *lrv-debug.setmetatable* ------------------------------------- -Sets the metatable for the given$object$to the given$table$(which can be -#nil#). - - -$debug.setupvalue (func, up, value)$ *lrv-debug.setupvalue* ------------------------------------- -This function assigns the value$value$to the upvalue with index$up$of the -function$func$. The function returns#nil#if there is no upvalue with the given -index. Otherwise, it returns the name of the upvalue. - - -$debug.traceback ([thread,] [message] [,level])$ *lrv-debug.traceback* ------------------------------------------------- -Returns a string with a traceback of the call stack. An optional$message$ -string is appended at the beginning of the traceback. An optional$level$number -tells at which level to start the traceback (default is 1, the function -calling$traceback$). - - -============================================================================== -6 LUA STAND-ALONE *lrv-lua* *lrv-LuaSA* -============================================================================== - - -Although Lua has been designed as an extension language, to be embedded in a -host C program, it is also frequently used as a stand-alone language. An -interpreter for Lua as a stand-alone language, called simply$lua$, is provided -with the standard distribution. The stand-alone interpreter includes all -standard libraries, including the debug library. Its usage is: -> - lua [options] [script [args]] -> -The options are: - - #o#$-e$@stat@: executes string@stat@; - #o#$-l$@mod@: "requires"@mod@; - #o#$-i$: enters interactive mode after running@script@; - #o#$-v$: prints version information; - #o#$--$: stops handling options; - #o#$-$: executes$stdin$as a file and stops handling options. - -After handling its options,$lua$runs the given@script@, passing to it the -given@args@as string arguments. When called without arguments,$lua$behaves -as$lua -v -i$when the standard input ($stdin$) is a terminal, and as -$lua -$otherwise. - -Before running any argument, the interpreter checks for an environment -variable$LUA_INIT$. If its format is$@filename$, then$lua$executes the file. -Otherwise,$lua$executes the string itself. - -All options are handled in order, except$-i$. For instance, an invocation -like -> - $ lua -e'a=1' -e 'print(a)' script.lua -> -will first set$a$to 1, then print the value of$a$(which is$'1'$), and finally -run the file$script.lua$with no arguments. (Here, '$' is the shell prompt. -Your prompt may be different.) - -Before starting to run the script,$lua$collects all arguments in the command -line in a global table called$arg$. The script name is stored in index 0, the -first argument after the script name goes to index 1, and so on. Any arguments -before the script name (that is, the interpreter name plus the options) go to -negative indices. For instance, in the call -> - $ lua -la b.lua t1 t2 -> -the interpreter first runs the file$a.lua$, then creates a table -> - arg = { [-2] = "lua", [-1] = "-la", - [0] = "b.lua", - [1] = "t1", [2] = "t2" } -> -and finally runs the file$b.lua$. The script is called with$arg[1]$,$arg[2]$, -... as arguments; it can also access these arguments with the vararg expression -$'...'$. - -In interactive mode, if you write an incomplete statement, the interpreter -waits for its completion by issuing a different prompt. - -If the global variable$_PROMPT$contains a string, then its value is used as -the prompt. Similarly, if the global variable$_PROMPT2$contains a string, its -value is used as the secondary prompt (issued during incomplete statements). -Therefore, both prompts can be changed directly on the command line. For -instance, -> - $ lua -e"_PROMPT='myprompt> '" -i -> -(the outer pair of quotes is for the shell, the inner pair is for Lua), or in -any Lua programs by assigning to$_PROMPT$. Note the use of$-i$to enter -interactive mode; otherwise, the program would just end silently right after -the assignment to$_PROMPT$. - -To allow the use of Lua as a script interpreter in Unix systems, the -stand-alone interpreter skips the first line of a chunk if it starts with$#$. -Therefore, Lua scripts can be made into executable programs by using$chmod +x$ -and the$#!$form, as in -> - #!/usr/local/bin/lua -> -(Of course, the location of the Lua interpreter may be different in your -machine. If$lua$is in your$PATH$, then -> - #!/usr/bin/env lua -> -is a more portable solution.) - - -============================================================================== -A BIBLIOGRAPHY *lrv-bibliography* -============================================================================== - -This help file is a minor adaptation from this main reference: - - #o# R. Ierusalimschy, L. H. de Figueiredo, and W. Celes., - "Lua: 5.1 reference manual",$http://www.lua.org/manual/5.1/manual.html$ - -Lua is discussed in these references: - - #o#R. Ierusalimschy, L. H. de Figueiredo, and W. Celes., - "Lua --- an extensible extension language". - @Software: Practice & Experience@#26##6 (1996) 635-652. - - #o#L. H. de Figueiredo, R. Ierusalimschy, and W. Celes., - "The design and implementation of a language for extending applications". - @Proc. of XXI Brazilian Seminar on Software and Hardware@(1994) 273-283. - - #o#L. H. de Figueiredo, R. Ierusalimschy, and W. Celes., - "Lua: an extensible embedded language". - @Dr. Dobb's Journal@#21##12 (Dec 1996) 26-33. - - #o#R. Ierusalimschy, L. H. de Figueiredo, and W. Celes., - "The evolution of an extension language: a history of Lua". - @Proc. of V Brazilian Symposium on Programming Languages@(2001) B-14-B-28. - - -============================================================================== -B COPYRIGHT & LICENSES *lrv-copyright* -============================================================================== - - -This help file has the same copyright and license as Lua 5.1 and the Lua 5.1 - manual: - -Copyright (c) 1994-2006 Lua.org, PUC-Rio. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -============================================================================== -C LUAREFVIM DOC *luarefvim* *luarefvimdoc* *lrv-help* *lrv-doc* -============================================================================== - - -This is a Vim help file containing a reference for Lua 5.1, and it is -- with -a few exceptions and adaptations -- a copy of the Lua 5.1 Reference Manual -(see |lrv-bibliography|). For usage information, refer to |lrv-docUsage|; for -instalation, refer to |lrv-docInstall|. - -This manual is composed of three parts: this file,$luarefvim.txt$, that is, -the manual itself; a plugin file, $luarefvim.vim$, defining key bindings; and -a help file syntax extension, $help.vim$. See |lrv-docInstall| for more -information on these files. For copyright information, see |lrv-copyright|. - -The main ideas and concepts on how to implement this reference were taken from -Christian Habermann's CRefVim project -($http://www.vim.org/scripts/script.php?script_id=614$). - - -============================================================================== -C.1 Installation *lrv-docInstall* - - -This reference consists of three files: the manual itself,$luarefvim.txt$, -a plugin file,$luarefvim.vim$, to load key bindings, and a help file syntax -extension$help.vim$. To install luarefvim, copy these files to their -respective locations: - - +-----------------+----------------+ - |# file #|# location #| - + ----------------+----------------+ - |$ luarefvim.txt $|$ doc $| - |$ luarefvim.vim $|$ plugin $| - |$ help.vim $|$ after/syntax $| - +-----------------+----------------+ - -where #location# is relative to 'runtimepath', that is, $HOME/.vim for a local -Un*x install or $HOME/vimfiles for a local Win32 install, for example. -Finally, to generate the tags, change dir to$doc$above (where you installed -$luarefvim.txt$), start Vim, and issue$:helptags .$For more information on -installing help files, call$:help add-local-help$. - - -============================================================================== -C.2 Usage *lrv-docUsage* - - -The usage is really simple, and similar to CRefVim: - - +----------+--------------+----------------------------------------+ - |# edit #|# key #| | - |# mode #|# sequence #|# action #| - +----------+--------------+----------------------------------------+ - |@ normal @| <Leader>lr | reference for word under cursor | - |@ visual @| <Leader>lr | reference for visually selected text | - |$ any $| <Leader>lc | manual's table of contents | - +----------+--------------+----------------------------------------+ - -Since by default <Leader> is mapped to$'\'$, just pressing$\lc$would bring the -table of contents, for example.$lr$stands for@(l)ua (r)eference@, while$lc$ -stands for@(l)ua (c)ontents@. - - ------------------------------------------------------------------------------- - vi:tw=78:ts=4:ft=help:norl:noai - diff --git a/files/.vim/doc/rails.txt b/files/.vim/doc/rails.txt deleted file mode 100644 index 2390100..0000000 --- a/files/.vim/doc/rails.txt +++ /dev/null @@ -1,1131 +0,0 @@ -*rails.txt* Plugin for working with Ruby on Rails applications - -Author: Tim Pope <vimNOSPAM@tpope.info> |rails-plugin-author| - -|rails-introduction| Introduction and Feature Summary -|rails-installation| Installation and Usage -|rails-install-vim| Installing and Configuring Vim -|rails-install-plugin| Installing and Using the Plugin -|rails-commands| General Commands -|rails-navigation| Navigation -|rails-gf| File Under Cursor - gf -|rails-alternate-related| Alternate and Related Files -|rails-model-navigation| Model Navigation Commands -|rails-controller-navigation| Controller Navigation Commands -|rails-misc-navigation| Miscellaneous Navigation Commands -|rails-custom-navigation| Custom Navigation Commands -|rails-scripts| Script Wrappers -|rails-refactoring| Refactoring Helpers -|rails-partials| Partial Extraction -|rails-migrations| Migration Inversion -|rails-integration| Integration -|rails-vim-integration| Integration with the Vim Universe -|rails-rails-integration| Integration with the Rails Universe -|rails-abbreviations| Abbreviations -|rails-syntax| Syntax Highlighting -|rails-options| Managed Vim Options -|rails-configuration| Configuration -|rails-global-settings| Global Settings -|rails-about| About rails.vim -|rails-license| License - -This plugin is only available if 'compatible' is not set. - -{Vi does not have any of this} - -============================================================================== -INTRODUCTION *rails-introduction* *rails* - -TextMate may be the latest craze for developing Ruby on Rails applications, -but Vim is forever. This plugin offers the following features for Ruby on -Rails application development. - -1. Automatically detects buffers containing files from Rails applications, - and applies settings to those buffers (and only those buffers). You can - use an autocommand to apply your own custom settings as well. - |rails-configuration| - -2. Unintrusive. Only files in a Rails application should be affected; regular - Ruby scripts are left untouched. Even when enabled, the plugin should keep - out of your way if you're not using its features. (If you find a situation - where this is not a case, contact the |rails-plugin-author|.) - -3. Provides reasonable settings for working with Rails applications. Rake is - the 'makeprg' (and it always knows where your Rakefile is), 'shiftwidth' - is 2, and 'path' includes an appropriate collection of directories from - your application. |rails-options| - -4. Easy navigation of the Rails directory structure. |gf| considers context - and knows about partials, fixtures, and much more. There are two commands, - :A (alternate) and :R (related) for easy jumping between files, including - favorites like model to migration, template to helper, and controller to - functional test. For more advanced usage, :Rmodel, :Rview, :Rcontroller, - and several other commands are provided. |rails-navigation| - -5. Enhanced syntax highlighting. From has_and_belongs_to_many to - distance_of_time_in_words, it's here. For Vim 7 users, 'completefunc' is - set to enable syntax based completion on |i_CTRL-X_CTRL-U|, making it easy - to complete such long method names. |rails-syntax| - -6. Interface to script/*. Generally, use ":Rscript about" to call - "script/about". Most commands have wrappers with additional features: - ":Rgenerate controller Blog" generates a blog controller and edits - app/controllers/blog_controller.rb. |rails-scripts| - -7. Partial extraction and migration inversion. |:Rextract| {file} replaces - the desired range (ideally selected in visual line mode) with "render - :partial => '{file}'", which is automatically created with your content. - The @{file} instance variable is replaced with the {file} local variable. - |:Rinvert| takes a self.up migration and writes a self.down. - |rails-refactoring| - -8. Integration with other plugins. |:Rproject| creates a new project.vim - project. |:Rdbext| loads database settings from database.yml for dbext.vim - (and this happens by default under most circumstances). Cream users get - some additional mappings, and all GUI users get a menu. |rails-integration| - -============================================================================== -INSTALLATION AND USAGE *rails-installation* - -If you are familiar Vim and have the latest version installed, you may skip -directly to |rails-install-plugin| below. - -Installing and Configuring Vim ~ - *rails-install-vim* -Because it is common for users to utilize an older version of Vim that came -installed on a system, rails.vim has a design goal of remaining compatible -with versions of Vim 6.2 and newer. However, if you have a choice in the -matter, you are strongly encouraged to install the latest version available. -Older versions of Vim should work, but increasingly, new plugin features will -require Vim 7 or newer. If possible, install a version of Vim with the |Ruby| -interface compiled in, as a few features will make use of it when available. - -If you are new to Vim, you need to create a vimrc. For Windows, this file -goes in ~\_vimrc (try :e ~\_vimrc if you don't know where this is). On other -platforms, use ~/.vimrc. A very minimal example file is shown below. -> - set nocompatible - syntax on - filetype plugin indent on -> -Installing and Using the Plugin ~ - *rails-install-plugin* -If you have the zip file, extract it to vimfiles (Windows) or ~/.vim -(everything else). You should have the following files: > - plugin/rails.vim - doc/rails.txt -See |add-local-help| for instructions on enabling the documentation. In a -nutshell: > - :helptags ~/.vim/doc - -Whenever you edit a file in a Rails application, this plugin will be -automatically activated. This sets various options and defines a few -buffer-specific commands. - -If you are in a hurry to get started, with a minimal amount of reading, you -are encouraged to at least skim through the headings and command names in this -file, to get a better idea of what is offered. If you only read one thing, -make sure it is the navigation section: |rails-navigation|. - -============================================================================== -GENERAL COMMANDS *rails-commands* - -All commands are buffer local, unless otherwise stated. This means you must -actually edit a file from a Rails application. - - *rails-:Rails* -:Rails {directory} The only global command. Creates a new Rails - application in {directory}, and loads the README. - - *rails-:Rake* -:Rake {targets} Like calling |:make| {targets} (with 'makeprg' being - rake). However, in some contexts, if {targets} are - omitted, :Rake defaults to something sensible (like - db:migrate in a migration, or your current test). - - *rails-:Rake!* -:Rake! {targets} Called with a bang, :Rake will use an alternate - 'errorformat' which attempts to parse the full stack - backtrace. - - *rails-:Rcd* -:Rcd [{directory}] |:cd| to /path/to/railsapp/{directory}. - - *rails-:Rlcd* -:Rlcd [{directory}] |:lcd| to /path/to/railsapp/{directory}. - - *rails-:Rdoc* -:Rdoc Browse to the Rails API, either in doc/api in the - current Rails application, gem_server if it is - running, or http://api.rubyonrails.org/ . Requires - :OpenURL to be defined (see |rails-:OpenURL|). - - *rails-:Rdoc!* -:Rdoc! Make the appropriate |:helptags| call and invoke - |:help| rails. - - *rails-:Redit* -:Redit {file} Edit {file}, relative to the application root. - - *rails-:Rlog* -:Rlog [{logfile}] Split window and open {logfile} ($RAILS_ENV or - development by default). The control characters used - for highlighting are removed. If you have a :Tail - command (provided by |tailminusf|.vim), that is used; - otherwise, the file does NOT reload upon change. - Use |:checktime| to tell Vim to check for changes. - |G| has been mapped to do just that prior to jumping - to the end of the file, and q is mapped to close the - window. If the delay in loading is too long, you - might like :Rake log:clear. - - *rails-:Rpreview* -:Rpreview [{path}] Creates a URL from http://localhost:3000/ and the - {path} given. If {path} is omitted, a sensible - default is used (considers the current - controller/template, but does not take routing into - account). The not too useful default is to then edit - this URL using Vim itself, allowing |netrw| to - download it. More useful is to define a :OpenURL - command, which will be used instead (see - |rails-:OpenURL|). - - *rails-:Rpreview!* -:Rpreview! [{path}] As with :Rpreview, except :OpenURL is never used. - - *rails-:Rtags* -:Rtags Calls ctags -R on the current application root. - Exuberant ctags must be installed. - - *rails-:Rrefresh* -:Rrefresh Refreshes certain cached settings. Most noticeably, - this clears the cached list of classes that are syntax - highlighted as railsUserClass. - - *rails-:Rrefresh!* -:Rrefresh! As above, and also reloads rails.vim. - - *rails-:OpenURL* -:OpenURL {url} This is not a command provided by the plugin, but - rather provided by user and utilized by other plugin - features. This command should be defined to open the - provided {url} in a web browser. An example command - on a Mac might be: > - :command -bar -nargs=1 OpenURL :!open <args> -< The following appears to work on Windows: > - :command -bar -nargs=1 OpenURL :!start cmd /cstart /b <args> -< On Debian compatible distributions, the following is - the preferred method: > - :command -bar -nargs=1 OpenURL :!sensible-browser <args> -< If has("mac_gui"), has("win32_gui"), or - executable("sensible-browser") is true, the - corresponding command above will be automatically - defined. Otherwise, you must provide your own (which - is recommended, regardless). - -============================================================================== -NAVIGATION *rails-navigation* - -Navigation is where the real power of this plugin lies. Efficient use of the -following features will greatly ease navigating the Rails file structure. - -The 'path' has been modified to include all the best places to be. -> - :find blog_controller - :find book_test -< - *rails-:Rfind* -:Rfind [{file}] Find {file}. Very similar to :find, but things like - BlogController are properly handled, and if - genutils.vim is installed (1.x not 2.x), tab complete - works. The default filename is taken from under the - cursor in a manner quite similar to gf, described - below. - -File Under Cursor - gf ~ - *rails-gf* -The |gf| command, which normally edits the current file under the cursor, has -been remapped to take context into account. |CTRL-W_f|(open in new window) and -|CTRL-W_gf| (open in new tab) are also remapped. - -Example uses of |gf|, and where they might lead. -(* indicates cursor position) -> - Pos*t.find(:first) -< app/models/post.rb ~ -> - has_many :c*omments -< app/models/comment.rb ~ -> - link_to "Home", :controller => :bl*og -< app/controllers/blog_controller.rb ~ -> - <%= render :partial => 'sh*ared/sidebar' %> -< app/views/shared/_sidebar.rhtml ~ -> - <%= stylesheet_link_tag :scaf*fold %> -< public/stylesheets/scaffold.css ~ -> - class BlogController < Applica*tionController -< app/controllers/application.rb ~ -> - class ApplicationController < ActionCont*roller::Base -< .../action_controller/base.rb ~ -> - fixtures :pos*ts -< test/fixtures/posts.yml ~ -> - layout :pri*nt -< app/views/layouts/print.rhtml ~ -> - <%= link_to "New", new_comme*nt_path %> -< app/controllers/comments_controller.rb (jumps to def new) ~ - -In the last example, the controller and action for the named route are -determined by evaluating routes.rb as Ruby and doing some introspection. This -means code from the application is executed. Keep this in mind when -navigating unfamiliar applications. - -Alternate and Related Files ~ - *rails-alternate-related* -Two commands, :A and :R, are used quickly jump to an "alternate" and a -"related" file, defined below. - - *rails-:A* *rails-:AE* *rails-:AS* *rails-:AV* *rails-:AT* -:A These commands were picked to mimic Michael Sharpe's -:AE a.vim. Briefly, they edit the "alternate" file, in -:AS either the same window (:A and :AE), a new split -:AV window (:AS), a new vertically split window (:AV), or -:AT a new tab (:AT). A mapping for :A is [f . - - *rails-:R* *rails-:RE* *rails-:RS* *rails-:RV* *rails-:RT* -:R These are similar |rails-:A| and friends above, only -:RE they jump to the "related" file rather than the -:RS "alternate." A mapping for :R is ]f . -:RV -:RT - - *rails-alternate* *rails-related* -The alternate file is most frequently the test file, though there are -exceptions. The related file varies, and is sometimes dependent on current -current location in the file. For example, when editing a controller, the -related file is template for the method currently being edited. - -The easiest way to learn these commands is to experiment. A few examples of -alternate and related files follow: - -Current file Alternate file Related file ~ -model unit test related migration -controller (in method) functional test template (view) -template (view) helper controller (jump to method) -migration previous migration next migration -config/routes.rb config/database.yml config/environment.rb - -Suggestions for further contexts to consider for the alternate file, related -file, and file under the cursor are welcome. They are subtly tweaked from -release to release. - -For the less common cases, a more deliberate set of commands are provided. -Each of the following takes an optional argument (with tab completion) but -defaults to a reasonable guess that follows Rails conventions. For example, -when editing app/models/employee.rb, :Rcontroller will default to -app/controllers/employees_controller.rb. The controller and model options, -ideally set from |rails-modelines|, can override the mapping from model -related files to controller related files (Rset controller=hiring) and vice -versa (Rset model=employee). See |rails-:Rset|. - -Each of the following commands has variants for splitting, vertical splitting -and opening in a new tab. For :Rmodel, those variants would be :RSmodel, -:RVmodel, and :RTmodel. There is also :REmodel which is a synonym for :Rmodel -(future versions might allow customization of the behavior of :Rmodel). - - -Model Navigation Commands ~ - *rails-model-navigation* -The default for model navigation commands is the current model, if it can be -determined. For example, test/unit/post_test.rb would have a current model -of post. Otherwise, if a controller name can be determined, said controller -name will be singularized and used. To override this, use a command or -modeline like: > - Rset model=comment - -:Rmodel |rails-:Rmodel| -:Rmigration |rails-:Rmigration| -:Robserver |rails-:Robserver| -:Rfixtures |rails-:Rfixtures| -:Runittest |rails-:Runittest| - - *rails-:Rmodel* -:Rmodel [{name}] Edit the specified model. - - *rails-:Rmigration* -:Rmigration [{pattern}] If {pattern} is a number, find the migration for that - particular set of digits, zero-padding if necessary. - Otherwise, find the newest migration containing the - given pattern. The pattern defaults to the current - model name, pluralized. So when editing the Post - model, :Rmigration with no arguments might find - create_posts.rb, or add_date_to_posts.rb. - - *rails-:Robserver* -:Robserver [{name}] Find the observer with a name like - {model}_observer.rb. When in an observer, most - commands (like :Rmodel) will seek based on the - observed model ({model}) and not the actual observer - ({model}_observer). However, for the command - :Runittest, a file of the form - {model}_observer_test.rb will be found. - - *rails-:Rfixtures* -:Rfixtures [{name}] Edit the fixtures for the given model. If an argument - is given, it must be pluralized, like the final - filename (this may change in the future). If omitted, - the current model is pluralized automatically. An - optional extension can be given, to distinguish - between YAML and CSV fixtures. - - *rails-:Runittest* -:Runittest [{name}] Edit the unit test for the specified model. - -Controller Navigation Commands ~ - *rails-controller-navigation* -The default for controller navigation commands is the current controller, if -it can be determined. For example, test/functional/blog_test.rb would have a -current controller of blog. Otherwise, if a model name can be determined, -said model name will be pluralized and used. To override this, use a command -or modeline like: > - Rset controller=blog - -:Rcontroller |rails-:Rcontroller| -:Rhelper |rails-:Rhelper| -:Rview |rails-:Rview| -:Rlayout |rails-:Rlayout| -:Rfunctionaltest |rails-:Rfunctionaltest| - - *rails-:Rcontroller* -:Rcontroller [{name}] Edit the specified controller. - - *rails-:Rhelper* -:Rhelper [{name}] Edit the helper for the specified controller. - - *rails-:Rview* -:Rview [[{controller}/]{view}] - Edit the specified view. The controller will default - sensibly, and the view name can be omitted when - editing a method of a controller. If a view name is - given with an extension, a new file will be created. - This is a quick way to create a new view. - - *rails-:Rlayout* -:Rlayout [{name}] Edit the specified layout. Defaults to the layout for - the current controller, or the application layout if - that cannot be found. A new layout will be created if - an extension is given. - - *rails-:Rapi* -:Rapi [{name}] Edit the API for the specified controller. This - command is deprecated; add it yourself with - |:Rcommand| if you still desire it. - - *rails-:Rfunctionaltest* -:Rfunctionaltest [{name}] - Edit the functional test for the specified controller. - -Miscellaneous Navigation Commands ~ - *rails-misc-navigation* - -The following commands are not clearly associated with models or controllers. - -:Rstylesheet |rails-:Rstylesheet| -:Rjavascript |rails-:Rjavascript| -:Rplugin |rails-:Rplugin| -:Rlib |rails-:Rlib| -:Rtask |rails-:Rtask| -:Rintegrationtest |rails-:Rintegrationtest| - - *rails-:Rstylesheet* -:Rstylesheet [{name}] Edit the stylesheet for the specified name, defaulting - to the current controller's name. - - *rails-:Rjavascript* -:Rjavascript [{name}] Edit the javascript for the specified name, defaulting - to the current controller's name. - - *rails-:Rplugin* -:Rplugin {plugin}[/{path}] - Edits a file within a plugin. If the path to the file - is omitted, it defaults to init.rb. - - *rails-:Rlib* -:Rlib {name} Edit the library from the lib directory for the - specified name. If the current file is part of a - plugin, the libraries from that plugin can be - specified as well. - - *rails-:Rtask* -:Rtask [{name}] Edit the .rake file from lib/tasks for the specified - name. If the current file is part of a plugin, the - tasks for that plugin can be specified as well. If no - argument is given, either the current plugin's - Rakefile or the application Rakefile will be edited. - - *rails-:Rintegrationtest* -:Rintegrationtest [{name}] - Edit the integration test specified. The default - is based on the current controller or model, with no - singularization or pluralization done. - -Custom Navigation Commands ~ - *rails-custom-navigation* - -It is also possible to create custom navigation commands. This is best done -in an initialization routine of some sort (e.g., an autocommand); see -|rails-configuration| for details. - - *rails-:Rcommand* -:Rcommand [options] {name} [{path} ...] - Create a navigation command with the supplied - name, looking in the supplied paths, using the - supplied options. The -suffix option specifies what - suffix to filter on, and strip from the filename, and - defaults to -suffix=.rb . The -glob option specifies - a file glob to use to find files, _excluding_ the - suffix. Useful values include -glob=* and -glob=**/*. - The -default option specifies a default argument (not - a full path). If it is specified as -default=model(), - -default=controller(), or -default=both(), the current - model, controller, or both (as with :Rintegrationtest) - is used as a default. - -:Rcommand is still under development and far from fully documented, but the -following examples should illustrate the basics: -> - Rcommand api app/apis -glob=**/* -suffix=_api.rb - Rcommand config config -glob=*.* -suffix= -default=routes.rb - Rcommand environment config/environments -default=../environment - Rcommand concern app/concerns -glob=**/* - -Finally, one Vim feature that proves helpful in conjunction with all of the -above is |CTRL-^|. This keystroke edits the previous file, and is helpful to -back out of any of the above commands. - -============================================================================== -SCRIPT WRAPPERS *rails-scripts* - -The following commands are wrappers around the scripts in the script directory -of the Rails application. Most have extra features beyond calling the script. -A limited amount of completion with <Tab> is supported. - - *rails-:Rscript* -:Rscript {script} {options} - Call ruby script/{script} {options}. - - *rails-:Rconsole* -:Rconsole {options} Start script/console. On Windows it will be launched - in the background with |!start|. In the terminal - version GNU Screen is used if it is running and - |g:rails_gnu_screen| is set. - - *rails-:Rrunner* -:[range]Rrunner {code} Executes {code} with script/runner. Differs from - :Rscript runner {code} in that the code is passed as - one argument. Also, |system()| is used instead of - |:!|. This is to help eliminate annoying "Press - ENTER" prompts. If a line number is given in the - range slot, the output is pasted into the buffer after - that line. - - *rails-:Rp* -:[range]Rp {code} Like :Rrunner, but call the Ruby p method on the - result. Literally "p begin {code} end". - - *rails-:Rpp* *rails-:Ry* -:[range]Rpp {code} Like :Rp, but with pp (pretty print) or y (YAML -:[range]Ry {code} output). - - *rails-:Rgenerate* -:Rgenerate {options} Calls script/generate {options}, and then edits the - first file generated. Respects |g:rails_subversion|. - - *rails-:Rdestroy* -:Rdestroy {options} Calls script/destroy {options}. Respects - |g:rails_subversion|. - - *rails-:Rserver* -:Rserver {options} Launches script/server {options} in the background. - On win32, this means |!start|. On other systems, this - uses the --daemon option. - - *rails-:Rserver!* -:Rserver! {options} Same as |:Rserver|, only first attempts to kill any - other server using the same port. On non-Windows - systems, lsof must be installed for this to work. - -============================================================================== -REFACTORING HELPERS *rails-refactoring* - -A few features are dedicated to helping you refactor your code. - -Partial Extraction ~ - *rails-partials* - -The :Rextract command can be used to extract a partial to a new file. - - *rails-:Rextract* -:[range]Rextract [{controller}/]{name} - Create a {name} partial from [range] lines (default: - current line). - - *rails-:Rpartial* -:[range]Rpartial [{controller}/]{name} - Deprecated alias for :Rextract. - -If this is your file, in app/views/blog/show.rhtml: > - - 1 <div> - 2 <h2><%= @post.title %></h2> - 3 <p><%= @post.body %></p> - 4 </div> - -And you issue this command: > - - :2,3Rextract post - -Your file will change to this: > - - 1 <div> - 2 <%= render :partial => 'post' %> - 3 </div> - -And app/views/blog/_post.rhtml will now contain: > - - 1 <h2><%= post.title %></h2> - 2 <p><%= post.body %></p> - -As a special case, if the file had looked like this: > - - 1 <% for object in @posts -%> - 2 <h2><%= object.title %></h2> - 3 <p><%= object.body %></p> - 4 <% end -%> -< -The end result would have been this: > - - 1 <%= render :partial => 'post', :collection => @posts %> -< -The easiest way to choose what to extract is to use |linewise-visual| mode. -Then, a simple > - :'<,'>Rextract blog/post -will suffice. (Note the use of a controller name in this example.) - -Migration Inversion ~ - *rails-migrations* *rails-:Rinvert* -:Rinvert In a migration, rewrite the self.up method into a - self.down method. If self.up is empty, the process is - reversed. This chokes on more complicated - instructions, but works reasonably well for simple - calls to create_table, add_column, and the like. - -============================================================================== -INTEGRATION *rails-integration* - -Having one foot in Rails and one in Vim, rails.vim has two worlds with which -to interact. - -Integration with the Vim Universe ~ - *rails-vim-integration* - -A handful of Vim plugins are enhanced by rails.vim. All plugins mentioned can -be found at http://www.vim.org/. Cream and GUI menus (for lack of a better -place) are also covered in this section. - - *rails-:Rproject* *rails-project* -:Rproject [{file}] This command is only provided when the |project| - plugin is installed. Invoke :Project (typically - without an argument), and search for the root of the - current Rails application. If it is not found, create - a new project, with appropriate directories (app, - etc., but not vendor). - - *rails-:Rproject!* -:Rproject! [{file}] Same as :Rproject, only delete existing project if it - exists and recreate it. The logic to delete the old - project is convoluted and possibly erroneous; report - any problems to the |rails-plugin-author|. A handy - mapping might look something like: > - autocmd User Rails map <buffer> <F6> :Rproject!|silent w<CR> -< As a bonus, this command organizes views into separate - directories for easier navigation. The downside of - this is that you will have to regenerate your project - each time you add another view directory (which is why - this command recreates your project each time!). - - *rails-:Rdbext* *rails-dbext* -:Rdbext [{environment}] This command is only provided when the |dbext| plugin - is installed. Loads the {environment} configuration - (defaults to $RAILS_ENV or development) from - config/database.yml and uses it to configure dbext. - The configuration is cached until a different Rails - application is edited. This command is called for you - automatically when |g:rails_dbext| is set (default on - non-Windows systems). - - *rails-:Rdbext!* -:Rdbext! [{environment}] - Load the database configuration as above, and then - attempt a CREATE DATABASE for it. This is primarily - useful for demonstrations. - - *rails-surround* -The |surround| plugin available from vim.org enables adding and removing -"surroundings" like parentheses, quotes, and HTML tags. Even by itself, it is -quite useful for Rails development, particularly eRuby editing. When coupled -with this plugin, a few additional replacement surroundings are available in -eRuby files. See the |surround| documentation for details on how to use them. -The table below uses ^ to represent the position of the surrounded text. - -Key Surrounding ~ -= <%= ^ %> -- <% ^ -%> -# <%# ^ %> -<C-E> <% ^ -%>\n<% end -%> - -The last surrounding is particularly useful in insert mode with the following -map in one's vimrc. Use Alt+o to open a new line below the current one. This -works nicely even in a terminal (where most alt/meta maps will fail) because -most terminals send <M-o> as <Esc>o anyways. -> - imap <M-o> <Esc>o -< -One can also use the <C-E> surrounding in a plain Ruby file to append a bare -"end" on the following line. - - *rails-cream* -This plugin provides a few additional key bindings if it is running under -Cream, the user friendly editor which uses Vim as a back-end. Ctrl+Enter -finds the file under the cursor (as in |rails-gf|), and Alt+[ and Alt+] find -the alternate (|rails-alternate|) and related (|rails-related|) files. - - *rails-menu* -If the GUI is running, a menu for several commonly used features is provided. -Also on this menu is a list of recently accessed projects. This list of -projects can persist across restarts if a 'viminfo' flag is set to enable -retaining certain global variables. If this interests you, add something like -the following to your vimrc: > - set viminfo^=! -< -Integration with the Rails Universe ~ - *rails-rails-integration* -The general policy of rails.vim is to focus exclusively on the Ruby on Rails -core. Supporting plugins and other add-ons to Rails has the potential to -rapidly get out of hand. However, a few pragmatic exceptions have been made. - - *rails-template-types* -Commands like :Rview use a hardwired list of extensions (rhtml, rjs, etc.) -when searching for files. In order to facilitate working with non-standard -template types, several popular extensions are featured in this list, -including haml, liquid, and mab (markaby). These extensions will disappear -once a related configuration option is added to rails.vim. - - *rails-rspec* -Support for RSpec is currently experimental and incomplete, with only a -handful of features being implemented. :A knows about specs and will jump to -them, but only if no test file is found. The associated controller or model -of a spec is detected, so all navigation commands should work as expected -inside a spec file. :Rfixtures will find spec fixtures, but the extension is -mandatory and tab completion will not work. :Rake will run the currently -edited spec. - -While there are currently no built-in dedicated RSpec navigation commands, you -can approximate your own with |:Rcommand|. -> - Rcommand specmodel spec/models -glob=**/* - \ -suffix=_spec.rb -default=model() - Rcommand spechelper spec/helpers -glob=**/* - \ -suffix=_helper_spec.rb -default=controller() - Rcommand speccontroller spec/controllers -glob=**/* - \ -suffix=_controller_spec.rb -default=controller() - Rcommand specview spec/views -glob=**/* -suffix=_view_spec.rb -< -============================================================================== -ABBREVIATIONS *rails-abbreviations* *rails-snippets* - -Abbreviations are still experimental. They may later be extracted into a -separate plugin, or removed entirely. - - *rails-:Rabbrev* -:Rabbrev List all Rails abbreviations. - -:Rabbrev {abbr} {expn} [{extra}] - Define a new Rails abbreviation. {extra} is permitted - if and only if {expn} ends with "(". - - *rails-:Rabbrev!* -:Rabbrev! {abbr} Remove an abbreviation. - -Rails abbreviations differ from regular abbreviations in that they only expand -after a <C-]> (see |i_CTRL-]|) or a <Tab> (if <Tab> does not work, it is -likely mapped by another plugin). If the abbreviation ends in certain -punctuation marks, additional expansions are possible. A few examples will -hopefully clear this up (all of the following are enabled by default in -appropriate file types). - -Command Sequence typed Resulting text ~ -Rabbrev rp( render :partial\ => rp( render(:partial => -Rabbrev rp( render :partial\ => rp<Tab> render :partial => -Rabbrev vs( validates_size_of vs( validates_size_of( -Rabbrev pa[ params pa[:id] params[:id] -Rabbrev pa[ params pa<C-]> params -Rabbrev pa[ params pa.inspect params.inspect -Rabbrev AR:: ActionRecord AR::Base ActiveRecord::Base -Rabbrev :a :action\ =>\ render :a<Tab> render :action => - -In short, :: expands on :, ( expands on (, and [ expands on both . and [. -These trailing punctuation marks are NOT part of the final abbreviation, and -you cannot have two mappings that differ only by punctuation. - -You must escape spaces in your expansion, either as "\ " or as "<Space>". For -an abbreviation ending with "(", you may define where to insert the -parenthesis by splitting the expansion into two parts (divided by an unescaped -space). - -Many abbreviations abbreviations are provided by default: use :Rabbrev to list -them. They vary depending on the type of file (models have different -abbreviations than controllers). There is one "smart" abbreviation, :c, which -expands to ":controller => ", ":collection => ", or ":conditions => " -depending on context. - -============================================================================== -SYNTAX HIGHLIGHTING *rails-syntax* - -Syntax highlighting is by and large a transparent process. For the full -effect, however, you need a colorscheme which accentuates rails.vim -extensions. One such colorscheme is vividchalk, available from vim.org. - -The following is a summary of the changes made by rails.vim to the standard -syntax highlighting. - - *rails-syntax-keywords* -Rails specific keywords are highlighted in a filetype specific manner. For -example, in a model, has_many is highlighted, whereas in a controller, -before_filter is highlighted. A wide variety of syntax groups are used but -they all link by default to railsMethod. - -If you feel a method has been wrongfully omitted, submit it to the -|rails-plugin-author|. - - *rails-@params* *rails-syntax-deprecated* -Certain deprecated syntax (like @params and render_text) is highlighted as an -error. If you trigger this highlighting, generally it means you need to -update your code. - - *rails-syntax-classes* -Models, helpers, and controllers are given special highlighting. Depending on -the version of Vim installed, you may need a rails.vim aware colorscheme in -order to see this. Said colorscheme needs to provide highlighting for the -railsUserClass syntax group. - -The class names are determined by camelizing filenames from certain -directories of your application. If app/models/line_item.rb exists, the class -"LineItem" will be highlighted. - -The list of classes is refreshed automatically after certain commands like -|:Rgenerate|. Use |:Rrefresh| to trigger the process manually. - - *rails-syntax-assertions* -If you define custom assertions in test_helper.rb, these will be highlighted -in your tests. These are found by scanning test_helper.rb for lines of the -form " def assert_..." and extracting the method name. The railsUserMethod -syntax group is used. The list of assertions can be refreshed with -|:Rrefresh|. - - *rails-syntax-strings* -In the following line of code, the "?" in the conditions clause and the "ASC" -in the order clause will be highlighted: > - Post.find(:all, :conditions => ["body like ?","%e%"] :order => "title ASC") -< -A string literal using %Q<> delimiters will have its contents highlighted as -HTML. This is sometimes useful when writing helpers. > - link = %Q<<a href="http://www.vim.org">Vim</a>> -< - *rails-syntax-yaml* -YAML syntax highlighting has been extended to highlight eRuby, which can be -used in most Rails YAML files (including database.yml and fixtures). - -============================================================================== -MANAGED VIM OPTIONS *rails-options* - -The following options are set local to buffers where the plugin is active. - - *rails-'shiftwidth'* *rails-'sw'* - *rails-'softtabstop'* *rails-'sts'* - *rails-'expandtab'* *rails-'et'* -A value of 2 is used for 'shiftwidth' (and 'softtabstop'), and 'expandtab' is -enabled. This is a strong convention in Rails, so the conventional wisdom -that this is a user preference has been ignored. - - *rails-'path'* *rails-'pa'* -All the relevant directories from your application are added to your 'path'. -This makes it easy to access a buried file: > - :find blog_controller.rb -< - *rails-'suffixesadd'* *rails-'sua'* -This is filetype dependent, but typically includes .rb, .rhtml, and several -others. This allows shortening the above example: > - :find blog_controller -< - *rails-'includeexpr'* *rails-'inex'* -The 'includeexpr' option is set to enable the magic described in |rails-gf|. - - *rails-'statusline'* *rails-'stl'* -Useful information is added to the 'statusline', when |g:rails_statusline| is -enabled. - - *rails-'makeprg'* *rails-'mp'* - *rails-'errorformat'* *rails-'efm'* -Rake is used as the 'makeprg', so |:make| will work as expected. Also, -'errorformat' is set appropriately to handle your tests. - - *rails-'filetype'* *rails-'ft'* -The 'filetype' is sometimes adjusted for Rails files. Most notably, *.rxml -and *.rjs are treated as Ruby files, and files that have been falsely -identified as Mason sources are changed back to eRuby files (but only when -they are part of a Rails application). - - *rails-'completefunc'* *rails-'cfu'* -A 'completefunc' is provided (if not already set). It is very simple, as it -uses syntax highlighting to make its guess. See |i_CTRL-X_CTRL-U|. - -============================================================================== -CONFIGURATION *rails-configuration* - -Very little configuration is actually required; this plugin automatically -detects your Rails application and adjusts Vim sensibly. - - *rails-:autocmd* *rails-autocommands* -If you would like to set your own custom Vim settings whenever a Rails file is -loaded, you can use an autocommand like the following in your vimrc: > - autocmd User Rails silent! Rlcd - autocmd User Rails map <buffer> <F9> :Rake<CR> -You can also have autocommands that only apply to certain types of files. -These are based off the information shown in the 'statusline' (see -|rails-'statusline'|), with hyphens changed to periods. A few examples: > - autocmd User Rails.controller* iabbr <buffer> wsn wsdl_service_name - autocmd User Rails.model.arb* iabbr <buffer> vfo validates_format_of - autocmd User Rails.view.rhtml* imap <buffer> <C-Z> <%= %><C-O>3h -End all such Rails autocommands with asterisks, even if you have an exact -specification. There is also a filename matching syntax: > - autocmd User Rails/db/schema.rb Rset task=db:schema:dump - autocmd User Rails/**/foo_bar.rb Rabbrev FB:: FooBar -Use the filetype based syntax whenever possible, reserving the filename based -syntax for more advanced cases. - - *macros/rails.vim* -If you have several commands to run on initialization for all file types, they -can be placed in a "macros/rails.vim" file in the 'runtimepath' (for example, -"~/.vim/macros/rails.vim"). This file is sourced by rails.vim each time a -Rails file is loaded. - - *config/rails.vim* -If you have settings particular to a specific project, they can be put in a -config/rails.vim file in the root directory of the application. The file is -sourced in the |sandbox| for security reasons. This only works in Vim 7 or -newer. - - *rails-:Rset* -:Rset {option}[={value}] - Query or set a local option. This command may be - called directly, from an autocommand, or from - config/rails.vim. - -Options may be set set in one of four scopes, which my be indicated by an -optional prefix. These scopes determine how broadly an option will apply. -Generally, the default scope is sufficient - -Scope Description ~ -a: All files in one Rails application -b: Buffer (file) specific -g: Global to all applications -l: Local to method (same as b: in non-Ruby files) - -Options are shown below with their default scope, which should be omitted. -While you may override the scope with a prefix, this is rarely necessary and -oftentimes useless. (For example, setting g:task is useless because the -default rake task will apply before considering this option.) - -Option Meaning ~ -b:alternate Custom alternate file for :A, relative to the Rails root -b:controller Default controller for certain commands (e.g., :Rhelper) -b:model Default model for certain commands (e.g., :Rfixtures) -l:preview URL stub for :Rpreview (e.g., blog/show/1) -b:task Default task used with :Rake -l:related Custom related file for :R, relative to the Rails root -a:root_url Root URL for commands like :Rpreview -a:ruby_fork_port Experimental: use ruby_fork on given port to speed things up - -Examples: > - :Rset root_url=http://localhost:12345 - :Rset related=app/views/blog/edit.rhtml preview=blog/edit/1 - :Rset alternate=app/models/ - :Rset l:task=preview " Special pseudo-task for :Rake - -Note the use of a scope prefix in the last example. - - *rails-modelines* -If |g:rails_modelines| is enabled, these options can also be set from -modelines near the beginning or end of the file. These modelines will always -set buffer-local options; scope should never be specified. Examples: > - # Rset task=db:schema:load - <%# Rset alternate=app/views/layouts/application.rhtml %> -Modelines can also be local to a method. Example: > - def test_comment - # rset alternate=app/models/comment.rb -These two forms differ only in case. - -============================================================================== -GLOBAL SETTINGS *rails-global-settings* - -A few global variables control the behavior of this plugin. In general, they -can be enabled by setting them to 1 in your vimrc, and disabled by setting -them to 0. > - let g:rails_some_option=1 - let g:rails_some_option=0 -Most of these should never need to be used. The few that might be interesting -are |g:rails_expensive|, |g:rails_subversion|, and |g:rails_default_database|. - - *g:loaded_rails* > - let g:loaded_rails=1 -Do not load the plugin. For emergency use only. - - *g:rails_abbreviations* -Enable Rails abbreviations. See |rails-abbreviations|. Enabled by default. - - *g:rails_dbext* > - let g:rails_dbext=1 -Enable integration with the dbext plugin, if it is installed. Defaults to the -value of |g:rails_expensive|. When this option is set, dbext settings are -automagically extracted from config/database.yml. Then, you can use features -like table name completion and commands like > - :Create database brablog_development - :Select * from posts where title like '%Denmark%' -Note that dbext is a complicated plugin, and may require additional -configuration. See |dbext| (if installed) and |sql-completion-dynamic| (in -Vim 7). - - *g:rails_default_file* > - let g:rails_default_file='config/database.yml' -File to load when a new Rails application is created, or when loading an -existing project from the menu. Defaults to the README. - - *g:rails_default_database* > - let g:rails_default_database='sqlite3' -Database to use for new applications. Defaults to letting Rails decide. - - *rails-slow* *g:rails_expensive* > - let g:rails_expensive=1 -Enables or disables expensive (slow) features (typically involving calls to -the Ruby interpreter). Recommended for moderately fast computers. This -option used to be disabled by default on Windows, but now it is enabled by -default everywhere. If the Vim Ruby interface is available, this option is -mostly ignored, as spawning a new process is generally the bottleneck for most -expensive operations. Set this option to 0 if you experience painful delays -when first editing a file from a Rails application. - - *rails-screen* *g:rails_gnu_screen* > - let g:rails_gnu_screen=1 -Use GNU Screen (if it is running) to launch |:Rconsole| and |:Rserver| in the -background. Enabled by default. - - *g:rails_history_size* > - let g:rails_history_size=5 -Number of projects to remember. Set to 0 to disable. See |rails-menu| for -information on retaining these projects across a restart. - - *g:rails_mappings* > - let g:rails_mappings=1 -Enables a few mappings (mostly for |rails-navigation|). Enabled by default. - - *g:rails_modelines* > - let g:rails_modelines=1 -Enable modelines like the following: > - # Rset task=db:schema:load -Modelines set buffer-local options using the :Rset command. -Also enables method specific modelines (note the case difference): > - def show - # rset preview=blog/show/1 -Modelines are extremely useful but may cause security concerns when editing -projects from an untrusted source. Enabled by default. - - *g:rails_menu* > - let g:rails_menu=1 -When 2, a Rails menu is created. When 1, this menu is a submenu under the -Plugin menu. The default is 1. - - *g:rails_url* > - let g:rails_url='http://localhost:3000/' -Used for the |:Rpreview| command. Default is as shown above. Overridden by -b:rails_url. - - *g:rails_statusline* > - let g:rails_statusline=1 -Give a clue in the statusline when this plugin is enabled. Enabled by -default. - - *g:rails_subversion* > - let g:rails_subversion=1 -Automatically add/remove files to the subversion repository for commands like -|:Rgenerate| and |:Rdestroy| (but not |:Rscript|). Ignored when the -application is not part of a subversion repository. Disabled by default. - - *g:rails_syntax* > - let g:rails_syntax=1 -When enabled, this tweaks the syntax highlighting to be more Rails friendly. -Enabled by default. See |rails-syntax|. - - *rails-tabs* *g:rails_tabstop* > - let g:rails_tabstop=4 -This option is for people who dislike the default 'shiftwidth' of 2. When -non-zero, all files will have a |:retab|! done with 'tabstop' set to 2 on -load, to convert the initial indent from spaces to tabs. Then, 'tabstop' and -'shiftwidth' will be set to the option's value. The process is reversed on -write. Thus, one can use a custom indent when editing files, yet conform to -Rails conventions when saving them. There is also a local buffer version -of this option, to allow for things like: > - autocmd User Rails if &ft == 'ruby' | let b:rails_tabstop = 4 | endif -This option defaults to 0, which is the recommended value. - -If instead of all this magic, you would prefer to just override this plugin's -settings and use your own custom 'shiftwidth', adjust things manually in an -autocommand: > - autocmd User Rails set sw=4 sts=4 noet -This is highly discouraged: don't fight Rails. - -============================================================================== -ABOUT *rails-about* *rails-plugin-author* - -This plugin was written by Tim Pope. Email him at <vimNOSPAM@tpope.info>. He -can also be found on Freenode's IRC network, hanging out in #rubyonrails and -#vim as tpope. - -The official homepage is - http://rails.vim.tpope.net -The latest stable version can be found at - http://www.vim.org/scripts/script.php?script_id=1567 -In Vim 7, you can keep up to date with |GetLatestVimScripts|. - -Development versions can be found at the following URLs: - http://tpope.us/rails.vba - http://tpope.us/rails.zip - http://svn.tpope.net/rails/vim/railsvim -The first is a |vimball| for Vim 7. The third is a subversion repository -and contains the very latest features and bugs. - -Feedback is highly desired on this plugin. Please send all comments, -complaints, and compliments to the author. No bug is too small to report. - - *rails-license* -This plugin is distributable under the same terms as Vim itself. See -|license|. No warranties, expressed or implied. - -============================================================================== -vim:tw=78:ts=8:ft=help:norl: diff --git a/files/.vim/doc/tags b/files/.vim/doc/tags deleted file mode 100644 index 287a004..0000000 --- a/files/.vim/doc/tags +++ /dev/null @@ -1,896 +0,0 @@ -'NERDChristmasTree' NERD_tree.txt /*'NERDChristmasTree'* -'NERDTreeAutoCenter' NERD_tree.txt /*'NERDTreeAutoCenter'* -'NERDTreeAutoCenterThreshold' NERD_tree.txt /*'NERDTreeAutoCenterThreshold'* -'NERDTreeBookmarksFile' NERD_tree.txt /*'NERDTreeBookmarksFile'* -'NERDTreeCaseSensitiveSort' NERD_tree.txt /*'NERDTreeCaseSensitiveSort'* -'NERDTreeChDirMode' NERD_tree.txt /*'NERDTreeChDirMode'* -'NERDTreeHighlightCursorline' NERD_tree.txt /*'NERDTreeHighlightCursorline'* -'NERDTreeIgnore' NERD_tree.txt /*'NERDTreeIgnore'* -'NERDTreeMouseMode' NERD_tree.txt /*'NERDTreeMouseMode'* -'NERDTreeQuitOnOpen' NERD_tree.txt /*'NERDTreeQuitOnOpen'* -'NERDTreeShowBookmarks' NERD_tree.txt /*'NERDTreeShowBookmarks'* -'NERDTreeShowFiles' NERD_tree.txt /*'NERDTreeShowFiles'* -'NERDTreeShowHidden' NERD_tree.txt /*'NERDTreeShowHidden'* -'NERDTreeShowLineNumbers' NERD_tree.txt /*'NERDTreeShowLineNumbers'* -'NERDTreeSortOrder' NERD_tree.txt /*'NERDTreeSortOrder'* -'NERDTreeWinPos' NERD_tree.txt /*'NERDTreeWinPos'* -'NERDTreeWinSize' NERD_tree.txt /*'NERDTreeWinSize'* -'Tlist_Auto_Highlight_Tag' taglist.txt /*'Tlist_Auto_Highlight_Tag'* -'Tlist_Auto_Open' taglist.txt /*'Tlist_Auto_Open'* -'Tlist_Auto_Update' taglist.txt /*'Tlist_Auto_Update'* -'Tlist_Close_On_Select' taglist.txt /*'Tlist_Close_On_Select'* -'Tlist_Compact_Format' taglist.txt /*'Tlist_Compact_Format'* -'Tlist_Ctags_Cmd' taglist.txt /*'Tlist_Ctags_Cmd'* -'Tlist_Display_Prototype' taglist.txt /*'Tlist_Display_Prototype'* -'Tlist_Display_Tag_Scope' taglist.txt /*'Tlist_Display_Tag_Scope'* -'Tlist_Enable_Fold_Column' taglist.txt /*'Tlist_Enable_Fold_Column'* -'Tlist_Exit_OnlyWindow' taglist.txt /*'Tlist_Exit_OnlyWindow'* -'Tlist_File_Fold_Auto_Close' taglist.txt /*'Tlist_File_Fold_Auto_Close'* -'Tlist_GainFocus_On_ToggleOpen' taglist.txt /*'Tlist_GainFocus_On_ToggleOpen'* -'Tlist_Highlight_Tag_On_BufEnter' taglist.txt /*'Tlist_Highlight_Tag_On_BufEnter'* -'Tlist_Inc_Winwidth' taglist.txt /*'Tlist_Inc_Winwidth'* -'Tlist_Max_Submenu_Items' taglist.txt /*'Tlist_Max_Submenu_Items'* -'Tlist_Max_Tag_Length' taglist.txt /*'Tlist_Max_Tag_Length'* -'Tlist_Process_File_Always' taglist.txt /*'Tlist_Process_File_Always'* -'Tlist_Show_Menu' taglist.txt /*'Tlist_Show_Menu'* -'Tlist_Show_One_File' taglist.txt /*'Tlist_Show_One_File'* -'Tlist_Sort_Type' taglist.txt /*'Tlist_Sort_Type'* -'Tlist_Use_Horiz_Window' taglist.txt /*'Tlist_Use_Horiz_Window'* -'Tlist_Use_Right_Window' taglist.txt /*'Tlist_Use_Right_Window'* -'Tlist_Use_SingleClick' taglist.txt /*'Tlist_Use_SingleClick'* -'Tlist_WinHeight' taglist.txt /*'Tlist_WinHeight'* -'Tlist_WinWidth' taglist.txt /*'Tlist_WinWidth'* -'loaded_nerd_tree' NERD_tree.txt /*'loaded_nerd_tree'* -'snippets' snipMate.txt /*'snippets'* -.snippet snipMate.txt /*.snippet* -.snippets snipMate.txt /*.snippets* -:CSApproxSnapshot CSApprox.txt /*:CSApproxSnapshot* -:MatchDebug matchit.txt /*:MatchDebug* -:NERDTree NERD_tree.txt /*:NERDTree* -:NERDTreeFromBookmark NERD_tree.txt /*:NERDTreeFromBookmark* -:NERDTreeToggle NERD_tree.txt /*:NERDTreeToggle* -:TlistAddFiles taglist.txt /*:TlistAddFiles* -:TlistAddFilesRecursive taglist.txt /*:TlistAddFilesRecursive* -:TlistClose taglist.txt /*:TlistClose* -:TlistDebug taglist.txt /*:TlistDebug* -:TlistHighlightTag taglist.txt /*:TlistHighlightTag* -:TlistLock taglist.txt /*:TlistLock* -:TlistMessages taglist.txt /*:TlistMessages* -:TlistOpen taglist.txt /*:TlistOpen* -:TlistSessionLoad taglist.txt /*:TlistSessionLoad* -:TlistSessionSave taglist.txt /*:TlistSessionSave* -:TlistShowPrototype taglist.txt /*:TlistShowPrototype* -:TlistShowTag taglist.txt /*:TlistShowTag* -:TlistToggle taglist.txt /*:TlistToggle* -:TlistUndebug taglist.txt /*:TlistUndebug* -:TlistUnlock taglist.txt /*:TlistUnlock* -:TlistUpdate taglist.txt /*:TlistUpdate* -CSApprox.txt CSApprox.txt /*CSApprox.txt* -ExtractSnips() snipMate.txt /*ExtractSnips()* -ExtractSnipsFile() snipMate.txt /*ExtractSnipsFile()* -Filename() snipMate.txt /*Filename()* -Lua-Reference lua51refvim.txt /*Lua-Reference* -MatchError matchit.txt /*MatchError* -NERDTree NERD_tree.txt /*NERDTree* -NERDTree-! NERD_tree.txt /*NERDTree-!* -NERDTree-? NERD_tree.txt /*NERDTree-?* -NERDTree-B NERD_tree.txt /*NERDTree-B* -NERDTree-C NERD_tree.txt /*NERDTree-C* -NERDTree-D NERD_tree.txt /*NERDTree-D* -NERDTree-F NERD_tree.txt /*NERDTree-F* -NERDTree-H NERD_tree.txt /*NERDTree-H* -NERDTree-J NERD_tree.txt /*NERDTree-J* -NERDTree-K NERD_tree.txt /*NERDTree-K* -NERDTree-O NERD_tree.txt /*NERDTree-O* -NERDTree-P NERD_tree.txt /*NERDTree-P* -NERDTree-R NERD_tree.txt /*NERDTree-R* -NERDTree-T NERD_tree.txt /*NERDTree-T* -NERDTree-U NERD_tree.txt /*NERDTree-U* -NERDTree-X NERD_tree.txt /*NERDTree-X* -NERDTree-c-j NERD_tree.txt /*NERDTree-c-j* -NERDTree-c-k NERD_tree.txt /*NERDTree-c-k* -NERDTree-contents NERD_tree.txt /*NERDTree-contents* -NERDTree-e NERD_tree.txt /*NERDTree-e* -NERDTree-f NERD_tree.txt /*NERDTree-f* -NERDTree-go NERD_tree.txt /*NERDTree-go* -NERDTree-gtab NERD_tree.txt /*NERDTree-gtab* -NERDTree-m NERD_tree.txt /*NERDTree-m* -NERDTree-o NERD_tree.txt /*NERDTree-o* -NERDTree-p NERD_tree.txt /*NERDTree-p* -NERDTree-q NERD_tree.txt /*NERDTree-q* -NERDTree-r NERD_tree.txt /*NERDTree-r* -NERDTree-t NERD_tree.txt /*NERDTree-t* -NERDTree-tab NERD_tree.txt /*NERDTree-tab* -NERDTree-u NERD_tree.txt /*NERDTree-u* -NERDTree-x NERD_tree.txt /*NERDTree-x* -NERDTreeAuthor NERD_tree.txt /*NERDTreeAuthor* -NERDTreeBookmarkCommands NERD_tree.txt /*NERDTreeBookmarkCommands* -NERDTreeBookmarkTable NERD_tree.txt /*NERDTreeBookmarkTable* -NERDTreeBookmarks NERD_tree.txt /*NERDTreeBookmarks* -NERDTreeChangelog NERD_tree.txt /*NERDTreeChangelog* -NERDTreeCredits NERD_tree.txt /*NERDTreeCredits* -NERDTreeFilesysMenu NERD_tree.txt /*NERDTreeFilesysMenu* -NERDTreeFunctionality NERD_tree.txt /*NERDTreeFunctionality* -NERDTreeGlobalCommands NERD_tree.txt /*NERDTreeGlobalCommands* -NERDTreeInvalidBookmarks NERD_tree.txt /*NERDTreeInvalidBookmarks* -NERDTreeLicense NERD_tree.txt /*NERDTreeLicense* -NERDTreeMappings NERD_tree.txt /*NERDTreeMappings* -NERDTreeOptionDetails NERD_tree.txt /*NERDTreeOptionDetails* -NERDTreeOptionSummary NERD_tree.txt /*NERDTreeOptionSummary* -NERDTreeOptions NERD_tree.txt /*NERDTreeOptions* -NERDTreePublicFunctions NERD_tree.txt /*NERDTreePublicFunctions* -NERDTreeTodo NERD_tree.txt /*NERDTreeTodo* -NERD_tree.txt NERD_tree.txt /*NERD_tree.txt* -ResetSnippets() snipMate.txt /*ResetSnippets()* -Tlist_Get_Tag_Prototype_By_Line() taglist.txt /*Tlist_Get_Tag_Prototype_By_Line()* -Tlist_Get_Tagname_By_Line() taglist.txt /*Tlist_Get_Tagname_By_Line()* -Tlist_Set_App() taglist.txt /*Tlist_Set_App()* -Tlist_Update_File_Tags() taglist.txt /*Tlist_Update_File_Tags()* -[% matchit.txt /*[%* -]% matchit.txt /*]%* -b:match_col matchit.txt /*b:match_col* -b:match_debug matchit.txt /*b:match_debug* -b:match_ignorecase matchit.txt /*b:match_ignorecase* -b:match_ini matchit.txt /*b:match_ini* -b:match_iniBR matchit.txt /*b:match_iniBR* -b:match_match matchit.txt /*b:match_match* -b:match_pat matchit.txt /*b:match_pat* -b:match_skip matchit.txt /*b:match_skip* -b:match_table matchit.txt /*b:match_table* -b:match_tail matchit.txt /*b:match_tail* -b:match_wholeBR matchit.txt /*b:match_wholeBR* -b:match_word matchit.txt /*b:match_word* -b:match_words matchit.txt /*b:match_words* -config/rails.vim rails.txt /*config\/rails.vim* -csapprox CSApprox.txt /*csapprox* -csapprox-+gui CSApprox.txt /*csapprox-+gui* -csapprox-aterm CSApprox.txt /*csapprox-aterm* -csapprox-author CSApprox.txt /*csapprox-author* -csapprox-changelog CSApprox.txt /*csapprox-changelog* -csapprox-configure CSApprox.txt /*csapprox-configure* -csapprox-design CSApprox.txt /*csapprox-design* -csapprox-eterm CSApprox.txt /*csapprox-eterm* -csapprox-gnome-terminal CSApprox.txt /*csapprox-gnome-terminal* -csapprox-gui-support CSApprox.txt /*csapprox-gui-support* -csapprox-hooks CSApprox.txt /*csapprox-hooks* -csapprox-intro CSApprox.txt /*csapprox-intro* -csapprox-iterm.app CSApprox.txt /*csapprox-iterm.app* -csapprox-konsole CSApprox.txt /*csapprox-konsole* -csapprox-kterm CSApprox.txt /*csapprox-kterm* -csapprox-limitations CSApprox.txt /*csapprox-limitations* -csapprox-mlterm CSApprox.txt /*csapprox-mlterm* -csapprox-mrxvt CSApprox.txt /*csapprox-mrxvt* -csapprox-palettes CSApprox.txt /*csapprox-palettes* -csapprox-pterm CSApprox.txt /*csapprox-pterm* -csapprox-putty CSApprox.txt /*csapprox-putty* -csapprox-requirements CSApprox.txt /*csapprox-requirements* -csapprox-roxterm CSApprox.txt /*csapprox-roxterm* -csapprox-screen CSApprox.txt /*csapprox-screen* -csapprox-terminal CSApprox.txt /*csapprox-terminal* -csapprox-terminal-example CSApprox.txt /*csapprox-terminal-example* -csapprox-terminal-list CSApprox.txt /*csapprox-terminal-list* -csapprox-terminal.app CSApprox.txt /*csapprox-terminal.app* -csapprox-terminals-bad CSApprox.txt /*csapprox-terminals-bad* -csapprox-terminals-good CSApprox.txt /*csapprox-terminals-good* -csapprox-toc CSApprox.txt /*csapprox-toc* -csapprox-transparency CSApprox.txt /*csapprox-transparency* -csapprox-urxvt CSApprox.txt /*csapprox-urxvt* -csapprox-wterm CSApprox.txt /*csapprox-wterm* -csapprox-xfce4-terminal CSApprox.txt /*csapprox-xfce4-terminal* -csapprox-xiterm CSApprox.txt /*csapprox-xiterm* -csapprox-xterm CSApprox.txt /*csapprox-xterm* -csapprox.vim CSApprox.txt /*csapprox.vim* -g% matchit.txt /*g%* -g:CSApprox_approximator_function CSApprox.txt /*g:CSApprox_approximator_function* -g:CSApprox_attr_map CSApprox.txt /*g:CSApprox_attr_map* -g:CSApprox_eterm CSApprox.txt /*g:CSApprox_eterm* -g:CSApprox_hook_post CSApprox.txt /*g:CSApprox_hook_post* -g:CSApprox_hook_pre CSApprox.txt /*g:CSApprox_hook_pre* -g:CSApprox_hook_{scheme}_post CSApprox.txt /*g:CSApprox_hook_{scheme}_post* -g:CSApprox_hook_{scheme}_pre CSApprox.txt /*g:CSApprox_hook_{scheme}_pre* -g:CSApprox_konsole CSApprox.txt /*g:CSApprox_konsole* -g:CSApprox_loaded CSApprox.txt /*g:CSApprox_loaded* -g:CSApprox_redirfallback CSApprox.txt /*g:CSApprox_redirfallback* -g:CSApprox_use_showrgb CSApprox.txt /*g:CSApprox_use_showrgb* -g:CSApprox_verbose_level CSApprox.txt /*g:CSApprox_verbose_level* -g:loaded_rails rails.txt /*g:loaded_rails* -g:rails_abbreviations rails.txt /*g:rails_abbreviations* -g:rails_dbext rails.txt /*g:rails_dbext* -g:rails_default_database rails.txt /*g:rails_default_database* -g:rails_default_file rails.txt /*g:rails_default_file* -g:rails_expensive rails.txt /*g:rails_expensive* -g:rails_gnu_screen rails.txt /*g:rails_gnu_screen* -g:rails_history_size rails.txt /*g:rails_history_size* -g:rails_mappings rails.txt /*g:rails_mappings* -g:rails_menu rails.txt /*g:rails_menu* -g:rails_modelines rails.txt /*g:rails_modelines* -g:rails_statusline rails.txt /*g:rails_statusline* -g:rails_subversion rails.txt /*g:rails_subversion* -g:rails_syntax rails.txt /*g:rails_syntax* -g:rails_tabstop rails.txt /*g:rails_tabstop* -g:rails_url rails.txt /*g:rails_url* -g:snippets_dir snipMate.txt /*g:snippets_dir* -g:snips_author snipMate.txt /*g:snips_author* -im_1 imaps.txt /*im_1* -imaps-usage imaps.txt /*imaps-usage* -imaps.txt imaps.txt /*imaps.txt* -imaps.txt-toc imaps.txt /*imaps.txt-toc* -java-parser-history javacomplete.txt /*java-parser-history* -javacomplete-ast javacomplete.txt /*javacomplete-ast* -javacomplete-commands javacomplete.txt /*javacomplete-commands* -javacomplete-compiler javacomplete.txt /*javacomplete-compiler* -javacomplete-constants javacomplete.txt /*javacomplete-constants* -javacomplete-download javacomplete.txt /*javacomplete-download* -javacomplete-faq javacomplete.txt /*javacomplete-faq* -javacomplete-features javacomplete.txt /*javacomplete-features* -javacomplete-functions javacomplete.txt /*javacomplete-functions* -javacomplete-history javacomplete.txt /*javacomplete-history* -javacomplete-install javacomplete.txt /*javacomplete-install* -javacomplete-kindletter javacomplete.txt /*javacomplete-kindletter* -javacomplete-launcher javacomplete.txt /*javacomplete-launcher* -javacomplete-limitations javacomplete.txt /*javacomplete-limitations* -javacomplete-options javacomplete.txt /*javacomplete-options* -javacomplete-overview javacomplete.txt /*javacomplete-overview* -javacomplete-parser javacomplete.txt /*javacomplete-parser* -javacomplete-reflection javacomplete.txt /*javacomplete-reflection* -javacomplete-requirements javacomplete.txt /*javacomplete-requirements* -javacomplete-sample javacomplete.txt /*javacomplete-sample* -javacomplete-thanks javacomplete.txt /*javacomplete-thanks* -javacomplete-todo javacomplete.txt /*javacomplete-todo* -javacomplete-usage javacomplete.txt /*javacomplete-usage* -javacomplete.txt javacomplete.txt /*javacomplete.txt* -lrv-API lua51refvim.txt /*lrv-API* -lrv-Lib lua51refvim.txt /*lrv-Lib* -lrv-LuaSA lua51refvim.txt /*lrv-LuaSA* -lrv-_G lua51refvim.txt /*lrv-_G* -lrv-_VERSION lua51refvim.txt /*lrv-_VERSION* -lrv-__add lua51refvim.txt /*lrv-__add* -lrv-__call lua51refvim.txt /*lrv-__call* -lrv-__concat lua51refvim.txt /*lrv-__concat* -lrv-__div lua51refvim.txt /*lrv-__div* -lrv-__eq lua51refvim.txt /*lrv-__eq* -lrv-__gc lua51refvim.txt /*lrv-__gc* -lrv-__index lua51refvim.txt /*lrv-__index* -lrv-__le lua51refvim.txt /*lrv-__le* -lrv-__len lua51refvim.txt /*lrv-__len* -lrv-__lt lua51refvim.txt /*lrv-__lt* -lrv-__mod lua51refvim.txt /*lrv-__mod* -lrv-__mode lua51refvim.txt /*lrv-__mode* -lrv-__mul lua51refvim.txt /*lrv-__mul* -lrv-__newindex lua51refvim.txt /*lrv-__newindex* -lrv-__pow lua51refvim.txt /*lrv-__pow* -lrv-__sub lua51refvim.txt /*lrv-__sub* -lrv-__tostring lua51refvim.txt /*lrv-__tostring* -lrv-__unm lua51refvim.txt /*lrv-__unm* -lrv-and lua51refvim.txt /*lrv-and* -lrv-apiCClosures lua51refvim.txt /*lrv-apiCClosures* -lrv-apiDebug lua51refvim.txt /*lrv-apiDebug* -lrv-apiError lua51refvim.txt /*lrv-apiError* -lrv-apiFunctions lua51refvim.txt /*lrv-apiFunctions* -lrv-apiPseudoIndices lua51refvim.txt /*lrv-apiPseudoIndices* -lrv-apiRegistry lua51refvim.txt /*lrv-apiRegistry* -lrv-apiStack lua51refvim.txt /*lrv-apiStack* -lrv-apiStackSize lua51refvim.txt /*lrv-apiStackSize* -lrv-assert lua51refvim.txt /*lrv-assert* -lrv-aux lua51refvim.txt /*lrv-aux* -lrv-auxFunctions lua51refvim.txt /*lrv-auxFunctions* -lrv-bibliography lua51refvim.txt /*lrv-bibliography* -lrv-block lua51refvim.txt /*lrv-block* -lrv-break lua51refvim.txt /*lrv-break* -lrv-capture lua51refvim.txt /*lrv-capture* -lrv-cclosure lua51refvim.txt /*lrv-cclosure* -lrv-cfunction lua51refvim.txt /*lrv-cfunction* -lrv-cfunctionexample lua51refvim.txt /*lrv-cfunctionexample* -lrv-chunk lua51refvim.txt /*lrv-chunk* -lrv-closure lua51refvim.txt /*lrv-closure* -lrv-collectgarbage lua51refvim.txt /*lrv-collectgarbage* -lrv-colonsyntax lua51refvim.txt /*lrv-colonsyntax* -lrv-comment lua51refvim.txt /*lrv-comment* -lrv-copyright lua51refvim.txt /*lrv-copyright* -lrv-coroutine lua51refvim.txt /*lrv-coroutine* -lrv-coroutine.create lua51refvim.txt /*lrv-coroutine.create* -lrv-coroutine.resume lua51refvim.txt /*lrv-coroutine.resume* -lrv-coroutine.running lua51refvim.txt /*lrv-coroutine.running* -lrv-coroutine.status lua51refvim.txt /*lrv-coroutine.status* -lrv-coroutine.wrap lua51refvim.txt /*lrv-coroutine.wrap* -lrv-coroutine.yield lua51refvim.txt /*lrv-coroutine.yield* -lrv-debug.debug lua51refvim.txt /*lrv-debug.debug* -lrv-debug.getfenv lua51refvim.txt /*lrv-debug.getfenv* -lrv-debug.gethook lua51refvim.txt /*lrv-debug.gethook* -lrv-debug.getinfo lua51refvim.txt /*lrv-debug.getinfo* -lrv-debug.getlocal lua51refvim.txt /*lrv-debug.getlocal* -lrv-debug.getmetatable lua51refvim.txt /*lrv-debug.getmetatable* -lrv-debug.getregistry lua51refvim.txt /*lrv-debug.getregistry* -lrv-debug.getupvalue lua51refvim.txt /*lrv-debug.getupvalue* -lrv-debug.setfenv lua51refvim.txt /*lrv-debug.setfenv* -lrv-debug.sethook lua51refvim.txt /*lrv-debug.sethook* -lrv-debug.setlocal lua51refvim.txt /*lrv-debug.setlocal* -lrv-debug.setmetatable lua51refvim.txt /*lrv-debug.setmetatable* -lrv-debug.setupvalue lua51refvim.txt /*lrv-debug.setupvalue* -lrv-debug.traceback lua51refvim.txt /*lrv-debug.traceback* -lrv-debugexample lua51refvim.txt /*lrv-debugexample* -lrv-do lua51refvim.txt /*lrv-do* -lrv-doc lua51refvim.txt /*lrv-doc* -lrv-docInstall lua51refvim.txt /*lrv-docInstall* -lrv-docUsage lua51refvim.txt /*lrv-docUsage* -lrv-dofile lua51refvim.txt /*lrv-dofile* -lrv-else lua51refvim.txt /*lrv-else* -lrv-elseif lua51refvim.txt /*lrv-elseif* -lrv-end lua51refvim.txt /*lrv-end* -lrv-environment lua51refvim.txt /*lrv-environment* -lrv-error lua51refvim.txt /*lrv-error* -lrv-false lua51refvim.txt /*lrv-false* -lrv-file:close lua51refvim.txt /*lrv-file:close* -lrv-file:flush lua51refvim.txt /*lrv-file:flush* -lrv-file:lines lua51refvim.txt /*lrv-file:lines* -lrv-file:read lua51refvim.txt /*lrv-file:read* -lrv-file:seek lua51refvim.txt /*lrv-file:seek* -lrv-file:setvbuf lua51refvim.txt /*lrv-file:setvbuf* -lrv-file:write lua51refvim.txt /*lrv-file:write* -lrv-for lua51refvim.txt /*lrv-for* -lrv-function lua51refvim.txt /*lrv-function* -lrv-getfenv lua51refvim.txt /*lrv-getfenv* -lrv-getmetatable lua51refvim.txt /*lrv-getmetatable* -lrv-help lua51refvim.txt /*lrv-help* -lrv-identifiers lua51refvim.txt /*lrv-identifiers* -lrv-if lua51refvim.txt /*lrv-if* -lrv-in lua51refvim.txt /*lrv-in* -lrv-intro lua51refvim.txt /*lrv-intro* -lrv-io.close lua51refvim.txt /*lrv-io.close* -lrv-io.flush lua51refvim.txt /*lrv-io.flush* -lrv-io.input lua51refvim.txt /*lrv-io.input* -lrv-io.lines lua51refvim.txt /*lrv-io.lines* -lrv-io.open lua51refvim.txt /*lrv-io.open* -lrv-io.output lua51refvim.txt /*lrv-io.output* -lrv-io.popen lua51refvim.txt /*lrv-io.popen* -lrv-io.read lua51refvim.txt /*lrv-io.read* -lrv-io.tmpfile lua51refvim.txt /*lrv-io.tmpfile* -lrv-io.type lua51refvim.txt /*lrv-io.type* -lrv-io.write lua51refvim.txt /*lrv-io.write* -lrv-ipairs lua51refvim.txt /*lrv-ipairs* -lrv-langArithOp lua51refvim.txt /*lrv-langArithOp* -lrv-langAssign lua51refvim.txt /*lrv-langAssign* -lrv-langBlocks lua51refvim.txt /*lrv-langBlocks* -lrv-langChunks lua51refvim.txt /*lrv-langChunks* -lrv-langCoercion lua51refvim.txt /*lrv-langCoercion* -lrv-langConcat lua51refvim.txt /*lrv-langConcat* -lrv-langContStructs lua51refvim.txt /*lrv-langContStructs* -lrv-langCoro lua51refvim.txt /*lrv-langCoro* -lrv-langEnvironments lua51refvim.txt /*lrv-langEnvironments* -lrv-langError lua51refvim.txt /*lrv-langError* -lrv-langExpressions lua51refvim.txt /*lrv-langExpressions* -lrv-langForStat lua51refvim.txt /*lrv-langForStat* -lrv-langFuncCalls lua51refvim.txt /*lrv-langFuncCalls* -lrv-langFuncDefs lua51refvim.txt /*lrv-langFuncDefs* -lrv-langFuncStat lua51refvim.txt /*lrv-langFuncStat* -lrv-langGC lua51refvim.txt /*lrv-langGC* -lrv-langGCMeta lua51refvim.txt /*lrv-langGCMeta* -lrv-langLength lua51refvim.txt /*lrv-langLength* -lrv-langLexConv lua51refvim.txt /*lrv-langLexConv* -lrv-langLocalDec lua51refvim.txt /*lrv-langLocalDec* -lrv-langLogOp lua51refvim.txt /*lrv-langLogOp* -lrv-langMetatables lua51refvim.txt /*lrv-langMetatables* -lrv-langPrec lua51refvim.txt /*lrv-langPrec* -lrv-langRelOp lua51refvim.txt /*lrv-langRelOp* -lrv-langStats lua51refvim.txt /*lrv-langStats* -lrv-langTableConst lua51refvim.txt /*lrv-langTableConst* -lrv-langValTypes lua51refvim.txt /*lrv-langValTypes* -lrv-langVariables lua51refvim.txt /*lrv-langVariables* -lrv-langVisibRules lua51refvim.txt /*lrv-langVisibRules* -lrv-langWeaktables lua51refvim.txt /*lrv-langWeaktables* -lrv-language lua51refvim.txt /*lrv-language* -lrv-libBasic lua51refvim.txt /*lrv-libBasic* -lrv-libCoro lua51refvim.txt /*lrv-libCoro* -lrv-libDebug lua51refvim.txt /*lrv-libDebug* -lrv-libIO lua51refvim.txt /*lrv-libIO* -lrv-libMath lua51refvim.txt /*lrv-libMath* -lrv-libModule lua51refvim.txt /*lrv-libModule* -lrv-libOS lua51refvim.txt /*lrv-libOS* -lrv-libString lua51refvim.txt /*lrv-libString* -lrv-libStringPat lua51refvim.txt /*lrv-libStringPat* -lrv-libTable lua51refvim.txt /*lrv-libTable* -lrv-lightuserdata lua51refvim.txt /*lrv-lightuserdata* -lrv-literal lua51refvim.txt /*lrv-literal* -lrv-load lua51refvim.txt /*lrv-load* -lrv-loadfile lua51refvim.txt /*lrv-loadfile* -lrv-loadstring lua51refvim.txt /*lrv-loadstring* -lrv-local lua51refvim.txt /*lrv-local* -lrv-lua lua51refvim.txt /*lrv-lua* -lrv-luaL_Buffer lua51refvim.txt /*lrv-luaL_Buffer* -lrv-luaL_Reg lua51refvim.txt /*lrv-luaL_Reg* -lrv-luaL_addchar lua51refvim.txt /*lrv-luaL_addchar* -lrv-luaL_addlstring lua51refvim.txt /*lrv-luaL_addlstring* -lrv-luaL_addsize lua51refvim.txt /*lrv-luaL_addsize* -lrv-luaL_addstring lua51refvim.txt /*lrv-luaL_addstring* -lrv-luaL_addvalue lua51refvim.txt /*lrv-luaL_addvalue* -lrv-luaL_argcheck lua51refvim.txt /*lrv-luaL_argcheck* -lrv-luaL_argerror lua51refvim.txt /*lrv-luaL_argerror* -lrv-luaL_buffinit lua51refvim.txt /*lrv-luaL_buffinit* -lrv-luaL_callmeta lua51refvim.txt /*lrv-luaL_callmeta* -lrv-luaL_checkany lua51refvim.txt /*lrv-luaL_checkany* -lrv-luaL_checkint lua51refvim.txt /*lrv-luaL_checkint* -lrv-luaL_checkinteger lua51refvim.txt /*lrv-luaL_checkinteger* -lrv-luaL_checklong lua51refvim.txt /*lrv-luaL_checklong* -lrv-luaL_checklstring lua51refvim.txt /*lrv-luaL_checklstring* -lrv-luaL_checknumber lua51refvim.txt /*lrv-luaL_checknumber* -lrv-luaL_checkoption lua51refvim.txt /*lrv-luaL_checkoption* -lrv-luaL_checkstack lua51refvim.txt /*lrv-luaL_checkstack* -lrv-luaL_checkstring lua51refvim.txt /*lrv-luaL_checkstring* -lrv-luaL_checktype lua51refvim.txt /*lrv-luaL_checktype* -lrv-luaL_checkudata lua51refvim.txt /*lrv-luaL_checkudata* -lrv-luaL_dofile lua51refvim.txt /*lrv-luaL_dofile* -lrv-luaL_dostring lua51refvim.txt /*lrv-luaL_dostring* -lrv-luaL_error lua51refvim.txt /*lrv-luaL_error* -lrv-luaL_getmetafield lua51refvim.txt /*lrv-luaL_getmetafield* -lrv-luaL_getmetatable lua51refvim.txt /*lrv-luaL_getmetatable* -lrv-luaL_gsub lua51refvim.txt /*lrv-luaL_gsub* -lrv-luaL_loadbuffer lua51refvim.txt /*lrv-luaL_loadbuffer* -lrv-luaL_loadfile lua51refvim.txt /*lrv-luaL_loadfile* -lrv-luaL_loadstring lua51refvim.txt /*lrv-luaL_loadstring* -lrv-luaL_newmetatable lua51refvim.txt /*lrv-luaL_newmetatable* -lrv-luaL_newstate lua51refvim.txt /*lrv-luaL_newstate* -lrv-luaL_openlibs lua51refvim.txt /*lrv-luaL_openlibs* -lrv-luaL_optint lua51refvim.txt /*lrv-luaL_optint* -lrv-luaL_optinteger lua51refvim.txt /*lrv-luaL_optinteger* -lrv-luaL_optlong lua51refvim.txt /*lrv-luaL_optlong* -lrv-luaL_optlstring lua51refvim.txt /*lrv-luaL_optlstring* -lrv-luaL_optnumber lua51refvim.txt /*lrv-luaL_optnumber* -lrv-luaL_optstring lua51refvim.txt /*lrv-luaL_optstring* -lrv-luaL_prepbuffer lua51refvim.txt /*lrv-luaL_prepbuffer* -lrv-luaL_pushresult lua51refvim.txt /*lrv-luaL_pushresult* -lrv-luaL_ref lua51refvim.txt /*lrv-luaL_ref* -lrv-luaL_register lua51refvim.txt /*lrv-luaL_register* -lrv-luaL_typename lua51refvim.txt /*lrv-luaL_typename* -lrv-luaL_typerror lua51refvim.txt /*lrv-luaL_typerror* -lrv-luaL_unref lua51refvim.txt /*lrv-luaL_unref* -lrv-luaL_where lua51refvim.txt /*lrv-luaL_where* -lrv-lua_Alloc lua51refvim.txt /*lrv-lua_Alloc* -lrv-lua_CFunction lua51refvim.txt /*lrv-lua_CFunction* -lrv-lua_Debug lua51refvim.txt /*lrv-lua_Debug* -lrv-lua_Hook lua51refvim.txt /*lrv-lua_Hook* -lrv-lua_Integer lua51refvim.txt /*lrv-lua_Integer* -lrv-lua_Number lua51refvim.txt /*lrv-lua_Number* -lrv-lua_Reader lua51refvim.txt /*lrv-lua_Reader* -lrv-lua_State lua51refvim.txt /*lrv-lua_State* -lrv-lua_Writer lua51refvim.txt /*lrv-lua_Writer* -lrv-lua_atpanic lua51refvim.txt /*lrv-lua_atpanic* -lrv-lua_call lua51refvim.txt /*lrv-lua_call* -lrv-lua_checkstack lua51refvim.txt /*lrv-lua_checkstack* -lrv-lua_close lua51refvim.txt /*lrv-lua_close* -lrv-lua_concat lua51refvim.txt /*lrv-lua_concat* -lrv-lua_cpcall lua51refvim.txt /*lrv-lua_cpcall* -lrv-lua_createtable lua51refvim.txt /*lrv-lua_createtable* -lrv-lua_dump lua51refvim.txt /*lrv-lua_dump* -lrv-lua_equal lua51refvim.txt /*lrv-lua_equal* -lrv-lua_error lua51refvim.txt /*lrv-lua_error* -lrv-lua_gc lua51refvim.txt /*lrv-lua_gc* -lrv-lua_getallocf lua51refvim.txt /*lrv-lua_getallocf* -lrv-lua_getfenv lua51refvim.txt /*lrv-lua_getfenv* -lrv-lua_getfield lua51refvim.txt /*lrv-lua_getfield* -lrv-lua_getglobal lua51refvim.txt /*lrv-lua_getglobal* -lrv-lua_gethook lua51refvim.txt /*lrv-lua_gethook* -lrv-lua_gethookcount lua51refvim.txt /*lrv-lua_gethookcount* -lrv-lua_gethookmask lua51refvim.txt /*lrv-lua_gethookmask* -lrv-lua_getinfo lua51refvim.txt /*lrv-lua_getinfo* -lrv-lua_getlocal lua51refvim.txt /*lrv-lua_getlocal* -lrv-lua_getmetatable lua51refvim.txt /*lrv-lua_getmetatable* -lrv-lua_getstack lua51refvim.txt /*lrv-lua_getstack* -lrv-lua_gettable lua51refvim.txt /*lrv-lua_gettable* -lrv-lua_gettop lua51refvim.txt /*lrv-lua_gettop* -lrv-lua_getupvalue lua51refvim.txt /*lrv-lua_getupvalue* -lrv-lua_insert lua51refvim.txt /*lrv-lua_insert* -lrv-lua_isboolean lua51refvim.txt /*lrv-lua_isboolean* -lrv-lua_iscfunction lua51refvim.txt /*lrv-lua_iscfunction* -lrv-lua_isfunction lua51refvim.txt /*lrv-lua_isfunction* -lrv-lua_islightuserdata lua51refvim.txt /*lrv-lua_islightuserdata* -lrv-lua_isnil lua51refvim.txt /*lrv-lua_isnil* -lrv-lua_isnumber lua51refvim.txt /*lrv-lua_isnumber* -lrv-lua_isstring lua51refvim.txt /*lrv-lua_isstring* -lrv-lua_istable lua51refvim.txt /*lrv-lua_istable* -lrv-lua_isthread lua51refvim.txt /*lrv-lua_isthread* -lrv-lua_isuserdata lua51refvim.txt /*lrv-lua_isuserdata* -lrv-lua_lessthan lua51refvim.txt /*lrv-lua_lessthan* -lrv-lua_load lua51refvim.txt /*lrv-lua_load* -lrv-lua_newstate lua51refvim.txt /*lrv-lua_newstate* -lrv-lua_newtable lua51refvim.txt /*lrv-lua_newtable* -lrv-lua_newthread lua51refvim.txt /*lrv-lua_newthread* -lrv-lua_newuserdata lua51refvim.txt /*lrv-lua_newuserdata* -lrv-lua_next lua51refvim.txt /*lrv-lua_next* -lrv-lua_objlen lua51refvim.txt /*lrv-lua_objlen* -lrv-lua_pcall lua51refvim.txt /*lrv-lua_pcall* -lrv-lua_pop lua51refvim.txt /*lrv-lua_pop* -lrv-lua_pushboolean lua51refvim.txt /*lrv-lua_pushboolean* -lrv-lua_pushcclosure lua51refvim.txt /*lrv-lua_pushcclosure* -lrv-lua_pushcfunction lua51refvim.txt /*lrv-lua_pushcfunction* -lrv-lua_pushfstring lua51refvim.txt /*lrv-lua_pushfstring* -lrv-lua_pushinteger lua51refvim.txt /*lrv-lua_pushinteger* -lrv-lua_pushlightuserdata lua51refvim.txt /*lrv-lua_pushlightuserdata* -lrv-lua_pushlstring lua51refvim.txt /*lrv-lua_pushlstring* -lrv-lua_pushnil lua51refvim.txt /*lrv-lua_pushnil* -lrv-lua_pushnumber lua51refvim.txt /*lrv-lua_pushnumber* -lrv-lua_pushstring lua51refvim.txt /*lrv-lua_pushstring* -lrv-lua_pushthread lua51refvim.txt /*lrv-lua_pushthread* -lrv-lua_pushvalue lua51refvim.txt /*lrv-lua_pushvalue* -lrv-lua_pushvfstring lua51refvim.txt /*lrv-lua_pushvfstring* -lrv-lua_rawequal lua51refvim.txt /*lrv-lua_rawequal* -lrv-lua_rawget lua51refvim.txt /*lrv-lua_rawget* -lrv-lua_rawgeti lua51refvim.txt /*lrv-lua_rawgeti* -lrv-lua_rawset lua51refvim.txt /*lrv-lua_rawset* -lrv-lua_rawseti lua51refvim.txt /*lrv-lua_rawseti* -lrv-lua_register lua51refvim.txt /*lrv-lua_register* -lrv-lua_remove lua51refvim.txt /*lrv-lua_remove* -lrv-lua_replace lua51refvim.txt /*lrv-lua_replace* -lrv-lua_resume lua51refvim.txt /*lrv-lua_resume* -lrv-lua_setallocf lua51refvim.txt /*lrv-lua_setallocf* -lrv-lua_setfenv lua51refvim.txt /*lrv-lua_setfenv* -lrv-lua_setfield lua51refvim.txt /*lrv-lua_setfield* -lrv-lua_setglobal lua51refvim.txt /*lrv-lua_setglobal* -lrv-lua_sethook lua51refvim.txt /*lrv-lua_sethook* -lrv-lua_setlocal lua51refvim.txt /*lrv-lua_setlocal* -lrv-lua_setmetatable lua51refvim.txt /*lrv-lua_setmetatable* -lrv-lua_settable lua51refvim.txt /*lrv-lua_settable* -lrv-lua_settop lua51refvim.txt /*lrv-lua_settop* -lrv-lua_setupvalue lua51refvim.txt /*lrv-lua_setupvalue* -lrv-lua_status lua51refvim.txt /*lrv-lua_status* -lrv-lua_toboolean lua51refvim.txt /*lrv-lua_toboolean* -lrv-lua_tocfunction lua51refvim.txt /*lrv-lua_tocfunction* -lrv-lua_tointeger lua51refvim.txt /*lrv-lua_tointeger* -lrv-lua_tolstring lua51refvim.txt /*lrv-lua_tolstring* -lrv-lua_tonumber lua51refvim.txt /*lrv-lua_tonumber* -lrv-lua_topointer lua51refvim.txt /*lrv-lua_topointer* -lrv-lua_tostring lua51refvim.txt /*lrv-lua_tostring* -lrv-lua_tothread lua51refvim.txt /*lrv-lua_tothread* -lrv-lua_touserdata lua51refvim.txt /*lrv-lua_touserdata* -lrv-lua_type lua51refvim.txt /*lrv-lua_type* -lrv-lua_typename lua51refvim.txt /*lrv-lua_typename* -lrv-lua_xmove lua51refvim.txt /*lrv-lua_xmove* -lrv-lua_yield lua51refvim.txt /*lrv-lua_yield* -lrv-math.abs lua51refvim.txt /*lrv-math.abs* -lrv-math.acos lua51refvim.txt /*lrv-math.acos* -lrv-math.asin lua51refvim.txt /*lrv-math.asin* -lrv-math.atan lua51refvim.txt /*lrv-math.atan* -lrv-math.atan2 lua51refvim.txt /*lrv-math.atan2* -lrv-math.ceil lua51refvim.txt /*lrv-math.ceil* -lrv-math.cos lua51refvim.txt /*lrv-math.cos* -lrv-math.cosh lua51refvim.txt /*lrv-math.cosh* -lrv-math.deg lua51refvim.txt /*lrv-math.deg* -lrv-math.exp lua51refvim.txt /*lrv-math.exp* -lrv-math.floor lua51refvim.txt /*lrv-math.floor* -lrv-math.fmod lua51refvim.txt /*lrv-math.fmod* -lrv-math.frexp lua51refvim.txt /*lrv-math.frexp* -lrv-math.huge lua51refvim.txt /*lrv-math.huge* -lrv-math.ldexp lua51refvim.txt /*lrv-math.ldexp* -lrv-math.log lua51refvim.txt /*lrv-math.log* -lrv-math.log10 lua51refvim.txt /*lrv-math.log10* -lrv-math.max lua51refvim.txt /*lrv-math.max* -lrv-math.min lua51refvim.txt /*lrv-math.min* -lrv-math.modf lua51refvim.txt /*lrv-math.modf* -lrv-math.pi lua51refvim.txt /*lrv-math.pi* -lrv-math.pow lua51refvim.txt /*lrv-math.pow* -lrv-math.rad lua51refvim.txt /*lrv-math.rad* -lrv-math.random lua51refvim.txt /*lrv-math.random* -lrv-math.randomseed lua51refvim.txt /*lrv-math.randomseed* -lrv-math.sin lua51refvim.txt /*lrv-math.sin* -lrv-math.sinh lua51refvim.txt /*lrv-math.sinh* -lrv-math.sqrt lua51refvim.txt /*lrv-math.sqrt* -lrv-math.tan lua51refvim.txt /*lrv-math.tan* -lrv-math.tanh lua51refvim.txt /*lrv-math.tanh* -lrv-metatable lua51refvim.txt /*lrv-metatable* -lrv-module lua51refvim.txt /*lrv-module* -lrv-names lua51refvim.txt /*lrv-names* -lrv-next lua51refvim.txt /*lrv-next* -lrv-nil lua51refvim.txt /*lrv-nil* -lrv-not lua51refvim.txt /*lrv-not* -lrv-number lua51refvim.txt /*lrv-number* -lrv-numconstant lua51refvim.txt /*lrv-numconstant* -lrv-openlibs lua51refvim.txt /*lrv-openlibs* -lrv-or lua51refvim.txt /*lrv-or* -lrv-os.clock lua51refvim.txt /*lrv-os.clock* -lrv-os.date lua51refvim.txt /*lrv-os.date* -lrv-os.difftime lua51refvim.txt /*lrv-os.difftime* -lrv-os.execute lua51refvim.txt /*lrv-os.execute* -lrv-os.exit lua51refvim.txt /*lrv-os.exit* -lrv-os.getenv lua51refvim.txt /*lrv-os.getenv* -lrv-os.remove lua51refvim.txt /*lrv-os.remove* -lrv-os.rename lua51refvim.txt /*lrv-os.rename* -lrv-os.setlocale lua51refvim.txt /*lrv-os.setlocale* -lrv-os.time lua51refvim.txt /*lrv-os.time* -lrv-os.tmpname lua51refvim.txt /*lrv-os.tmpname* -lrv-package.cpath lua51refvim.txt /*lrv-package.cpath* -lrv-package.loaded lua51refvim.txt /*lrv-package.loaded* -lrv-package.loadlib lua51refvim.txt /*lrv-package.loadlib* -lrv-package.path lua51refvim.txt /*lrv-package.path* -lrv-package.preload lua51refvim.txt /*lrv-package.preload* -lrv-package.seeall lua51refvim.txt /*lrv-package.seeall* -lrv-pairs lua51refvim.txt /*lrv-pairs* -lrv-pattern lua51refvim.txt /*lrv-pattern* -lrv-patternitem lua51refvim.txt /*lrv-patternitem* -lrv-patterns lua51refvim.txt /*lrv-patterns* -lrv-pcall lua51refvim.txt /*lrv-pcall* -lrv-print lua51refvim.txt /*lrv-print* -lrv-pseudoindex lua51refvim.txt /*lrv-pseudoindex* -lrv-rawequal lua51refvim.txt /*lrv-rawequal* -lrv-rawget lua51refvim.txt /*lrv-rawget* -lrv-rawset lua51refvim.txt /*lrv-rawset* -lrv-registry lua51refvim.txt /*lrv-registry* -lrv-repeat lua51refvim.txt /*lrv-repeat* -lrv-require lua51refvim.txt /*lrv-require* -lrv-return lua51refvim.txt /*lrv-return* -lrv-select lua51refvim.txt /*lrv-select* -lrv-setfenv lua51refvim.txt /*lrv-setfenv* -lrv-setmetatable lua51refvim.txt /*lrv-setmetatable* -lrv-stack lua51refvim.txt /*lrv-stack* -lrv-stackexample lua51refvim.txt /*lrv-stackexample* -lrv-stackindex lua51refvim.txt /*lrv-stackindex* -lrv-string lua51refvim.txt /*lrv-string* -lrv-string.byte lua51refvim.txt /*lrv-string.byte* -lrv-string.char lua51refvim.txt /*lrv-string.char* -lrv-string.dump lua51refvim.txt /*lrv-string.dump* -lrv-string.find lua51refvim.txt /*lrv-string.find* -lrv-string.format lua51refvim.txt /*lrv-string.format* -lrv-string.gmatch lua51refvim.txt /*lrv-string.gmatch* -lrv-string.gsub lua51refvim.txt /*lrv-string.gsub* -lrv-string.len lua51refvim.txt /*lrv-string.len* -lrv-string.lower lua51refvim.txt /*lrv-string.lower* -lrv-string.match lua51refvim.txt /*lrv-string.match* -lrv-string.rep lua51refvim.txt /*lrv-string.rep* -lrv-string.reverse lua51refvim.txt /*lrv-string.reverse* -lrv-string.sub lua51refvim.txt /*lrv-string.sub* -lrv-string.upper lua51refvim.txt /*lrv-string.upper* -lrv-table lua51refvim.txt /*lrv-table* -lrv-table.concat lua51refvim.txt /*lrv-table.concat* -lrv-table.foreach lua51refvim.txt /*lrv-table.foreach* -lrv-table.foreachi lua51refvim.txt /*lrv-table.foreachi* -lrv-table.insert lua51refvim.txt /*lrv-table.insert* -lrv-table.maxn lua51refvim.txt /*lrv-table.maxn* -lrv-table.remove lua51refvim.txt /*lrv-table.remove* -lrv-table.sort lua51refvim.txt /*lrv-table.sort* -lrv-tabletraversal lua51refvim.txt /*lrv-tabletraversal* -lrv-tailcall lua51refvim.txt /*lrv-tailcall* -lrv-then lua51refvim.txt /*lrv-then* -lrv-thread lua51refvim.txt /*lrv-thread* -lrv-tonumber lua51refvim.txt /*lrv-tonumber* -lrv-tostring lua51refvim.txt /*lrv-tostring* -lrv-true lua51refvim.txt /*lrv-true* -lrv-type lua51refvim.txt /*lrv-type* -lrv-types lua51refvim.txt /*lrv-types* -lrv-unpack lua51refvim.txt /*lrv-unpack* -lrv-until lua51refvim.txt /*lrv-until* -lrv-upvalue lua51refvim.txt /*lrv-upvalue* -lrv-userdata lua51refvim.txt /*lrv-userdata* -lrv-userdatatype lua51refvim.txt /*lrv-userdatatype* -lrv-vararg lua51refvim.txt /*lrv-vararg* -lrv-weaktable lua51refvim.txt /*lrv-weaktable* -lrv-while lua51refvim.txt /*lrv-while* -lrv-xpcall lua51refvim.txt /*lrv-xpcall* -luaref lua51refvim.txt /*luaref* -luarefvim lua51refvim.txt /*luarefvim* -luarefvim.txt lua51refvim.txt /*luarefvim.txt* -luarefvimdoc lua51refvim.txt /*luarefvimdoc* -macros/rails.vim rails.txt /*macros\/rails.vim* -matchit matchit.txt /*matchit* -matchit-% matchit.txt /*matchit-%* -matchit-\1 matchit.txt /*matchit-\\1* -matchit-activate matchit.txt /*matchit-activate* -matchit-backref matchit.txt /*matchit-backref* -matchit-bugs matchit.txt /*matchit-bugs* -matchit-choose matchit.txt /*matchit-choose* -matchit-configure matchit.txt /*matchit-configure* -matchit-debug matchit.txt /*matchit-debug* -matchit-details matchit.txt /*matchit-details* -matchit-highlight matchit.txt /*matchit-highlight* -matchit-hl matchit.txt /*matchit-hl* -matchit-intro matchit.txt /*matchit-intro* -matchit-languages matchit.txt /*matchit-languages* -matchit-modes matchit.txt /*matchit-modes* -matchit-newlang matchit.txt /*matchit-newlang* -matchit-o_% matchit.txt /*matchit-o_%* -matchit-parse matchit.txt /*matchit-parse* -matchit-s:notend matchit.txt /*matchit-s:notend* -matchit-s:sol matchit.txt /*matchit-s:sol* -matchit-spaces matchit.txt /*matchit-spaces* -matchit-troubleshoot matchit.txt /*matchit-troubleshoot* -matchit-v_% matchit.txt /*matchit-v_%* -matchit.txt matchit.txt /*matchit.txt* -matchit.vim matchit.txt /*matchit.vim* -multi_snip snipMate.txt /*multi_snip* -o_[% matchit.txt /*o_[%* -o_]% matchit.txt /*o_]%* -o_g% matchit.txt /*o_g%* -project project.txt /*project* -project-adding-mappings project.txt /*project-adding-mappings* -project-example project.txt /*project-example* -project-flags project.txt /*project-flags* -project-inheritance project.txt /*project-inheritance* -project-invoking project.txt /*project-invoking* -project-mappings project.txt /*project-mappings* -project-plugin project.txt /*project-plugin* -project-settings project.txt /*project-settings* -project-syntax project.txt /*project-syntax* -project-tips project.txt /*project-tips* -project.txt project.txt /*project.txt* -rails rails.txt /*rails* -rails-'cfu' rails.txt /*rails-'cfu'* -rails-'completefunc' rails.txt /*rails-'completefunc'* -rails-'efm' rails.txt /*rails-'efm'* -rails-'errorformat' rails.txt /*rails-'errorformat'* -rails-'et' rails.txt /*rails-'et'* -rails-'expandtab' rails.txt /*rails-'expandtab'* -rails-'filetype' rails.txt /*rails-'filetype'* -rails-'ft' rails.txt /*rails-'ft'* -rails-'includeexpr' rails.txt /*rails-'includeexpr'* -rails-'inex' rails.txt /*rails-'inex'* -rails-'makeprg' rails.txt /*rails-'makeprg'* -rails-'mp' rails.txt /*rails-'mp'* -rails-'pa' rails.txt /*rails-'pa'* -rails-'path' rails.txt /*rails-'path'* -rails-'shiftwidth' rails.txt /*rails-'shiftwidth'* -rails-'softtabstop' rails.txt /*rails-'softtabstop'* -rails-'statusline' rails.txt /*rails-'statusline'* -rails-'stl' rails.txt /*rails-'stl'* -rails-'sts' rails.txt /*rails-'sts'* -rails-'sua' rails.txt /*rails-'sua'* -rails-'suffixesadd' rails.txt /*rails-'suffixesadd'* -rails-'sw' rails.txt /*rails-'sw'* -rails-:A rails.txt /*rails-:A* -rails-:AE rails.txt /*rails-:AE* -rails-:AS rails.txt /*rails-:AS* -rails-:AT rails.txt /*rails-:AT* -rails-:AV rails.txt /*rails-:AV* -rails-:OpenURL rails.txt /*rails-:OpenURL* -rails-:R rails.txt /*rails-:R* -rails-:RE rails.txt /*rails-:RE* -rails-:RS rails.txt /*rails-:RS* -rails-:RT rails.txt /*rails-:RT* -rails-:RV rails.txt /*rails-:RV* -rails-:Rabbrev rails.txt /*rails-:Rabbrev* -rails-:Rabbrev! rails.txt /*rails-:Rabbrev!* -rails-:Rails rails.txt /*rails-:Rails* -rails-:Rake rails.txt /*rails-:Rake* -rails-:Rake! rails.txt /*rails-:Rake!* -rails-:Rapi rails.txt /*rails-:Rapi* -rails-:Rcd rails.txt /*rails-:Rcd* -rails-:Rcommand rails.txt /*rails-:Rcommand* -rails-:Rconsole rails.txt /*rails-:Rconsole* -rails-:Rcontroller rails.txt /*rails-:Rcontroller* -rails-:Rdbext rails.txt /*rails-:Rdbext* -rails-:Rdbext! rails.txt /*rails-:Rdbext!* -rails-:Rdestroy rails.txt /*rails-:Rdestroy* -rails-:Rdoc rails.txt /*rails-:Rdoc* -rails-:Rdoc! rails.txt /*rails-:Rdoc!* -rails-:Redit rails.txt /*rails-:Redit* -rails-:Rextract rails.txt /*rails-:Rextract* -rails-:Rfind rails.txt /*rails-:Rfind* -rails-:Rfixtures rails.txt /*rails-:Rfixtures* -rails-:Rfunctionaltest rails.txt /*rails-:Rfunctionaltest* -rails-:Rgenerate rails.txt /*rails-:Rgenerate* -rails-:Rhelper rails.txt /*rails-:Rhelper* -rails-:Rintegrationtest rails.txt /*rails-:Rintegrationtest* -rails-:Rinvert rails.txt /*rails-:Rinvert* -rails-:Rjavascript rails.txt /*rails-:Rjavascript* -rails-:Rlayout rails.txt /*rails-:Rlayout* -rails-:Rlcd rails.txt /*rails-:Rlcd* -rails-:Rlib rails.txt /*rails-:Rlib* -rails-:Rlog rails.txt /*rails-:Rlog* -rails-:Rmigration rails.txt /*rails-:Rmigration* -rails-:Rmodel rails.txt /*rails-:Rmodel* -rails-:Robserver rails.txt /*rails-:Robserver* -rails-:Rp rails.txt /*rails-:Rp* -rails-:Rpartial rails.txt /*rails-:Rpartial* -rails-:Rplugin rails.txt /*rails-:Rplugin* -rails-:Rpp rails.txt /*rails-:Rpp* -rails-:Rpreview rails.txt /*rails-:Rpreview* -rails-:Rpreview! rails.txt /*rails-:Rpreview!* -rails-:Rproject rails.txt /*rails-:Rproject* -rails-:Rproject! rails.txt /*rails-:Rproject!* -rails-:Rrefresh rails.txt /*rails-:Rrefresh* -rails-:Rrefresh! rails.txt /*rails-:Rrefresh!* -rails-:Rrunner rails.txt /*rails-:Rrunner* -rails-:Rscript rails.txt /*rails-:Rscript* -rails-:Rserver rails.txt /*rails-:Rserver* -rails-:Rserver! rails.txt /*rails-:Rserver!* -rails-:Rset rails.txt /*rails-:Rset* -rails-:Rstylesheet rails.txt /*rails-:Rstylesheet* -rails-:Rtags rails.txt /*rails-:Rtags* -rails-:Rtask rails.txt /*rails-:Rtask* -rails-:Runittest rails.txt /*rails-:Runittest* -rails-:Rview rails.txt /*rails-:Rview* -rails-:Ry rails.txt /*rails-:Ry* -rails-:autocmd rails.txt /*rails-:autocmd* -rails-@params rails.txt /*rails-@params* -rails-abbreviations rails.txt /*rails-abbreviations* -rails-about rails.txt /*rails-about* -rails-alternate rails.txt /*rails-alternate* -rails-alternate-related rails.txt /*rails-alternate-related* -rails-autocommands rails.txt /*rails-autocommands* -rails-commands rails.txt /*rails-commands* -rails-configuration rails.txt /*rails-configuration* -rails-controller-navigation rails.txt /*rails-controller-navigation* -rails-cream rails.txt /*rails-cream* -rails-custom-navigation rails.txt /*rails-custom-navigation* -rails-dbext rails.txt /*rails-dbext* -rails-gf rails.txt /*rails-gf* -rails-global-settings rails.txt /*rails-global-settings* -rails-install-plugin rails.txt /*rails-install-plugin* -rails-install-vim rails.txt /*rails-install-vim* -rails-installation rails.txt /*rails-installation* -rails-integration rails.txt /*rails-integration* -rails-introduction rails.txt /*rails-introduction* -rails-license rails.txt /*rails-license* -rails-menu rails.txt /*rails-menu* -rails-migrations rails.txt /*rails-migrations* -rails-misc-navigation rails.txt /*rails-misc-navigation* -rails-model-navigation rails.txt /*rails-model-navigation* -rails-modelines rails.txt /*rails-modelines* -rails-navigation rails.txt /*rails-navigation* -rails-options rails.txt /*rails-options* -rails-partials rails.txt /*rails-partials* -rails-plugin-author rails.txt /*rails-plugin-author* -rails-project rails.txt /*rails-project* -rails-rails-integration rails.txt /*rails-rails-integration* -rails-refactoring rails.txt /*rails-refactoring* -rails-related rails.txt /*rails-related* -rails-rspec rails.txt /*rails-rspec* -rails-screen rails.txt /*rails-screen* -rails-scripts rails.txt /*rails-scripts* -rails-slow rails.txt /*rails-slow* -rails-snippets rails.txt /*rails-snippets* -rails-surround rails.txt /*rails-surround* -rails-syntax rails.txt /*rails-syntax* -rails-syntax-assertions rails.txt /*rails-syntax-assertions* -rails-syntax-classes rails.txt /*rails-syntax-classes* -rails-syntax-deprecated rails.txt /*rails-syntax-deprecated* -rails-syntax-keywords rails.txt /*rails-syntax-keywords* -rails-syntax-strings rails.txt /*rails-syntax-strings* -rails-syntax-yaml rails.txt /*rails-syntax-yaml* -rails-tabs rails.txt /*rails-tabs* -rails-template-types rails.txt /*rails-template-types* -rails-vim-integration rails.txt /*rails-vim-integration* -rails.txt rails.txt /*rails.txt* -snipMate snipMate.txt /*snipMate* -snipMate-$# snipMate.txt /*snipMate-$#* -snipMate-${#:} snipMate.txt /*snipMate-${#:}* -snipMate-${#} snipMate.txt /*snipMate-${#}* -snipMate-author snipMate.txt /*snipMate-author* -snipMate-commands snipMate.txt /*snipMate-commands* -snipMate-contact snipMate.txt /*snipMate-contact* -snipMate-description snipMate.txt /*snipMate-description* -snipMate-disadvantages snipMate.txt /*snipMate-disadvantages* -snipMate-expandtab snipMate.txt /*snipMate-expandtab* -snipMate-features snipMate.txt /*snipMate-features* -snipMate-filename snipMate.txt /*snipMate-filename* -snipMate-indenting snipMate.txt /*snipMate-indenting* -snipMate-placeholders snipMate.txt /*snipMate-placeholders* -snipMate-remap snipMate.txt /*snipMate-remap* -snipMate-settings snipMate.txt /*snipMate-settings* -snipMate-usage snipMate.txt /*snipMate-usage* -snipMate.txt snipMate.txt /*snipMate.txt* -snippet snipMate.txt /*snippet* -snippet-syntax snipMate.txt /*snippet-syntax* -snippets snipMate.txt /*snippets* -taglist-commands taglist.txt /*taglist-commands* -taglist-debug taglist.txt /*taglist-debug* -taglist-extend taglist.txt /*taglist-extend* -taglist-faq taglist.txt /*taglist-faq* -taglist-functions taglist.txt /*taglist-functions* -taglist-install taglist.txt /*taglist-install* -taglist-internet taglist.txt /*taglist-internet* -taglist-intro taglist.txt /*taglist-intro* -taglist-keys taglist.txt /*taglist-keys* -taglist-license taglist.txt /*taglist-license* -taglist-menu taglist.txt /*taglist-menu* -taglist-options taglist.txt /*taglist-options* -taglist-requirements taglist.txt /*taglist-requirements* -taglist-session taglist.txt /*taglist-session* -taglist-todo taglist.txt /*taglist-todo* -taglist-using taglist.txt /*taglist-using* -taglist.txt taglist.txt /*taglist.txt* -v_[% matchit.txt /*v_[%* -v_]% matchit.txt /*v_]%* -v_a% matchit.txt /*v_a%* -v_g% matchit.txt /*v_g%* -xml-plugin-callbacks xml-plugin.txt /*xml-plugin-callbacks* -xml-plugin-html xml-plugin.txt /*xml-plugin-html* -xml-plugin-mappings xml-plugin.txt /*xml-plugin-mappings* -xml-plugin-settings xml-plugin.txt /*xml-plugin-settings* -xml-plugin.txt xml-plugin.txt /*xml-plugin.txt* diff --git a/files/.vim/ftdetect/asciidoc_filetype.vim b/files/.vim/ftdetect/asciidoc_filetype.vim deleted file mode 100644 index 4180ab0..0000000 --- a/files/.vim/ftdetect/asciidoc_filetype.vim +++ /dev/null @@ -1,53 +0,0 @@ -" Vim filetype detection file -" Language: AsciiDoc -" Author: Stuart Rackham <srackham@gmail.com> -" Last Change: AsciiDoc 8.2.0 -" URL: http://www.methods.co.nz/asciidoc/ -" Licence: GPL (http://www.gnu.org) -" Remarks: Vim 6 or greater - -" COMMENT OUT ONE OF THE TWO FOLLOWING COMMANDS -" The first sets asciidoc syntax highlighting on all .txt files, the second -" only existing files *.txt that appear to be AsciiDoc files. - -au BufNewFile,BufRead *.txt,README,TODO,CHANGELOG,NOTES setfiletype asciidoc -"au BufRead *.txt,README,TODO,CHANGELOG,NOTES call s:FTasciidoc() - -" This function checks for a valid AsciiDoc document title after first -" skipping any leading comments. -function! s:FTasciidoc() - let in_comment_block = 0 - let n = 1 - while n < 50 - let line = getline(n) - let n = n + 1 - if line =~ '^/\{4,}$' - if ! in_comment_block - let in_comment_block = 1 - else - let in_comment_block = 0 - endif - continue - endif - if in_comment_block - continue - endif - if line !~ '\(^//\)\|\(^\s*$\)' - break - endif - endwhile - if line !~ '.\{3,}' - return - endif - let len = len(line) - let line = getline(n) - if line !~ '[-=]\{3,}' - return - endif - if len < len(line) - 3 || len > len(line) + 3 - return - endif - setfiletype asciidoc -endfunction - -" vim: et sw=2 ts=2 sts=2: diff --git a/files/.vim/ftplugin/dockbk.vim b/files/.vim/ftplugin/dockbk.vim deleted file mode 120000 index 65289a9..0000000 --- a/files/.vim/ftplugin/dockbk.vim +++ /dev/null @@ -1 +0,0 @@ -xml.vim
\ No newline at end of file diff --git a/files/.vim/ftplugin/html.vim b/files/.vim/ftplugin/html.vim deleted file mode 100644 index 55e9023..0000000 --- a/files/.vim/ftplugin/html.vim +++ /dev/null @@ -1,1854 +0,0 @@ -" Vim script file vim600:fdm=marker: -" FileType: XML -" Author: Rene de Zwart <renez (at) lightcon.xs4all.nl> -" Maintainer: Rene de Zwart <renez (at) lightcon.xs4all.nl> -" Last Change: Date: 2009-11-12 -" Version: Revision: 1.37 -" -" Licence: This program is free software; you can redistribute it -" and/or modify it under the terms of the GNU General Public -" License. See http://www.gnu.org/copyleft/gpl.txt -" Credits: Devin Weaver <vim (at) tritarget.com> et all -" for the original code. Guo-Peng Wen for the self -" install documentation code. -" Bart vam Deenen for makeElement function -" Rene de Zwart - - -" Observation - If you want to do something to a match pair most of the time -" you must do first the close tag. Because doing first the open -" tag could change the close tag position. - -" NOTE with filetype index on de standard indent/html.vim interferes -" with xml.vim. You can -" 1) set filetype indent off in .vimrc -" 2) echo "let b:did_indent = 1" > .vim/indent/html.vim - - -" Only do this when not done yet for this buffer -if exists("b:did_ftplugin") - finish -endif -let b:did_ftplugin = 1 - -setlocal commentstring=<!--%s--> - -" XML: thanks to Johannes Zellner and Akbar Ibrahim -" - case sensitive -" - don't match empty tags <fred/> -" - match <!--, --> style comments (but not --, --) -" - match <!, > inlined dtd's. This is not perfect, as it -" gets confused for example by -" <!ENTITY gt ">"> -if exists("loaded_matchit") - let b:match_ignorecase=0 - let b:match_words = - \ '<:>,' . - \ '<\@<=!\[CDATA\[:]]>,'. - \ '<\@<=!--:-->,'. - \ '<\@<=?\k\+:?>,'. - \ '<\@<=\([^ \t>/]\+\)\%(\s\+[^>]*\%([^/]>\|$\)\|>\|$\):<\@<=/\1>,'. - \ '<\@<=\%([^ \t>/]\+\)\%(\s\+[^/>]*\|$\):/>' -endif - -" Script rgular expresion used. Documents those nasty criters {{{1 -let s:NoSlashBeforeGt = '\(\/\)\@\<!>' -" Don't check for quotes around attributes!!! -let s:Attrib = '\(\(\s\|\n\)\+\([^>= \t]\+=[^>&]\+\)\(\s\|\n\)*\)' -let s:OptAttrib = s:Attrib . '*'. s:NoSlashBeforeGt -let s:ReqAttrib = s:Attrib . '\+'. s:NoSlashBeforeGt -let s:OpenTag = '<[^!/?][^>]*' . s:OptAttrib -let s:OpenOrCloseTag = '<[^!?][^>]*'. s:OptAttrib -let s:CloseTag = '<\/[^>]*'. s:NoSlashBeforeGt -let s:SpaceInfront = '^\s*<' -let s:EndofName = '\($\|\s\|>\)' - -" Buffer variables {{{1 -let b:emptyTags='^\(img\|input\|param\|frame\|br\|hr\|meta\|link\|base\|area\)$' -let b:firstWasEndTag = 0 -let b:html_mode =((&filetype =~ 'x\?html') && !exists("g:xml_no_html")) -let b:haveAtt = 0 -let b:lastTag = "" -let b:lastAtt = "" -let b:suffix = (exists('g:makeElementSuf') ? g:makeElementSuf : ';;') -let b:xml_use_xhtml = 0 -if exists('g:xml_use_xhtml') - let b:xml_use_xhtml = g:xml_use_xhtml -elseif &filetype == 'xhtml' - let b:xml_use_xhtml = 1 -en - - - - -" NewFileXML -> Inserts <?xml?> at top of new file. {{{1 -if !exists("*NewFileXML") -function! NewFileXML( ) - " Where is g:did_xhtmlcf_inits defined? - if &filetype == 'xml' || - \ (!exists ("g:did_xhtmlcf_inits") && - \ b:xml_use_xhtml && - \ (&filetype =~ 'x\?html')) - if append (0, '<?xml version="1.0"?>') - normal! G - endif - endif -endfunction -endif - - - -" Callback -> Checks for tag callbacks and executes them. {{{1 -if !exists("*s:Callback") -function! s:Callback( xml_tag, isHtml ) - let text = 0 - if a:isHtml == 1 && exists ("*HtmlAttribCallback") - let text = HtmlAttribCallback (a:xml_tag) - elseif exists ("*XmlAttribCallback") - let text = XmlAttribCallback (a:xml_tag) - endif - if text != '0' - execute "normal! i " . text ."\<Esc>l" - endif -endfunction -endif - -" SavePos() saves position in bufferwide variable {{{1 -fun! s:SavePos() - retu 'call cursor('.line('.').','. col('.'). ')' -endf - -" findOpenTag() {{{1 -fun! s:findOpenTag(flag) - call search(s:OpenTag,a:flag) -endf - -" findCloseTag() {{{1 -fun! s:findCloseTag(flag) - call search(s:CloseTag,a:flag) -endf - -" GetTagName() Gets the tagname from start position {{{1 -"Now lets go for the name part. The namepart are xmlnamechars which -"is quite a big range. We assume that everything after '<' or '</' -"until the first 'space', 'forward slash' or '>' ends de name part. -if !exists('*s:GetTagName') -fun! s:GetTagName(from) - let l:end = match(getline('.'), s:EndofName,a:from) - return strpart(getline('.'),a:from, l:end - a:from ) -endf -en -" hasAtt() Looks for attribute in open tag {{{1 -" expect cursor to be on < -fun! s:hasAtt() - "Check if this open tag has attributes - let l:line = line('.') | let l:col = col('.') - if search(b:tagName . s:ReqAttrib,'W') > 0 - if l:line == line('.') && l:col == (col('.')-1) - let b:haveAtt = 1 - en - en -endf - - -" TagUnderCursor() Is there a tag under the cursor? {{{1 -" Set bufer wide variable -" - b:firstWasEndTag -" - b:tagName -" - b:endcol & b:endline only used by Match() -" - b:gotoCloseTag (if the tag under the cursor is one) -" - b:gotoOpenTag (if the tag under the cursor is one) -" on exit -" - returns 1 (true) or 0 (false) -" - position is at '<' -if !exists('*s:TagUnderCursor') -fun! s:TagUnderCursor() - let b:firstWasEndTag = 0 - let l:haveTag = 0 - let b:haveAtt = 0 - - "Lets find forward a < or a >. If we first find a > we might be in a tag. - "If we find a < first or nothing we are definitly not in a tag - - if getline('.')[col('.') - 1] == '>' - let b:endcol = col('.') - let b:endline = line('.') - if getline('.')[col('.')-2] == '/' - "we don't work with empty tags - retu l:haveTag - en - " begin: gwang customization for JSP development - if getline('.')[col('.')-2] == '%' - "we don't work with jsp %> tags - retu l:haveTag - en - " end: gwang customization for JSP development - " begin: gwang customization for PHP development - if getline('.')[col('.')-2] == '?' - "we don't work with php ?> tags - retu l:haveTag - en - " end: gwang customization for PHP development - elseif search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - let b:endcol = col('.') - let b:endline = line('.') - if getline('.')[col('.')-2] == '-' - "we don't work with comment tags - retu l:haveTag - en - if getline('.')[col('.')-2] == '/' - "we don't work with empty tags - retu l:haveTag - en - el - retu l:haveTag - en - el - retu l:haveTag - en - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' - if getline('.')[col('.')] == '/' - let b:firstWasEndTag = 1 - let b:gotoCloseTag = s:SavePos() - elseif getline('.')[col('.')] == '?' || getline('.')[col('.')] == '!' - "we don't deal with processing instructions or dtd - "related definitions - retu l:haveTag - el - let b:gotoOpenTag = s:SavePos() - en - el - retu l:haveTag - en - el - retu l:haveTag - en - - "we have established that we are between something like - "'</\?[^>]*>' - - let b:tagName = s:GetTagName(col('.') + b:firstWasEndTag) - "echo 'Tag ' . b:tagName - - "begin: gwang customization, do not work with an empty tag name - if b:tagName == '' - retu l:haveTag - en - "end: gwang customization, do not work with an empty tag name - - let l:haveTag = 1 - if b:firstWasEndTag == 0 - call s:hasAtt() - exe b:gotoOpenTag - en - retu l:haveTag -endf -en - -" Match(tagname) Looks for open or close tag of tagname {{{1 -" Set buffer wide variable -" - b:gotoCloseTag (if the Match tag is one) -" - b:gotoOpenTag (if the Match tag is one) -" on exit -" - returns 1 (true) or 0 (false) -" - position is at '<' -if !exists('*s:Match') -fun! s:Match(name) - let l:pat = '</\=' . a:name . s:OptAttrib - if b:firstWasEndTag - exe b:gotoCloseTag - let l:flags='bW' - let l:level = -1 - el - exe 'normal! '.b:endline.'G0'.(b:endcol-1).'l' - let l:flags='W' - let l:level = 1 - en - while l:level && search(l:pat,l:flags) > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level - echo "no matching tag!!!!!" - retu l:level - en - if b:firstWasEndTag - let b:gotoOpenTag = s:SavePos() - call s:hasAtt() - exe b:gotoOpenTag - el - let b:gotoCloseTag = s:SavePos() - en - retu l:level == 0 -endf -en - -" InComment() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:InComment') -fun! s:InComment() -let b:endcom=0 -let b:begcom=0 - - "Lets find forward a < or a >. If we first find a > we might be in a comment. - "If we find a < first or nothing we are definitly not in a Comment - - if getline('.')[col('.') - 1] == '>' - if getline('.')[col('.')-2] == '-' && getline('.')[col('.')-3] == '-' - let b:endcomcol=col('.') - let b:endcomline=line('.') - let b:endcom=1 - retu 1 - en - elseif getline('.')[col('.')-1] == '<' && getline('.')[col('.')] == '!' - \ && getline('.')[col('.')+1] == '-' && getline('.')[col('.')+2] == '-' - let b:begcomcol= col('.') - let b:begcomline=line('.') - let b:begcom=1 - retu 1 - en - "We are not standing on a begin/end comment - "Is the first > an ending comment? - if search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - if getline('.')[col('.')-2] == '-' && getline('.')[col('.')-3] == '-' - let b:endcomcol=col('.') - let b:endcomline=line('.') - let b:endcom=1 - retu 1 - en - en - en - "Forward is not a ending comment - "is backward a starting comment - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' && getline('.')[col('.')] == '!' - \ && getline('.')[col('.')+1] == '-' && getline('.')[col('.')+2] == '-' - let b:begcomcol=col('.') - let b:begcomline=line('.') - let b:begcom=1 - retu 1 - en - en - retu 0 -endf -en - -" DelComment() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelComment') -fun! s:DelComment() - - let l:restore = s:SavePos() - if s:InComment() - if b:begcom - if search('-->','W' ) >=0 - normal! hh3x - call cursor(b:begcomline,b:begcomcol) - normal! 4x - retu 1 - en - el - if search('<!--','bW' ) >=0 - normal! 4x - call cursor(b:endcomline,b:endcomcol) - normal! hh3x - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" DelCommentSection() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCommentSection') -fun! s:DelCommentSection() - - let l:restore = s:SavePos() - if s:InComment() - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - if b:begcom - if search('-->','W' ) >=0 - exe "normal! f>a".l:sentinel."\<Esc>" - call cursor(b:begcomline,b:begcomcol) - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - el - if search('<!--','bW' ) >=0 - let l:restore = s:SavePos() - call cursor(b:endcomline,b:endcomcol) - exe "normal! a".l:sentinel."\<Esc>" - exe l:restore - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" DelCData() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCData') -fun! s:DelCData() - - let l:restore = s:SavePos() - if s:InCData() - if b:begdat - if search(']]>','W' ) >=0 - normal! hh3x - call cursor(b:begdatline,b:begdatcol) - normal! 9x - retu 1 - en - el - if search('<![CDATA[','bW' ) >=0 - normal! 9x - call cursor(b:enddatline,b:enddatcol) - normal! hh3x - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" InCData() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:InCData') -fun! s:InCData() -let b:enddat=0 -let b:begdat=0 - - "Lets find forward a < or a >. If we first find a > we might be in a comment. - "If we find a < first or nothing we are definitly not in a Comment - - if getline('.')[col('.') - 1] == '>' - if getline('.')[col('.')-2] == ']' && getline('.')[col('.')-3] == ']' - let b:enddatcol=col('.') - let b:enddatline=line('.') - let b:enddat=1 - retu 1 - en - elseif getline('.')[col('.')-1] == '<' - if match(getline('.'),'<![CDATA[') > 0 - let b:begdatcol= col('.') - let b:begdatline=line('.') - let b:begdat=1 - retu 1 - en - en - "We are not standing on a begin/end comment - "Is the first > aending comment? - if search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - if getline('.')[col('.')-2] == ']' && getline('.')[col('.')-3] == ']' - let b:enddatcol=col('.') - let b:enddatline=line('.') - let b:enddat=1 - retu 1 - en - en - en - "Forward is not a ending datment - "is backward a starting comment - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' - if match(getline('.'),'<![CDATA[') > 0 - let l:newname = inputdialog('Found CDATA') - let b:begdatcol=col('.') - let b:begdatline=line('.') - let b:begdat=1 - retu 1 - en - en - en - retu 0 -endf -en - - -" DelCDataSection() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCDataSection') -fun! s:DelCDataSection() - - let l:restore = s:SavePos() - if s:InCData() - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - if b:begdat - if search(']]>','W' ) >=0 - exe "normal! f>a".l:sentinel."\<Esc>" - call cursor(b:begdatline,b:begdatcol) - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - el - if search('<![CDATA[','bW' ) >=0 - let l:restore = s:SavePos() - call cursor(b:enddatline,b:enddatcol) - exe "normal! a".l:sentinel."\<Esc>" - exe l:restore - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - - -" Matches() Matches de tagname under de cursor {{{1 -if !exists('*s:Matches') -fun! s:Matches() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - retu - en - en - exe l:restore -endf -en - -" MatchesVisual() Matches de tagname under de cursor {{{1 -if !exists('*s:MatchesVisual') -fun! s:MatchesVisual() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if b:firstWasEndTag - normal! f> - en - normal! gv - if s:Match(b:tagName) - if b:firstWasEndTag == 0 - normal! f> - en - retu - en - normal! v - en - exe l:restore -endf -en - -" makeElement() makes the previous woord an tag and close {{{1 -if !exists('*s:makeElement') -function! s:makeElement() - let b:tagName = @@ - let b:haveAtt = 0 - let l:alone = (match(getline('.'),'^\s*>\s*$') >= 0) - let l:endOfLine = ((col('.')+1) == col('$')) - normal! i<pf> - if b:html_mode && b:tagName =~? b:emptyTags - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - endif - if b:xml_use_xhtml - exe "normal! i/\<Esc>l" - en - if l:endOfLine - start! - el - normal! l - start - en - el - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - end - if l:alone - exe 'normal! o</pa>Ox>>$x' - start! - el - exe 'normal! a</pa>F<' - start - en - en -endfunction -en - -" CloseTagFun() closing the tag which is being typed {{{1 -if !exists('*s:CloseTagFun') -fun! s:CloseTagFun() - let l:restore = s:SavePos() - let l:endOfLine = ((col('.')+1) == col('$')) - if col('.') > 1 && getline('.')[col('.')-2] == '>' - "Multiline request. <t>></t> --> - "<t> - " cursor comes here - "</t> - normal! h - if s:TagUnderCursor() - if b:firstWasEndTag == 0 - exe "normal! 2f>s\<Cr>\<Esc>Ox\<Esc>>>$x" - start! - retu - en - en - elseif s:TagUnderCursor() - if b:firstWasEndTag == 0 - exe "normal! />\<Cr>" - if b:html_mode && b:tagName =~? b:emptyTags - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - en - if b:xml_use_xhtml - exe "normal! i/\<Esc>l" - en - if l:endOfLine - start! - retu - el - normal! l - start - retu - en - el - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - en - exe "normal! a</" . b:tagName . ">\<Esc>F<" - start - retu - en - en - en - exe l:restore - if (col('.')+1) == col("$") - startinsert! - else - normal! l - startinsert - en -endf -en - -" BlockTag() Surround a visual block with a tag {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:BlockTag') -fun! s:BlockTag(multi) - let l:newname = inputdialog('Surround block with : ',b:lastTag) - if strlen( l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - - "Get at the end of the block - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - if a:multi - exe "normal! a\<Cr></".l:newname.">\<Cr>\<Esc>" - let l:eline = line('.') - normal! gvov - if col('.') == col("'>") && line('.') == line("'>") - normal! gvov - en - let l:sline = line(".") + 2 - exe "normal! i\<Cr><".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \ .">\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe l:sline.','.l:eline.'>' - let &report= l:rep - exe 'normal! '.l:sline.'G0mh'.l:eline."G$v'hgq" - el - exe "normal! a</".l:newname.">\<Esc>gvov" - if col('.') == col("'>") && line('.') == line("'>") - normal! gvov - en - exe "normal! i<".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \ .">\<Esc>" - en -endf -en -" BlockWith() Surround a visual block with a open and a close {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:BlockWith') -fun! s:BlockWith(open,close) - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - exe "normal! a\<Cr>;x\<Esc>0cfx".a:close."\<Cr>\<Esc>" - normal! gvov - exe "normal! i\<Cr>;x\<Esc>0cfx".a:open."\<Cr>\<Esc>" -endf -en -" vlistitem() Surround a visual block with a listitem para tag {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:vlistitem') -fun! s:vlistitem() - "Get at the end of the block - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - exe "normal! a</para>\<Cr></listitem>\<Esc>mh" - normal! gvov - exe "normal! i\<Cr><listitem>\<Cr>\<Tab><para>\<Esc>'h/listitem>/e+1\<Cr>" -endf -en -" Change() Only renames the tag {{{1 -if !exists('*s:Change') -fun! s:Change() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = inputdialog('Change tag '.b:tagName.' to : ',b:lastTag) - if strlen( l:newname) == 0 - retu - en - let b:lastTag = l:newname - if s:Match(b:tagName) - exe b:gotoCloseTag - exe 'normal! 2lcw' . l:newname . "\<Esc>" - exe b:gotoOpenTag - exe 'normal! lcw' . l:newname . "\<Esc>" - en - en -endf -en - -" Join() Joins two the same tag adjacent sections {{{1 -if !exists('*s:Join') -fun! s:Join() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:pat = '<[^?!]\S\+\($\| \|\t\|>\)' - let l:flags='W' - if b:firstWasEndTag == 0 - let l:flags='Wb' - en - if search(s:OpenOrCloseTag,l:flags) > 0 - - let l:secondChar = getline('.')[col('.')] - if l:secondChar == '/' && b:firstWasEndTag ||l:secondChar != '/' && !b:firstWasEndTag - exe l:restore - retu - en - let l:end = 0 - if l:secondChar == '/' - let l:end = 1 - en - let l:name = s:GetTagName(col('.') + l:end) - if l:name == b:tagName - if b:firstWasEndTag - let b:gotoOpenTag = s:SavePos() - el - let b:gotoCloseTag = s:SavePos() - en - let l:DeleteTag = "normal! d/>/e\<Cr>" - exe b:gotoCloseTag - exe l:DeleteTag - exe b:gotoOpenTag - exe l:DeleteTag - en - en - en - exe l:restore -endf -en - -" ChangeWholeTag() removes attributes and rename tag {{{1 -if !exists('*s:ChangeWholeTag') -fun! s:ChangeWholeTag() - if s:TagUnderCursor() - let l:newname = inputdialog('Change whole tag '.b:tagName.' to : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! 2lc/>\<Cr>".l:newname."\<Esc>" - exe b:gotoOpenTag - exe "normal! lc/>/\<Cr>".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \."\<Esc>" - en - en -endf -en - -" Delete() Removes a tag '<a id="a">blah</a>' --> 'blah' {{{1 -if !exists('*s:Delete') -fun! s:Delete() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - let l:DeleteTag = "normal! d/>/e\<Cr>" - exe b:gotoCloseTag - exe l:DeleteTag - exe b:gotoOpenTag - exe l:DeleteTag - en - else - exe l:restore - en -endf -en - - -" DeleteSection() Deletes everything between start of open tag and end of {{{1 -" closing tag -if !exists('*s:DeleteSection') -fun! s:DeleteSection() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - let l:rep=&report - let &report=999999 - exe b:gotoCloseTag - exe "normal! />\<Cr>a".l:sentinel."\<Esc>" - exe b:gotoOpenTag - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - let &report= l:rep - en - en -endf -en -" -" FoldTag() Fold the tag under the cursor {{{1 -if !exists('*s:FoldTag') -fun! s:FoldTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - if b:firstWasEndTag - exe '.,'.l:sline.'fold' - el - exe l:sline.',.fold' - en - en - el - exe l:restore - en -endf -en - -" FoldTagAll() Fold all tags of under the cursor {{{1 -" If no tag under the cursor it asks for a tag -if !exists('*s:FoldTagAll') -fun! s:FoldTagAll() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:tname = b:tagName - el - let l:tname = inputdialog('Which tag to fold : ',b:lastTag) - if strlen(l:tname) == 0 - exe l:restore - retu - en - let b:lastTag = l:tname - en - normal! G$ - let l:flag='w' - while search('<'.l:tname.s:OptAttrib,l:flag) > 0 - let l:flag='W' - let l:sline = line('.') - let l:level = 1 - while l:level && search('</\='.l:tname.s:OptAttrib,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - exe l:sline.',.fold' - el - let l:tmp = - \ inputdialog("The tag ".l:tname."(".l:sline.") doesn't have a closetag") - break - en - endwhile - exe l:restore -endf -en - - -" StartTag() provide the opening tag {{{1 -if !exists('*s:StartTag') -fun! s:StartTag() - let l:restore = s:SavePos() - let l:level = 1 - if getline('.')[col('.')-1] == '<' - if s:TagUnderCursor() - if b:firstWasEndTag - exe 'normal! i<'. b:tagName.">\<Esc>F<" - retu - el - let l:level = l:level + 1 - en - en - exe l:restore - en - while l:level && search(s:OpenOrCloseTag ,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - let l:Name = s:GetTagName(col('.') + 1) - exe l:restore - exe 'normal! i<'. l:Name.">\<Esc>" - en - exe l:restore -endf -en - - - -" EndTag() search for open tag and produce endtaf {{{1 -if !exists('*s:EndTag') -fun! s:EndTag() - let l:restore = s:SavePos() - let l:level = -1 - while l:level && search(s:OpenOrCloseTag,'bW') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - let l:Name = s:GetTagName(col('.')) - exe l:restore - exe 'normal! a</'. l:Name.">\e" - el - exe l:restore - en -endf -en - - -" BeforeTag() surrounds the current tag with a new one {{{1 -if !exists('*s:BeforeTag') -fun! s:BeforeTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = - \ inputdialog('Surround Before Tag '.b:tagName.' with : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! />\<Cr>a\<Cr></" . l:newname . ">\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe 'normal! i<' . l:newname . - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \.">\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - exe l:restore - en -endf -en - -" CommentTag() surrounds the current tag with a new one {{{1 -if !exists('*s:CommentTag') -fun! s:CommentTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! />\<Cr>a\<Cr>-->\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe "normal! i<!--\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - else - exe l:restore - en -endf -en -" AfterTag() surrounds the tags after the current one with new {{{1 -if !exists('*s:AfterTag') -fun! s:AfterTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = - \ inputdialog('Add Tag After '.b:tagName.' with : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe 'normal! i</' . l:newname . ">\<Cr>\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe "normal! />\<Cr>a\<Cr><".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \.">\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - en - exe l:restore -endf -en -" ShiftRight() Shift the tag to the right {{{1 -if !exists('*s:ShiftRight') -fun! s:ShiftRight() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - let l:eline = line('.') - if b:firstWasEndTag - exe l:eline.','.l:sline.'>' - el - exe l:sline.','.l:eline.'>' - en - en - en -endf -en - -" ShiftLeft() Shift the tag to the left {{{1 -if !exists('*s:ShiftLeft') -fun! s:ShiftLeft() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - let l:eline = line('.') - if b:firstWasEndTag - exe l:eline.','.l:sline.'<' - el - exe l:sline.','.l:eline.'<' - en - en - en -endf -en -" FormatTag() visual select the block and use gq {{{1 -if !exists('*s:FormatTag') -fun! s:FormatTag() - if s:TagUnderCursor() - if s:Match(b:tagName) - exe b:gotoCloseTag - normal! hhmh - exe b:gotoOpenTag - exe "normal! />/e+1\<Cr>v'hgq" - en - en -endf -en - - - - -" FormatTagAll() Format all tags of name under the cursor {{{1 -" If no tag under the cursor it asks for a tag -if !exists('*s:FormatTagAll') -fun! s:FormatTagAll() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:tname = b:tagName - el - let l:tname = inputdialog('Format every tag : ') - if strlen(l:tname) == 0 - exe l:restore - retu - en - en - normal! G$ - let l:flag = 'w' - while search('<'.l:tname . s:OptAttrib, l:flag) > 0 - let l:flag = 'W' - let l:sline = line('.') - let l:level = 1 - exe "normal! />/e+1\<cr>mh" - while l:level && search('</\='.l:tname . s:EndofName,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - normal! hv'hogq - el - let l:tmp = - \ inputdialog("The tag ".l:tname."(".l:sline.") doesn't have a closetag") - break - en - endwhile - exe l:restore -endf -en - - -" IndentAll() indent all tags multiline {{{1 -if !exists('*s:IndentAll') -fun! s:IndentAll() - - let l:restore = s:SavePos() - let l:rep=&report - let &report=999999 - "shift everything left - normal! 1G<G<G<G<G<G<GG$ - if search(s:OpenTag,'w') > 0 - let l:level = 1 - normal! f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - echo "after tag".line('.') - exe "normal! a\<Cr>\<Esc>" - el - normal! j - en - normal! >Gk$ - while search(s:OpenOrCloseTag,'W') > 0 - "if there is text before the tag then move the tag to the next line - if match(getline('.'),s:SpaceInfront) == -1 - exe "normal! i\<Cr>\<Esc>l" - en - if getline('.')[col('.')] == '/' - normal! <G0f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - exe "normal! a\<Cr>\<Esc>" - en - let l:level = l:level - 1 - el - normal! f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - exe "normal! a\<Cr>\<Esc>" - el - normal! j0 - en - normal! >Gk$ - let l:level = l:level + 1 - en - endwhile - if l:level - let l:tmp = - \ inputdialog("The tags opening and closing are unbalanced ".l:level) - en - en - exe l:restore - let &report= l:rep -endf -en - - -" Menu options: {{{1 -augroup XML_menu_autos -au! -autocmd BufLeave,BufWinLeave * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ amenu disable Xml | - \ amenu disable Xml.* | - \ endif -autocmd BufEnter,BufWinEnter * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ amenu enable Xml | - \ amenu enable Xml.* | - \ endif -au BufNewFile * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ call NewFileXML() | - \ endif -augroup END -if !exists("g:did_xml_menu") - let g:did_xml_menu = 1 - :1011 vmenu <script> &Xml.BlockTag\ multi<Tab>V <Esc>:call <SID>BlockTag(1)<Cr> - vmenu <script> Xml.BlockTag\ inline<Tab>v <Esc>:call <SID>BlockTag(0)<CR> - vmenu <script> Xml.Insert\ listitem<Tab>l <Esc>:call <SID>vlistitem()<CR> - vmenu <script> Xml.Comment<Tab>< <Esc>:call <SID>BlockWith('<!--','-->')<Cr> - vmenu <script> Xml.Comment\ With\ CData<Tab>c <Esc>:call <SID>BlockWith('<![CDATA[',']]>')<Cr> - nmenu <script> Xml.Comment\ Tag<Tab>= <Esc>:call <SID>CommentTag()<Cr> - imenu <script> Xml.Comment\ Tag<Tab>= <Esc>:call <SID>CommentTag()<Cr> - nmenu <script> Xml.Change<Tab>c :call <SID>Change()<CR> - imenu <script> Xml.Change<Tab>c <C-C>:call <SID>Change()<CR> - nmenu <script> Xml.Change\ Whole\ Tag<Tab>C :call <SID>ChangeWholeTag()<CR> - imenu <script> Xml.Change\ Whole\ Tag<Tab>C <C-C>:call <SID>ChangeWholeTag()<CR> - nmenu <script> Xml.Delete\ Comment<Tab>] :call <SID>DelComment()<CR> - imenu <script> Xml.Delete\ Comment<Tab>] <C-C>:call <SID>DelComment()<CR> - nmenu <script> Xml.Delete\ Comment\ Section<Tab>} :call <SID>DelCommentSection()<CR> - imenu <script> Xml.Delete\ Comment\ Section<Tab>} <C-C>:call <SID>DelCommentSection()<CR> - nmenu <script> Xml.Delete\ CData<Tab>[ :call <SID>DelCData()<CR> - imenu <script> Xml.Delete\ CData<Tab>[ <C-C>:call <SID>DelCData()<CR> - nmenu <script> Xml.Delete\ CData\ Section<Tab>[ :call <SID>DelCDataSection()<CR> - imenu <script> Xml.Delete\ CData\ Section<Tab>[ <C-C>:call <SID>DelCDataSection()<CR> - nmenu <script> Xml.Delete\ Tag<Tab>d :call <SID>Delete()<CR> - imenu <script> Xml.Delete\ Tag<Tab>d <C-C>:call <SID>Delete()<CR> - nmenu <script> Xml.Delete\ Section<Tab>D :call <SID>DeleteSection()<CR> - imenu <script> Xml.Delete\ Section<Tab>D <C-C>:call <SID>DeleteSection()<CR> - nmenu <script> Xml.End\ Tag<Tab>e :call <SID>EndTag()<CR> - imenu <script> Xml.End\ Tag<Tab>e <C-C>:call <SID>EndTag()<CR> - nmenu <script> Xml.Fold\ Comment :?<!--?,/-->/fo<CR> - nmenu <script> Xml.Fold\ CData :?<!\[CDATA\[?,/\]\]>/fo<CR> - nmenu <script> Xml.Fold\ Processing\ instruc :?<\?[a-zA-Z]*?,/?>/fo<CR> - nmenu <script> Xml.Fold\ Tag<Tab>f :call <SID>FoldTag()<CR> - nmenu <script> Xml.Fold\ All\ Tags<Tab>F :call <SID>FoldTagAll()<CR> - nmenu <script> Xml.Format\ Tags<Tab>g :call <SID>FormatTag()<CR> - nmenu <script> Xml.Format\ All\ Tags<Tab>G :call <SID>FormatTagAll()<CR> - nmenu <script> Xml.Join<Tab>j :call <SID>Join()<CR> - imenu <script> Xml.Join<Tab>j <C-C>:call <SID>Join()<CR> - nmenu <script> Xml.Open\ After\ Tag<Tab>O :call <SID>AfterTag()<CR> - imenu <script> Xml.Open\ After\ Tag<Tab>O <C-C>:call <SID>AfterTag()<CR> - nmenu <script> Xml.open\ Before\ Tag<Tab>o :call <SID>BeforeTag()<CR> - imenu <script> Xml.open\ Before\ Tag<Tab>o <C-C>:call <SID>BeforeTag()<CR> - nmenu <script> Xml.Match<Tab>5 :call <SID>Matches()<CR> - imenu <script> Xml.Match<Tab>5 <C-C>:call <SID>Matches()<CR><C-\><C-G> - nmenu <script> Xml.Shift\ Left<Tab>< :call <SID>ShiftLeft()<CR> - imenu <script> Xml.Shift\ Left<Tab>< <C-C>:call <SID>ShiftLeft()<CR><C-\><C-G> - nmenu <script> Xml.Shift\ Right<Tab>> :call <SID>ShiftRight()<CR> - imenu <script> Xml.Shift\ Right<Tab>> <C-C>:call <SID>ShiftRight()<CR><C-\><C-G> - nmenu <script> Xml.Start\ Tag<Tab>s :call <SID>StartTag()<CR> - imenu <script> Xml.Start\ Tag<Tab>s <C-C>:call <SID>StartTag()<CR><C-\><C-G> -en - -" Section: Doc installation {{{1 -" Function: s:XmlInstallDocumentation(full_name, revision) {{{2 -" Install help documentation. -" Arguments: -" full_name: Full name of this vim plugin script, including path name. -" revision: Revision of the vim script. #version# mark in the document file -" will be replaced with this string with 'v' prefix. -" Return: -" 1 if new document installed, 0 otherwise. -" Note: Cleaned and generalized by guo-peng Wen -"''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -function! s:XmlInstallDocumentation(full_name, revision) - " Name of the document path based on the system we use: - if (has("unix")) - " On UNIX like system, using forward slash: - let l:slash_char = '/' - let l:mkdir_cmd = ':silent !mkdir -p ' - else - " On M$ system, use backslash. Also mkdir syntax is different. - " This should only work on W2K and up. - let l:slash_char = '\' - let l:mkdir_cmd = ':silent !mkdir ' - endif - - let l:doc_path = l:slash_char . 'doc' - "let l:doc_home = l:slash_char . '.vim' . l:slash_char . 'doc' - - " Figure out document path based on full name of this script: - let l:vim_plugin_path = fnamemodify(a:full_name, ':h') - "let l:vim_doc_path = fnamemodify(a:full_name, ':h:h') . l:doc_path - let l:vim_doc_path = matchstr(l:vim_plugin_path, - \ '.\{-}\ze\%(\%(ft\)\=plugin\|macros\)') . l:doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - echomsg "Doc path: " . l:vim_doc_path - execute l:mkdir_cmd . l:vim_doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - " Try a default configuration in user home: - "let l:vim_doc_path = expand("~") . l:doc_home - let l:vim_doc_path = matchstr(&rtp, - \ escape($HOME, ' \') .'[/\\]\%(\.vim\|vimfiles\)') - if (!(filewritable(l:vim_doc_path) == 2)) - execute l:mkdir_cmd . l:vim_doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - " Put a warning: - echomsg "Unable to open documentation directory" - echomsg " type :help add-local-help for more informations." - return 0 - endif - endif - endif - endif - - " Exit if we have problem to access the document directory: - if (!isdirectory(l:vim_plugin_path) - \ || !isdirectory(l:vim_doc_path) - \ || filewritable(l:vim_doc_path) != 2) - return 0 - endif - - " Full name of script and documentation file: - let l:script_name = 'xml.vim' - let l:doc_name = 'xml-plugin.txt' - let l:plugin_file = l:vim_plugin_path . l:slash_char . l:script_name - let l:doc_file = l:vim_doc_path . l:slash_char . l:doc_name - - " Bail out if document file is still up to date: - if (filereadable(l:doc_file) && - \ getftime(l:plugin_file) < getftime(l:doc_file)) - return 0 - endif - - " Prepare window position restoring command: - if (strlen(@%)) - let l:go_back = 'b ' . bufnr("%") - else - let l:go_back = 'enew!' - endif - - " Create a new buffer & read in the plugin file (me): - setl nomodeline - exe 'enew!' - exe 'r ' . l:plugin_file - - setl modeline - let l:buf = bufnr("%") - setl noswapfile modifiable - - norm zR - norm gg - - " Delete from first line to a line starts with - " === START_DOC - 1,/^=\{3,}\s\+START_DOC\C/ d - - " Delete from a line starts with - " === END_DOC - " to the end of the documents: - /^=\{3,}\s\+END_DOC\C/,$ d - - " Remove fold marks: - "% s/{\{3}[1-9]/ / - - " Add modeline for help doc: the modeline string is mangled intentionally - " to avoid it be recognized by VIM: - call append(line('$'), '') - call append(line('$'), ' v' . 'im:tw=78:ts=8:fen:fdm=marker:ft=help:norl:') - - " Replace revision: - exe "normal! :1,5s/#version#/ v" . a:revision . "/\<CR>" - - " Save the help document: - exe 'w! ' . l:doc_file - exe l:go_back - exe 'bw ' . l:buf - - " Build help tags: - exe 'helptags ' . l:vim_doc_path - - return 1 -endfunction -" }}}2 - -let s:revision= - \ substitute("$Revision: 1.36 $",'\$\S*: \([.0-9]\+\) \$','\1','') -silent! let s:install_status = - \ s:XmlInstallDocumentation(expand('<sfile>:p'), s:revision) -if (s:install_status == 1) - echom expand("<sfile>:t:r") . '-plugin v' . s:revision . - \ ': Help-documentation installed.' -endif - - -" Mappings of keys to functions {{{1 -nnoremap <silent> <buffer> <LocalLeader>5 :call <SID>Matches()<Cr> -vnoremap <silent> <buffer> <LocalLeader>5 <Esc>:call <SID>MatchesVisual()<Cr> -nnoremap <silent> <buffer> <LocalLeader>% :call <SID>Matches()<Cr> -vnoremap <silent> <buffer> <LocalLeader>% <Esc>:call <SID>MatchesVisual()<Cr> -nnoremap <silent> <buffer> <LocalLeader>c :call <SID>Change()<Cr> -nnoremap <silent> <buffer> <LocalLeader>C :call <SID>ChangeWholeTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>d :call <SID>Delete()<Cr> -nnoremap <silent> <buffer> <LocalLeader>D :call <SID>DeleteSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>e :call <SID>EndTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>] :call <SID>DelComment()<Cr> -nnoremap <silent> <buffer> <LocalLeader>} :call <SID>DelCommentSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>f :call <SID>FoldTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>F :call <SID>FoldTagAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>g :call <SID>FormatTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>G :call <SID>FormatTagAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>I :call <SID>IndentAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>j :call <SID>Join()<Cr> -nnoremap <silent> <buffer> <LocalLeader>O :call <SID>BeforeTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>= :call <SID>CommentTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>o :call <SID>AfterTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>s :call <SID>StartTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>[ :call <SID>DelCData()<Cr> -nnoremap <silent> <buffer> <LocalLeader>{ :call <SID>DelCDataSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>> :call <SID>ShiftRight()<Cr> -nnoremap <silent> <buffer> <LocalLeader>< :call <SID>ShiftLeft()<Cr> -vnoremap <silent> <buffer> <LocalLeader>l <Esc>:call <SID>vlistitem()<Cr> -vnoremap <silent> <buffer> <LocalLeader>v <Esc>:call <SID>BlockTag(0)<Cr> -vnoremap <silent> <buffer> <LocalLeader>V <Esc>:call <SID>BlockTag(1)<Cr> -vnoremap <silent> <buffer> <LocalLeader>c <Esc>:call <SID>BlockWith('<![CDATA[',']]>')<Cr> -vnoremap <silent> <buffer> <LocalLeader>< <Esc>:call <SID>BlockWith('<!--','-->')<Cr> - -" Move around functions. -noremap <silent><buffer> [[ m':call <SID>findOpenTag("bW")<CR> -noremap <silent><buffer> ]] m':call <SID>findOpenTag( "W")<CR> -noremap <silent><buffer> [] m':call <SID>findCloseTag( "bW")<CR> -noremap <silent><buffer> ][ m':call <SID>findCloseTag( "W")<CR> - -" Move around comments -noremap <silent><buffer> ]" :call search('^\(\s*<!--.*\n\)\@<!\(\s*-->\)', "W")<CR> -noremap <silent><buffer> [" :call search('\%(^\s*<!--.*\n\)\%(^\s*-->\)\@!', "bW")<CR> - - -setlocal iskeyword=@,48-57,_,192-255,58 -exe 'inoremap <silent> <buffer> '.b:suffix. " ><Esc>db:call <SID>makeElement()<Cr>" -if !exists("g:xml_tag_completion_map") - inoremap <silent> <buffer> > ><Esc>:call <SID>CloseTagFun()<Cr> -else - execute "inoremap <silent> <buffer> " . g:xml_tag_completion_map . " ><Esc>:call <SID>CloseTagFun()<Cr>" -endif - - - -finish - -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""/*}}}*/ -" Section: Documentation content {{{1 -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -=== START_DOC -*xml-plugin.txt* Help edit XML and SGML documents. #version# - - XML Edit ~ - -A filetype plugin to help edit XML and SGML documents. - -This script provides some convenience when editing XML (and some SGML -including HTML) formated documents. It allows you to jump to the -beginning or end of the tag block your cursor is in. '%' will jump -between '<' and '>' within the tag your cursor is in. When in insert -mode and you finish a tag (pressing '>') the tag will be completed. If -you press '>' twice it will place the cursor in the middle of the tags -on it's own line (helps with nested tags). - -Usage: Place this file into your ftplugin directory. To add html support -Sym-link or copy this file to html.vim in your ftplugin directory. To activte -the script place 'filetype plugin on' in your |.vimrc| file. See |ftplugins| -for more information on this topic. - -If the file edited is of type "html" and "xml_use_html" is defined then -the following tags will not auto complete: <img>, <input>, <param>, -<frame>, <br>, <hr>, <meta>, <link>, <base>, <area> - -If the file edited is of type 'html' and 'xml_use_xhtml' is defined the -above tags will autocomplete the xml closing staying xhtml compatable. -ex. <hr> becomes <hr /> (see |xml-plugin-settings|) - -Known Bugs {{{1 ~ - -- < & > marks inside of a CDATA section are interpreted as actual XML tags - even if unmatched. -- The script can not handle leading spaces such as < tag></ tag> it is - illegal XML syntax and considered very bad form. -- Placing a literal `>' in an attribute value will auto complete despite that - the start tag isn't finished. This is poor XML anyway you should use - > instead. - - ------------------------------------------------------------------------------- - *xml-plugin-settings* -Options {{{1 - -(All options must be placed in your |.vimrc| prior to the |ftplugin| -command.) - -xml_tag_completion_map - Use this setting to change the default mapping to auto complete a - tag. By default typing a literal `>' will cause the tag your editing - to auto complete; pressing twice will auto nest the tag. By using - this setting the `>' will be a literal `>' and you must use the new - mapping to perform auto completion and auto nesting. For example if - you wanted Control-L to perform auto completion inmstead of typing a - `>' place the following into your .vimrc: > - let xml_tag_completion_map = "<C-l>" -< -xml_no_auto_nesting (Not Working!!!!!) - This turns off the auto nesting feature. After a completion is made - and another `>' is typed xml-edit automatically will break the tag - accross multiple lines and indent the curser to make creating nested - tqags easier. This feature turns it off. Enter the following in your - .vimrc: > - let xml_no_auto_nesting = 1 -< -xml_use_xhtml - When editing HTML this will auto close the short tags to make valid - XML like <hr/> and <br/>. Enter the following in your vimrc to - turn this option on: > - let xml_use_xhtml = 1 - if the filetype is xhtml and g:xml_use_xhtml doesn't exists - the script defines it to be 1. (This also assumes that you have linked - xml.vim to xhtml.vim. Otherwise this item is moot) - For a file to be of xhtml type there need to be a doctype declaration!! - just naming a file something.xhtml doesn't make it type xhtml! -< -xml_no_html - This turns of the support for HTML specific tags. Place this in your - .vimrc: > - let xml_no_html = 1 -< ------------------------------------------------------------------------------- - *xml-plugin-mappings* - -Mapings and their functions {{{1 - -Typing '>' will start the tag closing routine. -Typing (Where | means cursor position) - <para>| -results in - <para>|</para> - -Typing - <para>>|</para> -results in - <para> - | - </para> -typing a lone '>' and no '<' in front of it accepts the '>' (But having -lone '>' or '<' in a XML file is frown upon except in <!CDATA> sections, -and that will throw of the plugin!!). - -Typing </tag> or <tag/> also results in na expanding. So when editing -html type <input .... /> - -The closing routing also ignores DTD tags '<!,,>' and processing -instructions '<?....?>'. Thus typing these result in no expansion. - - -<LocalLeader> is a setting in VIM that depicts a prefix for scripts and -plugins to use. By default this is the backslash key `\'. See |mapleader| -for details. - -;; make element out previous word and close it {{{2 - - when typing a word;; wil create <word>|</word> - when word on its own line it will be - <word> - | - </word> - the suffix can be changed by setting - let makeElementSuf = ',,,' in your .vimrc - Thanks to Bart van Deenen - (http://www.vim.org/scripts/script.php?script_id=632) - -[ and ] mappings {{{2 - <LocalLeader>[ Delete <![CDATA[ ]]> delimiters - <LocalLeader>{ Delete <![CDATA[ ]]> section - <LocalLeader>] Delete <!-- --> delimiters - <LocalLeader>} Delete <!-- --> section - [[ Goto to the previous open tag - [[ Goto to the next open tag - [] Goto to the previous close tag - ][ Goto to the next close tag - [" Goto to the next comment - ]" Goto the previous comment -<LocalLeader>5 Jump to the matching tag. {{{2 -<LocalLeader>% Jump to the matching tag. - - -<LocalLeader>c Rename tag {{{2 - -<LocalLeader>C Rename tag and remove attributes {{{2 - Will ask for attributes - -<LocalLeader>d Deletes the surrounding tags from the cursor. {{{2 - <tag1>outter <tag2>inner text</tag2> text</tag1> - | - Turns to: - outter <tag2>inner text</tag2> text - | - -<LocalLeader>D Deletes the tag and it contents {{{2 - - and put it in register x. - <tag1>outter <tag2>inner text</tag2> text</tag1> - | - Turns to: - <tag1>outter text</tag1> - -<LocalLeader>e provide endtag for open tags. {{{2 - - provide endtag for open tags. Watch where de cursor is - <para><listitem>list item content - | - pressing \e twice produces - <para><listitem>list item content</para></listitem> - -<LocalLeader>f fold the tag under the cursor {{{2 - <para> - line 1 - line 2 - line 3 - </para> - \f produces - +-- 5 lines: <para>-------------------------- - - -<LocalLeader>F all tags of name 'tag' will be fold. {{{2 - - If there isn't a tag under - the cursor you will be asked for one. - -<LocalLeader>g Format (Vim's gq function) {{{2 - - will make a visual block of tag under cursor and then format using gq - - -<LocalLeader>G Format all tags under cursor (Vim's gq function) {{{2 - - If there isn't a tag under - the cursor you will be asked for one. - - -<LocalLeader>I Indent all tags {{{2 - - will create a multiline layout every opening tag will be shifted out - and every closing tag will be shifted in. Be aware that the rendering - of the XML through XSLT and/or DSSSL, might be changed by this. - Be aware tha if the file is big, more than 1000 lines, the reformatting - takes a long time because vim has to make a big undo buffer. - For example using \I on the example below: - - <chapter><title>Indent</title><para>The documentation</para></chapter> - - - Becomes - - <chapter> - <title> - Indent - </title> - <para> - The documentation - </para> - </chapter> - - -<LocalLeader>j Joins two the SAME sections together. {{{2 - - The sections must be next to each other. - <para> This is line 1 - of a paragraph. </para> - <para> This is line 2 - | - of a paragraph. </para> - \j produces - <para> This is line 1 - of a paragraph. - This is line 2 - of a paragraph. </para> - -<LocalLeader>l visual surround the block with listitem and para {{{2 - When marking up docbook tekst you have the issue that listitems - consist of 2 item. This key combination inserts them both, - - blaah - | - \l produces - <listitem> - <para>blaah</para> - </listitem> - -<LocalLeader>o Insert a tag inside the current one (like vim o) {{{2 - You are asked for tag and attributes. - - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - | - \o produces - <tag1> - <aftertag><tag2><tag3>blaah</tag3></tag2></aftertag> - </tag1> - -<LocalLeader>O Insert a tag outside the current one (like vim O) {{{2 - You are asked for tag and attributes. - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - | - \O produces - <beforetag> - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - </beforetag> - -<LocalLeader>s Insert an opening tag for an closing tag. {{{2 - list item content</para></listitem> - | - pressing \s twice produces - <para><listitem>list item content</para></listitem> - -<LocalLeader>[ Delete <![CDATA[ ]]> delimiters {{{2 - Removes Only <CDATA[ and ]]> - handy when you want to uncomment a section. - You need to stand in the tag and not on an other tag - <![CDATA[ <tag> ]]> - if you cursor is outside <tag> but inside the - CDATA tag the delition works. -<LocalLeader>{ Delete <![CDATA[ ]]> section {{{2 - Removes everything tag and Content -<LocalLeader>] Delete <!-- --> delimiters {{{2 - Uncommnet a block. -<LocalLeader>} Delete <!-- --> section {{{2 - Removes everything tag and Content -<LocalLeader>> shift right opening tag and closing tag. {{{2 - shift everything between the tags 1 shiftwide right -<LocalLeader>< shift left opening tag and closing tag. {{{2 - shift everything between the tags 1 shiftwide left -<LocalLeader>c Visual Place a CDATA section around the selected text. {{{2 - Place Cdata section around the block -<LocalLeader>< Visual Place a Comment around the selected text. {{{2 - Place comment around the block -<LocalLeader>5 Extend the visual selection to the matching tag. {{{2 -<LocalLeader>% - Extend the visual selection to the matching tag. Make sure you are at - the start of the opening tag or the end of the closing tag. -<LocalLeader>v Visual Place a tag around the selected text. {{{2 - - You are asked for tag and attributes. You - need to have selected text in visual mode before you can use this - mapping. See |visual-mode| for details. - Be careful where you place the marks. - The top uses append - The bottom uses append - Useful when marking up a text file - ------------------------------------------------------------------------------- - *xml-plugin-callbacks* - -Callback Functions {{{2 ~ - -A callback function is a function used to customize features on a per tag -basis. For example say you wish to have a default set of attributs when you -type an empty tag like this: - You type: <tag> - You get: <tag default="attributes"></tag> - -This is for any script programmers who wish to add xml-plugin support to -there own filetype plugins. - -Callback functions recive one attribute variable which is the tag name. The -all must return either a string or the number zero. If it returns a string -the plugin will place the string in the proper location. If it is a zero the -plugin will ignore and continue as if no callback existed. - -The following are implemented callback functions: - -HtmlAttribCallback - This is used to add default attributes to html tag. It is intended - for HTML files only. - -XmlAttribCallback - This is a generic callback for xml tags intended to add attributes. - - *xml-plugin-html* -Callback Example {{{2 ~ - -The following is an example of using XmlAttribCallback in your .vimrc -> - function XmlAttribCallback (xml_tag) - if a:xml_tag ==? "my-xml-tag" - return "attributes=\"my xml attributes\"" - else - return 0 - endif - endfunction -< -The following is a sample html.vim file type plugin you could use: -> - " Vim script file vim600:fdm=marker: - " FileType: HTML - " Maintainer: Devin Weaver <vim (at) tritarget.com> - " Location: http://www.vim.org/scripts/script.php?script_id=301 - - " This is a wrapper script to add extra html support to xml documents. - " Original script can be seen in xml-plugin documentation. - - " Only do this when not done yet for this buffer - if exists("b:did_ftplugin") - finish - endif - " Don't set 'b:did_ftplugin = 1' because that is xml.vim's responsability. - - let b:html_mode = 1 - - if !exists("*HtmlAttribCallback") - function HtmlAttribCallback( xml_tag ) - if a:xml_tag ==? "table" - return "cellpadding=\"0\" cellspacing=\"0\" border=\"0\"" - elseif a:xml_tag ==? "link" - return "href=\"/site.css\" rel=\"StyleSheet\" type=\"text/css\"" - elseif a:xml_tag ==? "body" - return "bgcolor=\"white\"" - elseif a:xml_tag ==? "frame" - return "name=\"NAME\" src=\"/\" scrolling=\"auto\" noresize" - elseif a:xml_tag ==? "frameset" - return "rows=\"0,*\" cols=\"*,0\" border=\"0\"" - elseif a:xml_tag ==? "img" - return "src=\"\" width=\"0\" height=\"0\" border=\"0\" alt=\"\"" - elseif a:xml_tag ==? "a" - if has("browse") - " Look up a file to fill the href. Used in local relative file - " links. typeing your own href before closing the tag with `>' - " will override this. - let cwd = getcwd() - let cwd = substitute (cwd, "\\", "/", "g") - let href = browse (0, "Link to href...", getcwd(), "") - let href = substitute (href, cwd . "/", "", "") - let href = substitute (href, " ", "%20", "g") - else - let href = "" - endif - return "href=\"" . href . "\"" - else - return 0 - endif - endfunction - endif - - " On to loading xml.vim - runtime ftplugin/xml.vim -< -=== END_DOC -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" v im:tw=78:ts=8:ft=help:norl: -" vim600: set foldmethod=marker tabstop=8 shiftwidth=2 softtabstop=2 smartindent smarttab : -"fileencoding=iso-8859-15 -=== END_DOC -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - - - - - - -" Vim settingѕ {{{1 -" vim:tw=78:ts=2:ft=help:norl: -" vim: set foldmethod=marker tabstop=2 shiftwidth=2 softtabstop=2 smartindent smarttab : -"fileencoding=utf-8 - diff --git a/files/.vim/ftplugin/htmldjango.vim b/files/.vim/ftplugin/htmldjango.vim deleted file mode 100644 index daa1044..0000000 --- a/files/.vim/ftplugin/htmldjango.vim +++ /dev/null @@ -1 +0,0 @@ -imap {{ {{ }}<Esc>2hi diff --git a/files/.vim/ftplugin/rfc.vim b/files/.vim/ftplugin/rfc.vim deleted file mode 100644 index 0a8bb13..0000000 --- a/files/.vim/ftplugin/rfc.vim +++ /dev/null @@ -1,21 +0,0 @@ -" Vim script file -" FileType: RFC -" Author: lilydjwg <lilydjwg@gmail.com> -" Last Change: 2010年1月16日 - -function! s:rfcTag() - " 从目录跳转到正文 - let syn = synIDattr(synID(line("."), col("."), 1), "name") - if syn == 'rfcContents' || syn == 'rfcDots' - let l = getline('.') - let l = matchstr(l, '\v[0-9.]+\s(\w|\s)\S') - let l = '^\V' . l - call search(l, 's') - else - echohl Error - echomsg '光标不位于目录项!' - echohl None - endif -endfunction - -nmap <buffer> <silent> <C-]> :call <SID>rfcTag()<CR> diff --git a/files/.vim/ftplugin/xhtml.vim b/files/.vim/ftplugin/xhtml.vim deleted file mode 100644 index 55e9023..0000000 --- a/files/.vim/ftplugin/xhtml.vim +++ /dev/null @@ -1,1854 +0,0 @@ -" Vim script file vim600:fdm=marker: -" FileType: XML -" Author: Rene de Zwart <renez (at) lightcon.xs4all.nl> -" Maintainer: Rene de Zwart <renez (at) lightcon.xs4all.nl> -" Last Change: Date: 2009-11-12 -" Version: Revision: 1.37 -" -" Licence: This program is free software; you can redistribute it -" and/or modify it under the terms of the GNU General Public -" License. See http://www.gnu.org/copyleft/gpl.txt -" Credits: Devin Weaver <vim (at) tritarget.com> et all -" for the original code. Guo-Peng Wen for the self -" install documentation code. -" Bart vam Deenen for makeElement function -" Rene de Zwart - - -" Observation - If you want to do something to a match pair most of the time -" you must do first the close tag. Because doing first the open -" tag could change the close tag position. - -" NOTE with filetype index on de standard indent/html.vim interferes -" with xml.vim. You can -" 1) set filetype indent off in .vimrc -" 2) echo "let b:did_indent = 1" > .vim/indent/html.vim - - -" Only do this when not done yet for this buffer -if exists("b:did_ftplugin") - finish -endif -let b:did_ftplugin = 1 - -setlocal commentstring=<!--%s--> - -" XML: thanks to Johannes Zellner and Akbar Ibrahim -" - case sensitive -" - don't match empty tags <fred/> -" - match <!--, --> style comments (but not --, --) -" - match <!, > inlined dtd's. This is not perfect, as it -" gets confused for example by -" <!ENTITY gt ">"> -if exists("loaded_matchit") - let b:match_ignorecase=0 - let b:match_words = - \ '<:>,' . - \ '<\@<=!\[CDATA\[:]]>,'. - \ '<\@<=!--:-->,'. - \ '<\@<=?\k\+:?>,'. - \ '<\@<=\([^ \t>/]\+\)\%(\s\+[^>]*\%([^/]>\|$\)\|>\|$\):<\@<=/\1>,'. - \ '<\@<=\%([^ \t>/]\+\)\%(\s\+[^/>]*\|$\):/>' -endif - -" Script rgular expresion used. Documents those nasty criters {{{1 -let s:NoSlashBeforeGt = '\(\/\)\@\<!>' -" Don't check for quotes around attributes!!! -let s:Attrib = '\(\(\s\|\n\)\+\([^>= \t]\+=[^>&]\+\)\(\s\|\n\)*\)' -let s:OptAttrib = s:Attrib . '*'. s:NoSlashBeforeGt -let s:ReqAttrib = s:Attrib . '\+'. s:NoSlashBeforeGt -let s:OpenTag = '<[^!/?][^>]*' . s:OptAttrib -let s:OpenOrCloseTag = '<[^!?][^>]*'. s:OptAttrib -let s:CloseTag = '<\/[^>]*'. s:NoSlashBeforeGt -let s:SpaceInfront = '^\s*<' -let s:EndofName = '\($\|\s\|>\)' - -" Buffer variables {{{1 -let b:emptyTags='^\(img\|input\|param\|frame\|br\|hr\|meta\|link\|base\|area\)$' -let b:firstWasEndTag = 0 -let b:html_mode =((&filetype =~ 'x\?html') && !exists("g:xml_no_html")) -let b:haveAtt = 0 -let b:lastTag = "" -let b:lastAtt = "" -let b:suffix = (exists('g:makeElementSuf') ? g:makeElementSuf : ';;') -let b:xml_use_xhtml = 0 -if exists('g:xml_use_xhtml') - let b:xml_use_xhtml = g:xml_use_xhtml -elseif &filetype == 'xhtml' - let b:xml_use_xhtml = 1 -en - - - - -" NewFileXML -> Inserts <?xml?> at top of new file. {{{1 -if !exists("*NewFileXML") -function! NewFileXML( ) - " Where is g:did_xhtmlcf_inits defined? - if &filetype == 'xml' || - \ (!exists ("g:did_xhtmlcf_inits") && - \ b:xml_use_xhtml && - \ (&filetype =~ 'x\?html')) - if append (0, '<?xml version="1.0"?>') - normal! G - endif - endif -endfunction -endif - - - -" Callback -> Checks for tag callbacks and executes them. {{{1 -if !exists("*s:Callback") -function! s:Callback( xml_tag, isHtml ) - let text = 0 - if a:isHtml == 1 && exists ("*HtmlAttribCallback") - let text = HtmlAttribCallback (a:xml_tag) - elseif exists ("*XmlAttribCallback") - let text = XmlAttribCallback (a:xml_tag) - endif - if text != '0' - execute "normal! i " . text ."\<Esc>l" - endif -endfunction -endif - -" SavePos() saves position in bufferwide variable {{{1 -fun! s:SavePos() - retu 'call cursor('.line('.').','. col('.'). ')' -endf - -" findOpenTag() {{{1 -fun! s:findOpenTag(flag) - call search(s:OpenTag,a:flag) -endf - -" findCloseTag() {{{1 -fun! s:findCloseTag(flag) - call search(s:CloseTag,a:flag) -endf - -" GetTagName() Gets the tagname from start position {{{1 -"Now lets go for the name part. The namepart are xmlnamechars which -"is quite a big range. We assume that everything after '<' or '</' -"until the first 'space', 'forward slash' or '>' ends de name part. -if !exists('*s:GetTagName') -fun! s:GetTagName(from) - let l:end = match(getline('.'), s:EndofName,a:from) - return strpart(getline('.'),a:from, l:end - a:from ) -endf -en -" hasAtt() Looks for attribute in open tag {{{1 -" expect cursor to be on < -fun! s:hasAtt() - "Check if this open tag has attributes - let l:line = line('.') | let l:col = col('.') - if search(b:tagName . s:ReqAttrib,'W') > 0 - if l:line == line('.') && l:col == (col('.')-1) - let b:haveAtt = 1 - en - en -endf - - -" TagUnderCursor() Is there a tag under the cursor? {{{1 -" Set bufer wide variable -" - b:firstWasEndTag -" - b:tagName -" - b:endcol & b:endline only used by Match() -" - b:gotoCloseTag (if the tag under the cursor is one) -" - b:gotoOpenTag (if the tag under the cursor is one) -" on exit -" - returns 1 (true) or 0 (false) -" - position is at '<' -if !exists('*s:TagUnderCursor') -fun! s:TagUnderCursor() - let b:firstWasEndTag = 0 - let l:haveTag = 0 - let b:haveAtt = 0 - - "Lets find forward a < or a >. If we first find a > we might be in a tag. - "If we find a < first or nothing we are definitly not in a tag - - if getline('.')[col('.') - 1] == '>' - let b:endcol = col('.') - let b:endline = line('.') - if getline('.')[col('.')-2] == '/' - "we don't work with empty tags - retu l:haveTag - en - " begin: gwang customization for JSP development - if getline('.')[col('.')-2] == '%' - "we don't work with jsp %> tags - retu l:haveTag - en - " end: gwang customization for JSP development - " begin: gwang customization for PHP development - if getline('.')[col('.')-2] == '?' - "we don't work with php ?> tags - retu l:haveTag - en - " end: gwang customization for PHP development - elseif search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - let b:endcol = col('.') - let b:endline = line('.') - if getline('.')[col('.')-2] == '-' - "we don't work with comment tags - retu l:haveTag - en - if getline('.')[col('.')-2] == '/' - "we don't work with empty tags - retu l:haveTag - en - el - retu l:haveTag - en - el - retu l:haveTag - en - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' - if getline('.')[col('.')] == '/' - let b:firstWasEndTag = 1 - let b:gotoCloseTag = s:SavePos() - elseif getline('.')[col('.')] == '?' || getline('.')[col('.')] == '!' - "we don't deal with processing instructions or dtd - "related definitions - retu l:haveTag - el - let b:gotoOpenTag = s:SavePos() - en - el - retu l:haveTag - en - el - retu l:haveTag - en - - "we have established that we are between something like - "'</\?[^>]*>' - - let b:tagName = s:GetTagName(col('.') + b:firstWasEndTag) - "echo 'Tag ' . b:tagName - - "begin: gwang customization, do not work with an empty tag name - if b:tagName == '' - retu l:haveTag - en - "end: gwang customization, do not work with an empty tag name - - let l:haveTag = 1 - if b:firstWasEndTag == 0 - call s:hasAtt() - exe b:gotoOpenTag - en - retu l:haveTag -endf -en - -" Match(tagname) Looks for open or close tag of tagname {{{1 -" Set buffer wide variable -" - b:gotoCloseTag (if the Match tag is one) -" - b:gotoOpenTag (if the Match tag is one) -" on exit -" - returns 1 (true) or 0 (false) -" - position is at '<' -if !exists('*s:Match') -fun! s:Match(name) - let l:pat = '</\=' . a:name . s:OptAttrib - if b:firstWasEndTag - exe b:gotoCloseTag - let l:flags='bW' - let l:level = -1 - el - exe 'normal! '.b:endline.'G0'.(b:endcol-1).'l' - let l:flags='W' - let l:level = 1 - en - while l:level && search(l:pat,l:flags) > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level - echo "no matching tag!!!!!" - retu l:level - en - if b:firstWasEndTag - let b:gotoOpenTag = s:SavePos() - call s:hasAtt() - exe b:gotoOpenTag - el - let b:gotoCloseTag = s:SavePos() - en - retu l:level == 0 -endf -en - -" InComment() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:InComment') -fun! s:InComment() -let b:endcom=0 -let b:begcom=0 - - "Lets find forward a < or a >. If we first find a > we might be in a comment. - "If we find a < first or nothing we are definitly not in a Comment - - if getline('.')[col('.') - 1] == '>' - if getline('.')[col('.')-2] == '-' && getline('.')[col('.')-3] == '-' - let b:endcomcol=col('.') - let b:endcomline=line('.') - let b:endcom=1 - retu 1 - en - elseif getline('.')[col('.')-1] == '<' && getline('.')[col('.')] == '!' - \ && getline('.')[col('.')+1] == '-' && getline('.')[col('.')+2] == '-' - let b:begcomcol= col('.') - let b:begcomline=line('.') - let b:begcom=1 - retu 1 - en - "We are not standing on a begin/end comment - "Is the first > an ending comment? - if search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - if getline('.')[col('.')-2] == '-' && getline('.')[col('.')-3] == '-' - let b:endcomcol=col('.') - let b:endcomline=line('.') - let b:endcom=1 - retu 1 - en - en - en - "Forward is not a ending comment - "is backward a starting comment - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' && getline('.')[col('.')] == '!' - \ && getline('.')[col('.')+1] == '-' && getline('.')[col('.')+2] == '-' - let b:begcomcol=col('.') - let b:begcomline=line('.') - let b:begcom=1 - retu 1 - en - en - retu 0 -endf -en - -" DelComment() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelComment') -fun! s:DelComment() - - let l:restore = s:SavePos() - if s:InComment() - if b:begcom - if search('-->','W' ) >=0 - normal! hh3x - call cursor(b:begcomline,b:begcomcol) - normal! 4x - retu 1 - en - el - if search('<!--','bW' ) >=0 - normal! 4x - call cursor(b:endcomline,b:endcomcol) - normal! hh3x - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" DelCommentSection() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCommentSection') -fun! s:DelCommentSection() - - let l:restore = s:SavePos() - if s:InComment() - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - if b:begcom - if search('-->','W' ) >=0 - exe "normal! f>a".l:sentinel."\<Esc>" - call cursor(b:begcomline,b:begcomcol) - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - el - if search('<!--','bW' ) >=0 - let l:restore = s:SavePos() - call cursor(b:endcomline,b:endcomcol) - exe "normal! a".l:sentinel."\<Esc>" - exe l:restore - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" DelCData() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCData') -fun! s:DelCData() - - let l:restore = s:SavePos() - if s:InCData() - if b:begdat - if search(']]>','W' ) >=0 - normal! hh3x - call cursor(b:begdatline,b:begdatcol) - normal! 9x - retu 1 - en - el - if search('<![CDATA[','bW' ) >=0 - normal! 9x - call cursor(b:enddatline,b:enddatcol) - normal! hh3x - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" InCData() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:InCData') -fun! s:InCData() -let b:enddat=0 -let b:begdat=0 - - "Lets find forward a < or a >. If we first find a > we might be in a comment. - "If we find a < first or nothing we are definitly not in a Comment - - if getline('.')[col('.') - 1] == '>' - if getline('.')[col('.')-2] == ']' && getline('.')[col('.')-3] == ']' - let b:enddatcol=col('.') - let b:enddatline=line('.') - let b:enddat=1 - retu 1 - en - elseif getline('.')[col('.')-1] == '<' - if match(getline('.'),'<![CDATA[') > 0 - let b:begdatcol= col('.') - let b:begdatline=line('.') - let b:begdat=1 - retu 1 - en - en - "We are not standing on a begin/end comment - "Is the first > aending comment? - if search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - if getline('.')[col('.')-2] == ']' && getline('.')[col('.')-3] == ']' - let b:enddatcol=col('.') - let b:enddatline=line('.') - let b:enddat=1 - retu 1 - en - en - en - "Forward is not a ending datment - "is backward a starting comment - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' - if match(getline('.'),'<![CDATA[') > 0 - let l:newname = inputdialog('Found CDATA') - let b:begdatcol=col('.') - let b:begdatline=line('.') - let b:begdat=1 - retu 1 - en - en - en - retu 0 -endf -en - - -" DelCDataSection() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCDataSection') -fun! s:DelCDataSection() - - let l:restore = s:SavePos() - if s:InCData() - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - if b:begdat - if search(']]>','W' ) >=0 - exe "normal! f>a".l:sentinel."\<Esc>" - call cursor(b:begdatline,b:begdatcol) - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - el - if search('<![CDATA[','bW' ) >=0 - let l:restore = s:SavePos() - call cursor(b:enddatline,b:enddatcol) - exe "normal! a".l:sentinel."\<Esc>" - exe l:restore - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - - -" Matches() Matches de tagname under de cursor {{{1 -if !exists('*s:Matches') -fun! s:Matches() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - retu - en - en - exe l:restore -endf -en - -" MatchesVisual() Matches de tagname under de cursor {{{1 -if !exists('*s:MatchesVisual') -fun! s:MatchesVisual() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if b:firstWasEndTag - normal! f> - en - normal! gv - if s:Match(b:tagName) - if b:firstWasEndTag == 0 - normal! f> - en - retu - en - normal! v - en - exe l:restore -endf -en - -" makeElement() makes the previous woord an tag and close {{{1 -if !exists('*s:makeElement') -function! s:makeElement() - let b:tagName = @@ - let b:haveAtt = 0 - let l:alone = (match(getline('.'),'^\s*>\s*$') >= 0) - let l:endOfLine = ((col('.')+1) == col('$')) - normal! i<pf> - if b:html_mode && b:tagName =~? b:emptyTags - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - endif - if b:xml_use_xhtml - exe "normal! i/\<Esc>l" - en - if l:endOfLine - start! - el - normal! l - start - en - el - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - end - if l:alone - exe 'normal! o</pa>Ox>>$x' - start! - el - exe 'normal! a</pa>F<' - start - en - en -endfunction -en - -" CloseTagFun() closing the tag which is being typed {{{1 -if !exists('*s:CloseTagFun') -fun! s:CloseTagFun() - let l:restore = s:SavePos() - let l:endOfLine = ((col('.')+1) == col('$')) - if col('.') > 1 && getline('.')[col('.')-2] == '>' - "Multiline request. <t>></t> --> - "<t> - " cursor comes here - "</t> - normal! h - if s:TagUnderCursor() - if b:firstWasEndTag == 0 - exe "normal! 2f>s\<Cr>\<Esc>Ox\<Esc>>>$x" - start! - retu - en - en - elseif s:TagUnderCursor() - if b:firstWasEndTag == 0 - exe "normal! />\<Cr>" - if b:html_mode && b:tagName =~? b:emptyTags - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - en - if b:xml_use_xhtml - exe "normal! i/\<Esc>l" - en - if l:endOfLine - start! - retu - el - normal! l - start - retu - en - el - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - en - exe "normal! a</" . b:tagName . ">\<Esc>F<" - start - retu - en - en - en - exe l:restore - if (col('.')+1) == col("$") - startinsert! - else - normal! l - startinsert - en -endf -en - -" BlockTag() Surround a visual block with a tag {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:BlockTag') -fun! s:BlockTag(multi) - let l:newname = inputdialog('Surround block with : ',b:lastTag) - if strlen( l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - - "Get at the end of the block - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - if a:multi - exe "normal! a\<Cr></".l:newname.">\<Cr>\<Esc>" - let l:eline = line('.') - normal! gvov - if col('.') == col("'>") && line('.') == line("'>") - normal! gvov - en - let l:sline = line(".") + 2 - exe "normal! i\<Cr><".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \ .">\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe l:sline.','.l:eline.'>' - let &report= l:rep - exe 'normal! '.l:sline.'G0mh'.l:eline."G$v'hgq" - el - exe "normal! a</".l:newname.">\<Esc>gvov" - if col('.') == col("'>") && line('.') == line("'>") - normal! gvov - en - exe "normal! i<".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \ .">\<Esc>" - en -endf -en -" BlockWith() Surround a visual block with a open and a close {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:BlockWith') -fun! s:BlockWith(open,close) - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - exe "normal! a\<Cr>;x\<Esc>0cfx".a:close."\<Cr>\<Esc>" - normal! gvov - exe "normal! i\<Cr>;x\<Esc>0cfx".a:open."\<Cr>\<Esc>" -endf -en -" vlistitem() Surround a visual block with a listitem para tag {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:vlistitem') -fun! s:vlistitem() - "Get at the end of the block - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - exe "normal! a</para>\<Cr></listitem>\<Esc>mh" - normal! gvov - exe "normal! i\<Cr><listitem>\<Cr>\<Tab><para>\<Esc>'h/listitem>/e+1\<Cr>" -endf -en -" Change() Only renames the tag {{{1 -if !exists('*s:Change') -fun! s:Change() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = inputdialog('Change tag '.b:tagName.' to : ',b:lastTag) - if strlen( l:newname) == 0 - retu - en - let b:lastTag = l:newname - if s:Match(b:tagName) - exe b:gotoCloseTag - exe 'normal! 2lcw' . l:newname . "\<Esc>" - exe b:gotoOpenTag - exe 'normal! lcw' . l:newname . "\<Esc>" - en - en -endf -en - -" Join() Joins two the same tag adjacent sections {{{1 -if !exists('*s:Join') -fun! s:Join() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:pat = '<[^?!]\S\+\($\| \|\t\|>\)' - let l:flags='W' - if b:firstWasEndTag == 0 - let l:flags='Wb' - en - if search(s:OpenOrCloseTag,l:flags) > 0 - - let l:secondChar = getline('.')[col('.')] - if l:secondChar == '/' && b:firstWasEndTag ||l:secondChar != '/' && !b:firstWasEndTag - exe l:restore - retu - en - let l:end = 0 - if l:secondChar == '/' - let l:end = 1 - en - let l:name = s:GetTagName(col('.') + l:end) - if l:name == b:tagName - if b:firstWasEndTag - let b:gotoOpenTag = s:SavePos() - el - let b:gotoCloseTag = s:SavePos() - en - let l:DeleteTag = "normal! d/>/e\<Cr>" - exe b:gotoCloseTag - exe l:DeleteTag - exe b:gotoOpenTag - exe l:DeleteTag - en - en - en - exe l:restore -endf -en - -" ChangeWholeTag() removes attributes and rename tag {{{1 -if !exists('*s:ChangeWholeTag') -fun! s:ChangeWholeTag() - if s:TagUnderCursor() - let l:newname = inputdialog('Change whole tag '.b:tagName.' to : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! 2lc/>\<Cr>".l:newname."\<Esc>" - exe b:gotoOpenTag - exe "normal! lc/>/\<Cr>".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \."\<Esc>" - en - en -endf -en - -" Delete() Removes a tag '<a id="a">blah</a>' --> 'blah' {{{1 -if !exists('*s:Delete') -fun! s:Delete() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - let l:DeleteTag = "normal! d/>/e\<Cr>" - exe b:gotoCloseTag - exe l:DeleteTag - exe b:gotoOpenTag - exe l:DeleteTag - en - else - exe l:restore - en -endf -en - - -" DeleteSection() Deletes everything between start of open tag and end of {{{1 -" closing tag -if !exists('*s:DeleteSection') -fun! s:DeleteSection() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - let l:rep=&report - let &report=999999 - exe b:gotoCloseTag - exe "normal! />\<Cr>a".l:sentinel."\<Esc>" - exe b:gotoOpenTag - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - let &report= l:rep - en - en -endf -en -" -" FoldTag() Fold the tag under the cursor {{{1 -if !exists('*s:FoldTag') -fun! s:FoldTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - if b:firstWasEndTag - exe '.,'.l:sline.'fold' - el - exe l:sline.',.fold' - en - en - el - exe l:restore - en -endf -en - -" FoldTagAll() Fold all tags of under the cursor {{{1 -" If no tag under the cursor it asks for a tag -if !exists('*s:FoldTagAll') -fun! s:FoldTagAll() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:tname = b:tagName - el - let l:tname = inputdialog('Which tag to fold : ',b:lastTag) - if strlen(l:tname) == 0 - exe l:restore - retu - en - let b:lastTag = l:tname - en - normal! G$ - let l:flag='w' - while search('<'.l:tname.s:OptAttrib,l:flag) > 0 - let l:flag='W' - let l:sline = line('.') - let l:level = 1 - while l:level && search('</\='.l:tname.s:OptAttrib,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - exe l:sline.',.fold' - el - let l:tmp = - \ inputdialog("The tag ".l:tname."(".l:sline.") doesn't have a closetag") - break - en - endwhile - exe l:restore -endf -en - - -" StartTag() provide the opening tag {{{1 -if !exists('*s:StartTag') -fun! s:StartTag() - let l:restore = s:SavePos() - let l:level = 1 - if getline('.')[col('.')-1] == '<' - if s:TagUnderCursor() - if b:firstWasEndTag - exe 'normal! i<'. b:tagName.">\<Esc>F<" - retu - el - let l:level = l:level + 1 - en - en - exe l:restore - en - while l:level && search(s:OpenOrCloseTag ,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - let l:Name = s:GetTagName(col('.') + 1) - exe l:restore - exe 'normal! i<'. l:Name.">\<Esc>" - en - exe l:restore -endf -en - - - -" EndTag() search for open tag and produce endtaf {{{1 -if !exists('*s:EndTag') -fun! s:EndTag() - let l:restore = s:SavePos() - let l:level = -1 - while l:level && search(s:OpenOrCloseTag,'bW') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - let l:Name = s:GetTagName(col('.')) - exe l:restore - exe 'normal! a</'. l:Name.">\e" - el - exe l:restore - en -endf -en - - -" BeforeTag() surrounds the current tag with a new one {{{1 -if !exists('*s:BeforeTag') -fun! s:BeforeTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = - \ inputdialog('Surround Before Tag '.b:tagName.' with : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! />\<Cr>a\<Cr></" . l:newname . ">\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe 'normal! i<' . l:newname . - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \.">\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - exe l:restore - en -endf -en - -" CommentTag() surrounds the current tag with a new one {{{1 -if !exists('*s:CommentTag') -fun! s:CommentTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! />\<Cr>a\<Cr>-->\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe "normal! i<!--\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - else - exe l:restore - en -endf -en -" AfterTag() surrounds the tags after the current one with new {{{1 -if !exists('*s:AfterTag') -fun! s:AfterTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = - \ inputdialog('Add Tag After '.b:tagName.' with : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe 'normal! i</' . l:newname . ">\<Cr>\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe "normal! />\<Cr>a\<Cr><".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \.">\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - en - exe l:restore -endf -en -" ShiftRight() Shift the tag to the right {{{1 -if !exists('*s:ShiftRight') -fun! s:ShiftRight() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - let l:eline = line('.') - if b:firstWasEndTag - exe l:eline.','.l:sline.'>' - el - exe l:sline.','.l:eline.'>' - en - en - en -endf -en - -" ShiftLeft() Shift the tag to the left {{{1 -if !exists('*s:ShiftLeft') -fun! s:ShiftLeft() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - let l:eline = line('.') - if b:firstWasEndTag - exe l:eline.','.l:sline.'<' - el - exe l:sline.','.l:eline.'<' - en - en - en -endf -en -" FormatTag() visual select the block and use gq {{{1 -if !exists('*s:FormatTag') -fun! s:FormatTag() - if s:TagUnderCursor() - if s:Match(b:tagName) - exe b:gotoCloseTag - normal! hhmh - exe b:gotoOpenTag - exe "normal! />/e+1\<Cr>v'hgq" - en - en -endf -en - - - - -" FormatTagAll() Format all tags of name under the cursor {{{1 -" If no tag under the cursor it asks for a tag -if !exists('*s:FormatTagAll') -fun! s:FormatTagAll() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:tname = b:tagName - el - let l:tname = inputdialog('Format every tag : ') - if strlen(l:tname) == 0 - exe l:restore - retu - en - en - normal! G$ - let l:flag = 'w' - while search('<'.l:tname . s:OptAttrib, l:flag) > 0 - let l:flag = 'W' - let l:sline = line('.') - let l:level = 1 - exe "normal! />/e+1\<cr>mh" - while l:level && search('</\='.l:tname . s:EndofName,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - normal! hv'hogq - el - let l:tmp = - \ inputdialog("The tag ".l:tname."(".l:sline.") doesn't have a closetag") - break - en - endwhile - exe l:restore -endf -en - - -" IndentAll() indent all tags multiline {{{1 -if !exists('*s:IndentAll') -fun! s:IndentAll() - - let l:restore = s:SavePos() - let l:rep=&report - let &report=999999 - "shift everything left - normal! 1G<G<G<G<G<G<GG$ - if search(s:OpenTag,'w') > 0 - let l:level = 1 - normal! f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - echo "after tag".line('.') - exe "normal! a\<Cr>\<Esc>" - el - normal! j - en - normal! >Gk$ - while search(s:OpenOrCloseTag,'W') > 0 - "if there is text before the tag then move the tag to the next line - if match(getline('.'),s:SpaceInfront) == -1 - exe "normal! i\<Cr>\<Esc>l" - en - if getline('.')[col('.')] == '/' - normal! <G0f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - exe "normal! a\<Cr>\<Esc>" - en - let l:level = l:level - 1 - el - normal! f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - exe "normal! a\<Cr>\<Esc>" - el - normal! j0 - en - normal! >Gk$ - let l:level = l:level + 1 - en - endwhile - if l:level - let l:tmp = - \ inputdialog("The tags opening and closing are unbalanced ".l:level) - en - en - exe l:restore - let &report= l:rep -endf -en - - -" Menu options: {{{1 -augroup XML_menu_autos -au! -autocmd BufLeave,BufWinLeave * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ amenu disable Xml | - \ amenu disable Xml.* | - \ endif -autocmd BufEnter,BufWinEnter * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ amenu enable Xml | - \ amenu enable Xml.* | - \ endif -au BufNewFile * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ call NewFileXML() | - \ endif -augroup END -if !exists("g:did_xml_menu") - let g:did_xml_menu = 1 - :1011 vmenu <script> &Xml.BlockTag\ multi<Tab>V <Esc>:call <SID>BlockTag(1)<Cr> - vmenu <script> Xml.BlockTag\ inline<Tab>v <Esc>:call <SID>BlockTag(0)<CR> - vmenu <script> Xml.Insert\ listitem<Tab>l <Esc>:call <SID>vlistitem()<CR> - vmenu <script> Xml.Comment<Tab>< <Esc>:call <SID>BlockWith('<!--','-->')<Cr> - vmenu <script> Xml.Comment\ With\ CData<Tab>c <Esc>:call <SID>BlockWith('<![CDATA[',']]>')<Cr> - nmenu <script> Xml.Comment\ Tag<Tab>= <Esc>:call <SID>CommentTag()<Cr> - imenu <script> Xml.Comment\ Tag<Tab>= <Esc>:call <SID>CommentTag()<Cr> - nmenu <script> Xml.Change<Tab>c :call <SID>Change()<CR> - imenu <script> Xml.Change<Tab>c <C-C>:call <SID>Change()<CR> - nmenu <script> Xml.Change\ Whole\ Tag<Tab>C :call <SID>ChangeWholeTag()<CR> - imenu <script> Xml.Change\ Whole\ Tag<Tab>C <C-C>:call <SID>ChangeWholeTag()<CR> - nmenu <script> Xml.Delete\ Comment<Tab>] :call <SID>DelComment()<CR> - imenu <script> Xml.Delete\ Comment<Tab>] <C-C>:call <SID>DelComment()<CR> - nmenu <script> Xml.Delete\ Comment\ Section<Tab>} :call <SID>DelCommentSection()<CR> - imenu <script> Xml.Delete\ Comment\ Section<Tab>} <C-C>:call <SID>DelCommentSection()<CR> - nmenu <script> Xml.Delete\ CData<Tab>[ :call <SID>DelCData()<CR> - imenu <script> Xml.Delete\ CData<Tab>[ <C-C>:call <SID>DelCData()<CR> - nmenu <script> Xml.Delete\ CData\ Section<Tab>[ :call <SID>DelCDataSection()<CR> - imenu <script> Xml.Delete\ CData\ Section<Tab>[ <C-C>:call <SID>DelCDataSection()<CR> - nmenu <script> Xml.Delete\ Tag<Tab>d :call <SID>Delete()<CR> - imenu <script> Xml.Delete\ Tag<Tab>d <C-C>:call <SID>Delete()<CR> - nmenu <script> Xml.Delete\ Section<Tab>D :call <SID>DeleteSection()<CR> - imenu <script> Xml.Delete\ Section<Tab>D <C-C>:call <SID>DeleteSection()<CR> - nmenu <script> Xml.End\ Tag<Tab>e :call <SID>EndTag()<CR> - imenu <script> Xml.End\ Tag<Tab>e <C-C>:call <SID>EndTag()<CR> - nmenu <script> Xml.Fold\ Comment :?<!--?,/-->/fo<CR> - nmenu <script> Xml.Fold\ CData :?<!\[CDATA\[?,/\]\]>/fo<CR> - nmenu <script> Xml.Fold\ Processing\ instruc :?<\?[a-zA-Z]*?,/?>/fo<CR> - nmenu <script> Xml.Fold\ Tag<Tab>f :call <SID>FoldTag()<CR> - nmenu <script> Xml.Fold\ All\ Tags<Tab>F :call <SID>FoldTagAll()<CR> - nmenu <script> Xml.Format\ Tags<Tab>g :call <SID>FormatTag()<CR> - nmenu <script> Xml.Format\ All\ Tags<Tab>G :call <SID>FormatTagAll()<CR> - nmenu <script> Xml.Join<Tab>j :call <SID>Join()<CR> - imenu <script> Xml.Join<Tab>j <C-C>:call <SID>Join()<CR> - nmenu <script> Xml.Open\ After\ Tag<Tab>O :call <SID>AfterTag()<CR> - imenu <script> Xml.Open\ After\ Tag<Tab>O <C-C>:call <SID>AfterTag()<CR> - nmenu <script> Xml.open\ Before\ Tag<Tab>o :call <SID>BeforeTag()<CR> - imenu <script> Xml.open\ Before\ Tag<Tab>o <C-C>:call <SID>BeforeTag()<CR> - nmenu <script> Xml.Match<Tab>5 :call <SID>Matches()<CR> - imenu <script> Xml.Match<Tab>5 <C-C>:call <SID>Matches()<CR><C-\><C-G> - nmenu <script> Xml.Shift\ Left<Tab>< :call <SID>ShiftLeft()<CR> - imenu <script> Xml.Shift\ Left<Tab>< <C-C>:call <SID>ShiftLeft()<CR><C-\><C-G> - nmenu <script> Xml.Shift\ Right<Tab>> :call <SID>ShiftRight()<CR> - imenu <script> Xml.Shift\ Right<Tab>> <C-C>:call <SID>ShiftRight()<CR><C-\><C-G> - nmenu <script> Xml.Start\ Tag<Tab>s :call <SID>StartTag()<CR> - imenu <script> Xml.Start\ Tag<Tab>s <C-C>:call <SID>StartTag()<CR><C-\><C-G> -en - -" Section: Doc installation {{{1 -" Function: s:XmlInstallDocumentation(full_name, revision) {{{2 -" Install help documentation. -" Arguments: -" full_name: Full name of this vim plugin script, including path name. -" revision: Revision of the vim script. #version# mark in the document file -" will be replaced with this string with 'v' prefix. -" Return: -" 1 if new document installed, 0 otherwise. -" Note: Cleaned and generalized by guo-peng Wen -"''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -function! s:XmlInstallDocumentation(full_name, revision) - " Name of the document path based on the system we use: - if (has("unix")) - " On UNIX like system, using forward slash: - let l:slash_char = '/' - let l:mkdir_cmd = ':silent !mkdir -p ' - else - " On M$ system, use backslash. Also mkdir syntax is different. - " This should only work on W2K and up. - let l:slash_char = '\' - let l:mkdir_cmd = ':silent !mkdir ' - endif - - let l:doc_path = l:slash_char . 'doc' - "let l:doc_home = l:slash_char . '.vim' . l:slash_char . 'doc' - - " Figure out document path based on full name of this script: - let l:vim_plugin_path = fnamemodify(a:full_name, ':h') - "let l:vim_doc_path = fnamemodify(a:full_name, ':h:h') . l:doc_path - let l:vim_doc_path = matchstr(l:vim_plugin_path, - \ '.\{-}\ze\%(\%(ft\)\=plugin\|macros\)') . l:doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - echomsg "Doc path: " . l:vim_doc_path - execute l:mkdir_cmd . l:vim_doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - " Try a default configuration in user home: - "let l:vim_doc_path = expand("~") . l:doc_home - let l:vim_doc_path = matchstr(&rtp, - \ escape($HOME, ' \') .'[/\\]\%(\.vim\|vimfiles\)') - if (!(filewritable(l:vim_doc_path) == 2)) - execute l:mkdir_cmd . l:vim_doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - " Put a warning: - echomsg "Unable to open documentation directory" - echomsg " type :help add-local-help for more informations." - return 0 - endif - endif - endif - endif - - " Exit if we have problem to access the document directory: - if (!isdirectory(l:vim_plugin_path) - \ || !isdirectory(l:vim_doc_path) - \ || filewritable(l:vim_doc_path) != 2) - return 0 - endif - - " Full name of script and documentation file: - let l:script_name = 'xml.vim' - let l:doc_name = 'xml-plugin.txt' - let l:plugin_file = l:vim_plugin_path . l:slash_char . l:script_name - let l:doc_file = l:vim_doc_path . l:slash_char . l:doc_name - - " Bail out if document file is still up to date: - if (filereadable(l:doc_file) && - \ getftime(l:plugin_file) < getftime(l:doc_file)) - return 0 - endif - - " Prepare window position restoring command: - if (strlen(@%)) - let l:go_back = 'b ' . bufnr("%") - else - let l:go_back = 'enew!' - endif - - " Create a new buffer & read in the plugin file (me): - setl nomodeline - exe 'enew!' - exe 'r ' . l:plugin_file - - setl modeline - let l:buf = bufnr("%") - setl noswapfile modifiable - - norm zR - norm gg - - " Delete from first line to a line starts with - " === START_DOC - 1,/^=\{3,}\s\+START_DOC\C/ d - - " Delete from a line starts with - " === END_DOC - " to the end of the documents: - /^=\{3,}\s\+END_DOC\C/,$ d - - " Remove fold marks: - "% s/{\{3}[1-9]/ / - - " Add modeline for help doc: the modeline string is mangled intentionally - " to avoid it be recognized by VIM: - call append(line('$'), '') - call append(line('$'), ' v' . 'im:tw=78:ts=8:fen:fdm=marker:ft=help:norl:') - - " Replace revision: - exe "normal! :1,5s/#version#/ v" . a:revision . "/\<CR>" - - " Save the help document: - exe 'w! ' . l:doc_file - exe l:go_back - exe 'bw ' . l:buf - - " Build help tags: - exe 'helptags ' . l:vim_doc_path - - return 1 -endfunction -" }}}2 - -let s:revision= - \ substitute("$Revision: 1.36 $",'\$\S*: \([.0-9]\+\) \$','\1','') -silent! let s:install_status = - \ s:XmlInstallDocumentation(expand('<sfile>:p'), s:revision) -if (s:install_status == 1) - echom expand("<sfile>:t:r") . '-plugin v' . s:revision . - \ ': Help-documentation installed.' -endif - - -" Mappings of keys to functions {{{1 -nnoremap <silent> <buffer> <LocalLeader>5 :call <SID>Matches()<Cr> -vnoremap <silent> <buffer> <LocalLeader>5 <Esc>:call <SID>MatchesVisual()<Cr> -nnoremap <silent> <buffer> <LocalLeader>% :call <SID>Matches()<Cr> -vnoremap <silent> <buffer> <LocalLeader>% <Esc>:call <SID>MatchesVisual()<Cr> -nnoremap <silent> <buffer> <LocalLeader>c :call <SID>Change()<Cr> -nnoremap <silent> <buffer> <LocalLeader>C :call <SID>ChangeWholeTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>d :call <SID>Delete()<Cr> -nnoremap <silent> <buffer> <LocalLeader>D :call <SID>DeleteSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>e :call <SID>EndTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>] :call <SID>DelComment()<Cr> -nnoremap <silent> <buffer> <LocalLeader>} :call <SID>DelCommentSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>f :call <SID>FoldTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>F :call <SID>FoldTagAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>g :call <SID>FormatTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>G :call <SID>FormatTagAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>I :call <SID>IndentAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>j :call <SID>Join()<Cr> -nnoremap <silent> <buffer> <LocalLeader>O :call <SID>BeforeTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>= :call <SID>CommentTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>o :call <SID>AfterTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>s :call <SID>StartTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>[ :call <SID>DelCData()<Cr> -nnoremap <silent> <buffer> <LocalLeader>{ :call <SID>DelCDataSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>> :call <SID>ShiftRight()<Cr> -nnoremap <silent> <buffer> <LocalLeader>< :call <SID>ShiftLeft()<Cr> -vnoremap <silent> <buffer> <LocalLeader>l <Esc>:call <SID>vlistitem()<Cr> -vnoremap <silent> <buffer> <LocalLeader>v <Esc>:call <SID>BlockTag(0)<Cr> -vnoremap <silent> <buffer> <LocalLeader>V <Esc>:call <SID>BlockTag(1)<Cr> -vnoremap <silent> <buffer> <LocalLeader>c <Esc>:call <SID>BlockWith('<![CDATA[',']]>')<Cr> -vnoremap <silent> <buffer> <LocalLeader>< <Esc>:call <SID>BlockWith('<!--','-->')<Cr> - -" Move around functions. -noremap <silent><buffer> [[ m':call <SID>findOpenTag("bW")<CR> -noremap <silent><buffer> ]] m':call <SID>findOpenTag( "W")<CR> -noremap <silent><buffer> [] m':call <SID>findCloseTag( "bW")<CR> -noremap <silent><buffer> ][ m':call <SID>findCloseTag( "W")<CR> - -" Move around comments -noremap <silent><buffer> ]" :call search('^\(\s*<!--.*\n\)\@<!\(\s*-->\)', "W")<CR> -noremap <silent><buffer> [" :call search('\%(^\s*<!--.*\n\)\%(^\s*-->\)\@!', "bW")<CR> - - -setlocal iskeyword=@,48-57,_,192-255,58 -exe 'inoremap <silent> <buffer> '.b:suffix. " ><Esc>db:call <SID>makeElement()<Cr>" -if !exists("g:xml_tag_completion_map") - inoremap <silent> <buffer> > ><Esc>:call <SID>CloseTagFun()<Cr> -else - execute "inoremap <silent> <buffer> " . g:xml_tag_completion_map . " ><Esc>:call <SID>CloseTagFun()<Cr>" -endif - - - -finish - -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""/*}}}*/ -" Section: Documentation content {{{1 -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -=== START_DOC -*xml-plugin.txt* Help edit XML and SGML documents. #version# - - XML Edit ~ - -A filetype plugin to help edit XML and SGML documents. - -This script provides some convenience when editing XML (and some SGML -including HTML) formated documents. It allows you to jump to the -beginning or end of the tag block your cursor is in. '%' will jump -between '<' and '>' within the tag your cursor is in. When in insert -mode and you finish a tag (pressing '>') the tag will be completed. If -you press '>' twice it will place the cursor in the middle of the tags -on it's own line (helps with nested tags). - -Usage: Place this file into your ftplugin directory. To add html support -Sym-link or copy this file to html.vim in your ftplugin directory. To activte -the script place 'filetype plugin on' in your |.vimrc| file. See |ftplugins| -for more information on this topic. - -If the file edited is of type "html" and "xml_use_html" is defined then -the following tags will not auto complete: <img>, <input>, <param>, -<frame>, <br>, <hr>, <meta>, <link>, <base>, <area> - -If the file edited is of type 'html' and 'xml_use_xhtml' is defined the -above tags will autocomplete the xml closing staying xhtml compatable. -ex. <hr> becomes <hr /> (see |xml-plugin-settings|) - -Known Bugs {{{1 ~ - -- < & > marks inside of a CDATA section are interpreted as actual XML tags - even if unmatched. -- The script can not handle leading spaces such as < tag></ tag> it is - illegal XML syntax and considered very bad form. -- Placing a literal `>' in an attribute value will auto complete despite that - the start tag isn't finished. This is poor XML anyway you should use - > instead. - - ------------------------------------------------------------------------------- - *xml-plugin-settings* -Options {{{1 - -(All options must be placed in your |.vimrc| prior to the |ftplugin| -command.) - -xml_tag_completion_map - Use this setting to change the default mapping to auto complete a - tag. By default typing a literal `>' will cause the tag your editing - to auto complete; pressing twice will auto nest the tag. By using - this setting the `>' will be a literal `>' and you must use the new - mapping to perform auto completion and auto nesting. For example if - you wanted Control-L to perform auto completion inmstead of typing a - `>' place the following into your .vimrc: > - let xml_tag_completion_map = "<C-l>" -< -xml_no_auto_nesting (Not Working!!!!!) - This turns off the auto nesting feature. After a completion is made - and another `>' is typed xml-edit automatically will break the tag - accross multiple lines and indent the curser to make creating nested - tqags easier. This feature turns it off. Enter the following in your - .vimrc: > - let xml_no_auto_nesting = 1 -< -xml_use_xhtml - When editing HTML this will auto close the short tags to make valid - XML like <hr/> and <br/>. Enter the following in your vimrc to - turn this option on: > - let xml_use_xhtml = 1 - if the filetype is xhtml and g:xml_use_xhtml doesn't exists - the script defines it to be 1. (This also assumes that you have linked - xml.vim to xhtml.vim. Otherwise this item is moot) - For a file to be of xhtml type there need to be a doctype declaration!! - just naming a file something.xhtml doesn't make it type xhtml! -< -xml_no_html - This turns of the support for HTML specific tags. Place this in your - .vimrc: > - let xml_no_html = 1 -< ------------------------------------------------------------------------------- - *xml-plugin-mappings* - -Mapings and their functions {{{1 - -Typing '>' will start the tag closing routine. -Typing (Where | means cursor position) - <para>| -results in - <para>|</para> - -Typing - <para>>|</para> -results in - <para> - | - </para> -typing a lone '>' and no '<' in front of it accepts the '>' (But having -lone '>' or '<' in a XML file is frown upon except in <!CDATA> sections, -and that will throw of the plugin!!). - -Typing </tag> or <tag/> also results in na expanding. So when editing -html type <input .... /> - -The closing routing also ignores DTD tags '<!,,>' and processing -instructions '<?....?>'. Thus typing these result in no expansion. - - -<LocalLeader> is a setting in VIM that depicts a prefix for scripts and -plugins to use. By default this is the backslash key `\'. See |mapleader| -for details. - -;; make element out previous word and close it {{{2 - - when typing a word;; wil create <word>|</word> - when word on its own line it will be - <word> - | - </word> - the suffix can be changed by setting - let makeElementSuf = ',,,' in your .vimrc - Thanks to Bart van Deenen - (http://www.vim.org/scripts/script.php?script_id=632) - -[ and ] mappings {{{2 - <LocalLeader>[ Delete <![CDATA[ ]]> delimiters - <LocalLeader>{ Delete <![CDATA[ ]]> section - <LocalLeader>] Delete <!-- --> delimiters - <LocalLeader>} Delete <!-- --> section - [[ Goto to the previous open tag - [[ Goto to the next open tag - [] Goto to the previous close tag - ][ Goto to the next close tag - [" Goto to the next comment - ]" Goto the previous comment -<LocalLeader>5 Jump to the matching tag. {{{2 -<LocalLeader>% Jump to the matching tag. - - -<LocalLeader>c Rename tag {{{2 - -<LocalLeader>C Rename tag and remove attributes {{{2 - Will ask for attributes - -<LocalLeader>d Deletes the surrounding tags from the cursor. {{{2 - <tag1>outter <tag2>inner text</tag2> text</tag1> - | - Turns to: - outter <tag2>inner text</tag2> text - | - -<LocalLeader>D Deletes the tag and it contents {{{2 - - and put it in register x. - <tag1>outter <tag2>inner text</tag2> text</tag1> - | - Turns to: - <tag1>outter text</tag1> - -<LocalLeader>e provide endtag for open tags. {{{2 - - provide endtag for open tags. Watch where de cursor is - <para><listitem>list item content - | - pressing \e twice produces - <para><listitem>list item content</para></listitem> - -<LocalLeader>f fold the tag under the cursor {{{2 - <para> - line 1 - line 2 - line 3 - </para> - \f produces - +-- 5 lines: <para>-------------------------- - - -<LocalLeader>F all tags of name 'tag' will be fold. {{{2 - - If there isn't a tag under - the cursor you will be asked for one. - -<LocalLeader>g Format (Vim's gq function) {{{2 - - will make a visual block of tag under cursor and then format using gq - - -<LocalLeader>G Format all tags under cursor (Vim's gq function) {{{2 - - If there isn't a tag under - the cursor you will be asked for one. - - -<LocalLeader>I Indent all tags {{{2 - - will create a multiline layout every opening tag will be shifted out - and every closing tag will be shifted in. Be aware that the rendering - of the XML through XSLT and/or DSSSL, might be changed by this. - Be aware tha if the file is big, more than 1000 lines, the reformatting - takes a long time because vim has to make a big undo buffer. - For example using \I on the example below: - - <chapter><title>Indent</title><para>The documentation</para></chapter> - - - Becomes - - <chapter> - <title> - Indent - </title> - <para> - The documentation - </para> - </chapter> - - -<LocalLeader>j Joins two the SAME sections together. {{{2 - - The sections must be next to each other. - <para> This is line 1 - of a paragraph. </para> - <para> This is line 2 - | - of a paragraph. </para> - \j produces - <para> This is line 1 - of a paragraph. - This is line 2 - of a paragraph. </para> - -<LocalLeader>l visual surround the block with listitem and para {{{2 - When marking up docbook tekst you have the issue that listitems - consist of 2 item. This key combination inserts them both, - - blaah - | - \l produces - <listitem> - <para>blaah</para> - </listitem> - -<LocalLeader>o Insert a tag inside the current one (like vim o) {{{2 - You are asked for tag and attributes. - - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - | - \o produces - <tag1> - <aftertag><tag2><tag3>blaah</tag3></tag2></aftertag> - </tag1> - -<LocalLeader>O Insert a tag outside the current one (like vim O) {{{2 - You are asked for tag and attributes. - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - | - \O produces - <beforetag> - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - </beforetag> - -<LocalLeader>s Insert an opening tag for an closing tag. {{{2 - list item content</para></listitem> - | - pressing \s twice produces - <para><listitem>list item content</para></listitem> - -<LocalLeader>[ Delete <![CDATA[ ]]> delimiters {{{2 - Removes Only <CDATA[ and ]]> - handy when you want to uncomment a section. - You need to stand in the tag and not on an other tag - <![CDATA[ <tag> ]]> - if you cursor is outside <tag> but inside the - CDATA tag the delition works. -<LocalLeader>{ Delete <![CDATA[ ]]> section {{{2 - Removes everything tag and Content -<LocalLeader>] Delete <!-- --> delimiters {{{2 - Uncommnet a block. -<LocalLeader>} Delete <!-- --> section {{{2 - Removes everything tag and Content -<LocalLeader>> shift right opening tag and closing tag. {{{2 - shift everything between the tags 1 shiftwide right -<LocalLeader>< shift left opening tag and closing tag. {{{2 - shift everything between the tags 1 shiftwide left -<LocalLeader>c Visual Place a CDATA section around the selected text. {{{2 - Place Cdata section around the block -<LocalLeader>< Visual Place a Comment around the selected text. {{{2 - Place comment around the block -<LocalLeader>5 Extend the visual selection to the matching tag. {{{2 -<LocalLeader>% - Extend the visual selection to the matching tag. Make sure you are at - the start of the opening tag or the end of the closing tag. -<LocalLeader>v Visual Place a tag around the selected text. {{{2 - - You are asked for tag and attributes. You - need to have selected text in visual mode before you can use this - mapping. See |visual-mode| for details. - Be careful where you place the marks. - The top uses append - The bottom uses append - Useful when marking up a text file - ------------------------------------------------------------------------------- - *xml-plugin-callbacks* - -Callback Functions {{{2 ~ - -A callback function is a function used to customize features on a per tag -basis. For example say you wish to have a default set of attributs when you -type an empty tag like this: - You type: <tag> - You get: <tag default="attributes"></tag> - -This is for any script programmers who wish to add xml-plugin support to -there own filetype plugins. - -Callback functions recive one attribute variable which is the tag name. The -all must return either a string or the number zero. If it returns a string -the plugin will place the string in the proper location. If it is a zero the -plugin will ignore and continue as if no callback existed. - -The following are implemented callback functions: - -HtmlAttribCallback - This is used to add default attributes to html tag. It is intended - for HTML files only. - -XmlAttribCallback - This is a generic callback for xml tags intended to add attributes. - - *xml-plugin-html* -Callback Example {{{2 ~ - -The following is an example of using XmlAttribCallback in your .vimrc -> - function XmlAttribCallback (xml_tag) - if a:xml_tag ==? "my-xml-tag" - return "attributes=\"my xml attributes\"" - else - return 0 - endif - endfunction -< -The following is a sample html.vim file type plugin you could use: -> - " Vim script file vim600:fdm=marker: - " FileType: HTML - " Maintainer: Devin Weaver <vim (at) tritarget.com> - " Location: http://www.vim.org/scripts/script.php?script_id=301 - - " This is a wrapper script to add extra html support to xml documents. - " Original script can be seen in xml-plugin documentation. - - " Only do this when not done yet for this buffer - if exists("b:did_ftplugin") - finish - endif - " Don't set 'b:did_ftplugin = 1' because that is xml.vim's responsability. - - let b:html_mode = 1 - - if !exists("*HtmlAttribCallback") - function HtmlAttribCallback( xml_tag ) - if a:xml_tag ==? "table" - return "cellpadding=\"0\" cellspacing=\"0\" border=\"0\"" - elseif a:xml_tag ==? "link" - return "href=\"/site.css\" rel=\"StyleSheet\" type=\"text/css\"" - elseif a:xml_tag ==? "body" - return "bgcolor=\"white\"" - elseif a:xml_tag ==? "frame" - return "name=\"NAME\" src=\"/\" scrolling=\"auto\" noresize" - elseif a:xml_tag ==? "frameset" - return "rows=\"0,*\" cols=\"*,0\" border=\"0\"" - elseif a:xml_tag ==? "img" - return "src=\"\" width=\"0\" height=\"0\" border=\"0\" alt=\"\"" - elseif a:xml_tag ==? "a" - if has("browse") - " Look up a file to fill the href. Used in local relative file - " links. typeing your own href before closing the tag with `>' - " will override this. - let cwd = getcwd() - let cwd = substitute (cwd, "\\", "/", "g") - let href = browse (0, "Link to href...", getcwd(), "") - let href = substitute (href, cwd . "/", "", "") - let href = substitute (href, " ", "%20", "g") - else - let href = "" - endif - return "href=\"" . href . "\"" - else - return 0 - endif - endfunction - endif - - " On to loading xml.vim - runtime ftplugin/xml.vim -< -=== END_DOC -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" v im:tw=78:ts=8:ft=help:norl: -" vim600: set foldmethod=marker tabstop=8 shiftwidth=2 softtabstop=2 smartindent smarttab : -"fileencoding=iso-8859-15 -=== END_DOC -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - - - - - - -" Vim settingѕ {{{1 -" vim:tw=78:ts=2:ft=help:norl: -" vim: set foldmethod=marker tabstop=2 shiftwidth=2 softtabstop=2 smartindent smarttab : -"fileencoding=utf-8 - diff --git a/files/.vim/ftplugin/xml.vim b/files/.vim/ftplugin/xml.vim deleted file mode 100644 index 55e9023..0000000 --- a/files/.vim/ftplugin/xml.vim +++ /dev/null @@ -1,1854 +0,0 @@ -" Vim script file vim600:fdm=marker: -" FileType: XML -" Author: Rene de Zwart <renez (at) lightcon.xs4all.nl> -" Maintainer: Rene de Zwart <renez (at) lightcon.xs4all.nl> -" Last Change: Date: 2009-11-12 -" Version: Revision: 1.37 -" -" Licence: This program is free software; you can redistribute it -" and/or modify it under the terms of the GNU General Public -" License. See http://www.gnu.org/copyleft/gpl.txt -" Credits: Devin Weaver <vim (at) tritarget.com> et all -" for the original code. Guo-Peng Wen for the self -" install documentation code. -" Bart vam Deenen for makeElement function -" Rene de Zwart - - -" Observation - If you want to do something to a match pair most of the time -" you must do first the close tag. Because doing first the open -" tag could change the close tag position. - -" NOTE with filetype index on de standard indent/html.vim interferes -" with xml.vim. You can -" 1) set filetype indent off in .vimrc -" 2) echo "let b:did_indent = 1" > .vim/indent/html.vim - - -" Only do this when not done yet for this buffer -if exists("b:did_ftplugin") - finish -endif -let b:did_ftplugin = 1 - -setlocal commentstring=<!--%s--> - -" XML: thanks to Johannes Zellner and Akbar Ibrahim -" - case sensitive -" - don't match empty tags <fred/> -" - match <!--, --> style comments (but not --, --) -" - match <!, > inlined dtd's. This is not perfect, as it -" gets confused for example by -" <!ENTITY gt ">"> -if exists("loaded_matchit") - let b:match_ignorecase=0 - let b:match_words = - \ '<:>,' . - \ '<\@<=!\[CDATA\[:]]>,'. - \ '<\@<=!--:-->,'. - \ '<\@<=?\k\+:?>,'. - \ '<\@<=\([^ \t>/]\+\)\%(\s\+[^>]*\%([^/]>\|$\)\|>\|$\):<\@<=/\1>,'. - \ '<\@<=\%([^ \t>/]\+\)\%(\s\+[^/>]*\|$\):/>' -endif - -" Script rgular expresion used. Documents those nasty criters {{{1 -let s:NoSlashBeforeGt = '\(\/\)\@\<!>' -" Don't check for quotes around attributes!!! -let s:Attrib = '\(\(\s\|\n\)\+\([^>= \t]\+=[^>&]\+\)\(\s\|\n\)*\)' -let s:OptAttrib = s:Attrib . '*'. s:NoSlashBeforeGt -let s:ReqAttrib = s:Attrib . '\+'. s:NoSlashBeforeGt -let s:OpenTag = '<[^!/?][^>]*' . s:OptAttrib -let s:OpenOrCloseTag = '<[^!?][^>]*'. s:OptAttrib -let s:CloseTag = '<\/[^>]*'. s:NoSlashBeforeGt -let s:SpaceInfront = '^\s*<' -let s:EndofName = '\($\|\s\|>\)' - -" Buffer variables {{{1 -let b:emptyTags='^\(img\|input\|param\|frame\|br\|hr\|meta\|link\|base\|area\)$' -let b:firstWasEndTag = 0 -let b:html_mode =((&filetype =~ 'x\?html') && !exists("g:xml_no_html")) -let b:haveAtt = 0 -let b:lastTag = "" -let b:lastAtt = "" -let b:suffix = (exists('g:makeElementSuf') ? g:makeElementSuf : ';;') -let b:xml_use_xhtml = 0 -if exists('g:xml_use_xhtml') - let b:xml_use_xhtml = g:xml_use_xhtml -elseif &filetype == 'xhtml' - let b:xml_use_xhtml = 1 -en - - - - -" NewFileXML -> Inserts <?xml?> at top of new file. {{{1 -if !exists("*NewFileXML") -function! NewFileXML( ) - " Where is g:did_xhtmlcf_inits defined? - if &filetype == 'xml' || - \ (!exists ("g:did_xhtmlcf_inits") && - \ b:xml_use_xhtml && - \ (&filetype =~ 'x\?html')) - if append (0, '<?xml version="1.0"?>') - normal! G - endif - endif -endfunction -endif - - - -" Callback -> Checks for tag callbacks and executes them. {{{1 -if !exists("*s:Callback") -function! s:Callback( xml_tag, isHtml ) - let text = 0 - if a:isHtml == 1 && exists ("*HtmlAttribCallback") - let text = HtmlAttribCallback (a:xml_tag) - elseif exists ("*XmlAttribCallback") - let text = XmlAttribCallback (a:xml_tag) - endif - if text != '0' - execute "normal! i " . text ."\<Esc>l" - endif -endfunction -endif - -" SavePos() saves position in bufferwide variable {{{1 -fun! s:SavePos() - retu 'call cursor('.line('.').','. col('.'). ')' -endf - -" findOpenTag() {{{1 -fun! s:findOpenTag(flag) - call search(s:OpenTag,a:flag) -endf - -" findCloseTag() {{{1 -fun! s:findCloseTag(flag) - call search(s:CloseTag,a:flag) -endf - -" GetTagName() Gets the tagname from start position {{{1 -"Now lets go for the name part. The namepart are xmlnamechars which -"is quite a big range. We assume that everything after '<' or '</' -"until the first 'space', 'forward slash' or '>' ends de name part. -if !exists('*s:GetTagName') -fun! s:GetTagName(from) - let l:end = match(getline('.'), s:EndofName,a:from) - return strpart(getline('.'),a:from, l:end - a:from ) -endf -en -" hasAtt() Looks for attribute in open tag {{{1 -" expect cursor to be on < -fun! s:hasAtt() - "Check if this open tag has attributes - let l:line = line('.') | let l:col = col('.') - if search(b:tagName . s:ReqAttrib,'W') > 0 - if l:line == line('.') && l:col == (col('.')-1) - let b:haveAtt = 1 - en - en -endf - - -" TagUnderCursor() Is there a tag under the cursor? {{{1 -" Set bufer wide variable -" - b:firstWasEndTag -" - b:tagName -" - b:endcol & b:endline only used by Match() -" - b:gotoCloseTag (if the tag under the cursor is one) -" - b:gotoOpenTag (if the tag under the cursor is one) -" on exit -" - returns 1 (true) or 0 (false) -" - position is at '<' -if !exists('*s:TagUnderCursor') -fun! s:TagUnderCursor() - let b:firstWasEndTag = 0 - let l:haveTag = 0 - let b:haveAtt = 0 - - "Lets find forward a < or a >. If we first find a > we might be in a tag. - "If we find a < first or nothing we are definitly not in a tag - - if getline('.')[col('.') - 1] == '>' - let b:endcol = col('.') - let b:endline = line('.') - if getline('.')[col('.')-2] == '/' - "we don't work with empty tags - retu l:haveTag - en - " begin: gwang customization for JSP development - if getline('.')[col('.')-2] == '%' - "we don't work with jsp %> tags - retu l:haveTag - en - " end: gwang customization for JSP development - " begin: gwang customization for PHP development - if getline('.')[col('.')-2] == '?' - "we don't work with php ?> tags - retu l:haveTag - en - " end: gwang customization for PHP development - elseif search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - let b:endcol = col('.') - let b:endline = line('.') - if getline('.')[col('.')-2] == '-' - "we don't work with comment tags - retu l:haveTag - en - if getline('.')[col('.')-2] == '/' - "we don't work with empty tags - retu l:haveTag - en - el - retu l:haveTag - en - el - retu l:haveTag - en - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' - if getline('.')[col('.')] == '/' - let b:firstWasEndTag = 1 - let b:gotoCloseTag = s:SavePos() - elseif getline('.')[col('.')] == '?' || getline('.')[col('.')] == '!' - "we don't deal with processing instructions or dtd - "related definitions - retu l:haveTag - el - let b:gotoOpenTag = s:SavePos() - en - el - retu l:haveTag - en - el - retu l:haveTag - en - - "we have established that we are between something like - "'</\?[^>]*>' - - let b:tagName = s:GetTagName(col('.') + b:firstWasEndTag) - "echo 'Tag ' . b:tagName - - "begin: gwang customization, do not work with an empty tag name - if b:tagName == '' - retu l:haveTag - en - "end: gwang customization, do not work with an empty tag name - - let l:haveTag = 1 - if b:firstWasEndTag == 0 - call s:hasAtt() - exe b:gotoOpenTag - en - retu l:haveTag -endf -en - -" Match(tagname) Looks for open or close tag of tagname {{{1 -" Set buffer wide variable -" - b:gotoCloseTag (if the Match tag is one) -" - b:gotoOpenTag (if the Match tag is one) -" on exit -" - returns 1 (true) or 0 (false) -" - position is at '<' -if !exists('*s:Match') -fun! s:Match(name) - let l:pat = '</\=' . a:name . s:OptAttrib - if b:firstWasEndTag - exe b:gotoCloseTag - let l:flags='bW' - let l:level = -1 - el - exe 'normal! '.b:endline.'G0'.(b:endcol-1).'l' - let l:flags='W' - let l:level = 1 - en - while l:level && search(l:pat,l:flags) > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level - echo "no matching tag!!!!!" - retu l:level - en - if b:firstWasEndTag - let b:gotoOpenTag = s:SavePos() - call s:hasAtt() - exe b:gotoOpenTag - el - let b:gotoCloseTag = s:SavePos() - en - retu l:level == 0 -endf -en - -" InComment() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:InComment') -fun! s:InComment() -let b:endcom=0 -let b:begcom=0 - - "Lets find forward a < or a >. If we first find a > we might be in a comment. - "If we find a < first or nothing we are definitly not in a Comment - - if getline('.')[col('.') - 1] == '>' - if getline('.')[col('.')-2] == '-' && getline('.')[col('.')-3] == '-' - let b:endcomcol=col('.') - let b:endcomline=line('.') - let b:endcom=1 - retu 1 - en - elseif getline('.')[col('.')-1] == '<' && getline('.')[col('.')] == '!' - \ && getline('.')[col('.')+1] == '-' && getline('.')[col('.')+2] == '-' - let b:begcomcol= col('.') - let b:begcomline=line('.') - let b:begcom=1 - retu 1 - en - "We are not standing on a begin/end comment - "Is the first > an ending comment? - if search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - if getline('.')[col('.')-2] == '-' && getline('.')[col('.')-3] == '-' - let b:endcomcol=col('.') - let b:endcomline=line('.') - let b:endcom=1 - retu 1 - en - en - en - "Forward is not a ending comment - "is backward a starting comment - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' && getline('.')[col('.')] == '!' - \ && getline('.')[col('.')+1] == '-' && getline('.')[col('.')+2] == '-' - let b:begcomcol=col('.') - let b:begcomline=line('.') - let b:begcom=1 - retu 1 - en - en - retu 0 -endf -en - -" DelComment() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelComment') -fun! s:DelComment() - - let l:restore = s:SavePos() - if s:InComment() - if b:begcom - if search('-->','W' ) >=0 - normal! hh3x - call cursor(b:begcomline,b:begcomcol) - normal! 4x - retu 1 - en - el - if search('<!--','bW' ) >=0 - normal! 4x - call cursor(b:endcomline,b:endcomcol) - normal! hh3x - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" DelCommentSection() Is there a Comment under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCommentSection') -fun! s:DelCommentSection() - - let l:restore = s:SavePos() - if s:InComment() - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - if b:begcom - if search('-->','W' ) >=0 - exe "normal! f>a".l:sentinel."\<Esc>" - call cursor(b:begcomline,b:begcomcol) - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - el - if search('<!--','bW' ) >=0 - let l:restore = s:SavePos() - call cursor(b:endcomline,b:endcomcol) - exe "normal! a".l:sentinel."\<Esc>" - exe l:restore - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" DelCData() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCData') -fun! s:DelCData() - - let l:restore = s:SavePos() - if s:InCData() - if b:begdat - if search(']]>','W' ) >=0 - normal! hh3x - call cursor(b:begdatline,b:begdatcol) - normal! 9x - retu 1 - en - el - if search('<![CDATA[','bW' ) >=0 - normal! 9x - call cursor(b:enddatline,b:enddatcol) - normal! hh3x - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - -" InCData() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:InCData') -fun! s:InCData() -let b:enddat=0 -let b:begdat=0 - - "Lets find forward a < or a >. If we first find a > we might be in a comment. - "If we find a < first or nothing we are definitly not in a Comment - - if getline('.')[col('.') - 1] == '>' - if getline('.')[col('.')-2] == ']' && getline('.')[col('.')-3] == ']' - let b:enddatcol=col('.') - let b:enddatline=line('.') - let b:enddat=1 - retu 1 - en - elseif getline('.')[col('.')-1] == '<' - if match(getline('.'),'<![CDATA[') > 0 - let b:begdatcol= col('.') - let b:begdatline=line('.') - let b:begdat=1 - retu 1 - en - en - "We are not standing on a begin/end comment - "Is the first > aending comment? - if search('[<>]','W') >0 - if getline('.')[col('.')-1] == '>' - if getline('.')[col('.')-2] == ']' && getline('.')[col('.')-3] == ']' - let b:enddatcol=col('.') - let b:enddatline=line('.') - let b:enddat=1 - retu 1 - en - en - en - "Forward is not a ending datment - "is backward a starting comment - - if search('[<>]','bW' ) >=0 - if getline('.')[col('.')-1] == '<' - if match(getline('.'),'<![CDATA[') > 0 - let l:newname = inputdialog('Found CDATA') - let b:begdatcol=col('.') - let b:begdatline=line('.') - let b:begdat=1 - retu 1 - en - en - en - retu 0 -endf -en - - -" DelCDataSection() Is there a CData under the cursor? {{{1 -" - returns 1 (true) or 0 (false) - -if !exists('*s:DelCDataSection') -fun! s:DelCDataSection() - - let l:restore = s:SavePos() - if s:InCData() - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - if b:begdat - if search(']]>','W' ) >=0 - exe "normal! f>a".l:sentinel."\<Esc>" - call cursor(b:begdatline,b:begdatcol) - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - el - if search('<![CDATA[','bW' ) >=0 - let l:restore = s:SavePos() - call cursor(b:enddatline,b:enddatcol) - exe "normal! a".l:sentinel."\<Esc>" - exe l:restore - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - retu 1 - en - en - en - exe l:restore - retu 0 -endf -en - - -" Matches() Matches de tagname under de cursor {{{1 -if !exists('*s:Matches') -fun! s:Matches() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - retu - en - en - exe l:restore -endf -en - -" MatchesVisual() Matches de tagname under de cursor {{{1 -if !exists('*s:MatchesVisual') -fun! s:MatchesVisual() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if b:firstWasEndTag - normal! f> - en - normal! gv - if s:Match(b:tagName) - if b:firstWasEndTag == 0 - normal! f> - en - retu - en - normal! v - en - exe l:restore -endf -en - -" makeElement() makes the previous woord an tag and close {{{1 -if !exists('*s:makeElement') -function! s:makeElement() - let b:tagName = @@ - let b:haveAtt = 0 - let l:alone = (match(getline('.'),'^\s*>\s*$') >= 0) - let l:endOfLine = ((col('.')+1) == col('$')) - normal! i<pf> - if b:html_mode && b:tagName =~? b:emptyTags - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - endif - if b:xml_use_xhtml - exe "normal! i/\<Esc>l" - en - if l:endOfLine - start! - el - normal! l - start - en - el - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - end - if l:alone - exe 'normal! o</pa>Ox>>$x' - start! - el - exe 'normal! a</pa>F<' - start - en - en -endfunction -en - -" CloseTagFun() closing the tag which is being typed {{{1 -if !exists('*s:CloseTagFun') -fun! s:CloseTagFun() - let l:restore = s:SavePos() - let l:endOfLine = ((col('.')+1) == col('$')) - if col('.') > 1 && getline('.')[col('.')-2] == '>' - "Multiline request. <t>></t> --> - "<t> - " cursor comes here - "</t> - normal! h - if s:TagUnderCursor() - if b:firstWasEndTag == 0 - exe "normal! 2f>s\<Cr>\<Esc>Ox\<Esc>>>$x" - start! - retu - en - en - elseif s:TagUnderCursor() - if b:firstWasEndTag == 0 - exe "normal! />\<Cr>" - if b:html_mode && b:tagName =~? b:emptyTags - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - en - if b:xml_use_xhtml - exe "normal! i/\<Esc>l" - en - if l:endOfLine - start! - retu - el - normal! l - start - retu - en - el - if b:haveAtt == 0 - call s:Callback (b:tagName, b:html_mode) - en - exe "normal! a</" . b:tagName . ">\<Esc>F<" - start - retu - en - en - en - exe l:restore - if (col('.')+1) == col("$") - startinsert! - else - normal! l - startinsert - en -endf -en - -" BlockTag() Surround a visual block with a tag {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:BlockTag') -fun! s:BlockTag(multi) - let l:newname = inputdialog('Surround block with : ',b:lastTag) - if strlen( l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - - "Get at the end of the block - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - if a:multi - exe "normal! a\<Cr></".l:newname.">\<Cr>\<Esc>" - let l:eline = line('.') - normal! gvov - if col('.') == col("'>") && line('.') == line("'>") - normal! gvov - en - let l:sline = line(".") + 2 - exe "normal! i\<Cr><".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \ .">\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe l:sline.','.l:eline.'>' - let &report= l:rep - exe 'normal! '.l:sline.'G0mh'.l:eline."G$v'hgq" - el - exe "normal! a</".l:newname.">\<Esc>gvov" - if col('.') == col("'>") && line('.') == line("'>") - normal! gvov - en - exe "normal! i<".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \ .">\<Esc>" - en -endf -en -" BlockWith() Surround a visual block with a open and a close {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:BlockWith') -fun! s:BlockWith(open,close) - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - exe "normal! a\<Cr>;x\<Esc>0cfx".a:close."\<Cr>\<Esc>" - normal! gvov - exe "normal! i\<Cr>;x\<Esc>0cfx".a:open."\<Cr>\<Esc>" -endf -en -" vlistitem() Surround a visual block with a listitem para tag {{{1 -" Be carefull where You place the block -" the top is done with insert! -" the bottem is done with append! -if !exists('*s:vlistitem') -fun! s:vlistitem() - "Get at the end of the block - if col('.') == col("'<") && line('.') == line("'<") - normal! gvov - en - exe "normal! a</para>\<Cr></listitem>\<Esc>mh" - normal! gvov - exe "normal! i\<Cr><listitem>\<Cr>\<Tab><para>\<Esc>'h/listitem>/e+1\<Cr>" -endf -en -" Change() Only renames the tag {{{1 -if !exists('*s:Change') -fun! s:Change() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = inputdialog('Change tag '.b:tagName.' to : ',b:lastTag) - if strlen( l:newname) == 0 - retu - en - let b:lastTag = l:newname - if s:Match(b:tagName) - exe b:gotoCloseTag - exe 'normal! 2lcw' . l:newname . "\<Esc>" - exe b:gotoOpenTag - exe 'normal! lcw' . l:newname . "\<Esc>" - en - en -endf -en - -" Join() Joins two the same tag adjacent sections {{{1 -if !exists('*s:Join') -fun! s:Join() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:pat = '<[^?!]\S\+\($\| \|\t\|>\)' - let l:flags='W' - if b:firstWasEndTag == 0 - let l:flags='Wb' - en - if search(s:OpenOrCloseTag,l:flags) > 0 - - let l:secondChar = getline('.')[col('.')] - if l:secondChar == '/' && b:firstWasEndTag ||l:secondChar != '/' && !b:firstWasEndTag - exe l:restore - retu - en - let l:end = 0 - if l:secondChar == '/' - let l:end = 1 - en - let l:name = s:GetTagName(col('.') + l:end) - if l:name == b:tagName - if b:firstWasEndTag - let b:gotoOpenTag = s:SavePos() - el - let b:gotoCloseTag = s:SavePos() - en - let l:DeleteTag = "normal! d/>/e\<Cr>" - exe b:gotoCloseTag - exe l:DeleteTag - exe b:gotoOpenTag - exe l:DeleteTag - en - en - en - exe l:restore -endf -en - -" ChangeWholeTag() removes attributes and rename tag {{{1 -if !exists('*s:ChangeWholeTag') -fun! s:ChangeWholeTag() - if s:TagUnderCursor() - let l:newname = inputdialog('Change whole tag '.b:tagName.' to : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! 2lc/>\<Cr>".l:newname."\<Esc>" - exe b:gotoOpenTag - exe "normal! lc/>/\<Cr>".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \."\<Esc>" - en - en -endf -en - -" Delete() Removes a tag '<a id="a">blah</a>' --> 'blah' {{{1 -if !exists('*s:Delete') -fun! s:Delete() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - let l:DeleteTag = "normal! d/>/e\<Cr>" - exe b:gotoCloseTag - exe l:DeleteTag - exe b:gotoOpenTag - exe l:DeleteTag - en - else - exe l:restore - en -endf -en - - -" DeleteSection() Deletes everything between start of open tag and end of {{{1 -" closing tag -if !exists('*s:DeleteSection') -fun! s:DeleteSection() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - let l:sentinel = 'XmLSeNtInElXmL' - let l:len = strlen(l:sentinel) - let l:rep=&report - let &report=999999 - exe b:gotoCloseTag - exe "normal! />\<Cr>a".l:sentinel."\<Esc>" - exe b:gotoOpenTag - exe "normal! \"xd/".l:sentinel."/e-".l:len."\<Cr>" - exe "normal! ".l:len."x" - let &report= l:rep - en - en -endf -en -" -" FoldTag() Fold the tag under the cursor {{{1 -if !exists('*s:FoldTag') -fun! s:FoldTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - if b:firstWasEndTag - exe '.,'.l:sline.'fold' - el - exe l:sline.',.fold' - en - en - el - exe l:restore - en -endf -en - -" FoldTagAll() Fold all tags of under the cursor {{{1 -" If no tag under the cursor it asks for a tag -if !exists('*s:FoldTagAll') -fun! s:FoldTagAll() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:tname = b:tagName - el - let l:tname = inputdialog('Which tag to fold : ',b:lastTag) - if strlen(l:tname) == 0 - exe l:restore - retu - en - let b:lastTag = l:tname - en - normal! G$ - let l:flag='w' - while search('<'.l:tname.s:OptAttrib,l:flag) > 0 - let l:flag='W' - let l:sline = line('.') - let l:level = 1 - while l:level && search('</\='.l:tname.s:OptAttrib,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - exe l:sline.',.fold' - el - let l:tmp = - \ inputdialog("The tag ".l:tname."(".l:sline.") doesn't have a closetag") - break - en - endwhile - exe l:restore -endf -en - - -" StartTag() provide the opening tag {{{1 -if !exists('*s:StartTag') -fun! s:StartTag() - let l:restore = s:SavePos() - let l:level = 1 - if getline('.')[col('.')-1] == '<' - if s:TagUnderCursor() - if b:firstWasEndTag - exe 'normal! i<'. b:tagName.">\<Esc>F<" - retu - el - let l:level = l:level + 1 - en - en - exe l:restore - en - while l:level && search(s:OpenOrCloseTag ,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - let l:Name = s:GetTagName(col('.') + 1) - exe l:restore - exe 'normal! i<'. l:Name.">\<Esc>" - en - exe l:restore -endf -en - - - -" EndTag() search for open tag and produce endtaf {{{1 -if !exists('*s:EndTag') -fun! s:EndTag() - let l:restore = s:SavePos() - let l:level = -1 - while l:level && search(s:OpenOrCloseTag,'bW') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - let l:Name = s:GetTagName(col('.')) - exe l:restore - exe 'normal! a</'. l:Name.">\e" - el - exe l:restore - en -endf -en - - -" BeforeTag() surrounds the current tag with a new one {{{1 -if !exists('*s:BeforeTag') -fun! s:BeforeTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = - \ inputdialog('Surround Before Tag '.b:tagName.' with : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! />\<Cr>a\<Cr></" . l:newname . ">\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe 'normal! i<' . l:newname . - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \.">\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - exe l:restore - en -endf -en - -" CommentTag() surrounds the current tag with a new one {{{1 -if !exists('*s:CommentTag') -fun! s:CommentTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - if s:Match(b:tagName) - exe b:gotoCloseTag - exe "normal! />\<Cr>a\<Cr>-->\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe "normal! i<!--\<Cr>\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - else - exe l:restore - en -endf -en -" AfterTag() surrounds the tags after the current one with new {{{1 -if !exists('*s:AfterTag') -fun! s:AfterTag() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:newname = - \ inputdialog('Add Tag After '.b:tagName.' with : ',b:lastTag) - if strlen(l:newname) == 0 - retu - en - let b:lastTag = l:newname - let l:newatt = inputdialog('Attributes for '.l:newname.' : ',b:lastAtt) - if strlen(l:newatt) - let b:lastAtt = l:newatt - en - if s:Match(b:tagName) - exe b:gotoCloseTag - exe 'normal! i</' . l:newname . ">\<Cr>\<Esc>" - let l:To = line('.') - exe b:gotoOpenTag - exe "normal! />\<Cr>a\<Cr><".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \.">\<Esc>" - let l:rep=&report - let &report=999999 - exe line('.').','.l:To.'>' - let &report= l:rep - en - en - exe l:restore -endf -en -" ShiftRight() Shift the tag to the right {{{1 -if !exists('*s:ShiftRight') -fun! s:ShiftRight() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - let l:eline = line('.') - if b:firstWasEndTag - exe l:eline.','.l:sline.'>' - el - exe l:sline.','.l:eline.'>' - en - en - en -endf -en - -" ShiftLeft() Shift the tag to the left {{{1 -if !exists('*s:ShiftLeft') -fun! s:ShiftLeft() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:sline = line('.') - if s:Match(b:tagName) - let l:eline = line('.') - if b:firstWasEndTag - exe l:eline.','.l:sline.'<' - el - exe l:sline.','.l:eline.'<' - en - en - en -endf -en -" FormatTag() visual select the block and use gq {{{1 -if !exists('*s:FormatTag') -fun! s:FormatTag() - if s:TagUnderCursor() - if s:Match(b:tagName) - exe b:gotoCloseTag - normal! hhmh - exe b:gotoOpenTag - exe "normal! />/e+1\<Cr>v'hgq" - en - en -endf -en - - - - -" FormatTagAll() Format all tags of name under the cursor {{{1 -" If no tag under the cursor it asks for a tag -if !exists('*s:FormatTagAll') -fun! s:FormatTagAll() - let l:restore = s:SavePos() - if s:TagUnderCursor() - let l:tname = b:tagName - el - let l:tname = inputdialog('Format every tag : ') - if strlen(l:tname) == 0 - exe l:restore - retu - en - en - normal! G$ - let l:flag = 'w' - while search('<'.l:tname . s:OptAttrib, l:flag) > 0 - let l:flag = 'W' - let l:sline = line('.') - let l:level = 1 - exe "normal! />/e+1\<cr>mh" - while l:level && search('</\='.l:tname . s:EndofName,'W') > 0 - let l:level = l:level + (getline('.')[col('.')] == '/' ? -1 : 1) - endwhile - if l:level == 0 - normal! hv'hogq - el - let l:tmp = - \ inputdialog("The tag ".l:tname."(".l:sline.") doesn't have a closetag") - break - en - endwhile - exe l:restore -endf -en - - -" IndentAll() indent all tags multiline {{{1 -if !exists('*s:IndentAll') -fun! s:IndentAll() - - let l:restore = s:SavePos() - let l:rep=&report - let &report=999999 - "shift everything left - normal! 1G<G<G<G<G<G<GG$ - if search(s:OpenTag,'w') > 0 - let l:level = 1 - normal! f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - echo "after tag".line('.') - exe "normal! a\<Cr>\<Esc>" - el - normal! j - en - normal! >Gk$ - while search(s:OpenOrCloseTag,'W') > 0 - "if there is text before the tag then move the tag to the next line - if match(getline('.'),s:SpaceInfront) == -1 - exe "normal! i\<Cr>\<Esc>l" - en - if getline('.')[col('.')] == '/' - normal! <G0f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - exe "normal! a\<Cr>\<Esc>" - en - let l:level = l:level - 1 - el - normal! f> - "if there is something after the tag move that to the next line - if col('.')+1 != col('$') - exe "normal! a\<Cr>\<Esc>" - el - normal! j0 - en - normal! >Gk$ - let l:level = l:level + 1 - en - endwhile - if l:level - let l:tmp = - \ inputdialog("The tags opening and closing are unbalanced ".l:level) - en - en - exe l:restore - let &report= l:rep -endf -en - - -" Menu options: {{{1 -augroup XML_menu_autos -au! -autocmd BufLeave,BufWinLeave * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ amenu disable Xml | - \ amenu disable Xml.* | - \ endif -autocmd BufEnter,BufWinEnter * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ amenu enable Xml | - \ amenu enable Xml.* | - \ endif -au BufNewFile * - \ if &filetype == "xml" || &filetype == "html" || &filetype == "xhtml" | - \ call NewFileXML() | - \ endif -augroup END -if !exists("g:did_xml_menu") - let g:did_xml_menu = 1 - :1011 vmenu <script> &Xml.BlockTag\ multi<Tab>V <Esc>:call <SID>BlockTag(1)<Cr> - vmenu <script> Xml.BlockTag\ inline<Tab>v <Esc>:call <SID>BlockTag(0)<CR> - vmenu <script> Xml.Insert\ listitem<Tab>l <Esc>:call <SID>vlistitem()<CR> - vmenu <script> Xml.Comment<Tab>< <Esc>:call <SID>BlockWith('<!--','-->')<Cr> - vmenu <script> Xml.Comment\ With\ CData<Tab>c <Esc>:call <SID>BlockWith('<![CDATA[',']]>')<Cr> - nmenu <script> Xml.Comment\ Tag<Tab>= <Esc>:call <SID>CommentTag()<Cr> - imenu <script> Xml.Comment\ Tag<Tab>= <Esc>:call <SID>CommentTag()<Cr> - nmenu <script> Xml.Change<Tab>c :call <SID>Change()<CR> - imenu <script> Xml.Change<Tab>c <C-C>:call <SID>Change()<CR> - nmenu <script> Xml.Change\ Whole\ Tag<Tab>C :call <SID>ChangeWholeTag()<CR> - imenu <script> Xml.Change\ Whole\ Tag<Tab>C <C-C>:call <SID>ChangeWholeTag()<CR> - nmenu <script> Xml.Delete\ Comment<Tab>] :call <SID>DelComment()<CR> - imenu <script> Xml.Delete\ Comment<Tab>] <C-C>:call <SID>DelComment()<CR> - nmenu <script> Xml.Delete\ Comment\ Section<Tab>} :call <SID>DelCommentSection()<CR> - imenu <script> Xml.Delete\ Comment\ Section<Tab>} <C-C>:call <SID>DelCommentSection()<CR> - nmenu <script> Xml.Delete\ CData<Tab>[ :call <SID>DelCData()<CR> - imenu <script> Xml.Delete\ CData<Tab>[ <C-C>:call <SID>DelCData()<CR> - nmenu <script> Xml.Delete\ CData\ Section<Tab>[ :call <SID>DelCDataSection()<CR> - imenu <script> Xml.Delete\ CData\ Section<Tab>[ <C-C>:call <SID>DelCDataSection()<CR> - nmenu <script> Xml.Delete\ Tag<Tab>d :call <SID>Delete()<CR> - imenu <script> Xml.Delete\ Tag<Tab>d <C-C>:call <SID>Delete()<CR> - nmenu <script> Xml.Delete\ Section<Tab>D :call <SID>DeleteSection()<CR> - imenu <script> Xml.Delete\ Section<Tab>D <C-C>:call <SID>DeleteSection()<CR> - nmenu <script> Xml.End\ Tag<Tab>e :call <SID>EndTag()<CR> - imenu <script> Xml.End\ Tag<Tab>e <C-C>:call <SID>EndTag()<CR> - nmenu <script> Xml.Fold\ Comment :?<!--?,/-->/fo<CR> - nmenu <script> Xml.Fold\ CData :?<!\[CDATA\[?,/\]\]>/fo<CR> - nmenu <script> Xml.Fold\ Processing\ instruc :?<\?[a-zA-Z]*?,/?>/fo<CR> - nmenu <script> Xml.Fold\ Tag<Tab>f :call <SID>FoldTag()<CR> - nmenu <script> Xml.Fold\ All\ Tags<Tab>F :call <SID>FoldTagAll()<CR> - nmenu <script> Xml.Format\ Tags<Tab>g :call <SID>FormatTag()<CR> - nmenu <script> Xml.Format\ All\ Tags<Tab>G :call <SID>FormatTagAll()<CR> - nmenu <script> Xml.Join<Tab>j :call <SID>Join()<CR> - imenu <script> Xml.Join<Tab>j <C-C>:call <SID>Join()<CR> - nmenu <script> Xml.Open\ After\ Tag<Tab>O :call <SID>AfterTag()<CR> - imenu <script> Xml.Open\ After\ Tag<Tab>O <C-C>:call <SID>AfterTag()<CR> - nmenu <script> Xml.open\ Before\ Tag<Tab>o :call <SID>BeforeTag()<CR> - imenu <script> Xml.open\ Before\ Tag<Tab>o <C-C>:call <SID>BeforeTag()<CR> - nmenu <script> Xml.Match<Tab>5 :call <SID>Matches()<CR> - imenu <script> Xml.Match<Tab>5 <C-C>:call <SID>Matches()<CR><C-\><C-G> - nmenu <script> Xml.Shift\ Left<Tab>< :call <SID>ShiftLeft()<CR> - imenu <script> Xml.Shift\ Left<Tab>< <C-C>:call <SID>ShiftLeft()<CR><C-\><C-G> - nmenu <script> Xml.Shift\ Right<Tab>> :call <SID>ShiftRight()<CR> - imenu <script> Xml.Shift\ Right<Tab>> <C-C>:call <SID>ShiftRight()<CR><C-\><C-G> - nmenu <script> Xml.Start\ Tag<Tab>s :call <SID>StartTag()<CR> - imenu <script> Xml.Start\ Tag<Tab>s <C-C>:call <SID>StartTag()<CR><C-\><C-G> -en - -" Section: Doc installation {{{1 -" Function: s:XmlInstallDocumentation(full_name, revision) {{{2 -" Install help documentation. -" Arguments: -" full_name: Full name of this vim plugin script, including path name. -" revision: Revision of the vim script. #version# mark in the document file -" will be replaced with this string with 'v' prefix. -" Return: -" 1 if new document installed, 0 otherwise. -" Note: Cleaned and generalized by guo-peng Wen -"''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -function! s:XmlInstallDocumentation(full_name, revision) - " Name of the document path based on the system we use: - if (has("unix")) - " On UNIX like system, using forward slash: - let l:slash_char = '/' - let l:mkdir_cmd = ':silent !mkdir -p ' - else - " On M$ system, use backslash. Also mkdir syntax is different. - " This should only work on W2K and up. - let l:slash_char = '\' - let l:mkdir_cmd = ':silent !mkdir ' - endif - - let l:doc_path = l:slash_char . 'doc' - "let l:doc_home = l:slash_char . '.vim' . l:slash_char . 'doc' - - " Figure out document path based on full name of this script: - let l:vim_plugin_path = fnamemodify(a:full_name, ':h') - "let l:vim_doc_path = fnamemodify(a:full_name, ':h:h') . l:doc_path - let l:vim_doc_path = matchstr(l:vim_plugin_path, - \ '.\{-}\ze\%(\%(ft\)\=plugin\|macros\)') . l:doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - echomsg "Doc path: " . l:vim_doc_path - execute l:mkdir_cmd . l:vim_doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - " Try a default configuration in user home: - "let l:vim_doc_path = expand("~") . l:doc_home - let l:vim_doc_path = matchstr(&rtp, - \ escape($HOME, ' \') .'[/\\]\%(\.vim\|vimfiles\)') - if (!(filewritable(l:vim_doc_path) == 2)) - execute l:mkdir_cmd . l:vim_doc_path - if (!(filewritable(l:vim_doc_path) == 2)) - " Put a warning: - echomsg "Unable to open documentation directory" - echomsg " type :help add-local-help for more informations." - return 0 - endif - endif - endif - endif - - " Exit if we have problem to access the document directory: - if (!isdirectory(l:vim_plugin_path) - \ || !isdirectory(l:vim_doc_path) - \ || filewritable(l:vim_doc_path) != 2) - return 0 - endif - - " Full name of script and documentation file: - let l:script_name = 'xml.vim' - let l:doc_name = 'xml-plugin.txt' - let l:plugin_file = l:vim_plugin_path . l:slash_char . l:script_name - let l:doc_file = l:vim_doc_path . l:slash_char . l:doc_name - - " Bail out if document file is still up to date: - if (filereadable(l:doc_file) && - \ getftime(l:plugin_file) < getftime(l:doc_file)) - return 0 - endif - - " Prepare window position restoring command: - if (strlen(@%)) - let l:go_back = 'b ' . bufnr("%") - else - let l:go_back = 'enew!' - endif - - " Create a new buffer & read in the plugin file (me): - setl nomodeline - exe 'enew!' - exe 'r ' . l:plugin_file - - setl modeline - let l:buf = bufnr("%") - setl noswapfile modifiable - - norm zR - norm gg - - " Delete from first line to a line starts with - " === START_DOC - 1,/^=\{3,}\s\+START_DOC\C/ d - - " Delete from a line starts with - " === END_DOC - " to the end of the documents: - /^=\{3,}\s\+END_DOC\C/,$ d - - " Remove fold marks: - "% s/{\{3}[1-9]/ / - - " Add modeline for help doc: the modeline string is mangled intentionally - " to avoid it be recognized by VIM: - call append(line('$'), '') - call append(line('$'), ' v' . 'im:tw=78:ts=8:fen:fdm=marker:ft=help:norl:') - - " Replace revision: - exe "normal! :1,5s/#version#/ v" . a:revision . "/\<CR>" - - " Save the help document: - exe 'w! ' . l:doc_file - exe l:go_back - exe 'bw ' . l:buf - - " Build help tags: - exe 'helptags ' . l:vim_doc_path - - return 1 -endfunction -" }}}2 - -let s:revision= - \ substitute("$Revision: 1.36 $",'\$\S*: \([.0-9]\+\) \$','\1','') -silent! let s:install_status = - \ s:XmlInstallDocumentation(expand('<sfile>:p'), s:revision) -if (s:install_status == 1) - echom expand("<sfile>:t:r") . '-plugin v' . s:revision . - \ ': Help-documentation installed.' -endif - - -" Mappings of keys to functions {{{1 -nnoremap <silent> <buffer> <LocalLeader>5 :call <SID>Matches()<Cr> -vnoremap <silent> <buffer> <LocalLeader>5 <Esc>:call <SID>MatchesVisual()<Cr> -nnoremap <silent> <buffer> <LocalLeader>% :call <SID>Matches()<Cr> -vnoremap <silent> <buffer> <LocalLeader>% <Esc>:call <SID>MatchesVisual()<Cr> -nnoremap <silent> <buffer> <LocalLeader>c :call <SID>Change()<Cr> -nnoremap <silent> <buffer> <LocalLeader>C :call <SID>ChangeWholeTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>d :call <SID>Delete()<Cr> -nnoremap <silent> <buffer> <LocalLeader>D :call <SID>DeleteSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>e :call <SID>EndTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>] :call <SID>DelComment()<Cr> -nnoremap <silent> <buffer> <LocalLeader>} :call <SID>DelCommentSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>f :call <SID>FoldTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>F :call <SID>FoldTagAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>g :call <SID>FormatTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>G :call <SID>FormatTagAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>I :call <SID>IndentAll()<Cr> -nnoremap <silent> <buffer> <LocalLeader>j :call <SID>Join()<Cr> -nnoremap <silent> <buffer> <LocalLeader>O :call <SID>BeforeTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>= :call <SID>CommentTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>o :call <SID>AfterTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>s :call <SID>StartTag()<Cr> -nnoremap <silent> <buffer> <LocalLeader>[ :call <SID>DelCData()<Cr> -nnoremap <silent> <buffer> <LocalLeader>{ :call <SID>DelCDataSection()<Cr> -nnoremap <silent> <buffer> <LocalLeader>> :call <SID>ShiftRight()<Cr> -nnoremap <silent> <buffer> <LocalLeader>< :call <SID>ShiftLeft()<Cr> -vnoremap <silent> <buffer> <LocalLeader>l <Esc>:call <SID>vlistitem()<Cr> -vnoremap <silent> <buffer> <LocalLeader>v <Esc>:call <SID>BlockTag(0)<Cr> -vnoremap <silent> <buffer> <LocalLeader>V <Esc>:call <SID>BlockTag(1)<Cr> -vnoremap <silent> <buffer> <LocalLeader>c <Esc>:call <SID>BlockWith('<![CDATA[',']]>')<Cr> -vnoremap <silent> <buffer> <LocalLeader>< <Esc>:call <SID>BlockWith('<!--','-->')<Cr> - -" Move around functions. -noremap <silent><buffer> [[ m':call <SID>findOpenTag("bW")<CR> -noremap <silent><buffer> ]] m':call <SID>findOpenTag( "W")<CR> -noremap <silent><buffer> [] m':call <SID>findCloseTag( "bW")<CR> -noremap <silent><buffer> ][ m':call <SID>findCloseTag( "W")<CR> - -" Move around comments -noremap <silent><buffer> ]" :call search('^\(\s*<!--.*\n\)\@<!\(\s*-->\)', "W")<CR> -noremap <silent><buffer> [" :call search('\%(^\s*<!--.*\n\)\%(^\s*-->\)\@!', "bW")<CR> - - -setlocal iskeyword=@,48-57,_,192-255,58 -exe 'inoremap <silent> <buffer> '.b:suffix. " ><Esc>db:call <SID>makeElement()<Cr>" -if !exists("g:xml_tag_completion_map") - inoremap <silent> <buffer> > ><Esc>:call <SID>CloseTagFun()<Cr> -else - execute "inoremap <silent> <buffer> " . g:xml_tag_completion_map . " ><Esc>:call <SID>CloseTagFun()<Cr>" -endif - - - -finish - -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""/*}}}*/ -" Section: Documentation content {{{1 -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -=== START_DOC -*xml-plugin.txt* Help edit XML and SGML documents. #version# - - XML Edit ~ - -A filetype plugin to help edit XML and SGML documents. - -This script provides some convenience when editing XML (and some SGML -including HTML) formated documents. It allows you to jump to the -beginning or end of the tag block your cursor is in. '%' will jump -between '<' and '>' within the tag your cursor is in. When in insert -mode and you finish a tag (pressing '>') the tag will be completed. If -you press '>' twice it will place the cursor in the middle of the tags -on it's own line (helps with nested tags). - -Usage: Place this file into your ftplugin directory. To add html support -Sym-link or copy this file to html.vim in your ftplugin directory. To activte -the script place 'filetype plugin on' in your |.vimrc| file. See |ftplugins| -for more information on this topic. - -If the file edited is of type "html" and "xml_use_html" is defined then -the following tags will not auto complete: <img>, <input>, <param>, -<frame>, <br>, <hr>, <meta>, <link>, <base>, <area> - -If the file edited is of type 'html' and 'xml_use_xhtml' is defined the -above tags will autocomplete the xml closing staying xhtml compatable. -ex. <hr> becomes <hr /> (see |xml-plugin-settings|) - -Known Bugs {{{1 ~ - -- < & > marks inside of a CDATA section are interpreted as actual XML tags - even if unmatched. -- The script can not handle leading spaces such as < tag></ tag> it is - illegal XML syntax and considered very bad form. -- Placing a literal `>' in an attribute value will auto complete despite that - the start tag isn't finished. This is poor XML anyway you should use - > instead. - - ------------------------------------------------------------------------------- - *xml-plugin-settings* -Options {{{1 - -(All options must be placed in your |.vimrc| prior to the |ftplugin| -command.) - -xml_tag_completion_map - Use this setting to change the default mapping to auto complete a - tag. By default typing a literal `>' will cause the tag your editing - to auto complete; pressing twice will auto nest the tag. By using - this setting the `>' will be a literal `>' and you must use the new - mapping to perform auto completion and auto nesting. For example if - you wanted Control-L to perform auto completion inmstead of typing a - `>' place the following into your .vimrc: > - let xml_tag_completion_map = "<C-l>" -< -xml_no_auto_nesting (Not Working!!!!!) - This turns off the auto nesting feature. After a completion is made - and another `>' is typed xml-edit automatically will break the tag - accross multiple lines and indent the curser to make creating nested - tqags easier. This feature turns it off. Enter the following in your - .vimrc: > - let xml_no_auto_nesting = 1 -< -xml_use_xhtml - When editing HTML this will auto close the short tags to make valid - XML like <hr/> and <br/>. Enter the following in your vimrc to - turn this option on: > - let xml_use_xhtml = 1 - if the filetype is xhtml and g:xml_use_xhtml doesn't exists - the script defines it to be 1. (This also assumes that you have linked - xml.vim to xhtml.vim. Otherwise this item is moot) - For a file to be of xhtml type there need to be a doctype declaration!! - just naming a file something.xhtml doesn't make it type xhtml! -< -xml_no_html - This turns of the support for HTML specific tags. Place this in your - .vimrc: > - let xml_no_html = 1 -< ------------------------------------------------------------------------------- - *xml-plugin-mappings* - -Mapings and their functions {{{1 - -Typing '>' will start the tag closing routine. -Typing (Where | means cursor position) - <para>| -results in - <para>|</para> - -Typing - <para>>|</para> -results in - <para> - | - </para> -typing a lone '>' and no '<' in front of it accepts the '>' (But having -lone '>' or '<' in a XML file is frown upon except in <!CDATA> sections, -and that will throw of the plugin!!). - -Typing </tag> or <tag/> also results in na expanding. So when editing -html type <input .... /> - -The closing routing also ignores DTD tags '<!,,>' and processing -instructions '<?....?>'. Thus typing these result in no expansion. - - -<LocalLeader> is a setting in VIM that depicts a prefix for scripts and -plugins to use. By default this is the backslash key `\'. See |mapleader| -for details. - -;; make element out previous word and close it {{{2 - - when typing a word;; wil create <word>|</word> - when word on its own line it will be - <word> - | - </word> - the suffix can be changed by setting - let makeElementSuf = ',,,' in your .vimrc - Thanks to Bart van Deenen - (http://www.vim.org/scripts/script.php?script_id=632) - -[ and ] mappings {{{2 - <LocalLeader>[ Delete <![CDATA[ ]]> delimiters - <LocalLeader>{ Delete <![CDATA[ ]]> section - <LocalLeader>] Delete <!-- --> delimiters - <LocalLeader>} Delete <!-- --> section - [[ Goto to the previous open tag - [[ Goto to the next open tag - [] Goto to the previous close tag - ][ Goto to the next close tag - [" Goto to the next comment - ]" Goto the previous comment -<LocalLeader>5 Jump to the matching tag. {{{2 -<LocalLeader>% Jump to the matching tag. - - -<LocalLeader>c Rename tag {{{2 - -<LocalLeader>C Rename tag and remove attributes {{{2 - Will ask for attributes - -<LocalLeader>d Deletes the surrounding tags from the cursor. {{{2 - <tag1>outter <tag2>inner text</tag2> text</tag1> - | - Turns to: - outter <tag2>inner text</tag2> text - | - -<LocalLeader>D Deletes the tag and it contents {{{2 - - and put it in register x. - <tag1>outter <tag2>inner text</tag2> text</tag1> - | - Turns to: - <tag1>outter text</tag1> - -<LocalLeader>e provide endtag for open tags. {{{2 - - provide endtag for open tags. Watch where de cursor is - <para><listitem>list item content - | - pressing \e twice produces - <para><listitem>list item content</para></listitem> - -<LocalLeader>f fold the tag under the cursor {{{2 - <para> - line 1 - line 2 - line 3 - </para> - \f produces - +-- 5 lines: <para>-------------------------- - - -<LocalLeader>F all tags of name 'tag' will be fold. {{{2 - - If there isn't a tag under - the cursor you will be asked for one. - -<LocalLeader>g Format (Vim's gq function) {{{2 - - will make a visual block of tag under cursor and then format using gq - - -<LocalLeader>G Format all tags under cursor (Vim's gq function) {{{2 - - If there isn't a tag under - the cursor you will be asked for one. - - -<LocalLeader>I Indent all tags {{{2 - - will create a multiline layout every opening tag will be shifted out - and every closing tag will be shifted in. Be aware that the rendering - of the XML through XSLT and/or DSSSL, might be changed by this. - Be aware tha if the file is big, more than 1000 lines, the reformatting - takes a long time because vim has to make a big undo buffer. - For example using \I on the example below: - - <chapter><title>Indent</title><para>The documentation</para></chapter> - - - Becomes - - <chapter> - <title> - Indent - </title> - <para> - The documentation - </para> - </chapter> - - -<LocalLeader>j Joins two the SAME sections together. {{{2 - - The sections must be next to each other. - <para> This is line 1 - of a paragraph. </para> - <para> This is line 2 - | - of a paragraph. </para> - \j produces - <para> This is line 1 - of a paragraph. - This is line 2 - of a paragraph. </para> - -<LocalLeader>l visual surround the block with listitem and para {{{2 - When marking up docbook tekst you have the issue that listitems - consist of 2 item. This key combination inserts them both, - - blaah - | - \l produces - <listitem> - <para>blaah</para> - </listitem> - -<LocalLeader>o Insert a tag inside the current one (like vim o) {{{2 - You are asked for tag and attributes. - - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - | - \o produces - <tag1> - <aftertag><tag2><tag3>blaah</tag3></tag2></aftertag> - </tag1> - -<LocalLeader>O Insert a tag outside the current one (like vim O) {{{2 - You are asked for tag and attributes. - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - | - \O produces - <beforetag> - <tag1><tag2><tag3>blaah</tag3></tag2></tag1> - </beforetag> - -<LocalLeader>s Insert an opening tag for an closing tag. {{{2 - list item content</para></listitem> - | - pressing \s twice produces - <para><listitem>list item content</para></listitem> - -<LocalLeader>[ Delete <![CDATA[ ]]> delimiters {{{2 - Removes Only <CDATA[ and ]]> - handy when you want to uncomment a section. - You need to stand in the tag and not on an other tag - <![CDATA[ <tag> ]]> - if you cursor is outside <tag> but inside the - CDATA tag the delition works. -<LocalLeader>{ Delete <![CDATA[ ]]> section {{{2 - Removes everything tag and Content -<LocalLeader>] Delete <!-- --> delimiters {{{2 - Uncommnet a block. -<LocalLeader>} Delete <!-- --> section {{{2 - Removes everything tag and Content -<LocalLeader>> shift right opening tag and closing tag. {{{2 - shift everything between the tags 1 shiftwide right -<LocalLeader>< shift left opening tag and closing tag. {{{2 - shift everything between the tags 1 shiftwide left -<LocalLeader>c Visual Place a CDATA section around the selected text. {{{2 - Place Cdata section around the block -<LocalLeader>< Visual Place a Comment around the selected text. {{{2 - Place comment around the block -<LocalLeader>5 Extend the visual selection to the matching tag. {{{2 -<LocalLeader>% - Extend the visual selection to the matching tag. Make sure you are at - the start of the opening tag or the end of the closing tag. -<LocalLeader>v Visual Place a tag around the selected text. {{{2 - - You are asked for tag and attributes. You - need to have selected text in visual mode before you can use this - mapping. See |visual-mode| for details. - Be careful where you place the marks. - The top uses append - The bottom uses append - Useful when marking up a text file - ------------------------------------------------------------------------------- - *xml-plugin-callbacks* - -Callback Functions {{{2 ~ - -A callback function is a function used to customize features on a per tag -basis. For example say you wish to have a default set of attributs when you -type an empty tag like this: - You type: <tag> - You get: <tag default="attributes"></tag> - -This is for any script programmers who wish to add xml-plugin support to -there own filetype plugins. - -Callback functions recive one attribute variable which is the tag name. The -all must return either a string or the number zero. If it returns a string -the plugin will place the string in the proper location. If it is a zero the -plugin will ignore and continue as if no callback existed. - -The following are implemented callback functions: - -HtmlAttribCallback - This is used to add default attributes to html tag. It is intended - for HTML files only. - -XmlAttribCallback - This is a generic callback for xml tags intended to add attributes. - - *xml-plugin-html* -Callback Example {{{2 ~ - -The following is an example of using XmlAttribCallback in your .vimrc -> - function XmlAttribCallback (xml_tag) - if a:xml_tag ==? "my-xml-tag" - return "attributes=\"my xml attributes\"" - else - return 0 - endif - endfunction -< -The following is a sample html.vim file type plugin you could use: -> - " Vim script file vim600:fdm=marker: - " FileType: HTML - " Maintainer: Devin Weaver <vim (at) tritarget.com> - " Location: http://www.vim.org/scripts/script.php?script_id=301 - - " This is a wrapper script to add extra html support to xml documents. - " Original script can be seen in xml-plugin documentation. - - " Only do this when not done yet for this buffer - if exists("b:did_ftplugin") - finish - endif - " Don't set 'b:did_ftplugin = 1' because that is xml.vim's responsability. - - let b:html_mode = 1 - - if !exists("*HtmlAttribCallback") - function HtmlAttribCallback( xml_tag ) - if a:xml_tag ==? "table" - return "cellpadding=\"0\" cellspacing=\"0\" border=\"0\"" - elseif a:xml_tag ==? "link" - return "href=\"/site.css\" rel=\"StyleSheet\" type=\"text/css\"" - elseif a:xml_tag ==? "body" - return "bgcolor=\"white\"" - elseif a:xml_tag ==? "frame" - return "name=\"NAME\" src=\"/\" scrolling=\"auto\" noresize" - elseif a:xml_tag ==? "frameset" - return "rows=\"0,*\" cols=\"*,0\" border=\"0\"" - elseif a:xml_tag ==? "img" - return "src=\"\" width=\"0\" height=\"0\" border=\"0\" alt=\"\"" - elseif a:xml_tag ==? "a" - if has("browse") - " Look up a file to fill the href. Used in local relative file - " links. typeing your own href before closing the tag with `>' - " will override this. - let cwd = getcwd() - let cwd = substitute (cwd, "\\", "/", "g") - let href = browse (0, "Link to href...", getcwd(), "") - let href = substitute (href, cwd . "/", "", "") - let href = substitute (href, " ", "%20", "g") - else - let href = "" - endif - return "href=\"" . href . "\"" - else - return 0 - endif - endfunction - endif - - " On to loading xml.vim - runtime ftplugin/xml.vim -< -=== END_DOC -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" v im:tw=78:ts=8:ft=help:norl: -" vim600: set foldmethod=marker tabstop=8 shiftwidth=2 softtabstop=2 smartindent smarttab : -"fileencoding=iso-8859-15 -=== END_DOC -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - - - - - - -" Vim settingѕ {{{1 -" vim:tw=78:ts=2:ft=help:norl: -" vim: set foldmethod=marker tabstop=2 shiftwidth=2 softtabstop=2 smartindent smarttab : -"fileencoding=utf-8 - diff --git a/files/.vim/ftplugin/xsl.vim b/files/.vim/ftplugin/xsl.vim deleted file mode 120000 index 65289a9..0000000 --- a/files/.vim/ftplugin/xsl.vim +++ /dev/null @@ -1 +0,0 @@ -xml.vim
\ No newline at end of file diff --git a/files/.vim/ftplugin/yaml.vim b/files/.vim/ftplugin/yaml.vim deleted file mode 100755 index ca3abe2..0000000 --- a/files/.vim/ftplugin/yaml.vim +++ /dev/null @@ -1,32 +0,0 @@ -" Vim indent file
-" Language: Yaml
-" Author: Ian Young
-" Get it bundled for pathogen: https://github.com/avakhov/vim-yaml
-
-if exists("b:did_indent")
- finish
-endif
-"runtime! indent/ruby.vim
-"unlet! b:did_indent
-let b:did_indent = 1
-
-setlocal autoindent sw=2 et
-setlocal indentexpr=GetYamlIndent()
-setlocal indentkeys=o,O,*<Return>,!^F
-
-function! GetYamlIndent()
- let lnum = v:lnum - 1
- if lnum == 0
- return 0
- endif
- let line = substitute(getline(lnum),'\s\+$','','')
- let indent = indent(lnum)
- let increase = indent + &sw
- if line =~ ':$'
- return increase
- else
- return indent
- endif
-endfunction
-
-" vim:set sw=2:
diff --git a/files/.vim/plugin/luarefvim.vim b/files/.vim/plugin/luarefvim.vim deleted file mode 100644 index cb5664c..0000000 --- a/files/.vim/plugin/luarefvim.vim +++ /dev/null @@ -1,30 +0,0 @@ -" luarefvim plugin -" This is somewhat based on CRefVim -" Maintainer: Luis Carvalho <lexcarvalho@gmail.com> -" Last Change: Jun, 3, 2005 -" Version: 0.2 - -" initial setup: avoid loading more than once -if exists("loaded_luarefvim") - finish -endif -let loaded_luarefvim = 1 - -" mappings: -vmap <silent> <unique> <Leader>lr y:call <SID>LookUp('<c-r>"')<CR> -nmap <silent> <unique> <Leader>lr :call <SID>LookUp(expand("<cword>"))<CR> -map <silent> <unique> <Leader>lc :help luaref<CR> - -function <SID>LookUp(str) - if a:str == "--" "comment? - silent! execute ":help lrv-comment" - elseif a:str == "" - silent! execute ":help luaref" - else - silent! execute ":help lrv-" . a:str - if v:errmsg != "" - echo "luarefvim: \`" . a:str . "\' not found" - endif - endif -endfunction - diff --git a/files/.vim/plugin/rails.vim b/files/.vim/plugin/rails.vim deleted file mode 100644 index 1ac6057..0000000 --- a/files/.vim/plugin/rails.vim +++ /dev/null @@ -1,4666 +0,0 @@ -" rails.vim - Detect a rails application -" Author: Tim Pope <vimNOSPAM@tpope.info> -" GetLatestVimScripts: 1567 1 :AutoInstall: rails.vim -" URL: http://rails.vim.tpope.net/ -" $Id: rails.vim 239 2008-01-03 15:55:55Z tpope $ - -" See doc/rails.txt for details. Grab it from the URL above if you don't have it -" To access it from Vim, see :help add-local-help (hint: :helptags ~/.vim/doc) -" Afterwards, you should be able to do :help rails - -" ============================================================================ - -" Exit quickly when: -" - this plugin was already loaded (or disabled) -" - when 'compatible' is set -if &cp || (exists("g:loaded_rails") && g:loaded_rails) && !(exists("g:rails_debug") && g:rails_debug) - finish -endif -let g:loaded_rails = 1 - -let s:cpo_save = &cpo -set cpo&vim - -" Utility Functions {{{1 - -function! s:sub(str,pat,rep) - return substitute(a:str,'\v\C'.a:pat,a:rep,'') -endfunction - -function! s:gsub(str,pat,rep) - return substitute(a:str,'\v\C'.a:pat,a:rep,'g') -endfunction - -function! s:string(str) - if exists("*string") - return string(a:str) - else - return "'" . s:gsub(a:str,"'","'.\"'\".'") . "'" - endif -endfunction - -function! s:compact(ary) - return s:sub(s:sub(s:gsub(a:ary,'\n\n+','\n'),'\n$',''),'^\n','') -endfunction - -function! s:escarg(p) - return s:gsub(a:p,'[ !%#]','\\&') -endfunction - -function! s:esccmd(p) - return s:gsub(a:p,'[!%#]','\\&') -endfunction - -function! s:ra() - " Rails root, escaped for use as single argument - return s:escarg(RailsRoot()) -endfunction - -function! s:rc() - " Rails root, escaped for use with a command (spaces not escaped) - return s:esccmd(RailsRoot()) -endfunction - -function! s:escvar(r) - let r = fnamemodify(a:r,':~') - let r = s:gsub(r,'\W','\="_".char2nr(submatch(0))."_"') - let r = s:gsub(r,'^\d','_&') - return r -endfunction - -function! s:rv() - " Rails root, escaped to be a variable name - return s:escvar(RailsRoot()) -endfunction - -function! s:rquote(str) - " Imperfect but adequate for Ruby arguments - if a:str =~ '^[A-Za-z0-9_/.:-]\+$' - return a:str - elseif &shell =~? 'cmd' - return '"'.s:gsub(s:gsub(a:str,'\','\\'),'"','\\"').'"' - else - return "'".s:gsub(s:gsub(a:str,'\','\\'),"'","'\\\\''")."'" - endif -endfunction - -function! s:sname() - return fnamemodify(s:file,':t:r') -endfunction - -function! s:hasfile(file) - return filereadable(RailsRoot().'/'.a:file) -endfunction - -function! s:rubyexestr(cmd) - if RailsRoot() =~ '://' - return "ruby ".a:cmd - else - return "ruby -C ".s:rquote(RailsRoot())." ".a:cmd - endif -endfunction - -function! s:rubyexestrwithfork(cmd) - if s:getopt("ruby_fork_port","ab") && executable("ruby_fork_client") - return "ruby_fork_client -p ".s:getopt("ruby_fork_port","ab")." ".a:cmd - else - return s:rubyexestr(a:cmd) - endif -endfunction - -function! s:rubyexebg(cmd) - let cmd = s:esccmd(s:rubyexestr(a:cmd)) - if has("gui_win32") - if &shellcmdflag == "-c" && ($PATH . &shell) =~? 'cygwin' - silent exe "!cygstart -d ".s:rquote(RailsRoot())." ruby ".a:cmd - else - exe "!start ".cmd - endif - elseif exists("$STY") && !has("gui_running") && s:getopt("gnu_screen","abg") && executable("screen") - silent exe "!screen -ln -fn -t ".s:sub(s:sub(a:cmd,'\s.*',''),'^%(script|-rcommand)/','rails-').' '.cmd - else - exe "!".cmd - endif - return v:shell_error -endfunction - -function! s:rubyexe(cmd,...) - if a:0 - call s:rubyexebg(a:cmd) - else - exe "!".s:esccmd(s:rubyexestr(a:cmd)) - endif - return v:shell_error -endfunction - -function! s:rubyeval(ruby,...) - if a:0 > 0 - let def = a:1 - else - let def = "" - endif - if !executable("ruby") - return def - endif - let cmd = s:rubyexestr('-e '.s:rquote('begin; require %{rubygems}; rescue LoadError; end; begin; require %{active_support}; rescue LoadError; end; '.a:ruby)) - "let g:rails_last_ruby_command = cmd - " If the shell is messed up, this command could cause an error message - silent! let results = system(cmd) - "let g:rails_last_ruby_result = results - if v:shell_error != 0 " results =~ '-e:\d' || results =~ 'ruby:.*(fatal)' - return def - else - return results - endif -endfunction - -function! s:railseval(ruby) - if a:0 > 0 - let def = a:1 - else - let def = "" - endif - if !executable("ruby") - return def - endif - let args = "-r./config/boot -r ".s:rquote(RailsRoot()."/config/environment")." -e ".s:rquote(a:ruby) - let cmd = s:rubyexestrwithfork(args) - " If the shell is messed up, this command could cause an error message - silent! let results = system(cmd) - if v:shell_error != 0 " results =~ '-e:\d' || results =~ 'ruby:.*(fatal)' - return def - else - return results - endif -endfunction - -function! s:endof(lnum) - if a:lnum == 0 - return 0 - endif - if &ft == "yaml" || expand("%:e") == "yml" - return -1 - endif - let cline = getline(a:lnum) - let spc = matchstr(cline,'^\s*') - let endpat = '\<end\>' - if matchstr(getline(a:lnum+1),'^'.spc) && !matchstr(getline(a:lnum+1),'^'.spc.endpat) && matchstr(cline,endpat) - return a:lnum - endif - let endl = a:lnum - while endl <= line('$') - let endl = endl + 1 - if getline(endl) =~ '^'.spc.endpat - return endl - elseif getline(endl) =~ '^=begin\>' - while getline(endl) !~ '^=end\>' && endl <= line('$') - let endl = endl + 1 - endwhile - let endl = endl + 1 - elseif getline(endl) !~ '^'.spc && getline(endl) !~ '^\s*\%(#.*\)\=$' - return 0 - endif - endwhile - return 0 -endfunction - -function! s:lastmethodline(...) - if a:0 - let line = a:1 - else - let line = line(".") - endif - while line > 0 && getline(line) !~ &l:define - let line = line - 1 - endwhile - let lend = s:endof(line) - if lend < 0 || lend >= (a:0 ? a:1 : line(".")) - return line - else - return 0 - endif -endfunction - -function! s:lastmethod() - let line = s:lastmethodline() - if line - return s:sub(matchstr(getline(line),'\%('.&define.'\)\zs\h\%(\k\|[:.]\)*[?!=]\='),':$','') - else - return "" - endif -endfunction - -function! s:lastrespondtoline(...) - let mline = s:lastmethodline() - if a:0 - let line = a:1 - else - let line = line(".") - endif - while line > mline && getline(line) !~ '\C^\s*respond_to\s*\%(\<do\)\s*|\zs\h\k*\ze|' - let line = line - 1 - endwhile - let lend = s:endof(line) - if lend >= (a:0 ? a:1 : line(".")) - return line - else - return -1 - endif -endfunction - -function! s:lastformat() - let rline = s:lastrespondtoline() - if rline - let variable = matchstr(getline(rline),'\C^\s*respond_to\s*\%(\<do\|{\)\s*|\zs\h\k*\ze|') - let line = line('.') - while line > rline - let match = matchstr(getline(line),'\C^\s*'.variable.'\s*\.\s*\zs\h\k*') - if match != '' - return match - endif - let line = line - 1 - endwhile - endif - return "" -endfunction - -function! s:format(...) - if RailsFileType() =~ '^view\>' - let format = fnamemodify(RailsFilePath(),':r:e') - else - let format = s:lastformat() - endif - if format == '' - if fnamemodify(RailsFilePath(),':e') == 'rhtml' - let format = 'html' - elseif fnamemodify(RailsFilePath(),':e') == 'rxml' - let format = 'xml' - elseif fnamemodify(RailsFilePath(),':e') == 'rjs' - let format = 'js' - elseif a:0 - return a:1 - endif - endif - return format -endfunction - -function! s:viewspattern() - return '\%('.s:gsub(s:view_types,',','\\|').'\)' -endfunction - -function! s:controller(...) - let t = RailsFileType() - let f = RailsFilePath() - let o = s:getopt("controller","lb") - if o != "" - return o - elseif f =~ '\<app/views/layouts/' - return s:sub(f,'.*<app/views/layouts/(.{-})\..*','\1') - elseif f =~ '\<app/views/' - return s:sub(f,'.*<app/views/(.{-})/\k+\.\k+%(\.\k+)=$','\1') - elseif f =~ '\<app/helpers/.*_helper\.rb$' - return s:sub(f,'.*<app/helpers/(.{-})_helper\.rb$','\1') - elseif f =~ '\<app/controllers/application\.rb$' - return "application" - elseif f =~ '\<app/controllers/.*_controller\.rb$' - return s:sub(f,'.*<app/controllers/(.{-})_controller\.rb$','\1') - elseif f =~ '\<app/apis/.*_api\.rb$' - return s:sub(f,'.*<app/apis/(.{-})_api\.rb$','\1') - elseif f =~ '\<test/functional/.*_controller_test\.rb$' - return s:sub(f,'.*<test/functional/(.{-})_controller_test\.rb$','\1') - elseif f =~ '\<spec/controllers/.*_controller_spec\.rb$' - return s:sub(f,'.*<spec/controllers/(.{-})_controller_spec\.rb$','\1') - elseif f =~ '\<spec/helpers/.*_helper_spec\.rb$' - return s:sub(f,'.*<spec/helpers/(.{-})_helper_spec\.rb$','\1') - elseif f =~ '\<spec/views/.*/\w\+_view_spec\.rb$' - return s:sub(f,'.*<spec/views/(.{-})/\w+_view_spec\.rb$','\1') - elseif f =~ '\<components/.*_controller\.rb$' - return s:sub(f,'.*<components/(.{-})_controller\.rb$','\1') - elseif f =~ '\<components/.*\.'.s:viewspattern().'$' - return s:sub(f,'.*<components/(.{-})/\k+\.\k+$','\1') - elseif f =~ '\<app/models/.*\.rb$' && t =~ '^model-mailer\>' - return s:sub(f,'.*<app/models/(.{-})\.rb$','\1') - elseif f =~ '\<public/stylesheets/.*\.css$' - return s:sub(f,'.*<public/stylesheets/(.{-})\.css$','\1') - elseif a:0 && a:1 - return s:pluralize(s:model()) - endif - return "" -endfunction - -function! s:model(...) - let f = RailsFilePath() - let o = s:getopt("model","lb") - if o != "" - return o - elseif f =~ '\<app/models/.*_observer.rb$' - return s:sub(f,'.*<app/models/(.*)_observer\.rb$','\1') - elseif f =~ '\<app/models/.*\.rb$' - return s:sub(f,'.*<app/models/(.*)\.rb$','\1') - elseif f =~ '\<test/unit/.*_observer_test\.rb$' - return s:sub(f,'.*<test/unit/(.*)_observer_test\.rb$','\1') - elseif f =~ '\<test/unit/.*_test\.rb$' - return s:sub(f,'.*<test/unit/(.*)_test\.rb$','\1') - elseif f =~ '\<spec/models/.*_spec\.rb$' - return s:sub(f,'.*<spec/models/(.*)_spec\.rb$','\1') - elseif f =~ '\<\%(test\|spec\)/fixtures/.*\.\w*\~\=$' - return s:singularize(s:sub(f,'.*<%(test|spec)/fixtures/(.*)\.\w*\~=$','\1')) - elseif a:0 && a:1 - return s:singularize(s:controller()) - endif - return "" -endfunction - -function! s:underscore(str) - let str = s:gsub(a:str,'::','/') - let str = s:gsub(str,'(\u+)(\u\l)','\1_\2') - let str = s:gsub(str,'(\l|\d)(\u)','\1_\2') - let str = s:gsub(str,'-','_') - let str = tolower(str) - return str -endfunction - -function! s:camelize(str) - let str = s:gsub(a:str,'/(.)','::\u\1') - let str = s:gsub(str,'%([_-]|<)(.)','\u\1') - return str -endfunction - -function! s:singularize(word) - " Probably not worth it to be as comprehensive as Rails but we can - " still hit the common cases. - let word = a:word - if word =~? '\.js$' || word == '' - return word - endif - let word = s:sub(word,'eople$','ersons') - let word = s:sub(word,'[aeio]@<!ies$','ys') - let word = s:sub(word,'xe[ns]$','xs') - let word = s:sub(word,'ves$','fs') - let word = s:sub(word,'ss%(es)=$','sss') - let word = s:sub(word,'s$','') - return word -endfunction - -function! s:pluralize(word) - let word = a:word - if word == '' - return word - endif - let word = s:sub(word,'[aeio]@<!y$','ie') - let word = s:sub(word,'%([osxz]|[cs]h)$','&e') - let word = s:sub(word,'f@<!f$','ve') - let word = word."s" - let word = s:sub(word,'ersons$','eople') - return word -endfunction - -function! s:usesubversion() - if !exists("b:rails_use_subversion") - let b:rails_use_subversion = s:getopt("subversion","abg") && (RailsRoot()!="") && isdirectory(RailsRoot()."/.svn") - endif - return b:rails_use_subversion -endfunction - -function! s:environment() - if exists('$RAILS_ENV') - return $RAILS_ENV - else - return "development" - endif -endfunction - -function! s:environments(...) - let e = s:getopt("environment","abg") - if e == '' - return "development\ntest\nproduction" - else - return s:gsub(e,'[:;,- ]',"\n") - endif -endfunction - -function! s:warn(str) - echohl WarningMsg - echomsg a:str - echohl None - " Sometimes required to flush output - echo "" - let v:warningmsg = a:str -endfunction - -function! s:error(str) - echohl ErrorMsg - echomsg a:str - echohl None - let v:errmsg = a:str -endfunction - -function! s:debug(str) - if g:rails_debug - echohl Debug - echomsg a:str - echohl None - endif -endfunction - -" }}}1 -" "Public" Interface {{{1 - -" RailsRevision() and RailsRoot() the only official public functions - -function! RailsRevision() - return s:revision -endfunction - -function! RailsRoot() - if exists("b:rails_root") - return b:rails_root - else - return "" - endif -endfunction - -function! RailsFilePath() - if !exists("b:rails_root") - return "" - elseif exists("b:rails_file_path") - return b:rails_file_path - endif - let f = s:gsub(expand('%:p'),'\\ @!','/') - let f = s:sub(f,'/$','') - if s:gsub(b:rails_root,'\\ @!','/') == strpart(f,0,strlen(b:rails_root)) - return strpart(f,strlen(b:rails_root)+1) - else - return f - endif -endfunction - -function! RailsFile() - return RailsFilePath() -endfunction - -function! RailsFileType() - if !exists("b:rails_root") - return "" - elseif exists("b:rails_file_type") - return b:rails_file_type - elseif exists("b:rails_cached_file_type") - return b:rails_cached_file_type - endif - let f = RailsFilePath() - let e = fnamemodify(RailsFilePath(),':e') - let r = "" - let top = getline(1)." ".getline(2)." ".getline(3)." ".getline(4)." ".getline(5).getline(6)." ".getline(7)." ".getline(8)." ".getline(9)." ".getline(10) - if f == "" - let r = f - elseif f =~ '_controller\.rb$' || f =~ '\<app/controllers/application\.rb$' - if top =~ '\<wsdl_service_name\>' - let r = "controller-api" - else - let r = "controller" - endif - elseif f =~ '_api\.rb' - let r = "api" - elseif f =~ '\<test/test_helper\.rb$' - let r = "test" - elseif f =~ '\<spec/spec_helper\.rb$' - let r = "spec" - elseif f =~ '_helper\.rb$' - let r = "helper" - elseif f =~ '\<app/models\>' - let class = matchstr(top,'\<Acti\w\w\u\w\+\%(::\h\w*\)\+\>') - if class == "ActiveResoure::Base" - let class = "ares" - let r = "model-ares" - elseif class != '' - "let class = s:sub(class,'::Base$','') - let class = tolower(s:gsub(class,'[^A-Z]','')) - let r = "model-".s:sub(class,'^amb>','mailer') - elseif f =~ '_mailer\.rb$' - let r = "model-mailer" - elseif top =~ '\<\%(validates_\w\+_of\|set_\%(table_name\|primary_key\)\|has_one\|has_many\|belongs_to\)\>' - let r = "model-arb" - else - let r = "model" - endif - elseif f =~ '\<app/views/layouts\>.*\.' - let r = "view-layout-" . e - elseif f =~ '\<\%(app/views\|components\)/.*/_\k\+\.\k\+\%(\.\k\+\)\=$' - let r = "view-partial-" . e - elseif f =~ '\<app/views\>.*\.' || f =~ '\<components/.*/.*\.'.s:viewspattern().'$' - let r = "view-" . e - elseif f =~ '\<test/unit/.*_test\.rb$' - let r = "test-unit" - elseif f =~ '\<test/functional/.*_test\.rb$' - let r = "test-functional" - elseif f =~ '\<test/integration/.*_test\.rb$' - let r = "test-integration" - elseif f =~ '\<spec/\w*s/.*_spec\.rb$' - let r = s:sub(f,'.*<spec/(\w*)s/.*','spec-\1') - elseif f =~ '\<\%(test\|spec\)/fixtures\>' - if e == "yml" - let r = "fixtures-yaml" - else - let r = "fixtures" . (e == "" ? "" : "-" . e) - endif - elseif f =~ '\<test/.*_test\.rb' - let r = "test" - elseif f =~ '\<spec/.*_spec\.rb' - let r = "spec" - elseif f =~ '\<db/migrate\>' || f=~ '\<db/schema\.rb$' - let r = "migration" - elseif f =~ '\<vendor/plugins/.*/recipes/.*\.rb$' || f =~ '\.rake$' || f =~ '\<\%(Rake\|Cap\)file$' || f =~ '\<config/deploy\.rb$' - let r = "task" - elseif f =~ '\<log/.*\.log$' - let r = "log" - elseif e == "css" || e == "js" || e == "html" - let r = e - elseif f =~ '\<config/routes\>.*\.rb$' - let r = "config-routes" - elseif f =~ '\<config/' - let r = "config" - endif - return r -endfunction - -function! RailsType() - return RailsFileType() -endfunction - -function! RailsEval(ruby,...) - if !exists("b:rails_root") - return a:0 ? a:1 : "" - elseif a:0 - return s:railseval(a:ruby,a:1) - else - return s:railseval(a:ruby) - endif -endfunction - -" }}}1 -" Configuration {{{ - -function! s:SetOptDefault(opt,val) - if !exists("g:".a:opt) - let g:{a:opt} = a:val - endif -endfunction - -function! s:InitConfig() - call s:SetOptDefault("rails_level",3) - call s:SetOptDefault("rails_statusline",1) - call s:SetOptDefault("rails_syntax",1) - call s:SetOptDefault("rails_mappings",1) - call s:SetOptDefault("rails_abbreviations",1) - call s:SetOptDefault("rails_expensive",1+0*(has("win32")||has("win32unix"))) - call s:SetOptDefault("rails_dbext",g:rails_expensive) - call s:SetOptDefault("rails_subversion",0) - call s:SetOptDefault("rails_tabstop",0) - call s:SetOptDefault("rails_default_file","README") - call s:SetOptDefault("rails_default_database","") - call s:SetOptDefault("rails_root_url",'http://localhost:3000/') - call s:SetOptDefault("rails_modelines",1) - call s:SetOptDefault("rails_menu",1) - call s:SetOptDefault("rails_gnu_screen",1) - call s:SetOptDefault("rails_history_size",5) - call s:SetOptDefault("rails_debug",0) - call s:SetOptDefault("rails_generators","controller\nintegration_test\nmailer\nmigration\nmodel\nobserver\nplugin\nresource\nscaffold\nsession_migration") - call s:SetOptDefault("rails_rake_tasks","db:charset\ndb:collation\ndb:create\ndb:create:all\ndb:drop\ndb:drop:all\ndb:fixtures:identify\ndb:fixtures:load\ndb:migrate\ndb:reset\ndb:rollback\ndb:schema:dump\ndb:schema:load\ndb:sessions:clear\ndb:sessions:create\ndb:structure:dump\ndb:test:clone\ndb:test:clone_structure\ndb:test:prepare\ndb:test:purge\ndb:version\ndoc:app\ndoc:clobber_app\ndoc:clobber_plugins\ndoc:clobber_rails\ndoc:plugins\ndoc:rails\ndoc:reapp\ndoc:rerails\nlog:clear\nnotes\nnotes:fixme\nnotes:optimize\nnotes:todo\nrails:freeze:edge\nrails:freeze:gems\nrails:unfreeze\nrails:update\nrails:update:configs\nrails:update:javascripts\nrails:update:scripts\nroutes\nstats\ntest\ntest:functionals\ntest:integration\ntest:plugins\ntest:recent\ntest:uncommitted\ntest:units\ntmp:cache:clear\ntmp:clear\ntmp:create\ntmp:pids:clear\ntmp:sessions:clear\ntmp:sockets:clear") - if g:rails_dbext - if exists("g:loaded_dbext") && executable("sqlite3") && ! executable("sqlite") - " Since dbext can't find it by itself - call s:SetOptDefault("dbext_default_SQLITE_bin","sqlite3") - endif - endif -endfunction - -" }}}1 -" Autocommand Functions {{{1 - -function! s:QuickFixCmdPre() - if exists("b:rails_root") - if strpart(getcwd(),0,strlen(RailsRoot())) != RailsRoot() - let s:last_dir = getcwd() - echo "lchdir ".s:ra() - "exe "lchdir ".s:ra() - lchdir `=RailsRoot()` - endif - endif -endfunction - -function! s:QuickFixCmdPost() - if exists("s:last_dir") - "exe "lchdir ".s:escarg(s:last_dir) - lchdir `=s:last_dir` - unlet s:last_dir - endif -endfunction - -function! s:BufEnter() - if exists("b:rails_refresh") && b:rails_refresh - unlet! b:rails_root b:rails_use_subversion - let b:rails_refresh = 0 - call s:Detect(expand("%:p")) - unlet! b:rails_refresh - elseif !exists("b:rails_root") && isdirectory(expand('%;p')) - " FIXME: This doesn't catch all directories - call s:Detect(expand('%:p')) - endif - if exists("b:rails_root") - if exists("+completefunc") && &completefunc == 'syntaxcomplete#Complete' - if exists("g:loaded_syntax_completion") - " Ugly but necessary, until we have our own completion - unlet g:loaded_syntax_completion - silent! delfunction syntaxcomplete#Complete - endif - endif - call s:BufDatabase(-1) - call s:menuBufEnter() - endif -endfunction - -function! s:BufLeave() - call s:menuBufLeave() -endfunction - -" }}}1 -" Commands {{{1 - -function! s:BufCommands() - call s:BufFinderCommands() " Provides Rcommand! - call s:BufNavCommands() - call s:BufScriptWrappers() - Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:RakeComplete Rake :call s:Rake(<bang>0,<q-args>) - Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:PreviewComplete Rpreview :call s:Preview(<bang>0,<q-args>) - Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:environments Rlog :call s:Log(<bang>0,<q-args>) - Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:SetComplete Rset :call s:Set(<bang>0,<f-args>) - command! -buffer -bar -nargs=0 Rtags :call s:Tags(<bang>0) - " Embedding all this logic directly into the command makes the error - " messages more concise. - command! -buffer -bar -nargs=? -bang Rdoc : - \ if <bang>0 || <q-args> =~ "^\\([:'-]\\|g:\\)" | call s:prephelp() | - \ if <q-args> =~ '^-\=$' | help rails | - \ elseif <q-args> =~ '^g:' | help <args> | - \ elseif <q-args> =~ '^-' | help rails<args> | - \ else | help rails-<args> | endif | - \ else | call s:Doc(<bang>0,<q-args>) | endif - command! -buffer -bar -nargs=0 -bang Rrefresh :if <bang>0|unlet! g:loaded_rails|source `=s:file`|endif|call s:Refresh(<bang>0) - if exists(":Project") - command! -buffer -bar -nargs=? -bang Rproject :call s:Project(<bang>0,<q-args>) - endif - if exists("g:loaded_dbext") - Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:environments Rdbext :call s:BufDatabase(2,<q-args>,<bang>0) - endif - let ext = expand("%:e") - if ext =~ s:viewspattern() - " TODO: complete controller names with trailing slashes here - Rcommand! -buffer -bar -nargs=? -range -complete=custom,s:controllerList Rextract :<line1>,<line2>call s:Extract(<bang>0,<f-args>) - command! -buffer -bar -nargs=? -range Rpartial :call s:warn("Warning: :Rpartial has been deprecated in favor of :Rextract") | <line1>,<line2>Rextract<bang> <args> - endif - if RailsFilePath() =~ '\<db/migrate/.*\.rb$' - command! -buffer -bar Rinvert :call s:Invert(<bang>0) - endif -endfunction - -function! s:Doc(bang, string) - if a:string != "" - if exists("g:rails_search_url") - let query = substitute(a:string,'[^A-Za-z0-9_.~-]','\="%".printf("%02X",char2nr(submatch(0)))','g') - let url = printf(g:rails_search_url, query) - else - return s:error("specify a g:rails_search_url with %s for a query placeholder") - endif - elseif isdirectory(RailsRoot()."/doc/api/classes") - let url = RailsRoot()."/doc/api/index.html" - elseif s:getpidfor("0.0.0.0","8808") > 0 - let url = "http://localhost:8808" - else - let url = "http://api.rubyonrails.org" - endif - call s:initOpenURL() - if exists(":OpenURL") - exe "OpenURL ".s:escarg(url) - else - return s:error("No :OpenURL command found") - endif -endfunction - -function! s:Log(bang,arg) - if a:arg == "" - let lf = "log/".s:environment().".log" - else - let lf = "log/".a:arg.".log" - endif - let size = getfsize(RailsRoot()."/".lf) - if size >= 1048576 - call s:warn("Log file is ".((size+512)/1024)."KB. Consider :Rake log:clear") - endif - if a:bang - exe "cgetfile ".lf - clast - else - if exists(":Tail") - " TODO: check if :Tail works with `=` - exe "Tail ".s:ra().'/'.lf - else - "exe "pedit ".s:ra().'/'.lf - pedit `=RailsRoot().'/'.lf` - endif - endif -endfunction - -function! s:NewApp(bang,...) - if a:0 == 0 - if a:bang - echo "rails.vim revision ".s:revision - else - !rails - endif - return - endif - let dir = "" - if a:1 !~ '^-' - let dir = a:1 - elseif a:{a:0} =~ '[\/]' - let dir = a:{a:0} - else - let dir = a:1 - endif - let str = "" - let c = 1 - while c <= a:0 - let str = str . " " . s:rquote(expand(a:{c})) - let c = c + 1 - endwhile - "let str = s:sub(str,'^ ','') - let dir = expand(dir) - if isdirectory(fnamemodify(dir,':h')."/.svn") && g:rails_subversion - let append = " -c" - else - let append = "" - endif - if g:rails_default_database != "" && str !~ '-d \|--database=' - let append = append." -d ".g:rails_default_database - endif - if a:bang - let append = append." --force" - endif - exe "!rails".append.str - if filereadable(dir."/".g:rails_default_file) - "exe "edit ".s:escarg(dir)."/".g:rails_default_file - edit `=dir.'/'.g:rails_default_file` - endif -endfunction - -function! s:Tags(bang) - if exists("g:Tlist_Ctags_Cmd") - let cmd = g:Tlist_Ctags_Cmd - elseif executable("exuberant-ctags") - let cmd = "exuberant-ctags" - elseif executable("ctags-exuberant") - let cmd = "ctags-exuberant" - elseif executable("ctags") - let cmd = "ctags" - elseif executable("ctags.exe") - let cmd = "ctags.exe" - else - return s:error("ctags not found") - endif - exe "!".cmd." -R ".s:ra() -endfunction - -function! s:Refresh(bang) - " What else? - if a:bang - unlet! s:rails_helper_methods - endif - if exists("g:rubycomplete_rails") && g:rubycomplete_rails && has("ruby") - silent! ruby ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) - silent! ruby Dependencies.clear if defined?(Dependencies) - if a:bang - silent! ruby ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) - endif - endif - call s:cacheclear() - call s:BufLeave() - if a:bang && s:cacheworks() - let s:cache = {} - endif - let i = 1 - let max = bufnr('$') - while i <= max - let rr = getbufvar(i,"rails_root") - if rr != "" - unlet! s:user_classes_{s:escvar(rr)} - unlet! s:dbext_type_{s:escvar(rr)} - call setbufvar(i,"rails_refresh",1) - endif - let i = i + 1 - endwhile - call s:BufEnter() -endfunction - -" }}}1 -" Rake {{{1 - -" Depends: s:efm, s:rubyexestrwithfork, s:sub, s:lastmethodline, s:getopt, s;rquote, s:QuickFixCmdPre, ... - -let s:efm_backtrace='%D(in\ %f),' - \.'%\\s%#from\ %f:%l:%m,' - \.'%\\s#{RAILS_ROOT}/%f:%l:\ %#%m,' - \.'%\\s%#[%f:%l:\ %#%m,' - \.'%\\s%#%f:%l:\ %#%m' - -function! s:makewithruby(arg,...) - if &efm == s:efm - if a:0 ? a:1 : 1 - setlocal efm=\%-E-e:%.%#,\%+E%f:%l:\ parse\ error,%W%f:%l:\ warning:\ %m,%E%f:%l:in\ %*[^:]:\ %m,%E%f:%l:\ %m,%-C%\tfrom\ %f:%l:in\ %.%#,%-Z%\tfrom\ %f:%l,%-Z%p^,%-G%.%# - endif - endif - let old_make = &makeprg - let &l:makeprg = s:rubyexestrwithfork(a:arg) - make - let &l:makeprg = old_make -endfunction - -function! s:Rake(bang,arg) - let oldefm = &efm - if a:bang - let &efm = s:efm_backtrace - "errorformat=%*[^"]"%f"%*\D%l: %m,"%f"%*\D%l: %m,%-G%f:%l: (Each undeclared identifier is reported only once,%-G%f:%l: for each function it appears in.),%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,"%f"\, line %l%*\D%c%*[^ ] %m,%D%*\a[%*\d]: Entering directory `%f',%X%*\a[%*\d]: Leaving directory `%f',%D%*\a: Entering directory `% - endif - let t = RailsFileType() - let arg = a:arg - if &filetype == "ruby" && arg == '' && g:rails_modelines - let lnum = s:lastmethodline() - let str = getline(lnum)."\n".getline(lnum+1)."\n".getline(lnum+2)."\n" - let pat = '\s\+\zs.\{-\}\ze\%(\n\|\s\s\|#{\@!\|$\)' - let mat = matchstr(str,'#\s*rake'.pat) - let mat = s:sub(mat,'\s+$','') - if mat != "" - let arg = mat - endif - endif - if arg == '' - let opt = s:getopt('task','bl') - if opt != '' - let arg = opt - endif - endif - let withrubyargs = '-r ./config/boot -r '.s:rquote(RailsRoot().'/config/environment').' -e "puts \%((in \#{Dir.getwd}))" ' - if arg =~# '^\%(stats\|routes\|notes\|db:\%(charset\|collation\|version\)\)\%(:\|$\)' - " So you can see the output even with an inadequate redirect - call s:QuickFixCmdPre() - exe "!".&makeprg." ".arg - call s:QuickFixCmdPost() - elseif arg =~ '^preview\>' - exe 'R'.s:gsub(arg,':','/') - elseif arg =~ '^runner:' - let arg = s:sub(arg,'^runner:','') - let root = matchstr(arg,'%\%(:\w\)*') - let file = expand(root).matchstr(arg,'%\%(:\w\)*\zs.*') - if file =~ '[@#].*$' - let extra = " -- -n ".matchstr(file,'[@#]\zs.*') - let file = s:sub(file,'[@#].*','') - else - let extra = '' - endif - if s:hasfile(file) || s:hasfile(file.'.rb') - call s:makewithruby(withrubyargs.'-r"'.file.'"'.extra,file !~# '_\%(spec\|test\)\%(\.rb\)\=$') - else - call s:makewithruby(withrubyargs.'-e '.s:esccmd(s:rquote(arg))) - endif - elseif arg == 'run' || arg == 'runner' - call s:makewithruby(withrubyargs.'-r"'.RailsFilePath().'"',RailsFilePath() !~# '_\%(spec\|test\)\%(\.rb\)\=$') - elseif arg =~ '^run:' - let arg = s:sub(arg,'^run:','') - let arg = s:sub(arg,'^%:h',expand('%:h')) - let arg = s:sub(arg,'^%(\%|$|[@#]@=)',expand('%')) - let arg = s:sub(arg,'[@#](\w+)$',' -- -n\1') - call s:makewithruby(withrubyargs.'-r'.arg,arg !~# '_\%(spec\|test\)\.rb$') - elseif arg != '' - exe 'make '.arg - elseif t =~ '^task\>' - let lnum = s:lastmethodline() - let line = getline(lnum) - " We can't grab the namespace so only run tasks at the start of the line - if line =~ '^\%(task\|file\)\>' - exe 'make '.s:lastmethod() - else - make - endif - elseif t =~ '^spec\>' - if RailsFilePath() =~# '\<test/test_helper\.rb$' - make spec SPEC_OPTS= - else - make spec SPEC="%:p" SPEC_OPTS= - endif - elseif t =~ '^test\>' - let meth = s:lastmethod() - if meth =~ '^test_' - let call = " -n".meth."" - else - let call = "" - endif - if t =~ '^test-\%(unit\|functional\|integration\)$' - exe "make ".s:sub(s:gsub(t,'-',':'),'unit$|functional$','&s')." TEST=\"%:p\"".s:sub(call,'^ ',' TESTOPTS=') - elseif RailsFilePath() =~# '\<test/test_helper\.rb$' - make test - else - call s:makewithruby('-e "puts \%((in \#{Dir.getwd}))" -r"%:p" -- '.call,0) - endif - elseif t=~ '^\%(db-\)\=migration\>' && RailsFilePath() !~# '\<db/schema\.rb$' - let ver = matchstr(RailsFilePath(),'\<db/migrate/0*\zs\d*\ze_') - if ver != "" - exe "make db:migrate VERSION=".ver - else - make db:migrate - endif - elseif t=~ '^model\>' - make test:units TEST="%:p:r:s?[\/]app[\/]models[\/]?/test/unit/?_test.rb" - elseif t=~ '^api\>' - make test:units TEST="%:p:r:s?[\/]app[\/]apis[\/]?/test/functional/?_test.rb" - elseif t=~ '^\<\%(controller\|helper\|view\)\>' - if RailsFilePath() =~ '\<app/' && s:controller() !~# '^\%(application\)\=$' - exe 'make test:functionals TEST="'.s:ra().'/test/functional/'.s:controller().'_controller_test.rb"' - else - make test:functionals - endif - else - make - endif - if oldefm != '' - let &efm = oldefm - endif -endfunction - -function! s:RakeComplete(A,L,P) - return g:rails_rake_tasks -endfunction - -" }}}1 -" Preview {{{1 - -" Depends: s:getopt, s:sub, s:controller, s:lastmethod, s:Detect -" Provides: s:initOpenURL - -function! s:initOpenURL() - if !exists(":OpenURL") - if has("gui_mac") - command -bar -nargs=1 OpenURL :!open <args> - elseif has("gui_win32") - command -bar -nargs=1 OpenURL :!start cmd /cstart /b <args> - elseif executable("sensible-browser") - command -bar -nargs=1 OpenURL :!sensible-browser <args> - endif - endif -endfunction - -" This returns the URI with a trailing newline if it is found -function! s:scanlineforuri(lnum) - let line = getline(a:lnum) - let url = matchstr(line,"\\v\\C%(%(GET|PUT|POST|DELETE)\\s+|\w+:/)/[^ \n\r\t<>\"]*[^] .,;\n\r\t<>\":]") - if url =~ '\C^\u\+\s\+' - let method = matchstr(url,'^\u\+') - let url = matchstr(url,'\s\+\zs.*') - if method !=? "GET" - if url =~ '?' - let url = url.'&' - else - let url = url.'?' - endif - let url = url.'_method='.tolower(method) - endif - endif - if url != "" - return s:sub(url,'^/','') . "\n" - else - return "" - endif -endfunction - -function! s:defaultpreview() - let ret = '' - if s:getopt('preview','l') != '' - let uri = s:getopt('preview','l') - elseif s:controller() != '' && s:controller() != 'application' && RailsFilePath() !~ '^public/' - if RailsFileType() =~ '^controller\>' - let start = s:lastmethodline() - 1 - if start + 1 - while getline(start) =~ '^\s*\%(#.*\)\=$' - let ret = s:scanlineforuri(start).ret - let start = start - 1 - endwhile - let ret = ret.s:controller().'/'.s:lastmethod().'/' - else - let ret = ret.s:controller().'/' - endif - elseif s:getopt('preview','b') != '' - let ret = s:getopt('preview','b') - elseif RailsFileType() =~ '^view\%(-partial\|-layout\)\@!' - let ret = ret.s:controller().'/'.expand('%:t:r:r').'/' - endif - elseif s:getopt('preview','b') != '' - let uri = s:getopt('preview','b') - elseif RailsFilePath() =~ '^public/' - let ret = s:sub(RailsFilePath(),'^public/','') - elseif s:getopt('preview','ag') != '' - let ret = s:getopt('preview','ag') - endif - return ret -endfunction - -function! s:Preview(bang,arg) - let root = s:getopt("root_url") - if root == '' - let root = s:getopt("url") - endif - let root = s:sub(root,'/$','') - if a:arg =~ '://' - let uri = a:arg - elseif a:arg != '' - let uri = root.'/'.s:sub(a:arg,'^/','') - else - let uri = matchstr(s:defaultpreview(),'.\{-\}\%(\n\@=\|$\)') - let uri = root.'/'.s:sub(s:sub(uri,'^/',''),'/$','') - endif - call s:initOpenURL() - if exists(':OpenURL') && !a:bang - exe 'OpenURL '.uri - else - " Work around bug where URLs ending in / get handled as FTP - let url = uri.(uri =~ '/$' ? '?' : '') - silent exe 'pedit '.url - wincmd w - if &filetype == '' - if uri =~ '\.css$' - setlocal filetype=css - elseif uri =~ '\.js$' - setlocal filetype=javascript - elseif getline(1) =~ '^\s*<' - setlocal filetype=xhtml - endif - endif - call s:Detect(RailsRoot()) - map <buffer> <silent> q :bwipe<CR> - wincmd p - if !a:bang - call s:warn("Define a :OpenURL command to use a browser") - endif - endif -endfunction - -function! s:PreviewComplete(A,L,P) - return s:defaultpreview() -endfunction - -" }}}1 -" Script Wrappers {{{1 - -" Depends: s:rquote, s:rubyexebg, s:rubyexe, s:rubyexestrwithfork, s:sub, s:getopt, s:usesubversion, s:user_classes_..., ..., s:pluginList, ... - -function! s:BufScriptWrappers() - Rcommand! -buffer -bar -nargs=+ -complete=custom,s:ScriptComplete Rscript :call s:Script(<bang>0,<f-args>) - Rcommand! -buffer -bar -nargs=* -complete=custom,s:ConsoleComplete Rconsole :call s:Console(<bang>0,'console',<f-args>) - "Rcommand! -buffer -bar -nargs=* Rbreakpointer :call s:Console(<bang>0,'breakpointer',<f-args>) - Rcommand! -buffer -bar -nargs=* -complete=custom,s:GenerateComplete Rgenerate :call s:Generate(<bang>0,<f-args>) - Rcommand! -buffer -bar -nargs=* -complete=custom,s:DestroyComplete Rdestroy :call s:Destroy(<bang>0,<f-args>) - Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:ServerComplete Rserver :call s:Server(<bang>0,<q-args>) - Rcommand! -buffer -bang -nargs=1 -range=0 -complete=custom,s:RubyComplete Rrunner :call s:Runner(<bang>0 ? -2 : (<count>==<line2>?<count>:-1),<f-args>) - Rcommand! -buffer -nargs=1 -range=0 -complete=custom,s:RubyComplete Rp :call s:Runner(<count>==<line2>?<count>:-1,'p begin '.<f-args>.' end') - Rcommand! -buffer -nargs=1 -range=0 -complete=custom,s:RubyComplete Rpp :call s:Runner(<count>==<line2>?<count>:-1,'require %{pp}; pp begin '.<f-args>.' end') - Rcommand! -buffer -nargs=1 -range=0 -complete=custom,s:RubyComplete Ry :call s:Runner(<count>==<line2>?<count>:-1,'y begin '.<f-args>.' end') -endfunction - -function! s:Script(bang,cmd,...) - let str = "" - let c = 1 - while c <= a:0 - let str = str . " " . s:rquote(a:{c}) - let c = c + 1 - endwhile - if a:bang - call s:rubyexebg(s:rquote("script/".a:cmd).str) - else - call s:rubyexe(s:rquote("script/".a:cmd).str) - endif -endfunction - -function! s:Runner(count,args) - if a:count == -2 - call s:Script(a:bang,"runner",a:args) - else - let str = s:rubyexestrwithfork('-r./config/boot -e "require '."'commands/runner'".'" '.s:rquote(a:args)) - let res = s:sub(system(str),'\n$','') - if a:count < 0 - echo res - else - exe a:count.'put =res' - endif - endif -endfunction - -function! s:Console(bang,cmd,...) - let str = "" - let c = 1 - while c <= a:0 - let str = str . " " . s:rquote(a:{c}) - let c = c + 1 - endwhile - call s:rubyexebg(s:rquote("script/".a:cmd).str) -endfunction - -function! s:getpidfor(bind,port) - if has("win32") || has("win64") - let netstat = system("netstat -anop tcp") - let pid = matchstr(netstat,'\<'.a:bind.':'.a:port.'\>.\{-\}LISTENING\s\+\zs\d\+') - elseif executable('lsof') - let pid = system("lsof -i 4tcp@".a:bind.':'.a:port."|grep LISTEN|awk '{print $2}'") - let pid = s:sub(pid,'\n','') - else - let pid = "" - endif - return pid -endfunction - -function! s:Server(bang,arg) - let port = matchstr(a:arg,'\%(-p\|--port=\=\)\s*\zs\d\+') - if port == '' - let port = "3000" - endif - " TODO: Extract bind argument - let bind = "0.0.0.0" - if a:bang && executable("ruby") - let pid = s:getpidfor(bind,port) - if pid =~ '^\d\+$' - echo "Killing server with pid ".pid - if !has("win32") - call system("ruby -e 'Process.kill(:TERM,".pid.")'") - sleep 100m - endif - call system("ruby -e 'Process.kill(9,".pid.")'") - sleep 100m - endif - if a:arg == "-" - return - endif - endif - if has("win32") || has("win64") || (exists("$STY") && !has("gui_running") && s:getopt("gnu_screen","abg") && executable("screen")) - call s:rubyexebg(s:rquote("script/server")." ".a:arg) - else - "--daemon would be more descriptive but lighttpd does not support it - call s:rubyexe(s:rquote("script/server")." ".a:arg." -d") - endif - call s:setopt('a:root_url','http://'.(bind=='0.0.0.0'?'localhost': bind).':'.port.'/') -endfunction - -function! s:Destroy(bang,...) - if a:0 == 0 - call s:rubyexe("script/destroy") - return - elseif a:0 == 1 - call s:rubyexe("script/destroy ".s:rquote(a:1)) - return - endif - let str = "" - let c = 1 - while c <= a:0 - let str = str . " " . s:rquote(a:{c}) - let c = c + 1 - endwhile - call s:rubyexe(s:rquote("script/destroy").str.(s:usesubversion()?' -c':'')) - unlet! s:user_classes_{s:rv()} -endfunction - -function! s:Generate(bang,...) - if a:0 == 0 - call s:rubyexe("script/generate") - return - elseif a:0 == 1 - call s:rubyexe("script/generate ".s:rquote(a:1)) - return - endif - let target = s:rquote(a:1) - let str = "" - let c = 2 - while c <= a:0 - let str = str . " " . s:rquote(a:{c}) - let c = c + 1 - endwhile - if str !~ '-p\>' && str !~ '--pretend\>' - let execstr = s:rubyexestr('-r./config/boot -e "require '."'commands/generate'".'" -- '.target." -p -f".str) - let res = system(execstr) - let file = matchstr(res,'\s\+\%(create\|force\)\s\+\zs\f\+\.rb\ze\n') - if file == "" - let file = matchstr(res,'\s\+\%(exists\)\s\+\zs\f\+\.rb\ze\n') - endif - "echo file - else - let file = "" - endif - if !s:rubyexe("script/generate ".target.(s:usesubversion()?' -c':'').str) && file != "" - unlet! s:user_classes_{s:rv()} - "exe "edit ".s:ra()."/".file - edit `=RailsRoot().'/'.file` - endif -endfunction - -function! s:ScriptComplete(ArgLead,CmdLine,P) - let cmd = s:sub(a:CmdLine,'^\u\w*\s+','') - let P = a:P - strlen(a:CmdLine)+strlen(cmd) - if cmd !~ '^[ A-Za-z0-9_=-]*$' - " You're on your own, bud - return "" - elseif cmd =~ '^\w*$' - return "about\nconsole\ndestroy\ngenerate\nperformance/benchmarker\nperformance/profiler\nplugin\nproccess/reaper\nprocess/spawner\nrunner\nserver" - elseif cmd =~ '^\%(plugin\)\s\+'.a:ArgLead.'$' - return "discover\nlist\ninstall\nupdate\nremove\nsource\nunsource\nsources" - elseif cmd =~ '\%(plugin\)\s\+\%(install\|remove\)\s\+'.a:ArgLead.'$' || cmd =~ '\%(generate\|destroy\)\s\+plugin\s\+'.a:ArgLead.'$' - return s:pluginList(a:ArgLead,a:CmdLine,a:P) - elseif cmd =~ '^\%(generate\|destroy\)\s\+'.a:ArgLead.'$' - return g:rails_generators - elseif cmd =~ '^\%(generate\|destroy\)\s\+\w\+\s\+'.a:ArgLead.'$' - let target = matchstr(cmd,'^\w\+\s\+\zs\w\+\ze\s\+') - let pattern = "" " TODO - if target =~# '^\%(\w*_\)\=controller$' - return s:sub(s:controllerList(pattern,"",""),'^application\n=','') - elseif target =~# '^\%(\w*_\)\=model$' || target =~# '^scaffold\%(_resource\)\=$' || target == 'mailer' - return s:modelList(pattern,"","") - elseif target == 'migration' || target == 'session_migration' - return s:migrationList(pattern,"","") - elseif target == 'integration_test' - return s:integrationtestList(pattern,"","") - elseif target == 'observer' - " script/generate observer is in Edge Rails - let observers = s:observerList(pattern,"","") - let models = s:modelList(pattern,"","") - if cmd =~ '^destroy\>' - let models = "" - endif - while strlen(models) > 0 - let tmp = matchstr(models."\n",'.\{-\}\ze\n') - let models = s:sub(models,'.{-}%(\n|$)','') - if stridx("\n".observers."\n","\n".tmp."\n") == -1 && tmp !~'_observer$' - let observers = observers."\n".tmp - endif - endwhile - return s:sub(observers,'^\n','') - elseif target == 'web_service' - return s:apiList(pattern,"","") - else - return "" - endif - elseif cmd =~ '^\%(generate\|destroy\)\s\+scaffold\s\+\w\+\s\+'.a:ArgLead.'$' - return s:sub(s:controllerList("","",""),'^application\n=','') - elseif cmd =~ '^\%(console\)\s\+\(--\=\w\+\s\+\)\='.a:ArgLead."$" - return s:environments()."\n-s\n--sandbox" - elseif cmd =~ '^\%(server\)\s\+.*-e\s\+'.a:ArgLead."$" - return s:environments() - elseif cmd =~ '^\%(server\)\s\+' - return "-p\n-b\n-e\n-m\n-d\n-u\n-c\n-h\n--port=\n--binding=\n--environment=\n--mime-types=\n--daemon\n--debugger\n--charset=\n--help\n" - endif - return "" -" return s:relglob(RailsRoot()."/script/",a:ArgLead."*") -endfunction - -function! s:CustomComplete(A,L,P,cmd) - let L = "Rscript ".a:cmd." ".s:sub(a:L,'^\h\w*\s+','') - let P = a:P - strlen(a:L) + strlen(L) - return s:ScriptComplete(a:A,L,P) -endfunction - -function! s:ServerComplete(A,L,P) - return s:CustomComplete(a:A,a:L,a:P,"server") -endfunction - -function! s:ConsoleComplete(A,L,P) - return s:CustomComplete(a:A,a:L,a:P,"console") -endfunction - -function! s:GenerateComplete(A,L,P) - return s:CustomComplete(a:A,a:L,a:P,"generate") -endfunction - -function! s:DestroyComplete(A,L,P) - return s:CustomComplete(a:A,a:L,a:P,"destroy") -endfunction - -function! s:RubyComplete(A,L,R) - return s:gsub(RailsUserClasses(),' ','\n')."\nActiveRecord::Base" -endfunction - -" }}}1 -" Navigation {{{1 - -function! s:BufNavCommands() - " TODO: completion - "silent exe "command! -bar -buffer -nargs=? Rcd :cd ".s:ra()."/<args>" - "silent exe "command! -bar -buffer -nargs=? Rlcd :lcd ".s:ra()."/<args>" - command! -buffer -bar -nargs=? Rcd :cd `=RailsRoot().'/'.<q-args>` - command! -buffer -bar -nargs=? Rlcd :lcd `=RailsRoot().'/'.<q-args>` - " Vim 6.2 chokes on script local completion functions (e.g., s:FindList). - " :Rcommand! is a thin wrapper arround :command! which works around this - Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList Rfind :call s:Find(<bang>0,<count>,'' ,<f-args>) - Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList REfind :call s:Find(<bang>0,<count>,'E',<f-args>) - Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList RSfind :call s:Find(<bang>0,<count>,'S',<f-args>) - Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList RVfind :call s:Find(<bang>0,<count>,'V',<f-args>) - Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList RTfind :call s:Find(<bang>0,<count>,'T',<f-args>) - Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList Rsfind :<count>RSfind<bang> <args> - Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList Rtabfind :<count>RTfind<bang> <args> - Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList Redit :call s:Edit(<bang>0,<count>,'' ,<f-args>) - Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList REedit :call s:Edit(<bang>0,<count>,'E',<f-args>) - Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList RSedit :call s:Edit(<bang>0,<count>,'S',<f-args>) - Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList RVedit :call s:Edit(<bang>0,<count>,'V',<f-args>) - Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList RTedit :call s:Edit(<bang>0,<count>,'T',<f-args>) - command! -buffer -bar -nargs=0 A :call s:Alternate(<bang>0,"") - command! -buffer -bar -nargs=0 AE :call s:Alternate(<bang>0,"E") - command! -buffer -bar -nargs=0 AS :call s:Alternate(<bang>0,"S") - command! -buffer -bar -nargs=0 AV :call s:Alternate(<bang>0,"V") - command! -buffer -bar -nargs=0 AT :call s:Alternate(<bang>0,"T") - command! -buffer -bar -nargs=0 AN :call s:Related(<bang>0,"") - command! -buffer -bar -nargs=0 R :call s:Related(<bang>0,"") - command! -buffer -bar -nargs=0 RE :call s:Related(<bang>0,"E") - command! -buffer -bar -nargs=0 RS :call s:Related(<bang>0,"S") - command! -buffer -bar -nargs=0 RV :call s:Related(<bang>0,"V") - command! -buffer -bar -nargs=0 RT :call s:Related(<bang>0,"T") - "command! -buffer -bar -nargs=0 RN :call s:Alternate(<bang>0,"") -endfunction - -function! s:djump(def) - let def = s:sub(a:def,'^[@#]','') - if def != '' - let ext = matchstr(def,'\.\zs.*') - let def = matchstr(def,'[^.]*') - let v:errmsg = '' - silent! exe "djump ".def - if ext != '' && (v:errmsg == '' || v:errmsg =~ '^E387') - let rpat = '\C^\s*respond_to\s*\%(\<do\|{\)\s*|\zs\h\k*\ze|' - let end = s:endof(line('.')) - let rline = search(rpat,'',end) - if rline > 0 - "call cursor(rline,1) - let variable = matchstr(getline(rline),rpat) - let success = search('\C^\s*'.variable.'\s*\.\s*\zs'.ext.'\>','',end) - if !success - silent! exe "djump ".def - endif - endif - endif - endif -endfunction - -function! s:Find(bang,count,arg,...) - let cmd = a:arg . (a:bang ? '!' : '') - let str = "" - if a:0 - let i = 1 - while i < a:0 - let str = str . s:escarg(a:{i}) . " " - let i = i + 1 - endwhile - let file = a:{i} - let tail = matchstr(file,'[@#].*$') - if tail != "" - let file = s:sub(file,'[@#].*$','') - endif - if file != "" - let file = s:RailsIncludefind(file) - endif - else - let file = s:RailsFind() - let tail = "" - endif - if file =~ '^\%(app\|config\|db\|public\|spec\|test\|vendor\)/.*\.' || !a:0 || 1 - call s:findedit((a:count==1?'' : a:count).cmd,file.tail,str) - else - " Old way - let fcmd = (a:count==1?'' : a:count).s:findcmdfor(cmd) - let fcmd = s:sub(fcmd,'(\d+)vert ','vert \1') - if file != "" - exe fcmd.' '.str.s:escarg(file) - endif - call s:djump(tail) - endif -endfunction - -function! s:Edit(bang,count,arg,...) - let cmd = a:arg . (a:bang ? '!' : '') - if a:0 - let str = "" - let i = 1 - while i < a:0 - "let str = str . s:escarg(a:{i}) . " " - let str = str . "`=a:".i."` " - let i = i + 1 - endwhile - let file = a:{i} - call s:findedit(s:editcmdfor(cmd),file,str) - else - exe s:editcmdfor(cmd) - endif -endfunction - -function! s:FindList(ArgLead, CmdLine, CursorPos) - if exists("*UserFileComplete") " genutils.vim - return UserFileComplete(s:RailsIncludefind(a:ArgLead), a:CmdLine, a:CursorPos, 1, &path) - else - return "" - endif -endfunction - -function! s:EditList(ArgLead, CmdLine, CursorPos) - return s:relglob("",a:ArgLead."*[^~]") -endfunction - -function! RailsIncludeexpr() - " Is this foolproof? - if mode() =~ '[iR]' || expand("<cfile>") != v:fname - return s:RailsIncludefind(v:fname) - else - return s:RailsIncludefind(v:fname,1) - endif -endfunction - -function! s:linepeak() - let line = getline(line(".")) - let line = s:sub(line,'^(.{'.col(".").'}).*','\1') - let line = s:sub(line,'([:"'."'".']|\%[qQ]=[[({<])=\f*$','') - return line -endfunction - -function! s:matchcursor(pat) - let line = getline(".") - let lastend = 0 - while lastend >= 0 - let beg = match(line,'\C'.a:pat,lastend) - let end = matchend(line,'\C'.a:pat,lastend) - if beg < col(".") && end >= col(".") - return matchstr(line,'\C'.a:pat,lastend) - endif - let lastend = end - endwhile - return "" -endfunction - -function! s:findit(pat,repl) - let res = s:matchcursor(a:pat) - if res != "" - return substitute(res,'\C'.a:pat,a:repl,'') - else - return "" - endif -endfunction - -function! s:findamethod(func,repl) - return s:findit('\s*\<\%('.a:func.'\)\s*(\=\s*[@:'."'".'"]\(\f\+\)\>.\=',a:repl) -endfunction - -function! s:findasymbol(sym,repl) - return s:findit('\s*:\%('.a:sym.'\)\s*=>\s*(\=\s*[@:'."'".'"]\(\f\+\)\>.\=',a:repl) -endfunction - -function! s:findfromview(func,repl) - return s:findit('\s*\%(<%\)\==\=\s*\<\%('.a:func.'\)\s*(\=\s*[@:'."'".'"]\(\f\+\)\>['."'".'"]\=\s*\%(%>\s*\)\=',a:repl) -endfunction - -function! s:RailsFind() - " UGH - let format = s:format('html') - let res = s:findit('\v\s*<require\s*\(=\s*File.dirname\(__FILE__\)\s*\+\s*[:'."'".'"](\f+)>.=',expand('%:h').'/\1') - if res != ""|return res.(fnamemodify(res,':e') == '' ? '.rb' : '')|endif - let res = s:findit('\v<File.dirname\(__FILE__\)\s*\+\s*[:'."'".'"](\f+)>['."'".'"]=',expand('%:h').'\1') - if res != ""|return res|endif - let res = s:findamethod('require','\1') - if res != ""|return res.(fnamemodify(res,':e') == '' ? '.rb' : '')|endif - let res = s:findamethod('belongs_to\|has_one\|composed_of\|validates_associated\|scaffold','app/models/\1.rb') - if res != ""|return res|endif - let res = s:singularize(s:findamethod('has_many\|has_and_belongs_to_many','app/models/\1')) - if res != ""|return res.".rb"|endif - let res = s:singularize(s:findamethod('create_table\|drop_table\|add_column\|rename_column\|remove_column\|add_index','app/models/\1')) - if res != ""|return res.".rb"|endif - let res = s:singularize(s:findasymbol('through','app/models/\1')) - if res != ""|return res.".rb"|endif - let res = s:findamethod('fixtures','fixtures/\1') - if res != "" - return RailsFilePath() =~ '\<spec/' ? 'spec/'.res : res - endif - let res = s:findamethod('map\.resources','app/controllers/\1_controller.rb') - if res != ""|return res|endif - let res = s:findamethod('layout','app/views/layouts/\1') - if res != ""|return res|endif - let res = s:findasymbol('layout','app/views/layouts/\1') - if res != ""|return res|endif - let res = s:findamethod('helper','app/helpers/\1_helper.rb') - if res != ""|return res|endif - let res = s:findasymbol('controller','app/controllers/\1_controller.rb') - if res != ""|return res|endif - let res = s:findasymbol('action','\1') - if res != ""|return res|endif - let res = s:sub(s:sub(s:findasymbol('partial','\1'),'^/',''),'\k+$','_&') - if res != ""|return res."\n".s:findview(res)|endif - let res = s:sub(s:sub(s:findfromview('render\s*(\=\s*:partial\s\+=>\s*','\1'),'^/',''),'\k+$','_&') - if res != ""|return res."\n".s:findview(res)|endif - let res = s:findamethod('render\s*:\%(template\|action\)\s\+=>\s*','\1.'.format.'\n\1') - if res != ""|return res|endif - let res = s:findamethod('redirect_to\s*(\=\s*:action\s\+=>\s*','\1') - if res != ""|return res|endif - let res = s:findfromview('stylesheet_link_tag','public/stylesheets/\1.css') - if res != ""|return res|endif - let res = s:sub(s:findfromview('javascript_include_tag','public/javascripts/\1.js'),'/defaults>','/application') - if res != ""|return res|endif - if RailsFileType() =~ '^controller\>' - let res = s:findit('\s*\<def\s\+\(\k\+\)\>(\=',s:sub(s:sub(RailsFilePath(),'/controllers/','/views/'),'_controller\.rb$','').'/\1') - if res != ""|return res|endif - endif - let isf_keep = &isfname - set isfname=@,48-57,/,-,_,: ",\",' - " TODO: grab visual selection in visual mode - let cfile = expand("<cfile>") - let res = s:RailsIncludefind(cfile,1) - let &isfname = isf_keep - return res -endfunction - -function! s:initnamedroutes() - if s:cacheneeds("named_routes") - let exec = "ActionController::Routing::Routes.named_routes.each {|n,r| puts %{#{n} app/controllers/#{r.requirements[:controller]}_controller.rb##{r.requirements[:action]}}}" - let string = s:railseval(exec) - let routes = {} - let list = split(string,"\n") - let i = 0 - " If we use for, Vim 6.2 dumbly treats endfor like endfunction - while i < len(list) - let route = split(list[i]," ") - let name = route[0] - let routes[name] = route[1] - let i = i + 1 - endwhile - call s:cacheset("named_routes",routes) - endif -endfunction - -function! s:namedroutefile(route) - call s:initnamedroutes() - if s:cachehas("named_routes") && has_key(s:cache("named_routes"),a:route) - return s:cache("named_routes")[a:route] - endif - return "" -endfunction - -function! RailsNamedRoutes() - call s:initnamedroutes() - if s:cachehas("named_routes") - return keys(s:cache("named_routes")) - else - " Dead code - if s:cacheneeds("route_names") - let lines = readfile(RailsRoot()."/config/routes.rb") - let plurals = map(filter(copy(lines),'v:val =~# "^ map\\.resources\\s\\+:\\w"'),'matchstr(v:val,"^ map\\.resources\\=\\s\\+:\\zs\\w\\+")') - let singulars = map(copy(plurals),'s:singularize(v:val)') - let extras = map(copy(singulars),'"new_".v:val')+map(copy(singulars),'"edit_".v:val') - let all = plurals + singulars + extras - let named = map(filter(copy(lines),'v:val =~# "^ map\\.\\%(connect\\>\\|resources\\=\\>\\)\\@!\\w\\+"'),'matchstr(v:val,"^ map\\.\\zs\\w\\+")') - call s:cacheset("route_names",named+all+map(copy(all),'"formatted_".v:val')) - endif - if s:cachehas("route_names") - return s:cache("route_names") - endif - endif -endfunction - -function! s:RailsIncludefind(str,...) - if a:str == "ApplicationController" - return "app/controllers/application.rb" - elseif a:str == "Test::Unit::TestCase" - return "test/unit/testcase.rb" - elseif a:str == "<%=" - " Probably a silly idea - return "action_view.rb" - endif - let str = a:str - if a:0 == 1 - " Get the text before the filename under the cursor. - " We'll cheat and peak at this in a bit - let line = s:linepeak() - let line = s:sub(line,'([:"'."'".']|\%[qQ]=[[({<])=\f*$','') - else - let line = "" - endif - let str = s:sub(str,'^\s*','') - let str = s:sub(str,'\s*$','') - let str = s:sub(str,'^[:@]','') - "let str = s:sub(str,"\\([\"']\\)\\(.*\\)\\1",'\2') - let str = s:sub(str,':0x\x+$','') " For #<Object:0x...> style output - let str = s:gsub(str,"[\"']",'') - if line =~ '\<\(require\|load\)\s*(\s*$' - return str - endif - let str = s:underscore(str) - let fpat = '\(\s*\%("\f*"\|:\f*\|'."'\\f*'".'\)\s*,\s*\)*' - if a:str =~ '\u' - " Classes should always be in .rb files - let str = str . '.rb' - elseif line =~ ':partial\s*=>\s*' - let str = s:sub(str,'([^/]+)$','_\1') - let str = s:findview(str) - elseif line =~ '\<layout\s*(\=\s*' || line =~ ':layout\s*=>\s*' - let str = s:findview(s:sub(str,'^/=','layouts/')) - elseif line =~ ':controller\s*=>\s*' - let str = 'app/controllers/'.str.'_controller.rb' - elseif line =~ '\<helper\s*(\=\s*' - let str = 'app/helpers/'.str.'_helper.rb' - elseif line =~ '\<fixtures\s*(\='.fpat - if RailsFilePath() =~# '\<spec/' - let str = s:sub(str,'^/@!','spec/fixtures/') - else - let str = s:sub(str,'^/@!','test/fixtures/') - endif - elseif line =~ '\<stylesheet_\(link_tag\|path\)\s*(\='.fpat - let str = s:sub(str,'^/@!','/stylesheets/') - let str = 'public'.s:sub(str,'^[^.]*$','&.css') - elseif line =~ '\<javascript_\(include_tag\|path\)\s*(\='.fpat - if str == "defaults" - let str = "application" - endif - let str = s:sub(str,'^/@!','/javascripts/') - let str = 'public'.s:sub(str,'^[^.]*$','&.js') - elseif line =~ '\<\(has_one\|belongs_to\)\s*(\=\s*' - let str = 'app/models/'.str.'.rb' - elseif line =~ '\<has_\(and_belongs_to_\)\=many\s*(\=\s*' - let str = 'app/models/'.s:singularize(str).'.rb' - elseif line =~ '\<def\s\+' && expand("%:t") =~ '_controller\.rb' - let str = s:sub(s:sub(RailsFilePath(),'/controllers/','/views/'),'_controller\.rb$','/'.str) - "let str = s:sub(expand("%:p"),'.*[\/]app[\/]controllers[\/](.{-})_controller.rb','views/\1').'/'.str - " FIXME: support nested extensions - let vt = s:view_types."," - while vt != "" - let t = matchstr(vt,'[^,]*') - let vt = s:sub(vt,'[^,]*,','') - if filereadable(str.".".t) - let str = str.".".t - break - endif - endwhile - elseif str =~ '_\%(path\|url\)$' - " REST helpers - let str = s:sub(str,'_%(path|url)$','') - let str = s:sub(str,'^hash_for_','') - let file = s:namedroutefile(str) - if file == "" - let str = s:sub(str,'^formatted_','') - if str =~ '^\%(new\|edit\)_' - let str = 'app/controllers/'.s:sub(s:pluralize(str),'^(new|edit)_(.*)','\2_controller.rb#\1') - elseif str == s:singularize(str) - " If the word can't be singularized, it's probably a link to the show - " method. We should verify by checking for an argument, but that's - " difficult the way things here are currently structured. - let str = 'app/controllers/'.s:pluralize(str).'_controller.rb#show' - else - let str = 'app/controllers/'.str.'_controller.rb#index' - endif - else - let str = file - endif - elseif str !~ '/' - " If we made it this far, we'll risk making it singular. - let str = s:singularize(str) - let str = s:sub(str,'_id$','') - endif - if str =~ '^/' && !filereadable(str) - let str = s:sub(str,'^/','') - endif - if str =~ '^lib/' && !filereadable(str) - let str = s:sub(str,'^lib/','') - endif - return str -endfunction - -" }}}1 -" File Finders {{{1 - -function! s:addfilecmds(type) - let l = s:sub(a:type,'^.','\l&') - let cmds = 'ESVT ' - let cmd = '' - while cmds != '' - let cplt = " -complete=custom,".s:sid.l."List" - exe "command! -buffer -bar -nargs=*".cplt." R".cmd.l." :call s:".l.'Edit(<bang>0,"'.cmd.'",<f-args>)' - let cmd = strpart(cmds,0,1) - let cmds = strpart(cmds,1) - endwhile -endfunction - -function! s:BufFinderCommands() - command! -buffer -bar -bang -nargs=+ Rcommand :call s:Command(<bang>0,<f-args>) - call s:addfilecmds("model") - call s:addfilecmds("view") - call s:addfilecmds("controller") - call s:addfilecmds("migration") - call s:addfilecmds("observer") - call s:addfilecmds("helper") - call s:addfilecmds("api") - call s:addfilecmds("layout") - call s:addfilecmds("fixtures") - call s:addfilecmds("unittest") - call s:addfilecmds("functionaltest") - call s:addfilecmds("integrationtest") - call s:addfilecmds("stylesheet") - call s:addfilecmds("javascript") - call s:addfilecmds("task") - call s:addfilecmds("lib") - call s:addfilecmds("plugin") -endfunction - -function! s:autocamelize(files,test) - if a:test =~# '^\u' - return s:camelize(a:files) - else - return a:files - endif -endfunction - -function! RailsUserClasses() - if !exists("b:rails_root") - return "" - elseif s:getopt('classes','ab') != '' - return s:getopt('classes','ab') - endif - let var = "user_classes_".s:rv() - if !exists("s:".var) - let s:{var} = s:sub(s:sub(s:gsub(s:camelize( - \ s:relglob("app/models/","**/*",".rb") . "\n" . - \ s:sub(s:relglob("app/controllers/","**/*",".rb"),'<application>','&_controller') . "\n" . - \ s:relglob("app/helpers/","**/*",".rb") . "\n" . - \ s:relglob("lib/","**/*",".rb") . "\n" . - \ ""),'\n+',' '),'^\s+',''),'\s+$','') - endif - return s:{var} -endfunction - -function! s:relglob(path,glob,...) - " How could such a simple operation be so complicated? - if exists("+shellslash") && ! &shellslash - let old_ss = &shellslash - let &shellslash = 1 - endif - if a:path =~ '[\/]$' - let path = a:path - else - let path = a:path . '' - endif - if path !~ '^/' && path !~ '^\w:' && RailsRoot() != '' - let path = RailsRoot() . '/' . path - endif - let suffix = a:0 ? a:1 : '' - let badres = glob(path.a:glob.suffix)."\n" - if v:version <= 602 - " Nasty Vim bug in version 6.2 - let badres = glob(path.a:glob.suffix)."\n" - endif - let goodres = "" - let striplen = strlen(path) - let stripend = strlen(suffix) - while strlen(badres) > 0 - let idx = stridx(badres,"\n") - "if idx == -1 - "let idx = strlen(badres) - "endif - let tmp = strpart(badres,0,idx) - let badres = strpart(badres,idx+1) - let goodres = goodres.strpart(tmp,striplen,strlen(tmp)-striplen-stripend) - if suffix == '' && isdirectory(tmp) && goodres !~ '/$' - let goodres = goodres."/" - endif - let goodres = goodres."\n" - endwhile - "let goodres = s:gsub("\n".goodres,'\n.{-}\~\n','\n') - if exists("old_ss") - let &shellslash = old_ss - endif - return s:compact(goodres) -endfunction - -if v:version <= 602 - " Yet another Vim 6.2 limitation - let s:recurse = "*" -else - let s:recurse = "**/*" -endif - -function! s:helperList(A,L,P) - return s:autocamelize(s:relglob("app/helpers/",s:recurse,"_helper.rb"),a:A) -endfunction - -function! s:controllerList(A,L,P) - let con = s:gsub(s:relglob("app/controllers/",s:recurse,".rb"),'_controller>','') - return s:autocamelize(con,a:A) -endfunction - -function! s:viewList(A,L,P) - let c = s:controller(1) - let top = s:relglob("app/views/",a:A."*[^~]") - if c != '' - let local = s:relglob("app/views/".c."/",a:A."*.*[^~]") - if local != '' - return local."\n".top - endif - endif - return top -endfunction - -function! s:layoutList(A,L,P) - return s:relglob("app/views/layouts/","*") -endfunction - -function! s:stylesheetList(A,L,P) - return s:relglob("public/stylesheets/",s:recurse,".css") -endfunction - -function! s:javascriptList(A,L,P) - return s:relglob("public/javascripts/",s:recurse,".js") -endfunction - -function! s:modelList(A,L,P) - let models = s:relglob("app/models/",s:recurse,".rb")."\n" - " . matches everything, and no good way to exclude newline. Lame. - let models = s:gsub(models,'[ -~]*_observer\n',"") - let models = s:compact(models) - return s:autocamelize(models,a:A) -endfunction - -function! s:observerList(A,L,P) - return s:autocamelize(s:relglob("app/models/",s:recurse,"_observer.rb"),a:A) -endfunction - -function! s:fixturesList(A,L,P) - return s:compact(s:relglob("test/fixtures/",s:recurse)."\n".s:relglob("spec/fixtures/",s:recurse)) -endfunction - -function! s:migrationList(A,L,P) - return s:autocamelize(s:relglob("db/migrate/???_",a:A."*",".rb"),a:A) -endfunction - -function! s:apiList(A,L,P) - return s:autocamelize(s:relglob("app/apis/",s:recurse,"_api.rb"),a:A) -endfunction - -function! s:unittestList(A,L,P) - return s:autocamelize(s:relglob("test/unit/",s:recurse,"_test.rb"),a:A) -endfunction - -function! s:functionaltestList(A,L,P) - return s:autocamelize(s:relglob("test/functional/",s:recurse,"_test.rb"),a:A) -endfunction - -function! s:integrationtestList(A,L,P) - return s:autocamelize(s:relglob("test/integration/",s:recurse,"_test.rb"),a:A) -endfunction - -function! s:pluginList(A,L,P) - if a:A =~ '/' - return s:relglob('vendor/plugins/',matchstr(a:A,'.\{-\}/').'**/*') - else - return s:relglob('vendor/plugins/',"*","/init.rb") - endif -endfunction - -" Task files, not actual rake tasks -function! s:taskList(A,L,P) - let top = s:relglob("lib/tasks/",s:recurse,".rake") - if RailsFilePath() =~ '\<vendor/plugins/.' - let path = s:sub(RailsFilePath(),'<vendor/plugins/[^/]*/\zs.*','tasks/') - return s:relglob(path,s:recurse,".rake") . "\n" . top - else - return top - endif -endfunction - -function! s:libList(A,L,P) - let all = s:relglob('lib/',s:recurse,".rb") - if RailsFilePath() =~ '\<vendor/plugins/.' - let path = s:sub(RailsFilePath(),'<vendor/plugins/[^/]*/\zs.*','lib/') - let all = s:relglob(path,s:recurse,".rb") . "\n" . all - endif - return s:autocamelize(all,a:A) -endfunction - -function! s:Command(bang,...) - if a:bang - let str = "" - let i = 0 - while i < a:0 - let i = i + 1 - if a:{i} =~# '^-complete=custom,s:' && v:version <= 602 - let str = str . " " . s:sub(a:{i},',s:',','.s:sid) - else - let str = str . " " . a:{i} - endif - endwhile - exe "command!".str - return - endif - let suffix = ".rb" - let filter = "**/*" - let prefix = "" - let default = "" - let name = "" - let i = 0 - while i < a:0 - let i = i + 1 - let arg = a:{i} - if arg =~# '^-suffix=' - let suffix = matchstr(arg,'-suffix=\zs.*') - elseif arg =~# '^-default=' - let default = matchstr(arg,'-default=\zs.*') - elseif arg =~# '^-\%(glob\|filter\)=' - let filter = matchstr(arg,'-\w*=\zs.*') - elseif arg !~# '^-' - " A literal '\n'. For evaluation below - if name == "" - let name = arg - else - let prefix = prefix."\\n".s:sub(arg,'/=$','/') - endif - endif - endwhile - let prefix = s:sub(prefix,'^\\n','') - if name !~ '^[A-Za-z]\+$' - return s:error("E182: Invalid command name") - endif - let cmds = 'ESVT ' - let cmd = '' - while cmds != '' - exe 'command! -buffer -bar -bang -nargs=* -complete=custom,'.s:sid.'CommandList R'.cmd.name." :call s:CommandEdit(<bang>0,'".cmd."','".name."',\"".prefix."\",".s:string(suffix).",".s:string(filter).",".s:string(default).",<f-args>)" - let cmd = strpart(cmds,0,1) - let cmds = strpart(cmds,1) - endwhile -endfunction - -function! s:CommandList(A,L,P) - let cmd = matchstr(a:L,'\CR[A-Z]\=\w\+') - exe cmd." &" - let lp = s:last_prefix . "\n" - let res = "" - while lp != "" - let p = matchstr(lp,'.\{-\}\ze\n') - let lp = s:sub(lp,'.{-}\n','') - let res = res . s:relglob(p,s:last_filter,s:last_suffix)."\n" - endwhile - let res = s:compact(res) - if s:last_camelize - return s:autocamelize(res,a:A) - else - return res - endif -endfunction - -function! s:CommandEdit(bang,cmd,name,prefix,suffix,filter,default,...) - if a:0 && a:1 == "&" - let s:last_prefix = a:prefix - let s:last_suffix = a:suffix - let s:last_filter = a:filter - let s:last_camelize = (a:suffix =~# '\.rb$') - else - if a:default == "both()" - if s:model() != "" - let default = s:model() - else - let default = s:controller() - endif - elseif a:default == "model()" - let default = s:model(1) - elseif a:default == "controller()" - let default = s:controller(1) - else - let default = a:default - endif - call s:EditSimpleRb(a:bang,a:cmd,a:name,a:0 ? a:1 : default,a:prefix,a:suffix) - endif -endfunction - -function! s:EditSimpleRb(bang,cmd,name,target,prefix,suffix) - let cmd = s:findcmdfor(a:cmd.(a:bang?'!':'')) - if a:target == "" - " Good idea to emulate error numbers like this? - return s:error("E471: Argument required") " : R',a:name) - "else - "let g:target = a:target - endif - let f = s:underscore(a:target) - let jump = matchstr(f,'[@#].*') - let f = s:sub(f,'[@#].*','') - if f == '.' - let f = s:sub(f,'\.$','') - else - let f = f.a:suffix.jump - if a:suffix !~ '\.' - "let f = f.".rb" - endif - endif - let f = s:gsub(a:prefix,'\n',f.'\n').f - return s:findedit(cmd,f) -endfunction - -function! s:migrationfor(file) - let tryagain = 0 - let arg = a:file - if arg =~ '^\d$' - let glob = '00'.arg.'_*.rb' - elseif arg =~ '^\d\d$' - let glob = '0'.arg.'_*.rb' - elseif arg =~ '^\d\d\d$' - let glob = ''.arg.'_*.rb' - elseif arg == '' - if s:model(1) != '' - let glob = '*_'.s:pluralize(s:model(1)).'.rb' - let tryagain = 1 - else - let glob = '*.rb' - endif - else - let glob = '*'.arg.'*rb' - endif - let migr = s:sub(glob(RailsRoot().'/db/migrate/'.glob),'.*\n','') - if migr == '' && tryagain - let migr = s:sub(glob(RailsRoot().'/db/migrate/*.rb'),'.*\n','') - endif - if strpart(migr,0,strlen(RailsRoot())) == RailsRoot() - let migr = strpart(migr,1+strlen(RailsRoot())) - endif - return migr -endfunction - -function! s:migrationEdit(bang,cmd,...) - let cmd = s:findcmdfor(a:cmd.(a:bang?'!':'')) - let arg = a:0 ? a:1 : '' - let migr = arg == "." ? "db/migrate" : s:migrationfor(arg) - if migr != '' - call s:findedit(cmd,migr) - else - return s:error("Migration not found".(arg=='' ? '' : ': '.arg)) - endif -endfunction - -function! s:fixturesEdit(bang,cmd,...) - if a:0 - let c = s:underscore(a:1) - else - let c = s:pluralize(s:model(1)) - endif - if c == "" - return s:error("E471: Argument required") - endif - let e = fnamemodify(c,':e') - let e = e == '' ? e : '.'.e - let c = fnamemodify(c,':r') - let file = 'test/fixtures/'.c.e - if file =~ '\.\w\+$' && !s:hasfile("spec/fixtures/".c.e) - call s:edit(a:cmd.(a:bang?'!':''),file) - else - call s:findedit(a:cmd.(a:bang?'!':''),file."\nspec/fixtures/".c.e) - endif -endfunction - -function! s:modelEdit(bang,cmd,...) - call s:EditSimpleRb(a:bang,a:cmd,"model",a:0? a:1 : s:model(1),"app/models/",".rb") -endfunction - -function! s:observerEdit(bang,cmd,...) - call s:EditSimpleRb(a:bang,a:cmd,"observer",a:0? a:1 : s:model(1),"app/models/","_observer.rb") -endfunction - -function! s:viewEdit(bang,cmd,...) - if a:0 - let view = a:1 - elseif RailsFileType() == 'controller' - let view = s:lastmethod() - else - let view = '' - endif - if view == '' - return s:error("No view name given") - elseif view == '.' - return s:edit(a:cmd.(a:bang?'!':''),'app/views') - elseif view !~ '/' && s:controller(1) != '' - let view = s:controller(1) . '/' . view - endif - if view !~ '/' - return s:error("Cannot find view without controller") - endif - let file = "app/views/".view - let found = s:findview(view) - if found != '' - call s:edit(a:cmd.(a:bang?'!':''),found) - elseif file =~ '\.\w\+\.\w\+$' || file =~ '\.'.s:viewspattern().'$' - call s:edit(a:cmd.(a:bang?'!':''),file) - elseif file =~ '\.\w\+$' - call s:findedit(a:cmd.(a:bang?'!':''),file) - else - let format = s:format('html') - if glob(RailsRoot().'/'.file.'.'.format.'.*[^~]') != '' - let file = file . '.' . format - endif - call s:findedit(a:cmd.(a:bang?'!':''),file) - endif -endfunction - -function! s:findview(name) - " TODO: full support of nested extensions - let c = a:name - let pre = "app/views/" - let file = "" - if c !~ '/' - let controller = s:controller(1) - if controller != '' - let c = controller.'/'.c - endif - endif - if c =~ '\.\w\+\.\w\+$' || c =~ '\.'.s:viewspattern().'$' - return pre.c - elseif s:hasfile(pre.c.".rhtml") - let file = pre.c.".rhtml" - elseif s:hasfile(pre.c.".rxml") - let file = pre.c.".rxml" - else - let format = "." . s:format('html') - let vt = s:view_types."," - while 1 - while vt != "" - let t = matchstr(vt,'[^,]*') - let vt = s:sub(vt,'[^,]*,','') - if s:hasfile(pre.c.format.".".t) - let file = pre.c.format.".".t - break - endif - endwhile - if format == '' || file != '' - break - else - let format = '' - endif - endwhile - endif - return file -endfunction - -function! s:findlayout(name) - return s:findview("layouts/".a:name) -endfunction - -function! s:layoutEdit(bang,cmd,...) - if a:0 - let c = s:underscore(a:1) - else - let c = s:controller(1) - endif - if c == "" - let c = "application" - endif - let file = s:findlayout(c) - if file == "" - let file = s:findlayout("application") - endif - if file == "" - let file = "app/views/layouts/application.rhtml" - endif - call s:edit(a:cmd.(a:bang?'!':''),s:sub(file,'^/','')) -endfunction - -function! s:controllerEdit(bang,cmd,...) - let suffix = '.rb' - if a:0 == 0 - let controller = s:controller(1) - if RailsFileType() =~ '^view\%(-layout\|-partial\)\@!' - let suffix = suffix.'#'.expand('%:t:r') - endif - else - let controller = a:1 - endif - if s:hasfile("app/controllers/".controller."_controller.rb") || !s:hasfile("app/controllers/".controller.".rb") - let suffix = "_controller".suffix - endif - return s:EditSimpleRb(a:bang,a:cmd,"controller",controller,"app/controllers/",suffix) -endfunction - -function! s:helperEdit(bang,cmd,...) - return s:EditSimpleRb(a:bang,a:cmd,"helper",a:0? a:1 : s:controller(1),"app/helpers/","_helper.rb") -endfunction - -function! s:apiEdit(bang,cmd,...) - return s:EditSimpleRb(a:bang,a:cmd,"api",a:0 ? a:1 : s:controller(1),"app/apis/","_api.rb") -endfunction - -function! s:stylesheetEdit(bang,cmd,...) - return s:EditSimpleRb(a:bang,a:cmd,"stylesheet",a:0? a:1 : s:controller(1),"public/stylesheets/",".css") -endfunction - -function! s:javascriptEdit(bang,cmd,...) - return s:EditSimpleRb(a:bang,a:cmd,"javascript",a:0? a:1 : "application","public/javascripts/",".js") -endfunction - -function! s:unittestEdit(bang,cmd,...) - let f = a:0 ? a:1 : s:model(1) - if !a:0 && RailsFileType() =~ '^model-aro\>' && f != '' && f !~ '_observer$' - if s:hasfile("test/unit/".f."_observer.rb") || !s:hasfile("test/unit/".f.".rb") - let f = f . "_observer" - endif - endif - return s:EditSimpleRb(a:bang,a:cmd,"unittest",f,"test/unit/","_test.rb") -endfunction - -function! s:functionaltestEdit(bang,cmd,...) - if a:0 - let f = a:1 - else - let f = s:controller() - endif - if f != '' && !s:hasfile("test/functional/".f."_test.rb") - if s:hasfile("test/functional/".f."_controller_test.rb") - let f = f . "_controller" - elseif s:hasfile("test/functional/".f."_api_test.rb") - let f = f . "_api" - endif - endif - return s:EditSimpleRb(a:bang,a:cmd,"functionaltest",f,"test/functional/","_test.rb") -endfunction - -function! s:integrationtestEdit(bang,cmd,...) - if a:0 - let f = a:1 - elseif s:model() != '' - let f = s:model() - else - let f = s:controller() - endif - return s:EditSimpleRb(a:bang,a:cmd,"integrationtest",f,"test/integration/","_test.rb") -endfunction - -function! s:pluginEdit(bang,cmd,...) - let cmd = s:findcmdfor(a:cmd.(a:bang?'!':'')) - let plugin = "" - let extra = "" - if RailsFilePath() =~ '\<vendor/plugins/.' - let plugin = matchstr(RailsFilePath(),'\<vendor/plugins/\zs[^/]*\ze') - let extra = "vendor/plugins/" . plugin . "/\n" - endif - if a:0 - if a:1 =~ '^[^/.]*/\=$' && s:hasfile("vendor/plugins/".a:1."/init.rb") - return s:EditSimpleRb(a:bang,a:cmd,"plugin",s:sub(a:1,'/$',''),"vendor/plugins/","/init.rb") - elseif plugin == "" - call s:edit(cmd,"vendor/plugins/".s:sub(a:1,'\.$','')) - elseif a:1 == "." - call s:findedit(cmd,"vendor/plugins/".plugin) - elseif isdirectory(RailsRoot()."/vendor/plugins/".matchstr(a:1,'^[^/]*')) - call s:edit(cmd,"vendor/plugins/".a:1) - else - call s:findedit(cmd,"vendor/plugins/".a:1."\nvendor/plugins/".plugin."/".a:1) - endif - else - return s:EditSimpleRb(a:bang,a:cmd,"plugin",plugin,"vendor/plugins/","/init.rb") - endif -endfunction - -function! s:taskEdit(bang,cmd,...) - let plugin = "" - let extra = "" - if RailsFilePath() =~ '\<vendor/plugins/.' - let plugin = matchstr(RailsFilePath(),'\<vendor/plugins/[^/]*') - let extra = plugin."/tasks/\n" - endif - if a:0 - call s:EditSimpleRb(a:bang,a:cmd,"task",a:1,extra."lib/tasks/",".rake") - else - call s:findedit((a:bang ? "!" : ""),(plugin != "" ? plugin."/Rakefile\n" : "")."Rakefile") - endif -endfunction - -function! s:libEdit(bang,cmd,...) - let extra = "" - if RailsFilePath() =~ '\<vendor/plugins/.' - let extra = s:sub(RailsFilePath(),'<vendor/plugins/[^/]*/\zs.*','lib/')."\n" - endif - if a:0 - call s:EditSimpleRb(a:bang,a:cmd,"task",a:0? a:1 : "",extra."lib/",".rb") - else - " Easter egg - call s:EditSimpleRb(a:bang,a:cmd,"task","environment","config/",".rb") - endif -endfunction - -" }}}1 -" Alternate/Related {{{1 - -function! s:findcmdfor(cmd) - let bang = '' - if a:cmd =~ '\!$' - let bang = '!' - let cmd = s:sub(a:cmd,'\!$','') - else - let cmd = a:cmd - endif - if cmd =~ '^\d' - let num = matchstr(cmd,'^\d\+') - let cmd = s:sub(cmd,'^\d+','') - else - let num = '' - endif - if cmd == '' || cmd == 'E' || cmd == 'F' - return num.'find'.bang - elseif cmd == 'S' - return num.'sfind'.bang - elseif cmd == 'V' - return 'vert '.num.'sfind'.bang - elseif cmd == 'T' - return num.'tabfind'.bang - else - return num.cmd.bang - endif -endfunction - -function! s:editcmdfor(cmd) - let cmd = s:findcmdfor(a:cmd) - let cmd = s:sub(cmd,'<sfind>','split') - let cmd = s:sub(cmd,'find>','edit') - return cmd -endfunction - -function! s:try(cmd) abort - if !exists(":try") - " I've seen at least one weird setup without :try - exe a:cmd - else - try - exe a:cmd - catch - call s:error(s:sub(v:exception,'^.{-}:\zeE','')) - return 0 - endtry - endif - return 1 -endfunction - -function! s:findedit(cmd,file,...) abort - let cmd = s:findcmdfor(a:cmd) - if a:file =~ '\n' - let filelist = a:file . "\n" - let file = '' - while file == '' && filelist != '' - let maybe = matchstr(filelist,'^.\{-\}\ze\n') - let filelist = s:sub(filelist,'^.{-}\n','') - if s:hasfile(s:sub(maybe,'[@#].*','')) - let file = maybe - endif - endwhile - if file == '' - let file = matchstr(a:file."\n",'^.\{-\}\ze\n') - endif - else - let file = a:file - endif - if file =~ '[@#]' - let djump = matchstr(file,'[@#]\zs.*') - let file = matchstr(file,'.\{-\}\ze[@#]') - else - let djump = '' - endif - if file == '' - let testcmd = "edit" - elseif RailsRoot() =~ '://' || cmd =~ 'edit' || cmd =~ 'split' - if file !~ '^/' && file !~ '^\w:' && file !~ '://' - let file = s:ra().'/'.file - endif - let testcmd = s:editcmdfor(cmd).' '.(a:0 ? a:1 . ' ' : '').file - elseif isdirectory(RailsRoot().'/'.file) - let testcmd = s:editcmdfor(cmd).' '.(a:0 ? a:1 . ' ' : '').s:ra().'/'.file - exe testcmd - return - else - let testcmd = cmd.' '.(a:0 ? a:1 . ' ' : '').file - endif - if s:try(testcmd) - " Shorten the file name (I don't fully understand how Vim decides when to - " use a relative/absolute path for the file name, so lets blindly force it - " to be as short as possible) - "silent! file %:~:. - "silent! lcd . - call s:djump(djump) - endif -endfunction - -function! s:edit(cmd,file,...) - let cmd = s:editcmdfor(a:cmd) - let cmd = cmd.' '.(a:0 ? a:1 . ' ' : '') - let file = a:file - if file !~ '^/' && file !~ '^\w:' && file !~ '://' - "let file = s:ra().'/'.file - exe cmd."`=RailsRoot().'/'.file`" - else - exe cmd.file - endif - "exe cmd.file -endfunction - -function! s:Alternate(bang,cmd) - let cmd = a:cmd.(a:bang?"!":"") - let file = s:AlternateFile() - if file != "" - call s:findedit(cmd,file) - else - call s:warn("No alternate file is defined") - endif -endfunction - -function! s:AlternateFile() - let f = RailsFilePath() - let t = RailsFileType() - let altopt = s:getopt("alternate","bl") - if altopt != "" - return altopt - elseif f =~ '\<config/environments/' - return "config/environment.rb" - elseif f == 'README' - return "config/database.yml" - elseif f =~ '\<config/database\.yml$' | return "config/routes.rb" - elseif f =~ '\<config/routes\.rb$' | return "config/environment.rb" - elseif f =~ '\<config/environment\.rb$' | return "config/database.yml" - elseif f =~ '\<db/migrate/\d\d\d_' - let num = matchstr(f,'\<db/migrate/0*\zs\d\+\ze_')-1 - return num ? s:migrationfor(num) : "db/schema.rb" - elseif f =~ '\<application\.js$' - return "app/helpers/application_helper.rb" - elseif t =~ '^js\>' - return "public/javascripts/application.js" - elseif f =~ '\<db/schema\.rb$' - return s:migrationfor("") - elseif t =~ '^view\>' - if t =~ '\<layout\>' - let dest = fnamemodify(f,':r:s?/layouts\>??').'/layout.'.fnamemodify(f,':e') - else - let dest = f - endif - " Go to the (r)spec, helper, controller, or (mailer) model - let spec = fnamemodify(dest,':r:s?\<app/?spec/?')."_view_spec.rb" - let helper = fnamemodify(dest,':h:s?/views/?/helpers/?')."_helper.rb" - let controller = fnamemodify(dest,':h:s?/views/?/controllers/?')."_controller.rb" - let model = fnamemodify(dest,':h:s?/views/?/models/?').".rb" - if s:hasfile(spec) - return spec - elseif s:hasfile(helper) - return helper - elseif s:hasfile(controller) - let jumpto = expand("%:t:r") - return controller.'#'.jumpto - elseif s:hasfile(model) - return model - else - return helper - endif - elseif t =~ '^controller-api\>' - let api = s:sub(s:sub(f,'/controllers/','/apis/'),'_controller\.rb$','_api.rb') - return api - elseif t =~ '^helper\>' - let controller = s:sub(s:sub(f,'/helpers/','/controllers/'),'_helper\.rb$','_controller.rb') - let controller = s:sub(controller,'application_controller','application') - let spec = s:sub(s:sub(f,'<app/','spec/'),'\.rb$','_spec.rb') - if s:hasfile(spec) - return spec - else - return controller - endif - elseif t =~ '\<fixtures\>' && f =~ '\<spec/' - let file = s:singularize(expand("%:t:r")).'_spec.rb' - return file - elseif t =~ '\<fixtures\>' - let file = s:singularize(expand("%:t:r")).'_test.rb' " .expand('%:e') - return file - elseif f == '' - call s:warn("No filename present") - elseif f =~ '\<test/unit/routing_test\.rb$' - return 'config/routes.rb' - elseif t=~ '^spec-view\>' - return s:sub(s:sub(f,'<spec/','app/'),'_view_spec\.rb$','') - elseif fnamemodify(f,":e") == "rb" - let file = fnamemodify(f,":r") - if file =~ '_\%(test\|spec\)$' - let file = s:sub(file,'_%(test|spec)$','.rb') - else - let file = file.'_test.rb' - endif - if t =~ '^model\>' - return s:sub(file,'app/models/','test/unit/')."\n".s:sub(s:sub(file,'_test\.rb$','_spec.rb'),'app/models/','spec/models/') - elseif t =~ '^controller\>' - "return s:sub(file,'app/controllers/','test/functional/') - return s:sub(file,'<app/controllers/','test/functional/')."\n".s:sub(s:sub(file,'_test\.rb$','_spec.rb'),'app/controllers/','spec/controllers/') - elseif t =~ '^test-unit\>' - return s:sub(file,'test/unit/','app/models/') - elseif t =~ '^test-functional\>' - if file =~ '_api\.rb' - return s:sub(file,'test/functional/','app/apis/') - elseif file =~ '_controller\.rb' - return s:sub(file,'test/functional/','app/controllers/') - else - return s:sub(file,'test/functional/','') - endif - elseif t =~ '^spec\>' - return s:sub(file,'<spec/','app/') - elseif file =~ '\<vendor/.*/lib/' - return s:sub(file,'<vendor/.{-}/\zslib/','test/') - elseif file =~ '\<vendor/.*/test/' - return s:sub(file,'<vendor/.{-}/\zstest/','lib/') - else - return fnamemodify(file,":t") - endif - else - return "" - endif -endfunction - -function! s:Related(bang,cmd) - let cmd = a:cmd.(a:bang?"!":"") - let file = s:RelatedFile() - if file != "" - call s:findedit(cmd,file) - else - call s:warn("No related file is defined") - endif -endfunction - -function! s:RelatedFile() - let f = RailsFilePath() - let t = RailsFileType() - let lastmethod = s:lastmethod() - if s:getopt("related","l") != "" - return s:getopt("related","l") - elseif t =~ '^\%(controller\|model-mailer\)\>' && lastmethod != "" - let root = s:sub(s:sub(s:sub(f,'/application\.rb$','/shared_controller.rb'),'/%(controllers|models)/','/views/'),'%(_controller)=\.rb$','/'.lastmethod) - let format = s:format('html') - if glob(RailsRoot().'/'.root.'.'.format.'.*[^~]') != '' - return root . '.' . format - else - return root - endif - elseif s:getopt("related","b") != "" - return s:getopt("related","b") - elseif f =~ '\<config/environments/' - return "config/database.yml#". expand("%:t:r") - elseif f == 'README' - return "config/database.yml" - elseif f =~ '\<config/database\.yml$' - let lm = s:lastmethod() - if lm != "" - return "config/environments/".lm.".rb\nconfig/environment.rb" - else - return "config/environment.rb" - endif - elseif f =~ '\<config/routes\.rb$' | return "config/database.yml" - elseif f =~ '\<config/environment\.rb$' | return "config/routes.rb" - elseif f =~ '\<db/migrate/\d\d\d_' - let num = matchstr(f,'\<db/migrate/0*\zs\d\+\ze_')+1 - let migr = s:migrationfor(num) - return migr == '' ? "db/schema.rb" : migr - elseif t =~ '^test\>' && f =~ '\<test/\w\+/' - let target = s:sub(f,'.*<test/\w+/','test/mocks/test/') - let target = s:sub(target,'_test\.rb$','.rb') - return target - elseif f =~ '\<application\.js$' - return "app/helpers/application_helper.rb" - elseif t =~ '^js\>' - return "public/javascripts/application.js" - elseif t =~ '^view-layout\>' - return s:sub(s:sub(s:sub(f,'/views/','/controllers/'),'/layouts/(\k+)\..*$','/\1_controller.rb'),'<application_controller\.rb$','application.rb') - "elseif t=~ '^view-partial\>' - "call s:warn("No related file is defined") - elseif t =~ '^view\>' - let controller = s:sub(s:sub(f,'/views/','/controllers/'),'/(\k+%(\.\k+)=)\..*$','_controller.rb#\1') - let model = s:sub(s:sub(f,'/views/','/models/'),'/(\k+)\..*$','.rb#\1') - if filereadable(s:sub(controller,'#.{-}$','')) - return controller - elseif filereadable(s:sub(model,'#.{-}$','')) || model =~ '_mailer\.rb#' - return model - else - return controller - endif - elseif t =~ '^controller-api\>' - return s:sub(s:sub(f,'/controllers/','/apis/'),'_controller\.rb$','_api.rb') - elseif t =~ '^controller\>' - return s:sub(s:sub(f,'/controllers/','/helpers/'),'%(_controller)=\.rb$','_helper.rb') - elseif t=~ '^helper\>' - return s:sub(s:sub(f,'/helpers/','/views/layouts/'),'%(_helper)=\.rb$','') - elseif t =~ '^model-arb\>' - "call s:migrationEdit(0,cmd,'create_'.s:pluralize(expand('%:t:r'))) - return s:migrationfor('create_'.s:pluralize(expand('%:t:r'))) - elseif t =~ '^model-aro\>' - return s:sub(f,'_observer\.rb$','.rb') - elseif t =~ '^api\>' - return s:sub(s:sub(f,'/apis/','/controllers/'),'_api\.rb$','_controller.rb') - elseif f =~ '\<db/schema\.rb$' - return s:migrationfor(1) - else - "call s:warn("No related file is defined") - return "" - endif -endfunction - -" }}}1 -" Partial Extraction {{{1 - -" Depends: s:error, s:sub, s:viewspattern, s:Detect, s:warn - -function! s:Extract(bang,...) range abort - if a:0 == 0 || a:0 > 1 - return s:error("Incorrect number of arguments") - endif - if a:1 =~ '[^a-z0-9_/.]' - return s:error("Invalid partial name") - endif - let ext = expand("%:e") - let file = a:1 - let first = a:firstline - let last = a:lastline - let range = first.",".last - if RailsFileType() =~ '^view-layout\>' - if RailsFilePath() =~ '\<app/views/layouts/application\>' - let curdir = 'app/views/shared' - if file !~ '/' - let file = "shared/" .file - endif - else - let curdir = s:sub(RailsFilePath(),'.*<app/views/layouts/(.*)%(\.\w*)$','app/views/\1') - endif - else - let curdir = fnamemodify(RailsFilePath(),':h') - endif - let curdir = RailsRoot()."/".curdir - let dir = fnamemodify(file,":h") - let fname = fnamemodify(file,":t") - if fnamemodify(fname,":e") == "" - let name = fname - let fname = fname.".".matchstr(expand("%:t"),'\.\zs.*') - elseif fnamemodify(fname,":e") !~ '^'.s:viewspattern().'$' - let name = fnamemodify(fname,":r") - let fname = fname.".".ext - else - let name = fnamemodify(fname,":r:r") - endif - let var = "@".name - let collection = "" - if dir =~ '^/' - let out = (RailsRoot()).dir."/_".fname - elseif dir == "" - let out = (curdir)."/_".fname - elseif isdirectory(curdir."/".dir) - let out = (curdir)."/".dir."/_".fname - else - let out = (RailsRoot())."/app/views/".dir."/_".fname - endif - if filereadable(out) - let partial_warn = 1 - "echoerr "Partial exists" - "return - endif - if bufnr(out) > 0 - if bufloaded(out) - return s:error("Partial already open in buffer ".bufnr(out)) - else - exe "bwipeout ".bufnr(out) - endif - endif - " No tabs, they'll just complicate things - if ext =~? '^\%(rhtml\|erb\|dryml\)$' - let erub1 = '\<\%\s*' - let erub2 = '\s*-=\%\>' - else - let erub1 = '' - let erub2 = '' - endif - let spaces = matchstr(getline(first),"^ *") - if getline(last+1) =~ '\v^\s*'.erub1.'end'.erub2.'\s*$' - let fspaces = matchstr(getline(last+1),"^ *") - if getline(first-1) =~ '\v^'.fspaces.erub1.'for\s+(\k+)\s+in\s+([^ %>]+)'.erub2.'\s*$' - let collection = s:sub(getline(first-1),'^'.fspaces.erub1.'for\s+(\k+)\s+in\s+([^ >]+)'.erub2.'\s*$','\1>\2') - elseif getline(first-1) =~ '\v^'.fspaces.erub1.'([^ %>]+)\.each\s+do\s+\|\s*(\k+)\s*\|'.erub2.'\s*$' - let collection = s:sub(getline(first-1),'^'.fspaces.erub1.'([^ %>]+)\.each\s+do\s+\|\s*(\k+)\s*\|'.erub2.'\s*$','\2>\1') - endif - if collection != '' - let var = matchstr(collection,'^\k\+') - let collection = s:sub(collection,'^\k+\>','') - let first = first - 1 - let last = last + 1 - endif - else - let fspaces = spaces - endif - "silent exe range."write ".out - let renderstr = "render :partial => '".fnamemodify(file,":r:r")."'" - if collection != "" - let renderstr = renderstr.", :collection => ".collection - elseif "@".name != var - let renderstr = renderstr.", :object => ".var - endif - if ext =~? '^\%(rhtml\|erb\|dryml\)$' - let renderstr = "<%= ".renderstr." %>" - elseif ext == "rxml" || ext == "builder" - let renderstr = "xml << ".s:sub(renderstr,"render ","render(").")" - elseif ext == "rjs" - let renderstr = "page << ".s:sub(renderstr,"render ","render(").")" - elseif ext == "haml" - let renderstr = "= ".renderstr - endif - let buf = @@ - silent exe range."yank" - let partial = @@ - let @@ = buf - let ai = &ai - let &ai = 0 - silent exe "norm! :".first.",".last."change\<CR>".fspaces.renderstr."\<CR>.\<CR>" - let &ai = ai - if renderstr =~ '<%' - norm ^6w - else - norm ^5w - endif - let ft = &ft - if &hidden - enew - else - new - endif - let shortout = fnamemodify(out,':~:.') - "exe "silent file ".s:escarg(shortout) - silent file `=shortout` - let &ft = ft - let @@ = partial - silent put - 0delete - let @@ = buf - if spaces != "" - silent! exe '%substitute/^'.spaces.'//' - endif - silent! exe '%substitute?\%(\w\|[@:"'."'".'-]\)\@<!'.var.'\>?'.name.'?g' - 1 - call s:Detect(out) - if exists("l:partial_warn") - call s:warn("Warning: partial exists!") - endif -endfunction - -" }}}1 -" Migration Inversion {{{1 - -" Depends: s:sub, s:endof, s:gsub, s:error - -function! s:mkeep(str) - " Things to keep (like comments) from a migration statement - return matchstr(a:str,' #[^{].*') -endfunction - -function! s:mextargs(str,num) - if a:str =~ '^\s*\w\+\s*(' - return s:sub(matchstr(a:str,'^\s*\w\+\s*\zs(\%([^,)]\+[,)]\)\{,'.a:num.'\}'),',$',')') - else - return s:sub(s:sub(matchstr(a:str,'\w\+\>\zs\s*\%([^,){ ]*[, ]*\)\{,'.a:num.'\}'),'[, ]*$',''),'^\s+',' ') - endif -endfunction - -function! s:migspc(line) - return matchstr(a:line,'^\s*') -endfunction - -function! s:invertrange(beg,end) - let str = "" - let lnum = a:beg - while lnum <= a:end - let line = getline(lnum) - let add = "" - if line == '' - let add = ' ' - elseif line =~ '^\s*\(#[^{].*\)\=$' - let add = line - elseif line =~ '\<create_table\>' - let add = s:migspc(line)."drop_table".s:mextargs(line,1).s:mkeep(line) - let lnum = s:endof(lnum) - elseif line =~ '\<drop_table\>' - let add = s:sub(line,'<drop_table>\s*\(=\s*([^,){ ]*).*','create_table \1 do |t|'."\n".matchstr(line,'^\s*').'end').s:mkeep(line) - elseif line =~ '\<add_column\>' - let add = s:migspc(line).'remove_column'.s:mextargs(line,2).s:mkeep(line) - elseif line =~ '\<remove_column\>' - let add = s:sub(line,'<remove_column>','add_column') - elseif line =~ '\<add_index\>' - let add = s:migspc(line).'remove_index'.s:mextargs(line,1) - let mat = matchstr(line,':name\s*=>\s*\zs[^ ,)]*') - if mat != '' - let add = s:sub(add,'\)=$',', :name => '.mat.'&') - else - let mat = matchstr(line,'\<add_index\>[^,]*,\s*\zs\%(\[[^]]*\]\|[:"'."'".']\w*["'."'".']\=\)') - if mat != '' - let add = s:sub(add,'\)=$',', :column => '.mat.'&') - endif - endif - let add = add.s:mkeep(line) - elseif line =~ '\<remove_index\>' - let add = s:sub(s:sub(line,'<remove_index','add_index'),':column\s*=>\s*','') - elseif line =~ '\<rename_\%(table\|column\)\>' - let add = s:sub(line,'<rename_%(table\s*\(=\s*|column\s*\(=\s*[^,]*,\s*)\zs([^,]*)(,\s*)([^,]*)','\3\2\1') - elseif line =~ '\<change_column\>' - let add = s:migspc(line).'change_column'.s:mextargs(line,2).s:mkeep(line) - elseif line =~ '\<change_column_default\>' - let add = s:migspc(line).'change_column_default'.s:mextargs(line,2).s:mkeep(line) - elseif line =~ '\.update_all(\(["'."'".']\).*\1)$' || line =~ '\.update_all \(["'."'".']\).*\1$' - " .update_all('a = b') => .update_all('b = a') - let pre = matchstr(line,'^.*\.update_all[( ][}'."'".'"]') - let post = matchstr(line,'["'."'".'])\=$') - let mat = strpart(line,strlen(pre),strlen(line)-strlen(pre)-strlen(post)) - let mat = s:gsub(','.mat.',','%(,\s*)@<=([^ ,=]{-})(\s*\=\s*)([^,=]{-})%(\s*,)@=','\3\2\1') - let add = pre.s:sub(s:sub(mat,'^,',''),',$','').post - elseif line =~ '^s\*\%(if\|unless\|while\|until\|for\)\>' - let lnum = s:endof(lnum) - endif - if lnum == 0 - return -1 - endif - if add == "" - let add = s:sub(line,'^\s*\zs.*','raise ActiveRecord::IrreversableMigration') - elseif add == " " - let add = "" - endif - let str = add."\n".str - let lnum = lnum + 1 - endwhile - let str = s:gsub(str,'(\s*raise ActiveRecord::IrreversableMigration\n)+','\1') - return str -endfunction - -function! s:Invert(bang) - let err = "Could not parse method" - let src = "up" - let dst = "down" - let beg = search('\%('.&l:define.'\).*'.src.'\>',"w") - let end = s:endof(beg) - if beg + 1 == end - let src = "down" - let dst = "up" - let beg = search('\%('.&l:define.'\).*'.src.'\>',"w") - let end = s:endof(beg) - endif - if !beg || !end - return s:error(err) - endif - let str = s:invertrange(beg+1,end-1) - if str == -1 - return s:error(err) - endif - let beg = search('\%('.&l:define.'\).*'.dst.'\>',"w") - let end = s:endof(beg) - if !beg || !end - return s:error(err) - endif - if beg + 1 < end - exe (beg+1).",".(end-1)."delete _" - endif - if str != "" - let reg_keep = @" - let @" = str - exe beg."put" - exe 1+beg - let @" = reg_keep - endif -endfunction - -" }}}1 -" Cache {{{1 - -function! s:cacheworks() - if v:version < 700 - return 0 - endif - if !exists("s:cache") - let s:cache = {} - endif - if !has_key(s:cache,RailsRoot()) - let s:cache[RailsRoot()] = {} - endif - return 1 -endfunction - -function! s:cacheclear(...) - if RailsRoot() == "" | return "" | endif - if !s:cacheworks() | return "" | endif - if a:0 == 1 - if s:cachehas(a:1) - unlet! s:cache[RailsRoot()][a:1] - endif - else - let s:cache[RailsRoot()] = {} - endif -endfunction - -function! s:cache(...) - if !s:cacheworks() | return "" | endif - if a:0 == 1 - return s:cache[RailsRoot()][a:1] - else - return s:cache[RailsRoot()] - endif -endfunction - -"function! RailsCache(...) - "if !s:cacheworks() | return "" | endif - "if a:0 == 1 - "if s:cachehas(a:1) - "return s:cache(a:1) - "else - "return "" - "endif - "else - "return s:cache() - "endif -"endfunction - -function! s:cachehas(key) - if !s:cacheworks() | return "" | endif - return has_key(s:cache(),a:key) -endfunction - -function! s:cacheneeds(key) - if !s:cacheworks() | return "" | endif - return !has_key(s:cache(),a:key) -endfunction - -function! s:cacheset(key,value) - if !s:cacheworks() | return "" | endif - let s:cache[RailsRoot()][a:key] = a:value -endfunction - -" }}}1 -" Syntax {{{1 - -" Depends: s:rubyeval, s:gsub, cache functions - -function! s:helpermethods() - let s:rails_helper_methods = "" - \."atom_feed auto_discovery_link_tag auto_link " - \."benchmark button_to button_to_function " - \."cache capture cdata_section check_box check_box_tag collection_select concat content_for content_tag content_tag_for country_options_for_select country_select cycle " - \."date_select datetime_select debug define_javascript_functions distance_of_time_in_words distance_of_time_in_words_to_now div_for dom_class dom_id draggable_element draggable_element_js drop_receiving_element drop_receiving_element_js " - \."error_message_on error_messages_for escape_javascript escape_once evaluate_remote_response excerpt " - \."field_set_tag fields_for file_field file_field_tag form form_for form_remote_for form_remote_tag form_tag " - \."hidden_field hidden_field_tag highlight " - \."image_path image_submit_tag image_tag input " - \."javascript_cdata_section javascript_include_tag javascript_path javascript_tag " - \."label link_to link_to_function link_to_if link_to_remote link_to_unless link_to_unless_current " - \."mail_to markdown " - \."number_to_currency number_to_human_size number_to_percentage number_to_phone number_with_delimiter number_with_precision " - \."observe_field observe_form option_groups_from_collection_for_select options_for_select options_from_collection_for_select " - \."partial_path password_field password_field_tag path_to_image path_to_javascript path_to_stylesheet periodically_call_remote pluralize " - \."radio_button radio_button_tag remote_form_for remote_function reset_cycle " - \."sanitize sanitize_css select select_date select_datetime select_day select_hour select_minute select_month select_second select_tag select_time select_year simple_format sortable_element sortable_element_js strip_links strip_tags stylesheet_link_tag stylesheet_path submit_tag submit_to_remote " - \."tag text_area text_area_tag text_field text_field_tag textilize textilize_without_paragraph time_ago_in_words time_select time_zone_options_for_select time_zone_select truncate " - \."update_page update_page_tag url_for " - \."visual_effect " - \."word_wrap" - - " The list of helper methods used to be derived automatically. Let's keep - " this code around in case it's needed again. - if !exists("s:rails_helper_methods") - if g:rails_expensive - let s:rails_helper_methods = "" - if has("ruby") - " && (has("win32") || has("win32unix")) - ruby begin; require 'rubygems'; rescue LoadError; end - if exists("g:rubycomplete_rails") && g:rubycomplete_rails - ruby begin; require VIM::evaluate('RailsRoot()')+'/config/environment'; rescue Exception; end - else - ruby begin; require 'active_support'; require 'action_controller'; require 'action_view'; rescue LoadError; end - end - ruby begin; h = ActionView::Helpers.constants.grep(/Helper$/).collect {|c|ActionView::Helpers.const_get c}.collect {|c| c.public_instance_methods(false)}.collect {|es| es.reject {|e| e =~ /_with(out)?_deprecation$/ || es.include?("#{e}_without_deprecation")}}.flatten.sort.uniq.reject {|m| m =~ /[=?!]$/}; VIM::command('let s:rails_helper_methods = "%s"' % h.join(" ")); rescue Exception; end - endif - if s:rails_helper_methods == "" - let s:rails_helper_methods = s:rubyeval('require %{action_controller}; require %{action_view}; h = ActionView::Helpers.constants.grep(/Helper$/).collect {|c|ActionView::Helpers.const_get c}.collect {|c| c.public_instance_methods(false)}.collect {|es| es.reject {|e| e =~ /_with(out)?_deprecation$/ || es.include?(%{#{e}_without_deprecation})}}.flatten.sort.uniq.reject {|m| m =~ /[=?!]$/}; puts h.join(%{ })',"link_to") - endif - else - let s:rails_helper_methods = "link_to" - endif - endif - "let g:rails_helper_methods = s:rails_helper_methods - return s:rails_helper_methods -endfunction - -function! s:BufSyntax() - if (!exists("g:rails_syntax") || g:rails_syntax) - let t = RailsFileType() - let s:prototype_functions = "$ $$ $A $F $H $R $w" - " From the Prototype bundle for TextMate - let s:prototype_classes = "Prototype Class Abstract Try PeriodicalExecuter Enumerable Hash ObjectRange Element Ajax Responders Base Request Updater PeriodicalUpdater Toggle Insertion Before Top Bottom After ClassNames Form Serializers TimedObserver Observer EventObserver Event Position Effect Effect2 Transitions ScopedQueue Queues DefaultOptions Parallel Opacity Move MoveBy Scale Highlight ScrollTo Fade Appear Puff BlindUp BlindDown SwitchOff DropOut Shake SlideDown SlideUp Squish Grow Shrink Pulsate Fold" - - let rails_helper_methods = '+\.\@<!\<\('.s:gsub(s:helpermethods(),'\s+','\\|').'\)\>+' - let classes = s:gsub(RailsUserClasses(),'::',' ') - if &syntax == 'ruby' - if classes != '' - exe "syn keyword rubyRailsUserClass ".classes." containedin=rubyClassDeclaration,rubyModuleDeclaration,rubyClass,rubyModule" - endif - if t == '' - syn keyword rubyRailsMethod params request response session headers cookies flash - endif - if t =~ '^api\>' - syn keyword rubyRailsAPIMethod api_method inflect_names - endif - if t =~ '^model$' || t =~ '^model-arb\>' - syn keyword rubyRailsARMethod acts_as_list acts_as_nested_set acts_as_tree composed_of serialize - syn keyword rubyRailsARAssociationMethod belongs_to has_one has_many has_and_belongs_to_many - "syn match rubyRailsARCallbackMethod '\<\(before\|after\)_\(create\|destroy\|save\|update\|validation\|validation_on_create\|validation_on_update\)\>' - syn keyword rubyRailsARCallbackMethod before_create before_destroy before_save before_update before_validation before_validation_on_create before_validation_on_update - syn keyword rubyRailsARCallbackMethod after_create after_destroy after_save after_update after_validation after_validation_on_create after_validation_on_update - syn keyword rubyRailsARClassMethod attr_accessible attr_protected establish_connection set_inheritance_column set_locking_column set_primary_key set_sequence_name set_table_name - "syn keyword rubyRailsARCallbackMethod after_find after_initialize - syn keyword rubyRailsARValidationMethod validate validate_on_create validate_on_update validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of - syn keyword rubyRailsMethod logger - endif - if t =~ '^model-aro\>' - syn keyword rubyRailsARMethod observe - endif - if t =~ '^model-mailer\>' - syn keyword rubyRailsMethod logger - " Misnomer but who cares - syn keyword rubyRailsControllerMethod helper helper_attr helper_method - endif - if t =~ '^controller\>' || t =~ '^view\>' || t=~ '^helper\>' - syn keyword rubyRailsMethod params request response session headers cookies flash - syn match rubyRailsError '[@:]\@<!@\%(params\|request\|response\|session\|headers\|cookies\|flash\)\>' - syn match rubyRailsError '\<\%(render_partial\|puts\)\>' - syn keyword rubyRailsRenderMethod render - syn keyword rubyRailsMethod logger - endif - if t =~ '^helper\>' || t=~ '^view\>' - "exe "syn match rubyRailsHelperMethod ".rails_helper_methods - exe "syn keyword rubyRailsHelperMethod ".s:sub(s:helpermethods(),'<select\s+','') - syn match rubyRailsHelperMethod '\<select\>\%(\s*{\|\s*do\>\|\s*(\=\s*&\)\@!' - syn match rubyRailsViewMethod '\.\@<!\<\(h\|html_escape\|u\|url_encode\|controller\)\>' - if t =~ '\<partial\>' - syn keyword rubyRailsMethod local_assigns - endif - "syn keyword rubyRailsDeprecatedMethod start_form_tag end_form_tag link_to_image human_size update_element_function - elseif t =~ '^controller\>' - syn keyword rubyRailsControllerMethod helper helper_attr helper_method filter layout url_for serialize exempt_from_layout filter_parameter_logging hide_action cache_sweeper - syn match rubyRailsDeprecatedMethod '\<render_\%(action\|text\|file\|template\|nothing\|without_layout\)\>' - syn keyword rubyRailsRenderMethod render_to_string redirect_to head - syn match rubyRailsRenderMethod '\<respond_to\>?\@!' - syn keyword rubyRailsFilterMethod before_filter append_before_filter prepend_before_filter after_filter append_after_filter prepend_after_filter around_filter append_around_filter prepend_around_filter skip_before_filter skip_after_filter - syn keyword rubyRailsFilterMethod verify - endif - if t =~ '^\%(db-\)\=\%(migration\|schema\)\>' - syn keyword rubyRailsMigrationMethod create_table drop_table rename_table add_column rename_column change_column change_column_default remove_column add_index remove_index - endif - if t =~ '^test\>' - if s:cacheneeds("user_asserts") && filereadable(RailsRoot()."/test/test_helper.rb") - call s:cacheset("user_asserts",map(filter(readfile(RailsRoot()."/test/test_helper.rb"),'v:val =~ "^ def assert_"'),'matchstr(v:val,"^ def \\zsassert_\\w\\+")')) - endif - if s:cachehas("user_asserts") && !empty(s:cache("user_asserts")) - exe "syn keyword rubyRailsUserMethod ".join(s:cache("user_asserts")) - endif - syn keyword rubyRailsTestMethod add_assertion assert assert_block assert_equal assert_in_delta assert_instance_of assert_kind_of assert_match assert_nil assert_no_match assert_not_equal assert_not_nil assert_not_same assert_nothing_raised assert_nothing_thrown assert_operator assert_raise assert_respond_to assert_same assert_send assert_throws assert_recognizes assert_generates assert_routing flunk fixtures fixture_path use_transactional_fixtures use_instantiated_fixtures assert_difference assert_no_difference - if t !~ '^test-unit\>' - syn match rubyRailsTestControllerMethod '\.\@<!\<\%(get\|post\|put\|delete\|head\|process\|assigns\)\>' - syn keyword rubyRailsTestControllerMethod assert_response assert_redirected_to assert_template assert_recognizes assert_generates assert_routing assert_dom_equal assert_dom_not_equal assert_valid assert_select assert_select_rjs assert_select_encoded assert_select_email - endif - elseif t=~ '^spec\>' - syn keyword rubyRailsTestMethod describe context it specify it_should_behave_like before after fixtures controller_name helper_name - syn keyword rubyRailsTestMethod violated pending - if t !~ '^spec-model\>' - syn match rubyRailsTestControllerMethod '\.\@<!\<\%(get\|post\|put\|delete\|head\|process\|assigns\)\>' - syn keyword rubyRailsMethod params request response session flash - endif - endif - if t =~ '^task\>' - syn match rubyRailsRakeMethod '^\s*\zs\%(task\|file\|namespace\|desc\|before\|after\|on\)\>\%(\s*=\)\@!' - endif - if t =~ '^model-awss\>' - syn keyword rubyRailsMethod member - endif - if t =~ '^config-routes\>' - syn match rubyRailsMethod '\.\zs\%(connect\|resources\=\|root\|named_route\|namespace\)\>' - endif - syn keyword rubyRailsMethod debugger - syn keyword rubyRailsMethod alias_attribute alias_method_chain attr_accessor_with_default attr_internal attr_internal_accessor attr_internal_reader attr_internal_writer delegate mattr_accessor mattr_reader mattr_writer - syn keyword rubyRailsMethod cattr_accessor cattr_reader cattr_writer class_inheritable_accessor class_inheritable_array class_inheritable_array_writer class_inheritable_hash class_inheritable_hash_writer class_inheritable_option class_inheritable_reader class_inheritable_writer inheritable_attributes read_inheritable_attribute reset_inheritable_attributes write_inheritable_array write_inheritable_attribute write_inheritable_hash - syn keyword rubyRailsInclude require_dependency gem - - syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:order\s*=>\s*\)\@<="+ skip=+\\\\\|\\"+ end=+"+ contains=@rubyStringSpecial,railsOrderSpecial - syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:order\s*=>\s*\)\@<='+ skip=+\\\\\|\\'+ end=+'+ contains=@rubyStringSpecial,railsOrderSpecial - syn match railsOrderSpecial +\c\<\%(DE\|A\)SC\>+ contained - syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:conditions\s*=>\s*\[\s*\)\@<="+ skip=+\\\\\|\\"+ end=+"+ contains=@rubyStringSpecial,railsConditionsSpecial - syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:conditions\s*=>\s*\[\s*\)\@<='+ skip=+\\\\\|\\'+ end=+'+ contains=@rubyStringSpecial,railsConditionsSpecial - syn match railsConditionsSpecial +?\|:\h\w*+ contained - syn cluster rubyNotTop add=railsOrderSpecial,railsConditionsSpecial - - " XHTML highlighting inside %Q<> - unlet! b:current_syntax - let removenorend = !exists("g:html_no_rendering") - let g:html_no_rendering = 1 - syn include @htmlTop syntax/xhtml.vim - if removenorend - unlet! g:html_no_rendering - endif - let b:current_syntax = "ruby" - " Restore syn sync, as best we can - if !exists("g:ruby_minlines") - let g:ruby_minlines = 50 - endif - syn sync fromstart - exe "syn sync minlines=" . g:ruby_minlines - syn case match - syn region rubyString matchgroup=rubyStringDelimiter start=+%Q\=<+ end=+>+ contains=@htmlTop,@rubyStringSpecial - "syn region rubyString matchgroup=rubyStringDelimiter start=+%q<+ end=+>+ contains=@htmlTop - syn cluster htmlArgCluster add=@rubyStringSpecial - syn cluster htmlPreProc add=@rubyStringSpecial - - elseif &syntax == "eruby" || &syntax == "haml" " && t =~ '^view\>' - syn case match - if classes != '' - exe "syn keyword erubyRailsUserClass ".classes." contained containedin=@erubyRailsRegions" - endif - if &syntax == "haml" - syn cluster erubyRailsRegions contains=hamlRubyCodeIncluded,hamlRubyCode,hamlRubyHash,rubyInterpolation - else - syn cluster erubyRailsRegions contains=erubyOneLiner,erubyBlock,erubyExpression,rubyInterpolation - endif - syn match rubyRailsError '[@:]\@<!@\%(params\|request\|response\|session\|headers\|cookies\|flash\)\>' contained containedin=@erubyRailsRegions,@rubyTop - "exe "syn match erubyRailsHelperMethod ".rails_helper_methods." contained containedin=@erubyRailsRegions" - exe "syn keyword erubyRailsHelperMethod ".s:sub(s:helpermethods(),'<select\s+','')." contained containedin=@erubyRailsRegions" - syn match erubyRailsHelperMethod '\<select\>\%(\s*{\|\s*do\>\|\s*(\=\s*&\)\@!' contained containedin=@erubyRailsRegions - syn keyword erubyRailsMethod debugger logger contained containedin=@erubyRailsRegions - syn keyword erubyRailsMethod params request response session headers cookies flash contained containedin=@erubyRailsRegions - syn match erubyRailsViewMethod '\.\@<!\<\(h\|html_escape\|u\|url_encode\|controller\)\>' contained containedin=@erubyRailsRegions - if t =~ '\<partial\>' - syn keyword erubyRailsMethod local_assigns contained containedin=@erubyRailsRegions - endif - syn keyword erubyRailsRenderMethod render contained containedin=@erubyRailsRegions - syn match rubyRailsError '[^@:]\@<!@\%(params\|request\|response\|session\|headers\|cookies\|flash\)\>' contained containedin=@erubyRailsRegions - syn match rubyRailsError '\<\%(render_partial\|puts\)\>' contained containedin=@erubyRailsRegions - syn case match - set isk+=$ - exe "syn keyword javascriptRailsClass contained ".s:prototype_classes - exe "syn keyword javascriptRailsFunction contained ".s:prototype_functions - syn cluster htmlJavaScript add=javascriptRailsClass,javascriptRailsFunction - elseif &syntax == "yaml" - syn case match - " Modeled after syntax/eruby.vim - unlet! b:current_syntax - let g:main_syntax = 'eruby' - syn include @rubyTop syntax/ruby.vim - unlet g:main_syntax - syn cluster yamlRailsRegions contains=yamlRailsOneLiner,yamlRailsBlock,yamlRailsExpression - syn region yamlRailsOneLiner matchgroup=yamlRailsDelimiter start="^%%\@!" end="$" contains=@rubyRailsTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment keepend oneline - syn region yamlRailsBlock matchgroup=yamlRailsDelimiter start="<%%\@!" end="%>" contains=@rubyTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment - syn region yamlRailsExpression matchgroup=yamlRailsDelimiter start="<%=" end="%>" contains=@rubyTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment - syn region yamlRailsComment matchgroup=yamlRailsDelimiter start="<%#" end="%>" contains=rubyTodo,@Spell containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment keepend - syn match yamlRailsMethod '\.\@<!\<\(h\|html_escape\|u\|url_encode\)\>' contained containedin=@yamlRailsRegions - if classes != '' - exe "syn keyword yamlRailsUserClass ".classes." contained containedin=@yamlRailsRegions" - endif - let b:current_syntax = "yaml" - elseif &syntax == "html" - syn case match - set isk+=$ - exe "syn keyword javascriptRailsClass contained ".s:prototype_classes - exe "syn keyword javascriptRailsFunction contained ".s:prototype_functions - syn cluster htmlJavaScript add=javascriptRailsClass,javascriptRailsFunction - elseif &syntax == "javascript" - " The syntax file included with Vim incorrectly sets syn case ignore. - syn case match - set isk+=$ - exe "syn keyword javascriptRailsClass ".s:prototype_classes - exe "syn keyword javascriptRailsFunction ".s:prototype_functions - - endif - endif - call s:HiDefaults() -endfunction - -function! s:HiDefaults() - hi def link rubyRailsAPIMethod rubyRailsMethod - hi def link rubyRailsARAssociationMethod rubyRailsARMethod - hi def link rubyRailsARCallbackMethod rubyRailsARMethod - hi def link rubyRailsARClassMethod rubyRailsARMethod - hi def link rubyRailsARValidationMethod rubyRailsARMethod - hi def link rubyRailsARMethod rubyRailsMethod - hi def link rubyRailsRenderMethod rubyRailsMethod - hi def link rubyRailsHelperMethod rubyRailsMethod - hi def link rubyRailsViewMethod rubyRailsMethod - hi def link rubyRailsMigrationMethod rubyRailsMethod - hi def link rubyRailsControllerMethod rubyRailsMethod - hi def link rubyRailsDeprecatedMethod rubyRailsError - hi def link rubyRailsFilterMethod rubyRailsMethod - hi def link rubyRailsTestControllerMethod rubyRailsTestMethod - hi def link rubyRailsTestMethod rubyRailsMethod - hi def link rubyRailsRakeMethod rubyRailsMethod - hi def link rubyRailsMethod railsMethod - hi def link rubyRailsError rubyError - hi def link rubyRailsInclude rubyInclude - hi def link rubyRailsUserClass railsUserClass - hi def link rubyRailsUserMethod railsUserMethod - hi def link erubyRailsHelperMethod erubyRailsMethod - hi def link erubyRailsViewMethod erubyRailsMethod - hi def link erubyRailsRenderMethod erubyRailsMethod - hi def link erubyRailsMethod railsMethod - hi def link erubyRailsUserMethod railsUserMethod - hi def link railsUserMethod railsMethod - hi def link erubyRailsUserClass railsUserClass - hi def link yamlRailsDelimiter Delimiter - hi def link yamlRailsMethod railsMethod - hi def link yamlRailsComment Comment - hi def link yamlRailsUserClass railsUserClass - hi def link yamlRailsUserMethod railsUserMethod - hi def link javascriptRailsFunction railsMethod - hi def link javascriptRailsClass railsClass - hi def link railsUserClass railsClass - hi def link railsMethod Function - hi def link railsClass Type - hi def link railsOrderSpecial railsStringSpecial - hi def link railsConditionsSpecial railsStringSpecial - hi def link railsStringSpecial Identifier -endfunction - -function! s:RailslogSyntax() - syn match railslogRender '^\s*\<\%(Processing\|Rendering\|Rendered\|Redirected\|Completed\)\>' - syn match railslogComment '^\s*# .*' - syn match railslogModel '^\s*\u\%(\w\|:\)* \%(Load\%( Including Associations\| IDs For Limited Eager Loading\)\=\|Columns\|Count\|Update\|Destroy\|Delete all\)\>' skipwhite nextgroup=railslogModelNum - syn match railslogModel '^\s*SQL\>' skipwhite nextgroup=railslogModelNum - syn region railslogModelNum start='(' end=')' contains=railslogNumber contained skipwhite nextgroup=railslogSQL - syn match railslogSQL '\u.*$' contained - " Destroy generates multiline SQL, ugh - syn match railslogSQL '^ \%(FROM\|WHERE\|ON\|AND\|OR\|ORDER\) .*$' - syn match railslogNumber '\<\d\+\>%' - syn match railslogNumber '[ (]\@<=\<\d\+\.\d\+\>' - syn region railslogString start='"' skip='\\"' end='"' oneline contained - syn region railslogHash start='{' end='}' oneline contains=railslogHash,railslogString - syn match railslogIP '\<\d\{1,3\}\%(\.\d\{1,3}\)\{3\}\>' - syn match railslogTimestamp '\<\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\>' - syn match railslogSessionID '\<\x\{32\}\>' - syn match railslogIdentifier '^\s*\%(Session ID\|Parameters\)\ze:' - syn match railslogSuccess '\<2\d\d \u[A-Za-z0-9 ]*\>' - syn match railslogRedirect '\<3\d\d \u[A-Za-z0-9 ]*\>' - syn match railslogError '\<[45]\d\d \u[A-Za-z0-9 ]*\>' - syn match railslogError '^DEPRECATION WARNING\>' - syn keyword railslogHTTP OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT - syn region railslogStackTrace start=":\d\+:in `\w\+'$" end="^\s*$" keepend fold - hi def link railslogComment Comment - hi def link railslogRender Keyword - hi def link railslogModel Type - hi def link railslogSQL PreProc - hi def link railslogNumber Number - hi def link railslogString String - hi def link railslogSessionID Constant - hi def link railslogIdentifier Identifier - hi def link railslogRedirect railslogSuccess - hi def link railslogSuccess Special - hi def link railslogError Error - hi def link railslogHTTP Special -endfunction - -" }}}1 -" Statusline {{{1 - -" Depends: nothing! -" Provides: s:BufInitStatusline - -function! s:addtostatus(letter,status) - let status = a:status - if status !~ 'Rails' && g:rails_statusline - let status=substitute(status,'\C%'.tolower(a:letter),'%'.tolower(a:letter).'%{RailsStatusline()}','') - if status !~ 'Rails' - let status=substitute(status,'\C%'.toupper(a:letter),'%'.toupper(a:letter).'%{RailsSTATUSLINE()}','') - endif - endif - return status -endfunction - -function! s:BufInitStatusline() - if g:rails_statusline - if &l:statusline == '' - let &l:statusline = &g:statusline - endif - if &l:statusline == '' - let &l:statusline='%<%f %h%m%r%=' - if &ruler - let &l:statusline = &l:statusline . '%-16( %l,%c-%v %)%P' - endif - endif - let &l:statusline = s:InjectIntoStatusline(&l:statusline) - endif -endfunction - -function! s:InitStatusline() - if g:rails_statusline - if &g:statusline == '' - let &g:statusline='%<%f %h%m%r%=' - if &ruler - let &g:statusline = &g:statusline . '%-16( %l,%c-%v %)%P' - endif - endif - let &g:statusline = s:InjectIntoStatusline(&g:statusline) - endif -endfunction - -function! s:InjectIntoStatusline(status) - let status = a:status - if status !~ 'Rails' - let status = s:addtostatus('y',status) - let status = s:addtostatus('r',status) - let status = s:addtostatus('m',status) - let status = s:addtostatus('w',status) - let status = s:addtostatus('h',status) - if status !~ 'Rails' - let status=substitute(status,'%=','%{RailsStatusline()}%=','') - endif - if status !~ 'Rails' && status != '' - let status=status.'%{RailsStatusline()}' - endif - endif - return status -endfunction - -function! RailsStatusline() - if exists("b:rails_root") - let t = RailsFileType() - if t != "" - return "[Rails-".t."]" - else - return "[Rails]" - endif - else - return "" - endif -endfunction - -function! RailsSTATUSLINE() - if exists("b:rails_root") - let t = RailsFileType() - if t != "" - return ",RAILS-".toupper(t) - else - return ",RAILS" - endif - else - return "" - endif -endfunction - -" }}}1 -" Mappings {{{1 - -" Depends: nothing! -" Exports: s:BufMappings - -function! s:BufMappings() - map <buffer> <silent> <Plug>RailsAlternate :A<CR> - map <buffer> <silent> <Plug>RailsRelated :R<CR> - map <buffer> <silent> <Plug>RailsFind :REfind<CR> - map <buffer> <silent> <Plug>RailsSplitFind :RSfind<CR> - map <buffer> <silent> <Plug>RailsVSplitFind :RVfind<CR> - map <buffer> <silent> <Plug>RailsTabFind :RTfind<CR> - if g:rails_mappings - if !hasmapto("<Plug>RailsFind") - nmap <buffer> gf <Plug>RailsFind - endif - if !hasmapto("<Plug>RailsSplitFind") - nmap <buffer> <C-W>f <Plug>RailsSplitFind - endif - if !hasmapto("<Plug>RailsTabFind") - nmap <buffer> <C-W>gf <Plug>RailsTabFind - endif - if !hasmapto("<Plug>RailsAlternate") - nmap <buffer> [f <Plug>RailsAlternate - endif - if !hasmapto("<Plug>RailsRelated") - nmap <buffer> ]f <Plug>RailsRelated - endif - if exists("$CREAM") - imap <buffer> <C-CR> <C-O><Plug>RailsFind - " Are these a good idea? - imap <buffer> <M-[> <C-O><Plug>RailsAlternate - imap <buffer> <M-]> <C-O><Plug>RailsRelated - endif - endif - " SelectBuf you're a dirty hack - let v:errmsg = "" -endfunction - -" }}}1 -" Menus {{{1 - -" Depends: s:gsub, s:sub, s:error -" Provides: s:prephelp - -function! s:CreateMenus() abort - if exists("g:rails_installed_menu") && g:rails_installed_menu != "" - exe "aunmenu ".s:gsub(g:rails_installed_menu,'\&','') - unlet g:rails_installed_menu - endif - if has("menu") && (exists("g:did_install_default_menus") || exists("$CREAM")) && g:rails_menu - if g:rails_menu > 1 - let g:rails_installed_menu = '&Rails' - else - let g:rails_installed_menu = '&Plugin.&Rails' - endif - if exists("$CREAM") - let menucmd = '87anoremenu <script> ' - exe menucmd.g:rails_installed_menu.'.-PSep- :' - exe menucmd.g:rails_installed_menu.'.&Related\ file\ :R\ /\ Alt+] :R<CR>' - exe menucmd.g:rails_installed_menu.'.&Alternate\ file\ :A\ /\ Alt+[ :A<CR>' - exe menucmd.g:rails_installed_menu.'.&File\ under\ cursor\ Ctrl+Enter :Rfind<CR>' - else - let menucmd = 'anoremenu <script> ' - exe menucmd.g:rails_installed_menu.'.-PSep- :' - "exe menucmd.g:rails_installed_menu.'.&Related\ file\ :R :R<CR>' - "exe menucmd.g:rails_installed_menu.'.&Alternate\ file\ :A :A<CR>' - exe menucmd.g:rails_installed_menu.'.&Related\ file\ :R\ /\ ]f :R<CR>' - exe menucmd.g:rails_installed_menu.'.&Alternate\ file\ :A\ /\ [f :A<CR>' - exe menucmd.g:rails_installed_menu.'.&File\ under\ cursor\ gf :Rfind<CR>' - endif - exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Controller :find app/controllers/application.rb<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Helper :find app/helpers/application_helper.rb<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Javascript :find public/javascripts/application.js<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Layout :Rlayout application<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &README :find doc/README_FOR_APP<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.&Environment :find config/environment.rb<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.&Database\ Configuration :find config/database.yml<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.Database\ &Schema :call <SID>findschema()<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.R&outes :find config/routes.rb<CR>' - exe menucmd.g:rails_installed_menu.'.&Other\ files.&Test\ Helper :find test/test_helper.rb<CR>' - exe menucmd.g:rails_installed_menu.'.-FSep- :' - exe menucmd.g:rails_installed_menu.'.Ra&ke\ :Rake :Rake<CR>' - let tasks = g:rails_rake_tasks - while tasks != '' - let task = matchstr(tasks,'.\{-\}\ze\%(\n\|$\)') - let tasks = s:sub(tasks,'.{-}%(\n|$)','') - exe menucmd.g:rails_installed_menu.'.Rake\ &tasks\ :Rake.'.s:sub(s:sub(task,'^[^:]*$','&:all'),':','.').' :Rake '.task.'<CR>' - endwhile - let tasks = g:rails_generators - while tasks != '' - let task = matchstr(tasks,'.\{-\}\ze\%(\n\|$\)') - let tasks = s:sub(tasks,'.{-}%(\n|$)','') - exe menucmd.'<silent> '.g:rails_installed_menu.'.&Generate\ :Rgen.'.s:gsub(task,'_','\\ ').' :call <SID>menuprompt("Rgenerate '.task.'","Arguments for script/generate '.task.': ")<CR>' - exe menucmd.'<silent> '.g:rails_installed_menu.'.&Destroy\ :Rdestroy.'.s:gsub(task,'_','\\ ').' :call <SID>menuprompt("Rdestroy '.task.'","Arguments for script/destroy '.task.': ")<CR>' - endwhile - exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Start\ :Rserver :Rserver<CR>' - exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Force\ start\ :Rserver! :Rserver!<CR>' - exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Kill\ :Rserver!\ - :Rserver! -<CR>' - exe menucmd.'<silent> '.g:rails_installed_menu.'.&Evaluate\ Ruby\.\.\.\ :Rp :call <SID>menuprompt("Rp","Code to execute and output: ")<CR>' - exe menucmd.g:rails_installed_menu.'.&Console\ :Rconsole :Rconsole<CR>' - exe menucmd.g:rails_installed_menu.'.&Preview\ :Rpreview :Rpreview<CR>' - exe menucmd.g:rails_installed_menu.'.&Log\ file\ :Rlog :Rlog<CR>' - exe s:sub(menucmd,'anoremenu','vnoremenu').' <silent> '.g:rails_installed_menu.'.E&xtract\ as\ partial\ :Rextract :call <SID>menuprompt("'."'".'<,'."'".'>Rextract","Partial name (e.g., template or /controller/template): ")<CR>' - exe menucmd.g:rails_installed_menu.'.&Migration\ writer\ :Rinvert :Rinvert<CR>' - exe menucmd.' '.g:rails_installed_menu.'.-HSep- :' - exe menucmd.'<silent> '.g:rails_installed_menu.'.&Help\ :help\ rails :call <SID>prephelp()<Bar>help rails<CR>' - exe menucmd.'<silent> '.g:rails_installed_menu.'.Abo&ut\ :call <SID>prephelp()<Bar>help rails-about<CR>' - let g:rails_did_menus = 1 - call s:ProjectMenu() - call s:menuBufLeave() - if exists("b:rails_root") - call s:menuBufEnter() - endif - endif -endfunction - -function! s:ProjectMenu() - if exists("g:rails_did_menus") && g:rails_history_size > 0 - if !exists("g:RAILS_HISTORY") - let g:RAILS_HISTORY = "" - endif - let history = g:RAILS_HISTORY - let menu = s:gsub(g:rails_installed_menu,'\&','') - silent! exe "aunmenu <script> ".menu.".Projects" - let dots = s:gsub(menu,'[^.]','') - exe 'anoremenu <script> <silent> '.(exists("$CREAM") ? '87' : '').dots.'.100 '.menu.'.Pro&jects.&New\.\.\.\ :Rails :call <SID>menuprompt("Rails","New application path and additional arguments: ")<CR>' - exe 'anoremenu <script> '.menu.'.Pro&jects.-FSep- :' - while history =~ '\n' - let proj = matchstr(history,'^.\{-\}\ze\n') - let history = s:sub(history,'^.{-}\n','') - exe 'anoremenu <script> '.menu.'.Pro&jects.'.s:gsub(proj,'[.\\ ]','\\&').' :e '.s:gsub(proj."/".g:rails_default_file,'[ !%#]','\\&')."<CR>" - endwhile - endif -endfunction - -function! s:menuBufEnter() - if exists("g:rails_installed_menu") && g:rails_installed_menu != "" - let menu = s:gsub(g:rails_installed_menu,'\&','') - exe 'amenu enable '.menu.'.*' - if RailsFileType() !~ '^view\>' - exe 'vmenu disable '.menu.'.Extract\ as\ partial' - endif - if RailsFileType() !~ '^\%(db-\)\=migration$' || RailsFilePath() =~ '\<db/schema\.rb$' - exe 'amenu disable '.menu.'.Migration\ writer' - endif - call s:ProjectMenu() - endif -endfunction - -function! s:menuBufLeave() - if exists("g:rails_installed_menu") && g:rails_installed_menu != "" - let menu = s:gsub(g:rails_installed_menu,'\&','') - exe 'amenu disable '.menu.'.*' - exe 'amenu enable '.menu.'.Help\ ' - exe 'amenu enable '.menu.'.About\ ' - exe 'amenu enable '.menu.'.Projects' - endif -endfunction - -function! s:menuprompt(vimcmd,prompt) - let res = inputdialog(a:prompt,'','!!!') - if res == '!!!' - return "" - endif - exe a:vimcmd." ".res -endfunction - -function! s:prephelp() - let fn = fnamemodify(s:file,':h:h').'/doc/' - if filereadable(fn.'rails.txt') - if !filereadable(fn.'tags') || getftime(fn.'tags') <= getftime(fn.'rails.txt') - "silent! exe 'helptags '.s:escarg(fn) - silent! helptags `=fn` - endif - endif -endfunction - -function! s:findschema() - let env = exists('$RAILS_ENV') ? $RAILS_ENV : return "development" - if filereadable(RailsRoot()."/db/schema.rb") - "exe "edit ".s:ra()."/db/schema.rb" - edit `=RailsRoot().'/db/schema.rb'` - elseif filereadable(RailsRoot().'/db/'.env.'_structure.sql') - "exe "edit ".s:ra()."/db/".env."_structure.sql" - edit `=RailsRoot().'/db/'.env.'_structure.sql'` - else - return s:error("Schema not found: try :Rake db:schema:dump") - endif -endfunction - -" }}}1 -" Project {{{ - -" Depends: s:gsub, s:escarg, s:warn, s:sub, s:relglob - -function! s:Project(bang,arg) - let rr = RailsRoot() - exe "Project ".a:arg - let line = search('^[^ =]*="'.s:gsub(rr,'[\/]','[\\/]').'"') - let projname = s:gsub(fnamemodify(rr,':t'),'\=','-') " .'_on_rails' - if line && a:bang - let projname = matchstr(getline('.'),'^[^=]*') - " Most of this would be unnecessary if the project.vim author had just put - " the newlines AFTER each project rather than before. Ugh. - norm zR0"_d% - if line('.') > 2 - delete _ - endif - if line('.') != line('$') - .-2 - endif - let line = 0 - elseif !line - $ - endif - if !line - if line('.') > 1 - append - -. - endif - let line = line('.')+1 - call s:NewProject(projname,rr,a:bang) - endif - normal! zMzo - if search("^ app=app {","W",line+10) - normal! zo - exe line - endif - normal! 0zt -endfunction - -function! s:NewProject(proj,rr,fancy) - let line = line('.')+1 - let template = s:NewProjectTemplate(a:proj,a:rr,a:fancy) - silent put =template - exe line - " Ugh. how else can I force detecting folds? - setlocal foldmethod=manual - norm! $% - silent exe "doautocmd User ".s:escarg(a:rr)."/Rproject" - let newline = line('.') - exe line - norm! $% - if line('.') != newline - call s:warn("Warning: Rproject autocommand failed to leave cursor at end of project") - endif - exe line - setlocal foldmethod=marker - setlocal nomodified - " FIXME: make undo stop here - if !exists("g:maplocalleader") - silent! normal \R - else " Needs to be tested - exe 'silent! normal '.g:maplocalleader.'R' - endif -endfunction - -function! s:NewProjectTemplate(proj,rr,fancy) - let str = a:proj.'="'.a:rr."\" CD=. filter=\"*\" {\n" - let str = str." app=app {\n" - if isdirectory(a:rr.'/app/apis') - let str = str." apis=apis {\n }\n" - endif - let str = str." controllers=controllers filter=\"**\" {\n }\n" - let str = str." helpers=helpers filter=\"**\" {\n }\n" - let str = str." models=models filter=\"**\" {\n }\n" - if a:fancy - let str = str." views=views {\n" - let views = s:relglob(a:rr.'/app/views/','*')."\n" - while views != '' - let dir = matchstr(views,'^.\{-\}\ze\n') - let views = s:sub(views,'^.{-}\n','') - let str = str." ".dir."=".dir.' filter="**" {'."\n }\n" - endwhile - let str = str." }\n" - else - let str = str." views=views filter=\"**\" {\n }\n" - endif - let str = str . " }\n" - let str = str . " config=config {\n environments=environments {\n }\n }\n" - let str = str . " db=db {\n" - if isdirectory(a:rr.'/db/migrate') - let str = str . " migrate=migrate {\n }\n" - endif - let str = str . " }\n" - let str = str . " lib=lib filter=\"* */**/*.rb \" {\n tasks=tasks filter=\"**/*.rake\" {\n }\n }\n" - let str = str . " public=public {\n images=images {\n }\n javascripts=javascripts {\n }\n stylesheets=stylesheets {\n }\n }\n" - if isdirectory(a:rr.'/spec') - let str = str . " spec=spec {\n" - let str = str . " controllers=controllers filter=\"**\" {\n }\n" - let str = str . " fixtures=fixtures filter=\"**\" {\n }\n" - let str = str . " helpers=helpers filter=\"**\" {\n }\n" - let str = str . " models=models filter=\"**\" {\n }\n" - let str = str . " views=views filter=\"**\" {\n }\n }\n" - endif - let str = str . " test=test {\n" - if isdirectory(a:rr.'/test/fixtures') - let str = str . " fixtures=fixtures filter=\"**\" {\n }\n" - endif - if isdirectory(a:rr.'/test/functional') - let str = str . " functional=functional filter=\"**\" {\n }\n" - endif - if isdirectory(a:rr.'/test/integration') - let str = str . " integration=integration filter=\"**\" {\n }\n" - endif - let str = str . " mocks=mocks filter=\"**\" {\n }\n" - if isdirectory(a:rr.'/test/unit') - let str = str . " unit=unit filter=\"**\" {\n }\n" - endif - let str = str . " }\n}\n" - "if exists("*RailsProcessProject") - "let str = call RailsProcessProject(a:rr,str) - "endif - return str -endfunction - -" }}}1 -" Database {{{1 - -" Depends: s:environment, s:rubyeval, s:rv, reloadability - -function! s:extractdbvar(str,arg) - return matchstr("\n".a:str."\n",'\n'.a:arg.'=\zs.\{-\}\ze\n') -endfunction - -function! s:BufDatabase(...) - if exists("s:lock_database") - return - endif - let s:lock_database = 1 - let rv = s:rv() - if (a:0 && a:1 > 1) - unlet! s:dbext_type_{rv} - endif - if (a:0 > 1 && a:2 != '') - let env = a:2 - else - let env = s:environment() - endif - " Crude caching mechanism - if !exists("s:dbext_type_".rv) - if exists("g:loaded_dbext") && (g:rails_dbext + (a:0 ? a:1 : 0)) > 0 && filereadable(RailsRoot()."/config/database.yml") - " Ideally we would filter this through ERB but that could be insecure. - " It might be possible to make use of taint checking. - let out = "" - if has("ruby") - ruby require 'yaml'; VIM::command('let out = %s' % File.open(VIM::evaluate("RailsRoot()")+"/config/database.yml") {|f| y = YAML::load(f); e = y[VIM::evaluate("env")]; i=0; e=y[e] while e.respond_to?(:to_str) && (i+=1)<16; e.map {|k,v| "#{k}=#{v}\n" if v}.compact.join }.inspect) rescue nil - endif - if out == "" - let cmdb = 'require %{yaml}; File.open(%q{'.RailsRoot().'/config/database.yml}) {|f| y = YAML::load(f); e = y[%{' - let cmde = '}]; i=0; e=y[e] while e.respond_to?(:to_str) && (i+=1)<16; e.each{|k,v|puts k+%{=}+v if v}}' - if a:0 ? a:1 : g:rails_expensive - let out = s:rubyeval(cmdb.env.cmde,'') - else - unlet! s:lock_database - return - endif - endif - let adapter = s:extractdbvar(out,'adapter') - let s:dbext_bin_{rv} = '' - let s:dbext_integratedlogin_{rv} = '' - if adapter == 'postgresql' - let adapter = 'pgsql' - elseif adapter == 'sqlite3' - let adapter = 'sqlite' - " Does not appear to work - let s:dbext_bin = 'sqlite3' - elseif adapter == 'sqlserver' - let adapter = 'sqlsrv' - elseif adapter == 'sybase' - let adapter = 'asa' - elseif adapter == 'oci' - let adapter = 'ora' - endif - let s:dbext_type_{rv} = toupper(adapter) - let s:dbext_user_{rv} = s:extractdbvar(out,'username') - let s:dbext_passwd_{rv} = s:extractdbvar(out,'password') - if s:dbext_passwd_{rv} == '' && adapter == 'mysql' - " Hack to override password from .my.cnf - let s:dbext_extra_{rv} = ' --password=' - else - let s:dbext_extra_{rv} = '' - endif - let s:dbext_dbname_{rv} = s:extractdbvar(out,'database') - if s:dbext_dbname_{rv} != '' && s:dbext_dbname_{rv} !~ '^:' && adapter =~? '^sqlite' - let s:dbext_dbname_{rv} = RailsRoot().'/'.s:dbext_dbname_{rv} - endif - let s:dbext_profile_{rv} = '' - let s:dbext_host_{rv} = s:extractdbvar(out,'host') - let s:dbext_port_{rv} = s:extractdbvar(out,'port') - let s:dbext_dsnname_{rv} = s:extractdbvar(out,'dsn') - if s:dbext_host_{rv} =~? '^\cDBI:' - if s:dbext_host_{rv} =~? '\c\<Trusted[_ ]Connection\s*=\s*yes\>' - let s:dbext_integratedlogin_{rv} = 1 - endif - let s:dbext_host_{rv} = matchstr(s:dbext_host_{rv},'\c\<\%(Server\|Data Source\)\s*=\s*\zs[^;]*') - endif - endif - endif - if exists("s:dbext_type_".rv) - silent! let b:dbext_type = s:dbext_type_{rv} - silent! let b:dbext_profile = s:dbext_profile_{rv} - silent! let b:dbext_bin = s:dbext_bin_{rv} - silent! let b:dbext_user = s:dbext_user_{rv} - silent! let b:dbext_passwd = s:dbext_passwd_{rv} - silent! let b:dbext_dbname = s:dbext_dbname_{rv} - silent! let b:dbext_host = s:dbext_host_{rv} - silent! let b:dbext_port = s:dbext_port_{rv} - silent! let b:dbext_dsnname = s:dbext_dsnname_{rv} - silent! let b:dbext_extra = s:dbext_extra_{rv} - silent! let b:dbext_integratedlogin = s:dbext_integratedlogin_{rv} - if b:dbext_type == 'PGSQL' - let $PGPASSWORD = b:dbext_passwd - elseif exists('$PGPASSWORD') - let $PGPASSWORD = '' - endif - endif - if a:0 >= 3 && a:3 && exists(":Create") - if exists("b:dbext_dbname") && exists("b:dbext_type") && b:dbext_type !~? 'sqlite' - let db = b:dbext_dbname - if b:dbext_type == 'PGSQL' - " I don't always have a default database for a user so using the - " default user's database is a better choice for my setup. It - " probably won't work for everyone but nothing will. - let b:dbext_dbname = 'postgres' - else - let b:dbext_dbname = '' - endif - exe "Create database ".db - let b:dbext_dbname = db - endif - endif - unlet! s:lock_database -endfunction - -" }}}1 -" Abbreviations {{{1 - -" Depends: s:sub, s:gsub, s:string, s:linepeak, s:error - -function! s:selectiveexpand(pat,good,default,...) - if a:0 > 0 - let nd = a:1 - else - let nd = "" - endif - let c = nr2char(getchar(0)) - let good = a:good - if c == "" " ^] - return s:sub(good.(a:0 ? " ".a:1 : ''),'\s+$','') - elseif c == "\t" - return good.(a:0 ? " ".a:1 : '') - elseif c =~ a:pat - return good.c.(a:0 ? a:1 : '') - else - return a:default.c - endif -endfunction - -function! s:TheMagicC() - let l = s:linepeak() - if l =~ '\<find\s*\((\|:first,\|:all,\)' || l =~ '\<paginate\>' - return s:selectiveexpand('..',':conditions => ',':c') - elseif l =~ '\<render\s*(\=\s*:partial\s\*=>\s*' - return s:selectiveexpand('..',':collection => ',':c') - elseif RailsFileType() =~ '^model\>' - return s:selectiveexpand('..',':conditions => ',':c') - else - return s:selectiveexpand('..',':controller => ',':c') - endif -endfunction - -function! s:AddSelectiveExpand(abbr,pat,expn,...) - let expn = s:gsub(s:gsub(a:expn ,'[\"|]','\\&'),'\<','\\<Lt>') - let expn2 = s:gsub(s:gsub(a:0 ? a:1 : '','[\"|]','\\&'),'\<','\\<Lt>') - if a:0 - exe "inoreabbrev <buffer> <silent> ".a:abbr." <C-R>=<SID>selectiveexpand(".s:string(a:pat).",\"".expn."\",".s:string(a:abbr).",\"".expn2."\")<CR>" - else - exe "inoreabbrev <buffer> <silent> ".a:abbr." <C-R>=<SID>selectiveexpand(".s:string(a:pat).",\"".expn."\",".s:string(a:abbr).")<CR>" - endif -endfunction - -function! s:AddTabExpand(abbr,expn) - call s:AddSelectiveExpand(a:abbr,'..',a:expn) -endfunction - -function! s:AddBracketExpand(abbr,expn) - call s:AddSelectiveExpand(a:abbr,'[[.]',a:expn) -endfunction - -function! s:AddColonExpand(abbr,expn) - call s:AddSelectiveExpand(a:abbr,':',a:expn) -endfunction - -function! s:AddParenExpand(abbr,expn,...) - if a:0 - call s:AddSelectiveExpand(a:abbr,'(',a:expn,a:1) - else - call s:AddSelectiveExpand(a:abbr,'(',a:expn,'') - endif -endfunction - -function! s:BufAbbreviations() - command! -buffer -bar -nargs=* -bang Rabbrev :call s:Abbrev(<bang>0,<f-args>) - " Some of these were cherry picked from the TextMate snippets - if g:rails_abbreviations - let t = RailsFileType() - " Limit to the right filetypes. But error on the liberal side - if t =~ '^\(controller\|view\|helper\|test-functional\|test-integration\)\>' - Rabbrev pa[ params - Rabbrev rq[ request - Rabbrev rs[ response - Rabbrev se[ session - Rabbrev hd[ headers - Rabbrev co[ cookies - Rabbrev fl[ flash - Rabbrev rr( render - Rabbrev ra( render :action\ =>\ - Rabbrev rc( render :controller\ =>\ - Rabbrev rf( render :file\ =>\ - Rabbrev ri( render :inline\ =>\ - Rabbrev rj( render :json\ =>\ - Rabbrev rl( render :layout\ =>\ - Rabbrev rp( render :partial\ =>\ - Rabbrev rt( render :text\ =>\ - Rabbrev rx( render :xml\ =>\ - endif - if t =~ '^\%(view\|helper\)\>' - Rabbrev dotiw distance_of_time_in_words - Rabbrev taiw time_ago_in_words - endif - if t =~ '^controller\>' - "call s:AddSelectiveExpand('rn','[,\r]','render :nothing => true') - "let b:rails_abbreviations = b:rails_abbreviations . "rn\trender :nothing => true\n" - Rabbrev re( redirect_to - Rabbrev rea( redirect_to :action\ =>\ - Rabbrev rec( redirect_to :controller\ =>\ - Rabbrev rst( respond_to - endif - if t =~ '^model-arb\>' || t =~ '^model$' - Rabbrev bt( belongs_to - Rabbrev ho( has_one - Rabbrev hm( has_many - Rabbrev habtm( has_and_belongs_to_many - Rabbrev co( composed_of - Rabbrev va( validates_associated - Rabbrev vb( validates_acceptance_of - Rabbrev vc( validates_confirmation_of - Rabbrev ve( validates_exclusion_of - Rabbrev vf( validates_format_of - Rabbrev vi( validates_inclusion_of - Rabbrev vl( validates_length_of - Rabbrev vn( validates_numericality_of - Rabbrev vp( validates_presence_of - Rabbrev vu( validates_uniqueness_of - endif - if t =~ '^\%(db-\)\=\%(migration\|schema\)\>' - Rabbrev mac( add_column - Rabbrev mrnc( rename_column - Rabbrev mrc( remove_column - Rabbrev mct( create_table - "Rabbrev mct create_table\ :\ do\ <Bar>t<Bar><CR>end<Esc>k$6hi - Rabbrev mrnt( rename_table - Rabbrev mdt( drop_table - Rabbrev mcc( t.column - endif - if t =~ '^test\>' - "Rabbrev ae( assert_equal - Rabbrev ase( assert_equal - "Rabbrev ako( assert_kind_of - Rabbrev asko( assert_kind_of - "Rabbrev ann( assert_not_nil - Rabbrev asnn( assert_not_nil - "Rabbrev ar( assert_raise - Rabbrev asr( assert_raise - "Rabbrev are( assert_response - Rabbrev asre( assert_response - Rabbrev art( assert_redirected_to - endif - Rabbrev :a :action\ =>\ - inoreabbrev <buffer> <silent> :c <C-R>=<SID>TheMagicC()<CR> - " Lie a little - if t =~ '^view\>' - let b:rails_abbreviations = b:rails_abbreviations . ":c\t:collection => \n" - elseif s:controller() != '' - let b:rails_abbreviations = b:rails_abbreviations . ":c\t:controller => \n" - else - let b:rails_abbreviations = b:rails_abbreviations . ":c\t:conditions => \n" - endif - Rabbrev :i :id\ =>\ - Rabbrev :o :object\ =>\ - Rabbrev :p :partial\ =>\ - Rabbrev logd( logger.debug - Rabbrev logi( logger.info - Rabbrev logw( logger.warn - Rabbrev loge( logger.error - Rabbrev logf( logger.fatal - Rabbrev fi( find - Rabbrev AR:: ActiveRecord - Rabbrev AV:: ActionView - Rabbrev AC:: ActionController - Rabbrev AS:: ActiveSupport - Rabbrev AM:: ActionMailer - Rabbrev AE:: ActiveResource - Rabbrev AWS:: ActionWebService - endif -endfunction - -function! s:Abbrev(bang,...) abort - if !exists("b:rails_abbreviations") - let b:rails_abbreviations = "\n" - endif - if a:0 > 3 || (a:bang && (a:0 != 1)) - return s:error("Rabbrev: invalid arguments") - endif - if a:bang - return s:unabbrev(a:1) - endif - if a:0 == 0 - echo s:sub(b:rails_abbreviations,'^\n','') - return - endif - let lhs = a:1 - if a:0 > 3 || a:0 < 2 - return s:error("Rabbrev: invalid arguments") - endif - let rhs = a:2 - silent! call s:unabbrev(lhs) - if lhs =~ '($' - let b:rails_abbreviations = b:rails_abbreviations . lhs . "\t" . rhs . "" . (a:0 > 2 ? "\t".a:3 : ""). "\n" - let llhs = s:sub(lhs,'\($','') - if a:0 > 2 - call s:AddParenExpand(llhs,rhs,a:3) - else - call s:AddParenExpand(llhs,rhs) - endif - return - endif - if a:0 > 2 - return s:error("Rabbrev: invalid arguments") - endif - if lhs =~ ':$' - let llhs = s:sub(lhs,':=:$','') - call s:AddColonExpand(llhs,rhs) - elseif lhs =~ '\[$' - let llhs = s:sub(lhs,'\[$','') - call s:AddBracketExpand(llhs,rhs) - elseif lhs =~ '\w$' - call s:AddTabExpand(lhs,rhs) - else - return s:error("Rabbrev: unimplemented") - endif - let b:rails_abbreviations = b:rails_abbreviations . lhs . "\t" . rhs . "\n" -endfunction - -function! s:unabbrev(abbr) - let abbr = s:sub(a:abbr,'%(::|\(|\[)$','') - let pat = s:sub(abbr,'\\','\\\\') - if !exists("b:rails_abbreviations") - let b:rails_abbreviations = "\n" - endif - let b:rails_abbreviations = substitute(b:rails_abbreviations,'\V\C\n'.pat.'\(\t\|::\t\|(\t\|[\t\)\.\{-\}\n','\n','') - exe "iunabbrev <buffer> ".abbr -endfunction - -" }}}1 -" Tab Hacks {{{1 - -" Depends: nothing! - -function! s:tabstop() - if !exists("b:rails_root") - return 0 - elseif &filetype !~ '^\%(ruby\|'.s:gsub(s:view_types,',','\\|').'\|html\|css\|sass\|yaml\|javascript\)$' - return 0 - elseif exists("b:rails_tabstop") - return b:rails_tabstop - elseif exists("g:rails_tabstop") - return g:rails_tabstop - endif -endfunction - -function! s:breaktabs() - let ts = s:tabstop() - if ts - if exists("s:retab_in_process") - unlet s:retab_in_process - let line = line('.') - lockmarks silent! undo - lockmarks exe line - else - let &l:tabstop = 2 - setlocal noexpandtab - let mod = &l:modifiable - setlocal modifiable - let line = line('.') - " FIXME: when I say g/^\s/, only apply to those lines - lockmarks g/^\s/retab! - lockmarks exe line - let &l:modifiable = mod - endif - let &l:tabstop = ts - let &l:softtabstop = ts - let &l:shiftwidth = ts - endif -endfunction - -function! s:fixtabs() - let ts = s:tabstop() - if ts && ! &l:expandtab && !exists("s:retab_in_process") - let s:retab_in_process = 1 - let &l:tabstop = 2 - setlocal expandtab - let line = line('.') - lockmarks retab - lockmarks exe line - let &l:tabstop = ts - endif -endfunction - -" }}}1 -" Settings {{{1 - -" Depends: s:error, s:sub, s:sname, s:escvar, s:lastmethod, s:environment, s:gsub, s:lastmethodlib, s:gsub - -function! s:Set(bang,...) - let c = 1 - let defscope = '' - while c <= a:0 - let arg = a:{c} - let c = c + 1 - if arg =~? '^<[abgl]\=>$' - let defscope = (matchstr(arg,'<\zs.*\ze>')) - elseif arg !~ '=' - if defscope != '' && arg !~ '^\w:' - let arg = defscope.':'.opt - endif - let val = s:getopt(arg) - if val == '' && s:opts() !~ '\<'.arg.'\n' - call s:error("No such rails.vim option: ".arg) - else - echo arg."=".val - endif - else - let opt = matchstr(arg,'[^=]*') - let val = s:sub(arg,'^[^=]*\=','') - if defscope != '' && opt !~ '^\w:' - let opt = defscope.':'.opt - endif - call s:setopt(opt,val) - endif - endwhile -endfunction - -function! s:getopt(opt,...) - let opt = a:opt - if a:0 - let scope = a:1 - elseif opt =~ '^[abgl]:' - let scope = tolower(matchstr(opt,'^\w')) - let opt = s:sub(opt,'^\w:','') - else - let scope = 'abgl' - endif - if scope =~ 'l' && &filetype != 'ruby' - let scope = s:sub(scope,'l','b') - endif - if scope =~ 'l' - call s:LocalModelines() - endif - let opt = s:sub(opt,'<%(rake|rake_task|rake_target)$','task') - " Get buffer option - if scope =~ 'l' && exists("b:_".s:sname()."_".s:escvar(s:lastmethod())."_".opt) - return b:_{s:sname()}_{s:escvar(s:lastmethod())}_{opt} - elseif exists("b:".s:sname()."_".opt) && (scope =~ 'b' || (scope =~ 'l' && s:lastmethod() == '')) - return b:{s:sname()}_{opt} - elseif scope =~ 'a' && exists("s:_".s:rv()."_".s:environment()."_".opt) - return s:_{s:rv()}_{s:environment()}_{opt} - elseif scope =~ 'g' && exists("g:".s:sname()."_".opt) - return g:{s:sname()}_{opt} - else - return "" - endif -endfunction - -function! s:setopt(opt,val) - if a:opt =~? '[abgl]:' - let scope = matchstr(a:opt,'^\w') - let opt = s:sub(a:opt,'^\w:','') - else - let scope = '' - let opt = a:opt - endif - let opt = s:sub(opt,'<%(rake|rake_task|rake_target)$','task') - let defscope = matchstr(s:opts(),'\n\zs\w\ze:'.opt,'\n') - if defscope == '' - let defscope = 'a' - endif - if scope == '' - let scope = defscope - endif - if &filetype == 'ruby' && (scope == 'B' || scope == 'l') - let scope = 'b' - endif - if opt =~ '\W' - return s:error("Invalid option ".a:opt) - elseif scope =~? 'a' - let s:_{s:rv()}_{s:environment()}_{opt} = a:val - elseif scope == 'B' && defscope == 'l' - let b:_{s:sname()}_{s:escvar('')}_{opt} = a:val - elseif scope =~? 'b' - let b:{s:sname()}_{opt} = a:val - elseif scope =~? 'g' - let g:{s:sname()}_{opt} = a:val - elseif scope =~? 'l' - let b:_{s:sname()}_{s:escvar(s:lastmethod())}_{opt} = a:val - else - return s:error("Invalid scope for ".a:opt) - endif -endfunction - -function! s:opts() - return "\nb:alternate\nb:controller\na:gnu_screen\nb:model\nl:preview\nb:task\nl:related\na:root_url\na:ruby_fork_port\n" -endfunction - -function! s:SetComplete(A,L,P) - if a:A =~ '=' - let opt = matchstr(a:A,'[^=]*') - return opt."=".s:getopt(opt) - else - let extra = matchstr(a:A,'^[abgl]:') - let opts = s:gsub(s:sub(s:gsub(s:opts(),'\n\w:','\n'.extra),'^\n',''),'\n','=\n') - return opts - endif - return "" -endfunction - -function! s:BufModelines() - if !g:rails_modelines - return - endif - let lines = getline("$")."\n".getline(line("$")-1)."\n".getline(1)."\n".getline(2)."\n".getline(3)."\n" - let pat = '\s\+\zs.\{-\}\ze\%(\n\|\s\s\|#{\@!\|%>\|-->\|$\)' - let cnt = 1 - let mat = matchstr(lines,'\C\<Rset'.pat) - let matend = matchend(lines,'\C\<Rset'.pat) - while mat != "" && cnt < 10 - let mat = s:sub(mat,'\s+$','') - let mat = s:gsub(mat,'\|','\\|') - if mat != '' - silent! exe "Rset <B> ".mat - endif - let mat = matchstr(lines,'\C\<Rset'.pat,matend) - let matend = matchend(lines,'\C\<Rset'.pat,matend) - let cnt = cnt + 1 - endwhile -endfunction - -function! s:LocalModelines() - if !g:rails_modelines - return - endif - let lbeg = s:lastmethodline() - let lend = s:endof(lbeg) - if lbeg == 0 || lend == 0 - return - endif - let lines = "\n" - let lnum = lbeg - while lnum < lend && lnum < lbeg + 5 - let lines = lines . getline(lnum) . "\n" - let lnum = lnum + 1 - endwhile - let pat = '\s\+\zs.\{-\}\ze\%(\n\|\s\s\|#{\@!\|%>\|-->\|$\)' - let cnt = 1 - let mat = matchstr(lines,'\C\<rset'.pat) - let matend = matchend(lines,'\C\<rset'.pat) - while mat != "" && cnt < 10 - let mat = s:sub(mat,'\s+$','') - let mat = s:gsub(mat,'\|','\\|') - if mat != '' - silent! exe "Rset <l> ".mat - endif - let mat = matchstr(lines,'\C\<rset'.pat,matend) - let matend = matchend(lines,'\C\<rset'.pat,matend) - let cnt = cnt + 1 - endwhile -endfunction - -" }}}1 -" Detection {{{1 - -function! s:Detect(filename) - let fn = substitute(fnamemodify(a:filename,":p"),'\c^file://','','') - if fn =~ '[\/]config[\/]environment\.rb$' - return s:BufInit(strpart(fn,0,strlen(fn)-22)) - endif - if isdirectory(fn) - let fn = fnamemodify(fn,":s?[\/]$??") - else - let fn = fnamemodify(fn,':s?\(.*\)[\/][^\/]*$?\1?') - endif - let ofn = "" - let nfn = fn - while nfn != ofn && nfn != "" - if exists("s:_".s:escvar(nfn)) - return s:BufInit(nfn) - endif - let ofn = nfn - let nfn = fnamemodify(nfn,':h') - endwhile - let ofn = "" - while fn != ofn - if filereadable(fn . "/config/environment.rb") - return s:BufInit(fn) - endif - let ofn = fn - let fn = fnamemodify(ofn,':s?\(.*\)[\/]\(app\|config\|db\|doc\|lib\|log\|public\|script\|spec\|test\|tmp\|vendor\)\($\|[\/].*$\)?\1?') - endwhile - return 0 -endfunction - -function! s:scrub(collection,item) - " Removes item from a newline separated collection - let col = "\n" . a:collection - let idx = stridx(col,"\n".a:item."\n") - let cnt = 0 - while idx != -1 && cnt < 100 - let col = strpart(col,0,idx).strpart(col,idx+strlen(a:item)+1) - let idx = stridx(col,"\n".a:item."\n") - let cnt = cnt + 1 - endwhile - return strpart(col,1) -endfunction - -function! s:callback(file) - if RailsRoot() != "" - let var = "callback_".s:rv()."_".s:escvar(a:file) - if !exists("s:".var) || exists("b:rails_refresh") - let s:{var} = s:hasfile(a:file) - endif - if s:{var} - if exists(":sandbox") - sandbox source `=RailsRoot().'/'.a:file` - elseif g:rails_modelines - source `=RailsRoot().'/'.a:file` - endif - endif - endif -endfunction - -function! s:BufInit(path) - let cpo_save = &cpo - set cpo&vim - let firsttime = !(exists("b:rails_root") && b:rails_root == a:path) - let b:rails_root = a:path - let s:_{s:rv()} = 1 - " Apparently RailsFileType() can be slow if the underlying file system is - " slow (even though it doesn't really do anything IO related). This caching - " is a temporary hack; if it doesn't cause problems it should probably be - " refactored. - unlet! b:rails_cached_file_type - let b:rails_cached_file_type = RailsFileType() - if g:rails_history_size > 0 - if !exists("g:RAILS_HISTORY") - let g:RAILS_HISTORY = "" - endif - let path = a:path - let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,path) - if has("win32") - let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,s:gsub(path,'\\','/')) - endif - let path = fnamemodify(path,':p:~:h') - let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,path) - if has("win32") - let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,s:gsub(path,'\\','/')) - endif - let g:RAILS_HISTORY = path."\n".g:RAILS_HISTORY - let g:RAILS_HISTORY = s:sub(g:RAILS_HISTORY,'%(.{-}\n){,'.g:rails_history_size.'}\zs.*','') - endif - call s:callback("config/syntax.vim") - if &ft == "mason" - setlocal filetype=eruby - elseif &ft =~ '^\%(conf\|ruby\)\=$' && expand("%:e") =~ '^\%(rjs\|rxml\|builder\|rake\|mab\)$' - setlocal filetype=ruby - elseif &ft =~ '^\%(conf\|ruby\)\=$' && expand("%:t") =~ '^\%(Rake\|Cap\)file$' - setlocal filetype=ruby - elseif &ft =~ '^\%(liquid\)\=$' && expand("%:e") == "liquid" - setlocal filetype=liquid - elseif &ft =~ '^\%(haml\|x\=html\)\=$' && expand("%:e") == "haml" - setlocal filetype=haml - elseif &ft =~ '^\%(sass\|conf\)\=$' && expand("%:e") == "sass" - setlocal filetype=sass - elseif &ft =~ '^\%(dryml\)\=$' && expand("%:e") == "dryml" - setlocal filetype=dryml - elseif (&ft == "" || v:version < 701) && expand("%:e") =~ '^\%(rhtml\|erb\)$' - setlocal filetype=eruby - elseif (&ft == "" || v:version < 700) && expand("%:e") == 'yml' - setlocal filetype=yaml - elseif firsttime - " Activate custom syntax - let &syntax = &syntax - endif - if firsttime - call s:BufInitStatusline() - endif - if expand("%:e") == "log" - setlocal modifiable filetype=railslog - silent! %s/\%(\e\[[0-9;]*m\|\r$\)//g - setlocal readonly nomodifiable noswapfile autoread foldmethod=syntax - nnoremap <buffer> <silent> R :checktime<CR> - nnoremap <buffer> <silent> G :checktime<Bar>$<CR> - nnoremap <buffer> <silent> q :bwipe<CR> - $ - endif - call s:BufSettings() - call s:BufCommands() - call s:BufAbbreviations() - call s:BufDatabase() - " snippetsEmu.vim - if exists('g:loaded_snippet') - silent! runtime! ftplugin/rails_snippets.vim - " filetype snippets need to come last for higher priority - exe "silent! runtime! ftplugin/".&filetype."_snippets.vim" - endif - let t = RailsFileType() - let t = "-".t - let f = '/'.RailsFilePath() - if f =~ '[ !#$%\,]' - let f = '' - endif - runtime! macros/rails.vim - silent doautocmd User Rails - if t != '-' - exe "silent doautocmd User Rails".s:gsub(t,'-','.') - endif - if f != '' - exe "silent doautocmd User Rails".f - endif - call s:callback("config/rails.vim") - call s:BufModelines() - call s:BufMappings() - "unlet! b:rails_cached_file_type - let &cpo = cpo_save - return b:rails_root -endfunction - -function! s:SetBasePath() - let rp = s:gsub(RailsRoot(),'[ ,]','\\&') - let t = RailsFileType() - let oldpath = s:sub(&l:path,'^\.,','') - if stridx(oldpath,rp) == 2 - let oldpath = '' - endif - let &l:path = '.,'.rp.",".rp."/app/controllers,".rp."/app,".rp."/app/models,".rp."/app/helpers,".rp."/config,".rp."/lib,".rp."/vendor,".rp."/vendor/plugins/*/lib,".rp."/test/unit,".rp."/test/functional,".rp."/test/integration,".rp."/app/apis,".rp."/app/services,".rp."/test,"."/vendor/plugins/*/test,".rp."/vendor/rails/*/lib,".rp."/vendor/rails/*/test,".rp."/spec,".rp."/spec/*," - if s:controller() != '' - let &l:path = &l:path . rp . '/app/views/' . s:controller() . ',' . rp . '/app/views,' . rp . '/public,' - endif - if t =~ '^log\>' - let &l:path = &l:path . rp . '/app/views,' - endif - if &l:path =~ '://' - let &l:path = ".," - endif - let &l:path = &l:path . oldpath -endfunction - -function! s:BufSettings() - if !exists('b:rails_root') - return '' - endif - call s:SetBasePath() - let rp = s:gsub(RailsRoot(),'[ ,]','\\&') - let &errorformat=s:efm - setlocal makeprg=rake - if stridx(&tags,rp) == -1 - let &l:tags = &tags . "," . rp . "/tags," . rp . "/.tags" - endif - if has("gui_win32") || has("gui_running") - let code = '*.rb;*.rake;Rakefile' - let templates = '*.'.s:gsub(s:view_types,',',';*.') - let fixtures = '*.yml;*.csv' - let statics = '*.html;*.css;*.js;*.xml;*.xsd;*.sql;.htaccess;README;README_FOR_APP' - let b:browsefilter = "" - \."All Rails Files\t".code.';'.templates.';'.fixtures.';'.statics."\n" - \."Source Code (*.rb, *.rake)\t".code."\n" - \."Templates (*.rhtml, *.rxml, *.rjs)\t".templates."\n" - \."Fixtures (*.yml, *.csv)\t".fixtures."\n" - \."Static Files (*.html, *.css, *.js)\t".statics."\n" - \."All Files (*.*)\t*.*\n" - endif - setlocal includeexpr=RailsIncludeexpr() - let &l:suffixesadd=".rb,.".s:gsub(s:view_types,',',',.').",.css,.js,.yml,.csv,.rake,.sql,.html,.xml" - if &ft =~ '^\%(e\=ruby\|[yh]aml\|javascript\|css\|sass\)$' - setlocal sw=2 sts=2 et - "set include=\\<\\zsAct\\f*::Base\\ze\\>\\\|^\\s*\\(require\\\|load\\)\\s\\+['\"]\\zs\\f\\+\\ze - if exists('+completefunc') - if &completefunc == '' - set completefunc=syntaxcomplete#Complete - endif - endif - endif - if &filetype == "ruby" - let &l:suffixesadd=".rb,.".s:gsub(s:view_types,',',',.').",.yml,.csv,.rake,s.rb" - if expand('%:e') == 'rake' - setlocal define=^\\s*def\\s\\+\\(self\\.\\)\\=\\\|^\\s*\\%(task\\\|file\\)\\s\\+[:'\"] - else - setlocal define=^\\s*def\\s\\+\\(self\\.\\)\\= - endif - " This really belongs in after/ftplugin/ruby.vim but we'll be nice - if exists("g:loaded_surround") && !exists("b:surround_101") - let b:surround_5 = "\r\nend" - let b:surround_69 = "\1expr: \1\rend" - let b:surround_101 = "\r\nend" - endif - elseif &filetype == 'yaml' || expand('%:e') == 'yml' - setlocal define=^\\%(\\h\\k*:\\)\\@= - let &l:suffixesadd=".yml,.csv,.rb,.".s:gsub(s:view_types,',',',.').",.rake,s.rb" - elseif &filetype == "eruby" - let &l:suffixesadd=".".s:gsub(s:view_types,',',',.').",.rb,.css,.js,.html,.yml,.csv" - if exists("g:loaded_allml") - " allml is available on vim.org. - let b:allml_stylesheet_link_tag = "<%= stylesheet_link_tag '\r' %>" - let b:allml_javascript_include_tag = "<%= javascript_include_tag '\r' %>" - let b:allml_doctype_index = 10 - endif - endif - if &filetype == "eruby" || &filetype == "yaml" - " surround.vim - if exists("g:loaded_surround") - " The idea behind the || part here is that one can normally define the - " surrounding to omit the hyphen (since standard ERuby does not use it) - " but have it added in Rails ERuby files. Unfortunately, this makes it - " difficult if you really don't want a hyphen in Rails ERuby files. If - " this is your desire, you will need to accomplish it via a rails.vim - " autocommand. - if !exists("b:surround_45") || b:surround_45 == "<% \r %>" " - - let b:surround_45 = "<% \r -%>" - endif - if !exists("b:surround_61") " = - let b:surround_61 = "<%= \r %>" - endif - if !exists("b:surround_35") " # - let b:surround_35 = "<%# \r %>" - endif - if !exists("b:surround_101") || b:surround_101 == "<% \r %>\n<% end %>" "e - let b:surround_5 = "<% \r -%>\n<% end -%>" - let b:surround_69 = "<% \1expr: \1 -%>\r<% end -%>" - let b:surround_101 = "<% \r -%>\n<% end -%>" - endif - endif - endif -endfunction - -" }}}1 -" Initialization {{{1 - -function! s:InitPlugin() - call s:InitConfig() - "call s:InitStatusline() - if has("autocmd") - - augroup railsPluginDetect - autocmd! - autocmd BufNewFile,BufRead * call s:Detect(expand("<afile>:p")) - autocmd VimEnter * if expand("<amatch>") == "" && !exists("b:rails_root") | call s:Detect(getcwd()) | call s:BufEnter() | endif - autocmd BufEnter * call s:BufEnter() - autocmd BufLeave * call s:BufLeave() - " g:RAILS_HISTORY hasn't been set when s:InitPlugin() is called. - autocmd VimEnter * call s:ProjectMenu() - autocmd BufWritePost */config/database.yml unlet! s:dbext_type_{s:rv()} " Force reload - autocmd BufWritePost */test/test_helper.rb call s:cacheclear("user_asserts") - autocmd BufWritePost */config/routes.rb call s:cacheclear("named_routes") - autocmd FileType railslog call s:RailslogSyntax() - autocmd FileType * if exists("b:rails_root") | call s:BufSettings() | endif - autocmd FileType netrw call s:Detect(expand("<afile>:p")) | call s:BufEnter() - autocmd Syntax ruby,eruby,yaml,haml,javascript,railslog if exists("b:rails_root") | call s:BufSyntax() | endif - silent! autocmd QuickFixCmdPre make* call s:QuickFixCmdPre() - silent! autocmd QuickFixCmdPost make* call s:QuickFixCmdPost() - augroup END - augroup railsPluginTabstop - autocmd! - autocmd BufWritePost,BufReadPost * call s:breaktabs() - autocmd BufWritePre * call s:fixtabs() - augroup END - - endif - let s:view_types = 'rhtml,erb,rxml,builder,rjs,mab,liquid,haml,dryml' - " Current directory - let s:efm='%D(in\ %f),' - " Failure and Error headers, start a multiline message - let s:efm=s:efm - \.'%A\ %\\+%\\d%\\+)\ Failure:,' - \.'%A\ %\\+%\\d%\\+)\ Error:,' - \.'%+A'."'".'%.%#'."'".'\ FAILED,' - " Exclusions - let s:efm=s:efm - \.'%C%.%#(eval)%.%#,' - \.'%C-e:%.%#,' - \.'%C%.%#/lib/gems/%\\d.%\\d/gems/%.%#,' - \.'%C%.%#/lib/ruby/%\\d.%\\d/%.%#,' - \.'%C%.%#/vendor/rails/%.%#,' - " Specific to template errors - let s:efm=s:efm - \.'%C\ %\\+On\ line\ #%l\ of\ %f,' - \.'%CActionView::TemplateError:\ compile\ error,' - " stack backtrace is in brackets. if multiple lines, it starts on a new line. - let s:efm=s:efm - \.'%Ctest_%.%#(%.%#):%#,' - \.'%C%.%#\ [%f:%l]:,' - \.'%C\ \ \ \ [%f:%l:%.%#,' - \.'%C\ \ \ \ %f:%l:%.%#,' - \.'%C\ \ \ \ \ %f:%l:%.%#]:,' - \.'%C\ \ \ \ \ %f:%l:%.%#,' - " Catch all - let s:efm=s:efm - \.'%Z%f:%l:\ %#%m,' - \.'%Z%f:%l:,' - \.'%C%m,' - " Syntax errors in the test itself - let s:efm=s:efm - \.'%.%#.rb:%\\d%\\+:in\ `load'."'".':\ %f:%l:\ syntax\ error\\\, %m,' - \.'%.%#.rb:%\\d%\\+:in\ `load'."'".':\ %f:%l:\ %m,' - " And required files - let s:efm=s:efm - \.'%.%#:in\ `require'."'".':in\ `require'."'".':\ %f:%l:\ syntax\ error\\\, %m,' - \.'%.%#:in\ `require'."'".':in\ `require'."'".':\ %f:%l:\ %m,' - " Exclusions - let s:efm=s:efm - \.'%-G%.%#/lib/gems/%\\d.%\\d/gems/%.%#,' - \.'%-G%.%#/lib/ruby/%\\d.%\\d/%.%#,' - \.'%-G%.%#/vendor/rails/%.%#,' - \.'%-G%.%#%\\d%\\d:%\\d%\\d:%\\d%\\d%.%#,' - " Final catch all for one line errors - let s:efm=s:efm - \.'%-G%\\s%#from\ %.%#,' - \.'%f:%l:\ %#%m,' - " Drop everything else - let s:efm=s:efm - \.'%-G%.%#' - " OLD - let s:efm_old='' - \.'%Z%f:%l:\ syntax\ error\\,\ %m,' - \.'%Z\ %#,' - \.'%Z%p^,' - \.'%CActionView::TemplateError:\ %f:%l:in\ `%.%#'."'".':\ %m,' - \.'%CActionView::TemplateError:\ You\ have\ a\ %m!,' - \.'%CNoMethodError:\ You\ have\ a\ %m!,' - \.'%CActionView::TemplateError:\ %m,' - \.'%CThe\ error\ occured\ while\ %m,' - \.'ActionView::TemplateError\ (%m)\ on\ line\ #%l\ of\ %f:,' - \.'%AActionView::TemplateError\ (compile\ error,' - " from - command! -bar -bang -nargs=* -complete=dir Rails :call s:NewApp(<bang>0,<f-args>) - call s:CreateMenus() - map <SID>xx <SID>xx - let s:sid = s:sub(maparg("<SID>xx"),'xx$','') - unmap <SID>xx - " Apparently, the nesting level within Vim when the Ruby interface is - " initialized determines how much stack space Ruby gets. In previous - " versions of rails.vim, sporadic stack overflows occured when omnicomplete - " was used. This was apparently due to rails.vim having first initialized - " ruby deep in a nested function call. - silent! ruby nil -endfunction - -" }}}1 - -let s:file = expand('<sfile>:p') -let s:revision = ' $Id: rails.vim 239 2008-01-03 15:55:55Z tpope $ ' -let s:revision = s:sub(s:revision,'^ [$]Id:.{-}(<[0-9a-f]+>).*[$] $','\1') -call s:InitPlugin() - -let &cpo = s:cpo_save - -" vim:set sw=2 sts=2: diff --git a/files/.vim/plugin/sqlplus.vim b/files/.vim/plugin/sqlplus.vim deleted file mode 100644 index 4360fb4..0000000 --- a/files/.vim/plugin/sqlplus.vim +++ /dev/null @@ -1,257 +0,0 @@ -" sqlplus.vim -" author: Jamis Buck (jgb3@email.byu.edu) -" version: 1.2.3 -" -" This file contains routines that may be used to execute SQL queries and describe -" tables from within VIM. It depends on SQL*Plus. You must have $ORACLE_HOME -" $ORACLE_SID set in your environment, although you can explicitly set the -" database name to use with the :DB <db-name> command. -" -" In command mode: -" <F8>: execute the SELECT query under your cursor. The query must begin with -" the "select" keyword and end with a ";" -" <Leader><F8>: prompt for an SQL command/query to execute. -" <F9>: treat the identifier under the cursor as a table name, and do a 'describe' -" on it. -" <F10>: prompt for a table to describe. -" <F11>: set the current SQL*Plus username and password -" <Leader>sb: open an empty buffer in a new window to enter SQL commands in -" <Leader>ss: execute the (one-line) query on the current line -" <Leader>se: execute the query under the cursor (as <F8>) -" <Leader>st: describe the table under the cursor (as <F9>) -" <Leader>sc: open the user's common SQL buffer (g:sqlplus_common_buffer) in a -" new window. -" -" :Select <...> -- execute the given Select query. -" :Update <...> -- execute the given Update command. -" :Delete <...> -- execute the given Delete command -" :DB <db-name> -- set the database name to <db-name> -" :SQL <...> -- open a blank SQL buffer in a new window, or if a filename is -" specified, open the given file in a new window. -" -" In visual mode: -" <F8>: execute the selected query -" -" If queries contain bind variables, you will be prompted to give a value for -" each one. if the value is a string, you must explicitly put quotes around it. -" If the query contains an INTO clause, it is removed before executing. -" -" You will be prompted for your user-name and password the first time you access -" one of these functions during a session. After that, your user-id and password -" will be remembered until the session ends. -" -" The results of the query/command are displayed in a separate window. -" -" You can specify the values of the following global variables in your .vimrc -" file, to alter the behavior of this plugin: -" -" g:sqlplus_userid -- the user-id to log in to the database as. If this -" is specified, g:sqlplus_passwd must be given as well, which is the -" password to use. Default: "" -" g:sqlplus_path -- the path the the SQL*Plus executable, including any -" command line options. Default: $ORACLE_HOME . "/bin/sqlplus -s" -" g:sqlplus_common_commands -- any SQL*Plus commands that should be -" executed every time SQL*Plus is invoked. -" Default: "set pagesize 10000\nset wrap off\nset linesize 9999\n" -" g:sqlplus_common_buffer -- the name of a file that will contain -" common SQL queries and expressions, that may be opened via the -" <Leader>sc command. -" g:sqlplus_db -- the name of the database to connect to. This variable -" may also be modified via the :DB command. -" -" ------------------------------------------------------------------------------ -" Thanks to: -" Matt Kunze (kunzem@optimiz.com) for getting this script to work under -" Windows -" ------------------------------------------------------------------------------ - - -" Global variables (may be set in ~/.vimrc) {{{1 -if !exists( "g:sqlplus_userid" ) - let g:sqlplus_userid = "" - let g:sqlplus_passwd = "" -endif -if !exists( "g:sqlplus_path" ) - let g:sqlplus_path = $ORACLE_HOME . "/bin/sqlplus -s " -endif -if !exists( "g:sqlplus_common_commands" ) - let g:sqlplus_common_commands = "set pagesize 10000\nset wrap off\nset linesize 9999\n" -endif -if !exists( "g:sqlplus_common_buffer" ) - let g:sqlplus_common_buffer = "~/.vim_sql" -endif -if !exists( "g:sqlplus_db" ) - let g:sqlplus_db = $ORACLE_SID -endif -"}}} - -function! AE_getSQLPlusUIDandPasswd( force ) "{{{1 - if g:sqlplus_userid == "" || a:force != 0 - if g:sqlplus_userid == "" - if has("win32") - let l:userid = '' - else - let l:userid = substitute( system( "whoami" ), "\n", "", "g" ) - endif - else - let l:userid = g:sqlplus_userid - endif - let g:sqlplus_userid = input( "Please enter your SQL*Plus user-id: ", l:userid ) - let g:sqlplus_passwd = inputsecret( "Please enter your SQL*Plus password: " ) - let g:sqlplus_db = input( "Please enter your database name: ", g:sqlplus_db ) - endif -endfunction "}}} - -function! AE_configureOutputWindow() "{{{1 - set ts=8 buftype=nofile nowrap sidescroll=5 listchars+=precedes:<,extends:> - normal $G - while getline(".") == "" - normal dd - endwhile - normal 1G - let l:newheight = line("$") - if l:newheight < winheight(0) - exe "resize " . l:newheight - endif -endfunction "}}} - -function! AE_configureSqlBuffer() "{{{1 - set syn=sql -endfunction "}}} - -function! AE_describeTable( tableName ) "{{{1 - let l:cmd = "prompt DESCRIBING TABLE '" . a:tableName . "'\ndesc " . a:tableName - call AE_execQuery( l:cmd ) -endfunction "}}} - -function! AE_describeTableUnderCursor() "{{{1 - normal viw"zy - call AE_describeTable( @z ) -endfunction "}}} - -function! AE_describeTablePrompt() "{{{1 - let l:tablename = input( "Please enter the name of the table to describe: " ) - call AE_describeTable( l:tablename ) -endfunction "}}} - -function! AE_execQuery( sql_query ) "{{{1 - call AE_getSQLPlusUIDandPasswd( 0 ) - new - let l:tmpfile = tempname() . ".sql" - let l:oldo = @o - let @o="i" . g:sqlplus_common_commands . a:sql_query - let l:pos = match( @o, ";$" ) - if l:pos < 0 - let @o=@o . ";" - endif - let @o=@o . "\n" - normal @o - let @o=l:oldo - exe "silent write " . l:tmpfile - close - new - let l:cmd = g:sqlplus_path . g:sqlplus_userid . "/" . g:sqlplus_passwd . "@" . g:sqlplus_db - let l:cmd = l:cmd . " @" . l:tmpfile - exe "1,$!" . l:cmd - call AE_configureOutputWindow() - call delete( l:tmpfile ) -endfunction "}}} - -function! AE_promptQuery() "{{{1 - let l:sqlquery = input( "SQL Query: " ) - call AE_execQuery( l:sqlquery ) -endfunction "}}} - -function! AE_resetPassword() "{{{1 - let g:sqlplus_userid = "" - let g:sqlplus_passwd = "" -endfunction "}}} - -function! AE_execLiteralQuery( sql_query ) "{{{1 - let l:query = substitute( a:sql_query, '\c\<INTO\>.*\<FROM\>', 'FROM', 'g' ) - - let l:idx = stridx( l:query, "\n" ) - while l:idx >= 0 - let l:query = strpart( l:query, 0, l:idx ) . " " . strpart( l:query, l:idx+1 ) - let l:idx = stridx( l:query, "\n" ) - endwhile - - let l:var = matchstr( l:query, ':\h\w*' ) - while l:var > "" - let l:var_val = input( "Enter value for " . strpart( l:var, 1 ) . ": " ) - let l:query = substitute( l:query, l:var . '\>', l:var_val, 'g' ) - let l:var = matchstr( l:query, ':\h\w*' ) - endwhile - - call AE_execQuery( l:query ) -endfunction "}}} - -function! AE_execQueryUnderCursor() "{{{1 - exe "silent norm! ?\\c[^.]*\\<\\(select\\|update\\|delete\\)\\>\nv/;\nh\"zy" - noh - call AE_execLiteralQuery( @z ) -endfunction "}}} - -function! AE_execWholeScript() "{{{1 - "exe "silent norm! :%y z" - exe "%y z" - call AE_getSQLPlusUIDandPasswd( 0 ) - new - let l:tmpfile = tempname() . ".sql" - let @z="i" . @z . "\n" - normal @z - exe "silent write " . l:tmpfile - close - new - let l:cmd = g:sqlplus_path . g:sqlplus_userid . "/" . g:sqlplus_passwd . "@" . g:sqlplus_db - let l:cmd = l:cmd . " @" . l:tmpfile - exe "1,$!" . l:cmd - call AE_configureOutputWindow() - call delete( l:tmpfile ) -endfunction "}}} - - -function! AE_openSqlBuffer( fname ) "{{{1 - exe "new " . a:fname - call AE_configureSqlBuffer() -endfunction "}}} - -function! AE_openEmptySqlBuffer() "{{{1 - call AE_openSqlBuffer( "" ) -endfunction "}}} - - -" command-mode mappings {{{1 -map <Leader>sb :call AE_openEmptySqlBuffer()<CR> -map <Leader>ss "zyy:call AE_execLiteralQuery( @z )<CR> -map <Leader>se :call AE_execQueryUnderCursor()<CR> -map <Leader>st :call AE_describeTableUnderCursor()<CR> -exe "map <Leader>sc :call AE_openSqlBuffer( \"" . g:sqlplus_common_buffer . "\" )<CR>" - -map <F7> :call AE_execWholeScript()<CR> -map <F8> :call AE_execQueryUnderCursor()<CR> -map <Leader><F8> :call AE_promptQuery()<CR> -map <F9> :call AE_describeTableUnderCursor()<CR> -map <F10> :call AE_describeTablePrompt()<CR> -map <F11> :call AE_getSQLPlusUIDandPasswd(1)<CR> -"}}} - -" visual mode mappings {{{1 -vmap <F8> "zy:call AE_execLiteralQuery( @z )<CR> -"}}} - -" commands {{{1 -command! -nargs=+ Select :call AE_execQuery( "select <a>" ) -command! -nargs=+ Update :call AE_execQuery( "update <a>" ) -command! -nargs=+ Delete :call AE_execQuery( "delete <a>" ) -command! -nargs=1 DB :let g:sqlplus_db="<args>" -command! -nargs=? SQL :call AE_openSqlBuffer( "<args>" ) - -:menu Oracle.Execute\ whole\ script<Tab>F7 :call AE_execWholeScript()<CR> -:menu Oracle.Execute\ query\ under\ cursor<Tab>F8 :call AE_execQueryUnderCursor()<CR> -:menu Oracle.Prompt\ for\ query<Tab>\\F8 :call AE_promptQuery()<CR> -:menu Oracle.Describe\ table\ under\ cursor<Tab>F09 :call AE_describeTableUnderCursor()<CR> -:menu Oracle.Prompt\ for\ table\ to\ describe<Tab>F10 :call AE_describeTablePrompt()<CR> -:menu Oracle.Change\ connect\ information<Tab>F11 :call AE_getSQLPlusUIDandPasswd(1)<CR> - -"}}} diff --git a/files/.vim/syntax/asciidoc.vim b/files/.vim/syntax/asciidoc.vim deleted file mode 100644 index a102e5a..0000000 --- a/files/.vim/syntax/asciidoc.vim +++ /dev/null @@ -1,166 +0,0 @@ -" Vim syntax file -" Language: AsciiDoc -" Author: Stuart Rackham <srackham@gmail.com> (inspired by Felix -" Obenhuber's original asciidoc.vim script). -" URL: http://www.methods.co.nz/asciidoc/ -" Licence: GPL (http://www.gnu.org) -" Remarks: Vim 6 or greater -" Limitations: See 'Appendix E: Vim Syntax Highlighter' in the AsciiDoc 'User -" Guide'. - -if exists("b:current_syntax") - finish -endif - -syn clear -syn sync fromstart -syn sync linebreaks=1 - -" Run :help syn-priority to review syntax matching priority. -syn keyword asciidocToDo TODO FIXME XXX ZZZ -syn match asciidocBackslash /\\/ -syn region asciidocIdMarker start=/^\$Id:\s/ end=/\s\$$/ -syn match asciidocCallout /\\\@<!<\d\{1,2}>/ -syn match asciidocListBlockDelimiter /^--$/ -syn match asciidocLineBreak /[ \t]+$/ -syn match asciidocRuler /^'\{3,}$/ -syn match asciidocPagebreak /^<\{3,}$/ -syn match asciidocEntityRef /\\\@<!&[#a-zA-Z]\S\{-};/ -" The tricky part is not triggering on indented list items that are also -" preceeded by blank line, handles only bulleted items (see 'Limitations' above -" for workarounds). -syn region asciidocLiteralParagraph start=/^\n[ \t]\+\(\([^-*. \t] \)\|\(\S\S\)\)/ end=/\(^+\?\s*$\)\@=/ -syn match asciidocURL /\\\@<!\<\(http\|https\|ftp\|file\|irc\):\/\/[^| \t]*\(\w\|\/\)/ -syn match asciidocEmail /\\\@<!\(\<\|<\)\w\(\w\|[.-]\)*@\(\w\|[.-]\)*\w>\?[0-9A-Za-z_]\@!/ -syn match asciidocAttributeRef /\\\@<!{\w\(\w\|-\)*\([=!@#$%?:].*\)\?}/ -syn match asciidocAdmonition /^\u\{3,15}:\(\s\+.*\)\@=/ - -" As a damage control measure quoted patterns always terminate at a blank -" line (see 'Limitations' above). -syn match asciidocQuotedSubscript /\\\@<!\~\S\_.\{-}\(\~\|\n\s*\n\)/ -syn match asciidocQuotedSuperscript /\\\@<!\^\S\_.\{-}\(\^\|\n\s*\n\)/ -syn match asciidocQuotedMonospaced /\(^\|[| \t([.,=\]]\)\@<=+\([ )\n]\)\@!\_.\{-}\S\(+\([| \t)[\],.?!;:=]\|$\)\@=\|\n\s*\n\)/ -syn match asciidocQuotedMonospaced2 /\(^\|[| \t([.,=]\)\@<=`\([ )\n]\)\@!\_.\{-}\S\(`\([| \t)[\],.?!;:=]\|$\)\@=\|\n\s*\n\)/ -syn match asciidocQuotedUnconstrainedMonospaced /\\\@<!++\S\_.\{-}\(++\|\n\s*\n\)/ -syn match asciidocQuotedEmphasized /\(^\|[| \t([.,=\]]\)\@<=_\([ )\n]\)\@!\_.\{-}\S\(_\([| \t)[\],.?!;:=]\|$\)\@=\|\n\s*\n\)/ -syn match asciidocQuotedEmphasized2 /\(^\|[| \t([.,=\]]\)\@<='\([ )\n]\)\@!\_.\{-}\S\('\([| \t)[\],.?!;:=]\|$\)\@=\|\n\s*\n\)/ -syn match asciidocQuotedUnconstrainedEmphasized /\\\@<!__\S\_.\{-}\(__\|\n\s*\n\)/ -syn match asciidocQuotedBold /\(^\|[| \t([.,=\]]\)\@<=\*\([ )\n]\)\@!\_.\{-}\S\(\*\([| \t)[\],.?!;:=]\|$\)\@=\|\n\s*\n\)/ -syn match asciidocQuotedUnconstrainedBold /\\\@<!\*\*\S\_.\{-}\(\*\*\|\n\s*\n\)/ -"syn match asciidocQuotedSingleQuoted /\(^\|[| \t([.,=]\)\@<=`\([ )\n]\)\@!\_.\{-}\S\('\([| \t)[\],.?!;:=]\|$\)\@=\|\n\s*\n\)/ -" Don't allow ` in single quoted (a kludge to stop confusion with `monospaced`). -syn match asciidocQuotedSingleQuoted /\(^\|[| \t([.,=]\)\@<=`\([ )\n]\)\@!\([^`]\|\n\)\{-}[^`\s]\('\([| \t)[\],.?!;:=]\|$\)\@=\|\n\s*\n\)/ -syn match asciidocQuotedDoubleQuoted /\(^\|[| \t([.,=]\)\@<=``\([ )\n]\)\@!\_.\{-}\S\(''\([| \t)[\],.?!;:=]\|$\)\@=\|\n\s*\n\)/ - -syn match asciidocDoubleDollarPassthrough /\\\@<!\(^\|[^0-9a-zA-Z$]\)\@<=\$\$..\{-}\(\$\$\([^0-9a-zA-Z$]\|$\)\@=\|^$\)/ -syn match asciidocTriplePlusPassthrough /\\\@<!\(^\|[^0-9a-zA-Z$]\)\@<=+++..\{-}\(+++\([^0-9a-zA-Z$]\|$\)\@=\|^$\)/ - -syn match asciidocListBullet /^\s*\zs\(-\|\*\{1,5}\)\ze\s/ -syn match asciidocListNumber /^\s*\zs\(\(\d\+\.\)\|\.\{1,5}\|\(\a\.\)\|\([ivxIVX]\+)\)\)\ze\s\+/ - -syn region asciidocTable_OLD start=/^\([`.']\d*[-~_]*\)\+[-~_]\+\d*$/ end=/^$/ -syn match asciidocBlockTitle /^\.[^. \t].*[^-~_]$/ contains=asciidocQuoted.*,asciidocAttributeRef -syn match asciidocOneLineTitle /^=\{1,5}\s\+\S.*$/ contains=asciidocQuoted.*,asciidocAttributeRef - -syn match asciidocTitleUnderline /[-=~^+]\{2,}$/ transparent contained contains=NONE -syn match asciidocTwoLineTitle /^[^. +/].*[^.:]\n[-=~^+]\{2,}$/ contains=asciidocQuoted.*,asciidocAttributeRef,asciidocTitleUnderline - -syn match asciidocAttributeList /^\[[^[ \t].*\]$/ -syn match asciidocQuoteBlockDelimiter /^_\{4,}$/ -syn match asciidocExampleBlockDelimiter /^=\{4,}$/ -syn match asciidocSidebarDelimiter /^*\{4,}$/ - -"See http://vimdoc.sourceforge.net/htmldoc/usr_44.html for excluding region -"contents from highlighting. -syn match asciidocTablePrefix /\(\S\@<!\(\([0-9.]\+\)\([*+]\)\)\?\([<\^>.]\{,3}\)\?\([a-z]\)\?\)\?|/ containedin=asciidocTableBlock contained -syn region asciidocTableBlock matchgroup=asciidocTableDelimiter start=/^|=\{3,}$/ end=/^|=\{3,}$/ keepend contains=ALL -syn match asciidocTablePrefix /\(\S\@<!\(\([0-9.]\+\)\([*+]\)\)\?\([<\^>.]\{,3}\)\?\([a-z]\)\?\)\?!/ containedin=asciidocTableBlock contained -syn region asciidocTableBlock2 matchgroup=asciidocTableDelimiter2 start=/^!=\{3,}$/ end=/^!=\{3,}$/ keepend contains=ALL - -syn match asciidocListContinuation /^+$/ -syn region asciidocLiteralBlock start=/^\.\{4,}$/ end=/^\.\{4,}$/ contains=asciidocCallout keepend -syn region asciidocOpenBlock start=/^-\{4,}$/ end=/^-\{4,}$/ contains=asciidocCallout keepend -syn region asciidocCommentBlock start="^/\{4,}$" end="^/\{4,}$" contains=asciidocToDo -syn region asciidocPassthroughBlock start="^+\{4,}$" end="^+\{4,}$" -" Allowing leading \w characters in the filter delimiter is to accomodate -" the pre version 8.2.7 syntax and may be removed in future releases. -syn region asciidocFilterBlock start=/^\w*\~\{4,}$/ end=/^\w*\~\{4,}$/ - -syn region asciidocMacroAttributes matchgroup=asciidocRefMacro start=/\\\@<!<<"\{-}\w\(\w\|-\)*"\?,\?/ end=/\(>>\)\|^$/ contains=asciidocQuoted.* keepend -syn region asciidocMacroAttributes matchgroup=asciidocAnchorMacro start=/\\\@<!\[\{2}\(\w\|-\)\+,\?/ end=/\]\{2}/ keepend -syn region asciidocMacroAttributes matchgroup=asciidocAnchorMacro start=/\\\@<!\[\{3}\(\w\|-\)\+/ end=/\]\{3}/ keepend -syn region asciidocMacroAttributes matchgroup=asciidocMacro start=/[\\0-9a-zA-Z]\@<!\w\(\w\|-\)*:\S\{-}\[/ skip=/\\\]/ end=/\]\|^$/ contains=asciidocQuoted.* keepend -syn region asciidocMacroAttributes matchgroup=asciidocIndexTerm start=/\\\@<!(\{2,3}/ end=/)\{2,3}/ contains=asciidocQuoted.* keepend -syn region asciidocMacroAttributes matchgroup=asciidocAttributeMacro start=/\({\(\w\|-\)\+}\)\@<=\[/ skip=/\\\]/ end=/\]/ keepend - -syn match asciidocCommentLine "^//\([^/].*\|\)$" contains=asciidocToDo - -syn region asciidocVLabel start=/^\s*/ end=/\(::\|;;\)$/ oneline contains=asciidocQuoted.*,asciidocMacroAttributes keepend -syn region asciidocHLabel start=/^\s*/ end=/\(::\|;;\)\(\s\+\|\\$\)/ oneline contains=asciidocQuoted.*,asciidocMacroAttributes keepend - -syn region asciidocAttributeEntry start=/^:\w/ end=/:\(\s\|$\)/ oneline - -highlight link asciidocMacroAttributes Label -highlight link asciidocIdMarker Special -highlight link asciidocDoubleDollarPassthrough Special -highlight link asciidocTriplePlusPassthrough Special -highlight link asciidocQuotedSubscript Type -highlight link asciidocQuotedSuperscript Type -highlight link asciidocOneLineTitle Title -highlight link asciidocTwoLineTitle Title -highlight link asciidocBlockTitle Title -highlight link asciidocRefMacro Macro -highlight link asciidocIndexTerm Macro -highlight link asciidocMacro Macro -highlight link asciidocAttributeMacro Macro -highlight link asciidocAnchorMacro Macro -highlight link asciidocEmail Macro -highlight link asciidocListBullet Label -highlight link asciidocListNumber Label -highlight link asciidocVLabel Label -highlight link asciidocHLabel Label -highlight link asciidocTable_OLD Type -highlight link asciidocTableDelimiter Label -highlight link asciidocTableBlock NONE -highlight link asciidocTablePrefix Label -highlight link asciidocTableDelimiter2 Label -highlight link asciidocTableBlock2 NONE -highlight link asciidocTablePrefix2 Label -highlight link asciidocListBlockDelimiter Label -highlight link asciidocListContinuation Label -highlight link asciidocLiteralParagraph Identifier -highlight link asciidocQuoteBlockDelimiter Type -highlight link asciidocExampleBlockDelimiter Type -highlight link asciidocSidebarDelimiter Type -highlight link asciidocLiteralBlock Identifier -highlight link asciidocOpenBlock Identifier -highlight link asciidocPassthroughBlock Identifier -highlight link asciidocCommentBlock Comment -highlight link asciidocFilterBlock Type -highlight link asciidocQuotedBold Special -highlight link asciidocQuotedUnconstrainedBold Special -highlight link asciidocQuotedEmphasized Type -highlight link asciidocQuotedEmphasized2 Type -highlight link asciidocQuotedUnconstrainedEmphasized Type -highlight link asciidocQuotedMonospaced Identifier -highlight link asciidocQuotedMonospaced2 Identifier -highlight link asciidocQuotedUnconstrainedMonospaced Identifier -highlight link asciidocQuotedSingleQuoted Label -highlight link asciidocQuotedDoubleQuoted Label -highlight link asciidocToDo Todo -highlight link asciidocCommentLine Comment -highlight link asciidocAdmonition Special -highlight link asciidocAttributeRef Special -highlight link asciidocAttributeList Special -highlight link asciidocAttributeEntry Special -highlight link asciidocBackslash Special -highlight link asciidocEntityRef Special -highlight link asciidocCallout Label -highlight link asciidocLineBreak Special -highlight link asciidocRuler Type -highlight link asciidocPagebreak Type -highlight link asciidocURL Macro - -let b:current_syntax = "asciidoc" - -" vim: wrap et sw=2 sts=2: diff --git a/files/.vim/syntax/rfc.vim b/files/.vim/syntax/rfc.vim deleted file mode 100644 index faa1466..0000000 --- a/files/.vim/syntax/rfc.vim +++ /dev/null @@ -1,30 +0,0 @@ -" Vim syntax file -" Filetype: RFC -" Author: lilydjwg <lilydjwg@gmail.con> -" Last Change: 2010年1月16日 - -syntax clear -syntax case match - -syn match rfcTitle /^\v(\n)@<!\S.*$/ -syn match rfcTheTitle /^\v\s{7,40}\S.*$/ -syn match rfcRFCTitle /^\v(\n)@<=RFC.*$/ -syn match rfcRFC /.\@<=RFC\s\+[0-9]\+/ -syn match rfcNumber /\[\d\+\]/ -syn match rfcComment /^\S.*\ze\n/ -syn match rfcDots /\v\.+\ze\d+$/ contained -" 允许换一次行;如果允许无限换行,会将后面的标题也高亮 -syn match rfcContents /^\v\s*\d.*(\n.*)?(\s|\.)\d+$/ contains=rfcDots -syn keyword rfcNote NOTE note: Note: NOTE: Notes Notes: MUST NOT - -hi link rfcTitle Title -hi link rfcTheTitle Type -hi link rfcRFCTitle PreProc -hi link rfcNote Todo -hi link rfcRFC Number -hi link rfcComment Comment -hi link rfcNumber Number -hi link rfcDots Comment -hi link rfcContents Tag - -let b:current_syntax = "rfc" diff --git a/files/.vim/syntax/scala.vim b/files/.vim/syntax/scala.vim deleted file mode 100644 index 7f7d9e2..0000000 --- a/files/.vim/syntax/scala.vim +++ /dev/null @@ -1,87 +0,0 @@ -" Vim syntax file -" Language: Scala -" Version: 0.1 -" Maintainer: Raphael Haberer-Proust <raphael.haberer-proust at epfl.ch> -" URL: http://diwww.epfl.ch/~haberer/syntax/scala.html -" Last Change: 2004 April 18 -" Disclaimer: It's an absolut basic, very simple and by far not finished -" syntax file! It only recognizes basic keywords and constructs like comments -" any help is welcome - -" Remove any old syntax stuff -syn clear - -" syntax highlighting for words that are not identifiers: -" int unit double String Array byte short char long float -syn keyword scalaExternal import package -syn keyword scalaConditional if then else -syn keyword scalaRepeat while for do -syn keyword scalaType boolean int double byte short char long float -syn keyword scalaType unit -syn keyword scalaType val with type var yield - -syn keyword scalaStatement return -syn keyword scalaBoolean true false -syn keyword scalaConstant null -syn keyword scalaTypedef this super -syn keyword scalaLangClass String Array -syn keyword scalaScopeDecl private protected override -syn keyword scalaStorageClass abstract final sealed -syn keyword scalaExceptions throw try catch finally -syn keyword scalaClassDecl extends -" TODO differentiate the keyword class from MyClass.class -> use a match here -syn keyword scalaTypedef class -syn keyword scalaTypedef case -syn keyword scalaTypedef trait - -syn match scalaTypedef "\s*\<object\>" - -syn keyword scalaOperator new - -" same number definition as in java.vim -syn match scalaNumber "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>" -syn match scalaNumber "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\=" -syn match scalaNumber "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>" -syn match scalaNumber "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>" - -syn region scalaString start=+"+ end=+"+ - -" Functions -" def [name] [(prototype)] { -" -syn match scalaFunction "\s*\<def\>" - -" Comments -syn region scalaComment start="/\*" end="\*/" -syn match scalaLineComment "//.*" - - -if !exists("did_scala_syntax_inits") - let did_scala_syntax_inits = 1 - - " The default methods for highlighting. Can be overridden later - hi link scalaExternal Include - hi link scalaStatement Statement - hi link scalaConditional Conditional - hi link scalaRepeat Repeat - hi link scalaType Type - hi link scalaTypedef Typedef - hi link scalaBoolean Boolean - hi link scalaFunction Function - hi link scalaLangClass Constant - hi link scalaConstant Constant - hi link scalaScopeDecl scalaStorageClass - hi link scalaClassDecl scalaStorageClass - hi link scalaStorageClass StorageClass - hi link scalaExceptions Exception - hi link scalaOperator Operator - hi link scalaNumber Number - hi link scalaString String - hi link scalaComment Comment - hi link scalaLineComment Comment -endif - -let b:current_syntax = "scala" - -" if you want to override default methods for highlighting -"hi Conditional term=bold ctermfg=Cyan guifg=#80a0ff diff --git a/files/.zsh/rc/S50_functions b/files/.zsh/rc/S50_functions new file mode 100644 index 0000000..731c98f --- /dev/null +++ b/files/.zsh/rc/S50_functions @@ -0,0 +1,5 @@ +mcd() { + mkdir -p "$1" && cd "$1" +} + +# vim: ft=zsh : |
