summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcos <cos>2022-10-02 23:58:50 +0200
committercos <cos>2022-10-02 23:58:50 +0200
commite0330cb6feb7800608186d9374a99a9f6ab5dd63 (patch)
treec8154189e006c00ef03a30bb4f8efbfaae825787
downloadmicmot-main.zip
Initial commitHEADmain
-rw-r--r--irssi/scripts/micmot.pl90
-rwxr-xr-xlib/micmot-irssi-wrapper7
-rwxr-xr-xlib/micmot-menu-pane73
-rwxr-xr-xlib/micmot-weechat-wrapper7
-rw-r--r--lib/tmux-micmot.conf2
-rwxr-xr-xmicmot17
-rw-r--r--weechat/python/micmot.py82
7 files changed, 278 insertions, 0 deletions
diff --git a/irssi/scripts/micmot.pl b/irssi/scripts/micmot.pl
new file mode 100644
index 0000000..1ff8f87
--- /dev/null
+++ b/irssi/scripts/micmot.pl
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+#
+# Irssi script to display buffer activity in tmux pane name.
+#
+# Ideally one single feature complete chat client should be used, but this
+# workaround makes life a bit more bearably in our contemporary world requiring
+# multiple chat clients.
+#
+# Requires something like: `F=~/.irssi/micmot-fifo; mkfifo $F; tail -f $F &`
+#
+# Also requires ":set-option allow-rename on" in the tmux buffer.
+
+use strict;
+use vars qw ($VERSION %IRSSI);
+use 5.32.0;
+
+use Irssi;
+
+$VERSION = '0.1.0';
+%IRSSI = (
+ authors => 'cos',
+ contact => '|cos|',
+ description => 'Abusing tmux pane names for displaying channel activity.',
+ license => 'MIT',
+ name => 'micmot',
+);
+
+my $TMUX_FIFO = $ENV{'IRSSI_TMUX_FIFO'};
+$TMUX_FIFO = $ENV{'HOME'}.'/.irssi/micmot-fifo' unless $TMUX_FIFO;
+
+my $PANE_NAME = $ENV{'IRSSI_TMUX_PANE'};
+$PANE_NAME = 'irssi' unless $PANE_NAME;
+
+sub set_pane_title {
+ my ( $title ) = @_;
+
+ my $FILE_HANDLE;
+ open $FILE_HANDLE, '>>', $TMUX_FIFO or return;
+ printf($FILE_HANDLE "%c]2;%s%c\\", 0x1b, $title, 0x1b);
+ close $FILE_HANDLE;
+}
+
+sub set_pane_name {
+ my ( $name ) = @_;
+
+ my $FILE_HANDLE;
+ open $FILE_HANDLE, '>>', $TMUX_FIFO or return;
+ printf($FILE_HANDLE "%ck%s%c\\", 0x1b, $name, 0x1b);
+ close $FILE_HANDLE;
+}
+
+sub highlight_pane {
+ my $FILE_HANDLE;
+ open $FILE_HANDLE, '>>', $TMUX_FIFO or return;
+ printf($FILE_HANDLE "\x07");
+ close $FILE_HANDLE;
+}
+
+sub activity_to_tmux {
+ my $active_win = Irssi::active_win() or return;
+ my $active_win_refnum = $active_win->{'refnum'} or return;
+
+ my @windows = Irssi::windows() or return;
+ my $tmux = "";
+ for ( @windows ) {
+ # Skip the currently active window.
+ next if $_->{'refnum'} eq $active_win_refnum;
+
+ # Include any windows with data_level 'msg' or 'highlight'.
+ if ($_->{'active'}->{'data_level'} ge 2) {
+ if (length($tmux) > 0) {
+ $tmux .= ",";
+ }
+ $tmux .= $_->{'active'}->{'visible_name'};
+ }
+ }
+
+ set_pane_name( $tmux ? "[" . $tmux =~ s/[^.,#0-9A-Za-z-]+//rg . "]" :
+ $PANE_NAME );
+ if ( $tmux ) {
+ highlight_pane();
+ }
+}
+
+say qq($IRSSI{name} $VERSION using "$TMUX_FIFO");
+set_pane_name( $PANE_NAME );
+set_pane_title( $PANE_NAME );
+
+Irssi::signal_add 'window activity' => \&activity_to_tmux;
+Irssi::signal_add 'window changed' => \&activity_to_tmux;
diff --git a/lib/micmot-irssi-wrapper b/lib/micmot-irssi-wrapper
new file mode 100755
index 0000000..60869fe
--- /dev/null
+++ b/lib/micmot-irssi-wrapper
@@ -0,0 +1,7 @@
+#!/bin/sh -eu
+
+_fifo="${IRSSI_TMUX_FIFO:-${HOME}/.irssi/micmot-fifo}"
+
+mkfifo "${_fifo}"
+tail -f "${_fifo}" &
+irssi
diff --git a/lib/micmot-menu-pane b/lib/micmot-menu-pane
new file mode 100755
index 0000000..0b4900e
--- /dev/null
+++ b/lib/micmot-menu-pane
@@ -0,0 +1,73 @@
+#!/usr/bin/sh -eu
+
+_script_name='micmot'
+
+_micmot_menu_i_cmd='micmot-irssi-wrapper irssi'
+_micmot_menu_i_desc='Launch irssi as current user'
+_micmot_menu_w_cmd='micmot-weechat-wrapper weechat'
+_micmot_menu_w_desc='Launch weechat as current user'
+_micmot_menu_d_cmd='sudo -u bar WEECHAT_TMUX_PANE=foo
+ `which micmot-weechat-wrapper` weechat'
+_micmot_menu_d_desc='Launch weechat for foo as user bar'
+
+text_width() {
+ IFS=''
+ echo "$@" | while read -r _line; do
+ echo ${#_line}
+ done | sort -n | tail -1
+ unset IFS
+}
+
+micmot_banner() {
+ _micmot_banner="$( figlet -f slant "${_script_name}" )" || return 0
+ _text_width=$( text_width "$_micmot_banner" ) || return 0
+ _terminal_width=$( tput cols ) || return 0
+
+ _padding=$( printf "%$(( (_terminal_width - _text_width) / 2 ))s" ' ' )
+ IFS=''
+ echo "$_micmot_banner" | while read -r _line; do
+ echo "${_padding}${_line}"
+ done
+ unset IFS
+
+ unset _micmot_banner _terminal_width _text_width
+}
+
+micmot_menu() {
+ for _menu_option in $( set | sed -n 's/.*_micmot_menu_\(.\)_desc=.*/\1/p' )
+ do
+ printf "%3s %s\n" "${_menu_option}" \
+ "$( eval echo \${_micmot_menu_${_menu_option}_desc} )"
+ done
+ printf '\n'
+ printf "%3s %s\n" 'q' "Quit ${_script_name}. (Will not kill other panes)"
+ printf '\n> '
+ unset _menu_option
+}
+
+clear
+_input=''
+while ( true ); do
+ printf "\ek${_script_name}\e\\"
+ printf "\e]2;${_script_name}\e\\"
+ micmot_banner
+ micmot_menu
+
+ read -r _input
+ case "${_input}" in
+ 'q' | 'Q')
+ break
+ ;;
+ *)
+ if [ "$( eval echo \${_micmot_menu_${_input}_cmd} 2>/dev/null )" ]; then
+ echo "Selected: $( eval echo \${_micmot_menu_${_input}_desc} )"
+ tmux -L "${MICMOT_SOCKET}" \
+ new-window "$( eval echo \${_micmot_menu_${_input}_cmd} )"
+ else
+ echo "Unknown choice: ${_input}" >&2
+ fi
+ ;;
+ esac
+done
+
+# vim: sw=2 et
diff --git a/lib/micmot-weechat-wrapper b/lib/micmot-weechat-wrapper
new file mode 100755
index 0000000..ec18f78
--- /dev/null
+++ b/lib/micmot-weechat-wrapper
@@ -0,0 +1,7 @@
+#!/bin/sh -eu
+
+_fifo="${HOME}/.weechat/micmot-fifo"
+
+mkfifo "${_fifo}"
+tail -f "${_fifo}" &
+weechat
diff --git a/lib/tmux-micmot.conf b/lib/tmux-micmot.conf
new file mode 100644
index 0000000..58da856
--- /dev/null
+++ b/lib/tmux-micmot.conf
@@ -0,0 +1,2 @@
+set-option -g allow-rename on
+set-option -g remain-on-exit on
diff --git a/micmot b/micmot
new file mode 100755
index 0000000..4571011
--- /dev/null
+++ b/micmot
@@ -0,0 +1,17 @@
+#!/bin/sh -eu
+
+[ "${MICMOT_SOCKET:-}" ] || MICMOT_SOCKET='micmot'
+[ "${MICMOT_SESSION:-}" ] || MICMOT_SESSION='chat'
+
+export MICMOT_SOCKET
+
+_basedir="$( realpath "$( dirname "$0" )" )"
+PATH="${PATH}:${_basedir}/lib"
+export PATH
+
+tmux -f "./lib/tmux-micmot.conf" \
+ -L "${MICMOT_SOCKET}" \
+ new-session -s "${MICMOT_SESSION}" \
+ "micmot-menu-pane"
+
+unset _basedir
diff --git a/weechat/python/micmot.py b/weechat/python/micmot.py
new file mode 100644
index 0000000..e1a77b3
--- /dev/null
+++ b/weechat/python/micmot.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python3
+#
+# Weechat script to display buffer actitity in tmux pane name.
+#
+# A workaround for: https://github.com/weechat/weechat/issues/741
+#
+# Ideally weechat should support multiple hotlists, to make it possible to
+# logically separate different chats into groups. Since such a feature is
+# missing, and implementing it would be non-trivial, this script helps if
+# running multiple weechat instances within a tmux. It abuses the ability to
+# rename pane to make them double as channel activity indicators.
+#
+# Requires something like: `F=~/.weechat/micmot-fifo; mkfifo $F; tail -f $F &`
+#
+# Also requires ":set-option allow-rename on" in the tmux buffer.
+
+import os
+import re
+import weechat
+
+TMUX_FIFO = os.environ.get('WEECHAT_TMUX_FIFO',
+ os.environ['HOME'] + '/.weechat/micmot-fifo')
+
+PANE_NAME = os.environ.get('WEECHAT_TMUX_PANE', 'weechat')
+
+weechat.register(
+ "micmot",
+ "|cos|",
+ "0.1.0",
+ "MIT",
+ "Abusing tmux pane names for displaying channel activity.",
+ "",
+ ""
+)
+
+def set_pane_name(name):
+ with open(TMUX_FIFO,'a') as f:
+ f.write("\x1bk%s\x1b\\" % name)
+
+def highlight_pane():
+ with open(TMUX_FIFO,'a') as f:
+ f.write("\x07")
+
+def set_pane_title(name):
+ with open(TMUX_FIFO, 'a') as f:
+ f.write("\x1b]2;%s\x1b\\" % name)
+
+def hotlist_cb(a, b, c):
+ # https://weechat.org/files/doc/stable/weechat_user.en.html#notify_levels
+ tmux = ""
+ infolist = weechat.infolist_get("hotlist", "", "")
+ while weechat.infolist_next(infolist) != 0:
+ buffer_name = weechat.infolist_string(infolist, "buffer_name")
+ plugin_name = weechat.infolist_string(infolist, "plugin_name")
+ needle_pointer = weechat.buffer_search(plugin_name, buffer_name)
+ if needle_pointer:
+ short = weechat.buffer_get_string(needle_pointer, "short_name")
+ count_01 = weechat.infolist_integer(infolist, "count_01")
+ count_02 = weechat.infolist_integer(infolist, "count_02")
+ count_03 = weechat.infolist_integer(infolist, "count_03")
+ if count_01 > 0 or count_02 > 0 or count_03 > 0:
+ if tmux:
+ tmux = "{},{}".format(tmux,short)
+ else:
+ tmux = "{}".format(short)
+ else:
+ weechat.prnt("", "No buffer matching {} for plugin {}."
+ .format(buffer_name, plugin_name))
+
+ if tmux:
+ set_pane_name("[{}]".format(re.sub(r'[^.,#0-9A-Za-z-]+', '', tmux)))
+ highlight_pane()
+ else:
+ set_pane_name(PANE_NAME)
+
+ weechat.infolist_free(infolist)
+ return weechat.WEECHAT_RC_OK
+
+weechat.prnt("", "micmot " + PANE_NAME + TMUX_FIFO)
+set_pane_name(PANE_NAME)
+set_pane_title(PANE_NAME)
+weechat.hook_signal("hotlist_changed", "hotlist_cb", "")