From bde33c9ffb21a7a0fa71e73a106154c451d48ad2 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Thu, 11 Nov 2010 15:16:00 -0700 Subject: [PATCH] don't wait on vim processes fixes #4, #7, #8 --- .classpath | 11 - .project | 17 -- src/com/dogcows/Editor.java | 182 +++++++++++++++ src/com/dogcows/Utilities.java | 95 ++++++++ src/com/dogcows/VimCoder.java | 318 ++++---------------------- src/com/dogcows/resources/C++Makefile | 2 + src/com/dogcows/resources/C++Template | 2 +- 7 files changed, 323 insertions(+), 304 deletions(-) delete mode 100644 .classpath delete mode 100644 .project create mode 100644 src/com/dogcows/Editor.java create mode 100644 src/com/dogcows/Utilities.java diff --git a/.classpath b/.classpath deleted file mode 100644 index fc6d16a..0000000 --- a/.classpath +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index 2880acc..0000000 --- a/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - VimCoder - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/src/com/dogcows/Editor.java b/src/com/dogcows/Editor.java new file mode 100644 index 0000000..dda5481 --- /dev/null +++ b/src/com/dogcows/Editor.java @@ -0,0 +1,182 @@ + +package com.dogcows; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import com.topcoder.client.contestant.ProblemComponentModel; +import com.topcoder.shared.language.Language; +import com.topcoder.shared.problem.DataType; +import com.topcoder.shared.problem.Renderer; +import com.topcoder.shared.problem.TestCase; + +/** + * @author Charles McGarvey + * + */ +public class Editor +{ + private String id; + private String name; + + private File sourceFile; + private File directory; + + + private static final Map languageExtension = new HashMap(); + static + { + languageExtension.put("Java", "java"); + languageExtension.put("C++", "cc"); + languageExtension.put("C#", "cs"); + languageExtension.put("VB", "vb"); + languageExtension.put("Python", "py"); + } + + + public Editor(ProblemComponentModel component, + Language language, + Renderer renderer) throws IOException + { + this.id = String.valueOf(component.getProblem().getProblemID()); + this.name = component.getClassName(); + + File topDir = new File(System.getProperty("user.home"), ".vimcoder"); + if (!topDir.isDirectory()) + { + if (!topDir.mkdirs()) throw new IOException(topDir.getPath()); + } + + 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); + + HashMap terms = new HashMap(); + terms.put("RETURNTYPE", component.getReturnType().getDescriptor(language)); + terms.put("CLASSNAME", component.getClassName()); + terms.put("METHODNAME", component.getMethodName()); + terms.put("METHODPARAMS", getMethodParams(component.getParamTypes(), + component.getParamNames(), + language)); + terms.put("METHODPARAMNAMES", Utilities.join(component.getParamNames(), ", ")); + + File problemFile = new File(directory, "Problem.html"); + if (!problemFile.canRead()) + { + FileWriter writer = new FileWriter(problemFile); + try + { + writer.write(renderer.toHTML(language)); + } + catch (Exception exception) + { + } + writer.close(); + } + + sourceFile = new File(directory, terms.get("CLASSNAME") + "." + ext); + if (!sourceFile.canRead()) + { + String text = Utilities.expandTemplate(Utilities.readResource(lang + "Template"), + terms); + FileWriter writer = new FileWriter(sourceFile); + writer.write(text); + writer.close(); + } + + File driverFile = new File(directory, "driver" + "." + ext); + if (!driverFile.canRead()) + { + StringBuilder testCases = new StringBuilder(); + if (component.hasTestCases()) + { + HashMap testTerms = new HashMap(); + testTerms.putAll(terms); + String template = Utilities.readResource(lang + "Test"); + for (TestCase testCase : component.getTestCases()) + { + testTerms.put("TESTOUTPUT", "\"" + Utilities.quote(testCase.getOutput()) + "\""); + testTerms.put("TESTINPUTS", Utilities.join(testCase.getInput(), ", ")); + testCases.append(Utilities.expandTemplate(template, testTerms)); + } + } + terms.put("TESTCASES", testCases.toString()); + + String text = Utilities.expandTemplate(Utilities.readResource(lang + "Driver"), + terms); + FileWriter writer = new FileWriter(driverFile); + writer.write(text); + writer.close(); + } + + File makeFile = new File(directory, "Makefile"); + { + String text = Utilities.expandTemplate(Utilities.readResource(lang + "Makefile"), + terms); + FileWriter writer = new FileWriter(makeFile); + writer.write(text); + writer.close(); + } + } + + public void setSource(String source) throws IOException + { + FileWriter writer = new FileWriter(new File(directory, name)); + writer.write(source); + writer.close(); + doVimCommand("--remote-tab-silent", sourceFile.getPath()); + } + + public String getSource() throws IOException + { + return Utilities.readFile(sourceFile) + "\n// Edited by " + VimCoder.version + "\n// " + VimCoder.website + "\n\n"; + } + + + private boolean doVimCommand(String command, String argument) + { + String[] arguments = {argument}; + return doVimCommand(command, arguments); + } + + private boolean doVimCommand(String command, String[] arguments) + { + try + { + String[] exec = {"gvim", "--servername", "VimCoder" + id, + command}; + exec = Utilities.concat(exec, arguments); + Runtime.getRuntime().exec(exec, null, directory); + } + catch (IOException exception) + { + System.out.println("Failed to launch external vim process. :-("); + } + return false; + } + + private String getMethodParams(DataType[] types, String[] names, Language language) + { + StringBuilder text = new StringBuilder(); + + text.append(types[0].getDescriptor(language) + " " + names[0]); + for (int i = 1; i < names.length; ++i) + { + text.append(", " + types[i].getDescriptor(language) + " " + names[i]); + } + + return text.toString(); + } +} + diff --git a/src/com/dogcows/Utilities.java b/src/com/dogcows/Utilities.java new file mode 100644 index 0000000..7dddd1f --- /dev/null +++ b/src/com/dogcows/Utilities.java @@ -0,0 +1,95 @@ + +package com.dogcows; + +import java.io.*; +import java.util.Arrays; +import java.util.Map; + +/** + * @author Charles McGarvey + * + */ +public abstract class Utilities +{ + + public static 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; + } + + 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(); + } + + public static String quote(String a) + { + a = a.replaceAll("\\\\", "\\\\\\\\"); + a = a.replaceAll("\"", "\\\\\\\""); + return a; + } + + 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(); + } + + public static String readResource(String path) throws IOException + { + StringBuilder text = new StringBuilder(); + + InputStream stream = Utilities.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(); + } + + public static String expandTemplate(String template, Map terms) + { + String text = template; + for (String key : terms.keySet()) + { + text = text.replaceAll("\\$" + key + "\\$", + Utilities.quote(terms.get(key))); + } + return text; + } +} diff --git a/src/com/dogcows/VimCoder.java b/src/com/dogcows/VimCoder.java index 489e789..5f69aaa 100644 --- a/src/com/dogcows/VimCoder.java +++ b/src/com/dogcows/VimCoder.java @@ -23,269 +23,13 @@ public class VimCoder /** * */ - private final static String version = "VimCoder 0.1"; - private final static String website = "http://www.dogcows.com/vimcoder"; + public final static String version = "VimCoder 0.1"; + public final static String website = "http://www.dogcows.com/vimcoder"; private JPanel panel; private JTextArea logArea; private Editor editor; - - - private static final Map languageExtension = new HashMap(); - static - { - languageExtension.put("Java", "java"); - languageExtension.put("C++", "cc"); - languageExtension.put("C#", "cs"); - languageExtension.put("VB", "vb"); - languageExtension.put("Python", "py"); - } - - - private class Editor - { - private String id; - private String name; - - private File sourceFile; - private File directory; - - - public Editor(ProblemComponentModel component, Language language, Renderer renderer) throws IOException - { - this.id = String.valueOf(component.getProblem().getProblemID()); - this.name = component.getClassName(); - - File topDir = new File(System.getProperty("user.home"), ".vimcoder"); - if (!topDir.isDirectory()) - { - if (!topDir.mkdirs()) throw new IOException(topDir.getPath()); - } - - this.directory = new File(topDir, String.valueOf(component.getProblem().getProblemID())); - if (!directory.isDirectory()) - { - if (!directory.mkdirs()) throw new IOException(directory.getPath()); - } - - String lang = language.getName(); - String ext = languageExtension.get(lang); - - HashMap terms = new HashMap(); - terms.put("RETURNTYPE", component.getReturnType().getDescriptor(language)); - terms.put("CLASSNAME", component.getClassName()); - terms.put("METHODNAME", component.getMethodName()); - terms.put("METHODPARAMS", getMethodParams(component.getParamTypes(), component.getParamNames(), language)); - terms.put("METHODPARAMNAMES", join(component.getParamNames(), ", ")); - - File problemFile = new File(directory, "Problem.html"); - if (!problemFile.canRead()) - { - FileWriter writer = new FileWriter(problemFile); - try - { - writer.write(renderer.toHTML(language)); - } - catch (Exception exception) - { - } - writer.close(); - } - - sourceFile = new File(directory, terms.get("CLASSNAME") + "." + ext); - if (!sourceFile.canRead()) - { - String text = expandTemplate(readResource(lang + "Template"), terms); - FileWriter writer = new FileWriter(sourceFile); - writer.write(text); - writer.close(); - } - - File driverFile = new File(directory, "driver" + "." + ext); - if (!driverFile.canRead()) - { - StringBuilder testCases = new StringBuilder(); - if (component.hasTestCases()) - { - HashMap testTerms = new HashMap(); - testTerms.putAll(terms); - String template = readResource(lang + "Test"); - for (TestCase testCase : component.getTestCases()) - { - testTerms.put("TESTOUTPUT", "\"" + quote(testCase.getOutput()) + "\""); - testTerms.put("TESTINPUTS", join(testCase.getInput(), ", ")); - testCases.append(expandTemplate(template, testTerms)); - } - } - terms.put("TESTCASES", testCases.toString()); - - String text = expandTemplate(readResource(lang + "Driver"), terms); - FileWriter writer = new FileWriter(driverFile); - writer.write(text); - writer.close(); - } - - File makeFile = new File(directory, "Makefile"); - { - String text = expandTemplate(readResource(lang + "Makefile"), terms); - FileWriter writer = new FileWriter(makeFile); - writer.write(text); - writer.close(); - } - } - - public void setSource(String source) throws IOException - { - String actualSource = readFile(sourceFile); - if (!actualSource.equals(source)) - { - File actualFile = new File(directory, name); - FileWriter writer = new FileWriter(actualFile); - writer.write(source); - writer.close(); - } - doVimCommand("--remote-tab-silent", sourceFile.getPath()); - doVimCommand("--remote-send", ":if search('\\$CARAT\\\\$') != 0normal df$endif:redraw"); - } - - public String getSource() throws IOException - { - return readFile(sourceFile) + "\n// Edited by " + version + "\n// " + website + "\n\n"; - } - - public void setTextEnabled(boolean enable) - { - doVimCommand("--remote-send", ":set readonly:echo \"The contest is over.\""); - } - - - private boolean doVimCommand(String command, String argument) - { - String[] arguments = {argument}; - return doVimCommand(command, arguments); - } - - private boolean doVimCommand(String command, String[] arguments) - { - try - { - String[] exec = {"gvim", "--servername", "VimCoder" + id, command}; - exec = concat(exec, arguments); - - Process child = Runtime.getRuntime().exec(exec); - if (child.waitFor() == 0) - { - return true; - } - else - { - logError("vim command failed"); - } - } - catch (IOException exception) - { - logError("failed to launch external vim process"); - return false; - } - catch (InterruptedException exception) - { - logWarning("interrupted while waiting on vim process"); - } - return false; - } - - private String getMethodParams(DataType[] types, String[] names, Language language) - { - StringBuilder text = new StringBuilder(); - - text.append(types[0].getDescriptor(language) + " " + names[0]); - for (int i = 1; i < names.length; ++i) - { - text.append(", " + types[i].getDescriptor(language) + " " + names[i]); - } - - return text.toString(); - } - - private 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(); - } - - private String readResource(String path) throws IOException - { - StringBuilder text = new StringBuilder(); - - InputStream stream = getClass().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(); - } - - private String expandTemplate(String template, Map terms) - { - String text = template; - for (String key : terms.keySet()) - { - text = text.replaceAll("\\$" + key + "\\$", quote(terms.get(key))); - } - return text; - } - } - - - public static 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; - } - - 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(); - } - - public static String quote(String a) - { - a = a.replaceAll("\\\\", "\\\\\\\\"); - a = a.replaceAll("\"", "\\\\\\\""); - return a; - } public VimCoder() @@ -304,7 +48,21 @@ public class VimCoder public void startUsing() { - logArea.setText(""); + Runnable task = new Runnable() + { + public void run() + { + logArea.setText(""); + } + }; + if (SwingUtilities.isEventDispatchThread()) + { + task.run(); + } + else + { + SwingUtilities.invokeLater(task); + } } public void stopUsing() @@ -317,7 +75,7 @@ public class VimCoder return panel; } - public String getSource() + public String getSource() throws IOException { try { @@ -327,8 +85,8 @@ public class VimCoder } catch (IOException exception) { - logError("failed to open file source file for reading"); - return ""; + logError("Failed to open source file for reading."); + throw exception; } } @@ -337,16 +95,18 @@ public class VimCoder try { editor.setSource(source); - logInfo("source set"); + logInfo("Source code downloaded from server."); } catch (IOException exception) { - logError("failed setting the source"); + logError("Failed to save the source given by the server."); return; } } - public void setProblemComponent(ProblemComponentModel component, Language language, Renderer renderer) + public void setProblemComponent(ProblemComponentModel component, + Language language, + Renderer renderer) { try { @@ -354,21 +114,29 @@ public class VimCoder } catch (IOException exception) { - logError("failed while loading the problem"); + logError("An error occured while loading the problem."); } } - public void setTextEnabled(Boolean enable) - { - editor.setTextEnabled(enable); - } - - private void log(String what) + private void log(final String what) { - SimpleDateFormat format = new SimpleDateFormat("kk:mm:ss"); - String time = format.format(new Date()); - logArea.append(time + ", " + 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); + } } private void logInfo(String what) diff --git a/src/com/dogcows/resources/C++Makefile b/src/com/dogcows/resources/C++Makefile index b1cb4ed..062a464 100644 --- a/src/com/dogcows/resources/C++Makefile +++ b/src/com/dogcows/resources/C++Makefile @@ -9,6 +9,8 @@ run: all test: all ./driver -exit_on_fail + +driver.o: $CLASSNAME$.o driver: driver.o $(CXX) $(CXXFLAGS) $< -o $@ $(LDFLAGS) $(LIBS) diff --git a/src/com/dogcows/resources/C++Template b/src/com/dogcows/resources/C++Template index e106cb5..7cd56b2 100644 --- a/src/com/dogcows/resources/C++Template +++ b/src/com/dogcows/resources/C++Template @@ -36,7 +36,7 @@ class $CLASSNAME$ public: $RETURNTYPE$ $METHODNAME$($METHODPARAMS$) { - $CARAT$ + } }; -- 2.43.0