File Source: TabCompleter.java

         /* 
    P/P   *  Method: com.dmdirc.ui.input.TabCompleter__static_init
          */
     1  /*
     2   * Copyright (c) 2006-2009 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.ui.input;
    24  
    25  import com.dmdirc.commandparser.CommandInfo;
    26  import com.dmdirc.commandparser.CommandManager;
    27  import com.dmdirc.commandparser.commands.Command;
    28  import com.dmdirc.commandparser.commands.IntelligentCommand;
    29  import com.dmdirc.config.IdentityManager;
    30  import com.dmdirc.util.MapList;
    31  
    32  import java.io.Serializable;
    33  import java.util.Arrays;
    34  import java.util.List;
    35  import java.util.Locale;
    36  import java.util.Map;
    37  
    38  /**
    39   * The tab completer handles a user's request to tab complete some word.
    40   * 
    41   * @author chris
    42   */
    43  public final class TabCompleter implements Serializable {
    44      
    45      /**
    46       * A version number for this class. It should be changed whenever the class
    47       * structure is changed (or anything else that would prevent serialized
    48       * objects being unserialized with the new class).
    49       */
    50      private static final long serialVersionUID = 1;
    51      
    52      /**
    53       * The parent TabCompleter. Results from parents are merged with results
    54       * from this completer.
    55       */
    56      private TabCompleter parent;
    57  
    58      /**
    59       * The entries in this completer.
    60       */
    61      private final MapList<TabCompletionType, String> entries
    62              = new MapList<TabCompletionType, String>();
    63      
    64      /** Creates a new instance of TabCompleter. */
             /* 
    P/P       *  Method: void com.dmdirc.ui.input.TabCompleter()
              * 
              *  Postconditions:
              *    this.entries == &amp;new MapList(TabCompleter#1)
              *    new MapList(TabCompleter#1) num objects == 1
              */
    65      public TabCompleter() {
    66          //Do nothing.
    67      }
    68      
    69      /**
    70       * Creates a new instance of TabCompleter, with a designated parent.
    71       * @param newParent The parent TabCompleter, which is checked for matches if
    72       * local ones fail
    73       */
             /* 
    P/P       *  Method: void com.dmdirc.ui.input.TabCompleter(TabCompleter)
              * 
              *  Postconditions:
              *    this.entries == &amp;new MapList(TabCompleter#1)
              *    this.parent == newParent
              *    init'ed(this.parent)
              *    new MapList(TabCompleter#1) num objects == 1
              */
    74      public TabCompleter(final TabCompleter newParent) {
    75          this.parent = newParent;
    76      }
    77      
    78      /**
    79       * Attempts to complete the partial string.
    80       *
    81       * @param partial The string to tab complete
    82       * @param additionals A list of additional strings to use
    83       * @return A TabCompleterResult containing any matches found
    84       */
    85      public TabCompleterResult complete(final String partial,
    86              final AdditionalTabTargets additionals) {
                 /* 
    P/P           *  Method: TabCompleterResult complete(String, AdditionalTabTargets)
                  * 
                  *  Preconditions:
                  *    partial != null
                  *    (soft) additionals.includes != null
                  *    (soft) init'ed(this...parent)
                  *    (soft) init'ed(this.parent)
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@92 != null
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@94 != null
                  *    init'ed(com.dmdirc.ui.input.TabCompletionType.ADDITIONAL)
                  *    com.dmdirc.util.MapList:entrySet(...)@105 != null
                  *    com.dmdirc.util.MapList:safeGet(...)@102 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    return_value == &amp;new TabCompleterResult(complete#1)
                  *    new TabCompleterResult(complete#1) num objects == 1
                  * 
                  *  Test Vectors:
                  *    additionals: Addr_Set{null}, Inverse{null}
                  *    this.parent: Addr_Set{null}, Inverse{null}
                  *    com.dmdirc.config.ConfigManager:getOptionBool(...)@92: {0}, {1}
                  *    com.dmdirc.config.ConfigManager:getOptionBool(...)@94: {1}, {0}
                  *    com.dmdirc.ui.input.TabCompleterResult:hasResult(...)@113: {0}, {1}
                  *    java.lang.String:isEmpty(...)@97: {0}, {1}
                  *    java.lang.String:startsWith(...)@117: {0}, {1}
                  *    java.lang.String:startsWith(...)@119: {0}, {1}
                  *    java.util.Iterator:hasNext(...)@105: {0}, {1}
                  *    java.util.Iterator:hasNext(...)@111: {0}, {1}
                  *    ...
                  */
    87          final TabCompleterResult result = new TabCompleterResult();
    88          
    89          final MapList<TabCompletionType, String> targets
    90                  = new MapList<TabCompletionType, String>(entries);
    91          
    92          final boolean caseSensitive = IdentityManager.getGlobalConfig()
    93                  .getOptionBool("tabcompletion", "casesensitive");
    94          final boolean allowEmpty = IdentityManager.getGlobalConfig()
    95                  .getOptionBool("tabcompletion", "allowempty");
    96  
    97          if (partial.isEmpty() && !allowEmpty) {
    98              return result;
    99          }
   100                  
   101          if (additionals != null) {
   102              targets.safeGet(TabCompletionType.ADDITIONAL).addAll(additionals);
   103          }
   104          
   105          for (Map.Entry<TabCompletionType, List<String>> typeEntry : targets.entrySet()) {
   106              if (additionals != null && !additionals.shouldInclude(typeEntry.getKey())) {
   107                  // If we're not including this type, skip to the next.
   108                  continue;
   109              }
   110              
   111              for (String entry : typeEntry.getValue()) {
   112                  // Skip over duplicates
   113                  if (result.hasResult(entry)) {
   114                      continue;
   115                  }
   116  
   117                  if (caseSensitive && entry.startsWith(partial)) {
   118                      result.addResult(entry);
   119                  } else if (!caseSensitive && entry.toLowerCase(Locale.getDefault())
   120                          .startsWith(partial.toLowerCase(Locale.getDefault()))) {
   121                      result.addResult(entry);
   122                  }
   123              }
   124          }
   125          
   126          if (parent != null) {
   127              if (additionals != null) {
   128                  additionals.clear();
   129              }
   130              
   131              result.merge(parent.complete(partial, additionals));
   132          }
   133          
   134          return result;
   135      }
   136      
   137      /**
   138       * Adds a new entry to this tab completer's list.
   139       * 
   140       * @param type The type of the entry that's being added
   141       * @param entry The new entry to be added
   142       */
   143      public void addEntry(final TabCompletionType type, final String entry) {
                 /* 
    P/P           *  Method: void addEntry(TabCompletionType, String)
                  * 
                  *  Preconditions:
                  *    this.entries != null
                  */
   144          entries.add(type, entry);
   145      }
   146      
   147      /**
   148       * Adds multiple new entries to this tab completer's list.
   149       * 
   150       * @param type The type of the entries that're being added
   151       * @param newEntries Entries to be added
   152       */
   153      public void addEntries(final TabCompletionType type, final List<String> newEntries) {
                 /* 
    P/P           *  Method: void addEntries(TabCompletionType, List)
                  * 
                  *  Preconditions:
                  *    (soft) this.entries != null
                  * 
                  *  Test Vectors:
                  *    newEntries: Inverse{null}, Addr_Set{null}
                  *    java.util.Iterator:hasNext(...)@158: {0}, {1}
                  */
   154          if (newEntries == null) {
   155              return;
   156          }
   157          
   158          for (String entry : newEntries) {
   159              addEntry(type, entry);
   160          }
   161      }
   162      
   163      /**
   164       * Removes a specified entry from this tab completer's list.
   165       * 
   166       * @param type The type of the entry that should be removed
   167       * @param entry The entry to be removed
   168       */
   169      public void removeEntry(final TabCompletionType type, final String entry) {
                 /* 
    P/P           *  Method: void removeEntry(TabCompletionType, String)
                  * 
                  *  Preconditions:
                  *    this.entries != null
                  */
   170          entries.remove(type, entry);
   171      }
   172      
   173      /**
   174       * Replaces the current entries with the new list.
   175       * 
   176       * @param type The type of entry which should be replaced
   177       * @param newEntries the new entries to use
   178       */
   179      public void replaceEntries(final TabCompletionType type, final List<String> newEntries) {
                 /* 
    P/P           *  Method: void replaceEntries(TabCompletionType, List)
                  * 
                  *  Preconditions:
                  *    this.entries != null
                  */
   180          entries.clear(type);
   181          entries.add(type, newEntries);
   182      }
   183      
   184      /**
   185       * Clears all entries in this tab completer.
   186       */
   187      public void clear() {
                 /* 
    P/P           *  Method: void clear()
                  * 
                  *  Preconditions:
                  *    this.entries != null
                  */
   188          entries.clear();
   189      }
   190      
   191      /**
   192       * Clears all entries of the specified type in this tab completer.
   193       * 
   194       * @param type The type of entry to clear
   195       */
   196      public void clear(final TabCompletionType type) {
                 /* 
    P/P           *  Method: void clear(TabCompletionType)
                  * 
                  *  Preconditions:
                  *    this.entries != null
                  */
   197          entries.clear(type);
   198      }
   199      
   200      /**
   201       * Retrieves intelligent results for a deferred command.
   202       * 
   203       * @param arg The argument number that is being requested
   204       * @param previousArgs The full list of previous arguments
   205       * @param offset The number of arguments our command used before deferring
   206       * to this method
   207       * @return Additional tab targets for the text, or null if none are available
   208       */
   209      public static AdditionalTabTargets getIntelligentResults(final int arg,
   210              final List<String> previousArgs, final int offset) {
                 /* 
    P/P           *  Method: AdditionalTabTargets getIntelligentResults(int, List, int)
                  * 
                  *  Preconditions:
                  *    (soft) previousArgs != null
                  * 
                  *  Presumptions:
                  *    init'ed(com.dmdirc.ui.input.TabCompletionType.COMMAND)
                  *    java.util.List:subList(...)@216 != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  *    new AdditionalTabTargets(getIntelligentResults#1) num objects <= 1
                  *    new AdditionalTabTargets(getIntelligentResults#1).includes == &amp;new ArrayList(AdditionalTabTargets#1)
                  *    new ArrayList(AdditionalTabTargets#1) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    offset - arg: {-6_442_450_943..-1, 1..6_442_450_943}, {0}
                  */
   211          if (arg == offset) {
   212              final AdditionalTabTargets targets = new AdditionalTabTargets().excludeAll();
   213              targets.include(TabCompletionType.COMMAND);
   214              return targets;
   215          } else {
   216              return TabCompleter.getIntelligentResults(previousArgs.subList(offset,
   217                      previousArgs.size()));
   218          }        
   219      }
   220      
   221      /**
   222       * Retrieves the intelligent results for the command and its arguments
   223       * formed from args.
   224       * 
   225       * @param args A list of "words" in the input
   226       * @return Additional tab targets for the text, or null if none are available
   227       */
   228      private static AdditionalTabTargets getIntelligentResults(final List<String> args) {
                 /* 
    P/P           *  Method: AdditionalTabTargets getIntelligentResults(List)
                  * 
                  *  Preconditions:
                  *    args != null
                  * 
                  *  Presumptions:
                  *    java.util.List:get(...)@229 != null
                  *    java.util.List:get(...)@233 != null
                  *    java.util.List:size(...)@237 >= -231+1
                  *    java.util.Map_Entry:getValue(...)@237 != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    com.dmdirc.commandparser.CommandManager:getCommand(...)@234: Addr_Set{null}, Inverse{null}
                  *    java.util.List:isEmpty(...)@229: {1}, {0}
                  */
   229          if (args.isEmpty() || args.get(0).charAt(0) != CommandManager.getCommandChar()) {
   230              return null;
   231          }
   232          
   233          final String signature = args.get(0).substring(1);
   234          final Map.Entry<CommandInfo, Command> command = CommandManager.getCommand(signature);
   235          
   236          if (command != null && command.getValue() instanceof IntelligentCommand) {
   237              return ((IntelligentCommand) command.getValue()).getSuggestions(args.size() - 1,
   238                      args.subList(1, args.size()));
   239          } else {
   240              return null;
   241          }        
   242      }
   243      
   244      /**
   245       * Handles potentially intelligent tab completion.
   246       *
   247       * @param text The text that is being completed
   248       * @return Additional tab targets for the text, or null if none are available
   249       */
   250      public static AdditionalTabTargets getIntelligentResults(final String text) {
                 /* 
    P/P           *  Method: AdditionalTabTargets getIntelligentResults(String)
                  * 
                  *  Preconditions:
                  *    text != null
                  * 
                  *  Presumptions:
                  *    java.util.Arrays:asList(...)@251 != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   251          return getIntelligentResults(Arrays.asList(text.split(" ")));
   252      }
   253  }








SofCheck Inspector Build Version : 2.17854
TabCompleter.java 2009-Jun-25 01:54:24
TabCompleter.class 2009-Sep-02 17:04:12