Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
vnotepad
Exa
提交
f505bdc8
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,发现更多精彩内容 >>
提交
f505bdc8
编写于
2月 24, 2015
作者:
B
Ben S
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add --level option to limit tree and recursion
上级
0cb721a6
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
99 addition
and
25 deletion
+99
-25
src/main.rs
src/main.rs
+11
-7
src/options.rs
src/options.rs
+79
-13
src/output/details.rs
src/output/details.rs
+9
-5
未找到文件。
src/main.rs
浏览文件 @
f505bdc8
#![feature(collections,
core,
env,
libc,
old_io,
old_path,
plugin,
std_misc)]
// Other platforms then macos don’t need std_misc but you can’t
// Other platforms than macos don't need std_misc but you can't
// use #[cfg] on features.
#![allow(unused_features)]
#![allow(unused_features)]
extern
crate
ansi_term
;
extern
crate
datetime
;
...
...
@@ -17,10 +18,11 @@ extern crate git2;
use
std
::
env
;
use
std
::
old_io
::{
fs
,
FileType
};
use
std
::
path
::
Component
::
CurDir
;
use
dir
::
Dir
;
use
file
::
File
;
use
options
::{
Options
,
View
,
DirAction
};
use
options
::{
Options
,
View
};
use
output
::
lines_view
;
pub
mod
column
;
...
...
@@ -58,7 +60,7 @@ impl<'a> Exa<'a> {
match
fs
::
stat
(
&
path
)
{
Ok
(
stat
)
=>
{
if
stat
.kind
==
FileType
::
Directory
{
if
self
.options.dir_action
==
DirAction
::
Tree
{
if
self
.options.dir_action
.is_tree
()
{
self
.files
.push
(
File
::
with_stat
(
stat
,
&
path
,
None
,
true
));
}
else
{
...
...
@@ -111,9 +113,11 @@ impl<'a> Exa<'a> {
// backwards: the *last* element of the stack is used each
// time, so by inserting them backwards, they get displayed in
// the correct sort order.
if
self
.options.dir_action
==
DirAction
::
Recurse
{
for
dir
in
files
.iter
()
.filter
(|
f
|
f
.stat.kind
==
FileType
::
Directory
)
.rev
()
{
self
.dirs
.push
(
dir
.path
.clone
());
if
let
Some
(
recurse_opts
)
=
self
.options.dir_action
.recurse_options
()
{
if
!
recurse_opts
.tree
&&
!
recurse_opts
.is_too_deep
(
dir_path
.components
()
.count
()
+
1
)
{
for
dir
in
files
.iter
()
.filter
(|
f
|
f
.stat.kind
==
FileType
::
Directory
)
.rev
()
{
self
.dirs
.push
(
dir
.path
.clone
());
}
}
}
...
...
src/options.rs
浏览文件 @
f505bdc8
...
...
@@ -8,6 +8,7 @@ use xattr;
use
std
::
cmp
::
Ordering
;
use
std
::
fmt
;
use
std
::
num
::
ParseIntError
;
use
getopts
;
use
natord
;
...
...
@@ -44,11 +45,6 @@ impl Options {
/// Call getopts on the given slice of command-line strings.
pub
fn
getopts
(
args
:
&
[
String
])
->
Result
<
(
Options
,
Vec
<
String
>
),
Misfire
>
{
let
mut
opts
=
getopts
::
Options
::
new
();
if
xattr
::
feature_implemented
()
{
opts
.optflag
(
"@"
,
"extended"
,
"display extended attribute keys and sizes in long (-l) output"
);
}
opts
.optflag
(
"1"
,
"oneline"
,
"display one entry per line"
);
opts
.optflag
(
"a"
,
"all"
,
"show dot-files"
);
opts
.optflag
(
"b"
,
"binary"
,
"use binary prefixes in file sizes"
);
...
...
@@ -59,6 +55,7 @@ impl Options {
opts
.optflag
(
"H"
,
"links"
,
"show number of hard links"
);
opts
.optflag
(
"i"
,
"inode"
,
"show each file's inode number"
);
opts
.optflag
(
"l"
,
"long"
,
"display extended details and attributes"
);
opts
.optopt
(
"L"
,
"level"
,
"maximum depth of recursion"
,
"DEPTH"
);
opts
.optflag
(
"m"
,
"modified"
,
"display timestamp of most recent modification"
);
opts
.optflag
(
"r"
,
"reverse"
,
"reverse order of files"
);
opts
.optflag
(
"R"
,
"recurse"
,
"recurse into directories"
);
...
...
@@ -71,6 +68,10 @@ impl Options {
opts
.optflag
(
"x"
,
"across"
,
"sort multi-column view entries across"
);
opts
.optflag
(
"?"
,
"help"
,
"show list of command-line options"
);
if
xattr
::
feature_implemented
()
{
opts
.optflag
(
"@"
,
"extended"
,
"display extended attribute keys and sizes in long (-l) output"
);
}
let
matches
=
match
opts
.parse
(
args
)
{
Ok
(
m
)
=>
m
,
Err
(
e
)
=>
return
Err
(
Misfire
::
InvalidOptions
(
e
)),
...
...
@@ -98,9 +99,12 @@ impl Options {
matches
.free
.clone
()
};
let
dir_action
=
try!
(
DirAction
::
deduce
(
&
matches
));
let
view
=
try!
(
View
::
deduce
(
&
matches
,
filter
,
dir_action
));
Ok
((
Options
{
dir_action
:
try!
(
DirAction
::
deduce
(
&
matches
))
,
view
:
try!
(
View
::
deduce
(
&
matches
,
filter
))
,
dir_action
:
dir_action
,
view
:
view
,
filter
:
filter
,
},
path_strs
))
}
...
...
@@ -179,12 +183,15 @@ pub enum Misfire {
/// this enum isn't named Error!
Help
(
String
),
/// Two options were given that conflict with one another
/// Two options were given that conflict with one another
.
Conflict
(
&
'static
str
,
&
'static
str
),
/// An option was given that does nothing when another one either is or
/// isn't present.
Useless
(
&
'static
str
,
bool
,
&
'static
str
),
/// A numeric option was given that failed to be parsed as a number.
FailedParse
(
ParseIntError
),
}
impl
Misfire
{
...
...
@@ -203,12 +210,13 @@ impl fmt::Display for Misfire {
Conflict
(
a
,
b
)
=>
write!
(
f
,
"Option --{} conflicts with option {}."
,
a
,
b
),
Useless
(
a
,
false
,
b
)
=>
write!
(
f
,
"Option --{} is useless without option --{}."
,
a
,
b
),
Useless
(
a
,
true
,
b
)
=>
write!
(
f
,
"Option --{} is useless given option --{}."
,
a
,
b
),
FailedParse
(
ref
e
)
=>
write!
(
f
,
"Failed to parse number: {}"
,
e
),
}
}
}
impl
View
{
pub
fn
deduce
(
matches
:
&
getopts
::
Matches
,
filter
:
FileFilter
)
->
Result
<
View
,
Misfire
>
{
pub
fn
deduce
(
matches
:
&
getopts
::
Matches
,
filter
:
FileFilter
,
dir_action
:
DirAction
)
->
Result
<
View
,
Misfire
>
{
if
matches
.opt_present
(
"long"
)
{
if
matches
.opt_present
(
"across"
)
{
Err
(
Misfire
::
Useless
(
"across"
,
true
,
"long"
))
...
...
@@ -220,7 +228,7 @@ impl View {
let
details
=
Details
{
columns
:
try!
(
Columns
::
deduce
(
matches
)),
header
:
matches
.opt_present
(
"header"
),
tree
:
matches
.opt_present
(
"recurse"
)
||
matches
.opt_present
(
"tree"
),
recurse
:
dir_action
.recurse_options
(
),
xattr
:
xattr
::
feature_implemented
()
&&
matches
.opt_present
(
"extended"
),
filter
:
filter
,
};
...
...
@@ -373,7 +381,9 @@ impl TimeTypes {
/// What to do when encountering a directory?
#[derive(PartialEq,
Debug,
Copy)]
pub
enum
DirAction
{
AsFile
,
List
,
Recurse
,
Tree
AsFile
,
List
,
Recurse
(
RecurseOptions
),
}
impl
DirAction
{
...
...
@@ -385,12 +395,68 @@ impl DirAction {
match
(
recurse
,
list
,
tree
)
{
(
true
,
true
,
_
)
=>
Err
(
Misfire
::
Conflict
(
"recurse"
,
"list-dirs"
)),
(
_
,
true
,
true
)
=>
Err
(
Misfire
::
Conflict
(
"tree"
,
"list-dirs"
)),
(
true
,
false
,
false
)
=>
Ok
(
DirAction
::
Recurse
),
(
_
,
_
,
true
)
=>
Ok
(
DirAction
::
Tree
),
(
true
,
false
,
false
)
=>
Ok
(
DirAction
::
Recurse
(
try!
(
RecurseOptions
::
deduce
(
matches
,
false
)))
),
(
_
,
_
,
true
)
=>
Ok
(
DirAction
::
Recurse
(
try!
(
RecurseOptions
::
deduce
(
matches
,
true
)))
),
(
false
,
true
,
_
)
=>
Ok
(
DirAction
::
AsFile
),
(
false
,
false
,
_
)
=>
Ok
(
DirAction
::
List
),
}
}
pub
fn
recurse_options
(
&
self
)
->
Option
<
RecurseOptions
>
{
match
*
self
{
DirAction
::
Recurse
(
opts
)
=>
Some
(
opts
),
_
=>
None
,
}
}
pub
fn
is_tree
(
&
self
)
->
bool
{
match
*
self
{
DirAction
::
Recurse
(
RecurseOptions
{
max_depth
:
_
,
tree
})
=>
tree
,
_
=>
false
,
}
}
pub
fn
is_recurse
(
&
self
)
->
bool
{
match
*
self
{
DirAction
::
Recurse
(
RecurseOptions
{
max_depth
:
_
,
tree
})
=>
!
tree
,
_
=>
false
,
}
}
}
#[derive(PartialEq,
Debug,
Copy)]
pub
struct
RecurseOptions
{
pub
tree
:
bool
,
pub
max_depth
:
Option
<
usize
>
,
}
impl
RecurseOptions
{
pub
fn
deduce
(
matches
:
&
getopts
::
Matches
,
tree
:
bool
)
->
Result
<
RecurseOptions
,
Misfire
>
{
let
max_depth
=
if
let
Some
(
level
)
=
matches
.opt_str
(
"level"
)
{
match
level
.parse
()
{
Ok
(
l
)
=>
Some
(
l
),
Err
(
e
)
=>
return
Err
(
Misfire
::
FailedParse
(
e
)),
}
}
else
{
None
};
Ok
(
RecurseOptions
{
tree
:
tree
,
max_depth
:
max_depth
,
})
}
pub
fn
is_too_deep
(
&
self
,
depth
:
usize
)
->
bool
{
match
self
.max_depth
{
None
=>
false
,
Some
(
d
)
=>
{
println!
(
"Comparing {} to {}"
,
d
,
depth
);
d
<=
depth
}
}
}
}
#[derive(PartialEq,
Copy,
Debug)]
...
...
src/output/details.rs
浏览文件 @
f505bdc8
...
...
@@ -2,7 +2,7 @@ use column::{Alignment, Column, Cell};
use
xattr
::
Attribute
;
use
dir
::
Dir
;
use
file
::{
File
,
GREY
};
use
options
::{
Columns
,
FileFilter
};
use
options
::{
Columns
,
FileFilter
,
RecurseOptions
};
use
users
::
OSUsers
;
use
locale
;
...
...
@@ -12,7 +12,7 @@ use ansi_term::Style::Plain;
pub
struct
Details
{
pub
columns
:
Columns
,
pub
header
:
bool
,
pub
tree
:
bool
,
pub
recurse
:
Option
<
RecurseOptions
>
,
pub
xattr
:
bool
,
pub
filter
:
FileFilter
,
}
...
...
@@ -57,7 +57,7 @@ impl Details {
print!
(
"{} "
,
column
.alignment
()
.pad_string
(
&
row
.cells
[
num
]
.text
,
padding
));
}
if
self
.
tree
{
if
self
.
recurse
.is_some
()
{
stack
.resize
(
row
.depth
+
1
,
"├──"
);
stack
[
row
.depth
]
=
if
row
.last
{
"└──"
}
else
{
"├──"
};
...
...
@@ -75,7 +75,7 @@ impl Details {
}
print!
(
"{}
\n
"
,
row
.name
);
if
self
.xattr
{
let
width
=
row
.attrs
.iter
()
.map
(|
a
|
a
.name
()
.len
())
.max
()
.unwrap_or
(
0
);
for
attr
in
row
.attrs
.iter
()
{
...
...
@@ -103,7 +103,11 @@ impl Details {
dest
.push
(
row
);
if
self
.tree
{
if
let
Some
(
r
)
=
self
.recurse
{
if
r
.tree
==
false
||
r
.is_too_deep
(
depth
)
{
continue
;
}
if
let
Some
(
ref
dir
)
=
file
.this
{
let
mut
files
=
dir
.files
(
true
);
self
.filter
.transform_files
(
&
mut
files
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录