]> Dogcows Code - chaz/vimcoder/blob - src/com/dogcows/VimCoder.java
initial commit
[chaz/vimcoder] / src / com / dogcows / VimCoder.java
1
2 package com.dogcows;
3
4 import javax.swing.*;
5 import java.awt.*;
6 import java.io.*;
7 import java.text.SimpleDateFormat;
8 import java.util.*;
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;
13
14 /**
15 * @author Charles McGarvey
16 * The TopCoder Arena editor plug-in providing support for Vim.
17 *
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.
20 */
21 public class VimCoder
22 {
23 /**
24 *
25 */
26 private final static String version = "VimCoder 0.1";
27 private final static String website = "http://www.dogcows.com/vimcoder";
28
29 private JPanel panel;
30 private JTextArea logArea;
31
32 private Editor editor;
33
34
35 private static final Map<String,String> languageExtension = new HashMap<String,String>();
36 static
37 {
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");
43 }
44
45
46 private class Editor
47 {
48 private String id;
49 private String name;
50
51 private File sourceFile;
52 private File directory;
53
54
55 public Editor(ProblemComponentModel component, Language language, Renderer renderer) throws IOException
56 {
57 this.id = String.valueOf(component.getProblem().getProblemID());
58 this.name = component.getClassName();
59
60 File topDir = new File(System.getProperty("user.home"), ".vimcoder");
61 if (!topDir.isDirectory())
62 {
63 if (!topDir.mkdirs()) throw new IOException(topDir.getPath());
64 }
65
66 this.directory = new File(topDir, String.valueOf(component.getProblem().getProblemID()));
67 if (!directory.isDirectory())
68 {
69 if (!directory.mkdirs()) throw new IOException(directory.getPath());
70 }
71
72 String lang = language.getName();
73 String ext = languageExtension.get(lang);
74
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(), ", "));
81
82 File problemFile = new File(directory, "Problem.html");
83 if (!problemFile.canRead())
84 {
85 FileWriter writer = new FileWriter(problemFile);
86 try
87 {
88 writer.write(renderer.toHTML(language));
89 }
90 catch (Exception exception)
91 {
92 }
93 writer.close();
94 }
95
96 sourceFile = new File(directory, terms.get("CLASSNAME") + "." + ext);
97 if (!sourceFile.canRead())
98 {
99 String text = expandTemplate(readResource(lang + "Template"), terms);
100 FileWriter writer = new FileWriter(sourceFile);
101 writer.write(text);
102 writer.close();
103 }
104
105 File driverFile = new File(directory, "driver" + "." + ext);
106 if (!driverFile.canRead())
107 {
108 StringBuilder testCases = new StringBuilder();
109 if (component.hasTestCases())
110 {
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())
115 {
116 testTerms.put("TESTOUTPUT", "\"" + quote(testCase.getOutput()) + "\"");
117 testTerms.put("TESTINPUTS", join(testCase.getInput(), ", "));
118 testCases.append(expandTemplate(template, testTerms));
119 }
120 }
121 terms.put("TESTCASES", testCases.toString());
122
123 String text = expandTemplate(readResource(lang + "Driver"), terms);
124 FileWriter writer = new FileWriter(driverFile);
125 writer.write(text);
126 writer.close();
127 }
128
129 File makeFile = new File(directory, "Makefile");
130 {
131 String text = expandTemplate(readResource(lang + "Makefile"), terms);
132 FileWriter writer = new FileWriter(makeFile);
133 writer.write(text);
134 writer.close();
135 }
136 }
137
138 public void setSource(String source) throws IOException
139 {
140 String actualSource = readFile(sourceFile);
141 if (!actualSource.equals(source))
142 {
143 File actualFile = new File(directory, name);
144 FileWriter writer = new FileWriter(actualFile);
145 writer.write(source);
146 writer.close();
147 }
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>");
150 }
151
152 public String getSource() throws IOException
153 {
154 return readFile(sourceFile) + "\n// Edited by " + version + "\n// " + website + "\n\n";
155 }
156
157 public void setTextEnabled(boolean enable)
158 {
159 doVimCommand("--remote-send", "<C-\\><C-N>:set readonly<CR>:echo \"The contest is over.\"<CR>");
160 }
161
162
163 private boolean doVimCommand(String command, String argument)
164 {
165 String[] arguments = {argument};
166 return doVimCommand(command, arguments);
167 }
168
169 private boolean doVimCommand(String command, String[] arguments)
170 {
171 try
172 {
173 String[] exec = {"gvim", "--servername", "VimCoder" + id, command};
174 exec = concat(exec, arguments);
175
176 Process child = Runtime.getRuntime().exec(exec);
177 if (child.waitFor() == 0)
178 {
179 return true;
180 }
181 else
182 {
183 logError("vim command failed");
184 }
185 }
186 catch (IOException exception)
187 {
188 logError("failed to launch external vim process");
189 return false;
190 }
191 catch (InterruptedException exception)
192 {
193 logWarning("interrupted while waiting on vim process");
194 }
195 return false;
196 }
197
198 private String getMethodParams(DataType[] types, String[] names, Language language)
199 {
200 StringBuilder text = new StringBuilder();
201
202 text.append(types[0].getDescriptor(language) + " " + names[0]);
203 for (int i = 1; i < names.length; ++i)
204 {
205 text.append(", " + types[i].getDescriptor(language) + " " + names[i]);
206 }
207
208 return text.toString();
209 }
210
211 private String readFile(File file) throws IOException
212 {
213 StringBuilder text = new StringBuilder();
214
215 BufferedReader reader = new BufferedReader(new FileReader(file.getPath()));
216 try
217 {
218 String line = null;
219
220 while ((line = reader.readLine()) != null)
221 {
222 text.append(line + System.getProperty("line.separator"));
223 }
224 }
225 finally
226 {
227 reader.close();
228 }
229
230 return text.toString();
231 }
232
233 private String readResource(String path) throws IOException
234 {
235 StringBuilder text = new StringBuilder();
236
237 InputStream stream = getClass().getResourceAsStream("resources/" + path);
238 if (stream != null)
239 {
240 try
241 {
242 byte[] buffer = new byte[4096];
243 int numBytes = 0;
244 while (0 < (numBytes = stream.read(buffer))) text.append(new String(buffer, 0, numBytes));
245 }
246 finally
247 {
248 stream.close();
249 }
250 }
251
252 return text.toString();
253 }
254
255 private String expandTemplate(String template, Map<String,String> terms)
256 {
257 String text = template;
258 for (String key : terms.keySet())
259 {
260 text = text.replaceAll("\\$" + key + "\\$", quote(terms.get(key)));
261 }
262 return text;
263 }
264 }
265
266
267 public static <T> T[] concat(T[] a, T[] b)
268 {
269 T[] result = Arrays.copyOf(a, a.length + b.length);
270 System.arraycopy(b, 0, result, a.length, b.length);
271 return result;
272 }
273
274 public static String join(String[] a, String glue)
275 {
276 if (a.length == 0) return "";
277 StringBuilder result = new StringBuilder();
278 result.append(a[0]);
279 for (int i = 1; i < a.length; ++i) result.append(glue).append(a[i]);
280 return result.toString();
281 }
282
283 public static String quote(String a)
284 {
285 a = a.replaceAll("\\\\", "\\\\\\\\");
286 a = a.replaceAll("\"", "\\\\\\\"");
287 return a;
288 }
289
290
291 public VimCoder()
292 {
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);
299
300 panel = new JPanel(new BorderLayout());
301 panel.add(new JScrollPane(logArea), BorderLayout.CENTER);
302 }
303
304
305 public void startUsing()
306 {
307 logArea.setText("");
308 }
309
310 public void stopUsing()
311 {
312 editor = null;
313 }
314
315 public JPanel getEditorPanel()
316 {
317 return panel;
318 }
319
320 public String getSource()
321 {
322 try
323 {
324 String source = editor.getSource();
325 logInfo("Source code uploaded to server.");
326 return source;
327 }
328 catch (IOException exception)
329 {
330 logError("failed to open file source file for reading");
331 return "";
332 }
333 }
334
335 public void setSource(String source)
336 {
337 try
338 {
339 editor.setSource(source);
340 logInfo("source set");
341 }
342 catch (IOException exception)
343 {
344 logError("failed setting the source");
345 return;
346 }
347 }
348
349 public void setProblemComponent(ProblemComponentModel component, Language language, Renderer renderer)
350 {
351 try
352 {
353 editor = new Editor(component, language, renderer);
354 }
355 catch (IOException exception)
356 {
357 logError("failed while loading the problem");
358 }
359 }
360
361 public void setTextEnabled(Boolean enable)
362 {
363 editor.setTextEnabled(enable);
364 }
365
366
367 private void log(String what)
368 {
369 SimpleDateFormat format = new SimpleDateFormat("kk:mm:ss");
370 String time = format.format(new Date());
371 logArea.append(time + ", " + what);
372 }
373
374 private void logInfo(String what)
375 {
376 log(" INFO: " + what + "\n");
377 }
378
379 private void logWarning(String what)
380 {
381 log(" WARN: " + what + "\n");
382 }
383
384 private void logError(String what)
385 {
386 log("ERROR: " + what + "\n");
387 }
388
389
390 public static void main(String args[])
391 {
392 VimCoder plugin = new VimCoder();
393
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);
399
400 plugin.startUsing();
401 }
402 }
403
This page took 0.054978 seconds and 4 git commands to generate.