From a9ab774a3fa4a1f161771b1291d1a8e4c5845084 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 19:35:57 -0500 Subject: [PATCH 1/8] Move function --- ext/bg/js/translator.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index ff1d24f3..d04b1cb3 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -47,22 +47,6 @@ class Translator { await this.database.deleteDictionary(dictionaryName); } - async findTermsGrouped(text, dictionaries, alphanumeric, options) { - const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); - - const definitionsGrouped = dictTermsGroup(definitions, dictionaries); - await this.buildTermFrequencies(definitionsGrouped, titles); - - if (options.general.compactTags) { - for (const definition of definitionsGrouped) { - dictTermsCompressTags(definition.definitions); - } - } - - return {length, definitions: definitionsGrouped}; - } - async getSequencedDefinitions(definitions, mainDictionary) { const definitionsBySequence = dictTermsMergeBySequence(definitions, mainDictionary); const defaultDefinitions = definitionsBySequence['-1']; @@ -157,6 +141,22 @@ class Translator { return result; } + async findTermsGrouped(text, dictionaries, alphanumeric, options) { + const titles = Object.keys(dictionaries); + const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); + + const definitionsGrouped = dictTermsGroup(definitions, dictionaries); + await this.buildTermFrequencies(definitionsGrouped, titles); + + if (options.general.compactTags) { + for (const definition of definitionsGrouped) { + dictTermsCompressTags(definition.definitions); + } + } + + return {length, definitions: definitionsGrouped}; + } + async findTermsMerged(text, dictionaries, alphanumeric, options) { const secondarySearchTitles = Object.keys(options.dictionaries).filter(dict => options.dictionaries[dict].allowSecondarySearches); const titles = Object.keys(dictionaries); From fe829139914bbcb9584f11b6bece798b987fbd8b Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 19:36:50 -0500 Subject: [PATCH 2/8] Rename function --- ext/bg/js/translator.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index d04b1cb3..305619a5 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -143,7 +143,7 @@ class Translator { async findTermsGrouped(text, dictionaries, alphanumeric, options) { const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); + const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); const definitionsGrouped = dictTermsGroup(definitions, dictionaries); await this.buildTermFrequencies(definitionsGrouped, titles); @@ -160,7 +160,7 @@ class Translator { async findTermsMerged(text, dictionaries, alphanumeric, options) { const secondarySearchTitles = Object.keys(options.dictionaries).filter(dict => options.dictionaries[dict].allowSecondarySearches); const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); + const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); const {sequencedDefinitions, defaultDefinitions} = await this.getSequencedDefinitions(definitions, options.general.mainDictionary); const definitionsMerged = []; const mergedByTermIndices = new Set(); @@ -196,14 +196,14 @@ class Translator { async findTermsSplit(text, dictionaries, alphanumeric) { const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); + const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); await this.buildTermFrequencies(definitions, titles); return {length, definitions}; } - async findTerms(text, dictionaries, alphanumeric) { + async findTermsInternal(text, dictionaries, alphanumeric) { if (!alphanumeric && text.length > 0) { const c = text[0]; if (!jpIsKana(c) && !jpIsKanji(c)) { From ae10bb7096fafc94ffb7227a16e13373c1c1c403 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 19:53:25 -0500 Subject: [PATCH 3/8] Simplify dictTermsSort --- ext/bg/js/dictionary.js | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index a4cf34ed..9aa0af9c 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -55,39 +55,23 @@ function dictRowsSort(rows, options) { function dictTermsSort(definitions, dictionaries=null) { return definitions.sort((v1, v2) => { + let i; if (dictionaries !== null) { - const p1 = (dictionaries[v1.dictionary] || {}).priority || 0; - const p2 = (dictionaries[v2.dictionary] || {}).priority || 0; - if (p1 > p2) { - return -1; - } else if (p1 < p2) { - return 1; - } + i = ( + ((dictionaries[v2.dictionary] || {}).priority || 0) - + ((dictionaries[v1.dictionary] || {}).priority || 0) + ); + if (i !== 0) { return i; } } - const sl1 = v1.source.length; - const sl2 = v2.source.length; - if (sl1 > sl2) { - return -1; - } else if (sl1 < sl2) { - return 1; - } + i = v2.source.length - v1.source.length; + if (i !== 0) { return i; } - const rl1 = v1.reasons.length; - const rl2 = v2.reasons.length; - if (rl1 < rl2) { - return -1; - } else if (rl1 > rl2) { - return 1; - } + i = v2.reasons.length - v1.reasons.length; + if (i !== 0) { return i; } - const s1 = v1.score; - const s2 = v2.score; - if (s1 > s2) { - return -1; - } else if (s1 < s2) { - return 1; - } + i = v2.score - v1.score; + if (i !== 0) { return i; } return v2.expression.toString().localeCompare(v1.expression.toString()); }); From af1662acadbfb7a96e06257a9dfad71ed6e2c478 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:09:34 -0500 Subject: [PATCH 4/8] Update how apiTermsFind works --- ext/bg/js/api.js | 16 +--------------- ext/bg/js/translator.js | 38 +++++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 9fed99a1..9751d4a1 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -74,21 +74,7 @@ async function apiOptionsSave(source) { async function apiTermsFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); - const translator = utilBackend().translator; - - const searcher = { - 'merge': translator.findTermsMerged, - 'split': translator.findTermsSplit, - 'group': translator.findTermsGrouped - }[options.general.resultOutputMode].bind(translator); - - const {definitions, length} = await searcher( - text, - dictEnabledSet(options), - options.scanning.alphanumeric, - options - ); - + const [definitions, length] = await utilBackend().translator.findTerms(text, options); return { length, definitions: definitions.slice(0, options.general.maxResults) diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 305619a5..d33a2e27 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -141,9 +141,23 @@ class Translator { return result; } - async findTermsGrouped(text, dictionaries, alphanumeric, options) { + async findTerms(text, options) { + switch (options.general.resultOutputMode) { + case 'group': + return await this.findTermsGrouped(text, options); + case 'merge': + return await this.findTermsMerged(text, options); + case 'split': + return await this.findTermsSplit(text, options); + default: + return [[], 0]; + } + } + + async findTermsGrouped(text, options) { + const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); const definitionsGrouped = dictTermsGroup(definitions, dictionaries); await this.buildTermFrequencies(definitionsGrouped, titles); @@ -154,13 +168,14 @@ class Translator { } } - return {length, definitions: definitionsGrouped}; + return [definitionsGrouped, length]; } - async findTermsMerged(text, dictionaries, alphanumeric, options) { + async findTermsMerged(text, options) { + const dictionaries = dictEnabledSet(options); const secondarySearchTitles = Object.keys(options.dictionaries).filter(dict => options.dictionaries[dict].allowSecondarySearches); const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); const {sequencedDefinitions, defaultDefinitions} = await this.getSequencedDefinitions(definitions, options.general.mainDictionary); const definitionsMerged = []; const mergedByTermIndices = new Set(); @@ -191,23 +206,24 @@ class Translator { } } - return {length, definitions: dictTermsSort(definitionsMerged)}; + return [dictTermsSort(definitionsMerged), length]; } - async findTermsSplit(text, dictionaries, alphanumeric) { + async findTermsSplit(text, options) { + const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); await this.buildTermFrequencies(definitions, titles); - return {length, definitions}; + return [definitions, length]; } async findTermsInternal(text, dictionaries, alphanumeric) { if (!alphanumeric && text.length > 0) { const c = text[0]; if (!jpIsKana(c) && !jpIsKanji(c)) { - return {length: 0, definitions: []}; + return [[], 0]; } } @@ -246,7 +262,7 @@ class Translator { length = Math.max(length, definition.source.length); } - return {length, definitions}; + return [definitions, length]; } async findTermDeinflections(text, text2, titles) { From 58c099799940fce56c7a57ce566c522c7eb0eb12 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:13:03 -0500 Subject: [PATCH 5/8] Give findKanji the same API as findTerms --- ext/bg/js/api.js | 2 +- ext/bg/js/translator.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 9751d4a1..f379e65a 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -83,7 +83,7 @@ async function apiTermsFind(text, optionsContext) { async function apiKanjiFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); - const definitions = await utilBackend().translator.findKanji(text, dictEnabledSet(options)); + const definitions = await utilBackend().translator.findKanji(text, options); return definitions.slice(0, options.general.maxResults); } diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index d33a2e27..1cdd79db 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -330,7 +330,8 @@ class Translator { return deinflections; } - async findKanji(text, dictionaries) { + async findKanji(text, options) { + const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); const kanjiUnique = {}; const kanjiList = []; From 7093d8f06e26daf825745be26238d92ed122e60b Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:14:51 -0500 Subject: [PATCH 6/8] Simplify how definition count is limited --- ext/bg/js/api.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index f379e65a..c50db76f 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -75,16 +75,15 @@ async function apiOptionsSave(source) { async function apiTermsFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); const [definitions, length] = await utilBackend().translator.findTerms(text, options); - return { - length, - definitions: definitions.slice(0, options.general.maxResults) - }; + definitions.splice(options.general.maxResults); + return {length, definitions}; } async function apiKanjiFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); const definitions = await utilBackend().translator.findKanji(text, options); - return definitions.slice(0, options.general.maxResults); + definitions.splice(options.general.maxResults); + return definitions; } async function apiDefinitionAdd(definition, mode, context, optionsContext) { From 3a225c3f916d435e04fb30afa731c30c4309fc7f Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:43:40 -0500 Subject: [PATCH 7/8] Add details field to apiTermsFind --- ext/bg/js/api.js | 4 ++-- ext/bg/js/backend.js | 2 +- ext/bg/js/search.js | 2 +- ext/bg/js/translator.js | 22 +++++++++++----------- ext/fg/js/api.js | 4 ++-- ext/fg/js/frontend.js | 2 +- ext/mixed/js/display.js | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index c50db76f..df73aa2a 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -72,9 +72,9 @@ async function apiOptionsSave(source) { backend.onOptionsUpdated(source); } -async function apiTermsFind(text, optionsContext) { +async function apiTermsFind(text, details, optionsContext) { const options = await apiOptionsGet(optionsContext); - const [definitions, length] = await utilBackend().translator.findTerms(text, options); + const [definitions, length] = await utilBackend().translator.findTerms(text, details, options); definitions.splice(options.general.maxResults); return {length, definitions}; } diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 71393467..efad153a 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -179,7 +179,7 @@ Backend.messageHandlers = { optionsGet: ({optionsContext}) => apiOptionsGet(optionsContext), optionsSet: ({changedOptions, optionsContext, source}) => apiOptionsSet(changedOptions, optionsContext, source), kanjiFind: ({text, optionsContext}) => apiKanjiFind(text, optionsContext), - termsFind: ({text, optionsContext}) => apiTermsFind(text, optionsContext), + termsFind: ({text, details, optionsContext}) => apiTermsFind(text, details, optionsContext), definitionAdd: ({definition, mode, context, optionsContext}) => apiDefinitionAdd(definition, mode, context, optionsContext), definitionsAddable: ({definitions, modes, optionsContext}) => apiDefinitionsAddable(definitions, modes, optionsContext), noteView: ({noteId}) => apiNoteView(noteId), diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index ad579918..abd40640 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -207,7 +207,7 @@ class DisplaySearch extends Display { this.setIntroVisible(!valid, animate); this.updateSearchButton(); if (valid) { - const {definitions} = await apiTermsFind(query, this.optionsContext); + const {definitions} = await apiTermsFind(query, {}, this.optionsContext); this.setContentTerms(definitions, { focus: false, sentence: null, diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 1cdd79db..dac53f93 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -141,23 +141,23 @@ class Translator { return result; } - async findTerms(text, options) { + async findTerms(text, details, options) { switch (options.general.resultOutputMode) { case 'group': - return await this.findTermsGrouped(text, options); + return await this.findTermsGrouped(text, details, options); case 'merge': - return await this.findTermsMerged(text, options); + return await this.findTermsMerged(text, details, options); case 'split': - return await this.findTermsSplit(text, options); + return await this.findTermsSplit(text, details, options); default: return [[], 0]; } } - async findTermsGrouped(text, options) { + async findTermsGrouped(text, details, options) { const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); - const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details); const definitionsGrouped = dictTermsGroup(definitions, dictionaries); await this.buildTermFrequencies(definitionsGrouped, titles); @@ -171,11 +171,11 @@ class Translator { return [definitionsGrouped, length]; } - async findTermsMerged(text, options) { + async findTermsMerged(text, details, options) { const dictionaries = dictEnabledSet(options); const secondarySearchTitles = Object.keys(options.dictionaries).filter(dict => options.dictionaries[dict].allowSecondarySearches); const titles = Object.keys(dictionaries); - const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details); const {sequencedDefinitions, defaultDefinitions} = await this.getSequencedDefinitions(definitions, options.general.mainDictionary); const definitionsMerged = []; const mergedByTermIndices = new Set(); @@ -209,17 +209,17 @@ class Translator { return [dictTermsSort(definitionsMerged), length]; } - async findTermsSplit(text, options) { + async findTermsSplit(text, details, options) { const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); - const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details); await this.buildTermFrequencies(definitions, titles); return [definitions, length]; } - async findTermsInternal(text, dictionaries, alphanumeric) { + async findTermsInternal(text, dictionaries, alphanumeric, details) { if (!alphanumeric && text.length > 0) { const c = text[0]; if (!jpIsKana(c) && !jpIsKanji(c)) { diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js index 54818702..945ba076 100644 --- a/ext/fg/js/api.js +++ b/ext/fg/js/api.js @@ -25,8 +25,8 @@ function apiOptionsSet(changedOptions, optionsContext, source) { return utilInvoke('optionsSet', {changedOptions, optionsContext, source}); } -function apiTermsFind(text, optionsContext) { - return utilInvoke('termsFind', {text, optionsContext}); +function apiTermsFind(text, details, optionsContext) { + return utilInvoke('termsFind', {text, details, optionsContext}); } function apiKanjiFind(text, optionsContext) { diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 7c62b51b..6002dfcb 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -413,7 +413,7 @@ class Frontend { const searchText = textSource.text(); if (searchText.length === 0) { return null; } - const {definitions, length} = await apiTermsFind(searchText, this.getOptionsContext()); + const {definitions, length} = await apiTermsFind(searchText, {}, this.getOptionsContext()); if (definitions.length === 0) { return null; } textSource.setEndOffset(length); diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 801011df..8ad3ee1b 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -112,7 +112,7 @@ class Display { try { textSource.setEndOffset(this.options.scanning.length); - ({definitions, length} = await apiTermsFind(textSource.text(), this.getOptionsContext())); + ({definitions, length} = await apiTermsFind(textSource.text(), {}, this.getOptionsContext())); if (definitions.length === 0) { return false; } From 7333873244ccaeeefe01bd3a63447f39dd4f3bbe Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:52:08 -0500 Subject: [PATCH 8/8] Add support for wildcards --- ext/bg/js/database.js | 9 +++++---- ext/bg/js/search.js | 9 ++++++++- ext/bg/js/translator.js | 27 +++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index b6cf9063..9b560f78 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -130,7 +130,7 @@ class Database { await Promise.all(promises); } - async findTermsBulk(termList, titles) { + async findTermsBulk(termList, titles, wildcard) { this.validate(); const promises = []; @@ -149,10 +149,11 @@ class Database { const dbIndex2 = dbTerms.index('reading'); for (let i = 0; i < termList.length; ++i) { - const only = IDBKeyRange.only(termList[i]); + const term = termList[i]; + const query = wildcard ? IDBKeyRange.bound(term, `${term}\uffff`, false, false) : IDBKeyRange.only(term); promises.push( - Database.getAll(dbIndex1, only, i, processRow), - Database.getAll(dbIndex2, only, i, processRow) + Database.getAll(dbIndex1, query, i, processRow), + Database.getAll(dbIndex2, query, i, processRow) ); } diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index abd40640..aa56d1a6 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -203,11 +203,18 @@ class DisplaySearch extends Display { async onSearchQueryUpdated(query, animate) { try { + const details = {}; + const match = /[\*\uff0a]+$/.exec(query); + if (match !== null) { + details.wildcard = true; + query = query.substr(0, query.length - match[0].length); + } + const valid = (query.length > 0); this.setIntroVisible(!valid, animate); this.updateSearchButton(); if (valid) { - const {definitions} = await apiTermsFind(query, {}, this.optionsContext); + const {definitions} = await apiTermsFind(query, details, this.optionsContext); this.setContentTerms(definitions, { focus: false, sentence: null, diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index dac53f93..583d6e31 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -227,9 +227,12 @@ class Translator { } } - const textHiragana = jpKatakanaToHiragana(text); const titles = Object.keys(dictionaries); - const deinflections = await this.findTermDeinflections(text, textHiragana, titles); + const deinflections = ( + details.wildcard ? + await this.findTermWildcard(text, titles) : + await this.findTermDeinflections(text, titles) + ); let definitions = []; for (const deinflection of deinflections) { @@ -265,7 +268,23 @@ class Translator { return [definitions, length]; } - async findTermDeinflections(text, text2, titles) { + async findTermWildcard(text, titles) { + const definitions = await this.database.findTermsBulk([text], titles, true); + if (definitions.length === 0) { + return []; + } + + return [{ + source: text, + term: text, + rules: 0, + definitions, + reasons: [] + }]; + } + + async findTermDeinflections(text, titles) { + const text2 = jpKatakanaToHiragana(text); const deinflections = (text === text2 ? this.getDeinflections(text) : this.getDeinflections2(text, text2)); if (deinflections.length === 0) { @@ -289,7 +308,7 @@ class Translator { deinflectionArray.push(deinflection); } - const definitions = await this.database.findTermsBulk(uniqueDeinflectionTerms, titles); + const definitions = await this.database.findTermsBulk(uniqueDeinflectionTerms, titles, false); for (const definition of definitions) { const definitionRules = Deinflector.rulesToRuleFlags(definition.rules);