Skip to content

Commit d4aaa5a

Browse files
committed
doc
1 parent 990b482 commit d4aaa5a

File tree

4 files changed

+104
-4
lines changed

4 files changed

+104
-4
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@ jsq is a secure, jQuery/Lodash-style JSON processor with 110+ built-in methods,
1414
## ✨ Why jsq?
1515

1616
```bash
17-
# 🚀 20x faster with parallel processing
18-
cat huge.jsonl | jsq --parallel '$.filter(item => item.active)'
19-
2017
# 🔗 jQuery-style chaining with 110+ built-in methods
2118
cat data.json | jsq '$.users.filter(u => u.active).pluck("name").uniq()'
2219

2320
# 🎨 Beautiful interactive REPL with real-time evaluation
24-
jsq --repl --file data.json
21+
curl -H "Accept: application/json" https://api.example.com/data | jsq
2522

2623
# 🔒 Secure VM isolation by default
2724
cat sensitive.json | jsq '$.private' # Safe: No file/network access
2825

2926
# 📝 Intuitive variable declarations
3027
jsq "const names = ['Alice', 'Bob'] | names.map(n => n.toUpperCase())"
28+
29+
# 🚀 parallel processing
30+
cat huge.jsonl | jsq --parallel '$.filter(item => item.active)'
3131
```
3232

3333
## 🚀 Quick Start

src/core/repl/prompts/prompts-repl-manager.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
DefaultPromptsProvider,
4545
} from '../../../utils/default-providers.js';
4646
import { OutputFormatter } from '../../../utils/output-formatter.js';
47+
import { Pager } from '../../../utils/pager.js';
4748
import { AutocompleteEngine } from '../autocomplete-engine.js';
4849

4950
interface PromptsReplOptions {
@@ -589,6 +590,12 @@ export class PromptsReplManager implements ReplManagerInterface {
589590
}
590591
}
591592

593+
// Handle Ctrl+R for showing last result in pager
594+
if (key && key.ctrl && key.name === 'r') {
595+
await this.showLastResultInPager();
596+
return;
597+
}
598+
592599
if (!key || key.name === 'return' || key.name === 'tab' || key.ctrl || key.meta) {
593600
// Clear preview line on return key
594601
if (key && key.name === 'return') {
@@ -1136,4 +1143,45 @@ export class PromptsReplManager implements ReplManagerInterface {
11361143
// 保存に失敗しても続行
11371144
}
11381145
}
1146+
1147+
private async showLastResultInPager(): Promise<void> {
1148+
// 最後の評価結果がない場合は何もしない
1149+
if (this.lastResult === undefined) {
1150+
return;
1151+
}
1152+
1153+
// 現在の入力を保存
1154+
const savedLine = this.rl?.line || '';
1155+
const savedCursor = this.rl?.cursor || 0;
1156+
1157+
// 評価結果をフォーマット
1158+
const formattedResult = OutputFormatter.format(this.lastResult, {
1159+
isReplMode: false,
1160+
oneline: false,
1161+
noColor: false,
1162+
});
1163+
1164+
// 画面をクリア
1165+
this.console.log('\x1b[2J\x1b[H');
1166+
1167+
// Pagerで表示
1168+
const pager = new Pager(formattedResult);
1169+
await pager.show();
1170+
1171+
// REPLの画面を再描画
1172+
if (this.rl) {
1173+
// Clear screen and redraw
1174+
this.rl.write(null, { ctrl: true, name: 'l' });
1175+
this.rl.prompt();
1176+
// Restore the saved line
1177+
if (savedLine) {
1178+
this.rl.write(savedLine);
1179+
// Move cursor to the saved position
1180+
const moveBack = savedLine.length - savedCursor;
1181+
if (moveBack > 0) {
1182+
this.rl.write(null, { ctrl: true, name: 'b', sequence: '\x1b[D'.repeat(moveBack) });
1183+
}
1184+
}
1185+
}
1186+
}
11391187
}

src/core/repl/repl-manager.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { JsqOptions } from '@/types/cli';
33
import type { ReplIO, ReplOptions } from '@/types/repl';
44
import { type DebouncedFunction, debounce } from '@/utils/debounce';
55
import { OutputFormatter } from '@/utils/output-formatter';
6+
import { Pager } from '@/utils/pager';
67
import { AutocompleteEngine, type CompletionContext } from './autocomplete-engine';
78
import { StringBuffer } from './string-buffer';
89

@@ -238,6 +239,9 @@ export class ReplManager {
238239
case 'w':
239240
this.deleteWord();
240241
break;
242+
case 'r':
243+
await this.showLastResultInPager();
244+
break;
241245
}
242246
}
243247

@@ -967,4 +971,35 @@ export class ReplManager {
967971
this.io.output.write('\x1b[A');
968972
}
969973
}
974+
975+
private async showLastResultInPager(): Promise<void> {
976+
// 最後の評価結果がない場合は何もしない
977+
if (this.state.lastResult === undefined) {
978+
return;
979+
}
980+
981+
// 現在の入力を保存
982+
const savedInput = this.state.currentInput.toString();
983+
const savedCursorPosition = this.state.cursorPosition;
984+
985+
// 評価結果をフォーマット
986+
const formattedResult = OutputFormatter.format(this.state.lastResult, {
987+
...this.state.options,
988+
isReplMode: false,
989+
oneline: false,
990+
});
991+
992+
// 画面をクリア
993+
this.io.output.write('\x1b[2J\x1b[H');
994+
995+
// Pagerで表示
996+
const pager = new Pager(formattedResult);
997+
await pager.show();
998+
999+
// REPLの画面を再描画
1000+
this.io.output.clearLine(0);
1001+
this.io.output.cursorTo(0);
1002+
this.io.output.write(this.prompt + savedInput);
1003+
this.io.output.cursorTo(this.prompt.length + savedCursorPosition);
1004+
}
9701005
}

test-repl-pager.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
# Test script for REPL pager functionality
4+
5+
echo "Testing JSQ REPL Ctrl+R functionality..."
6+
echo ""
7+
echo "Instructions:"
8+
echo "1. Type an expression like: [1,2,3].map(x => x*2)"
9+
echo "2. Press Enter to evaluate"
10+
echo "3. Press Ctrl+R to view the result in pager mode"
11+
echo "4. Press 'q' to exit pager and return to REPL"
12+
echo "5. Press Ctrl+D to exit REPL"
13+
echo ""
14+
echo "Starting REPL..."
15+
16+
# Start REPL with some initial data
17+
echo '{"test": [1,2,3], "nested": {"value": 42}}' | node dist/index.js

0 commit comments

Comments
 (0)