Skip to content

Commit 6e5886b

Browse files
committed
Support shopt -u and -s
1 parent 4505dc0 commit 6e5886b

File tree

2 files changed

+69
-49
lines changed

2 files changed

+69
-49
lines changed

src/core/builtins/shopt.rs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,42 @@
33

44
use crate::ShellCore;
55

6-
pub fn shopt(core: &mut ShellCore, args: &mut Vec<String>) -> i32 {
7-
if args.len() == 1 {
6+
pub fn shopt_print(core: &mut ShellCore, args: &mut Vec<String>, all: bool) -> i32 {
7+
if all {
88
core.shopts.print_all();
99
return 0;
1010
}
1111

12-
if args[1] == "-s" {
13-
if args.len() == 2 {
14-
core.shopts.print_if(true);
15-
}else{
16-
core.shopts.set(&args[2], true);
17-
}
18-
return 0;
12+
let mut res = true;
13+
match args[1].as_str() {
14+
"-s" => core.shopts.print_if(true),
15+
"-u" => core.shopts.print_if(false),
16+
opt => res = core.shopts.print_opt(opt),
1917
}
2018

21-
if args[1] == "-u" {
22-
if args.len() == 2 {
23-
core.shopts.print_if(false);
24-
}else{
25-
core.shopts.set(&args[2], false);
26-
}
27-
return 0;
19+
match res {
20+
true => 0,
21+
false => 1,
2822
}
23+
}
2924

30-
0
25+
pub fn shopt(core: &mut ShellCore, args: &mut Vec<String>) -> i32 {
26+
if args.len() < 3 {
27+
return shopt_print(core, args, args.len() < 2);
28+
}
29+
30+
let res = match args[1].as_str() {
31+
"-s" => core.shopts.set(&args[2], true),
32+
"-u" => core.shopts.set(&args[2], false),
33+
arg => {
34+
eprintln!("sush: shopt: {}: invalid shell option name", arg);
35+
eprintln!("shopt: usage: shopt [-su] [optname ...]");
36+
false
37+
},
38+
};
39+
40+
match res {
41+
true => 0,
42+
false => 1,
43+
}
3144
}

src/core/shopts.rs

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -36,44 +36,45 @@ impl Shopts {
3636
shopts
3737
}
3838

39-
pub fn print_all(&self) {
40-
let mut list = vec![];
41-
42-
for opt in &self.opts {
43-
let onoff = match opt.1 {
44-
true => "on",
45-
false => "off",
46-
};
47-
if opt.0.len() < 16 {
48-
list.push(format!("{:16}{}", opt.0, onoff));
49-
}else{
50-
list.push(format!("{}\t{}", opt.0, onoff));
51-
}
52-
}
53-
54-
list.sort();
55-
list.iter().for_each(|e| println!("{}", e));
56-
}
57-
58-
pub fn print_if(&self, onoff: bool) {
59-
let mut list = vec![];
60-
39+
pub fn format(opt: &str, onoff: bool) -> String {
6140
let onoff_str = match onoff {
6241
true => "on",
6342
false => "off",
6443
};
6544

66-
for opt in &self.opts {
67-
if *opt.1 != onoff {
68-
continue;
69-
}
45+
match opt.len() < 16 {
46+
true => format!("{:16}{}", opt, onoff_str),
47+
false => format!("{}\t{}", opt, onoff_str),
48+
}
49+
}
7050

71-
if opt.0.len() < 16 {
72-
list.push(format!("{:16}{}", opt.0, onoff_str));
73-
}else{
74-
list.push(format!("{}\t{}", opt.0, onoff_str));
75-
}
51+
pub fn print_opt(&self, opt: &str) -> bool {
52+
match self.opts.get_key_value(opt) {
53+
None => {
54+
eprintln!("sush: shopt: {}: invalid shell option name", opt);
55+
false
56+
},
57+
Some(kv) => {
58+
println!("{}", Self::format(kv.0, *kv.1));
59+
true
60+
},
7661
}
62+
}
63+
64+
pub fn print_all(&self) {
65+
let mut list = self.opts.iter()
66+
.map(|opt| Self::format(opt.0, *opt.1))
67+
.collect::<Vec<String>>();
68+
69+
list.sort();
70+
list.iter().for_each(|e| println!("{}", e));
71+
}
72+
73+
pub fn print_if(&self, onoff: bool) {
74+
let mut list = self.opts.iter()
75+
.filter(|opt| *opt.1 == onoff)
76+
.map(|opt| Self::format(opt.0, *opt.1))
77+
.collect::<Vec<String>>();
7778

7879
list.sort();
7980
list.iter().for_each(|e| println!("{}", e));
@@ -83,7 +84,13 @@ impl Shopts {
8384
self.opts[opt]
8485
}
8586

86-
pub fn set(&mut self, opt: &str, onoff: bool) {
87+
pub fn set(&mut self, opt: &str, onoff: bool) -> bool {
88+
if ! self.opts.contains_key(opt) {
89+
eprintln!("sush: shopt: {}: invalid shell option name", opt);
90+
return false;
91+
}
92+
8793
self.opts.insert(opt.to_string(), onoff);
94+
true
8895
}
8996
}

0 commit comments

Comments
 (0)