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 "Compat.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 using WorksheetWords = std::unordered_map<wxString, int, wxStringHash>;
63public:
64 using WordList = std::vector<wxString>;
65
68 {
69 command = 0,
77 };
78 explicit AutoComplete(Configuration *configuration);
79
81 ~AutoComplete() override;
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(const wxXmlDocument& xml);
101 void AddSymbols_Backgroundtask_string(const stop_token &stopToken, const wxString &xml);
103 void AddSymbols_Backgroundtask(const stop_token& stopToken, const 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
115 return (type == loadfile) || (type == demofile) || (type == generalfile);
116 }
117
126 void UpdateFiles(autoCompletionType type, const wxString &partial,
127 const wxString &maximaDir);
128
130 void AddWorksheetWords(const WordList &words);
131 void AddWorksheetWords(WordList::const_iterator begin, WordList::const_iterator end);
132
134 void ClearWorksheetWords();
136 void ClearDemofileList();
137
139 std::vector<wxString> CompleteSymbol(wxString partial, autoCompletionType type = command);
147 static bool IsEscHexCompletion(const wxString &completion);
153 static wxString EscCompletionLabel(const wxString &completion);
155 static wxString FixTemplate(wxString templ);
157 std::vector<wxString> GetDemoFilesList();
159 std::vector<wxString> GetSymbolList();
161 bool HasDemofile(const wxString &commandname);
162
163private:
169 void WaitForSymbolTask();
171 Configuration *m_configuration;
173 void LoadableFiles_BackgroundTask(const stop_token& stopToken, const wxString& sharedir, const wxString& demodir);
175 void BuiltinSymbols_BackgroundTask(const stop_token& stopToken);
176
178 std::vector<wxString> m_builtInLoadFiles;
180 std::vector<wxString> m_builtInDemoFiles;
182 class GetGeneralFiles : public wxDirTraverser
183 {
184 public:
185 explicit GetGeneralFiles(std::vector<wxString>& files,
186 std::mutex *lock,
187 stop_token stopToken = {},
188 const wxString &prefix = wxEmptyString) :
189 m_files(files), m_lock(lock), m_stopToken(std::move(stopToken)), m_prefix(prefix) {
190 for(const auto &i : m_files)
191 m_filesHash[i];
192 }
193 wxDirTraverseResult OnFile(const wxString& filename) override
194 {
195 if (m_stopToken.stop_requested()) return wxDIR_STOP;
196 wxFileName newItemName(filename);
197 wxString newItem = "\"" + m_prefix + newItemName.GetFullName() + "\"";
198 newItem.Replace(wxFileName::GetPathSeparator(), "/");
199 {
200 const std::lock_guard<std::mutex> lock(*m_lock);
201 if (!m_filesHash.contains(newItem))
202 {
203 m_files.push_back(newItem);
204 m_filesHash[newItem];
205 }
206 }
207 return wxDIR_CONTINUE;
208 }
209 wxDirTraverseResult OnDir(const wxString& dirname) override
210 {
211 if (m_stopToken.stop_requested()) return wxDIR_STOP;
212 wxFileName newItemName(dirname);
213 wxString newItem = "\"" + m_prefix + newItemName.GetFullName() + "/\"";
214 newItem.Replace(wxFileName::GetPathSeparator(), "/");
215 {
216 const std::lock_guard<std::mutex> lock(*m_lock);
217 if (!m_filesHash.contains(newItem))
218 {
219 m_files.push_back(newItem);
220 m_filesHash[newItem];
221 }
222 }
223 return wxDIR_IGNORE;
224 }
225 std::vector<wxString> GetResult(){
226 const std::lock_guard<std::mutex> lock(*m_lock);
227 return m_files;
228 }
229 protected:
231 std::vector<wxString>& m_files;
233 std::unordered_map<wxString, wxEvtHandler*, wxStringHash> m_filesHash;
234 std::mutex *m_lock;
235 stop_token m_stopToken;
236 wxString m_prefix;
237 };
238
240 class GetMacFiles_includingSubdirs : public wxDirTraverser
241 {
242 public:
243 explicit GetMacFiles_includingSubdirs(std::vector<wxString>& files,
244 std::mutex *lock,
245 stop_token stopToken = {},
246 const wxString &prefix = wxEmptyString) :
247 m_files(files), m_lock(lock), m_stopToken(std::move(stopToken)), m_prefix(prefix)
248 {
249 for(const auto &i : m_files)
250 m_filesHash[i];
251 }
252 wxDirTraverseResult OnFile(const wxString& filename) override
253 {
254 if (m_stopToken.stop_requested()) return wxDIR_STOP;
255 if(
256 (filename.EndsWith(".mac"))||
257 (filename.EndsWith(".lisp"))||
258 (filename.EndsWith(".wxm"))
259 )
260 {
261 wxFileName newItemName(filename);
262 wxString newItem = "\"" + m_prefix + newItemName.GetName() + "\"";
263 newItem.Replace(wxFileName::GetPathSeparator(), "/");
264 {
265 const std::lock_guard<std::mutex> lock(*m_lock);
266 if (!m_filesHash.contains(newItem))
267 {
268 m_files.push_back(newItem);
269 m_filesHash[newItem];
270 }
271 }
272 }
273 return wxDIR_CONTINUE;
274 }
275 wxDirTraverseResult OnDir(const wxString& dirname) override
276 {
277 if (m_stopToken.stop_requested()) return wxDIR_STOP;
278 if((dirname.EndsWith(".git")) ||
279 (dirname.EndsWith("/share/share")) ||
280 (dirname.EndsWith("/src/src")) ||
281 (dirname.EndsWith("/doc/doc")) ||
282 (dirname.EndsWith("/interfaces/interfaces"))
283 )
284 return wxDIR_STOP;
285 else
286 return wxDIR_CONTINUE;
287 }
288 std::vector<wxString> GetResult(){
289 const std::lock_guard<std::mutex> lock(*m_lock);
290 return m_files;
291 }
292 protected:
294 std::vector<wxString>& m_files;
296 std::unordered_map<wxString, wxEvtHandler*, wxStringHash> m_filesHash;
297 std::mutex *m_lock;
298 stop_token m_stopToken;
299 wxString m_prefix;
300 };
301
303 class GetMacFiles : public GetMacFiles_includingSubdirs
304 {
305 public:
306 explicit GetMacFiles(std::vector<wxString>& files,
307 std::mutex *lock,
308 stop_token stopToken = {},
309 const wxString &prefix = wxEmptyString) :
310 GetMacFiles_includingSubdirs(files, lock, std::move(stopToken), prefix){ }
311 wxDirTraverseResult OnDir(const wxString& dirname) override
312 {
313 if (m_stopToken.stop_requested()) return wxDIR_STOP;
314 wxFileName newItemName(dirname);
315 wxString newItem = "\"" + m_prefix + newItemName.GetFullName() + "/\"";
316 newItem.Replace(wxFileName::GetPathSeparator(), "/");
317 {
318 const std::lock_guard<std::mutex> lock(*m_lock);
319 if (!m_filesHash.contains(newItem))
320 {
321 m_files.push_back(newItem);
322 m_filesHash[newItem];
323 }
324 }
325 return wxDIR_IGNORE;
326 }
327 };
328
330 class GetDemoFiles_includingSubdirs : public wxDirTraverser
331 {
332 public:
333 explicit GetDemoFiles_includingSubdirs(std::vector<wxString>& files,
334 std::mutex *lock,
335 stop_token stopToken = {},
336 const wxString &prefix = wxEmptyString) :
337 m_files(files), m_lock(lock), m_stopToken(std::move(stopToken)), m_prefix(prefix)
338 {
339 for(const auto &i : m_files)
340 m_filesHash[i];
341 }
342 wxDirTraverseResult OnFile(const wxString& filename) override
343 {
344 if (m_stopToken.stop_requested()) return wxDIR_STOP;
345 if(filename.EndsWith(".dem"))
346 {
347 wxFileName newItemName(filename);
348 wxString newItem = "\"" + m_prefix + newItemName.GetName() + "\"";
349 newItem.Replace(wxFileName::GetPathSeparator(), "/");
350 {
351 const std::lock_guard<std::mutex> lock(*m_lock);
352 if (!m_filesHash.contains(newItem))
353 {
354 m_files.push_back(newItem);
355 m_filesHash[newItem];
356 }
357 }
358 }
359 return wxDIR_CONTINUE;
360 }
361 wxDirTraverseResult OnDir(const wxString& dirname) override
362 {
363 if (m_stopToken.stop_requested()) return wxDIR_STOP;
364 if((dirname.EndsWith(".git")) ||
365 (dirname.EndsWith("/share/share")) ||
366 (dirname.EndsWith("/src/src")) ||
367 (dirname.EndsWith("/doc/doc")) ||
368 (dirname.EndsWith("/interfaces/interfaces"))
369 )
370 return wxDIR_STOP;
371 else
372 return wxDIR_CONTINUE;
373 }
374 std::vector<wxString> GetResult(){
375 const std::lock_guard<std::mutex> lock(*m_lock);
376 return m_files;
377 }
378 protected:
380 std::vector<wxString>& m_files;
382 std::unordered_map<wxString, wxEvtHandler*, wxStringHash> m_filesHash;
383 std::mutex *m_lock;
384 stop_token m_stopToken;
385 wxString m_prefix;
386 };
387
389 class GetDemoFiles : public GetDemoFiles_includingSubdirs
390 {
391 public:
392 explicit GetDemoFiles(std::vector<wxString>& files,
393 std::mutex *lock,
394 stop_token stopToken = {},
395 const wxString &prefix = wxEmptyString) :
396 GetDemoFiles_includingSubdirs(files, lock, std::move(stopToken), prefix){ }
397 wxDirTraverseResult OnDir(const wxString& dirname) override
398 {
399 if (m_stopToken.stop_requested()) return wxDIR_STOP;
400 wxFileName newItemName(dirname);
401 wxString newItem = "\"" + m_prefix + newItemName.GetFullName() + "/\"";
402 newItem.Replace(wxFileName::GetPathSeparator(), "/");
403 {
404 const std::lock_guard<std::mutex> lock(*m_lock);
405 if (!m_filesHash.contains(newItem))
406 {
407 m_files.push_back(newItem);
408 m_filesHash[newItem];
409 }
410 }
411 return wxDIR_IGNORE;
412 }
413 };
414
415 jthread m_addSymbols_backgroundThread;
416 jthread m_addFiles_backgroundThread;
418 std::mutex m_keywordsLock;
420 std::vector<std::vector<wxString>> m_wordList;
421 static wxRegEx m_args;
422 WorksheetWords m_worksheetWords;
423};
424
425wxDECLARE_EVENT(NEW_DEMO_FILES_EVENT, wxCommandEvent);
426
427#endif // AUTOCOMPLETE_H
Small compatibility shims for older toolchains and older wxWidgets.
Definition: Autocomplete.h:61
std::vector< wxString > GetSymbolList()
Returns a list of Symbols we know.
Definition: Autocomplete.cpp:64
void ClearDemofileList()
Clear the list of files demo() can be applied on.
Definition: Autocomplete.cpp:131
void UpdateFiles(autoCompletionType type, const wxString &partial, const wxString &maximaDir)
Re-scan the directory a file-name completion currently points into.
Definition: Autocomplete.cpp:491
std::vector< wxString > GetDemoFilesList()
Returns a list of demo files we know of.
Definition: Autocomplete.cpp:59
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:508
static bool IsEscHexCompletion(const wxString &completion)
Is this ESC completion a code point typed as a hex number, not a name?
Definition: Autocomplete.cpp:701
static bool CompletesFiles(autoCompletionType type)
Is this completion type one that completes file names?
Definition: Autocomplete.h:114
void LoadSymbols()
Load all autocomplete symbols wxMaxima knows about by itself.
Definition: Autocomplete.cpp:299
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:641
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:594
void LoadBuiltinSymbols()
Makes wxMaxima know all its builtin symbols.
Definition: Autocomplete.cpp:70
~AutoComplete() override
The destructor of AutoComplete.
Definition: Autocomplete.cpp:291
void AddSymbols_Backgroundtask_string(const stop_token &stopToken, const wxString &xml)
The real work of AddSymbols is made here and in the background.
Definition: Autocomplete.cpp:175
void UpdateGeneralFiles(wxString partial, const wxString &maximaDir)
Assemble a list of files.
Definition: Autocomplete.cpp:549
void AddSymbols(wxString xml)
Interprets the XML autocompletable symbol list maxima can send us.
Definition: Autocomplete.cpp:136
void AddWorksheetWords(const WordList &words)
Add words to the list of words that appear in the workSheet's code cells.
Definition: Autocomplete.cpp:287
static wxString EscCompletionLabel(const wxString &completion)
What the ESC popup shows for a completion: the symbol next to its name.
Definition: Autocomplete.cpp:710
static wxString FixTemplate(wxString templ)
Basically runs a regex over templates.
Definition: Autocomplete.cpp:783
bool HasDemofile(const wxString &commandname)
Does a demo file for this command exist?
Definition: Autocomplete.cpp:121
void AddSymbols_Backgroundtask(const stop_token &stopToken, const wxXmlDocument &xmldoc)
The real work of AddSymbols is made here and in the background.
Definition: Autocomplete.cpp:182
void AddSymbol(wxString fun, autoCompletionType type=command)
Manually add an autocompletable symbol to our symbols lists.
Definition: Autocomplete.cpp:728
void ClearWorksheetWords()
Clear the list of words that appear in the workSheet's code cells.
Definition: Autocomplete.cpp:54
The configuration storage for the current worksheet.
Definition: Configuration.h:102
Definition: Compat.h:58
Definition: Compat.h:47