Skip to content

Commit 39554e7

Browse files
committed
refactor: remove archive mode
1 parent 75cc332 commit 39554e7

4 files changed

Lines changed: 105 additions & 175 deletions

File tree

README.md

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ Interactive grep
2828
and it is possible to switch to a mode
2929
where you can grep through these N entries
3030
based on key inputs at any given moment.
31-
- Additionally, by starting in this mode,
32-
it is also possible to grep through static data such as files.
31+
- For static data such as files, *sig* automatically switches
32+
to archived mode when the input reaches EOF.
3333
- like [ugrep](https://github.com/Genivia/ugrep) with `-Q` option.
3434

3535
## Installation
@@ -76,7 +76,7 @@ nix shell github:ynqa/sig
7676

7777
Or run it directly:
7878
```nix
79-
cat README.md | nix run github:ynqa/sig -- --archived
79+
cat README.md | nix run github:ynqa/sig
8080
```
8181

8282
### Nix (classic)
@@ -109,12 +109,9 @@ stern --context kind-kind etcd |& sig
109109
sig --cmd "stern --context kind-kind etcd" # this is able to retry command by ctrl+r.
110110
```
111111

112-
### Archived mode
113-
112+
Static input (switches to archived view after EOF):
114113
```bash
115-
cat README.md |& sig -a
116-
# or
117-
sig -a --cmd "cat README.md"
114+
cat README.md |& sig
118115
```
119116

120117
## Keymap
@@ -156,10 +153,8 @@ $ stern --context kind-kind etcd |& sig
156153
Or the method to retry command by pressing ctrl+r:
157154
$ sig --cmd "stern --context kind-kind etcd"
158155

159-
Archived mode:
160-
$ cat README.md |& sig -a
161-
Or
162-
$ sig -a --cmd "cat README.md"
156+
Static input (switches to archived view after EOF):
157+
$ cat README.md |& sig
163158

164159
Options:
165160
--retrieval-timeout <RETRIEVAL_TIMEOUT_MILLIS>
@@ -168,8 +163,6 @@ Options:
168163
Interval to render a line in milliseconds.
169164
-q, --queue-capacity <QUEUE_CAPACITY>
170165
Queue capacity to store lines. [default: 1000]
171-
-a, --archived
172-
Archived mode to grep through static data.
173166
-i, --ignore-case
174167
Case insensitive search.
175168
--cmd <CMD>

src/main.rs

Lines changed: 66 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
use std::{collections::VecDeque, io};
1+
use std::io;
22

33
use clap::Parser;
4-
use tokio::{
5-
sync::mpsc,
6-
time::{timeout, Duration},
7-
};
4+
use tokio::time::Duration;
85

96
use promkit_core::crossterm::{
107
self, cursor,
@@ -47,10 +44,8 @@ $ stern --context kind-kind etcd |& sig
4744
Or the method to retry command by pressing ctrl+r:
4845
$ sig --cmd \"stern --context kind-kind etcd\"
4946
50-
Archived mode:
51-
$ cat README.md |& sig -a
52-
Or
53-
$ sig -a --cmd \"cat README.md\"
47+
Static input (switches to archived view after EOF):
48+
$ cat README.md |& sig
5449
5550
Options:
5651
{options}
@@ -86,14 +81,6 @@ pub struct Args {
8681
)]
8782
pub queue_capacity: usize,
8883

89-
#[arg(
90-
short = 'a',
91-
long = "archived",
92-
default_value = "false",
93-
help = "Archived mode to grep through static data."
94-
)]
95-
pub archived: bool,
96-
9784
#[arg(
9885
short = 'i',
9986
long = "ignore-case",
@@ -139,149 +126,78 @@ async fn main() -> anyhow::Result<()> {
139126
..Default::default()
140127
};
141128

142-
if args.archived {
143-
let (tx, mut rx) = mpsc::channel(1);
144-
145-
let input_task = match &args.cmd {
146-
Some(cmd) => spawn::spawn_cmd_result_sender(
147-
cmd,
148-
tx,
149-
Duration::from_millis(args.retrieval_timeout_millis),
150-
),
151-
None => {
152-
spawn::spawn_stdin_sender(tx, Duration::from_millis(args.retrieval_timeout_millis))
153-
}
154-
}?;
155-
156-
let mut queue = VecDeque::with_capacity(args.queue_capacity);
157-
loop {
158-
match timeout(
159-
Duration::from_millis(args.retrieval_timeout_millis),
160-
rx.recv(),
161-
)
162-
.await
163-
{
164-
Ok(Some(line)) => {
165-
if queue.len() > args.queue_capacity {
166-
queue.pop_front().unwrap();
167-
}
168-
queue.push_back(line.clone());
169-
}
170-
Ok(None) => break,
171-
Err(_) => break,
172-
}
173-
}
174-
175-
// Stop the input task
176-
input_task.handle.abort();
177-
129+
while let Ok((signal, queue)) = sig::run(
130+
text_editor::State {
131+
texteditor: TextEditor::new(args.query.clone().unwrap_or_default()),
132+
prefix: String::from("❯❯ "),
133+
prefix_style: ContentStyle {
134+
foreground_color: Some(Color::DarkGreen),
135+
..Default::default()
136+
},
137+
active_char_style: ContentStyle {
138+
background_color: Some(Color::DarkCyan),
139+
..Default::default()
140+
},
141+
..Default::default()
142+
},
143+
highlight_style,
144+
Duration::from_millis(args.retrieval_timeout_millis),
145+
args.render_interval_millis.map(Duration::from_millis),
146+
args.queue_capacity,
147+
args.case_insensitive,
148+
args.cmd.clone(),
149+
)
150+
.await
151+
{
178152
crossterm::execute!(
179153
io::stdout(),
180154
crossterm::terminal::Clear(crossterm::terminal::ClearType::All),
181155
cursor::MoveTo(0, 0),
182156
)?;
183157

184-
archived::run(
185-
text_editor::State {
186-
texteditor: TextEditor::new(args.query.clone().unwrap_or_default()),
187-
prefix: String::from("❯❯❯ "),
188-
prefix_style: ContentStyle {
189-
foreground_color: Some(Color::DarkBlue),
190-
..Default::default()
191-
},
192-
active_char_style: ContentStyle {
193-
background_color: Some(Color::DarkCyan),
194-
..Default::default()
195-
},
196-
..Default::default()
197-
},
198-
listbox::State {
199-
listbox: listbox::Listbox::from_displayable(queue),
200-
cursor: String::from("❯ "),
201-
active_item_style: None,
202-
inactive_item_style: None,
203-
lines: Default::default(),
204-
},
205-
highlight_style,
206-
args.case_insensitive,
207-
// In archived mode, command for retry is meaningless.
208-
None,
209-
)
210-
.await?;
211-
} else {
212-
while let Ok((signal, queue)) = sig::run(
213-
text_editor::State {
214-
texteditor: TextEditor::new(args.query.clone().unwrap_or_default()),
215-
prefix: String::from("❯❯ "),
216-
prefix_style: ContentStyle {
217-
foreground_color: Some(Color::DarkGreen),
218-
..Default::default()
219-
},
220-
active_char_style: ContentStyle {
221-
background_color: Some(Color::DarkCyan),
222-
..Default::default()
223-
},
224-
..Default::default()
225-
},
226-
highlight_style,
227-
Duration::from_millis(args.retrieval_timeout_millis),
228-
args.render_interval_millis.map(Duration::from_millis),
229-
args.queue_capacity,
230-
args.case_insensitive,
231-
args.cmd.clone(),
232-
)
233-
.await
234-
{
235-
crossterm::execute!(
236-
io::stdout(),
237-
crossterm::terminal::Clear(crossterm::terminal::ClearType::All),
238-
cursor::MoveTo(0, 0),
239-
)?;
240-
241-
match signal {
242-
Signal::GotoArchived => {
243-
archived::run(
244-
text_editor::State {
245-
prefix: String::from("❯❯❯ "),
246-
prefix_style: ContentStyle {
247-
foreground_color: Some(Color::DarkBlue),
248-
..Default::default()
249-
},
250-
active_char_style: ContentStyle {
251-
background_color: Some(Color::DarkCyan),
252-
..Default::default()
253-
},
158+
match signal {
159+
Signal::GotoArchived => {
160+
archived::run(
161+
text_editor::State {
162+
prefix: String::from("❯❯❯ "),
163+
prefix_style: ContentStyle {
164+
foreground_color: Some(Color::DarkBlue),
254165
..Default::default()
255166
},
256-
listbox::State {
257-
listbox: listbox::Listbox::from_displayable(queue),
258-
cursor: String::from("❯ "),
259-
active_item_style: None,
260-
inactive_item_style: None,
261-
lines: Default::default(),
167+
active_char_style: ContentStyle {
168+
background_color: Some(Color::DarkCyan),
169+
..Default::default()
262170
},
263-
highlight_style,
264-
args.case_insensitive,
265-
args.cmd.clone(),
266-
)
267-
.await?;
268-
269-
// Re-enable raw mode and hide the cursor again here
270-
// because they are disabled and shown, respectively, by promkit.
271-
enable_raw_mode()?;
272-
execute!(io::stdout(), EnableMouseCapture, cursor::Hide)?;
273-
274-
crossterm::execute!(
275-
io::stdout(),
276-
crossterm::terminal::Clear(crossterm::terminal::ClearType::All),
277-
cursor::MoveTo(0, 0),
278-
)?;
279-
}
280-
Signal::GotoStreaming => {
281-
continue;
282-
}
283-
_ => {}
171+
..Default::default()
172+
},
173+
listbox::State {
174+
listbox: listbox::Listbox::from_displayable(queue),
175+
cursor: String::from("❯ "),
176+
active_item_style: None,
177+
inactive_item_style: None,
178+
lines: Default::default(),
179+
},
180+
highlight_style,
181+
args.case_insensitive,
182+
args.cmd.clone(),
183+
)
184+
.await?;
185+
186+
// Re-enable raw mode and hide the cursor again here
187+
// because they are disabled and shown, respectively, by promkit.
188+
enable_raw_mode()?;
189+
execute!(io::stdout(), EnableMouseCapture, cursor::Hide)?;
190+
191+
crossterm::execute!(
192+
io::stdout(),
193+
crossterm::terminal::Clear(crossterm::terminal::ClearType::All),
194+
cursor::MoveTo(0, 0),
195+
)?;
196+
}
197+
Signal::GotoStreaming => {
198+
continue;
284199
}
200+
_ => {}
285201
}
286202
}
287203

src/sig.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,21 +183,29 @@ pub async fn run(
183183
Ok(queue)
184184
});
185185

186-
let mut signal: Signal;
187-
loop {
186+
let signal = loop {
187+
// Treat an exhausted input source as archived data.
188+
if keeping.is_finished() {
189+
break Signal::GotoArchived;
190+
}
191+
192+
if !event::poll(retrieval_timeout)? {
193+
continue;
194+
}
195+
188196
let event = event::read()?;
189197
let mut text_editor = shared_text_editor.write().await;
190-
signal = evaluate_event(&event, &mut text_editor, cmd.clone())?;
198+
let signal = evaluate_event(&event, &mut text_editor, cmd.clone())?;
191199
if signal == Signal::GotoArchived || signal == Signal::GotoStreaming {
192-
break;
200+
break signal;
193201
}
194202

195203
let size = crossterm::terminal::size()?;
196204
let pane = text_editor.create_pane(size.0, size.1);
197205
let mut term = shared_term.write().await;
198206
term.sync_layout(size, Terminal::pane_rows(size, &pane))?;
199207
term.draw_pane(&pane)?;
200-
}
208+
};
201209

202210
if let Some(mut child) = input_task.child {
203211
let _ = child.kill().await;

src/spawn.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,30 +70,43 @@ pub fn spawn_cmd_result_sender(
7070

7171
Ok(InputTask {
7272
handle: tokio::spawn(async move {
73+
let mut stdout_closed = false;
74+
let mut stderr_closed = false;
75+
7376
loop {
77+
if stdout_closed && stderr_closed {
78+
break;
79+
}
80+
7481
tokio::select! {
75-
stdout_res = timeout(retrieval_timeout, stdout_reader.next_line()) => {
82+
stdout_res = timeout(retrieval_timeout, stdout_reader.next_line()), if !stdout_closed => {
7683
match stdout_res {
7784
Ok(Ok(Some(line))) => {
7885
let escaped = strip_ansi_escapes::strip_str(line.replace(['\n', '\t'], " "));
7986
tx.send(escaped).await?;
8087
},
81-
// Don't break on stdout end, continue to read stderr (maybe)
82-
_ => continue,
88+
Ok(Ok(None)) => stdout_closed = true,
89+
Ok(Err(err)) => return Err(err.into()),
90+
// ignore timeout and continue
91+
Err(_) => continue,
8392
}
8493
},
85-
stderr_res = timeout(retrieval_timeout, stderr_reader.next_line()) => {
94+
stderr_res = timeout(retrieval_timeout, stderr_reader.next_line()), if !stderr_closed => {
8695
match stderr_res {
8796
Ok(Ok(Some(line))) => {
8897
let escaped = strip_ansi_escapes::strip_str(line.replace(['\n', '\t'], " "));
8998
tx.send(escaped).await?;
9099
},
91-
// Don't break on stdout end, continue to read stdout (maybe)
92-
_ => continue,
100+
Ok(Ok(None)) => stderr_closed = true,
101+
Ok(Err(err)) => return Err(err.into()),
102+
// ignore timeout and continue
103+
Err(_) => continue,
93104
}
94105
}
95106
}
96107
}
108+
109+
Ok(())
97110
}),
98111
child: Some(child),
99112
})

0 commit comments

Comments
 (0)