コマンドラインのヒストリと補完のためjline2を使っていろいろ試し中。全然途中。
@@ -16,11 +16,12 @@ | ||
16 | 16 | <property name="javadocDir" value="doc"/> |
17 | 17 | <property name="distDir" value="dist"/> |
18 | 18 | <property name="exeDir" value="exe"/> |
19 | + <property name="libDir" value="lib"/> | |
19 | 20 | |
20 | - <property name="jpicosheetJar" value="C:/Users/Yusuke/Develop/Java/PicoSheet-Workspace/JPicosheet/jarfile/JPicosheet-0.1.4.jar"/> | |
21 | + <property name="jpicosheetJar" value="C:/Users/nishikawa.MEGATRADE/Apps/Eclipse-workspace-private/consolePicocalc/jarfile/JPicosheet-0.1.4.jar"/> | |
21 | 22 | <!-- <property name="jpicosheetJar" value="/home/yusuke/Develop/Eclipse-workspaces/PicoSheet-Workspace/JPicosheet/jarfile/JPicosheet-0.1.4.jar"/ --> |
22 | 23 | |
23 | - <target name="all" depends="init,makedir,copyJarFile,jar,makeExe,clean" /> | |
24 | + <target name="all" depends="init,makedir,copyJarFile,copylib,jar,makeExe,clean" /> | |
24 | 25 | |
25 | 26 | <target name="init"> |
26 | 27 | <tstamp></tstamp> |
@@ -37,6 +38,12 @@ | ||
37 | 38 | <mkdir dir="${exeDir}"/> |
38 | 39 | </target> |
39 | 40 | |
41 | + <target name="copylib"> | |
42 | + <copy todir="${exeDir}"> | |
43 | + <fileset file="${libDir}/jline-2.9.jar"/> | |
44 | + </copy> | |
45 | + </target> | |
46 | + | |
40 | 47 | <target name="copyJarFile" depends="makedir"> |
41 | 48 | <copy todir="${jarWorkDir}"> |
42 | 49 | <fileset dir="${binDir}"> |
@@ -1,7 +1,7 @@ | ||
1 | 1 | echo off |
2 | 2 | |
3 | 3 | set EXEDIR=%~dp0 |
4 | -set CLASSPATH=%EXEDIR%\ConsolePicocalc-0.1.jar;%EXEDIR%\JPicosheet-0.1.4.jar | |
4 | +set CLASSPATH=%EXEDIR%\ConsolePicocalc-0.1.jar;%EXEDIR%\JPicosheet-0.1.4.jar;%EXEDIR%\jline-2.9.jar | |
5 | 5 | |
6 | 6 | echo %CLASSPATH% |
7 | 7 |
@@ -14,9 +14,12 @@ | ||
14 | 14 | import java.nio.file.Paths; |
15 | 15 | import java.util.ArrayList; |
16 | 16 | import java.util.Arrays; |
17 | +import java.util.Collections; | |
17 | 18 | import java.util.HashMap; |
18 | 19 | import java.util.LinkedList; |
20 | +import java.util.List; | |
19 | 21 | import java.util.Map; |
22 | +import java.util.SortedSet; | |
20 | 23 | import java.util.TreeSet; |
21 | 24 | |
22 | 25 | import com.nissy_ki_chi.jpicosheet.core.Book; |
@@ -25,6 +28,13 @@ | ||
25 | 28 | import com.nissy_ki_chi.jpicosheet.util.SimpleReader; |
26 | 29 | import com.nissy_ki_chi.jpicosheet.util.SimpleWriter; |
27 | 30 | |
31 | +import jline.console.ConsoleReader; | |
32 | +import jline.console.completer.ArgumentCompleter; | |
33 | +import jline.console.completer.ArgumentCompleter.ArgumentDelimiter; | |
34 | +import jline.console.completer.ArgumentCompleter.ArgumentList; | |
35 | +import jline.console.completer.Completer; | |
36 | +import jline.console.completer.StringsCompleter; | |
37 | + | |
28 | 38 | public class ConsolePicocalc { |
29 | 39 | |
30 | 40 |
@@ -37,9 +47,9 @@ | ||
37 | 47 | GroupCommand _groupCommand = new GroupCommand(); |
38 | 48 | TableCommand _tableCommand = new TableCommand(); |
39 | 49 | |
40 | - LinkedList<String> cmdHistory = new LinkedList<>(); | |
41 | - LinkedList<String> aggregatedHistory = new LinkedList<>(); | |
42 | - String _nextCommand = ""; | |
50 | + LinkedList<String> _cmdHistory = new LinkedList<>(); | |
51 | + LinkedList<String> _aggregatedHistory = new LinkedList<>(); | |
52 | + String _nextCommand = null; | |
43 | 53 | |
44 | 54 | CommandFragment _commandStorage = new CommandFragment("."); |
45 | 55 |
@@ -104,27 +114,117 @@ | ||
104 | 114 | |
105 | 115 | // コンソールから1行づつ読み込んで処理する |
106 | 116 | InputStreamReader isr = null; |
107 | - BufferedReader br = null; | |
117 | +// BufferedReader br = null; | |
118 | + ConsoleReader consoleReader = null; | |
108 | 119 | try { |
120 | + consoleReader = new ConsoleReader(); | |
121 | +// List<Completer> completers = new LinkedList<>(); | |
122 | + | |
123 | + String[] commands = this._commandStorage.getCommandNameList(); | |
124 | + | |
125 | + ArgumentDelimiter ad = new ArgumentDelimiter() { | |
126 | + | |
127 | + @Override | |
128 | + public boolean isDelimiter(CharSequence arg0, int arg1) { | |
129 | + return arg0.charAt(arg1) == ' ' ? true : false; | |
130 | + } | |
131 | + | |
132 | + @Override | |
133 | + public ArgumentList delimit(CharSequence arg0, int arg1) { | |
134 | + String[] arguments = arg0.toString().split("\\s"); | |
135 | + ArgumentList al = new ArgumentList( new String[] {"appl", "bppl"}, 0, 0, 2); | |
136 | +// ArgumentList al = new ArgumentList(arguments, arguments.length-1, 0, arg0.length()); | |
137 | +// ArgumentList al = new ArgumentList(arguments, 0, arg0.length()-1, arg0.length()-1); | |
138 | + return al; | |
139 | + } | |
140 | + }; | |
141 | +// StringsCompleter sc = new StringsCompleter(commands); | |
142 | +// ArgumentCompleter ac = new ArgumentCompleter(ad, sc); | |
143 | +// consoleReader.addCompleter(ac); | |
144 | +// consoleReader.addCompleter(new ConPicoCompleter()); | |
145 | + CompleterOfCellNames cocn = new CompleterOfCellNames(_books.get(_currentBookName).getResolver().getCurrentSheet()); | |
146 | + ArgumentCompleter ac = new ArgumentCompleter(ad, cocn); | |
147 | + consoleReader.addCompleter(ac); | |
148 | + | |
149 | + } catch (IOException e2) { | |
150 | + // TODO 自動生成された catch ブロック | |
151 | + e2.printStackTrace(); | |
152 | + } | |
153 | + | |
154 | + try { | |
109 | 155 | isr = new InputStreamReader(System.in, "JISAutoDetect"); |
110 | - br = new BufferedReader(isr); | |
156 | +// br = new BufferedReader(isr); | |
111 | 157 | } catch (UnsupportedEncodingException e1) { |
112 | 158 | e1.printStackTrace(); |
113 | 159 | } |
114 | 160 | |
115 | 161 | try { |
116 | - String line; | |
162 | + String line = null; | |
163 | + String candidate = null; | |
164 | + List<String> cellNames = null; | |
165 | + int cellNamesPos = 0; | |
166 | + boolean candiMode = false; | |
117 | 167 | while(true) { |
118 | 168 | try { |
119 | 169 | |
170 | + Book currentBook = _books.get(_currentBookName); | |
171 | +// consoleReader.readLine(makePrompt(currentBook)); | |
172 | + | |
120 | 173 | // ヒストリからの実行か? |
121 | 174 | if (_nextCommand == null) { |
122 | 175 | // ヒストリではない。 |
123 | - // プロンプト表示 | |
124 | - Book currentBook = _books.get(_currentBookName); | |
125 | - printPrompt(currentBook); | |
126 | 176 | // 入力がなくなったら終了 |
127 | - if ((line = br.readLine().trim()) == null) { | |
177 | + | |
178 | + StringBuilder linebuf = new StringBuilder(); | |
179 | + char ch = 0; | |
180 | + int p = 0; | |
181 | + int cellSearchedPos = 0; | |
182 | + | |
183 | +// while(true) { | |
184 | +//// ch = (char) br.read(); | |
185 | +// // TODO: リターンキーを押さなくてもキーを入力できるようにする | |
186 | +//// ch = (char) isr.read(); | |
187 | +// ch = (char) System.in.read(); | |
188 | +// if (ch == '\r') { | |
189 | +// if ((char) isr.read() == '\n') { | |
190 | +// line = linebuf.toString(); | |
191 | +// break; | |
192 | +// } | |
193 | +// } | |
194 | +// if (ch != '\t') { | |
195 | +// linebuf.append(ch); | |
196 | +// // 補完機能関連の変数をリセット | |
197 | +// candiMode = false; | |
198 | +// cellSearchedPos = 0; | |
199 | +// cellNames = null; | |
200 | +// } else { | |
201 | +// if (!candiMode) { | |
202 | +// candiMode = true; | |
203 | +// // 候補文字列の取得 | |
204 | +// candidate = linebuf.substring(p); | |
205 | +// // カレントシートのセル名リストが無ければ作成 | |
206 | +// if (cellNames == null) { | |
207 | +// cellNames = new ArrayList<>(new TreeSet<>(_books.get(_currentBookName).getResolver().getCurrentSheet().getCellNames())); | |
208 | +// cellNamesPos = 0; | |
209 | +// } | |
210 | +// } | |
211 | +// // セル名リストの中でマッチするセル名を探す | |
212 | +// for (; cellSearchedPos < cellNames.size(); cellSearchedPos++) { | |
213 | +// String cellName = cellNames.get(cellSearchedPos); | |
214 | +// if (cellName.indexOf(candidate) == 0) { | |
215 | +// linebuf.replace(p, linebuf.length(), cellName); | |
216 | +// } | |
217 | +// } | |
218 | +// line = linebuf.toString(); | |
219 | +// } | |
220 | +// System.out.println(line); | |
221 | +// } | |
222 | + | |
223 | +// if ((line = br.readLine().trim()) == null) { | |
224 | +// break; | |
225 | +// } | |
226 | + | |
227 | + if ((line = consoleReader.readLine(makePrompt(currentBook))) == null ) { | |
128 | 228 | break; |
129 | 229 | } |
130 | 230 | } else { |
@@ -145,9 +245,9 @@ | ||
145 | 245 | |
146 | 246 | // ヒストリからの実行でない場合、入力内容を履歴に保持 |
147 | 247 | if (_nextCommand == null) { |
148 | - cmdHistory.add(line); | |
149 | - aggregatedHistory.remove(line); | |
150 | - aggregatedHistory.add(line); | |
248 | + _cmdHistory.add(line); | |
249 | + _aggregatedHistory.remove(line); | |
250 | + _aggregatedHistory.add(line); | |
151 | 251 | } |
152 | 252 | |
153 | 253 | // 1文字目がドットか否かでコマンドもしくはセル入力を判断 |
@@ -167,7 +267,8 @@ | ||
167 | 267 | } |
168 | 268 | } finally { |
169 | 269 | try { |
170 | - br.close(); | |
270 | +// br.close(); | |
271 | + isr.close(); | |
171 | 272 | } catch (IOException e) { |
172 | 273 | e.printStackTrace(); |
173 | 274 | } |
@@ -175,8 +276,8 @@ | ||
175 | 276 | } |
176 | 277 | |
177 | 278 | |
178 | - private void printPrompt(Book currentBook) { | |
179 | - System.out.print("[" + _currentBookName + "]" + currentBook.getResolver().getCurrentSheet().getName() + ": "); | |
279 | + private String makePrompt(Book currentBook) { | |
280 | + return "[" + _currentBookName + "]" + currentBook.getResolver().getCurrentSheet().getName() + ": "; | |
180 | 281 | } |
181 | 282 | |
182 | 283 |
@@ -227,66 +328,31 @@ | ||
227 | 328 | } |
228 | 329 | |
229 | 330 | |
230 | -// if (cmdArr[0].equals("book")) { | |
231 | -// _bookCommand.processBookCmd(cmdArr, argStr); | |
232 | -// return; | |
233 | -// } | |
234 | -// | |
235 | -// if (cmdArr[0].equals("sheet")) { | |
236 | -// Book book = _books.get(_currentBookName); | |
237 | -// _sheetCommand.processSheetCmd(book, cmdArr, argStr); | |
238 | -// return; | |
239 | -// } | |
240 | -// | |
241 | -// if (cmdArr[0].equals("group")) { | |
242 | -// Sheet sheet = _books.get(_currentBookName).getResolver().getCurrentSheet(); | |
243 | -// _groupCommand.processGroupCmd(sheet, cmdArr, argStr); | |
244 | -// return; | |
245 | -// } | |
246 | -// | |
247 | -// if (cmdArr[0].equals("table")) { | |
248 | -// Sheet sheet = _books.get(_currentBookName).getResolver().getCurrentSheet(); | |
249 | -// _tableCommand.processTableCmd(sheet, cmdArr, argStr); | |
250 | -// return; | |
251 | -// } | |
252 | -// | |
253 | -// if (cmdArr[0].equals("list") && cmdArr.length == 1) { | |
254 | -// Sheet sheet = _books.get(_currentBookName).getResolver().getCurrentSheet(); | |
255 | -// _cellCommand.listCells(sheet); | |
256 | -// _groupCommand.listGroups(sheet); | |
257 | -// _tableCommand.listTables(sheet); | |
258 | -// return; | |
259 | -// } else { | |
260 | -// Sheet sheet = _books.get(_currentBookName).getResolver().getCurrentSheet(); | |
261 | -// _cellCommand.processListCmd(sheet, cmdArr, argStr); | |
262 | -// return; | |
263 | -// } | |
264 | 331 | |
265 | 332 | |
266 | 333 | } |
267 | 334 | |
268 | -// private void listSheets(Book book) { | |
269 | -// TreeSet<String> sheetNames = new TreeSet<String>(); | |
270 | -// for (Sheet s: book.getSheets()) { | |
271 | -// sheetNames.add(s.getName()); | |
272 | -// } | |
273 | -// for (String sName: sheetNames) { | |
274 | -// System.out.println(sName); | |
275 | -// } | |
276 | -// } | |
277 | - | |
278 | 335 | private void doQuit(String argStr) { |
279 | 336 | _needQuit = true; |
280 | 337 | } |
281 | 338 | |
282 | 339 | private void doHelp(String argStr) { |
283 | - System.out.println(_commandStorage.getHelp()); | |
340 | + if (argStr.isEmpty()){ | |
341 | + System.out.println(_commandStorage.getHelp()); | |
342 | + } else { | |
343 | + String helpString = _commandStorage.getHelp(argStr); | |
344 | + if (helpString != null) { | |
345 | + System.out.println(helpString); | |
346 | + } else { | |
347 | + System.out.println("command " + argStr + " が見つかりません。"); | |
348 | + } | |
349 | + } | |
284 | 350 | } |
285 | 351 | |
286 | 352 | private void doHistory(String argStr) { |
287 | 353 | StringBuilder sb = new StringBuilder(); |
288 | 354 | int cnt = 1; |
289 | - for (String s : cmdHistory) { | |
355 | + for (String s : _cmdHistory) { | |
290 | 356 | sb.append(cnt).append("\t").append(s).append("\n"); |
291 | 357 | cnt++; |
292 | 358 | } |
@@ -304,7 +370,7 @@ | ||
304 | 370 | return; |
305 | 371 | } |
306 | 372 | |
307 | - this._nextCommand = this.cmdHistory.get(reqHistNo - 1); | |
373 | + this._nextCommand = this._cmdHistory.get(reqHistNo - 1); | |
308 | 374 | System.out.println(_nextCommand); |
309 | 375 | |
310 | 376 | } |
@@ -1,6 +1,10 @@ | ||
1 | 1 | package com.nissy_ki_chi.ConsolePicocalc; |
2 | 2 | |
3 | +import java.util.ArrayList; | |
4 | +import java.util.Arrays; | |
3 | 5 | import java.util.HashMap; |
6 | +import java.util.LinkedList; | |
7 | +import java.util.List; | |
4 | 8 | import java.util.Stack; |
5 | 9 | |
6 | 10 | public class CommandFragment { |
@@ -9,6 +13,7 @@ | ||
9 | 13 | private String _methodName = null; |
10 | 14 | private String _description = null; |
11 | 15 | private HashMap<String, CommandFragment> _subFragment = null; |
16 | + private CommandFragment parent = null; | |
12 | 17 | |
13 | 18 | @SuppressWarnings("unused") |
14 | 19 | private CommandFragment() {}; |
@@ -20,6 +25,11 @@ | ||
20 | 25 | public CommandFragment(String commandFragmentName) { |
21 | 26 | this._commandFragmentName = commandFragmentName; |
22 | 27 | } |
28 | + | |
29 | + public CommandFragment(String commandFragmentName, CommandFragment parent) { | |
30 | + this._commandFragmentName = commandFragmentName; | |
31 | + this.parent = parent; | |
32 | + } | |
23 | 33 | |
24 | 34 | // void setMethodName(String methodName) { |
25 | 35 | // _methodName = methodName; |
@@ -49,7 +59,9 @@ | ||
49 | 59 | } |
50 | 60 | |
51 | 61 | if (! this._subFragment.containsKey(cmdFragment)) { |
52 | - this._subFragment.put(cmdFragment, new CommandFragment(cmdFragment)); | |
62 | + CommandFragment child = new CommandFragment(cmdFragment, this); | |
63 | + this._subFragment.put(cmdFragment, child); | |
64 | + | |
53 | 65 | } |
54 | 66 | this._subFragment.get(cmdFragment).addCommand(commandStack, methodName, description); |
55 | 67 | } |
@@ -86,6 +98,16 @@ | ||
86 | 98 | return helpSb.toString(); |
87 | 99 | } |
88 | 100 | |
101 | + String getHelp(String command) { | |
102 | + CommandFragment helpCmd = getCommandFragment(command); | |
103 | + if (helpCmd != null && helpCmd._description != null) { | |
104 | + return helpCmd._description; | |
105 | + } else { | |
106 | + return null; | |
107 | + } | |
108 | + } | |
109 | + | |
110 | + | |
89 | 111 | private void getHelp(CommandFragment cmdFragment, StringBuilder helpSb) { |
90 | 112 | // メソッドが定義されているCommandFragmentについてヘルプを追加 |
91 | 113 | if (cmdFragment._methodName != null) { |
@@ -99,6 +121,63 @@ | ||
99 | 121 | } |
100 | 122 | } |
101 | 123 | |
124 | + private CommandFragment getCommandFragment(String command) { | |
125 | + List<String> cmdList = new LinkedList<>(); | |
126 | + cmdList.addAll(Arrays.asList(command.substring(1).split("\\."))); | |
127 | + return getCommandFragment(cmdList); | |
128 | + } | |
129 | + | |
130 | + private CommandFragment getCommandFragment(List<String> cmdList) { | |
131 | + if (cmdList.size() == 0) { | |
132 | + return this; | |
133 | + } else { | |
134 | + String cmdStr = cmdList.remove(0); | |
135 | + if (_subFragment != null && _subFragment.containsKey(cmdStr)) { | |
136 | + return _subFragment.get(cmdStr).getCommandFragment(cmdList); | |
137 | + } else { | |
138 | + return null; | |
139 | + } | |
140 | + } | |
141 | + } | |
142 | + | |
143 | + | |
144 | + String[] getCommandNameList() { | |
145 | + List<String> commandNames = new ArrayList<>(); | |
146 | + getCommandNameList(commandNames); | |
147 | + String[] commandNamesArr = commandNames.toArray(new String[]{}); | |
148 | + Arrays.sort(commandNamesArr); | |
149 | + return commandNamesArr; | |
150 | + } | |
151 | + | |
152 | + private void getCommandNameList(List<String> commandNames) { | |
153 | + if (this._subFragment != null) { | |
154 | + if (this._methodName != null) { | |
155 | + commandNames.add(getCommandName()); | |
156 | + } | |
157 | + for (CommandFragment cf : this._subFragment.values()) { | |
158 | + cf.getCommandNameList(commandNames); | |
159 | + } | |
160 | + } else { | |
161 | + commandNames.add(getCommandName()); | |
162 | + } | |
163 | + } | |
164 | + | |
165 | + private String getCommandName(){ | |
166 | + StringBuilder sb = new StringBuilder(); | |
167 | + getCommandName(sb); | |
168 | + return sb.toString(); | |
169 | + } | |
170 | + | |
171 | + private void getCommandName(StringBuilder sb) { | |
172 | + if (this.parent != null && sb.length() > 0) { | |
173 | + sb.insert(0, "."); | |
174 | + } | |
175 | + sb.insert(0, this._commandFragmentName); | |
176 | + if (this.parent != null) { | |
177 | + this.parent.getCommandName(sb); | |
178 | + } | |
179 | + } | |
180 | + | |
102 | 181 | @Override |
103 | 182 | public String toString() { |
104 | 183 | StringBuilder sb = new StringBuilder(this._commandFragmentName).append("=").append(this._methodName); |
@@ -0,0 +1,27 @@ | ||
1 | +package com.nissy_ki_chi.ConsolePicocalc; | |
2 | + | |
3 | +import java.util.List; | |
4 | + | |
5 | +import com.nissy_ki_chi.jpicosheet.core.Sheet; | |
6 | + | |
7 | +import jline.console.completer.Completer; | |
8 | + | |
9 | +public class CompleterOfCellNames implements Completer { | |
10 | + | |
11 | + Sheet _sheet; | |
12 | + | |
13 | + public CompleterOfCellNames(Sheet sheet) { | |
14 | + _sheet = sheet; | |
15 | + } | |
16 | + | |
17 | + @Override | |
18 | + public int complete(String buffer, int cursor, List<CharSequence> candidates) { | |
19 | + for (String cellName: _sheet.getCellNames()) { | |
20 | + if (cellName.startsWith(buffer)) { | |
21 | + candidates.add(cellName); | |
22 | + } | |
23 | + } | |
24 | + return 0; | |
25 | + } | |
26 | + | |
27 | +} |
@@ -0,0 +1,15 @@ | ||
1 | +package com.nissy_ki_chi.ConsolePicocalc; | |
2 | + | |
3 | +import java.util.List; | |
4 | + | |
5 | +import jline.console.completer.Completer; | |
6 | + | |
7 | +public class ConPicoCompleter implements Completer { | |
8 | + | |
9 | + @Override | |
10 | + public int complete(String buffer, int cursor, List<CharSequence> candidates) { | |
11 | + System.out.println("------" + buffer); | |
12 | + return 0; | |
13 | + } | |
14 | + | |
15 | +} |