Changeset 1238


Ignore:
Timestamp:
06/27/13 17:15:26 (11 years ago)
Author:
pharms
Message:
  • added autocompletion and history of commands
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/java-utils/src/main/java/de/ugoe/cs/util/console/CommandExecuter.java

    r1018 r1238  
    7878     */ 
    7979    private List<String> commandPackageList; 
     80     
     81    /** 
     82     * <p> 
     83     * the list of available commands (lazy instantiation in the method 
     84     * {@link #getAvailableCommands()}) 
     85     * <p> 
     86     */ 
     87    private Command[] availableCommands; 
    8088 
    8189    /** 
     
    218226     */ 
    219227    public Command[] getAvailableCommands() { 
    220         List<Command> commands = new ArrayList<Command>(); 
    221         List<String> packages = new ArrayList<String>(); 
    222         packages.addAll(commandPackageList); 
    223         packages.add(defaultPackage); 
    224  
    225         FilenameFilter filter = new FilenameFilter() { 
    226             @Override 
    227             public boolean accept(File dir, String name) { 
    228                 return (name != null) && (name.startsWith(cmdPrefix)) && (name.endsWith(".class")); 
    229             } 
    230         }; 
    231  
    232         SortedSet<String> classNames = new TreeSet<String>(new Comparator<String>() { 
    233             @Override 
    234             public int compare(String arg1, String arg2) { 
    235                 String str1 = arg1.substring(arg1.lastIndexOf('.') + cmdPrefix.length() + 1); 
    236                 String str2 = arg2.substring(arg2.lastIndexOf('.') + cmdPrefix.length() + 1); 
    237                 return str1.compareTo(str2); 
    238             } 
    239  
    240         }); 
    241  
    242         for (String packageName : packages) { 
    243             String path = packageName.replace('.', '/'); 
    244             try { 
    245                 Enumeration<URL> resources = ClassLoader.getSystemResources(path); 
    246  
    247                 while (resources.hasMoreElements()) { 
    248                     URL resource = resources.nextElement(); 
    249                     File packageDir = new File(resource.getFile()); 
    250  
    251                     if (packageDir.isDirectory()) { 
    252                         for (File classFile : packageDir.listFiles(filter)) { 
    253                             String className = 
    254                                 classFile.getName().substring(0, 
    255                                                               classFile.getName().lastIndexOf('.')); 
    256                             classNames.add(packageName + "." + className); 
     228        if (availableCommands == null) { 
     229            List<Command> commands = new ArrayList<Command>(); 
     230            List<String> packages = new ArrayList<String>(); 
     231            packages.addAll(commandPackageList); 
     232            packages.add(defaultPackage); 
     233 
     234            FilenameFilter filter = new FilenameFilter() { 
     235                @Override 
     236                public boolean accept(File dir, String name) { 
     237                    return 
     238                        (name != null) && (name.startsWith(cmdPrefix)) && (name.endsWith(".class")); 
     239                } 
     240            }; 
     241 
     242            SortedSet<String> classNames = new TreeSet<String>(new Comparator<String>() { 
     243                @Override 
     244                public int compare(String arg1, String arg2) { 
     245                    String str1 = arg1.substring(arg1.lastIndexOf('.') + cmdPrefix.length() + 1); 
     246                    String str2 = arg2.substring(arg2.lastIndexOf('.') + cmdPrefix.length() + 1); 
     247                    return str1.compareTo(str2); 
     248                } 
     249 
     250            }); 
     251 
     252            for (String packageName : packages) { 
     253                String path = packageName.replace('.', '/'); 
     254                try { 
     255                    Enumeration<URL> resources = ClassLoader.getSystemResources(path); 
     256 
     257                    while (resources.hasMoreElements()) { 
     258                        URL resource = resources.nextElement(); 
     259                        File packageDir = new File(resource.getFile()); 
     260 
     261                        if (packageDir.isDirectory()) { 
     262                            for (File classFile : packageDir.listFiles(filter)) { 
     263                                String className = classFile.getName().substring 
     264                                    (0, classFile.getName().lastIndexOf('.')); 
     265                                classNames.add(packageName + "." + className); 
     266                            } 
     267                        } 
     268                        else { 
     269                            int index = resource.getFile().lastIndexOf('!'); 
     270                            if ((index > 0) && (resource.getFile().startsWith("file:")) && 
     271                                (resource.getFile().endsWith("!/" + path))) 
     272                            { 
     273                                String jarFile = 
     274                                    resource.getFile().substring("file:".length(), index); 
     275 
     276                                // we have to read the package content from a jar file 
     277                                JarInputStream jarInputStream = null; 
     278                                try { 
     279                                    jarInputStream = 
     280                                        new JarInputStream(new FileInputStream(jarFile)); 
     281                                    JarEntry entry = null; 
     282                                    do { 
     283                                        entry = jarInputStream.getNextJarEntry(); 
     284                                        if ((entry != null) && (!entry.isDirectory()) && 
     285                                                (entry.getName().startsWith(path))) 
     286                                        { 
     287                                            String className = entry.getName().substring 
     288                                                (path.length() + 1, entry.getName().lastIndexOf('.')); 
     289                                            classNames.add(packageName + "." + className); 
     290                                        } 
     291                                    } 
     292                                    while (entry != null); 
     293                                } 
     294                                catch (Exception e) { 
     295                                    e.printStackTrace(); 
     296                                    Console.traceln(Level.WARNING, "could not read contents of " + 
     297                                                    "jar " + jarFile); 
     298                                } 
     299                                finally { 
     300                                    if (jarInputStream != null) { 
     301                                        jarInputStream.close(); 
     302                                    } 
     303                                } 
     304 
     305                            } 
    257306                        } 
    258307                    } 
    259                     else { 
    260                         int index = resource.getFile().lastIndexOf('!'); 
    261                         if ((index > 0) && (resource.getFile().startsWith("file:")) && 
    262                             (resource.getFile().endsWith("!/" + path))) 
    263                         { 
    264                             String jarFile = resource.getFile().substring("file:".length(), index); 
    265  
    266                             // we have to read the package content from a jar file 
    267                             JarInputStream jarInputStream = null; 
    268                             try { 
    269                                 jarInputStream = new JarInputStream(new FileInputStream(jarFile)); 
    270                                 JarEntry entry = null; 
    271                                 do { 
    272                                     entry = jarInputStream.getNextJarEntry(); 
    273                                     if ((entry != null) && (!entry.isDirectory()) && 
    274                                             (entry.getName().startsWith(path))) 
    275                                     { 
    276                                         String className = entry.getName().substring 
    277                                             (path.length() + 1, entry.getName().lastIndexOf('.')); 
    278                                         classNames.add(packageName + "." + className); 
    279                                     } 
    280                                 } 
    281                                 while (entry != null); 
    282                             } 
    283                             catch (Exception e) { 
    284                                 e.printStackTrace(); 
    285                                 Console.traceln(Level.WARNING, "could not read contents of jar " + 
    286                                     jarFile); 
    287                             } 
    288                             finally { 
    289                                 if (jarInputStream != null) { 
    290                                     jarInputStream.close(); 
    291                                 } 
    292                             } 
    293  
    294                         } 
    295                     } 
    296                 } 
    297             } 
    298             catch (IOException e) { 
    299                 Console.traceln(Level.WARNING, "could not read commands of package " + packageName); 
    300             } 
    301         } 
    302  
    303         for (String className : classNames) { 
    304             // class may still be inner classes. Therefore load the command, to 
    305             // see if it is really available and a command. 
    306             Command cmd = loadCMD(className); 
    307             if (cmd != null) { 
    308                 commands.add(cmd); 
    309             } 
    310         } 
    311  
    312         Command[] commandArray = commands.toArray(new Command[commands.size()]); 
    313         return commandArray; 
     308                } 
     309                catch (IOException e) { 
     310                    Console.traceln 
     311                        (Level.WARNING, "could not read commands of package " + packageName); 
     312                } 
     313            } 
     314 
     315            for (String className : classNames) { 
     316                // class may still be inner classes. Therefore load the command, to 
     317                // see if it is really available and a command. 
     318                Command cmd = loadCMD(className); 
     319                if (cmd != null) { 
     320                    commands.add(cmd); 
     321                } 
     322            } 
     323 
     324            availableCommands = commands.toArray(new Command[commands.size()]); 
     325        } 
     326         
     327        return availableCommands; 
    314328    } 
    315329     
     
    326340        return commandPackageListCopy; 
    327341    } 
     342 
     343    /** 
     344     * <p> 
     345     * this method method performs an auto completion of the provided String as far as possible 
     346     * regarding the available commands. It auto completes to the full command name, if only 
     347     * one command matches the given prefix. It auto completes to the common denominator, if 
     348     * several commands match the prefix 
     349     * </p> 
     350     * 
     351     * @param commandPrefix the prefix to be auto completed 
     352     *  
     353     * @return as described 
     354     */ 
     355    public String autoCompleteCommand(String commandPrefix) { 
     356        Command[] commands = getAvailableCommands(); 
     357         
     358        List<Command> matchingCommands = new ArrayList<Command>(); 
     359        for (Command command : commands) { 
     360            String commandName = command.getClass().getSimpleName().substring(3); 
     361            if (commandName.startsWith(commandPrefix)) { 
     362                matchingCommands.add(command); 
     363            } 
     364        } 
     365         
     366        StringBuffer completedPrefix = new StringBuffer(commandPrefix); 
     367         
     368        boolean foundCompletion = false; 
     369         
     370        while (!foundCompletion) { 
     371            char nextCompletionChar = 0; 
     372            for (Command command : matchingCommands) { 
     373                String commandName = command.getClass().getSimpleName().substring(3); 
     374                if (commandName.length() > completedPrefix.length()) { 
     375                    if (nextCompletionChar == 0) { 
     376                        nextCompletionChar = commandName.charAt(completedPrefix.length()); 
     377                    } 
     378                    else if (nextCompletionChar != commandName.charAt(completedPrefix.length())) { 
     379                        foundCompletion = true; 
     380                    } 
     381                } 
     382                else { 
     383                    foundCompletion = true; 
     384                } 
     385            } 
     386             
     387            if (!foundCompletion && (nextCompletionChar != 0)) { 
     388                completedPrefix.append(nextCompletionChar); 
     389            } 
     390            else { 
     391                foundCompletion = true; 
     392            } 
     393        } 
     394         
     395        return completedPrefix.toString(); 
     396    } 
    328397} 
Note: See TracChangeset for help on using the changeset viewer.