aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2020-08-27 17:35:02 -0400
committerB. Watson <yalhcru@gmail.com>2020-08-27 17:35:02 -0400
commita70da6c048c16a40f598ddd1384d44f89a07d980 (patch)
treeccfea42ec70314fb1fd2ae75fccf9d0aa6ab6150
parent8651992edf3b47cc9d6161310517baff130c9baa (diff)
downloadmisc-scripts-a70da6c048c16a40f598ddd1384d44f89a07d980.tar.gz
Add unifmt.pl (Unicode formatting for irssi)
-rwxr-xr-xslacksrc3
-rw-r--r--unifmt.pl391
2 files changed, 391 insertions, 3 deletions
diff --git a/slacksrc b/slacksrc
index 4cc6d19..9d4f561 100755
--- a/slacksrc
+++ b/slacksrc
@@ -172,9 +172,6 @@ if [ ! -s $FILELIST ]; then
wget -O- $TOPDIR/FILELIST.TXT | \
sed -n 's,.*\./source/\([^/]\+/[^/]\+/\).*$,\1,p' | \
sort -u > $FILELIST
-
-#TODO: handle extra/ somehow
-#wget -O $FILELIST.tmp $TOPDIR/FILELIST.TXT
fi
rm -f $TMPFILE
diff --git a/unifmt.pl b/unifmt.pl
new file mode 100644
index 0000000..53302d1
--- /dev/null
+++ b/unifmt.pl
@@ -0,0 +1,391 @@
+#!/usr/bin/perl
+
+# to read the docs outside of irssi: perldoc /path/to/unifmt.pl
+# in irssi, "/script load unifmt.pl", then "/unifmt_help"
+
+=encoding utf8
+
+=pod
+
+=head1 NAME
+
+unifmt.pl - unicode text formatting for irssi
+
+=head1 SYNOPSIS
+
+in shell: cp unifmt.pl ~/.irssi/scripts/
+
+in irssi: /script load unifmt.pl
+
+=head1 DESCRIPTION
+
+unifmt.pl adds keystrokes to irssi that allow you to type double-width
+ASCII (Unicode FF00 block) characters, and use Unicode combining
+characters to make your text appear underlined (single or double line),
+struck out, or "slashed" out.
+
+Rather than executing the script as an irssi slash-command, the modes are
+controlled via keystrokes. This allows the formatted text to be mixed
+with normal text on the same line of input. Only one of the underline,
+strikeout, slashout modes can be enabled at the same time, but they can
+be combined with wide mode.
+
+=head1 KEYSTROKES
+
+All the formatting controls must be preceded by a prefix character,
+which defaults B<^F> (control-F). The default keystrokes are shown
+here; see SETTINGS, below, to change them.
+
+=over 4
+
+=item B<^F w>
+
+Enables wide formatting. Each character you type is replaced by its
+double-width equivalent from the Unicode B<U+FF01-U+FFE1> range, if
+it has one. Only characters B<U+0021-U+007E> (AKA the printable ASCII
+charset) have double-width equivalents. As a special case, the space
+(B<U+0020>) character is replaced with B<U+3000>, B<IDEOGRAPHIC SPACE>, which
+is a double-width space. All other characters are treated normally.
+
+ Example: This is wide text
+
+Wide formatting can be combined with one (at a time) of the other
+formatting options.
+
+=item B<^F _>
+
+Enables underlining. Each character you type is followed by the Unicode
+combining character B<U+0332>, B<COMBINING LOW LINE>. Example: U̲n̲d̲e̲r̲l̲i̲n̲e̲d̲
+
+=item B<^F =>
+
+Enables double underlining. Each character you type is followed by the Unicode
+combining character B<U+0333>, B<COMBINING DOUBLE LOW LINE>. Example: U̳n̳d̳e̳r̳l̳i̳n̳e̳d̳
+
+=item B<^F ->
+
+Enables strikethrough. Each character you type is followed by the Unicode
+combining character B<U+0336>, B<COMBINING LONG STROKE OVERLAY>. Example: S̶t̶r̶i̶k̶e̶t̶h̶r̶o̶u̶g̶h̶
+
+=item B<^F />
+
+Enables slashthrough. Each character you type is followed by the Unicode
+combining character B<U+0338>, B<COMBINING LONG SOLIDUS OVERLAY>. Example: S̸l̸a̸s̸h̸o̸u̸t̸
+
+=item B<^F ^F>
+
+Acts like a single B<^F> was pressed. Does not disable formatting. If
+you have a regular irssi keybinding for B<^F>, it will be acted on.
+Otherwise, a B<^F> will be inserted into the input buffer.
+
+=item B<^F F>
+
+Disables all the formatting modes. Actually, B<^F> followed by any character
+not listed above will do the same thing, but I promise not to change
+the B<^F F> combo in any future versions of this script.
+
+=back
+
+=head1 SETTINGS
+
+=over 4
+
+=item B<unifmt_keys>
+
+String, the 6 keystrokes used to enable the formatting modes. This
+defaults to B<fw_=-/>. The order is: Prefix, Wide, Underline,
+Double-Underline, Strikethrough, Slashthrough. The prefix key is used as
+a control key, but when you set it, use a regular alphabetic (e.g. don't
+say B<^X>, just say B<x> or B<X>).
+
+=item B<unifmt_spaces>
+
+Boolean, whether or not to apply formatting to spaces (default: false).
+Does not affect wide mode (spaces will always be double-wide).
+
+=back
+
+=head1 NOTES
+
+For any of this to work, you'll have to enable UTF-8 in irssi, and use
+a UTF-8 capable terminal. This applies to everyone else too: if you're
+sending UTF-8 encoded Unicode to them, their client (and terminal if
+it's a terminal client) will have to know how to display it. If not,
+they'll see garbage in place of what you intended.
+
+This script was developed with urxvt (AKA rxvt-unicode). It should work
+with any terminal that fully supports UTF-8 and Unicode... but you want
+a terminal that supports looking up glyphs from a list of fonts, like
+urxvt does. Otherwise, you might have a hard time finding a single font
+that has all the glyphs you'll need.
+
+The editing keys (arrows, home/end, pgup/pgdn, and any alt-? combos)
+might act strangely while the formatting modes are enabled, depending
+on your terminal and TERM environment variable. Backspace and ^U
+(kill line) should still work OK. This will probably be fixed in the
+future. Tab-completing nicks doesn't work either, but fixing that will
+be a huge PITA (or maybe impossible).
+
+None of the formatting modes persist past the end of the current line of
+input. Pressing Enter always clears all the modes. This is to minimize
+annoyance, as there's no visual indicator of which mode(s) you're in.
+
+Before you use this script on a public channel, you'd better make sure
+the channel doesn't have rules against using fancy Unicode. You may
+annoy the other users, and/or find yourself banned.
+
+tmux doesn't seem to be capable of actually displaying the wide +
+combining character combinations. They render as plain wide. If you
+copy/paste them to another window (a terminal not running tmux for
+instance), they show up correctly. So tmux "knows" the formatting is
+there, but doesn't display it.
+
+The underline, strike, slashout combinations don't work with screen,
+and probably never will. I'd love to be proven wrong, so let me know if
+you get it working there. I at least can see the wide characters with
+"screen -U".
+
+=head1 AUTHOR
+
+Urchlay <yalhcru@gmail.com>
+
+=head1 LICENSE
+
+WTFPL: Do WTF you want with this.
+
+=head1 SEE ALSO
+
+irssi(1), urxvt(1), unicode(7), utf-8(7)
+
+=cut
+
+our $VERSION = "0.1";
+our %IRSSI = (
+ authors => 'Urchlay',
+ contact => 'Urchlay on FreeNode',
+ name => 'unifmt',
+ description => 'Fancy Unicode text formatting',
+ license => 'WTFPL',
+ url => 'https://slackware.uk/~urchlay/repos/misc-scripts',
+);
+
+use warnings;
+use strict;
+
+# 20200827 bkw: adding gui_input_get_pos to the list of imports causes
+# this script to fail to autoload when irssi starts (but it'll load OK
+# if manually loaded after startup). I only use it for debugging anyway.
+use Irssi qw{
+ command command_bind parse_special signal_register
+ signal_add_first signal_add_last signal_continue signal_emit
+ signal_stop settings_set_str settings_get_str settings_add_str
+ settings_get_bool settings_add_bool
+ };
+
+our $SELF = $IRSSI{name};
+our $default_keys = "fw_=-/";
+
+# These 3 are controlled by setting unifmt_keys:
+our $prefix_key;
+our $wide_key;
+our %combining_map;
+
+# Toggled with ^F w
+our $widemode = 0;
+
+# Which of combining_map is active, or 0 for none
+our $combining_char = 0;
+
+# True if the last keypress was ^F
+our $was_prefix = 0;
+
+# 2 if the last keypress was escape, 1 if the last 2 were escape and [,
+# 0 otherwise.
+our $was_escape = 0;
+
+# There's no way to enable debugging without editing the script.
+our $DEBUG = 0;
+
+# Only used for debugging.
+our $count = 0;
+
+# Ditto.
+sub dump_buf {
+ my $buf = parse_special('$L', 0, 0);
+ my $len = length($buf);
+ my $pos = Irssi::gui_input_get_pos();
+ my $out = "pos==" . $pos . " ";
+ for(my $i = 0; $i < $len; $i++) {
+ my $star = ($i == $len ? "*" : "");
+ $out .= sprintf("$star%02x ", ord(substr($buf, $i, 1)));
+ }
+ print $out;
+}
+
+sub get_ctrl_key {
+ return ord(uc($_[0])) - 0x40;
+}
+
+sub fmt_key {
+ # \002 is "toggle bold"
+ return "'\002" . $_[0] . "\002'";
+}
+
+sub init_keys {
+ our $default_keys;
+
+ my $keys = settings_get_str('unifmt_keys');
+ if(length $keys != 6) {
+ print "$SELF: Invalid unifmt_keys, should be 6 keystrokes, defaulting to '$default_keys'";
+ settings_set_str('unifmt_keys', ($keys = $default_keys) );
+ }
+
+ my ($p, $w, $u, $d, $s, $l) = split "", $keys;
+
+ $p = get_ctrl_key($p);
+ if($p < 0 || $p > 0x1f) {
+ my $pd = uc substr($default_keys, 0, 1);
+ print "$SELF: Invalid prefix key, defaulting to " . fmt_key("^" . $pd);
+ $p = get_ctrl_key($pd);
+ }
+
+ our $prefix_key = $p;
+ our $wide_key = $w;
+
+ our %combining_map = (
+ $u => 0x332, # underline
+ $d => 0x333, # double underline
+ $s => 0x336, # strikethrough
+ $l => 0x338, # slash-through
+ );
+
+ print "$SELF: " .
+ "prefix " . fmt_key("^" . chr($prefix_key + 0x40)) . ", " .
+ "wide " . fmt_key($wide_key) . ", " .
+ "underline " . fmt_key($u) . ", " .
+ "double " . fmt_key($d) . ", " .
+ "strike " . fmt_key($s) . ", " .
+ "slash " . fmt_key($l);
+}
+
+sub handle_keypress {
+ my $key = shift;
+
+ if($DEBUG) { printf $count++ . ": got key 0x%x", $key; dump_buf(); }
+
+ # hackish way to let most escape codes through unmodified. assumes
+ # (incorrectly) that all escape codes are either Esc-[-(something),
+ # 3 bytes... or else Esc-(something that isn't [), 2 bytes. This
+ # happens to let urxvt's arrow keys and alt-numbers through, at least.
+ if($was_escape) {
+ if($was_escape == 2 && $key != ord('[')) {
+ $was_escape = 0;
+ } else {
+ $was_escape--;
+ }
+ signal_continue($key);
+ return;
+ }
+
+ # don't try to combine with combining chars!
+ for(values our %combining_map) {
+ #warn "$key $_";
+ if($key == $_) {
+ signal_continue($key);
+ return;
+ }
+ }
+
+ # ctrl-space is mapped to the null character. make it dump the
+ # current input buffer contents in hex, if debugging is active.
+ if($DEBUG && $key == 0) {
+ dump_buf();
+ signal_stop();
+ return;
+ }
+
+ # ^F pressed once: set flag, but don't insert into buffer.
+ # Pressed twice = unset flag, inset into buffer.
+ if($key == $prefix_key) {
+ if($was_prefix) {
+ $was_prefix = 0;
+ signal_continue($key);
+ } else {
+ $was_prefix = 1;
+ signal_stop();
+ }
+ return;
+ }
+
+ # enter/return, turn off formatting
+ if($key == 0x0d || $key == 0x0a) {
+ $widemode = $combining_char = $was_prefix = 0;
+ signal_continue($key);
+ return;
+ }
+
+ # backspace/delete and control characters are acted on normally, except
+ # that escape has to set a flag
+ if($key == 0x7f || $key < 0x20) {
+ if($key == 0x1b) {
+ $was_escape = 2;
+ }
+ signal_continue($key);
+ return;
+ }
+
+ # last key pressed was ^F, act on it, but don't insert into the buffer
+ if($was_prefix) {
+ if($key == ord($wide_key)) {
+ $widemode = 1;
+ } else {
+ $combining_char = $combining_map{chr($key)} || 0;
+ # unrecognized keys also turn off wide mode
+ $widemode = 0 unless $combining_char;
+ }
+
+ $was_prefix = 0;
+ signal_stop();
+ return;
+ }
+
+ # unicode 0x0f01 to 0x0fee are wide versions of ASCII
+ if($widemode) {
+ if($key == 0x20) {
+ $key = 0x3000;
+ } elsif($key >= 0x21 && $key <= 0x7e) {
+ $key += 0xfee0;
+ }
+ # else pass it through as-is
+ }
+
+ signal_continue($key);
+
+ # if it was a space and we're not formatting spaces, we're done
+ if(($key == 0x20 || $key == 0x3000) && !settings_get_bool('unifmt_spaces')) {
+ return;
+ }
+
+ if($combining_char) {
+ if($DEBUG) { print "combining($key, $combining_char)"; }
+ signal_emit('gui key pressed', $combining_char);
+ }
+}
+
+sub unifmt_help {
+ command("/exec - pod2text " . __FILE__);
+}
+
+### main()
+settings_add_str($SELF, 'unifmt_keys', $default_keys);
+settings_add_bool($SELF, 'unifmt_spaces', 0);
+init_keys();
+
+signal_add_last('setup changed', \&init_keys);
+
+signal_register({ "gui key pressed", [ "integer" ] });
+signal_add_first("gui key pressed", \&handle_keypress);
+
+command_bind("unifmt_help", \&unifmt_help);
+
+print "$SELF.pl loaded, /unifmt_help for help"