1c9af18a5SGreg Clayton //===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
2c9af18a5SGreg Clayton //
3c9af18a5SGreg Clayton //                     The LLVM Compiler Infrastructure
4c9af18a5SGreg Clayton //
5c9af18a5SGreg Clayton // This file is distributed under the University of Illinois Open Source
6c9af18a5SGreg Clayton // License. See LICENSE.TXT for details.
7c9af18a5SGreg Clayton //
8c9af18a5SGreg Clayton //===----------------------------------------------------------------------===//
9c9af18a5SGreg Clayton 
1093a64300SDaniel Malea #include "lldb/lldb-python.h"
11c9af18a5SGreg Clayton 
12c9af18a5SGreg Clayton // C Includes
13558ce124SJim Ingham #include <sys/stat.h>
14fd18426eSGreg Clayton #if defined(__APPLE__) || defined(__linux__)
157cc478b9SJim Ingham #include <pwd.h>
16fd18426eSGreg Clayton #endif
17558ce124SJim Ingham 
18c9af18a5SGreg Clayton // C++ Includes
19c9af18a5SGreg Clayton // Other libraries and framework includes
20c9af18a5SGreg Clayton // Project includes
2153239f00SGreg Clayton #include "lldb/Host/FileSpec.h"
229b62fd2fSGreg Clayton #include "lldb/Core/FileSpecList.h"
23ab65b34fSGreg Clayton #include "lldb/Core/PluginManager.h"
241f746071SGreg Clayton #include "lldb/Core/Module.h"
259b62fd2fSGreg Clayton #include "lldb/Interpreter/Args.h"
269b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h"
279b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
281f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
29f21feadcSGreg Clayton #include "lldb/Symbol/Variable.h"
309b62fd2fSGreg Clayton #include "lldb/Target/Target.h"
319b62fd2fSGreg Clayton #include "lldb/Utility/CleanUp.h"
32c9af18a5SGreg Clayton 
33c9af18a5SGreg Clayton using namespace lldb_private;
34c9af18a5SGreg Clayton 
35c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement
36c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] =
37c9af18a5SGreg Clayton {
38c9af18a5SGreg Clayton     {eCustomCompletion,          NULL},
39c9af18a5SGreg Clayton     {eSourceFileCompletion,      CommandCompletions::SourceFiles},
40558ce124SJim Ingham     {eDiskFileCompletion,        CommandCompletions::DiskFiles},
41558ce124SJim Ingham     {eDiskDirectoryCompletion,   CommandCompletions::DiskDirectories},
42c9af18a5SGreg Clayton     {eSymbolCompletion,          CommandCompletions::Symbols},
43c9af18a5SGreg Clayton     {eModuleCompletion,          CommandCompletions::Modules},
443df9a8dfSCaroline Tice     {eSettingsNameCompletion,    CommandCompletions::SettingsNames},
45ab65b34fSGreg Clayton     {ePlatformPluginCompletion,  CommandCompletions::PlatformPluginNames},
46ab65b34fSGreg Clayton     {eArchitectureCompletion,    CommandCompletions::ArchitectureNames},
47f21feadcSGreg Clayton     {eVariablePathCompletion,    CommandCompletions::VariablePath},
48c9af18a5SGreg Clayton     {eNoCompletion,              NULL}      // This one has to be last in the list.
49c9af18a5SGreg Clayton };
50c9af18a5SGreg Clayton 
51c9af18a5SGreg Clayton bool
526611103cSGreg Clayton CommandCompletions::InvokeCommonCompletionCallbacks
536611103cSGreg Clayton (
546611103cSGreg Clayton     CommandInterpreter &interpreter,
556611103cSGreg Clayton     uint32_t completion_mask,
56c9af18a5SGreg Clayton     const char *completion_str,
57c9af18a5SGreg Clayton     int match_start_point,
58c9af18a5SGreg Clayton     int max_return_elements,
59c9af18a5SGreg Clayton     SearchFilter *searcher,
60558ce124SJim Ingham     bool &word_complete,
616611103cSGreg Clayton     StringList &matches
626611103cSGreg Clayton )
63c9af18a5SGreg Clayton {
64c9af18a5SGreg Clayton     bool handled = false;
65c9af18a5SGreg Clayton 
66c9af18a5SGreg Clayton     if (completion_mask & eCustomCompletion)
67c9af18a5SGreg Clayton         return false;
68c9af18a5SGreg Clayton 
69c9af18a5SGreg Clayton     for (int i = 0; ; i++)
70c9af18a5SGreg Clayton     {
71c9af18a5SGreg Clayton         if (g_common_completions[i].type == eNoCompletion)
72c9af18a5SGreg Clayton             break;
73c9af18a5SGreg Clayton          else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
74c9af18a5SGreg Clayton                    && g_common_completions[i].callback != NULL)
75c9af18a5SGreg Clayton          {
76c9af18a5SGreg Clayton             handled = true;
776611103cSGreg Clayton             g_common_completions[i].callback (interpreter,
786611103cSGreg Clayton                                               completion_str,
79c9af18a5SGreg Clayton                                               match_start_point,
80c9af18a5SGreg Clayton                                               max_return_elements,
81c9af18a5SGreg Clayton                                               searcher,
82558ce124SJim Ingham                                               word_complete,
83c9af18a5SGreg Clayton                                               matches);
84c9af18a5SGreg Clayton         }
85c9af18a5SGreg Clayton     }
86c9af18a5SGreg Clayton     return handled;
87c9af18a5SGreg Clayton }
88c9af18a5SGreg Clayton 
89c9af18a5SGreg Clayton int
906611103cSGreg Clayton CommandCompletions::SourceFiles
916611103cSGreg Clayton (
926611103cSGreg Clayton     CommandInterpreter &interpreter,
936611103cSGreg Clayton     const char *partial_file_name,
94c9af18a5SGreg Clayton     int match_start_point,
95c9af18a5SGreg Clayton     int max_return_elements,
96c9af18a5SGreg Clayton     SearchFilter *searcher,
97558ce124SJim Ingham     bool &word_complete,
986611103cSGreg Clayton     StringList &matches
996611103cSGreg Clayton )
100c9af18a5SGreg Clayton {
101558ce124SJim Ingham     word_complete = true;
102c9af18a5SGreg Clayton     // Find some way to switch "include support files..."
1036611103cSGreg Clayton     SourceFileCompleter completer (interpreter,
1046611103cSGreg Clayton                                    false,
1056611103cSGreg Clayton                                    partial_file_name,
1066611103cSGreg Clayton                                    match_start_point,
1076611103cSGreg Clayton                                    max_return_elements,
108c9af18a5SGreg Clayton                                    matches);
109c9af18a5SGreg Clayton 
110c9af18a5SGreg Clayton     if (searcher == NULL)
111c9af18a5SGreg Clayton     {
1122976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
113c9af18a5SGreg Clayton         SearchFilter null_searcher (target_sp);
114c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
115c9af18a5SGreg Clayton     }
116c9af18a5SGreg Clayton     else
117c9af18a5SGreg Clayton     {
118c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
119c9af18a5SGreg Clayton     }
120c9af18a5SGreg Clayton     return matches.GetSize();
121c9af18a5SGreg Clayton }
122c9af18a5SGreg Clayton 
123*b2f1fb29SVirgile Bello typedef struct DiskFilesOrDirectoriesBaton
124*b2f1fb29SVirgile Bello {
125*b2f1fb29SVirgile Bello     const char *remainder;
126*b2f1fb29SVirgile Bello     char *partial_name_copy;
127*b2f1fb29SVirgile Bello     bool only_directories;
128*b2f1fb29SVirgile Bello     bool *saw_directory;
129*b2f1fb29SVirgile Bello     StringList *matches;
130*b2f1fb29SVirgile Bello     char *end_ptr;
131*b2f1fb29SVirgile Bello     size_t baselen;
132*b2f1fb29SVirgile Bello };
133*b2f1fb29SVirgile Bello 
134*b2f1fb29SVirgile Bello FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
135*b2f1fb29SVirgile Bello {
136*b2f1fb29SVirgile Bello     const char *name = spec.GetFilename().AsCString();
137*b2f1fb29SVirgile Bello 
138*b2f1fb29SVirgile Bello     const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
139*b2f1fb29SVirgile Bello     char *end_ptr = parameters->end_ptr;
140*b2f1fb29SVirgile Bello     char *partial_name_copy = parameters->partial_name_copy;
141*b2f1fb29SVirgile Bello     size_t baselen = end_ptr - partial_name_copy;
142*b2f1fb29SVirgile Bello     const char *remainder = parameters->remainder;
143*b2f1fb29SVirgile Bello 
144*b2f1fb29SVirgile Bello     // Omit ".", ".." and any . files if the match string doesn't start with .
145*b2f1fb29SVirgile Bello     if (name[0] == '.')
146*b2f1fb29SVirgile Bello     {
147*b2f1fb29SVirgile Bello         if (name[1] == '\0')
148*b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
149*b2f1fb29SVirgile Bello         else if (name[1] == '.' && name[2] == '\0')
150*b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
151*b2f1fb29SVirgile Bello         else if (remainder[0] != '.')
152*b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
153*b2f1fb29SVirgile Bello     }
154*b2f1fb29SVirgile Bello 
155*b2f1fb29SVirgile Bello     // If we found a directory, we put a "/" at the end of the name.
156*b2f1fb29SVirgile Bello 
157*b2f1fb29SVirgile Bello     if (remainder[0] == '\0' || strstr(name, remainder) == name)
158*b2f1fb29SVirgile Bello     {
159*b2f1fb29SVirgile Bello         if (strlen(name) + parameters->baselen >= PATH_MAX)
160*b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
161*b2f1fb29SVirgile Bello 
162*b2f1fb29SVirgile Bello         strcpy(end_ptr, name);
163*b2f1fb29SVirgile Bello 
164*b2f1fb29SVirgile Bello         bool isa_directory = false;
165*b2f1fb29SVirgile Bello         if (file_type == FileSpec::eFileTypeDirectory)
166*b2f1fb29SVirgile Bello             isa_directory = true;
167*b2f1fb29SVirgile Bello         else if (file_type == FileSpec::eFileTypeSymbolicLink)
168*b2f1fb29SVirgile Bello         {
169*b2f1fb29SVirgile Bello             struct stat stat_buf;
170*b2f1fb29SVirgile Bello             if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
171*b2f1fb29SVirgile Bello                 isa_directory = true;
172*b2f1fb29SVirgile Bello         }
173*b2f1fb29SVirgile Bello 
174*b2f1fb29SVirgile Bello         if (isa_directory)
175*b2f1fb29SVirgile Bello         {
176*b2f1fb29SVirgile Bello             *parameters->saw_directory = true;
177*b2f1fb29SVirgile Bello             size_t len = strlen(parameters->partial_name_copy);
178*b2f1fb29SVirgile Bello             partial_name_copy[len] = '/';
179*b2f1fb29SVirgile Bello             partial_name_copy[len + 1] = '\0';
180*b2f1fb29SVirgile Bello         }
181*b2f1fb29SVirgile Bello         if (parameters->only_directories && !isa_directory)
182*b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
183*b2f1fb29SVirgile Bello         parameters->matches->AppendString(partial_name_copy);
184*b2f1fb29SVirgile Bello     }
185*b2f1fb29SVirgile Bello 
186*b2f1fb29SVirgile Bello     return FileSpec::eEnumerateDirectoryResultNext;
187*b2f1fb29SVirgile Bello }
188*b2f1fb29SVirgile Bello 
189558ce124SJim Ingham static int
190558ce124SJim Ingham DiskFilesOrDirectories
191558ce124SJim Ingham (
192558ce124SJim Ingham     const char *partial_file_name,
193558ce124SJim Ingham     bool only_directories,
194558ce124SJim Ingham     bool &saw_directory,
195558ce124SJim Ingham     StringList &matches
196558ce124SJim Ingham )
197558ce124SJim Ingham {
198558ce124SJim Ingham     // I'm going to  use the "glob" function with GLOB_TILDE for user directory expansion.
199558ce124SJim Ingham     // If it is not defined on your host system, you'll need to implement it yourself...
200558ce124SJim Ingham 
201c7bece56SGreg Clayton     size_t partial_name_len = strlen(partial_file_name);
202558ce124SJim Ingham 
203558ce124SJim Ingham     if (partial_name_len >= PATH_MAX)
204558ce124SJim Ingham         return matches.GetSize();
205558ce124SJim Ingham 
206558ce124SJim Ingham     // This copy of the string will be cut up into the directory part, and the remainder.  end_ptr
207558ce124SJim Ingham     // below will point to the place of the remainder in this string.  Then when we've resolved the
208558ce124SJim Ingham     // containing directory, and opened it, we'll read the directory contents and overwrite the
209558ce124SJim Ingham     // partial_name_copy starting from end_ptr with each of the matches.  Thus we will preserve
210558ce124SJim Ingham     // the form the user originally typed.
211558ce124SJim Ingham 
212558ce124SJim Ingham     char partial_name_copy[PATH_MAX];
213021b605dSBenjamin Kramer     memcpy(partial_name_copy, partial_file_name, partial_name_len);
214558ce124SJim Ingham     partial_name_copy[partial_name_len] = '\0';
215558ce124SJim Ingham 
216710dd5aeSGreg Clayton     // We'll need to save a copy of the remainder for comparison, which we do here.
217558ce124SJim Ingham     char remainder[PATH_MAX];
218558ce124SJim Ingham 
219558ce124SJim Ingham     // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
220558ce124SJim Ingham     char *end_ptr;
221558ce124SJim Ingham 
222558ce124SJim Ingham     end_ptr = strrchr(partial_name_copy, '/');
223558ce124SJim Ingham 
224558ce124SJim Ingham     // This will store the resolved form of the containing directory
225558ce124SJim Ingham     char containing_part[PATH_MAX];
226558ce124SJim Ingham 
227558ce124SJim Ingham     if (end_ptr == NULL)
228558ce124SJim Ingham     {
229558ce124SJim Ingham         // There's no directory.  If the thing begins with a "~" then this is a bare
230558ce124SJim Ingham         // user name.
231558ce124SJim Ingham         if (*partial_name_copy == '~')
232558ce124SJim Ingham         {
233558ce124SJim Ingham             // Nothing here but the user name.  We could just put a slash on the end,
2347cc478b9SJim Ingham             // but for completeness sake we'll resolve the user name and only put a slash
235558ce124SJim Ingham             // on the end if it exists.
2367cc478b9SJim Ingham             char resolved_username[PATH_MAX];
237c982c768SGreg Clayton             size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
2387cc478b9SJim Ingham                                                           sizeof (resolved_username));
2397cc478b9SJim Ingham 
2407cc478b9SJim Ingham            // Not sure how this would happen, a username longer than PATH_MAX?  Still...
2417cc478b9SJim Ingham             if (resolved_username_len >= sizeof (resolved_username))
242558ce124SJim Ingham                 return matches.GetSize();
24384363078SJim Ingham             else if (resolved_username_len == 0)
2447cc478b9SJim Ingham             {
2457cc478b9SJim Ingham                 // The user name didn't resolve, let's look in the password database for matches.
2467cc478b9SJim Ingham                 // The user name database contains duplicates, and is not in alphabetical order, so
2477cc478b9SJim Ingham                 // we'll use a set to manage that for us.
24884363078SJim Ingham                 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
24984363078SJim Ingham                 if (matches.GetSize() > 0)
2507cc478b9SJim Ingham                     saw_directory = true;
2517cc478b9SJim Ingham                 return matches.GetSize();
2527cc478b9SJim Ingham             }
25384363078SJim Ingham             else
25484363078SJim Ingham             {
255558ce124SJim Ingham                 //The thing exists, put a '/' on the end, and return it...
256558ce124SJim Ingham                 // FIXME: complete user names here:
257558ce124SJim Ingham                 partial_name_copy[partial_name_len] = '/';
258558ce124SJim Ingham                 partial_name_copy[partial_name_len+1] = '\0';
259558ce124SJim Ingham                 matches.AppendString(partial_name_copy);
260021b605dSBenjamin Kramer                 saw_directory = true;
261558ce124SJim Ingham                 return matches.GetSize();
262558ce124SJim Ingham             }
26384363078SJim Ingham         }
264558ce124SJim Ingham         else
265558ce124SJim Ingham         {
266558ce124SJim Ingham             // The containing part is the CWD, and the whole string is the remainder.
267558ce124SJim Ingham             containing_part[0] = '.';
268558ce124SJim Ingham             containing_part[1] = '\0';
269558ce124SJim Ingham             strcpy(remainder, partial_name_copy);
270558ce124SJim Ingham             end_ptr = partial_name_copy;
271558ce124SJim Ingham         }
272558ce124SJim Ingham     }
273558ce124SJim Ingham     else
274558ce124SJim Ingham     {
275558ce124SJim Ingham         if (end_ptr == partial_name_copy)
276558ce124SJim Ingham         {
277558ce124SJim Ingham             // We're completing a file or directory in the root volume.
278558ce124SJim Ingham             containing_part[0] = '/';
279558ce124SJim Ingham             containing_part[1] = '\0';
280558ce124SJim Ingham         }
281558ce124SJim Ingham         else
282558ce124SJim Ingham         {
283558ce124SJim Ingham             size_t len = end_ptr - partial_name_copy;
284558ce124SJim Ingham             memcpy(containing_part, partial_name_copy, len);
285558ce124SJim Ingham             containing_part[len] = '\0';
286558ce124SJim Ingham         }
287558ce124SJim Ingham         // Push end_ptr past the final "/" and set remainder.
288558ce124SJim Ingham         end_ptr++;
289558ce124SJim Ingham         strcpy(remainder, end_ptr);
290558ce124SJim Ingham     }
291558ce124SJim Ingham 
2927cc478b9SJim Ingham     // Look for a user name in the containing part, and if it's there, resolve it and stick the
293558ce124SJim Ingham     // result back into the containing_part:
294558ce124SJim Ingham 
295558ce124SJim Ingham     if (*partial_name_copy == '~')
296558ce124SJim Ingham     {
29784363078SJim Ingham         size_t resolved_username_len = FileSpec::ResolveUsername(containing_part,
29884363078SJim Ingham                                                                  containing_part,
29984363078SJim Ingham                                                                  sizeof (containing_part));
300558ce124SJim Ingham         // User name doesn't exist, we're not getting any further...
301a0807356SGreg Clayton         if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
302558ce124SJim Ingham             return matches.GetSize();
303558ce124SJim Ingham     }
304558ce124SJim Ingham 
305558ce124SJim Ingham     // Okay, containing_part is now the directory we want to open and look for files:
306558ce124SJim Ingham 
307558ce124SJim Ingham     size_t baselen = end_ptr - partial_name_copy;
308558ce124SJim Ingham 
309*b2f1fb29SVirgile Bello     DiskFilesOrDirectoriesBaton parameters;
310*b2f1fb29SVirgile Bello     parameters.remainder = remainder;
311*b2f1fb29SVirgile Bello     parameters.partial_name_copy = partial_name_copy;
312*b2f1fb29SVirgile Bello     parameters.only_directories = only_directories;
313*b2f1fb29SVirgile Bello     parameters.saw_directory = &saw_directory;
314*b2f1fb29SVirgile Bello     parameters.matches = &matches;
315*b2f1fb29SVirgile Bello     parameters.end_ptr = end_ptr;
316*b2f1fb29SVirgile Bello     parameters.baselen = baselen;
317558ce124SJim Ingham 
318*b2f1fb29SVirgile Bello     FileSpec::EnumerateDirectory(containing_part, true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
319558ce124SJim Ingham 
320558ce124SJim Ingham     return matches.GetSize();
321558ce124SJim Ingham }
322558ce124SJim Ingham 
323558ce124SJim Ingham int
324558ce124SJim Ingham CommandCompletions::DiskFiles
325558ce124SJim Ingham (
326558ce124SJim Ingham     CommandInterpreter &interpreter,
327558ce124SJim Ingham     const char *partial_file_name,
328558ce124SJim Ingham     int match_start_point,
329558ce124SJim Ingham     int max_return_elements,
330558ce124SJim Ingham     SearchFilter *searcher,
331558ce124SJim Ingham     bool &word_complete,
332558ce124SJim Ingham     StringList &matches
333558ce124SJim Ingham )
334558ce124SJim Ingham {
335558ce124SJim Ingham 
336558ce124SJim Ingham     int ret_val = DiskFilesOrDirectories (partial_file_name,
337558ce124SJim Ingham                                           false,
338558ce124SJim Ingham                                           word_complete,
339558ce124SJim Ingham                                           matches);
340558ce124SJim Ingham     word_complete = !word_complete;
341558ce124SJim Ingham     return ret_val;
342558ce124SJim Ingham }
343558ce124SJim Ingham 
344558ce124SJim Ingham int
345558ce124SJim Ingham CommandCompletions::DiskDirectories
346558ce124SJim Ingham (
347558ce124SJim Ingham     CommandInterpreter &interpreter,
348558ce124SJim Ingham     const char *partial_file_name,
349558ce124SJim Ingham     int match_start_point,
350558ce124SJim Ingham     int max_return_elements,
351558ce124SJim Ingham     SearchFilter *searcher,
352558ce124SJim Ingham     bool &word_complete,
353558ce124SJim Ingham     StringList &matches
354558ce124SJim Ingham )
355558ce124SJim Ingham {
356558ce124SJim Ingham     int ret_val =  DiskFilesOrDirectories (partial_file_name,
357558ce124SJim Ingham                                            true,
358558ce124SJim Ingham                                            word_complete,
359558ce124SJim Ingham                                            matches);
360558ce124SJim Ingham     word_complete = false;
361558ce124SJim Ingham     return ret_val;
362558ce124SJim Ingham }
363558ce124SJim Ingham 
364c9af18a5SGreg Clayton int
3656611103cSGreg Clayton CommandCompletions::Modules
3666611103cSGreg Clayton (
3676611103cSGreg Clayton     CommandInterpreter &interpreter,
3686611103cSGreg Clayton     const char *partial_file_name,
369c9af18a5SGreg Clayton     int match_start_point,
370c9af18a5SGreg Clayton     int max_return_elements,
371c9af18a5SGreg Clayton     SearchFilter *searcher,
372558ce124SJim Ingham     bool &word_complete,
3736611103cSGreg Clayton     StringList &matches
3746611103cSGreg Clayton )
375c9af18a5SGreg Clayton {
376558ce124SJim Ingham     word_complete = true;
3776611103cSGreg Clayton     ModuleCompleter completer (interpreter,
3786611103cSGreg Clayton                                partial_file_name,
3796611103cSGreg Clayton                                match_start_point,
3806611103cSGreg Clayton                                max_return_elements,
3816611103cSGreg Clayton                                matches);
382c9af18a5SGreg Clayton 
383c9af18a5SGreg Clayton     if (searcher == NULL)
384c9af18a5SGreg Clayton     {
3852976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
386c9af18a5SGreg Clayton         SearchFilter null_searcher (target_sp);
387c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
388c9af18a5SGreg Clayton     }
389c9af18a5SGreg Clayton     else
390c9af18a5SGreg Clayton     {
391c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
392c9af18a5SGreg Clayton     }
393c9af18a5SGreg Clayton     return matches.GetSize();
394c9af18a5SGreg Clayton }
395c9af18a5SGreg Clayton 
396c9af18a5SGreg Clayton int
3976611103cSGreg Clayton CommandCompletions::Symbols
3986611103cSGreg Clayton (
3996611103cSGreg Clayton     CommandInterpreter &interpreter,
4006611103cSGreg Clayton     const char *partial_file_name,
401c9af18a5SGreg Clayton     int match_start_point,
402c9af18a5SGreg Clayton     int max_return_elements,
403c9af18a5SGreg Clayton     SearchFilter *searcher,
404558ce124SJim Ingham     bool &word_complete,
4056611103cSGreg Clayton     StringList &matches)
406c9af18a5SGreg Clayton {
407558ce124SJim Ingham     word_complete = true;
4086611103cSGreg Clayton     SymbolCompleter completer (interpreter,
4096611103cSGreg Clayton                                partial_file_name,
4106611103cSGreg Clayton                                match_start_point,
4116611103cSGreg Clayton                                max_return_elements,
4126611103cSGreg Clayton                                matches);
413c9af18a5SGreg Clayton 
414c9af18a5SGreg Clayton     if (searcher == NULL)
415c9af18a5SGreg Clayton     {
4162976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
417c9af18a5SGreg Clayton         SearchFilter null_searcher (target_sp);
418c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
419c9af18a5SGreg Clayton     }
420c9af18a5SGreg Clayton     else
421c9af18a5SGreg Clayton     {
422c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
423c9af18a5SGreg Clayton     }
424c9af18a5SGreg Clayton     return matches.GetSize();
425c9af18a5SGreg Clayton }
426c9af18a5SGreg Clayton 
4273df9a8dfSCaroline Tice int
4283df9a8dfSCaroline Tice CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
4293df9a8dfSCaroline Tice                                    const char *partial_setting_name,
4303df9a8dfSCaroline Tice                                    int match_start_point,
4313df9a8dfSCaroline Tice                                    int max_return_elements,
4323df9a8dfSCaroline Tice                                    SearchFilter *searcher,
4333df9a8dfSCaroline Tice                                    bool &word_complete,
4343df9a8dfSCaroline Tice                                    StringList &matches)
4353df9a8dfSCaroline Tice {
43667cc0636SGreg Clayton     // Cache the full setting name list
43767cc0636SGreg Clayton     static StringList g_property_names;
43867cc0636SGreg Clayton     if (g_property_names.GetSize() == 0)
43967cc0636SGreg Clayton     {
44067cc0636SGreg Clayton         // Generate the full setting name list on demand
44167cc0636SGreg Clayton         lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
44267cc0636SGreg Clayton         if (properties_sp)
44367cc0636SGreg Clayton         {
44467cc0636SGreg Clayton             StreamString strm;
44567cc0636SGreg Clayton             properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
44667cc0636SGreg Clayton             const std::string &str = strm.GetString();
44767cc0636SGreg Clayton             g_property_names.SplitIntoLines(str.c_str(), str.size());
44867cc0636SGreg Clayton         }
44967cc0636SGreg Clayton     }
4503df9a8dfSCaroline Tice 
45167cc0636SGreg Clayton     size_t exact_matches_idx = SIZE_MAX;
45267cc0636SGreg Clayton     const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
45367cc0636SGreg Clayton     word_complete = exact_matches_idx != SIZE_MAX;
45467cc0636SGreg Clayton     return num_matches;
4553df9a8dfSCaroline Tice }
4563df9a8dfSCaroline Tice 
457ab65b34fSGreg Clayton 
458ab65b34fSGreg Clayton int
459ab65b34fSGreg Clayton CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
460ab65b34fSGreg Clayton                                          const char *partial_name,
461ab65b34fSGreg Clayton                                          int match_start_point,
462ab65b34fSGreg Clayton                                          int max_return_elements,
463ab65b34fSGreg Clayton                                          SearchFilter *searcher,
464ab65b34fSGreg Clayton                                          bool &word_complete,
465ab65b34fSGreg Clayton                                          lldb_private::StringList &matches)
466ab65b34fSGreg Clayton {
467ab65b34fSGreg Clayton     const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
468ab65b34fSGreg Clayton     word_complete = num_matches == 1;
469ab65b34fSGreg Clayton     return num_matches;
470ab65b34fSGreg Clayton }
471ab65b34fSGreg Clayton 
472ab65b34fSGreg Clayton int
473ab65b34fSGreg Clayton CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
474ab65b34fSGreg Clayton                                        const char *partial_name,
475ab65b34fSGreg Clayton                                        int match_start_point,
476ab65b34fSGreg Clayton                                        int max_return_elements,
477ab65b34fSGreg Clayton                                        SearchFilter *searcher,
478ab65b34fSGreg Clayton                                        bool &word_complete,
479ab65b34fSGreg Clayton                                        lldb_private::StringList &matches)
480ab65b34fSGreg Clayton {
481ab65b34fSGreg Clayton     const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
482ab65b34fSGreg Clayton     word_complete = num_matches == 1;
483ab65b34fSGreg Clayton     return num_matches;
484ab65b34fSGreg Clayton }
485ab65b34fSGreg Clayton 
486ab65b34fSGreg Clayton 
487f21feadcSGreg Clayton int
488f21feadcSGreg Clayton CommandCompletions::VariablePath (CommandInterpreter &interpreter,
489f21feadcSGreg Clayton                                   const char *partial_name,
490f21feadcSGreg Clayton                                   int match_start_point,
491f21feadcSGreg Clayton                                   int max_return_elements,
492f21feadcSGreg Clayton                                   SearchFilter *searcher,
493f21feadcSGreg Clayton                                   bool &word_complete,
494f21feadcSGreg Clayton                                   lldb_private::StringList &matches)
495f21feadcSGreg Clayton {
496f21feadcSGreg Clayton     return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
497f21feadcSGreg Clayton }
498f21feadcSGreg Clayton 
499f21feadcSGreg Clayton 
5006611103cSGreg Clayton CommandCompletions::Completer::Completer
5016611103cSGreg Clayton (
5026611103cSGreg Clayton     CommandInterpreter &interpreter,
503c9af18a5SGreg Clayton     const char *completion_str,
504c9af18a5SGreg Clayton     int match_start_point,
505c9af18a5SGreg Clayton     int max_return_elements,
506c9af18a5SGreg Clayton     StringList &matches
507c9af18a5SGreg Clayton ) :
5086611103cSGreg Clayton     m_interpreter (interpreter),
509c9af18a5SGreg Clayton     m_completion_str (completion_str),
510c9af18a5SGreg Clayton     m_match_start_point (match_start_point),
511c9af18a5SGreg Clayton     m_max_return_elements (max_return_elements),
512c9af18a5SGreg Clayton     m_matches (matches)
513c9af18a5SGreg Clayton {
514c9af18a5SGreg Clayton }
515c9af18a5SGreg Clayton 
516c9af18a5SGreg Clayton CommandCompletions::Completer::~Completer ()
517c9af18a5SGreg Clayton {
518c9af18a5SGreg Clayton 
519c9af18a5SGreg Clayton }
520c9af18a5SGreg Clayton 
521c9af18a5SGreg Clayton //----------------------------------------------------------------------
522c9af18a5SGreg Clayton // SourceFileCompleter
523c9af18a5SGreg Clayton //----------------------------------------------------------------------
524c9af18a5SGreg Clayton 
5256611103cSGreg Clayton CommandCompletions::SourceFileCompleter::SourceFileCompleter
5266611103cSGreg Clayton (
5276611103cSGreg Clayton     CommandInterpreter &interpreter,
528c9af18a5SGreg Clayton     bool include_support_files,
529c9af18a5SGreg Clayton     const char *completion_str,
530c9af18a5SGreg Clayton     int match_start_point,
531c9af18a5SGreg Clayton     int max_return_elements,
532c9af18a5SGreg Clayton     StringList &matches
533c9af18a5SGreg Clayton ) :
5346611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
535c9af18a5SGreg Clayton     m_include_support_files (include_support_files),
536c9af18a5SGreg Clayton     m_matching_files()
537c9af18a5SGreg Clayton {
538274060b6SGreg Clayton     FileSpec partial_spec (m_completion_str.c_str(), false);
539c9af18a5SGreg Clayton     m_file_name = partial_spec.GetFilename().GetCString();
540c9af18a5SGreg Clayton     m_dir_name = partial_spec.GetDirectory().GetCString();
541c9af18a5SGreg Clayton }
542c9af18a5SGreg Clayton 
543c9af18a5SGreg Clayton Searcher::Depth
544c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth()
545c9af18a5SGreg Clayton {
546c9af18a5SGreg Clayton     return eDepthCompUnit;
547c9af18a5SGreg Clayton }
548c9af18a5SGreg Clayton 
549c9af18a5SGreg Clayton Searcher::CallbackReturn
550c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::SearchCallback (
551c9af18a5SGreg Clayton     SearchFilter &filter,
552c9af18a5SGreg Clayton     SymbolContext &context,
553c9af18a5SGreg Clayton     Address *addr,
554c9af18a5SGreg Clayton     bool complete
555c9af18a5SGreg Clayton )
556c9af18a5SGreg Clayton {
557c9af18a5SGreg Clayton     if (context.comp_unit != NULL)
558c9af18a5SGreg Clayton     {
559c9af18a5SGreg Clayton         if (m_include_support_files)
560c9af18a5SGreg Clayton         {
561c9af18a5SGreg Clayton             FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
562c9af18a5SGreg Clayton             for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
563c9af18a5SGreg Clayton             {
564c9af18a5SGreg Clayton                 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
565c9af18a5SGreg Clayton                 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
566c9af18a5SGreg Clayton                 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
567c9af18a5SGreg Clayton                 bool match = false;
568c9af18a5SGreg Clayton                 if (m_file_name && sfile_file_name
569c9af18a5SGreg Clayton                     && strstr (sfile_file_name, m_file_name) == sfile_file_name)
570c9af18a5SGreg Clayton                     match = true;
571c9af18a5SGreg Clayton                 if (match && m_dir_name && sfile_dir_name
572c9af18a5SGreg Clayton                     && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
573c9af18a5SGreg Clayton                     match = false;
574c9af18a5SGreg Clayton 
575c9af18a5SGreg Clayton                 if (match)
576c9af18a5SGreg Clayton                 {
577c9af18a5SGreg Clayton                     m_matching_files.AppendIfUnique(sfile_spec);
578c9af18a5SGreg Clayton                 }
579c9af18a5SGreg Clayton             }
580c9af18a5SGreg Clayton 
581c9af18a5SGreg Clayton         }
582c9af18a5SGreg Clayton         else
583c9af18a5SGreg Clayton         {
584c9af18a5SGreg Clayton             const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
585c9af18a5SGreg Clayton             const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
586c9af18a5SGreg Clayton 
587c9af18a5SGreg Clayton             bool match = false;
588c9af18a5SGreg Clayton             if (m_file_name && cur_file_name
589c9af18a5SGreg Clayton                 && strstr (cur_file_name, m_file_name) == cur_file_name)
590c9af18a5SGreg Clayton                 match = true;
591c9af18a5SGreg Clayton 
592c9af18a5SGreg Clayton             if (match && m_dir_name && cur_dir_name
593c9af18a5SGreg Clayton                 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
594c9af18a5SGreg Clayton                 match = false;
595c9af18a5SGreg Clayton 
596c9af18a5SGreg Clayton             if (match)
597c9af18a5SGreg Clayton             {
598c9af18a5SGreg Clayton                 m_matching_files.AppendIfUnique(context.comp_unit);
599c9af18a5SGreg Clayton             }
600c9af18a5SGreg Clayton         }
601c9af18a5SGreg Clayton     }
602c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
603c9af18a5SGreg Clayton }
604c9af18a5SGreg Clayton 
605c9af18a5SGreg Clayton size_t
606c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
607c9af18a5SGreg Clayton {
608c9af18a5SGreg Clayton     filter->Search (*this);
609c9af18a5SGreg Clayton     // Now convert the filelist to completions:
610c9af18a5SGreg Clayton     for (size_t i = 0; i < m_matching_files.GetSize(); i++)
611c9af18a5SGreg Clayton     {
612c9af18a5SGreg Clayton         m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
613c9af18a5SGreg Clayton     }
614c9af18a5SGreg Clayton     return m_matches.GetSize();
615c9af18a5SGreg Clayton 
616c9af18a5SGreg Clayton }
617c9af18a5SGreg Clayton 
618c9af18a5SGreg Clayton //----------------------------------------------------------------------
619c9af18a5SGreg Clayton // SymbolCompleter
620c9af18a5SGreg Clayton //----------------------------------------------------------------------
621c9af18a5SGreg Clayton 
622c9af18a5SGreg Clayton static bool
623c9af18a5SGreg Clayton regex_chars (const char comp)
624c9af18a5SGreg Clayton {
625649f8b9bSGreg Clayton     if (comp == '[' || comp == ']' ||
626649f8b9bSGreg Clayton         comp == '(' || comp == ')' ||
627649f8b9bSGreg Clayton         comp == '{' || comp == '}' ||
628649f8b9bSGreg Clayton         comp == '+' ||
629649f8b9bSGreg Clayton         comp == '.' ||
630649f8b9bSGreg Clayton         comp == '*' ||
631649f8b9bSGreg Clayton         comp == '|' ||
632649f8b9bSGreg Clayton         comp == '^' ||
633649f8b9bSGreg Clayton         comp == '$' ||
634649f8b9bSGreg Clayton         comp == '\\' ||
635649f8b9bSGreg Clayton         comp == '?')
636c9af18a5SGreg Clayton         return true;
637c9af18a5SGreg Clayton     else
638c9af18a5SGreg Clayton         return false;
639c9af18a5SGreg Clayton }
6406611103cSGreg Clayton CommandCompletions::SymbolCompleter::SymbolCompleter
6416611103cSGreg Clayton (
6426611103cSGreg Clayton     CommandInterpreter &interpreter,
643c9af18a5SGreg Clayton     const char *completion_str,
644c9af18a5SGreg Clayton     int match_start_point,
645c9af18a5SGreg Clayton     int max_return_elements,
646c9af18a5SGreg Clayton     StringList &matches
647c9af18a5SGreg Clayton ) :
6486611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
649c9af18a5SGreg Clayton {
650649f8b9bSGreg Clayton     std::string regex_str;
651649f8b9bSGreg Clayton     if (completion_str && completion_str[0])
652649f8b9bSGreg Clayton     {
653649f8b9bSGreg Clayton         regex_str.append("^");
654c9af18a5SGreg Clayton         regex_str.append(completion_str);
655649f8b9bSGreg Clayton     }
656649f8b9bSGreg Clayton     else
657649f8b9bSGreg Clayton     {
658649f8b9bSGreg Clayton         // Match anything since the completion string is empty
659649f8b9bSGreg Clayton         regex_str.append(".");
660649f8b9bSGreg Clayton     }
661649f8b9bSGreg Clayton     std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
662649f8b9bSGreg Clayton     while (pos < regex_str.end())
663649f8b9bSGreg Clayton     {
664c9af18a5SGreg Clayton         pos = regex_str.insert(pos, '\\');
665649f8b9bSGreg Clayton         pos = find_if(pos + 2, regex_str.end(), regex_chars);
666c9af18a5SGreg Clayton     }
667c9af18a5SGreg Clayton     m_regex.Compile(regex_str.c_str());
668c9af18a5SGreg Clayton }
669c9af18a5SGreg Clayton 
670c9af18a5SGreg Clayton Searcher::Depth
671c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth()
672c9af18a5SGreg Clayton {
673c9af18a5SGreg Clayton     return eDepthModule;
674c9af18a5SGreg Clayton }
675c9af18a5SGreg Clayton 
676c9af18a5SGreg Clayton Searcher::CallbackReturn
677c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::SearchCallback (
678c9af18a5SGreg Clayton     SearchFilter &filter,
679c9af18a5SGreg Clayton     SymbolContext &context,
680c9af18a5SGreg Clayton     Address *addr,
681c9af18a5SGreg Clayton     bool complete
682c9af18a5SGreg Clayton )
683c9af18a5SGreg Clayton {
684c9af18a5SGreg Clayton     if (context.module_sp)
685c9af18a5SGreg Clayton     {
686931180e6SGreg Clayton         SymbolContextList sc_list;
687931180e6SGreg Clayton         const bool include_symbols = true;
6889df05fbbSSean Callanan         const bool include_inlines = true;
689931180e6SGreg Clayton         const bool append = true;
6909df05fbbSSean Callanan         context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
691c9af18a5SGreg Clayton 
692c9af18a5SGreg Clayton         SymbolContext sc;
693c9af18a5SGreg Clayton         // Now add the functions & symbols to the list - only add if unique:
694931180e6SGreg Clayton         for (uint32_t i = 0; i < sc_list.GetSize(); i++)
695c9af18a5SGreg Clayton         {
696931180e6SGreg Clayton             if (sc_list.GetContextAtIndex(i, sc))
697c9af18a5SGreg Clayton             {
698530a413cSJim Ingham                 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
699530a413cSJim Ingham                 if (!func_name.IsEmpty())
700530a413cSJim Ingham                     m_match_set.insert (func_name);
701c9af18a5SGreg Clayton             }
702c9af18a5SGreg Clayton         }
703c9af18a5SGreg Clayton     }
704c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
705c9af18a5SGreg Clayton }
706c9af18a5SGreg Clayton 
707c9af18a5SGreg Clayton size_t
708c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
709c9af18a5SGreg Clayton {
710c9af18a5SGreg Clayton     filter->Search (*this);
711c9af18a5SGreg Clayton     collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
712c9af18a5SGreg Clayton     for (pos = m_match_set.begin(); pos != end; pos++)
713c9af18a5SGreg Clayton         m_matches.AppendString((*pos).GetCString());
714c9af18a5SGreg Clayton 
715c9af18a5SGreg Clayton     return m_matches.GetSize();
716c9af18a5SGreg Clayton }
717c9af18a5SGreg Clayton 
718c9af18a5SGreg Clayton //----------------------------------------------------------------------
719c9af18a5SGreg Clayton // ModuleCompleter
720c9af18a5SGreg Clayton //----------------------------------------------------------------------
7216611103cSGreg Clayton CommandCompletions::ModuleCompleter::ModuleCompleter
7226611103cSGreg Clayton (
7236611103cSGreg Clayton     CommandInterpreter &interpreter,
724c9af18a5SGreg Clayton     const char *completion_str,
725c9af18a5SGreg Clayton     int match_start_point,
726c9af18a5SGreg Clayton     int max_return_elements,
727c9af18a5SGreg Clayton     StringList &matches
728c9af18a5SGreg Clayton ) :
7296611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
730c9af18a5SGreg Clayton {
731274060b6SGreg Clayton     FileSpec partial_spec (m_completion_str.c_str(), false);
732c9af18a5SGreg Clayton     m_file_name = partial_spec.GetFilename().GetCString();
733c9af18a5SGreg Clayton     m_dir_name = partial_spec.GetDirectory().GetCString();
734c9af18a5SGreg Clayton }
735c9af18a5SGreg Clayton 
736c9af18a5SGreg Clayton Searcher::Depth
737c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth()
738c9af18a5SGreg Clayton {
739c9af18a5SGreg Clayton     return eDepthModule;
740c9af18a5SGreg Clayton }
741c9af18a5SGreg Clayton 
742c9af18a5SGreg Clayton Searcher::CallbackReturn
743c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::SearchCallback (
744c9af18a5SGreg Clayton     SearchFilter &filter,
745c9af18a5SGreg Clayton     SymbolContext &context,
746c9af18a5SGreg Clayton     Address *addr,
747c9af18a5SGreg Clayton     bool complete
748c9af18a5SGreg Clayton )
749c9af18a5SGreg Clayton {
750747bcb03SGreg Clayton     if (context.module_sp)
751c9af18a5SGreg Clayton     {
752c9af18a5SGreg Clayton         const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
753c9af18a5SGreg Clayton         const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
754c9af18a5SGreg Clayton 
755c9af18a5SGreg Clayton         bool match = false;
756c9af18a5SGreg Clayton         if (m_file_name && cur_file_name
757c9af18a5SGreg Clayton             && strstr (cur_file_name, m_file_name) == cur_file_name)
758c9af18a5SGreg Clayton             match = true;
759c9af18a5SGreg Clayton 
760c9af18a5SGreg Clayton         if (match && m_dir_name && cur_dir_name
761c9af18a5SGreg Clayton             && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
762c9af18a5SGreg Clayton             match = false;
763c9af18a5SGreg Clayton 
764c9af18a5SGreg Clayton         if (match)
765c9af18a5SGreg Clayton         {
766c9af18a5SGreg Clayton             m_matches.AppendString (cur_file_name);
767c9af18a5SGreg Clayton         }
768c9af18a5SGreg Clayton     }
769c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
770c9af18a5SGreg Clayton }
771c9af18a5SGreg Clayton 
772c9af18a5SGreg Clayton size_t
773c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
774c9af18a5SGreg Clayton {
775c9af18a5SGreg Clayton     filter->Search (*this);
776c9af18a5SGreg Clayton     return m_matches.GetSize();
777c9af18a5SGreg Clayton }
778