Skip to content
Snippets Groups Projects
Commit 213eff2c authored by gwenn's avatar gwenn
Browse files

Introduce State.output_handle field on windows.

It seems that we need both (out and output_handle)
parent 200afea8
No related branches found
No related tags found
No related merge requests found
...@@ -66,6 +66,8 @@ struct State<'out, 'prompt> { ...@@ -66,6 +66,8 @@ struct State<'out, 'prompt> {
cols: usize, // Number of columns in terminal cols: usize, // Number of columns in terminal
history_index: usize, // The history index we are currently editing. history_index: usize, // The history index we are currently editing.
snapshot: LineBuffer, // Current edited line before history browsing/completion snapshot: LineBuffer, // Current edited line before history browsing/completion
#[cfg(windows)]
output_handle: winapi::HANDLE,
} }
#[derive(Copy, Clone, Debug, Default)] #[derive(Copy, Clone, Debug, Default)]
...@@ -75,14 +77,15 @@ struct Position { ...@@ -75,14 +77,15 @@ struct Position {
} }
impl<'out, 'prompt> State<'out, 'prompt> { impl<'out, 'prompt> State<'out, 'prompt> {
#[cfg(unix)]
fn new(out: &'out mut Write, fn new(out: &'out mut Write,
prompt: &'prompt str, prompt: &'prompt str,
capacity: usize,
cols: usize,
history_index: usize) history_index: usize)
-> State<'out, 'prompt> { -> Result<State<'out, 'prompt>> {
let capacity = MAX_LINE;
let cols = get_columns();
let prompt_size = calculate_position(prompt, Default::default(), cols); let prompt_size = calculate_position(prompt, Default::default(), cols);
State { let state = State {
out: out, out: out,
prompt: prompt, prompt: prompt,
prompt_size: prompt_size, prompt_size: prompt_size,
...@@ -91,7 +94,30 @@ impl<'out, 'prompt> State<'out, 'prompt> { ...@@ -91,7 +94,30 @@ impl<'out, 'prompt> State<'out, 'prompt> {
cols: cols, cols: cols,
history_index: history_index, history_index: history_index,
snapshot: LineBuffer::with_capacity(capacity), snapshot: LineBuffer::with_capacity(capacity),
} };
Ok(state)
}
#[cfg(windows)]
fn new(out: &'out mut Write,
prompt: &'prompt str,
history_index: usize)
-> Result<State<'out, 'prompt>> {
let handle = try!(get_std_handle(STDOUT_FILENO));
let capacity = MAX_LINE;
let cols = get_columns(handle);
let prompt_size = calculate_position(prompt, Default::default(), cols);
let state = State {
out: out,
prompt: prompt,
prompt_size: prompt_size,
line: LineBuffer::with_capacity(capacity),
cursor: prompt_size,
cols: cols,
history_index: history_index,
snapshot: LineBuffer::with_capacity(capacity),
output_handle: handle,
};
Ok(state)
} }
fn snapshot(&mut self) { fn snapshot(&mut self) {
...@@ -159,6 +185,16 @@ impl<'out, 'prompt> State<'out, 'prompt> { ...@@ -159,6 +185,16 @@ impl<'out, 'prompt> State<'out, 'prompt> {
fn refresh(&mut self, prompt: &str, prompt_size: Position) -> Result<()> { fn refresh(&mut self, prompt: &str, prompt_size: Position) -> Result<()> {
unimplemented!() unimplemented!()
} }
#[cfg(unix)]
fn update_columns(&mut self) {
self.cols = get_columns();
}
#[cfg(windows)]
fn update_columns(&mut self) {
self.cols = get_columns(self.output_handle);
}
} }
impl<'out, 'prompt> fmt::Debug for State<'out, 'prompt> { impl<'out, 'prompt> fmt::Debug for State<'out, 'prompt> {
...@@ -327,12 +363,7 @@ fn get_columns() -> usize { ...@@ -327,12 +363,7 @@ fn get_columns() -> usize {
} }
} }
#[cfg(windows)] #[cfg(windows)]
fn get_columns() -> usize { fn get_columns(handle: winapi::HANDLE) -> usize {
let handle = get_std_handle(STDOUT_FILENO);
if handle.is_err() {
return 80;
}
let handle = handle.unwrap();
let mut info = unsafe { mem::zeroed() }; let mut info = unsafe { mem::zeroed() };
match unsafe { kernel32::GetConsoleScreenBufferInfo(handle, &mut info) } { match unsafe { kernel32::GetConsoleScreenBufferInfo(handle, &mut info) } {
0 => 80, 0 => 80,
...@@ -348,12 +379,12 @@ fn write_and_flush(w: &mut Write, buf: &[u8]) -> Result<()> { ...@@ -348,12 +379,12 @@ fn write_and_flush(w: &mut Write, buf: &[u8]) -> Result<()> {
/// Clear the screen. Used to handle ctrl+l /// Clear the screen. Used to handle ctrl+l
#[cfg(unix)] #[cfg(unix)]
fn clear_screen(out: &mut Write) -> Result<()> { fn clear_screen(s: &mut State) -> Result<()> {
write_and_flush(out, b"\x1b[H\x1b[2J") write_and_flush(s.out, b"\x1b[H\x1b[2J")
} }
#[cfg(windows)] #[cfg(windows)]
fn clear_screen(_: &mut Write) -> Result<()> { fn clear_screen(s: &mut State) -> Result<()> {
let handle = try!(get_std_handle(STDOUT_FILENO)); let handle = s.output_handle;
let mut info = unsafe { mem::zeroed() }; let mut info = unsafe { mem::zeroed() };
check!(kernel32::GetConsoleScreenBufferInfo(handle, &mut info)); check!(kernel32::GetConsoleScreenBufferInfo(handle, &mut info));
let coord = winapi::COORD { X: 0, Y: 0 }; let coord = winapi::COORD { X: 0, Y: 0 };
...@@ -849,7 +880,6 @@ impl Read for InputBuffer { ...@@ -849,7 +880,6 @@ impl Read for InputBuffer {
} }
} }
/// Handles reading and editting the readline buffer. /// Handles reading and editting the readline buffer.
/// It will also handle special inputs in an appropriate fashion /// It will also handle special inputs in an appropriate fashion
/// (e.g., C-c will exit readline) /// (e.g., C-c will exit readline)
...@@ -861,10 +891,10 @@ fn readline_edit(prompt: &str, ...@@ -861,10 +891,10 @@ fn readline_edit(prompt: &str,
original_mode: Mode) original_mode: Mode)
-> Result<String> { -> Result<String> {
let mut stdout = io::stdout(); let mut stdout = io::stdout();
try!(write_and_flush(&mut stdout, prompt.as_bytes()));
kill_ring.reset(); kill_ring.reset();
let mut s = State::new(&mut stdout, prompt, MAX_LINE, get_columns(), history.len()); let mut s = try!(State::new(&mut stdout, prompt, history.len()));
try!(s.refresh_line());
let stdin = try!(stdin()); let stdin = try!(stdin());
let mut chars = stdin.chars(); // TODO stdin.lock() ??? let mut chars = stdin.chars(); // TODO stdin.lock() ???
...@@ -872,7 +902,7 @@ fn readline_edit(prompt: &str, ...@@ -872,7 +902,7 @@ fn readline_edit(prompt: &str,
loop { loop {
let c = chars.next().unwrap(); let c = chars.next().unwrap();
if c.is_err() && SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst) { if c.is_err() && SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst) {
s.cols = get_columns(); s.update_columns();
try!(s.refresh_line()); try!(s.refresh_line());
continue; continue;
} }
...@@ -961,7 +991,7 @@ fn readline_edit(prompt: &str, ...@@ -961,7 +991,7 @@ fn readline_edit(prompt: &str,
} }
KeyPress::CTRL_L => { KeyPress::CTRL_L => {
// Clear the screen leaving the current line at the top of the screen. // Clear the screen leaving the current line at the top of the screen.
try!(clear_screen(s.out)); try!(clear_screen(&mut s));
try!(s.refresh_line()) try!(s.refresh_line())
} }
KeyPress::CTRL_N => { KeyPress::CTRL_N => {
...@@ -1241,11 +1271,30 @@ mod test { ...@@ -1241,11 +1271,30 @@ mod test {
use State; use State;
use super::Result; use super::Result;
#[cfg(unix)]
fn init_state<'out>(out: &'out mut Write,
line: &str,
pos: usize,
cols: usize)
-> State<'out, 'static> {
State {
out: out,
prompt: "",
prompt_size: Default::default(),
line: LineBuffer::init(line, pos),
cursor: Default::default(),
cols: cols,
history_index: 0,
snapshot: LineBuffer::with_capacity(100),
}
}
#[cfg(windows)]
fn init_state<'out>(out: &'out mut Write, fn init_state<'out>(out: &'out mut Write,
line: &str, line: &str,
pos: usize, pos: usize,
cols: usize) cols: usize)
-> State<'out, 'static> { -> State<'out, 'static> {
use std::ptr;
State { State {
out: out, out: out,
prompt: "", prompt: "",
...@@ -1255,6 +1304,7 @@ mod test { ...@@ -1255,6 +1304,7 @@ mod test {
cols: cols, cols: cols,
history_index: 0, history_index: 0,
snapshot: LineBuffer::with_capacity(100), snapshot: LineBuffer::with_capacity(100),
output_handle: ptr::null_mut(),
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment