Menu

[8f66b6]: / help.html  Maximize  Restore  History

Download this file

522 lines (506 with data), 22.1 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Documentation for CodeBeagle</title>
</head>
<body>
<b>Introduction to CodeBeagle</b>
<p>
CodeBeagle allows you to quickly find all occurrences of a search term inside source code files. To do so it creates a full text index of
the desired source files. Because it is tolerant to white-space its search syntax works great for searching source code. The search
results are displayed in a source viewer with customizable syntax highlighting.
It runs without installation and leaves you in full control when to update the index.
Advanced features are the support of multiple indexes and custom search scripts which allow to automate sequences of searches.
CodeBeagle is written in Python and based on SqLite and Qt.
</p>
<br/>
<b>Search syntax</b>
<pre>foo bar</pre>
<p>
Matches <strong>foo</strong> followed by any number of white-space followed by <strong>bar</strong> but not <strong>foobar</strong>.
</p>
<p>The asterisk is allowed as the wildcard character to search for keywords that are only partially known:</p>
<pre>foo*</pre>
<p>
Matches any keywords starting with <strong>foo</strong>. This should be quite efficient as the keywords are internally sorted alphabetically and SqLite should easily determine those
starting with a particular string.
</p>
<pre>*bar</pre>
<p>Matches any keyword ending with <strong>bar</strong>. This is less efficient as it requires to scan over all keywords.</p>
<pre>int*ate</pre>
<p>The asterisk is certainly also allowed in the middle of keywords. The example above would match <strong>intermediate</strong>.</p>
<p>To search for a literal asterisk sign it must be separated by a blank:</p>
<pre>a* * b</pre>
<p>This matches all keywords starting with <strong>a</strong> followed by a literal asterisk and then by <strong>b</strong>.</p>
<pre>a&lt;=b</pre>
<p>
Matches <strong>a</strong> followed by any number of white-space followed by <strong>&lt;=</strong> and finally followed by <strong>b</strong>.
By typing a blank between <strong>&lt;</strong> and <strong>=</strong> the search phrase would also match if there are any number of white-space characters
in between.
</p>
<p>
<pre>hello **3 world</pre> matches <strong>hello</strong> followed by one to three unknown words/tokens followed by <strong>world</strong>. This is useful
if you know the beginning and end of the search phrase but in the middle there are some unknown parts.
</p>
<p>
<pre>class &lt;!C|Q!&gt;</pre> allows to directly inject a regex into the query. In the example the query searches for <strong>class</strong> followed by something
starting with <strong>C</strong> or <strong>Q</strong>. As you can see the part between <strong>&lt;!</strong> and <strong>!&gt;</strong> contains the regex.
</p>
<br/>
Technical background:<br/>
The indexing associates the processed documents with their containing keywords. A keyword is an arbitrary
length string of alpha numerical characters, the underscore and the hash sign. The first step of searching is to split the search phrase into a sequence
of keyword and none-keyword parts.
An example:
</p>
<pre>a != b</pre>
<p>
This yields the sequence <strong>a</strong>,<strong>!=</strong>,<strong>b</strong>. <strong>a</strong> and
<strong>b</strong> are keywords. The search can then compute all documents which contain these two
keywords. This set of results will then be stripped down to the final result by reading the files and scanning for the full search phrase
using a regular expression. Any number of white-space is allowed between all parts of the sequence. In the example above there is no
white-space allowed between <strong>!</strong> and <strong>=</strong>. This would be the case if the search phrase was
<strong>a ! = b</strong>.
</p>
<br/>
<b>Filtering the results</b>
<p>The UI offers three filters to drill down the results:</p>
<table border="1" summary="Filter options">
<tr>
<td>Filter by file/path</td>
<td>The file path of the results must contain this filter text as a sub-string to yield a match. If you want to pass more than one filter
separate them with a comma. A minus sign before a filter allows to exclude matches.</td>
</tr>
<tr>
<td>Filter by extension</td>
<td>Specified a list of extensions which are allowed in the result. The separator is the comma. The following syntax is allowed and all
means the same:<strong>cpp,*.cpp,.cpp</strong>. A minus sign before an extension allows to exclude this extension.</td>
</tr>
<tr>
<td>Case sensitive</td>
<td>If checked the case of the search phrase must match</td>
</tr>
</table>
<p><br/></p>
<b>Configuration</b>
<p>
Clicking on the <strong>Settings</strong> button opens a dialog which allows to configure search locations and general settings
like the font type and font size used in the file viewer. Search locations define the directory and file extensions to search. They come
in two flavours: Indexed and not indexed. Indexed search locations depend on an index file to be generated before any
search can be performed. Therefore the search speed is high. Searching non indexed search locations does not need an
index file but is slower instead. The settings done in the dialog are stored in the user profile. If you want to configure machine wide
search locations independent of the currently logged on user read the chapter about the <a href="#GlobalConfig">global configuration file</a>.
</p>
<br>
<b>Updating indexed search locations</b>
<p>
Indexed search locations can be created and updated in two ways. The first way is from the UI by clicking on the
<strong>Update index</strong> button. This allows to select which indexes you want to update. The update itself
is then started as a background process and continues even if CodeBeagle is closed.<br/>
The second way is by directly calling "UpdateIndex.exe". This allows to automate the index update for instance using a
scheduled task.
</p>
<p>
All indexes specified in the global configuration are created or updated when calling the command line program "UpdateIndex.exe".
Use the "--config" switch to additionaly update indexes configured for a specific user. The switch allows to specify the full path to
a user config file. User specific config files are written by CodeBeagle if you use the settings dialog to configure search locations.
They are located under "%APPDATA%\..\local\CodeBeagle\config.txt". If there is no "local" directory the %APPDATA% directory is
used. If %APPDATA% is not defined %HOME% is used. Call "UpdateIndex.exe" with "--help" to show all parameters.<br/>
For an automated index update I recommend to create a scheduled task which runs "UpdateIndex.exe".
</p>
<p>
The index update can be time consuming especially when being called for the first time.
Building a fresh index for 30000 files takes about 80 minutes on my machine at work.
The good thing is that an update for an already existing index is much faster as only modified and new files are processed.
</p>
<br/>
<a name="GlobalConfig"/>
<b>Global configuration file</b>
<p>
The global configuration is stored in "config.txt". CodeBeagle first reads the global "config.txt" and then merges it with
per user configuration from the user profile. This means that the user configuration takes precedence over the machine wide settings.
This global config.txt is expected to be in the same directory as the executables itself. The most important things to configure
are the directories to index, the extensions of the files to collect and the path where the index is stored. Here is an example how
to define an index:
</p>
<pre>
Index1 {
indexdb=D:\mysource.dat
extensions=h,cpp,c
directories=D:\source1,E:\source2
# optional directory excludes
dirExcludes=\dir1,\dir2
}
Index2 {
...
}
</pre>
<p>
This indexes all files in "D:\source1" and "E:\source2" with the extensions "h","cpp" and "c" and stores the result in
"D:\mysource.dat". The section name which specifies the index must start with "index" (case doesn't matter). Optionally
you can specify a list of comma separated strings in the property "dirExcludes". All directories containing one of these strings
will be excluded. The path they are compared with is not terminated with a path separator. As illustrated by the
section "Index2" you are not restricted to only one index definition. When several indexes are defined you can select
the index to search in the upper right corner.
</p>
<p>Here is a full table of all supported settings in "config.txt":</p>
<table border="1" summary="Configuration options">
<tr>
<th>Setting</th>
<th>Meaning</th>
</tr>
<tr>
<td>showCloseConfirmation</td>
<td>If set to none zero the user must confirm a message box when closing the application</td>
</tr>
<tr>
<td>matchOverFiles</td>
<td>Continue with next/previous file if no next/previous match exists in the current file</td>
</tr>
<tr>
<td>updateIndexLog</td>
<td>If set UpdateIndex.exe writes a log file. The setting must contain the full path to the log file</td>
</tr>
<tr>
<td>profileUpdate</td>
<td>If set to none zero UpdateIndex.exe is run in the profiler and the resulting profiling data is printed to stdout.
This really slows down the update and is a debugging option</td>
</tr>
<tr>
<td>IndexXYZ {</td>
<td>All groups starting with <strong>Index</strong> contain an index definition as described above</td>
</tr>
</table>
<p>The config syntax allows to import other config files.<p>
<p>"config.txt" imports "config\SourceViewer.txt" which contains settings about the source viewer:</p>
<table border="1" summary="Source viewer configuration">
<tr>
<th>Setting</th>
<th>Meaning</th>
</tr>
<tr>
<td>fontFamily</td>
<td>Set your desired font family here. E.g. "Courier"</td>
</tr>
<tr>
<td>fontSize</td>
<td>Configures the font size</td>
</tr>
<tr>
<td>tabWidth</td>
<td>Configures the tab width</td>
</tr>
<tr>
<td>HighlighterXYZ {</td>
<td>All groups starting with <strong>Highlighter</strong> contain a syntax highlighting definition. This is explained in the section "Customizing syntax highlighting"</a></td>
</tr>
</table>
<p>
The "config.txt" file also imports "UserConfig.txt" at the very end. The recommendation is to leave "config.txt" unchanged and create
a "UserConfig.txt" where you put all your custom configuration changes. The reason behind this is to keep your settings when you upgrade to a new
version which ships a new "config.txt". This works because a second definition of the same key,value pair overrides
the first. Here is an example of a "UserConfig.txt" which defines one index and overrides the tab width:
</p>
<pre>
Index1 {
indexdb=D:\mysource.dat
extensions=h,cpp,c
directories=D:\source1,E:\source2
}
SourceViewer {
tabWidth = 2
}
</pre>
<p>
Some remarks about the syntax of the configuration:<br/>
The basic syntax is "key = value". A string followed by '{' starts a group. Groups may contain any
number of key value pairs and other groups. The content of another config file may be imported as
a group using the "import {file} as {group}" syntax. The syntax "import {file} imports the content
of a config file in the current group.
</p>
<br/>
<b>Keyboard shortcuts</b>
<p>
<table border="1" summary="Keyboard shortcuts">
<tr>
<td>F7</td>
<td>Jumps to previous match in current document</td>
</tr>
<tr>
<td>F8</td>
<td>Jumps to next match in current document</td>
</tr>
<tr>
<td>CTRL+F</td>
<td>Opens a UI which allows to search for text in the current document</td>
</tr>
<tr>
<td>F3</td>
<td>Shows next occurrence of text in current document</td>
</tr>
<tr>
<td>F4</td>
<td>Shows previous occurrence of text in current document</td>
</tr>
<tr>
<td>F5</td>
<td>Reloads the current document</td>
</tr>
<tr>
<td>CTRL+T</td>
<td>Opens a new search tab</td>
</tr>
<tr>
<td>CTRL+W</td>
<td>Closes the current search tab</td>
</tr>
<tr>
<td>CTRL+S</td>
<td>Opens the settings dialog</td>
</tr>
<tr>
<td>CTRL+G</td>
<td>Goto line in current document</td>
<tr>
<td>ALT+n</td>
<td>Jumps to the n-th tab. Where n is a number of one to six</td>
</tr>
<tr>
<td>CTRL+Text selection</td>
<td>Searches for the selection in a new tab. As a double click on a word selects it this is quite handy to quickly navigate through the source</td>
</tr>
<tr>
<td>CTRL+Shift+Text selection</td>
<td>Searches for the selection in the current tab</td>
</tr>
<tr>
<td>CTRL+B</td>
<td>Jump to matching brace</td>
</tr>
</table>
</p>
<p><br/></p>
<b>Custom context menu entries</b>
<p>
The context menu of the list control which shows the matches can be extended with additonal entries. These entries can either simply
start an executable or execute a script file which contains python code. The following examples show how to configure both types:
</p>
<pre>
ContextMenu1 {
title = Notepad
executable = %windir%\notepad.exe
args = "%file%"
showWindow = True
}
</pre>
<p>
As the example illustrates environment variables are resolved properly. The command line of the executable is specified in <strong>args</strong>.
The special variable <strong>%file%</strong> is resolved as the selected file in the tree control. If more than one file is selected the
executable is started for each of the files.
</p>
<p>
There is also a variant that supports calling programs that need exactly two file parameters like diffing tools. In this case provide two variables
in your <strong>args</strong> with the name <strong>file1</strong> and <strong>file2</strong>.
Here is an example that starts WinMerge:
<pre>
ContextMenu2 {
title = WinMerge
executable = C:\Program Files (x86)\WinMerge\WinMergeU.exe
args = "%file1%" "%file2%"
showWindow = True
}
</pre>
</p>
<pre>
ContextMenu2 {
title = Checkout from version control
script = contextmenu\checkout.py
}
</pre>
<p>
The list of selected files in the tree control is passed as a string list in the variable <strong>files</strong>. Here is an example:
</p>
<pre>
import subprocess
for file in files:
subprocess.Popen ([r"C:\windows\notepad.exe"] + [file])
</pre>
<p><br/></p>
<b>Custom search scripts</b>
<p>
These scripts written in Python allow to automate search tasks. At start-up of the application all files with the extension ".script"
are collected from the sub folder <strong>scripts</strong>.
To execute a custom search script type your search phrase and then select the "wizard hat" icon right of "Find" button and select the
desired script. The script is then called with the search phrase and all filters settings and is expected to return a set of results.
Here is a basic example to illustrate this:
</p>
<pre>
result.matches.extend (performSearch(query, folders, extensions, caseSensitive))
</pre>
<p>The result of this script is identical to what the regular "Find" button does. As you can see the script uses predefined variables and the function
<strong>performSearch</strong>. Here is a list of all other input variables and functions:</p>
<table border="1" summary="Input variables">
<tr>
<td>query</td>
<td>The search phrase as string</td>
</tr>
<tr>
<td>folders</td>
<td>The folder filter as string</td>
</tr>
<tr>
<td>extensions</td>
<td>The extension filter as string</td>
</tr>
<tr>
<td>caseSensitive</td>
<td>Boolean if case sensitive is checked</td>
</tr>
<tr>
<td>regexFromText(query)</td>
<td>Returns the regex object which can be used to highlight "query"</td>
</tr>
</table>
<p>After the script has finished its work the following variables are inspected to be able display the result:</p>
<table border="1" summary="Output variables">
<tr>
<td>result.matches</td>
<td>A list of file names with the matches. Each list entry must be the full path to the matching file</td>
</tr>
<tr>
<td>result.highlight</td>
<td>A regular expression object from the module <strong>re</strong> which is used to highlight the
matches in each of the matching files. This is necessary because only the search script knows what the criterias
are which resulted in the returned matches. If you do not set this variable the default is to highlight the initial
<strong>query </strong> string. Use <strong>regexFromText </strong> to obtain the regex for
instance in order to combine multiple regexes.</td>
</tr>
<tr>
<td>result.label</td>
<td>Allows to set the label of the search tab. If you do not set this variable the default is "Custom script"</td>
</tr>
</table>
<p><br/></p>
<b><a name="customsyntaxhighlighting">Customizing syntax highlighting</a></b>
<p>
The default syntax highlighting works fine for C++ and languages with similar keywords (C#,Java,...). It is configured
in "config\SourceViewer.txt" like this:
</p>
<pre>
Highlighter_Default {
config = C++.txt
extensions = *
}
Highlighter_CPP {
config = C++.txt
extensions = c*,h*,inl
}
</pre>
<p>
Each group starting with <strong>Highlighter</strong> defines a syntax highlighting definition. Each definition contains two entries:
</p>
<table border="1" summary="Highlighting configuration">
<tr>
<td>config</td>
<td>A file containing the syntax highlighting rules. The file must reside in the "config" directory.</td>
</tr>
<tr>
<td>extensions</td>
<td>A list of extensions, possible with wildcards (* and ? allowed)</td>
</tr>
</table>
<p>
The sequence of the <strong>Highlighter</strong> groups is not important. The corresponding highlighting definition for a file is looked up
by the file's extension. If the extension rules of more than one highlighting definition match the one which fits best is used. That means the
one which contains the most none wildcard characters. This allows to define a default rule using an asterisk as shown above.
</p>
<p>
The actual syntax highlighting rule files are Python scripts. The environment for these scripts is constructed in a way to make it easy to
access font weights and colors. It might also help to know that "PyQt5.QtCore" is imported as "QtCore" and "PyQt5.QtGui" is imported as "QtGui".
Highlighting rules are added using three functions. The functions expect the pair <strong>fontWeight</strong> and <strong>foreground</strong>
which is internally used to construct a <strong>QTextCharFormat</strong>:
</p>
<table border="1" summary="Adding highlighting rules">
<tr>
<td>addKeywords (keywordList, fontWeight, foreground)</td>
<td>Adds highlighting to keywords. <strong>keywordList</strong> is a comma separated string with all keywords.
</tr>
<tr>
<td>addCommentRule (singleLine, multiLineStart, multiLineEnd, fontWeight, foreground)</td>
<td>Adds a rule for comments. <strong>singleLine</strong> is a string with a regular expression which matches
the single line comment. <strong>multiLineStart</strong> and <strong>multiLineEnd</strong> are regular expressions
which must match the start and end of a multi-line comment. E.g. for C++ the expression should match
<code>/*</code> resp. <code>*/</code></td>
</tr>
<tr>
<td>addRule (expr, fontWeight, foreground)</td>
<td>Adds an arbitrary rule which highlights the result of the regular expression in <strong>expr</strong></td>
</tr>
<tr>
<td>setColor(color)</td>
<td>Sets the text color used to display documents.</td>
</tr>
</table>
<p>Predefined colors which can be used as <strong>foreground</strong> color:</p>
<ul>
<li>white</li>
<li>black</li>
<li>red</li>
<li>darkRed</li>
<li>green</li>
<li>darkGreen</li>
<li>blue</li>
<li>darkBlue</li>
<li>cyan</li>
<li>darkCyan</li>
<li>magenta</li>
<li>darkMagenta</li>
<li>yellow</li>
<li>darkYellow</li>
<li>gray</li>
<li>darkGray</li>
<li>lightGray</li>
</ul>
<p>
Alternativly you can create any color by using the function <strong>rgb(r,g,b)</strong> or <strong>rgba(r,g,b,a)</strong>.
</p>
<p>Predefined font weights used as <strong>fontWeight</strong> (ordered from light to bold):</p>
<ul>
<li>Light</li>
<li>Normal</li>
<li>DemiBold</li>
<li>Bold</li>
<li>Black</li>
</ul>
<br/>
<b>License</b>
<p>
CodeBeagle Copyright (C) 2011-2021 Oliver Tengler
</p>
<p>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
</p>
<p>
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
</p>
<p>
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>.
</p>
<p>
Most icons were taken from the great "Crystal" icon set found
at <a href="http://www.everaldo.com/crystal/">http://www.everaldo.com/crystal/</a>.
</p>
<p>
Dark theme by Colin Duquesnoy (see <a href="https://github.com/ColinDuquesnoy/QDarkStyleSheet">GitHub</a>)
</p>
<br/>
</body>
</html>
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.