Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
vnotepad
Exa
提交
728e7dd9
E
Exa
项目概览
vnotepad
/
Exa
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
Exa
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
728e7dd9
编写于
1月 13, 2015
作者:
B
Benjamin Sago
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Forbid certain argument combinations
上级
3d59a48e
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
133 addition
and
65 deletion
+133
-65
src/column.rs
src/column.rs
+2
-0
src/exa.rs
src/exa.rs
+12
-0
src/options.rs
src/options.rs
+118
-65
src/output.rs
src/output.rs
+1
-0
未找到文件。
src/column.rs
浏览文件 @
728e7dd9
use
std
::
iter
::
repeat
;
#[derive(PartialEq,
Show)]
pub
enum
Column
{
Permissions
,
FileName
,
...
...
@@ -13,6 +14,7 @@ pub enum Column {
impl
Copy
for
Column
{
}
#[derive(PartialEq,
Show)]
pub
enum
SizeFormat
{
DecimalBytes
,
BinaryBytes
,
...
...
src/exa.rs
浏览文件 @
728e7dd9
...
...
@@ -98,5 +98,17 @@ fn main() {
println!
(
"{}"
,
e
);
set_exit_status
(
3
);
},
Err
(
Conflict
(
a
,
b
))
=>
{
println!
(
"Option --{} conflicts with option {}"
,
a
,
b
);
set_exit_status
(
3
);
},
Err
(
Useless
(
a
,
false
,
b
))
=>
{
println!
(
"Option --{} is useless without option --{}"
,
a
,
b
);
set_exit_status
(
3
);
},
Err
(
Useless
(
a
,
true
,
b
))
=>
{
println!
(
"Option --{} is useless given option --{}"
,
a
,
b
);
set_exit_status
(
3
);
},
};
}
src/options.rs
浏览文件 @
728e7dd9
...
...
@@ -10,6 +10,7 @@ use term::dimensions;
use
std
::
ascii
::
AsciiExt
;
use
std
::
slice
::
Iter
;
#[derive(PartialEq,
Show)]
pub
enum
SortField
{
Unsorted
,
Name
,
Extension
,
Size
,
FileInode
}
...
...
@@ -33,6 +34,7 @@ fn no_sort_field(field: &str) -> Error {
Error
::
InvalidOptions
(
getopts
::
Fail
::
UnrecognizedOption
(
format!
(
"--sort {}"
,
field
)))
}
#[derive(PartialEq,
Show)]
pub
struct
Options
{
pub
list_dirs
:
bool
,
pub
path_strs
:
Vec
<
String
>
,
...
...
@@ -42,10 +44,12 @@ pub struct Options {
pub
view
:
View
,
}
#[derive(Show)]
#[derive(
PartialEq,
Show)]
pub
enum
Error
{
InvalidOptions
(
getopts
::
Fail
),
Help
(
String
),
Conflict
(
&
'static
str
,
&
'static
str
),
Useless
(
&
'static
str
,
bool
,
&
'static
str
),
}
impl
Options
{
...
...
@@ -88,7 +92,7 @@ impl Options {
reverse
:
matches
.opt_present
(
"reverse"
),
show_invisibles
:
matches
.opt_present
(
"all"
),
sort_field
:
sort_field
,
view
:
Options
::
view
(
&
matches
),
view
:
try!
(
view
(
&
matches
)
),
})
}
...
...
@@ -96,90 +100,113 @@ impl Options {
self
.path_strs
.iter
()
}
fn
view
(
matches
:
&
getopts
::
Matches
)
->
View
{
if
matches
.opt_present
(
"long"
)
{
View
::
Details
(
Options
::
columns
(
matches
),
matches
.opt_present
(
"header"
))
pub
fn
transform_files
<
'a
>
(
&
self
,
unordered_files
:
Vec
<
File
<
'a
>>
)
->
Vec
<
File
<
'a
>>
{
let
mut
files
:
Vec
<
File
<
'a
>>
=
unordered_files
.into_iter
()
.filter
(|
f
|
self
.should_display
(
f
))
.collect
();
match
self
.sort_field
{
SortField
::
Unsorted
=>
{},
SortField
::
Name
=>
files
.sort_by
(|
a
,
b
|
natord
::
compare
(
a
.name
.as_slice
(),
b
.name
.as_slice
())),
SortField
::
Size
=>
files
.sort_by
(|
a
,
b
|
a
.stat.size
.cmp
(
&
b
.stat.size
)),
SortField
::
FileInode
=>
files
.sort_by
(|
a
,
b
|
a
.stat.unstable.inode
.cmp
(
&
b
.stat.unstable.inode
)),
SortField
::
Extension
=>
files
.sort_by
(|
a
,
b
|
{
let
exts
=
a
.ext
.clone
()
.map
(|
e
|
e
.to_ascii_lowercase
())
.cmp
(
&
b
.ext
.clone
()
.map
(|
e
|
e
.to_ascii_lowercase
()));
let
names
=
a
.name
.to_ascii_lowercase
()
.cmp
(
&
b
.name
.to_ascii_lowercase
());
exts
.cmp
(
&
names
)
}),
}
else
if
matches
.opt_present
(
"oneline"
)
{
View
::
Lines
if
self
.reverse
{
files
.reverse
();
}
files
}
fn
should_display
(
&
self
,
f
:
&
File
)
->
bool
{
if
self
.show_invisibles
{
true
}
else
{
match
dimensions
()
{
None
=>
View
::
Lines
,
Some
((
width
,
_
))
=>
View
::
Grid
(
matches
.opt_present
(
"across"
),
width
),
}
!
f
.name
.as_slice
()
.starts_with
(
"."
)
}
}
}
fn
columns
(
matches
:
&
getopts
::
Matches
)
->
Vec
<
Column
>
{
let
mut
columns
=
vec!
[];
if
matches
.opt_present
(
"inode"
)
{
columns
.push
(
Inode
);
fn
view
(
matches
:
&
getopts
::
Matches
)
->
Result
<
View
,
Error
>
{
if
matches
.opt_present
(
"long"
)
{
if
matches
.opt_present
(
"across"
)
{
Err
(
Error
::
Useless
(
"across"
,
true
,
"long"
))
}
columns
.push
(
Permissions
);
if
matches
.opt_present
(
"links"
)
{
columns
.push
(
HardLinks
);
else
if
matches
.opt_present
(
"oneline"
)
{
Err
(
Error
::
Useless
(
"across"
,
true
,
"long"
))
}
if
matches
.opt_present
(
"binary"
)
{
columns
.push
(
FileSize
(
SizeFormat
::
BinaryBytes
))
else
{
Ok
(
View
::
Details
(
try!
(
columns
(
matches
)),
matches
.opt_present
(
"header"
)))
}
else
if
matches
.opt_present
(
"bytes"
)
{
columns
.push
(
FileSize
(
SizeFormat
::
JustBytes
))
}
else
if
matches
.opt_present
(
"binary"
)
{
Err
(
Error
::
Useless
(
"binary"
,
false
,
"long"
))
}
else
if
matches
.opt_present
(
"bytes"
)
{
Err
(
Error
::
Useless
(
"bytes"
,
false
,
"long"
))
}
else
if
matches
.opt_present
(
"oneline"
)
{
if
matches
.opt_present
(
"across"
)
{
Err
(
Error
::
Useless
(
"across"
,
true
,
"oneline"
))
}
else
{
columns
.push
(
FileSize
(
SizeFormat
::
DecimalBytes
)
)
Ok
(
View
::
Lines
)
}
if
matches
.opt_present
(
"blocks"
)
{
columns
.push
(
Blocks
);
}
else
{
match
dimensions
()
{
None
=>
Ok
(
View
::
Lines
),
Some
((
width
,
_
))
=>
Ok
(
View
::
Grid
(
matches
.opt_present
(
"across"
),
width
)),
}
}
}
columns
.push
(
User
);
fn
file_size
(
matches
:
&
getopts
::
Matches
)
->
Result
<
SizeFormat
,
Error
>
{
let
binary
=
matches
.opt_present
(
"binary"
);
let
bytes
=
matches
.opt_present
(
"bytes"
);
if
matches
.opt_present
(
"group"
)
{
columns
.push
(
Group
);
}
match
(
binary
,
bytes
)
{
(
true
,
true
)
=>
Err
(
Error
::
Conflict
(
"binary"
,
"bytes"
)),
(
true
,
false
)
=>
Ok
(
SizeFormat
::
BinaryBytes
),
(
false
,
true
)
=>
Ok
(
SizeFormat
::
JustBytes
),
(
false
,
false
)
=>
Ok
(
SizeFormat
::
DecimalBytes
),
}
}
fn
columns
(
matches
:
&
getopts
::
Matches
)
->
Result
<
Vec
<
Column
>
,
Error
>
{
let
mut
columns
=
vec!
[];
columns
.push
(
FileName
);
columns
if
matches
.opt_present
(
"inode"
)
{
columns
.push
(
Inode
);
}
fn
should_display
(
&
self
,
f
:
&
File
)
->
bool
{
if
self
.show_invisibles
{
true
}
else
{
!
f
.name
.as_slice
()
.starts_with
(
"."
)
}
columns
.push
(
Permissions
);
if
matches
.opt_present
(
"links"
)
{
columns
.push
(
HardLinks
);
}
pub
fn
transform_files
<
'a
>
(
&
self
,
unordered_files
:
Vec
<
File
<
'a
>>
)
->
Vec
<
File
<
'a
>>
{
let
mut
files
:
Vec
<
File
<
'a
>>
=
unordered_files
.into_iter
()
.filter
(|
f
|
self
.should_display
(
f
))
.collect
();
columns
.push
(
FileSize
(
try!
(
file_size
(
matches
))));
match
self
.sort_field
{
SortField
::
Unsorted
=>
{},
SortField
::
Name
=>
files
.sort_by
(|
a
,
b
|
natord
::
compare
(
a
.name
.as_slice
(),
b
.name
.as_slice
())),
SortField
::
Size
=>
files
.sort_by
(|
a
,
b
|
a
.stat.size
.cmp
(
&
b
.stat.size
)),
SortField
::
FileInode
=>
files
.sort_by
(|
a
,
b
|
a
.stat.unstable.inode
.cmp
(
&
b
.stat.unstable.inode
)),
SortField
::
Extension
=>
files
.sort_by
(|
a
,
b
|
{
let
exts
=
a
.ext
.clone
()
.map
(|
e
|
e
.to_ascii_lowercase
())
.cmp
(
&
b
.ext
.clone
()
.map
(|
e
|
e
.to_ascii_lowercase
()));
let
names
=
a
.name
.to_ascii_lowercase
()
.cmp
(
&
b
.name
.to_ascii_lowercase
());
exts
.cmp
(
&
names
)
}),
}
if
matches
.opt_present
(
"blocks"
)
{
columns
.push
(
Blocks
);
}
if
self
.reverse
{
files
.reverse
();
}
columns
.push
(
User
);
files
if
matches
.opt_present
(
"group"
)
{
columns
.push
(
Group
);
}
columns
.push
(
FileName
);
Ok
(
columns
)
}
#[cfg(test)]
...
...
@@ -220,8 +247,34 @@ mod test {
}
#[test]
fn
view
()
{
let
opts
=
Options
::
getopts
(
&
[
"this file"
.to_string
(),
"that file"
.to_string
()
]);
assert_eq!
(
opts
.unwrap
()
.path_strs
,
vec!
[
"this file"
.to_string
(),
"that file"
.to_string
()
])
fn
file_sizes
()
{
let
opts
=
Options
::
getopts
(
&
[
"--long"
.to_string
(),
"--binary"
.to_string
(),
"--bytes"
.to_string
()
]);
assert_eq!
(
opts
.unwrap_err
(),
Error
::
Conflict
(
"binary"
,
"bytes"
))
}
#[test]
fn
just_binary
()
{
let
opts
=
Options
::
getopts
(
&
[
"--binary"
.to_string
()
]);
assert_eq!
(
opts
.unwrap_err
(),
Error
::
Useless
(
"binary"
,
false
,
"long"
))
}
#[test]
fn
just_bytes
()
{
let
opts
=
Options
::
getopts
(
&
[
"--bytes"
.to_string
()
]);
assert_eq!
(
opts
.unwrap_err
(),
Error
::
Useless
(
"bytes"
,
false
,
"long"
))
}
#[test]
fn
long_across
()
{
let
opts
=
Options
::
getopts
(
&
[
"--long"
.to_string
(),
"--across"
.to_string
()
]);
assert_eq!
(
opts
.unwrap_err
(),
Error
::
Useless
(
"across"
,
true
,
"long"
))
}
#[test]
fn
oneline_across
()
{
let
opts
=
Options
::
getopts
(
&
[
"--oneline"
.to_string
(),
"--across"
.to_string
()
]);
assert_eq!
(
opts
.unwrap_err
(),
Error
::
Useless
(
"across"
,
true
,
"oneline"
))
}
}
src/output.rs
浏览文件 @
728e7dd9
...
...
@@ -9,6 +9,7 @@ use users::OSUsers;
use
ansi_term
::
Style
::
Plain
;
use
ansi_term
::
strip_formatting
;
#[derive(PartialEq,
Show)]
pub
enum
View
{
Details
(
Vec
<
Column
>
,
bool
),
Lines
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录