From 6357209dc9ad199a0fb274011f73c9a922c670cc Mon Sep 17 00:00:00 2001
From: Xavier L'Heureux <xavier.lheureux@icloud.com>
Date: Tue, 25 Jun 2019 14:42:04 -0400
Subject: [PATCH] Document the Status and add a man page for the fn builtin

---
 src/lib/builtins/functions.rs | 18 +++++++++++++++---
 src/lib/builtins/helpers.rs   | 17 +++++++++++++++++
 src/lib/builtins/man_pages.rs |  1 +
 src/lib/builtins/mod.rs       | 11 +++--------
 4 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/src/lib/builtins/functions.rs b/src/lib/builtins/functions.rs
index 5d2a68c3..b143b352 100644
--- a/src/lib/builtins/functions.rs
+++ b/src/lib/builtins/functions.rs
@@ -1,12 +1,24 @@
 use super::Status;
-use crate::shell::variables::Variables;
+use crate as ion_shell;
+use crate::{types, Shell};
+use builtins_proc::builtin;
 use std::io::{self, Write};
 
-pub fn print_functions(vars: &Variables<'_>) -> Status {
+#[builtin(
+    names = "fn",
+    desc = "print a short description of every defined function",
+    man = "
+SYNOPSIS
+    fn [ -h | --help ]
+
+DESCRIPTION
+    Prints all the defined functions along with their help, if provided"
+)]
+pub fn fn_(args: &[types::Str], shell: &mut Shell<'_>) -> Status {
     let stdout = io::stdout();
     let stdout = &mut stdout.lock();
     let _ = writeln!(stdout, "# Functions");
-    for (fn_name, function) in vars.functions() {
+    for (fn_name, function) in shell.variables().functions() {
         let description = function.description();
         if let Some(ref description) = description {
             let _ = writeln!(stdout, "    {} -- {}", fn_name, description);
diff --git a/src/lib/builtins/helpers.rs b/src/lib/builtins/helpers.rs
index ad3b88dc..346f4f37 100644
--- a/src/lib/builtins/helpers.rs
+++ b/src/lib/builtins/helpers.rs
@@ -1,20 +1,32 @@
 use super::{super::types, Value};
 
+/// The exit status of a command
+///
+/// Provides some helpers for defining builtins like error messages and semantic constants
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
 pub struct Status(i32);
 
 impl Status {
+    /// Failed to execute a given command (a parsing/expansion error occured)
     pub const COULD_NOT_EXEC: Self = Status(126);
+    /// In builtins that output bools, indicates negation
     pub const FALSE: Self = Status(1);
+    /// The command does not exist
     pub const NO_SUCH_COMMAND: Self = Status(127);
+    /// The execution succeeded
     pub const SUCCESS: Self = Status(0);
+    /// The process was killed
     pub const TERMINATED: Self = Status(143);
+    /// In builtins that outputs bools, indicates that the result is true
     pub const TRUE: Self = Status(0);
 
+    /// Make an exit code out of a signal
     pub fn from_signal(signal: u8) -> Self { Status(i32::from(128 + signal)) }
 
+    /// From a raw exit code (native commands)
     pub fn from_exit_code(code: i32) -> Self { Status(code) }
 
+    /// A generic error occured. Prints an helper text
     pub fn error<T: AsRef<str>>(err: T) -> Self {
         let err = err.as_ref();
         if !err.is_empty() {
@@ -23,6 +35,7 @@ impl Status {
         Status(1)
     }
 
+    /// Wrong arguments submitted to the builtin
     pub fn bad_argument<T: AsRef<str>>(err: T) -> Self {
         let err = err.as_ref();
         if !err.is_empty() {
@@ -31,12 +44,16 @@ impl Status {
         Status(2)
     }
 
+    /// Indicates if the operation is successful
     pub fn is_success(self) -> bool { self.0 == 0 }
 
+    /// Indicates if the operation is unsuccessful
     pub fn is_failure(self) -> bool { self.0 != 0 }
 
+    /// Convert to a raw OS exit code
     pub fn as_os_code(self) -> i32 { self.0 }
 
+    /// Change true to false and false to true. Looses information
     pub fn toggle(&mut self) { self.0 = if self.is_success() { 1 } else { 0 }; }
 }
 
diff --git a/src/lib/builtins/man_pages.rs b/src/lib/builtins/man_pages.rs
index f0ed8ff9..0ef29d55 100644
--- a/src/lib/builtins/man_pages.rs
+++ b/src/lib/builtins/man_pages.rs
@@ -1,5 +1,6 @@
 use crate::types;
 
+/// Print the given help if the -h or --help argument are found
 pub fn check_help(args: &[types::Str], man_page: &'static str) -> bool {
     for arg in args {
         if arg == "-h" || arg == "--help" {
diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs
index f820471e..31563d54 100644
--- a/src/lib/builtins/mod.rs
+++ b/src/lib/builtins/mod.rs
@@ -1,3 +1,4 @@
+/// helpers for creating help
 pub mod man_pages;
 
 mod calc;
@@ -21,7 +22,7 @@ pub use self::{
     conditionals::{contains, ends_with, starts_with},
     echo::builtin_echo,
     exists::builtin_exists,
-    functions::print_functions,
+    functions::builtin_fn_,
     helpers::Status,
     is::builtin_is,
     man_pages::check_help,
@@ -156,7 +157,7 @@ impl<'a> BuiltinMap<'a> {
     ///
     /// Contains `fn`, `alias`, `unalias`, `drop`, `read`
     pub fn with_variables(&mut self) -> &mut Self {
-        self.add("fn", &builtin_fn, "Print list of functions")
+        self.add("fn", &builtin_fn_, "Print list of functions")
             .add("alias", &builtin_alias, "View, set or unset aliases")
             .add("unalias", &builtin_unalias, "Delete an alias")
             .add("drop", &builtin_drop, "Delete a variable")
@@ -553,12 +554,6 @@ pub fn popd(args: &[types::Str], shell: &mut Shell<'_>) -> Status {
     }
 }
 
-// TODO There is a man page for fn however the -h and --help flags are not
-// checked for.
-pub fn builtin_fn(_: &[types::Str], shell: &mut Shell<'_>) -> Status {
-    print_functions(shell.variables())
-}
-
 struct EmptyCompleter;
 
 impl Completer for EmptyCompleter {
-- 
GitLab