Skip to content

Commit

Permalink
feat: Use Deno.Kv to create a database of dictionaries
Browse files Browse the repository at this point in the history
  • Loading branch information
uga-rosa committed Dec 25, 2023
1 parent f8f5a89 commit a1410a0
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
# - macos-latest
- ubuntu-latest
version:
- "1.32.0"
- "1.38.0"
- "1.x"
host_version:
- vim: "v9.0.1499"
Expand Down
1 change: 1 addition & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"lock": false,
"unstable": ["kv"],
"tasks": {
"fmt-check": "deno fmt --check denops",
"lint": "deno lint",
Expand Down
2 changes: 2 additions & 0 deletions denops/skkeleton/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const config: ConfigOptions = {
usePopup: true,
useSkkServer: false,
userJisyo: "~/.skkeleton",
databasePath: "",
};

type Validators = {
Expand Down Expand Up @@ -111,6 +112,7 @@ const validators: Validators = {
useGoogleJapaneseInput: (x) => ensure(x, is.Boolean),
useSkkServer: (x) => ensure(x, is.Boolean),
userJisyo: (x) => ensure(x, is.String),
databasePath: (x) => ensure(x, is.String),
};

export async function setConfig(
Expand Down
71 changes: 61 additions & 10 deletions denops/skkeleton/jisyo/skk_dictionary.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { config } from "../config.ts";
import { getKanaTable } from "../kana.ts";
import { readFileWithEncoding } from "../util.ts";
import type { CompletionData } from "../types.ts";
Expand All @@ -17,6 +18,8 @@ interface Jisyo {
export class SkkDictionary implements Dictionary {
#okuriAri: Map<string, string[]>;
#okuriNasi: Map<string, string[]>;
#db?: Deno.Kv;
#path?: string;

#cachedCandidates: Map<string, CompletionData>;

Expand All @@ -29,27 +32,35 @@ export class SkkDictionary implements Dictionary {
this.#cachedCandidates = new Map();
}

getHenkanResult(type: HenkanType, word: string): Promise<string[]> {
const target = type === "okuriari" ? this.#okuriAri : this.#okuriNasi;
return Promise.resolve(target.get(word) ?? []);
async getHenkanResult(type: HenkanType, word: string): Promise<string[]> {
if (this.#db && this.#path) {
const result = await this.#db.get<string[]>([this.#path, type, ...word]);
return result.value ?? [];
} else {
const target = type === "okuriari" ? this.#okuriAri : this.#okuriNasi;
return target.get(word) ?? [];
}
}

getCompletionResult(prefix: string, feed: string): Promise<CompletionData> {
async getCompletionResult(
prefix: string,
feed: string,
): Promise<CompletionData> {
const candidates: CompletionData = [];
if (feed != "") {
const table = getKanaTable();
for (const [key, kanas] of table) {
if (key.startsWith(feed) && kanas.length > 1) {
const feedPrefix = prefix + (kanas as string[])[0];
for (const entry of this.getCachedCandidates(prefix[0])) {
for (const entry of await this.getCachedCandidates(prefix[0])) {
if (entry[0].startsWith(feedPrefix)) {
candidates.push(entry);
}
}
}
}
} else {
for (const entry of this.getCachedCandidates(prefix[0])) {
for (const entry of await this.getCachedCandidates(prefix[0])) {
if (entry[0].startsWith(prefix)) {
candidates.push(entry);
}
Expand All @@ -60,16 +71,26 @@ export class SkkDictionary implements Dictionary {
return Promise.resolve(candidates);
}

private getCachedCandidates(prefix: string): CompletionData {
private async getCachedCandidates(prefix: string): Promise<CompletionData> {
if (this.#cachedCandidates.has(prefix)) {
const candidates = this.#cachedCandidates.get(prefix);
return candidates ?? [];
}

const candidates: CompletionData = [];
for (const entry of this.#okuriNasi) {
if (entry[0].startsWith(prefix)) {
candidates.push(entry);
if (this.#db && this.#path) {
for await (
const entry of this.#db.list<string[]>({
prefix: [this.#path, "okurinasi", ...prefix],
})
) {
candidates.push([entry.key.slice(2).join(""), entry.value]);
}
} else {
for (const entry of this.#okuriNasi) {
if (entry[0].startsWith(prefix)) {
candidates.push(entry);
}
}
}

Expand All @@ -78,6 +99,16 @@ export class SkkDictionary implements Dictionary {
}

async load(path: string, encoding: string) {
if (config.databasePath) {
this.#db = await Deno.openKv(config.databasePath);
this.#path = path;
}
const stat = await Deno.stat(path);
const mtime = stat.mtime?.getTime();
if (mtime && (await this.#db?.get([path, "mtime"]))?.value === mtime) {
return this;
}

if (path.endsWith(".yaml") || path.endsWith(".yml")) {
const file = await Deno.readTextFile(path);
this.loadYaml(file);
Expand All @@ -92,6 +123,26 @@ export class SkkDictionary implements Dictionary {
this.loadString(file);
}

if (this.#db) {
let [atm, count] = [this.#db.atomic(), 0];
for (
const [type, map] of [
["okuriari", this.#okuriAri],
["okurinasi", this.#okuriNasi],
] as const
) {
for (const [k, v] of map) {
atm = atm.set([path, type, ...k], v);
if (++count >= 500) {
await atm.commit();
[atm, count] = [this.#db.atomic(), 0];
}
}
}
await atm.commit();
await this.#db.set([path, "mtime"], mtime);
}

return this;
}

Expand Down
1 change: 1 addition & 0 deletions denops/skkeleton/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,5 @@ export type ConfigOptions = {
usePopup: boolean;
useSkkServer: boolean;
userJisyo: string;
databasePath: string;
};
7 changes: 7 additions & 0 deletions doc/skkeleton.jax
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,13 @@ userJisyo *skkeleton-config-userJisyo*
ユーザー辞書のパス
JavaScriptの制約によりエンコーディングはUTF-8限定になります。

databasePath *skkeleton-config-databasePath*
(デフォルト "")
データベースの保存先パスです。
空文字列でないときに有効になり、Deno.Kv を使って辞書をデータベース化し
ます。skkeleton の起動時に辞書ファイルに更新があったとき、データベース
を更新します。

------------------------------------------------------------------------------
*skkeleton#register_kanatable()*
skkeleton#register_kanatable({tableName}, {table} [, {create}])
Expand Down

0 comments on commit a1410a0

Please sign in to comment.