summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2021-05-26 01:36:03 +0200
committerJohn Ankarström <john@ankarstrom.se>2021-05-26 01:36:03 +0200
commitb9ed52e3684e49b9b00ef08b29111758cc4777ee (patch)
tree1554f0465c0de4f5a01ec2b938e7cb9547938e76
parente0b52520b57cbcf6454ea35e97c99003d5596508 (diff)
downloadmum-b9ed52e3684e49b9b00ef08b29111758cc4777ee.tar.gz
Add main 'mum' script
-rwxr-xr-xsrc/mum121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/mum b/src/mum
new file mode 100755
index 0000000..3c7d0b0
--- /dev/null
+++ b/src/mum
@@ -0,0 +1,121 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use feature qw/switch/;
+no warnings qw/experimental::smartmatch/;
+
+use Data::Dumper;
+
+# Open TTY for reading and writing
+
+open my $tty, '+<:unix', '/dev/tty' or die "Could not open /dev/tty: $!";
+
+# Define range syntax
+
+my @range; # range (one/two references)
+our %ref; # current reference in range
+my $d = qr{
+ (?(DEFINE)
+ (?<range> (?{ @range = () })
+ ( (?&ref)
+ | (?&ref),(?&ref)
+ | (?&pattern)
+ )
+ (?{ push @range, \%ref })
+ )
+ (?<ref> ( (\d+) (?{ local %ref = (line => $^N) })
+ | (\.|\$) (?{ local %ref = (spec => $^N) })
+ | ' ([a-z]) (?{ local %ref = (mark => $^N) })
+ | /((\\/|[^/])*)/ (?{ local %ref = (next => $^N) })
+ | \?((\\\?|[^?])*)\? (?{ local %ref = (prev => $^N) })
+ )
+ ( ([+-] \d+) (?{ local %ref = (%ref, plus => $^N) })
+ )?
+ )
+ (?<pattern> g/((\\/|[^/])*)/ (?{ local %ref = (patt => $^N) })
+ )
+ )
+}x;
+
+# Define program state
+
+my $message = 1; # selected message
+
+# Run program
+
+while () {
+ print $tty "$message& ";
+
+ # Read next command from user
+
+ my $cmd = <$tty>;
+ $cmd = '' if not $cmd;
+ chomp $cmd;
+ $cmd =~ s/^\s+|\s+$//g;
+
+ # Parse user-given command
+
+ for ($cmd) {
+ # q
+ if (/^q$/) {
+ exit;
+ }
+
+ # range without command
+ elsif (/^(?&range) \Z $d/x) {
+ print Dumper(@range), "\n";
+ # select last message in range
+ print "range without command\n";
+ }
+
+ # +/- (++/--)
+ elsif (/^(?<num> \d*) (?<dir> (\+\+?|--?)) \Z/x) {
+ for ($+{dir}) {
+ $message += $+{num} || 1 if /\+/;
+ $message -= $+{num} || 1 if /-/;
+ goto h if length($_) > 1;
+ }
+ }
+
+ # c
+ elsif (/^c\s+(.*)/) {
+ chdir $1;
+ }
+
+ # h
+ elsif (/^ (?&range)? h \Z $d/x) {
+h:
+ print "h\n";
+ }
+
+ # p
+ elsif (/^ (?&range)? p \Z $d/x) {
+ print Dumper(@range), "\n";
+ print "p\n";
+ }
+
+ # |
+ elsif (/^ (?&range)? \| (?<rest>.+) $d/x) {
+ print "|\n";
+ }
+
+ # !
+ elsif (/^!/) {
+ $cmd =~ s/!//;
+ system $cmd;
+ print "!\n";
+ }
+
+ # empty command
+ elsif (/^$/) {
+ $message++;
+ }
+
+ # unrecognized command
+ else {
+ warn "unrecognized command syntax\n";
+ next;
+ }
+ }
+}