vietnam-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # vietnam-cli
2
+
3
+ Fix Vietnamese input method (Unikey, EVKey, etc.) for CLI tools like **Auggie CLI** and **Claude Code**.
4
+
5
+ ## Problem
6
+
7
+ Vietnamese IME (Input Method Editor) like Unikey or EVKey uses a technique where it sends a DEL character (`\x7F`) to delete the previous character, then inserts the new accented character.
8
+
9
+ Some CLI tools incorrectly interpret `\x7F` as the "Delete" key (forward delete) instead of "Backspace" (backward delete), causing Vietnamese input to malfunction.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install -g vietnam-cli
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### Apply patch to all supported tools
20
+ ```bash
21
+ vietnam-cli patch
22
+ ```
23
+
24
+ ### Check patch status
25
+ ```bash
26
+ vietnam-cli check
27
+ ```
28
+
29
+ ### Patch specific tool
30
+ ```bash
31
+ vietnam-cli patch auggie # Patch only Auggie CLI
32
+ vietnam-cli patch claude # Patch only Claude Code
33
+ ```
34
+
35
+ ### Restore original files
36
+ ```bash
37
+ vietnam-cli restore
38
+ ```
39
+
40
+ ### Show help
41
+ ```bash
42
+ vietnam-cli help
43
+ ```
44
+
45
+ ## Supported Tools
46
+
47
+ | Tool | Package | Status |
48
+ |------|---------|--------|
49
+ | Auggie CLI | `@augmentcode/auggie` | ✅ Supported |
50
+ | Claude Code | `@anthropic-ai/claude-code` | ✅ Supported |
51
+
52
+ ## How It Works
53
+
54
+ The patch modifies the key parsing code in the CLI tools:
55
+
56
+ **Before (broken):**
57
+ ```javascript
58
+ else if(e==="\x7F"||e==="\x1B\x7F")n.name="delete"
59
+ ```
60
+
61
+ **After (fixed):**
62
+ ```javascript
63
+ else if(e==="\x7F"||e==="\x1B\x7F")n.name="backspace"
64
+ ```
65
+
66
+ This change makes the `\x7F` character behave as backspace, which is what Vietnamese IME expects.
67
+
68
+ ## Important Notes
69
+
70
+ ⚠️ **After updating the CLI tools** (e.g., `npm update -g @augmentcode/auggie`), you need to **re-apply the patch**:
71
+
72
+ ```bash
73
+ vietnam-cli patch
74
+ ```
75
+
76
+ ## Programmatic Usage
77
+
78
+ ```javascript
79
+ const { patch, check, restore } = require('vietnam-cli');
80
+
81
+ // Apply patch
82
+ await patch('auggie');
83
+
84
+ // Check status
85
+ await check('all');
86
+
87
+ // Restore original
88
+ await restore('auggie');
89
+ ```
90
+
91
+ ## License
92
+
93
+ MIT
94
+
95
+ ## Contributing
96
+
97
+ Issues and PRs are welcome at [GitHub](https://github.com/user/vietnam-cli).
98
+
package/bin/cli.js ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Vietnamese IME Patch CLI
5
+ * Fix Vietnamese input (Unikey/EVKey) for CLI tools
6
+ */
7
+
8
+ const { patch, check, restore, findTargets } = require('../src/index.js');
9
+
10
+ const args = process.argv.slice(2);
11
+ const command = args[0] || 'help';
12
+ const target = args[1] || 'all';
13
+
14
+ const HELP_TEXT = `
15
+ Vietnamese IME Patch - Fix Vietnamese input for CLI tools
16
+ ==========================================================
17
+
18
+ Usage: vietnam-cli <command> [target]
19
+
20
+ Commands:
21
+ patch [target] Apply Vietnamese IME fix (default: all)
22
+ check [target] Check if patch is applied
23
+ restore [target] Restore original files from backup
24
+ list List all supported targets and their status
25
+ help Show this help message
26
+
27
+ Targets:
28
+ all All supported CLI tools (default)
29
+ auggie Auggie CLI (@augmentcode/auggie)
30
+ claude Claude Code CLI (@anthropic-ai/claude-code)
31
+
32
+ Examples:
33
+ vietnam-cli patch # Patch all supported tools
34
+ vietnam-cli patch auggie # Patch only auggie-cli
35
+ vietnam-cli check # Check patch status
36
+ vietnam-cli restore auggie # Restore auggie to original
37
+
38
+ What this fixes:
39
+ Vietnamese IME (Unikey, EVKey, etc.) sends DEL character (\\x7F) to delete
40
+ the previous character before inserting accented characters. Some CLI tools
41
+ incorrectly treat \\x7F as "delete" (forward delete) instead of "backspace".
42
+ This patch fixes that behavior.
43
+
44
+ `;
45
+
46
+ async function main() {
47
+ switch (command) {
48
+ case 'patch':
49
+ console.log('🔧 Applying Vietnamese IME patch...\n');
50
+ await patch(target);
51
+ break;
52
+
53
+ case 'check':
54
+ console.log('🔍 Checking Vietnamese IME patch status...\n');
55
+ await check(target);
56
+ break;
57
+
58
+ case 'restore':
59
+ console.log('↩️ Restoring original files...\n');
60
+ await restore(target);
61
+ break;
62
+
63
+ case 'list':
64
+ console.log('📋 Supported targets:\n');
65
+ await findTargets();
66
+ break;
67
+
68
+ case 'help':
69
+ case '--help':
70
+ case '-h':
71
+ console.log(HELP_TEXT);
72
+ break;
73
+
74
+ default:
75
+ console.error(`Unknown command: ${command}`);
76
+ console.log(HELP_TEXT);
77
+ process.exit(1);
78
+ }
79
+ }
80
+
81
+ main().catch(err => {
82
+ console.error('Error:', err.message);
83
+ process.exit(1);
84
+ });
85
+
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "vietnam-cli",
3
+ "version": "1.0.0",
4
+ "description": "Fix Vietnamese IME input (Unikey/EVKey) for CLI tools like auggie-cli and claude-code",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "vietnam-cli": "bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "test": "node bin/cli.js check",
11
+ "patch": "node bin/cli.js patch",
12
+ "check": "node bin/cli.js check",
13
+ "restore": "node bin/cli.js restore",
14
+ "prepublishOnly": "node scripts/prepare-publish.js",
15
+ "postpublish": "node scripts/restore-readme.js"
16
+ },
17
+ "keywords": [
18
+ "vietnamese",
19
+ "ime",
20
+ "unikey",
21
+ "evkey",
22
+ "telex",
23
+ "vni",
24
+ "auggie",
25
+ "claude-code",
26
+ "input-method",
27
+ "keyboard",
28
+ "patch",
29
+ "fix",
30
+ "tieng-viet"
31
+ ],
32
+ "author": "",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/user/vietnam-cli.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/user/vietnam-cli/issues"
40
+ },
41
+ "homepage": "https://github.com/user/vietnam-cli#readme",
42
+ "engines": {
43
+ "node": ">=14.0.0"
44
+ },
45
+ "files": [
46
+ "bin/",
47
+ "src/",
48
+ "README.md",
49
+ "LICENSE"
50
+ ]
51
+ }
52
+
package/src/index.js ADDED
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Vietnamese IME Patch
3
+ * Fix Vietnamese input (Unikey/EVKey) for CLI tools
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { execSync } = require('child_process');
9
+
10
+ // Patch configurations for different CLI tools
11
+ const PATCH_CONFIGS = {
12
+ auggie: {
13
+ name: 'Auggie CLI',
14
+ package: '@augmentcode/auggie',
15
+ file: 'augment.mjs',
16
+ patterns: [
17
+ {
18
+ original: 'else if(e==="\\x7F"||e==="\\x1B\\x7F")n.name="delete"',
19
+ patched: 'else if(e==="\\x7F"||e==="\\x1B\\x7F")n.name="backspace"',
20
+ description: 'Map \\x7F to backspace instead of delete'
21
+ }
22
+ ]
23
+ },
24
+ claude: {
25
+ name: 'Claude Code CLI',
26
+ package: '@anthropic-ai/claude-code',
27
+ file: 'cli.mjs',
28
+ patterns: [
29
+ {
30
+ original: 'else if(e==="\\x7F"||e==="\\x1B\\x7F")n.name="delete"',
31
+ patched: 'else if(e==="\\x7F"||e==="\\x1B\\x7F")n.name="backspace"',
32
+ description: 'Map \\x7F to backspace instead of delete'
33
+ }
34
+ ]
35
+ }
36
+ };
37
+
38
+ /**
39
+ * Get npm global root path
40
+ */
41
+ function getNpmGlobalRoot() {
42
+ try {
43
+ return execSync('npm root -g', { encoding: 'utf8' }).trim();
44
+ } catch (e) {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Find installation path for a package
51
+ */
52
+ function findPackagePath(packageName, fileName) {
53
+ const possibleRoots = [
54
+ getNpmGlobalRoot(),
55
+ path.join(process.env.APPDATA || '', 'npm', 'node_modules'),
56
+ path.join(process.env.NVM_HOME || '', 'nodejs', 'node_modules'),
57
+ 'C:\\nvm4w\\nodejs\\node_modules',
58
+ '/usr/local/lib/node_modules',
59
+ '/usr/lib/node_modules',
60
+ path.join(process.env.HOME || '', '.nvm', 'versions', 'node', process.version, 'lib', 'node_modules'),
61
+ ].filter(Boolean);
62
+
63
+ for (const root of possibleRoots) {
64
+ const filePath = path.join(root, packageName, fileName);
65
+ if (fs.existsSync(filePath)) {
66
+ return filePath;
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+
72
+ /**
73
+ * Check patch status for a target
74
+ */
75
+ function checkPatchStatus(targetKey) {
76
+ const config = PATCH_CONFIGS[targetKey];
77
+ if (!config) {
78
+ return { found: false, error: `Unknown target: ${targetKey}` };
79
+ }
80
+
81
+ const filePath = findPackagePath(config.package, config.file);
82
+ if (!filePath) {
83
+ return { found: false, installed: false, name: config.name };
84
+ }
85
+
86
+ const content = fs.readFileSync(filePath, 'utf8');
87
+
88
+ for (const pattern of config.patterns) {
89
+ if (content.includes(pattern.patched)) {
90
+ return { found: true, installed: true, patched: true, path: filePath, name: config.name };
91
+ }
92
+ if (content.includes(pattern.original)) {
93
+ return { found: true, installed: true, patched: false, path: filePath, name: config.name };
94
+ }
95
+ }
96
+
97
+ return { found: true, installed: true, patched: 'unknown', path: filePath, name: config.name };
98
+ }
99
+
100
+ /**
101
+ * Apply patch to a target
102
+ */
103
+ function applyPatch(targetKey) {
104
+ const config = PATCH_CONFIGS[targetKey];
105
+ const status = checkPatchStatus(targetKey);
106
+
107
+ if (!status.installed) {
108
+ console.log(`⚠️ ${config.name}: Not installed`);
109
+ return false;
110
+ }
111
+
112
+ if (status.patched === true) {
113
+ console.log(`✅ ${config.name}: Already patched`);
114
+ return true;
115
+ }
116
+
117
+ let content = fs.readFileSync(status.path, 'utf8');
118
+
119
+ // Create backup
120
+ const backupPath = status.path + '.backup';
121
+ if (!fs.existsSync(backupPath)) {
122
+ fs.writeFileSync(backupPath, content);
123
+ console.log(`📦 Created backup: ${backupPath}`);
124
+ }
125
+
126
+ // Apply patches
127
+ let patchedCount = 0;
128
+ for (const pattern of config.patterns) {
129
+ if (content.includes(pattern.original)) {
130
+ content = content.replace(pattern.original, pattern.patched);
131
+ patchedCount++;
132
+ }
133
+ }
134
+
135
+ if (patchedCount > 0) {
136
+ fs.writeFileSync(status.path, content);
137
+ console.log(`✅ ${config.name}: Patched successfully (${patchedCount} changes)`);
138
+ return true;
139
+ } else {
140
+ console.log(`⚠️ ${config.name}: Could not find patterns to patch`);
141
+ return false;
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Restore original file from backup
147
+ */
148
+ function restoreBackup(targetKey) {
149
+ const config = PATCH_CONFIGS[targetKey];
150
+ const status = checkPatchStatus(targetKey);
151
+
152
+ if (!status.installed) {
153
+ console.log(`⚠️ ${config.name}: Not installed`);
154
+ return false;
155
+ }
156
+
157
+ const backupPath = status.path + '.backup';
158
+ if (fs.existsSync(backupPath)) {
159
+ fs.copyFileSync(backupPath, status.path);
160
+ console.log(`✅ ${config.name}: Restored from backup`);
161
+ return true;
162
+ } else {
163
+ console.log(`⚠️ ${config.name}: No backup found`);
164
+ return false;
165
+ }
166
+ }
167
+
168
+ // Export functions
169
+ module.exports = {
170
+ async patch(target = 'all') {
171
+ const targets = target === 'all' ? Object.keys(PATCH_CONFIGS) : [target];
172
+ for (const t of targets) {
173
+ applyPatch(t);
174
+ }
175
+ },
176
+
177
+ async check(target = 'all') {
178
+ const targets = target === 'all' ? Object.keys(PATCH_CONFIGS) : [target];
179
+ for (const t of targets) {
180
+ const status = checkPatchStatus(t);
181
+ if (!status.installed) {
182
+ console.log(`⬚ ${status.name}: Not installed`);
183
+ } else if (status.patched === true) {
184
+ console.log(`✅ ${status.name}: Patched`);
185
+ } else if (status.patched === false) {
186
+ console.log(`❌ ${status.name}: Not patched`);
187
+ } else {
188
+ console.log(`⚠️ ${status.name}: Unknown status`);
189
+ }
190
+ }
191
+ },
192
+
193
+ async restore(target = 'all') {
194
+ const targets = target === 'all' ? Object.keys(PATCH_CONFIGS) : [target];
195
+ for (const t of targets) {
196
+ restoreBackup(t);
197
+ }
198
+ },
199
+
200
+ async findTargets() {
201
+ for (const [key, config] of Object.entries(PATCH_CONFIGS)) {
202
+ const status = checkPatchStatus(key);
203
+ const statusIcon = !status.installed ? '⬚' : status.patched ? '✅' : '❌';
204
+ const statusText = !status.installed ? 'not installed' : status.patched ? 'patched' : 'not patched';
205
+ console.log(` ${statusIcon} ${key.padEnd(10)} ${config.name} (${statusText})`);
206
+ if (status.path) {
207
+ console.log(` Path: ${status.path}`);
208
+ }
209
+ }
210
+ },
211
+
212
+ PATCH_CONFIGS,
213
+ checkPatchStatus,
214
+ applyPatch,
215
+ restoreBackup,
216
+ findPackagePath
217
+ };
218
+