ep_vim 0.12.3 → 0.13.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/README.md CHANGED
@@ -19,7 +19,7 @@ A vim-mode plugin for [Etherpad](https://etherpad.org/). Adds modal editing with
19
19
  - **Line operations** — `dd`, `cc`, `yy`, `D`, `J` (join), `Y` (yank line)
20
20
  - **Registers** — `"a`–`"z` named registers for yank/delete/put, `"_` blackhole register
21
21
  - **Put** — `p` / `P` with linewise and characterwise register handling
22
- - **Editing** — `i` `a` `A` `I` (insert/append), `x`, `X`, `r`, `s`, `S`, `C`, `o`, `O`, `~` (toggle case)
22
+ - **Editing** — `i` `a` `A` `I` (insert/append), `x`, `X`, `r`, `R` (replace mode), `s`, `S`, `C`, `o`, `O`, `~` (toggle case)
23
23
  - **Marks** — `m{a-z}` to set, `'{a-z}` / `` `{a-z} `` to jump
24
24
  - **Search** — `/` and `?` forward/backward, `n`/`N` repeat, `*`/`#` search word under cursor
25
25
  - **Scrolling** — `zz`/`zt`/`zb` center/top/bottom, `Ctrl+d`/`Ctrl+u` half-page, `Ctrl+f`/`Ctrl+b` full-page (requires ctrl keys enabled)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ep_vim",
3
- "version": "0.12.3",
3
+ "version": "0.13.0",
4
4
  "description": "Vim-mode plugin for Etherpad with modal editing, motions, and operators",
5
5
  "author": {
6
6
  "name": "Seth Rothschild",
@@ -850,6 +850,12 @@ commands.normal["O"] = ({ editorInfo, line }) => {
850
850
  state.mode = "insert";
851
851
  };
852
852
 
853
+ commands.normal["R"] = ({ editorInfo, line, char }) => {
854
+ clearEmptyLineCursor();
855
+ moveCursor(editorInfo, line, char);
856
+ state.mode = "replace";
857
+ };
858
+
853
859
  // --- Editing commands ---
854
860
 
855
861
  commands.normal["r"] = () => {
@@ -1324,7 +1330,7 @@ exports.aceKeyEvent = (_hookName, { evt, rep, editorInfo }) => {
1324
1330
  const [vLine, vChar] = state.visualCursor;
1325
1331
  state.mode = "normal";
1326
1332
  moveBlockCursor(editorInfo, vLine, vChar);
1327
- } else if (state.mode === "insert") {
1333
+ } else if (state.mode === "insert" || state.mode === "replace") {
1328
1334
  state.mode = "normal";
1329
1335
  const [curLine, curChar] = rep.selStart;
1330
1336
  moveBlockCursor(editorInfo, curLine, Math.max(0, curChar - 1));
@@ -1342,6 +1348,40 @@ exports.aceKeyEvent = (_hookName, { evt, rep, editorInfo }) => {
1342
1348
 
1343
1349
  if (state.mode === "insert") return false;
1344
1350
 
1351
+ if (state.mode === "replace") {
1352
+ if (evt.key === "Backspace") {
1353
+ const [curLine, curChar] = rep.selStart;
1354
+ if (curChar > 0) {
1355
+ moveCursor(editorInfo, curLine, curChar - 1);
1356
+ }
1357
+ evt.preventDefault();
1358
+ return true;
1359
+ }
1360
+ if (evt.key.length === 1 && !evt.ctrlKey && !evt.metaKey) {
1361
+ const [curLine, curChar] = rep.selStart;
1362
+ const curLineText = rep.lines.atIndex(curLine).text;
1363
+ if (curChar < curLineText.length) {
1364
+ replaceRange(
1365
+ editorInfo,
1366
+ [curLine, curChar],
1367
+ [curLine, curChar + 1],
1368
+ evt.key,
1369
+ );
1370
+ } else {
1371
+ replaceRange(
1372
+ editorInfo,
1373
+ [curLine, curChar],
1374
+ [curLine, curChar],
1375
+ evt.key,
1376
+ );
1377
+ }
1378
+ moveCursor(editorInfo, curLine, curChar + 1);
1379
+ evt.preventDefault();
1380
+ return true;
1381
+ }
1382
+ return false;
1383
+ }
1384
+
1345
1385
  if (state.searchMode) {
1346
1386
  if (evt.key === "Enter") {
1347
1387
  state.searchMode = false;
@@ -184,8 +184,8 @@ describe("visual mode", () => {
184
184
  commands.normal["V"](ctx);
185
185
 
186
186
  assert.equal(state.mode, "visual-line");
187
- assert.deepEqual(state.visualAnchor, [0, 0]);
188
- assert.deepEqual(state.visualCursor, [0, 0]);
187
+ assert.deepEqual(state.visualAnchor, [0, 2]);
188
+ assert.deepEqual(state.visualCursor, [0, 2]);
189
189
  });
190
190
 
191
191
  it("y in visual-line yanks lines", () => {