wxMaxima
Loading...
Searching...
No Matches
Autocomplete.h
Go to the documentation of this file.
1// -*- mode: c++; c-file-style: "linux"; c-basic-offset: 2; indent-tabs-mode: nil -*-
2//
3// Copyright (C) 2009-2015 Andrej Vodopivec <andrej.vodopivec@gmail.com>
4// Copyright (C) 2015 Gunter Königsmann <wxMaxima@physikbuch.de>
5//
6// This program is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20//
21// SPDX-License-Identifier: GPL-2.0+
22
30#ifndef AUTOCOMPLETE_H
31#define AUTOCOMPLETE_H
32
33#include <thread>
34#include <algorithm>
35#include <memory>
36#include <mutex>
37#include <atomic>
38#include <wx/wx.h>
39#include <wx/xml/xml.h>
40#include <wx/event.h>
41#include <wx/dir.h>
42#include <vector>
43#include <wx/object.h>
44#include <wx/regex.h>
45#include <wx/filename.h>
46#include <wx/hashmap.h>
47#include "Configuration.h"
48#include "precomp.h"
49#include "Version.h"
50#include <unordered_map>
51/* The autocompletion logic
52
53 The wordlists for autocompletion for keywords come from several sources:
54
55 - wxMaxima::ReadLoadSymbols receive the contents of maxima's variables
56 "values" and "functions" after a package is loaded.
57 - all words that appear in the worksheet
58 - and a list of maxima's builtin commands.
59*/
60class AutoComplete : public wxEvtHandler
61{
62 typedef std::unordered_map <wxString, int, wxStringHash> WorksheetWords;
63public:
64 using WordList = std::vector<wxString>;
65
68 {
69 command = 0,
77 };
78 explicit AutoComplete(Configuration *configuration);
79
81 virtual ~AutoComplete();
82
84 void LoadSymbols();
85
92 void LoadBuiltinSymbols();
93
95 void AddSymbol(wxString fun, autoCompletionType type = command);
97 void AddSymbols(wxString xml);
99 void AddSymbols(wxXmlDocument xml);
101 void AddSymbols_Backgroundtask_string(wxString xml);
103 void AddSymbols_Backgroundtask(wxXmlDocument xmldoc);
104
105
107 void UpdateDemoFiles(wxString partial, const wxString &maximaDir);
109 void UpdateLoadFiles(wxString partial, const wxString &maximaDir);
111 void UpdateGeneralFiles(wxString partial, const wxString &maximaDir);
112
114 void AddWorksheetWords(const WordList &words);
115 void AddWorksheetWords(WordList::const_iterator begin, WordList::const_iterator end);
116
118 void ClearWorksheetWords();
120 void ClearDemofileList();
121
123 std::vector<wxString> CompleteSymbol(wxString partial, autoCompletionType type = command);
125 static wxString FixTemplate(wxString templ);
127 std::vector<wxString> GetDemoFilesList();
129 std::vector<wxString> GetSymbolList();
131 bool HasDemofile(const wxString &commandname);
132
133private:
135 Configuration *m_configuration;
137 void LoadableFiles_BackgroundTask(wxString sharedir, wxString demodir);
139 void BuiltinSymbols_BackgroundTask();
140
142 void UpdateLoadFiles_BackgroundTask(wxString partial, wxString maximaDir);
144 std::vector<wxString> m_builtInLoadFiles;
146 std::vector<wxString> m_builtInDemoFiles;
148 class GetGeneralFiles : public wxDirTraverser
149 {
150 public:
151 explicit GetGeneralFiles(std::vector<wxString>& files,
152 std::mutex *lock,
153 std::atomic_bool *abort = nullptr,
154 const wxString &prefix = wxEmptyString) :
155 m_files(files), m_lock(lock), m_abort(abort), m_prefix(prefix) {
156 for(const auto &i : m_files)
157 m_filesHash[i];
158 }
159 wxDirTraverseResult OnFile(const wxString& filename) override
160 {
161 if (m_abort && *m_abort) return wxDIR_STOP;
162 wxFileName newItemName(filename);
163 wxString newItem = "\"" + m_prefix + newItemName.GetFullName() + "\"";
164 newItem.Replace(wxFileName::GetPathSeparator(), "/");
165 {
166 const std::lock_guard<std::mutex> lock(*m_lock);
167 if (m_filesHash.find(newItem) == m_filesHash.end())
168 {
169 m_files.push_back(newItem);
170 m_filesHash[newItem];
171 }
172 }
173 return wxDIR_CONTINUE;
174 }
175 wxDirTraverseResult OnDir(const wxString& dirname) override
176 {
177 if (m_abort && *m_abort) return wxDIR_STOP;
178 wxFileName newItemName(dirname);
179 wxString newItem = "\"" + m_prefix + newItemName.GetFullName() + "/\"";
180 newItem.Replace(wxFileName::GetPathSeparator(), "/");
181 {
182 const std::lock_guard<std::mutex> lock(*m_lock);
183 if (m_filesHash.find(newItem) == m_filesHash.end())
184 {
185 m_files.push_back(newItem);
186 m_filesHash[newItem];
187 }
188 }
189 return wxDIR_IGNORE;
190 }
191 std::vector<wxString> GetResult(){
192 const std::lock_guard<std::mutex> lock(*m_lock);
193 return m_files;
194 }
195 protected:
197 std::vector<wxString>& m_files;
199 std::unordered_map<wxString, wxEvtHandler*, wxStringHash> m_filesHash;
200 std::mutex *m_lock;
201 std::atomic_bool *m_abort;
202 wxString m_prefix;
203 };
204
206 class GetMacFiles_includingSubdirs : public wxDirTraverser
207 {
208 public:
209 explicit GetMacFiles_includingSubdirs(std::vector<wxString>& files,
210 std::mutex *lock,
211 std::atomic_bool *abort = nullptr,
212 const wxString &prefix = wxEmptyString) :
213 m_files(files), m_lock(lock), m_abort(abort), m_prefix(prefix)
214 {
215 for(const auto &i : m_files)
216 m_filesHash[i];
217 }
218 wxDirTraverseResult OnFile(const wxString& filename) override
219 {
220 if (m_abort && *m_abort) return wxDIR_STOP;
221 if(
222 (filename.EndsWith(".mac"))||
223 (filename.EndsWith(".lisp"))||
224 (filename.EndsWith(".wxm"))
225 )
226 {
227 wxFileName newItemName(filename);
228 wxString newItem = "\"" + m_prefix + newItemName.GetName() + "\"";
229 newItem.Replace(wxFileName::GetPathSeparator(), "/");
230 {
231 const std::lock_guard<std::mutex> lock(*m_lock);
232 if (m_filesHash.find(newItem) == m_filesHash.end())
233 {
234 m_files.push_back(newItem);
235 m_filesHash[newItem];
236 }
237 }
238 }
239 return wxDIR_CONTINUE;
240 }
241 wxDirTraverseResult OnDir(const wxString& dirname) override
242 {
243 if (m_abort && *m_abort) return wxDIR_STOP;
244 if((dirname.EndsWith(".git")) ||
245 (dirname.EndsWith("/share/share")) ||
246 (dirname.EndsWith("/src/src")) ||
247 (dirname.EndsWith("/doc/doc")) ||
248 (dirname.EndsWith("/interfaces/interfaces"))
249 )
250 return wxDIR_STOP;
251 else
252 return wxDIR_CONTINUE;
253 }
254 std::vector<wxString> GetResult(){
255 const std::lock_guard<std::mutex> lock(*m_lock);
256 return m_files;
257 }
258 protected:
260 std::vector<wxString>& m_files;
262 std::unordered_map<wxString, wxEvtHandler*, wxStringHash> m_filesHash;
263 std::mutex *m_lock;
264 std::atomic_bool *m_abort;
265 wxString m_prefix;
266 };
267
269 class GetMacFiles : public GetMacFiles_includingSubdirs
270 {
271 public:
272 explicit GetMacFiles(std::vector<wxString>& files,
273 std::mutex *lock,
274 std::atomic_bool *abort = nullptr,
275 const wxString &prefix = wxEmptyString) :
276 GetMacFiles_includingSubdirs(files, lock, abort, prefix){ }
277 wxDirTraverseResult OnDir(const wxString& dirname) override
278 {
279 if (m_abort && *m_abort) return wxDIR_STOP;
280 wxFileName newItemName(dirname);
281 wxString newItem = "\"" + m_prefix + newItemName.GetFullName() + "/\"";
282 newItem.Replace(wxFileName::GetPathSeparator(), "/");
283 {
284 const std::lock_guard<std::mutex> lock(*m_lock);
285 if (m_filesHash.find(newItem) == m_filesHash.end())
286 {
287 m_files.push_back(newItem);
288 m_filesHash[newItem];
289 }
290 }
291 return wxDIR_IGNORE;
292 }
293 };
294
296 class GetDemoFiles_includingSubdirs : public wxDirTraverser
297 {
298 public:
299 explicit GetDemoFiles_includingSubdirs(std::vector<wxString>& files,
300 std::mutex *lock,
301 std::atomic_bool *abort = nullptr,
302 const wxString &prefix = wxEmptyString) :
303 m_files(files), m_lock(lock), m_abort(abort), m_prefix(prefix)
304 {
305 for(const auto &i : m_files)
306 m_filesHash[i];
307 }
308 wxDirTraverseResult OnFile(const wxString& filename) override
309 {
310 if (m_abort && *m_abort) return wxDIR_STOP;
311 if(filename.EndsWith(".dem"))
312 {
313 wxFileName newItemName(filename);
314 wxString newItem = "\"" + m_prefix + newItemName.GetName() + "\"";
315 newItem.Replace(wxFileName::GetPathSeparator(), "/");
316 {
317 const std::lock_guard<std::mutex> lock(*m_lock);
318 if (m_filesHash.find(newItem) == m_filesHash.end())
319 {
320 m_files.push_back(newItem);
321 m_filesHash[newItem];
322 }
323 }
324 }
325 return wxDIR_CONTINUE;
326 }
327 wxDirTraverseResult OnDir(const wxString& dirname) override
328 {
329 if (m_abort && *m_abort) return wxDIR_STOP;
330 if((dirname.EndsWith(".git")) ||
331 (dirname.EndsWith("/share/share")) ||
332 (dirname.EndsWith("/src/src")) ||
333 (dirname.EndsWith("/doc/doc")) ||
334 (dirname.EndsWith("/interfaces/interfaces"))
335 )
336 return wxDIR_STOP;
337 else
338 return wxDIR_CONTINUE;
339 }
340 std::vector<wxString> GetResult(){
341 const std::lock_guard<std::mutex> lock(*m_lock);
342 return m_files;
343 }
344 protected:
346 std::vector<wxString>& m_files;
348 std::unordered_map<wxString, wxEvtHandler*, wxStringHash> m_filesHash;
349 std::mutex *m_lock;
350 std::atomic_bool *m_abort;
351 wxString m_prefix;
352 };
353
355 class GetDemoFiles : public GetDemoFiles_includingSubdirs
356 {
357 public:
358 explicit GetDemoFiles(std::vector<wxString>& files,
359 std::mutex *lock,
360 std::atomic_bool *abort = nullptr,
361 const wxString &prefix = wxEmptyString) :
362 GetDemoFiles_includingSubdirs(files, lock, abort, prefix){ }
363 virtual wxDirTraverseResult OnDir(const wxString& dirname) override
364 {
365 if (m_abort && *m_abort) return wxDIR_STOP;
366 wxFileName newItemName(dirname);
367 wxString newItem = "\"" + m_prefix + newItemName.GetFullName() + "/\"";
368 newItem.Replace(wxFileName::GetPathSeparator(), "/");
369 {
370 const std::lock_guard<std::mutex> lock(*m_lock);
371 if (m_filesHash.find(newItem) == m_filesHash.end())
372 {
373 m_files.push_back(newItem);
374 m_filesHash[newItem];
375 }
376 }
377 return wxDIR_IGNORE;
378 }
379 };
380
381 jthread m_addSymbols_backgroundThread;
382 jthread m_addFiles_backgroundThread;
384 std::atomic_bool m_abortBackgroundTask{false};
386 std::mutex m_keywordsLock;
388 std::vector<std::vector<wxString>> m_wordList;
389 static wxRegEx m_args;
390 WorksheetWords m_worksheetWords;
391};
392
393wxDECLARE_EVENT(NEW_DEMO_FILES_EVENT, wxCommandEvent);
394
395#endif // AUTOCOMPLETE_H
Definition: Autocomplete.h:61
std::vector< wxString > GetSymbolList()
Returns a list of Symbols we know.
Definition: Autocomplete.cpp:62
void AddSymbols_Backgroundtask(wxXmlDocument xmldoc)
The real work of AddSymbols is made here and in the background.
Definition: Autocomplete.cpp:148
virtual ~AutoComplete()
The destructor of AutoComplete.
Definition: Autocomplete.cpp:228
void ClearDemofileList()
Clear the list of files demo() can be applied on.
Definition: Autocomplete.cpp:103
std::vector< wxString > GetDemoFilesList()
Returns a list of demo files we know of.
Definition: Autocomplete.cpp:57
void UpdateDemoFiles(wxString partial, const wxString &maximaDir)
Replace the list of files in the directory the worksheet file is in to the demo files list.
Definition: Autocomplete.cpp:412
void LoadSymbols()
Load all autocomplete symbols wxMaxima knows about by itself.
Definition: Autocomplete.cpp:235
autoCompletionType
All types of things we can autocomplete.
Definition: Autocomplete.h:68
@ tmplte
Command names.
Definition: Autocomplete.h:70
@ generalfile
loadable files
Definition: Autocomplete.h:73
@ demofile
loadable files
Definition: Autocomplete.h:72
@ numberOfTypes
Unit names.
Definition: Autocomplete.h:76
@ unit
Esc commands describing symbols.
Definition: Autocomplete.h:75
@ loadfile
Function templates.
Definition: Autocomplete.h:71
@ esccommand
general files
Definition: Autocomplete.h:74
std::vector< wxString > CompleteSymbol(wxString partial, autoCompletionType type=command)
Returns a list of possible autocompletions for the string "partial".
Definition: Autocomplete.cpp:523
void UpdateLoadFiles(wxString partial, const wxString &maximaDir)
Replace the list of files in the directory the worksheet file is in to the load files list.
Definition: Autocomplete.cpp:481
void LoadBuiltinSymbols()
Makes wxMaxima know all its builtin symbols.
Definition: Autocomplete.cpp:68
void UpdateGeneralFiles(wxString partial, const wxString &maximaDir)
Assemble a list of files.
Definition: Autocomplete.cpp:448
void AddSymbols(wxString xml)
Interprets the XML autocompletable symbol list maxima can send us.
Definition: Autocomplete.cpp:108
void AddWorksheetWords(const WordList &words)
Add words to the list of words that appear in the workSheet's code cells.
Definition: Autocomplete.cpp:224
void AddSymbols_Backgroundtask_string(wxString xml)
The real work of AddSymbols is made here and in the background.
Definition: Autocomplete.cpp:141
static wxString FixTemplate(wxString templ)
Basically runs a regex over templates.
Definition: Autocomplete.cpp:634
bool HasDemofile(const wxString &commandname)
Does a demo file for this command exist?
Definition: Autocomplete.cpp:93
void AddSymbol(wxString fun, autoCompletionType type=command)
Manually add an autocompletable symbol to our symbols lists.
Definition: Autocomplete.cpp:578
void ClearWorksheetWords()
Clear the list of words that appear in the workSheet's code cells.
Definition: Autocomplete.cpp:52
The configuration storage for the current worksheet.
Definition: Configuration.h:85