It’s surprisingly hard to get this right. I feel like I need this in order to use `ed` as the editor for `tin`, my current news client.
This is what I use:
alias tin='env EDITOR=ted tin -r'
Here’s “bin/ted”:
#! /bin/sh ed "$1" article-wrap < "$1" > "$1.fmt" mv "$1.fmt" "$1"
So first it calls ed and then it pipes the article through a filter.
This is the filter, “bin/article-wrap”:
#!/usr/bin/env perl use Modern::Perl; die "This filter wraps news posts.\n" if @ARGV; binmode(STDIN, ':utf8'); binmode(STDOUT, ':utf8'); # headers while (<STDIN>) { chomp; last if not $_; # end of headers say; # header line } say; # empty line after headers my $max = 72; my $buffer; my $prefix = ''; my $wrap = 1; while (<STDIN>) { chomp; my ($new_prefix) = /([> ]*)/; # empty lines don't get wrapped, nor lines with a space at the end, nor indented lines my $empty = length() == 0 || /^$prefix\s*$/ || /\s$/ || /^\s/ || /^$prefix.{0,10}$/; # ``` toggles wrap $wrap = not $wrap if /^$prefix\s*```$/; # end old paragraph with the old prefix if the prefix changed, an empty line, # or not wrapping anymore if ($buffer and ($new_prefix ne $prefix or $empty or not $wrap)) { say $prefix . $buffer; $buffer = ''; } # print empty lines or not wrapped lines without stripping trailing whitespace if ($empty or not $wrap) { say $_; next; } # continue old paragraph $buffer .= " " if $buffer; # strip the prefix $prefix = $new_prefix; $buffer .= substr($_, length($prefix)); # wrap what we have while (length($buffer) > $max) { # if there's a word that crosses the $max line size, break before if (substr($buffer, 0, $max - length($prefix) + 1) =~ /(\s+(\w+))\w$/) { say $prefix . substr($buffer, 0, $max - length($prefix) - length($1)); $buffer = substr($buffer, $max - length($prefix) - length($2)); } else { my $line = substr($buffer, 0, $max - length($prefix)); $line =~ s/\s+$//; say $prefix . $line; $buffer = substr($buffer, $max - length($prefix)); $buffer =~ s/^\s+//; } } } say $prefix . $buffer if $buffer; 1;
Related “.tin/tinrc” settings:
#Programming #Mail #News
(Please contact me if you want to remove your comment.)
⁂
I’m wondering about implementing `aed` as a wrapper that calls `ed` and adds more commands... Or should I look at the `ed` source code‽
– Alex 2023-06-06 13:03 UTC
---
I fear I’d have to track whether ed is in command-mode or edit mode…
This is based on the `perlipc(1)` man page.
use strict; use warnings; use IO::Socket; use IPC::Open2; my $file = shift; local $SIG{PIPE} = sub { die "ed is done\n" }; my $pid = open2(my $out, my $in, 'ed', $file); $in->autoflush(1); $out->autoflush(1); # split the program into two processes die "can't fork: $!" unless defined(my $kidpid = fork()); if ($kidpid) { # parent: copy ed output to standard output while (<$out>) { last unless defined; print STDOUT $_; } kill("TERM", $kidpid); # send SIGTERM to child } else { # child: copy standard input to ed input while (<STDIN>) { print $in $_; } waitpid($pid, 0 ); exit($? >> 8); }
– Alex 2023-06-06 21:29 UTC
---
Much blast from the past in June. Deliberately wrote a program in nano today.
– Blue Tyson 2023-07-28 11:33 UTC
---
Wow! How many lines? Code formatting by hand or using a tool?
– Alex 2023-07-28 11:38 UTC