Lexitron 2.0.4__tar.gz → 2.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {Lexitron-2.0.4 → lexitron-2.1.2/Lexitron.egg-info}/PKG-INFO +48 -52
- {Lexitron-2.0.4 → lexitron-2.1.2}/Lexitron.egg-info/SOURCES.txt +5 -2
- {Lexitron-2.0.4 → lexitron-2.1.2}/Lexitron.egg-info/top_level.txt +1 -0
- {Lexitron-2.0.4/Lexitron.egg-info → lexitron-2.1.2}/PKG-INFO +48 -52
- {Lexitron-2.0.4 → lexitron-2.1.2}/README.md +43 -49
- lexitron-2.1.2/lexitron/lexitron.py +282 -0
- lexitron-2.1.2/pyproject.toml +39 -0
- lexitron-2.1.2/setup.cfg +4 -0
- Lexitron-2.0.4/lexitron/lexitron.py +0 -190
- Lexitron-2.0.4/pyproject.toml +0 -3
- Lexitron-2.0.4/setup.cfg +0 -38
- {Lexitron-2.0.4 → lexitron-2.1.2}/LICENSE +0 -0
- {Lexitron-2.0.4 → lexitron-2.1.2}/Lexitron.egg-info/dependency_links.txt +0 -0
- {Lexitron-2.0.4 → lexitron-2.1.2}/Lexitron.egg-info/entry_points.txt +0 -0
- {Lexitron-2.0.4 → lexitron-2.1.2}/Lexitron.egg-info/not-zip-safe +0 -0
- {Lexitron-2.0.4 → lexitron-2.1.2}/Lexitron.egg-info/requires.txt +0 -0
- {Lexitron-2.0.4 → lexitron-2.1.2}/lexitron/__init__.py +0 -0
- {Lexitron-2.0.4 → lexitron-2.1.2}/lexitron/agid-common.txt +0 -0
- {Lexitron-2.0.4 → lexitron-2.1.2}/lexitron/agid-proper.txt +0 -0
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: Lexitron
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: A command-line regex search engine for the English language
|
|
5
|
-
Home-page: http://github.com/rothos/lexitron
|
|
6
5
|
Author: Rothos
|
|
7
6
|
License: GNU GPL Version 2
|
|
7
|
+
Project-URL: Homepage, http://github.com/rothos/lexitron
|
|
8
8
|
Keywords: english,dictionary,crossword,spelling,words,lexicon,search
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Requires-Python: >=3.7
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
|
+
Requires-Dist: importlib-metadata; python_version < "3.8"
|
|
14
|
+
Requires-Dist: importlib-resources; python_version < "3.8"
|
|
13
15
|
|
|
14
16
|
Lexitron
|
|
15
17
|
==============================================================================
|
|
@@ -57,11 +59,12 @@ where `expression` is a regular expression and `[options]` are as follows.
|
|
|
57
59
|
|
|
58
60
|
option | function
|
|
59
61
|
--------|-------------------------------------------------
|
|
60
|
-
`-
|
|
62
|
+
`-h` | Print help and exit
|
|
63
|
+
`-i` | Print info header along with search results
|
|
61
64
|
`-n` | Print only the number of matches
|
|
62
|
-
`-u` |
|
|
63
|
-
`-U` | Search only for uppercase/proper
|
|
64
|
-
`-v` |
|
|
65
|
+
`-u` | Include uppercase/proper words (like "France") in addition to lowercase/common words
|
|
66
|
+
`-U` | Search only for uppercase/proper words
|
|
67
|
+
`-v` | Print version and exit
|
|
65
68
|
`-x` | Print unformatted output, one word per line
|
|
66
69
|
|
|
67
70
|
Type `$ lx -h` for full help text.
|
|
@@ -87,37 +90,30 @@ Examples
|
|
|
87
90
|
------------------------------------------------------------------------------
|
|
88
91
|
|
|
89
92
|
### Example 1
|
|
90
|
-
A list of English words ending with "icide".
|
|
93
|
+
A list of lowercase English words ending with "icide".
|
|
91
94
|
```
|
|
92
95
|
$ lx icide$
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
feticide larvicide parricide spermicide
|
|
108
|
-
filicide liberticide patricide sporicide
|
|
96
|
+
aborticide germicide ovicide spermicide
|
|
97
|
+
acaricide giganticide parasiticide sporicide
|
|
98
|
+
agricide herbicide parasuicide stillicide
|
|
99
|
+
algicide homicide parricide suicide
|
|
100
|
+
aphicide infanticide patricide tyrannicide
|
|
101
|
+
aphidicide insecticide pesticide uxoricide
|
|
102
|
+
bacillicide larvicide prolicide vaticide
|
|
103
|
+
bactericide liberticide pulicide verbicide
|
|
104
|
+
deicide matricide raticide vermicide
|
|
105
|
+
feticide medicide regicide viricide
|
|
106
|
+
filicide menticide rodenticide vulpicide
|
|
107
|
+
foeticide miticide scabicide
|
|
108
|
+
fratricide molluscicide silicide
|
|
109
|
+
fungicide nematicide sororicide
|
|
109
110
|
```
|
|
110
111
|
|
|
111
112
|
### Example 2
|
|
112
|
-
A list of English words that contain the substring "rdb".
|
|
113
|
+
A list of lowercase English words that contain the substring "rdb", printed with info header.
|
|
113
114
|
```
|
|
114
|
-
$ lx rdb
|
|
115
|
-
|
|
116
|
-
21 results for /rdb/
|
|
117
|
-
1 proper ~ 20 common
|
|
118
|
-
---------------------------------------------------------------------------
|
|
119
|
-
|
|
120
|
-
Standardbred
|
|
115
|
+
$ lx -i rdb
|
|
116
|
+
20 matches for /rdb/
|
|
121
117
|
|
|
122
118
|
birdbath herdbook
|
|
123
119
|
birdbrain herdboy
|
|
@@ -134,7 +130,7 @@ hardbound yardbird
|
|
|
134
130
|
### Example 3
|
|
135
131
|
The number of lowercase English words that end in "tion".
|
|
136
132
|
```
|
|
137
|
-
$ lx -
|
|
133
|
+
$ lx -n ".*tion"
|
|
138
134
|
3837
|
|
139
135
|
```
|
|
140
136
|
(This number should be taken with a grain of salt, since no dictionary
|
|
@@ -145,13 +141,10 @@ and which technical or niche jargons are included; etc etc.)
|
|
|
145
141
|
### Example 4
|
|
146
142
|
A list of English words with the same double letter appearing twice, except
|
|
147
143
|
for those whose double letter is a vowel or the letter `s` (to ignore
|
|
148
|
-
words of the form `*lessness`).
|
|
144
|
+
words of the form `*lessness`), printed with info header.
|
|
149
145
|
```
|
|
150
|
-
$ lx "([^aeious])\1.*\1\1"
|
|
151
|
-
|
|
152
|
-
45 results for /([^aeious])\1.*\1\1/
|
|
153
|
-
9 proper ~ 36 common
|
|
154
|
-
---------------------------------------------------------------------------
|
|
146
|
+
$ lx -iu "([^aeious])\1.*\1\1"
|
|
147
|
+
45 matches for /([^aeious])\1.*\1\1/ (9 proper, 36 common)
|
|
155
148
|
|
|
156
149
|
Allhallowmas
|
|
157
150
|
Allhallows
|
|
@@ -163,26 +156,29 @@ Gallirallus
|
|
|
163
156
|
Hunnemannia
|
|
164
157
|
Llullaillaco
|
|
165
158
|
|
|
166
|
-
acciaccatura
|
|
167
|
-
bellpull
|
|
168
|
-
chiffchaff
|
|
169
|
-
dillydallier
|
|
170
|
-
dillydally
|
|
171
|
-
dullsville
|
|
172
|
-
flibbertigibbet
|
|
173
|
-
granddaddy
|
|
174
|
-
hallalling
|
|
159
|
+
acciaccatura jellyroll rollcollar
|
|
160
|
+
bellpull kinnikinnic rollerball
|
|
161
|
+
chiffchaff kinnikinnick scuttlebutt
|
|
162
|
+
dillydallier millefeuille shillyshally
|
|
163
|
+
dillydally niffnaff skillfully
|
|
164
|
+
dullsville parallelling snippersnapper
|
|
165
|
+
flibbertigibbet pellmell villanelle
|
|
166
|
+
granddaddy pizzazz volleyball
|
|
167
|
+
hallalling pralltriller volleyballer
|
|
168
|
+
hillbilly razzamatazz whippersnapper
|
|
169
|
+
huggermugger razzmatazz willfully
|
|
170
|
+
hullaballoo riffraff yellowbelly
|
|
175
171
|
```
|
|
176
172
|
|
|
177
173
|
### Example 5
|
|
178
|
-
Compare the number of lowercase
|
|
174
|
+
Compare the number of lowercase English words that end in "woman"
|
|
179
175
|
with the number that end in "man".
|
|
180
176
|
```
|
|
181
|
-
$ lx -
|
|
177
|
+
$ lx -n ".*woman"
|
|
182
178
|
107
|
|
183
179
|
```
|
|
184
180
|
```
|
|
185
|
-
$ lx -
|
|
181
|
+
$ lx -n ".*(?<\!wo)man"
|
|
186
182
|
1145
|
|
187
183
|
```
|
|
188
184
|
|
|
@@ -202,4 +198,4 @@ Lexitron is licensed under GNU GPL Version 2.
|
|
|
202
198
|
Contact
|
|
203
199
|
------------------------------------------------------------------------------
|
|
204
200
|
Questions, bug reports, and feature requests can be filed on the [Github
|
|
205
|
-
issues tracker](//github.com/
|
|
201
|
+
issues tracker](//github.com/rothos/lexitron/issues).
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
|
-
setup.cfg
|
|
5
4
|
./lexitron/__init__.py
|
|
6
5
|
./lexitron/agid-common.txt
|
|
7
6
|
./lexitron/agid-proper.txt
|
|
@@ -12,4 +11,8 @@ Lexitron.egg-info/dependency_links.txt
|
|
|
12
11
|
Lexitron.egg-info/entry_points.txt
|
|
13
12
|
Lexitron.egg-info/not-zip-safe
|
|
14
13
|
Lexitron.egg-info/requires.txt
|
|
15
|
-
Lexitron.egg-info/top_level.txt
|
|
14
|
+
Lexitron.egg-info/top_level.txt
|
|
15
|
+
lexitron/__init__.py
|
|
16
|
+
lexitron/agid-common.txt
|
|
17
|
+
lexitron/agid-proper.txt
|
|
18
|
+
lexitron/lexitron.py
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: Lexitron
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: A command-line regex search engine for the English language
|
|
5
|
-
Home-page: http://github.com/rothos/lexitron
|
|
6
5
|
Author: Rothos
|
|
7
6
|
License: GNU GPL Version 2
|
|
7
|
+
Project-URL: Homepage, http://github.com/rothos/lexitron
|
|
8
8
|
Keywords: english,dictionary,crossword,spelling,words,lexicon,search
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Requires-Python: >=3.7
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
|
+
Requires-Dist: importlib-metadata; python_version < "3.8"
|
|
14
|
+
Requires-Dist: importlib-resources; python_version < "3.8"
|
|
13
15
|
|
|
14
16
|
Lexitron
|
|
15
17
|
==============================================================================
|
|
@@ -57,11 +59,12 @@ where `expression` is a regular expression and `[options]` are as follows.
|
|
|
57
59
|
|
|
58
60
|
option | function
|
|
59
61
|
--------|-------------------------------------------------
|
|
60
|
-
`-
|
|
62
|
+
`-h` | Print help and exit
|
|
63
|
+
`-i` | Print info header along with search results
|
|
61
64
|
`-n` | Print only the number of matches
|
|
62
|
-
`-u` |
|
|
63
|
-
`-U` | Search only for uppercase/proper
|
|
64
|
-
`-v` |
|
|
65
|
+
`-u` | Include uppercase/proper words (like "France") in addition to lowercase/common words
|
|
66
|
+
`-U` | Search only for uppercase/proper words
|
|
67
|
+
`-v` | Print version and exit
|
|
65
68
|
`-x` | Print unformatted output, one word per line
|
|
66
69
|
|
|
67
70
|
Type `$ lx -h` for full help text.
|
|
@@ -87,37 +90,30 @@ Examples
|
|
|
87
90
|
------------------------------------------------------------------------------
|
|
88
91
|
|
|
89
92
|
### Example 1
|
|
90
|
-
A list of English words ending with "icide".
|
|
93
|
+
A list of lowercase English words ending with "icide".
|
|
91
94
|
```
|
|
92
95
|
$ lx icide$
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
feticide larvicide parricide spermicide
|
|
108
|
-
filicide liberticide patricide sporicide
|
|
96
|
+
aborticide germicide ovicide spermicide
|
|
97
|
+
acaricide giganticide parasiticide sporicide
|
|
98
|
+
agricide herbicide parasuicide stillicide
|
|
99
|
+
algicide homicide parricide suicide
|
|
100
|
+
aphicide infanticide patricide tyrannicide
|
|
101
|
+
aphidicide insecticide pesticide uxoricide
|
|
102
|
+
bacillicide larvicide prolicide vaticide
|
|
103
|
+
bactericide liberticide pulicide verbicide
|
|
104
|
+
deicide matricide raticide vermicide
|
|
105
|
+
feticide medicide regicide viricide
|
|
106
|
+
filicide menticide rodenticide vulpicide
|
|
107
|
+
foeticide miticide scabicide
|
|
108
|
+
fratricide molluscicide silicide
|
|
109
|
+
fungicide nematicide sororicide
|
|
109
110
|
```
|
|
110
111
|
|
|
111
112
|
### Example 2
|
|
112
|
-
A list of English words that contain the substring "rdb".
|
|
113
|
+
A list of lowercase English words that contain the substring "rdb", printed with info header.
|
|
113
114
|
```
|
|
114
|
-
$ lx rdb
|
|
115
|
-
|
|
116
|
-
21 results for /rdb/
|
|
117
|
-
1 proper ~ 20 common
|
|
118
|
-
---------------------------------------------------------------------------
|
|
119
|
-
|
|
120
|
-
Standardbred
|
|
115
|
+
$ lx -i rdb
|
|
116
|
+
20 matches for /rdb/
|
|
121
117
|
|
|
122
118
|
birdbath herdbook
|
|
123
119
|
birdbrain herdboy
|
|
@@ -134,7 +130,7 @@ hardbound yardbird
|
|
|
134
130
|
### Example 3
|
|
135
131
|
The number of lowercase English words that end in "tion".
|
|
136
132
|
```
|
|
137
|
-
$ lx -
|
|
133
|
+
$ lx -n ".*tion"
|
|
138
134
|
3837
|
|
139
135
|
```
|
|
140
136
|
(This number should be taken with a grain of salt, since no dictionary
|
|
@@ -145,13 +141,10 @@ and which technical or niche jargons are included; etc etc.)
|
|
|
145
141
|
### Example 4
|
|
146
142
|
A list of English words with the same double letter appearing twice, except
|
|
147
143
|
for those whose double letter is a vowel or the letter `s` (to ignore
|
|
148
|
-
words of the form `*lessness`).
|
|
144
|
+
words of the form `*lessness`), printed with info header.
|
|
149
145
|
```
|
|
150
|
-
$ lx "([^aeious])\1.*\1\1"
|
|
151
|
-
|
|
152
|
-
45 results for /([^aeious])\1.*\1\1/
|
|
153
|
-
9 proper ~ 36 common
|
|
154
|
-
---------------------------------------------------------------------------
|
|
146
|
+
$ lx -iu "([^aeious])\1.*\1\1"
|
|
147
|
+
45 matches for /([^aeious])\1.*\1\1/ (9 proper, 36 common)
|
|
155
148
|
|
|
156
149
|
Allhallowmas
|
|
157
150
|
Allhallows
|
|
@@ -163,26 +156,29 @@ Gallirallus
|
|
|
163
156
|
Hunnemannia
|
|
164
157
|
Llullaillaco
|
|
165
158
|
|
|
166
|
-
acciaccatura
|
|
167
|
-
bellpull
|
|
168
|
-
chiffchaff
|
|
169
|
-
dillydallier
|
|
170
|
-
dillydally
|
|
171
|
-
dullsville
|
|
172
|
-
flibbertigibbet
|
|
173
|
-
granddaddy
|
|
174
|
-
hallalling
|
|
159
|
+
acciaccatura jellyroll rollcollar
|
|
160
|
+
bellpull kinnikinnic rollerball
|
|
161
|
+
chiffchaff kinnikinnick scuttlebutt
|
|
162
|
+
dillydallier millefeuille shillyshally
|
|
163
|
+
dillydally niffnaff skillfully
|
|
164
|
+
dullsville parallelling snippersnapper
|
|
165
|
+
flibbertigibbet pellmell villanelle
|
|
166
|
+
granddaddy pizzazz volleyball
|
|
167
|
+
hallalling pralltriller volleyballer
|
|
168
|
+
hillbilly razzamatazz whippersnapper
|
|
169
|
+
huggermugger razzmatazz willfully
|
|
170
|
+
hullaballoo riffraff yellowbelly
|
|
175
171
|
```
|
|
176
172
|
|
|
177
173
|
### Example 5
|
|
178
|
-
Compare the number of lowercase
|
|
174
|
+
Compare the number of lowercase English words that end in "woman"
|
|
179
175
|
with the number that end in "man".
|
|
180
176
|
```
|
|
181
|
-
$ lx -
|
|
177
|
+
$ lx -n ".*woman"
|
|
182
178
|
107
|
|
183
179
|
```
|
|
184
180
|
```
|
|
185
|
-
$ lx -
|
|
181
|
+
$ lx -n ".*(?<\!wo)man"
|
|
186
182
|
1145
|
|
187
183
|
```
|
|
188
184
|
|
|
@@ -202,4 +198,4 @@ Lexitron is licensed under GNU GPL Version 2.
|
|
|
202
198
|
Contact
|
|
203
199
|
------------------------------------------------------------------------------
|
|
204
200
|
Questions, bug reports, and feature requests can be filed on the [Github
|
|
205
|
-
issues tracker](//github.com/
|
|
201
|
+
issues tracker](//github.com/rothos/lexitron/issues).
|
|
@@ -44,11 +44,12 @@ where `expression` is a regular expression and `[options]` are as follows.
|
|
|
44
44
|
|
|
45
45
|
option | function
|
|
46
46
|
--------|-------------------------------------------------
|
|
47
|
-
`-
|
|
47
|
+
`-h` | Print help and exit
|
|
48
|
+
`-i` | Print info header along with search results
|
|
48
49
|
`-n` | Print only the number of matches
|
|
49
|
-
`-u` |
|
|
50
|
-
`-U` | Search only for uppercase/proper
|
|
51
|
-
`-v` |
|
|
50
|
+
`-u` | Include uppercase/proper words (like "France") in addition to lowercase/common words
|
|
51
|
+
`-U` | Search only for uppercase/proper words
|
|
52
|
+
`-v` | Print version and exit
|
|
52
53
|
`-x` | Print unformatted output, one word per line
|
|
53
54
|
|
|
54
55
|
Type `$ lx -h` for full help text.
|
|
@@ -74,37 +75,30 @@ Examples
|
|
|
74
75
|
------------------------------------------------------------------------------
|
|
75
76
|
|
|
76
77
|
### Example 1
|
|
77
|
-
A list of English words ending with "icide".
|
|
78
|
+
A list of lowercase English words ending with "icide".
|
|
78
79
|
```
|
|
79
80
|
$ lx icide$
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
feticide larvicide parricide spermicide
|
|
95
|
-
filicide liberticide patricide sporicide
|
|
81
|
+
aborticide germicide ovicide spermicide
|
|
82
|
+
acaricide giganticide parasiticide sporicide
|
|
83
|
+
agricide herbicide parasuicide stillicide
|
|
84
|
+
algicide homicide parricide suicide
|
|
85
|
+
aphicide infanticide patricide tyrannicide
|
|
86
|
+
aphidicide insecticide pesticide uxoricide
|
|
87
|
+
bacillicide larvicide prolicide vaticide
|
|
88
|
+
bactericide liberticide pulicide verbicide
|
|
89
|
+
deicide matricide raticide vermicide
|
|
90
|
+
feticide medicide regicide viricide
|
|
91
|
+
filicide menticide rodenticide vulpicide
|
|
92
|
+
foeticide miticide scabicide
|
|
93
|
+
fratricide molluscicide silicide
|
|
94
|
+
fungicide nematicide sororicide
|
|
96
95
|
```
|
|
97
96
|
|
|
98
97
|
### Example 2
|
|
99
|
-
A list of English words that contain the substring "rdb".
|
|
98
|
+
A list of lowercase English words that contain the substring "rdb", printed with info header.
|
|
100
99
|
```
|
|
101
|
-
$ lx rdb
|
|
102
|
-
|
|
103
|
-
21 results for /rdb/
|
|
104
|
-
1 proper ~ 20 common
|
|
105
|
-
---------------------------------------------------------------------------
|
|
106
|
-
|
|
107
|
-
Standardbred
|
|
100
|
+
$ lx -i rdb
|
|
101
|
+
20 matches for /rdb/
|
|
108
102
|
|
|
109
103
|
birdbath herdbook
|
|
110
104
|
birdbrain herdboy
|
|
@@ -121,7 +115,7 @@ hardbound yardbird
|
|
|
121
115
|
### Example 3
|
|
122
116
|
The number of lowercase English words that end in "tion".
|
|
123
117
|
```
|
|
124
|
-
$ lx -
|
|
118
|
+
$ lx -n ".*tion"
|
|
125
119
|
3837
|
|
126
120
|
```
|
|
127
121
|
(This number should be taken with a grain of salt, since no dictionary
|
|
@@ -132,13 +126,10 @@ and which technical or niche jargons are included; etc etc.)
|
|
|
132
126
|
### Example 4
|
|
133
127
|
A list of English words with the same double letter appearing twice, except
|
|
134
128
|
for those whose double letter is a vowel or the letter `s` (to ignore
|
|
135
|
-
words of the form `*lessness`).
|
|
129
|
+
words of the form `*lessness`), printed with info header.
|
|
136
130
|
```
|
|
137
|
-
$ lx "([^aeious])\1.*\1\1"
|
|
138
|
-
|
|
139
|
-
45 results for /([^aeious])\1.*\1\1/
|
|
140
|
-
9 proper ~ 36 common
|
|
141
|
-
---------------------------------------------------------------------------
|
|
131
|
+
$ lx -iu "([^aeious])\1.*\1\1"
|
|
132
|
+
45 matches for /([^aeious])\1.*\1\1/ (9 proper, 36 common)
|
|
142
133
|
|
|
143
134
|
Allhallowmas
|
|
144
135
|
Allhallows
|
|
@@ -150,26 +141,29 @@ Gallirallus
|
|
|
150
141
|
Hunnemannia
|
|
151
142
|
Llullaillaco
|
|
152
143
|
|
|
153
|
-
acciaccatura
|
|
154
|
-
bellpull
|
|
155
|
-
chiffchaff
|
|
156
|
-
dillydallier
|
|
157
|
-
dillydally
|
|
158
|
-
dullsville
|
|
159
|
-
flibbertigibbet
|
|
160
|
-
granddaddy
|
|
161
|
-
hallalling
|
|
144
|
+
acciaccatura jellyroll rollcollar
|
|
145
|
+
bellpull kinnikinnic rollerball
|
|
146
|
+
chiffchaff kinnikinnick scuttlebutt
|
|
147
|
+
dillydallier millefeuille shillyshally
|
|
148
|
+
dillydally niffnaff skillfully
|
|
149
|
+
dullsville parallelling snippersnapper
|
|
150
|
+
flibbertigibbet pellmell villanelle
|
|
151
|
+
granddaddy pizzazz volleyball
|
|
152
|
+
hallalling pralltriller volleyballer
|
|
153
|
+
hillbilly razzamatazz whippersnapper
|
|
154
|
+
huggermugger razzmatazz willfully
|
|
155
|
+
hullaballoo riffraff yellowbelly
|
|
162
156
|
```
|
|
163
157
|
|
|
164
158
|
### Example 5
|
|
165
|
-
Compare the number of lowercase
|
|
159
|
+
Compare the number of lowercase English words that end in "woman"
|
|
166
160
|
with the number that end in "man".
|
|
167
161
|
```
|
|
168
|
-
$ lx -
|
|
162
|
+
$ lx -n ".*woman"
|
|
169
163
|
107
|
|
170
164
|
```
|
|
171
165
|
```
|
|
172
|
-
$ lx -
|
|
166
|
+
$ lx -n ".*(?<\!wo)man"
|
|
173
167
|
1145
|
|
174
168
|
```
|
|
175
169
|
|
|
@@ -189,4 +183,4 @@ Lexitron is licensed under GNU GPL Version 2.
|
|
|
189
183
|
Contact
|
|
190
184
|
------------------------------------------------------------------------------
|
|
191
185
|
Questions, bug reports, and feature requests can be filed on the [Github
|
|
192
|
-
issues tracker](//github.com/
|
|
186
|
+
issues tracker](//github.com/rothos/lexitron/issues).
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import sys, os, re, argparse
|
|
2
|
+
from importlib import resources, metadata
|
|
3
|
+
from math import ceil, floor
|
|
4
|
+
from typing import Dict, List, Tuple
|
|
5
|
+
|
|
6
|
+
class Lexitron:
|
|
7
|
+
"""Main class for the Lexitron command line tool."""
|
|
8
|
+
|
|
9
|
+
# Configuration constants
|
|
10
|
+
DEFAULT_ENCODING = 'utf-8'
|
|
11
|
+
WORDLIST_PATHS = {
|
|
12
|
+
'common': 'agid-common.txt',
|
|
13
|
+
'proper': 'agid-proper.txt'
|
|
14
|
+
}
|
|
15
|
+
FORMATTING = {
|
|
16
|
+
'gutter_width': 4,
|
|
17
|
+
'terminal_margin': 1,
|
|
18
|
+
'show_rules': False
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
def __init__(self):
|
|
22
|
+
"""Initialize Lexitron with wordlist files and argument parser configuration."""
|
|
23
|
+
# The wordlist files
|
|
24
|
+
self.wordlist_common_file = resources.files('lexitron').joinpath(self.WORDLIST_PATHS['common'])
|
|
25
|
+
self.wordlist_proper_file = resources.files('lexitron').joinpath(self.WORDLIST_PATHS['proper'])
|
|
26
|
+
|
|
27
|
+
# Here is the argument parser
|
|
28
|
+
description = "Lexitron, a regex search engine for the English " +\
|
|
29
|
+
"language. By default, Lexitron searches only for common " +\
|
|
30
|
+
"(lowercase) words."
|
|
31
|
+
epilog = "Currently, Lexitron only allows case-insensitive " +\
|
|
32
|
+
"searching.\n\nSee <https://github.com/rothos/lexitron> for " +\
|
|
33
|
+
"further documentation and examples."
|
|
34
|
+
self.parser = argparse.ArgumentParser(prog='lx',
|
|
35
|
+
description=description, epilog=epilog)
|
|
36
|
+
|
|
37
|
+
# Add the positional argument
|
|
38
|
+
self.parser.add_argument('expression', type=str,
|
|
39
|
+
help='the regular expression to search')
|
|
40
|
+
|
|
41
|
+
# Add the optional arguments
|
|
42
|
+
self.parser.add_argument('-n', '--number-only',
|
|
43
|
+
dest='number', action='store_true',
|
|
44
|
+
help='print only the total number of matches')
|
|
45
|
+
self.parser.add_argument('-i', '--info',
|
|
46
|
+
dest='show_info', action='store_true',
|
|
47
|
+
help='print info header along with search results')
|
|
48
|
+
self.parser.add_argument('-u', '--uppercase',
|
|
49
|
+
dest='include_proper', action='store_true',
|
|
50
|
+
help='include uppercase/proper words (like "France") in addition to lowercase/common words')
|
|
51
|
+
self.parser.add_argument('-U', '--only-uppercase',
|
|
52
|
+
dest='only_proper', action='store_true',
|
|
53
|
+
help='search only for uppercase/proper words')
|
|
54
|
+
self.parser.add_argument('-v', '--version',
|
|
55
|
+
action='version', version="Lexitron "+metadata.version('lexitron'),
|
|
56
|
+
help='print version and exit')
|
|
57
|
+
self.parser.add_argument('-x', '--plain',
|
|
58
|
+
dest='unformatted', action='store_true',
|
|
59
|
+
help='print unformatted output, one word per line')
|
|
60
|
+
|
|
61
|
+
def print_help(self):
|
|
62
|
+
"""Display the help message for the command line interface."""
|
|
63
|
+
self.parser.print_help()
|
|
64
|
+
|
|
65
|
+
def parse_args(self, argv: List[str]) -> argparse.Namespace:
|
|
66
|
+
"""Parse command line arguments.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
argv: List of command line arguments
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Parsed argument namespace
|
|
73
|
+
"""
|
|
74
|
+
# Parse the incoming arguments
|
|
75
|
+
args = self.parser.parse_args(argv)
|
|
76
|
+
return args
|
|
77
|
+
|
|
78
|
+
def search(self, args: argparse.Namespace) -> Dict[str, List[str]]:
|
|
79
|
+
"""Search wordlists for matches to the given regular expression.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
args: Parsed command line arguments containing search parameters
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Dictionary with 'common' and 'proper' lists of matching words
|
|
86
|
+
"""
|
|
87
|
+
# Get the expression ready.
|
|
88
|
+
expr = self.sanitize(args.expression)
|
|
89
|
+
|
|
90
|
+
# Currently, lexitron search is case-insensitive.
|
|
91
|
+
expr = re.compile(expr, flags=re.IGNORECASE)
|
|
92
|
+
matches = {'common': [], 'proper': []}
|
|
93
|
+
|
|
94
|
+
# Now open each wordlist and start searching.
|
|
95
|
+
# Always search common words unless only_proper is specified
|
|
96
|
+
if not args.only_proper:
|
|
97
|
+
for word in self._iter_words(self.wordlist_common_file):
|
|
98
|
+
if expr.search(word):
|
|
99
|
+
matches['common'].append(word)
|
|
100
|
+
|
|
101
|
+
# Only search proper words if include_proper or only_proper is specified
|
|
102
|
+
if args.include_proper or args.only_proper:
|
|
103
|
+
for word in self._iter_words(self.wordlist_proper_file):
|
|
104
|
+
if expr.search(word):
|
|
105
|
+
matches['proper'].append(word)
|
|
106
|
+
|
|
107
|
+
matches['common'] = sorted(list(set(matches['common'])))
|
|
108
|
+
matches['proper'] = sorted(list(set(matches['proper'])))
|
|
109
|
+
|
|
110
|
+
return matches
|
|
111
|
+
|
|
112
|
+
def sanitize(self, expr: str) -> str:
|
|
113
|
+
"""Remove wrapping quotation marks from the input expression.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
expr: Regular expression string
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Sanitized expression string
|
|
120
|
+
"""
|
|
121
|
+
# Remove any wrapping quotation marks from the input.
|
|
122
|
+
if expr[0] in ('"',"'"): expr = expr[1:]
|
|
123
|
+
if expr[-1] in ('"',"'"): expr = expr[:-1]
|
|
124
|
+
return expr
|
|
125
|
+
|
|
126
|
+
def _iter_words(self, wordlist_file) -> str:
|
|
127
|
+
"""Iterate through words in a wordlist file.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
wordlist_file: A Path object pointing to the wordlist file
|
|
131
|
+
|
|
132
|
+
Yields:
|
|
133
|
+
str: Each word from the file, one at a time
|
|
134
|
+
"""
|
|
135
|
+
with wordlist_file.open('rb') as f:
|
|
136
|
+
for line in f:
|
|
137
|
+
line = line.strip()
|
|
138
|
+
if line and not line.startswith(b'#'): # Skip empty lines and comments
|
|
139
|
+
try:
|
|
140
|
+
yield self.parse_line(line)
|
|
141
|
+
except LexitronParseError:
|
|
142
|
+
continue # Skip lines that can't be parsed
|
|
143
|
+
|
|
144
|
+
def parse_line(self, line: bytes) -> str:
|
|
145
|
+
"""Parse a line from the wordlist file.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
line: A line from the wordlist file
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
The word from the line
|
|
152
|
+
"""
|
|
153
|
+
# This only returns the word right now, but since the agid.txt list
|
|
154
|
+
# contains other information (part of speech, derivative words, etc),
|
|
155
|
+
# the search may become more robust in the future.
|
|
156
|
+
try:
|
|
157
|
+
return line.split()[0].decode()
|
|
158
|
+
except (IndexError, UnicodeDecodeError) as e:
|
|
159
|
+
raise LexitronParseError(f"Failed to parse line: {e}")
|
|
160
|
+
|
|
161
|
+
def print_results(self, matches: Dict[str, List[str]], args: argparse.Namespace):
|
|
162
|
+
"""Print search results according to specified format.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
matches: Dictionary containing lists of matching common and proper words
|
|
166
|
+
args: Parsed arguments controlling output format
|
|
167
|
+
"""
|
|
168
|
+
commons = matches['common']
|
|
169
|
+
propers = matches['proper']
|
|
170
|
+
|
|
171
|
+
if args.unformatted:
|
|
172
|
+
if args.number:
|
|
173
|
+
# Unformatted number only
|
|
174
|
+
print(str(len(propers + commons)))
|
|
175
|
+
else:
|
|
176
|
+
# Unformatted matches
|
|
177
|
+
print('\n'.join(propers + commons))
|
|
178
|
+
else:
|
|
179
|
+
width, height = os.get_terminal_size()
|
|
180
|
+
width = width - 1 # Wiggle room
|
|
181
|
+
|
|
182
|
+
if args.number:
|
|
183
|
+
# Print only the total number
|
|
184
|
+
print(len(propers + commons))
|
|
185
|
+
else:
|
|
186
|
+
# Print header if requested
|
|
187
|
+
if args.show_info:
|
|
188
|
+
print(self.header(commons, propers, args, width))
|
|
189
|
+
if propers or commons:
|
|
190
|
+
print()
|
|
191
|
+
|
|
192
|
+
# Print matches
|
|
193
|
+
if propers:
|
|
194
|
+
print(self.formatted(propers, width, height))
|
|
195
|
+
if commons and propers:
|
|
196
|
+
print()
|
|
197
|
+
if commons:
|
|
198
|
+
print(self.formatted(commons, width, height))
|
|
199
|
+
|
|
200
|
+
def header(self, commons: List[str], propers: List[str], args: argparse.Namespace, width: int) -> str:
|
|
201
|
+
"""Generate header string showing search results summary.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
commons: List of matching common words
|
|
205
|
+
propers: List of matching proper words
|
|
206
|
+
args: Parsed arguments containing search expression
|
|
207
|
+
width: Terminal width for formatting
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Formatted header string
|
|
211
|
+
"""
|
|
212
|
+
rule = '-' * width if self.FORMATTING['show_rules'] else ''
|
|
213
|
+
total = len(commons + propers)
|
|
214
|
+
expr = self.sanitize(args.expression)
|
|
215
|
+
|
|
216
|
+
breakdown = ''
|
|
217
|
+
if args.include_proper and not args.only_proper:
|
|
218
|
+
breakdown = ' (' + str(len(propers)) + ' proper, ' + str(len(commons)) + ' common)'
|
|
219
|
+
|
|
220
|
+
if self.FORMATTING['show_rules']:
|
|
221
|
+
txt = "{rule}\n{total} matches for /{expr}/{breakdown}\n{rule}"
|
|
222
|
+
else:
|
|
223
|
+
txt = "{total} matches for /{expr}/{breakdown}"
|
|
224
|
+
|
|
225
|
+
return txt.format(rule=rule, total=total, expr=expr, breakdown=breakdown)
|
|
226
|
+
|
|
227
|
+
def formatted(self, words: List[str], termwidth: int, termheight: int) -> str:
|
|
228
|
+
"""Format word list into columns that fit the terminal dimensions.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
words: List of words to format
|
|
232
|
+
termwidth: Width of terminal in characters
|
|
233
|
+
termheight: Height of terminal in characters
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
String of words formatted in columns
|
|
237
|
+
"""
|
|
238
|
+
N = len(words)
|
|
239
|
+
GUTTER = self.FORMATTING['gutter_width']
|
|
240
|
+
COLWIDTH = max([len(word) for word in words])
|
|
241
|
+
|
|
242
|
+
# Adjust terminal width by margin
|
|
243
|
+
termwidth = termwidth - self.FORMATTING['terminal_margin']
|
|
244
|
+
|
|
245
|
+
# The maximum number of columns that will fit in the terminal
|
|
246
|
+
# (taking into account gutter width). The mathematics:
|
|
247
|
+
# termwidth = n*colwidth + (n-1)*gutter, solve for n.
|
|
248
|
+
max_num_cols = max(1, floor((GUTTER + termwidth)/float(GUTTER + COLWIDTH)))
|
|
249
|
+
|
|
250
|
+
# These are heuristics for determining the number of columns of output.
|
|
251
|
+
num_cols = max(1, min(max_num_cols, ceil(N/(termheight/2.))))
|
|
252
|
+
num_rows = ceil(N/float(num_cols))
|
|
253
|
+
|
|
254
|
+
# Convert to integers.
|
|
255
|
+
num_cols = int(num_cols)
|
|
256
|
+
num_rows = int(num_rows)
|
|
257
|
+
|
|
258
|
+
# Fill in the rest of the matrix with blanks.
|
|
259
|
+
# words = words + ['']*((numcols - (n-numcols*numrows)) % numcols)
|
|
260
|
+
words = words + ['']*(num_cols*num_rows - N)
|
|
261
|
+
|
|
262
|
+
rowlist = []
|
|
263
|
+
for k in range(num_rows):
|
|
264
|
+
rowlist += [''.join(word.ljust(COLWIDTH+GUTTER) \
|
|
265
|
+
for word in words[k::num_rows]).rstrip()]
|
|
266
|
+
|
|
267
|
+
pretty_printed_results = '\n'.join(rowlist)
|
|
268
|
+
return pretty_printed_results
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
# This is invoked when there's an error parsing the wordlist files
|
|
272
|
+
class LexitronParseError(Exception):
|
|
273
|
+
pass
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
# The function that will be called from the command line
|
|
277
|
+
def main():
|
|
278
|
+
"""Entry point for the Lexitron command line interface."""
|
|
279
|
+
lx = Lexitron()
|
|
280
|
+
args = lx.parse_args(sys.argv[1:])
|
|
281
|
+
matches = lx.search(args)
|
|
282
|
+
lx.print_results(matches, args)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "Lexitron"
|
|
7
|
+
version = "2.1.2"
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "Rothos"}
|
|
10
|
+
]
|
|
11
|
+
description = "A command-line regex search engine for the English language"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.7"
|
|
14
|
+
keywords = ["english", "dictionary", "crossword", "spelling", "words", "lexicon", "search"]
|
|
15
|
+
license = {text = "GNU GPL Version 2"}
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"importlib-metadata;python_version<'3.8'",
|
|
21
|
+
"importlib-resources;python_version<'3.8'"
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "http://github.com/rothos/lexitron"
|
|
26
|
+
|
|
27
|
+
[tool.setuptools]
|
|
28
|
+
zip-safe = false
|
|
29
|
+
include-package-data = true
|
|
30
|
+
package-dir = {""= "."}
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.packages.find]
|
|
33
|
+
where = ["."]
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.package-data]
|
|
36
|
+
"*" = ["*.txt"]
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
lx = "lexitron.lexitron:main"
|
lexitron-2.1.2/setup.cfg
ADDED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import sys, os, re, argparse
|
|
2
|
-
from importlib import resources, metadata
|
|
3
|
-
from math import ceil, floor
|
|
4
|
-
|
|
5
|
-
class Lexitron:
|
|
6
|
-
def __init__(self):
|
|
7
|
-
# The wordlist files
|
|
8
|
-
self.wordlist_common_file = resources.files('lexitron').joinpath('agid-common.txt')
|
|
9
|
-
self.wordlist_proper_file = resources.files('lexitron').joinpath('agid-proper.txt')
|
|
10
|
-
|
|
11
|
-
with self.wordlist_common_file.open('rb') as f:
|
|
12
|
-
self.wordlist_common = f.read()
|
|
13
|
-
f.close()
|
|
14
|
-
|
|
15
|
-
with self.wordlist_proper_file.open('rb') as f:
|
|
16
|
-
self.wordlist_proper = f.read()
|
|
17
|
-
f.close()
|
|
18
|
-
|
|
19
|
-
# Here is the argument parser
|
|
20
|
-
description = "Lexitron, a regex search engine for the English " +\
|
|
21
|
-
"language."
|
|
22
|
-
epilog = "Currently, Lexitron only allows case-insensitive " +\
|
|
23
|
-
"searching.\n\nSee <http://github.com/rothos/lexitron> for " +\
|
|
24
|
-
"further documentation and examples."
|
|
25
|
-
self.parser = argparse.ArgumentParser(prog='lx',
|
|
26
|
-
description=description, epilog=epilog)
|
|
27
|
-
|
|
28
|
-
# Add the positional argument
|
|
29
|
-
self.parser.add_argument('expression', type=str,
|
|
30
|
-
help='The regular expression to search')
|
|
31
|
-
|
|
32
|
-
# Add the optional arguments
|
|
33
|
-
# self.parser.add_argument('-a',
|
|
34
|
-
# dest='all', action='store_true',
|
|
35
|
-
# help='Search all words, including plurals and conjugations')
|
|
36
|
-
self.parser.add_argument('-n', '--number-only',
|
|
37
|
-
dest='number', action='store_true',
|
|
38
|
-
help='Print only the number of matches')
|
|
39
|
-
self.parser.add_argument('-u', '--lowercase',
|
|
40
|
-
dest='only_common', action='store_true',
|
|
41
|
-
help='Search only for lowercase/common/uncapitalized words (like "boat")')
|
|
42
|
-
self.parser.add_argument('-U', '--uppercase',
|
|
43
|
-
dest='only_proper', action='store_true',
|
|
44
|
-
help='Search only for uppercase/proper/capitalized words (like "France")')
|
|
45
|
-
self.parser.add_argument('-v', '--version',
|
|
46
|
-
action='version', version="Lexitron "+metadata.version('lexitron'),
|
|
47
|
-
help='Show version and exit')
|
|
48
|
-
self.parser.add_argument('-x', '--plain',
|
|
49
|
-
dest='unformatted', action='store_true',
|
|
50
|
-
help='Print unformatted output, one word per line')
|
|
51
|
-
|
|
52
|
-
def print_help(self):
|
|
53
|
-
self.parser.print_help()
|
|
54
|
-
|
|
55
|
-
def parse_args(self, argv):
|
|
56
|
-
# Parse the incoming arguments
|
|
57
|
-
args = self.parser.parse_args(argv)
|
|
58
|
-
return args
|
|
59
|
-
|
|
60
|
-
def search(self, args):
|
|
61
|
-
# Figure out which files to search
|
|
62
|
-
if args.only_common and args.only_proper:
|
|
63
|
-
msg = 'Mutually exclusive options -u and -U may not ' \
|
|
64
|
-
+ 'be used together.'
|
|
65
|
-
raise LexitronOptionsError(msg)
|
|
66
|
-
|
|
67
|
-
# Get the expression ready.
|
|
68
|
-
expr = self.sanitize(args.expression)
|
|
69
|
-
|
|
70
|
-
# Currently, lexitron search is case-insensitive.
|
|
71
|
-
expr = re.compile(expr, flags=re.IGNORECASE)
|
|
72
|
-
matches = {'common': [], 'proper': []}
|
|
73
|
-
|
|
74
|
-
# Now open each wordlist and start searching.
|
|
75
|
-
if not args.only_proper:
|
|
76
|
-
for line in self.wordlist_common.splitlines():
|
|
77
|
-
word = self.parse_line(line)
|
|
78
|
-
if expr.search(word):
|
|
79
|
-
matches['common'] += [word]
|
|
80
|
-
|
|
81
|
-
if not args.only_common:
|
|
82
|
-
for line in self.wordlist_proper.splitlines():
|
|
83
|
-
word = self.parse_line(line)
|
|
84
|
-
if expr.search(word):
|
|
85
|
-
matches['proper'] += [word]
|
|
86
|
-
|
|
87
|
-
matches['common'] = sorted(list(set(matches['common'])))
|
|
88
|
-
matches['proper'] = sorted(list(set(matches['proper'])))
|
|
89
|
-
|
|
90
|
-
return matches
|
|
91
|
-
|
|
92
|
-
def sanitize(self, expr):
|
|
93
|
-
# Remove any wrapping quotation marks from the input.
|
|
94
|
-
if expr[0] in ('"',"'"): expr = expr[1:]
|
|
95
|
-
if expr[-1] in ('"',"'"): expr = expr[:-1]
|
|
96
|
-
return expr
|
|
97
|
-
|
|
98
|
-
def parse_line(self, line):
|
|
99
|
-
# This only returns the word right now, but since the agid.txt list
|
|
100
|
-
# contains other information (part of speech, derivative words, etc),
|
|
101
|
-
# the search may become more robust in the future.
|
|
102
|
-
return line.split()[0].decode()
|
|
103
|
-
|
|
104
|
-
def print_results(self, matches, args):
|
|
105
|
-
commons = matches['common']
|
|
106
|
-
propers = matches['proper']
|
|
107
|
-
|
|
108
|
-
if args.unformatted:
|
|
109
|
-
if args.number:
|
|
110
|
-
# Unformatted number
|
|
111
|
-
print(str(len(propers + commons)))
|
|
112
|
-
else:
|
|
113
|
-
# Unformatted matches
|
|
114
|
-
print('\n'.join(propers + commons))
|
|
115
|
-
|
|
116
|
-
else:
|
|
117
|
-
width, height = os.get_terminal_size()
|
|
118
|
-
width = width - 1 # Wiggle room
|
|
119
|
-
|
|
120
|
-
if args.number:
|
|
121
|
-
# Formatted number
|
|
122
|
-
print(self.header(commons, propers, args, width))
|
|
123
|
-
else:
|
|
124
|
-
# Formatted matches
|
|
125
|
-
print(self.header(commons, propers, args, width))
|
|
126
|
-
if propers:
|
|
127
|
-
print(self.formatted(propers, width, height))
|
|
128
|
-
if commons:
|
|
129
|
-
print(self.formatted(commons, width, height))
|
|
130
|
-
|
|
131
|
-
def header(self, commons, propers, args, width):
|
|
132
|
-
rule = '-' * width
|
|
133
|
-
total = len(commons + propers)
|
|
134
|
-
expr = self.sanitize(args.expression)
|
|
135
|
-
|
|
136
|
-
breakdown = [str(len(propers)) + ' proper', str(len(commons)) + ' common']
|
|
137
|
-
if args.only_proper:
|
|
138
|
-
breakdown = ['(restricted search)']
|
|
139
|
-
elif args.only_common:
|
|
140
|
-
breakdown = ['(restricted search)']
|
|
141
|
-
breakdown = ' ~ '.join(breakdown)
|
|
142
|
-
|
|
143
|
-
txt = "{rule}\n{total} results for /{expr}/\n" \
|
|
144
|
-
"{breakdown}\n{rule}\n".format(rule=rule,
|
|
145
|
-
total=total, expr=expr, breakdown=breakdown)
|
|
146
|
-
|
|
147
|
-
return txt
|
|
148
|
-
|
|
149
|
-
def formatted(self, words, termwidth, termheight):
|
|
150
|
-
n = len(words)
|
|
151
|
-
gutter = 4
|
|
152
|
-
colwidth = max([len(word) for word in words])
|
|
153
|
-
|
|
154
|
-
# The maximum number of columns that will fit in the terminal
|
|
155
|
-
# (taking into account gutter width). The mathematics:
|
|
156
|
-
# termwidth = n*colwidth + (n-1)*gutter, solve for n.
|
|
157
|
-
maxnumcols = max(1, floor((gutter + termwidth)/float(gutter + colwidth)))
|
|
158
|
-
|
|
159
|
-
# These are heuristics for determining the number of columns of output.
|
|
160
|
-
numcols = max(1, min(maxnumcols, ceil(n/(termheight/2.))))
|
|
161
|
-
numrows = ceil(n/float(numcols))
|
|
162
|
-
|
|
163
|
-
# Convert to integers.
|
|
164
|
-
numcols = int(numcols)
|
|
165
|
-
numrows = int(numrows)
|
|
166
|
-
|
|
167
|
-
# Fill in the rest of the matrix with blanks.
|
|
168
|
-
# words = words + ['']*((numcols - (n-numcols*numrows)) % numcols)
|
|
169
|
-
words = words + ['']*(numcols*numrows - n)
|
|
170
|
-
|
|
171
|
-
rowlist = []
|
|
172
|
-
for k in range(numrows):
|
|
173
|
-
rowlist += [''.join(word.ljust(colwidth+gutter) \
|
|
174
|
-
for word in words[k::numrows]).rstrip()]
|
|
175
|
-
|
|
176
|
-
pretty_printed_results = '\n'.join(rowlist) + '\n'
|
|
177
|
-
return pretty_printed_results
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
# This is invoked when mutually exclusive options -a and -A are used together.
|
|
181
|
-
class LexitronOptionsError(Exception):
|
|
182
|
-
pass
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
# The function that will be called from the command line
|
|
186
|
-
def main():
|
|
187
|
-
lx = Lexitron()
|
|
188
|
-
args = lx.parse_args(sys.argv[1:])
|
|
189
|
-
matches = lx.search(args)
|
|
190
|
-
lx.print_results(matches, args)
|
Lexitron-2.0.4/pyproject.toml
DELETED
Lexitron-2.0.4/setup.cfg
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
[metadata]
|
|
2
|
-
name = Lexitron
|
|
3
|
-
version = 2.0.4
|
|
4
|
-
author = Rothos
|
|
5
|
-
url = http://github.com/rothos/lexitron
|
|
6
|
-
description = A command-line regex search engine for the English language
|
|
7
|
-
long_description = file: README.md
|
|
8
|
-
long_description_content_type = text/markdown
|
|
9
|
-
keywords = english, dictionary, crossword, spelling, words, lexicon, search
|
|
10
|
-
license = GNU GPL Version 2
|
|
11
|
-
classifiers =
|
|
12
|
-
Programming Language :: Python :: 3
|
|
13
|
-
|
|
14
|
-
[options]
|
|
15
|
-
zip_safe = False
|
|
16
|
-
include_package_data = True
|
|
17
|
-
packages = find:
|
|
18
|
-
python_requires = >=3.7
|
|
19
|
-
install_requires =
|
|
20
|
-
importlib-metadata;python_version<'3.8'
|
|
21
|
-
importlib-resources;python_version<'3.8'
|
|
22
|
-
package_dir =
|
|
23
|
-
= .
|
|
24
|
-
|
|
25
|
-
[options.packages.find]
|
|
26
|
-
where = .
|
|
27
|
-
|
|
28
|
-
[options.package_data]
|
|
29
|
-
* = *.txt
|
|
30
|
-
|
|
31
|
-
[options.entry_points]
|
|
32
|
-
console_scripts =
|
|
33
|
-
lx = lexitron.lexitron:main
|
|
34
|
-
|
|
35
|
-
[egg_info]
|
|
36
|
-
tag_build =
|
|
37
|
-
tag_date = 0
|
|
38
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|