Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
redox-os
ion
Commits
d195ccaf
Commit
d195ccaf
authored
Dec 06, 2017
by
Sag0Sag0
Browse files
Add tests for builtin is
parent
22244125
Changes
68
Hide whitespace changes
Inline
Side-by-side
src/ascii_helpers.rs
View file @
d195ccaf
...
...
@@ -23,7 +23,10 @@ impl AsciiReplaceInPlace for str {
// I tried replacing these `assert!` calls with `debug_assert!` but it looks
// like they get const-folded away anyway since it doesn't affect the speed
fn
ascii_replace_in_place
(
&
mut
self
,
needle
:
char
,
haystack
:
char
)
{
assert
!
(
needle
.is_ascii
(),
"AsciiReplace functions can only be used for ascii characters"
);
assert
!
(
needle
.is_ascii
(),
"AsciiReplace functions can only be used for ascii characters"
);
assert
!
(
haystack
.is_ascii
(),
"AsciiReplace functions can only be used for ascii characters"
...
...
src/builtins/exists.rs
View file @
d195ccaf
...
...
@@ -27,9 +27,9 @@ fn evaluate_arguments(arguments: &[&str], shell: &Shell) -> Result<bool, String>
})
}
Some
(
&
s
)
if
s
.starts_with
(
"-"
)
=>
{
// Access the second character in the flag string: this will be type of the
flag.
// If no flag was given, return `SUCCESS`, as this means a
string with value "-" was
// checked.
// Access the second character in the flag string: this will be type of the
//
flag.
If no flag was given, return `SUCCESS`, as this means a
//
string with value "-" was
checked.
s
.chars
()
.nth
(
1
)
.map_or
(
Ok
(
true
),
|
flag
|
{
// If no argument was given, return `SUCCESS`, as this means a string starting
// with a dash was given
...
...
@@ -45,7 +45,8 @@ fn evaluate_arguments(arguments: &[&str], shell: &Shell) -> Result<bool, String>
}
}
/// Matches flag arguments to their respective functionaity when the `-` character is detected.
/// Matches flag arguments to their respective functionaity when the `-`
/// character is detected.
fn
match_flag_argument
(
flag
:
char
,
argument
:
&
str
,
shell
:
&
Shell
)
->
bool
{
match
flag
{
'a'
=>
array_var_is_not_empty
(
argument
,
shell
),
...
...
@@ -67,20 +68,24 @@ fn match_option_argument(option: &str, argument: &str, shell: &Shell) -> bool {
/// Returns true if the file is a regular file
fn
path_is_file
(
filepath
:
&
str
)
->
bool
{
fs
::
metadata
(
filepath
)
.ok
()
.map_or
(
false
,
|
metadata
|
metadata
.file_type
()
.is_file
())
fs
::
metadata
(
filepath
)
.ok
()
.map_or
(
false
,
|
metadata
|
metadata
.file_type
()
.is_file
())
}
/// Returns true if the file is a directory
fn
path_is_directory
(
filepath
:
&
str
)
->
bool
{
fs
::
metadata
(
filepath
)
.ok
()
.map_or
(
false
,
|
metadata
|
metadata
.file_type
()
.is_dir
())
fs
::
metadata
(
filepath
)
.ok
()
.map_or
(
false
,
|
metadata
|
metadata
.file_type
()
.is_dir
())
}
/// Returns true if the binary is found in path (and is executable)
fn
binary_is_in_path
(
binaryname
:
&
str
,
shell
:
&
Shell
)
->
bool
{
// TODO: Maybe this function should reflect the logic for spawning new processes
// TODO: Right now they use an entirely different logic which means that it
*might* be possible
// TODO: that `exists` reports a binary to be in the
path, while the shell cannot find it or
// TODO: vice-versa
// TODO: Right now they use an entirely different logic which means that it
//
*might* be possible
TODO: that `exists` reports a binary to be in the
//
path, while the shell cannot find it or
TODO: vice-versa
if
let
Some
(
path
)
=
shell
.get_var
(
"PATH"
)
{
for
dir
in
path
.split
(
":"
)
{
let
fname
=
format!
(
"{}/{}"
,
dir
,
binaryname
);
...
...
@@ -113,7 +118,9 @@ fn file_has_execute_permission(filepath: &str) -> bool {
}
/// Returns true if the string is not empty
fn
string_is_nonzero
(
string
:
&
str
)
->
bool
{
!
string
.is_empty
()
}
fn
string_is_nonzero
(
string
:
&
str
)
->
bool
{
!
string
.is_empty
()
}
/// Returns true if the variable is an array and the array is not empty
fn
array_var_is_not_empty
(
arrayvar
:
&
str
,
shell
:
&
Shell
)
->
bool
{
...
...
@@ -160,7 +167,9 @@ fn test_evaluate_arguments() {
// check `exists -a`
// no argument means we treat it as a string
assert_eq!
(
evaluate_arguments
(
&
[
"-a"
],
&
shell
),
Ok
(
true
));
shell
.variables
.set_array
(
"emptyarray"
,
SmallVec
::
from_vec
(
Vec
::
new
()));
shell
.variables
.set_array
(
"emptyarray"
,
SmallVec
::
from_vec
(
Vec
::
new
()));
assert_eq!
(
evaluate_arguments
(
&
[
"-a"
,
"emptyarray"
],
&
shell
),
Ok
(
false
));
let
mut
vec
=
Vec
::
new
();
vec
.push
(
"element"
.to_owned
());
...
...
@@ -176,27 +185,45 @@ fn test_evaluate_arguments() {
let
oldpath
=
shell
.get_var
(
"PATH"
)
.unwrap_or
(
"/usr/bin"
.to_owned
());
shell
.set_var
(
"PATH"
,
"testing/"
);
assert_eq!
(
evaluate_arguments
(
&
[
"-b"
,
"executable_file"
],
&
shell
),
Ok
(
true
));
assert_eq!
(
evaluate_arguments
(
&
[
"-b"
,
"executable_file"
],
&
shell
),
Ok
(
true
)
);
assert_eq!
(
evaluate_arguments
(
&
[
"-b"
,
"empty_file"
],
&
shell
),
Ok
(
false
));
assert_eq!
(
evaluate_arguments
(
&
[
"-b"
,
"file_does_not_exist"
],
&
shell
),
Ok
(
false
));
assert_eq!
(
evaluate_arguments
(
&
[
"-b"
,
"file_does_not_exist"
],
&
shell
),
Ok
(
false
)
);
// restore original PATH. Not necessary for the currently defined test cases
but this might
// change in the future? Better safe than sorry!
// restore original PATH. Not necessary for the currently defined test cases
//
but this might
change in the future? Better safe than sorry!
shell
.set_var
(
"PATH"
,
&
oldpath
);
// check `exists -d`
// no argument means we treat it as a string
assert_eq!
(
evaluate_arguments
(
&
[
"-d"
],
&
shell
),
Ok
(
true
));
assert_eq!
(
evaluate_arguments
(
&
[
"-d"
,
"testing/"
],
&
shell
),
Ok
(
true
));
assert_eq!
(
evaluate_arguments
(
&
[
"-d"
,
"testing/empty_file"
],
&
shell
),
Ok
(
false
));
assert_eq!
(
evaluate_arguments
(
&
[
"-d"
,
"does/not/exist/"
],
&
shell
),
Ok
(
false
));
assert_eq!
(
evaluate_arguments
(
&
[
"-d"
,
"testing/empty_file"
],
&
shell
),
Ok
(
false
)
);
assert_eq!
(
evaluate_arguments
(
&
[
"-d"
,
"does/not/exist/"
],
&
shell
),
Ok
(
false
)
);
// check `exists -f`
// no argument means we treat it as a string
assert_eq!
(
evaluate_arguments
(
&
[
"-f"
],
&
shell
),
Ok
(
true
));
assert_eq!
(
evaluate_arguments
(
&
[
"-f"
,
"testing/"
],
&
shell
),
Ok
(
false
));
assert_eq!
(
evaluate_arguments
(
&
[
"-f"
,
"testing/empty_file"
],
&
shell
),
Ok
(
true
));
assert_eq!
(
evaluate_arguments
(
&
[
"-f"
,
"does-not-exist"
],
&
shell
),
Ok
(
false
));
assert_eq!
(
evaluate_arguments
(
&
[
"-f"
,
"testing/empty_file"
],
&
shell
),
Ok
(
true
)
);
assert_eq!
(
evaluate_arguments
(
&
[
"-f"
,
"does-not-exist"
],
&
shell
),
Ok
(
false
)
);
// check `exists -s`
// no argument means we treat it as a string
...
...
@@ -218,18 +245,25 @@ fn test_evaluate_arguments() {
let
name_str
=
"test_function"
;
let
name
=
SmallString
::
from_str
(
name_str
);
let
mut
args
=
Vec
::
new
();
args
.push
(
KeyBuf
{
name
:
"testy"
.into
(),
kind
:
Primitive
::
Any
});
args
.push
(
KeyBuf
{
name
:
"testy"
.into
(),
kind
:
Primitive
::
Any
,
});
let
mut
statements
=
Vec
::
new
();
statements
.push
(
Statement
::
End
);
let
description
=
"description"
.to_owned
();
shell
.functions
.insert
(
name
.clone
(),
Function
::
new
(
Some
(
description
),
name
,
args
,
statements
));
shell
.functions
.insert
(
name
.clone
(),
Function
::
new
(
Some
(
description
),
name
,
args
,
statements
),
);
assert_eq!
(
evaluate_arguments
(
&
[
"--fn"
,
name_str
],
&
shell
),
Ok
(
true
));
shell
.functions
.remove
(
name_str
);
assert_eq!
(
evaluate_arguments
(
&
[
"--fn"
,
name_str
],
&
shell
),
Ok
(
false
));
// check invalid flags / parameters (should all be treated as strings and therefore succeed)
// check invalid flags / parameters (should all be treated as strings and
// therefore succeed)
assert_eq!
(
evaluate_arguments
(
&
[
"--foo"
],
&
shell
),
Ok
(
true
));
assert_eq!
(
evaluate_arguments
(
&
[
"-x"
],
&
shell
),
Ok
(
true
));
}
...
...
@@ -238,12 +272,28 @@ fn test_evaluate_arguments() {
fn
test_match_flag_argument
()
{
let
shell
=
Shell
::
new
();
// we don't really care about the passed values, as long as both sited return the same value
assert_eq!
(
match_flag_argument
(
'a'
,
"ARRAY"
,
&
shell
),
array_var_is_not_empty
(
"ARRAY"
,
&
shell
));
assert_eq!
(
match_flag_argument
(
'b'
,
"binary"
,
&
shell
),
binary_is_in_path
(
"binary"
,
&
shell
));
assert_eq!
(
match_flag_argument
(
'd'
,
"path"
,
&
shell
),
path_is_directory
(
"path"
));
assert_eq!
(
match_flag_argument
(
'f'
,
"file"
,
&
shell
),
path_is_file
(
"file"
));
assert_eq!
(
match_flag_argument
(
's'
,
"STR"
,
&
shell
),
string_var_is_not_empty
(
"STR"
,
&
shell
));
// we don't really care about the passed values, as long as both sited return
// the same value
assert_eq!
(
match_flag_argument
(
'a'
,
"ARRAY"
,
&
shell
),
array_var_is_not_empty
(
"ARRAY"
,
&
shell
)
);
assert_eq!
(
match_flag_argument
(
'b'
,
"binary"
,
&
shell
),
binary_is_in_path
(
"binary"
,
&
shell
)
);
assert_eq!
(
match_flag_argument
(
'd'
,
"path"
,
&
shell
),
path_is_directory
(
"path"
)
);
assert_eq!
(
match_flag_argument
(
'f'
,
"file"
,
&
shell
),
path_is_file
(
"file"
)
);
assert_eq!
(
match_flag_argument
(
's'
,
"STR"
,
&
shell
),
string_var_is_not_empty
(
"STR"
,
&
shell
)
);
// Any flag which is not implemented
assert_eq!
(
match_flag_argument
(
'x'
,
"ARG"
,
&
shell
),
false
);
...
...
@@ -253,8 +303,12 @@ fn test_match_flag_argument() {
fn
test_match_option_argument
()
{
let
shell
=
Shell
::
new
();
// we don't really care about the passed values, as long as both sited return the same value
assert_eq!
(
match_option_argument
(
"fn"
,
"FUN"
,
&
shell
),
array_var_is_not_empty
(
"FUN"
,
&
shell
));
// we don't really care about the passed values, as long as both sited return
// the same value
assert_eq!
(
match_option_argument
(
"fn"
,
"FUN"
,
&
shell
),
array_var_is_not_empty
(
"FUN"
,
&
shell
)
);
// Any option which is not implemented
assert_eq!
(
match_option_argument
(
"foo"
,
"ARG"
,
&
shell
),
false
);
...
...
@@ -280,8 +334,8 @@ fn test_binary_is_in_path() {
// TODO: multiple/:directories/
// TODO: PATH containing directories which do not exist
// TODO: PATH containing directories without read permission (for user)
// TODO: PATH containing directories without execute ("enter") permission (for
user)
// TODO: empty PATH?
// TODO: PATH containing directories without execute ("enter") permission (for
//
user)
TODO: empty PATH?
shell
.set_var
(
"PATH"
,
"testing/"
);
assert_eq!
(
binary_is_in_path
(
"executable_file"
,
&
shell
),
true
);
...
...
@@ -307,19 +361,24 @@ fn test_string_is_nonzero() {
fn
test_array_var_is_not_empty
()
{
let
mut
shell
=
Shell
::
new
();
shell
.variables
.set_array
(
"EMPTY_ARRAY"
,
SmallVec
::
from_vec
(
Vec
::
new
()));
shell
.variables
.set_array
(
"EMPTY_ARRAY"
,
SmallVec
::
from_vec
(
Vec
::
new
()));
assert_eq!
(
array_var_is_not_empty
(
"EMPTY_ARRAY"
,
&
shell
),
false
);
let
mut
not_empty_vec
=
Vec
::
new
();
not_empty_vec
.push
(
"array not empty"
.to_owned
());
shell
.variables
.set_array
(
"NOT_EMPTY_ARRAY"
,
SmallVec
::
from_vec
(
not_empty_vec
));
shell
.variables
.set_array
(
"NOT_EMPTY_ARRAY"
,
SmallVec
::
from_vec
(
not_empty_vec
));
assert_eq!
(
array_var_is_not_empty
(
"NOT_EMPTY_ARRAY"
,
&
shell
),
true
);
// test for array which does not even exist
shell
.variables
.unset_array
(
"NOT_EMPTY_ARRAY"
);
assert_eq!
(
array_var_is_not_empty
(
"NOT_EMPTY_ARRAY"
,
&
shell
),
false
);
// array_var_is_not_empty should NOT match for non-array variables with the same name
// array_var_is_not_empty should NOT match for non-array variables with the
// same name
shell
.set_var
(
"VARIABLE"
,
"notempty-variable"
);
assert_eq!
(
array_var_is_not_empty
(
"VARIABLE"
,
&
shell
),
false
);
}
...
...
@@ -337,7 +396,9 @@ fn test_string_var_is_not_empty() {
// string_var_is_not_empty should NOT match for arrays with the same name
let
mut
vec
=
Vec
::
new
();
vec
.push
(
"not-empty"
.to_owned
());
shell
.variables
.set_array
(
"ARRAY_NOT_EMPTY"
,
SmallVec
::
from_vec
(
vec
));
shell
.variables
.set_array
(
"ARRAY_NOT_EMPTY"
,
SmallVec
::
from_vec
(
vec
));
assert_eq!
(
string_var_is_not_empty
(
"ARRAY_NOT_EMPTY"
,
&
shell
),
false
);
// test for a variable which does not even exist
...
...
@@ -354,12 +415,18 @@ fn test_function_is_defined() {
let
name_str
=
"test_function"
;
let
name
=
SmallString
::
from_str
(
name_str
);
let
mut
args
=
Vec
::
new
();
args
.push
(
KeyBuf
{
name
:
"testy"
.into
(),
kind
:
Primitive
::
Any
});
args
.push
(
KeyBuf
{
name
:
"testy"
.into
(),
kind
:
Primitive
::
Any
,
});
let
mut
statements
=
Vec
::
new
();
statements
.push
(
Statement
::
End
);
let
description
=
"description"
.to_owned
();
shell
.functions
.insert
(
name
.clone
(),
Function
::
new
(
Some
(
description
),
name
,
args
,
statements
));
shell
.functions
.insert
(
name
.clone
(),
Function
::
new
(
Some
(
description
),
name
,
args
,
statements
),
);
assert_eq!
(
function_is_defined
(
name_str
,
&
shell
),
true
);
shell
.functions
.remove
(
name_str
);
...
...
src/builtins/is.rs
View file @
d195ccaf
...
...
@@ -21,10 +21,9 @@ pub(crate) fn is(args: &[&str], shell: &mut Shell) -> Result<(), String> {
}
fn
eval_arg
(
arg
:
&
str
,
shell
:
&
mut
Shell
)
->
String
{
let
var_value
=
get_var_string
(
arg
,
shell
);
if
var_value
!=
""
{
return
var_value
;
let
value
=
get_var_string
(
arg
,
shell
);
if
value
!=
""
{
return
value
;
}
arg
.to_string
()
}
...
...
@@ -43,3 +42,45 @@ fn get_var_string(name: &str, shell: &mut Shell) -> String {
sh_var
.to_string
()
}
#[test]
fn
test_is
()
{
let
mut
shell
=
Shell
::
new
();
shell
.set_var
(
"x"
,
"value"
);
shell
.set_var
(
"y"
,
"0"
);
// Four arguments
assert_eq!
(
is
(
&
[
"is"
,
" "
,
" "
,
" "
],
&
mut
shell
),
Err
(
"Expected 'not' instead found ' '
\n
"
.to_string
())
);
assert_eq!
(
is
(
&
[
"is"
,
"not"
,
" "
,
" "
],
&
mut
shell
),
Err
(
""
.to_string
())
);
assert_eq!
(
is
(
&
[
"is"
,
"not"
,
"$x"
,
"$x"
],
&
mut
shell
),
Err
(
""
.to_string
())
);
assert_eq!
(
is
(
&
[
"is"
,
"not"
,
"2"
,
"1"
],
&
mut
shell
),
Ok
(()));
assert_eq!
(
is
(
&
[
"is"
,
"not"
,
"$x"
,
"$y"
],
&
mut
shell
),
Ok
(()));
// Three arguments
assert_eq!
(
is
(
&
[
"is"
,
"1"
,
"2"
],
&
mut
shell
),
Err
(
""
.to_string
()));
assert_eq!
(
is
(
&
[
"is"
,
"$x"
,
"$y"
],
&
mut
shell
),
Err
(
""
.to_string
()));
assert_eq!
(
is
(
&
[
"is"
,
" "
,
" "
],
&
mut
shell
),
Ok
(()));
assert_eq!
(
is
(
&
[
"is"
,
"$x"
,
"$x"
],
&
mut
shell
),
Ok
(()));
// Two arguments
assert_eq!
(
is
(
&
[
"is"
,
" "
],
&
mut
shell
),
Err
(
"is needs 3 or 4 arguments
\n
"
.to_string
())
);
assert_eq!
(
is
(
&
[
"is"
,
"-h"
],
&
mut
shell
),
Ok
(()));
// One argument
assert_eq!
(
is
(
&
[
"is"
],
&
mut
shell
),
Err
(
"is needs 3 or 4 arguments
\n
"
.to_string
())
);
}
src/builtins/job_control.rs
View file @
d195ccaf
//! Contains the `jobs`, `disown`, `bg`, and `fg` commands that manage job control in the shell.
//! Contains the `jobs`, `disown`, `bg`, and `fg` commands that manage job
//! control in the shell.
use
shell
::
Shell
;
use
shell
::
job_control
::{
JobControl
,
ProcessState
};
...
...
@@ -10,7 +11,6 @@ use std::io::{stderr, Write};
/// The `-a` flag selects all jobs, `-r` selects all running jobs, and `-h` specifies to mark
/// SIGHUP ignoral.
pub
(
crate
)
fn
disown
(
shell
:
&
mut
Shell
,
args
:
&
[
&
str
])
->
Result
<
(),
String
>
{
const
NO_SIGHUP
:
u8
=
1
;
const
ALL_JOBS
:
u8
=
2
;
const
RUN_JOBS
:
u8
=
4
;
...
...
@@ -84,8 +84,14 @@ pub(crate) fn jobs(shell: &mut Shell) {
let
mut
stderr
=
stderr
.lock
();
for
(
id
,
process
)
in
shell
.background
.lock
()
.unwrap
()
.iter
()
.enumerate
()
{
if
process
.state
!=
ProcessState
::
Empty
{
let
_
=
writeln!
(
stderr
,
"[{}] {} {}
\t
{}"
,
id
,
process
.pid
,
process
.state
,
process
.name
);
let
_
=
writeln!
(
stderr
,
"[{}] {} {}
\t
{}"
,
id
,
process
.pid
,
process
.state
,
process
.name
);
}
}
}
...
...
@@ -146,7 +152,13 @@ pub(crate) fn fg(shell: &mut Shell, args: &[&str]) -> i32 {
/// Resumes a stopped background process, if it was stopped.
pub
(
crate
)
fn
bg
(
shell
:
&
mut
Shell
,
args
:
&
[
&
str
])
->
i32
{
fn
bg_job
(
shell
:
&
mut
Shell
,
njob
:
u32
)
->
bool
{
if
let
Some
(
job
)
=
shell
.background
.lock
()
.unwrap
()
.iter_mut
()
.nth
(
njob
as
usize
)
{
if
let
Some
(
job
)
=
shell
.background
.lock
()
.unwrap
()
.iter_mut
()
.nth
(
njob
as
usize
)
{
match
job
.state
{
ProcessState
::
Running
=>
{
eprintln!
(
"ion: bg: job {} is already running"
,
njob
);
...
...
src/builtins/man_pages.rs
View file @
d195ccaf
...
...
@@ -4,7 +4,10 @@ use std::io::{stdout, Write};
pub
(
crate
)
fn
print_man
(
man_page
:
&
'static
str
)
{
let
stdout
=
stdout
();
let
mut
stdout
=
stdout
.lock
();
match
stdout
.write_all
(
man_page
.as_bytes
())
.and_then
(|
_
|
stdout
.flush
())
{
match
stdout
.write_all
(
man_page
.as_bytes
())
.and_then
(|
_
|
stdout
.flush
())
{
Ok
(
_
)
=>
(),
Err
(
err
)
=>
panic!
(
"{}"
,
err
.description
()
.to_owned
()),
}
...
...
@@ -14,7 +17,7 @@ pub(crate) fn check_help(args: &[&str], man_page: &'static str) -> bool {
for
arg
in
args
{
if
*
arg
==
"-h"
||
*
arg
==
"--help"
{
print_man
(
man_page
);
return
true
return
true
;
}
}
false
...
...
@@ -106,31 +109,33 @@ DESCRIPTION
pushd adds directories to the stack.
"#
;
/*pub(crate) const MAN_FN: &'static str = r#"NAME
fn - print a list of all functions or create a function
SYNOPSIS
fn
fn example arg:int
echo $arg
end
DESCRIPTION
fn prints a list of all functions that exist in the shell or creates a function when combined
with the 'end' keyword. Functions can have type hints, to tell ion to check the type of a
functions arguments. An error will occur if an argument supplied to a function is of the wrong type.
The supported types in ion are, [], bool, bool[], float, float[], int, int[], str, str[].
Functions are called by typing the function name and then the function arguments, separated
by a space.
fn example arg0:int arg1:int
echo $arg
end
example 1
"#;*/
// pub(crate) const MAN_FN: &'static str = r#"NAME
// fn - print a list of all functions or create a function
//
// SYNOPSIS
// fn
//
// fn example arg:int
// echo $arg
// end
//
// DESCRIPTION
// fn prints a list of all functions that exist in the shell or creates a
// function when combined with the 'end' keyword. Functions can have type
// hints, to tell ion to check the type of a functions arguments. An error will
// occur if an argument supplied to a function is of the wrong type.
// The supported types in ion are, [], bool, bool[], float, float[], int,
// int[], str, str[].
//
// Functions are called by typing the function name and then the function
// arguments, separated by a space.
//
// fn example arg0:int arg1:int
// echo $arg
// end
//
// example 1
// "#;
pub
(
crate
)
const
MAN_READ
:
&
'static
str
=
r#"NAME
read - read a line of input into some variables
...
...
@@ -582,4 +587,4 @@ SYNOPSIS
DESCRIPTION
The which utility takes a list of command names and searches for the
alias/builtin/function/executable that would be executed if you ran that command.
"#
;
\ No newline at end of file
"#
;
src/builtins/mod.rs
View file @
d195ccaf
...
...
@@ -60,8 +60,8 @@ macro_rules! map {
}
}}
/// If you are implementing a builtin add it to the table below, create a well named manpage in
man_pages
/// and check for help flags by adding to the start of your builtin the following
/// If you are implementing a builtin add it to the table below, create a well named manpage in
///
man_pages
and check for help flags by adding to the start of your builtin the following
/// if check_help(args, MAN_CD) {
/// return SUCCESS
/// }
...
...
@@ -120,8 +120,8 @@ pub struct Builtin {
}
pub
struct
BuiltinMap
{
pub
(
crate
)
name
:
&
'static
[
&
'static
str
],
pub
(
crate
)
help
:
&
'static
[
&
'static
str
],
pub
(
crate
)
name
:
&
'static
[
&
'static
str
],
pub
(
crate
)
help
:
&
'static
[
&
'static
str
],
pub
(
crate
)
functions
:
&
'static
[
BuiltinFunction
],
}
...
...
@@ -136,9 +136,13 @@ impl BuiltinMap {
})
}
pub
fn
keys
(
&
self
)
->
&
'static
[
&
'static
str
]
{
self
.name
}
pub
fn
keys
(
&
self
)
->
&
'static
[
&
'static
str
]
{
self
.name
}
pub
fn
contains_key
(
&
self
,
func
:
&
str
)
->
bool
{
self
.name
.iter
()
.any
(|
&
name
|
name
==
func
)
}
pub
fn
contains_key
(
&
self
,
func
:
&
str
)
->
bool
{
self
.name
.iter
()
.any
(|
&
name
|
name
==
func
)
}
}
// Definitions of simple builtins go here
...
...
@@ -156,7 +160,7 @@ fn builtin_status(args: &[&str], shell: &mut Shell) -> i32 {
pub
fn
builtin_cd
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_CD
)
{
return
SUCCESS
return
SUCCESS
;
}
match
shell
.directory_stack
.cd
(
args
,
&
shell
.variables
)
{
...
...
@@ -212,15 +216,15 @@ fn builtin_is(args: &[&str], shell: &mut Shell) -> i32 {
fn
builtin_dirs
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_DIRS
)
{
return
SUCCESS
return
SUCCESS
;
}
shell
.directory_stack
.dirs
(
args
)
shell
.directory_stack
.dirs
(
args
)
}
fn
builtin_pushd
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_PUSHD
)
{
return
SUCCESS
return
SUCCESS
;
}
match
shell
.directory_stack
.pushd
(
args
,
&
shell
.variables
)
{
Ok
(())
=>
SUCCESS
,
...
...
@@ -235,7 +239,7 @@ fn builtin_pushd(args: &[&str], shell: &mut Shell) -> i32 {
fn
builtin_popd
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_POPD
)
{
return
SUCCESS
return
SUCCESS
;
}
match
shell
.directory_stack
.popd
(
args
)
{
...
...
@@ -258,21 +262,22 @@ fn builtin_unalias(args: &[&str], shell: &mut Shell) -> i32 {
drop_alias
(
&
mut
shell
.variables
,
args
)
}
// TODO There is a man page for fn however the -h and --help flags are not checked for.
// TODO There is a man page for fn however the -h and --help flags are not
// checked for.
fn
builtin_fn
(
_
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
fn_
(
&
mut
shell
.functions
)
}
fn
builtin_read
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_READ
)
{
return
SUCCESS
return
SUCCESS
;
}
shell
.variables
.read
(
args
)
shell
.variables
.read
(
args
)
}
fn
builtin_drop
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_DROP
)
{
return
SUCCESS
return
SUCCESS
;
}
if
args
.len
()
>=
2
&&
args
[
1
]
==
"-a"
{
drop_array
(
&
mut
shell
.variables
,
args
)
...
...
@@ -283,14 +288,14 @@ fn builtin_drop(args: &[&str], shell: &mut Shell) -> i32 {
fn
builtin_set
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_SET
)
{
return
SUCCESS
return
SUCCESS
;
}
set
::
set
(
args
,
shell
)
}
fn
builtin_eval
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_EVAL
)
{
return
SUCCESS
return
SUCCESS
;
}
let
evaluated_command
=
args
[
1
..
]
.join
(
" "
);
let
mut
buffer
=
Terminator
::
new
(
evaluated_command
);
...
...
@@ -305,16 +310,16 @@ fn builtin_eval(args: &[&str], shell: &mut Shell) -> i32 {
}
}
fn
builtin_history
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
fn
builtin_history
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_HISTORY
)
{
return
SUCCESS
return
SUCCESS
;
}
shell
.print_history
(
args
)
}
fn
builtin_source
(
args
:
&
[
&
str
],
shell
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_SOURCE
)
{
return
SUCCESS
return
SUCCESS
;
}
match
source
(
shell
,
args
)
{
Ok
(())
=>
SUCCESS
,
...
...
@@ -329,7 +334,7 @@ fn builtin_source(args: &[&str], shell: &mut Shell) -> i32 {
fn
builtin_echo
(
args
:
&
[
&
str
],
_
:
&
mut
Shell
)
->
i32
{
if
check_help
(
args
,
MAN_ECHO
)
{
return
SUCCESS