From 37c35100485d15875f7053d4fabf6ebb926c4eb5 Mon Sep 17 00:00:00 2001 From: Xavier L'Heureux <xavier.lheureux@icloud.com> Date: Tue, 2 Jul 2019 14:48:11 -0400 Subject: [PATCH] Reduce the number of shell options --- src/binary/mod.rs | 43 ++++++++++++++++++++++++++++------------- src/binary/prompt.rs | 2 +- src/binary/readln.rs | 4 ++-- src/lib/builtins/set.rs | 9 --------- src/lib/shell/mod.rs | 5 ----- 5 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/binary/mod.rs b/src/binary/mod.rs index fa0cc5cd..abe624e0 100644 --- a/src/binary/mod.rs +++ b/src/binary/mod.rs @@ -8,7 +8,7 @@ mod prompt; mod readln; use ion_shell::{ - builtins::{man_pages, Status}, + builtins::{man_pages, BuiltinFunction, Status}, expansion::Expander, parser::Terminator, types, IonError, PipelineError, Shell, Signal, Value, @@ -16,7 +16,7 @@ use ion_shell::{ use itertools::Itertools; use liner::{Buffer, Context, KeyBindings}; use std::{ - cell::RefCell, + cell::{Cell, RefCell}, fs::{self, OpenOptions}, io, path::Path, @@ -57,8 +57,10 @@ DESCRIPTION Prints the command history."#; pub struct InteractiveShell<'a> { - context: Rc<RefCell<Context>>, - shell: RefCell<Shell<'a>>, + context: Rc<RefCell<Context>>, + shell: RefCell<Shell<'a>>, + terminated: Cell<bool>, + huponexit: Rc<Cell<bool>>, } impl<'a> InteractiveShell<'a> { @@ -74,7 +76,12 @@ impl<'a> InteractiveShell<'a> { } let _ = context.history.set_file_name_and_load_history(path.as_str()); } - InteractiveShell { context: Rc::new(RefCell::new(context)), shell: RefCell::new(shell) } + InteractiveShell { + context: Rc::new(RefCell::new(context)), + shell: RefCell::new(shell), + terminated: Cell::new(true), + huponexit: Rc::new(Cell::new(false)), + } } /// Handles commands given by the REPL, and saves them to history. @@ -123,10 +130,11 @@ impl<'a> InteractiveShell<'a> { /// Liner. pub fn execute_interactive(self) -> ! { let context_bis = self.context.clone(); + let huponexit = self.huponexit.clone(); let prep_for_exit = &move |shell: &mut Shell<'_>| { // context will be sent a signal to commit all changes to the history file, // and waiting for the history thread in the background to finish. - if shell.opts().huponexit { + if huponexit.get() { shell.resume_stopped(); shell.background_send(Signal::SIGHUP).expect("Failed to prepare for exit"); } @@ -155,6 +163,15 @@ impl<'a> InteractiveShell<'a> { Status::SUCCESS }; + let huponexit = self.huponexit.clone(); + let set_huponexit: BuiltinFunction = &move |args, _shell| { + huponexit.set(match args.get(1).map(AsRef::as_ref) { + Some("false") | Some("off") => false, + _ => true, + }); + Status::SUCCESS + }; + let context_bis = self.context.clone(); let keybindings = &move |args: &[types::Str], _shell: &mut Shell<'_>| -> Status { match args.get(1).map(|s| s.as_str()) { @@ -172,18 +189,20 @@ impl<'a> InteractiveShell<'a> { }; // change the lifetime to allow adding local builtins - let InteractiveShell { context, shell } = self; + let InteractiveShell { context, shell, terminated, huponexit } = self; let mut shell = shell.into_inner(); shell .builtins_mut() .add("history", history, "Display a log of all commands previously executed") .add("keybindings", keybindings, "Change the keybindings") .add("exit", exit, "Exits the current session") - .add("exec", exec, "Replace the shell with the given command."); + .add("exec", exec, "Replace the shell with the given command.") + .add("huponexit", set_huponexit, "Hangup the shell's background jobs on exit"); Self::exec_init_file(&mut shell); - InteractiveShell { context, shell: RefCell::new(shell) }.exec(prep_for_exit) + InteractiveShell { context, shell: RefCell::new(shell), terminated, huponexit } + .exec(prep_for_exit) } fn exec_init_file(shell: &mut Shell) { @@ -220,9 +239,9 @@ impl<'a> InteractiveShell<'a> { &self.context.borrow(), command.trim_end(), ); + self.terminated.set(true); { let mut shell = self.shell.borrow_mut(); - shell.unterminated = false; match shell.on_command(&cmd) { Ok(_) => (), Err(IonError::PipelineExecutionError( @@ -249,9 +268,7 @@ impl<'a> InteractiveShell<'a> { } self.save_command(&cmd); } - None => { - self.shell.borrow_mut().unterminated = true; - } + None => self.terminated.set(false), } } } diff --git a/src/binary/prompt.rs b/src/binary/prompt.rs index 9758eb97..bb6c7beb 100644 --- a/src/binary/prompt.rs +++ b/src/binary/prompt.rs @@ -5,7 +5,7 @@ impl<'a> InteractiveShell<'a> { /// Generates the prompt that will be used by Liner. pub fn prompt(&self) -> String { let shell = self.shell.borrow(); - let blocks = shell.block_len() + if shell.unterminated { 1 } else { 0 }; + let blocks = if self.terminated.get() { shell.block_len() } else { shell.block_len() + 1 }; if blocks == 0 { shell.command("PROMPT").map(|res| res.to_string()).unwrap_or_else(|_| { diff --git a/src/binary/readln.rs b/src/binary/readln.rs index 4339a883..278a76d6 100644 --- a/src/binary/readln.rs +++ b/src/binary/readln.rs @@ -18,7 +18,7 @@ impl<'a> InteractiveShell<'a> { if line.bytes().next() != Some(b'#') && line.bytes().any(|c| !c.is_ascii_whitespace()) { - self.shell.borrow_mut().unterminated = true; + self.terminated.set(false); } Some(line) } @@ -27,7 +27,7 @@ impl<'a> InteractiveShell<'a> { // Handles Ctrl + D Err(ref err) if err.kind() == ErrorKind::UnexpectedEof => { let mut shell = self.shell.borrow_mut(); - if !shell.unterminated && shell.exit_block().is_err() { + if self.terminated.get() && shell.exit_block().is_err() { prep_for_exit(&mut shell); std::process::exit(shell.previous_status().as_os_code()) } diff --git a/src/lib/builtins/set.rs b/src/lib/builtins/set.rs index 4b373cff..bb051178 100644 --- a/src/lib/builtins/set.rs +++ b/src/lib/builtins/set.rs @@ -62,15 +62,6 @@ pub fn set(args: &[types::Str], shell: &mut Shell<'_>) -> Status { for flag in arg.bytes().skip(1) { match flag { b'e' => shell.opts_mut().err_exit = false, - b'o' => match args_iter.next().map(|s| s as &str) { - Some("huponexit") => shell.opts_mut().huponexit = false, - Some(_) => { - return Status::error("ion: set: invalid option"); - } - None => { - return Status::error("ion: set: no option given"); - } - }, _ => return Status::SUCCESS, } } diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs index 10b5e9d6..2cd59f73 100644 --- a/src/lib/shell/mod.rs +++ b/src/lib/shell/mod.rs @@ -103,8 +103,6 @@ pub struct Options { pub err_exit: bool, /// Do not execute any commands given to the shell. pub no_exec: bool, - /// Hangup on exiting the shell. - pub huponexit: bool, /// If set, denotes that this shell is running as a background job. pub grab_tty: bool, } @@ -133,8 +131,6 @@ pub struct Shell<'a> { /// Contains information on all of the active background processes that are being managed /// by the shell. background: Arc<Mutex<Vec<BackgroundProcess>>>, - /// Used by an interactive session to know when the input is not terminated. - pub unterminated: bool, /// When the `fg` command is run, this will be used to communicate with the specified /// background process. foreground_signals: Arc<foreground::Signals>, @@ -217,7 +213,6 @@ impl<'a> Shell<'a> { on_command: None, pre_command: None, background_event: None, - unterminated: false, stdin: None, stdout: None, -- GitLab