Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
N
nccf
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
702
Provoz
nccf
Commits
448fa9e7
Commit
448fa9e7
authored
3 years ago
by
Yorhel
Browse files
Options
Downloads
Patches
Plain Diff
Implement shell spawning
parent
6c2ab500
No related branches found
No related tags found
No related merge requests found
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
README.md
+0
-1
0 additions, 1 deletion
README.md
doc/ncdu.pod
+6
-0
6 additions, 0 deletions
doc/ncdu.pod
src/browser.zig
+25
-4
25 additions, 4 deletions
src/browser.zig
src/main.zig
+71
-7
71 additions, 7 deletions
src/main.zig
src/ui.zig
+12
-6
12 additions, 6 deletions
src/ui.zig
with
114 additions
and
18 deletions
README.md
+
0
−
1
View file @
448fa9e7
...
@@ -30,7 +30,6 @@ Missing features:
...
@@ -30,7 +30,6 @@ Missing features:
-
Help window
-
Help window
-
File deletion
-
File deletion
-
Opening a shell
### Improvements compared to the C version
### Improvements compared to the C version
...
...
This diff is collapsed.
Click to expand it.
doc/ncdu.pod
+
6
−
0
View file @
448fa9e7
...
@@ -287,6 +287,12 @@ run ncdu as follows:
...
@@ -287,6 +287,12 @@ run ncdu as follows:
export NCDU_SHELL=vifm
export NCDU_SHELL=vifm
ncdu
ncdu
Ncdu will set the C<NCDU_LEVEL> environment variable or increment it before
spawning the shell. This variable allows you to detect when your shell is
running from within ncdu, which can be useful to avoid nesting multiple
instances of ncdu. Ncdu itself does not (currently) warn when attempting to run
nested instances.
=item q
=item q
Quit
Quit
...
...
This diff is collapsed.
Click to expand it.
src/browser.zig
+
25
−
4
View file @
448fa9e7
...
@@ -7,7 +7,7 @@ const c = @cImport(@cInclude("time.h"));
...
@@ -7,7 +7,7 @@ const c = @cImport(@cInclude("time.h"));
usingnamespace
@import
(
"util.zig"
);
usingnamespace
@import
(
"util.zig"
);
// Currently opened directory and its parents.
// Currently opened directory and its parents.
var
dir_parents
=
model
.
Parents
{};
pub
var
dir_parents
=
model
.
Parents
{};
// Sorted list of all items in the currently opened directory.
// Sorted list of all items in the currently opened directory.
// (first item may be null to indicate the "parent directory" item)
// (first item may be null to indicate the "parent directory" item)
...
@@ -305,6 +305,7 @@ const Row = struct {
...
@@ -305,6 +305,7 @@ const Row = struct {
};
};
var
state
:
enum
{
main
,
quit
,
info
}
=
.
main
;
var
state
:
enum
{
main
,
quit
,
info
}
=
.
main
;
var
message
:
?
[:
0
]
const
u8
=
null
;
const
quit
=
struct
{
const
quit
=
struct
{
fn
draw
()
void
{
fn
draw
()
void
{
...
@@ -625,6 +626,13 @@ pub fn draw() void {
...
@@ -625,6 +626,13 @@ pub fn draw() void {
.
quit
=>
quit
.
draw
(),
.
quit
=>
quit
.
draw
(),
.
info
=>
info
.
draw
(),
.
info
=>
info
.
draw
(),
}
}
if
(
message
)
|
m
|
{
const
box
=
ui
.
Box
.
create
(
6
,
60
,
"Message"
);
box
.
move
(
2
,
2
);
ui
.
addstr
(
m
);
box
.
move
(
4
,
34
);
ui
.
addstr
(
"Press any key to continue"
);
}
if
(
sel_row
>
0
)
ui
.
move
(
sel_row
,
0
);
if
(
sel_row
>
0
)
ui
.
move
(
sel_row
,
0
);
}
}
...
@@ -656,6 +664,11 @@ fn keyInputSelection(ch: i32, idx: *usize, len: usize, page: u32) bool {
...
@@ -656,6 +664,11 @@ fn keyInputSelection(ch: i32, idx: *usize, len: usize, page: u32) bool {
pub
fn
keyInput
(
ch
:
i32
)
void
{
pub
fn
keyInput
(
ch
:
i32
)
void
{
defer
current_view
.
save
();
defer
current_view
.
save
();
if
(
message
!=
null
)
{
message
=
null
;
return
;
}
switch
(
state
)
{
switch
(
state
)
{
.
main
=>
{},
// fallthrough
.
main
=>
{},
// fallthrough
.
quit
=>
return
quit
.
keyInput
(
ch
),
.
quit
=>
return
quit
.
keyInput
(
ch
),
...
@@ -666,13 +679,21 @@ pub fn keyInput(ch: i32) void {
...
@@ -666,13 +679,21 @@ pub fn keyInput(ch: i32) void {
'q'
=>
if
(
main
.
config
.
confirm_quit
)
{
state
=
.
quit
;
}
else
ui
.
quit
(),
'q'
=>
if
(
main
.
config
.
confirm_quit
)
{
state
=
.
quit
;
}
else
ui
.
quit
(),
'i'
=>
info
.
set
(
dir_items
.
items
[
cursor_idx
],
.
info
),
'i'
=>
info
.
set
(
dir_items
.
items
[
cursor_idx
],
.
info
),
'r'
=>
{
'r'
=>
{
if
(
main
.
config
.
imported
)
{
if
(
main
.
config
.
imported
)
// TODO: Display message
message
=
"Directory imported from file, refreshing is disabled."
}
else
{
else
{
main
.
state
=
.
refresh
;
main
.
state
=
.
refresh
;
scan
.
setupRefresh
(
dir_parents
.
copy
());
scan
.
setupRefresh
(
dir_parents
.
copy
());
}
}
},
},
'b'
=>
{
if
(
main
.
config
.
imported
)
message
=
"Shell feature not available for imported directories."
else
if
(
!
main
.
config
.
can_shell
)
message
=
"Shell feature disabled in read-only mode."
else
main
.
state
=
.
shell
;
},
// Sort & filter settings
// Sort & filter settings
'n'
=>
sortToggle
(.
name
,
.
asc
),
'n'
=>
sortToggle
(.
name
,
.
asc
),
...
...
This diff is collapsed.
Click to expand it.
src/main.zig
+
71
−
7
View file @
448fa9e7
...
@@ -67,7 +67,7 @@ pub const config = struct {
...
@@ -67,7 +67,7 @@ pub const config = struct {
pub
var
confirm_quit
:
bool
=
false
;
pub
var
confirm_quit
:
bool
=
false
;
};
};
pub
var
state
:
enum
{
scan
,
browse
,
refresh
}
=
.
scan
;
pub
var
state
:
enum
{
scan
,
browse
,
refresh
,
shell
}
=
.
scan
;
// Simple generic argument parser, supports getopt_long() style arguments.
// Simple generic argument parser, supports getopt_long() style arguments.
// T can be any type that has a 'fn next(T) ?[:0]const u8' method, e.g.:
// T can be any type that has a 'fn next(T) ?[:0]const u8' method, e.g.:
...
@@ -174,6 +174,62 @@ fn help() noreturn {
...
@@ -174,6 +174,62 @@ fn help() noreturn {
std
.
process
.
exit
(
0
);
std
.
process
.
exit
(
0
);
}
}
fn
spawnShell
()
void
{
ui
.
deinit
();
defer
ui
.
init
();
var
path
=
std
.
ArrayList
(
u8
).
init
(
allocator
);
defer
path
.
deinit
();
browser
.
dir_parents
.
fmtPath
(
true
,
&
path
);
var
env
=
std
.
process
.
getEnvMap
(
allocator
)
catch
unreachable
;
defer
env
.
deinit
();
// NCDU_LEVEL can only count to 9, keeps the implementation simple.
if
(
env
.
get
(
"NCDU_LEVEL"
))
|
l
|
env
.
put
(
"NCDU_LEVEL"
,
if
(
l
.
len
==
0
)
"1"
else
switch
(
l
[
0
])
{
'0'
...
'8'
=>
@as
([]
const
u8
,
&.
{
l
[
0
]
+
1
}),
'9'
=>
"9"
,
else
=>
"1"
})
catch
unreachable
else
env
.
put
(
"NCDU_LEVEL"
,
"1"
)
catch
unreachable
;
const
shell
=
std
.
os
.
getenvZ
(
"NCDU_SHELL"
)
orelse
std
.
os
.
getenvZ
(
"SHELL"
)
orelse
"/bin/sh"
;
var
child
=
std
.
ChildProcess
.
init
(
&.
{
shell
},
allocator
)
catch
unreachable
;
defer
child
.
deinit
();
child
.
cwd
=
path
.
items
;
child
.
env_map
=
&
env
;
const
term
=
child
.
spawnAndWait
()
catch
|
e
|
blk
:
{
_
=
std
.
io
.
getStdErr
().
writer
().
print
(
"Error spawning shell: {s}
\n\n
Press enter to continue.
\n
"
,
.
{
ui
.
errorString
(
e
)
}
)
catch
{};
_
=
std
.
io
.
getStdIn
().
reader
().
skipUntilDelimiterOrEof
(
'\n'
)
catch
unreachable
;
break
:
blk
std
.
ChildProcess
.
Term
{
.
Exited
=
0
};
};
if
(
term
!=
.
Exited
)
{
const
n
=
switch
(
term
)
{
.
Exited
=>
"status"
,
.
Signal
=>
"signal"
,
.
Stopped
=>
"stopped"
,
.
Unknown
=>
"unknown"
,
};
const
v
=
switch
(
term
)
{
.
Exited
=>
|
v
|
v
,
.
Signal
=>
|
v
|
v
,
.
Stopped
=>
|
v
|
v
,
.
Unknown
=>
|
v
|
v
,
};
_
=
std
.
io
.
getStdErr
().
writer
().
print
(
"Shell returned with {s} code {}.
\n\n
Press enter to continue.
\n
"
,
.
{
n
,
v
}
)
catch
{};
_
=
std
.
io
.
getStdIn
().
reader
().
skipUntilDelimiterOrEof
(
'\n'
)
catch
unreachable
;
}
}
fn
readExcludeFile
(
path
:
[]
const
u8
)
!
void
{
fn
readExcludeFile
(
path
:
[]
const
u8
)
!
void
{
const
f
=
try
std
.
fs
.
cwd
().
openFile
(
path
,
.
{});
const
f
=
try
std
.
fs
.
cwd
().
openFile
(
path
,
.
{});
defer
f
.
close
();
defer
f
.
close
();
...
@@ -279,12 +335,18 @@ pub fn main() void {
...
@@ -279,12 +335,18 @@ pub fn main() void {
browser
.
loadDir
();
browser
.
loadDir
();
while
(
true
)
{
while
(
true
)
{
if
(
state
==
.
refresh
)
{
switch
(
state
)
{
scan
.
scan
();
.
refresh
=>
{
state
=
.
browse
;
scan
.
scan
();
browser
.
loadDir
();
state
=
.
browse
;
}
else
browser
.
loadDir
();
handleEvent
(
true
,
false
);
},
.
shell
=>
{
spawnShell
();
state
=
.
browse
;
},
else
=>
handleEvent
(
true
,
false
)
}
}
}
}
}
...
@@ -298,6 +360,7 @@ pub fn handleEvent(block: bool, force_draw: bool) void {
...
@@ -298,6 +360,7 @@ pub fn handleEvent(block: bool, force_draw: bool) void {
switch
(
state
)
{
switch
(
state
)
{
.
scan
,
.
refresh
=>
scan
.
draw
(),
.
scan
,
.
refresh
=>
scan
.
draw
(),
.
browse
=>
browser
.
draw
(),
.
browse
=>
browser
.
draw
(),
.
shell
=>
unreachable
,
}
}
if
(
ui
.
inited
)
_
=
ui
.
c
.
refresh
();
if
(
ui
.
inited
)
_
=
ui
.
c
.
refresh
();
event_delay_timer
.
reset
();
event_delay_timer
.
reset
();
...
@@ -315,6 +378,7 @@ pub fn handleEvent(block: bool, force_draw: bool) void {
...
@@ -315,6 +378,7 @@ pub fn handleEvent(block: bool, force_draw: bool) void {
switch
(
state
)
{
switch
(
state
)
{
.
scan
,
.
refresh
=>
scan
.
keyInput
(
ch
),
.
scan
,
.
refresh
=>
scan
.
keyInput
(
ch
),
.
browse
=>
browser
.
keyInput
(
ch
),
.
browse
=>
browser
.
keyInput
(
ch
),
.
shell
=>
unreachable
,
}
}
firstblock
=
false
;
firstblock
=
false
;
}
}
...
...
This diff is collapsed.
Click to expand it.
src/ui.zig
+
12
−
6
View file @
448fa9e7
...
@@ -52,19 +52,25 @@ pub fn oom() void {
...
@@ -52,19 +52,25 @@ pub fn oom() void {
// (Would be nicer if Zig just exposed errno so I could call strerror() directly)
// (Would be nicer if Zig just exposed errno so I could call strerror() directly)
pub
fn
errorString
(
e
:
anyerror
)
[:
0
]
const
u8
{
pub
fn
errorString
(
e
:
anyerror
)
[:
0
]
const
u8
{
return
switch
(
e
)
{
return
switch
(
e
)
{
error
.
AccessDenied
=>
"Access denied"
,
error
.
DiskQuota
=>
"Disk quota exceeded"
,
error
.
DiskQuota
=>
"Disk quota exceeded"
,
error
.
FileNotFound
=>
"No such file or directory"
,
error
.
FileSystem
=>
"I/O error"
,
// This one is shit, Zig uses this for both EIO and ELOOP in execve().
error
.
FileTooBig
=>
"File too big"
,
error
.
FileTooBig
=>
"File too big"
,
error
.
FileBusy
=>
"File is busy"
,
error
.
InputOutput
=>
"I/O error"
,
error
.
InputOutput
=>
"I/O error"
,
error
.
InvalidExe
=>
"Invalid executable"
,
error
.
IsDir
=>
"Is a directory"
,
error
.
NameTooLong
=>
"Filename too long"
,
error
.
NoSpaceLeft
=>
"No space left on device"
,
error
.
NoSpaceLeft
=>
"No space left on device"
,
error
.
AccessDenied
=>
"Access denied
"
,
error
.
NotDir
=>
"Not a directory
"
,
error
.
SymlinkLoop
=>
"Symlink loop
"
,
error
.
OutOfMemory
,
error
.
SystemResources
=>
"Out of memory
"
,
error
.
ProcessFdQuotaExceeded
=>
"Process file descriptor limit exceeded"
,
error
.
ProcessFdQuotaExceeded
=>
"Process file descriptor limit exceeded"
,
error
.
SymlinkLoop
=>
"Symlink loop"
,
error
.
SystemFdQuotaExceeded
=>
"System file descriptor limit exceeded"
,
error
.
SystemFdQuotaExceeded
=>
"System file descriptor limit exceeded"
,
error
.
NameTooLong
=>
"Filename too long"
,
error
.
FileNotFound
=>
"No such file or directory"
,
error
.
IsDir
=>
"Is a directory"
,
error
.
NotDir
=>
"Not a directory"
,
else
=>
"Unknown error"
,
// rather useless :(
else
=>
"Unknown error"
,
// rather useless :(
// ^ TODO: remove that one and accept only a restricted error set for
// compile-time exhaustiveness checks.
};
};
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment