Skip to content

Commit d5f6106

Browse files
author
Kratos
committed
feature:创建错词本
1 parent e0dc7a0 commit d5f6106

File tree

2 files changed

+121
-42
lines changed

2 files changed

+121
-42
lines changed

src/index.ts

+115-41
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ import { getConfig } from './utils'
66
import { soundPlayer } from './sound'
77
import { voicePlayer } from './resource/voice'
88
import PluginState from './utils/PluginState'
9+
import * as fs from 'fs';
10+
import * as path from 'path';
911

1012
const PLAY_VOICE_COMMAND = 'qwerty-learner.playVoice'
1113
const PREV_WORD_COMMAND = 'qwerty-learner.prevWord'
1214
const NEXT_WORD_COMMAND = 'qwerty-learner.nextWord'
1315
const TOGGLE_TRANSLATION_COMMAND = 'qwerty-learner.toggleTranslation'
1416
const TOGGLE_DIC_NAME_COMMAND = 'qwerty-learner.toggleDicName'
17+
const OPEN_WRONG_WORDS_COMMAND = 'qwerty-learner.openWrongWords'
1518

1619
export function activate(context: vscode.ExtensionContext) {
1720
const pluginState = new PluginState(context)
@@ -22,6 +25,7 @@ export function activate(context: vscode.ExtensionContext) {
2225
const translationBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, -103)
2326
const prevWord = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, -104)
2427
const nextWord = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, -105)
28+
const wrongWords = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, -106)
2529
prevWord.text = '<'
2630
prevWord.tooltip = '切换上一个单词'
2731
prevWord.command = PREV_WORD_COMMAND
@@ -34,54 +38,108 @@ export function activate(context: vscode.ExtensionContext) {
3438
translationBar.command = TOGGLE_TRANSLATION_COMMAND
3539
wordBar.command = TOGGLE_DIC_NAME_COMMAND
3640
wordBar.tooltip = '隐藏/显示字典名称'
41+
wrongWords.text = '错词本'
42+
wrongWords.tooltip = '点击打开错词本'
43+
wrongWords.command = OPEN_WRONG_WORDS_COMMAND
3744

38-
vscode.workspace.onDidChangeTextDocument((e) => {
39-
if (!pluginState.isStart) {
40-
return
41-
}
45+
function logWrongWord(word: string, translation: string) {
46+
const filePath = path.join(__dirname, 'wrong_words.txt');
4247

43-
if (pluginState.readOnlyMode) {
44-
return
48+
let fileContent = '';
49+
try {
50+
fileContent = fs.readFileSync(filePath, 'utf8');
51+
} catch (err) {
52+
if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;
4553
}
4654

47-
const { uri } = e.document
48-
// 避免破坏配置文件
49-
if (uri.scheme.indexOf('vscode') !== -1) {
50-
return
51-
}
55+
const lines = fileContent.split('\n').filter(line => line.trim() !== '');
56+
const wordMap: { [key: string]: { translation: string, count: number } } = {};
57+
lines.forEach(line => {
58+
const parts = line.split(' ');
59+
const count = parseInt(parts.pop()!, 10);
60+
const translation = parts.pop()!;
61+
const word = parts.join(' ');
62+
wordMap[word] = { translation, count };
63+
});
5264

53-
const { range, text, rangeLength } = e.contentChanges[0]
54-
if (!(text !== '' && text.length === 1)) {
55-
return
56-
}
57-
// 删除用户输入的字符
58-
const newRange = new vscode.Range(range.start.line, range.start.character, range.end.line, range.end.character + 1)
59-
const editAction = new vscode.WorkspaceEdit()
60-
editAction.delete(uri, newRange)
61-
vscode.workspace.applyEdit(editAction)
62-
if (pluginState.hasWrong) {
63-
return
65+
if (wordMap[word]) {
66+
wordMap[word].count += 1;
67+
} else {
68+
wordMap[word] = { translation, count: 1 };
6469
}
65-
soundPlayer('click')
66-
inputBar.text = pluginState.getCurrentInputBarContent(text)
67-
68-
const compareResult = pluginState.compareResult
69-
if (compareResult === -2) {
70-
// 用户完成单词输入
71-
soundPlayer('success')
72-
pluginState.finishWord()
73-
initializeBar()
74-
} else if (compareResult >= 0) {
75-
pluginState.wrongInput()
76-
inputBar.color = pluginState.highlightWrongColor
77-
soundPlayer('wrong')
70+
71+
const newLines = Object.keys(wordMap)
72+
.map(word => `${word} ${wordMap[word].translation} ${wordMap[word].count}`)
73+
.sort((a, b) => {
74+
const countA = parseInt(a.split(' ').pop()!, 10);
75+
const countB = parseInt(b.split(' ').pop()!, 10);
76+
return countB - countA;
77+
});
78+
79+
fs.writeFileSync(filePath, newLines.join('\n'), 'utf8');
80+
console.log(`单词 "${word}" 和翻译 "${translation}" 已记录.`);
81+
}
82+
83+
84+
85+
86+
vscode.workspace.onDidChangeTextDocument((e) => {
87+
if (!pluginState.isStart) {
88+
return;
89+
}
90+
91+
if (pluginState.readOnlyMode) {
92+
return;
93+
}
94+
95+
const { uri } = e.document;
96+
97+
if (uri.scheme.indexOf('vscode') !== -1) {
98+
return;
99+
}
100+
101+
const { range, text, rangeLength } = e.contentChanges[0];
102+
103+
if (!(text !== '' && text.length === 1)) {
104+
return;
105+
}
106+
107+
const newRange = new vscode.Range(range.start.line, range.start.character, range.end.line, range.end.character + 1);
108+
const editAction = new vscode.WorkspaceEdit();
109+
editAction.delete(uri, newRange);
110+
vscode.workspace.applyEdit(editAction);
111+
112+
if (pluginState.hasWrong) {
113+
return;
114+
}
115+
116+
soundPlayer('click');
117+
inputBar.text = pluginState.getCurrentInputBarContent(text);
118+
119+
const compareResult = pluginState.compareResult;
120+
121+
if (compareResult === -2) {
122+
soundPlayer('success');
123+
pluginState.finishWord();
124+
initializeBar();
125+
} else if (compareResult >= 0) {
126+
pluginState.wrongInput();
127+
inputBar.color = pluginState.highlightWrongColor;
128+
soundPlayer('wrong');
129+
130+
// 调用记录正确单词和翻译的函数
131+
const currentWord = pluginState.getCurrentWord();
132+
const translation = pluginState.getCurrentTranslation()
133+
logWrongWord(currentWord, translation);
134+
78135
setTimeout(() => {
79-
pluginState.clearWrong()
80-
inputBar.color = undefined
81-
initializeBar()
82-
}, pluginState.highlightWrongDelay)
83-
}
84-
})
136+
pluginState.clearWrong();
137+
inputBar.color = undefined;
138+
initializeBar();
139+
}, pluginState.highlightWrongDelay);
140+
}e
141+
});
142+
85143

86144
vscode.workspace.onDidChangeConfiguration((event) => {
87145
if (event.affectsConfiguration('qwerty-learner.placeholder')) {
@@ -108,6 +166,7 @@ export function activate(context: vscode.ExtensionContext) {
108166
prevWord.show()
109167
nextWord.show()
110168
translationBar.show()
169+
wrongWords.show()
111170
if (pluginState.readOnlyMode) {
112171
setUpReadOnlyInterval()
113172
}
@@ -118,6 +177,7 @@ export function activate(context: vscode.ExtensionContext) {
118177
prevWord.hide()
119178
nextWord.hide()
120179
translationBar.hide()
180+
wrongWords.hide()
121181
removeReadOnlyInterval()
122182
}
123183
}),
@@ -179,6 +239,19 @@ export function activate(context: vscode.ExtensionContext) {
179239
vscode.window.showInformationMessage('章节循环模式已关闭')
180240
}
181241
}),
242+
// 注册打开错词本的命令
243+
vscode.commands.registerCommand(OPEN_WRONG_WORDS_COMMAND, () => {
244+
const filePath = path.join(__dirname, 'wrong_words.txt');
245+
fs.exists(filePath, (exists) => {
246+
if (!exists) {
247+
fs.writeFile(filePath, '', (error) => {})
248+
}
249+
});
250+
251+
vscode.workspace.openTextDocument(filePath).then(doc => {
252+
vscode.window.showTextDocument(doc);
253+
});
254+
})
182255
],
183256
)
184257

@@ -196,6 +269,7 @@ export function activate(context: vscode.ExtensionContext) {
196269
})
197270
}
198271
}
272+
199273
function setUpWordBar() {
200274
wordBar.text = pluginState.getInitialWordBarContent()
201275
playVoice()

src/utils/PluginState.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ export default class PluginState {
7272
dictKey: this._dictKey,
7373
}
7474
}
75-
75+
getCurrentWord(): string {
76+
return this.currentWord.name;
77+
}
78+
getCurrentTranslation(): string {
79+
return this.currentWord.trans.join('; ');
80+
}
7681
get chapter(): number {
7782
return this._chapter
7883
}

0 commit comments

Comments
 (0)