]> Dogcows Code - chaz/vimcoder/commitdiff
new build system; fixed white space problems
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Thu, 18 Nov 2010 03:05:56 +0000 (20:05 -0700)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Thu, 18 Nov 2010 03:05:56 +0000 (20:05 -0700)
Makefile [new file with mode: 0644]
make.sh [new file with mode: 0755]
src/com/dogcows/Editor.java
src/com/dogcows/Util.java
src/com/dogcows/VimCoder.java

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e9f4f77
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,44 @@
+
+project                := VimCoder
+version                := 0.3
+
+mainclass      = bin/com/dogcows/VimCoder.class
+library                = lib/ContestApplet.jar
+jarfile                = $(project)-$(version).jar
+
+JAVAC          := javac
+JAVACFLAGS     := -d bin -sourcepath src -classpath bin:$(library)
+
+
+.PHONY: all clean distclean dist fetch jar
+
+all: $(library) $(mainclass)
+
+clean:
+       rm -rf bin build
+
+distclean: clean
+       rm -rf lib
+
+dist:
+       git archive HEAD --prefix=vimcoder-$(version)/ | bzip2 >vimcoder-$(version).tar.bz2
+
+fetch: $(library)
+
+jar: all $(jarfile)
+
+
+$(library):
+       sh make.sh fetch $@
+
+bin/com/dogcows/%.class: src/com/dogcows/%.java
+       mkdir -p bin/com/dogcows/resources &&\
+$(JAVAC) $(JAVACFLAGS) $< &&\
+cp -R src/com/dogcows/resources bin/com/dogcows/
+
+$(jarfile): $(mainclass)
+       sh make.sh jar $@
+
+
+$(mainclass): src/com/dogcows/Util.java src/com/dogcows/Editor.java
+
diff --git a/make.sh b/make.sh
new file mode 100755 (executable)
index 0000000..0bb3d82
--- /dev/null
+++ b/make.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+action=$1
+shift
+
+case "$action"
+in
+
+       fetch)
+               echo "Fetching dependencies..."
+               mkdir -p lib
+               curl -o $1 http://www.topcoder.com/contest/classes/ContestApplet.jar
+               ;;
+
+       jar)
+               echo "Packaging jar file..."
+               rm -rf build
+               mkdir -p build/META-INF
+               printf "Manifest-Version: 1.0\n\n" >build/META-INF/MANIFEST.MF
+               cp -R bin/com COPYING README build/
+               cd build
+               files=$(find com -type f | sort)
+               zip $1 META-INF/MANIFEST.MF README COPYING $files
+               cd ..
+               mv build/$1 .
+               rm -rf build
+               echo "Done."
+               ;;
+esac
+
index 15dad35a8f5712c70c21017377e30e73dbea181f..2f2896248113e30da45d75d3d68995bc04141389 100644 (file)
@@ -24,313 +24,320 @@ import com.topcoder.shared.problem.TestCase;
  */
 public class Editor
 {
-    /**
-     * The problem ID number.
-     */
-    private String  id;
-    
-    /**
-     * The name of the class.
-     */
-    private String  name;
-    
-    /**
-     * The path of the current source file.
-     */
-    private File    sourceFile;
-    
-    /**
-     * The path of the problem directory.
-     */
-    private File    directory;
-    
-    
-    /**
-     * Map languages names to file extensions.
-     */
-    private static final Map<String,String> languageExtension = new HashMap<String,String>();
-    static
-    {
-        languageExtension.put("Java",   "java");
-        languageExtension.put("C++",    "cc");
-        languageExtension.put("C#",     "cs");
-        languageExtension.put("VB",     "vb");
-        languageExtension.put("Python", "py");
-    }
-
-    
-    /**
-     * Construct an editor with the problem objects given us by the Arena.
-     * @param component A container for the particulars of the problem.
-     * @param language The currently selected language.
-     * @param renderer A helper object to help format the problem statement.
-     * @throws Exception If the editor could not set itself up.
-     */
-    public Editor(ProblemComponentModel component,
-                  Language language,
-                  Renderer renderer) throws Exception
-    {
-        this.id = String.valueOf(component.getProblem().getProblemID());
-        this.name = component.getClassName();
-        
-        // Make sure the top-level vimcoder directory exists.
-        File topDir = VimCoder.getStorageDirectory();
-        if (!topDir.isDirectory())
-        {
-            if (!topDir.mkdirs()) throw new IOException(topDir.getPath());
-        }
-        
-        // Make sure the problem directory exists.
-        this.directory = new File(topDir, id);
-        if (!directory.isDirectory())
-        {
-            if (!directory.mkdirs()) throw new IOException(directory.getPath());
-        }
-        
-        String lang = language.getName();
-        String ext  = languageExtension.get(lang);
-        
-        // Set up the terms used for the template expansion.
-        HashMap<String,String> terms = new HashMap<String,String>();
-        terms.put("RETURNTYPE",component.getReturnType().getDescriptor(language).replaceAll("\\s+", ""));
-        terms.put("CLASSNAME",  name);
-        terms.put("METHODNAME", component.getMethodName());
-        terms.put("METHODPARAMS", getMethodParams(component.getParamTypes(),
-                                                  component.getParamNames(),
-                                                  language));
-        terms.put("METHODPARAMNAMES", Util.join(component.getParamNames(), ", "));
-        terms.put("METHODPARAMSTREAMIN", Util.join(component.getParamNames(), " >> "));
-        terms.put("METHODPARAMSTREAMOUT", Util.join(component.getParamNames(), " << "));
-        terms.put("METHODPARAMDECLARES", getMethodParamDeclarations(component.getParamTypes(),
-                                                                    component.getParamNames(),
-                                                                    language));
-        
-        // Write the problem statement as an HTML file in the problem directory.
-        File problemFile = new File(directory, "Problem.html");
-        if (!problemFile.canRead())
-        {
-            FileWriter writer = new FileWriter(problemFile);
-            try
-            {
-                writer.write(renderer.toHTML(language));
-            }
-            finally
-            {
-                writer.close();
-            }
-        }
-        
-        // Expand the template for the main class and write it to the current
-        // source file.
-        sourceFile = new File(directory, name + "." + ext);
-        if (!sourceFile.canRead())
-        {
-            String text = Util.expandTemplate(readTemplate(lang + "Template"),
-                                              terms);
-            FileWriter writer = new FileWriter(sourceFile);
-            writer.write(text);
-            writer.close();
-        }
-        
-        // Expand the driver template and write it to a source file.
-        File driverFile = new File(directory, "driver." + ext);
-        if (!driverFile.canRead())
-        {
-            String text = Util.expandTemplate(readTemplate(lang + "Driver"),
-                                              terms);
-            FileWriter writer = new FileWriter(driverFile);
-            writer.write(text);
-            writer.close();
-        }
-
-        // Write the test cases to a text file.  The driver code can read this
-        // file and perform the tests based on what it reads.
-        File testcaseFile = new File(directory, "testcases.txt");
-        if (!testcaseFile.canRead())
-        {
-            StringBuilder text = new StringBuilder();
-            if (component.hasTestCases())
-            {
-                for (TestCase testCase : component.getTestCases())
-                {
-                    text.append(testCase.getOutput() + System.getProperty("line.separator"));
-                    for (String input : testCase.getInput())
-                    {
-                        text.append(input + System.getProperty("line.separator"));
-                    }
-                }
-            }
-            FileWriter writer = new FileWriter(testcaseFile);
-            writer.write(text.toString());
-            writer.close();
-        }
-        
-        // Finally, expand the Makefile template and write it.
-        File makeFile = new File(directory, "Makefile");
-        {
-            String text = Util.expandTemplate(readTemplate(lang + "Makefile"),
-                                              terms);
-            FileWriter writer = new FileWriter(makeFile);
-            writer.write(text);
-            writer.close();
-        }
-    }
-
-    /**
-     * Save the source code provided by the server, and tell the Vim server to
-     * edit the current source file.
-     * @param source The source code.
-     * @throws Exception If the source couldn't be written or the Vim server
-     * had a problem.
-     */
-    public void setSource(String source) throws Exception
-    {
-        FileWriter writer = new FileWriter(new File(directory, name));
-        writer.write(source);
-        writer.close();
-        sendVimCommand("--remote-tab-silent", sourceFile.getPath());
-    }
-
-    /**
-     * Read the source code from the current source file.
-     * @return The source code.
-     * @throws IOException If the source file could not be read.
-     */
-    public String getSource() throws IOException
-    {
-        return Util.readFile(sourceFile) + "\n// Edited by " +
-        VimCoder.version + "\n// " + VimCoder.website + "\n\n";
-    }
-    
-    
-    /**
-     * Send a command to the Vim server.  If the server isn't running, it will
-     * be started with the name VIMCODER#### where #### is the problem ID.
-     * @param command The command to send to the server.
-     * @param argument A single argument for the remote command.
-     * @throws Exception If the command could not be sent.
-     */
-    private void sendVimCommand(String command,
-                                String argument) throws Exception
-    {
-        String[] arguments = {argument};
-        sendVimCommand(command, arguments);
-    }
-    
-    /**
-     * Send a command to the Vim server.  If the server isn't running, it will
-     * be started with the name VIMCODER#### where #### is the problem ID.
-     * @param command The command to send to the server.
-     * @param argument Arguments for the remote command.
-     * @throws Exception If the command could not be sent.
-     */
-    private void sendVimCommand(String command,
-                                String[] arguments) throws Exception
-    {
-        String[] vimCommand = VimCoder.getVimCommand().split("\\s");
-        String[] flags = {"--servername", "VimCoder" + id, command};
-        vimCommand = Util.concat(vimCommand, flags);
-        vimCommand = Util.concat(vimCommand, arguments);
-        Process child = Runtime.getRuntime().exec(vimCommand, null, directory);
-        
-        /* FIXME: This is a hack with a magic number.  The problem is the Vim
-         * process doesn't fork to the background on some systems, so we can't
-         * wait on the child.  At the same time, calling this method before the
-         * previous child could finish initializing the server may result in
-         * multiple editor windows popping up.  We'd also like to be able to
-         * get the return code from the child if we can.  The workaround here is
-         * to stall the thread for a little while or until we know the child
-         * does exit.  If the child never exits before the timeout, we will
-         * assume it is not backgrounding and that everything worked. */
-        long expire = System.currentTimeMillis() + 250;
-        while (System.currentTimeMillis() < expire)
-        {
-            Thread.yield();
-            try
-            {
-                int exitCode = child.exitValue();
-                if (exitCode != 0) throw new Exception("Vim process returned exit code " + exitCode + ".");
-                break;
-            }
-            catch (IllegalThreadStateException exception)
-            {
-                // The child has not exited; intentionally ignoring exception.
-            }
-        }
-    }
-    
-    
-    /**
-     * Read a template.  We first look in the storage directory.  If we can't
-     * find one, we look among the resources.
-     * @param tName The name of the template.
-     * @return The contents of the template file, or an empty string.
-     */
-    private String readTemplate(String tName)
-    {
-        File templateFile = new File(VimCoder.getStorageDirectory(), tName);
-        try
-        {
-            if (templateFile.canRead()) return Util.readFile(templateFile);
-            return Util.readResource(tName);
-        }
-        catch (IOException exception)
-        {
-            return "";
-        }
-    }
-    
-    
-    /**
-     * Convert an array of data types to an array of strings according to a
-     * given language.
-     * @param types The data types.
-     * @param language The language to use in the conversion.
-     * @return The array of string representations of the data types.
-     */
-    private String[] getStringTypes(DataType[] types, Language language)
-    {
-        String[] strings = new String[types.length];
-        for (int i = 0; i < types.length; ++i)
-        {
-            strings[i] = types[i].getDescriptor(language).replaceAll("\\s+", "");
-        }
-        return strings;
-    }
-    
-    /**
-     * Combine the data types and parameter names into a comma-separated list of
-     * the method parameters.  The result could be used inside the parentheses
-     * of a method declaration.
-     * @param types The data types of the parameters.
-     * @param names The names of the parameters.
-     * @param language The language used for representing the data types.
-     * @return The list of parameters.
-     */
-    private String getMethodParams(DataType[] types,
-                                   String[] names,
-                                   Language language)
-    {
-        String[] typeStrings = getStringTypes(types, language);
-        return Util.join(Util.combine(typeStrings, names, " "), ", ");
-    }
-    
-    /**
-     * Combine the data types and parameter names into a group of variable
-     * declarations.  Each declaration is separated by a new line and terminated
-     * with a semicolon.
-     * @param types The data types of the parameters.
-     * @param names The names of the parameters.
-     * @param language The language used for representing the data types.
-     * @return The parameters as a block of declarations.
-     */
-    private String getMethodParamDeclarations(DataType[] types,
-                                               String[] names,
-                                               Language language)
-    {
-        final String end = ";" + System.getProperty("line.separator");
-        String[] typeStrings = getStringTypes(types, language);
-        return Util.join(Util.combine(typeStrings, names, "\t"), end) + end;
-    }
+       /**
+        * The problem ID number.
+        */
+       private String  id;
+
+       /**
+        * The name of the class.
+        */
+       private String  name;
+
+       /**
+        * The path of the current source file.
+        */
+       private File    sourceFile;
+
+       /**
+        * The path of the problem directory.
+        */
+       private File    directory;
+
+
+       /**
+        * Map languages names to file extensions.
+        */
+       private static final Map<String,String> languageExtension = new HashMap<String,String>();
+       static
+       {
+               languageExtension.put("Java",   "java");
+               languageExtension.put("C++",    "cc");
+               languageExtension.put("C#",             "cs");
+               languageExtension.put("VB",             "vb");
+               languageExtension.put("Python", "py");
+       }
+
+
+       /**
+        * Construct an editor with the problem objects given us by the Arena.
+        * @param component A container for the particulars of the problem.
+        * @param language The currently selected language.
+        * @param renderer A helper object to help format the problem statement.
+        * @throws Exception If the editor could not set itself up.
+        */
+       public Editor(ProblemComponentModel component,
+                                 Language language,
+                                 Renderer renderer) throws Exception
+       {
+               this.id = String.valueOf(component.getProblem().getProblemID());
+               this.name = component.getClassName();
+
+               // Make sure the top-level vimcoder directory exists.
+               File topDir = VimCoder.getStorageDirectory();
+               if (!topDir.isDirectory())
+               {
+                       if (!topDir.mkdirs()) throw new IOException(topDir.getPath());
+               }
+
+               // Make sure the problem directory exists.
+               this.directory = new File(topDir, id);
+               if (!directory.isDirectory())
+               {
+                       if (!directory.mkdirs()) throw new IOException(directory.getPath());
+               }
+
+               String lang = language.getName();
+               String ext      = languageExtension.get(lang);
+
+               // Set up the terms used for the template expansion.
+               HashMap<String,String> terms = new HashMap<String,String>();
+               terms.put("RETURNTYPE",   component.getReturnType().getDescriptor(language).replaceAll("\\s+", ""));
+               terms.put("CLASSNAME",    name);
+               terms.put("METHODNAME",   component.getMethodName());
+               terms.put("METHODPARAMS", getMethodParams(component.getParamTypes(),
+                                                                                                 component.getParamNames(),
+                                                                                                 language));
+               terms.put("METHODPARAMNAMES",     Util.join(component.getParamNames(), ", "));
+               terms.put("METHODPARAMSTREAMIN",  Util.join(component.getParamNames(), " >> "));
+               terms.put("METHODPARAMSTREAMOUT", Util.join(component.getParamNames(), " << "));
+               terms.put("METHODPARAMDECLARES",  getMethodParamDeclarations(component.getParamTypes(),
+                                                                                                                                        component.getParamNames(),
+                                                                                                                                        language));
+
+               // Write the problem statement as an HTML file in the problem directory.
+               File problemFile = new File(directory, "Problem.html");
+               if (!problemFile.canRead())
+               {
+                       FileWriter writer = new FileWriter(problemFile);
+                       try
+                       {
+                               writer.write(renderer.toHTML(language));
+                       }
+                       finally
+                       {
+                               writer.close();
+                       }
+               }
+
+               // Expand the template for the main class and write it to the current
+               // source file.
+               sourceFile = new File(directory, name + "." + ext);
+               if (!sourceFile.canRead())
+               {
+                       String text = Util.expandTemplate(readTemplate(lang + "Template"),
+                                                                                         terms);
+                       FileWriter writer = new FileWriter(sourceFile);
+                       writer.write(text);
+                       writer.close();
+               }
+
+               // Expand the driver template and write it to a source file.
+               File driverFile = new File(directory, "driver." + ext);
+               if (!driverFile.canRead())
+               {
+                       String text = Util.expandTemplate(readTemplate(lang + "Driver"),
+                                                                                         terms);
+                       FileWriter writer = new FileWriter(driverFile);
+                       writer.write(text);
+                       writer.close();
+               }
+
+               // Write the test cases to a text file.  The driver code can read this
+               // file and perform the tests based on what it reads.
+               File testcaseFile = new File(directory, "testcases.txt");
+               if (!testcaseFile.canRead())
+               {
+                       StringBuilder text = new StringBuilder();
+                       if (component.hasTestCases())
+                       {
+                               for (TestCase testCase : component.getTestCases())
+                               {
+                                       text.append(testCase.getOutput() + System.getProperty("line.separator"));
+                                       for (String input : testCase.getInput())
+                                       {
+                                               text.append(input + System.getProperty("line.separator"));
+                                       }
+                               }
+                       }
+                       FileWriter writer = new FileWriter(testcaseFile);
+                       writer.write(text.toString());
+                       writer.close();
+               }
+
+               // Finally, expand the Makefile template and write it.
+               File makeFile = new File(directory, "Makefile");
+               {
+                       String text = Util.expandTemplate(readTemplate(lang + "Makefile"),
+                                                                                         terms);
+                       FileWriter writer = new FileWriter(makeFile);
+                       writer.write(text);
+                       writer.close();
+               }
+       }
+
+       /**
+        * Save the source code provided by the server, and tell the Vim server to
+        * edit the current source file.
+        * @param source The source code.
+        * @throws Exception If the source couldn't be written or the Vim server
+        * had a problem.
+        */
+       public void setSource(String source) throws Exception
+       {
+               FileWriter writer = new FileWriter(new File(directory, name));
+               writer.write(source);
+               writer.close();
+               sendVimCommand("--remote-tab-silent", sourceFile.getPath());
+       }
+
+       /**
+        * Read the source code from the current source file.
+        * @return The source code.
+        * @throws IOException If the source file could not be read.
+        */
+       public String getSource() throws IOException
+       {
+               return Util.readFile(sourceFile) + "\n// Edited by " +
+               VimCoder.version + "\n// " + VimCoder.website + "\n\n";
+       }
+
+
+       /**
+        * Send a command to the Vim server.
+        * If the server isn't running, it will be started with the name
+        * VIMCODER#### where #### is the problem ID.
+        * @param command The command to send to the server.
+        * @param argument A single argument for the remote command.
+        * @throws Exception If the command could not be sent.
+        */
+       private void sendVimCommand(String command,
+                                                               String argument) throws Exception
+       {
+               String[] arguments = {argument};
+               sendVimCommand(command, arguments);
+       }
+
+       /**
+        * Send a command to the Vim server.
+        * If the server isn't running, it will be started with the name
+        * VIMCODER#### where #### is the problem ID.
+        * @param command The command to send to the server.
+        * @param argument Arguments for the remote command.
+        * @throws Exception If the command could not be sent.
+        */
+       private void sendVimCommand(String command,
+                                                               String[] arguments) throws Exception
+       {
+               String[] vimCommand = VimCoder.getVimCommand().split("\\s");
+               String[] flags = {"--servername", "VimCoder" + id, command};
+               vimCommand = Util.concat(vimCommand, flags);
+               vimCommand = Util.concat(vimCommand, arguments);
+               Process child = Runtime.getRuntime().exec(vimCommand, null, directory);
+
+               /* FIXME: This is a pretty bad hack.  The problem is that the Vim
+                * process doesn't fork to the background on some systems, so we
+                * can't wait on the child.  At the same time, calling this method
+                * before the previous child could finish initializing the server
+                * may result in multiple editor windows popping up.    We'd also
+                * like to be able to get the return code from the child if we can.
+                * The workaround here is to stall the thread for a little while or
+                * until we see that the child exits.  If the child never exits
+                * before the timeout, we will assume it is not backgrounding and
+                * that everything worked.  This works as long as the Vim server is
+                * able to start within the stall period. */
+               long expire = System.currentTimeMillis() + 250;
+               while (System.currentTimeMillis() < expire)
+               {
+                       Thread.yield();
+                       try
+                       {
+                               int exitCode = child.exitValue();
+                               if (exitCode != 0) throw new Exception("Vim process returned exit code " + exitCode + ".");
+                               break;
+                       }
+                       catch (IllegalThreadStateException exception)
+                       {
+                               // The child has not exited; intentionally ignoring exception.
+                       }
+               }
+       }
+
+
+       /**
+        * Read a template.
+        * We first look in the storage directory.  If we can't find one, we
+        * look among the resources.
+        * @param tName The name of the template.
+        * @return The contents of the template file, or an empty string.
+        */
+       private String readTemplate(String tName)
+       {
+               File templateFile = new File(VimCoder.getStorageDirectory(), tName);
+               try
+               {
+                       if (templateFile.canRead()) return Util.readFile(templateFile);
+                       return Util.readResource(tName);
+               }
+               catch (IOException exception)
+               {
+                       return "";
+               }
+       }
+
+
+       /**
+        * Convert an array of data types to an array of strings according to a
+        * given language.
+        * @param types The data types.
+        * @param language The language to use in the conversion.
+        * @return The array of string representations of the data types.
+        */
+       private String[] getStringTypes(DataType[] types, Language language)
+       {
+               String[] strings = new String[types.length];
+               for (int i = 0; i < types.length; ++i)
+               {
+                       strings[i] = types[i].getDescriptor(language).replaceAll("\\s+", "");
+               }
+               return strings;
+       }
+
+       /**
+        * Combine the data types and parameter names into a comma-separated list of
+        * the method parameters.
+        * The result could be used inside the parentheses of a method
+        * declaration.
+        * @param types The data types of the parameters.
+        * @param names The names of the parameters.
+        * @param language The language used for representing the data types.
+        * @return The list of parameters.
+        */
+       private String getMethodParams(DataType[] types,
+                                                                  String[] names,
+                                                                  Language language)
+       {
+               String[] typeStrings = getStringTypes(types, language);
+               return Util.join(Util.combine(typeStrings, names, " "), ", ");
+       }
+
+       /**
+        * Combine the data types and parameter names into a group of variable
+        * declarations.
+        * Each declaration is separated by a new line and terminated with a
+        * semicolon.
+        * @param types The data types of the parameters.
+        * @param names The names of the parameters.
+        * @param language The language used for representing the data types.
+        * @return The parameters as a block of declarations.
+        */
+       private String getMethodParamDeclarations(DataType[] types,
+                                                                                         String[] names,
+                                                                                         Language language)
+       {
+               final String end = ";" + System.getProperty("line.separator");
+               String[] typeStrings = getStringTypes(types, language);
+               return Util.join(Util.combine(typeStrings, names, "\t"), end) + end;
+       }
 }
 
index bc5bdb891acb4ed1867d52b71fd1aeb284e88f54..47fdd20d1cdef9c51d0d23ad90c7e0702ba59ab1 100644 (file)
@@ -14,145 +14,147 @@ import java.util.Map;
  */
 public abstract class Util
 {
-    /**
-     * Concatenate two arrays into a single array.
-     * @param a First array.
-     * @param b Second array.
-     * @return The combined array.
-     */
-    public static <T> T[] concat(T[] a, T[] b)
-    {
-        T[] result = Arrays.copyOf(a, a.length + b.length);
-        System.arraycopy(b, 0, result, a.length, b.length);
-        return result;
-    }
-    
-    /**
-     * Combined string elements from two arrays into a single array, gluing
-     * together elements of the same index with a delimiter string.
-     * @param a First string array.
-     * @param b Second string array.
-     * @param glue The delimiter string.
-     * @return The combined array.
-     */
-    public static String[] combine(String[] a, String[] b, String glue)
-    {
-        String[] result = new String[Math.min(a.length, b.length)];
-        for (int i = 0; i < result.length; ++i)
-        {
-            result[i] = a[i] + glue + b[i];
-        }
-        return result;
-    }
+       /**
+        * Concatenate two arrays into a single array.
+        * @param a First array.
+        * @param b Second array.
+        * @return The combined array.
+        */
+       public static <T> T[] concat(T[] a, T[] b)
+       {
+               T[] result = Arrays.copyOf(a, a.length + b.length);
+               System.arraycopy(b, 0, result, a.length, b.length);
+               return result;
+       }
 
-    /**
-     * Join the elements of a string array with a delimiter.
-     * @param a The array.
-     * @param glue The delimiter string.
-     * @return The joined string.
-     */
-    public static String join(String[] a, String glue)
-    {
-        if (a.length == 0) return "";
-        StringBuilder result = new StringBuilder();
-        result.append(a[0]);
-        for (int i = 1; i < a.length; ++i) result.append(glue).append(a[i]);
-        return result.toString();
-    }
-    
-    /**
-     * Quote a string by replacing prepending backslashes and double
-     * quotation characters with an extra backslash.
-     * @param The string to be quoted.
-     * @return The quoted string.
-     */
-    public static String quote(String a)
-    {
-        a = a.replaceAll("\\\\", "\\\\\\\\");
-        a = a.replaceAll("\"",   "\\\\\\\"");
-        return a;
-    }
-    
-    /**
-     * Simply read a file's contents into a string object.
-     * @param file The file to read.
-     * @return The contents of the file.
-     * @throws IOException If the file is not readable.
-     */
-    public static String readFile(File file) throws IOException
-    {
-        StringBuilder text = new StringBuilder();
-    
-        BufferedReader reader = new BufferedReader(new FileReader(file.getPath()));
-        try
-        {
-            String line = null;
-            
-            while ((line = reader.readLine()) != null)
-            {
-                text.append(line + System.getProperty("line.separator"));
-            }
-        }
-        finally
-        {
-            reader.close();
-        }
-    
-        return text.toString();
-    }
-    
-    /**
-     * Read a resource file into a string object.  The resources should be
-     * placed in the directory `resources' underneath the parent directory of
-     * this class.  Reading resources packaged in a jar is allowable.
-     * @param path Relative path to the resource.
-     * @return The contents of the resource.
-     * @throws IOException If the resource is not readable.
-     */
-    public static String readResource(String path) throws IOException
-    {
-        StringBuilder text = new StringBuilder();
-        
-        InputStream stream = Util.class.getResourceAsStream("resources/" + path);
-        if (stream != null)
-        {
-            try
-            {
-                byte[]  buffer = new byte[4096];
-                int     numBytes = 0;
-                while (0 < (numBytes = stream.read(buffer)))
-                {
-                    text.append(new String(buffer, 0, numBytes));
-                }
-            }
-            finally
-            {
-                stream.close();
-            }
-        }
-        
-        return text.toString();
-    }
-    
-    /**
-     * The poor man's template package.  Provide a template and a map of terms
-     * to build the result with the terms expanded into the template.  Terms
-     * in the template should appear surrounded with dollar signs.  For example,
-     * if $MYTERM$ appears in the template, it will be replaced by the value
-     * into the terms map with the key MYTERM (if it exists in the map).
-     * @param template The template string.
-     * @param terms A map of key/value terms.
-     * @return The string expanded from the template and terms.
-     */
-    public static String expandTemplate(String template, Map<String,String> terms)
-    {
-        String text = template;
-        for (String key : terms.keySet())
-        {
-            text = text.replaceAll("\\$" + key + "\\$",
-                                   Util.quote(terms.get(key)));
-        }
-        return text;
-    }
+       /**
+        * Combined string elements from two arrays into a single array, gluing
+        * together elements of the same index with a delimiter string.
+        * @param a First string array.
+        * @param b Second string array.
+        * @param glue The delimiter string.
+        * @return The combined array.
+        */
+       public static String[] combine(String[] a, String[] b, String glue)
+       {
+               String[] result = new String[Math.min(a.length, b.length)];
+               for (int i = 0; i < result.length; ++i)
+               {
+                       result[i] = a[i] + glue + b[i];
+               }
+               return result;
+       }
+
+       /**
+        * Join the elements of a string array with a delimiter.
+        * @param a The array.
+        * @param glue The delimiter string.
+        * @return The joined string.
+        */
+       public static String join(String[] a, String glue)
+       {
+               if (a.length == 0) return "";
+               StringBuilder result = new StringBuilder();
+               result.append(a[0]);
+               for (int i = 1; i < a.length; ++i) result.append(glue).append(a[i]);
+               return result.toString();
+       }
+
+       /**
+        * Quote a string by replacing prepending backslashes and double
+        * quotation characters with an extra backslash.
+        * @param The string to be quoted.
+        * @return The quoted string.
+        */
+       public static String quote(String a)
+       {
+               a = a.replaceAll("\\\\", "\\\\\\\\");
+               a = a.replaceAll("\"",   "\\\\\\\"");
+               return a;
+       }
+
+       /**
+        * Simply read a file's contents into a string object.
+        * @param file The file to read.
+        * @return The contents of the file.
+        * @throws IOException If the file is not readable.
+        */
+       public static String readFile(File file) throws IOException
+       {
+               StringBuilder text = new StringBuilder();
+
+               BufferedReader reader = new BufferedReader(new FileReader(file.getPath()));
+               try
+               {
+                       String line = null;
+
+                       while ((line = reader.readLine()) != null)
+                       {
+                               text.append(line + System.getProperty("line.separator"));
+                       }
+               }
+               finally
+               {
+                       reader.close();
+               }
+
+               return text.toString();
+       }
+
+       /**
+        * Read a resource file into a string object.
+        * The resources should be placed in the directory `resources'
+        * underneath the parent directory of this class.       Reading resources
+        * packaged in a jar is allowable.
+        * @param path Relative path to the resource.
+        * @return The contents of the resource.
+        * @throws IOException If the resource is not readable.
+        */
+       public static String readResource(String path) throws IOException
+       {
+               StringBuilder text = new StringBuilder();
+
+               InputStream stream = Util.class.getResourceAsStream("resources/" + path);
+               if (stream != null)
+               {
+                       try
+                       {
+                               byte[]  buffer = new byte[4096];
+                               int             numBytes = 0;
+                               while (0 < (numBytes = stream.read(buffer)))
+                               {
+                                       text.append(new String(buffer, 0, numBytes));
+                               }
+                       }
+                       finally
+                       {
+                               stream.close();
+                       }
+               }
+
+               return text.toString();
+       }
+
+       /**
+        * The poor man's template package.
+        * Provide a template and a map of terms to build the result with the
+        * terms expanded into the template.  Terms in the template should
+        * appear surrounded with dollar signs. For example, if $MYTERM$
+        * appears in the template, it will be replaced by the value into the
+        * terms map with the key MYTERM (if it exists in the map).
+        * @param template The template string.
+        * @param terms A map of key/value terms.
+        * @return The string expanded from the template and terms.
+        */
+       public static String expandTemplate(String template, Map<String,String> terms)
+       {
+               String text = template;
+               for (String key : terms.keySet())
+               {
+                       text = text.replaceAll("\\$" + key + "\\$",
+                                                                  Util.quote(terms.get(key)));
+               }
+               return text;
+       }
 }
 
index a12846174651fe88062d54c0b399ebd19e3eeac2..658bae13051ddc080a266bd9610cec8bf721929e 100644 (file)
@@ -1,7 +1,6 @@
 
 package com.dogcows;
 
-import javax.swing.*;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -9,12 +8,13 @@ import java.beans.PropertyChangeListener;
 import java.io.*;
 import java.text.SimpleDateFormat;
 import java.util.*;
-import com.topcoder.client.contestant.ProblemComponentModel;
-import com.topcoder.shared.language.*;
-import com.topcoder.shared.problem.*;
-import com.topcoder.shared.problem.Renderer;
+import javax.swing.*;
+
 import com.topcoder.client.contestApplet.common.Common;
 import com.topcoder.client.contestApplet.common.LocalPreferences;
+import com.topcoder.client.contestant.ProblemComponentModel;
+import com.topcoder.shared.language.Language;
+import com.topcoder.shared.problem.Renderer;
 
 /**
  * @author Charles McGarvey
@@ -25,377 +25,379 @@ import com.topcoder.client.contestApplet.common.LocalPreferences;
  */
 public class VimCoder
 {
-    /**
-     * The name and version of this plugin.
-     */
-    public final static String     version = "VimCoder 0.3";
-    
-    /**
-     * The website of the plugin project.
-     */
-    public final static String     website = "http://www.dogcows.com/vimcoder";
-    
-    
-    /**
-     * The first part of the command used to invoke the Vim server.
-     */
-    private static String   vimCommand = "gvim";
-    
-    /**
-     * The path to the main VimCoder directory.
-     */
-    private static File     rootDir;
-    static
-    {
-        if (System.getProperty("os.name").toLowerCase().equals("win"))
-        {
-            vimCommand = "C:\\WINDOWS\\gvim.bat";
-        }
-        rootDir = new File(System.getProperty("user.home") +
-                           System.getProperty("file.separator") + ".vimcoder");
-    }
-    
-    
-    /**
-     * The panel given to the Arena applet when it is requested.
-     */
-    private JPanel      panel;
-    
-    /**
-     * The text widget where log messages are appended.
-     */
-    private JTextArea   logArea;
-    
-    /**
-     * The current editor object (or null if there is none).
-     */
-    private Editor      editor;
-    
-    /**
-     * The configuration panel.
-     */
-    private JDialog     configDialog;
-    
-    
-    /**
-     * The key for the vim command preference.
-     */
-    private final static String VIMCOMMAND = "com.dogcows.VimCoder.config.vimcommand";
-    
-    /**
-     * The key for the root directory preference.
-     */
-    private final static String ROOTDIR = "com.dogcows.VimCoder.config.rootdir";
-    
-    /**
-     * The preferences object for storing plugin settings.
-     */
-    private static LocalPreferences prefs = LocalPreferences.getInstance();
-    
-    
-    /**
-     * Get the command for invoking vim.
-     * @return The command.
-     */
-    public static String getVimCommand()
-    {
-        return vimCommand;
-    }
-    
-    /**
-     * Get the storage directory.
-     * @return The directory.
-     */
-    public static File getStorageDirectory()
-    {
-        return rootDir;
-    }
-
-   
-    /**
-     * Instantiate the entry point of the editor plugin.  Sets up the log widget
-     * and panel.
-     */
-    public VimCoder()
-    {
-        logArea = new JTextArea();
-        logArea.setForeground(Color.GREEN);
-        logArea.setBackground(Color.BLACK);
-        logArea.setEditable(false);
-        Font font = new Font("Courier", Font.PLAIN, 12);
-        if (font != null) logArea.setFont(font);
-           
-        panel = new JPanel(new BorderLayout());
-        panel.add(new JScrollPane(logArea), BorderLayout.CENTER);
-    }
-
-    
-    /**
-     * Called by the Arena when the plugin is about to be used.
-     */
-    public void startUsing()
-    {
-        Runnable task = new Runnable()
-        {
-            public void run()
-            {
-                logArea.setText("");
-            }
-        };
-        if (SwingUtilities.isEventDispatchThread())
-        {
-            task.run();
-        }
-        else
-        {
-            SwingUtilities.invokeLater(task);
-        }
-        loadConfiguration();
-    }
-    
-    /**
-     * Called by the Arena when the plugin is no longer needed.
-     */
-    public void stopUsing()
-    {
-        editor = null;
-    }
-    
-    /**
-     * Called by the Arena to obtain the editor panel which we will use to show
-     * log messages.
-     * @return The editor panel.
-     */
-    public JPanel getEditorPanel()
-    {
-        return panel;
-    }
-   
-    /**
-     * Called by the Arena to obtain the current source.  This happens when the
-     * user is saving, compiling, and/or submitting.
-     * @return The current source code.
-     * @throws Exception If the source file edited by Vim couldn't be read.
-     */
-    public String getSource() throws Exception
-    {
-        try
-        {
-            String source = editor.getSource();
-            logInfo("Source code uploaded to server.");
-            return source;
-        }
-        catch (Exception exception)
-        {
-            logError("Failed to get source code: " +
-                     exception.getLocalizedMessage());
-            throw exception;
-        }
-    }
-    
-    /**
-     * Called by the Arena to pass the source it has.
-     * @param source The source code.
-     */
-    public void setSource(String source)
-    {
-        try
-        {
-            editor.setSource(source);
-            logInfo("Source code downloaded from server.");
-        }
-        catch (Exception exception)
-        {
-            logError("Failed to save the source given by the server: " +
-                     exception.getLocalizedMessage());
-            return;
-        }
-    }
-    
-    /**
-     * Called by the Arena to pass along information about the current problem.
-     * @param component A container for the particulars of the problem.
-     * @param language The currently selected language.
-     * @param renderer A helper object to help format the problem statement.
-     */
-    public void setProblemComponent(ProblemComponentModel component, 
-                                    Language language,
-                                    Renderer renderer)
-    {
-        try
-        {
-            editor = new Editor(component, language, renderer);
-        }
-        catch (Exception exception)
-        {
-            logError("An error occured while loading the problem: " +
-                     exception.getLocalizedMessage());
-        }
-    }
-    
-    /**
-     * Called by the Arena when it's time to show our configuration panel.
-     */
-    public void configure()
-    {
-        loadConfiguration();
-        
-        configDialog = new JDialog();
-        Container pane = configDialog.getContentPane();
-        
-        pane.setPreferredSize(new Dimension(550, 135));
-        pane.setLayout(new GridBagLayout());
-        pane.setForeground(Common.FG_COLOR);
-        pane.setBackground(Common.WPB_COLOR);
-        GridBagConstraints c = new GridBagConstraints();
-        
-        JLabel rootDirLabel = new JLabel("Storage Directory:", SwingConstants.RIGHT);
-        rootDirLabel.setForeground(Common.FG_COLOR);
-        c.fill = GridBagConstraints.HORIZONTAL;
-        c.insets = new Insets(5, 5, 5, 5);
-        c.gridx = 0;
-        c.gridy = 0;
-        c.gridwidth = 1;
-        pane.add(rootDirLabel, c);
-        
-        final JTextField rootDirField = new JTextField(rootDir.getPath(), 25);
-        c.gridx = 1;
-        c.gridy = 0;
-        pane.add(rootDirField, c);
-        
-        JButton browseButton = new JButton("Browse");
-        c.gridx = 2;
-        c.gridy = 0;
-        c.anchor = GridBagConstraints.BASELINE_LEADING;
-        pane.add(browseButton, c);
-        
-        JLabel vimCommandLabel = new JLabel("Vim Command:", SwingConstants.RIGHT);
-        vimCommandLabel.setForeground(Common.FG_COLOR);
-        c.fill = GridBagConstraints.HORIZONTAL;
-        c.gridx = 0;
-        c.gridy = 1;
-        pane.add(vimCommandLabel, c);
-        
-        final JTextField vimCommandField = new JTextField(vimCommand, 25);
-        c.gridx = 1;
-        c.gridy = 1;
-        c.gridwidth = 2;
-        pane.add(vimCommandField, c);
-        
-        JButton closeButton = new JButton("Cancel");
-        c.fill = GridBagConstraints.NONE;
-        c.gridx = 1;
-        c.gridy = 2;
-        c.gridwidth = 1;
-        c.anchor = GridBagConstraints.EAST;
-        pane.add(closeButton, c);
-        
-        JButton saveButton = new JButton("Save");
-        c.fill = GridBagConstraints.HORIZONTAL;
-        c.gridx = 2;
-        c.gridy = 2;
-        c.anchor = GridBagConstraints.EAST;
-        pane.add(saveButton, c);
-        configDialog.getRootPane().setDefaultButton(saveButton);
-        
-        browseButton.addActionListener(new ActionListener()
-        {
-            public void actionPerformed(ActionEvent actionEvent)
-            {
-                JFileChooser chooser = new JFileChooser();
-                chooser.setCurrentDirectory(new File("."));
-                chooser.setDialogTitle("Choose Storage Directory");
-                chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-                chooser.setAcceptAllFileFilterUsed(false);
-                
-                if (chooser.showOpenDialog(configDialog) == JFileChooser.APPROVE_OPTION)
-                {
-                    rootDirField.setText(chooser.getSelectedFile().getPath());
-                }
-            }
-        });
-        
-        closeButton.addActionListener(new ActionListener()
-        {
-            public void actionPerformed(ActionEvent actionEvent)
-            {
-                configDialog.dispose();
-            }
-        });
-        
-        saveButton.addActionListener(new ActionListener()
-        {
-            public void actionPerformed(ActionEvent actionEvent)
-            {
-                prefs.setProperty(VIMCOMMAND, vimCommandField.getText());
-                prefs.setProperty(ROOTDIR, rootDirField.getText());
-                configDialog.dispose();
-            }
-        });
-         
-        configDialog.setTitle("VimCoder Preferences");
-        configDialog.pack();
-        configDialog.setLocationByPlatform(true);
-        configDialog.setModalityType(Dialog.DEFAULT_MODALITY_TYPE);
-        configDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
-        configDialog.setVisible(true);
-    }
-    
-    
-    /**
-     * Load the local preferences related to this plugin.
-     */
-    private void loadConfiguration()
-    {
-        String vc  = prefs.getProperty(VIMCOMMAND);
-        if (vc != null) vimCommand = vc;
-        
-        String dir = prefs.getProperty(ROOTDIR);
-        if (dir != null) rootDir = new File(dir);
-    }
-
-    
-    /**
-     * A generic logging function, appends text to the text area.  A timestamp
-     * is also prepended to the next text.
-     * @param what The text to append.
-     */
-    private void log(final String what)
-    {
-        Runnable task = new Runnable()
-        {
-            public void run()
-            {
-                SimpleDateFormat format = new SimpleDateFormat("kk:mm:ss");
-                logArea.append(format.format(new Date()) + ", " + what);
-            }
-        };
-        if (SwingUtilities.isEventDispatchThread())
-        {
-            task.run();
-        }
-        else
-        {
-            SwingUtilities.invokeLater(task);
-        }
-    }
-    
-    /**
-     * Output non-critical messages to the log.
-     * @param what The text of the message.
-     */
-    private void logInfo(String what)
-    {
-        log(" INFO: " + what + System.getProperty("line.separator"));
-    }
-
-    /**
-     * Output critical messages and errors to the log.
-     * @param what The text of the message.
-     */
-    private void logError(String what)
-    {
-        log("ERROR: " + what + System.getProperty("line.separator"));
-    }
+       /**
+        * The name and version of this plugin.
+        */
+       public final static String      version = "VimCoder 0.3";
+
+       /**
+        * The website of the plugin project.
+        */
+       public final static String      website = "http://www.dogcows.com/vimcoder";
+
+
+       /**
+        * The first part of the command used to invoke the Vim server.
+        */
+       private static String           vimCommand = "gvim";
+
+       /**
+        * The path to the main VimCoder directory.
+        */
+       private static File                     rootDir;
+       static
+       {
+               if (System.getProperty("os.name").toLowerCase().equals("win"))
+               {
+                       vimCommand = "C:\\WINDOWS\\gvim.bat";
+               }
+               rootDir = new File(System.getProperty("user.home") +
+                                                  System.getProperty("file.separator") + ".vimcoder");
+       }
+
+
+       /**
+        * The panel given to the Arena applet when it is requested.
+        */
+       private JPanel          panel;
+
+       /**
+        * The text widget where log messages are appended.
+        */
+       private JTextArea       logArea;
+
+       /**
+        * The current editor object (or null if there is none).
+        */
+       private Editor          editor;
+
+       /**
+        * The configuration panel.
+        */
+       private JDialog         configDialog;
+
+
+       /**
+        * The key for the vim command preference.
+        */
+       private final static String VIMCOMMAND = "com.dogcows.VimCoder.config.vimcommand";
+
+       /**
+        * The key for the root directory preference.
+        */
+       private final static String ROOTDIR = "com.dogcows.VimCoder.config.rootdir";
+
+       /**
+        * The preferences object for storing plugin settings.
+        */
+       private static LocalPreferences prefs = LocalPreferences.getInstance();
+
+
+       /**
+        * Get the command for invoking vim.
+        * @return The command.
+        */
+       public static String getVimCommand()
+       {
+               return vimCommand;
+       }
+
+       /**
+        * Get the storage directory.
+        * @return The directory.
+        */
+       public static File getStorageDirectory()
+       {
+               return rootDir;
+       }
+
+
+       /**
+        * Instantiate the entry point of the editor plugin.
+        * Sets up the log widget and panel.
+        */
+       public VimCoder()
+       {
+               logArea = new JTextArea();
+               logArea.setForeground(Color.GREEN);
+               logArea.setBackground(Color.BLACK);
+               logArea.setEditable(false);
+               Font font = new Font("Courier", Font.PLAIN, 12);
+               if (font != null) logArea.setFont(font);
+
+               panel = new JPanel(new BorderLayout());
+               panel.add(new JScrollPane(logArea), BorderLayout.CENTER);
+       }
+
+
+       /**
+        * Called by the Arena when the plugin is about to be used.
+        */
+       public void startUsing()
+       {
+               Runnable task = new Runnable()
+               {
+                       public void run()
+                       {
+                               logArea.setText("");
+                       }
+               };
+               if (SwingUtilities.isEventDispatchThread())
+               {
+                       task.run();
+               }
+               else
+               {
+                       SwingUtilities.invokeLater(task);
+               }
+               loadConfiguration();
+       }
+
+       /**
+        * Called by the Arena when the plugin is no longer needed.
+        */
+       public void stopUsing()
+       {
+               editor = null;
+       }
+
+       /**
+        * Called by the Arena to obtain the editor panel which we will use to
+        * show log messages.
+        * @return The editor panel.
+        */
+       public JPanel getEditorPanel()
+       {
+               return panel;
+       }
+
+       /**
+        * Called by the Arena to obtain the current source.
+        * This happens when the user is saving, compiling, and/or submitting.
+        * @return The current source code.
+        * @throws Exception If the source file edited by Vim couldn't be read.
+        */
+       public String getSource() throws Exception
+       {
+               try
+               {
+                       String source = editor.getSource();
+                       logInfo("Source code uploaded to server.");
+                       return source;
+               }
+               catch (Exception exception)
+               {
+                       logError("Failed to get source code: " +
+                                        exception.getLocalizedMessage());
+                       throw exception;
+               }
+       }
+
+       /**
+        * Called by the Arena to pass the source it has.
+        * @param source The source code.
+        */
+       public void setSource(String source)
+       {
+               try
+               {
+                       editor.setSource(source);
+                       logInfo("Source code downloaded from server.");
+               }
+               catch (Exception exception)
+               {
+                       logError("Failed to save the source given by the server: " +
+                                        exception.getLocalizedMessage());
+                       return;
+               }
+       }
+
+       /**
+        * Called by the Arena to pass along information about the current
+        * problem.
+        * @param component A container for the particulars of the problem.
+        * @param language The currently selected language.
+        * @param renderer A helper object to help format the problem
+        * statement.
+        */
+       public void setProblemComponent(ProblemComponentModel component,
+                                                                       Language language,
+                                                                       Renderer renderer)
+       {
+               try
+               {
+                       editor = new Editor(component, language, renderer);
+               }
+               catch (Exception exception)
+               {
+                       logError("An error occured while loading the problem: " +
+                                        exception.getLocalizedMessage());
+               }
+       }
+
+       /**
+        * Called by the Arena when it's time to show our configuration panel.
+        */
+       public void configure()
+       {
+               loadConfiguration();
+
+               configDialog = new JDialog();
+               Container pane = configDialog.getContentPane();
+
+               pane.setPreferredSize(new Dimension(550, 135));
+               pane.setLayout(new GridBagLayout());
+               pane.setForeground(Common.FG_COLOR);
+               pane.setBackground(Common.WPB_COLOR);
+               GridBagConstraints c = new GridBagConstraints();
+
+               JLabel rootDirLabel = new JLabel("Storage Directory:", SwingConstants.RIGHT);
+               rootDirLabel.setForeground(Common.FG_COLOR);
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.insets = new Insets(5, 5, 5, 5);
+               c.gridx = 0;
+               c.gridy = 0;
+               c.gridwidth = 1;
+               pane.add(rootDirLabel, c);
+
+               final JTextField rootDirField = new JTextField(rootDir.getPath(), 25);
+               c.gridx = 1;
+               c.gridy = 0;
+               pane.add(rootDirField, c);
+
+               JButton browseButton = new JButton("Browse");
+               c.gridx = 2;
+               c.gridy = 0;
+               c.anchor = GridBagConstraints.BASELINE_LEADING;
+               pane.add(browseButton, c);
+
+               JLabel vimCommandLabel = new JLabel("Vim Command:", SwingConstants.RIGHT);
+               vimCommandLabel.setForeground(Common.FG_COLOR);
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.gridx = 0;
+               c.gridy = 1;
+               pane.add(vimCommandLabel, c);
+
+               final JTextField vimCommandField = new JTextField(vimCommand, 25);
+               c.gridx = 1;
+               c.gridy = 1;
+               c.gridwidth = 2;
+               pane.add(vimCommandField, c);
+
+               JButton closeButton = new JButton("Cancel");
+               c.fill = GridBagConstraints.NONE;
+               c.gridx = 1;
+               c.gridy = 2;
+               c.gridwidth = 1;
+               c.anchor = GridBagConstraints.EAST;
+               pane.add(closeButton, c);
+
+               JButton saveButton = new JButton("Save");
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.gridx = 2;
+               c.gridy = 2;
+               c.anchor = GridBagConstraints.EAST;
+               pane.add(saveButton, c);
+               configDialog.getRootPane().setDefaultButton(saveButton);
+
+               browseButton.addActionListener(new ActionListener()
+               {
+                       public void actionPerformed(ActionEvent actionEvent)
+                       {
+                               JFileChooser chooser = new JFileChooser();
+                               chooser.setCurrentDirectory(new File("."));
+                               chooser.setDialogTitle("Choose Storage Directory");
+                               chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+                               chooser.setAcceptAllFileFilterUsed(false);
+
+                               if (chooser.showOpenDialog(configDialog) == JFileChooser.APPROVE_OPTION)
+                               {
+                                       rootDirField.setText(chooser.getSelectedFile().getPath());
+                               }
+                       }
+               });
+
+               closeButton.addActionListener(new ActionListener()
+               {
+                       public void actionPerformed(ActionEvent actionEvent)
+                       {
+                               configDialog.dispose();
+                       }
+               });
+
+               saveButton.addActionListener(new ActionListener()
+               {
+                       public void actionPerformed(ActionEvent actionEvent)
+                       {
+                               prefs.setProperty(VIMCOMMAND, vimCommandField.getText());
+                               prefs.setProperty(ROOTDIR, rootDirField.getText());
+                               configDialog.dispose();
+                       }
+               });
+
+               configDialog.setTitle("VimCoder Preferences");
+               configDialog.pack();
+               configDialog.setLocationByPlatform(true);
+               configDialog.setModalityType(Dialog.DEFAULT_MODALITY_TYPE);
+               configDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+               configDialog.setVisible(true);
+       }
+
+
+       /**
+        * Load the local preferences related to this plugin.
+        */
+       private void loadConfiguration()
+       {
+               String vc  = prefs.getProperty(VIMCOMMAND);
+               if (vc != null) vimCommand = vc;
+
+               String dir = prefs.getProperty(ROOTDIR);
+               if (dir != null) rootDir = new File(dir);
+       }
+
+
+       /**
+        * A generic logging function, appends text to the text area.  A timestamp
+        * is also prepended to the next text.
+        * @param what The text to append.
+        */
+       private void log(final String what)
+       {
+               Runnable task = new Runnable()
+               {
+                       public void run()
+                       {
+                               SimpleDateFormat format = new SimpleDateFormat("kk:mm:ss");
+                               logArea.append(format.format(new Date()) + ", " + what);
+                       }
+               };
+               if (SwingUtilities.isEventDispatchThread())
+               {
+                       task.run();
+               }
+               else
+               {
+                       SwingUtilities.invokeLater(task);
+               }
+       }
+
+       /**
+        * Output non-critical messages to the log.
+        * @param what The text of the message.
+        */
+       private void logInfo(String what)
+       {
+               log(" INFO: " + what + System.getProperty("line.separator"));
+       }
+
+       /**
+        * Output critical messages and errors to the log.
+        * @param what The text of the message.
+        */
+       private void logError(String what)
+       {
+               log("ERROR: " + what + System.getProperty("line.separator"));
+       }
 }
 
This page took 0.068203 seconds and 4 git commands to generate.