aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/x178
1 files changed, 112 insertions, 66 deletions
diff --git a/bin/x b/bin/x
index ed967a5..21bd1f7 100755
--- a/bin/x
+++ b/bin/x
@@ -1,94 +1,140 @@
-#!/bin/sh
-set -eu
+#!/usr/bin/env perl
-usage() {
- cat <<-'EOF'
+use v5.34;
+use strict;
+use warnings;
+use feature 'signatures';
+no warnings 'experimental';
+use Getopt::Std ();
+
+sub usage($fh) {
+ print $fh <<~'EOF'
Usage:
- x COMMANDS... [ '&&' / '||' / '|' ] COMMANDS...
+ x COMMANDS... [ '&&' / '||' / '|' ] COMMANDS...
+ x COMMANDS... [ 'AND' / 'OR' / 'PIPE' ] COMMANDS...
x -h
- EOF
+ EOF
}
-help() {
- cat <<-'EOF'
+sub help($fh) {
+ print $fh <<~'EOF'
Options:
-h, --help show this message
COMMAND the command to be executed
- && "AND" logical operator
- || "OR" logical operator
- | pipe operator
+ '&&' / AND "AND" logical operator
+ '||' / OR "OR" logical operator
+ '|' / PIPE pipe operator
Run command chained together with operators.
+ NOTE: Remember to quote '&&', 'OR' and '|' operators, otherwise
+ they'll get captured by the shell and not be passed to the 'x'
+ program!
+
Examples:
Measure the time of two commands:
$ time x sleep 1 '&&' sleep 2
- # same as:
+ # equivalent to:
$ time sh -c 'sleep 1 && sleep 2'
Notify when either of the commands finish:
$ boop x cmd-1 '||' cmd-2
- EOF
+ EOF
+}
+
+
+for (@ARGV) {
+ last if $_ eq '--';
+ if ($_ eq '--help') {
+ usage *STDOUT;
+ help *STDOUT;
+ exit;
+ }
+}
+
+my %opts;
+if (!Getopt::Std::getopts('h', \%opts)) {
+ usage *STDERR;
+ exit 2;
}
-for flag in "$@"; do
- case "$flag" in
- --)
- break
- ;;
- --help)
- usage
- help
- exit
- ;;
- *)
- ;;
- esac
-done
-
-while getopts 'h' flag; do
- case "$flag" in
- h)
- usage
- help
- exit
- ;;
- *)
- usage >&2
- exit 2
- ;;
- esac
-done
-shift $((OPTIND - 1))
-
-
-CMD=''
-for arg in "$@"; do
- case "$arg" in
- '&&'|'||')
- set +e
- sh -c "$CMD"
- STATUS=$?
- set -e
- CMD=''
- if [ "$arg" = '&&' ] && [ "$STATUS" != 0 ]; then
- exit "$STATUS"
- elif [ "$arg" = '||' ] && [ "$STATUS" = 0 ]; then
- exit 0
- fi
- ;;
- *)
- CMD="$CMD${CMD:+ }'$arg'"
- ;;
- esac
-done
-
-sh -c "$CMD"
+if ($opts{h}) {
+ usage *STDOUT;
+ help *STDOUT;
+ exit;
+}
+
+
+sub status_for($n) {
+ if ($n == -1) {
+ return 127;
+ } elsif ($n & 127) {
+ return $n & 127;
+ } else {
+ return $n >> 8;
+ }
+}
+
+my @AND = ('&&', 'AND');
+my @OR = ('||', 'OR');
+my @PIPE = ('|', 'PIPE');
+my @OPS = (@AND, @OR, @PIPE);
+
+my @CMD;
+for (@ARGV) {
+ if ($_ ~~ @OPS) {
+ system @CMD;
+ @CMD = ();
+ if ($_ ~~ @AND && $?) {
+ exit status_for($?);
+ } elsif ($_ ~~ @OR && !$?) {
+ exit 0;
+ } elsif ($_ ~~ @PIPE) {
+ ...
+ }
+ } else {
+ push @CMD, $_;
+ }
+}
+
+exit status_for(system @CMD);
+
+# FIXME: implement manpage in pod
+__END__
+.TH x 1 1970-01-01 "x latest" "x user manual"
+
+
+.SH NAME
+
+x - chain shell commands without creating a subshell.
+
+
+.SH SYNOPSYS
+
+\fBx\fR [\fIOPTIONS\fR] COMMAND... [ \fI'&&'\fR / \fI'||'\fR / \fI'|'\fR ] COMMAND...
+
+
+.SH DESCRIPTION
+
+\fBx\fR is a \m[blue]\fBtool\fP\m[], from
+.pdfhref W -D https://euandre.org/ -- The best website ever
+.
+
+
+.SH OPTIONS
+
+.TP
+\fB-h\fR, \fB--help\fR
+Show help text.
+
+
+.SH OPERATORS
+