7 import java
.text
.SimpleDateFormat
;
9 import com
.topcoder
.client
.contestant
.ProblemComponentModel
;
10 import com
.topcoder
.shared
.language
.*;
11 import com
.topcoder
.shared
.problem
.*;
12 import com
.topcoder
.shared
.problem
.Renderer
;
15 * @author Charles McGarvey
16 * The TopCoder Arena editor plug-in providing support for Vim.
18 * Distributable under the terms and conditions of the 2-clause BSD license;
19 * see the file COPYING for a complete text of the license.
26 private final static String version
= "VimCoder 0.1";
27 private final static String website
= "http://www.dogcows.com/vimcoder";
30 private JTextArea logArea
;
32 private Editor editor
;
35 private static final Map
<String
,String
> languageExtension
= new HashMap
<String
,String
>();
38 languageExtension
.put("Java", "java");
39 languageExtension
.put("C++", "cc");
40 languageExtension
.put("C#", "cs");
41 languageExtension
.put("VB", "vb");
42 languageExtension
.put("Python", "py");
51 private File sourceFile
;
52 private File directory
;
55 public Editor(ProblemComponentModel component
, Language language
, Renderer renderer
) throws IOException
57 this.id
= String
.valueOf(component
.getProblem().getProblemID());
58 this.name
= component
.getClassName();
60 File topDir
= new File(System
.getProperty("user.home"), ".vimcoder");
61 if (!topDir
.isDirectory())
63 if (!topDir
.mkdirs()) throw new IOException(topDir
.getPath());
66 this.directory
= new File(topDir
, String
.valueOf(component
.getProblem().getProblemID()));
67 if (!directory
.isDirectory())
69 if (!directory
.mkdirs()) throw new IOException(directory
.getPath());
72 String lang
= language
.getName();
73 String ext
= languageExtension
.get(lang
);
75 HashMap
<String
,String
> terms
= new HashMap
<String
,String
>();
76 terms
.put("RETURNTYPE", component
.getReturnType().getDescriptor(language
));
77 terms
.put("CLASSNAME", component
.getClassName());
78 terms
.put("METHODNAME", component
.getMethodName());
79 terms
.put("METHODPARAMS", getMethodParams(component
.getParamTypes(), component
.getParamNames(), language
));
80 terms
.put("METHODPARAMNAMES", join(component
.getParamNames(), ", "));
82 File problemFile
= new File(directory
, "Problem.html");
83 if (!problemFile
.canRead())
85 FileWriter writer
= new FileWriter(problemFile
);
88 writer
.write(renderer
.toHTML(language
));
90 catch (Exception exception
)
96 sourceFile
= new File(directory
, terms
.get("CLASSNAME") + "." + ext
);
97 if (!sourceFile
.canRead())
99 String text
= expandTemplate(readResource(lang
+ "Template"), terms
);
100 FileWriter writer
= new FileWriter(sourceFile
);
105 File driverFile
= new File(directory
, "driver" + "." + ext
);
106 if (!driverFile
.canRead())
108 StringBuilder testCases
= new StringBuilder();
109 if (component
.hasTestCases())
111 HashMap
<String
,String
> testTerms
= new HashMap
<String
,String
>();
112 testTerms
.putAll(terms
);
113 String template
= readResource(lang
+ "Test");
114 for (TestCase testCase
: component
.getTestCases())
116 testTerms
.put("TESTOUTPUT", "\"" + quote(testCase
.getOutput()) + "\"");
117 testTerms
.put("TESTINPUTS", join(testCase
.getInput(), ", "));
118 testCases
.append(expandTemplate(template
, testTerms
));
121 terms
.put("TESTCASES", testCases
.toString());
123 String text
= expandTemplate(readResource(lang
+ "Driver"), terms
);
124 FileWriter writer
= new FileWriter(driverFile
);
129 File makeFile
= new File(directory
, "Makefile");
131 String text
= expandTemplate(readResource(lang
+ "Makefile"), terms
);
132 FileWriter writer
= new FileWriter(makeFile
);
138 public void setSource(String source
) throws IOException
140 String actualSource
= readFile(sourceFile
);
141 if (!actualSource
.equals(source
))
143 File actualFile
= new File(directory
, name
);
144 FileWriter writer
= new FileWriter(actualFile
);
145 writer
.write(source
);
148 doVimCommand("--remote-tab-silent", sourceFile
.getPath());
149 doVimCommand("--remote-send", "<C-\\><C-N>:if search('\\$CARAT\\\\$') != 0<CR>normal df$<CR>endif<CR>:redraw<CR>");
152 public String
getSource() throws IOException
154 return readFile(sourceFile
) + "\n// Edited by " + version
+ "\n// " + website
+ "\n\n";
157 public void setTextEnabled(boolean enable
)
159 doVimCommand("--remote-send", "<C-\\><C-N>:set readonly<CR>:echo \"The contest is over.\"<CR>");
163 private boolean doVimCommand(String command
, String argument
)
165 String
[] arguments
= {argument
};
166 return doVimCommand(command
, arguments
);
169 private boolean doVimCommand(String command
, String
[] arguments
)
173 String
[] exec
= {"gvim", "--servername", "VimCoder" + id
, command
};
174 exec
= concat(exec
, arguments
);
176 Process child
= Runtime
.getRuntime().exec(exec
);
177 if (child
.waitFor() == 0)
183 logError("vim command failed");
186 catch (IOException exception
)
188 logError("failed to launch external vim process");
191 catch (InterruptedException exception
)
193 logWarning("interrupted while waiting on vim process");
198 private String
getMethodParams(DataType
[] types
, String
[] names
, Language language
)
200 StringBuilder text
= new StringBuilder();
202 text
.append(types
[0].getDescriptor(language
) + " " + names
[0]);
203 for (int i
= 1; i
< names
.length
; ++i
)
205 text
.append(", " + types
[i
].getDescriptor(language
) + " " + names
[i
]);
208 return text
.toString();
211 private String
readFile(File file
) throws IOException
213 StringBuilder text
= new StringBuilder();
215 BufferedReader reader
= new BufferedReader(new FileReader(file
.getPath()));
220 while ((line
= reader
.readLine()) != null)
222 text
.append(line
+ System
.getProperty("line.separator"));
230 return text
.toString();
233 private String
readResource(String path
) throws IOException
235 StringBuilder text
= new StringBuilder();
237 InputStream stream
= getClass().getResourceAsStream("resources/" + path
);
242 byte[] buffer
= new byte[4096];
244 while (0 < (numBytes
= stream
.read(buffer
))) text
.append(new String(buffer
, 0, numBytes
));
252 return text
.toString();
255 private String
expandTemplate(String template
, Map
<String
,String
> terms
)
257 String text
= template
;
258 for (String key
: terms
.keySet())
260 text
= text
.replaceAll("\\$" + key
+ "\\$", quote(terms
.get(key
)));
267 public static <T
> T
[] concat(T
[] a
, T
[] b
)
269 T
[] result
= Arrays
.copyOf(a
, a
.length
+ b
.length
);
270 System
.arraycopy(b
, 0, result
, a
.length
, b
.length
);
274 public static String
join(String
[] a
, String glue
)
276 if (a
.length
== 0) return "";
277 StringBuilder result
= new StringBuilder();
279 for (int i
= 1; i
< a
.length
; ++i
) result
.append(glue
).append(a
[i
]);
280 return result
.toString();
283 public static String
quote(String a
)
285 a
= a
.replaceAll("\\\\", "\\\\\\\\");
286 a
= a
.replaceAll("\"", "\\\\\\\"");
293 logArea
= new JTextArea();
294 logArea
.setForeground(Color
.GREEN
);
295 logArea
.setBackground(Color
.BLACK
);
296 logArea
.setEditable(false);
297 Font font
= new Font("Courier", Font
.PLAIN
, 12);
298 if (font
!= null) logArea
.setFont(font
);
300 panel
= new JPanel(new BorderLayout());
301 panel
.add(new JScrollPane(logArea
), BorderLayout
.CENTER
);
305 public void startUsing()
310 public void stopUsing()
315 public JPanel
getEditorPanel()
320 public String
getSource()
324 String source
= editor
.getSource();
325 logInfo("Source code uploaded to server.");
328 catch (IOException exception
)
330 logError("failed to open file source file for reading");
335 public void setSource(String source
)
339 editor
.setSource(source
);
340 logInfo("source set");
342 catch (IOException exception
)
344 logError("failed setting the source");
349 public void setProblemComponent(ProblemComponentModel component
, Language language
, Renderer renderer
)
353 editor
= new Editor(component
, language
, renderer
);
355 catch (IOException exception
)
357 logError("failed while loading the problem");
361 public void setTextEnabled(Boolean enable
)
363 editor
.setTextEnabled(enable
);
367 private void log(String what
)
369 SimpleDateFormat format
= new SimpleDateFormat("kk:mm:ss");
370 String time
= format
.format(new Date());
371 logArea
.append(time
+ ", " + what
);
374 private void logInfo(String what
)
376 log(" INFO: " + what
+ "\n");
379 private void logWarning(String what
)
381 log(" WARN: " + what
+ "\n");
384 private void logError(String what
)
386 log("ERROR: " + what
+ "\n");
390 public static void main(String args
[])
392 VimCoder plugin
= new VimCoder();
394 JFrame frame
= new JFrame("VimCoder");
395 frame
.add(plugin
.getEditorPanel());
396 frame
.setSize(640, 480);
397 frame
.setVisible(true);
398 frame
.setDefaultCloseOperation(JFrame
.EXIT_ON_CLOSE
);