diff --git a/src/binary/builtins.rs b/src/binary/builtins.rs
index a700ef1c7fd07e381a03b1938f3e8c9fa4685a9a..31825b94f68384d194ecf33d7452e5de115db2ef 100644
--- a/src/binary/builtins.rs
+++ b/src/binary/builtins.rs
@@ -17,6 +17,29 @@ pub fn suspend(args: &[Str], _shell: &mut Shell<'_>) -> Status {
     Status::SUCCESS
 }
 
+#[builtin(
+    desc = "toggle debug mode (print commands)",
+    man = "
+SYNOPSIS
+    debug on | off
+
+DESCRIPTION
+    Turn on or off the feature to print each command executed to stderr (debug mode)."
+)]
+pub fn debug(args: &[Str], shell: &mut Shell<'_>) -> Status {
+    match args.get(1).map(Str::as_str) {
+        Some("on") => shell.set_pre_command(Some(Box::new(|_shell, pipeline| {
+            // A string representing the command is stored here.
+            eprintln!("> {}", pipeline);
+        }))),
+        Some("off") => shell.set_pre_command(None),
+        _ => {
+            return Status::bad_argument("debug: the debug builtin requires on or off as argument")
+        }
+    }
+    Status::SUCCESS
+}
+
 #[builtin(
     desc = "exit the shell",
     man = "
diff --git a/src/binary/completer.rs b/src/binary/completer.rs
index d98baf6b409a87fc9ac72d57d03ec38961d7fe07..0f95014f758d21619269e4428a0e72fcea6e0b07 100644
--- a/src/binary/completer.rs
+++ b/src/binary/completer.rs
@@ -97,7 +97,7 @@ impl<'a, 'b> Completer for IonCompleter<'a, 'b> {
                 let file_completers: Vec<_> = if let Some(paths) = env::var_os("PATH") {
                     env::split_paths(&paths)
                         .map(|s| {
-                            let s = if !s.to_string_lossy().ends_with("/") {
+                            let s = if !s.to_string_lossy().ends_with('/') {
                                 let mut oss = s.into_os_string();
                                 oss.push("/");
                                 oss.into()
@@ -134,9 +134,9 @@ impl<'a, 'b> Completer for IonCompleter<'a, 'b> {
                             .nth(index - 1)
                             .map(|(start, end)| event.editor.current_buffer().range(start, end))
                             .filter(|filename| {
-                                filename.ends_with("|")
-                                    || filename.ends_with("&")
-                                    || filename.ends_with(";")
+                                filename.ends_with('|')
+                                    || filename.ends_with('&')
+                                    || filename.ends_with(';')
                             })
                             .is_some();
                         if is_pipe {
diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs
index e76fbd3174d21e31ace89ea90387985de262a479..a5d452f58a4e81f7b5a0ed8dd839187eb7d3634d 100644
--- a/src/lib/builtins/mod.rs
+++ b/src/lib/builtins/mod.rs
@@ -296,13 +296,13 @@ pub fn cd(args: &[types::Str], shell: &mut Shell<'_>) -> Status {
                         })
                         .find(Result::is_ok)
                         .unwrap_or_else(|| {
-                            shell.dir_stack_mut().change_and_push_dir(&Path::new(dir))
+                            shell.dir_stack_mut().change_and_push_dir(Path::new(dir))
                         });
                     shell.dir_stack_mut().popd(1);
                     check_cdpath_first
                 }
             } else {
-                shell.dir_stack_mut().change_and_push_dir(&Path::new(dir))
+                shell.dir_stack_mut().change_and_push_dir(Path::new(dir))
             }
         }
         None => shell.dir_stack_mut().switch_to_home_directory(),
diff --git a/src/lib/builtins/set.rs b/src/lib/builtins/set.rs
index bb051178ce1fda8ea0cf3f709a84e7e7cf5677a7..cb5e1438004e91c9d0704bdfcadc4c6dece7ab1f 100644
--- a/src/lib/builtins/set.rs
+++ b/src/lib/builtins/set.rs
@@ -17,7 +17,7 @@ enum PositionalArgs {
     desc = "Set or unset values of shell options and positional parameters.",
     man = "
 SYNOPSIS
-    set [ --help ] [-e | +e] [-x | +x] [-o [vi | emacs]] [- | --] [STRING]...
+    set [ --help ] [-e | +e] [- | --] [STRING]...
 
 DESCRIPTION
     Shell options may be set using the '-' character, and unset using the '+' character.
@@ -25,45 +25,38 @@ DESCRIPTION
 OPTIONS
     -e  Exit immediately if a command exits with a non-zero status.
 
-    -o  Specifies that an argument will follow that sets the key map.
-        The keymap argument may be either `vi` or `emacs`.
-
-    -x  Specifies that commands will be printed as they are executed.
-
     --  Following arguments will be set as positional arguments in the shell.
         If no argument are supplied, arguments will be unset.
 
     -   Following arguments will be set as positional arguments in the shell.
-        If no arguments are suppled, arguments will not be unset."
+        If no arguments are suppled, arguments will not be unset.
+
+BASH EQUIVALENTS
+    To set the keybindings, see the `keybindings` builtin
+    To print commands as they are executed (only with the Ion Shell), see `debug`"
 )]
 pub fn set(args: &[types::Str], shell: &mut Shell<'_>) -> Status {
     let mut args_iter = args.iter();
     let mut positionals = None;
 
     while let Some(arg) = args_iter.next() {
-        if arg.starts_with("--") {
-            if arg.len() == 2 {
+        match arg.as_str() {
+            "--" => {
                 positionals = Some(PositionalArgs::UnsetIfNone);
                 break;
             }
-            return Status::SUCCESS;
-        } else if arg.starts_with('-') {
-            if arg.len() == 1 {
+            "-" => {
                 positionals = Some(PositionalArgs::RetainIfNone);
                 break;
             }
-            for flag in arg.bytes().skip(1) {
-                match flag {
-                    b'e' => shell.opts_mut().err_exit = true,
-                    _ => return Status::SUCCESS,
-                }
-            }
-        } else if arg.starts_with('+') {
-            for flag in arg.bytes().skip(1) {
-                match flag {
-                    b'e' => shell.opts_mut().err_exit = false,
-                    _ => return Status::SUCCESS,
-                }
+            "-e" => shell.opts_mut().err_exit = true,
+            "+e" => shell.opts_mut().err_exit = false,
+            _ => {
+                return Status::bad_argument(format!(
+                    "set: argument '{}' is not recognized. Try adding `--` before it to pass it \
+                     as argument to the shell script",
+                    arg
+                ))
             }
         }
     }
diff --git a/src/lib/expansion/words/mod.rs b/src/lib/expansion/words/mod.rs
index da1e545383810fc38ef2a413b5b911e12fceb960..484b2aba75214d3620288297b8ac745b74a006c4 100644
--- a/src/lib/expansion/words/mod.rs
+++ b/src/lib/expansion/words/mod.rs
@@ -646,7 +646,7 @@ impl<'a> WordIterator<'a> {
     }
 
     /// Creates a new iterator with a given expander
-    pub fn new(data: &'a str, do_glob: bool) -> WordIterator<'a> {
+    pub const fn new(data: &'a str, do_glob: bool) -> WordIterator<'a> {
         WordIterator { data, backsl: false, read: 0, quotes: Quotes::None, do_glob }
     }
 }
diff --git a/src/lib/shell/directory_stack.rs b/src/lib/shell/directory_stack.rs
index 7dc10164244d151a736f0ecda9d0fd6e2660f36e..fe7ab7e763ea3dbc0cea3f40502d1ee21dd2f752 100644
--- a/src/lib/shell/directory_stack.rs
+++ b/src/lib/shell/directory_stack.rs
@@ -143,7 +143,7 @@ impl DirectoryStack {
 
         self.dirs.remove(0);
         println!("{}", prev);
-        self.change_and_push_dir(&Path::new(&prev))
+        self.change_and_push_dir(Path::new(&prev))
     }
 
     pub fn switch_to_home_directory(&mut self) -> Result<(), DirStackError> {
diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs
index 0f5d345f51eb000b5e8ea201cbc19b9526500a80..44a261d7a0d2aeacf2bc84a24c4e9810af00a4b6 100644
--- a/src/lib/shell/mod.rs
+++ b/src/lib/shell/mod.rs
@@ -298,8 +298,8 @@ impl<'a> Shell<'a> {
         let null_file =
             if pipeline.pipe == PipeType::Disown { File::open(NULL_PATH).ok() } else { None };
         let (stderr, stdout) = (
-            null_file.as_ref().or(self.stderr.as_ref()),
-            null_file.as_ref().or(self.stdout.as_ref()),
+            null_file.as_ref().or_else(|| self.stderr.as_ref()),
+            null_file.as_ref().or_else(|| self.stdout.as_ref()),
         );
 
         for item in &mut pipeline.items {
diff --git a/src/lib/shell/shell_expand.rs b/src/lib/shell/shell_expand.rs
index 52e21b1690f8a55e0fe3403ccf5ad269f71ffe5d..295cb6d772d4318decd03681cdd8253d78c51769 100644
--- a/src/lib/shell/shell_expand.rs
+++ b/src/lib/shell/shell_expand.rs
@@ -209,7 +209,7 @@ impl<'a, 'b> Expander for Shell<'b> {
 
         match tilde_prefix {
             "+" => Ok(env::var("PWD").unwrap_or_else(|_| "?".into()).into()),
-            "-" => Ok(self.variables.get_str("OLDPWD")?.into()),
+            "-" => Ok(self.variables.get_str("OLDPWD")?),
             _ => {
                 let (neg, tilde_num) = if tilde_prefix.starts_with('+') {
                     (false, &tilde_prefix[1..])
@@ -219,24 +219,23 @@ impl<'a, 'b> Expander for Shell<'b> {
                     (false, tilde_prefix)
                 };
 
-                match tilde_num.parse() {
-                    Ok(num) => if neg {
+                if let Ok(num) = tilde_num.parse() {
+                    if neg {
                         self.directory_stack.dir_from_top(num)
                     } else {
                         self.directory_stack.dir_from_bottom(num)
                     }
                     .map(|path| path.to_str().unwrap().into())
-                    .ok_or_else(|| Error::OutOfStack(num)),
-                    Err(_) => {
-                        let user = if tilde_prefix.is_empty() {
-                            users::get_user_by_uid(users::get_current_uid())
-                        } else {
-                            users::get_user_by_name(tilde_prefix)
-                        };
-                        match user {
-                            Some(user) => Ok(user.home_dir().to_string_lossy().as_ref().into()),
-                            None => Err(Error::HomeNotFound),
-                        }
+                    .ok_or_else(|| Error::OutOfStack(num))
+                } else {
+                    let user = if tilde_prefix.is_empty() {
+                        users::get_user_by_uid(users::get_current_uid())
+                    } else {
+                        users::get_user_by_name(tilde_prefix)
+                    };
+                    match user {
+                        Some(user) => Ok(user.home_dir().to_string_lossy().as_ref().into()),
+                        None => Err(Error::HomeNotFound),
                     }
                 }
             }
diff --git a/src/lib/shell/variables.rs b/src/lib/shell/variables.rs
index 9f65a41932dd971edcafe7f27636ccace9407081..09f214cbd7f244ffff6c2dca121ca61292643cf7 100644
--- a/src/lib/shell/variables.rs
+++ b/src/lib/shell/variables.rs
@@ -6,7 +6,7 @@ use crate::{
 };
 use nix::unistd::{geteuid, gethostname, getpid, getuid};
 use scopes::{Namespace, Scope, Scopes};
-use std::{env, rc::Rc};
+use std::{env, ffi::CStr, rc::Rc};
 use unicode_segmentation::UnicodeSegmentation;
 
 /// Contain a dynamically-typed variable value
@@ -256,7 +256,7 @@ impl<'a> Default for Variables<'a> {
             "HOST",
             &gethostname(&mut host_name)
                 .ok()
-                .map_or_else(|| "?".into(), |hostname| hostname.to_string_lossy())
+                .map_or_else(|| "?".into(), CStr::to_string_lossy)
                 .as_ref(),
         );
 
diff --git a/src/main.rs b/src/main.rs
index d66c44a3987b709f187223d796ff783ae423ae3d..31f7d0703819767a1a78f13fa7c6e2c785a390f3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -164,6 +164,7 @@ fn main() {
     let mut builtins = BuiltinMap::default();
     builtins
         .with_unsafe()
+        .add("debug", &builtins::builtin_debug, "Toggle debug mode (print commands on exec)")
         .add("exec", &builtins::builtin_exec, "Replace the shell with the given command.")
         .add("exit", &builtins::builtin_exit, "Exits the current session")
         .add("suspend", &builtins::builtin_suspend, "Suspends the shell with a SIGTSTOP signal");