cliedit 0.1.0 → 0.1.2

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.
@@ -0,0 +1,21 @@
1
+ # Acknowledgements & Copyright (ACKNOWLEDGEMENTS)
2
+
3
+ `cliedit` is an open-source project that utilizes components (or modified/converted versions thereof) from other open-source projects. We express our deep gratitude to the communities and authors who provided the foundation for these components.
4
+
5
+ All components listed below are included as vendored code (integrated directly into the project source code) and have been adapted to fit **cliedit**'s TypeScript architecture and remove unnecessary features (e.g., mouse support).
6
+
7
+ ## Vendored Components List
8
+
9
+ **Original Project Name: `keypress`**
10
+
11
+ **Description & Origin:** Provides raw key event parsing logic for the TTY environment. The source code was converted from the original JavaScript version and optimized for Node.js.
12
+
13
+ **Repository:** https://github.com/TooTallNate/keypress
14
+
15
+ **License:** MIT
16
+
17
+ **Copyright Notes:**
18
+
19
+ - `keypress` was originally authored by **Nathan Rajlich** (tootallnate.net).
20
+ - Copyright (c) 2012 Nathan Rajlich.
21
+ - The module is based on the keypress logic found within the Node.js Core `readline` module.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 CodeTease
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.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CodeTease
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.
package/README.md CHANGED
@@ -1,88 +1,92 @@
1
- # cliedit
2
-
3
- A lightweight, zero-dependency (other than `keypress`), raw-mode terminal editor component for Node.js.
4
-
5
- `cliedit` is designed to be imported into your own CLI application to provide a full-featured, TTY-based text editing experience. It's perfect for applications that need to ask the user for multi-line input, edit configuration files, or write commit messages.
6
-
7
- It includes line wrapping, visual navigation, undo/redo, text selection, and clipboard support.
8
-
9
- ## Features
10
-
11
- - **Raw Mode TTY:** Takes over the terminal for a full "app-like" feel.
12
- - **Visual Line Wrapping:** Text wraps to fit the terminal width.
13
- - **Visual Navigation:** `Up`/`Down` arrows move by visual rows, not logical lines.
14
- - **Undo/Redo:** `Ctrl+Z` / `Ctrl+Y` for persistent history.
15
- - **Text Selection:** `Ctrl+Arrow` keys to select text.
16
- - **Clipboard Support:** `Ctrl+C` (Copy), `Ctrl+X` (Cut), `Ctrl+V` (Paste) for system clipboard (macOS/Windows).
17
- - **File I/O:** Loads from and saves to the filesystem.
18
- - **Search:** `Ctrl+W` to find text.
19
-
20
- ## Installation
21
- ```bash
22
- npm install cliedit
23
- ```
24
-
25
- ## Usage
26
-
27
- The package exports an `async` function `openEditor` that returns a `Promise`. The promise resolves when the user quits the editor.
28
- ```javascript
29
- import { openEditor } from 'cliedit';
30
- import path from 'path';
31
-
32
- async function getCommitMessage() {
33
- const tempFile = path.resolve(process.cwd(), 'COMMIT_MSG.txt');
34
- console.log('Opening editor for commit message...');
35
-
36
- try {
37
- const result = await openEditor(tempFile);
38
-
39
- // Give the terminal a moment to restore
40
- await new Promise(res => setTimeout(res, 50));
41
-
42
- if (result.saved) {
43
- console.log('Message saved!');
44
- console.log('---------------------');
45
- console.log(result.content);
46
- console.log('---------------------');
47
- } else {
48
- console.log('Editor quit without saving.');
49
- }
50
- } catch (err) {
51
- console.error('Editor failed to start:', err);
52
- }
53
- }
54
-
55
- getCommitMessage();
56
- ```
57
-
58
- ## Public API
59
-
60
- `openEditor(filepath: string)`
61
-
62
- Opens the editor for the specified file. If the file doesn't exist, it will be created upon saving.
63
- - **Returns:** `Promise<{ saved: boolean; content: string }>`
64
- * `saved`: `true` if the user saved (Ctrl+S), `false` otherwise (Ctrl+Q).
65
- * `content`: The final content of the file as a string.
66
-
67
- `CliEditor`
68
-
69
- The main editor class. You can import this directly if you need to extend or instantiate the editor with custom logic.
70
- ```javascript
71
- import { CliEditor } from 'cliedit';
72
- ```
73
-
74
- ### Types
75
-
76
- Key types are also exported for convenience:
77
- ```javascript
78
- import type {
79
- DocumentState,
80
- VisualRow,
81
- EditorMode,
82
- NormalizedRange,
83
- } from 'cliedit';
84
- ```
85
-
86
- ## License
87
-
1
+ # cliedit
2
+
3
+ A lightweight, zero-dependency, raw-mode terminal editor component for Node.js.
4
+
5
+ `cliedit` is designed to be imported into your own CLI application to provide a full-featured, TTY-based text editing experience. It's perfect for applications that need to ask the user for multi-line input, edit configuration files, or write commit messages.
6
+
7
+ It includes line wrapping, visual navigation, undo/redo, text selection, and clipboard support.
8
+
9
+ ## Features
10
+
11
+ - **Raw Mode TTY:** Takes over the terminal for a full "app-like" feel.
12
+ - **Visual Line Wrapping:** Text wraps to fit the terminal width.
13
+ - **Visual Navigation:** `Up`/`Down` arrows move by visual rows, not logical lines.
14
+ - **Undo/Redo:** `Ctrl+Z` / `Ctrl+Y` for persistent history.
15
+ - **Text Selection:** `Ctrl+Arrow` keys to select text.
16
+ - **Clipboard Support:** `Ctrl+C` (Copy), `Ctrl+X` (Cut), `Ctrl+V` (Paste) for system clipboard (macOS/Windows).
17
+ - **File I/O:** Loads from and saves to the filesystem.
18
+ - **Search:** `Ctrl+W` to find text.
19
+
20
+ ## Installation
21
+ ```bash
22
+ npm install cliedit
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ The package exports an `async` function `openEditor` that returns a `Promise`. The promise resolves when the user quits the editor.
28
+ ```javascript
29
+ import { openEditor } from 'cliedit';
30
+ import path from 'path';
31
+
32
+ async function getCommitMessage() {
33
+ const tempFile = path.resolve(process.cwd(), 'COMMIT_MSG.txt');
34
+ console.log('Opening editor for commit message...');
35
+
36
+ try {
37
+ const result = await openEditor(tempFile);
38
+
39
+ // Give the terminal a moment to restore
40
+ await new Promise(res => setTimeout(res, 50));
41
+
42
+ if (result.saved) {
43
+ console.log('Message saved!');
44
+ console.log('---------------------');
45
+ console.log(result.content);
46
+ console.log('---------------------');
47
+ } else {
48
+ console.log('Editor quit without saving.');
49
+ }
50
+ } catch (err) {
51
+ console.error('Editor failed to start:', err);
52
+ }
53
+ }
54
+
55
+ getCommitMessage();
56
+ ```
57
+
58
+ ## Public API
59
+
60
+ `openEditor(filepath: string)`
61
+
62
+ Opens the editor for the specified file. If the file doesn't exist, it will be created upon saving.
63
+ - **Returns:** `Promise<{ saved: boolean; content: string }>`
64
+ * `saved`: `true` if the user saved (Ctrl+S), `false` otherwise (Ctrl+Q).
65
+ * `content`: The final content of the file as a string.
66
+
67
+ `CliEditor`
68
+
69
+ The main editor class. You can import this directly if you need to extend or instantiate the editor with custom logic.
70
+ ```javascript
71
+ import { CliEditor } from 'cliedit';
72
+ ```
73
+
74
+ ### Types
75
+
76
+ Key types are also exported for convenience:
77
+ ```javascript
78
+ import type {
79
+ DocumentState,
80
+ VisualRow,
81
+ EditorMode,
82
+ NormalizedRange,
83
+ } from 'cliedit';
84
+ ```
85
+
86
+ ## Acknowledgements
87
+
88
+ Please see the [ACKNOWLEDGEMENTS.md](ACKNOWLEDGEMENTS.md) file for important copyright information regarding the vendored `keypress` component.
89
+
90
+ ## License
91
+
88
92
  [MIT](LICENSE)
@@ -20,7 +20,9 @@ export declare const KEYS: {
20
20
  CTRL_Q: string;
21
21
  CTRL_S: string;
22
22
  CTRL_W: string;
23
+ CTRL_R: string;
23
24
  CTRL_G: string;
25
+ CTRL_L: string;
24
26
  CTRL_Z: string;
25
27
  CTRL_Y: string;
26
28
  CTRL_K: string;
package/dist/constants.js CHANGED
@@ -22,7 +22,9 @@ export const KEYS = {
22
22
  CTRL_Q: '\x11', // Quit
23
23
  CTRL_S: '\x13', // Save
24
24
  CTRL_W: '\x17', // Find (Where is)
25
+ CTRL_R: '\x12', // Replace
25
26
  CTRL_G: '\x07', // Go to next
27
+ CTRL_L: '\x0c', // Go to Line (L)
26
28
  CTRL_Z: '\x1a', // Undo
27
29
  CTRL_Y: '\x19', // Redo
28
30
  CTRL_K: '\x0b', // Cut/Kill line
@@ -15,8 +15,11 @@ function setClipboard(text) {
15
15
  case 'win32':
16
16
  command = 'clip';
17
17
  break;
18
+ case 'linux': // <--- THÊM HỖ TRỢ LINUX
19
+ command = 'xclip -selection clipboard';
20
+ break;
18
21
  default:
19
- this.setStatusMessage('Clipboard only supported on macOS/Windows for now');
22
+ this.setStatusMessage('Clipboard not supported on this platform');
20
23
  return resolve();
21
24
  }
22
25
  const process = exec(command, (error) => {
@@ -43,8 +46,11 @@ function getClipboard() {
43
46
  case 'win32':
44
47
  command = 'powershell -command "Get-Clipboard"';
45
48
  break;
49
+ case 'linux': // <--- THÊM HỖ TRỢ LINUX
50
+ command = 'xclip -selection clipboard -o'; // -o (hoặc -out) để đọc
51
+ break;
46
52
  default:
47
- this.setStatusMessage('Clipboard only supported on macOS/Windows for now');
53
+ this.setStatusMessage('Clipboard not supported on this platform');
48
54
  return resolve('');
49
55
  }
50
56
  exec(command, (error, stdout) => {
package/dist/editor.d.ts CHANGED
@@ -1,14 +1,5 @@
1
1
  import { HistoryManager } from './history.js';
2
2
  import { VisualRow, EditorMode } from './types.js';
3
- declare module 'keypress' {
4
- interface KeypressEvent {
5
- name?: string;
6
- ctrl: boolean;
7
- meta: boolean;
8
- shift: boolean;
9
- sequence: string;
10
- }
11
- }
12
3
  import { editingMethods } from './editor.editing.js';
13
4
  import { clipboardMethods } from './editor.clipboard.js';
14
5
  import { navigationMethods } from './editor.navigation.js';
@@ -51,8 +42,10 @@ export declare class CliEditor {
51
42
  statusTimeout: NodeJS.Timeout | null;
52
43
  isMessageCustom: boolean;
53
44
  quitConfirm: boolean;
54
- readonly DEFAULT_STATUS = "HELP: Ctrl+S = Save & Quit | Ctrl+Q = Quit | Ctrl+C = Copy All | Ctrl+Arrow = Select";
45
+ readonly DEFAULT_STATUS = "HELP: Ctrl+S = Save | Ctrl+Q = Quit | Ctrl+W = Find | Ctrl+R = Replace | Ctrl+L = Go to Line";
55
46
  searchQuery: string;
47
+ replaceQuery: string | null;
48
+ goToLineQuery: string;
56
49
  searchResults: {
57
50
  y: number;
58
51
  x: number;
@@ -18,6 +18,7 @@ declare function insertCharacter(this: CliEditor, char: string): void;
18
18
  declare function insertSoftTab(this: CliEditor): void;
19
19
  /**
20
20
  * Inserts a new line, splitting the current line at the cursor position.
21
+ * Implements auto-indent.
21
22
  */
22
23
  declare function insertNewLine(this: CliEditor): void;
23
24
  /**
@@ -51,14 +51,19 @@ function insertSoftTab() {
51
51
  }
52
52
  /**
53
53
  * Inserts a new line, splitting the current line at the cursor position.
54
+ * Implements auto-indent.
54
55
  */
55
56
  function insertNewLine() {
56
57
  const line = this.lines[this.cursorY] || '';
58
+ // Find indentation of the current line
59
+ const match = line.match(/^(\s*)/);
60
+ const indent = match ? match[1] : '';
57
61
  const remainder = line.slice(this.cursorX);
58
62
  this.lines[this.cursorY] = line.slice(0, this.cursorX);
59
- this.lines.splice(this.cursorY + 1, 0, remainder);
63
+ // Add new line with the same indentation + remainder
64
+ this.lines.splice(this.cursorY + 1, 0, indent + remainder);
60
65
  this.cursorY++;
61
- this.cursorX = 0;
66
+ this.cursorX = indent.length; // Move cursor to end of indent
62
67
  this.setDirty();
63
68
  }
64
69
  /**
package/dist/editor.js CHANGED
@@ -1,6 +1,8 @@
1
- import keypress from 'keypress';
1
+ // Cập nhật 1: Import từ ./vendor/keypress.js
2
+ import keypress from './vendor/keypress.js';
2
3
  import { ANSI } from './constants.js';
3
4
  import { HistoryManager } from './history.js';
5
+ // Block `declare module 'keypress'` đã bị xóa
4
6
  // Import all functional modules
5
7
  import { editingMethods } from './editor.editing.js';
6
8
  import { clipboardMethods } from './editor.clipboard.js';
@@ -11,7 +13,7 @@ import { historyMethods } from './editor.history.js';
11
13
  import { ioMethods } from './editor.io.js';
12
14
  import { keyHandlingMethods } from './editor.keys.js';
13
15
  import { selectionMethods } from './editor.selection.js';
14
- const DEFAULT_STATUS = 'HELP: Ctrl+S = Save & Quit | Ctrl+Q = Quit | Ctrl+C = Copy All | Ctrl+Arrow = Select';
16
+ const DEFAULT_STATUS = 'HELP: Ctrl+S = Save | Ctrl+Q = Quit | Ctrl+W = Find | Ctrl+R = Replace | Ctrl+L = Go to Line';
15
17
  /**
16
18
  * Main editor class managing application state, TTY interaction, and rendering.
17
19
  */
@@ -34,6 +36,8 @@ export class CliEditor {
34
36
  this.quitConfirm = false;
35
37
  this.DEFAULT_STATUS = DEFAULT_STATUS;
36
38
  this.searchQuery = '';
39
+ this.replaceQuery = null; // null = Find mode, string = Replace mode
40
+ this.goToLineQuery = ''; // For Go to Line prompt
37
41
  this.searchResults = [];
38
42
  this.searchResultIndex = -1;
39
43
  this.isCleanedUp = false;
@@ -1,17 +1,10 @@
1
- import type { KeypressEvent } from 'keypress';
2
- declare module 'keypress' {
3
- interface KeypressEvent {
4
- name?: string;
5
- ctrl: boolean;
6
- meta: boolean;
7
- shift: boolean;
8
- sequence: string;
9
- }
10
- }
1
+ import type { KeypressEvent } from './vendor/keypress.js';
11
2
  export type TKeyHandlingMethods = {
12
3
  handleKeypressEvent: (ch: string, key: KeypressEvent) => void;
13
4
  handleEditKeys: (key: string) => boolean;
14
5
  handleSearchKeys: (key: string) => void;
6
+ handleSearchConfirmKeys: (key: string) => void;
7
+ handleGoToLineKeys: (key: string) => void;
15
8
  handleCtrlQ: () => void;
16
9
  handleCopy: () => Promise<void>;
17
10
  handleCharacterKey: (ch: string) => void;