aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2020-07-05 21:03:38 -0400
committerB. Watson <yalhcru@gmail.com>2020-07-05 21:03:38 -0400
commit94ea7a8cd41b5b0cebf2606f4319ca5050e80520 (patch)
tree703f962eb3713871172e766565e4fa35b599b800
parent135b6988a809f22a633d9a90273cd6447cfa85be (diff)
downloadmisc-scripts-94ea7a8cd41b5b0cebf2606f4319ca5050e80520.tar.gz
Add some new stuff
-rwxr-xr-xcrc329
-rwxr-xr-xdumprpath6
-rwxr-xr-ximagebin16
-rwxr-xr-xnetqiv7
-rwxr-xr-xslacklog4
-rwxr-xr-xsmartfmt51
-rwxr-xr-xuleft41
-rwxr-xr-xunibmptxt.pl875
-rwxr-xr-xurxvt-change-font9
-rwxr-xr-xutf8ord12
-rwxr-xr-xvipaste53
-rwxr-xr-xwide.pl112
-rwxr-xr-xx113
-rwxr-xr-xxcleanpaste153
14 files changed, 1361 insertions, 0 deletions
diff --git a/crc32 b/crc32
new file mode 100755
index 0000000..1adfa3b
--- /dev/null
+++ b/crc32
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Horribly inefficient way to calculate crc32 of a file.
+
+Z=/tmp/crc32hack.$$.$RANDOM.zip
+rm -f $Z
+zip -q $Z "$1"
+zipinfo -v $Z | grep CRC | sed 's,.* ,,'
+rm -f $Z
diff --git a/dumprpath b/dumprpath
new file mode 100755
index 0000000..cc07fd0
--- /dev/null
+++ b/dumprpath
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+for i in "$@"; do
+ echo -n "$i: "
+ objdump -x "$i" | grep RPATH
+done
diff --git a/imagebin b/imagebin
new file mode 100755
index 0000000..a5de360
--- /dev/null
+++ b/imagebin
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# pastebin an image. if xsel is installed, copy the URL to the X clipboard.
+# uses this API: https://ibin.co/tools.php
+# no support for using a login + API key, don't need it.
+
+url="$(
+ curl -F file="@${1:-}" https://imagebin.ca/upload.php | \
+ grep ^url: | \
+ cut -d: -f2-
+)"
+
+if [ -n "$url" ]; then
+ echo "$url"
+ which xsel &>/dev/null && echo -n "$url" | xsel
+fi
diff --git a/netqiv b/netqiv
new file mode 100755
index 0000000..c5bea0f
--- /dev/null
+++ b/netqiv
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -e
+mkdir -p ~/.netqiv
+cd ~/.netqiv
+wget "$1"
+qiv "$@" "$( basename "$1" )"
diff --git a/slacklog b/slacklog
new file mode 100755
index 0000000..819b4b1
--- /dev/null
+++ b/slacklog
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+VER=${@:-14.2}
+exec tmux new links ftp://ftp.osuosl.org/pub/slackware/slackware-$VER/ChangeLog.txt
diff --git a/smartfmt b/smartfmt
new file mode 100755
index 0000000..71ca8c7
--- /dev/null
+++ b/smartfmt
@@ -0,0 +1,51 @@
+#!/usr/bin/perl -w
+
+# wrapper for fmt, detects when every line has
+# the same prefix (or is blank) and passes the prefix
+# as a -p option to fmt. Called by ~/.vimrc, F mapping.
+
+sub shortest {
+ my $oldprefix = shift;
+ my $line = shift;
+ my $newprefix = "";
+
+ for(my $i = 0; $i < length($oldprefix) && $i < length($line); $i++) {
+ last if substr($line, $i, 1) ne substr($oldprefix, $i, 1);
+ $newprefix .= substr($line, $i, 1);
+ }
+
+ return $newprefix;
+}
+
+$nonblank = 0;
+while(<STDIN>) {
+ chomp;
+ s/^\s+$//;
+ push @lines, $_;
+ next if /^$/;
+
+ $nonblank++;
+
+ if(not defined $prefix) {
+ $prefix = $_;
+ } elsif($prefix ne "") {
+ $prefix = shortest($prefix, $_);
+ }
+}
+
+$width = 71;
+if($nonblank > 1 && $prefix ne "" && ($prefix =~ /[^A-Za-z]$/)) {
+ $opt = ' -p' . quotemeta($prefix) . ' ';
+ if(@ARGV && ($ARGV[0] eq '-s')) {
+ $width = (length($prefix) + 71);
+ }
+}
+
+$opt.= "-w $width -g $width";
+
+#warn "line: $_" for @lines;
+#warn "opt: $opt";
+
+open OUT,"|fmt $opt" or die $!;
+print OUT "$_\n" for @lines;
+close OUT;
diff --git a/uleft b/uleft
new file mode 100755
index 0000000..0efe972
--- /dev/null
+++ b/uleft
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# uleft, uright, ukill, ufull, unext - start & kill urxvt with
+# preferred geometry. the terminals persist when their shells exit
+# (they just start a new one).
+
+# any arguments passed to this script are passed thru to urxvt.
+
+GLEFT="96x53+0+0"
+GRIGHT="88x53+968+0"
+GFULL="185x53+0+0"
+
+murder_shell() {
+ # kill the shell that called the shell that's running this script
+ kill $( ps -o ppid --no-headers $( ps -o ppid --no-headers $$ ) )
+ exit 0
+}
+
+get_next_geom() {
+ # lets this script alternate between starting left and right terminals
+ if [ ! -e ~/.uleftright ] || grep -q right ~/.uleftright; then
+ G=$GLEFT
+ echo left > ~/.uleftright
+ else
+ G=$GRIGHT
+ echo right > ~/.uleftright
+ fi
+
+ echo "$G"
+}
+
+case "$0" in
+ *kill*) murder_shell ;;
+ *left*) G=$GLEFT ;;
+ *full*) G=$GFULL ;;
+ *next*) G=$( get_next_geom ) ;;
+ *) G=$GRIGHT ;;
+esac
+
+urxvt -g "$G" "$@" -e sh -c "while true; do bash -login; done" &>/dev/null &
+disown
diff --git a/unibmptxt.pl b/unibmptxt.pl
new file mode 100755
index 0000000..e20de65
--- /dev/null
+++ b/unibmptxt.pl
@@ -0,0 +1,875 @@
+#!/usr/bin/perl
+
+use warnings;
+no warnings 'utf8';
+use utf8;
+
+@block4x4s = split "", " ▗▖▄▝▐▞▟▘▚▌▙▀▜▛█";
+
+for($i = 0; $i < 95; $i++) {
+ <DATA>; # skip comment
+ for($j = 0; $j < 6; $j++) {
+ my $row = <DATA>;
+ chomp($row);
+ $row =~ s/X/1/g;
+ $row =~ s/\./0/g;
+ #warn @s;
+ $font[$i + 32][$j] = $row;
+ }
+ <DATA>; # skip blank
+}
+
+if(!@ARGV) {
+ @ARGV = (
+ " !\"#\$%&'()*+,-./",
+ "0123456789:;<=>?",
+ "\@ABCDEFGHIJKLMNO",
+ "PQRSTUVWXYZ[\\]^_",
+ "\`abcdefghijklmno",
+ "pqrstuvwxyz{|}~");
+}
+
+for $input (@ARGV) {
+ my @lines = ();
+ for(split "", $input) {
+ my $o = ord($_);
+ next if $o < 32 || $o > 126;
+ for(0..5) {
+ $lines[$_] .= $font[$o][$_];
+ }
+ }
+
+# always want an even number of columns
+ if(length($lines[0]) % 1) {
+ $lines[$_] .= "0" for 0..5;
+ }
+
+#print "$_\n" for @lines;
+
+ my @output = ();
+ for($y = 0; $y < 6; $y += 2) {
+ my $out = "";
+ for($x = 0; $x < length($lines[0]); $x += 2) {
+ my $index = 0;
+ $index |= 8 if substr($lines[$y], $x, 1) eq '1';
+ $index |= 4 if substr($lines[$y], $x + 1, 1) eq '1';
+ $index |= 2 if substr($lines[$y + 1], $x, 1) eq '1';
+ $index |= 1 if substr($lines[$y + 1], $x + 1, 1) eq '1';
+ $out .= $block4x4s[$index];
+ }
+ push @output, $out;
+ }
+
+ print "$_\n" for @output;
+}
+
+=for reference
+# __DATA__ section originally made thus:
+open my $f, "</home/urchlay/5x7.bdf" or die $!;
+
+$in_bitmap = 0;
+@bitmap = ();
+while(<$f>) {
+ chomp;
+ if(/^ENCODING\s+(\d+)/) {
+ $encoding = $1;
+ next;
+ }
+
+ if($in_bitmap) {
+ if(/^ENDCHAR/) {
+ $in_bitmap = 0;
+ $bitmaps{$encoding} = [ @bitmap ];
+ } else {
+ push @bitmap, $_;
+ #warn "encoding $encoding, byte $_";
+ }
+ } else {
+ if(/^BITMAP/) {
+ $in_bitmap = 1;
+ @bitmap = ();
+ }
+ }
+}
+
+## for(sort { $a <=> $b } keys %bitmaps) {
+## print $_ . " => " . join(" ", @{$bitmaps{$_}}) . "\n";
+## }
+
+for($i = 32; $i < 127; $i++) {
+ print "# $i " . chr($i) . "\n";
+ for(@{$bitmaps{$i}}) {
+ my $byte = hex($_);
+ my $bin = sprintf("%08b", $byte);
+ $bin =~ s/000$//;
+ $bin =~ s/0/./g;
+ $bin =~ s/1/X/g;
+ print $bin . "\n";
+ }
+ print "\n";
+}
+=cut
+
+# This stuff was taken from 5x7.bdf, but hand-edited to make it 6 rows
+# high, proportional, and fix some of the uglier glyphs.
+__DATA__
+# 32
+...
+...
+...
+...
+...
+...
+
+# 33 !
+X.
+X.
+X.
+..
+X.
+..
+
+# 34 "
+X.X.
+X.X.
+....
+....
+....
+....
+
+# 35 #
+.X.X..
+XXXXX.
+.X.X..
+XXXXX.
+.X.X..
+......
+
+# 36 $
+.XXXX.
+X.X...
+.XXX..
+..X.X.
+XXXX..
+......
+
+# 37 %
+.....
+X..X.
+..X..
+.X...
+X..X.
+.....
+
+# 38 &
+.X...
+X.X..
+.X...
+X.X..
+.X.X.
+.....
+
+# 39 '
+X.
+X.
+..
+..
+..
+..
+
+# 40 (
+.X.
+X..
+X..
+X..
+.X.
+...
+
+# 41 )
+X..
+.X.
+.X.
+.X.
+X..
+...
+
+# 42 *
+......
+X.X.X.
+.XXX..
+X.X.X.
+......
+......
+
+# 43 +
+....
+.X..
+XXX.
+.X..
+....
+....
+
+# 44 ,
+...
+...
+...
+...
+.X.
+X..
+
+# 45 -
+....
+....
+XXX.
+....
+....
+....
+
+# 46 .
+..
+..
+..
+..
+X.
+..
+
+# 47 /
+.....
+...X.
+..X..
+.X...
+X....
+.....
+
+# 48 0
+.XX..
+X..X.
+X.XX.
+X..X.
+.XX..
+.....
+
+# 49 1
+.X..
+XX..
+.X..
+.X..
+XXX.
+....
+
+# 50 2
+.XX..
+X..X.
+..X..
+.X...
+XXXX.
+.....
+
+# 51 3
+.XX..
+X..X.
+. X..
+X..X.
+.XX..
+.....
+
+# 52 4
+..X..
+.XX..
+X.X..
+XXXX.
+..X..
+.....
+
+# 53 5
+XXXX.
+X....
+XXX..
+...X.
+XXX..
+.....
+
+# 54 6
+.XX..
+X....
+XXX..
+X..X.
+.XX..
+.....
+
+# 55 7
+XXXX.
+...X.
+..X..
+.X...
+.X...
+.....
+
+# 56 8
+.XX..
+X..X.
+.XX..
+X..X.
+.XX..
+.....
+
+# 57 9
+.XX..
+X..X.
+.XXX.
+...X.
+.XX..
+.....
+
+# 58 :
+..
+X.
+..
+X.
+..
+..
+
+# 59 ;
+...
+.X.
+...
+.X.
+X..
+...
+
+# 60 <
+..X.
+.X..
+X...
+.X..
+..X.
+....
+
+# 61 =
+....
+XXX.
+....
+XXX.
+....
+....
+
+# 62 >
+X...
+.X..
+..X.
+.X..
+X...
+....
+
+# 63 ?
+.XX..
+X..X.
+..X..
+.....
+..X..
+.....
+
+# 64 @
+.XX..
+X..X.
+X.XX.
+X....
+.XX..
+.....
+
+# 65 A
+.XX..
+X..X.
+XXXX.
+X..X.
+X..X.
+.....
+
+# 66 B
+XXX..
+X..X.
+XXX..
+X..X.
+XXX..
+.....
+
+# 67 C
+.XX..
+X..X.
+X....
+X..X.
+.XX..
+.....
+
+# 68 D
+XXX..
+X..X.
+X..X.
+X..X.
+XXX..
+.....
+
+# 69 E
+XXXX.
+X....
+XXX..
+X....
+XXXX.
+.....
+
+# 70 F
+XXXX.
+X....
+XXX..
+X....
+X....
+.....
+
+# 71 G
+.XXX.
+X....
+X.XX.
+X..X.
+.XXX.
+.....
+
+# 72 H
+X..X.
+X..X.
+XXXX.
+X..X.
+X..X.
+.....
+
+# 73 I
+XXX.
+.X..
+.X..
+.X..
+XXX.
+....
+
+# 74 J
+...X.
+...X.
+...X.
+X..X.
+.XX..
+.....
+
+# 75 K
+X..X.
+X.X..
+XX...
+X.X..
+X..X.
+.....
+
+# 76 L
+X....
+X....
+X....
+X....
+XXXX.
+.....
+
+# 77 M
+X...X.
+XX.XX.
+X.X.X.
+X.X.X.
+X...X.
+......
+
+# 78 N
+X..X.
+XX.X.
+X.XX.
+X.XX.
+X..X.
+.....
+
+# 79 O
+.XX..
+X..X.
+X..X.
+X..X.
+.XX..
+.....
+
+# 80 P
+XXX..
+X..X.
+XXX..
+X....
+X....
+.....
+
+# 81 Q
+.XX..
+X..X.
+X..X.
+X..X.
+.XX..
+..XX.
+
+# 82 R
+XXX..
+X..X.
+XXX..
+X.X..
+X..X.
+.....
+
+# 83 S
+.XXX.
+X....
+.XX..
+...X.
+XXX..
+.....
+
+# 84 T
+XXXXX.
+..X...
+..X...
+..X...
+..X...
+......
+
+# 85 U
+X..X.
+X..X.
+X..X.
+X..X.
+.XX..
+.....
+
+# 86 V
+X...X.
+X...X.
+X...X.
+.X.X..
+..X...
+......
+
+# 87 W
+X...X.
+X...X.
+X.X.X.
+XX.XX.
+X...X.
+......
+
+# 88 X
+X..X.
+X..X.
+.XX..
+X..X.
+X..X.
+.....
+
+# 89 Y
+X...X.
+X...X.
+.XXX..
+..X...
+..X...
+......
+
+# 90 Z
+XXXX.
+...X.
+.XX..
+X....
+XXXX.
+.....
+
+# 91 [
+XX.
+X..
+X..
+X..
+XX.
+...
+
+# 92 \
+.....
+X....
+.X...
+..X..
+...X.
+.....
+
+# 93 ]
+XX.
+.X.
+.X.
+.X.
+XX.
+....
+
+# 94 ^
+.X..
+X.X.
+....
+....
+....
+....
+
+# 95 _
+.....
+.....
+.....
+.....
+XXXX.
+.....
+
+# 96 `
+X..
+.X.
+...
+...
+...
+...
+
+# 97 a
+.....
+.....
+.XXX.
+X..X.
+.XXX.
+.....
+
+# 98 b
+X....
+X....
+XXX..
+X..X.
+XXX..
+.....
+
+# 99 c
+....
+....
+.XX.
+X...
+.XX.
+....
+
+# 100 d
+...X.
+...X.
+.XXX.
+X..X.
+.XXX.
+.....
+
+# 101 e
+.....
+.XX..
+X..X.
+X.X..
+.XXX.
+.....
+
+# 102 f
+..XX.
+.X...
+XXX..
+.X...
+.X...
+.....
+
+# 103 g
+.....
+.XXX.
+X..X.
+.XXX.
+...X.
+.XX..
+
+# 104 h
+X....
+X....
+XXX..
+X..X.
+X..X.
+.....
+
+# 105 i
+.X..
+....
+XX..
+.X..
+XXX.
+....
+
+# 106 j
+..X.
+....
+..X.
+..X.
+X.X.
+.X..
+
+# 107 k
+X...
+X...
+X.X.
+XX..
+X.X.
+....
+
+# 108 l
+XX..
+.X..
+.X..
+.X..
+XXX.
+....
+
+# 109 m
+......
+......
+X.XX..
+XXXXX.
+X.X.X.
+......
+
+# 110 n
+.....
+.....
+XXX..
+X..X.
+X..X.
+.....
+
+# 111 o
+.....
+.....
+.XX..
+X..X.
+.XX..
+.....
+
+# 112 p
+.....
+.....
+XXX..
+X..X.
+XXX..
+X....
+
+# 113 q
+.....
+.....
+.XXX.
+X..X.
+.XXX.
+...X.
+
+# 114 r
+.....
+.....
+XXX..
+X..X.
+X....
+.....
+
+# 115 s
+.....
+.XXX.
+XX...
+..XX.
+XXX..
+.....
+
+# 116 t
+.X...
+.X...
+XXX..
+.X...
+..XX.
+.....
+
+# 117 u
+.....
+.....
+X..X.
+X..X.
+.XXX.
+.....
+
+# 118 v
+....
+....
+X.X.
+X.X.
+.X..
+....
+
+# 119 w
+......
+......
+X...X.
+X.X.X.
+XX.XX.
+......
+
+# 120 x
+.....
+.....
+X..X.
+.XX..
+X..X.
+.....
+
+# 121 y
+.....
+.....
+X..X.
+.X.X.
+..X..
+.X...
+
+# 122 z
+.....
+XXXX.
+..X..
+.X...
+XXXX.
+.....
+
+# 123 {
+..X.
+.X..
+XX..
+.X..
+..X.
+....
+
+# 124 |
+X.
+X.
+X.
+X.
+X.
+..
+
+# 125 }
+X...
+.X..
+.XX.
+.X..
+X...
+....
+
+# 126 ~
+.X.X.
+X.X..
+.....
+.....
+.....
+.....
+
diff --git a/urxvt-change-font b/urxvt-change-font
new file mode 100755
index 0000000..6556a2d
--- /dev/null
+++ b/urxvt-change-font
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Read default from X resources
+DFLT="$( xrdb -query |grep '^URxvt\*font'|cut -f2 )"
+DFLT="${DFLT:-xft:Deja Vu Sans Mono:size=13}"
+NEWFONT="$@"
+FONT=${NEWFONT:-$DFLT}
+echo "Setting urxvt font to '$FONT'"
+printf '\e]710;%s\007' "${1:-$FONT}"
diff --git a/utf8ord b/utf8ord
new file mode 100755
index 0000000..f413906
--- /dev/null
+++ b/utf8ord
@@ -0,0 +1,12 @@
+#!/usr/bin/perl -CIOESA -w
+
+use charnames qw/:full/;
+
+#print ord($_), "\n" for @ARGV;
+
+for(@ARGV) {
+ for(split "") {
+ my $c = ord;
+ printf("%s\t%d\t%04x\t%s\n", $_, $c, $c, charnames::viacode($c)) for split "";
+ }
+}
diff --git a/vipaste b/vipaste
new file mode 100755
index 0000000..15cc892
--- /dev/null
+++ b/vipaste
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+usage() {
+ cat <<EOF
+$SELF - edit X11 selection buffer
+
+Usage: $SELF [-n]
+
+Loads the current contents of the X11 selection (copy/paste) buffer
+into an editor. After editing & exiting the editor, the results are
+copied back into the selection buffer, for pasting elsewhere.
+
+The last line (only line, for 1-line selections) will have its newline
+removed, if there is one.
+
+If the file is empty after editing, or if the editor exits with
+non-zero (error) status, the selection buffer won't be altered.
+
+To start with an empty buffer rather than the current selection, use
+the -n option.
+
+The editor to be run is set via VISUAL in the environment. If it's not
+set, EDITOR is used if set. If neither is set, vi is used. If you're
+going to run this without a terminal (e.g. using xbindkeys or a "Run
+Program" dialog), you'll want to set VISUAL to something that doesn't
+require a terminal (e.g. a GUI editor like gvim or gedit).
+
+Requires xsel and perl on the PATH.
+
+Written by B. Watson <yalhcru@gmail.com> and released under the WTFPL.
+EOF
+ exit $1
+}
+
+set -e
+
+SELF="$( basename $0 )"
+CMD="xsel -o"
+
+[ "$1" = "--help" ] && usage 0
+[ "$1" = "-n" ] && CMD=":" && shift
+[ "$1" != "" ] && usage 1
+
+TMPFILE="$( mktemp -t $SELF.XXXXXX )"
+trap "rm -f \"$TMPFILE\"" EXIT
+
+$CMD > "$TMPFILE"
+${VISUAL:-${EDITOR:-vi}} "$TMPFILE"
+
+# remove the newline(s) from the end of the file
+perl -i -0777 -pe 's/\n*$//' "$TMPFILE"
+
+[ -s "$TMPFILE" ] && xsel -i < "$TMPFILE"
diff --git a/wide.pl b/wide.pl
new file mode 100755
index 0000000..dc93be7
--- /dev/null
+++ b/wide.pl
@@ -0,0 +1,112 @@
+#!/usr/bin/perl
+
+=pod
+
+=head1 NAME
+
+wide.pl - print double-width characters
+
+=head1 SYNOPSIS
+
+=head2 From the shell:
+
+wide.pl <[args ...]>
+
+=head2 From within irssi:
+
+/script load wide.pl
+
+/wide [args]
+
+=head1 DESCRIPTION
+
+wide.pl converts printable ASCII characters to their double-width
+equivalent from the Unicode 0xff block. See:
+
+https://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms_(Unicode_block)
+
+Characters that don't have double-wide equivalents are simply printed
+with a trailing space.
+
+This script can be run standalone or as an irssi /script. For things to work
+properly in irssi, you'll need UTF-8 and Unicode support in irssi and in the
+terminal you're using to run irssi.
+
+When run standalone with no arguments, reads from stdin and writes to stdout.
+If arguments are given, they're treated as input (not filenames). Use shell
+redirection to read from a file: wide.pl < message.txt
+
+=head1 AUTHOR
+
+Urchlay <yalhcru@gmail.com>
+
+=head1 LICENSE
+
+wide.pl is released under the WTFPL: Do WTF you want with this.
+
+=cut
+
+use warnings;
+use strict;
+
+sub wide {
+ my $text = shift;
+ my $res = "";
+
+ for (split "", $text) {
+ my $c = ord($_);
+ if($c >= 0x21 && $c <= 0x7e) {
+ $res .= chr($c + 0xfee0);
+ } else {
+ $res .= "$_$_";
+ }
+ }
+
+ return $res;
+}
+
+# main() if we're not running under irssi
+if(__PACKAGE__ eq 'main') {
+ no warnings 'utf8';
+
+ exec "perldoc $0" if @ARGV && $ARGV[0] =~ /--?h(elp)?/;
+
+ if(@ARGV) {
+ print wide($_) for @ARGV;
+ print "\n";
+ } else {
+ while(<>) {
+ chomp;
+ print wide($_);
+ print "\n";
+ }
+ }
+
+ exit 0;
+}
+
+# irssi stuff here
+require Irssi;
+Irssi->import(qw/command command_bind/);
+
+our $VERSION = "0.1";
+our %IRSSI = (
+ authors => 'Urchlay',
+ contact => 'Urchlay on FreeNode',
+ name => 'wide',
+ description => 'print double-width characters',
+ license => 'WTFPL',
+ url => 'none',
+ );
+
+sub cmd_wide {
+ my ($text, $srv, $chan) = @_;
+
+ return unless $text;
+ return unless $srv;
+ return unless $chan;
+
+ $chan->command('MSG ' . $chan->{name} . ' ' . wide($text));
+}
+
+command_bind("wide", \&cmd_wide);
diff --git a/x1 b/x1
new file mode 100755
index 0000000..e3f3dca
--- /dev/null
+++ b/x1
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+WM="${1:-/etc/X11/xinit/xinitrc.fvwm2}"
+case "$1" in
+ "") ;;
+ /*) ;;
+ *) WM=/etc/X11/xinit/xinitrc.$1 ;;
+esac
+
+[ ! -x "$WM" ] && WM="$( which $1 )"
+
+echo startx $WM -- :1
+exec startx $WM -- :1
diff --git a/xcleanpaste b/xcleanpaste
new file mode 100755
index 0000000..c122002
--- /dev/null
+++ b/xcleanpaste
@@ -0,0 +1,153 @@
+#!/usr/bin/perl -w
+
+=pod
+
+=head1 NAME
+
+xcleanpaste - join multi-line copy/paste into one long line
+
+=head1 SYNOPSIS
+
+B<xcleanpaste> [-n] [-u] [-e<line-ending>] [-v] [xsel-options]
+
+=head1 DESCRIPTION
+
+"Cleans" the X selection buffer: trims whitespace from the start
+and end of every line, replaces all newlines with spaces, replaces
+all tabs with 3 spaces each. Result is written back to the selection
+buffer, where you can paste it into whatever application you want.
+
+This is useful even for single-line pastes: it removes tabs and any
+newline at the end, so e.g. copying a command from a browser into the
+shell won't trigger tab-completion or execute the command immediately.
+
+The selection buffer is read/written using xsel, which must be
+installed and available on your PATH.
+
+xcleanpaste is best used by binding to a key using xbindkeys or
+similar, though you can run it from the shell too.
+
+If you're using keybinding, you probably want at least separate keys
+for xcleanpaste with no options and xcleanpaste with the -u option
+(URL cleaner; see below).
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-e><line-ending>
+
+Replace line endings with the given string rather than a space. Don't
+use a space between the -e and the ending. Beware of shell quoting
+rules.
+
+=item B<-n>
+
+Replace line endings with the string " \n " rather than a space. This is
+space, backslash, lowercase n, space. Equivalent to B<-e ' \n '>.
+
+=item B<-u>
+
+Remove CGI arguments from any URLs found in the buffer. Some sites
+including tracking info, e.g. https://site.blah/stuff?sessionID=12345,
+which you shouldn't be pasting into anything others can see (e.g. IRC
+or emails).
+
+=item B<-v>
+
+Verbose mode. Shows lines read and written from the xsel instances on
+stderr. Not much use with xbindkeys though.
+
+=back
+
+Any other arguments are passed to xsel. This is probably only useful
+for xsel's -p/-s/-b options (see xsel man page).
+
+=head1 EXAMPLE
+
+In B<~/.xbindkeys>:
+
+ "xcleanpaste &"
+ Control+Alt + period
+
+ "xcleanpaste -u &"
+ Control+Alt + slash
+
+If you copy these three lines:
+
+ This is
+ a long URL:
+ https://long.url?with=lots&of=arguments
+
+Then press Ctrl+Alt+Period, then paste into some window, you will get:
+
+ This is a long URL: https://long.url?with=lots&of=arguments
+
+If you instead press Ctrl+Alt+Slash, you'll get:
+
+ This is a long URL: https://long.url
+
+=head1 AUTHOR
+
+xcleanpaste was written by B. Watson <yalhcru@gmail.com> and released
+under the WTFPL: Do WTF you want with this.
+
+=cut
+
+( $SELF = $0 ) =~ s,.*/,,;
+
+@xselargs = ();
+$line_ends = " ";
+$url_clean = $verbose = 0;
+
+for(@ARGV) {
+ if(/^-?-h(?:elp)/) {
+ exec "perldoc $0";
+ exit 1; # if the exec failed
+ } elsif(/^-v/) {
+ $verbose++;
+ } elsif(/^-n/) {
+ $line_ends = " \\n ";
+ } elsif(/^-u/) {
+ $url_clean = 1;
+ } elsif(/^-e(.*)$/) {
+ if(!defined($1) || $1 eq "") {
+ die("$SELF: no space allowed between -e option and its argument\n");
+ }
+ $line_ends = $1;
+ } else {
+ push @xselargs, $_;
+ }
+}
+
+$xsel_extra_args = join(" ", @xselargs);
+warn "$SELF: xsel arguments: \"$xsel_extra_args\"\n" if $verbose;
+
+# We have to read the entire output of xsel -o into memory before
+# spawning the xsel -i, because otherwise the 2nd xsel will obliterate
+# the selection buffer the first one's still trying to read from.
+open my $in, "xsel -o $xsel_extra_args|" or die $!;
+while(<$in>) {
+ chomp;
+ warn "$SELF: read line $.: $_\n" if $verbose;
+ s,\s+$,,; # remove any trailing whitespace
+ s,^\s+,,; # remove any leading whitespace
+ s,[\r\n], ,g; # replace all CR or LF with a single space
+ s,\t, ,g; # replace all tabs with 3 spaces
+ if($url_clean) {
+ # get rid of ? and anything after it, in anything that looks like a URL
+ s,(https?:\/\/[^?\s]*)\?\S+,$1,g;
+ }
+ s/\S$/$&$line_ends/; # our ending LF became a space above; make it
+ # whatever the line ending is supposed to be
+ push @lines, $_;
+}
+close $in;
+
+$output = join("", @lines);
+$output =~ s/\s+$//; # trim trailing whitespace from last line only
+warn "$SELF: writing: $output\n" if $verbose;
+
+open my $out, "|xsel -i $xsel_extra_args" or die $!;
+print $out $output;
+close $out;