Skip to content

Commit

Permalink
connui: accommodate multi-line 2fac prompts
Browse files Browse the repository at this point in the history
This fixes up the cursor position when the remote host sends
a multi-line prompt.
  • Loading branch information
wez committed Feb 3, 2020
1 parent 6fb4d61 commit 2489abf
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions src/connui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,33 @@ impl ConnectionUI {
self.output(vec![Change::Text(s)]);
}

/// Crack a multi-line prompt into an optional preamble and the prompt
/// text on the final line. This is needed because the line editor
/// is only designed for a single line prompt; a multi-line prompt
/// messes up the cursor positioning.
fn split_multi_line_prompt(s: &str) -> (Option<String>, String) {
let text = s.replace("\n", "\r\n");
let bits: Vec<&str> = text.rsplitn(2, "\r\n").collect();

if bits.len() == 2 {
(Some(format!("{}\r\n", bits[1])), bits[0].to_owned())
} else {
(None, text)
}
}

pub fn input(&self, prompt: &str) -> anyhow::Result<String> {
let mut promise = Promise::new();
let future = promise.get_future().unwrap();

let (preamble, prompt) = Self::split_multi_line_prompt(prompt);
if let Some(preamble) = preamble {
self.output(vec![Change::Text(preamble)]);
}

self.tx
.send(UIRequest::Input {
prompt: prompt.replace("\n", "\r\n"),
prompt,
echo: true,
respond: promise,
})
Expand All @@ -182,9 +202,14 @@ impl ConnectionUI {
let mut promise = Promise::new();
let future = promise.get_future().unwrap();

let (preamble, prompt) = Self::split_multi_line_prompt(prompt);
if let Some(preamble) = preamble {
self.output(vec![Change::Text(preamble)]);
}

self.tx
.send(UIRequest::Input {
prompt: prompt.replace("\n", "\r\n"),
prompt,
echo: false,
respond: promise,
})
Expand Down

0 comments on commit 2489abf

Please sign in to comment.