Kaynağa Gözat

Implemented intelligent tab completion

git-svn-id: http://svn.dmdirc.com/trunk@1503 00569f92-eb28-0410-84fd-f71c24880f
tags/0.5
Chris Smith 17 yıl önce
ebeveyn
işleme
2d296e2f61

+ 19
- 0
src/com/dmdirc/commandparser/CommandManager.java Dosyayı Görüntüle

@@ -367,6 +367,25 @@ public final class CommandManager {
367 367
         queryParsers.add(parser);
368 368
     }
369 369
     
370
+    /**
371
+     * Retrieves the command identified by the specified signature, regardless
372
+     * of type.
373
+     * 
374
+     * @param signature The signature to look for
375
+     * @return A command with a matching signature, or null if none were found
376
+     */
377
+    public static Command getCommand(final String signature) {
378
+        if (getGlobalCommand(signature) != null) {
379
+            return (Command) getGlobalCommand(signature);
380
+        } else if (getServerCommand(signature) != null) {
381
+            return (Command) getServerCommand(signature);
382
+        } else if (getChannelCommand(signature) != null) {
383
+            return (Command) getChannelCommand(signature);
384
+        } else {
385
+            return (Command) getChannelCommand(signature);
386
+        }
387
+    }
388
+    
370 389
     /**
371 390
      * Retrieves the server command identified by the specified signature.
372 391
      * @param signature The signature to look for

+ 43
- 0
src/com/dmdirc/commandparser/IntelligentCommand.java Dosyayı Görüntüle

@@ -0,0 +1,43 @@
1
+/*
2
+ * Copyright (c) 2006-2007 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.commandparser;
24
+
25
+import java.util.List;
26
+
27
+/**
28
+ * Intelligent commands implement a method that provides a list of possible
29
+ * options for them, for use (for example) by table completers.
30
+ * @author chris
31
+ */
32
+public interface IntelligentCommand {
33
+
34
+    /**
35
+     * Returns a list of suggestions for the specified argument, given the list
36
+     * of previous arguments.
37
+     * @param arg The argument that is being completed
38
+     * @param previousArgs The contents of the previous arguments, if any
39
+     * @return A list of suggestions for the argument
40
+     */
41
+    List<String> getSuggestions(int arg, List<String> previousArgs);
42
+    
43
+}

+ 33
- 17
src/com/dmdirc/commandparser/commands/global/Set.java Dosyayı Görüntüle

@@ -26,12 +26,15 @@ import com.dmdirc.Config;
26 26
 import com.dmdirc.commandparser.CommandManager;
27 27
 import com.dmdirc.commandparser.CommandWindow;
28 28
 import com.dmdirc.commandparser.GlobalCommand;
29
+import com.dmdirc.commandparser.IntelligentCommand;
30
+import java.util.ArrayList;
31
+import java.util.List;
29 32
 
30 33
 /**
31 34
  * The set command allows the user to inspect and change global config settings.
32 35
  * @author chris
33 36
  */
34
-public final class Set extends GlobalCommand {
37
+public final class Set extends GlobalCommand implements IntelligentCommand {
35 38
     
36 39
     /**
37 40
      * Creates a new instance of Set.
@@ -46,17 +49,17 @@ public final class Set extends GlobalCommand {
46 49
     public void execute(final CommandWindow origin, final boolean isSilent,
47 50
             final String... args) {
48 51
         switch (args.length) {
49
-            case 0:
50
-                doDomainList(origin, isSilent);
51
-                break;
52
-            case 1:
53
-                doOptionsList(origin, isSilent, args[0]);
54
-                break;
55
-            case 2:
56
-                doShowOption(origin, isSilent, args[0], args[1]);
57
-                break;
58
-            default:
59
-                doSetOption(origin, isSilent, args[0], args[1], implodeArgs(2, args));
52
+        case 0:
53
+            doDomainList(origin, isSilent);
54
+            break;
55
+        case 1:
56
+            doOptionsList(origin, isSilent, args[0]);
57
+            break;
58
+        case 2:
59
+            doShowOption(origin, isSilent, args[0], args[1]);
60
+            break;
61
+        default:
62
+            doSetOption(origin, isSilent, args[0], args[1], implodeArgs(2, args));
60 63
         }
61 64
     }
62 65
     
@@ -142,29 +145,42 @@ public final class Set extends GlobalCommand {
142 145
         sendLine(origin, isSilent, "commandOutput", domain + "." + option + " has been set to: " + newvalue);
143 146
     }
144 147
     
145
-    /** {@inheritDoc}. */
148
+    /** {@inheritDoc} */
146 149
     public String getName() {
147 150
         return "set";
148 151
     }
149 152
     
150
-    /** {@inheritDoc}. */
153
+    /** {@inheritDoc} */
151 154
     public boolean showInHelp() {
152 155
         return true;
153 156
     }
154 157
     
155
-    /** {@inheritDoc}. */
158
+    /** {@inheritDoc} */
156 159
     public boolean isPolyadic() {
157 160
         return true;
158 161
     }
159 162
     
160
-    /** {@inheritDoc}. */
163
+    /** {@inheritDoc} */
161 164
     public int getArity() {
162 165
         return 0;
163 166
     }
164 167
     
165
-    /** {@inheritDoc}. */
168
+    /** {@inheritDoc} */
166 169
     public String getHelp() {
167 170
         return "set [domain [option [newvalue]]] - inspect or change configuration settings";
168 171
     }
169 172
     
173
+    /** {@inheritDoc} */
174
+    public List<String> getSuggestions(int arg, List<String> previousArgs) {
175
+        final List<String> res = new ArrayList<String>();
176
+        
177
+        if (arg == 0) {
178
+            res.addAll(Config.getDomains());
179
+        } else if (arg == 1 && previousArgs.size() >= 1) {
180
+            res.addAll(Config.getOptions(previousArgs.get(0)));
181
+        }
182
+        
183
+        return res;
184
+    }
185
+    
170 186
 }

+ 100
- 45
src/com/dmdirc/ui/input/InputHandler.java Dosyayı Görüntüle

@@ -23,8 +23,11 @@
23 23
 package com.dmdirc.ui.input;
24 24
 
25 25
 import com.dmdirc.Config;
26
+import com.dmdirc.commandparser.Command;
27
+import com.dmdirc.commandparser.CommandManager;
26 28
 import com.dmdirc.commandparser.CommandParser;
27 29
 import com.dmdirc.commandparser.CommandWindow;
30
+import com.dmdirc.commandparser.IntelligentCommand;
28 31
 import com.dmdirc.ui.components.ColourPickerDialog;
29 32
 import com.dmdirc.ui.messages.Styliser;
30 33
 
@@ -32,6 +35,8 @@ import java.awt.event.ActionEvent;
32 35
 import java.awt.event.ActionListener;
33 36
 import java.awt.event.KeyEvent;
34 37
 import java.awt.event.KeyListener;
38
+import java.util.ArrayList;
39
+import java.util.List;
35 40
 
36 41
 import javax.swing.JTextField;
37 42
 
@@ -177,46 +182,46 @@ public final class InputHandler implements KeyListener, ActionListener {
177 182
      */
178 183
     private void handleControlKey(final KeyEvent keyEvent) {
179 184
         switch (keyEvent.getKeyCode()) {
180
-            case KeyEvent.VK_B:
181
-                addControlCode(Styliser.CODE_BOLD, POSITION_END);
182
-                break;
183
-                
184
-            case KeyEvent.VK_U:
185
-                addControlCode(Styliser.CODE_UNDERLINE, POSITION_END);
186
-                break;
187
-                
188
-            case KeyEvent.VK_O:
189
-                addControlCode(Styliser.CODE_STOP, POSITION_END);
190
-                break;
191
-                
192
-            case KeyEvent.VK_I:
193
-                addControlCode(Styliser.CODE_ITALIC, POSITION_END);
194
-                break;
195
-                
196
-            case KeyEvent.VK_F:
197
-                if ((keyEvent.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
198
-                    addControlCode(Styliser.CODE_FIXED, POSITION_END);
199
-                }
200
-                break;
201
-                
202
-            case KeyEvent.VK_K:
203
-                if ((keyEvent.getModifiers() & KeyEvent.SHIFT_MASK) == 0) {
204
-                    addControlCode(Styliser.CODE_COLOUR, POSITION_START);
205
-                    showColourPicker(true, false);
206
-                } else {
207
-                    addControlCode(Styliser.CODE_HEXCOLOUR, POSITION_START);
208
-                    showColourPicker(false, true);
209
-                }
210
-                break;
211
-                
212
-            case KeyEvent.VK_ENTER:
213
-                commandParser.parseCommandCtrl(parentWindow, target.getText());
214
-                addToBuffer(target.getText());
215
-                break;
216
-                
217
-            default:
218
-                /* Do nothing. */
219
-                break;
185
+        case KeyEvent.VK_B:
186
+            addControlCode(Styliser.CODE_BOLD, POSITION_END);
187
+            break;
188
+            
189
+        case KeyEvent.VK_U:
190
+            addControlCode(Styliser.CODE_UNDERLINE, POSITION_END);
191
+            break;
192
+            
193
+        case KeyEvent.VK_O:
194
+            addControlCode(Styliser.CODE_STOP, POSITION_END);
195
+            break;
196
+            
197
+        case KeyEvent.VK_I:
198
+            addControlCode(Styliser.CODE_ITALIC, POSITION_END);
199
+            break;
200
+            
201
+        case KeyEvent.VK_F:
202
+            if ((keyEvent.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
203
+                addControlCode(Styliser.CODE_FIXED, POSITION_END);
204
+            }
205
+            break;
206
+            
207
+        case KeyEvent.VK_K:
208
+            if ((keyEvent.getModifiers() & KeyEvent.SHIFT_MASK) == 0) {
209
+                addControlCode(Styliser.CODE_COLOUR, POSITION_START);
210
+                showColourPicker(true, false);
211
+            } else {
212
+                addControlCode(Styliser.CODE_HEXCOLOUR, POSITION_START);
213
+                showColourPicker(false, true);
214
+            }
215
+            break;
216
+            
217
+        case KeyEvent.VK_ENTER:
218
+            commandParser.parseCommandCtrl(parentWindow, target.getText());
219
+            addToBuffer(target.getText());
220
+            break;
221
+            
222
+        default:
223
+            /* Do nothing. */
224
+            break;
220 225
         }
221 226
     }
222 227
     
@@ -277,17 +282,68 @@ public final class InputHandler implements KeyListener, ActionListener {
277 282
             return;
278 283
         }
279 284
         
285
+        if (start > 0 && text.charAt(0) == Config.getCommandChar().charAt(0)) {
286
+            doCommandTabCompletion(text, start, end);
287
+        } else {
288
+            doNormalTabCompletion(text, start, end, null);
289
+        }
290
+    }
291
+    
292
+    /**
293
+     * Handles potentially intelligent tab completion.
294
+     *
295
+     * @param text The text that is being completed
296
+     * @param start The start index of the word we're completing
297
+     * @param end The end index of the word we're completing
298
+     */
299
+    private void doCommandTabCompletion(final String text, final int start,
300
+            final int end) {
301
+        final String signature = text.substring(1, text.indexOf(' '));
302
+        final Command command = CommandManager.getCommand(signature);
303
+        
304
+        if (command instanceof IntelligentCommand) {
305
+            int args = 0;
306
+            int lastArg = signature.length() + 2;
307
+            final List<String> previousArgs = new ArrayList<String>();
308
+            
309
+            final String word = text.substring(start, end);
310
+            
311
+            for (int i = lastArg; i < start; i++) {
312
+                if (text.charAt(i) == ' ') {
313
+                    args++;
314
+                    previousArgs.add(text.substring(lastArg, i));
315
+                    lastArg = i + 1;
316
+                }
317
+            }
318
+            
319
+            final List<String> results = ((IntelligentCommand) command).getSuggestions(args, previousArgs);
320
+            
321
+            doNormalTabCompletion(text, start, end, results);
322
+        } else {
323
+            doNormalTabCompletion(text, start, end, null);
324
+        }
325
+    }
326
+    
327
+    /**
328
+     * Handles normal (non-intelligent-command) tab completion.
329
+     *
330
+     * @param text The text that is being completed
331
+     * @param start The start index of the word we're completing
332
+     * @param end The end index of the word we're completing
333
+     * @param additional A list of additional strings to use
334
+     */
335
+    private void doNormalTabCompletion(final String text, final int start,
336
+            final int end, final List<String> additional) {
280 337
         final String word = text.substring(start, end);
281 338
         
282
-        final TabCompleterResult res = tabCompleter.complete(word);
339
+        final TabCompleterResult res = tabCompleter.complete(word, additional);
283 340
         
284 341
         if (res.getResultCount() == 0) {
285 342
             // TODO: Beep, or something
286 343
         } else if (res.getResultCount() == 1) {
287 344
             // One result, just replace it
288 345
             final String result = res.getResults().get(0);
289
-            text = text.substring(0, start) + result + text.substring(end);
290
-            target.setText(text);
346
+            target.setText(text.substring(0, start) + result + text.substring(end));
291 347
             target.setCaretPosition(start + result.length());
292 348
         } else {
293 349
             // Multiple results
@@ -295,8 +351,7 @@ public final class InputHandler implements KeyListener, ActionListener {
295 351
             if (sub.equalsIgnoreCase(word)) {
296 352
                 // TODO: Beep, display possible answers, etc
297 353
             } else {
298
-                text = text.substring(0, start) + sub + text.substring(end);
299
-                target.setText(text);
354
+                target.setText(text.substring(0, start) + sub + text.substring(end));
300 355
                 target.setCaretPosition(start + sub.length());
301 356
             }
302 357
         }

+ 14
- 3
src/com/dmdirc/ui/input/TabCompleter.java Dosyayı Görüntüle

@@ -60,13 +60,24 @@ public final class TabCompleter {
60 60
     
61 61
     /**
62 62
      * Attempts to complete the partial string.
63
+     * 
63 64
      * @param partial The string to tab complete
65
+     * @param additionals A list of additional strings to use
64 66
      * @return A TabCompleterResult containing any matches found
65 67
      */
66
-    public TabCompleterResult complete(final String partial) {
68
+    public TabCompleterResult complete(final String partial,
69
+            final List<String> additionals) {
67 70
 	final TabCompleterResult result = new TabCompleterResult();
71
+        
72
+        final List<String> targets = new ArrayList<String>();
73
+        
74
+        if (additionals != null) { 
75
+            targets.addAll(additionals);
76
+        }
77
+        
78
+        targets.addAll(entries);
68 79
 	
69
-	for (String entry : entries) {
80
+	for (String entry : targets) {
70 81
 	    if (Config.getOptionBool("tabcompletion", "casesensitive")) {
71 82
 		if (entry.startsWith(partial)) {
72 83
 		    result.addResult(entry);
@@ -80,7 +91,7 @@ public final class TabCompleter {
80 91
 	}
81 92
 	
82 93
 	if (parent != null) {
83
-	    result.merge(parent.complete(partial));
94
+	    result.merge(parent.complete(partial, null));
84 95
 	}
85 96
 	return result;
86 97
     }

Loading…
İptal
Kaydet