Easier contraction typing (#289)
* removed isPunctiationPartOfWords hack and created a new contraction input method that allows typing just anything, instead of predefined list coming from the dictionary * updated the common compound words and contractions in Bulgarian, Dutch, English and French * removed some non-sense and rarely used English words * fixed crashing when trying to find words with apostrophes in the database * fixed a crash when trying to capitalize single character strings * improved dictionary validation at build time: spaces are now disallowed
This commit is contained in:
parent
cf766334d6
commit
241a4125b0
35 changed files with 389 additions and 35214 deletions
|
|
@ -54,11 +54,9 @@ To support a new language one needs to:
|
|||
- `locale` contains the language and the country codes (e.g. "en-US", "es-AR", "it-IT"). Refer to the list of [supported locales in Java](https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html#util-text).
|
||||
- `dictionaryFile` is the name of the dictionary in `assets/` folder.
|
||||
- `characterMap` contains the letters and punctuation marks associated with each key.
|
||||
- Set `isPunctuationPartOfWords` to `true`, if the dictionary contains words with apostrophes or dashes, such as: `it's`, `you'll`, `a'tje` or `п'ят`. This will allow using 1-key for typing them (they will appear as suggestions). `false` will enable faster typing when apostrophes or other punctuation are not part of the words (no such words will be suggested).
|
||||
- `abcString` _(optional)_. A custom string to display in ABC mode. By default, the first three letters on 2-key are used (e.g. "ABC" or "АБВ"). Set this if the first letters of the alphabet are _not_ on 2-key, like in Hebrew, or if a different string makes more sense.
|
||||
- `hasUpperCase` _(optional)_ set to `false` when the language has no upper- and lowercase letters. For example: Arabic, Hebrew, East Asian
|
||||
languages, and so on. The default is `true`.
|
||||
- `name` _(optional)_ defaults to the native name of the language (e.g. "English", "Deutsch", "Українська"). Useful to set when the default is ambiguous. For example, both Portuguese in Portugal and Brazil will default to "Português", so assigning "Português brasileiro" would make it clear it's the language used in Brazil.
|
||||
- `hasUpperCase` _(optional)_ set to `false` when the language has no upper- and lowercase letters. For example: Arabic, Hebrew, East Asian languages, and so on. The default is `true`.
|
||||
- `name` _(optional)_ is automatically generated and equals the native name of the language (e.g. "English", "Deutsch", "Українська"). However, sometimes, the automatically selected name may be ambiguous. For example, both Portuguese in Portugal and Brazil will default to "Português", so assigning "Português brasileiro" would make it clear it's the language used in Brazil.
|
||||
- Finally, add the new language to the list in `LanguageCollection.java`. You only need to add it in one place, in the constructor. Please, be nice and maintain the alphabetical order.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -490,6 +490,7 @@
|
|||
пия 170
|
||||
плу
|
||||
плю
|
||||
по-
|
||||
под 204
|
||||
пое
|
||||
пои
|
||||
|
|
@ -2246,6 +2247,7 @@
|
|||
наем 167
|
||||
нает 137
|
||||
наех
|
||||
най-
|
||||
назе
|
||||
нали 184
|
||||
нане 90
|
||||
|
|
|
|||
|
Can't render this file because it is too large.
|
34803
assets/en-utf8.csv
34803
assets/en-utf8.csv
File diff suppressed because it is too large
Load diff
|
|
@ -1,3 +1,26 @@
|
|||
c'
|
||||
ç'
|
||||
d'
|
||||
j'
|
||||
l'
|
||||
m'
|
||||
n'
|
||||
s'
|
||||
t'
|
||||
y'
|
||||
qu'
|
||||
-ce
|
||||
-ci
|
||||
-il
|
||||
-la
|
||||
-toi
|
||||
-elle
|
||||
-nous
|
||||
-vous
|
||||
jusqu'
|
||||
lorsqu'
|
||||
puisqu'
|
||||
quoiqu'
|
||||
abaissa 59
|
||||
abaissable
|
||||
abaissables
|
||||
|
|
|
|||
|
Can't render this file because it is too large.
|
|
|
@ -1,14 +1,19 @@
|
|||
's-Graveland 94
|
||||
's-Gravendeel 95
|
||||
's-Gravenhaags
|
||||
's-Gravenhage 129
|
||||
's-Gravenhagenaar
|
||||
's-Gravenmoer
|
||||
's-Gravenzande 103
|
||||
's-Gravenzander
|
||||
's-Gravenzands
|
||||
's-Hertogenbosch 129
|
||||
't 180
|
||||
Gravendeel 95
|
||||
Gravenhaags
|
||||
Gravenhage 129
|
||||
Gravenhagenaar
|
||||
Gravenmoer
|
||||
Gravenzande 103
|
||||
Gravenzander
|
||||
Gravenzands
|
||||
Hertogenbosch 129
|
||||
'k
|
||||
's
|
||||
't
|
||||
's-
|
||||
m'n
|
||||
d'r
|
||||
da's
|
||||
A-attest
|
||||
A-attesten
|
||||
A-biljet
|
||||
|
|
@ -23,7 +28,6 @@ A-omroep
|
|||
A-omroepen
|
||||
A-selectie 92
|
||||
A-status 90
|
||||
A.D.
|
||||
AAA 109
|
||||
AAW 96
|
||||
AAW-voorziening
|
||||
|
|
@ -1928,7 +1932,6 @@ ayses
|
|||
aytekin
|
||||
ayten
|
||||
aytens
|
||||
az.
|
||||
azad
|
||||
azads
|
||||
azarkan
|
||||
|
|
@ -5025,7 +5028,6 @@ chilenen 91
|
|||
chili 110
|
||||
chimène
|
||||
chimènes
|
||||
chin.
|
||||
china 163
|
||||
china's 104
|
||||
chinees 119
|
||||
|
|
@ -5719,7 +5721,6 @@ d-day 98
|
|||
d-sluiting
|
||||
d-trein 80
|
||||
d-treinen
|
||||
d.v.
|
||||
ddt 99
|
||||
deet 99
|
||||
dna 144
|
||||
|
|
@ -10520,8 +10521,6 @@ gül 85
|
|||
güls
|
||||
h-bom
|
||||
h-bommen
|
||||
h.k.h.
|
||||
h.m.
|
||||
hrm 122
|
||||
htm 111
|
||||
html 127
|
||||
|
|
@ -15930,7 +15929,6 @@ l-profiel
|
|||
l-profielen
|
||||
l-vormig 86
|
||||
l-vormige 104
|
||||
l.b.
|
||||
lan 99
|
||||
lgpl
|
||||
lto 75
|
||||
|
|
@ -19174,7 +19172,6 @@ mexx'
|
|||
meyer 123
|
||||
meyerode
|
||||
meys 75
|
||||
mgr.
|
||||
mia 90
|
||||
mia's 72
|
||||
mica 97
|
||||
|
|
@ -19962,12 +19959,6 @@ mälarmeer
|
|||
mélanie 73
|
||||
mélanies
|
||||
münchen 135
|
||||
n.b.
|
||||
n.h.
|
||||
n.n.
|
||||
n.o.
|
||||
n.v.
|
||||
n.w.
|
||||
nam 121
|
||||
nap 95
|
||||
nasa 125
|
||||
|
|
@ -20249,7 +20240,6 @@ neals
|
|||
nebahat 81
|
||||
nebahats
|
||||
nebbeling
|
||||
ned.
|
||||
Neder-Betuwe 90
|
||||
Neder-Californië
|
||||
Neder-Congo
|
||||
|
|
@ -21093,7 +21083,6 @@ nyssa
|
|||
nyssa's
|
||||
nürnberg 102
|
||||
o-benen 78
|
||||
o.l.v.
|
||||
ocmw 132
|
||||
ocmw's 108
|
||||
OCMW-raad 88
|
||||
|
|
@ -21525,7 +21514,6 @@ opdorp 81
|
|||
opel 132
|
||||
opels 84
|
||||
opendocument
|
||||
openoffice.org
|
||||
opentaal 113
|
||||
opgeldenaken
|
||||
opgenoort
|
||||
|
|
@ -23029,7 +23017,6 @@ quitoos
|
|||
quitoër
|
||||
quix 72
|
||||
qureshi
|
||||
r.i.p.
|
||||
ram 115
|
||||
rdw 124
|
||||
ret 117
|
||||
|
|
@ -26750,8 +26737,6 @@ srananmans
|
|||
sranantongo 88
|
||||
srebrenica 117
|
||||
sri 78
|
||||
st.-eustatius
|
||||
st.-maarten
|
||||
staaks
|
||||
staals
|
||||
staarink
|
||||
|
|
@ -26847,7 +26832,6 @@ stavast 80
|
|||
stavele 76
|
||||
stavenga
|
||||
stavleu
|
||||
stct.
|
||||
steef 85
|
||||
steefs
|
||||
steegers
|
||||
|
|
@ -29997,8 +29981,6 @@ vänermeer
|
|||
vättermeer
|
||||
véronique 99
|
||||
véroniques
|
||||
w.
|
||||
w.v.str.
|
||||
wa 115
|
||||
WA-verzekering 93
|
||||
WAM-sticker
|
||||
|
|
@ -31611,8 +31593,6 @@ z-verpleegkundige
|
|||
z-verpleegkundigen
|
||||
z-vormig
|
||||
z-vormige
|
||||
z.h.
|
||||
z.k.h.
|
||||
zaaijer 82
|
||||
zaan 89
|
||||
zaandam 132
|
||||
|
|
@ -32158,13 +32138,6 @@ a-priorisch 79
|
|||
a-priorische
|
||||
a-prioristisch 79
|
||||
a-prioristische 81
|
||||
a.d.h.v.
|
||||
a.g.v.
|
||||
a.h.w.
|
||||
a.j.b.
|
||||
a.m.
|
||||
a.s.
|
||||
a.u.b.
|
||||
aagt 84
|
||||
aagtappel 80
|
||||
aagtappels 79
|
||||
|
|
@ -35328,7 +35301,6 @@ aanvuring 85
|
|||
aanvuurde 84
|
||||
aanvuurden 82
|
||||
aanvuurt 83
|
||||
aanw.
|
||||
aanwaai 80
|
||||
aanwaaide 80
|
||||
aanwaaiden 78
|
||||
|
|
@ -38653,7 +38625,6 @@ afasiepatiënten
|
|||
afat
|
||||
afatisch 80
|
||||
afatische 84
|
||||
afb.
|
||||
afbad 77
|
||||
afbak 85
|
||||
afbakbrood
|
||||
|
|
@ -38907,7 +38878,6 @@ afbuigmagneet 81
|
|||
afbuigt 94
|
||||
afcentiemen
|
||||
afchecken
|
||||
afd.
|
||||
afdaal 84
|
||||
afdaalde 95
|
||||
afdaalden 92
|
||||
|
|
@ -43068,7 +43038,6 @@ afwrijft 85
|
|||
afwrijven 92
|
||||
afwrijvingen 77
|
||||
afwringen 82
|
||||
afz.
|
||||
afzaag 84
|
||||
afzaagde 82
|
||||
afzaagden 84
|
||||
|
|
@ -45222,7 +45191,6 @@ amuzikaal
|
|||
amygdala 99
|
||||
amylose 72
|
||||
amyotrofie 80
|
||||
an.
|
||||
anaal 121
|
||||
anabaptisme 81
|
||||
anabaptist 81
|
||||
|
|
@ -47864,7 +47832,6 @@ aronskelken 83
|
|||
aroom 82
|
||||
arpeggio 89
|
||||
arpeggio's 81
|
||||
arr.
|
||||
arrangeer 82
|
||||
arrangeerde 93
|
||||
arrangeerden 82
|
||||
|
|
@ -50164,9 +50131,6 @@ aïssen 73
|
|||
b's
|
||||
b'tje
|
||||
b'tjes
|
||||
b.d.
|
||||
b.g.g.
|
||||
b.v.d.
|
||||
baad 88
|
||||
baadde 96
|
||||
baadden 89
|
||||
|
|
@ -53282,7 +53246,6 @@ bazuintje 82
|
|||
bazuintjes 81
|
||||
bbp 121
|
||||
bbp-groei 81
|
||||
bc.
|
||||
beaam 90
|
||||
beaamd 98
|
||||
beaamde 104
|
||||
|
|
@ -61835,7 +61798,6 @@ betrouwde 84
|
|||
betrouwden 81
|
||||
betrouwen 99
|
||||
betrouwt 83
|
||||
bett.
|
||||
betuig 99
|
||||
betuigd 111
|
||||
betuigde 106
|
||||
|
|
@ -64941,7 +64903,6 @@ bijkrijgt 86
|
|||
bijkwam 98
|
||||
bijkwamen 91
|
||||
bijl 129
|
||||
bijl.
|
||||
bijladen 88
|
||||
bijlag 87
|
||||
bijlage 157
|
||||
|
|
@ -65325,7 +65286,6 @@ bijtten 79
|
|||
bijtwond 77
|
||||
bijtwonden 82
|
||||
bijtwondje
|
||||
bijv.
|
||||
bijvak 95
|
||||
bijvakken 90
|
||||
bijvakprogramma 80
|
||||
|
|
@ -68420,7 +68380,6 @@ bluts 87
|
|||
blutsen 89
|
||||
blutst 81
|
||||
blutste 76
|
||||
blz.
|
||||
blèrde 82
|
||||
blèrden 81
|
||||
blèren 97
|
||||
|
|
@ -76207,10 +76166,8 @@ buy-outs
|
|||
buzzer 85
|
||||
buzzers 75
|
||||
bv'tjes
|
||||
bv.
|
||||
bvba 119
|
||||
bvba's
|
||||
bw.
|
||||
bye 108
|
||||
byebye
|
||||
byes
|
||||
|
|
@ -76249,9 +76206,6 @@ c'tjes
|
|||
c-pion
|
||||
c-sleutel
|
||||
c-sleutels
|
||||
c.q.
|
||||
c.s.
|
||||
ca.
|
||||
caban 82
|
||||
cabans 83
|
||||
cabaret 123
|
||||
|
|
@ -85268,10 +85222,6 @@ d's 84
|
|||
d'tje
|
||||
d'tjes
|
||||
d-pion
|
||||
d.d.
|
||||
d.i.
|
||||
d.m.v.
|
||||
d.w.z.
|
||||
db 132
|
||||
daad 149
|
||||
daadkracht 122
|
||||
|
|
@ -86782,7 +86732,6 @@ daze
|
|||
dazen 97
|
||||
dc 143
|
||||
dc's
|
||||
dd.
|
||||
de 255
|
||||
de-escalatie 77
|
||||
de-escalaties
|
||||
|
|
@ -89593,7 +89542,6 @@ dezulken 101
|
|||
deïsme 89
|
||||
deïst 86
|
||||
deïsten 86
|
||||
dhr.
|
||||
dia 123
|
||||
dia's 119
|
||||
dia-avond
|
||||
|
|
@ -92158,7 +92106,6 @@ dittografieën 77
|
|||
ditzelfde 118
|
||||
diuretica 93
|
||||
diureticum 93
|
||||
div.
|
||||
divalifeest
|
||||
divalioptocht
|
||||
divalioptochten
|
||||
|
|
@ -95906,9 +95853,7 @@ dozijnen 97
|
|||
dozijntje 82
|
||||
dozijntjes 82
|
||||
dpi 111
|
||||
dr.
|
||||
dra 115
|
||||
dra.
|
||||
draad 153
|
||||
draadachtig 83
|
||||
draadachtige 89
|
||||
|
|
@ -97578,8 +97523,6 @@ droste-effect
|
|||
drostendiensten 82
|
||||
drostschap 80
|
||||
drozen 79
|
||||
drs.
|
||||
drs.-titel
|
||||
drug 123
|
||||
drugbaron
|
||||
drugbeleid 93
|
||||
|
|
@ -98141,7 +98084,6 @@ druïdetempel
|
|||
dryade 92
|
||||
dryaden 84
|
||||
drycleaning
|
||||
ds.
|
||||
dtp 80
|
||||
dtp-prik
|
||||
dtp-prikken
|
||||
|
|
@ -99536,12 +99478,6 @@ e-pion
|
|||
e-snaar 78
|
||||
e-zine 98
|
||||
e-zines 77
|
||||
e.a.
|
||||
e.d.
|
||||
e.e.a.
|
||||
e.o.
|
||||
e.v.
|
||||
e.v.a.
|
||||
earlgreythee
|
||||
earnings
|
||||
eau-de-colognefles 80
|
||||
|
|
@ -103004,7 +102940,6 @@ enveloppenfinanciering
|
|||
enveloppetje
|
||||
environment 97
|
||||
environments 72
|
||||
enz.
|
||||
enzoverder 93
|
||||
enzovoort 144
|
||||
enzovoorts 133
|
||||
|
|
@ -103963,7 +103898,6 @@ etappezege 94
|
|||
etappezeges 76
|
||||
etatistisch
|
||||
etatistische
|
||||
etc.
|
||||
eten 181
|
||||
etend 97
|
||||
etende 101
|
||||
|
|
@ -104600,7 +104534,6 @@ evolutionistisch 83
|
|||
evolutionistische 82
|
||||
evoqueerde
|
||||
evoqueren 80
|
||||
evt.
|
||||
ex 149
|
||||
ex-kamerleden
|
||||
ex-kamerlid
|
||||
|
|
@ -104956,7 +104889,6 @@ excitatie 92
|
|||
excitaties
|
||||
exciteerde
|
||||
exciteren 83
|
||||
excl.
|
||||
exclamatie 79
|
||||
exclamaties 81
|
||||
exclave 91
|
||||
|
|
@ -105784,7 +105716,6 @@ f-sleutel 81
|
|||
f-sleutels 76
|
||||
fa 123
|
||||
fa's
|
||||
fa.
|
||||
faal 98
|
||||
faalangst 117
|
||||
faalangsten
|
||||
|
|
@ -106188,7 +106119,6 @@ falsifieert 82
|
|||
falsifiëren 84
|
||||
falsifiëring 78
|
||||
falsifiëringen
|
||||
fam.
|
||||
fameus 98
|
||||
fameust 77
|
||||
fameuze 122
|
||||
|
|
@ -107751,7 +107681,6 @@ fietszoektocht 75
|
|||
fietszoektochten
|
||||
fifties 93
|
||||
fiftyfifty 85
|
||||
fig.
|
||||
figaro 83
|
||||
figaro's
|
||||
figgelen 78
|
||||
|
|
@ -110574,7 +110503,6 @@ foxtrotte 80
|
|||
foxtrotten 80
|
||||
foyer 117
|
||||
foyers 93
|
||||
fr.
|
||||
fraai 148
|
||||
fraaie 152
|
||||
fraaier 107
|
||||
|
|
@ -111851,7 +111779,6 @@ g'tjes
|
|||
g-sleutel 81
|
||||
g-sleutels
|
||||
g-spot 76
|
||||
g.g.d.
|
||||
ga 183
|
||||
gaaf 141
|
||||
gaafheid 102
|
||||
|
|
@ -113444,7 +113371,6 @@ geavanceerder 101
|
|||
geavanceerdere 92
|
||||
geavondmaald 77
|
||||
geavontuurd 82
|
||||
geb.
|
||||
gebaad 98
|
||||
gebaald 81
|
||||
gebaand 103
|
||||
|
|
@ -119363,7 +119289,6 @@ geluwd 97
|
|||
geluwde 83
|
||||
gelyncht 97
|
||||
gelynchte 82
|
||||
gem.
|
||||
gemaaid 122
|
||||
gemaaide 100
|
||||
gemaakt 193
|
||||
|
|
@ -123739,7 +123664,6 @@ gesynthetiseerd 97
|
|||
gesynthetiseerde 86
|
||||
gesystematiseerd 87
|
||||
gesystematiseerde 85
|
||||
get.
|
||||
getaakt 81
|
||||
getaald 82
|
||||
getaand 89
|
||||
|
|
@ -144284,19 +144208,6 @@ i-bankieren
|
|||
i-grec 81
|
||||
i-grecs
|
||||
i-mode 83
|
||||
i.c.
|
||||
i.c.m.
|
||||
i.e.
|
||||
i.h.a.
|
||||
i.h.b.
|
||||
i.m.
|
||||
i.o.
|
||||
i.o.v.
|
||||
i.p.v.
|
||||
i.s.m.
|
||||
i.t.t.
|
||||
i.v.m.
|
||||
i.z.g.st.
|
||||
ipod 130
|
||||
ipods 95
|
||||
ia 133
|
||||
|
|
@ -145935,7 +145846,6 @@ inciviek 81
|
|||
incivieke
|
||||
incivieken
|
||||
incivisme 80
|
||||
incl.
|
||||
inclinatie 90
|
||||
inclinatiekompas 74
|
||||
inclinaties 82
|
||||
|
|
@ -147169,7 +147079,6 @@ infuuspompen 78
|
|||
infuuspompjes
|
||||
infuusvloeistof
|
||||
infuusvloeistoffen
|
||||
ing.
|
||||
ingaan 146
|
||||
ingaand 97
|
||||
ingaande 116
|
||||
|
|
@ -152012,7 +151921,6 @@ ionosferisch
|
|||
ionosferische
|
||||
ippon 94
|
||||
ippons
|
||||
ir.
|
||||
irenisch 84
|
||||
irenische 81
|
||||
iridium 90
|
||||
|
|
@ -153492,7 +153400,6 @@ jezuïetenstijl 74
|
|||
jezuïtisch 78
|
||||
jezuïtische 83
|
||||
jezuïtisme 77
|
||||
jhr.
|
||||
jicht 114
|
||||
jichtaanval 85
|
||||
jichtaanvallen 83
|
||||
|
|
@ -153528,8 +153435,6 @@ jip-en-janneketaal
|
|||
jippie 89
|
||||
jiujitsu 90
|
||||
jive 89
|
||||
jkvr.
|
||||
jl.
|
||||
jobaanbieding
|
||||
jobaanbiedingen 79
|
||||
jobaanbod
|
||||
|
|
@ -154017,7 +153922,6 @@ joyriders
|
|||
joyriding 88
|
||||
joystick 108
|
||||
joysticks 90
|
||||
jr.
|
||||
jubee 82
|
||||
jubel 97
|
||||
jubelde 96
|
||||
|
|
@ -154414,7 +154318,6 @@ juxtapositie 87
|
|||
k's 74
|
||||
k'tje
|
||||
k'tjes
|
||||
k.k.
|
||||
khz 114
|
||||
kj 94
|
||||
kw 131
|
||||
|
|
@ -178201,7 +178104,6 @@ librettoschrijver
|
|||
librije 86
|
||||
librijen 78
|
||||
librium 81
|
||||
lic.
|
||||
licentiaat 109
|
||||
licentiaatsdiploma
|
||||
licentiaatsdiploma's
|
||||
|
|
@ -183132,16 +183034,6 @@ m'etjes
|
|||
m's
|
||||
m-bankierde
|
||||
m-bankieren
|
||||
m.
|
||||
m.a.w.
|
||||
m.b.t.
|
||||
m.b.v.
|
||||
m.i.
|
||||
m.i.v.
|
||||
m.m.
|
||||
m.m.v.
|
||||
m.n.
|
||||
m.u.v.
|
||||
m/s
|
||||
ma's 92
|
||||
maag 150
|
||||
|
|
@ -186676,7 +186568,6 @@ mavoleerlingen
|
|||
mavoniveau
|
||||
mavoscholen
|
||||
mavoschool
|
||||
max.
|
||||
maxi 111
|
||||
maximaal 166
|
||||
maximale 158
|
||||
|
|
@ -190491,7 +190382,6 @@ meurt 77
|
|||
meute 118
|
||||
meuten 84
|
||||
meutes 86
|
||||
mevr.
|
||||
mevrouw 162
|
||||
mevrouwde 78
|
||||
mevrouwen 93
|
||||
|
|
@ -191969,7 +191859,6 @@ mimosa 91
|
|||
mimosa's
|
||||
min-maxcontract
|
||||
min-maxcontracten
|
||||
min.
|
||||
minacht 94
|
||||
minachten 98
|
||||
minachtend 106
|
||||
|
|
@ -193069,9 +192958,7 @@ mixtures
|
|||
mixtuur 83
|
||||
mkb 119
|
||||
ml 146
|
||||
mld.
|
||||
mlk-school
|
||||
mln.
|
||||
mm 167
|
||||
mnemotechniek 78
|
||||
mnemotechnisch 83
|
||||
|
|
@ -195711,7 +195598,6 @@ mozetta's
|
|||
mozzarella 116
|
||||
mp 98
|
||||
mp's
|
||||
mr.
|
||||
ms 120
|
||||
mts 88
|
||||
mu 111
|
||||
|
|
@ -196751,7 +196637,6 @@ muzikantesk 78
|
|||
muzikanteske
|
||||
muzisch 90
|
||||
muzische 101
|
||||
mw.
|
||||
mycelium 97
|
||||
mycologen 85
|
||||
mycologie 84
|
||||
|
|
@ -196829,9 +196714,6 @@ n'en
|
|||
n'etje 75
|
||||
n'etjes
|
||||
n's 72
|
||||
n.a.v.
|
||||
n.o.t.k.
|
||||
n.v.t.
|
||||
na 119
|
||||
na-aapt
|
||||
na-apen 93
|
||||
|
|
@ -201545,8 +201427,6 @@ niëlleerde 74
|
|||
niëlleren 78
|
||||
njet 91
|
||||
njonja 80
|
||||
nl.
|
||||
nl.openoffice.org
|
||||
nm 121
|
||||
no-claim 97
|
||||
no-claimkorting 92
|
||||
|
|
@ -201561,7 +201441,6 @@ no-nonsense 111
|
|||
no-nonsensebeleid
|
||||
no-nonsensepolitiek
|
||||
no-showstudent
|
||||
no.
|
||||
noachitisch
|
||||
noachitische
|
||||
nobele 120
|
||||
|
|
@ -202435,8 +202314,6 @@ novum 100
|
|||
nozem 91
|
||||
nozempje
|
||||
nozems 92
|
||||
nr.
|
||||
nrs.
|
||||
nu 138
|
||||
nuance 125
|
||||
nuanceer 83
|
||||
|
|
@ -202657,14 +202534,6 @@ nymfomanie 82
|
|||
o's 85
|
||||
o'tje
|
||||
o'tjes
|
||||
o.a.
|
||||
o.b.v.
|
||||
o.i.
|
||||
o.i.d.
|
||||
o.m.
|
||||
o.t.t.
|
||||
o.v.t.
|
||||
o.v.v.
|
||||
oase 126
|
||||
oasen 90
|
||||
oases 100
|
||||
|
|
@ -208408,7 +208277,6 @@ onfrisser 75
|
|||
onfrist 78
|
||||
onfunctioneel
|
||||
onfunctionele
|
||||
ong.
|
||||
ongaar
|
||||
ongaarne 99
|
||||
ongans 88
|
||||
|
|
@ -221699,12 +221567,6 @@ oölieten 81
|
|||
p's 78
|
||||
p'tje
|
||||
p'tjes
|
||||
p.
|
||||
p.a.
|
||||
p.m.
|
||||
p.o.
|
||||
p.p.
|
||||
p.w.
|
||||
ph 129
|
||||
ph's
|
||||
ph-neutraal
|
||||
|
|
@ -222284,7 +222146,6 @@ pafte 84
|
|||
paften 80
|
||||
pafzak 76
|
||||
pafzakken 75
|
||||
pag.
|
||||
pagaai 85
|
||||
pagaaide 81
|
||||
pagaaiden 77
|
||||
|
|
@ -230065,7 +229926,6 @@ plissérok
|
|||
plissérokken
|
||||
plissés 84
|
||||
plistoceen
|
||||
plm.
|
||||
ploeg 158
|
||||
ploegachtervolging
|
||||
ploegarts 72
|
||||
|
|
@ -230503,7 +230363,6 @@ pluvier 80
|
|||
pluvieren 81
|
||||
pluviometer 84
|
||||
pluviometers 82
|
||||
plv.
|
||||
pneumatiek 92
|
||||
pneumatisch 106
|
||||
pneumatische 117
|
||||
|
|
@ -236150,7 +236009,6 @@ proeverij 118
|
|||
proeverijen 106
|
||||
proevers 94
|
||||
prof 145
|
||||
prof.
|
||||
profaan 93
|
||||
profaanst
|
||||
profafdeling
|
||||
|
|
@ -238598,8 +238456,6 @@ pythons 90
|
|||
q's
|
||||
q'tje
|
||||
q'tjes
|
||||
q.e.d.
|
||||
q.q.
|
||||
qat 94
|
||||
qua 162
|
||||
quad 110
|
||||
|
|
@ -238768,7 +238624,6 @@ r'en
|
|||
r'etje
|
||||
r'etjes
|
||||
r's
|
||||
r.-k.
|
||||
ra 122
|
||||
ra's 88
|
||||
raad 168
|
||||
|
|
@ -241970,7 +241825,6 @@ recyclingbedrijf 86
|
|||
recyclingbedrijven 73
|
||||
recyclingproces
|
||||
red 141
|
||||
red.
|
||||
redacteur 138
|
||||
redacteuren 122
|
||||
redacteurs 105
|
||||
|
|
@ -245250,7 +245104,6 @@ resort 130
|
|||
resorts 112
|
||||
resource 107
|
||||
resources 118
|
||||
resp.
|
||||
respect 158
|
||||
respectabel 105
|
||||
respectabele 115
|
||||
|
|
@ -251073,8 +250926,6 @@ s'en 72
|
|||
s'je
|
||||
s'jes
|
||||
s's
|
||||
s.j.
|
||||
s.v.p.
|
||||
sa 121
|
||||
saai 142
|
||||
saaie 133
|
||||
|
|
@ -269364,7 +269215,6 @@ squasht 80
|
|||
squashte
|
||||
squaw 82
|
||||
squaws 81
|
||||
sr.
|
||||
sta 156
|
||||
sta-in-de-weg 94
|
||||
sta-in-de-wegs 80
|
||||
|
|
@ -279562,16 +279412,6 @@ t'tje
|
|||
t'tjes
|
||||
t-groep
|
||||
t-groepen
|
||||
t.a.v.
|
||||
t.b.v.
|
||||
t.g.v.
|
||||
t.h.t.
|
||||
t.h.v.
|
||||
t.n.v.
|
||||
t.o.v.
|
||||
t.w.
|
||||
t.w.v.
|
||||
t.z.t.
|
||||
taai 124
|
||||
taaie 121
|
||||
taaien 87
|
||||
|
|
@ -298781,16 +298621,6 @@ uzi's 81
|
|||
v's
|
||||
v'tje
|
||||
v'tjes
|
||||
v.
|
||||
v.chr.
|
||||
v.d.
|
||||
v.h.
|
||||
v.l.n.r.
|
||||
v.r.n.l.
|
||||
v.t.t.
|
||||
v.v.
|
||||
v.v.t.
|
||||
v.w.b.
|
||||
va 138
|
||||
va-banque 75
|
||||
va-et-vient 82
|
||||
|
|
@ -304041,7 +303871,6 @@ verfwerken
|
|||
verfwinkel 89
|
||||
verfwinkels 82
|
||||
verg 104
|
||||
verg.
|
||||
verga 109
|
||||
vergaan 132
|
||||
vergaand 108
|
||||
|
|
@ -312173,7 +312002,6 @@ vezelvlies
|
|||
vezelvliezen
|
||||
vezelwortels 77
|
||||
vezen 81
|
||||
vgl.
|
||||
via 193
|
||||
viaduct 126
|
||||
viaducten 111
|
||||
|
|
@ -315274,8 +315102,6 @@ vmbo-leerling
|
|||
vmbo-leerlingen 91
|
||||
vmbo-scholen 84
|
||||
vmbo-school 80
|
||||
vnl.
|
||||
vnw.
|
||||
vocaal 114
|
||||
vocabulaire 112
|
||||
vocabulaires 87
|
||||
|
|
@ -319604,7 +319430,6 @@ voorwoord 127
|
|||
voorwoorden 87
|
||||
voorworp 79
|
||||
voorworpen 77
|
||||
voorz.
|
||||
voorzaal 86
|
||||
voorzag 130
|
||||
voorzagen 111
|
||||
|
|
@ -321752,7 +321577,6 @@ vruchtzak 79
|
|||
vruchtzakje 74
|
||||
vruchtzakken
|
||||
vruchtzetting 94
|
||||
vs.
|
||||
vuig 89
|
||||
vuige 100
|
||||
vuiger 81
|
||||
|
|
@ -322255,8 +322079,6 @@ véél 132
|
|||
w's
|
||||
w'tje
|
||||
w'tjes
|
||||
w.o.
|
||||
w.v.t.t.k.
|
||||
waad 88
|
||||
waadbaar 78
|
||||
waadbare 80
|
||||
|
|
@ -333505,7 +333327,6 @@ wurmen 108
|
|||
wurmpje 83
|
||||
wurmpjes 81
|
||||
wurmt 92
|
||||
ww.
|
||||
www 174
|
||||
wyandotte
|
||||
wybertje 81
|
||||
|
|
@ -333633,11 +333454,6 @@ z'n 171
|
|||
z's
|
||||
z'tje
|
||||
z'tjes
|
||||
z.g.
|
||||
z.g.a.n.
|
||||
z.i.
|
||||
z.o.z.
|
||||
z.s.m.
|
||||
zaad 146
|
||||
zaadbakje 81
|
||||
zaadbakjes 81
|
||||
|
|
@ -336652,7 +336468,6 @@ zeverden 80
|
|||
zeverlap 78
|
||||
zeverlappen 79
|
||||
zevert 84
|
||||
zgn.
|
||||
zich 210
|
||||
zicht 162
|
||||
zichtas 77
|
||||
|
|
|
|||
|
Can't render this file because it is too large.
|
49
build.gradle
49
build.gradle
|
|
@ -86,29 +86,6 @@ def getReleaseVersion = { ->
|
|||
return "${getVersionName()} (${getCurrentGitHash()})"
|
||||
}
|
||||
|
||||
def isPunctuationInWordsAllowed (String dictionaryFile) {
|
||||
boolean isAllowed = false
|
||||
|
||||
file("${project.projectDir}/src/io/github/sspanak/tt9/languages/definitions").listFiles().each { file ->
|
||||
boolean isTheDefinitionFile = false
|
||||
file.eachLine {line ->
|
||||
if (line.contains(dictionaryFile)) {
|
||||
isTheDefinitionFile = true
|
||||
}
|
||||
}
|
||||
|
||||
if (isTheDefinitionFile) {
|
||||
file.eachLine {line ->
|
||||
if (line.matches(".+?isPunctuationPartOfWords\\s*=\\s*true.+?")) {
|
||||
isAllowed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isAllowed
|
||||
}
|
||||
|
||||
task validateDictionaries {
|
||||
inputs.dir fileTree(dir:'assets', excludes:['dict.properties'])
|
||||
outputs.file "${project.buildDir}/dict.validation.txt"
|
||||
|
|
@ -116,7 +93,6 @@ task validateDictionaries {
|
|||
doLast {
|
||||
final String CSV_DELIMITER = ' ' // TAB
|
||||
final GEOGRAPHICAL_NAME = ~"[A-Z]\\w+-[^\\n]+"
|
||||
final PUNCTUATION_CHARS = ~".*?\\p{Punct}(?<!-).*?"
|
||||
|
||||
final MAX_ERRORS = 50
|
||||
String errors = ""
|
||||
|
|
@ -131,7 +107,6 @@ task validateDictionaries {
|
|||
|
||||
println "Validating dictionary: " + file.name
|
||||
|
||||
def isPunctuationAllowed = isPunctuationInWordsAllowed(file.name)
|
||||
def uniqueWords = [:]
|
||||
|
||||
int lineNumber = 0
|
||||
|
|
@ -151,6 +126,13 @@ task validateDictionaries {
|
|||
return
|
||||
}
|
||||
|
||||
if (line.contains(" ")) {
|
||||
isFileValid = false
|
||||
errorCount++
|
||||
errors += "Dictionary '" + file.name + "' is invalid. Found space on line " + lineNumber + ". Make sure each word is on a new line. Phrases are not allowed.\n"
|
||||
return
|
||||
}
|
||||
|
||||
String[] parts = line.split(CSV_DELIMITER, 2)
|
||||
String word = parts[0]
|
||||
String frequency = parts.length > 1 ? parts[1] : ""
|
||||
|
|
@ -179,12 +161,6 @@ task validateDictionaries {
|
|||
errors += "Dictionary '" + file.name + "' is invalid. Found a single letter: '" + word + "' on line " + lineNumber + ". Only uppercase single letters are allowed. The rest of the alphabet will be added automatically.\n"
|
||||
}
|
||||
|
||||
if (!isPunctuationAllowed && word.matches(PUNCTUATION_CHARS)) {
|
||||
isFileValid = false
|
||||
errorCount++
|
||||
errors += "Dictionary '" + file.name + "' is invalid. Found a punctuation mark in word: '" + word + "' on line " + lineNumber + ". Remove all punctuation characters when the language definition disallows them or update the definition.\n"
|
||||
}
|
||||
|
||||
String uniqueWordKey = word ==~ GEOGRAPHICAL_NAME ? word : word.toLowerCase()
|
||||
if (uniqueWords[uniqueWordKey] != null && uniqueWords[uniqueWordKey] == true) {
|
||||
isFileValid = false
|
||||
|
|
@ -235,21 +211,12 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
//noinspection ExpiredTargetSdkVersion
|
||||
targetSdk 30
|
||||
versionCode getVersionCode()
|
||||
versionName getVersionName()
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/a/19130098
|
||||
// signingConfigs {
|
||||
// release {
|
||||
// storeFile file(System.getenv("KEYSTORE"))
|
||||
// storePassword System.getenv("KEYSTORE_PASS")
|
||||
// keyAlias System.getenv("KEY_ALIAS")
|
||||
// keyPassword System.getenv("KEY_ALIAS_PASS")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
buildTypes {
|
||||
debug { data ->
|
||||
data.buildConfigField 'String', 'VERSION_FULL', "\"${getDebugVersion()}\""
|
||||
|
|
|
|||
43
src/io/github/sspanak/tt9/TextTools.java
Normal file
43
src/io/github/sspanak/tt9/TextTools.java
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package io.github.sspanak.tt9;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class TextTools {
|
||||
private static final Pattern containsOtherThan1 = Pattern.compile("[02-9]");
|
||||
private static final Pattern previousIsLetter = Pattern.compile("\\p{L}$");
|
||||
private static final Pattern nextIsPunctuation = Pattern.compile("^\\p{Punct}");
|
||||
private static final Pattern nextToWord = Pattern.compile("\\b$");
|
||||
private static final Pattern startOfSentence = Pattern.compile("(?<!\\.)(^|[.?!¿¡])\\s*$");
|
||||
|
||||
public static boolean containsOtherThan1(String str) {
|
||||
return str != null && containsOtherThan1.matcher(str).find();
|
||||
}
|
||||
|
||||
public static boolean isNextToWord(String str) {
|
||||
return str != null && nextToWord.matcher(str).find();
|
||||
}
|
||||
|
||||
public static boolean isStartOfSentence(String str) {
|
||||
return str != null && startOfSentence.matcher(str).find();
|
||||
}
|
||||
|
||||
public static boolean nextIsPunctuation(String str) {
|
||||
return str != null && nextIsPunctuation.matcher(str).find();
|
||||
}
|
||||
|
||||
public static boolean previousIsLetter(String str) {
|
||||
return str != null && previousIsLetter.matcher(str).find();
|
||||
}
|
||||
|
||||
public static boolean startsWithWhitespace(String str) {
|
||||
return str != null && !str.isEmpty() && (str.charAt(0) == ' ' || str.charAt(0) == '\n' || str.charAt(0) == '\t');
|
||||
}
|
||||
|
||||
public static boolean startsWithNumber(String str) {
|
||||
return str != null && !str.isEmpty() && (str.charAt(0) >= '0' && str.charAt(0) <= '9');
|
||||
}
|
||||
|
||||
public static String removeNonLetters(String str) {
|
||||
return str != null ? str.replaceAll("\\P{L}", "") : null;
|
||||
}
|
||||
}
|
||||
|
|
@ -191,24 +191,13 @@ public class DictionaryDb {
|
|||
|
||||
// In case the user has changed the text case, there would be no match.
|
||||
// Try again with the lowercase equivalent.
|
||||
String lowercaseWord = "";
|
||||
if (affectedRows == 0) {
|
||||
lowercaseWord = word.toLowerCase(language.getLocale());
|
||||
String lowercaseWord = word.toLowerCase(language.getLocale());
|
||||
affectedRows = getInstance().wordsDao().incrementFrequency(language.getId(), lowercaseWord, sequence);
|
||||
|
||||
Logger.d("incrementWordFrequency", "Attempting to increment frequency for lowercase variant: " + lowercaseWord);
|
||||
}
|
||||
|
||||
// Some languages permit appending the punctuation to the end of the words, like so: "try,".
|
||||
// But there are no such words in the dictionary, so try without the punctuation mark.
|
||||
if (affectedRows == 0 && language.isPunctuationPartOfWords() && sequence.endsWith("1")) {
|
||||
String truncatedWord = lowercaseWord.substring(0, word.length() - 1);
|
||||
String truncatedSequence = sequence.substring(0, sequence.length() - 1);
|
||||
affectedRows = getInstance().wordsDao().incrementFrequency(language.getId(), truncatedWord, truncatedSequence);
|
||||
|
||||
Logger.d("incrementWordFrequency", "Attempting to increment frequency with stripped punctuation: " + truncatedWord);
|
||||
}
|
||||
|
||||
Logger.d("incrementWordFrequency", "Affected rows: " + affectedRows);
|
||||
} catch (Exception e) {
|
||||
Logger.e(
|
||||
|
|
|
|||
39
src/io/github/sspanak/tt9/db/migrations/DB11.java
Normal file
39
src/io/github/sspanak/tt9/db/migrations/DB11.java
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package io.github.sspanak.tt9.db.migrations;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.languages.definitions.Dutch;
|
||||
import io.github.sspanak.tt9.languages.definitions.English;
|
||||
|
||||
public class DB11 {
|
||||
public static final Migration MIGRATION = new Migration(10, 11) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
final String enWords = "'I''d','I''m','d''annunzio','I''ll','I''ve','prud''hon','an''t','bo''s''n','bo''s''ns','bo''sun','bo''suns','bos''n','bos''ns','br''er','ca''canny','could''ve','d''arezzo','d''estaing','e''en','e''er','fo''c''s''le','fo''c''s''les','fo''c''sle','fo''c''sles','ha''penny','he''d','he''ll','how''d','how''re','howe''er','it''d','it''ll','might''ve','must''ve','n''importe','ne''er','nor''easter','nor''wester','o''er','rec''d','sec''y','she''d','she''ll','should''ve','sou''wester','ta''en','that''d','that''ll','they''d','they''ll','they''re','they''ve','we''d','we''ll','we''re','we''ve','whate''er','whatsoe''er','whene''er','where''er','who''d','who''ll','who''re','who''ve','why''d','would''ve','you''d','you''ll','you''re','you''ve','Ch''in','L''Amour','L''Enfant','L''Oreal','L''Ouverture','T''ang','Xi''an'";
|
||||
final String nlWords = "'''s-Graveland','''s-Gravendeel','''s-Gravenhaags','''s-Gravenhage','''s-Gravenhagenaar','''s-Gravenmoer','''s-Gravenzande','''s-Gravenzander','''s-Gravenzands','''s-Hertogenbosch','''t','A.D.','az.','chin.','d.v.','h.k.h.','h.m.','l.b.','mgr.','n.b.','n.h.','n.n.','n.o.','n.v.','n.w.','ned.','o.l.v.','openoffice.org','r.i.p.','st.-eustatius','st.-maarten','stct.','w.','w.v.str.','z.h.','z.k.h.','a.d.h.v.','a.g.v.','a.h.w.','a.j.b.','a.m.','a.s.','a.u.b.','aanw.','afb.','afd.','afz.','an.','arr.','b.d.','b.g.g.','b.v.d.','bc.','bett.','bijl.','bijv.','blz.','bv.','bw.','c.q.','c.s.','ca.','d.d.','d.i.','d.m.v.','d.w.z.','dd.','dhr.','div.','dr.','dra.','drs.','drs.-titel','ds.','e.a.','e.d.','e.e.a.','e.o.','e.v.','e.v.a.','enz.','etc.','evt.','excl.','fa.','fam.','fig.','fr.','g.g.d.','geb.','gem.','get.','i.c.','i.c.m.','i.e.','i.h.a.','i.h.b.','i.m.','i.o.','i.o.v.','i.p.v.','i.s.m.','i.t.t.','i.v.m.','i.z.g.st.','incl.','ing.','ir.','jhr.','jkvr.','jl.','jr.','k.k.','lic.','m.','m.a.w.','m.b.t.','m.b.v.','m.i.','m.i.v.','m.m.','m.m.v.','m.n.','m.u.v.','max.','mevr.','min.','mld.','mln.','mr.','mw.','n.a.v.','n.o.t.k.','n.v.t.','nl.','nl.openoffice.org','no.','nr.','nrs.','o.a.','o.b.v.','o.i.','o.i.d.','o.m.','o.t.t.','o.v.t.','o.v.v.','ong.','p.','p.a.','p.m.','p.o.','p.p.','p.w.','pag.','plm.','plv.','prof.','q.e.d.','q.q.','r.-k.','red.','resp.','s.j.','s.v.p.','sr.','t.a.v.','t.b.v.','t.g.v.','t.h.t.','t.h.v.','t.n.v.','t.o.v.','t.w.','t.w.v.','t.z.t.','v.','v.chr.','v.d.','v.h.','v.l.n.r.','v.r.n.l.','v.t.t.','v.v.','v.v.t.','v.w.b.','verg.','vgl.','vnl.','vnw.','voorz.','vs.','w.o.','w.v.t.t.k.','ww.','z.g.','z.g.a.n.','z.i.','z.o.z.','z.s.m.','zgn.'";
|
||||
|
||||
try {
|
||||
database.beginTransaction();
|
||||
database.execSQL(getDeleteEnglishSwordsQuery());
|
||||
database.execSQL(getDeleteWordsQuery(new English().getId(), enWords));
|
||||
database.execSQL(getDeleteWordsQuery(new Dutch().getId(), nlWords));
|
||||
database.setTransactionSuccessful();
|
||||
} catch (Exception e) {
|
||||
Logger.e("Migrate to DB11", "Migration failed. " + e.getMessage());
|
||||
} finally {
|
||||
database.endTransaction();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static String getDeleteEnglishSwordsQuery() {
|
||||
return "DELETE FROM words WHERE lang=" + new English().getId() + " AND word LIKE '%''s'";
|
||||
}
|
||||
|
||||
private static String getDeleteWordsQuery(int langId, String wordList) {
|
||||
return "DELETE FROM words WHERE lang=" + langId + " AND word IN(" + wordList + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -8,12 +8,13 @@ import androidx.room.RoomDatabase;
|
|||
import androidx.sqlite.db.SimpleSQLiteQuery;
|
||||
|
||||
import io.github.sspanak.tt9.db.migrations.DB10;
|
||||
import io.github.sspanak.tt9.db.migrations.DB11;
|
||||
import io.github.sspanak.tt9.db.migrations.DB6;
|
||||
import io.github.sspanak.tt9.db.migrations.DB7;
|
||||
import io.github.sspanak.tt9.db.migrations.DB8;
|
||||
import io.github.sspanak.tt9.db.migrations.DB9;
|
||||
|
||||
@Database(version = 10, entities = Word.class, exportSchema = false)
|
||||
@Database(version = 11, entities = Word.class, exportSchema = false)
|
||||
public abstract class TT9Room extends RoomDatabase {
|
||||
public abstract WordsDao wordsDao();
|
||||
|
||||
|
|
@ -25,7 +26,8 @@ public abstract class TT9Room extends RoomDatabase {
|
|||
new DB7().getMigration(context),
|
||||
DB8.MIGRATION,
|
||||
DB9.MIGRATION,
|
||||
DB10.MIGRATION
|
||||
DB10.MIGRATION,
|
||||
DB11.MIGRATION
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
|
@ -41,7 +43,7 @@ public abstract class TT9Room extends RoomDatabase {
|
|||
" LIMIT " + limit;
|
||||
|
||||
if (word != null) {
|
||||
sql = sql.replace("WHERE 1", "WHERE 1 AND word LIKE '" + word + "%'");
|
||||
sql = sql.replace("WHERE 1", "WHERE 1 AND word LIKE '" + word.replace("'", "''") + "%'");
|
||||
}
|
||||
|
||||
return new SimpleSQLiteQuery(sql);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public interface WordsDao {
|
|||
@Query("SELECT COUNT(id) FROM words WHERE :langId < 0 OR lang = :langId")
|
||||
int count(int langId);
|
||||
|
||||
@Query("DELETE FROM words WHERE LANG IN(:langIds)")
|
||||
@Query("DELETE FROM words WHERE lang IN(:langIds)")
|
||||
void deleteByLanguage(ArrayList<Integer> langIds);
|
||||
|
||||
@Query("SELECT COUNT(id) FROM words WHERE lang = :langId AND word = :word")
|
||||
|
|
|
|||
|
|
@ -262,18 +262,16 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
cancelAutoAccept();
|
||||
forceShowWindowIfHidden();
|
||||
|
||||
String currentWord = getComposingText();
|
||||
|
||||
// Automatically accept the current word, when the next one is a space or punctuation,
|
||||
// Automatically accept the previous word, when the next one is a space or punctuation,
|
||||
// instead of requiring "OK" before that.
|
||||
if (mInputMode.shouldAcceptCurrentSuggestion(key, hold, repeat > 0)) {
|
||||
// First pass, analyze the incoming key press and decide whether it could be the start of
|
||||
// a new word.
|
||||
if (mInputMode.shouldAcceptPreviousSuggestion(key)) {
|
||||
autoCorrectSpace(acceptIncompleteSuggestion(), false, key);
|
||||
currentWord = "";
|
||||
}
|
||||
|
||||
// Auto-adjust the text case before each word, if the InputMode supports it.
|
||||
// We don't do it too often, because it is somewhat resource-intensive.
|
||||
if (currentWord.length() == 0) {
|
||||
if (getComposingText().isEmpty()) {
|
||||
mInputMode.determineNextWordTextCase(textField.isThereText(), textField.getTextBeforeCursor());
|
||||
}
|
||||
|
||||
|
|
@ -543,11 +541,11 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
}
|
||||
|
||||
private void commitCurrentSuggestion(boolean entireSuggestion) {
|
||||
if (!isSuggestionViewHidden() && currentInputConnection != null) {
|
||||
if (!isSuggestionViewHidden()) {
|
||||
if (entireSuggestion) {
|
||||
textField.setComposingText(suggestionBar.getCurrentSuggestion());
|
||||
}
|
||||
currentInputConnection.finishComposingText();
|
||||
textField.finishComposingText();
|
||||
}
|
||||
|
||||
setSuggestions(null);
|
||||
|
|
@ -556,11 +554,8 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
private void clearSuggestions() {
|
||||
setSuggestions(null);
|
||||
|
||||
if (currentInputConnection != null) {
|
||||
textField.setComposingText("");
|
||||
currentInputConnection.finishComposingText();
|
||||
}
|
||||
textField.finishComposingText();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -570,10 +565,22 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
private void handleSuggestions() {
|
||||
// Automatically accept the previous word, without requiring OK. This is similar to what
|
||||
// Second pass, analyze the available suggestions and decide if combining them with the
|
||||
// last key press makes up a compound word like: (it)'s, (I)'ve, l'(oiseau), or it is
|
||||
// just the end of a sentence, like: "word." or "another?"
|
||||
if (mInputMode.shouldAcceptPreviousSuggestion()) {
|
||||
String lastComposingText = getComposingText(mInputMode.getSequenceLength() - 1);
|
||||
commitCurrentSuggestion(false);
|
||||
mInputMode.onAcceptSuggestion(lastComposingText, true);
|
||||
autoCorrectSpace(lastComposingText, false, -1);
|
||||
mInputMode.determineNextWordTextCase(textField.isThereText(), textField.getTextBeforeCursor());
|
||||
}
|
||||
|
||||
// key code "suggestions" take priority over words
|
||||
if (mInputMode.getKeyCode() > 0) {
|
||||
sendDownUpKeyEvents(mInputMode.getKeyCode());
|
||||
mInputMode.onAcceptSuggestion("");
|
||||
mInputMode.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -605,16 +612,27 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
}
|
||||
|
||||
|
||||
private String getComposingText() {
|
||||
private String getComposingText(int maxLength) {
|
||||
if (maxLength == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
maxLength = maxLength > 0 ? Math.min(maxLength, mInputMode.getSequenceLength()) : mInputMode.getSequenceLength();
|
||||
|
||||
String text = suggestionBar.getCurrentSuggestion();
|
||||
if (text.length() > 0 && text.length() > mInputMode.getSequenceLength()) {
|
||||
text = text.substring(0, mInputMode.getSequenceLength());
|
||||
if (text.length() > 0 && text.length() > maxLength) {
|
||||
text = text.substring(0, maxLength);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
private String getComposingText() {
|
||||
return getComposingText(-1);
|
||||
}
|
||||
|
||||
|
||||
private void refreshComposingText() {
|
||||
textField.setComposingText(getComposingText());
|
||||
}
|
||||
|
|
@ -729,11 +747,11 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
private void showAddWord() {
|
||||
if (currentInputConnection == null) {
|
||||
if (shouldBeOff()) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentInputConnection.finishComposingText();
|
||||
textField.finishComposingText();
|
||||
clearSuggestions();
|
||||
|
||||
UI.showAddWordDialog(this, mLanguage.getId(), textField.getSurroundingWord());
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ abstract public class InputMode {
|
|||
abstract public boolean onOtherKey(int key);
|
||||
|
||||
// Suggestions
|
||||
public void onAcceptSuggestion(@NonNull String suggestion) {}
|
||||
public void onAcceptSuggestion(@NonNull String word) { onAcceptSuggestion(word, false); }
|
||||
public void onAcceptSuggestion(@NonNull String word, boolean preserveWordList) {}
|
||||
|
||||
/**
|
||||
* loadSuggestions
|
||||
|
|
@ -97,7 +98,8 @@ abstract public class InputMode {
|
|||
}
|
||||
|
||||
// Interaction with the IME. Return "true" if it should perform the respective action.
|
||||
public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return false; }
|
||||
public boolean shouldAcceptPreviousSuggestion() { return false; }
|
||||
public boolean shouldAcceptPreviousSuggestion(int nextKey) { return false; }
|
||||
public boolean shouldAddAutoSpace(InputType inputType, TextField textField, boolean isWordAcceptedManually, int nextKey) { return false; }
|
||||
public boolean shouldDeletePrecedingSpace(InputType inputType) { return false; }
|
||||
public boolean shouldSelectNextSuggestion() { return false; }
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class ModeABC extends InputMode {
|
|||
@Override final public boolean isABC() { return true; }
|
||||
@Override public int getSequenceLength() { return 1; }
|
||||
|
||||
@Override public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return hold || !repeat; }
|
||||
@Override public boolean shouldAcceptPreviousSuggestion() { return autoAcceptTimeout == 0 || !shouldSelectNextLetter; }
|
||||
@Override public boolean shouldTrackUpDown() { return true; }
|
||||
@Override public boolean shouldTrackLeftRight() { return true; }
|
||||
@Override public boolean shouldSelectNextSuggestion() {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ package io.github.sspanak.tt9.ime.modes;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.TextTools;
|
||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||
|
|
@ -19,7 +22,6 @@ public class ModePredictive extends InputMode {
|
|||
|
||||
private String digitSequence = "";
|
||||
private String lastAcceptedWord = "";
|
||||
private String lastAcceptedSequence = "";
|
||||
|
||||
// stem filter
|
||||
private boolean isStemFuzzy = false;
|
||||
|
|
@ -123,6 +125,31 @@ public class ModePredictive extends InputMode {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* clearLastAcceptedWord
|
||||
* Removes the last accepted word from the suggestions list and the "digitSequence"
|
||||
* or stops silently, when there is nothing to do.
|
||||
*/
|
||||
private void clearLastAcceptedWord() {
|
||||
if (
|
||||
lastAcceptedWord.isEmpty()
|
||||
|| suggestions.isEmpty()
|
||||
|| !suggestions.get(0).toLowerCase(language.getLocale()).startsWith(lastAcceptedWord.toLowerCase(language.getLocale()))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
int lastAcceptedWordLength = lastAcceptedWord.length();
|
||||
digitSequence = digitSequence.length() > lastAcceptedWordLength ? digitSequence.substring(lastAcceptedWordLength) : "";
|
||||
|
||||
ArrayList<String> lastSuggestions = new ArrayList<>(suggestions);
|
||||
suggestions.clear();
|
||||
for (String s : lastSuggestions) {
|
||||
suggestions.add(s.length() >= lastAcceptedWordLength ? s.substring(lastAcceptedWordLength) : "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* clearWordStem
|
||||
* Do not filter the suggestions by the word set using "setWordStem()", use only the digit sequence.
|
||||
|
|
@ -156,15 +183,18 @@ public class ModePredictive extends InputMode {
|
|||
* Note that you need to manually get the suggestions again to obtain a filtered list.
|
||||
*/
|
||||
@Override
|
||||
public boolean setWordStem(String wordStem, boolean exact) {
|
||||
if (language == null || wordStem == null || wordStem.length() < 1) {
|
||||
public boolean setWordStem(String newStem, boolean exact) {
|
||||
String sanitizedStem = TextTools.removeNonLetters(newStem);
|
||||
if (language == null || sanitizedStem == null || sanitizedStem.length() < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
digitSequence = language.getDigitSequenceForWord(wordStem);
|
||||
// digitSequence = "the raw input", so that everything the user typed is preserved visually
|
||||
// stem = "the sanitized input", because filtering by anything that is not a letter makes no sense
|
||||
digitSequence = language.getDigitSequenceForWord(newStem);
|
||||
stem = sanitizedStem.toLowerCase(language.getLocale());
|
||||
isStemFuzzy = !exact;
|
||||
stem = digitSequence.startsWith("0") || digitSequence.startsWith("1") ? "" : wordStem.toLowerCase(language.getLocale());
|
||||
|
||||
Logger.d("tt9/setWordStem", "Stem is now: " + stem + (isStemFuzzy ? " (fuzzy)" : ""));
|
||||
return true;
|
||||
|
|
@ -172,7 +202,7 @@ public class ModePredictive extends InputMode {
|
|||
isStemFuzzy = false;
|
||||
stem = "";
|
||||
|
||||
Logger.w("tt9/setWordStem", "Ignoring invalid stem: " + wordStem + ". " + e.getMessage());
|
||||
Logger.w("tt9/setWordStem", "Ignoring invalid stem: " + newStem + ". " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -239,19 +269,26 @@ public class ModePredictive extends InputMode {
|
|||
|
||||
/**
|
||||
* onAcceptSuggestion
|
||||
* Bring this word up in the suggestions list next time.
|
||||
* Bring this word up in the suggestions list next time and if necessary preserves the suggestion list
|
||||
* with "currentWord" cleaned from them.
|
||||
*/
|
||||
@Override
|
||||
public void onAcceptSuggestion(@NonNull String currentWord) {
|
||||
public void onAcceptSuggestion(@NonNull String currentWord, boolean preserveWords) {
|
||||
lastAcceptedWord = currentWord;
|
||||
lastAcceptedSequence = digitSequence;
|
||||
reset();
|
||||
|
||||
if (currentWord.length() == 0) {
|
||||
if (preserveWords) {
|
||||
clearLastAcceptedWord();
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
stem = "";
|
||||
|
||||
if (currentWord.isEmpty()) {
|
||||
Logger.i("acceptCurrentSuggestion", "Current word is empty. Nothing to accept.");
|
||||
return;
|
||||
}
|
||||
|
||||
// increment the frequency of the given word
|
||||
try {
|
||||
String sequence = language.getDigitSequenceForWord(currentWord);
|
||||
|
||||
|
|
@ -284,22 +321,34 @@ public class ModePredictive extends InputMode {
|
|||
|
||||
|
||||
/**
|
||||
* shouldAcceptCurrentSuggestion
|
||||
* shouldAcceptPreviousSuggestion
|
||||
* In this mode, In addition to confirming the suggestion in the input field,
|
||||
* we also increase its' priority. This function determines whether we want to do all this or not.
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) {
|
||||
public boolean shouldAcceptPreviousSuggestion(int nextKey) {
|
||||
return
|
||||
hold
|
||||
// Quickly accept suggestions using "space" instead of pressing "ok" then "space"
|
||||
|| (key == 0 && !repeat)
|
||||
// Punctuation is considered "a word", so that we can increase the priority as needed
|
||||
// Also, it must break the current word.
|
||||
|| (!language.isPunctuationPartOfWords() && key == 1 && digitSequence.length() > 0 && !digitSequence.endsWith("1"))
|
||||
// On the other hand, letters also "break" punctuation.
|
||||
|| (!language.isPunctuationPartOfWords() && key != 1 && digitSequence.endsWith("1"))
|
||||
|| (digitSequence.endsWith("0") && key != 0);
|
||||
!digitSequence.isEmpty() && (
|
||||
(nextKey == 0 && digitSequence.charAt(digitSequence.length() - 1) != '0')
|
||||
|| (nextKey != 0 && digitSequence.charAt(digitSequence.length() - 1) == '0')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* shouldAcceptPreviousSuggestion
|
||||
* Variant for post suggestion load analysis.
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldAcceptPreviousSuggestion() {
|
||||
return
|
||||
(autoAcceptTimeout == 0 && !digitSequence.startsWith("0"))
|
||||
|| (
|
||||
!digitSequence.isEmpty()
|
||||
&& !predictions.areThereDbWords()
|
||||
&& digitSequence.contains("1")
|
||||
&& TextTools.containsOtherThan1(digitSequence)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -307,11 +356,10 @@ public class ModePredictive extends InputMode {
|
|||
public boolean shouldAddAutoSpace(InputType inputType, TextField textField, boolean isWordAcceptedManually, int nextKey) {
|
||||
return autoSpace
|
||||
.setLastWord(lastAcceptedWord)
|
||||
.setLastSequence(lastAcceptedSequence)
|
||||
.setLastSequence()
|
||||
.setInputType(inputType)
|
||||
.setTextField(textField)
|
||||
.shouldAddAutoSpace(isWordAcceptedManually, nextKey);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -319,7 +367,6 @@ public class ModePredictive extends InputMode {
|
|||
public boolean shouldDeletePrecedingSpace(InputType inputType) {
|
||||
return autoSpace
|
||||
.setLastWord(lastAcceptedWord)
|
||||
.setLastSequence(lastAcceptedSequence)
|
||||
.setInputType(inputType)
|
||||
.setTextField(null)
|
||||
.shouldDeletePrecedingSpace();
|
||||
|
|
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
package io.github.sspanak.tt9.ime.modes.helpers;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.github.sspanak.tt9.TextTools;
|
||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||
|
||||
public class AutoSpace {
|
||||
private final Pattern isNumber = Pattern.compile("\\s*\\d+\\s*");
|
||||
private final Pattern nextIsLetter = Pattern.compile("^\\p{L}+");
|
||||
private final Pattern nextIsPunctuation = Pattern.compile("^\\p{Punct}");
|
||||
|
||||
private final SettingsStore settings;
|
||||
|
||||
private InputType inputType;
|
||||
private TextField textField;
|
||||
private String lastWord;
|
||||
private String lastSequence;
|
||||
|
||||
public AutoSpace(SettingsStore settingsStore) {
|
||||
settings = settingsStore;
|
||||
|
|
@ -37,8 +31,7 @@ public class AutoSpace {
|
|||
return this;
|
||||
}
|
||||
|
||||
public AutoSpace setLastSequence(String lastSequence) {
|
||||
this.lastSequence = lastSequence;
|
||||
public AutoSpace setLastSequence() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -57,12 +50,11 @@ public class AutoSpace {
|
|||
return
|
||||
settings.getAutoSpace()
|
||||
&& !inputType.isSpecialized()
|
||||
&& !nextChars.startsWith(" ")
|
||||
&& !isNumber.matcher(previousChars).find()
|
||||
&& !nextIsPunctuation.matcher(nextChars).find()
|
||||
&& nextKey != 0
|
||||
&& !TextTools.startsWithWhitespace(nextChars)
|
||||
&& (
|
||||
shouldAddAfterPunctuation(previousChars, nextKey)
|
||||
|| shouldAddAfterWord(isWordAcceptedManually, nextChars)
|
||||
shouldAddAfterWord(isWordAcceptedManually, previousChars, nextChars, nextKey)
|
||||
|| shouldAddAfterPunctuation(previousChars, nextChars, nextKey)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -73,24 +65,23 @@ public class AutoSpace {
|
|||
* The rules are similar to the ones in the standard Android keyboard (with some exceptions,
|
||||
* because we are not using a QWERTY keyboard here).
|
||||
*/
|
||||
private boolean shouldAddAfterPunctuation(String previousChars, int nextKey) {
|
||||
return
|
||||
// no space after whitespace or special characters
|
||||
!previousChars.endsWith(" ") && !previousChars.endsWith("\n") && !previousChars.endsWith("\t") // previous whitespace
|
||||
&& !lastSequence.equals("0") // previous previous math/special char
|
||||
&& nextKey != 0 // composing (upcoming) whitespace or special character
|
||||
private boolean shouldAddAfterPunctuation(String previousChars, String nextChars, int nextKey) {
|
||||
char previousChar = previousChars.isEmpty() ? 0 : previousChars.charAt(previousChars.length() - 1);
|
||||
|
||||
// add space after the these
|
||||
return
|
||||
nextKey != 1
|
||||
&& !TextTools.nextIsPunctuation(nextChars)
|
||||
&& !TextTools.startsWithNumber(nextChars)
|
||||
&& (
|
||||
previousChars.endsWith(".")
|
||||
|| previousChars.endsWith(",")
|
||||
|| previousChars.endsWith(";")
|
||||
|| previousChars.endsWith(":")
|
||||
|| previousChars.endsWith("!")
|
||||
|| previousChars.endsWith("?")
|
||||
|| previousChars.endsWith(")")
|
||||
|| previousChars.endsWith("]")
|
||||
|| previousChars.endsWith("%")
|
||||
previousChar == '.'
|
||||
|| previousChar == ','
|
||||
|| previousChar == ';'
|
||||
|| previousChar == ':'
|
||||
|| previousChar == '!'
|
||||
|| previousChar == '?'
|
||||
|| previousChar == ')'
|
||||
|| previousChar == ']'
|
||||
|| previousChar == '%'
|
||||
|| previousChars.endsWith(" -")
|
||||
|| previousChars.endsWith(" /")
|
||||
);
|
||||
|
|
@ -98,15 +89,15 @@ public class AutoSpace {
|
|||
|
||||
|
||||
/**
|
||||
* shouldAddAfterPunctuation
|
||||
* shouldAddAfterWord
|
||||
* Similar to "shouldAddAfterPunctuation()", but determines whether to add a space after words.
|
||||
*/
|
||||
private boolean shouldAddAfterWord(boolean isWordAcceptedManually, String nextChars) {
|
||||
private boolean shouldAddAfterWord(boolean isWordAcceptedManually, String previousChars, String nextChars, int nextKey) {
|
||||
return
|
||||
// Do not add space when auto-accepting words, because it feels very confusing when typing.
|
||||
isWordAcceptedManually
|
||||
// Right before another word
|
||||
&& !nextIsLetter.matcher(nextChars).find();
|
||||
isWordAcceptedManually // Do not add space when auto-accepting words, because it feels very confusing when typing.
|
||||
&& nextKey != 1
|
||||
&& nextChars.isEmpty()
|
||||
&& TextTools.previousIsLetter(previousChars);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
package io.github.sspanak.tt9.ime.modes.helpers;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.github.sspanak.tt9.TextTools;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||
|
||||
public class AutoTextCase {
|
||||
private final Pattern nextToWordRegex = Pattern.compile("\\b$");
|
||||
private final Pattern startOfSentenceRegex = Pattern.compile("(?<!\\.)(^|[.?!¿¡])\\s*$");
|
||||
private final SettingsStore settings;
|
||||
|
||||
|
||||
|
|
@ -68,11 +65,11 @@ public class AutoTextCase {
|
|||
}
|
||||
|
||||
// start of sentence, excluding after "..."
|
||||
if (startOfSentenceRegex.matcher(textBeforeCursor).find()) {
|
||||
if (TextTools.isStartOfSentence(textBeforeCursor)) {
|
||||
return InputMode.CASE_CAPITALIZE;
|
||||
}
|
||||
|
||||
if (nextToWordRegex.matcher(textBeforeCursor).find()) {
|
||||
if (TextTools.isNextToWord(textBeforeCursor)) {
|
||||
return InputMode.CASE_LOWER;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public class Predictions {
|
|||
private Runnable onWordsChanged = () -> {};
|
||||
|
||||
// data
|
||||
private boolean areThereDbWords = false;
|
||||
private final ArrayList<String> words = new ArrayList<>();
|
||||
|
||||
// punctuation/emoji
|
||||
|
|
@ -82,6 +83,10 @@ public class Predictions {
|
|||
return words;
|
||||
}
|
||||
|
||||
public boolean areThereDbWords() {
|
||||
return areThereDbWords;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* suggestStem
|
||||
|
|
@ -89,7 +94,7 @@ public class Predictions {
|
|||
* the user has pressed X keys (otherwise, it makes no sense to add it).
|
||||
*/
|
||||
private void suggestStem() {
|
||||
if (stem.length() > 0 && stem.length() == digitSequence.length()) {
|
||||
if (!stem.isEmpty() && stem.length() == digitSequence.length()) {
|
||||
words.add(stem);
|
||||
}
|
||||
}
|
||||
|
|
@ -114,7 +119,7 @@ public class Predictions {
|
|||
* sequence or loads the static ones.
|
||||
*/
|
||||
public void load() {
|
||||
if (digitSequence == null || digitSequence.length() == 0) {
|
||||
if (digitSequence == null || digitSequence.isEmpty()) {
|
||||
words.clear();
|
||||
onWordsChanged.run();
|
||||
return;
|
||||
|
|
@ -124,7 +129,7 @@ public class Predictions {
|
|||
onWordsChanged.run();
|
||||
} else {
|
||||
DictionaryDb.getWords(
|
||||
this::onDbWords,
|
||||
(words) -> onDbWords(words, true),
|
||||
language,
|
||||
digitSequence,
|
||||
stem,
|
||||
|
|
@ -170,6 +175,23 @@ public class Predictions {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void loadWithoutLeadingPunctuation() {
|
||||
DictionaryDb.getWords(
|
||||
(dbWords) -> {
|
||||
char firstChar = inputWord.charAt(0);
|
||||
for (int i = 0; i < dbWords.size(); i++) {
|
||||
dbWords.set(i, firstChar + dbWords.get(i));
|
||||
}
|
||||
onDbWords(dbWords, false);
|
||||
},
|
||||
language,
|
||||
digitSequence.substring(1),
|
||||
stem.length() > 1 ? stem.substring(1) : "",
|
||||
settings.getSuggestionsMin(),
|
||||
settings.getSuggestionsMax()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dbWordsHandler
|
||||
|
|
@ -177,8 +199,18 @@ public class Predictions {
|
|||
* they will be generated based on the "inputWord". After the word list is compiled, it notifies the
|
||||
* external handler it is now possible to use it with "getList()".
|
||||
*/
|
||||
private void onDbWords (ArrayList<String> dbWords) {
|
||||
if (dbWords.size() == 0 && digitSequence.length() > 0) {
|
||||
private void onDbWords(ArrayList<String> dbWords, boolean isRetryAllowed) {
|
||||
// only the first round matters, the second one is just for getting the letters for a given key
|
||||
areThereDbWords = !dbWords.isEmpty() && isRetryAllowed;
|
||||
|
||||
// If there were no database words for ",a", try getting the letters only (e.g. "a", "b", "c").
|
||||
// We do this to display them in the correct order.
|
||||
if (dbWords.isEmpty() && isRetryAllowed && digitSequence.length() == 2 && digitSequence.charAt(0) == '1') {
|
||||
loadWithoutLeadingPunctuation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dbWords.isEmpty() && !digitSequence.isEmpty()) {
|
||||
emptyDbWarning.emitOnce(language);
|
||||
dbWords = generatePossibleCompletions(inputWord);
|
||||
}
|
||||
|
|
@ -186,7 +218,7 @@ public class Predictions {
|
|||
words.clear();
|
||||
suggestStem();
|
||||
suggestMissingWords(generatePossibleStemVariations(dbWords));
|
||||
suggestMissingWords(dbWords);
|
||||
suggestMissingWords(insertPunctuationCompletions(dbWords));
|
||||
|
||||
onWordsChanged.run();
|
||||
}
|
||||
|
|
@ -206,20 +238,16 @@ public class Predictions {
|
|||
|
||||
// Make sure the displayed word and the digit sequence, we will be generating suggestions from,
|
||||
// have the same length, to prevent visual discrepancies.
|
||||
baseWord = (baseWord != null && baseWord.length() > 0) ? baseWord.substring(0, Math.min(digitSequence.length() - 1, baseWord.length())) : "";
|
||||
baseWord = (baseWord != null && !baseWord.isEmpty()) ? baseWord.substring(0, Math.min(digitSequence.length() - 1, baseWord.length())) : "";
|
||||
|
||||
// append all letters for the last digit in the sequence (the last pressed key)
|
||||
int lastSequenceDigit = digitSequence.charAt(digitSequence.length() - 1) - '0';
|
||||
for (String keyLetter : language.getKeyCharacters(lastSequenceDigit)) {
|
||||
// let's skip numbers, because it's weird, for example:
|
||||
// | weird | weire | weirf | weir2 |
|
||||
if (keyLetter.charAt(0) < '0' || keyLetter.charAt(0) > '9') {
|
||||
for (String keyLetter : language.getKeyCharacters(lastSequenceDigit, false)) {
|
||||
generatedWords.add(baseWord + keyLetter);
|
||||
}
|
||||
}
|
||||
|
||||
// if there are no letters for this key, just append the number
|
||||
if (generatedWords.size() == 0) {
|
||||
if (generatedWords.isEmpty()) {
|
||||
generatedWords.add(baseWord + digitSequence.charAt(digitSequence.length() - 1));
|
||||
}
|
||||
|
||||
|
|
@ -227,6 +255,46 @@ public class Predictions {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* insertPunctuationCompletions
|
||||
* When given: "you'", for example, this also generates all other 1-key alternatives, like:
|
||||
* "you.", "you?", "you!" and so on. The generated words will be inserted after the direct
|
||||
* database matches and before the fuzzy matches, as if they were direct matches with low frequency.
|
||||
* This is to preserve the sorting by length and frequency.
|
||||
*/
|
||||
private ArrayList<String> insertPunctuationCompletions(ArrayList<String> dbWords) {
|
||||
if (!stem.isEmpty() || dbWords.isEmpty() || digitSequence.length() < 2 || !digitSequence.endsWith("1")) {
|
||||
return dbWords;
|
||||
}
|
||||
|
||||
ArrayList<String> complementedWords = new ArrayList<>();
|
||||
int exactMatchLength = digitSequence.length();
|
||||
|
||||
// shortest database words (exact matches)
|
||||
for (String w : dbWords) {
|
||||
if (w.length() <= exactMatchLength) {
|
||||
complementedWords.add(w);
|
||||
}
|
||||
}
|
||||
|
||||
// generated "exact matches"
|
||||
for (String w : generatePossibleCompletions(dbWords.get(0))) {
|
||||
if (!dbWords.contains(w) && !dbWords.contains(w.toLowerCase(language.getLocale()))) {
|
||||
complementedWords.add(w);
|
||||
}
|
||||
}
|
||||
|
||||
// longer database words (fuzzy matches)
|
||||
for (String w : dbWords) {
|
||||
if (w.length() > exactMatchLength) {
|
||||
complementedWords.add(w);
|
||||
}
|
||||
}
|
||||
|
||||
return complementedWords;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* generatePossibleStemVariations
|
||||
* Similar to generatePossibleCompletions(), but uses the current filter as a base word. This is
|
||||
|
|
@ -242,7 +310,7 @@ public class Predictions {
|
|||
*/
|
||||
private ArrayList<String> generatePossibleStemVariations(ArrayList<String> dbWords) {
|
||||
ArrayList<String> variations = new ArrayList<>();
|
||||
if (stem.length() == 0) {
|
||||
if (stem.isEmpty()) {
|
||||
return variations;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ public class Language {
|
|||
|
||||
// settings
|
||||
protected boolean hasUpperCase = true;
|
||||
protected boolean isPunctuationPartOfWords; // see the getter for more info
|
||||
|
||||
final public int getId() {
|
||||
if (id == 0) {
|
||||
|
|
@ -60,24 +59,6 @@ public class Language {
|
|||
return abcString;
|
||||
}
|
||||
|
||||
/**
|
||||
* isPunctuationPartOfWords
|
||||
* This plays a role in Predictive mode only.
|
||||
*
|
||||
* Return "true", if you need to use the 1-key for typing words, such as:
|
||||
* "it's" (English), "a'tje" (Dutch), "п'ят" (Ukrainian).
|
||||
*
|
||||
* Return "false" also:
|
||||
* - hide words like the above from the suggestions.
|
||||
* - 1-key would commit the current word, then display the punctuation list.
|
||||
* For example, pressing 1-key after "it" would accept "it" as a separate word,
|
||||
* then display only: | , | . | ! | ? | ...
|
||||
*
|
||||
* "false" is recommended when apostrophes or other punctuation are not part of the words,
|
||||
* because it would allow faster typing.
|
||||
*/
|
||||
final public boolean isPunctuationPartOfWords() { return isPunctuationPartOfWords; }
|
||||
|
||||
|
||||
public boolean hasUpperCase() {
|
||||
return hasUpperCase;
|
||||
|
|
@ -124,7 +105,21 @@ public class Language {
|
|||
}
|
||||
|
||||
public String capitalize(String word) {
|
||||
return word != null ? word.substring(0, 1).toUpperCase(locale) + word.substring(1).toLowerCase(locale) : null;
|
||||
if (word == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String capitalizedWord = "";
|
||||
|
||||
if (!word.isEmpty()) {
|
||||
capitalizedWord += word.substring(0, 1).toUpperCase(locale);
|
||||
}
|
||||
|
||||
if (word.length() > 1) {
|
||||
capitalizedWord += word.substring(1).toLowerCase(locale);
|
||||
}
|
||||
|
||||
return capitalizedWord;
|
||||
}
|
||||
|
||||
public boolean isMixedCaseWord(String word) {
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ public class BrazilianPortuguese extends English {
|
|||
locale = new Locale("pt","BR");
|
||||
dictionaryFile = "pt-BR-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = true;
|
||||
|
||||
characterMap.get(2).addAll(Arrays.asList("ç", "á", "â", "ã", "à"));
|
||||
characterMap.get(3).addAll(Arrays.asList("é", "ê", "è"));
|
||||
characterMap.get(4).add("í");
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ public class Bulgarian extends Language {
|
|||
locale = new Locale("bg","BG");
|
||||
dictionaryFile = "bg-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap = new ArrayList<>(Arrays.asList(
|
||||
Characters.Special, // 0
|
||||
Characters.Sentence, // 1
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ public class Dutch extends English {
|
|||
locale = new Locale("nl","NL");
|
||||
dictionaryFile = "nl-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = true;
|
||||
|
||||
characterMap.get(2).addAll(Arrays.asList("à", "ä", "ç"));
|
||||
characterMap.get(3).addAll(Arrays.asList("é", "è", "ê", "ë"));
|
||||
characterMap.get(4).addAll(Arrays.asList("î", "ï"));
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ public class English extends Language {
|
|||
locale = Locale.ENGLISH;
|
||||
dictionaryFile = "en-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = true;
|
||||
|
||||
characterMap = new ArrayList<>(Arrays.asList(
|
||||
Characters.Special, // 0
|
||||
Characters.Sentence, // 1
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ public class Finnish extends English {
|
|||
locale = new Locale("fi","FI");
|
||||
dictionaryFile = "fi-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = true;
|
||||
|
||||
characterMap.get(2).addAll(Arrays.asList("ä", "å"));
|
||||
characterMap.get(6).add("ö");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ public class French extends English {
|
|||
locale = Locale.FRENCH;
|
||||
dictionaryFile = "fr-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap.get(2).addAll(Arrays.asList("à", "â", "æ", "ç"));
|
||||
characterMap.get(3).addAll(Arrays.asList("é", "è", "ê", "ë"));
|
||||
characterMap.get(4).addAll(Arrays.asList("î", "ï"));
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ public class German extends English {
|
|||
locale = Locale.GERMAN;
|
||||
dictionaryFile = "de-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap.get(2).add("ä");
|
||||
characterMap.get(6).add("ö");
|
||||
characterMap.get(7).add("ß");
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ public class Hebrew extends Language {
|
|||
abcString = "אבג";
|
||||
|
||||
hasUpperCase = false;
|
||||
isPunctuationPartOfWords = true;
|
||||
|
||||
characterMap = new ArrayList<>(Arrays.asList(
|
||||
Characters.Special, // 0
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ public class Italian extends English {
|
|||
locale = Locale.ITALIAN;
|
||||
dictionaryFile = "it-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap.get(2).add("à");
|
||||
characterMap.get(3).addAll(Arrays.asList("é", "è"));
|
||||
characterMap.get(4).addAll(Arrays.asList("ì", "í", "î"));
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ public class Norwegian extends English {
|
|||
locale = new Locale("nb","NO");
|
||||
dictionaryFile = "nb-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap.get(2).addAll(Arrays.asList("æ", "å"));
|
||||
characterMap.get(3).addAll(Arrays.asList("é", "è"));
|
||||
characterMap.get(6).addAll(Arrays.asList("ø", "ó", "ò", "ô"));
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ public class Polish extends English {
|
|||
locale = new Locale("pl","PL");
|
||||
dictionaryFile = "pl-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap.get(2).addAll(Arrays.asList("ą", "ć"));
|
||||
characterMap.get(3).add("ę");
|
||||
characterMap.get(5).add("ł");
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ public class Russian extends Language {
|
|||
locale = new Locale("ru","RU");
|
||||
dictionaryFile = "ru-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap = new ArrayList<>(Arrays.asList(
|
||||
Characters.Special, // 0
|
||||
Characters.Sentence, // 1
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ public class Spanish extends English {
|
|||
locale = new Locale("es", "ES");
|
||||
dictionaryFile = "es-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap.set(1, new ArrayList<>(Characters.Sentence));
|
||||
characterMap.get(1).addAll(Arrays.asList("¡", "¿"));
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ public class Swedish extends English {
|
|||
locale = new Locale("sv","SE");
|
||||
dictionaryFile = "sv-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = false;
|
||||
|
||||
characterMap.get(2).addAll(Arrays.asList("å", "ä"));
|
||||
characterMap.get(3).add("é");
|
||||
characterMap.get(6).add("ö");
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ public class Ukrainian extends Language {
|
|||
locale = new Locale("uk","UA");
|
||||
dictionaryFile = "uk-utf8.csv";
|
||||
|
||||
isPunctuationPartOfWords = true;
|
||||
|
||||
characterMap = new ArrayList<>(Arrays.asList(
|
||||
Characters.Special, // 0
|
||||
Characters.Sentence, // 1
|
||||
|
|
|
|||
|
|
@ -8,6 +8,5 @@ public class Yiddish extends Hebrew {
|
|||
|
||||
locale = new Locale("ji","JI");
|
||||
dictionaryFile = "ji-utf8.csv";
|
||||
isPunctuationPartOfWords = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue