Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions doc/es.1
Original file line number Diff line number Diff line change
Expand Up @@ -1959,12 +1959,18 @@ Exits the current loop.
.I Value
is used as the return value for the loop command.
.TP
.Cr "catch \fIcatcher body\fP"
.Cr "catch \fR[\fP\fIexception\fP\fR]\fP \fIcatcher body\fP"
Runs
.IR body .
If it raises an exception,
If it raises an exception, and
.IR exception
is either not provided or matches the first term of the exception,
.IR catcher
is run and passed the exception as an argument.
If
.IR exception
is provided, then the passed argument does not include the first term
of the exception, which has already been matched.
.TP
.Cr "cd \fR[\fP\fIdirectory\fP\fR]\fP"
Changes the current directory to
Expand Down
26 changes: 24 additions & 2 deletions initial.es
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@

fn-. = $&dot
fn-access = $&access
fn-break = $&break
fn-catch = $&catch
fn-echo = $&echo
fn-exec = $&exec
fn-forever = $&forever
Expand Down Expand Up @@ -102,6 +100,30 @@ fn-break = throw break
fn-exit = throw exit
fn-return = throw return

# The catch function wraps $&catch and adds handling for "selectable
# exceptions": if catch is called like `catch foo $catcher $body`, then
# `catch` will only actually catch the 'foo' exception, and no others.

fn-catch = $&noreturn @ catcher body {
let (exception = ()) {
if {!~ $#body (0 1)} {
(exception catcher body) = $catcher $body
}
if {!~ $#body (0 1)} {
throw error catch 'usage: catch [exception] catcher body'
}
$&catch @ e rest {
if {~ $#exception 0} {
$&noreturn $catcher $e $rest
} {~ $exception $e} {
$&noreturn $catcher $rest
} {
throw $e $rest
}
} $body
}
}

# unwind-protect is a simple wrapper around catch that is used
# to ensure that some cleanup code is run after running a code
# fragment. This function must be written with care to make
Expand Down
1 change: 1 addition & 0 deletions prim-ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ PRIM(catch) {

SIGCHK();
} while (retry);
SIGCHK();
RefEnd(lp);
RefReturn(result);
}
Expand Down
8 changes: 2 additions & 6 deletions share/path-cache.es
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,8 @@ fn recache progs {
fn precache progs {
let (result = ())
for (p = $progs) {
catch @ e type msg {
if {~ $e error} {
echo >[1=2] $msg
} {
throw $e $type $msg
}
catch error @ _ msg {
echo >[1=2] $msg
} {
result = $result <={%pathsearch $p}
}
Expand Down
8 changes: 3 additions & 5 deletions share/status.es
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ fn %interactive-loop {
noexport = $noexport status
status = <=true
fn-%dispatch = $&noreturn @ {
catch @ e rest {
if {~ $e return} {
status = $rest
}
throw $e $rest
catch return @ value {
status = $value
return $value
} {
status = <={$d $*}
}
Expand Down