From a909de07c5f982968cb8cd0f2101ac052f4a0034 Mon Sep 17 00:00:00 2001 From: Anton Bobov Date: Thu, 3 Oct 2013 09:48:51 +0600 Subject: Vim plugins cleaning up. --- files/.vim/after/syntax/help.vim | 24 - files/.vim/autoload/Reflection.java | 670 ---- files/.vim/autoload/java_parser.vim | 3500 ------------------ files/.vim/autoload/javacomplete.vim | 2918 --------------- files/.vim/bundle/vim-yaml | 1 + files/.vim/bundle/xml.vim | 1 + files/.vim/doc/javacomplete.txt | 558 --- files/.vim/doc/lua51refvim.txt | 5617 ----------------------------- files/.vim/doc/rails.txt | 1131 ------ files/.vim/doc/tags | 896 ----- files/.vim/ftdetect/asciidoc_filetype.vim | 53 - files/.vim/ftplugin/dockbk.vim | 1 - files/.vim/ftplugin/html.vim | 1854 ---------- files/.vim/ftplugin/htmldjango.vim | 1 - files/.vim/ftplugin/rfc.vim | 21 - files/.vim/ftplugin/xhtml.vim | 1854 ---------- files/.vim/ftplugin/xml.vim | 1854 ---------- files/.vim/ftplugin/xsl.vim | 1 - files/.vim/ftplugin/yaml.vim | 32 - files/.vim/plugin/luarefvim.vim | 30 - files/.vim/plugin/rails.vim | 4666 ------------------------ files/.vim/plugin/sqlplus.vim | 257 -- files/.vim/syntax/asciidoc.vim | 166 - files/.vim/syntax/rfc.vim | 30 - files/.vim/syntax/scala.vim | 87 - 25 files changed, 2 insertions(+), 26221 deletions(-) delete mode 100644 files/.vim/after/syntax/help.vim delete mode 100644 files/.vim/autoload/Reflection.java delete mode 100644 files/.vim/autoload/java_parser.vim delete mode 100644 files/.vim/autoload/javacomplete.vim create mode 160000 files/.vim/bundle/vim-yaml create mode 160000 files/.vim/bundle/xml.vim delete mode 100644 files/.vim/doc/javacomplete.txt delete mode 100644 files/.vim/doc/lua51refvim.txt delete mode 100644 files/.vim/doc/rails.txt delete mode 100644 files/.vim/doc/tags delete mode 100644 files/.vim/ftdetect/asciidoc_filetype.vim delete mode 120000 files/.vim/ftplugin/dockbk.vim delete mode 100644 files/.vim/ftplugin/html.vim delete mode 100644 files/.vim/ftplugin/htmldjango.vim delete mode 100644 files/.vim/ftplugin/rfc.vim delete mode 100644 files/.vim/ftplugin/xhtml.vim delete mode 100644 files/.vim/ftplugin/xml.vim delete mode 120000 files/.vim/ftplugin/xsl.vim delete mode 100755 files/.vim/ftplugin/yaml.vim delete mode 100644 files/.vim/plugin/luarefvim.vim delete mode 100644 files/.vim/plugin/rails.vim delete mode 100644 files/.vim/plugin/sqlplus.vim delete mode 100644 files/.vim/syntax/asciidoc.vim delete mode 100644 files/.vim/syntax/rfc.vim delete mode 100644 files/.vim/syntax/scala.vim (limited to 'files/.vim') 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 -" 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 - * 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 -" 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 '' - 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 '' - 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 '' - 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 '' - 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 = '' - 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 .= '' - 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 -" 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 =~# '\ 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\' || 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), '\= 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, '\= 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('\' || str =~ '' - 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('\', '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]\+\)\?\(\\|\\)[ \t\n\r]\+HelloWorld[^a-zA-Z0-9_$]', 'W') -" echo substitute(getline('.'), '.*\(\(public\|protected\|private\)[ \t\n\r]\+\)\?\(\(static\)[ \t\n\r]\+\)\?\(\\|\\)\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('\(\\|\\)[ \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, '.*\(\\|\\)\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('\(\\|\\|\\)[ \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, '.*\(\\|\\)\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('') - - 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('') - 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('') - if cword == a:name - return 0 - endif - if getline('.')[col('.')-1] == '{' - normal % - endif - endwhile - endif - return 1 -endfu -"nmap :call Searchdecl(expand('')) - -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\' || 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 =~ '\' - 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 =~ '\' - 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, '\ 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 index 0000000..4b37a4f --- /dev/null +++ b/files/.vim/bundle/vim-yaml @@ -0,0 +1 @@ +Subproject commit 4b37a4fa8a91c44b517e3fb6de3ebba5e02ec9fb diff --git a/files/.vim/bundle/xml.vim b/files/.vim/bundle/xml.vim new file mode 160000 index 0000000..b878689 --- /dev/null +++ b/files/.vim/bundle/xml.vim @@ -0,0 +1 @@ +Subproject commit b878689de5f2ccf2b9c2593165dc810d53cbe4ee 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 - :inoremap - -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 - - - 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 # to () -> - -$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 # to () -> -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 @| lr | reference for word under cursor | - |@ visual @| lr | reference for visually selected text | - |$ any $| lc | manual's table of contents | - +----------+--------------+----------------------------------------+ - -Since by default 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 |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 -< The following appears to work on Windows: > - :command -bar -nargs=1 OpenURL :!start cmd /cstart /b -< On Debian compatible distributions, the following is - the preferred method: > - :command -bar -nargs=1 OpenURL :!sensible-browser -< 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 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
- 2

<%= @post.title %>

- 3

<%= @post.body %>

- 4
- -And you issue this command: > - - :2,3Rextract post - -Your file will change to this: > - - 1
- 2 <%= render :partial => 'post' %> - 3
- -And app/views/blog/_post.rhtml will now contain: > - - 1

<%= post.title %>

- 2

<%= post.body %>

- -As a special case, if the file had looked like this: > - - 1 <% for object in @posts -%> - 2

<%= object.title %>

- 3

<%= object.body %>

- 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 :Rproject!|silent w -< 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 ~ -= <%= ^ %> -- <% ^ -%> -# <%# ^ %> - <% ^ -%>\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 as o anyways. -> - imap o -< -One can also use the 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 (see |i_CTRL-]|) or a (if 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 render :partial => -Rabbrev vs( validates_size_of vs( validates_size_of( -Rabbrev pa[ params pa[:id] params[:id] -Rabbrev pa[ params pa params -Rabbrev pa[ params pa.inspect params.inspect -Rabbrev AR:: ActionRecord AR::Base ActiveRecord::Base -Rabbrev :a :action\ =>\ render :a 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 "". 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<Vim> -< - *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 :Rake -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 wsn wsdl_service_name - autocmd User Rails.model.arb* iabbr vfo validates_format_of - autocmd User Rails.view.rhtml* imap <%= %>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 . 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 -" 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 -" Maintainer: Rene de Zwart -" 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 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= - -" XML: thanks to Johannes Zellner and Akbar Ibrahim -" - case sensitive -" - don't match empty tags -" - match style comments (but not --, --) -" - match inlined dtd's. This is not perfect, as it -" gets confused for example by -" "> -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 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, '') - 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 ."\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 '' 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 = ' 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('','W' ) >=0 - exe "normal! f>a".l:sentinel."\" - call cursor(b:begcomline,b:begcomcol) - exe "normal! \"xd/".l:sentinel."/e-".l:len."\" - exe "normal! ".l:len."x" - retu 1 - en - el - if search(' - " - " cursor comes here - " - normal! h - if s:TagUnderCursor() - if b:firstWasEndTag == 0 - exe "normal! 2f>s\\Ox\>>$x" - start! - retu - en - en - elseif s:TagUnderCursor() - if b:firstWasEndTag == 0 - exe "normal! />\" - 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/\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\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\\\" - let l:eline = line('.') - normal! gvov - if col('.') == col("'>") && line('.') == line("'>") - normal! gvov - en - let l:sline = line(".") + 2 - exe "normal! i\<".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \ .">\\" - 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\gvov" - if col('.') == col("'>") && line('.') == line("'>") - normal! gvov - en - exe "normal! i<".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \ .">\" - 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\;x\0cfx".a:close."\\" - normal! gvov - exe "normal! i\;x\0cfx".a:open."\\" -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\\mh" - normal! gvov - exe "normal! i\\\\'h/listitem>/e+1\" -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 . "\" - exe b:gotoOpenTag - exe 'normal! lcw' . l:newname . "\" - 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\" - 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/>\".l:newname."\" - exe b:gotoOpenTag - exe "normal! lc/>/\".l:newname. - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \."\" - en - en -endf -en - -" Delete() Removes a tag 'blah' --> '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\" - 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! />\a".l:sentinel."\" - exe b:gotoOpenTag - exe "normal! \"xd/".l:sentinel."/e-".l:len."\" - 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(' 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.">\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.">\" - 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\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! />\a\\" - let l:To = line('.') - exe b:gotoOpenTag - exe 'normal! i<' . l:newname . - \ (strlen(l:newatt) ? ' '.l:newatt : '' ) - \.">\\" - 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! />\a\-->\" - let l:To = line('.') - exe b:gotoOpenTag - exe "normal! i') - vmenu