summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Traut <manut@ford.mecka.net>2019-08-07 22:47:19 +0200
committerManuel Traut <manut@ford.mecka.net>2019-08-07 22:47:19 +0200
commit120eccbfa839a0723f6ffeb9b80742bc960a3d41 (patch)
treecb3594a3e068fc89dc55a34a8302fb7887bc83bc
initial version from ford
Signed-off-by: Manuel Traut <manut@ford.mecka.net>
-rw-r--r--.Xresources84
-rw-r--r--.Xsession2
-rw-r--r--.irssi/config234
-rw-r--r--.irssi/default.theme294
-rw-r--r--.irssi/elpi.theme91
-rw-r--r--.irssi/mithru.theme299
-rw-r--r--.irssi/scripts/act.pl72
-rw-r--r--.irssi/scripts/adv_windowlist.pl2478
-rw-r--r--.irssi/scripts/autorun/act.pl72
-rw-r--r--.irssi/scripts/autorun/adv_windowlist.pl2478
-rw-r--r--.irssi/scripts/autorun/bitlbee_tab_completion.pl196
-rw-r--r--.irssi/scripts/autorun/chanact.pl479
-rw-r--r--.irssi/scripts/autorun/mail.pl414
-rw-r--r--.irssi/scripts/autorun/nickcolor.pl156
-rw-r--r--.irssi/scripts/autorun/trackbar.pl189
-rw-r--r--.irssi/scripts/bitlbee_tab_completion.pl196
-rw-r--r--.irssi/scripts/chanact.pl479
-rw-r--r--.irssi/scripts/mail.pl414
-rw-r--r--.irssi/scripts/nickcolor.pl156
-rw-r--r--.irssi/scripts/nicklist.pl611
-rw-r--r--.irssi/scripts/trackbar.pl189
-rw-r--r--.irssi/scripts/xlist.pl65
-rw-r--r--.mailcap7
-rw-r--r--.muttrc175
-rw-r--r--.vim/.netrwhist6
-rw-r--r--.vim/colors/solarized.vim1117
-rw-r--r--.vimrc56
-rwxr-xr-xaf.sh18
m---------config-awesome/battery-widget0
m---------config-awesome/brightness0
-rw-r--r--config-awesome/rc.lua556
-rwxr-xr-xicalview.pl86
-rwxr-xr-xicalview.sh2
33 files changed, 11671 insertions, 0 deletions
diff --git a/.Xresources b/.Xresources
new file mode 100644
index 0000000..6aa8dc1
--- /dev/null
+++ b/.Xresources
@@ -0,0 +1,84 @@
+*.faceName: Source Code Pro
+*.faceSize: 12
+
+URxvt.font: xft:Source Code Pro:size=12
+URxvt.scrollBar: false
+URxvt.letterSpace: -1
+
+*.selectToClipboard: true
+
+*.VT100.Translations: #override \
+ Ctrl Shift <Key>V: insert-selection(CLIPBOARD) \n\
+ Ctrl Shift <Key>C: copy-selection(CLIPBOARD) \n\
+ Shift <Btn1Up>: exec-formatted("firefox '%t'", PRIMARY)
+
+! Solarized color scheme for the X Window System
+!
+! http://ethanschoonover.com/solarized
+
+
+! Common
+
+#define S_yellow #b58900
+#define S_orange #cb4b16
+#define S_red #dc322f
+#define S_magenta #d33682
+#define S_violet #6c71c4
+#define S_blue #268bd2
+#define S_cyan #2aa198
+#define S_green #859900
+
+
+! Dark
+
+#define S_base03 #002b36
+#define S_base02 #073642
+#define S_base01 #586e75
+#define S_base00 #657b83
+#define S_base0 #839496
+#define S_base1 #93a1a1
+#define S_base2 #eee8d5
+#define S_base3 #fdf6e3
+
+
+! Light
+
+! #define S_base03 #fdf6e3
+! #define S_base02 #eee8d5
+! #define S_base01 #93a1a1
+! #define S_base00 #839496
+! #define S_base0 #657b83
+! #define S_base1 #586e75
+! #define S_base2 #073642
+! #define S_base3 #002b36
+
+
+! To only apply colors to your terminal, for example, prefix
+! the color assignment statement with its name. Example:
+!
+! URxvt*background: S_base03
+
+*background: S_base03
+*foreground: S_base0
+*fading: 40
+*fadeColor: S_base03
+*cursorColor: S_base1
+*pointerColorBackground: S_base01
+*pointerColorForeground: S_base1
+
+*color0: S_base02
+*color1: S_red
+*color2: S_green
+*color3: S_yellow
+*color4: S_blue
+*color5: S_magenta
+*color6: S_cyan
+*color7: S_base2
+*color9: S_orange
+*color8: S_base03
+*color10: S_base01
+*color11: S_base00
+*color12: S_base0
+*color13: S_violet
+*color14: S_base1
+*color15: S_base3
diff --git a/.Xsession b/.Xsession
new file mode 100644
index 0000000..c90f050
--- /dev/null
+++ b/.Xsession
@@ -0,0 +1,2 @@
+xrdb -load ~/.Xresources
+exec awesome
diff --git a/.irssi/config b/.irssi/config
new file mode 100644
index 0000000..e6615e8
--- /dev/null
+++ b/.irssi/config
@@ -0,0 +1,234 @@
+servers = (
+ # {
+ # address = "mail.linutronix.de";
+ # chatnet = "linutronix";
+ # port = "6669";
+ # use_ssl = "yes";
+ # ssl_verify = "no";
+ # autoconnect = "yes";
+ # password = "XXXX";
+ # },
+ {
+ address = "mecka.net";
+ chatnet = "mecka.net";
+ port = "6669";
+ use_ssl = "no";
+ ssl_verify = "no";
+ autoconnect = "yes";
+ password = "XXXX";
+ },
+ {
+ address = "irc.oftc.net";
+ chatnet = "OFTC";
+ port = "6667";
+ use_ssl = "no";
+ ssl_verify = "no";
+ autoconnect = "yes";
+ }
+);
+
+chatnets = {
+ # linutronix = { type = "IRC"; };
+ OFTC = {
+ type = "IRC";
+ autosendcmd = "/msg nickserv IDENTIFY XXXX ;wait 2000";
+ };
+ "mecka.net" = { type = "IRC"; };
+};
+
+channels = (
+ # { name = "#lx"; chatnet = "linutronix"; autojoin = "yes"; },
+ { name = "#linux-rt"; chatnet = "OFTC"; autojoin = "yes"; },
+ { name = "#lxhardcore"; chatnet = "mecka.net"; autojoin = "yes"; }
+);
+
+aliases = {
+ J = "join";
+ WJOIN = "join -window";
+ WQUERY = "query -window";
+ LEAVE = "part";
+ BYE = "quit";
+ EXIT = "quit";
+ SIGNOFF = "quit";
+ DESCRIBE = "action";
+ DATE = "time";
+ HOST = "userhost";
+ LAST = "lastlog";
+ SAY = "msg *";
+ WI = "whois";
+ WII = "whois $0 $0";
+ WW = "whowas";
+ W = "who";
+ N = "names";
+ M = "msg";
+ T = "topic";
+ C = "clear";
+ CL = "clear";
+ K = "kick";
+ KB = "kickban";
+ KN = "knockout";
+ BANS = "ban";
+ B = "ban";
+ MUB = "unban *";
+ UB = "unban";
+ IG = "ignore";
+ UNIG = "unignore";
+ SB = "scrollback";
+ UMODE = "mode $N";
+ WC = "window close";
+ WN = "window new hide";
+ SV = "say Irssi $J ($V) - http://irssi.org/";
+ GOTO = "sb goto";
+ CHAT = "dcc chat";
+ RUN = "SCRIPT LOAD";
+ CALC = "exec - if which bc &>/dev/null\\; then echo '$*' | bc | awk '{print \"$*=\"$$1}'\\; else echo bc was not found\\; fi";
+ SBAR = "STATUSBAR";
+ INVITELIST = "mode $C +I";
+ Q = "QUERY";
+ "MANUAL-WINDOWS" = "set use_status_window off;set autocreate_windows off;set autocreate_query_level none;set autoclose_windows off;set reuse_unused_windows on;save";
+ EXEMPTLIST = "mode $C +e";
+ ATAG = "WINDOW SERVER";
+};
+
+statusbar = {
+ # formats:
+ # when using {templates}, the template is shown only if it's argument isn't
+ # empty unless no argument is given. for example {sb} is printed always,
+ # but {sb $T} is printed only if $T isn't empty.
+
+ items = {
+ # start/end text in statusbars
+ barstart = "{sbstart}";
+ barend = "{sbend}";
+
+ topicbarstart = "{topicsbstart}";
+ topicbarend = "{topicsbend}";
+
+ # treated "normally", you could change the time/user name to whatever
+ time = "{sb $Z}";
+ user = "{sb {sbnickmode $cumode}$N{sbmode $usermode}{sbaway $A}}";
+
+ # treated specially .. window is printed with non-empty windows,
+ # window_empty is printed with empty windows
+ window = "{sb $winref:$tag/$itemname{sbmode $M}}";
+ window_empty = "{sb $winref{sbservertag $tag}}";
+ prompt = "{prompt $[.15]itemname}";
+ prompt_empty = "{prompt $winname}";
+ topic = " $topic";
+ topic_empty = " Irssi v$J - http://irssi.org/help/";
+
+ # all of these treated specially, they're only displayed when needed
+ lag = "{sb Lag: $0-}";
+ act = "{sb Act: $0-}";
+ more = "-- more --";
+ };
+
+ # there's two type of statusbars. root statusbars are either at the top
+ # of the screen or at the bottom of the screen. window statusbars are at
+ # the top/bottom of each split window in screen.
+ default = {
+ # the "default statusbar" to be displayed at the bottom of the window.
+ # contains all the normal items.
+ window = {
+ disabled = "no";
+
+ # window, root
+ type = "window";
+ # top, bottom
+ placement = "bottom";
+ # number
+ position = "1";
+ # active, inactive, always
+ visible = "active";
+
+ # list of items in statusbar in the display order
+ items = {
+ barstart = { priority = "100"; };
+ time = { };
+ user = { };
+ window = { };
+ window_empty = { };
+ lag = { priority = "-1"; };
+ act = { priority = "10"; };
+ more = { priority = "-1"; alignment = "right"; };
+ barend = { priority = "100"; alignment = "right"; };
+ };
+ };
+
+ # statusbar to use in inactive split windows
+ window_inact = {
+ type = "window";
+ placement = "bottom";
+ position = "1";
+ visible = "inactive";
+ items = {
+ barstart = { priority = "100"; };
+ window = { };
+ window_empty = { };
+ more = { priority = "-1"; alignment = "right"; };
+ barend = { priority = "100"; alignment = "right"; };
+ };
+ };
+
+ # we treat input line as yet another statusbar :) It's possible to
+ # add other items before or after the input line item.
+ prompt = {
+ type = "root";
+ placement = "bottom";
+ # we want to be at the bottom always
+ position = "100";
+ visible = "always";
+ items = {
+ prompt = { priority = "-1"; };
+ prompt_empty = { priority = "-1"; };
+ # treated specially, this is the real input line.
+ input = { priority = "10"; };
+ };
+ };
+
+ # topicbar
+ topic = {
+ type = "root";
+ placement = "top";
+ position = "1";
+ visible = "always";
+ items = {
+ topicbarstart = { priority = "100"; };
+ topic = { };
+ topic_empty = { };
+ topicbarend = { priority = "100"; alignment = "right"; };
+ };
+ };
+ awl_0 = {
+ items = {
+ barstart = { priority = "100"; };
+ awl_0 = { };
+ barend = { priority = "100"; alignment = "right"; };
+ };
+ };
+ };
+};
+settings = {
+ core = {
+ real_name = "Manuel Traut";
+ user_name = "manut";
+ nick = "manut";
+ timestamp_format = "%D-%H:%M:%S";
+ quit_message = "huhu";
+ };
+ "fe-text" = { actlist_sort = "refnum"; };
+ "fe-common/core" = {
+ theme = "mithru";
+ autolog = "yes";
+ autolog_path = "~/irclogs/$tag/$0.log";
+ autoclose_query = "99999999999999999999999";
+ show_quit_once = "yes";
+ };
+ "perl/core/scripts" = { nicklist_automode = "SCREEN"; };
+};
+hilights = ( { text = "nick"; nick = "yes"; word = "yes"; } );
+logs = { };
+ignores = (
+ { level = "JOINS QUITS MODES"; channels = ( "#bitlbee" ); }
+);
+keyboard = ( { key = "meta-p"; id = "change_window"; data = "20"; } );
diff --git a/.irssi/default.theme b/.irssi/default.theme
new file mode 100644
index 0000000..98af18b
--- /dev/null
+++ b/.irssi/default.theme
@@ -0,0 +1,294 @@
+# When testing changes, the easiest way to reload the theme is with /RELOAD.
+# This reloads the configuration file too, so if you did any changes remember
+# to /SAVE it first. Remember also that /SAVE overwrites the theme file with
+# old data so keep backups :)
+
+# TEMPLATES:
+
+# The real text formats that irssi uses are the ones you can find with
+# /FORMAT command. Back in the old days all the colors and texts were mixed
+# up in those formats, and it was really hard to change the colors since you
+# might have had to change them in tens of different places. So, then came
+# this templating system.
+
+# Now the /FORMATs don't have any colors in them, and they also have very
+# little other styling. Most of the stuff you need to change is in this
+# theme file. If you can't change something here, you can always go back
+# to change the /FORMATs directly, they're also saved in these .theme files.
+
+# So .. the templates. They're those {blahblah} parts you see all over the
+# /FORMATs and here. Their usage is simply {name parameter1 parameter2}.
+# When irssi sees this kind of text, it goes to find "name" from abstracts
+# block below and sets "parameter1" into $0 and "parameter2" into $1 (you
+# can have more parameters of course). Templates can have subtemplates.
+# Here's a small example:
+# /FORMAT format hello {colorify {underline world}}
+# abstracts = { colorify = "%G$0-%n"; underline = "%U$0-%U"; }
+# When irssi expands the templates in "format", the final string would be:
+# hello %G%Uworld%U%n
+# ie. underlined bright green "world" text.
+# and why "$0-", why not "$0"? $0 would only mean the first parameter,
+# $0- means all the parameters. With {underline hello world} you'd really
+# want to underline both of the words, not just the hello (and world would
+# actually be removed entirely).
+
+# COLORS:
+
+# You can find definitions for the color format codes in docs/formats.txt.
+
+# There's one difference here though. %n format. Normally it means the
+# default color of the terminal (white mostly), but here it means the
+# "reset color back to the one it was in higher template". For example
+# if there was /FORMAT test %g{foo}bar, and foo = "%Y$0%n", irssi would
+# print yellow "foo" (as set with %Y) but "bar" would be green, which was
+# set at the beginning before the {foo} template. If there wasn't the %g
+# at start, the normal behaviour of %n would occur. If you _really_ want
+# to use the terminal's default color, use %N.
+
+#############################################################################
+
+# default foreground color (%N) - -1 is the "default terminal color"
+default_color = "-1";
+
+# print timestamp/servertag at the end of line, not at beginning
+info_eol = "false";
+
+# these characters are automatically replaced with specified color
+# (dark grey by default)
+replaces = { "[]=" = "%K$*%n"; };
+
+abstracts = {
+ ##
+ ## generic
+ ##
+
+ # text to insert at the beginning of each non-message line
+ line_start = "%B-%W!%B-%n ";
+
+ # timestamp styling, nothing by default
+ timestamp = "$*";
+
+ # any kind of text that needs hilighting, default is to bold
+ hilight = "%_$*%_";
+
+ # any kind of error message, default is bright red
+ error = "%R$*%n";
+
+ # channel name is printed
+ channel = "%_$*%_";
+
+ # nick is printed
+ nick = "%_$*%_";
+
+ # nick host is printed
+ nickhost = "[$*]";
+
+ # server name is printed
+ server = "%_$*%_";
+
+ # some kind of comment is printed
+ comment = "[$*]";
+
+ # reason for something is printed (part, quit, kick, ..)
+ reason = "{comment $*}";
+
+ # mode change is printed ([+o nick])
+ mode = "{comment $*}";
+
+ ##
+ ## channel specific messages
+ ##
+
+ # highlighted nick/host is printed (joins)
+ channick_hilight = "%C$*%n";
+ chanhost_hilight = "{nickhost %c$*%n}";
+
+ # nick/host is printed (parts, quits, etc.)
+ channick = "%c$*%n";
+ chanhost = "{nickhost $*}";
+
+ # highlighted channel name is printed
+ channelhilight = "%c$*%n";
+
+ # ban/ban exception/invite list mask is printed
+ ban = "%c$*%n";
+
+ ##
+ ## messages
+ ##
+
+ # the basic styling of how to print message, $0 = nick mode, $1 = nick
+ msgnick = "%K<%n$0$1-%K>%n %|";
+
+ # message from you is printed. "msgownnick" specifies the styling of the
+ # nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the
+ # whole line.
+
+ # Example1: You want the message text to be green:
+ # ownmsgnick = "{msgnick $0 $1-}%g";
+ # Example2.1: You want < and > chars to be yellow:
+ # ownmsgnick = "%Y{msgnick $0 $1-%Y}%n";
+ # (you'll also have to remove <> from replaces list above)
+ # Example2.2: But you still want to keep <> grey for other messages:
+ # pubmsgnick = "%K{msgnick $0 $1-%K}%n";
+ # pubmsgmenick = "%K{msgnick $0 $1-%K}%n";
+ # pubmsghinick = "%K{msgnick $1 $0$2-%n%K}%n";
+ # ownprivmsgnick = "%K{msgnick $*%K}%n";
+ # privmsgnick = "%K{msgnick %R$*%K}%n";
+
+ # $0 = nick mode, $1 = nick
+ ownmsgnick = "{msgnick $0 $1-}";
+ ownnick = "%W$*%n";
+
+ # public message in channel, $0 = nick mode, $1 = nick
+ pubmsgnick = "{msgnick $0 $1-}";
+ pubnick = "%N$*%n";
+
+ # public message in channel meant for me, $0 = nick mode, $1 = nick
+ pubmsgmenick = "{msgnick $0 $1-}";
+ menick = "%Y$*%n";
+
+ # public highlighted message in channel
+ # $0 = highlight color, $1 = nick mode, $2 = nick
+ pubmsghinick = "{msgnick $1 $0$2-%n}";
+
+ # channel name is printed with message
+ msgchannel = "%K:%c$*%n";
+
+ # private message, $0 = nick, $1 = host
+ privmsg = "[%R$0%K(%r$1-%K)%n] ";
+
+ # private message from you, $0 = "msg", $1 = target nick
+ ownprivmsg = "[%r$0%K(%R$1-%K)%n] ";
+
+ # own private message in query
+ ownprivmsgnick = "{msgnick $*}";
+ ownprivnick = "%W$*%n";
+
+ # private message in query
+ privmsgnick = "{msgnick %R$*%n}";
+
+ ##
+ ## Actions (/ME stuff)
+ ##
+
+ # used internally by this theme
+ action_core = "%W * $*%n";
+
+ # generic one that's used by most actions
+ action = "{action_core $*} ";
+
+ # own action, both private/public
+ ownaction = "{action $*}";
+
+ # own action with target, both private/public
+ ownaction_target = "{action_core $0}%K:%c$1%n ";
+
+ # private action sent by others
+ pvtaction = "%W (*) $*%n ";
+ pvtaction_query = "{action $*}";
+
+ # public action sent by others
+ pubaction = "{action $*}";
+
+
+ ##
+ ## other IRC events
+ ##
+
+ # whois
+ whois = "%# $[8]0 : $1-";
+
+ # notices
+ ownnotice = "[%r$0%K(%R$1-%K)]%n ";
+ notice = "%K-%M$*%K-%n ";
+ pubnotice_channel = "%K:%m$*";
+ pvtnotice_host = "%K(%m$*%K)";
+ servernotice = "%g!$*%n ";
+
+ # CTCPs
+ ownctcp = "[%r$0%K(%R$1-%K)] ";
+ ctcp = "%g$*%n";
+
+ # wallops
+ wallop = "%W$*%n: ";
+ wallop_nick = "%n$*";
+ wallop_action = "%W * $*%n ";
+
+ # netsplits
+ netsplit = "%R$*%n";
+ netjoin = "%C$*%n";
+
+ # /names list
+ names_prefix = "";
+ names_nick = "[%_$0%_$1-] ";
+ names_nick_op = "{names_nick $*}";
+ names_nick_halfop = "{names_nick $*}";
+ names_nick_voice = "{names_nick $*}";
+ names_users = "[%g$*%n]";
+ names_channel = "%G$*%n";
+
+ # DCC
+ dcc = "%g$*%n";
+ dccfile = "%_$*%_";
+
+ # DCC chat, own msg/action
+ dccownmsg = "[%r$0%K($1-%K)%n] ";
+ dccownnick = "%R$*%n";
+ dccownquerynick = "%W$*%n";
+ dccownaction = "{action $*}";
+ dccownaction_target = "{action_core $0}%K:%c$1%n ";
+
+ # DCC chat, others
+ dccmsg = "[%G$1-%K(%g$0%K)%n] ";
+ dccquerynick = "%G$*%n";
+ dccaction = "%W (*dcc*) $*%n %|";
+
+ ##
+ ## statusbar
+ ##
+
+ # default background for all statusbars. You can also give
+ # the default foreground color for statusbar items.
+ sb_background = "%4%w";
+
+ # default backround for "default" statusbar group
+ #sb_default_bg = "%4";
+ # background for prompt / input line
+ sb_prompt_bg = "%n";
+ # background for info statusbar
+ sb_info_bg = "%8";
+ # background for topicbar (same default)
+ #sb_topic_bg = "%4";
+
+ # text at the beginning of statusbars. sb-item already puts
+ # space there,so we don't use anything by default.
+ sbstart = "";
+ # text at the end of statusbars. Use space so that it's never
+ # used for anything.
+ sbend = " ";
+
+ topicsbstart = "{sbstart $*}";
+ topicsbend = "{sbend $*}";
+
+ prompt = "[$*] ";
+
+ sb = " %c[%n$*%c]%n";
+ sbmode = "(%c+%n$*)";
+ sbaway = " (%GzZzZ%n)";
+ sbservertag = ":$0 (change with ^X)";
+ sbnickmode = "$0";
+
+ # activity in statusbar
+
+ # ',' separator
+ sb_act_sep = "%c$*";
+ # normal text
+ sb_act_text = "%c$*";
+ # public message
+ sb_act_msg = "%W$*";
+ # hilight
+ sb_act_hilight = "%M$*";
+ # hilight with specified color, $0 = color, $1 = text
+ sb_act_hilight_color = "$0$1-%n";
+};
diff --git a/.irssi/elpi.theme b/.irssi/elpi.theme
new file mode 100644
index 0000000..9aae356
--- /dev/null
+++ b/.irssi/elpi.theme
@@ -0,0 +1,91 @@
+default_color = "-1";
+info_eol = "false";
+replaces = { "[]=" = "%p$*%n"; };
+abstracts = {
+ line_start = " %5%w %n ";
+ timestamp = "$*";
+ hilight = "%_$*%_";
+ error = "%R$*%n";
+ channel = "%_$*%_";
+ nick = "%_$*%_";
+ nickhost = "[$*]";
+ server = "%_$*%_";
+ comment = "[$*]";
+ reason = "{comment $*}";
+ mode = "{comment $*}";
+ channick_hilight = "%C$*%n";
+ chanhost_hilight = "{nickhost %c$*%n}";
+ channick = "%c$*%n";
+ chanhost = "{nickhost $*}";
+ channelhilight = "%c$*%n";
+ ban = "%c$*%n";
+ msgnick = "%c<%n$0$1-%c>%n %|";
+ ownmsgnick = "{msgnick $0 $1-}";
+ ownnick = "%U$*%n";
+ pubmsgnick = "{msgnick $0 $1-}";
+ pubnick = "%N$*%n";
+ pubmsgmenick = "{msgnick $0 $1-}";
+ menick = "%C$*%n";
+ pubmsghinick = "{msgnick $1 $0$2-%n}";
+ msgchannel = "%K:%c$*%n";
+ privmsg = "[%W$0%K(%w$1-%K)%n] ";
+ ownprivmsg = "[%C$0%K(%c$1-%K)%n] ";
+ ownprivmsgnick = "{msgnick $*}";
+ ownprivnick = "%W$*%n";
+ privmsgnick = "{msgnick %C$*%n}";
+ action_core = "%c* %n$*";
+ action = "{action_core $*} ";
+ ownaction = "{action %U$*%n}";
+ ownaction_target = "{action_core $0}%K:%c$1%n ";
+ pvtaction = "%W (*) $*%n ";
+ pvtaction_query = "{action $*}";
+ pubaction = "{action $*}";
+ ownnotice = "[%C$0%K(%c$1-%K)]%n ";
+ notice = "%K-%M$*%K-%n ";
+ pubnotice_channel = "%K:%m$*";
+ pvtnotice_host = "%K(%m$*%K)";
+ servernotice = "%P!$*%n ";
+ ownctcp = "[%r$0%K(%R$1-%K)] ";
+ ctcp = "%g$*%n";
+ wallop = "%W$*%n: ";
+ wallop_nick = "%n$*";
+ wallop_action = "%W * $*%n ";
+ netsplit = "%R$*%n";
+ netjoin = "%C$*%n";
+ names_prefix = "";
+ names_nick = "[%_$0%_$1-] ";
+ names_nick_op = "{names_nick $*}";
+ names_nick_halfop = "{names_nick $*}";
+ names_nick_voice = "{names_nick $*}";
+ names_users = "[%g$*%n]";
+ names_channel = "%G$*%n";
+ dcc = "%g$*%n";
+ dccfile = "%_$*%_";
+ dccownmsg = "[%r$0%K($1-%K)%n] ";
+ dccownnick = "%R$*%n";
+ dccownquerynick = "%W$*%n";
+ dccownaction = "{action $*}";
+ dccownaction_target = "{action_core $0}%K:%c$1%n ";
+ dccmsg = "[%G$1-%K(%g$0%K)%n] ";
+ dccquerynick = "%G$*%n";
+ dccaction = "%W (*dcc*) $*%n %|";
+ sb_background = "%p";
+ sb_prompt_bg = "%p";
+ sb_info_bg = "%8";
+ sb_topic_bg = "%5";
+ sbstart = "%5 %n";
+ sbend = " ";
+ topicsbstart = "{sbstart $*}";
+ topicsbend = "{sbend $*}";
+ prompt = "$* ";
+ sb = "%c.%n$* ";
+ sbmode = "%c+%n$*";
+ sbaway = " %gzZzZ%n";
+ sbservertag = "%c:%n$0";
+ sbnickmode = "$0";
+ sb_act_sep = "%c$*";
+ sb_act_text = "%c$*";
+ sb_act_msg = "%w$*";
+ sb_act_hilight = "%W$*";
+ sb_act_hilight_color = "$0$1-%n";
+};
diff --git a/.irssi/mithru.theme b/.irssi/mithru.theme
new file mode 100644
index 0000000..ae41c9a
--- /dev/null
+++ b/.irssi/mithru.theme
@@ -0,0 +1,299 @@
+# When testing changes, the easiest way to reload the theme is with /RELOAD.
+# This reloads the configuration file too, so if you did any changes remember
+# to /SAVE it first. Remember also that /SAVE overwrites the theme file with
+# old data so keep backups :)
+
+# TEMPLATES:
+
+# The real text formats that irssi uses are the ones you can find with
+# /FORMAT command. Back in the old days all the colors and texts were mixed
+# up in those formats, and it was really hard to change the colors since you
+# might have had to change them in tens of different places. So, then came
+# this templating system.
+
+# Now the /FORMATs don't have any colors in them, and they also have very
+# little other styling. Most of the stuff you need to change is in this
+# theme file. If you can't change something here, you can always go back
+# to change the /FORMATs directly, they're also saved in these .theme files.
+
+# So .. the templates. They're those {blahblah} parts you see all over the
+# /FORMATs and here. Their usage is simply {name parameter1 parameter2}.
+# When irssi sees this kind of text, it goes to find "name" from abstracts
+# block below and sets "parameter1" into $0 and "parameter2" into $1 (you
+# can have more parameters of course). Templates can have subtemplates.
+# Here's a small example:
+# /FORMAT format hello {colorify {underline world}}
+# abstracts = { colorify = "%G$0-%n"; underline = "%U$0-%U"; }
+# When irssi expands the templates in "format", the final string would be:
+# hello %G%Uworld%U%n
+# ie. underlined bright green "world" text.
+# and why "$0-", why not "$0"? $0 would only mean the first parameter,
+# $0- means all the parameters. With {underline hello world} you'd really
+# want to underline both of the words, not just the hello (and world would
+# actually be removed entirely).
+
+# COLORS:
+
+# You can find definitions for the color format codes in docs/formats.txt.
+
+# There's one difference here though. %n format. Normally it means the
+# default color of the terminal (white mostly), but here it means the
+# "reset color back to the one it was in higher template". For example
+# if there was /FORMAT test %g{foo}bar, and foo = "%Y$0%n", irssi would
+# print yellow "foo" (as set with %Y) but "bar" would be green, which was
+# set at the beginning before the {foo} template. If there wasn't the %g
+# at start, the normal behaviour of %n would occur. If you _really_ want
+# to use the terminal's default color, use %N.
+
+#############################################################################
+
+# default foreground color (%N) - -1 is the "default terminal color"
+default_color = "-1";
+
+# print timestamp/servertag at the end of line, not at beginning
+info_eol = "false";
+
+# these characters are automatically replaced with specified color
+# (dark grey by default)
+replaces = { "[]=" = "%K$*%n"; };
+
+abstracts = {
+ ##
+ ## generic
+ ##
+
+ # text to insert at the beginning of each non-message line
+ # line_start = "%B-%G!%B-%n ";
+ #line_start = "%Y***%n ";
+ line_start = "%K-->%n ";
+
+ # timestamp styling, nothing by default
+ timestamp = "$*";
+
+ # any kind of text that needs hilighting, default is to bold
+ hilight = "%_$*%_";
+
+ # any kind of error message, default is bright red
+ error = "%R$*%n";
+
+ # channel name is printed
+ channel = "%_$*%_";
+
+ # nick is printed
+ nick = "%_$*%_";
+
+ # nick host is printed
+ nickhost = "%W[$*]";
+
+ # server name is printed
+ server = "%_$*%_";
+
+ # some kind of comment is printed
+ comment = "[%W$*%n]";
+
+ # reason for something is printed (part, quit, kick, ..)
+ reason = "{comment $*}";
+
+ # mode change is printed ([+o nick])
+ mode = "{comment $*}";
+
+ ##
+ ## channel specific messages
+ ##
+
+ # highlighted nick/host is printed (joins)
+ channick_hilight = "%g$*";
+ chanhost_hilight = "{nickhost %g$*}";
+
+ # nick/host is printed (parts, quits, etc.)
+ #channick = "%K$*%n";
+ channick = "%r$*%n";
+ chanhost = "{nickhost %r$*}";
+
+ # highlighted channel name is printed
+ channelhilight = "%W$*%n";
+
+ # ban/ban exception/invite list mask is printed
+ ban = "%W$*%n";
+
+ ##
+ ## messages
+ ##
+
+ # the basic styling of how to print message, $0 = nick mode, $1 = nick
+ msgnick = "%K<%n$0$1-%K>%n %|";
+
+ # message from you is printed. "msgownnick" specifies the styling of the
+ # nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the
+ # whole line.
+
+ # Example1: You want the message text to be green:
+ # ownmsgnick = "{msgnick $0 $1-}%g";
+ # Example2.1: You want < and > chars to be yellow:
+ # ownmsgnick = "%Y{msgnick $0 $1-%Y}%n";
+ # (you'll also have to remove <> from replaces list above)
+ # Example2.2: But you still want to keep <> grey for other messages:
+ # pubmsgnick = "%K{msgnick $0 $1-%K}%n";
+ # pubmsgmenick = "%K{msgnick $0 $1-%K}%n";
+ # pubmsghinick = "%K{msgnick $1 $0$2-%n%K}%n";
+ # ownprivmsgnick = "%K{msgnick $*%K}%n";
+ # privmsgnick = "%K{msgnick %R$*%K}%n";
+
+ # $0 = nick mode, $1 = nick
+ ownmsgnick = "{msgnick $0 $1-}";
+ ownnick = "%W$*%n";
+
+ # public message in channel, $0 = nick mode, $1 = nick
+ pubmsgnick = "{msgnick $0 $1-}";
+ pubnick = "%N$*%n";
+
+ # public message in channel meant for me, $0 = nick mode, $1 = nick
+ pubmsgmenick = "{msgnick $0 $1-}";
+ menick = "%Y$*%n";
+
+ # public highlighted message in channel
+ # $0 = highlight color, $1 = nick mode, $2 = nick
+ pubmsghinick = "{msgnick $1 $0$2-%n}";
+
+ # channel name is printed with message
+ msgchannel = "%K:%Y$*%n";
+
+ # private message, $0 = nick, $1 = host
+ privmsg = "[$0%K(%r$1-%K)%n] ";
+
+ # private message from you, $0 = "msg", $1 = target nick
+ ownprivmsg = "[%r$0%K(%R$1-%K)%n] ";
+
+ # own private message in query
+ ownprivmsgnick = "{msgnick $*}";
+ ownprivnick = "%W$*%n";
+
+ # private message in query
+ privmsgnick = "{msgnick $*}";
+
+ ##
+ ## Actions (/ME stuff)
+ ##
+
+ # used internally by this theme
+ action_core = "%W * $*%n";
+
+ # generic one that's used by most actions
+ action = "{action_core $*} ";
+
+ # own action, both private/public
+ ownaction = "{action $*}";
+
+ # own action with target, both private/public
+ ownaction_target = "{action_core $0}%K:%c$1%n ";
+
+ # private action sent by others
+ pvtaction = "%W (*) $*%n ";
+ pvtaction_query = "{action $*}";
+
+ # public action sent by others
+ pubaction = "{action $*}";
+
+
+ ##
+ ## other IRC events
+ ##
+
+ # whois
+ whois = "%# $[8]0 : $1-";
+
+ # notices
+ ownnotice = "[%r$0%K(%R$1-%K)]%n ";
+ notice = "%K-%C$*%K-%n ";
+ pubnotice_channel = "%K:%c$*";
+ pvtnotice_host = "%K(%c$*%K)";
+ servernotice = "%B!$*%n ";
+
+ # CTCPs
+ ownctcp = "[%r$0%K(%R$1-%K)] ";
+ ctcp = "%B$*%n";
+
+ # wallops
+ wallop = "%W$*%n: ";
+ wallop_nick = "%n$*";
+ wallop_action = "%W * $*%n ";
+
+ # netsplits
+ netsplit = "%R$*%n";
+ netjoin = "%C$*%n";
+
+ # /names list
+ names_prefix = "";
+ names_nick = "[%_$0%_$1-] ";
+ names_nick_op = "{names_nick $*}";
+ names_nick_halfop = "{names_nick $*}";
+ names_nick_voice = "{names_nick $*}";
+ names_users = "[%W$*%n]";
+ names_channel = "%W$*%n";
+
+ # DCC
+ dcc = "%W$*%n";
+ dccfile = "%_$*%_";
+
+ # DCC chat, own msg/action
+ dccownmsg = "[%r$0%K($1-%K)%n] ";
+ dccownnick = "%R$*%n";
+ dccownquerynick = "%W$*%n";
+ dccownaction = "{action $*}";
+ dccownaction_target = "{action_core $0}%K:%c$1%n ";
+
+ # DCC chat, others
+ dccmsg = "[%W$1-%K(%G$0%K)%n] ";
+ dccquerynick = "%W$*%n";
+ dccaction = "%W (*dcc*) $*%n %|";
+
+ ##
+ ## statusbar
+ ##
+
+ # default background for all statusbars. You can also give
+ # the default foreground color for statusbar items.
+ sb_background = "%N%w";
+
+ # default backround for "default" statusbar group
+ #sb_default_bg = "%4";
+ # background for prompt / input line
+ sb_prompt_bg = "%n";
+ # background for info statusbar
+ sb_info_bg = "%8";
+ # background for topicbar (same default)
+ #sb_topic_bg = "%4";
+
+ # text at the beginning of statusbars. sb-item already puts
+ # space there,so we don't use anything by default.
+ sbstart = "";
+ # text at the end of statusbars. Use space so that it's never
+ # used for anything.
+ sbend = " ";
+
+ topicsbstart = "{sbstart $*}";
+ topicsbend = "{sbend $*}";
+
+ prompt = "> ";
+
+ sb = " %K[%N$*%K]%N";
+ sbmode = "(%W+%N$*)";
+ sbaway = " (%YzZzZ%n)";
+ sbservertag = ":$0 (change with ^X)";
+
+ # activity in statusbar
+
+ # ',' separator
+ sb_act_sep = "%W$*";
+ # normal text
+ sb_act_text = "%B$*";
+ # public message
+ sb_act_msg = "%W$*";
+ # hilight
+ sb_act_hilight = "%G$*";
+ # hilight with specified color, $0 = color, $1 = text
+ sb_act_hilight_color = "$0$1-%n";
+};
+formats = {
+ "fe-common/core" = { pubmsg = "{pubmsgnick $2 {pubnick \00311$0}}$1"; };
+};
diff --git a/.irssi/scripts/act.pl b/.irssi/scripts/act.pl
new file mode 100644
index 0000000..0b20de8
--- /dev/null
+++ b/.irssi/scripts/act.pl
@@ -0,0 +1,72 @@
+#!/usr/bin/perl -w
+# resets window activity status
+# by c0ffee
+# - http://www.penguin-breeder.org/irssi/
+
+#<scriptinfo>
+use vars qw($VERSION %IRSSI);
+
+use Irssi 20020120;
+$VERSION = "0.13";
+%IRSSI = (
+ authors => "c0ffee",
+ contact => "c0ffee\@penguin-breeder.org",
+ name => "Reset window activity status",
+ description => "Reset window activity status. defines command /act",
+ license => "Public Domain",
+ url => "http://www.penguin-breeder.org/irssi/",
+ changed => "Wed Jun 23 08:34:53 CEST 2004",
+);
+#</scriptinfo>
+
+
+#
+# /ACT [PUBLIC|ALL]
+#
+# /ACT without parameters marks windows as non-active where no
+# public talk occured.
+#
+# /ACT PUBLIC also removes those where no nick hilight was triggered
+#
+# /ACT ALL sets all windows as non-active
+sub cmd_act {
+ my ($data, $server, $channel) = @_;
+
+ if ($data eq "") {
+ $level = 1;
+ } elsif ($data =~ /^public$/i) {
+ $level = 2;
+ } elsif ($data =~ /^all$/i) {
+ $level = 3;
+ } else {
+ Irssi::signal_emit("error command", -3, $data);
+ return;
+ }
+
+ foreach (Irssi::windows()) {
+
+ if ($_->{data_level} <= $level) {
+
+ Irssi::signal_emit("window dehilight", $_);
+
+ }
+
+ }
+}
+
+my @arguments = ('public', 'all');
+sub sig_complete ($$$$$) {
+ my ($list, $window, $word, $linestart, $want_space) = @_;
+ return unless $linestart =~ /^.act/;
+ foreach my $arg (@arguments) {
+ if ($arg =~ /^$word/i) {
+ $$want_space = 0;
+ push @$list, $arg;
+ }
+ }
+ Irssi::signal_stop();
+}
+
+
+Irssi::command_bind("act", "cmd_act");
+Irssi::signal_add_first('complete word', \&sig_complete);
diff --git a/.irssi/scripts/adv_windowlist.pl b/.irssi/scripts/adv_windowlist.pl
new file mode 100644
index 0000000..69725bf
--- /dev/null
+++ b/.irssi/scripts/adv_windowlist.pl
@@ -0,0 +1,2478 @@
+use strict; # use warnings;
+
+# {{{ debug
+
+#BEGIN {
+# open STDERR, '>', '/home/ailin/wlstatwarnings';
+#};
+
+# FIXME COULD SOMEONE PLEASE TELL ME HOW TO SHUT UP
+#
+# ...
+# Variable "*" will not stay shared at (eval *) line *.
+# Variable "*" will not stay shared at (eval *) line *.
+# ...
+# Can't locate package Irssi::Nick for @Irssi::Irc::Nick::ISA at (eval *) line *.
+# ...
+#
+# THANKS
+
+# }}}
+
+# if you don't know how to operate folds, type zn
+
+# {{{ header
+
+use Irssi (); # which is the minimum required version of Irssi ?
+use Irssi::TextUI;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '0.6ca';
+%IRSSI = (
+ original_authors => q(BC-bd, Veli, Timo Sirainen, ).
+ q(Wouter Coekaerts, Jean-Yves Lefort), # (decadix)
+ original_contact => q(bd@bc-bd.org, veli@piipiip.net, tss@iki.fi, ).
+ q(wouter@coekaerts.be, jylefort@brutele.be),
+ authors => q(Nei),
+ contact => q(Nei@QuakeNet),
+ url => "http://anti.teamidiot.de/",
+ name => q(awl),
+ description => q(Adds a permanent advanced window list on the right or ).
+ q(in a statusbar.),
+ description2 => q(Based on chanact.pl which was apparently based on ).
+ q(lightbar.c and nicklist.pl with various other ideas ).
+ q(from random scripts.),
+ license => q(GNU GPLv2 or later),
+);
+
+# }}}
+
+# {{{ *** D O C U M E N T A T I O N ***
+
+# adapted by Nei
+
+###############
+# {{{ original comment
+# ###########
+# # Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias).
+# # Lets you give alias characters to windows so that you can select those with
+# # meta-<char>.
+# #
+# # for irssi 0.8.2 by bd@bc-bd.org
+# #
+# # inspired by chanlist.pl by 'cumol@hammerhart.de'
+# #
+# #########
+# # {{{ Contributors
+# #########
+# #
+# # veli@piipiip.net /window_alias code
+# # qrczak@knm.org.pl chanact_abbreviate_names
+# # qerub@home.se Extra chanact_show_mode and chanact_chop_status
+# # }}}
+# }}}
+#
+# {{{ FURTHER THANKS TO
+# ############
+# # buu, fxn, Somni, Khisanth, integral, tybalt89 for much support in any aspect perl
+# # and the channel in general ( #perl @ freenode ) and especially the ir_* functions
+# #
+# # Valentin 'senneth' Batz ( vb@g-23.org ) for the pointer to grep.pl, continuous support
+# # and help in digging up ir_strip_codes
+# #
+# # OnetrixNET technology networks for the debian environment
+# #
+# # Monkey-Pirate.com / Spaceman Spiff for the webspace
+# #
+# }}}
+
+######
+# {{{ M A I N P R O B L E M
+#####
+#
+# It is impossible to place the awl on a statusbar together with other items,
+# because I do not know how to calculate the size that it is going to get
+# granted, and therefore I cannot do the linebreaks properly.
+# This is what is missing to make a nice script out of awl.
+# If you have any ideas, please contact me ASAP :).
+# }}}
+######
+
+######
+# {{{ UTF-8 PROBLEM
+#####
+#
+# Please help me find a solution to this:
+# this be your statusbar, it is using up the maximum term size
+# [[1=1]#abc [2=2]#defghi]
+#
+# now consider this example:i
+# "ascii" characters are marked with ., utf-8 characters with *
+# [[1=1]#... [2=2]#...***]
+#
+# you should think that this is how it would be displayed? WRONG!
+# [[1=1]#... [2=2]#...*** ]
+#
+# this is what Irssi does.. I believe my length calculating code to be correct,
+# however, I'd love to be proven wrong (or receive any other fix, too, of
+# course!)
+# }}}
+######
+
+#########
+# {{{ USAGE
+###
+#
+# copy the script to ~/.irssi/scripts/
+#
+# In irssi:
+#
+# /script load awl
+#
+#
+# Hint: to get rid of the old [Act:] display
+# /statusbar window remove act
+#
+# to get it back:
+# /statusbar window add -after lag -priority 10 act
+# }}}
+##########
+# {{{ OPTIONS
+########
+#
+# {{{ /set awl_display_nokey <string>
+# /set awl_display_key <string>
+# /set awl_display_nokey_active <string>
+# /set awl_display_key_active <string>
+# * string : Format String for one window. The following $'s are expanded:
+# $C : Name
+# $N : Number of the Window
+# $Q : meta-Keymap
+# $H : Start highlighting
+# $S : Stop highlighting
+# /+++++++++++++++++++++++++++++++++,
+# | **** I M P O R T A N T : **** |
+# | |
+# | don't forget to use $S if you |
+# | used $H before! |
+# | |
+# '+++++++++++++++++++++++++++++++++/
+# XXX NOTE ON *_active: there is a BUG somewhere in the length
+# XXX calculation. currently it's best to NOT remove $H/$S from those
+# XXX settings if you use it in the non-active settings.
+# }}}
+# {{{ /set awl_separator <string>
+# * string : Charater to use between the channel entries
+# you'll need to escape " " space and "$" like this:
+# "/set awl_separator \ "
+# "/set awl_separator \$"
+# and {}% like this:
+# "/set awl_separator %{"
+# "/set awl_separator %}"
+# "/set awl_separator %%"
+# (reason being, that the separator is used inside a {format })
+# }}}
+# {{{ /set awl_prefer_name <ON|OFF>
+# * this setting decides whether awl will use the active_name (OFF) or the
+# window name as the name/caption in awl_display_*.
+# That way you can rename windows using /window name myownname.
+# }}}
+# {{{ /set awl_hide_data <num>
+# * num : hide the window if its data_level is below num
+# set it to 0 to basically disable this feature,
+# 1 if you don't want windows without activity to be shown
+# 2 to show only those windows with channel text or hilight
+# 3 to show only windows with hilight
+# }}}
+# {{{ /set awl_maxlines <num>
+# * num : number of lines to use for the window list (0 to disable, negative
+# lock)
+# }}}
+# {{{ /set awl_columns <num>
+# * num : number of columns to use in screen mode (0 for unlimited)
+# }}}
+# {{{ /set awl_block <num>
+# * num : width of a column in screen mode (negative values = block display)
+# /+++++++++++++++++++++++++++++++++,
+# | ****** W A R N I N G ! ****** |
+# | |
+# | If your block display looks |
+# | DISTORTED, you need to add the |
+# | following line to your .theme |
+# | file under |
+# | abstracts = { : |
+# | |
+# | sb_act_none = "%n$*"; |
+# | |
+# '+++++++++++++++++++++++++++++++++/
+#.02:08:26. < shi> Irssi::current_theme()->get_format <.. can this be used?
+# }}}
+# {{{ /set awl_sbar_maxlength <ON|OFF>
+# * if you enable the maxlength setting, the block width will be used as a
+# maximum length for the non-block statusbar mode too.
+# }}}
+# {{{ /set awl_height_adjust <num>
+# * num : how many lines to leave empty in screen mode
+# }}}
+# {{{ /set awl_sort <-data_level|-last_line|refnum>
+# * you can change the window sort order with this variable
+# -data_level : sort windows with hilight first
+# -last_line : sort windows in order of activity
+# refnum : sort windows by window number
+# }}}
+# {{{ /set awl_placement <top|bottom>
+# /set awl_position <num>
+# * these settings correspond to /statusbar because awl will create
+# statusbars for you
+# (see /help statusbar to learn more)
+# }}}
+# {{{ /set awl_all_disable <ON|OFF>
+# * if you set awl_all_disable to ON, awl will also remove the
+# last statusbar it created if it is empty.
+# As you might guess, this only makes sense with awl_hide_data > 0 ;)
+# }}}
+# {{{ /set awl_automode <sbar|screen|emulate_lightbar>
+# * this setting defines whether the window list is shown in statusbars or
+# whether the screen hack is used (from nicklist.pl)
+# }}}
+# }}}
+##########
+# {{{ COMMANDS
+########
+# {{{ /awl paste <ON|OFF|TOGGLE>
+# * enables or disables the screen hack windowlist. This is useful when you
+# want to mark & copy text that you want to paste somewhere (hence the
+# name). (ON means AWL disabled!)
+# This is nicely bound to a function key for example.
+# }}}
+# {{{ /awl redraw
+# * redraws the screen hack windowlist. There are many occasions where the
+# screen hack windowlist can get destroyed so you can use this command to
+# fix it.
+# }}}
+# }}}
+###
+# {{{ WISHES
+####
+#
+# if you fiddle with my mess, provide me with your fixes so I can benefit as well
+#
+# Nei =^.^= ( QuakeNet accountname: ailin )
+# }}}
+
+# }}}
+
+# {{{ modules
+
+#use Class::Classless;
+#use Term::Info;
+
+# }}}
+
+# {{{ global variables
+
+my $replaces = '[=]'; # AARGH!!! (chars that are always surrounded by weird
+ # colour codes by Irssi)
+
+my $actString = []; # statusbar texts
+my $currentLines = 0;
+my $resetNeeded; # layout/screen has changed, redo everything
+my $needRemake; # "normal" changes
+#my $callcount = 0;
+sub GLOB_QUEUE_TIMER () { 100 }
+my $globTime = undef; # timer to limit remake() calls
+
+
+my $SCREEN_MODE;
+my $DISABLE_SCREEN_TEMP;
+my $currentColumns = 0;
+my $screenResizing;
+my ($screenHeight, $screenWidth);
+my $screenansi = bless {
+ NAME => 'Screen::ANSI',
+ PARENTS => [],
+ METHODS => {
+ dcs => sub { "\033P" },
+ st => sub { "\033\\"},
+ }
+}, 'Class::Classless::X';
+#my $terminfo = new Term::Info 'xterm'; # xterm here, make this modular
+# {{{{{{{{{{{{{{{
+my $terminfo = bless { # xterm here, make this modular
+ NAME => 'Term::Info::xterm',
+ PARENTS => [],
+ METHODS => {
+ # civis=\E[?25l,
+ civis => sub { "\033[?25l" },
+ # sc=\E7,
+ sc => sub { "\0337" },
+ # cup=\E[%i%p1%d;%p2%dH,
+ cup => sub { shift;shift; "\033[" . ($_[0] + 1) . ';' . ($_[1] + 1) . 'H' },
+ # el=\E[K,
+ el => sub { "\033[K" },
+ # rc=\E8,
+ rc => sub { "\0338" },
+ # cnorm=\E[?25h,
+ cnorm => sub { "\033[?25h" },
+ # setab=\E[4%p1%dm,
+ setab => sub { shift;shift; "\033[4" . $_[0] . 'm' },
+ # setaf=\E[3%p1%dm,
+ setaf => sub { shift;shift; "\033[3" . $_[0] . 'm' },
+ # bold=\E[1m,
+ bold => sub { "\033[1m" },
+ # blink=\E[5m,
+ blink => sub { "\033[5m" },
+ # rev=\E[7m,
+ rev => sub { "\033[7m" },
+ # op=\E[39;49m,
+ op => sub { "\033[39;49m" },
+ }
+}, 'Class::Classless::X';
+# }}}}}}}}}}}}}}}
+
+
+sub setc () {
+ $IRSSI{'name'}
+}
+sub set ($) {
+ setc . '_' . shift
+}
+
+# }}}
+
+
+# {{{ sbar mode
+
+my %statusbars; # currently active statusbars
+
+# maybe I should just tie the array ?
+sub add_statusbar {
+ for (@_) {
+ # add subs
+ for my $l ($_) { {
+ no strict 'refs'; # :P
+ *{set$l} = sub { awl($l, @_) };
+ }; }
+ Irssi::command('statusbar ' . (set$_) . ' reset');
+ Irssi::command('statusbar ' . (set$_) . ' enable');
+ if (lc Irssi::settings_get_str(set 'placement') eq 'top') {
+ Irssi::command('statusbar ' . (set$_) . ' placement top');
+ }
+ if ((my $x = int Irssi::settings_get_int(set 'position')) != 0) {
+ Irssi::command('statusbar ' . (set$_) . ' position ' . $x);
+ }
+ Irssi::command('statusbar ' . (set$_) . ' add -priority 100 -alignment left barstart');
+ Irssi::command('statusbar ' . (set$_) . ' add ' . (set$_));
+ Irssi::command('statusbar ' . (set$_) . ' add -priority 100 -alignment right barend');
+ Irssi::command('statusbar ' . (set$_) . ' disable');
+ Irssi::statusbar_item_register(set$_, '$0', set$_);
+ $statusbars{$_} = {};
+ }
+}
+
+sub remove_statusbar {
+ for (@_) {
+ Irssi::command('statusbar ' . (set$_) . ' reset');
+ Irssi::statusbar_item_unregister(set$_); # XXX does this actually work ?
+ # DO NOT REMOVE the sub before you have unregistered it :))
+ for my $l ($_) { {
+ no strict 'refs';
+ undef &{set$l};
+ }; }
+ delete $statusbars{$_};
+ }
+}
+
+sub syncLines {
+ my $temp = $currentLines;
+ $currentLines = @$actString;
+ #Irssi::print("current lines: $temp new lines: $currentLines");
+ my $currMaxLines = Irssi::settings_get_int(set 'maxlines');
+ if ($currMaxLines > 0 and @$actString > $currMaxLines) {
+ $currentLines = $currMaxLines;
+ }
+ elsif ($currMaxLines < 0) {
+ $currentLines = abs($currMaxLines);
+ }
+ return if ($temp == $currentLines);
+ if ($currentLines > $temp) {
+ for ($temp .. ($currentLines - 1)) {
+ add_statusbar($_);
+ Irssi::command('statusbar ' . (set$_) . ' enable');
+ }
+ }
+ else {
+ for ($_ = ($temp - 1); $_ >= $currentLines; $_--) {
+ Irssi::command('statusbar ' . (set$_) . ' disable');
+ remove_statusbar($_);
+ }
+ }
+}
+
+# FIXME implement $get_size_only check, and user $item->{min|max-size} ??
+sub awl {
+ my ($line, $item, $get_size_only) = @_;
+
+ if ($needRemake) {
+ $needRemake = undef;
+ remake();
+ }
+
+ my $text = $actString->[$line]; # DO NOT set the actual $actString->[$line] to '' here or
+ $text = '' unless defined $text; # you'll screw up the statusbar counter ($currentLines)
+ $item->default_handler($get_size_only, $text, '', 1);
+}
+
+# remove old statusbars
+my %killBar;
+sub get_old_status {
+ my ($textDest, $cont, $cont_stripped) = @_;
+ if ($textDest->{'level'} == 524288 and $textDest->{'target'} eq ''
+ and !defined($textDest->{'server'})
+ ) {
+ my $name = quotemeta(set '');
+ if ($cont_stripped =~ m/^$name(\d+)\s/) { $killBar{$1} = {}; }
+ Irssi::signal_stop();
+ }
+}
+sub killOldStatus {
+ %killBar = ();
+ Irssi::signal_add_first('print text' => 'get_old_status');
+ Irssi::command('statusbar');
+ Irssi::signal_remove('print text' => 'get_old_status');
+ remove_statusbar(keys %killBar);
+}
+#killOldStatus();
+
+# end sbar mode }}}
+
+
+# {{{ keymaps
+
+my %keymap;
+
+sub get_keymap {
+ my ($textDest, undef, $cont_stripped) = @_;
+ if ($textDest->{'level'} == 524288 and $textDest->{'target'} eq ''
+ and !defined($textDest->{'server'})
+ ) {
+ if ($cont_stripped =~ m/((?:meta-)+)(.)\s+change_window (\d+)/) {
+ my ($level, $key, $window) = ($1, $2, $3);
+ my $numlevel = ($level =~ y/-//) - 1;
+ $keymap{$window} = ('-' x $numlevel) . "$key";
+ }
+ Irssi::signal_stop();
+ }
+}
+
+sub update_keymap {
+ %keymap = ();
+ Irssi::signal_remove('command bind' => 'watch_keymap');
+ Irssi::signal_add_first('print text' => 'get_keymap');
+ Irssi::command('bind'); # stolen from grep
+ Irssi::signal_remove('print text' => 'get_keymap');
+ Irssi::signal_add('command bind' => 'watch_keymap');
+ Irssi::timeout_add_once(100, 'eventChanged', undef);
+}
+
+# watch keymap changes
+sub watch_keymap {
+ Irssi::timeout_add_once(1000, 'update_keymap', undef);
+}
+
+update_keymap();
+
+# end keymaps }}}
+
+# {{{ format handling
+
+# a bad way do do expansions but who cares
+sub expand {
+ my ($string, %format) = @_;
+ my ($exp, $repl);
+ $string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
+ return $string;
+}
+
+my %strip_table = (
+ # fe-common::core::formats.c:format_expand_styles
+ # delete format_backs format_fores bold_fores other stuff
+ (map { $_ => '' } (split //, '04261537' . 'kbgcrmyw' . 'KBGCRMYW' . 'U9_8:|FnN>#[')),
+ # escape
+ (map { $_ => $_ } (split //, '{}%')),
+);
+sub ir_strip_codes { # strip %codes
+ my $o = shift;
+ $o =~ s/(%(.))/exists $strip_table{$2} ? $strip_table{$2} : $1/gex;
+ $o
+}
+
+sub ir_parse_special {
+ my $o; my $i = shift;
+ #if ($_[0]) { # for the future?!?
+ # eval {
+ # $o = $_[0]->parse_special($i);
+ # };
+ # unless ($@) {
+ # return $o;
+ # }
+ #}
+ my $win = shift || Irssi::active_win();
+ my $server = Irssi::active_server();
+ if (ref $win and ref $win->{'active'}) {
+ $o = $win->{'active'}->parse_special($i);
+ }
+ elsif (ref $win and ref $win->{'active_server'}) {
+ $o = $win->{'active_server'}->parse_special($i);
+ }
+ elsif (ref $server) {
+ $o = $server->parse_special($i);
+ }
+ else {
+ $o = Irssi::parse_special($i);
+ }
+ $o
+}
+sub ir_parse_special_protected {
+ my $o; my $i = shift;
+ $i =~ s/
+ ( \\. ) | # skip over escapes (maybe)
+ ( \$[^% $\]+ ) # catch special variables
+ /
+ if ($1) { $1 }
+ elsif ($2) { my $i2 = $2; ir_fe(ir_parse_special($i2, @_)) }
+ else { $& }
+ /gex;
+ $i
+}
+
+
+sub sb_ctfe { # Irssi::current_theme->format_expand wrapper
+ Irssi::current_theme->format_expand(
+ shift,
+ (
+ Irssi::EXPAND_FLAG_IGNORE_REPLACES
+ |
+ ($_[0]?0:Irssi::EXPAND_FLAG_IGNORE_EMPTY)
+ )
+ )
+}
+sub sb_expand { # expand {format }s (and apply parse_special for $vars)
+ ir_parse_special(
+ sb_ctfe(shift)
+ )
+}
+sub sb_strip {
+ ir_strip_codes(
+ sb_expand(shift)
+ ); # does this get us the actual length of that s*ty bar :P ?
+}
+sub sb_length {
+ # unicode cludge, d*mn broken Irssi
+ # screw it, this will fail from broken joining anyway (and cause warnings)
+ my $term_type = 'term_type';
+ if (Irssi::version > 20040819) { # this is probably wrong, but I don't know
+ # when the setting name got changed
+ $term_type = 'term_charset';
+ }
+ #if (lc Irssi::settings_get_str($term_type) eq '8bit'
+ # or Irssi::settings_get_str($term_type) =~ /^iso/i
+ #) {
+ # length(sb_strip(shift))
+ #}
+ #else {
+ my $temp = sb_strip(shift);
+ # try to get the displayed width
+ my $length;
+ eval {
+ require Text::CharWidth;
+ $length = Text::CharWidth::mbswidth($temp);
+ };
+ unless ($@) {
+ return $length;
+ }
+ else {
+ if (lc Irssi::settings_get_str($term_type) eq 'utf-8') {
+ # try to switch on utf8
+ eval {
+ no warnings;
+ require Encode;
+ #$temp = Encode::decode_utf8($temp); # thanks for the hint, but I have my
+ # # reasons for _utf8_on
+ Encode::_utf8_on($temp);
+ };
+ }
+ # there is nothing more I can do
+ length($temp)
+ }
+ #}
+}
+
+# !!! G*DD*MN Irssi is adding an additional layer of backslashitis per { } layer
+# !!! AND I still don't know what I need to escape.
+# !!! and NOONE else seems to know or care either.
+# !!! f*ck open source. I mean it.
+# XXX any Irssi::print debug statement leads to SEGFAULT - why ?
+
+# major parts of the idea by buu (#perl @ freenode)
+# thanks to fxn and Somni for debugging
+# while ($_[0] =~ /(.)/g) {
+# my $c = $1; # XXX sooo... goto kills $1
+# if ($q eq '%') { goto ESC; }
+
+## <freenode:#perl:tybalt89> s/%(.)|(\{)|(\})|(\\|\$)/$1?$1:$2?($level++,$2):$3?($level>$min_level&&$level--,$3):'\\'x(2**$level-1).$4/ge; # untested...
+sub ir_escape {
+ my $min_level = $_[1] || 0; my $level = $min_level;
+ my $o = shift;
+ $o =~ s/
+ ( %. ) | # $1
+ ( \{ ) | # $2
+ ( \} ) | # $3
+ ( \\ ) | # $4
+ ( \$(?=[^\\]) ) | # $5
+ ( \$ ) # $6
+ /
+ if ($1) { $1 } # %. escape
+ elsif ($2) { $level++; $2 } # { nesting start
+ elsif ($3) { if ($level > $min_level) { $level--; } $3 } # } nesting end
+ elsif ($4) { '\\'x(2**$level) } # \ needs \\escaping
+ elsif ($5) { '\\'x(2**$level-1) . '$' . '\\'x(2**$level-1) } # and $ needs even more because of "parse_special"
+ else { '\\'x(2**$level-1) . '$' } # $ needs \$ escaping
+ /gex;
+ $o
+}
+#sub ir_escape {
+# my $min_level = $_[1] || 0; my $level = $min_level;
+# my $o = shift;
+# $o =~ s/
+# ( %. ) | # $1
+# ( \{ ) | # $2
+# ( \} ) | # $3
+# ( \\ | \$ ) # $4
+# /
+# if ($1) { $1 } # %. escape
+# elsif ($2) { $level++; $2 } # { nesting start
+# elsif ($3) { if ($level > $min_level) { $level--; } $3 } # } nesting end
+# else { '\\'x(2**($level-1)-1) . $4 } # \ or $ needs \\escaping
+# /gex;
+# $o
+#}
+
+sub ir_fe { # try to fix format stuff
+ my $x = shift;
+ # XXX why do I have to use two/four % here instead of one/two ??
+ # answer: you screwed up in ir_escape
+ $x =~ s/([%{}])/%$1/g;
+ #$x =~ s/(\\|\$|[ ])/\\$1/g; # XXX HOW CAN I HANDLE THE SPACES CORRECTLY XXX
+ $x =~ s/(\\|\$)/\\$1/g;
+ #$x =~ s/(\$(?=.))|(\$)/$1?"\\\$\\":"\\\$"/ge; # I think this should be here
+ # # (logic), but it doesn't work
+ # # that way :P
+ #$x =~ s/\\/\\\\/g; # that's right, escape escapes
+ $x
+}
+sub ir_ve { # escapes special vars but leave colours alone
+ my $x = shift;
+ #$x =~ s/([%{}])/%$1/g;
+ $x =~ s/(\\|\$|[ ])/\\$1/g;
+ $x
+}
+
+my %ansi_table;
+{
+ my ($i, $j, $k) = (0, 0, 0);
+ %ansi_table = (
+ # fe-common::core::formats.c:format_expand_styles
+ # do format_backs
+ (map { $_ => $terminfo->setab($i++) } (split //, '01234567' )),
+ # do format_fores
+ (map { $_ => $terminfo->setaf($j++) } (split //, 'krgybmcw' )),
+ # do bold_fores
+ (map { $_ => $terminfo->bold() .
+ $terminfo->setaf($k++) } (split //, 'KRGYBMCW')),
+ # reset
+ #(map { $_ => $terminfo->op() } (split //, 'nN')),
+ (map { $_ => $terminfo->op() } (split //, 'n')),
+ (map { $_ => "\033[0m" } (split //, 'N')), # XXX quick and DIRTY
+ # flash/bright
+ F => $terminfo->blink(),
+ # reverse
+ 8 => $terminfo->rev(),
+ # bold
+ (map { $_ => $terminfo->bold() } (split //, '9_')),
+ # delete other stuff
+ (map { $_ => '' } (split //, ':|>#[')),
+ # escape
+ (map { $_ => $_ } (split //, '{}%')),
+ )
+}
+sub formats_to_ansi_basic {
+ my $o = shift;
+ $o =~ s/(%(.))/exists $ansi_table{$2} ? $ansi_table{$2} : $1/gex;
+ $o
+}
+
+sub lc1459 ($) { my $x = shift; $x =~ y/A-Z][\^/a-z}{|~/; $x }
+Irssi::settings_add_str(setc, 'banned_channels', '');
+Irssi::settings_add_bool(setc, 'banned_channels_on', 0);
+my %banned_channels = map { lc1459($_) => undef }
+split ' ', Irssi::settings_get_str('banned_channels');
+Irssi::settings_add_str(setc, 'fancy_abbrev', 'fancy');
+
+# }}}
+
+# {{{ main
+
+sub remake () {
+ #$callcount++;
+ #my $xx = $callcount; Irssi::print("starting remake [ $xx ]");
+ my ($hilight, $number, $display);
+ my $separator = '{sb_act_sep ' . Irssi::settings_get_str(set 'separator') .
+ '}';
+ my $custSort = Irssi::settings_get_str(set 'sort');
+ my $custSortDir = 1;
+ if ($custSort =~ /^[-!](.*)/) {
+ $custSortDir = -1;
+ $custSort = $1;
+ }
+
+ my @wins =
+ sort {
+ (
+ ( (int($a->{$custSort}) <=> int($b->{$custSort})) * $custSortDir )
+ ||
+ ($a->{'refnum'} <=> $b->{'refnum'})
+ )
+ } Irssi::windows;
+ my $block = Irssi::settings_get_int(set 'block');
+ my $columns = $currentColumns;
+ my $oldActString = $actString if $SCREEN_MODE;
+ $actString = $SCREEN_MODE ? [' A W L'] : [];
+ my $line = $SCREEN_MODE ? 1 : 0;
+ my $width = $SCREEN_MODE
+ ?
+ $screenWidth - abs($block)*$columns + 1
+ :
+ ([Irssi::windows]->[0]{'width'} - sb_length('{sb x}'));
+ my $height = $screenHeight - abs(Irssi::settings_get_int(set
+ 'height_adjust'));
+ my ($numPad, $keyPad) = (0, 0);
+ my %abbrevList;
+ if ($SCREEN_MODE or Irssi::settings_get_bool(set 'sbar_maxlength')
+ or ($block < 0)
+ ) {
+ %abbrevList = ();
+ if (Irssi::settings_get_str('fancy_abbrev') !~ /^(no|off|head)/i) {
+ my @nameList = map { ref $_ ? $_->get_active_name : '' } @wins;
+ for (my $i = 0; $i < @nameList - 1; ++$i) {
+ my ($x, $y) = ($nameList[$i], $nameList[$i + 1]);
+ for ($x, $y) { s/^[+#!=]// }
+ my $res = Algorithm::LCSS::LCSS($x, $y);
+ if (defined $res) {
+ #Irssi::print("common pattern $x $y : $res");
+ #Irssi::print("found at $nameList[$i] ".index($nameList[$i],
+ # $res));
+ $abbrevList{$nameList[$i]} = int (index($nameList[$i], $res) +
+ (length($res) / 2));
+ #Irssi::print("found at ".$nameList[$i+1]." ".index($nameList[$i+1],
+ # $res));
+ $abbrevList{$nameList[$i+1]} = int (index($nameList[$i+1], $res) +
+ (length($res) / 2));
+ }
+ }
+ }
+ if ($SCREEN_MODE or ($block < 0)) {
+ $numPad = length((sort { length($b) <=> length($a) } keys %keymap)[0]);
+ $keyPad = length((sort { length($b) <=> length($a) } values %keymap)[0]);
+ }
+ }
+ if ($SCREEN_MODE) {
+ print STDERR $screenansi->dcs().
+ $terminfo->civis().
+ $terminfo->sc().
+ $screenansi->st();
+ if (@$oldActString < 1) {
+ print STDERR $screenansi->dcs().
+ $terminfo->cup(0, $width).
+ $actString->[0].
+ $terminfo->el().
+ $screenansi->st();
+ }
+ }
+ foreach my $win (@wins) {
+ unless ($SCREEN_MODE) {
+ $actString->[$line] = '' unless defined $actString->[$line]
+ or Irssi::settings_get_bool(set 'all_disable');
+ }
+
+ # all stolen from chanact, what does this code do and why do we need it ?
+ !ref($win) && next;
+
+ my $name = $win->get_active_name;
+ $name = '*' if (Irssi::settings_get_bool('banned_channels_on') and exists
+ $banned_channels{lc1459($name)});
+ $name = $win->{'name'} if $name ne '*' and $win->{'name'} ne ''
+ and Irssi::settings_get_bool(set 'prefer_name');
+ my $active = $win->{'active'};
+ my $colour = $win->{'hilight_color'};
+ if (!defined $colour) { $colour = ''; }
+
+ if ($win->{'data_level'} < Irssi::settings_get_int(set 'hide_data')) {
+ next; } # for Geert
+ if ($win->{'data_level'} == 0) { $hilight = '{sb_act_none '; }
+ elsif ($win->{'data_level'} == 1) { $hilight = '{sb_act_text '; }
+ elsif ($win->{'data_level'} == 2) { $hilight = '{sb_act_msg '; }
+ elsif ($colour ne '') { $hilight = "{sb_act_hilight_color $colour "; }
+ elsif ($win->{'data_level'} == 3) { $hilight = '{sb_act_hilight '; }
+ else { $hilight = '{sb_act_special '; }
+
+ $number = $win->{'refnum'};
+ my @display = ('display_nokey');
+ if (defined $keymap{$number} and $keymap{$number} ne '') {
+ unshift @display, map { (my $cpy = $_) =~ s/_no/_/; $cpy } @display;
+ }
+ if (Irssi::active_win->{'refnum'} == $number) {
+ unshift @display, map { my $cpy = $_; $cpy .= '_active'; $cpy } @display;
+ }
+ #Irssi::print("win $number [@display]: " . join '.', split //, join '<<', map {
+ # Irssi::settings_get_str(set $_) } @display);
+ $display = (grep { $_ }
+ map { Irssi::settings_get_str(set $_) }
+ @display)[0];
+ #Irssi::print("win $number : " . join '.', split //, $display);
+
+ if ($SCREEN_MODE or Irssi::settings_get_bool(set 'sbar_maxlength')
+ or ($block < 0)
+ ) {
+ my $baseLength = sb_length(ir_escape(ir_ve(ir_parse_special_protected(sb_ctfe(
+ '{sb_background}' . expand($display,
+ C => ir_fe('x'),
+ N => $number . (' 'x($numPad - length($number))),
+ Q => ir_fe((' 'x($keyPad - length($keymap{$number}))) . $keymap{$number}),
+ H => $hilight,
+ S => '}{sb_background}'
+ ), 1), $win)))) - 1;
+ my $diff = abs($block) - (length($name) + $baseLength);
+ if ($diff < 0) { # too long
+ if (abs($diff) >= length($name)) { $name = '' } # forget it
+ elsif (abs($diff) + 1 >= length($name)) { $name = substr($name,
+ 0, 1); }
+ else {
+ my $middle = exists $abbrevList{$name} ?
+ (($abbrevList{$name} + (2*(length($name) / 2)))/3) :
+ ((Irssi::settings_get_str('fancy_abbrev') =~ /^head/i) ?
+ length($name) :
+ (length($name) / 2));
+ my $cut = int($middle - (abs($diff) / 2) + .55);
+ $cut = 1 if $cut < 1;
+ $cut = length($name) - abs($diff) - 1 if $cut > (length($name) -
+ abs($diff) - 1);
+ $name = substr($name, 0, $cut) . '~' . substr($name, $cut +
+ abs($diff) + 1);
+ }
+ }
+ elsif ($SCREEN_MODE or ($block < 0)) {
+ $name .= (' ' x $diff);
+ }
+ }
+
+ my $add = ir_ve(ir_parse_special_protected(sb_ctfe('{sb_background}' . expand($display,
+ C => ir_fe($name),
+ N => $number . (' 'x($numPad - length($number))),
+ Q => ir_fe((' 'x($keyPad - length($keymap{$number}))) . $keymap{$number}),
+ H => $hilight,
+ S => '}{sb_background}'
+ ), 1), $win));
+ if ($SCREEN_MODE) {
+ $actString->[$line] = $add;
+ if ((!defined $oldActString->[$line]
+ or $oldActString->[$line] ne $actString->[$line])
+ and
+ $line <= ($columns * $height)
+ ) {
+ print STDERR $screenansi->dcs().
+ $terminfo->cup(($line-1) % $height+1, $width + (
+ abs($block) * int(($line-1) / $height))).
+ formats_to_ansi_basic(sb_expand(ir_escape($actString->[$line]))).
+ #$terminfo->el().
+ $screenansi->st();
+ }
+ $line++;
+ }
+ else {
+ #$temp =~ s/\{\S+?(?:\s(.*?))?\}/$1/g;
+ #$temp =~ s/\\\\\\\\/\\/g; # XXX I'm actually guessing here, someone point me
+ # # XXX to docs please
+ $actString->[$line] = '' unless defined $actString->[$line];
+
+ # XXX how can I check whether the content still fits in the bar? this would
+ # XXX allow awlstatus to reside on a statusbar together with other items...
+ if (sb_length(ir_escape($actString->[$line] . $add)) >= $width) {
+ # XXX doesn't correctly handle utf-8 multibyte ... help !!?
+ $actString->[$line] .= ' ' x ($width - sb_length(ir_escape(
+ $actString->[$line])));
+ $line++;
+ }
+ $actString->[$line] .= $add . $separator;
+ # XXX if I use these prints, output layout gets screwed up... why ?
+ #Irssi::print("line $line: ".$actString->[$line]);
+ #Irssi::print("temp $line: ".$temp);
+ }
+ }
+
+ if ($SCREEN_MODE) {
+ while ($line <= ($columns * $height)) {
+ print STDERR $screenansi->dcs().
+ $terminfo->cup(($line-1) % $height+1, $width + (
+ abs($block) * int(($line-1) / $height))).
+ $terminfo->el().
+ $screenansi->st();
+ $line++;
+ }
+ print STDERR $screenansi->dcs().
+ $terminfo->rc().
+ $terminfo->cnorm().
+ $screenansi->st();
+ }
+ else {
+ # XXX the Irssi::print statements lead to the MOST WEIRD results
+ # e.g.: the loop gets executed TWICE for p > 0 ?!?
+ for (my $p = 0; $p < @$actString; $p++) { # wrap each line in {sb }, escape it
+ my $x = $actString->[$p]; # properly, etc.
+ $x =~ s/\Q$separator\E([ ]*)$/$1/;
+ #Irssi::print("[$p]".'current:'.join'.',split//,sb_strip(ir_escape($x,0)));
+ #Irssi::print("assumed length before:".sb_length(ir_escape($x,0)));
+ $x = "{sb $x}";
+ #Irssi::print("[$p]".'new:'.join'.',split//,sb_expand(ir_escape($x,0)));
+ #Irssi::print("[$p]".'new:'.join'.',split//,ir_escape($x,0));
+ #Irssi::print("assumed length after:".sb_length(ir_escape($x,0)));
+ $x = ir_escape($x);
+ #Irssi::print("[$p]".'REALnew:'.join'.',split//,sb_strip($x));
+ $actString->[$p] = $x;
+ # XXX any Irssi::print debug statement leads to SEGFAULT (sometimes) - why ?
+ }
+ }
+ #Irssi::print("remake [ $xx ] finished");
+}
+
+sub awlHasChanged () {
+ $globTime = undef;
+ my $temp = ($SCREEN_MODE ?
+ "\\\n" . Irssi::settings_get_int(set 'block').
+ Irssi::settings_get_int(set 'height_adjust')
+ : "!\n" . Irssi::settings_get_str(set 'placement').
+ Irssi::settings_get_int(set 'position')).
+ Irssi::settings_get_str(set 'automode');
+ if ($temp ne $resetNeeded) { wlreset(); return; }
+ #Irssi::print("awl has changed, calls to remake so far: $callcount");
+ $needRemake = 1;
+
+ #remake();
+ if (
+ ($SCREEN_MODE and !$DISABLE_SCREEN_TEMP)
+ or
+ ($needRemake and Irssi::settings_get_bool(set 'all_disable'))
+ or
+ (!Irssi::settings_get_bool(set 'all_disable') and $currentLines < 1)
+ ) {
+ $needRemake = undef;
+ remake();
+ }
+
+ unless ($SCREEN_MODE) {
+ # XXX Irssi crashes if I try to do this without timer, why ? What's the minimum
+ # XXX delay I need to use in the timer ?
+ Irssi::timeout_add_once(100, 'syncLines', undef);
+
+ for (keys %statusbars) {
+ Irssi::statusbar_items_redraw(set$_);
+ }
+ }
+ else {
+ Irssi::timeout_add_once(100, 'syncColumns', undef);
+ }
+}
+
+sub eventChanged () { # Implement a change queue/blocker -.-)
+ if (defined $globTime) {
+ Irssi::timeout_remove($globTime);
+ } # delay the update further
+ $globTime = Irssi::timeout_add_once(GLOB_QUEUE_TIMER, 'awlHasChanged', undef);
+}
+
+# }}}
+
+
+# {{{ screen mode
+
+sub screenFullRedraw {
+ my ($window) = @_;
+ if (!ref $window or $window->{'refnum'} == Irssi::active_win->{'refnum'}) {
+ $actString = [];
+ eventChanged();
+ }
+}
+
+sub screenSize { # from nicklist.pl
+ $screenResizing = 1;
+ # fit screen
+ system 'screen -x '.$ENV{'STY'}.' -X fit';
+ # get size
+ my ($row, $col) = split ' ', `stty size`;
+ # set screen width
+ $screenWidth = $col-1;
+ $screenHeight = $row-1;
+
+ # on some recent systems, "screen -X fit; screen -X width -w 50" doesn't work, needs a sleep in between the 2 commands
+ # so we wait a second before setting the width
+ Irssi::timeout_add_once(100, sub {
+ my ($new_irssi_width) = @_;
+ $new_irssi_width -= abs(Irssi::settings_get_int(set
+ 'block'))*$currentColumns - 1;
+ system 'screen -x '.$ENV{'STY'}.' -X width -w ' . $new_irssi_width;
+ # and then we wait another second for the resizing, and then redraw.
+ Irssi::timeout_add_once(10,sub {$screenResizing = 0; screenFullRedraw()}, []);
+ }, $screenWidth);
+}
+
+sub screenOff {
+ my ($unloadMode) = @_;
+ Irssi::signal_remove('gui print text finished' => 'screenFullRedraw');
+ Irssi::signal_remove('gui page scrolled' => 'screenFullRedraw');
+ Irssi::signal_remove('window changed' => 'screenFullRedraw');
+ Irssi::signal_remove('window changed automatic' => 'screenFullRedraw');
+ if ($unloadMode) {
+ Irssi::signal_remove('terminal resized' => 'resizeTerm');
+ }
+ system 'screen -x '.$ENV{'STY'}.' -X fit';
+}
+
+sub syncColumns {
+ return if (@$actString == 0);
+ my $temp = $currentColumns;
+ #Irssi::print("current columns $temp");
+ my $height = $screenHeight - abs(Irssi::settings_get_int(set
+ 'height_adjust'));
+ $currentColumns = int(($#$actString-1) / $height) + 1;
+ #Irssi::print("objects in actstring:".scalar(@$actString).", screen height:".
+ # $height);
+ my $currMaxColumns = Irssi::settings_get_int(set 'columns');
+ if ($currMaxColumns > 0 and $currentColumns > $currMaxColumns) {
+ $currentColumns = $currMaxColumns;
+ }
+ elsif ($currMaxColumns < 0) {
+ $currentColumns = abs($currMaxColumns);
+ }
+ return if ($temp == $currentColumns);
+ screenSize();
+}
+
+#$needRemake = 1;
+sub resizeTerm () {
+ if ($SCREEN_MODE and !$screenResizing) {
+ $screenResizing = 1;
+ Irssi::timeout_add_once(10, 'screenSize', undef);
+ }
+ Irssi::timeout_add_once(100, 'eventChanged', undef);
+}
+
+# }}}
+
+
+# {{{ settings add
+
+Irssi::settings_add_str(setc, set 'display_nokey', '[$N]$H$C$S');
+Irssi::settings_add_str(setc, set 'display_key', '[$Q=$N]$H$C$S');
+Irssi::settings_add_str(setc, set 'display_nokey_active', '');
+Irssi::settings_add_str(setc, set 'display_key_active', '');
+Irssi::settings_add_str(setc, set 'separator', "\\ ");
+Irssi::settings_add_bool(setc, set 'prefer_name', 0);
+Irssi::settings_add_int(setc, set 'hide_data', 0);
+Irssi::settings_add_int(setc, set 'maxlines', 9);
+Irssi::settings_add_int(setc, set 'columns', 1);
+Irssi::settings_add_int(setc, set 'block', 20);
+Irssi::settings_add_bool(setc, set 'sbar_maxlength', 0);
+Irssi::settings_add_int(setc, set 'height_adjust', 2);
+Irssi::settings_add_str(setc, set 'sort', 'refnum');
+Irssi::settings_add_str(setc, set 'placement', 'bottom');
+Irssi::settings_add_int(setc, set 'position', 0);
+Irssi::settings_add_bool(setc, set 'all_disable', 0);
+Irssi::settings_add_str(setc, set 'automode', 'sbar');
+
+# }}}
+
+
+# {{{ init
+
+sub wlreset {
+ $actString = [];
+ $currentLines = 0; # 1; # mhmmmm .. we actually enable one line down there so
+ # let's try this.
+ #update_keymap();
+ killOldStatus();
+ # Register statusbar
+ #add_statusbar(0);
+ #Irssi::command('statusbar wl0 enable');
+ my $was_screen_mode = $SCREEN_MODE;
+ if ($SCREEN_MODE = (Irssi::settings_get_str(set 'automode') =~ /screen/i)
+ and
+ !$was_screen_mode
+ ) {
+ if (!defined $ENV{'STY'}) {
+ Irssi::print('Screen mode can only be used in GNU screen but no '.
+ 'screen was found.', MSGLEVEL_CLIENTERROR);
+ $SCREEN_MODE = undef;
+ }
+ else {
+ Irssi::signal_add_last('gui print text finished' => 'screenFullRedraw');
+ Irssi::signal_add_last('gui page scrolled' => 'screenFullRedraw');
+ Irssi::signal_add('window changed' => 'screenFullRedraw');
+ Irssi::signal_add('window changed automatic' => 'screenFullRedraw');
+ }
+ }
+ elsif ($was_screen_mode and !$SCREEN_MODE) {
+ screenOff();
+ }
+ $resetNeeded = ($SCREEN_MODE ?
+ "\\\n" . Irssi::settings_get_int(set 'block').
+ Irssi::settings_get_int(set 'height_adjust')
+ : "!\n" . Irssi::settings_get_str(set 'placement').
+ Irssi::settings_get_int(set 'position')).
+ Irssi::settings_get_str(set 'automode');
+ resizeTerm();
+}
+
+wlreset();
+
+# }}}
+
+
+# {{{ unload/deinit
+
+my $Unload;
+sub unload ($$$) {
+ $Unload = 1;
+ # pretend we didn't do anything ASAP
+ Irssi::timeout_add_once(10, sub { $Unload = undef; }, undef);
+}
+# last try to catch a sigsegv
+Irssi::signal_add_first('gui exit' => sub { $Unload = undef; });
+sub UNLOAD {
+ # this might well crash Irssi... try /eval /script unload someotherscript ;
+ # /quit (= SEGFAULT !)
+ if ($Unload) {
+ $actString = ['']; # syncLines(); # XXX Irssi crashes when trying to disable
+ killOldStatus(); # XXX all statusbars ?
+ if ($SCREEN_MODE) {
+ screenOff('unload mode');
+ }
+ }
+}
+
+# }}}
+
+
+# {{{ signals
+
+sub addPrintTextHook { # update on print text
+ return if $_[0]->{'level'} == 262144 and $_[0]->{'target'} eq ''
+ and !defined($_[0]->{'server'});
+ if (Irssi::settings_get_str(set 'sort') =~ /^[-!]?last_line$/) {
+ Irssi::timeout_add_once(100, 'eventChanged', undef);
+ }
+}
+
+#sub _x { my ($x, $y) = @_; ($x, sub { Irssi::print('-->signal '.$x); eval "$y();"; }) }
+#sub _x { @_ }
+Irssi::signal_add_first(
+ 'command script unload' => 'unload'
+);
+Irssi::signal_add_last({
+ 'setup changed' => 'eventChanged',
+ 'print text' => 'addPrintTextHook',
+ 'terminal resized' => 'resizeTerm',
+ 'setup reread' => 'wlreset',
+ 'window hilight' => 'eventChanged',
+});
+Irssi::signal_add({
+ 'window created' => 'eventChanged',
+ 'window destroyed' => 'eventChanged',
+ 'window name changed' => 'eventChanged',
+ 'window refnum changed' => 'eventChanged',
+ 'window changed' => 'eventChanged',
+ 'window changed automatic' => 'eventChanged',
+});
+
+#Irssi::signal_add('nick mode changed', 'chanactHasChanged'); # relicts
+
+# }}}
+
+# {{{ commands
+
+
+sub runsub {
+ my ($cmd) = @_;
+ sub {
+ my ($data, $server, $item) = @_;
+ Irssi::command_runsub($cmd, $data, $server, $item);
+ };
+}
+Irssi::command_bind( setc() => runsub(setc()) );
+Irssi::command_bind( setc() . ' paste' => runsub(setc() . ' paste') );
+Irssi::command_bind(
+ setc() . ' paste on' => sub {
+ return unless $SCREEN_MODE;
+ my $was_disabled = $DISABLE_SCREEN_TEMP;
+ $DISABLE_SCREEN_TEMP = 1;
+ Irssi::print('Paste mode is now ON, '.uc(setc()).' is temporarily '.
+ 'disabled.');
+ if (!$was_disabled) {
+ $screenResizing = 1;
+ screenOff();
+ }
+ }
+);
+Irssi::command_bind(
+ setc() . ' paste off' => sub {
+ return unless $SCREEN_MODE;
+ my $was_disabled = $DISABLE_SCREEN_TEMP;
+ $DISABLE_SCREEN_TEMP = undef;
+ Irssi::print('Paste mode is now OFF, '.uc(setc()).' is enabled.');
+ if ($was_disabled) {
+ $SCREEN_MODE = undef;
+ $screenResizing = 0;
+ wlreset();
+ }
+ }
+);
+Irssi::command_bind(
+ setc() . ' paste toggle' => sub {
+ if ($DISABLE_SCREEN_TEMP) {
+ Irssi::command(setc() . ' paste off');
+ }
+ else {
+ Irssi::command(setc() . ' paste on');
+ }
+ }
+);
+Irssi::command_bind(
+ setc() . ' redraw' => sub {
+ return unless $SCREEN_MODE;
+ screenFullRedraw();
+ }
+);
+
+
+# }}}
+
+# {{{ Algorithm::LCSS module
+{
+ package Algorithm::Diff;
+ # Skip to first "=head" line for documentation.
+ use strict;
+
+ use integer; # see below in _replaceNextLargerWith() for mod to make
+ # if you don't use this
+
+ # McIlroy-Hunt diff algorithm
+ # Adapted from the Smalltalk code of Mario I. Wolczko, <mario@wolczko.com>
+ # by Ned Konz, perl@bike-nomad.com
+ # Updates by Tye McQueen, http://perlmonks.org/?node=tye
+
+ # Create a hash that maps each element of $aCollection to the set of
+ # positions it occupies in $aCollection, restricted to the elements
+ # within the range of indexes specified by $start and $end.
+ # The fourth parameter is a subroutine reference that will be called to
+ # generate a string to use as a key.
+ # Additional parameters, if any, will be passed to this subroutine.
+ #
+ # my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen );
+
+ sub _withPositionsOfInInterval
+ {
+ my $aCollection = shift; # array ref
+ my $start = shift;
+ my $end = shift;
+ my $keyGen = shift;
+ my %d;
+ my $index;
+ for ( $index = $start ; $index <= $end ; $index++ )
+ {
+ my $element = $aCollection->[$index];
+ my $key = &$keyGen( $element, @_ );
+ if ( exists( $d{$key} ) )
+ {
+ unshift ( @{ $d{$key} }, $index );
+ }
+ else
+ {
+ $d{$key} = [$index];
+ }
+ }
+ return wantarray ? %d : \%d;
+ }
+
+ # Find the place at which aValue would normally be inserted into the
+ # array. If that place is already occupied by aValue, do nothing, and
+ # return undef. If the place does not exist (i.e., it is off the end of
+ # the array), add it to the end, otherwise replace the element at that
+ # point with aValue. It is assumed that the array's values are numeric.
+ # This is where the bulk (75%) of the time is spent in this module, so
+ # try to make it fast!
+
+ sub _replaceNextLargerWith
+ {
+ my ( $array, $aValue, $high ) = @_;
+ $high ||= $#$array;
+
+ # off the end?
+ if ( $high == -1 || $aValue > $array->[-1] )
+ {
+ push ( @$array, $aValue );
+ return $high + 1;
+ }
+
+ # binary search for insertion point...
+ my $low = 0;
+ my $index;
+ my $found;
+ while ( $low <= $high )
+ {
+ $index = ( $high + $low ) / 2;
+
+ # $index = int(( $high + $low ) / 2); # without 'use integer'
+ $found = $array->[$index];
+
+ if ( $aValue == $found )
+ {
+ return undef;
+ }
+ elsif ( $aValue > $found )
+ {
+ $low = $index + 1;
+ }
+ else
+ {
+ $high = $index - 1;
+ }
+ }
+
+ # now insertion point is in $low.
+ $array->[$low] = $aValue; # overwrite next larger
+ return $low;
+ }
+
+ # This method computes the longest common subsequence in $a and $b.
+
+ # Result is array or ref, whose contents is such that
+ # $a->[ $i ] == $b->[ $result[ $i ] ]
+ # foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined.
+
+ # An additional argument may be passed; this is a hash or key generating
+ # function that should return a string that uniquely identifies the given
+ # element. It should be the case that if the key is the same, the elements
+ # will compare the same. If this parameter is undef or missing, the key
+ # will be the element as a string.
+
+ # By default, comparisons will use "eq" and elements will be turned into keys
+ # using the default stringizing operator '""'.
+
+ # Additional parameters, if any, will be passed to the key generation
+ # routine.
+
+ sub _longestCommonSubsequence
+ {
+ my $a = shift; # array ref or hash ref
+ my $b = shift; # array ref or hash ref
+ my $counting = shift; # scalar
+ my $keyGen = shift; # code ref
+ my $compare; # code ref
+
+ if ( ref($a) eq 'HASH' )
+ { # prepared hash must be in $b
+ my $tmp = $b;
+ $b = $a;
+ $a = $tmp;
+ }
+
+ # Check for bogus (non-ref) argument values
+ if ( !ref($a) || !ref($b) )
+ {
+ my @callerInfo = caller(1);
+ die 'error: must pass array or hash references to ' . $callerInfo[3];
+ }
+
+ # set up code refs
+ # Note that these are optimized.
+ if ( !defined($keyGen) ) # optimize for strings
+ {
+ $keyGen = sub { $_[0] };
+ $compare = sub { my ( $a, $b ) = @_; $a eq $b };
+ }
+ else
+ {
+ $compare = sub {
+ my $a = shift;
+ my $b = shift;
+ &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ );
+ };
+ }
+
+ my ( $aStart, $aFinish, $matchVector ) = ( 0, $#$a, [] );
+ my ( $prunedCount, $bMatches ) = ( 0, {} );
+
+ if ( ref($b) eq 'HASH' ) # was $bMatches prepared for us?
+ {
+ $bMatches = $b;
+ }
+ else
+ {
+ my ( $bStart, $bFinish ) = ( 0, $#$b );
+
+ # First we prune off any common elements at the beginning
+ while ( $aStart <= $aFinish
+ and $bStart <= $bFinish
+ and &$compare( $a->[$aStart], $b->[$bStart], @_ ) )
+ {
+ $matchVector->[ $aStart++ ] = $bStart++;
+ $prunedCount++;
+ }
+
+ # now the end
+ while ( $aStart <= $aFinish
+ and $bStart <= $bFinish
+ and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) )
+ {
+ $matchVector->[ $aFinish-- ] = $bFinish--;
+ $prunedCount++;
+ }
+
+ # Now compute the equivalence classes of positions of elements
+ $bMatches =
+ _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ );
+ }
+ my $thresh = [];
+ my $links = [];
+
+ my ( $i, $ai, $j, $k );
+ for ( $i = $aStart ; $i <= $aFinish ; $i++ )
+ {
+ $ai = &$keyGen( $a->[$i], @_ );
+ if ( exists( $bMatches->{$ai} ) )
+ {
+ $k = 0;
+ for $j ( @{ $bMatches->{$ai} } )
+ {
+
+ # optimization: most of the time this will be true
+ if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j )
+ {
+ $thresh->[$k] = $j;
+ }
+ else
+ {
+ $k = _replaceNextLargerWith( $thresh, $j, $k );
+ }
+
+ # oddly, it's faster to always test this (CPU cache?).
+ if ( defined($k) )
+ {
+ $links->[$k] =
+ [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ];
+ }
+ }
+ }
+ }
+
+ if (@$thresh)
+ {
+ return $prunedCount + @$thresh if $counting;
+ for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] )
+ {
+ $matchVector->[ $link->[1] ] = $link->[2];
+ }
+ }
+ elsif ($counting)
+ {
+ return $prunedCount;
+ }
+
+ return wantarray ? @$matchVector : $matchVector;
+ }
+
+ sub traverse_sequences
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref
+ my $callbacks = shift || {};
+ my $keyGen = shift;
+ my $matchCallback = $callbacks->{'MATCH'} || sub { };
+ my $discardACallback = $callbacks->{'DISCARD_A'} || sub { };
+ my $finishedACallback = $callbacks->{'A_FINISHED'};
+ my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { };
+ my $finishedBCallback = $callbacks->{'B_FINISHED'};
+ my $matchVector = _longestCommonSubsequence( $a, $b, 0, $keyGen, @_ );
+
+ # Process all the lines in @$matchVector
+ my $lastA = $#$a;
+ my $lastB = $#$b;
+ my $bi = 0;
+ my $ai;
+
+ for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ )
+ {
+ my $bLine = $matchVector->[$ai];
+ if ( defined($bLine) ) # matched
+ {
+ &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine;
+ &$matchCallback( $ai, $bi++, @_ );
+ }
+ else
+ {
+ &$discardACallback( $ai, $bi, @_ );
+ }
+ }
+
+ # The last entry (if any) processed was a match.
+ # $ai and $bi point just past the last matching lines in their sequences.
+
+ while ( $ai <= $lastA or $bi <= $lastB )
+ {
+
+ # last A?
+ if ( $ai == $lastA + 1 and $bi <= $lastB )
+ {
+ if ( defined($finishedACallback) )
+ {
+ &$finishedACallback( $lastA, @_ );
+ $finishedACallback = undef;
+ }
+ else
+ {
+ &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB;
+ }
+ }
+
+ # last B?
+ if ( $bi == $lastB + 1 and $ai <= $lastA )
+ {
+ if ( defined($finishedBCallback) )
+ {
+ &$finishedBCallback( $lastB, @_ );
+ $finishedBCallback = undef;
+ }
+ else
+ {
+ &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA;
+ }
+ }
+
+ &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA;
+ &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB;
+ }
+
+ return 1;
+ }
+
+ sub traverse_balanced
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref
+ my $callbacks = shift || {};
+ my $keyGen = shift;
+ my $matchCallback = $callbacks->{'MATCH'} || sub { };
+ my $discardACallback = $callbacks->{'DISCARD_A'} || sub { };
+ my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { };
+ my $changeCallback = $callbacks->{'CHANGE'};
+ my $matchVector = _longestCommonSubsequence( $a, $b, 0, $keyGen, @_ );
+
+ # Process all the lines in match vector
+ my $lastA = $#$a;
+ my $lastB = $#$b;
+ my $bi = 0;
+ my $ai = 0;
+ my $ma = -1;
+ my $mb;
+
+ while (1)
+ {
+
+ # Find next match indices $ma and $mb
+ do {
+ $ma++;
+ } while(
+ $ma <= $#$matchVector
+ && !defined $matchVector->[$ma]
+ );
+
+ last if $ma > $#$matchVector; # end of matchVector?
+ $mb = $matchVector->[$ma];
+
+ # Proceed with discard a/b or change events until
+ # next match
+ while ( $ai < $ma || $bi < $mb )
+ {
+
+ if ( $ai < $ma && $bi < $mb )
+ {
+
+ # Change
+ if ( defined $changeCallback )
+ {
+ &$changeCallback( $ai++, $bi++, @_ );
+ }
+ else
+ {
+ &$discardACallback( $ai++, $bi, @_ );
+ &$discardBCallback( $ai, $bi++, @_ );
+ }
+ }
+ elsif ( $ai < $ma )
+ {
+ &$discardACallback( $ai++, $bi, @_ );
+ }
+ else
+ {
+
+ # $bi < $mb
+ &$discardBCallback( $ai, $bi++, @_ );
+ }
+ }
+
+ # Match
+ &$matchCallback( $ai++, $bi++, @_ );
+ }
+
+ while ( $ai <= $lastA || $bi <= $lastB )
+ {
+ if ( $ai <= $lastA && $bi <= $lastB )
+ {
+
+ # Change
+ if ( defined $changeCallback )
+ {
+ &$changeCallback( $ai++, $bi++, @_ );
+ }
+ else
+ {
+ &$discardACallback( $ai++, $bi, @_ );
+ &$discardBCallback( $ai, $bi++, @_ );
+ }
+ }
+ elsif ( $ai <= $lastA )
+ {
+ &$discardACallback( $ai++, $bi, @_ );
+ }
+ else
+ {
+
+ # $bi <= $lastB
+ &$discardBCallback( $ai, $bi++, @_ );
+ }
+ }
+
+ return 1;
+ }
+
+ sub prepare
+ {
+ my $a = shift; # array ref
+ my $keyGen = shift; # code ref
+
+ # set up code ref
+ $keyGen = sub { $_[0] } unless defined($keyGen);
+
+ return scalar _withPositionsOfInInterval( $a, 0, $#$a, $keyGen, @_ );
+ }
+
+ sub LCS
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref or hash ref
+ my $matchVector = _longestCommonSubsequence( $a, $b, 0, @_ );
+ my @retval;
+ my $i;
+ for ( $i = 0 ; $i <= $#$matchVector ; $i++ )
+ {
+ if ( defined( $matchVector->[$i] ) )
+ {
+ push ( @retval, $a->[$i] );
+ }
+ }
+ return wantarray ? @retval : \@retval;
+ }
+
+ sub LCS_length
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref or hash ref
+ return _longestCommonSubsequence( $a, $b, 1, @_ );
+ }
+
+ sub LCSidx
+ {
+ my $a= shift @_;
+ my $b= shift @_;
+ my $match= _longestCommonSubsequence( $a, $b, 0, @_ );
+ my @am= grep defined $match->[$_], 0..$#$match;
+ my @bm= @{$match}[@am];
+ return \@am, \@bm;
+ }
+
+ sub compact_diff
+ {
+ my $a= shift @_;
+ my $b= shift @_;
+ my( $am, $bm )= LCSidx( $a, $b, @_ );
+ my @cdiff;
+ my( $ai, $bi )= ( 0, 0 );
+ push @cdiff, $ai, $bi;
+ while( 1 ) {
+ while( @$am && $ai == $am->[0] && $bi == $bm->[0] ) {
+ shift @$am;
+ shift @$bm;
+ ++$ai, ++$bi;
+ }
+ push @cdiff, $ai, $bi;
+ last if ! @$am;
+ $ai = $am->[0];
+ $bi = $bm->[0];
+ push @cdiff, $ai, $bi;
+ }
+ push @cdiff, 0+@$a, 0+@$b
+ if $ai < @$a || $bi < @$b;
+ return wantarray ? @cdiff : \@cdiff;
+ }
+
+ sub diff
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref
+ my $retval = [];
+ my $hunk = [];
+ my $discard = sub {
+ push @$hunk, [ '-', $_[0], $a->[ $_[0] ] ];
+ };
+ my $add = sub {
+ push @$hunk, [ '+', $_[1], $b->[ $_[1] ] ];
+ };
+ my $match = sub {
+ push @$retval, $hunk
+ if 0 < @$hunk;
+ $hunk = []
+ };
+ traverse_sequences( $a, $b,
+ { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ );
+ &$match();
+ return wantarray ? @$retval : $retval;
+ }
+
+ sub sdiff
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref
+ my $retval = [];
+ my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) };
+ my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) };
+ my $change = sub {
+ push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] );
+ };
+ my $match = sub {
+ push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] );
+ };
+ traverse_balanced(
+ $a,
+ $b,
+ {
+ MATCH => $match,
+ DISCARD_A => $discard,
+ DISCARD_B => $add,
+ CHANGE => $change,
+ },
+ @_
+ );
+ return wantarray ? @$retval : $retval;
+ }
+
+ ########################################
+ my $Root= __PACKAGE__;
+ package Algorithm::Diff::_impl;
+ use strict;
+
+ sub _Idx() { 0 } # $me->[_Idx]: Ref to array of hunk indices
+ # 1 # $me->[1]: Ref to first sequence
+ # 2 # $me->[2]: Ref to second sequence
+ sub _End() { 3 } # $me->[_End]: Diff between forward and reverse pos
+ sub _Same() { 4 } # $me->[_Same]: 1 if pos 1 contains unchanged items
+ sub _Base() { 5 } # $me->[_Base]: Added to range's min and max
+ sub _Pos() { 6 } # $me->[_Pos]: Which hunk is currently selected
+ sub _Off() { 7 } # $me->[_Off]: Offset into _Idx for current position
+ sub _Min() { -2 } # Added to _Off to get min instead of max+1
+
+ sub Die
+ {
+ require Carp;
+ Carp::confess( @_ );
+ }
+
+ sub _ChkPos
+ {
+ my( $me )= @_;
+ return if $me->[_Pos];
+ my $meth= ( caller(1) )[3];
+ Die( "Called $meth on 'reset' object" );
+ }
+
+ sub _ChkSeq
+ {
+ my( $me, $seq )= @_;
+ return $seq + $me->[_Off]
+ if 1 == $seq || 2 == $seq;
+ my $meth= ( caller(1) )[3];
+ Die( "$meth: Invalid sequence number ($seq); must be 1 or 2" );
+ }
+
+ sub getObjPkg
+ {
+ my( $us )= @_;
+ return ref $us if ref $us;
+ return $us . "::_obj";
+ }
+
+ sub new
+ {
+ my( $us, $seq1, $seq2, $opts ) = @_;
+ my @args;
+ for( $opts->{keyGen} ) {
+ push @args, $_ if $_;
+ }
+ for( $opts->{keyGenArgs} ) {
+ push @args, @$_ if $_;
+ }
+ my $cdif= Algorithm::Diff::compact_diff( $seq1, $seq2, @args );
+ my $same= 1;
+ if( 0 == $cdif->[2] && 0 == $cdif->[3] ) {
+ $same= 0;
+ splice @$cdif, 0, 2;
+ }
+ my @obj= ( $cdif, $seq1, $seq2 );
+ $obj[_End] = (1+@$cdif)/2;
+ $obj[_Same] = $same;
+ $obj[_Base] = 0;
+ my $me = bless \@obj, $us->getObjPkg();
+ $me->Reset( 0 );
+ return $me;
+ }
+
+ sub Reset
+ {
+ my( $me, $pos )= @_;
+ $pos= int( $pos || 0 );
+ $pos += $me->[_End]
+ if $pos < 0;
+ $pos= 0
+ if $pos < 0 || $me->[_End] <= $pos;
+ $me->[_Pos]= $pos || !1;
+ $me->[_Off]= 2*$pos - 1;
+ return $me;
+ }
+
+ sub Base
+ {
+ my( $me, $base )= @_;
+ my $oldBase= $me->[_Base];
+ $me->[_Base]= 0+$base if defined $base;
+ return $oldBase;
+ }
+
+ sub Copy
+ {
+ my( $me, $pos, $base )= @_;
+ my @obj= @$me;
+ my $you= bless \@obj, ref($me);
+ $you->Reset( $pos ) if defined $pos;
+ $you->Base( $base );
+ return $you;
+ }
+
+ sub Next {
+ my( $me, $steps )= @_;
+ $steps= 1 if ! defined $steps;
+ if( $steps ) {
+ my $pos= $me->[_Pos];
+ my $new= $pos + $steps;
+ $new= 0 if $pos && $new < 0;
+ $me->Reset( $new )
+ }
+ return $me->[_Pos];
+ }
+
+ sub Prev {
+ my( $me, $steps )= @_;
+ $steps= 1 if ! defined $steps;
+ my $pos= $me->Next(-$steps);
+ $pos -= $me->[_End] if $pos;
+ return $pos;
+ }
+
+ sub Diff {
+ my( $me )= @_;
+ $me->_ChkPos();
+ return 0 if $me->[_Same] == ( 1 & $me->[_Pos] );
+ my $ret= 0;
+ my $off= $me->[_Off];
+ for my $seq ( 1, 2 ) {
+ $ret |= $seq
+ if $me->[_Idx][ $off + $seq + _Min ]
+ < $me->[_Idx][ $off + $seq ];
+ }
+ return $ret;
+ }
+
+ sub Min {
+ my( $me, $seq, $base )= @_;
+ $me->_ChkPos();
+ my $off= $me->_ChkSeq($seq);
+ $base= $me->[_Base] if !defined $base;
+ return $base + $me->[_Idx][ $off + _Min ];
+ }
+
+ sub Max {
+ my( $me, $seq, $base )= @_;
+ $me->_ChkPos();
+ my $off= $me->_ChkSeq($seq);
+ $base= $me->[_Base] if !defined $base;
+ return $base + $me->[_Idx][ $off ] -1;
+ }
+
+ sub Range {
+ my( $me, $seq, $base )= @_;
+ $me->_ChkPos();
+ my $off = $me->_ChkSeq($seq);
+ if( !wantarray ) {
+ return $me->[_Idx][ $off ]
+ - $me->[_Idx][ $off + _Min ];
+ }
+ $base= $me->[_Base] if !defined $base;
+ return ( $base + $me->[_Idx][ $off + _Min ] )
+ .. ( $base + $me->[_Idx][ $off ] - 1 );
+ }
+
+ sub Items {
+ my( $me, $seq )= @_;
+ $me->_ChkPos();
+ my $off = $me->_ChkSeq($seq);
+ if( !wantarray ) {
+ return $me->[_Idx][ $off ]
+ - $me->[_Idx][ $off + _Min ];
+ }
+ return
+ @{$me->[$seq]}[
+ $me->[_Idx][ $off + _Min ]
+ .. ( $me->[_Idx][ $off ] - 1 )
+ ];
+ }
+
+ sub Same {
+ my( $me )= @_;
+ $me->_ChkPos();
+ return wantarray ? () : 0
+ if $me->[_Same] != ( 1 & $me->[_Pos] );
+ return $me->Items(1);
+ }
+
+ my %getName;
+ %getName= (
+ same => \&Same,
+ diff => \&Diff,
+ base => \&Base,
+ min => \&Min,
+ max => \&Max,
+ range=> \&Range,
+ items=> \&Items, # same thing
+ );
+
+ sub Get
+ {
+ my $me= shift @_;
+ $me->_ChkPos();
+ my @value;
+ for my $arg ( @_ ) {
+ for my $word ( split ' ', $arg ) {
+ my $meth;
+ if( $word !~ /^(-?\d+)?([a-zA-Z]+)([12])?$/
+ || not $meth= $getName{ lc $2 }
+ ) {
+ Die( $Root, ", Get: Invalid request ($word)" );
+ }
+ my( $base, $name, $seq )= ( $1, $2, $3 );
+ push @value, scalar(
+ 4 == length($name)
+ ? $meth->( $me )
+ : $meth->( $me, $seq, $base )
+ );
+ }
+ }
+ if( wantarray ) {
+ return @value;
+ } elsif( 1 == @value ) {
+ return $value[0];
+ }
+ Die( 0+@value, " values requested from ",
+ $Root, "'s Get in scalar context" );
+ }
+
+
+ my $Obj= getObjPkg($Root);
+ no strict 'refs';
+
+ for my $meth ( qw( new getObjPkg ) ) {
+ *{$Root."::".$meth} = \&{$meth};
+ *{$Obj ."::".$meth} = \&{$meth};
+ }
+ for my $meth ( qw(
+ Next Prev Reset Copy Base Diff
+ Same Items Range Min Max Get
+ _ChkPos _ChkSeq
+ ) ) {
+ *{$Obj."::".$meth} = \&{$meth};
+ }
+
+};
+{
+ package Algorithm::LCSS;
+
+ use strict;
+ {
+ no strict 'refs';
+ *traverse_sequences = \&Algorithm::Diff::traverse_sequences;
+ }
+
+ sub _tokenize { [split //, $_[0]] }
+
+ sub CSS {
+ my $is_array = ref $_[0] eq 'ARRAY' ? 1 : 0;
+ my ( $seq1, $seq2, @match, $from_match );
+ my $i = 0;
+ if ( $is_array ) {
+ $seq1 = $_[0];
+ $seq2 = $_[1];
+ traverse_sequences( $seq1, $seq2, {
+ MATCH => sub { push @{$match[$i]}, $seq1->[$_[0]]; $from_match = 1 },
+ DISCARD_A => sub { do{$i++; $from_match = 0} if $from_match },
+ DISCARD_B => sub { do{$i++; $from_match = 0} if $from_match },
+ });
+ }
+ else {
+ $seq1 = _tokenize($_[0]);
+ $seq2 = _tokenize($_[1]);
+ traverse_sequences( $seq1, $seq2, {
+ MATCH => sub { $match[$i] .= $seq1->[$_[0]]; $from_match = 1 },
+ DISCARD_A => sub { do{$i++; $from_match = 0} if $from_match },
+ DISCARD_B => sub { do{$i++; $from_match = 0} if $from_match },
+ });
+ }
+ return \@match;
+ }
+
+ sub CSS_Sorted {
+ my $match = CSS(@_);
+ if ( ref $_[0] eq 'ARRAY' ) {
+ @$match = map{$_->[0]}sort{$b->[1]<=>$a->[1]}map{[$_,scalar(@$_)]}@$match
+ }
+ else {
+ @$match = map{$_->[0]}sort{$b->[1]<=>$a->[1]}map{[$_,length($_)]}@$match
+ }
+ return $match;
+ }
+
+ sub LCSS {
+ my $is_array = ref $_[0] eq 'ARRAY' ? 1 : 0;
+ my $css = CSS(@_);
+ my $index;
+ my $length = 0;
+ if ( $is_array ) {
+ for( my $i = 0; $i < @$css; $i++ ) {
+ next unless @{$css->[$i]}>$length;
+ $index = $i;
+ $length = @{$css->[$i]};
+ }
+ }
+ else {
+ for( my $i = 0; $i < @$css; $i++ ) {
+ next unless length($css->[$i])>$length;
+ $index = $i;
+ $length = length($css->[$i]);
+ }
+ }
+ return $css->[$index];
+ }
+
+};
+# }}}
+#{{{ Class::Classless module
+{
+ package Class::Classless;
+ use strict;
+ use vars qw(@ISA);
+ use Carp;
+
+ @ISA = ();
+
+ ###########################################################################
+
+ @Class::Classless::X::ISA = ();
+
+ ###########################################################################
+ ###########################################################################
+
+ sub Class::Classless::X::AUTOLOAD {
+ # This's the big dispatcher.
+
+ my $it = shift @_;
+ my $m = ($Class::Classless::X::AUTOLOAD =~ m/([^:]+)$/s )
+ ? $1 : $Class::Classless::X::AUTOLOAD;
+
+ croak "Can't call Class::Classless methods (like $m) without an object"
+ unless ref $it; # sanity, basically.
+
+ my $prevstate;
+ $prevstate = ${shift @_}
+ if scalar(@_) && defined($_[0]) &&
+ ref($_[0]) eq 'Class::Classless::CALLSTATE::SHIMMY'
+ ; # A shim! we were called via $callstate->NEXT
+
+ my $no_fail = $prevstate ? $prevstate->[3] : undef;
+ my $i = $prevstate ? ($prevstate->[1] + 1) : 0;
+ # where to start scanning
+ my $lineage;
+
+ # Get the linearization of the ISA tree
+ if($prevstate) {
+ $lineage = $prevstate->[2];
+ } elsif(defined $it->{'ISA_CACHE'} and ref $it->{'ISA_CACHE'} ){
+ $lineage = $it->{'ISA_CACHE'};
+ } else {
+ $lineage = [ &Class::Classless::X::ISA_TREE($it) ];
+ }
+
+ # Was:
+ #my @lineage =
+ # $prevstate ? @{$prevstate->[2]}
+ # : &Class::Classless::X::ISA_TREE($it);
+ # # Get the linearization of the ISA tree
+ # # ISA-memoization happens in the ISA_TREE function.
+
+ for(; $i < @$lineage; ++$i) {
+
+ if( !defined($no_fail) and exists($lineage->[$i]{'NO_FAIL'}) ) {
+ $no_fail = ($lineage->[$i]{'NO_FAIL'} || 0);
+ # so the first NO_FAIL sets it
+ }
+
+ if( ref($lineage->[$i]{'METHODS'} || 0) # sanity
+ && exists($lineage->[$i]{'METHODS'}{$m})
+ ){
+ # We found what we were after. Now see what to do with it.
+ my $v = $lineage->[$i]{'METHODS'}{$m};
+ return $v unless defined $v and ref $v;
+
+ if(ref($v) eq 'CODE') { # normal case, I expect!
+ # Used to have copying of the arglist here.
+ # But it was apparently useless, so I deleted it
+ unshift @_,
+ $it, # $_[0] -- target object
+ # a NEW callstate
+ bless([$m, $i, $lineage, $no_fail, $prevstate ? 1 : 0],
+ 'Class::Classless::CALLSTATE'
+ ), # $_[1] -- the callstate
+ ;
+ goto &{ $v }; # yes, magic goto! bimskalabim!
+ }
+ return @$v if ref($v) eq '_deref_array';
+ return $$v if ref($v) eq '_deref_scalar';
+ return $v; # fallthru
+ }
+ }
+
+ if($m eq 'DESTROY') { # mitigate DESTROY-lookup failure at global destruction
+ # should be impossible
+ } else {
+ if($no_fail || 0) {
+ return;
+ }
+ croak "Can't find ", $prevstate ? 'NEXT method' : 'method',
+ " $m in ", $it->{'NAME'} || $it,
+ " or any ancestors\n";
+ }
+ }
+
+ ###########################################################################
+ ###########################################################################
+
+ sub Class::Classless::X::DESTROY {
+ # noop
+ }
+
+ ###########################################################################
+ sub Class::Classless::X::ISA_TREE {
+ # The linearizer!
+ # Returns the search path for $_[0], starting with $_[0]
+ # Possibly memoized.
+
+ # I stopped being able to understand this algorithm about five
+ # minutes after I wrote it.
+ use strict;
+
+ my $set_cache = 0; # flag to set the cache on the way out
+
+ if(exists($_[0]{'ISA_CACHE'})) {
+ return @{$_[0]{'ISA_CACHE'}}
+ if defined $_[0]{'ISA_CACHE'}
+ and ref $_[0]{'ISA_CACHE'};
+
+ # Otherwise, if exists but is not a ref, it's a signal that it should
+ # be replaced at the earliest, with a listref
+ $set_cache = 1;
+ }
+
+ my $has_mi = 0; # set to 0 on the first node we see with 2 parents!
+ # First, just figure out what's in the tree.
+ my %last_child = ($_[0] => 1); # as if already seen
+
+ # if $last_child{$x} == $y, that means:
+ # 1) incidentally, we've passed the node $x before.
+ # 2) $x is the last child of $y,
+ # so that means that $y can be pushed to the stack only after
+ # we've pushed $x to the stack.
+
+ my @tree_nodes;
+ {
+ my $current;
+ my @in_stack = ($_[0]);
+ while(@in_stack) {
+ next unless
+ defined($current = shift @in_stack)
+ && ref($current) # sanity
+ && ref($current->{'PARENTS'} || 0) # sanity
+ ;
+
+ push @tree_nodes, $current;
+
+ $has_mi = 1 if @{$current->{'PARENTS'}} > 1;
+ unshift
+ @in_stack,
+ map {
+ if(exists $last_child{$_}) { # seen before!
+ $last_child{$_} = $current;
+ (); # seen -- don't re-explore
+ } else { # first time seen
+ $last_child{$_} = $current;
+ $_; # first time seen -- explore now
+ }
+ }
+ @{$current->{'PARENTS'}}
+ ;
+ }
+
+ # If there was no MI, then that first scan was sufficient.
+ unless($has_mi) {
+ $_[0]{'ISA_CACHE'} = \@tree_nodes if $set_cache;
+ return @tree_nodes;
+ }
+
+ # Otherwise, toss this list and rescan, consulting %last_child
+ }
+
+ # $last_child{$parent} holds the last (or only) child of $parent
+ # in this tree. When walking the tree this time, only that
+ # child is authorized to put its parent on the @in_stack.
+ # And that's the only way a node can get added to @in_stack,
+ # except for $_[0] (the start node) being there at the beginning.
+
+ # Now, walk again, but this time exploring parents the LAST
+ # time seen in the tree, not the first.
+
+ my @out;
+ {
+ my $current;
+ my @in_stack = ($_[0]);
+ while(@in_stack) {
+ next unless defined($current = shift @in_stack) && ref($current);
+ push @out, $current; # finally.
+ unshift
+ @in_stack,
+ grep(
+ (
+ defined($_) # sanity
+ && ref($_) # sanity
+ && $last_child{$_} eq $current,
+ ),
+ # I'm lastborn (or onlyborn) of this parent
+ # so it's OK to explore now
+ @{$current->{'PARENTS'}}
+ )
+ if ref($current->{'PARENTS'} || 0) # sanity
+ ;
+ }
+
+ unless(scalar(@out) == scalar(keys(%last_child))) {
+ # the counts should be equal
+ my %good_ones;
+ @good_ones{@out} = ();
+ croak
+ "ISA tree for " .
+ ($_[0]{'NAME'} || $_[0]) .
+ " is apparently cyclic, probably involving the nodes " .
+ nodelist( grep { ref($_) && !exists $good_ones{$_} }
+ values(%last_child) )
+ . "\n";
+ }
+ }
+ #print "Contents of out: ", nodelist(@out), "\n";
+
+ $_[0]{'ISA_CACHE'} = \@out if $set_cache;
+ return @out;
+ }
+
+ ###########################################################################
+
+ sub Class::Classless::X::can { # NOT like UNIVERSAL::can ...
+ # return 1 if $it is capable of the method given -- otherwise 0
+ my($it, $m) = @_[0,1];
+ return undef unless ref $it;
+
+ croak "undef is not a valid method name" unless defined($m);
+ croak "null-string is not a valid method name" unless length($m);
+
+ foreach my $o (&Class::Classless::X::ISA_TREE($it)) {
+ return 1
+ if ref($o->{'METHODS'} || 0) # sanity
+ && exists $o->{'METHODS'}{$m};
+ }
+
+ return 0;
+ }
+
+
+ ###########################################################################
+
+ sub Class::Classless::X::isa { # Like UNIVERSAL::isa
+ # Returns true for $X->isa($Y) iff $Y is $X or is an ancestor of $X.
+
+ return unless ref($_[0]) && ref($_[1]);
+ return scalar(grep {$_ eq $_[1]} &Class::Classless::X::ISA_TREE($_[0]));
+ }
+
+ ###########################################################################
+
+ sub nodelist { join ', ', map { "" . ($_->{'NAME'} || $_) . ""} @_ }
+
+ ###########################################################################
+ ###########################################################################
+ ###########################################################################
+ # Methods for the CALLSTATE class.
+ # Basically, CALLSTATE objects represent the state of the dispatcher,
+ # frozen at the moment when the method call was dispatched to the
+ # appropriate sub.
+ # In the grand scheme of things, this needn't be a class -- I could
+ # have just made the callstate data-object be a hash with documented
+ # keys, or a closure that responded to only certain parameters,
+ # etc. But I like it this way. And I like being able to say simply
+ # $cs->NEXT
+ # Yes, these are a bit cryptically written, but it's behoovy for
+ # them to be very very efficient.
+
+ @Class::Classless::ISA = ();
+ sub Class::Classless::CALLSTATE::found_name { $_[0][0] }
+ # the method name called and found
+ sub Class::Classless::CALLSTATE::found_depth { $_[0][1] }
+ # my depth in the lineage
+ sub Class::Classless::CALLSTATE::lineage { @{$_[0][2]} }
+ # my lineage
+ sub Class::Classless::CALLSTATE::target { $_[0][2][ 0 ] }
+ # the object that's the target -- same as $_[0] for the method called
+ sub Class::Classless::CALLSTATE::home { $_[0][2][ $_[0][1] ] }
+ # the object I was found in
+ sub Class::Classless::CALLSTATE::sub_found {
+ $_[0][2][ $_[0][1] ]{'METHODS'}{ $_[0][0] }
+ } # the routine called
+
+ sub Class::Classless::CALLSTATE::no_fail { $_[0][3] }
+ sub Class::Classless::CALLSTATE::set_no_fail_true { $_[0][3] = 1 }
+ sub Class::Classless::CALLSTATE::set_fail_false { $_[0][3] = 0 }
+ sub Class::Classless::CALLSTATE::set_fail_undef { $_[0][3] = undef }
+
+ sub Class::Classless::CALLSTATE::via_next { $_[0][4] }
+
+ sub Class::Classless::CALLSTATE::NEXT {
+ #croak "NEXT needs at least one argument: \$cs->NEXT('method'...)"
+ # unless @_ > 1;
+ # no longer true.
+ my $cs = shift @_;
+ my $m = shift @_; # which may be (or come out) undef...
+ $m = $cs->[0] unless defined $m; # the method name called and found
+
+ ($cs->[2][0])->$m(
+ bless( \$cs, 'Class::Classless::CALLSTATE::SHIMMY' ),
+ @_
+ );
+ }
+
+ ###########################################################################
+};
+#}}}
+
+###############
+###
+#
+# {{{ *** C h a n g e l o g ***
+#
+# 0.6ca
+# - add screen support (from nicklist.pl)
+# - rename to adv_windowlist.pl (advanced window list) since it isn't just a
+# window list status bar (wlstat) anymore
+# - names can now have a max length and window names can be used
+# - fixed a bug with block display in screen mode and statusbar mode
+# - added space handling to ir_fe and removed it again
+# - now handling formats on my own
+# - added warning about missing sb_act_none abstract leading to
+# - display*active settings
+# - added warning about the bug in awl_display_(no)key_active settings
+#
+# 0.5d
+# - add setting to also hide the last statusbar if empty (awl_all_disable)
+# - reverted to old utf8 code to also calculate broken utf8 length correctly
+# - simplified dealing with statusbars in wlreset
+# - added a little tweak for the renamed term_type somewhere after Irssi 0.8.9
+# - fixed bug in handling channel #$$
+# - typo on line 200 spotted by f0rked
+# - reset background colour at the beginning of an entry
+#
+# 0.4d
+# - fixed order of disabling statusbars
+# - several attempts at special chars, without any real success
+# and much more weird new bugs caused by this
+# - setting to specify sort order
+# - reduced timeout values
+# - added awl_hide_data for Geert Hauwaerts ( geert@irssi.org ) :)
+# - make it so the dynamic sub is actually deleted
+# - fix a bug with removing of the last separator
+# - take into consideration parse_special
+#
+# 0.3b
+# - automatically kill old statusbars
+# - reset on /reload
+# - position/placement settings
+#
+# 0.2
+# - automated retrieval of key bindings (thanks grep.pl authors)
+# - improved removing of statusbars
+# - got rid of status chop
+#
+# 0.1
+# - rewritten to suit my needs
+# - based on chanact 0.5.5
+# }}}
+# vim: se fdm=marker tw=80 :
diff --git a/.irssi/scripts/autorun/act.pl b/.irssi/scripts/autorun/act.pl
new file mode 100644
index 0000000..0b20de8
--- /dev/null
+++ b/.irssi/scripts/autorun/act.pl
@@ -0,0 +1,72 @@
+#!/usr/bin/perl -w
+# resets window activity status
+# by c0ffee
+# - http://www.penguin-breeder.org/irssi/
+
+#<scriptinfo>
+use vars qw($VERSION %IRSSI);
+
+use Irssi 20020120;
+$VERSION = "0.13";
+%IRSSI = (
+ authors => "c0ffee",
+ contact => "c0ffee\@penguin-breeder.org",
+ name => "Reset window activity status",
+ description => "Reset window activity status. defines command /act",
+ license => "Public Domain",
+ url => "http://www.penguin-breeder.org/irssi/",
+ changed => "Wed Jun 23 08:34:53 CEST 2004",
+);
+#</scriptinfo>
+
+
+#
+# /ACT [PUBLIC|ALL]
+#
+# /ACT without parameters marks windows as non-active where no
+# public talk occured.
+#
+# /ACT PUBLIC also removes those where no nick hilight was triggered
+#
+# /ACT ALL sets all windows as non-active
+sub cmd_act {
+ my ($data, $server, $channel) = @_;
+
+ if ($data eq "") {
+ $level = 1;
+ } elsif ($data =~ /^public$/i) {
+ $level = 2;
+ } elsif ($data =~ /^all$/i) {
+ $level = 3;
+ } else {
+ Irssi::signal_emit("error command", -3, $data);
+ return;
+ }
+
+ foreach (Irssi::windows()) {
+
+ if ($_->{data_level} <= $level) {
+
+ Irssi::signal_emit("window dehilight", $_);
+
+ }
+
+ }
+}
+
+my @arguments = ('public', 'all');
+sub sig_complete ($$$$$) {
+ my ($list, $window, $word, $linestart, $want_space) = @_;
+ return unless $linestart =~ /^.act/;
+ foreach my $arg (@arguments) {
+ if ($arg =~ /^$word/i) {
+ $$want_space = 0;
+ push @$list, $arg;
+ }
+ }
+ Irssi::signal_stop();
+}
+
+
+Irssi::command_bind("act", "cmd_act");
+Irssi::signal_add_first('complete word', \&sig_complete);
diff --git a/.irssi/scripts/autorun/adv_windowlist.pl b/.irssi/scripts/autorun/adv_windowlist.pl
new file mode 100644
index 0000000..69725bf
--- /dev/null
+++ b/.irssi/scripts/autorun/adv_windowlist.pl
@@ -0,0 +1,2478 @@
+use strict; # use warnings;
+
+# {{{ debug
+
+#BEGIN {
+# open STDERR, '>', '/home/ailin/wlstatwarnings';
+#};
+
+# FIXME COULD SOMEONE PLEASE TELL ME HOW TO SHUT UP
+#
+# ...
+# Variable "*" will not stay shared at (eval *) line *.
+# Variable "*" will not stay shared at (eval *) line *.
+# ...
+# Can't locate package Irssi::Nick for @Irssi::Irc::Nick::ISA at (eval *) line *.
+# ...
+#
+# THANKS
+
+# }}}
+
+# if you don't know how to operate folds, type zn
+
+# {{{ header
+
+use Irssi (); # which is the minimum required version of Irssi ?
+use Irssi::TextUI;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '0.6ca';
+%IRSSI = (
+ original_authors => q(BC-bd, Veli, Timo Sirainen, ).
+ q(Wouter Coekaerts, Jean-Yves Lefort), # (decadix)
+ original_contact => q(bd@bc-bd.org, veli@piipiip.net, tss@iki.fi, ).
+ q(wouter@coekaerts.be, jylefort@brutele.be),
+ authors => q(Nei),
+ contact => q(Nei@QuakeNet),
+ url => "http://anti.teamidiot.de/",
+ name => q(awl),
+ description => q(Adds a permanent advanced window list on the right or ).
+ q(in a statusbar.),
+ description2 => q(Based on chanact.pl which was apparently based on ).
+ q(lightbar.c and nicklist.pl with various other ideas ).
+ q(from random scripts.),
+ license => q(GNU GPLv2 or later),
+);
+
+# }}}
+
+# {{{ *** D O C U M E N T A T I O N ***
+
+# adapted by Nei
+
+###############
+# {{{ original comment
+# ###########
+# # Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias).
+# # Lets you give alias characters to windows so that you can select those with
+# # meta-<char>.
+# #
+# # for irssi 0.8.2 by bd@bc-bd.org
+# #
+# # inspired by chanlist.pl by 'cumol@hammerhart.de'
+# #
+# #########
+# # {{{ Contributors
+# #########
+# #
+# # veli@piipiip.net /window_alias code
+# # qrczak@knm.org.pl chanact_abbreviate_names
+# # qerub@home.se Extra chanact_show_mode and chanact_chop_status
+# # }}}
+# }}}
+#
+# {{{ FURTHER THANKS TO
+# ############
+# # buu, fxn, Somni, Khisanth, integral, tybalt89 for much support in any aspect perl
+# # and the channel in general ( #perl @ freenode ) and especially the ir_* functions
+# #
+# # Valentin 'senneth' Batz ( vb@g-23.org ) for the pointer to grep.pl, continuous support
+# # and help in digging up ir_strip_codes
+# #
+# # OnetrixNET technology networks for the debian environment
+# #
+# # Monkey-Pirate.com / Spaceman Spiff for the webspace
+# #
+# }}}
+
+######
+# {{{ M A I N P R O B L E M
+#####
+#
+# It is impossible to place the awl on a statusbar together with other items,
+# because I do not know how to calculate the size that it is going to get
+# granted, and therefore I cannot do the linebreaks properly.
+# This is what is missing to make a nice script out of awl.
+# If you have any ideas, please contact me ASAP :).
+# }}}
+######
+
+######
+# {{{ UTF-8 PROBLEM
+#####
+#
+# Please help me find a solution to this:
+# this be your statusbar, it is using up the maximum term size
+# [[1=1]#abc [2=2]#defghi]
+#
+# now consider this example:i
+# "ascii" characters are marked with ., utf-8 characters with *
+# [[1=1]#... [2=2]#...***]
+#
+# you should think that this is how it would be displayed? WRONG!
+# [[1=1]#... [2=2]#...*** ]
+#
+# this is what Irssi does.. I believe my length calculating code to be correct,
+# however, I'd love to be proven wrong (or receive any other fix, too, of
+# course!)
+# }}}
+######
+
+#########
+# {{{ USAGE
+###
+#
+# copy the script to ~/.irssi/scripts/
+#
+# In irssi:
+#
+# /script load awl
+#
+#
+# Hint: to get rid of the old [Act:] display
+# /statusbar window remove act
+#
+# to get it back:
+# /statusbar window add -after lag -priority 10 act
+# }}}
+##########
+# {{{ OPTIONS
+########
+#
+# {{{ /set awl_display_nokey <string>
+# /set awl_display_key <string>
+# /set awl_display_nokey_active <string>
+# /set awl_display_key_active <string>
+# * string : Format String for one window. The following $'s are expanded:
+# $C : Name
+# $N : Number of the Window
+# $Q : meta-Keymap
+# $H : Start highlighting
+# $S : Stop highlighting
+# /+++++++++++++++++++++++++++++++++,
+# | **** I M P O R T A N T : **** |
+# | |
+# | don't forget to use $S if you |
+# | used $H before! |
+# | |
+# '+++++++++++++++++++++++++++++++++/
+# XXX NOTE ON *_active: there is a BUG somewhere in the length
+# XXX calculation. currently it's best to NOT remove $H/$S from those
+# XXX settings if you use it in the non-active settings.
+# }}}
+# {{{ /set awl_separator <string>
+# * string : Charater to use between the channel entries
+# you'll need to escape " " space and "$" like this:
+# "/set awl_separator \ "
+# "/set awl_separator \$"
+# and {}% like this:
+# "/set awl_separator %{"
+# "/set awl_separator %}"
+# "/set awl_separator %%"
+# (reason being, that the separator is used inside a {format })
+# }}}
+# {{{ /set awl_prefer_name <ON|OFF>
+# * this setting decides whether awl will use the active_name (OFF) or the
+# window name as the name/caption in awl_display_*.
+# That way you can rename windows using /window name myownname.
+# }}}
+# {{{ /set awl_hide_data <num>
+# * num : hide the window if its data_level is below num
+# set it to 0 to basically disable this feature,
+# 1 if you don't want windows without activity to be shown
+# 2 to show only those windows with channel text or hilight
+# 3 to show only windows with hilight
+# }}}
+# {{{ /set awl_maxlines <num>
+# * num : number of lines to use for the window list (0 to disable, negative
+# lock)
+# }}}
+# {{{ /set awl_columns <num>
+# * num : number of columns to use in screen mode (0 for unlimited)
+# }}}
+# {{{ /set awl_block <num>
+# * num : width of a column in screen mode (negative values = block display)
+# /+++++++++++++++++++++++++++++++++,
+# | ****** W A R N I N G ! ****** |
+# | |
+# | If your block display looks |
+# | DISTORTED, you need to add the |
+# | following line to your .theme |
+# | file under |
+# | abstracts = { : |
+# | |
+# | sb_act_none = "%n$*"; |
+# | |
+# '+++++++++++++++++++++++++++++++++/
+#.02:08:26. < shi> Irssi::current_theme()->get_format <.. can this be used?
+# }}}
+# {{{ /set awl_sbar_maxlength <ON|OFF>
+# * if you enable the maxlength setting, the block width will be used as a
+# maximum length for the non-block statusbar mode too.
+# }}}
+# {{{ /set awl_height_adjust <num>
+# * num : how many lines to leave empty in screen mode
+# }}}
+# {{{ /set awl_sort <-data_level|-last_line|refnum>
+# * you can change the window sort order with this variable
+# -data_level : sort windows with hilight first
+# -last_line : sort windows in order of activity
+# refnum : sort windows by window number
+# }}}
+# {{{ /set awl_placement <top|bottom>
+# /set awl_position <num>
+# * these settings correspond to /statusbar because awl will create
+# statusbars for you
+# (see /help statusbar to learn more)
+# }}}
+# {{{ /set awl_all_disable <ON|OFF>
+# * if you set awl_all_disable to ON, awl will also remove the
+# last statusbar it created if it is empty.
+# As you might guess, this only makes sense with awl_hide_data > 0 ;)
+# }}}
+# {{{ /set awl_automode <sbar|screen|emulate_lightbar>
+# * this setting defines whether the window list is shown in statusbars or
+# whether the screen hack is used (from nicklist.pl)
+# }}}
+# }}}
+##########
+# {{{ COMMANDS
+########
+# {{{ /awl paste <ON|OFF|TOGGLE>
+# * enables or disables the screen hack windowlist. This is useful when you
+# want to mark & copy text that you want to paste somewhere (hence the
+# name). (ON means AWL disabled!)
+# This is nicely bound to a function key for example.
+# }}}
+# {{{ /awl redraw
+# * redraws the screen hack windowlist. There are many occasions where the
+# screen hack windowlist can get destroyed so you can use this command to
+# fix it.
+# }}}
+# }}}
+###
+# {{{ WISHES
+####
+#
+# if you fiddle with my mess, provide me with your fixes so I can benefit as well
+#
+# Nei =^.^= ( QuakeNet accountname: ailin )
+# }}}
+
+# }}}
+
+# {{{ modules
+
+#use Class::Classless;
+#use Term::Info;
+
+# }}}
+
+# {{{ global variables
+
+my $replaces = '[=]'; # AARGH!!! (chars that are always surrounded by weird
+ # colour codes by Irssi)
+
+my $actString = []; # statusbar texts
+my $currentLines = 0;
+my $resetNeeded; # layout/screen has changed, redo everything
+my $needRemake; # "normal" changes
+#my $callcount = 0;
+sub GLOB_QUEUE_TIMER () { 100 }
+my $globTime = undef; # timer to limit remake() calls
+
+
+my $SCREEN_MODE;
+my $DISABLE_SCREEN_TEMP;
+my $currentColumns = 0;
+my $screenResizing;
+my ($screenHeight, $screenWidth);
+my $screenansi = bless {
+ NAME => 'Screen::ANSI',
+ PARENTS => [],
+ METHODS => {
+ dcs => sub { "\033P" },
+ st => sub { "\033\\"},
+ }
+}, 'Class::Classless::X';
+#my $terminfo = new Term::Info 'xterm'; # xterm here, make this modular
+# {{{{{{{{{{{{{{{
+my $terminfo = bless { # xterm here, make this modular
+ NAME => 'Term::Info::xterm',
+ PARENTS => [],
+ METHODS => {
+ # civis=\E[?25l,
+ civis => sub { "\033[?25l" },
+ # sc=\E7,
+ sc => sub { "\0337" },
+ # cup=\E[%i%p1%d;%p2%dH,
+ cup => sub { shift;shift; "\033[" . ($_[0] + 1) . ';' . ($_[1] + 1) . 'H' },
+ # el=\E[K,
+ el => sub { "\033[K" },
+ # rc=\E8,
+ rc => sub { "\0338" },
+ # cnorm=\E[?25h,
+ cnorm => sub { "\033[?25h" },
+ # setab=\E[4%p1%dm,
+ setab => sub { shift;shift; "\033[4" . $_[0] . 'm' },
+ # setaf=\E[3%p1%dm,
+ setaf => sub { shift;shift; "\033[3" . $_[0] . 'm' },
+ # bold=\E[1m,
+ bold => sub { "\033[1m" },
+ # blink=\E[5m,
+ blink => sub { "\033[5m" },
+ # rev=\E[7m,
+ rev => sub { "\033[7m" },
+ # op=\E[39;49m,
+ op => sub { "\033[39;49m" },
+ }
+}, 'Class::Classless::X';
+# }}}}}}}}}}}}}}}
+
+
+sub setc () {
+ $IRSSI{'name'}
+}
+sub set ($) {
+ setc . '_' . shift
+}
+
+# }}}
+
+
+# {{{ sbar mode
+
+my %statusbars; # currently active statusbars
+
+# maybe I should just tie the array ?
+sub add_statusbar {
+ for (@_) {
+ # add subs
+ for my $l ($_) { {
+ no strict 'refs'; # :P
+ *{set$l} = sub { awl($l, @_) };
+ }; }
+ Irssi::command('statusbar ' . (set$_) . ' reset');
+ Irssi::command('statusbar ' . (set$_) . ' enable');
+ if (lc Irssi::settings_get_str(set 'placement') eq 'top') {
+ Irssi::command('statusbar ' . (set$_) . ' placement top');
+ }
+ if ((my $x = int Irssi::settings_get_int(set 'position')) != 0) {
+ Irssi::command('statusbar ' . (set$_) . ' position ' . $x);
+ }
+ Irssi::command('statusbar ' . (set$_) . ' add -priority 100 -alignment left barstart');
+ Irssi::command('statusbar ' . (set$_) . ' add ' . (set$_));
+ Irssi::command('statusbar ' . (set$_) . ' add -priority 100 -alignment right barend');
+ Irssi::command('statusbar ' . (set$_) . ' disable');
+ Irssi::statusbar_item_register(set$_, '$0', set$_);
+ $statusbars{$_} = {};
+ }
+}
+
+sub remove_statusbar {
+ for (@_) {
+ Irssi::command('statusbar ' . (set$_) . ' reset');
+ Irssi::statusbar_item_unregister(set$_); # XXX does this actually work ?
+ # DO NOT REMOVE the sub before you have unregistered it :))
+ for my $l ($_) { {
+ no strict 'refs';
+ undef &{set$l};
+ }; }
+ delete $statusbars{$_};
+ }
+}
+
+sub syncLines {
+ my $temp = $currentLines;
+ $currentLines = @$actString;
+ #Irssi::print("current lines: $temp new lines: $currentLines");
+ my $currMaxLines = Irssi::settings_get_int(set 'maxlines');
+ if ($currMaxLines > 0 and @$actString > $currMaxLines) {
+ $currentLines = $currMaxLines;
+ }
+ elsif ($currMaxLines < 0) {
+ $currentLines = abs($currMaxLines);
+ }
+ return if ($temp == $currentLines);
+ if ($currentLines > $temp) {
+ for ($temp .. ($currentLines - 1)) {
+ add_statusbar($_);
+ Irssi::command('statusbar ' . (set$_) . ' enable');
+ }
+ }
+ else {
+ for ($_ = ($temp - 1); $_ >= $currentLines; $_--) {
+ Irssi::command('statusbar ' . (set$_) . ' disable');
+ remove_statusbar($_);
+ }
+ }
+}
+
+# FIXME implement $get_size_only check, and user $item->{min|max-size} ??
+sub awl {
+ my ($line, $item, $get_size_only) = @_;
+
+ if ($needRemake) {
+ $needRemake = undef;
+ remake();
+ }
+
+ my $text = $actString->[$line]; # DO NOT set the actual $actString->[$line] to '' here or
+ $text = '' unless defined $text; # you'll screw up the statusbar counter ($currentLines)
+ $item->default_handler($get_size_only, $text, '', 1);
+}
+
+# remove old statusbars
+my %killBar;
+sub get_old_status {
+ my ($textDest, $cont, $cont_stripped) = @_;
+ if ($textDest->{'level'} == 524288 and $textDest->{'target'} eq ''
+ and !defined($textDest->{'server'})
+ ) {
+ my $name = quotemeta(set '');
+ if ($cont_stripped =~ m/^$name(\d+)\s/) { $killBar{$1} = {}; }
+ Irssi::signal_stop();
+ }
+}
+sub killOldStatus {
+ %killBar = ();
+ Irssi::signal_add_first('print text' => 'get_old_status');
+ Irssi::command('statusbar');
+ Irssi::signal_remove('print text' => 'get_old_status');
+ remove_statusbar(keys %killBar);
+}
+#killOldStatus();
+
+# end sbar mode }}}
+
+
+# {{{ keymaps
+
+my %keymap;
+
+sub get_keymap {
+ my ($textDest, undef, $cont_stripped) = @_;
+ if ($textDest->{'level'} == 524288 and $textDest->{'target'} eq ''
+ and !defined($textDest->{'server'})
+ ) {
+ if ($cont_stripped =~ m/((?:meta-)+)(.)\s+change_window (\d+)/) {
+ my ($level, $key, $window) = ($1, $2, $3);
+ my $numlevel = ($level =~ y/-//) - 1;
+ $keymap{$window} = ('-' x $numlevel) . "$key";
+ }
+ Irssi::signal_stop();
+ }
+}
+
+sub update_keymap {
+ %keymap = ();
+ Irssi::signal_remove('command bind' => 'watch_keymap');
+ Irssi::signal_add_first('print text' => 'get_keymap');
+ Irssi::command('bind'); # stolen from grep
+ Irssi::signal_remove('print text' => 'get_keymap');
+ Irssi::signal_add('command bind' => 'watch_keymap');
+ Irssi::timeout_add_once(100, 'eventChanged', undef);
+}
+
+# watch keymap changes
+sub watch_keymap {
+ Irssi::timeout_add_once(1000, 'update_keymap', undef);
+}
+
+update_keymap();
+
+# end keymaps }}}
+
+# {{{ format handling
+
+# a bad way do do expansions but who cares
+sub expand {
+ my ($string, %format) = @_;
+ my ($exp, $repl);
+ $string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
+ return $string;
+}
+
+my %strip_table = (
+ # fe-common::core::formats.c:format_expand_styles
+ # delete format_backs format_fores bold_fores other stuff
+ (map { $_ => '' } (split //, '04261537' . 'kbgcrmyw' . 'KBGCRMYW' . 'U9_8:|FnN>#[')),
+ # escape
+ (map { $_ => $_ } (split //, '{}%')),
+);
+sub ir_strip_codes { # strip %codes
+ my $o = shift;
+ $o =~ s/(%(.))/exists $strip_table{$2} ? $strip_table{$2} : $1/gex;
+ $o
+}
+
+sub ir_parse_special {
+ my $o; my $i = shift;
+ #if ($_[0]) { # for the future?!?
+ # eval {
+ # $o = $_[0]->parse_special($i);
+ # };
+ # unless ($@) {
+ # return $o;
+ # }
+ #}
+ my $win = shift || Irssi::active_win();
+ my $server = Irssi::active_server();
+ if (ref $win and ref $win->{'active'}) {
+ $o = $win->{'active'}->parse_special($i);
+ }
+ elsif (ref $win and ref $win->{'active_server'}) {
+ $o = $win->{'active_server'}->parse_special($i);
+ }
+ elsif (ref $server) {
+ $o = $server->parse_special($i);
+ }
+ else {
+ $o = Irssi::parse_special($i);
+ }
+ $o
+}
+sub ir_parse_special_protected {
+ my $o; my $i = shift;
+ $i =~ s/
+ ( \\. ) | # skip over escapes (maybe)
+ ( \$[^% $\]+ ) # catch special variables
+ /
+ if ($1) { $1 }
+ elsif ($2) { my $i2 = $2; ir_fe(ir_parse_special($i2, @_)) }
+ else { $& }
+ /gex;
+ $i
+}
+
+
+sub sb_ctfe { # Irssi::current_theme->format_expand wrapper
+ Irssi::current_theme->format_expand(
+ shift,
+ (
+ Irssi::EXPAND_FLAG_IGNORE_REPLACES
+ |
+ ($_[0]?0:Irssi::EXPAND_FLAG_IGNORE_EMPTY)
+ )
+ )
+}
+sub sb_expand { # expand {format }s (and apply parse_special for $vars)
+ ir_parse_special(
+ sb_ctfe(shift)
+ )
+}
+sub sb_strip {
+ ir_strip_codes(
+ sb_expand(shift)
+ ); # does this get us the actual length of that s*ty bar :P ?
+}
+sub sb_length {
+ # unicode cludge, d*mn broken Irssi
+ # screw it, this will fail from broken joining anyway (and cause warnings)
+ my $term_type = 'term_type';
+ if (Irssi::version > 20040819) { # this is probably wrong, but I don't know
+ # when the setting name got changed
+ $term_type = 'term_charset';
+ }
+ #if (lc Irssi::settings_get_str($term_type) eq '8bit'
+ # or Irssi::settings_get_str($term_type) =~ /^iso/i
+ #) {
+ # length(sb_strip(shift))
+ #}
+ #else {
+ my $temp = sb_strip(shift);
+ # try to get the displayed width
+ my $length;
+ eval {
+ require Text::CharWidth;
+ $length = Text::CharWidth::mbswidth($temp);
+ };
+ unless ($@) {
+ return $length;
+ }
+ else {
+ if (lc Irssi::settings_get_str($term_type) eq 'utf-8') {
+ # try to switch on utf8
+ eval {
+ no warnings;
+ require Encode;
+ #$temp = Encode::decode_utf8($temp); # thanks for the hint, but I have my
+ # # reasons for _utf8_on
+ Encode::_utf8_on($temp);
+ };
+ }
+ # there is nothing more I can do
+ length($temp)
+ }
+ #}
+}
+
+# !!! G*DD*MN Irssi is adding an additional layer of backslashitis per { } layer
+# !!! AND I still don't know what I need to escape.
+# !!! and NOONE else seems to know or care either.
+# !!! f*ck open source. I mean it.
+# XXX any Irssi::print debug statement leads to SEGFAULT - why ?
+
+# major parts of the idea by buu (#perl @ freenode)
+# thanks to fxn and Somni for debugging
+# while ($_[0] =~ /(.)/g) {
+# my $c = $1; # XXX sooo... goto kills $1
+# if ($q eq '%') { goto ESC; }
+
+## <freenode:#perl:tybalt89> s/%(.)|(\{)|(\})|(\\|\$)/$1?$1:$2?($level++,$2):$3?($level>$min_level&&$level--,$3):'\\'x(2**$level-1).$4/ge; # untested...
+sub ir_escape {
+ my $min_level = $_[1] || 0; my $level = $min_level;
+ my $o = shift;
+ $o =~ s/
+ ( %. ) | # $1
+ ( \{ ) | # $2
+ ( \} ) | # $3
+ ( \\ ) | # $4
+ ( \$(?=[^\\]) ) | # $5
+ ( \$ ) # $6
+ /
+ if ($1) { $1 } # %. escape
+ elsif ($2) { $level++; $2 } # { nesting start
+ elsif ($3) { if ($level > $min_level) { $level--; } $3 } # } nesting end
+ elsif ($4) { '\\'x(2**$level) } # \ needs \\escaping
+ elsif ($5) { '\\'x(2**$level-1) . '$' . '\\'x(2**$level-1) } # and $ needs even more because of "parse_special"
+ else { '\\'x(2**$level-1) . '$' } # $ needs \$ escaping
+ /gex;
+ $o
+}
+#sub ir_escape {
+# my $min_level = $_[1] || 0; my $level = $min_level;
+# my $o = shift;
+# $o =~ s/
+# ( %. ) | # $1
+# ( \{ ) | # $2
+# ( \} ) | # $3
+# ( \\ | \$ ) # $4
+# /
+# if ($1) { $1 } # %. escape
+# elsif ($2) { $level++; $2 } # { nesting start
+# elsif ($3) { if ($level > $min_level) { $level--; } $3 } # } nesting end
+# else { '\\'x(2**($level-1)-1) . $4 } # \ or $ needs \\escaping
+# /gex;
+# $o
+#}
+
+sub ir_fe { # try to fix format stuff
+ my $x = shift;
+ # XXX why do I have to use two/four % here instead of one/two ??
+ # answer: you screwed up in ir_escape
+ $x =~ s/([%{}])/%$1/g;
+ #$x =~ s/(\\|\$|[ ])/\\$1/g; # XXX HOW CAN I HANDLE THE SPACES CORRECTLY XXX
+ $x =~ s/(\\|\$)/\\$1/g;
+ #$x =~ s/(\$(?=.))|(\$)/$1?"\\\$\\":"\\\$"/ge; # I think this should be here
+ # # (logic), but it doesn't work
+ # # that way :P
+ #$x =~ s/\\/\\\\/g; # that's right, escape escapes
+ $x
+}
+sub ir_ve { # escapes special vars but leave colours alone
+ my $x = shift;
+ #$x =~ s/([%{}])/%$1/g;
+ $x =~ s/(\\|\$|[ ])/\\$1/g;
+ $x
+}
+
+my %ansi_table;
+{
+ my ($i, $j, $k) = (0, 0, 0);
+ %ansi_table = (
+ # fe-common::core::formats.c:format_expand_styles
+ # do format_backs
+ (map { $_ => $terminfo->setab($i++) } (split //, '01234567' )),
+ # do format_fores
+ (map { $_ => $terminfo->setaf($j++) } (split //, 'krgybmcw' )),
+ # do bold_fores
+ (map { $_ => $terminfo->bold() .
+ $terminfo->setaf($k++) } (split //, 'KRGYBMCW')),
+ # reset
+ #(map { $_ => $terminfo->op() } (split //, 'nN')),
+ (map { $_ => $terminfo->op() } (split //, 'n')),
+ (map { $_ => "\033[0m" } (split //, 'N')), # XXX quick and DIRTY
+ # flash/bright
+ F => $terminfo->blink(),
+ # reverse
+ 8 => $terminfo->rev(),
+ # bold
+ (map { $_ => $terminfo->bold() } (split //, '9_')),
+ # delete other stuff
+ (map { $_ => '' } (split //, ':|>#[')),
+ # escape
+ (map { $_ => $_ } (split //, '{}%')),
+ )
+}
+sub formats_to_ansi_basic {
+ my $o = shift;
+ $o =~ s/(%(.))/exists $ansi_table{$2} ? $ansi_table{$2} : $1/gex;
+ $o
+}
+
+sub lc1459 ($) { my $x = shift; $x =~ y/A-Z][\^/a-z}{|~/; $x }
+Irssi::settings_add_str(setc, 'banned_channels', '');
+Irssi::settings_add_bool(setc, 'banned_channels_on', 0);
+my %banned_channels = map { lc1459($_) => undef }
+split ' ', Irssi::settings_get_str('banned_channels');
+Irssi::settings_add_str(setc, 'fancy_abbrev', 'fancy');
+
+# }}}
+
+# {{{ main
+
+sub remake () {
+ #$callcount++;
+ #my $xx = $callcount; Irssi::print("starting remake [ $xx ]");
+ my ($hilight, $number, $display);
+ my $separator = '{sb_act_sep ' . Irssi::settings_get_str(set 'separator') .
+ '}';
+ my $custSort = Irssi::settings_get_str(set 'sort');
+ my $custSortDir = 1;
+ if ($custSort =~ /^[-!](.*)/) {
+ $custSortDir = -1;
+ $custSort = $1;
+ }
+
+ my @wins =
+ sort {
+ (
+ ( (int($a->{$custSort}) <=> int($b->{$custSort})) * $custSortDir )
+ ||
+ ($a->{'refnum'} <=> $b->{'refnum'})
+ )
+ } Irssi::windows;
+ my $block = Irssi::settings_get_int(set 'block');
+ my $columns = $currentColumns;
+ my $oldActString = $actString if $SCREEN_MODE;
+ $actString = $SCREEN_MODE ? [' A W L'] : [];
+ my $line = $SCREEN_MODE ? 1 : 0;
+ my $width = $SCREEN_MODE
+ ?
+ $screenWidth - abs($block)*$columns + 1
+ :
+ ([Irssi::windows]->[0]{'width'} - sb_length('{sb x}'));
+ my $height = $screenHeight - abs(Irssi::settings_get_int(set
+ 'height_adjust'));
+ my ($numPad, $keyPad) = (0, 0);
+ my %abbrevList;
+ if ($SCREEN_MODE or Irssi::settings_get_bool(set 'sbar_maxlength')
+ or ($block < 0)
+ ) {
+ %abbrevList = ();
+ if (Irssi::settings_get_str('fancy_abbrev') !~ /^(no|off|head)/i) {
+ my @nameList = map { ref $_ ? $_->get_active_name : '' } @wins;
+ for (my $i = 0; $i < @nameList - 1; ++$i) {
+ my ($x, $y) = ($nameList[$i], $nameList[$i + 1]);
+ for ($x, $y) { s/^[+#!=]// }
+ my $res = Algorithm::LCSS::LCSS($x, $y);
+ if (defined $res) {
+ #Irssi::print("common pattern $x $y : $res");
+ #Irssi::print("found at $nameList[$i] ".index($nameList[$i],
+ # $res));
+ $abbrevList{$nameList[$i]} = int (index($nameList[$i], $res) +
+ (length($res) / 2));
+ #Irssi::print("found at ".$nameList[$i+1]." ".index($nameList[$i+1],
+ # $res));
+ $abbrevList{$nameList[$i+1]} = int (index($nameList[$i+1], $res) +
+ (length($res) / 2));
+ }
+ }
+ }
+ if ($SCREEN_MODE or ($block < 0)) {
+ $numPad = length((sort { length($b) <=> length($a) } keys %keymap)[0]);
+ $keyPad = length((sort { length($b) <=> length($a) } values %keymap)[0]);
+ }
+ }
+ if ($SCREEN_MODE) {
+ print STDERR $screenansi->dcs().
+ $terminfo->civis().
+ $terminfo->sc().
+ $screenansi->st();
+ if (@$oldActString < 1) {
+ print STDERR $screenansi->dcs().
+ $terminfo->cup(0, $width).
+ $actString->[0].
+ $terminfo->el().
+ $screenansi->st();
+ }
+ }
+ foreach my $win (@wins) {
+ unless ($SCREEN_MODE) {
+ $actString->[$line] = '' unless defined $actString->[$line]
+ or Irssi::settings_get_bool(set 'all_disable');
+ }
+
+ # all stolen from chanact, what does this code do and why do we need it ?
+ !ref($win) && next;
+
+ my $name = $win->get_active_name;
+ $name = '*' if (Irssi::settings_get_bool('banned_channels_on') and exists
+ $banned_channels{lc1459($name)});
+ $name = $win->{'name'} if $name ne '*' and $win->{'name'} ne ''
+ and Irssi::settings_get_bool(set 'prefer_name');
+ my $active = $win->{'active'};
+ my $colour = $win->{'hilight_color'};
+ if (!defined $colour) { $colour = ''; }
+
+ if ($win->{'data_level'} < Irssi::settings_get_int(set 'hide_data')) {
+ next; } # for Geert
+ if ($win->{'data_level'} == 0) { $hilight = '{sb_act_none '; }
+ elsif ($win->{'data_level'} == 1) { $hilight = '{sb_act_text '; }
+ elsif ($win->{'data_level'} == 2) { $hilight = '{sb_act_msg '; }
+ elsif ($colour ne '') { $hilight = "{sb_act_hilight_color $colour "; }
+ elsif ($win->{'data_level'} == 3) { $hilight = '{sb_act_hilight '; }
+ else { $hilight = '{sb_act_special '; }
+
+ $number = $win->{'refnum'};
+ my @display = ('display_nokey');
+ if (defined $keymap{$number} and $keymap{$number} ne '') {
+ unshift @display, map { (my $cpy = $_) =~ s/_no/_/; $cpy } @display;
+ }
+ if (Irssi::active_win->{'refnum'} == $number) {
+ unshift @display, map { my $cpy = $_; $cpy .= '_active'; $cpy } @display;
+ }
+ #Irssi::print("win $number [@display]: " . join '.', split //, join '<<', map {
+ # Irssi::settings_get_str(set $_) } @display);
+ $display = (grep { $_ }
+ map { Irssi::settings_get_str(set $_) }
+ @display)[0];
+ #Irssi::print("win $number : " . join '.', split //, $display);
+
+ if ($SCREEN_MODE or Irssi::settings_get_bool(set 'sbar_maxlength')
+ or ($block < 0)
+ ) {
+ my $baseLength = sb_length(ir_escape(ir_ve(ir_parse_special_protected(sb_ctfe(
+ '{sb_background}' . expand($display,
+ C => ir_fe('x'),
+ N => $number . (' 'x($numPad - length($number))),
+ Q => ir_fe((' 'x($keyPad - length($keymap{$number}))) . $keymap{$number}),
+ H => $hilight,
+ S => '}{sb_background}'
+ ), 1), $win)))) - 1;
+ my $diff = abs($block) - (length($name) + $baseLength);
+ if ($diff < 0) { # too long
+ if (abs($diff) >= length($name)) { $name = '' } # forget it
+ elsif (abs($diff) + 1 >= length($name)) { $name = substr($name,
+ 0, 1); }
+ else {
+ my $middle = exists $abbrevList{$name} ?
+ (($abbrevList{$name} + (2*(length($name) / 2)))/3) :
+ ((Irssi::settings_get_str('fancy_abbrev') =~ /^head/i) ?
+ length($name) :
+ (length($name) / 2));
+ my $cut = int($middle - (abs($diff) / 2) + .55);
+ $cut = 1 if $cut < 1;
+ $cut = length($name) - abs($diff) - 1 if $cut > (length($name) -
+ abs($diff) - 1);
+ $name = substr($name, 0, $cut) . '~' . substr($name, $cut +
+ abs($diff) + 1);
+ }
+ }
+ elsif ($SCREEN_MODE or ($block < 0)) {
+ $name .= (' ' x $diff);
+ }
+ }
+
+ my $add = ir_ve(ir_parse_special_protected(sb_ctfe('{sb_background}' . expand($display,
+ C => ir_fe($name),
+ N => $number . (' 'x($numPad - length($number))),
+ Q => ir_fe((' 'x($keyPad - length($keymap{$number}))) . $keymap{$number}),
+ H => $hilight,
+ S => '}{sb_background}'
+ ), 1), $win));
+ if ($SCREEN_MODE) {
+ $actString->[$line] = $add;
+ if ((!defined $oldActString->[$line]
+ or $oldActString->[$line] ne $actString->[$line])
+ and
+ $line <= ($columns * $height)
+ ) {
+ print STDERR $screenansi->dcs().
+ $terminfo->cup(($line-1) % $height+1, $width + (
+ abs($block) * int(($line-1) / $height))).
+ formats_to_ansi_basic(sb_expand(ir_escape($actString->[$line]))).
+ #$terminfo->el().
+ $screenansi->st();
+ }
+ $line++;
+ }
+ else {
+ #$temp =~ s/\{\S+?(?:\s(.*?))?\}/$1/g;
+ #$temp =~ s/\\\\\\\\/\\/g; # XXX I'm actually guessing here, someone point me
+ # # XXX to docs please
+ $actString->[$line] = '' unless defined $actString->[$line];
+
+ # XXX how can I check whether the content still fits in the bar? this would
+ # XXX allow awlstatus to reside on a statusbar together with other items...
+ if (sb_length(ir_escape($actString->[$line] . $add)) >= $width) {
+ # XXX doesn't correctly handle utf-8 multibyte ... help !!?
+ $actString->[$line] .= ' ' x ($width - sb_length(ir_escape(
+ $actString->[$line])));
+ $line++;
+ }
+ $actString->[$line] .= $add . $separator;
+ # XXX if I use these prints, output layout gets screwed up... why ?
+ #Irssi::print("line $line: ".$actString->[$line]);
+ #Irssi::print("temp $line: ".$temp);
+ }
+ }
+
+ if ($SCREEN_MODE) {
+ while ($line <= ($columns * $height)) {
+ print STDERR $screenansi->dcs().
+ $terminfo->cup(($line-1) % $height+1, $width + (
+ abs($block) * int(($line-1) / $height))).
+ $terminfo->el().
+ $screenansi->st();
+ $line++;
+ }
+ print STDERR $screenansi->dcs().
+ $terminfo->rc().
+ $terminfo->cnorm().
+ $screenansi->st();
+ }
+ else {
+ # XXX the Irssi::print statements lead to the MOST WEIRD results
+ # e.g.: the loop gets executed TWICE for p > 0 ?!?
+ for (my $p = 0; $p < @$actString; $p++) { # wrap each line in {sb }, escape it
+ my $x = $actString->[$p]; # properly, etc.
+ $x =~ s/\Q$separator\E([ ]*)$/$1/;
+ #Irssi::print("[$p]".'current:'.join'.',split//,sb_strip(ir_escape($x,0)));
+ #Irssi::print("assumed length before:".sb_length(ir_escape($x,0)));
+ $x = "{sb $x}";
+ #Irssi::print("[$p]".'new:'.join'.',split//,sb_expand(ir_escape($x,0)));
+ #Irssi::print("[$p]".'new:'.join'.',split//,ir_escape($x,0));
+ #Irssi::print("assumed length after:".sb_length(ir_escape($x,0)));
+ $x = ir_escape($x);
+ #Irssi::print("[$p]".'REALnew:'.join'.',split//,sb_strip($x));
+ $actString->[$p] = $x;
+ # XXX any Irssi::print debug statement leads to SEGFAULT (sometimes) - why ?
+ }
+ }
+ #Irssi::print("remake [ $xx ] finished");
+}
+
+sub awlHasChanged () {
+ $globTime = undef;
+ my $temp = ($SCREEN_MODE ?
+ "\\\n" . Irssi::settings_get_int(set 'block').
+ Irssi::settings_get_int(set 'height_adjust')
+ : "!\n" . Irssi::settings_get_str(set 'placement').
+ Irssi::settings_get_int(set 'position')).
+ Irssi::settings_get_str(set 'automode');
+ if ($temp ne $resetNeeded) { wlreset(); return; }
+ #Irssi::print("awl has changed, calls to remake so far: $callcount");
+ $needRemake = 1;
+
+ #remake();
+ if (
+ ($SCREEN_MODE and !$DISABLE_SCREEN_TEMP)
+ or
+ ($needRemake and Irssi::settings_get_bool(set 'all_disable'))
+ or
+ (!Irssi::settings_get_bool(set 'all_disable') and $currentLines < 1)
+ ) {
+ $needRemake = undef;
+ remake();
+ }
+
+ unless ($SCREEN_MODE) {
+ # XXX Irssi crashes if I try to do this without timer, why ? What's the minimum
+ # XXX delay I need to use in the timer ?
+ Irssi::timeout_add_once(100, 'syncLines', undef);
+
+ for (keys %statusbars) {
+ Irssi::statusbar_items_redraw(set$_);
+ }
+ }
+ else {
+ Irssi::timeout_add_once(100, 'syncColumns', undef);
+ }
+}
+
+sub eventChanged () { # Implement a change queue/blocker -.-)
+ if (defined $globTime) {
+ Irssi::timeout_remove($globTime);
+ } # delay the update further
+ $globTime = Irssi::timeout_add_once(GLOB_QUEUE_TIMER, 'awlHasChanged', undef);
+}
+
+# }}}
+
+
+# {{{ screen mode
+
+sub screenFullRedraw {
+ my ($window) = @_;
+ if (!ref $window or $window->{'refnum'} == Irssi::active_win->{'refnum'}) {
+ $actString = [];
+ eventChanged();
+ }
+}
+
+sub screenSize { # from nicklist.pl
+ $screenResizing = 1;
+ # fit screen
+ system 'screen -x '.$ENV{'STY'}.' -X fit';
+ # get size
+ my ($row, $col) = split ' ', `stty size`;
+ # set screen width
+ $screenWidth = $col-1;
+ $screenHeight = $row-1;
+
+ # on some recent systems, "screen -X fit; screen -X width -w 50" doesn't work, needs a sleep in between the 2 commands
+ # so we wait a second before setting the width
+ Irssi::timeout_add_once(100, sub {
+ my ($new_irssi_width) = @_;
+ $new_irssi_width -= abs(Irssi::settings_get_int(set
+ 'block'))*$currentColumns - 1;
+ system 'screen -x '.$ENV{'STY'}.' -X width -w ' . $new_irssi_width;
+ # and then we wait another second for the resizing, and then redraw.
+ Irssi::timeout_add_once(10,sub {$screenResizing = 0; screenFullRedraw()}, []);
+ }, $screenWidth);
+}
+
+sub screenOff {
+ my ($unloadMode) = @_;
+ Irssi::signal_remove('gui print text finished' => 'screenFullRedraw');
+ Irssi::signal_remove('gui page scrolled' => 'screenFullRedraw');
+ Irssi::signal_remove('window changed' => 'screenFullRedraw');
+ Irssi::signal_remove('window changed automatic' => 'screenFullRedraw');
+ if ($unloadMode) {
+ Irssi::signal_remove('terminal resized' => 'resizeTerm');
+ }
+ system 'screen -x '.$ENV{'STY'}.' -X fit';
+}
+
+sub syncColumns {
+ return if (@$actString == 0);
+ my $temp = $currentColumns;
+ #Irssi::print("current columns $temp");
+ my $height = $screenHeight - abs(Irssi::settings_get_int(set
+ 'height_adjust'));
+ $currentColumns = int(($#$actString-1) / $height) + 1;
+ #Irssi::print("objects in actstring:".scalar(@$actString).", screen height:".
+ # $height);
+ my $currMaxColumns = Irssi::settings_get_int(set 'columns');
+ if ($currMaxColumns > 0 and $currentColumns > $currMaxColumns) {
+ $currentColumns = $currMaxColumns;
+ }
+ elsif ($currMaxColumns < 0) {
+ $currentColumns = abs($currMaxColumns);
+ }
+ return if ($temp == $currentColumns);
+ screenSize();
+}
+
+#$needRemake = 1;
+sub resizeTerm () {
+ if ($SCREEN_MODE and !$screenResizing) {
+ $screenResizing = 1;
+ Irssi::timeout_add_once(10, 'screenSize', undef);
+ }
+ Irssi::timeout_add_once(100, 'eventChanged', undef);
+}
+
+# }}}
+
+
+# {{{ settings add
+
+Irssi::settings_add_str(setc, set 'display_nokey', '[$N]$H$C$S');
+Irssi::settings_add_str(setc, set 'display_key', '[$Q=$N]$H$C$S');
+Irssi::settings_add_str(setc, set 'display_nokey_active', '');
+Irssi::settings_add_str(setc, set 'display_key_active', '');
+Irssi::settings_add_str(setc, set 'separator', "\\ ");
+Irssi::settings_add_bool(setc, set 'prefer_name', 0);
+Irssi::settings_add_int(setc, set 'hide_data', 0);
+Irssi::settings_add_int(setc, set 'maxlines', 9);
+Irssi::settings_add_int(setc, set 'columns', 1);
+Irssi::settings_add_int(setc, set 'block', 20);
+Irssi::settings_add_bool(setc, set 'sbar_maxlength', 0);
+Irssi::settings_add_int(setc, set 'height_adjust', 2);
+Irssi::settings_add_str(setc, set 'sort', 'refnum');
+Irssi::settings_add_str(setc, set 'placement', 'bottom');
+Irssi::settings_add_int(setc, set 'position', 0);
+Irssi::settings_add_bool(setc, set 'all_disable', 0);
+Irssi::settings_add_str(setc, set 'automode', 'sbar');
+
+# }}}
+
+
+# {{{ init
+
+sub wlreset {
+ $actString = [];
+ $currentLines = 0; # 1; # mhmmmm .. we actually enable one line down there so
+ # let's try this.
+ #update_keymap();
+ killOldStatus();
+ # Register statusbar
+ #add_statusbar(0);
+ #Irssi::command('statusbar wl0 enable');
+ my $was_screen_mode = $SCREEN_MODE;
+ if ($SCREEN_MODE = (Irssi::settings_get_str(set 'automode') =~ /screen/i)
+ and
+ !$was_screen_mode
+ ) {
+ if (!defined $ENV{'STY'}) {
+ Irssi::print('Screen mode can only be used in GNU screen but no '.
+ 'screen was found.', MSGLEVEL_CLIENTERROR);
+ $SCREEN_MODE = undef;
+ }
+ else {
+ Irssi::signal_add_last('gui print text finished' => 'screenFullRedraw');
+ Irssi::signal_add_last('gui page scrolled' => 'screenFullRedraw');
+ Irssi::signal_add('window changed' => 'screenFullRedraw');
+ Irssi::signal_add('window changed automatic' => 'screenFullRedraw');
+ }
+ }
+ elsif ($was_screen_mode and !$SCREEN_MODE) {
+ screenOff();
+ }
+ $resetNeeded = ($SCREEN_MODE ?
+ "\\\n" . Irssi::settings_get_int(set 'block').
+ Irssi::settings_get_int(set 'height_adjust')
+ : "!\n" . Irssi::settings_get_str(set 'placement').
+ Irssi::settings_get_int(set 'position')).
+ Irssi::settings_get_str(set 'automode');
+ resizeTerm();
+}
+
+wlreset();
+
+# }}}
+
+
+# {{{ unload/deinit
+
+my $Unload;
+sub unload ($$$) {
+ $Unload = 1;
+ # pretend we didn't do anything ASAP
+ Irssi::timeout_add_once(10, sub { $Unload = undef; }, undef);
+}
+# last try to catch a sigsegv
+Irssi::signal_add_first('gui exit' => sub { $Unload = undef; });
+sub UNLOAD {
+ # this might well crash Irssi... try /eval /script unload someotherscript ;
+ # /quit (= SEGFAULT !)
+ if ($Unload) {
+ $actString = ['']; # syncLines(); # XXX Irssi crashes when trying to disable
+ killOldStatus(); # XXX all statusbars ?
+ if ($SCREEN_MODE) {
+ screenOff('unload mode');
+ }
+ }
+}
+
+# }}}
+
+
+# {{{ signals
+
+sub addPrintTextHook { # update on print text
+ return if $_[0]->{'level'} == 262144 and $_[0]->{'target'} eq ''
+ and !defined($_[0]->{'server'});
+ if (Irssi::settings_get_str(set 'sort') =~ /^[-!]?last_line$/) {
+ Irssi::timeout_add_once(100, 'eventChanged', undef);
+ }
+}
+
+#sub _x { my ($x, $y) = @_; ($x, sub { Irssi::print('-->signal '.$x); eval "$y();"; }) }
+#sub _x { @_ }
+Irssi::signal_add_first(
+ 'command script unload' => 'unload'
+);
+Irssi::signal_add_last({
+ 'setup changed' => 'eventChanged',
+ 'print text' => 'addPrintTextHook',
+ 'terminal resized' => 'resizeTerm',
+ 'setup reread' => 'wlreset',
+ 'window hilight' => 'eventChanged',
+});
+Irssi::signal_add({
+ 'window created' => 'eventChanged',
+ 'window destroyed' => 'eventChanged',
+ 'window name changed' => 'eventChanged',
+ 'window refnum changed' => 'eventChanged',
+ 'window changed' => 'eventChanged',
+ 'window changed automatic' => 'eventChanged',
+});
+
+#Irssi::signal_add('nick mode changed', 'chanactHasChanged'); # relicts
+
+# }}}
+
+# {{{ commands
+
+
+sub runsub {
+ my ($cmd) = @_;
+ sub {
+ my ($data, $server, $item) = @_;
+ Irssi::command_runsub($cmd, $data, $server, $item);
+ };
+}
+Irssi::command_bind( setc() => runsub(setc()) );
+Irssi::command_bind( setc() . ' paste' => runsub(setc() . ' paste') );
+Irssi::command_bind(
+ setc() . ' paste on' => sub {
+ return unless $SCREEN_MODE;
+ my $was_disabled = $DISABLE_SCREEN_TEMP;
+ $DISABLE_SCREEN_TEMP = 1;
+ Irssi::print('Paste mode is now ON, '.uc(setc()).' is temporarily '.
+ 'disabled.');
+ if (!$was_disabled) {
+ $screenResizing = 1;
+ screenOff();
+ }
+ }
+);
+Irssi::command_bind(
+ setc() . ' paste off' => sub {
+ return unless $SCREEN_MODE;
+ my $was_disabled = $DISABLE_SCREEN_TEMP;
+ $DISABLE_SCREEN_TEMP = undef;
+ Irssi::print('Paste mode is now OFF, '.uc(setc()).' is enabled.');
+ if ($was_disabled) {
+ $SCREEN_MODE = undef;
+ $screenResizing = 0;
+ wlreset();
+ }
+ }
+);
+Irssi::command_bind(
+ setc() . ' paste toggle' => sub {
+ if ($DISABLE_SCREEN_TEMP) {
+ Irssi::command(setc() . ' paste off');
+ }
+ else {
+ Irssi::command(setc() . ' paste on');
+ }
+ }
+);
+Irssi::command_bind(
+ setc() . ' redraw' => sub {
+ return unless $SCREEN_MODE;
+ screenFullRedraw();
+ }
+);
+
+
+# }}}
+
+# {{{ Algorithm::LCSS module
+{
+ package Algorithm::Diff;
+ # Skip to first "=head" line for documentation.
+ use strict;
+
+ use integer; # see below in _replaceNextLargerWith() for mod to make
+ # if you don't use this
+
+ # McIlroy-Hunt diff algorithm
+ # Adapted from the Smalltalk code of Mario I. Wolczko, <mario@wolczko.com>
+ # by Ned Konz, perl@bike-nomad.com
+ # Updates by Tye McQueen, http://perlmonks.org/?node=tye
+
+ # Create a hash that maps each element of $aCollection to the set of
+ # positions it occupies in $aCollection, restricted to the elements
+ # within the range of indexes specified by $start and $end.
+ # The fourth parameter is a subroutine reference that will be called to
+ # generate a string to use as a key.
+ # Additional parameters, if any, will be passed to this subroutine.
+ #
+ # my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen );
+
+ sub _withPositionsOfInInterval
+ {
+ my $aCollection = shift; # array ref
+ my $start = shift;
+ my $end = shift;
+ my $keyGen = shift;
+ my %d;
+ my $index;
+ for ( $index = $start ; $index <= $end ; $index++ )
+ {
+ my $element = $aCollection->[$index];
+ my $key = &$keyGen( $element, @_ );
+ if ( exists( $d{$key} ) )
+ {
+ unshift ( @{ $d{$key} }, $index );
+ }
+ else
+ {
+ $d{$key} = [$index];
+ }
+ }
+ return wantarray ? %d : \%d;
+ }
+
+ # Find the place at which aValue would normally be inserted into the
+ # array. If that place is already occupied by aValue, do nothing, and
+ # return undef. If the place does not exist (i.e., it is off the end of
+ # the array), add it to the end, otherwise replace the element at that
+ # point with aValue. It is assumed that the array's values are numeric.
+ # This is where the bulk (75%) of the time is spent in this module, so
+ # try to make it fast!
+
+ sub _replaceNextLargerWith
+ {
+ my ( $array, $aValue, $high ) = @_;
+ $high ||= $#$array;
+
+ # off the end?
+ if ( $high == -1 || $aValue > $array->[-1] )
+ {
+ push ( @$array, $aValue );
+ return $high + 1;
+ }
+
+ # binary search for insertion point...
+ my $low = 0;
+ my $index;
+ my $found;
+ while ( $low <= $high )
+ {
+ $index = ( $high + $low ) / 2;
+
+ # $index = int(( $high + $low ) / 2); # without 'use integer'
+ $found = $array->[$index];
+
+ if ( $aValue == $found )
+ {
+ return undef;
+ }
+ elsif ( $aValue > $found )
+ {
+ $low = $index + 1;
+ }
+ else
+ {
+ $high = $index - 1;
+ }
+ }
+
+ # now insertion point is in $low.
+ $array->[$low] = $aValue; # overwrite next larger
+ return $low;
+ }
+
+ # This method computes the longest common subsequence in $a and $b.
+
+ # Result is array or ref, whose contents is such that
+ # $a->[ $i ] == $b->[ $result[ $i ] ]
+ # foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined.
+
+ # An additional argument may be passed; this is a hash or key generating
+ # function that should return a string that uniquely identifies the given
+ # element. It should be the case that if the key is the same, the elements
+ # will compare the same. If this parameter is undef or missing, the key
+ # will be the element as a string.
+
+ # By default, comparisons will use "eq" and elements will be turned into keys
+ # using the default stringizing operator '""'.
+
+ # Additional parameters, if any, will be passed to the key generation
+ # routine.
+
+ sub _longestCommonSubsequence
+ {
+ my $a = shift; # array ref or hash ref
+ my $b = shift; # array ref or hash ref
+ my $counting = shift; # scalar
+ my $keyGen = shift; # code ref
+ my $compare; # code ref
+
+ if ( ref($a) eq 'HASH' )
+ { # prepared hash must be in $b
+ my $tmp = $b;
+ $b = $a;
+ $a = $tmp;
+ }
+
+ # Check for bogus (non-ref) argument values
+ if ( !ref($a) || !ref($b) )
+ {
+ my @callerInfo = caller(1);
+ die 'error: must pass array or hash references to ' . $callerInfo[3];
+ }
+
+ # set up code refs
+ # Note that these are optimized.
+ if ( !defined($keyGen) ) # optimize for strings
+ {
+ $keyGen = sub { $_[0] };
+ $compare = sub { my ( $a, $b ) = @_; $a eq $b };
+ }
+ else
+ {
+ $compare = sub {
+ my $a = shift;
+ my $b = shift;
+ &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ );
+ };
+ }
+
+ my ( $aStart, $aFinish, $matchVector ) = ( 0, $#$a, [] );
+ my ( $prunedCount, $bMatches ) = ( 0, {} );
+
+ if ( ref($b) eq 'HASH' ) # was $bMatches prepared for us?
+ {
+ $bMatches = $b;
+ }
+ else
+ {
+ my ( $bStart, $bFinish ) = ( 0, $#$b );
+
+ # First we prune off any common elements at the beginning
+ while ( $aStart <= $aFinish
+ and $bStart <= $bFinish
+ and &$compare( $a->[$aStart], $b->[$bStart], @_ ) )
+ {
+ $matchVector->[ $aStart++ ] = $bStart++;
+ $prunedCount++;
+ }
+
+ # now the end
+ while ( $aStart <= $aFinish
+ and $bStart <= $bFinish
+ and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) )
+ {
+ $matchVector->[ $aFinish-- ] = $bFinish--;
+ $prunedCount++;
+ }
+
+ # Now compute the equivalence classes of positions of elements
+ $bMatches =
+ _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ );
+ }
+ my $thresh = [];
+ my $links = [];
+
+ my ( $i, $ai, $j, $k );
+ for ( $i = $aStart ; $i <= $aFinish ; $i++ )
+ {
+ $ai = &$keyGen( $a->[$i], @_ );
+ if ( exists( $bMatches->{$ai} ) )
+ {
+ $k = 0;
+ for $j ( @{ $bMatches->{$ai} } )
+ {
+
+ # optimization: most of the time this will be true
+ if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j )
+ {
+ $thresh->[$k] = $j;
+ }
+ else
+ {
+ $k = _replaceNextLargerWith( $thresh, $j, $k );
+ }
+
+ # oddly, it's faster to always test this (CPU cache?).
+ if ( defined($k) )
+ {
+ $links->[$k] =
+ [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ];
+ }
+ }
+ }
+ }
+
+ if (@$thresh)
+ {
+ return $prunedCount + @$thresh if $counting;
+ for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] )
+ {
+ $matchVector->[ $link->[1] ] = $link->[2];
+ }
+ }
+ elsif ($counting)
+ {
+ return $prunedCount;
+ }
+
+ return wantarray ? @$matchVector : $matchVector;
+ }
+
+ sub traverse_sequences
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref
+ my $callbacks = shift || {};
+ my $keyGen = shift;
+ my $matchCallback = $callbacks->{'MATCH'} || sub { };
+ my $discardACallback = $callbacks->{'DISCARD_A'} || sub { };
+ my $finishedACallback = $callbacks->{'A_FINISHED'};
+ my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { };
+ my $finishedBCallback = $callbacks->{'B_FINISHED'};
+ my $matchVector = _longestCommonSubsequence( $a, $b, 0, $keyGen, @_ );
+
+ # Process all the lines in @$matchVector
+ my $lastA = $#$a;
+ my $lastB = $#$b;
+ my $bi = 0;
+ my $ai;
+
+ for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ )
+ {
+ my $bLine = $matchVector->[$ai];
+ if ( defined($bLine) ) # matched
+ {
+ &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine;
+ &$matchCallback( $ai, $bi++, @_ );
+ }
+ else
+ {
+ &$discardACallback( $ai, $bi, @_ );
+ }
+ }
+
+ # The last entry (if any) processed was a match.
+ # $ai and $bi point just past the last matching lines in their sequences.
+
+ while ( $ai <= $lastA or $bi <= $lastB )
+ {
+
+ # last A?
+ if ( $ai == $lastA + 1 and $bi <= $lastB )
+ {
+ if ( defined($finishedACallback) )
+ {
+ &$finishedACallback( $lastA, @_ );
+ $finishedACallback = undef;
+ }
+ else
+ {
+ &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB;
+ }
+ }
+
+ # last B?
+ if ( $bi == $lastB + 1 and $ai <= $lastA )
+ {
+ if ( defined($finishedBCallback) )
+ {
+ &$finishedBCallback( $lastB, @_ );
+ $finishedBCallback = undef;
+ }
+ else
+ {
+ &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA;
+ }
+ }
+
+ &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA;
+ &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB;
+ }
+
+ return 1;
+ }
+
+ sub traverse_balanced
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref
+ my $callbacks = shift || {};
+ my $keyGen = shift;
+ my $matchCallback = $callbacks->{'MATCH'} || sub { };
+ my $discardACallback = $callbacks->{'DISCARD_A'} || sub { };
+ my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { };
+ my $changeCallback = $callbacks->{'CHANGE'};
+ my $matchVector = _longestCommonSubsequence( $a, $b, 0, $keyGen, @_ );
+
+ # Process all the lines in match vector
+ my $lastA = $#$a;
+ my $lastB = $#$b;
+ my $bi = 0;
+ my $ai = 0;
+ my $ma = -1;
+ my $mb;
+
+ while (1)
+ {
+
+ # Find next match indices $ma and $mb
+ do {
+ $ma++;
+ } while(
+ $ma <= $#$matchVector
+ && !defined $matchVector->[$ma]
+ );
+
+ last if $ma > $#$matchVector; # end of matchVector?
+ $mb = $matchVector->[$ma];
+
+ # Proceed with discard a/b or change events until
+ # next match
+ while ( $ai < $ma || $bi < $mb )
+ {
+
+ if ( $ai < $ma && $bi < $mb )
+ {
+
+ # Change
+ if ( defined $changeCallback )
+ {
+ &$changeCallback( $ai++, $bi++, @_ );
+ }
+ else
+ {
+ &$discardACallback( $ai++, $bi, @_ );
+ &$discardBCallback( $ai, $bi++, @_ );
+ }
+ }
+ elsif ( $ai < $ma )
+ {
+ &$discardACallback( $ai++, $bi, @_ );
+ }
+ else
+ {
+
+ # $bi < $mb
+ &$discardBCallback( $ai, $bi++, @_ );
+ }
+ }
+
+ # Match
+ &$matchCallback( $ai++, $bi++, @_ );
+ }
+
+ while ( $ai <= $lastA || $bi <= $lastB )
+ {
+ if ( $ai <= $lastA && $bi <= $lastB )
+ {
+
+ # Change
+ if ( defined $changeCallback )
+ {
+ &$changeCallback( $ai++, $bi++, @_ );
+ }
+ else
+ {
+ &$discardACallback( $ai++, $bi, @_ );
+ &$discardBCallback( $ai, $bi++, @_ );
+ }
+ }
+ elsif ( $ai <= $lastA )
+ {
+ &$discardACallback( $ai++, $bi, @_ );
+ }
+ else
+ {
+
+ # $bi <= $lastB
+ &$discardBCallback( $ai, $bi++, @_ );
+ }
+ }
+
+ return 1;
+ }
+
+ sub prepare
+ {
+ my $a = shift; # array ref
+ my $keyGen = shift; # code ref
+
+ # set up code ref
+ $keyGen = sub { $_[0] } unless defined($keyGen);
+
+ return scalar _withPositionsOfInInterval( $a, 0, $#$a, $keyGen, @_ );
+ }
+
+ sub LCS
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref or hash ref
+ my $matchVector = _longestCommonSubsequence( $a, $b, 0, @_ );
+ my @retval;
+ my $i;
+ for ( $i = 0 ; $i <= $#$matchVector ; $i++ )
+ {
+ if ( defined( $matchVector->[$i] ) )
+ {
+ push ( @retval, $a->[$i] );
+ }
+ }
+ return wantarray ? @retval : \@retval;
+ }
+
+ sub LCS_length
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref or hash ref
+ return _longestCommonSubsequence( $a, $b, 1, @_ );
+ }
+
+ sub LCSidx
+ {
+ my $a= shift @_;
+ my $b= shift @_;
+ my $match= _longestCommonSubsequence( $a, $b, 0, @_ );
+ my @am= grep defined $match->[$_], 0..$#$match;
+ my @bm= @{$match}[@am];
+ return \@am, \@bm;
+ }
+
+ sub compact_diff
+ {
+ my $a= shift @_;
+ my $b= shift @_;
+ my( $am, $bm )= LCSidx( $a, $b, @_ );
+ my @cdiff;
+ my( $ai, $bi )= ( 0, 0 );
+ push @cdiff, $ai, $bi;
+ while( 1 ) {
+ while( @$am && $ai == $am->[0] && $bi == $bm->[0] ) {
+ shift @$am;
+ shift @$bm;
+ ++$ai, ++$bi;
+ }
+ push @cdiff, $ai, $bi;
+ last if ! @$am;
+ $ai = $am->[0];
+ $bi = $bm->[0];
+ push @cdiff, $ai, $bi;
+ }
+ push @cdiff, 0+@$a, 0+@$b
+ if $ai < @$a || $bi < @$b;
+ return wantarray ? @cdiff : \@cdiff;
+ }
+
+ sub diff
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref
+ my $retval = [];
+ my $hunk = [];
+ my $discard = sub {
+ push @$hunk, [ '-', $_[0], $a->[ $_[0] ] ];
+ };
+ my $add = sub {
+ push @$hunk, [ '+', $_[1], $b->[ $_[1] ] ];
+ };
+ my $match = sub {
+ push @$retval, $hunk
+ if 0 < @$hunk;
+ $hunk = []
+ };
+ traverse_sequences( $a, $b,
+ { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ );
+ &$match();
+ return wantarray ? @$retval : $retval;
+ }
+
+ sub sdiff
+ {
+ my $a = shift; # array ref
+ my $b = shift; # array ref
+ my $retval = [];
+ my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) };
+ my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) };
+ my $change = sub {
+ push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] );
+ };
+ my $match = sub {
+ push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] );
+ };
+ traverse_balanced(
+ $a,
+ $b,
+ {
+ MATCH => $match,
+ DISCARD_A => $discard,
+ DISCARD_B => $add,
+ CHANGE => $change,
+ },
+ @_
+ );
+ return wantarray ? @$retval : $retval;
+ }
+
+ ########################################
+ my $Root= __PACKAGE__;
+ package Algorithm::Diff::_impl;
+ use strict;
+
+ sub _Idx() { 0 } # $me->[_Idx]: Ref to array of hunk indices
+ # 1 # $me->[1]: Ref to first sequence
+ # 2 # $me->[2]: Ref to second sequence
+ sub _End() { 3 } # $me->[_End]: Diff between forward and reverse pos
+ sub _Same() { 4 } # $me->[_Same]: 1 if pos 1 contains unchanged items
+ sub _Base() { 5 } # $me->[_Base]: Added to range's min and max
+ sub _Pos() { 6 } # $me->[_Pos]: Which hunk is currently selected
+ sub _Off() { 7 } # $me->[_Off]: Offset into _Idx for current position
+ sub _Min() { -2 } # Added to _Off to get min instead of max+1
+
+ sub Die
+ {
+ require Carp;
+ Carp::confess( @_ );
+ }
+
+ sub _ChkPos
+ {
+ my( $me )= @_;
+ return if $me->[_Pos];
+ my $meth= ( caller(1) )[3];
+ Die( "Called $meth on 'reset' object" );
+ }
+
+ sub _ChkSeq
+ {
+ my( $me, $seq )= @_;
+ return $seq + $me->[_Off]
+ if 1 == $seq || 2 == $seq;
+ my $meth= ( caller(1) )[3];
+ Die( "$meth: Invalid sequence number ($seq); must be 1 or 2" );
+ }
+
+ sub getObjPkg
+ {
+ my( $us )= @_;
+ return ref $us if ref $us;
+ return $us . "::_obj";
+ }
+
+ sub new
+ {
+ my( $us, $seq1, $seq2, $opts ) = @_;
+ my @args;
+ for( $opts->{keyGen} ) {
+ push @args, $_ if $_;
+ }
+ for( $opts->{keyGenArgs} ) {
+ push @args, @$_ if $_;
+ }
+ my $cdif= Algorithm::Diff::compact_diff( $seq1, $seq2, @args );
+ my $same= 1;
+ if( 0 == $cdif->[2] && 0 == $cdif->[3] ) {
+ $same= 0;
+ splice @$cdif, 0, 2;
+ }
+ my @obj= ( $cdif, $seq1, $seq2 );
+ $obj[_End] = (1+@$cdif)/2;
+ $obj[_Same] = $same;
+ $obj[_Base] = 0;
+ my $me = bless \@obj, $us->getObjPkg();
+ $me->Reset( 0 );
+ return $me;
+ }
+
+ sub Reset
+ {
+ my( $me, $pos )= @_;
+ $pos= int( $pos || 0 );
+ $pos += $me->[_End]
+ if $pos < 0;
+ $pos= 0
+ if $pos < 0 || $me->[_End] <= $pos;
+ $me->[_Pos]= $pos || !1;
+ $me->[_Off]= 2*$pos - 1;
+ return $me;
+ }
+
+ sub Base
+ {
+ my( $me, $base )= @_;
+ my $oldBase= $me->[_Base];
+ $me->[_Base]= 0+$base if defined $base;
+ return $oldBase;
+ }
+
+ sub Copy
+ {
+ my( $me, $pos, $base )= @_;
+ my @obj= @$me;
+ my $you= bless \@obj, ref($me);
+ $you->Reset( $pos ) if defined $pos;
+ $you->Base( $base );
+ return $you;
+ }
+
+ sub Next {
+ my( $me, $steps )= @_;
+ $steps= 1 if ! defined $steps;
+ if( $steps ) {
+ my $pos= $me->[_Pos];
+ my $new= $pos + $steps;
+ $new= 0 if $pos && $new < 0;
+ $me->Reset( $new )
+ }
+ return $me->[_Pos];
+ }
+
+ sub Prev {
+ my( $me, $steps )= @_;
+ $steps= 1 if ! defined $steps;
+ my $pos= $me->Next(-$steps);
+ $pos -= $me->[_End] if $pos;
+ return $pos;
+ }
+
+ sub Diff {
+ my( $me )= @_;
+ $me->_ChkPos();
+ return 0 if $me->[_Same] == ( 1 & $me->[_Pos] );
+ my $ret= 0;
+ my $off= $me->[_Off];
+ for my $seq ( 1, 2 ) {
+ $ret |= $seq
+ if $me->[_Idx][ $off + $seq + _Min ]
+ < $me->[_Idx][ $off + $seq ];
+ }
+ return $ret;
+ }
+
+ sub Min {
+ my( $me, $seq, $base )= @_;
+ $me->_ChkPos();
+ my $off= $me->_ChkSeq($seq);
+ $base= $me->[_Base] if !defined $base;
+ return $base + $me->[_Idx][ $off + _Min ];
+ }
+
+ sub Max {
+ my( $me, $seq, $base )= @_;
+ $me->_ChkPos();
+ my $off= $me->_ChkSeq($seq);
+ $base= $me->[_Base] if !defined $base;
+ return $base + $me->[_Idx][ $off ] -1;
+ }
+
+ sub Range {
+ my( $me, $seq, $base )= @_;
+ $me->_ChkPos();
+ my $off = $me->_ChkSeq($seq);
+ if( !wantarray ) {
+ return $me->[_Idx][ $off ]
+ - $me->[_Idx][ $off + _Min ];
+ }
+ $base= $me->[_Base] if !defined $base;
+ return ( $base + $me->[_Idx][ $off + _Min ] )
+ .. ( $base + $me->[_Idx][ $off ] - 1 );
+ }
+
+ sub Items {
+ my( $me, $seq )= @_;
+ $me->_ChkPos();
+ my $off = $me->_ChkSeq($seq);
+ if( !wantarray ) {
+ return $me->[_Idx][ $off ]
+ - $me->[_Idx][ $off + _Min ];
+ }
+ return
+ @{$me->[$seq]}[
+ $me->[_Idx][ $off + _Min ]
+ .. ( $me->[_Idx][ $off ] - 1 )
+ ];
+ }
+
+ sub Same {
+ my( $me )= @_;
+ $me->_ChkPos();
+ return wantarray ? () : 0
+ if $me->[_Same] != ( 1 & $me->[_Pos] );
+ return $me->Items(1);
+ }
+
+ my %getName;
+ %getName= (
+ same => \&Same,
+ diff => \&Diff,
+ base => \&Base,
+ min => \&Min,
+ max => \&Max,
+ range=> \&Range,
+ items=> \&Items, # same thing
+ );
+
+ sub Get
+ {
+ my $me= shift @_;
+ $me->_ChkPos();
+ my @value;
+ for my $arg ( @_ ) {
+ for my $word ( split ' ', $arg ) {
+ my $meth;
+ if( $word !~ /^(-?\d+)?([a-zA-Z]+)([12])?$/
+ || not $meth= $getName{ lc $2 }
+ ) {
+ Die( $Root, ", Get: Invalid request ($word)" );
+ }
+ my( $base, $name, $seq )= ( $1, $2, $3 );
+ push @value, scalar(
+ 4 == length($name)
+ ? $meth->( $me )
+ : $meth->( $me, $seq, $base )
+ );
+ }
+ }
+ if( wantarray ) {
+ return @value;
+ } elsif( 1 == @value ) {
+ return $value[0];
+ }
+ Die( 0+@value, " values requested from ",
+ $Root, "'s Get in scalar context" );
+ }
+
+
+ my $Obj= getObjPkg($Root);
+ no strict 'refs';
+
+ for my $meth ( qw( new getObjPkg ) ) {
+ *{$Root."::".$meth} = \&{$meth};
+ *{$Obj ."::".$meth} = \&{$meth};
+ }
+ for my $meth ( qw(
+ Next Prev Reset Copy Base Diff
+ Same Items Range Min Max Get
+ _ChkPos _ChkSeq
+ ) ) {
+ *{$Obj."::".$meth} = \&{$meth};
+ }
+
+};
+{
+ package Algorithm::LCSS;
+
+ use strict;
+ {
+ no strict 'refs';
+ *traverse_sequences = \&Algorithm::Diff::traverse_sequences;
+ }
+
+ sub _tokenize { [split //, $_[0]] }
+
+ sub CSS {
+ my $is_array = ref $_[0] eq 'ARRAY' ? 1 : 0;
+ my ( $seq1, $seq2, @match, $from_match );
+ my $i = 0;
+ if ( $is_array ) {
+ $seq1 = $_[0];
+ $seq2 = $_[1];
+ traverse_sequences( $seq1, $seq2, {
+ MATCH => sub { push @{$match[$i]}, $seq1->[$_[0]]; $from_match = 1 },
+ DISCARD_A => sub { do{$i++; $from_match = 0} if $from_match },
+ DISCARD_B => sub { do{$i++; $from_match = 0} if $from_match },
+ });
+ }
+ else {
+ $seq1 = _tokenize($_[0]);
+ $seq2 = _tokenize($_[1]);
+ traverse_sequences( $seq1, $seq2, {
+ MATCH => sub { $match[$i] .= $seq1->[$_[0]]; $from_match = 1 },
+ DISCARD_A => sub { do{$i++; $from_match = 0} if $from_match },
+ DISCARD_B => sub { do{$i++; $from_match = 0} if $from_match },
+ });
+ }
+ return \@match;
+ }
+
+ sub CSS_Sorted {
+ my $match = CSS(@_);
+ if ( ref $_[0] eq 'ARRAY' ) {
+ @$match = map{$_->[0]}sort{$b->[1]<=>$a->[1]}map{[$_,scalar(@$_)]}@$match
+ }
+ else {
+ @$match = map{$_->[0]}sort{$b->[1]<=>$a->[1]}map{[$_,length($_)]}@$match
+ }
+ return $match;
+ }
+
+ sub LCSS {
+ my $is_array = ref $_[0] eq 'ARRAY' ? 1 : 0;
+ my $css = CSS(@_);
+ my $index;
+ my $length = 0;
+ if ( $is_array ) {
+ for( my $i = 0; $i < @$css; $i++ ) {
+ next unless @{$css->[$i]}>$length;
+ $index = $i;
+ $length = @{$css->[$i]};
+ }
+ }
+ else {
+ for( my $i = 0; $i < @$css; $i++ ) {
+ next unless length($css->[$i])>$length;
+ $index = $i;
+ $length = length($css->[$i]);
+ }
+ }
+ return $css->[$index];
+ }
+
+};
+# }}}
+#{{{ Class::Classless module
+{
+ package Class::Classless;
+ use strict;
+ use vars qw(@ISA);
+ use Carp;
+
+ @ISA = ();
+
+ ###########################################################################
+
+ @Class::Classless::X::ISA = ();
+
+ ###########################################################################
+ ###########################################################################
+
+ sub Class::Classless::X::AUTOLOAD {
+ # This's the big dispatcher.
+
+ my $it = shift @_;
+ my $m = ($Class::Classless::X::AUTOLOAD =~ m/([^:]+)$/s )
+ ? $1 : $Class::Classless::X::AUTOLOAD;
+
+ croak "Can't call Class::Classless methods (like $m) without an object"
+ unless ref $it; # sanity, basically.
+
+ my $prevstate;
+ $prevstate = ${shift @_}
+ if scalar(@_) && defined($_[0]) &&
+ ref($_[0]) eq 'Class::Classless::CALLSTATE::SHIMMY'
+ ; # A shim! we were called via $callstate->NEXT
+
+ my $no_fail = $prevstate ? $prevstate->[3] : undef;
+ my $i = $prevstate ? ($prevstate->[1] + 1) : 0;
+ # where to start scanning
+ my $lineage;
+
+ # Get the linearization of the ISA tree
+ if($prevstate) {
+ $lineage = $prevstate->[2];
+ } elsif(defined $it->{'ISA_CACHE'} and ref $it->{'ISA_CACHE'} ){
+ $lineage = $it->{'ISA_CACHE'};
+ } else {
+ $lineage = [ &Class::Classless::X::ISA_TREE($it) ];
+ }
+
+ # Was:
+ #my @lineage =
+ # $prevstate ? @{$prevstate->[2]}
+ # : &Class::Classless::X::ISA_TREE($it);
+ # # Get the linearization of the ISA tree
+ # # ISA-memoization happens in the ISA_TREE function.
+
+ for(; $i < @$lineage; ++$i) {
+
+ if( !defined($no_fail) and exists($lineage->[$i]{'NO_FAIL'}) ) {
+ $no_fail = ($lineage->[$i]{'NO_FAIL'} || 0);
+ # so the first NO_FAIL sets it
+ }
+
+ if( ref($lineage->[$i]{'METHODS'} || 0) # sanity
+ && exists($lineage->[$i]{'METHODS'}{$m})
+ ){
+ # We found what we were after. Now see what to do with it.
+ my $v = $lineage->[$i]{'METHODS'}{$m};
+ return $v unless defined $v and ref $v;
+
+ if(ref($v) eq 'CODE') { # normal case, I expect!
+ # Used to have copying of the arglist here.
+ # But it was apparently useless, so I deleted it
+ unshift @_,
+ $it, # $_[0] -- target object
+ # a NEW callstate
+ bless([$m, $i, $lineage, $no_fail, $prevstate ? 1 : 0],
+ 'Class::Classless::CALLSTATE'
+ ), # $_[1] -- the callstate
+ ;
+ goto &{ $v }; # yes, magic goto! bimskalabim!
+ }
+ return @$v if ref($v) eq '_deref_array';
+ return $$v if ref($v) eq '_deref_scalar';
+ return $v; # fallthru
+ }
+ }
+
+ if($m eq 'DESTROY') { # mitigate DESTROY-lookup failure at global destruction
+ # should be impossible
+ } else {
+ if($no_fail || 0) {
+ return;
+ }
+ croak "Can't find ", $prevstate ? 'NEXT method' : 'method',
+ " $m in ", $it->{'NAME'} || $it,
+ " or any ancestors\n";
+ }
+ }
+
+ ###########################################################################
+ ###########################################################################
+
+ sub Class::Classless::X::DESTROY {
+ # noop
+ }
+
+ ###########################################################################
+ sub Class::Classless::X::ISA_TREE {
+ # The linearizer!
+ # Returns the search path for $_[0], starting with $_[0]
+ # Possibly memoized.
+
+ # I stopped being able to understand this algorithm about five
+ # minutes after I wrote it.
+ use strict;
+
+ my $set_cache = 0; # flag to set the cache on the way out
+
+ if(exists($_[0]{'ISA_CACHE'})) {
+ return @{$_[0]{'ISA_CACHE'}}
+ if defined $_[0]{'ISA_CACHE'}
+ and ref $_[0]{'ISA_CACHE'};
+
+ # Otherwise, if exists but is not a ref, it's a signal that it should
+ # be replaced at the earliest, with a listref
+ $set_cache = 1;
+ }
+
+ my $has_mi = 0; # set to 0 on the first node we see with 2 parents!
+ # First, just figure out what's in the tree.
+ my %last_child = ($_[0] => 1); # as if already seen
+
+ # if $last_child{$x} == $y, that means:
+ # 1) incidentally, we've passed the node $x before.
+ # 2) $x is the last child of $y,
+ # so that means that $y can be pushed to the stack only after
+ # we've pushed $x to the stack.
+
+ my @tree_nodes;
+ {
+ my $current;
+ my @in_stack = ($_[0]);
+ while(@in_stack) {
+ next unless
+ defined($current = shift @in_stack)
+ && ref($current) # sanity
+ && ref($current->{'PARENTS'} || 0) # sanity
+ ;
+
+ push @tree_nodes, $current;
+
+ $has_mi = 1 if @{$current->{'PARENTS'}} > 1;
+ unshift
+ @in_stack,
+ map {
+ if(exists $last_child{$_}) { # seen before!
+ $last_child{$_} = $current;
+ (); # seen -- don't re-explore
+ } else { # first time seen
+ $last_child{$_} = $current;
+ $_; # first time seen -- explore now
+ }
+ }
+ @{$current->{'PARENTS'}}
+ ;
+ }
+
+ # If there was no MI, then that first scan was sufficient.
+ unless($has_mi) {
+ $_[0]{'ISA_CACHE'} = \@tree_nodes if $set_cache;
+ return @tree_nodes;
+ }
+
+ # Otherwise, toss this list and rescan, consulting %last_child
+ }
+
+ # $last_child{$parent} holds the last (or only) child of $parent
+ # in this tree. When walking the tree this time, only that
+ # child is authorized to put its parent on the @in_stack.
+ # And that's the only way a node can get added to @in_stack,
+ # except for $_[0] (the start node) being there at the beginning.
+
+ # Now, walk again, but this time exploring parents the LAST
+ # time seen in the tree, not the first.
+
+ my @out;
+ {
+ my $current;
+ my @in_stack = ($_[0]);
+ while(@in_stack) {
+ next unless defined($current = shift @in_stack) && ref($current);
+ push @out, $current; # finally.
+ unshift
+ @in_stack,
+ grep(
+ (
+ defined($_) # sanity
+ && ref($_) # sanity
+ && $last_child{$_} eq $current,
+ ),
+ # I'm lastborn (or onlyborn) of this parent
+ # so it's OK to explore now
+ @{$current->{'PARENTS'}}
+ )
+ if ref($current->{'PARENTS'} || 0) # sanity
+ ;
+ }
+
+ unless(scalar(@out) == scalar(keys(%last_child))) {
+ # the counts should be equal
+ my %good_ones;
+ @good_ones{@out} = ();
+ croak
+ "ISA tree for " .
+ ($_[0]{'NAME'} || $_[0]) .
+ " is apparently cyclic, probably involving the nodes " .
+ nodelist( grep { ref($_) && !exists $good_ones{$_} }
+ values(%last_child) )
+ . "\n";
+ }
+ }
+ #print "Contents of out: ", nodelist(@out), "\n";
+
+ $_[0]{'ISA_CACHE'} = \@out if $set_cache;
+ return @out;
+ }
+
+ ###########################################################################
+
+ sub Class::Classless::X::can { # NOT like UNIVERSAL::can ...
+ # return 1 if $it is capable of the method given -- otherwise 0
+ my($it, $m) = @_[0,1];
+ return undef unless ref $it;
+
+ croak "undef is not a valid method name" unless defined($m);
+ croak "null-string is not a valid method name" unless length($m);
+
+ foreach my $o (&Class::Classless::X::ISA_TREE($it)) {
+ return 1
+ if ref($o->{'METHODS'} || 0) # sanity
+ && exists $o->{'METHODS'}{$m};
+ }
+
+ return 0;
+ }
+
+
+ ###########################################################################
+
+ sub Class::Classless::X::isa { # Like UNIVERSAL::isa
+ # Returns true for $X->isa($Y) iff $Y is $X or is an ancestor of $X.
+
+ return unless ref($_[0]) && ref($_[1]);
+ return scalar(grep {$_ eq $_[1]} &Class::Classless::X::ISA_TREE($_[0]));
+ }
+
+ ###########################################################################
+
+ sub nodelist { join ', ', map { "" . ($_->{'NAME'} || $_) . ""} @_ }
+
+ ###########################################################################
+ ###########################################################################
+ ###########################################################################
+ # Methods for the CALLSTATE class.
+ # Basically, CALLSTATE objects represent the state of the dispatcher,
+ # frozen at the moment when the method call was dispatched to the
+ # appropriate sub.
+ # In the grand scheme of things, this needn't be a class -- I could
+ # have just made the callstate data-object be a hash with documented
+ # keys, or a closure that responded to only certain parameters,
+ # etc. But I like it this way. And I like being able to say simply
+ # $cs->NEXT
+ # Yes, these are a bit cryptically written, but it's behoovy for
+ # them to be very very efficient.
+
+ @Class::Classless::ISA = ();
+ sub Class::Classless::CALLSTATE::found_name { $_[0][0] }
+ # the method name called and found
+ sub Class::Classless::CALLSTATE::found_depth { $_[0][1] }
+ # my depth in the lineage
+ sub Class::Classless::CALLSTATE::lineage { @{$_[0][2]} }
+ # my lineage
+ sub Class::Classless::CALLSTATE::target { $_[0][2][ 0 ] }
+ # the object that's the target -- same as $_[0] for the method called
+ sub Class::Classless::CALLSTATE::home { $_[0][2][ $_[0][1] ] }
+ # the object I was found in
+ sub Class::Classless::CALLSTATE::sub_found {
+ $_[0][2][ $_[0][1] ]{'METHODS'}{ $_[0][0] }
+ } # the routine called
+
+ sub Class::Classless::CALLSTATE::no_fail { $_[0][3] }
+ sub Class::Classless::CALLSTATE::set_no_fail_true { $_[0][3] = 1 }
+ sub Class::Classless::CALLSTATE::set_fail_false { $_[0][3] = 0 }
+ sub Class::Classless::CALLSTATE::set_fail_undef { $_[0][3] = undef }
+
+ sub Class::Classless::CALLSTATE::via_next { $_[0][4] }
+
+ sub Class::Classless::CALLSTATE::NEXT {
+ #croak "NEXT needs at least one argument: \$cs->NEXT('method'...)"
+ # unless @_ > 1;
+ # no longer true.
+ my $cs = shift @_;
+ my $m = shift @_; # which may be (or come out) undef...
+ $m = $cs->[0] unless defined $m; # the method name called and found
+
+ ($cs->[2][0])->$m(
+ bless( \$cs, 'Class::Classless::CALLSTATE::SHIMMY' ),
+ @_
+ );
+ }
+
+ ###########################################################################
+};
+#}}}
+
+###############
+###
+#
+# {{{ *** C h a n g e l o g ***
+#
+# 0.6ca
+# - add screen support (from nicklist.pl)
+# - rename to adv_windowlist.pl (advanced window list) since it isn't just a
+# window list status bar (wlstat) anymore
+# - names can now have a max length and window names can be used
+# - fixed a bug with block display in screen mode and statusbar mode
+# - added space handling to ir_fe and removed it again
+# - now handling formats on my own
+# - added warning about missing sb_act_none abstract leading to
+# - display*active settings
+# - added warning about the bug in awl_display_(no)key_active settings
+#
+# 0.5d
+# - add setting to also hide the last statusbar if empty (awl_all_disable)
+# - reverted to old utf8 code to also calculate broken utf8 length correctly
+# - simplified dealing with statusbars in wlreset
+# - added a little tweak for the renamed term_type somewhere after Irssi 0.8.9
+# - fixed bug in handling channel #$$
+# - typo on line 200 spotted by f0rked
+# - reset background colour at the beginning of an entry
+#
+# 0.4d
+# - fixed order of disabling statusbars
+# - several attempts at special chars, without any real success
+# and much more weird new bugs caused by this
+# - setting to specify sort order
+# - reduced timeout values
+# - added awl_hide_data for Geert Hauwaerts ( geert@irssi.org ) :)
+# - make it so the dynamic sub is actually deleted
+# - fix a bug with removing of the last separator
+# - take into consideration parse_special
+#
+# 0.3b
+# - automatically kill old statusbars
+# - reset on /reload
+# - position/placement settings
+#
+# 0.2
+# - automated retrieval of key bindings (thanks grep.pl authors)
+# - improved removing of statusbars
+# - got rid of status chop
+#
+# 0.1
+# - rewritten to suit my needs
+# - based on chanact 0.5.5
+# }}}
+# vim: se fdm=marker tw=80 :
diff --git a/.irssi/scripts/autorun/bitlbee_tab_completion.pl b/.irssi/scripts/autorun/bitlbee_tab_completion.pl
new file mode 100644
index 0000000..82cbe8f
--- /dev/null
+++ b/.irssi/scripts/autorun/bitlbee_tab_completion.pl
@@ -0,0 +1,196 @@
+use strict;
+use vars qw(%topics);
+use vars qw($VERSION %IRSSI);
+use Irssi qw(signal_add_last signal_add_first settings_add_bool settings_add_str
+ settings_get_bool settings_get_str signal_stop);
+use Irssi::Irc;
+
+$VERSION = '1.00';
+
+%IRSSI = (
+ authors => 'Tijmen Ruizendaal & Wilmer van der Gaast',
+ contact => 'timing@fokdat.nl timing@OFTC',
+ name => 'BitlBee_tab_completion',
+ description => 'Intelligent Tab-completion for Bitlbee commands (for more info: http://www.bitlbee.org).',
+ license => 'GPLv2',
+ url => 'http://fokdat.nl/~tijmen/software/index.html',
+ changed => '05-18-2004',
+);
+
+my $debug = 0; ## change this into 1 if you want to see some output in your control panel, it's not much, so don't be scared.
+
+## Hardcoded defaults, most of these will be auto-guessed when the BitlBee server supports this.
+
+my $root_nick = 'root';
+my $bitlbee_channel = '#bitlbee';
+my $getting_completions = '0';
+
+my @commands = ('account','allow','block','blist','help','identify','info','nick','qlist','register','remove','rename','save','set');
+my @setlist = ('auto_connect','auto_reconnect','auto_reconnect_delay','away_devoice','buddy_sendbuffer','buddy_sendbuffer_delay','charset','debug','handle_unknown','html','ops','private','save_on_quit','typing_notice','to_char');
+my @helplist = ('away','commands','groupchats','groupchats2','groupchats3','index','quickstart','quickstart2','quickstart3','quickstart4','quickstart5','smileys');
+
+my @accountlist = ('add','del','list','on','off');
+my @blist = ('all','away','offline','online');
+my @boolean = ('true', 'false');
+my @handle_unknown = ('root', 'add', 'add_private', 'add_channel', 'ignore');
+my @ops = ('both', 'root', 'user', 'none');
+my @html = ('strip', 'nostrip');
+
+##pfft, done with that...
+
+my $i;
+
+for $i ( @commands )
+{
+ @helplist = ( @helplist, $i );
+}
+
+signal_add_last 'channel sync' => sub {
+ my( $channel ) = @_;
+ my( $server ) = $channel->{server};
+
+ if( $channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information." )
+ {
+ $bitlbee_channel = $channel->{name};
+ $getting_completions = 1;
+ $server->send_raw( 'COMPLETIONS' );
+ if($debug == 1){
+ print( 'Detected a #bitlbee: ' . $channel->{name} );
+ }
+ }
+};
+
+signal_add_last 'message irc notice' => sub {
+ my( $server, $msg, $from, $address, $target ) = @_;
+
+ ## Ignore the notice if we have the completions already.
+ return unless $getting_completions;
+
+ if( $msg =~ s/^COMPLETIONS // )
+ {
+ $root_nick = $from;
+ if( $msg eq 'OK' )
+ {
+ ## We're sure that the server supports the COMPLETIONS
+ ## command now, so let's flush our hardcoded stuff.
+ @commands = @setlist = @helplist = ();
+ if($debug == 1)
+ {
+ print( 'COMPLETIONS fetching supported!' );
+ }
+ }
+ elsif( $msg eq 'END' )
+ {
+ ## Ignore further notices.
+ $getting_completions = 0;
+ if($debug == 1)
+ {
+ print( 'COMPLETIONS fetching finished!' );
+ }
+ }
+ elsif( $msg =~ s/^help // )
+ {
+ @helplist = ( @helplist, $msg );
+ }
+ elsif( $msg =~ s/^set // )
+ {
+ @setlist = ( @setlist, $msg );
+ }
+ else
+ {
+ @commands = ( @commands, $msg );
+ }
+
+ signal_stop();
+ }
+};
+
+signal_add_last 'complete word' => sub {
+ my ($complist, $window, $word, $linestart, $want_space) = @_;
+ my $channel = $window->get_active_name();
+ if ($channel eq $bitlbee_channel or $channel eq $root_nick or $linestart =~ /^\/(msg|query) \Q$root_nick\E */i){
+ $linestart =~ s/^\/(msg|query) \Q$root_nick\E *//i;
+ $linestart =~ s/^\Q$root_nick\E[:,] *//i;
+ if ($linestart eq ""){
+ foreach my $command(@commands)
+ {
+ if ($command =~ /^$word/i)
+ {
+ push @$complist, $command;
+ }
+ }
+ }elsif ($linestart eq "set" or $linestart eq "help set")
+ {
+ foreach my $set(@setlist)
+ {
+ if ($set =~ /^$word/i)
+ {
+ push @$complist, $set;
+ }
+ }
+ }elsif ($linestart eq "help")
+ {
+ foreach my $help(@helplist)
+ {
+ if ($help =~ /^$word/i)
+ {
+ push @$complist, $help;
+ }
+ }
+ }elsif ($linestart eq "blist")
+ {
+ foreach my $list(@blist)
+ {
+ if ($list =~ /^$word/i)
+ {
+ push @$complist, $list;
+ }
+ }
+ }elsif ($linestart eq "account" || $linestart eq "help account")
+ {
+ foreach my $account(@accountlist)
+ {
+ if ($account =~ /^$word/i)
+ {
+ push @$complist, $account;
+ }
+ }
+ }elsif($linestart eq 'set away_devoice' || $linestart eq 'set auto_connect' || $linestart eq 'set auto_reconnect' || $linestart eq 'set buddy_sendbuffer' || $linestart eq 'set debug' || $linestart eq 'set private' || $linestart eq 'set save_on_quit' || $linestart eq 'set typing_notice')
+ {
+ foreach my $bool(@boolean)
+ {
+ if ($bool =~ /^$word/i)
+ {
+ push @$complist, $bool;
+ }
+ }
+ }elsif($linestart eq 'set handle_unknown')
+ {
+ foreach my $handle(@handle_unknown)
+ {
+ if ($handle =~ /^$word/i)
+ {
+ push @$complist, $handle;
+ }
+ }
+ }elsif($linestart eq 'set ops')
+ {
+ foreach my $op(@ops)
+ {
+ if ($op =~ /^$word/i)
+ {
+ push @$complist, $op;
+ }
+ }
+ }elsif($linestart eq 'set html')
+ {
+ foreach my $strip(@html)
+ {
+ if ($strip =~ /^$word/i)
+ {
+ push @$complist, $strip;
+ }
+ }
+ }
+ }
+};
diff --git a/.irssi/scripts/autorun/chanact.pl b/.irssi/scripts/autorun/chanact.pl
new file mode 100644
index 0000000..e4aa247
--- /dev/null
+++ b/.irssi/scripts/autorun/chanact.pl
@@ -0,0 +1,479 @@
+use Irssi 20020101.0001 ();
+use strict;
+use Irssi::TextUI;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "0.5.5";
+%IRSSI = (
+ authors => 'BC-bd, Veli',
+ contact => 'bd@bc-bd.org, veli@piipiip.net',
+ name => 'chanact',
+ description => 'Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias). Lets you give alias characters to windows so that you can select those with meta-<char>',
+ license => 'GNU GPLv2 or later',
+ url => 'http://bc-bd.org/software.php3#irssi'
+);
+
+# Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias).
+# Lets you give alias characters to windows so that you can select those with
+# meta-<char>.
+#
+# for irssi 0.8.2 by bd@bc-bd.org
+#
+# inspired by chanlist.pl by 'cumol@hammerhart.de'
+#
+#########
+# Contributors
+#########
+#
+# veli@piipiip.net /window_alias code
+# qrczak@knm.org.pl chanact_abbreviate_names
+# qerub@home.se Extra chanact_show_mode and chanact_chop_status
+#
+#########
+# USAGE
+###
+#
+# copy the script to ~/.irssi/scripts/
+#
+# In irssi:
+#
+# /script load chanact
+# /statusbar window add chanact -after act
+#
+# If you want the item to appear on another position read the help
+# for /statusbar.
+# To remove the [Act: 1,2,3] item type:
+#
+# /statusbar window remove act
+#
+# To see all chanact options type:
+#
+# / set chanact_
+#
+# After these steps you have your new statusbar item and you can start giving
+# aliases to your windows. Go to the window you want to give the alias to
+# and say:
+#
+# /window_alias <alias char>
+#
+# You can also remove the aliases with:
+#
+# /window_unalias <alias char>
+#
+# or in aliased window:
+#
+# /window_unalias
+#
+# To see a list of your windows use:
+#
+# /window list
+#
+#########
+# OPTIONS
+#########
+#
+# /set chanact_show_all <ON|OFF>
+# * ON : show all windows
+# * OFF : show only those with activity
+#
+# /set chanact_display <string>
+# * string : Format String for one Channel. The following $'s are expanded:
+# $C : Channel
+# $N : Number of the Window
+# $M : Mode in that channel
+# $H : Start highlightning
+# $S : Stop highlightning
+# * example:
+#
+# /set chanact_display $H$N:$M.$S$C
+#
+# will give you on #irssi.de if you have voice
+#
+# [3:+.#irssi.de]
+#
+# with '3:+.' highlighted and the channel name printed in regular color
+#
+# /set chanact_display_alias <string>
+# as 'chanact_display' but is used if the window has an alias and
+# 'chanact_show_alias' is set to on.
+#
+# /set chanact_show_names <ON|OFF>
+# * ON : show the channelnames after the number/alias
+# * OFF : don't show the names
+#
+# /set chanact_abbreviate_names <int>
+# * 0 : don't abbreviate
+# * <int> : strip channel name prefix character and leave only
+# that many characters of the proper name
+#
+# /set chanact_show_alias <ON|OFF>
+# * ON : show the aliase instead of the refnum
+# * OFF : shot the refnum
+#
+# /set chanact_separator <str>
+# * <str> : Characters to be displayed at the start of the item.
+# Defaults to: "Act: "
+#
+# /set chanact_separator <str>
+# * <str> : Charater to use between the channel entries
+#
+# /set chanact_autorenumber <ON|OFF>
+# * ON : Move the window automatically to first available slot
+# starting from "chanact_renumber_start" when assigning
+# an alias to window. Also moves the window back to a
+# first available slot from refnum 1 when the window
+# loses it's alias.
+# * OFF : Don't move the windows automatically
+#
+# /set chanact_renumber_start <int>
+# * <int> : Move the window to first available slot after this
+# num when "chanact_autorenumber" is ON.
+#
+#
+#########
+# HINTS
+#########
+#
+# If you have trouble with wrong colored entries your 'default.theme' might
+# be too old. Try on a shell:
+#
+# $ mv ~/.irssi/default.theme /tmp/
+#
+# And in irssi:
+# /reload
+# /save
+#
+###
+#################
+
+my ($actString,$needRemake);
+
+sub expand {
+ my ($string, %format) = @_;
+ my ($exp, $repl);
+ $string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
+ return $string;
+}
+
+# method will get called every time the statusbar item will be displayed
+# but we dont need to recreate the item every time so we first
+# check if something has changed and only then we recreate the string
+# this might just save some cycles
+# FIXME implement $get_size_only check, and user $item->{min|max-size}
+sub chanact {
+ my ($item, $get_size_only) = @_;
+
+ if ($needRemake) {
+ remake();
+ }
+
+ $item->default_handler($get_size_only, $actString, undef, 1);
+}
+
+# this is the real creation method
+sub remake() {
+ my ($afternumber,$finish,$hilight,$mode,$number,$display);
+ my $separator = Irssi::settings_get_str('chanact_separator');
+ my $abbrev = Irssi::settings_get_int('chanact_abbreviate_names');
+
+ $actString = "";
+ foreach my $win (sort { ($a->{refnum}) <=> ($b->{refnum})} Irssi::windows) {
+
+ # since irssi is single threaded this shouldn't happen
+ !ref($win) && next;
+
+ my $name = $win->get_active_name;
+ my $active = $win->{active};
+
+ !ref($win) && next;
+
+ # (status) is an awfull long name, so make it short to 'S'
+ # some people don't like it, so make it configurable
+ if (Irssi::settings_get_bool('chanact_chop_status')
+ && $name eq "(status)") {
+ $name = "S";
+ }
+
+ # check if we should show the mode
+ $mode = "";
+ if ($active->{type} eq "CHANNEL") {
+ my $server = $win->{active_server};
+ !ref($server) && next;
+
+ my $channel = $server->channel_find($name);
+ !ref($channel) && next;
+
+ my $nick = $channel->nick_find($server->{nick});
+ !ref($nick) && next;
+
+ if ($nick->{op}) {
+ $mode = "@";
+ } elsif ($nick->{voice}) {
+ $mode = "+";
+ } elsif ($nick->{halfop}) {
+ $mode = "%";
+ }
+ }
+
+ # find the right color
+ if ($win->{data_level} == 1) {
+ $hilight = "{sb_act_text ";
+ } elsif ($win->{data_level} == 2) {
+ $hilight = "{sb_act_msg ";
+ } elsif ($win->{data_level} == 3) {
+ $hilight = "{sb_act_hilight ";
+ } else {
+ if (Irssi::settings_get_bool('chanact_show_all') == 1) {
+ $hilight = "{%n ";
+ } else {
+ next;
+ }
+ }
+
+ if ($abbrev) {
+ if ($name =~ /^[&#+!=]/) {
+ $name = substr($name, 0, $abbrev + 1);
+ } else {
+ $name = substr($name, 0, $abbrev);
+ }
+ }
+
+ if (Irssi::settings_get_bool('chanact_show_alias') == 1 &&
+ $win->{name} =~ /^[a-zA-Z+]$/) {
+ $number = $win->{name};
+ $display = Irssi::settings_get_str('chanact_display_alias');
+ } else {
+ $number = $win->{refnum};
+ $display = Irssi::settings_get_str('chanact_display');
+ }
+
+ $actString .= expand($display,"C",$name,"N",$number,"M",$mode,"H",$hilight,"S","}{sb_background}").$separator;
+ }
+
+ # assemble the final string
+ if ($actString ne "") {
+ # Remove the last separator
+ $actString =~ s/$separator$//;
+
+ if (Irssi::settings_get_bool('chanact_show_all') == 1) {
+ $actString = "{sb ".$actString."}";
+ } else {
+ $actString = "{sb ".Irssi::settings_get_str('chanact_header').$actString."}";
+ }
+ }
+
+ # no remake needed any longer
+ $needRemake = 0;
+}
+
+# method called because of some events. here we dont remake the item but just
+# remember that we have to remake it the next time we are called
+sub chanactHasChanged()
+{
+ $needRemake = 1;
+
+ Irssi::statusbar_items_redraw('chanact');
+}
+
+# function by veli@piipiip.net
+# Remove alias
+sub cmd_window_unalias {
+ my ($data, $server, $witem) = @_;
+ my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
+
+ unless ($data =~ /^[a-zA-Z]$/ ||
+ Irssi::active_win()->{name} =~ /^[a-zA-Z]$/) {
+ Irssi::print("Usage: /window_unalias <char>");
+ Irssi::print("or /window_alias in window that has an alias.");
+ return;
+ }
+
+ if ($data eq '') { $data = Irssi::active_win()->{name}; }
+
+ if (my $oldwin = Irssi::window_find_name($data)) {
+ $oldwin->set_name(undef);
+ Irssi::print("Removed alias with the key '$data'.");
+
+ if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
+ $oldwin->{refnum} >= $rn_start) {
+ my $old_refnum = $oldwin->{refnum};
+
+ # Find the first available slot and move the window
+ my $newnum = 1;
+ while (Irssi::window_find_refnum($newnum) ne "") { $newnum++; }
+ $oldwin->set_refnum($newnum);
+
+ Irssi::print("and moved it to from $old_refnum to $newnum");
+ }
+ }
+}
+
+# function by veli@piipiip.net
+# Make an alias
+sub cmd_window_alias {
+ my ($data, $server, $witem) = @_;
+ my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
+
+ unless ($data =~ /^[a-zA-Z+]$/) {
+ Irssi::print("Usage: /window_alias <char>");
+ return;
+ }
+
+ cmd_window_unalias($data, $server, $witem);
+
+ my $window = $witem->window();
+ my $winnum = $window->{refnum};
+
+ if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
+ $window->{refnum} < $rn_start) {
+ my $old_refnum = $window->{refnum};
+
+ $winnum = $rn_start;
+
+ # Find the first available slot and move the window
+ while (Irssi::window_find_refnum($winnum) ne "") { $winnum++; }
+ $window->set_refnum($winnum);
+
+ Irssi::print("Moved the window from $old_refnum to $winnum");
+ }
+
+ $window->set_name($data);
+ $server->command("/bind meta-$data change_window $winnum");
+ Irssi::print("Window $winnum is now known as '$data'");
+}
+
+# function by veli@piipiip.net
+# Makes the aliases if names have already been set
+sub cmd_rebuild_aliases {
+ foreach (sort { $a->{refnum} <=> $b->{refnum} } Irssi::windows) {
+ if ($_->{name} =~ /^[a-zA-Z]$/) {
+ cmd_window_alias($_->{name}, $_->{active_server}, $_->{active});
+ }
+ }
+}
+
+# function by veli@piipiip.net
+# Change the binding if the window refnum changes.
+sub refnum_changed {
+ my ($window, $oldref) = @_;
+ my $server = Irssi::active_server();
+
+ if ($window->{name} =~ /^[a-zA-Z]$/) {
+ $server->command("/bind meta-".$window->{name}." change_window ".$window->{refnum});
+ }
+}
+
+$needRemake = 1;
+
+# Window alias command
+Irssi::command_bind('window_alias','cmd_window_alias');
+Irssi::command_bind('window_unalias','cmd_window_unalias');
+# Irssi::command_bind('window_alias_rebuild','cmd_rebuild_aliases');
+
+# our config item
+Irssi::settings_add_str('chanact', 'chanact_display', '$H$N:$M$C$S');
+Irssi::settings_add_str('chanact', 'chanact_display_alias', '$H$N$M$S');
+Irssi::settings_add_bool('chanact', 'chanact_show_all', 0);
+Irssi::settings_add_int('chanact', 'chanact_abbreviate_names', 0);
+Irssi::settings_add_bool('chanact', 'chanact_show_alias', 1);
+Irssi::settings_add_str('chanact', 'chanact_separator', " ");
+Irssi::settings_add_bool('chanact', 'chanact_autorenumber', 0);
+Irssi::settings_add_int('chanact', 'chanact_renumber_start', 50);
+Irssi::settings_add_str('chanact', 'chanact_header', "Act: ");
+Irssi::settings_add_bool('chanact', 'chanact_chop_status', 1);
+
+# register the statusbar item
+Irssi::statusbar_item_register('chanact', '$0', 'chanact');
+# according to cras we shall not call this
+# Irssi::statusbars_recreate_items();
+
+# register all that nifty callbacks on special events
+Irssi::signal_add_last('setup changed', 'chanactHasChanged');
+Irssi::signal_add_last('window hilight', 'chanactHasChanged');
+Irssi::signal_add("window created", "chanactHasChanged");
+Irssi::signal_add("window destroyed", "chanactHasChanged");
+Irssi::signal_add("window name changed", "chanactHasChanged");
+Irssi::signal_add('nick mode changed', 'chanactHasChanged');
+
+Irssi::signal_add_last('window refnum changed', 'refnum_changed');
+
+###############
+###
+#
+# Changelog
+#
+# 0.5.5
+# - some speedups from David Leadbeater <dgl@dgl.cx>
+#
+# 0.5.4
+# - added help for chanact_display_alias
+#
+# 0.5.3
+# - added '+' to the available chars of aliase's
+# - added chanact_display_alias to allow different display modes if the window
+# has an alias
+#
+# 0.5.2
+# - removed unused chanact_show_name settings (thx to Qerub)
+# - fixed $mode display
+# - guarded reference operations to (hopefully) fix errors on server disconnect
+#
+# 0.5.1
+# - small typo fixed
+#
+# 0.5.0
+# - changed chanact_show_mode to chanact_display. reversed changes from
+# Qerub through that, but kept funcionality.
+# - removed chanact_color_all since it is no longer needed
+#
+# 0.4.3
+# - changes by Qerub
+# + added chanact_show_mode to show the mode just before the channel name
+# + added chanact_chop_status to be able to control the (status) chopping
+# [bd] minor implementation changes
+# - moved Changelog to the end of the file since it is getting pretty big
+#
+# 0.4.2
+# - changed back to old version numbering sheme
+# - added '=' to Qrczak's chanact_abbreviate_names stuff :)
+# - added chanact_header
+#
+# 0.41q
+# - changes by Qrczak
+# + added setting 'chanact_abbreviate_names'
+# + windows are sorted by refnum; I didn't understand the old
+# logic and it broke sorting for numbers above 9
+#
+# 0.41
+# - minor updates
+# + fixed channel sort [veli]
+# + removed few typos and added some documentation [veli]
+#
+# 0.4
+# - merge with window_alias.pl
+# + added /window_alias from window_alias.pl by veli@piipiip.net
+# + added setting 'chanact_show_alias'
+# + added setting 'chanact_show_names'
+# + changed setting 'chanact_show_mode' to int
+# + added setting 'chanact_separator' [veli]
+# + added setting 'chanact_autorenumber' [veli]
+# + added setting 'chanact_renumber_start' [veli]
+# + added /window_unalias [veli]
+# + moved setting to their own group 'chanact' [veli]
+#
+# 0.3
+# - merge with chanlist.pl
+# + added setting 'chanact_show_mode'
+# + added setting 'chanact_show_all'
+#
+# 0.2
+# - added 'Act' to the item
+# - added setting 'chanact_color_all'
+# - finally found format for statusbar hilight
+#
+# 0.1
+# - Initial Release
+#
+###
+################
diff --git a/.irssi/scripts/autorun/mail.pl b/.irssi/scripts/autorun/mail.pl
new file mode 100644
index 0000000..33b3c22
--- /dev/null
+++ b/.irssi/scripts/autorun/mail.pl
@@ -0,0 +1,414 @@
+$VERSION = "2.92";
+%IRSSI = (
+ authors => "Timo Sirainen, Matti Hiljanen, Joost Vunderink, Bart Matthaei",
+ contact => "tss\@iki.fi, matti\@hiljanen.com, joost\@carnique.nl, bart\@dreamflow.nl",
+ name => "mail",
+ description => "Fully customizable mail counter statusbar item with multiple mailbox and multiple Maildir support",
+ license => "Public Domain",
+ url => "http://irssi.org, http://scripts.irssi.de",
+);
+
+# Mail counter statusbar item
+# for irssi 0.8.1 by Timo Sirainen
+#
+# Maildir support added by Matti Hiljanen
+# Multiple Maildir/mbox and customization support added by Joost Vunderink
+# OLD mailtreatment switch added by Bart Matthaei.
+# Improved some regexps in maildirmode by Bart Matthaei.
+# Maildirmode regexps (hopefully) fixed for good by Matti Hiljanen.
+#
+# You can add any number of mailboxes or Maildirs to watch for new mail in.
+# Give them any name and <name>:<count> will appear in your mail
+# statusbar item, where <count> is the number of unread messages.
+# If only 1 mailbox/Maildir is defined, the statusbar item will have the
+# familiar form [Mail: <count>].
+# If you set mail_show_message to ON, irssi will print a message in the
+# active window whenever new mail arrives.
+#
+# Check /mailbox help for help.
+
+use Irssi::TextUI;
+
+my $maildirmode = 0; # maildir=1, file(spools)=0
+my $old_is_not_new = 0;
+my $extprog;
+my ($last_refresh_time, $refresh_tag);
+
+# for mbox caching
+my $last_size, $last_mtime, $last_mailcount, $last_mode;
+
+# list of mailboxes
+my %mailboxes = ();
+my %new_mails_in_box = ();
+my $nummailboxes = 0;
+
+# the string to be stored in Irssi's mail_mailboxes setting
+my $mailboxsetting = "";
+
+sub cmd_print_help {
+ Irssi::print(
+ "MAILBOX ADD <num> <file|dir>\n".
+ "MAILBOX DEL <num>\n".
+ "MAILBOX SHOW\n\n".
+ "Statusbar item to keep track of how many (new) emails there are in ".
+ "each of your mailboxes/Maildirs.\n\n".
+ "/MAILBOX ADD <name> <file|dir>\n".
+ " - Adds a mailbox or a Maildir to the list.\n".
+ "/MAILBOX DEL <name>\n".
+ " - Removes mailbox or Maildir named <name> from the list.\n".
+ "/MAILBOX SHOW\n".
+ " - Shows a list of the defined mailboxes.\n\n".
+ "Use the following commands to change the behaviour:\n\n".
+ "/SET MAILDIRMODE on|off\n".
+ " - If maildirmode is on, the mailboxes in the list are assumed to be ".
+ "directories. Otherwise they are assumed to be spool files.\n".
+ " Default: off.\n".
+ "/SET MAIL_OLDNOTNEW on|off\n".
+ " - If switched on, mail marked als \"OLD\" will not be treated as new.\n".
+ " Default: off.\n".
+ "/SET MAIL_EXT_PROGRAM <prog>\n".
+ " - <prog> will be used to check for mail.\n".
+ "/SET MAIL_REFRESH_TIME <num>\n".
+ " - Sets the time between checks to <num> seconds.\n Default: 60.\n".
+ "/SET MAIL_SHOW_MESSAGE on|off\n".
+ " - If this is on, a message will be printed in the active window ".
+ "whenever new email is received.\n Default: off.\n".
+ "/SET MAIL_SHOW_ONLY_UNREAD on|off\n".
+ " - If you don't want to see a mailbox if it does not contain any new ".
+ "mail, set this to on.\n Default: on.\n" .
+ "/SET MAIL_SEPARATOR <char>\n".
+ " - Sets the character to be printed between each mailbox.\n".
+ " The default is a comma.\n".
+ "/SET MAIL_FORMAT <format>\n".
+ " - Sets the format of each mailbox.\n".
+ " Allowed variables:\n".
+ " %%n = mailbox name\n".
+ " %%u = number of unread mail\n".
+ " %%r = number of read mail\n".
+ " %%t = total amount of mail\n".
+ " The default format is %%n:%%u/%%t.\n".
+ "\nSee also: STATUSBAR"
+ ,MSGLEVEL_CRAP);
+}
+
+sub mbox_count {
+ my $mailfile = shift;
+ my $unread = 0;
+ my $read = 0;
+ my $maildirmode=Irssi::settings_get_bool('maildir_mode');
+ my $old_is_not_new=Irssi::settings_get_bool('mail_oldnotnew');
+
+ if ($extprog ne "") {
+ $total = `$extprog`;
+ chomp $unread;
+ } else {
+ if (!$maildirmode) {
+ if (-f $mailfile) {
+ my @stat = stat($mailfile);
+ my $size = $stat[7];
+ my $mtime = $stat[9];
+
+ # if the file hasn't changed, get the count from cache
+ return $last_mailcount if ($last_size == $size && $last_mtime == $mtime);
+ $last_size = $size;
+ $last_mtime = $mtime;
+
+ my $f = gensym;
+ return 0 if (!open($f, $mailfile));
+
+ # count new mails only
+ my $internal_removed = 0;
+ while (<$f>) {
+ $unread++ if (/^From /);
+
+ if(!$old_is_not_new) {
+ $unread-- if (/^Status: R/);
+ } else {
+ $unread-- if (/^Status: [OR]/);
+ }
+
+ $read++ if (/^From /);
+
+ # Remove folder internal data, but only once
+ if (/^Subject: .*FOLDER INTERNAL DATA/) {
+ if ($internal_removed == 0) {
+ $internal_removed = 1;
+ $read--;
+ $unread--;
+ }
+ }
+ }
+ close($f);
+ }
+ } else {
+ opendir(DIR, "$mailfile/cur") or return 0;
+ while (defined(my $file = readdir(DIR))) {
+ next if $file =~ /^(.|..)$/;
+ # Maildir flags: http://cr.yp.to/proto/maildir.html
+ # My old regexps were useless if the MUA added any
+ # non-default flags -qvr
+ #
+ # deleted mail
+ next if $file =~ /\:.*?T.*?$/;
+ if($old_is_not_new) {
+ # when mail gets moved from new to cur it's name _always_
+ # changes from uniq to uniq:info, even when it's still not
+ # read. I assume "old mail" means mail which hasn't been read
+ # yet but it has been "acknowledged" by the user. (it's been
+ # moved to cur) -qvr
+ if ($file =~ /\:.*?$/) {
+ $read++;
+ next;
+ }
+ } else {
+ if ($file =~ /\:.*?S.*?$/) {
+ $read++;
+ next;
+ }
+ }
+ $unread++;
+ }
+ closedir(DIR);
+
+ opendir(DIR, "$mailfile/new") or return 0;
+ while (defined(my $file = readdir(DIR))) {
+ next if $file =~ /^(.|..)$/;
+ $unread++;
+ }
+ closedir(DIR);
+ }
+ }
+
+ if ($unread eq "" || $unread < 0) {
+ $unread = 0;
+ }
+ if ($read eq "" || $read < 0) {
+ $read = 0;
+ }
+
+ $last_mailcount = $unread;
+
+ return ($unread, $read);
+}
+
+# Checks for mail and sets the statusbar item to the right string.
+# Also shows a message in the active window if that setting is set.
+sub mail {
+ my ($item, $get_size_only) = @_;
+
+ my $result;
+ my $format = Irssi::settings_get_str('mail_format');
+ my $unread = 0;
+ my $read = 0;
+ my $total = 0;
+
+ # check all mailboxes for new email
+ foreach $name (keys(%mailboxes)) {
+ my $box = $mailboxes{$name};
+ # replace "~/" at the beginning by the user's home dir
+ $box =~ s/^~\//$ENV{'HOME'}\//;
+
+ ($unread, $read) = mbox_count($box);
+ $unread = "0" if ($unread eq "");
+ $read = "0" if ($read eq "");
+ $total = $unread + $read;
+ $total = "0" if ($total eq "");
+
+ next if (Irssi::settings_get_bool('mail_show_only_unread') && $unread == 0);
+
+ if ($total eq "") { $total = 0; }
+ if (length($result) > 0) {
+ $result .= Irssi::settings_get_str('mail_separator');
+ }
+ my $string = $format;
+ $string =~ s/%n/$name/;
+ $string =~ s/%u/$unread/;
+ $string =~ s/%r/$read/;
+ $string =~ s/%t/$total/;
+ $result .= $string;
+
+ # Show -!- You have <num> new messages in <name>.
+ # Show this only if there are any new, unread messages.
+ if (Irssi::settings_get_bool('mail_show_message') &&
+ $unread > $new_mails_in_box{$name}) {
+ $new_mails = $unread - $new_mails_in_box{$name};
+ if ($nummailboxes == 1) {
+ Irssi::print("You have $new_mails new message" . ($new_mails != 1 ? "s." : "."), MSGLEVEL_CRAP);
+ } else {
+ Irssi::print("You have $new_mails new message" . ($new_mails != 1 ? "s " : " ") . "in $name.", MSGLEVEL_CRAP);
+ }
+ }
+
+ $new_mails_in_box{$name} = $unread;
+ }
+
+ if (length($result) == 0) {
+ # no mail - don't print the [Mail: ] at all
+ if ($get_size_only) {
+ $item->{min_size} = $item->{max_size} = 0;
+ }
+ } else {
+ $item->default_handler($get_size_only, undef, $result, 1);
+ }
+}
+
+sub refresh_mail {
+ Irssi::statusbar_items_redraw('mail');
+}
+
+# Adds the mailboxes from a string. Only to be used during startup.
+sub add_mailboxes {
+ my $boxstring = $_[0];
+ my @boxes = split(/,/, $boxstring);
+
+ foreach $dbox(@boxes) {
+ my $name = $dbox;
+ $name = substr($dbox, 0, index($dbox, '='));
+ my $box = $dbox;
+ $box = substr($dbox, index($dbox, '=') + 1, length($dbox));
+ addmailbox($name, $box);
+ }
+}
+
+sub addmailbox {
+ my ($name, $box) = @_;
+
+ if (exists($mailboxes{$name})) {
+ if ($box eq $mailboxes{$name}) {
+ Irssi::print("Mailbox $name already set to $box", MSGLEVEL_CRAP);
+ } else {
+ Irssi::print("Mailbox $name changed to $box", MSGLEVEL_CRAP);
+ $new_mails_in_box{$name} = 0;
+ }
+ } else {
+ Irssi::print("Mailbox $name added: " . $box, MSGLEVEL_CRAP);
+ $new_mails_in_box{$name} = 0;
+ $nummailboxes++;
+ }
+ $mailboxes{$name} = $box;
+}
+
+sub delmailbox {
+ my $name = $_[0];
+
+ if (exists($mailboxes{$name})) {
+ Irssi::print("Mailbox $name removed", MSGLEVEL_CRAP);
+ delete($mailboxes{$name});
+ delete($new_mails_in_box{$name});
+ $nummailboxes--;
+ } else {
+ Irssi::print("No such mailbox $name. Use /mailbox show to see a list.", MSGLEVEL_CRAP);
+ }
+}
+
+sub update_settings_string {
+ my $setting;
+
+ foreach $name (keys(%mailboxes)) {
+ $setting .= $name . "=" . $mailboxes{$name} . ",";
+ }
+
+ Irssi::settings_set_str("mail_mailboxes", $setting);
+}
+
+sub cmd_addmailbox {
+ my ($name, $box) = split(/ +/, $_[0]);
+
+ if ($name eq "" || $box eq "") {
+ Irssi::print("Use /mailbox add <name> <mailbox> to add a mailbox.", MSGLEVEL_CRAP);
+ return;
+ }
+
+ addmailbox($name, $box);
+ update_settings_string();
+ refresh_mail();
+}
+
+sub cmd_delmailbox {
+ my $name = $_[0];
+
+ if ($name eq "") {
+ Irssi::print("Use /mailbox del <name> to delete a mailbox.", MSGLEVEL_CRAP);
+ return;
+ }
+
+ delmailbox($name);
+ update_settings_string();
+ refresh_mail();
+}
+
+sub cmd_showmailboxes {
+ if ($nummailboxes == 0) {
+ Irssi::print("No mailboxes defined.", MSGLEVEL_CRAP);
+ return;
+ }
+ Irssi::print("Mailboxes:", MSGLEVEL_CRAP);
+ foreach $box (keys(%mailboxes)) {
+ Irssi::print("$box: " . $mailboxes{$box}, MSGLEVEL_CRAP);
+ }
+}
+
+sub cmd_mailboxes {
+ my ($data, $server, $item) = @_;
+ if ($data =~ m/^[(show)|(add)|(del)]/i ) {
+ Irssi::command_runsub ('mailbox', $data, $server, $item);
+ }
+ else {
+ Irssi::print("Use /mailbox (show|add|del).")
+ }
+}
+
+sub init_mailboxes {
+ # Add the mailboxes at startup of the script
+ my $boxes = Irssi::settings_get_str('mail_mailboxes');
+ if (length($boxes) > 0) {
+ add_mailboxes($boxes);
+ }
+}
+
+sub read_settings {
+ $extprog = Irssi::settings_get_str('mail_ext_program');
+ my $time = Irssi::settings_get_int('mail_refresh_time');
+ my $mode = Irssi::settings_get_bool('maildir_mode');
+ unless ($time == $last_refresh_time) {
+ $last_refresh_time = $time;
+ Irssi::timeout_remove($refresh_tag) if ($refresh_tag);
+ $refresh_tag = Irssi::timeout_add($time*1000, 'refresh_mail', undef);
+ }
+ return if ($mode == $last_mode);
+ $last_mode = $mode;
+ refresh_mail;
+}
+
+
+if (!$maildirmode) {
+ my $default = "1=" . $ENV{'MAIL'} . ",";
+ Irssi::settings_add_str('misc', 'mail_mailboxes', $default);
+} else {
+ my $default = "1=~/Maildir/,";
+ Irssi::settings_add_str('misc', 'mail_mailboxes', $default);
+}
+
+Irssi::command_bind('mailbox show', 'cmd_showmailboxes');
+Irssi::command_bind('mailbox add', 'cmd_addmailbox');
+Irssi::command_bind('mailbox del', 'cmd_delmailbox');
+Irssi::command_bind('mailbox help', 'cmd_print_help');
+Irssi::command_bind('mailbox', 'cmd_mailboxes');
+
+Irssi::settings_add_str('misc', 'mail_ext_program', '');
+Irssi::settings_add_int('misc', 'mail_refresh_time', 60);
+Irssi::settings_add_bool('misc', 'maildir_mode', "$maildirmode");
+Irssi::settings_add_bool('misc', 'mail_oldnotnew', "$old_is_not_new");
+Irssi::settings_add_str('misc', 'mail_separator', ",");
+Irssi::settings_add_bool('misc', 'mail_show_message', "0");
+Irssi::settings_add_str('misc', 'mail_format', '%n:%u/%t');
+Irssi::settings_add_bool('misc', 'mail_show_only_unread', "1");
+
+Irssi::statusbar_item_register('mail', '{sb Mail: $0-}', 'mail');
+
+read_settings();
+init_mailboxes();
+Irssi::signal_add('setup changed', 'read_settings');
+refresh_mail();
+
+# EOF
diff --git a/.irssi/scripts/autorun/nickcolor.pl b/.irssi/scripts/autorun/nickcolor.pl
new file mode 100644
index 0000000..69f2936
--- /dev/null
+++ b/.irssi/scripts/autorun/nickcolor.pl
@@ -0,0 +1,156 @@
+use strict;
+use Irssi 20020101.0250 ();
+use vars qw($VERSION %IRSSI);
+$VERSION = "1";
+%IRSSI = (
+ authors => "Timo Sirainen, Ian Peters",
+ contact => "tss\@iki.fi",
+ name => "Nick Color",
+ description => "assign a different color for each nick",
+ license => "Public Domain",
+ url => "http://irssi.org/",
+ changed => "2002-03-04T22:47+0100"
+);
+
+# hm.. i should make it possible to use the existing one..
+Irssi::theme_register([
+ 'pubmsg_hilight', '{pubmsghinick $0 $3 $1}$2'
+]);
+
+my %saved_colors;
+my %session_colors = {};
+my @colors = qw/2 3 4 5 6 7 9 10 11 12 13/;
+
+sub load_colors {
+ open COLORS, "$ENV{HOME}/.irssi/saved_colors";
+
+ while (<COLORS>) {
+ # I don't know why this is necessary only inside of irssi
+ my @lines = split "\n";
+ foreach my $line (@lines) {
+ my($nick, $color) = split ":", $line;
+ $saved_colors{$nick} = $color;
+ }
+ }
+
+ close COLORS;
+}
+
+sub save_colors {
+ open COLORS, ">$ENV{HOME}/.irssi/saved_colors";
+
+ foreach my $nick (keys %saved_colors) {
+ print COLORS "$nick:$saved_colors{$nick}\n";
+ }
+
+ close COLORS;
+}
+
+# If someone we've colored (either through the saved colors, or the hash
+# function) changes their nick, we'd like to keep the same color associated
+# with them (but only in the session_colors, ie a temporary mapping).
+
+sub sig_nick {
+ my ($server, $newnick, $nick, $address) = @_;
+ my $color;
+
+ $newnick = substr ($newnick, 1) if ($newnick =~ /^:/);
+
+ if ($color = $saved_colors{$nick}) {
+ $session_colors{$newnick} = $color;
+ } elsif ($color = $session_colors{$nick}) {
+ $session_colors{$newnick} = $color;
+ }
+}
+
+# This gave reasonable distribution values when run across
+# /usr/share/dict/words
+
+sub simple_hash {
+ my ($string) = @_;
+ chomp $string;
+ my @chars = split //, $string;
+ my $counter;
+
+ foreach my $char (@chars) {
+ $counter += ord $char;
+ }
+
+ $counter = $colors[$counter % 11];
+
+ return $counter;
+}
+
+# FIXME: breaks /HILIGHT etc.
+sub sig_public {
+ my ($server, $msg, $nick, $address, $target) = @_;
+ my $chanrec = $server->channel_find($target);
+ return if not $chanrec;
+ my $nickrec = $chanrec->nick_find($nick);
+ return if not $nickrec;
+ my $nickmode = $nickrec->{op} ? "@" : $nickrec->{voice} ? "+" : "";
+
+ # Has the user assigned this nick a color?
+ my $color = $saved_colors{$nick};
+
+ # Have -we- already assigned this nick a color?
+ if (!$color) {
+ $color = $session_colors{$nick};
+ }
+
+ # Let's assign this nick a color
+ if (!$color) {
+ $color = simple_hash $nick;
+ $session_colors{$nick} = $color;
+ }
+
+ $color = "0".$color if ($color < 10);
+ $server->command('/^format pubmsg {pubmsgnick $2 {pubnick '.chr(3).$color.'$0}}$1');
+}
+
+sub cmd_color {
+ my ($data, $server, $witem) = @_;
+ my ($op, $nick, $color) = split " ", $data;
+
+ $op = lc $op;
+
+ if (!$op) {
+ Irssi::print ("No operation given");
+ } elsif ($op eq "save") {
+ save_colors;
+ } elsif ($op eq "set") {
+ if (!$nick) {
+ Irssi::print ("Nick not given");
+ } elsif (!$color) {
+ Irssi::print ("Color not given");
+ } elsif ($color < 2 || $color > 14) {
+ Irssi::print ("Color must be between 2 and 14 inclusive");
+ } else {
+ $saved_colors{$nick} = $color;
+ }
+ } elsif ($op eq "clear") {
+ if (!$nick) {
+ Irssi::print ("Nick not given");
+ } else {
+ delete ($saved_colors{$nick});
+ }
+ } elsif ($op eq "list") {
+ Irssi::print ("\nSaved Colors:");
+ foreach my $nick (keys %saved_colors) {
+ Irssi::print (chr (3) . "$saved_colors{$nick}$nick" .
+ chr (3) . "1 ($saved_colors{$nick})");
+ }
+ } elsif ($op eq "preview") {
+ Irssi::print ("\nAvailable colors:");
+ foreach my $i (2..14) {
+ Irssi::print (chr (3) . "$i" . "Color #$i");
+ }
+ }
+}
+
+load_colors;
+
+Irssi::command_bind('color', 'cmd_color');
+
+Irssi::signal_add('message public', 'sig_public');
+Irssi::signal_add('event nick', 'sig_nick');
diff --git a/.irssi/scripts/autorun/trackbar.pl b/.irssi/scripts/autorun/trackbar.pl
new file mode 100644
index 0000000..7123330
--- /dev/null
+++ b/.irssi/scripts/autorun/trackbar.pl
@@ -0,0 +1,189 @@
+# trackbar.pl
+#
+# This little script will do just one thing: it will draw a line each time you
+# switch away from a window. This way, you always know just upto where you've
+# been reading that window :) It also removes the previous drawn line, so you
+# don't see double lines.
+#
+# Usage:
+#
+# The script works right out of the box, but if you want you can change
+# the working by /set'ing the following variables:
+#
+# trackbar_string The characters to repeat to draw the bar
+# trackbar_style The style for the bar, %r is red for example
+# See formats.txt that came with irssi
+#
+# /mark is a command that will redraw the line at the bottom. However! This
+# requires irssi version after 20021228. otherwise you'll get the error
+# redraw: unknown command, and your screen is all goofed up :)
+#
+# /upgrade & buf.pl notice: This version tries to remove the trackbars before
+# the upgrade is done, so buf.pl does not restore them, as they are not removeable
+# afterwards by trackbar. Unfortiounatly, to make this work, trackbar and buf.pl
+# need to be loaded in a specific order. Please experiment to see which order works
+# for you (strangely, it differs from configuration to configuration, something I will
+# try to fix in a next version)
+#
+# Authors:
+# - Main maintainer & author: Peter 'kinlo' Leurs
+# - Many thanks to Timo 'cras' Sirainen for placing me on my way
+# - on-upgrade-remove-line patch by Uwe Dudenhoeffer
+#
+# Version history:
+# 1.4: - Changed our's by my's so the irssi script header is valid
+# - Removed utf-8 support. In theory, the script should work w/o any
+# problems for utf-8, just set trackbar_string to a valid utf-8 character
+# and everything *should* work. However, this script is being plagued by
+# irssi internal bugs. The function Irssi::settings_get_str does NOT handle
+# unicode strings properly, hence you will notice problems when setting the bar
+# to a unicode char. For changing your bar to utf-8 symbols, read the line sub.
+# 1.3: - Upgrade now removes the trackbars.
+# - Some code cleanups, other defaults
+# - /mark sets the line to the bottom
+# 1.2: - Support for utf-8
+# - How the bar looks can now be configured with trackbar_string
+# and trackbar_style
+# 1.1: - Fixed bug when closing window
+# 1.0: - Initial release
+#
+#
+# Call for help!
+#
+# There is a trackbar version 2.0 that properly handles resizes and immediate config change
+# activation. However, there is/are some bug(s) in irssi's main buffer/window code that causes
+# irssi to 'forget' lines, which is ofcourse completly unaccepteable. I haven't found the time
+# nor do I know the irssi's internals enough to find and fix this bug, if you want to help, please
+# contact me, I'll give you a copy of the 2.0 version that will immediatly show you the problems.
+#
+# Known bugs:
+# - if you /clear a window, it will be uncleared when returning to the window
+# - UTF-8 characters in the trackbar_string doesnt work. This is an irssi bug.
+# - if you resize your irssi (in xterm or so) the bar is not resized
+# - changing the trackbar style is only visible after returning to a window
+# however, changing style/resize takes in effect after you left the window.
+#
+# Whishlist/todo:
+# - instead of drawing a line, just invert timestamp or something,
+# to save a line (but I don't think this is possible with current irssi)
+# - some pageup keybinding possibility, to scroll up upto the trackbar
+# - <@coekie> kinlo: if i switch to another window, in another split window, i
+# want the trackbar to go down in the previouswindow in that splitwindow :)
+# - < bob_2> anyway to clear the line once the window is read?
+# - < elho> kinlo: wishlist item: a string that gets prepended to the repeating pattern
+# - < elho> an option to still have the timestamp in front of the bar
+# - < elho> oh and an option to not draw it in the status window :P
+#
+# BTW: when you have feature requests, mailing a patch that works is the fastest way
+# to get it added :p
+
+use strict;
+use 5.6.1;
+use Irssi;
+use Irssi::TextUI;
+
+my $VERSION = "1.4";
+
+my %IRSSI = (
+ authors => "Peter 'kinlo' Leurs",
+ contact => "peter\@pfoe.be",
+ name => "trackbar",
+ description => "Shows a bar where you've last read a window",
+ license => "GPLv2",
+ url => "http://www.pfoe.be/~peter/trackbar/",
+ changed => "Thu Feb 20 16:18:08 2003",
+);
+
+my %config;
+
+Irssi::settings_add_str('trackbar', 'trackbar_string' => '-');
+$config{'trackbar_string'} = Irssi::settings_get_str('trackbar_string');
+
+Irssi::settings_add_str('trackbar', 'trackbar_style' => '%K');
+$config{'trackbar_style'} = Irssi::settings_get_str('trackbar_style');
+
+Irssi::signal_add(
+ 'setup changed' => sub {
+ $config{'trackbar_string'} = Irssi::settings_get_str('trackbar_string');
+ $config{'trackbar_style'} = Irssi::settings_get_str('trackbar_style');
+ if ($config{'trackbar_style'} =~ /(?<!%)[^%]|%%|%$/) {
+ Irssi::print(
+ "trackbar: %RWarning!%n 'trackbar_style' seems to contain "
+ . "printable characters. Only use format codes (read "
+ . "formats.txt).", MSGLEVEL_CLIENTERROR);
+ }
+ }
+);
+
+Irssi::signal_add(
+ 'window changed' => sub {
+ my (undef, $oldwindow) = @_;
+
+ if ($oldwindow) {
+ my $line = $oldwindow->view()->get_bookmark('trackbar');
+ $oldwindow->view()->remove_line($line) if defined $line;
+ $oldwindow->print(line($oldwindow->{'width'}), MSGLEVEL_NEVER);
+ $oldwindow->view()->set_bookmark_bottom('trackbar');
+ }
+ }
+);
+
+sub line {
+ my $width = shift;
+ my $string = $config{'trackbar_string'};
+ $string = '-' unless defined $string;
+
+ # There is a bug in irssi's utf-8 handling on config file settings, as you
+ # can reproduce/see yourself by the following code sniplet:
+ #
+ # my $quake = pack 'U*', 8364; # EUR symbol
+ # Irssi::settings_add_str 'temp', 'temp_foo' => $quake;
+ # Irssi::print length $quake;
+ # # prints 1
+ # Irssi::print length Irssi::settings_get_str 'temp_foo';
+ # # prints 3
+ #
+ #
+ # Trackbar used to have a workaround, but on recent versions of perl/irssi
+ # it does no longer work. Therefore, if you want your trackbar to contain
+ # unicode characters, uncomment the line below for a nice full line, or set
+ # the string to whatever char you want.
+
+ # $string = pack('U*', 0x2500);
+
+
+ my $length = length $string;
+
+ if ($length == 0) {
+ $string = '-';
+ $length = 1;
+ }
+
+ my $times = $width / $length;
+ $times = int(1 + $times) if $times != int($times);
+ $string =~ s/%/%%/g;
+ return $config{'trackbar_style'} . substr($string x $times, 0, $width);
+}
+
+# Remove trackbars on upgrade - but this doesn't really work if the scripts are not loaded in the correct order... watch out!
+
+Irssi::signal_add_first( 'session save' => sub {
+ for my $window (Irssi::windows) {
+ next unless defined $window;
+ my $line = $window->view()->get_bookmark('trackbar');
+ $window->view()->remove_line($line) if defined $line;
+ }
+ }
+);
+
+sub cmd_mark {
+ my $window = Irssi::active_win();
+# return unless defined $window;
+ my $line = $window->view()->get_bookmark('trackbar');
+ $window->view()->remove_line($line) if defined $line;
+ $window->print(line($window->{'width'}), MSGLEVEL_NEVER);
+ $window->view()->set_bookmark_bottom('trackbar');
+ Irssi::command("redraw");
+}
+
+Irssi::command_bind('mark', 'cmd_mark');
diff --git a/.irssi/scripts/bitlbee_tab_completion.pl b/.irssi/scripts/bitlbee_tab_completion.pl
new file mode 100644
index 0000000..82cbe8f
--- /dev/null
+++ b/.irssi/scripts/bitlbee_tab_completion.pl
@@ -0,0 +1,196 @@
+use strict;
+use vars qw(%topics);
+use vars qw($VERSION %IRSSI);
+use Irssi qw(signal_add_last signal_add_first settings_add_bool settings_add_str
+ settings_get_bool settings_get_str signal_stop);
+use Irssi::Irc;
+
+$VERSION = '1.00';
+
+%IRSSI = (
+ authors => 'Tijmen Ruizendaal & Wilmer van der Gaast',
+ contact => 'timing@fokdat.nl timing@OFTC',
+ name => 'BitlBee_tab_completion',
+ description => 'Intelligent Tab-completion for Bitlbee commands (for more info: http://www.bitlbee.org).',
+ license => 'GPLv2',
+ url => 'http://fokdat.nl/~tijmen/software/index.html',
+ changed => '05-18-2004',
+);
+
+my $debug = 0; ## change this into 1 if you want to see some output in your control panel, it's not much, so don't be scared.
+
+## Hardcoded defaults, most of these will be auto-guessed when the BitlBee server supports this.
+
+my $root_nick = 'root';
+my $bitlbee_channel = '#bitlbee';
+my $getting_completions = '0';
+
+my @commands = ('account','allow','block','blist','help','identify','info','nick','qlist','register','remove','rename','save','set');
+my @setlist = ('auto_connect','auto_reconnect','auto_reconnect_delay','away_devoice','buddy_sendbuffer','buddy_sendbuffer_delay','charset','debug','handle_unknown','html','ops','private','save_on_quit','typing_notice','to_char');
+my @helplist = ('away','commands','groupchats','groupchats2','groupchats3','index','quickstart','quickstart2','quickstart3','quickstart4','quickstart5','smileys');
+
+my @accountlist = ('add','del','list','on','off');
+my @blist = ('all','away','offline','online');
+my @boolean = ('true', 'false');
+my @handle_unknown = ('root', 'add', 'add_private', 'add_channel', 'ignore');
+my @ops = ('both', 'root', 'user', 'none');
+my @html = ('strip', 'nostrip');
+
+##pfft, done with that...
+
+my $i;
+
+for $i ( @commands )
+{
+ @helplist = ( @helplist, $i );
+}
+
+signal_add_last 'channel sync' => sub {
+ my( $channel ) = @_;
+ my( $server ) = $channel->{server};
+
+ if( $channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information." )
+ {
+ $bitlbee_channel = $channel->{name};
+ $getting_completions = 1;
+ $server->send_raw( 'COMPLETIONS' );
+ if($debug == 1){
+ print( 'Detected a #bitlbee: ' . $channel->{name} );
+ }
+ }
+};
+
+signal_add_last 'message irc notice' => sub {
+ my( $server, $msg, $from, $address, $target ) = @_;
+
+ ## Ignore the notice if we have the completions already.
+ return unless $getting_completions;
+
+ if( $msg =~ s/^COMPLETIONS // )
+ {
+ $root_nick = $from;
+ if( $msg eq 'OK' )
+ {
+ ## We're sure that the server supports the COMPLETIONS
+ ## command now, so let's flush our hardcoded stuff.
+ @commands = @setlist = @helplist = ();
+ if($debug == 1)
+ {
+ print( 'COMPLETIONS fetching supported!' );
+ }
+ }
+ elsif( $msg eq 'END' )
+ {
+ ## Ignore further notices.
+ $getting_completions = 0;
+ if($debug == 1)
+ {
+ print( 'COMPLETIONS fetching finished!' );
+ }
+ }
+ elsif( $msg =~ s/^help // )
+ {
+ @helplist = ( @helplist, $msg );
+ }
+ elsif( $msg =~ s/^set // )
+ {
+ @setlist = ( @setlist, $msg );
+ }
+ else
+ {
+ @commands = ( @commands, $msg );
+ }
+
+ signal_stop();
+ }
+};
+
+signal_add_last 'complete word' => sub {
+ my ($complist, $window, $word, $linestart, $want_space) = @_;
+ my $channel = $window->get_active_name();
+ if ($channel eq $bitlbee_channel or $channel eq $root_nick or $linestart =~ /^\/(msg|query) \Q$root_nick\E */i){
+ $linestart =~ s/^\/(msg|query) \Q$root_nick\E *//i;
+ $linestart =~ s/^\Q$root_nick\E[:,] *//i;
+ if ($linestart eq ""){
+ foreach my $command(@commands)
+ {
+ if ($command =~ /^$word/i)
+ {
+ push @$complist, $command;
+ }
+ }
+ }elsif ($linestart eq "set" or $linestart eq "help set")
+ {
+ foreach my $set(@setlist)
+ {
+ if ($set =~ /^$word/i)
+ {
+ push @$complist, $set;
+ }
+ }
+ }elsif ($linestart eq "help")
+ {
+ foreach my $help(@helplist)
+ {
+ if ($help =~ /^$word/i)
+ {
+ push @$complist, $help;
+ }
+ }
+ }elsif ($linestart eq "blist")
+ {
+ foreach my $list(@blist)
+ {
+ if ($list =~ /^$word/i)
+ {
+ push @$complist, $list;
+ }
+ }
+ }elsif ($linestart eq "account" || $linestart eq "help account")
+ {
+ foreach my $account(@accountlist)
+ {
+ if ($account =~ /^$word/i)
+ {
+ push @$complist, $account;
+ }
+ }
+ }elsif($linestart eq 'set away_devoice' || $linestart eq 'set auto_connect' || $linestart eq 'set auto_reconnect' || $linestart eq 'set buddy_sendbuffer' || $linestart eq 'set debug' || $linestart eq 'set private' || $linestart eq 'set save_on_quit' || $linestart eq 'set typing_notice')
+ {
+ foreach my $bool(@boolean)
+ {
+ if ($bool =~ /^$word/i)
+ {
+ push @$complist, $bool;
+ }
+ }
+ }elsif($linestart eq 'set handle_unknown')
+ {
+ foreach my $handle(@handle_unknown)
+ {
+ if ($handle =~ /^$word/i)
+ {
+ push @$complist, $handle;
+ }
+ }
+ }elsif($linestart eq 'set ops')
+ {
+ foreach my $op(@ops)
+ {
+ if ($op =~ /^$word/i)
+ {
+ push @$complist, $op;
+ }
+ }
+ }elsif($linestart eq 'set html')
+ {
+ foreach my $strip(@html)
+ {
+ if ($strip =~ /^$word/i)
+ {
+ push @$complist, $strip;
+ }
+ }
+ }
+ }
+};
diff --git a/.irssi/scripts/chanact.pl b/.irssi/scripts/chanact.pl
new file mode 100644
index 0000000..e4aa247
--- /dev/null
+++ b/.irssi/scripts/chanact.pl
@@ -0,0 +1,479 @@
+use Irssi 20020101.0001 ();
+use strict;
+use Irssi::TextUI;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "0.5.5";
+%IRSSI = (
+ authors => 'BC-bd, Veli',
+ contact => 'bd@bc-bd.org, veli@piipiip.net',
+ name => 'chanact',
+ description => 'Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias). Lets you give alias characters to windows so that you can select those with meta-<char>',
+ license => 'GNU GPLv2 or later',
+ url => 'http://bc-bd.org/software.php3#irssi'
+);
+
+# Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias).
+# Lets you give alias characters to windows so that you can select those with
+# meta-<char>.
+#
+# for irssi 0.8.2 by bd@bc-bd.org
+#
+# inspired by chanlist.pl by 'cumol@hammerhart.de'
+#
+#########
+# Contributors
+#########
+#
+# veli@piipiip.net /window_alias code
+# qrczak@knm.org.pl chanact_abbreviate_names
+# qerub@home.se Extra chanact_show_mode and chanact_chop_status
+#
+#########
+# USAGE
+###
+#
+# copy the script to ~/.irssi/scripts/
+#
+# In irssi:
+#
+# /script load chanact
+# /statusbar window add chanact -after act
+#
+# If you want the item to appear on another position read the help
+# for /statusbar.
+# To remove the [Act: 1,2,3] item type:
+#
+# /statusbar window remove act
+#
+# To see all chanact options type:
+#
+# / set chanact_
+#
+# After these steps you have your new statusbar item and you can start giving
+# aliases to your windows. Go to the window you want to give the alias to
+# and say:
+#
+# /window_alias <alias char>
+#
+# You can also remove the aliases with:
+#
+# /window_unalias <alias char>
+#
+# or in aliased window:
+#
+# /window_unalias
+#
+# To see a list of your windows use:
+#
+# /window list
+#
+#########
+# OPTIONS
+#########
+#
+# /set chanact_show_all <ON|OFF>
+# * ON : show all windows
+# * OFF : show only those with activity
+#
+# /set chanact_display <string>
+# * string : Format String for one Channel. The following $'s are expanded:
+# $C : Channel
+# $N : Number of the Window
+# $M : Mode in that channel
+# $H : Start highlightning
+# $S : Stop highlightning
+# * example:
+#
+# /set chanact_display $H$N:$M.$S$C
+#
+# will give you on #irssi.de if you have voice
+#
+# [3:+.#irssi.de]
+#
+# with '3:+.' highlighted and the channel name printed in regular color
+#
+# /set chanact_display_alias <string>
+# as 'chanact_display' but is used if the window has an alias and
+# 'chanact_show_alias' is set to on.
+#
+# /set chanact_show_names <ON|OFF>
+# * ON : show the channelnames after the number/alias
+# * OFF : don't show the names
+#
+# /set chanact_abbreviate_names <int>
+# * 0 : don't abbreviate
+# * <int> : strip channel name prefix character and leave only
+# that many characters of the proper name
+#
+# /set chanact_show_alias <ON|OFF>
+# * ON : show the aliase instead of the refnum
+# * OFF : shot the refnum
+#
+# /set chanact_separator <str>
+# * <str> : Characters to be displayed at the start of the item.
+# Defaults to: "Act: "
+#
+# /set chanact_separator <str>
+# * <str> : Charater to use between the channel entries
+#
+# /set chanact_autorenumber <ON|OFF>
+# * ON : Move the window automatically to first available slot
+# starting from "chanact_renumber_start" when assigning
+# an alias to window. Also moves the window back to a
+# first available slot from refnum 1 when the window
+# loses it's alias.
+# * OFF : Don't move the windows automatically
+#
+# /set chanact_renumber_start <int>
+# * <int> : Move the window to first available slot after this
+# num when "chanact_autorenumber" is ON.
+#
+#
+#########
+# HINTS
+#########
+#
+# If you have trouble with wrong colored entries your 'default.theme' might
+# be too old. Try on a shell:
+#
+# $ mv ~/.irssi/default.theme /tmp/
+#
+# And in irssi:
+# /reload
+# /save
+#
+###
+#################
+
+my ($actString,$needRemake);
+
+sub expand {
+ my ($string, %format) = @_;
+ my ($exp, $repl);
+ $string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
+ return $string;
+}
+
+# method will get called every time the statusbar item will be displayed
+# but we dont need to recreate the item every time so we first
+# check if something has changed and only then we recreate the string
+# this might just save some cycles
+# FIXME implement $get_size_only check, and user $item->{min|max-size}
+sub chanact {
+ my ($item, $get_size_only) = @_;
+
+ if ($needRemake) {
+ remake();
+ }
+
+ $item->default_handler($get_size_only, $actString, undef, 1);
+}
+
+# this is the real creation method
+sub remake() {
+ my ($afternumber,$finish,$hilight,$mode,$number,$display);
+ my $separator = Irssi::settings_get_str('chanact_separator');
+ my $abbrev = Irssi::settings_get_int('chanact_abbreviate_names');
+
+ $actString = "";
+ foreach my $win (sort { ($a->{refnum}) <=> ($b->{refnum})} Irssi::windows) {
+
+ # since irssi is single threaded this shouldn't happen
+ !ref($win) && next;
+
+ my $name = $win->get_active_name;
+ my $active = $win->{active};
+
+ !ref($win) && next;
+
+ # (status) is an awfull long name, so make it short to 'S'
+ # some people don't like it, so make it configurable
+ if (Irssi::settings_get_bool('chanact_chop_status')
+ && $name eq "(status)") {
+ $name = "S";
+ }
+
+ # check if we should show the mode
+ $mode = "";
+ if ($active->{type} eq "CHANNEL") {
+ my $server = $win->{active_server};
+ !ref($server) && next;
+
+ my $channel = $server->channel_find($name);
+ !ref($channel) && next;
+
+ my $nick = $channel->nick_find($server->{nick});
+ !ref($nick) && next;
+
+ if ($nick->{op}) {
+ $mode = "@";
+ } elsif ($nick->{voice}) {
+ $mode = "+";
+ } elsif ($nick->{halfop}) {
+ $mode = "%";
+ }
+ }
+
+ # find the right color
+ if ($win->{data_level} == 1) {
+ $hilight = "{sb_act_text ";
+ } elsif ($win->{data_level} == 2) {
+ $hilight = "{sb_act_msg ";
+ } elsif ($win->{data_level} == 3) {
+ $hilight = "{sb_act_hilight ";
+ } else {
+ if (Irssi::settings_get_bool('chanact_show_all') == 1) {
+ $hilight = "{%n ";
+ } else {
+ next;
+ }
+ }
+
+ if ($abbrev) {
+ if ($name =~ /^[&#+!=]/) {
+ $name = substr($name, 0, $abbrev + 1);
+ } else {
+ $name = substr($name, 0, $abbrev);
+ }
+ }
+
+ if (Irssi::settings_get_bool('chanact_show_alias') == 1 &&
+ $win->{name} =~ /^[a-zA-Z+]$/) {
+ $number = $win->{name};
+ $display = Irssi::settings_get_str('chanact_display_alias');
+ } else {
+ $number = $win->{refnum};
+ $display = Irssi::settings_get_str('chanact_display');
+ }
+
+ $actString .= expand($display,"C",$name,"N",$number,"M",$mode,"H",$hilight,"S","}{sb_background}").$separator;
+ }
+
+ # assemble the final string
+ if ($actString ne "") {
+ # Remove the last separator
+ $actString =~ s/$separator$//;
+
+ if (Irssi::settings_get_bool('chanact_show_all') == 1) {
+ $actString = "{sb ".$actString."}";
+ } else {
+ $actString = "{sb ".Irssi::settings_get_str('chanact_header').$actString."}";
+ }
+ }
+
+ # no remake needed any longer
+ $needRemake = 0;
+}
+
+# method called because of some events. here we dont remake the item but just
+# remember that we have to remake it the next time we are called
+sub chanactHasChanged()
+{
+ $needRemake = 1;
+
+ Irssi::statusbar_items_redraw('chanact');
+}
+
+# function by veli@piipiip.net
+# Remove alias
+sub cmd_window_unalias {
+ my ($data, $server, $witem) = @_;
+ my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
+
+ unless ($data =~ /^[a-zA-Z]$/ ||
+ Irssi::active_win()->{name} =~ /^[a-zA-Z]$/) {
+ Irssi::print("Usage: /window_unalias <char>");
+ Irssi::print("or /window_alias in window that has an alias.");
+ return;
+ }
+
+ if ($data eq '') { $data = Irssi::active_win()->{name}; }
+
+ if (my $oldwin = Irssi::window_find_name($data)) {
+ $oldwin->set_name(undef);
+ Irssi::print("Removed alias with the key '$data'.");
+
+ if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
+ $oldwin->{refnum} >= $rn_start) {
+ my $old_refnum = $oldwin->{refnum};
+
+ # Find the first available slot and move the window
+ my $newnum = 1;
+ while (Irssi::window_find_refnum($newnum) ne "") { $newnum++; }
+ $oldwin->set_refnum($newnum);
+
+ Irssi::print("and moved it to from $old_refnum to $newnum");
+ }
+ }
+}
+
+# function by veli@piipiip.net
+# Make an alias
+sub cmd_window_alias {
+ my ($data, $server, $witem) = @_;
+ my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
+
+ unless ($data =~ /^[a-zA-Z+]$/) {
+ Irssi::print("Usage: /window_alias <char>");
+ return;
+ }
+
+ cmd_window_unalias($data, $server, $witem);
+
+ my $window = $witem->window();
+ my $winnum = $window->{refnum};
+
+ if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
+ $window->{refnum} < $rn_start) {
+ my $old_refnum = $window->{refnum};
+
+ $winnum = $rn_start;
+
+ # Find the first available slot and move the window
+ while (Irssi::window_find_refnum($winnum) ne "") { $winnum++; }
+ $window->set_refnum($winnum);
+
+ Irssi::print("Moved the window from $old_refnum to $winnum");
+ }
+
+ $window->set_name($data);
+ $server->command("/bind meta-$data change_window $winnum");
+ Irssi::print("Window $winnum is now known as '$data'");
+}
+
+# function by veli@piipiip.net
+# Makes the aliases if names have already been set
+sub cmd_rebuild_aliases {
+ foreach (sort { $a->{refnum} <=> $b->{refnum} } Irssi::windows) {
+ if ($_->{name} =~ /^[a-zA-Z]$/) {
+ cmd_window_alias($_->{name}, $_->{active_server}, $_->{active});
+ }
+ }
+}
+
+# function by veli@piipiip.net
+# Change the binding if the window refnum changes.
+sub refnum_changed {
+ my ($window, $oldref) = @_;
+ my $server = Irssi::active_server();
+
+ if ($window->{name} =~ /^[a-zA-Z]$/) {
+ $server->command("/bind meta-".$window->{name}." change_window ".$window->{refnum});
+ }
+}
+
+$needRemake = 1;
+
+# Window alias command
+Irssi::command_bind('window_alias','cmd_window_alias');
+Irssi::command_bind('window_unalias','cmd_window_unalias');
+# Irssi::command_bind('window_alias_rebuild','cmd_rebuild_aliases');
+
+# our config item
+Irssi::settings_add_str('chanact', 'chanact_display', '$H$N:$M$C$S');
+Irssi::settings_add_str('chanact', 'chanact_display_alias', '$H$N$M$S');
+Irssi::settings_add_bool('chanact', 'chanact_show_all', 0);
+Irssi::settings_add_int('chanact', 'chanact_abbreviate_names', 0);
+Irssi::settings_add_bool('chanact', 'chanact_show_alias', 1);
+Irssi::settings_add_str('chanact', 'chanact_separator', " ");
+Irssi::settings_add_bool('chanact', 'chanact_autorenumber', 0);
+Irssi::settings_add_int('chanact', 'chanact_renumber_start', 50);
+Irssi::settings_add_str('chanact', 'chanact_header', "Act: ");
+Irssi::settings_add_bool('chanact', 'chanact_chop_status', 1);
+
+# register the statusbar item
+Irssi::statusbar_item_register('chanact', '$0', 'chanact');
+# according to cras we shall not call this
+# Irssi::statusbars_recreate_items();
+
+# register all that nifty callbacks on special events
+Irssi::signal_add_last('setup changed', 'chanactHasChanged');
+Irssi::signal_add_last('window hilight', 'chanactHasChanged');
+Irssi::signal_add("window created", "chanactHasChanged");
+Irssi::signal_add("window destroyed", "chanactHasChanged");
+Irssi::signal_add("window name changed", "chanactHasChanged");
+Irssi::signal_add('nick mode changed', 'chanactHasChanged');
+
+Irssi::signal_add_last('window refnum changed', 'refnum_changed');
+
+###############
+###
+#
+# Changelog
+#
+# 0.5.5
+# - some speedups from David Leadbeater <dgl@dgl.cx>
+#
+# 0.5.4
+# - added help for chanact_display_alias
+#
+# 0.5.3
+# - added '+' to the available chars of aliase's
+# - added chanact_display_alias to allow different display modes if the window
+# has an alias
+#
+# 0.5.2
+# - removed unused chanact_show_name settings (thx to Qerub)
+# - fixed $mode display
+# - guarded reference operations to (hopefully) fix errors on server disconnect
+#
+# 0.5.1
+# - small typo fixed
+#
+# 0.5.0
+# - changed chanact_show_mode to chanact_display. reversed changes from
+# Qerub through that, but kept funcionality.
+# - removed chanact_color_all since it is no longer needed
+#
+# 0.4.3
+# - changes by Qerub
+# + added chanact_show_mode to show the mode just before the channel name
+# + added chanact_chop_status to be able to control the (status) chopping
+# [bd] minor implementation changes
+# - moved Changelog to the end of the file since it is getting pretty big
+#
+# 0.4.2
+# - changed back to old version numbering sheme
+# - added '=' to Qrczak's chanact_abbreviate_names stuff :)
+# - added chanact_header
+#
+# 0.41q
+# - changes by Qrczak
+# + added setting 'chanact_abbreviate_names'
+# + windows are sorted by refnum; I didn't understand the old
+# logic and it broke sorting for numbers above 9
+#
+# 0.41
+# - minor updates
+# + fixed channel sort [veli]
+# + removed few typos and added some documentation [veli]
+#
+# 0.4
+# - merge with window_alias.pl
+# + added /window_alias from window_alias.pl by veli@piipiip.net
+# + added setting 'chanact_show_alias'
+# + added setting 'chanact_show_names'
+# + changed setting 'chanact_show_mode' to int
+# + added setting 'chanact_separator' [veli]
+# + added setting 'chanact_autorenumber' [veli]
+# + added setting 'chanact_renumber_start' [veli]
+# + added /window_unalias [veli]
+# + moved setting to their own group 'chanact' [veli]
+#
+# 0.3
+# - merge with chanlist.pl
+# + added setting 'chanact_show_mode'
+# + added setting 'chanact_show_all'
+#
+# 0.2
+# - added 'Act' to the item
+# - added setting 'chanact_color_all'
+# - finally found format for statusbar hilight
+#
+# 0.1
+# - Initial Release
+#
+###
+################
diff --git a/.irssi/scripts/mail.pl b/.irssi/scripts/mail.pl
new file mode 100644
index 0000000..33b3c22
--- /dev/null
+++ b/.irssi/scripts/mail.pl
@@ -0,0 +1,414 @@
+$VERSION = "2.92";
+%IRSSI = (
+ authors => "Timo Sirainen, Matti Hiljanen, Joost Vunderink, Bart Matthaei",
+ contact => "tss\@iki.fi, matti\@hiljanen.com, joost\@carnique.nl, bart\@dreamflow.nl",
+ name => "mail",
+ description => "Fully customizable mail counter statusbar item with multiple mailbox and multiple Maildir support",
+ license => "Public Domain",
+ url => "http://irssi.org, http://scripts.irssi.de",
+);
+
+# Mail counter statusbar item
+# for irssi 0.8.1 by Timo Sirainen
+#
+# Maildir support added by Matti Hiljanen
+# Multiple Maildir/mbox and customization support added by Joost Vunderink
+# OLD mailtreatment switch added by Bart Matthaei.
+# Improved some regexps in maildirmode by Bart Matthaei.
+# Maildirmode regexps (hopefully) fixed for good by Matti Hiljanen.
+#
+# You can add any number of mailboxes or Maildirs to watch for new mail in.
+# Give them any name and <name>:<count> will appear in your mail
+# statusbar item, where <count> is the number of unread messages.
+# If only 1 mailbox/Maildir is defined, the statusbar item will have the
+# familiar form [Mail: <count>].
+# If you set mail_show_message to ON, irssi will print a message in the
+# active window whenever new mail arrives.
+#
+# Check /mailbox help for help.
+
+use Irssi::TextUI;
+
+my $maildirmode = 0; # maildir=1, file(spools)=0
+my $old_is_not_new = 0;
+my $extprog;
+my ($last_refresh_time, $refresh_tag);
+
+# for mbox caching
+my $last_size, $last_mtime, $last_mailcount, $last_mode;
+
+# list of mailboxes
+my %mailboxes = ();
+my %new_mails_in_box = ();
+my $nummailboxes = 0;
+
+# the string to be stored in Irssi's mail_mailboxes setting
+my $mailboxsetting = "";
+
+sub cmd_print_help {
+ Irssi::print(
+ "MAILBOX ADD <num> <file|dir>\n".
+ "MAILBOX DEL <num>\n".
+ "MAILBOX SHOW\n\n".
+ "Statusbar item to keep track of how many (new) emails there are in ".
+ "each of your mailboxes/Maildirs.\n\n".
+ "/MAILBOX ADD <name> <file|dir>\n".
+ " - Adds a mailbox or a Maildir to the list.\n".
+ "/MAILBOX DEL <name>\n".
+ " - Removes mailbox or Maildir named <name> from the list.\n".
+ "/MAILBOX SHOW\n".
+ " - Shows a list of the defined mailboxes.\n\n".
+ "Use the following commands to change the behaviour:\n\n".
+ "/SET MAILDIRMODE on|off\n".
+ " - If maildirmode is on, the mailboxes in the list are assumed to be ".
+ "directories. Otherwise they are assumed to be spool files.\n".
+ " Default: off.\n".
+ "/SET MAIL_OLDNOTNEW on|off\n".
+ " - If switched on, mail marked als \"OLD\" will not be treated as new.\n".
+ " Default: off.\n".
+ "/SET MAIL_EXT_PROGRAM <prog>\n".
+ " - <prog> will be used to check for mail.\n".
+ "/SET MAIL_REFRESH_TIME <num>\n".
+ " - Sets the time between checks to <num> seconds.\n Default: 60.\n".
+ "/SET MAIL_SHOW_MESSAGE on|off\n".
+ " - If this is on, a message will be printed in the active window ".
+ "whenever new email is received.\n Default: off.\n".
+ "/SET MAIL_SHOW_ONLY_UNREAD on|off\n".
+ " - If you don't want to see a mailbox if it does not contain any new ".
+ "mail, set this to on.\n Default: on.\n" .
+ "/SET MAIL_SEPARATOR <char>\n".
+ " - Sets the character to be printed between each mailbox.\n".
+ " The default is a comma.\n".
+ "/SET MAIL_FORMAT <format>\n".
+ " - Sets the format of each mailbox.\n".
+ " Allowed variables:\n".
+ " %%n = mailbox name\n".
+ " %%u = number of unread mail\n".
+ " %%r = number of read mail\n".
+ " %%t = total amount of mail\n".
+ " The default format is %%n:%%u/%%t.\n".
+ "\nSee also: STATUSBAR"
+ ,MSGLEVEL_CRAP);
+}
+
+sub mbox_count {
+ my $mailfile = shift;
+ my $unread = 0;
+ my $read = 0;
+ my $maildirmode=Irssi::settings_get_bool('maildir_mode');
+ my $old_is_not_new=Irssi::settings_get_bool('mail_oldnotnew');
+
+ if ($extprog ne "") {
+ $total = `$extprog`;
+ chomp $unread;
+ } else {
+ if (!$maildirmode) {
+ if (-f $mailfile) {
+ my @stat = stat($mailfile);
+ my $size = $stat[7];
+ my $mtime = $stat[9];
+
+ # if the file hasn't changed, get the count from cache
+ return $last_mailcount if ($last_size == $size && $last_mtime == $mtime);
+ $last_size = $size;
+ $last_mtime = $mtime;
+
+ my $f = gensym;
+ return 0 if (!open($f, $mailfile));
+
+ # count new mails only
+ my $internal_removed = 0;
+ while (<$f>) {
+ $unread++ if (/^From /);
+
+ if(!$old_is_not_new) {
+ $unread-- if (/^Status: R/);
+ } else {
+ $unread-- if (/^Status: [OR]/);
+ }
+
+ $read++ if (/^From /);
+
+ # Remove folder internal data, but only once
+ if (/^Subject: .*FOLDER INTERNAL DATA/) {
+ if ($internal_removed == 0) {
+ $internal_removed = 1;
+ $read--;
+ $unread--;
+ }
+ }
+ }
+ close($f);
+ }
+ } else {
+ opendir(DIR, "$mailfile/cur") or return 0;
+ while (defined(my $file = readdir(DIR))) {
+ next if $file =~ /^(.|..)$/;
+ # Maildir flags: http://cr.yp.to/proto/maildir.html
+ # My old regexps were useless if the MUA added any
+ # non-default flags -qvr
+ #
+ # deleted mail
+ next if $file =~ /\:.*?T.*?$/;
+ if($old_is_not_new) {
+ # when mail gets moved from new to cur it's name _always_
+ # changes from uniq to uniq:info, even when it's still not
+ # read. I assume "old mail" means mail which hasn't been read
+ # yet but it has been "acknowledged" by the user. (it's been
+ # moved to cur) -qvr
+ if ($file =~ /\:.*?$/) {
+ $read++;
+ next;
+ }
+ } else {
+ if ($file =~ /\:.*?S.*?$/) {
+ $read++;
+ next;
+ }
+ }
+ $unread++;
+ }
+ closedir(DIR);
+
+ opendir(DIR, "$mailfile/new") or return 0;
+ while (defined(my $file = readdir(DIR))) {
+ next if $file =~ /^(.|..)$/;
+ $unread++;
+ }
+ closedir(DIR);
+ }
+ }
+
+ if ($unread eq "" || $unread < 0) {
+ $unread = 0;
+ }
+ if ($read eq "" || $read < 0) {
+ $read = 0;
+ }
+
+ $last_mailcount = $unread;
+
+ return ($unread, $read);
+}
+
+# Checks for mail and sets the statusbar item to the right string.
+# Also shows a message in the active window if that setting is set.
+sub mail {
+ my ($item, $get_size_only) = @_;
+
+ my $result;
+ my $format = Irssi::settings_get_str('mail_format');
+ my $unread = 0;
+ my $read = 0;
+ my $total = 0;
+
+ # check all mailboxes for new email
+ foreach $name (keys(%mailboxes)) {
+ my $box = $mailboxes{$name};
+ # replace "~/" at the beginning by the user's home dir
+ $box =~ s/^~\//$ENV{'HOME'}\//;
+
+ ($unread, $read) = mbox_count($box);
+ $unread = "0" if ($unread eq "");
+ $read = "0" if ($read eq "");
+ $total = $unread + $read;
+ $total = "0" if ($total eq "");
+
+ next if (Irssi::settings_get_bool('mail_show_only_unread') && $unread == 0);
+
+ if ($total eq "") { $total = 0; }
+ if (length($result) > 0) {
+ $result .= Irssi::settings_get_str('mail_separator');
+ }
+ my $string = $format;
+ $string =~ s/%n/$name/;
+ $string =~ s/%u/$unread/;
+ $string =~ s/%r/$read/;
+ $string =~ s/%t/$total/;
+ $result .= $string;
+
+ # Show -!- You have <num> new messages in <name>.
+ # Show this only if there are any new, unread messages.
+ if (Irssi::settings_get_bool('mail_show_message') &&
+ $unread > $new_mails_in_box{$name}) {
+ $new_mails = $unread - $new_mails_in_box{$name};
+ if ($nummailboxes == 1) {
+ Irssi::print("You have $new_mails new message" . ($new_mails != 1 ? "s." : "."), MSGLEVEL_CRAP);
+ } else {
+ Irssi::print("You have $new_mails new message" . ($new_mails != 1 ? "s " : " ") . "in $name.", MSGLEVEL_CRAP);
+ }
+ }
+
+ $new_mails_in_box{$name} = $unread;
+ }
+
+ if (length($result) == 0) {
+ # no mail - don't print the [Mail: ] at all
+ if ($get_size_only) {
+ $item->{min_size} = $item->{max_size} = 0;
+ }
+ } else {
+ $item->default_handler($get_size_only, undef, $result, 1);
+ }
+}
+
+sub refresh_mail {
+ Irssi::statusbar_items_redraw('mail');
+}
+
+# Adds the mailboxes from a string. Only to be used during startup.
+sub add_mailboxes {
+ my $boxstring = $_[0];
+ my @boxes = split(/,/, $boxstring);
+
+ foreach $dbox(@boxes) {
+ my $name = $dbox;
+ $name = substr($dbox, 0, index($dbox, '='));
+ my $box = $dbox;
+ $box = substr($dbox, index($dbox, '=') + 1, length($dbox));
+ addmailbox($name, $box);
+ }
+}
+
+sub addmailbox {
+ my ($name, $box) = @_;
+
+ if (exists($mailboxes{$name})) {
+ if ($box eq $mailboxes{$name}) {
+ Irssi::print("Mailbox $name already set to $box", MSGLEVEL_CRAP);
+ } else {
+ Irssi::print("Mailbox $name changed to $box", MSGLEVEL_CRAP);
+ $new_mails_in_box{$name} = 0;
+ }
+ } else {
+ Irssi::print("Mailbox $name added: " . $box, MSGLEVEL_CRAP);
+ $new_mails_in_box{$name} = 0;
+ $nummailboxes++;
+ }
+ $mailboxes{$name} = $box;
+}
+
+sub delmailbox {
+ my $name = $_[0];
+
+ if (exists($mailboxes{$name})) {
+ Irssi::print("Mailbox $name removed", MSGLEVEL_CRAP);
+ delete($mailboxes{$name});
+ delete($new_mails_in_box{$name});
+ $nummailboxes--;
+ } else {
+ Irssi::print("No such mailbox $name. Use /mailbox show to see a list.", MSGLEVEL_CRAP);
+ }
+}
+
+sub update_settings_string {
+ my $setting;
+
+ foreach $name (keys(%mailboxes)) {
+ $setting .= $name . "=" . $mailboxes{$name} . ",";
+ }
+
+ Irssi::settings_set_str("mail_mailboxes", $setting);
+}
+
+sub cmd_addmailbox {
+ my ($name, $box) = split(/ +/, $_[0]);
+
+ if ($name eq "" || $box eq "") {
+ Irssi::print("Use /mailbox add <name> <mailbox> to add a mailbox.", MSGLEVEL_CRAP);
+ return;
+ }
+
+ addmailbox($name, $box);
+ update_settings_string();
+ refresh_mail();
+}
+
+sub cmd_delmailbox {
+ my $name = $_[0];
+
+ if ($name eq "") {
+ Irssi::print("Use /mailbox del <name> to delete a mailbox.", MSGLEVEL_CRAP);
+ return;
+ }
+
+ delmailbox($name);
+ update_settings_string();
+ refresh_mail();
+}
+
+sub cmd_showmailboxes {
+ if ($nummailboxes == 0) {
+ Irssi::print("No mailboxes defined.", MSGLEVEL_CRAP);
+ return;
+ }
+ Irssi::print("Mailboxes:", MSGLEVEL_CRAP);
+ foreach $box (keys(%mailboxes)) {
+ Irssi::print("$box: " . $mailboxes{$box}, MSGLEVEL_CRAP);
+ }
+}
+
+sub cmd_mailboxes {
+ my ($data, $server, $item) = @_;
+ if ($data =~ m/^[(show)|(add)|(del)]/i ) {
+ Irssi::command_runsub ('mailbox', $data, $server, $item);
+ }
+ else {
+ Irssi::print("Use /mailbox (show|add|del).")
+ }
+}
+
+sub init_mailboxes {
+ # Add the mailboxes at startup of the script
+ my $boxes = Irssi::settings_get_str('mail_mailboxes');
+ if (length($boxes) > 0) {
+ add_mailboxes($boxes);
+ }
+}
+
+sub read_settings {
+ $extprog = Irssi::settings_get_str('mail_ext_program');
+ my $time = Irssi::settings_get_int('mail_refresh_time');
+ my $mode = Irssi::settings_get_bool('maildir_mode');
+ unless ($time == $last_refresh_time) {
+ $last_refresh_time = $time;
+ Irssi::timeout_remove($refresh_tag) if ($refresh_tag);
+ $refresh_tag = Irssi::timeout_add($time*1000, 'refresh_mail', undef);
+ }
+ return if ($mode == $last_mode);
+ $last_mode = $mode;
+ refresh_mail;
+}
+
+
+if (!$maildirmode) {
+ my $default = "1=" . $ENV{'MAIL'} . ",";
+ Irssi::settings_add_str('misc', 'mail_mailboxes', $default);
+} else {
+ my $default = "1=~/Maildir/,";
+ Irssi::settings_add_str('misc', 'mail_mailboxes', $default);
+}
+
+Irssi::command_bind('mailbox show', 'cmd_showmailboxes');
+Irssi::command_bind('mailbox add', 'cmd_addmailbox');
+Irssi::command_bind('mailbox del', 'cmd_delmailbox');
+Irssi::command_bind('mailbox help', 'cmd_print_help');
+Irssi::command_bind('mailbox', 'cmd_mailboxes');
+
+Irssi::settings_add_str('misc', 'mail_ext_program', '');
+Irssi::settings_add_int('misc', 'mail_refresh_time', 60);
+Irssi::settings_add_bool('misc', 'maildir_mode', "$maildirmode");
+Irssi::settings_add_bool('misc', 'mail_oldnotnew', "$old_is_not_new");
+Irssi::settings_add_str('misc', 'mail_separator', ",");
+Irssi::settings_add_bool('misc', 'mail_show_message', "0");
+Irssi::settings_add_str('misc', 'mail_format', '%n:%u/%t');
+Irssi::settings_add_bool('misc', 'mail_show_only_unread', "1");
+
+Irssi::statusbar_item_register('mail', '{sb Mail: $0-}', 'mail');
+
+read_settings();
+init_mailboxes();
+Irssi::signal_add('setup changed', 'read_settings');
+refresh_mail();
+
+# EOF
diff --git a/.irssi/scripts/nickcolor.pl b/.irssi/scripts/nickcolor.pl
new file mode 100644
index 0000000..69f2936
--- /dev/null
+++ b/.irssi/scripts/nickcolor.pl
@@ -0,0 +1,156 @@
+use strict;
+use Irssi 20020101.0250 ();
+use vars qw($VERSION %IRSSI);
+$VERSION = "1";
+%IRSSI = (
+ authors => "Timo Sirainen, Ian Peters",
+ contact => "tss\@iki.fi",
+ name => "Nick Color",
+ description => "assign a different color for each nick",
+ license => "Public Domain",
+ url => "http://irssi.org/",
+ changed => "2002-03-04T22:47+0100"
+);
+
+# hm.. i should make it possible to use the existing one..
+Irssi::theme_register([
+ 'pubmsg_hilight', '{pubmsghinick $0 $3 $1}$2'
+]);
+
+my %saved_colors;
+my %session_colors = {};
+my @colors = qw/2 3 4 5 6 7 9 10 11 12 13/;
+
+sub load_colors {
+ open COLORS, "$ENV{HOME}/.irssi/saved_colors";
+
+ while (<COLORS>) {
+ # I don't know why this is necessary only inside of irssi
+ my @lines = split "\n";
+ foreach my $line (@lines) {
+ my($nick, $color) = split ":", $line;
+ $saved_colors{$nick} = $color;
+ }
+ }
+
+ close COLORS;
+}
+
+sub save_colors {
+ open COLORS, ">$ENV{HOME}/.irssi/saved_colors";
+
+ foreach my $nick (keys %saved_colors) {
+ print COLORS "$nick:$saved_colors{$nick}\n";
+ }
+
+ close COLORS;
+}
+
+# If someone we've colored (either through the saved colors, or the hash
+# function) changes their nick, we'd like to keep the same color associated
+# with them (but only in the session_colors, ie a temporary mapping).
+
+sub sig_nick {
+ my ($server, $newnick, $nick, $address) = @_;
+ my $color;
+
+ $newnick = substr ($newnick, 1) if ($newnick =~ /^:/);
+
+ if ($color = $saved_colors{$nick}) {
+ $session_colors{$newnick} = $color;
+ } elsif ($color = $session_colors{$nick}) {
+ $session_colors{$newnick} = $color;
+ }
+}
+
+# This gave reasonable distribution values when run across
+# /usr/share/dict/words
+
+sub simple_hash {
+ my ($string) = @_;
+ chomp $string;
+ my @chars = split //, $string;
+ my $counter;
+
+ foreach my $char (@chars) {
+ $counter += ord $char;
+ }
+
+ $counter = $colors[$counter % 11];
+
+ return $counter;
+}
+
+# FIXME: breaks /HILIGHT etc.
+sub sig_public {
+ my ($server, $msg, $nick, $address, $target) = @_;
+ my $chanrec = $server->channel_find($target);
+ return if not $chanrec;
+ my $nickrec = $chanrec->nick_find($nick);
+ return if not $nickrec;
+ my $nickmode = $nickrec->{op} ? "@" : $nickrec->{voice} ? "+" : "";
+
+ # Has the user assigned this nick a color?
+ my $color = $saved_colors{$nick};
+
+ # Have -we- already assigned this nick a color?
+ if (!$color) {
+ $color = $session_colors{$nick};
+ }
+
+ # Let's assign this nick a color
+ if (!$color) {
+ $color = simple_hash $nick;
+ $session_colors{$nick} = $color;
+ }
+
+ $color = "0".$color if ($color < 10);
+ $server->command('/^format pubmsg {pubmsgnick $2 {pubnick '.chr(3).$color.'$0}}$1');
+}
+
+sub cmd_color {
+ my ($data, $server, $witem) = @_;
+ my ($op, $nick, $color) = split " ", $data;
+
+ $op = lc $op;
+
+ if (!$op) {
+ Irssi::print ("No operation given");
+ } elsif ($op eq "save") {
+ save_colors;
+ } elsif ($op eq "set") {
+ if (!$nick) {
+ Irssi::print ("Nick not given");
+ } elsif (!$color) {
+ Irssi::print ("Color not given");
+ } elsif ($color < 2 || $color > 14) {
+ Irssi::print ("Color must be between 2 and 14 inclusive");
+ } else {
+ $saved_colors{$nick} = $color;
+ }
+ } elsif ($op eq "clear") {
+ if (!$nick) {
+ Irssi::print ("Nick not given");
+ } else {
+ delete ($saved_colors{$nick});
+ }
+ } elsif ($op eq "list") {
+ Irssi::print ("\nSaved Colors:");
+ foreach my $nick (keys %saved_colors) {
+ Irssi::print (chr (3) . "$saved_colors{$nick}$nick" .
+ chr (3) . "1 ($saved_colors{$nick})");
+ }
+ } elsif ($op eq "preview") {
+ Irssi::print ("\nAvailable colors:");
+ foreach my $i (2..14) {
+ Irssi::print (chr (3) . "$i" . "Color #$i");
+ }
+ }
+}
+
+load_colors;
+
+Irssi::command_bind('color', 'cmd_color');
+
+Irssi::signal_add('message public', 'sig_public');
+Irssi::signal_add('event nick', 'sig_nick');
diff --git a/.irssi/scripts/nicklist.pl b/.irssi/scripts/nicklist.pl
new file mode 100644
index 0000000..0dbe4fb
--- /dev/null
+++ b/.irssi/scripts/nicklist.pl
@@ -0,0 +1,611 @@
+# for documentation: see http://wouter.coekaerts.be/site/irssi/nicklist
+
+use Irssi;
+use strict;
+use IO::Handle; # for (auto)flush
+use Fcntl; # for sysopen
+use vars qw($VERSION %IRSSI);
+$VERSION = '0.4.6';
+%IRSSI = (
+ authors => 'Wouter Coekaerts',
+ contact => 'coekie@irssi.org',
+ name => 'nicklist',
+ description => 'draws a nicklist to another terminal, or at the right of your irssi in the same terminal',
+ license => 'GPLv2',
+ url => 'http://wouter.coekaerts.be/irssi',
+ changed => '29/06/2004'
+);
+
+sub cmd_help {
+ print ( <<EOF
+Commands:
+NICKLIST HELP
+NICKLIST SCROLL <nr of lines>
+NICKLIST SCREEN
+NICKLIST FIFO
+NICKLIST OFF
+NICKLIST UPDATE
+
+For help see: http://wouter.coekaerts.be/site/irssi/nicklist
+
+in short:
+
+1. FIFO MODE
+- in irssi: /NICKLIST FIFO (only the first time, to create the fifo)
+- in a shell, in a window where you want the nicklist: cat ~/.irssi/nicklistfifo
+- back in irssi:
+ /SET nicklist_heigth <height of nicklist>
+ /SET nicklist_width <width of nicklist>
+ /NICKLIST FIFO
+
+2. SCREEN MODE
+- start irssi inside screen ("screen irssi")
+- /NICKLIST SCREEN
+EOF
+ );
+}
+
+my $prev_lines = 0; # number of lines in previous written nicklist
+my $scroll_pos = 0; # scrolling position
+my $cursor_line; # line the cursor is currently on
+my ($OFF, $SCREEN, $FIFO) = (0,1,2); # modes
+my $mode = $OFF; # current mode
+my $need_redraw = 0; # nicklist needs redrawing
+my $screen_resizing = 0; # terminal is being resized
+my $active_channel; # (REC)
+
+my @nicklist=(); # array of hashes, containing the internal nicklist of the active channel
+ # nick => realnick
+ # mode =>
+ my ($MODE_OP, $MODE_HALFOP, $MODE_VOICE, $MODE_NORMAL) = (0,1,2,3);
+ # status =>
+ my ($STATUS_NORMAL, $STATUS_JOINING, $STATUS_PARTING, $STATUS_QUITING, $STATUS_KICKED, $STATUS_SPLIT) = (0,1,2,3,4,5);
+ # text => text to be printed
+ # cmp => text used to compare (sort) nicks
+
+
+# 'cached' settings
+my ($screen_prefix, $irssi_width, @prefix_mode, @prefix_status, $height, $nicklist_width);
+
+sub read_settings {
+ ($screen_prefix = Irssi::settings_get_str('nicklist_screen_prefix')) =~ s/\\e/\033/g;
+
+ ($prefix_mode[$MODE_OP] = Irssi::settings_get_str('nicklist_prefix_mode_op')) =~ s/\\e/\033/g;
+ ($prefix_mode[$MODE_HALFOP] = Irssi::settings_get_str('nicklist_prefix_mode_halfop')) =~ s/\\e/\033/g;
+ ($prefix_mode[$MODE_VOICE] = Irssi::settings_get_str('nicklist_prefix_mode_voice')) =~ s/\\e/\033/g;
+ ($prefix_mode[$MODE_NORMAL] = Irssi::settings_get_str('nicklist_prefix_mode_normal')) =~ s/\\e/\033/g;
+
+ if ($mode != $SCREEN) {
+ $height = Irssi::settings_get_int('nicklist_height');
+ }
+ my $new_nicklist_width = Irssi::settings_get_int('nicklist_width');
+ if ($new_nicklist_width != $nicklist_width && $mode == $SCREEN) {
+ sig_terminal_resized();
+ }
+ $nicklist_width = $new_nicklist_width;
+}
+
+sub update {
+ read_settings();
+ make_nicklist();
+}
+
+##################
+##### OUTPUT #####
+##################
+
+### off ###
+
+sub cmd_off {
+ if ($mode == $SCREEN) {
+ screen_stop();
+ } elsif ($mode == $FIFO) {
+ fifo_stop();
+ }
+}
+
+### fifo ###
+
+sub cmd_fifo_start {
+ read_settings();
+ my $path = Irssi::settings_get_str('nicklist_fifo_path');
+ unless (-p $path) { # not a pipe
+ if (-e _) { # but a something else
+ die "$0: $path exists and is not a pipe, please remove it\n";
+ } else {
+ require POSIX;
+ POSIX::mkfifo($path, 0666) or die "can\'t mkfifo $path: $!";
+ Irssi::print("Fifo created. Start reading it (\"cat $path\") and try again.");
+ return;
+ }
+ }
+ if (!sysopen(FIFO, $path, O_WRONLY | O_NONBLOCK)) { # or die "can't write $path: $!";
+ Irssi::print("Couldn\'t write to the fifo ($!). Please start reading the fifo (\"cat $path\") and try again.");
+ return;
+ }
+ FIFO->autoflush(1);
+ print FIFO "\033[2J\033[1;1H"; # erase screen & jump to 0,0
+ $cursor_line = 0;
+ if ($mode == $SCREEN) {
+ screen_stop();
+ }
+ $mode = $FIFO;
+ make_nicklist();
+}
+
+sub fifo_stop {
+ close FIFO;
+ $mode = $OFF;
+ Irssi::print("Fifo closed.");
+}
+
+### screen ###
+
+sub cmd_screen_start {
+ if (!defined($ENV{'STY'})) {
+ Irssi::print 'screen not detected, screen mode only works inside screen';
+ return;
+ }
+ read_settings();
+ if ($mode == $SCREEN) {return;}
+ if ($mode == $FIFO) {
+ fifo_stop();
+ }
+ $mode = $SCREEN;
+ Irssi::signal_add_last('gui print text finished', \&sig_gui_print_text_finished);
+ Irssi::signal_add_last('gui page scrolled', \&sig_page_scrolled);
+ Irssi::signal_add('terminal resized', \&sig_terminal_resized);
+ screen_size();
+ make_nicklist();
+}
+
+sub screen_stop {
+ $mode = $OFF;
+ Irssi::signal_remove('gui print text finished', \&sig_gui_print_text_finished);
+ Irssi::signal_remove('gui page scrolled', \&sig_page_scrolled);
+ Irssi::signal_remove('terminal resized', \&sig_terminal_resized);
+ system 'screen -x '.$ENV{'STY'}.' -X fit';
+}
+
+sub screen_size {
+ if ($mode != $SCREEN) {
+ return;
+ }
+ $screen_resizing = 1;
+ # fit screen
+ system 'screen -x '.$ENV{'STY'}.' -X fit';
+ # get size (from perldoc -q size)
+ my ($winsize, $row, $col, $xpixel, $ypixel);
+ eval 'use Term::ReadKey; ($col, $row, $xpixel, $ypixel) = GetTerminalSize';
+ # require Term::ReadKey 'GetTerminalSize';
+ # ($col, $row, $xpixel, $ypixel) = Term::ReadKey::GetTerminalSize;
+ #};
+ if ($@) { # no Term::ReadKey, try the ugly way
+ eval {
+ require 'sys/ioctl.ph';
+ # without this reloading doesn't work. workaround for some unknown bug
+ do 'asm/ioctls.ph';
+ };
+
+ # ugly way not working, let's try something uglier, the dg-hack(tm) (constant for linux only?)
+ if($@) { no strict 'refs'; *TIOCGWINSZ = sub { return 0x5413 } }
+
+ unless (defined &TIOCGWINSZ) {
+ die "Term::ReadKey not found, and ioctl 'workaround' failed. Install the Term::ReadKey perl module to use screen mode.\n";
+ }
+ open(TTY, "+</dev/tty") or die "No tty: $!";
+ unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {
+ die "Term::ReadKey not found, and ioctl 'workaround' failed ($!). Install the Term::ReadKey perl module to use screen mode.\n";
+ }
+ close(TTY);
+ ($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
+ }
+
+ # set screen width
+ $irssi_width = $col-$nicklist_width-1;
+ $height = $row-1;
+
+ # on some recent systems, "screen -X fit; screen -X width -w 50" doesn't work, needs a sleep in between the 2 commands
+ # so we wait a second before setting the width
+ Irssi::timeout_add_once(1000, sub {
+ my ($new_irssi_width) = @_;
+ system 'screen -x '.$ENV{'STY'}.' -X width -w ' . $new_irssi_width;
+ # and then we wait another second for the resizing, and then redraw.
+ Irssi::timeout_add_once(1000,sub {$screen_resizing = 0; redraw()}, []);
+ }, $irssi_width);
+}
+
+sub sig_terminal_resized {
+ if ($screen_resizing) {
+ return;
+ }
+ $screen_resizing = 1;
+ Irssi::timeout_add_once(1000,\&screen_size,[]);
+}
+
+
+### both ###
+
+sub nicklist_write_start {
+ if ($mode == $SCREEN) {
+ print STDERR "\033P\033[s\033\\"; # save cursor
+ }
+}
+
+sub nicklist_write_end {
+ if ($mode == $SCREEN) {
+ print STDERR "\033P\033[u\033\\"; # restore cursor
+ }
+}
+
+sub nicklist_write_line {
+ my ($line, $data) = @_;
+ if ($mode == $SCREEN) {
+ print STDERR "\033P\033[" . ($line+1) . ';'. ($irssi_width+1) .'H'. $screen_prefix . $data . "\033\\";
+ } elsif ($mode == $FIFO) {
+ $data = "\033[m$data"; # reset color
+ if ($line == $cursor_line+1) {
+ $data = "\n$data"; # next line
+ } elsif ($line == $cursor_line) {
+ $data = "\033[1G".$data; # back to beginning of line
+ } else {
+ $data = "\033[".($line+1).";0H".$data; # jump
+ }
+ $cursor_line=$line;
+ print(FIFO $data) or fifo_stop();
+ }
+}
+
+# recalc the text of the nicklist item
+sub calc_text {
+ my ($nick) = @_;
+ my $tmp = $nicklist_width-3;
+ (my $text = $nick->{'nick'}) =~ s/^(.{$tmp})..+$/$1\033[34m~\033[m/;
+ $nick->{'text'} = $prefix_mode[$nick->{'mode'}] . $text . (' ' x ($nicklist_width-length($nick->{'nick'})-1));
+ $nick->{'cmp'} = $nick->{'mode'}.lc($nick->{'nick'});
+}
+
+# redraw the given nick (nr) if it is visible
+sub redraw_nick_nr {
+ my ($nr) = @_;
+ my $line = $nr - $scroll_pos;
+ if ($line >= 0 && $line < $height) {
+ nicklist_write_line($line, $nicklist[$nr]->{'text'});
+ }
+}
+
+# nick was inserted, redraw area if necessary
+sub draw_insert_nick_nr {
+ my ($nr) = @_;
+ my $line = $nr - $scroll_pos;
+ if ($line < 0) { # nick is inserted above visible area
+ $scroll_pos++; # 'scroll' down :)
+ } elsif ($line < $height) { # line is visible
+ if ($mode == $SCREEN) {
+ need_redraw();
+ } elsif ($mode == $FIFO) {
+ my $data = "\033[m\033[L". $nicklist[$nr]->{'text'}; # reset color & insert line & write nick
+ if ($line == $cursor_line) {
+ $data = "\033[1G".$data; # back to beginning of line
+ } else {
+ $data = "\033[".($line+1).";1H".$data; # jump
+ }
+ $cursor_line=$line;
+ print(FIFO $data) or fifo_stop();
+ if ($prev_lines < $height) {
+ $prev_lines++; # the nicklist has one line more
+ }
+ }
+ }
+}
+
+sub draw_remove_nick_nr {
+ my ($nr) = @_;
+ my $line = $nr - $scroll_pos;
+ if ($line < 0) { # nick removed above visible area
+ $scroll_pos--; # 'scroll' up :)
+ } elsif ($line < $height) { # line is visible
+ if ($mode == $SCREEN) {
+ need_redraw();
+ } elsif ($mode == $FIFO) {
+ #my $data = "\033[m\033[L[i$line]". $nicklist[$nr]->{'text'}; # reset color & insert line & write nick
+ my $data = "\033[M"; # delete line
+ if ($line != $cursor_line) {
+ $data = "\033[".($line+1)."d".$data; # jump
+ }
+ $cursor_line=$line;
+ print(FIFO $data) or fifo_stop();
+ if (@nicklist-$scroll_pos >= $height) {
+ redraw_nick_nr($scroll_pos+$height-1);
+ }
+ }
+ }
+}
+
+# redraw the whole nicklist
+sub redraw {
+ $need_redraw = 0;
+ #make_nicklist();
+ nicklist_write_start();
+ my $line = 0;
+ ### draw nicklist ###
+ for (my $i=$scroll_pos;$line < $height && $i < @nicklist; $i++) {
+ nicklist_write_line($line++, $nicklist[$i]->{'text'});
+ }
+
+ ### clean up other lines ###
+ my $real_lines = $line;
+ while($line < $prev_lines) {
+ nicklist_write_line($line++,' ' x $nicklist_width);
+ }
+ $prev_lines = $real_lines;
+ nicklist_write_end();
+}
+
+# redraw (with little delay to avoid redrawing to much)
+sub need_redraw {
+ if(!$need_redraw) {
+ $need_redraw = 1;
+ Irssi::timeout_add_once(10,\&redraw,[]);
+ }
+}
+
+sub sig_page_scrolled {
+ $prev_lines = $height; # we'll need to redraw everything if he scrolled up
+ need_redraw;
+}
+
+# redraw (with delay) if the window is visible (only in screen mode)
+sub sig_gui_print_text_finished {
+ if ($need_redraw) { # there's already a redraw 'queued'
+ return;
+ }
+ my $window = @_[0];
+ if ($window->{'refnum'} == Irssi::active_win->{'refnum'} || Irssi::settings_get_str('nicklist_screen_split_windows') eq '*') {
+ need_redraw;
+ return;
+ }
+ foreach my $win (split(/[ ,]/, Irssi::settings_get_str('nicklist_screen_split_windows'))) {
+ if ($window->{'refnum'} == $win || $window->{'name'} eq $win) {
+ need_redraw;
+ return;
+ }
+ }
+}
+
+####################
+##### NICKLIST #####
+####################
+
+# returns the position of the given nick(as string) in the (internal) nicklist
+sub find_nick {
+ my ($nick) = @_;
+ for (my $i=0;$i < @nicklist; $i++) {
+ if ($nicklist[$i]->{'nick'} eq $nick) {
+ return $i;
+ }
+ }
+ return -1;
+}
+
+# find position where nick should be inserted into the list
+sub find_insert_pos {
+ my ($cmp)= @_;
+ for (my $i=0;$i < @nicklist; $i++) {
+ if ($nicklist[$i]->{'cmp'} gt $cmp) {
+ return $i;
+ }
+ }
+ return scalar(@nicklist); #last
+}
+
+# make the (internal) nicklist (@nicklist)
+sub make_nicklist {
+ @nicklist = ();
+ $scroll_pos = 0;
+
+ ### get & check channel ###
+ my $channel = Irssi::active_win->{active};
+
+ if (!$channel || (ref($channel) ne 'Irssi::Irc::Channel' && ref($channel) ne 'Irssi::Silc::Channel') || $channel->{'type'} ne 'CHANNEL' || ($channel->{chat_type} ne 'SILC' && !$channel->{'names_got'}) ) {
+ $active_channel = undef;
+ # no nicklist
+ } else {
+ $active_channel = $channel;
+ ### make nicklist ###
+ my $thisnick;
+ foreach my $nick (sort {(($a->{'op'}?'1':$a->{'halfop'}?'2':$a->{'voice'}?'3':'4').lc($a->{'nick'}))
+ cmp (($b->{'op'}?'1':$b->{'halfop'}?'2':$b->{'voice'}?'3':'4').lc($b->{'nick'}))} $channel->nicks()) {
+ $thisnick = {'nick' => $nick->{'nick'}, 'mode' => ($nick->{'op'}?$MODE_OP:$nick->{'halfop'}?$MODE_HALFOP:$nick->{'voice'}?$MODE_VOICE:$MODE_NORMAL)};
+ calc_text($thisnick);
+ push @nicklist, $thisnick;
+ }
+ }
+ need_redraw();
+}
+
+# insert nick(as hash) into nicklist
+# pre: cmp has to be calculated
+sub insert_nick {
+ my ($nick) = @_;
+ my $nr = find_insert_pos($nick->{'cmp'});
+ splice @nicklist, $nr, 0, $nick;
+ draw_insert_nick_nr($nr);
+}
+
+# remove nick(as nr) from nicklist
+sub remove_nick {
+ my ($nr) = @_;
+ splice @nicklist, $nr, 1;
+ draw_remove_nick_nr($nr);
+}
+
+###################
+##### ACTIONS #####
+###################
+
+# scroll the nicklist, arg = number of lines to scroll, positive = down, negative = up
+sub cmd_scroll {
+ if (!$active_channel) { # not a channel active
+ return;
+ }
+ my @nicks=Irssi::active_win->{active}->nicks;
+ my $nick_count = scalar(@nicks)+0;
+ my $channel = Irssi::active_win->{active};
+ if (!$channel || $channel->{type} ne 'CHANNEL' || !$channel->{names_got} || $nick_count <= Irssi::settings_get_int('nicklist_height')) {
+ return;
+ }
+ $scroll_pos += @_[0];
+
+ if ($scroll_pos > $nick_count - $height) {
+ $scroll_pos = $nick_count - $height;
+ }
+ if ($scroll_pos <= 0) {
+ $scroll_pos = 0;
+ }
+ need_redraw();
+}
+
+sub is_active_channel {
+ my ($server,$channel) = @_; # (channel as string)
+ return ($server && $server->{'tag'} eq $active_channel->{'server'}->{'tag'} && $server->channel_find($channel) && $active_channel && $server->channel_find($channel)->{'name'} eq $active_channel->{'name'});
+}
+
+sub sig_channel_wholist { # this is actualy a little late, when the names are received would be better
+ my ($channel) = @_;
+ if (Irssi::active_win->{'active'} && Irssi::active_win->{'active'}->{'name'} eq $channel->{'name'}) { # the channel joined is active
+ make_nicklist
+ }
+}
+
+sub sig_join {
+ my ($server,$channel,$nick,$address) = @_;
+ if (!is_active_channel($server,$channel)) {
+ return;
+ }
+ my $newnick = {'nick' => $nick, 'mode' => $MODE_NORMAL};
+ calc_text($newnick);
+ insert_nick($newnick);
+}
+
+sub sig_kick {
+ my ($server, $channel, $nick, $kicker, $address, $reason) = @_;
+ if (!is_active_channel($server,$channel)) {
+ return;
+ }
+ my $nr = find_nick($nick);
+ if ($nr == -1) {
+ Irssi::print("nicklist warning: $nick was kicked from $channel, but not found in nicklist");
+ } else {
+ remove_nick($nr);
+ }
+}
+
+sub sig_part {
+ my ($server,$channel,$nick,$address, $reason) = @_;
+ if (!is_active_channel($server,$channel)) {
+ return;
+ }
+ my $nr = find_nick($nick);
+ if ($nr == -1) {
+ Irssi::print("nicklist warning: $nick has parted $channel, but was not found in nicklist");
+ } else {
+ remove_nick($nr);
+ }
+
+}
+
+sub sig_quit {
+ my ($server,$nick,$address, $reason) = @_;
+ if ($server->{'tag'} ne $active_channel->{'server'}->{'tag'}) {
+ return;
+ }
+ my $nr = find_nick($nick);
+ if ($nr != -1) {
+ remove_nick($nr);
+ }
+}
+
+sub sig_nick {
+ my ($server, $newnick, $oldnick, $address) = @_;
+ if ($server->{'tag'} ne $active_channel->{'server'}->{'tag'}) {
+ return;
+ }
+ my $nr = find_nick($oldnick);
+ if ($nr != -1) { # if nick was found (nickchange is in current channel)
+ my $nick = $nicklist[$nr];
+ remove_nick($nr);
+ $nick->{'nick'} = $newnick;
+ calc_text($nick);
+ insert_nick($nick);
+ }
+}
+
+sub sig_mode {
+ my ($channel, $nick, $setby, $mode, $type) = @_; # (nick and channel as rec)
+ if ($channel->{'server'}->{'tag'} ne $active_channel->{'server'}->{'tag'} || $channel->{'name'} ne $active_channel->{'name'}) {
+ return;
+ }
+ my $nr = find_nick($nick->{'nick'});
+ if ($nr == -1) {
+ Irssi::print("nicklist warning: $nick->{'nick'} had mode set on $channel->{'name'}, but was not found in nicklist");
+ } else {
+ my $nicklist_item = $nicklist[$nr];
+ remove_nick($nr);
+ $nicklist_item->{'mode'} = ($nick->{'op'}?$MODE_OP:$nick->{'halfop'}?$MODE_HALFOP:$nick->{'voice'}?$MODE_VOICE:$MODE_NORMAL);
+ calc_text($nicklist_item);
+ insert_nick($nicklist_item);
+ }
+}
+
+##### command binds #####
+Irssi::command_bind 'nicklist' => sub {
+ my ( $data, $server, $item ) = @_;
+ $data =~ s/\s+$//g;
+ Irssi::command_runsub ('nicklist', $data, $server, $item ) ;
+};
+Irssi::signal_add_first 'default command nicklist' => sub {
+ # gets triggered if called with unknown subcommand
+ cmd_help();
+};
+Irssi::command_bind('nicklist update',\&update);
+Irssi::command_bind('nicklist help',\&cmd_help);
+Irssi::command_bind('nicklist scroll',\&cmd_scroll);
+Irssi::command_bind('nicklist fifo',\&cmd_fifo_start);
+Irssi::command_bind('nicklist screen',\&cmd_screen_start);
+Irssi::command_bind('nicklist screensize',\&screen_size);
+Irssi::command_bind('nicklist off',\&cmd_off);
+
+##### signals #####
+Irssi::signal_add_last('window item changed', \&make_nicklist);
+Irssi::signal_add_last('window changed', \&make_nicklist);
+Irssi::signal_add_last('channel wholist', \&sig_channel_wholist);
+Irssi::signal_add_first('message join', \&sig_join); # first, to be before ignores
+Irssi::signal_add_first('message part', \&sig_part);
+Irssi::signal_add_first('message kick', \&sig_kick);
+Irssi::signal_add_first('message quit', \&sig_quit);
+Irssi::signal_add_first('message nick', \&sig_nick);
+Irssi::signal_add_first('message own_nick', \&sig_nick);
+Irssi::signal_add_first('nick mode changed', \&sig_mode);
+
+Irssi::signal_add('setup changed', \&read_settings);
+
+##### settings #####
+Irssi::settings_add_str('nicklist', 'nicklist_screen_prefix', '\e[m ');
+Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_op', '\e[32m@\e[39m');
+Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_halfop', '\e[34m%\e[39m');
+Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_voice', '\e[33m+\e[39m');
+Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_normal', ' ');
+
+Irssi::settings_add_int('nicklist', 'nicklist_width',11);
+Irssi::settings_add_int('nicklist', 'nicklist_height',24);
+Irssi::settings_add_str('nicklist', 'nicklist_fifo_path', Irssi::get_irssi_dir . '/nicklistfifo');
+Irssi::settings_add_str('nicklist', 'nicklist_screen_split_windows', '');
+Irssi::settings_add_str('nicklist', 'nicklist_automode', '');
+
+read_settings();
+if (uc(Irssi::settings_get_str('nicklist_automode')) eq 'SCREEN') {
+ cmd_screen_start();
+} elsif (uc(Irssi::settings_get_str('nicklist_automode')) eq 'FIFO') {
+ cmd_fifo_start();
+}
diff --git a/.irssi/scripts/trackbar.pl b/.irssi/scripts/trackbar.pl
new file mode 100644
index 0000000..7123330
--- /dev/null
+++ b/.irssi/scripts/trackbar.pl
@@ -0,0 +1,189 @@
+# trackbar.pl
+#
+# This little script will do just one thing: it will draw a line each time you
+# switch away from a window. This way, you always know just upto where you've
+# been reading that window :) It also removes the previous drawn line, so you
+# don't see double lines.
+#
+# Usage:
+#
+# The script works right out of the box, but if you want you can change
+# the working by /set'ing the following variables:
+#
+# trackbar_string The characters to repeat to draw the bar
+# trackbar_style The style for the bar, %r is red for example
+# See formats.txt that came with irssi
+#
+# /mark is a command that will redraw the line at the bottom. However! This
+# requires irssi version after 20021228. otherwise you'll get the error
+# redraw: unknown command, and your screen is all goofed up :)
+#
+# /upgrade & buf.pl notice: This version tries to remove the trackbars before
+# the upgrade is done, so buf.pl does not restore them, as they are not removeable
+# afterwards by trackbar. Unfortiounatly, to make this work, trackbar and buf.pl
+# need to be loaded in a specific order. Please experiment to see which order works
+# for you (strangely, it differs from configuration to configuration, something I will
+# try to fix in a next version)
+#
+# Authors:
+# - Main maintainer & author: Peter 'kinlo' Leurs
+# - Many thanks to Timo 'cras' Sirainen for placing me on my way
+# - on-upgrade-remove-line patch by Uwe Dudenhoeffer
+#
+# Version history:
+# 1.4: - Changed our's by my's so the irssi script header is valid
+# - Removed utf-8 support. In theory, the script should work w/o any
+# problems for utf-8, just set trackbar_string to a valid utf-8 character
+# and everything *should* work. However, this script is being plagued by
+# irssi internal bugs. The function Irssi::settings_get_str does NOT handle
+# unicode strings properly, hence you will notice problems when setting the bar
+# to a unicode char. For changing your bar to utf-8 symbols, read the line sub.
+# 1.3: - Upgrade now removes the trackbars.
+# - Some code cleanups, other defaults
+# - /mark sets the line to the bottom
+# 1.2: - Support for utf-8
+# - How the bar looks can now be configured with trackbar_string
+# and trackbar_style
+# 1.1: - Fixed bug when closing window
+# 1.0: - Initial release
+#
+#
+# Call for help!
+#
+# There is a trackbar version 2.0 that properly handles resizes and immediate config change
+# activation. However, there is/are some bug(s) in irssi's main buffer/window code that causes
+# irssi to 'forget' lines, which is ofcourse completly unaccepteable. I haven't found the time
+# nor do I know the irssi's internals enough to find and fix this bug, if you want to help, please
+# contact me, I'll give you a copy of the 2.0 version that will immediatly show you the problems.
+#
+# Known bugs:
+# - if you /clear a window, it will be uncleared when returning to the window
+# - UTF-8 characters in the trackbar_string doesnt work. This is an irssi bug.
+# - if you resize your irssi (in xterm or so) the bar is not resized
+# - changing the trackbar style is only visible after returning to a window
+# however, changing style/resize takes in effect after you left the window.
+#
+# Whishlist/todo:
+# - instead of drawing a line, just invert timestamp or something,
+# to save a line (but I don't think this is possible with current irssi)
+# - some pageup keybinding possibility, to scroll up upto the trackbar
+# - <@coekie> kinlo: if i switch to another window, in another split window, i
+# want the trackbar to go down in the previouswindow in that splitwindow :)
+# - < bob_2> anyway to clear the line once the window is read?
+# - < elho> kinlo: wishlist item: a string that gets prepended to the repeating pattern
+# - < elho> an option to still have the timestamp in front of the bar
+# - < elho> oh and an option to not draw it in the status window :P
+#
+# BTW: when you have feature requests, mailing a patch that works is the fastest way
+# to get it added :p
+
+use strict;
+use 5.6.1;
+use Irssi;
+use Irssi::TextUI;
+
+my $VERSION = "1.4";
+
+my %IRSSI = (
+ authors => "Peter 'kinlo' Leurs",
+ contact => "peter\@pfoe.be",
+ name => "trackbar",
+ description => "Shows a bar where you've last read a window",
+ license => "GPLv2",
+ url => "http://www.pfoe.be/~peter/trackbar/",
+ changed => "Thu Feb 20 16:18:08 2003",
+);
+
+my %config;
+
+Irssi::settings_add_str('trackbar', 'trackbar_string' => '-');
+$config{'trackbar_string'} = Irssi::settings_get_str('trackbar_string');
+
+Irssi::settings_add_str('trackbar', 'trackbar_style' => '%K');
+$config{'trackbar_style'} = Irssi::settings_get_str('trackbar_style');
+
+Irssi::signal_add(
+ 'setup changed' => sub {
+ $config{'trackbar_string'} = Irssi::settings_get_str('trackbar_string');
+ $config{'trackbar_style'} = Irssi::settings_get_str('trackbar_style');
+ if ($config{'trackbar_style'} =~ /(?<!%)[^%]|%%|%$/) {
+ Irssi::print(
+ "trackbar: %RWarning!%n 'trackbar_style' seems to contain "
+ . "printable characters. Only use format codes (read "
+ . "formats.txt).", MSGLEVEL_CLIENTERROR);
+ }
+ }
+);
+
+Irssi::signal_add(
+ 'window changed' => sub {
+ my (undef, $oldwindow) = @_;
+
+ if ($oldwindow) {
+ my $line = $oldwindow->view()->get_bookmark('trackbar');
+ $oldwindow->view()->remove_line($line) if defined $line;
+ $oldwindow->print(line($oldwindow->{'width'}), MSGLEVEL_NEVER);
+ $oldwindow->view()->set_bookmark_bottom('trackbar');
+ }
+ }
+);
+
+sub line {
+ my $width = shift;
+ my $string = $config{'trackbar_string'};
+ $string = '-' unless defined $string;
+
+ # There is a bug in irssi's utf-8 handling on config file settings, as you
+ # can reproduce/see yourself by the following code sniplet:
+ #
+ # my $quake = pack 'U*', 8364; # EUR symbol
+ # Irssi::settings_add_str 'temp', 'temp_foo' => $quake;
+ # Irssi::print length $quake;
+ # # prints 1
+ # Irssi::print length Irssi::settings_get_str 'temp_foo';
+ # # prints 3
+ #
+ #
+ # Trackbar used to have a workaround, but on recent versions of perl/irssi
+ # it does no longer work. Therefore, if you want your trackbar to contain
+ # unicode characters, uncomment the line below for a nice full line, or set
+ # the string to whatever char you want.
+
+ # $string = pack('U*', 0x2500);
+
+
+ my $length = length $string;
+
+ if ($length == 0) {
+ $string = '-';
+ $length = 1;
+ }
+
+ my $times = $width / $length;
+ $times = int(1 + $times) if $times != int($times);
+ $string =~ s/%/%%/g;
+ return $config{'trackbar_style'} . substr($string x $times, 0, $width);
+}
+
+# Remove trackbars on upgrade - but this doesn't really work if the scripts are not loaded in the correct order... watch out!
+
+Irssi::signal_add_first( 'session save' => sub {
+ for my $window (Irssi::windows) {
+ next unless defined $window;
+ my $line = $window->view()->get_bookmark('trackbar');
+ $window->view()->remove_line($line) if defined $line;
+ }
+ }
+);
+
+sub cmd_mark {
+ my $window = Irssi::active_win();
+# return unless defined $window;
+ my $line = $window->view()->get_bookmark('trackbar');
+ $window->view()->remove_line($line) if defined $line;
+ $window->print(line($window->{'width'}), MSGLEVEL_NEVER);
+ $window->view()->set_bookmark_bottom('trackbar');
+ Irssi::command("redraw");
+}
+
+Irssi::command_bind('mark', 'cmd_mark');
diff --git a/.irssi/scripts/xlist.pl b/.irssi/scripts/xlist.pl
new file mode 100644
index 0000000..ace8ca6
--- /dev/null
+++ b/.irssi/scripts/xlist.pl
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+
+# (c) Matthäus 'JonnyBG' Wander <jbg@swznet.de>
+
+# Usage: Simply use /list as you always do
+
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.00';
+%IRSSI = (
+ authors => 'Matthäus \'JonnyBG\' Wander',
+ contact => 'jbg@swznet.de',
+ name => 'xlist',
+ description => 'Better readable listing of channel names',
+ license => 'GPLv2',
+ url => 'http://jbg.swznet.de/xlist/',
+);
+
+use Irssi;
+
+my %xlist = ();
+
+sub collect {
+ my ($server, $data) = @_;
+
+ my (undef, $channel, $users, $topic) = split(/\s/, $data, 4);
+ $topic = substr($topic, 1);
+
+ $xlist{$channel} = [ $users, $topic ];
+}
+
+sub list {
+ my ($data, $server) = @_;
+ %xlist = ();
+
+ print "%K[%n".$server->{'tag'}."%K]%n %B<-->%n xlist";
+}
+
+sub show {
+ my ($server) = @_;
+ my ($printstring, $channel);
+
+ for $channel ( sort { ${ $xlist{$b} }[0] <=> ${ $xlist{$a} }[0] } keys %xlist ) {
+ $printstring = "%K[%n" . $server->{'tag'} . "%K]%n " .
+ sprintf("%4d", ${ $xlist{$channel} }[0]) .
+ " " . $channel;
+
+ if (length ${ $xlist{$channel} }[1] > 0 ) {
+ $printstring .= " %B->%n ". ${ $xlist{$channel} }[1];
+ }
+
+ print $printstring;
+ }
+
+ %xlist = ();
+
+ print "%K[%n".$server->{'tag'}."%K]%n %B<-->%n End of xlist";
+}
+
+Irssi::command_bind('list', \&list);
+Irssi::signal_add('event 322', \&collect);
+Irssi::signal_add('event 323', \&show);
+
+print "%B<-->%n xlist v$VERSION: Simply use /list as you always do";
diff --git a/.mailcap b/.mailcap
new file mode 100644
index 0000000..36249ee
--- /dev/null
+++ b/.mailcap
@@ -0,0 +1,7 @@
+text/html; links %s; nametemplate=%s.html
+text/html; links -dump %s; nametemplate=%s.html; copiousoutput
+text/plain; vim %s
+text/calendar; /home/manut/icalview.sh; copiousoutput
+application/ms-tnef; tnef -w %s; copiousoutput
+applica/ms-tnef; tnef -w %s; copiousoutput
+
diff --git a/.muttrc b/.muttrc
new file mode 100644
index 0000000..b7e4ca9
--- /dev/null
+++ b/.muttrc
@@ -0,0 +1,175 @@
+set imap_user="manut"
+set imap_pass="XXXX"
+set imap_idle=yes # push mail
+set imap_check_subscribed
+set folder="imaps://mecka.net:10943"
+set spoolfile="imaps://mecka.net:10943"
+mailboxes +INBOX
+
+set header_cache = "~/.mutt/headercache"
+set message_cachedir = "~/.mutt/messagecache"
+
+set smtp_pass="XXXX"
+set smtp_url="smtp://$imap_user@mecka.net:25"
+set ssl_starttls=yes
+set ssl_force_tls=yes
+set use_from = yes
+
+set hostname="mecka.net"
+set realname = "Manuel Traut"
+set from = "manut@mecka.net"
+
+set sort=threads
+set sort_aux = last-date-sent
+set sort_re = no
+
+auto_view text/html
+alternative_order text/plain text/enriched text/calendar text/html
+
+set send_charset="us-ascii:iso-8859-15:utf-8"
+
+set record="=Sent"
+set postponed="=Drafts"
+
+set delete=yes
+set include=yes
+set fast_reply=yes
+set markers=no
+set edit_hdrs
+
+bind index \CP sidebar-prev
+bind index \CN sidebar-next
+bind index \CO sidebar-open
+bind pager \CP sidebar-prev
+bind pager \CN sidebar-next
+bind pager \CO sidebar-open
+
+macro index B '<enter-command>toggle sidebar_visible<enter>'
+macro pager B '<enter-command>toggle sidebar_visible<enter>'
+
+bind pager j next-line
+bind pager k previous-line
+bind pager h display-toggle-weed
+
+set menu_scroll
+set pager_index_lines=6
+set status_on_top
+
+# basic colors ---------------------------------------------------------
+color normal brightyellow default
+color error red default
+color tilde black default
+color message cyan default
+color markers red white
+color attachment white default
+color search brightmagenta default
+#color status J_black J_status
+color status brightyellow black
+color indicator brightblack yellow
+color tree yellow default # arrow in threads
+# index ----------------------------------------------------------------
+
+#color index red default "~D(!~p|~p)" # deleted
+#color index black default ~F # flagged
+#color index brightred default ~= # duplicate messages
+#color index brightgreen default "~A!~N!~T!~p!~Q!~F!~D!~P" # the rest
+#color index J_base default "~A~N!~T!~p!~Q!~F!~D" # the rest, new
+color index red default "~A" # all messages
+color index brightred default "~E" # expired messages
+color index blue default "~N" # new messages
+color index blue default "~O" # old messages
+color index brightmagenta default "~Q" # messages that have been replied to
+color index brightgreen default "~R" # read messages
+color index blue default "~U" # unread messages
+color index blue default "~U~$" # unread, unreferenced messages
+color index brightyellow default "~v" # messages part of a collapsed thread
+color index brightyellow default "~P" # messages from me
+color index cyan default "~p!~F" # messages to me
+color index cyan default "~N~p!~F" # new messages to me
+color index cyan default "~U~p!~F" # unread messages to me
+color index brightgreen default "~R~p!~F" # messages to me
+color index red default "~F" # flagged messages
+color index red default "~F~p" # flagged messages to me
+color index red default "~N~F" # new flagged messages
+color index red default "~N~F~p" # new flagged messages to me
+color index red default "~U~F~p" # new flagged messages to me
+color index black red "~D" # deleted messages
+color index brightcyan default "~v~(!~N)" # collapsed thread with no unread
+color index yellow default "~v~(~N)" # collapsed thread with some unread
+color index green default "~N~v~(~N)" # collapsed thread with unread parent
+# statusbg used to indicated flagged when foreground color shows other status
+# for collapsed thread
+color index red black "~v~(~F)!~N" # collapsed thread with flagged, no unread
+color index yellow black "~v~(~F~N)" # collapsed thread with some unread & flagged
+color index green black "~N~v~(~F~N)" # collapsed thread with unread parent & flagged
+color index green black "~N~v~(~F)" # collapsed thread with unread parent, no unread inside, but some flagged
+color index cyan black "~v~(~p)" # collapsed thread with unread parent, no unread inside, some to me directly
+color index yellow red "~v~(~D)" # thread with deleted (doesn't differentiate between all or partial)
+#color index yellow default "~(~N)" # messages in threads with some unread
+#color index green default "~S" # superseded messages
+#color index red default "~T" # tagged messages
+#color index brightred red "~=" # duplicated messages
+
+# message headers ------------------------------------------------------
+
+#color header brightgreen default "^"
+color hdrdefault brightgreen default
+color header brightyellow default "^(From)"
+color header blue default "^(Subject)"
+
+# body -----------------------------------------------------------------
+
+color quoted blue default
+color quoted1 cyan default
+color quoted2 yellow default
+color quoted3 red default
+color quoted4 brightred default
+
+color signature brightgreen default
+color bold black default
+color underline black default
+color normal default default
+#
+color body brightcyan default "[;:][-o][)/(|]" # emoticons
+color body brightcyan default "[;:][)(|]" # emoticons
+color body brightcyan default "[*]?((N)?ACK|CU|LOL|SCNR|BRB|BTW|CWYL|\
+ |FWIW|vbg|GD&R|HTH|HTHBE|IMHO|IMNSHO|\
+ |IRL|RTFM|ROTFL|ROFL|YMMV)[*]?"
+color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
+color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
+
+## pgp
+
+color body red default "(BAD signature)"
+color body cyan default "(Good signature)"
+color body brightblack default "^gpg: Good signature .*"
+color body brightyellow default "^gpg: "
+color body brightyellow red "^gpg: BAD signature from.*"
+mono body bold "^gpg: Good signature"
+mono body bold "^gpg: BAD signature from.*"
+
+# yes, an insance URL regex
+color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
+# and a heavy handed email regex
+#color body J_magent default "((@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]),)*@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]):)?[0-9a-z_.+%$-]+@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\])"
+
+# Various smilies and the like
+#color body brightwhite default "<[Gg]>" # <g>
+#color body brightwhite default "<[Bb][Gg]>" # <bg>
+#color body yellow default " [;:]-*[})>{(<|]" # :-) etc...
+# *bold*
+#color body blue default "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)"
+#mono body bold "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)"
+# _underline_
+#color body blue default "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)"
+#mono body underline "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)"
+# /italic/ (Sometimes gets directory names)
+#color body blue default "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)"
+#mono body underline "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)"
+
+# Border lines.
+#color body blue default "( *[-+=#*~_]){6,}"
+
+#folder-hook . "color status J_black J_status "
+#folder-hook gmail/inbox "color status J_black yellow "
+#folder-hook gmail/important "color status J_black yellow "
diff --git a/.vim/.netrwhist b/.vim/.netrwhist
new file mode 100644
index 0000000..7ee3c1f
--- /dev/null
+++ b/.vim/.netrwhist
@@ -0,0 +1,6 @@
+let g:netrw_dirhistmax =10
+let g:netrw_dirhist_cnt =4
+let g:netrw_dirhist_1='/home/manut/bla'
+let g:netrw_dirhist_2='/home/manut/linux-4.15.10/arch/arm64/boot/dts/actions'
+let g:netrw_dirhist_3='/home/manut/hiveeyes/.git/modules/libraries/Watterott-Arduino-Libs'
+let g:netrw_dirhist_4='/home/manut/.mutt'
diff --git a/.vim/colors/solarized.vim b/.vim/colors/solarized.vim
new file mode 100644
index 0000000..70f5223
--- /dev/null
+++ b/.vim/colors/solarized.vim
@@ -0,0 +1,1117 @@
+" Name: Solarized vim colorscheme
+" Author: Ethan Schoonover <es@ethanschoonover.com>
+" URL: http://ethanschoonover.com/solarized
+" (see this url for latest release & screenshots)
+" License: OSI approved MIT license (see end of this file)
+" Created: In the middle of the night
+" Modified: 2011 May 05
+"
+" Usage "{{{
+"
+" ---------------------------------------------------------------------
+" ABOUT:
+" ---------------------------------------------------------------------
+" Solarized is a carefully designed selective contrast colorscheme with dual
+" light and dark modes that runs in both GUI, 256 and 16 color modes.
+"
+" See the homepage above for screenshots and details.
+"
+" ---------------------------------------------------------------------
+" OPTIONS:
+" ---------------------------------------------------------------------
+" See the "solarized.txt" help file included with this colorscheme (in the
+" "doc" subdirectory) for information on options, usage, the Toggle Background
+" function and more. If you have already installed Solarized, this is available
+" from the Solarized menu and command line as ":help solarized"
+"
+" ---------------------------------------------------------------------
+" INSTALLATION:
+" ---------------------------------------------------------------------
+" Two options for installation: manual or pathogen
+"
+" MANUAL INSTALLATION OPTION:
+" ---------------------------------------------------------------------
+"
+" 1. Download the solarized distribution (available on the homepage above)
+" and unarchive the file.
+" 2. Move `solarized.vim` to your `.vim/colors` directory.
+" 3. Move each of the files in each subdirectories to the corresponding .vim
+" subdirectory (e.g. autoload/togglebg.vim goes into your .vim/autoload
+" directory as .vim/autoload/togglebg.vim).
+"
+" RECOMMENDED PATHOGEN INSTALLATION OPTION:
+" ---------------------------------------------------------------------
+"
+" 1. Download and install Tim Pope's Pathogen from:
+" https://github.com/tpope/vim-pathogen
+"
+" 2. Next, move or clone the `vim-colors-solarized` directory so that it is
+" a subdirectory of the `.vim/bundle` directory.
+"
+" a. **clone with git:**
+"
+" $ cd ~/.vim/bundle
+" $ git clone git://github.com/altercation/vim-colors-solarized.git
+"
+" b. **or move manually into the pathogen bundle directory:**
+" In the parent directory of vim-colors-solarized:
+"
+" $ mv vim-colors-solarized ~/.vim/bundle/
+"
+" MODIFY VIMRC:
+"
+" After either Option 1 or Option 2 above, put the following two lines in your
+" .vimrc:
+"
+" syntax enable
+" set background=dark
+" colorscheme solarized
+"
+" or, for the light background mode of Solarized:
+"
+" syntax enable
+" set background=light
+" colorscheme solarized
+"
+" I like to have a different background in GUI and terminal modes, so I can use
+" the following if-then. However, I find vim's background autodetection to be
+" pretty good and, at least with MacVim, I can leave this background value
+" assignment out entirely and get the same results.
+"
+" if has('gui_running')
+" set background=light
+" else
+" set background=dark
+" endif
+"
+" See the Solarized homepage at http://ethanschoonover.com/solarized for
+" screenshots which will help you select either the light or dark background.
+"
+" ---------------------------------------------------------------------
+" COLOR VALUES
+" ---------------------------------------------------------------------
+" Download palettes and files from: http://ethanschoonover.com/solarized
+"
+" L\*a\*b values are canonical (White D65, Reference D50), other values are
+" matched in sRGB space.
+"
+" SOLARIZED HEX 16/8 TERMCOL XTERM/HEX L*A*B sRGB HSB
+" --------- ------- ---- ------- ----------- ---------- ----------- -----------
+" base03 #002b36 8/4 brblack 234 #1c1c1c 15 -12 -12 0 43 54 193 100 21
+" base02 #073642 0/4 black 235 #262626 20 -12 -12 7 54 66 192 90 26
+" base01 #586e75 10/7 brgreen 240 #4e4e4e 45 -07 -07 88 110 117 194 25 46
+" base00 #657b83 11/7 bryellow 241 #585858 50 -07 -07 101 123 131 195 23 51
+" base0 #839496 12/6 brblue 244 #808080 60 -06 -03 131 148 150 186 13 59
+" base1 #93a1a1 14/4 brcyan 245 #8a8a8a 65 -05 -02 147 161 161 180 9 63
+" base2 #eee8d5 7/7 white 254 #d7d7af 92 -00 10 238 232 213 44 11 93
+" base3 #fdf6e3 15/7 brwhite 230 #ffffd7 97 00 10 253 246 227 44 10 99
+" yellow #b58900 3/3 yellow 136 #af8700 60 10 65 181 137 0 45 100 71
+" orange #cb4b16 9/3 brred 166 #d75f00 50 50 55 203 75 22 18 89 80
+" red #dc322f 1/1 red 160 #d70000 50 65 45 220 50 47 1 79 86
+" magenta #d33682 5/5 magenta 125 #af005f 50 65 -05 211 54 130 331 74 83
+" violet #6c71c4 13/5 brmagenta 61 #5f5faf 50 15 -45 108 113 196 237 45 77
+" blue #268bd2 4/4 blue 33 #0087ff 55 -10 -45 38 139 210 205 82 82
+" cyan #2aa198 6/6 cyan 37 #00afaf 60 -35 -05 42 161 152 175 74 63
+" green #859900 2/2 green 64 #5f8700 60 -20 65 133 153 0 68 100 60
+"
+" ---------------------------------------------------------------------
+" COLORSCHEME HACKING
+" ---------------------------------------------------------------------
+"
+" Useful commands for testing colorschemes:
+" :source $VIMRUNTIME/syntax/hitest.vim
+" :help highlight-groups
+" :help cterm-colors
+" :help group-name
+"
+" Useful links for developing colorschemes:
+" http://www.vim.org/scripts/script.php?script_id=2937
+" http://vimcasts.org/episodes/creating-colorschemes-for-vim/
+" http://www.frexx.de/xterm-256-notes/"
+"
+" }}}
+" Environment Specific Overrides "{{{
+" Allow or disallow certain features based on current terminal emulator or
+" environment.
+
+" Terminals that support italics
+let s:terms_italic=[
+ \"rxvt",
+ \"gnome-terminal"
+ \]
+" For reference only, terminals are known to be incomptible.
+" Terminals that are in neither list need to be tested.
+let s:terms_noitalic=[
+ \"iTerm.app",
+ \"Apple_Terminal"
+ \]
+if has("gui_running")
+ let s:terminal_italic=1 " TODO: could refactor to not require this at all
+else
+ let s:terminal_italic=0 " terminals will be guilty until proven compatible
+ for term in s:terms_italic
+ if $TERM_PROGRAM =~ term
+ let s:terminal_italic=1
+ endif
+ endfor
+endif
+
+" }}}
+" Default option values"{{{
+" ---------------------------------------------------------------------
+" s:options_list is used to autogenerate a list of all non-default options
+" using "call SolarizedOptions()" or with the "Generate .vimrc commands"
+" Solarized menu option. See the "Menus" section below for the function itself.
+let s:options_list=[
+ \'" this block of commands has been autogenerated by solarized.vim and',
+ \'" includes the current, non-default Solarized option values.',
+ \'" To use, place these commands in your .vimrc file (replacing any',
+ \'" existing colorscheme commands). See also ":help solarized"',
+ \'',
+ \'" ------------------------------------------------------------------',
+ \'" Solarized Colorscheme Config',
+ \'" ------------------------------------------------------------------',
+ \]
+let s:colorscheme_list=[
+ \'syntax enable',
+ \'set background='.&background,
+ \'colorscheme solarized',
+ \]
+let s:defaults_list=[
+ \'" ------------------------------------------------------------------',
+ \'',
+ \'" The following items are available options, but do not need to be',
+ \'" included in your .vimrc as they are currently set to their defaults.',
+ \''
+ \]
+let s:lazycat_list=[
+ \'" lazy method of appending this onto your .vimrc ":w! >> ~/.vimrc"',
+ \'" ------------------------------------------------------------------',
+ \]
+
+function! s:SetOption(name,default)
+ if type(a:default) == type(0)
+ let l:wrap=''
+ let l:ewrap=''
+ else
+ let l:wrap='"'
+ let l:ewrap='\"'
+ endif
+ if !exists("g:solarized_".a:name) || g:solarized_{a:name}==a:default
+ exe 'let g:solarized_'.a:name.'='.l:wrap.a:default.l:wrap.'"'
+ exe 'call add(s:defaults_list, "\" let g:solarized_'.a:name.'='.l:ewrap.g:solarized_{a:name}.l:ewrap.'")'
+ else
+ exe 'call add(s:options_list, "let g:solarized_'.a:name.'='.l:ewrap.g:solarized_{a:name}.l:ewrap.' \"default value is '.a:default.'")'
+ endif
+endfunction
+
+if ($TERM_PROGRAM ==? "apple_terminal" && &t_Co < 256)
+ let s:solarized_termtrans_default = 1
+else
+ let s:solarized_termtrans_default = 0
+endif
+call s:SetOption("termtrans",s:solarized_termtrans_default)
+call s:SetOption("degrade",0)
+call s:SetOption("bold",1)
+call s:SetOption("underline",1)
+call s:SetOption("italic",1) " note that we need to override this later if the terminal doesn't support
+call s:SetOption("termcolors",16)
+call s:SetOption("contrast","normal")
+call s:SetOption("visibility","normal")
+call s:SetOption("diffmode","normal")
+call s:SetOption("hitrail",0)
+call s:SetOption("menu",1)
+
+"}}}
+" Colorscheme initialization "{{{
+" ---------------------------------------------------------------------
+hi clear
+if exists("syntax_on")
+ syntax reset
+endif
+let colors_name = "solarized"
+
+"}}}
+" GUI & CSApprox hexadecimal palettes"{{{
+" ---------------------------------------------------------------------
+"
+" Set both gui and terminal color values in separate conditional statements
+" Due to possibility that CSApprox is running (though I suppose we could just
+" leave the hex values out entirely in that case and include only cterm colors)
+" We also check to see if user has set solarized (force use of the
+" neutral gray monotone palette component)
+if (has("gui_running") && g:solarized_degrade == 0)
+ let s:vmode = "gui"
+ let s:base03 = "#002b36"
+ let s:base02 = "#073642"
+ let s:base01 = "#586e75"
+ let s:base00 = "#657b83"
+ let s:base0 = "#839496"
+ let s:base1 = "#93a1a1"
+ let s:base2 = "#eee8d5"
+ let s:base3 = "#fdf6e3"
+ let s:yellow = "#b58900"
+ let s:orange = "#cb4b16"
+ let s:red = "#dc322f"
+ let s:magenta = "#d33682"
+ let s:violet = "#6c71c4"
+ let s:blue = "#268bd2"
+ let s:cyan = "#2aa198"
+ "let s:green = "#859900" "original
+ let s:green = "#719e07" "experimental
+elseif (has("gui_running") && g:solarized_degrade == 1)
+ " These colors are identical to the 256 color mode. They may be viewed
+ " while in gui mode via "let g:solarized_degrade=1", though this is not
+ " recommened and is for testing only.
+ let s:vmode = "gui"
+ let s:base03 = "#1c1c1c"
+ let s:base02 = "#262626"
+ let s:base01 = "#4e4e4e"
+ let s:base00 = "#585858"
+ let s:base0 = "#808080"
+ let s:base1 = "#8a8a8a"
+ let s:base2 = "#d7d7af"
+ let s:base3 = "#ffffd7"
+ let s:yellow = "#af8700"
+ let s:orange = "#d75f00"
+ let s:red = "#af0000"
+ let s:magenta = "#af005f"
+ let s:violet = "#5f5faf"
+ let s:blue = "#0087ff"
+ let s:cyan = "#00afaf"
+ let s:green = "#5f8700"
+elseif g:solarized_termcolors != 256 && &t_Co >= 16
+ let s:vmode = "cterm"
+ let s:base03 = "8"
+ let s:base02 = "0"
+ let s:base01 = "10"
+ let s:base00 = "11"
+ let s:base0 = "12"
+ let s:base1 = "14"
+ let s:base2 = "7"
+ let s:base3 = "15"
+ let s:yellow = "3"
+ let s:orange = "9"
+ let s:red = "1"
+ let s:magenta = "5"
+ let s:violet = "13"
+ let s:blue = "4"
+ let s:cyan = "6"
+ let s:green = "2"
+elseif g:solarized_termcolors == 256
+ let s:vmode = "cterm"
+ let s:base03 = "234"
+ let s:base02 = "235"
+ let s:base01 = "239"
+ let s:base00 = "240"
+ let s:base0 = "244"
+ let s:base1 = "245"
+ let s:base2 = "187"
+ let s:base3 = "230"
+ let s:yellow = "136"
+ let s:orange = "166"
+ let s:red = "124"
+ let s:magenta = "125"
+ let s:violet = "61"
+ let s:blue = "33"
+ let s:cyan = "37"
+ let s:green = "64"
+else
+ let s:vmode = "cterm"
+ let s:bright = "* term=bold cterm=bold"
+" let s:base03 = "0".s:bright
+" let s:base02 = "0"
+" let s:base01 = "2".s:bright
+" let s:base00 = "3".s:bright
+" let s:base0 = "4".s:bright
+" let s:base1 = "6".s:bright
+" let s:base2 = "7"
+" let s:base3 = "7".s:bright
+" let s:yellow = "3"
+" let s:orange = "1".s:bright
+" let s:red = "1"
+" let s:magenta = "5"
+" let s:violet = "5".s:bright
+" let s:blue = "4"
+" let s:cyan = "6"
+" let s:green = "2"
+ let s:base03 = "DarkGray" " 0*
+ let s:base02 = "Black" " 0
+ let s:base01 = "LightGreen" " 2*
+ let s:base00 = "LightYellow" " 3*
+ let s:base0 = "LightBlue" " 4*
+ let s:base1 = "LightCyan" " 6*
+ let s:base2 = "LightGray" " 7
+ let s:base3 = "White" " 7*
+ let s:yellow = "DarkYellow" " 3
+ let s:orange = "LightRed" " 1*
+ let s:red = "DarkRed" " 1
+ let s:magenta = "DarkMagenta" " 5
+ let s:violet = "LightMagenta" " 5*
+ let s:blue = "DarkBlue" " 4
+ let s:cyan = "DarkCyan" " 6
+ let s:green = "DarkGreen" " 2
+
+endif
+"}}}
+" Formatting options and null values for passthrough effect "{{{
+" ---------------------------------------------------------------------
+ let s:none = "NONE"
+ let s:none = "NONE"
+ let s:t_none = "NONE"
+ let s:n = "NONE"
+ let s:c = ",undercurl"
+ let s:r = ",reverse"
+ let s:s = ",standout"
+ let s:ou = ""
+ let s:ob = ""
+"}}}
+" Background value based on termtrans setting "{{{
+" ---------------------------------------------------------------------
+if (has("gui_running") || g:solarized_termtrans == 0)
+ let s:back = s:base03
+else
+ let s:back = "NONE"
+endif
+"}}}
+" Alternate light scheme "{{{
+" ---------------------------------------------------------------------
+if &background == "light"
+ let s:temp03 = s:base03
+ let s:temp02 = s:base02
+ let s:temp01 = s:base01
+ let s:temp00 = s:base00
+ let s:base03 = s:base3
+ let s:base02 = s:base2
+ let s:base01 = s:base1
+ let s:base00 = s:base0
+ let s:base0 = s:temp00
+ let s:base1 = s:temp01
+ let s:base2 = s:temp02
+ let s:base3 = s:temp03
+ if (s:back != "NONE")
+ let s:back = s:base03
+ endif
+endif
+"}}}
+" Optional contrast schemes "{{{
+" ---------------------------------------------------------------------
+if g:solarized_contrast == "high"
+ let s:base01 = s:base00
+ let s:base00 = s:base0
+ let s:base0 = s:base1
+ let s:base1 = s:base2
+ let s:base2 = s:base3
+ let s:back = s:back
+endif
+if g:solarized_contrast == "low"
+ let s:back = s:base02
+ let s:ou = ",underline"
+endif
+"}}}
+" Overrides dependent on user specified values and environment "{{{
+" ---------------------------------------------------------------------
+if (g:solarized_bold == 0 || &t_Co == 8 )
+ let s:b = ""
+ let s:bb = ",bold"
+else
+ let s:b = ",bold"
+ let s:bb = ""
+endif
+
+if g:solarized_underline == 0
+ let s:u = ""
+else
+ let s:u = ",underline"
+endif
+
+if g:solarized_italic == 0 || s:terminal_italic == 0
+ let s:i = ""
+else
+ let s:i = ",italic"
+endif
+"}}}
+" Highlighting primitives"{{{
+" ---------------------------------------------------------------------
+
+exe "let s:bg_none = ' ".s:vmode."bg=".s:none ."'"
+exe "let s:bg_back = ' ".s:vmode."bg=".s:back ."'"
+exe "let s:bg_base03 = ' ".s:vmode."bg=".s:base03 ."'"
+exe "let s:bg_base02 = ' ".s:vmode."bg=".s:base02 ."'"
+exe "let s:bg_base01 = ' ".s:vmode."bg=".s:base01 ."'"
+exe "let s:bg_base00 = ' ".s:vmode."bg=".s:base00 ."'"
+exe "let s:bg_base0 = ' ".s:vmode."bg=".s:base0 ."'"
+exe "let s:bg_base1 = ' ".s:vmode."bg=".s:base1 ."'"
+exe "let s:bg_base2 = ' ".s:vmode."bg=".s:base2 ."'"
+exe "let s:bg_base3 = ' ".s:vmode."bg=".s:base3 ."'"
+exe "let s:bg_green = ' ".s:vmode."bg=".s:green ."'"
+exe "let s:bg_yellow = ' ".s:vmode."bg=".s:yellow ."'"
+exe "let s:bg_orange = ' ".s:vmode."bg=".s:orange ."'"
+exe "let s:bg_red = ' ".s:vmode."bg=".s:red ."'"
+exe "let s:bg_magenta = ' ".s:vmode."bg=".s:magenta."'"
+exe "let s:bg_violet = ' ".s:vmode."bg=".s:violet ."'"
+exe "let s:bg_blue = ' ".s:vmode."bg=".s:blue ."'"
+exe "let s:bg_cyan = ' ".s:vmode."bg=".s:cyan ."'"
+
+exe "let s:fg_none = ' ".s:vmode."fg=".s:none ."'"
+exe "let s:fg_back = ' ".s:vmode."fg=".s:back ."'"
+exe "let s:fg_base03 = ' ".s:vmode."fg=".s:base03 ."'"
+exe "let s:fg_base02 = ' ".s:vmode."fg=".s:base02 ."'"
+exe "let s:fg_base01 = ' ".s:vmode."fg=".s:base01 ."'"
+exe "let s:fg_base00 = ' ".s:vmode."fg=".s:base00 ."'"
+exe "let s:fg_base0 = ' ".s:vmode."fg=".s:base0 ."'"
+exe "let s:fg_base1 = ' ".s:vmode."fg=".s:base1 ."'"
+exe "let s:fg_base2 = ' ".s:vmode."fg=".s:base2 ."'"
+exe "let s:fg_base3 = ' ".s:vmode."fg=".s:base3 ."'"
+exe "let s:fg_green = ' ".s:vmode."fg=".s:green ."'"
+exe "let s:fg_yellow = ' ".s:vmode."fg=".s:yellow ."'"
+exe "let s:fg_orange = ' ".s:vmode."fg=".s:orange ."'"
+exe "let s:fg_red = ' ".s:vmode."fg=".s:red ."'"
+exe "let s:fg_magenta = ' ".s:vmode."fg=".s:magenta."'"
+exe "let s:fg_violet = ' ".s:vmode."fg=".s:violet ."'"
+exe "let s:fg_blue = ' ".s:vmode."fg=".s:blue ."'"
+exe "let s:fg_cyan = ' ".s:vmode."fg=".s:cyan ."'"
+
+exe "let s:fmt_none = ' ".s:vmode."=NONE". " term=NONE". "'"
+exe "let s:fmt_bold = ' ".s:vmode."=NONE".s:b. " term=NONE".s:b."'"
+exe "let s:fmt_bldi = ' ".s:vmode."=NONE".s:b. " term=NONE".s:b."'"
+exe "let s:fmt_undr = ' ".s:vmode."=NONE".s:u. " term=NONE".s:u."'"
+exe "let s:fmt_undb = ' ".s:vmode."=NONE".s:u.s:b. " term=NONE".s:u.s:b."'"
+exe "let s:fmt_undi = ' ".s:vmode."=NONE".s:u. " term=NONE".s:u."'"
+exe "let s:fmt_uopt = ' ".s:vmode."=NONE".s:ou. " term=NONE".s:ou."'"
+exe "let s:fmt_curl = ' ".s:vmode."=NONE".s:c. " term=NONE".s:c."'"
+exe "let s:fmt_ital = ' ".s:vmode."=NONE".s:i. " term=NONE".s:i."'"
+exe "let s:fmt_stnd = ' ".s:vmode."=NONE".s:s. " term=NONE".s:s."'"
+exe "let s:fmt_revr = ' ".s:vmode."=NONE".s:r. " term=NONE".s:r."'"
+exe "let s:fmt_revb = ' ".s:vmode."=NONE".s:r.s:b. " term=NONE".s:r.s:b."'"
+" revbb (reverse bold for bright colors) is only set to actual bold in low
+" color terminals (t_co=8, such as OS X Terminal.app) and should only be used
+" with colors 8-15.
+exe "let s:fmt_revbb = ' ".s:vmode."=NONE".s:r.s:bb. " term=NONE".s:r.s:bb."'"
+exe "let s:fmt_revbbu = ' ".s:vmode."=NONE".s:r.s:bb.s:u." term=NONE".s:r.s:bb.s:u."'"
+
+if has("gui_running")
+ exe "let s:sp_none = ' guisp=".s:none ."'"
+ exe "let s:sp_back = ' guisp=".s:back ."'"
+ exe "let s:sp_base03 = ' guisp=".s:base03 ."'"
+ exe "let s:sp_base02 = ' guisp=".s:base02 ."'"
+ exe "let s:sp_base01 = ' guisp=".s:base01 ."'"
+ exe "let s:sp_base00 = ' guisp=".s:base00 ."'"
+ exe "let s:sp_base0 = ' guisp=".s:base0 ."'"
+ exe "let s:sp_base1 = ' guisp=".s:base1 ."'"
+ exe "let s:sp_base2 = ' guisp=".s:base2 ."'"
+ exe "let s:sp_base3 = ' guisp=".s:base3 ."'"
+ exe "let s:sp_green = ' guisp=".s:green ."'"
+ exe "let s:sp_yellow = ' guisp=".s:yellow ."'"
+ exe "let s:sp_orange = ' guisp=".s:orange ."'"
+ exe "let s:sp_red = ' guisp=".s:red ."'"
+ exe "let s:sp_magenta = ' guisp=".s:magenta."'"
+ exe "let s:sp_violet = ' guisp=".s:violet ."'"
+ exe "let s:sp_blue = ' guisp=".s:blue ."'"
+ exe "let s:sp_cyan = ' guisp=".s:cyan ."'"
+else
+ let s:sp_none = ""
+ let s:sp_back = ""
+ let s:sp_base03 = ""
+ let s:sp_base02 = ""
+ let s:sp_base01 = ""
+ let s:sp_base00 = ""
+ let s:sp_base0 = ""
+ let s:sp_base1 = ""
+ let s:sp_base2 = ""
+ let s:sp_base3 = ""
+ let s:sp_green = ""
+ let s:sp_yellow = ""
+ let s:sp_orange = ""
+ let s:sp_red = ""
+ let s:sp_magenta = ""
+ let s:sp_violet = ""
+ let s:sp_blue = ""
+ let s:sp_cyan = ""
+endif
+
+"}}}
+" Basic highlighting"{{{
+" ---------------------------------------------------------------------
+" note that link syntax to avoid duplicate configuration doesn't work with the
+" exe compiled formats
+
+exe "hi! Normal" .s:fmt_none .s:fg_base0 .s:bg_back
+
+exe "hi! Comment" .s:fmt_ital .s:fg_base01 .s:bg_none
+" *Comment any comment
+
+exe "hi! Constant" .s:fmt_none .s:fg_cyan .s:bg_none
+" *Constant any constant
+" String a string constant: "this is a string"
+" Character a character constant: 'c', '\n'
+" Number a number constant: 234, 0xff
+" Boolean a boolean constant: TRUE, false
+" Float a floating point constant: 2.3e10
+
+exe "hi! Identifier" .s:fmt_none .s:fg_blue .s:bg_none
+" *Identifier any variable name
+" Function function name (also: methods for classes)
+"
+exe "hi! Statement" .s:fmt_none .s:fg_green .s:bg_none
+" *Statement any statement
+" Conditional if, then, else, endif, switch, etc.
+" Repeat for, do, while, etc.
+" Label case, default, etc.
+" Operator "sizeof", "+", "*", etc.
+" Keyword any other keyword
+" Exception try, catch, throw
+
+exe "hi! PreProc" .s:fmt_none .s:fg_orange .s:bg_none
+" *PreProc generic Preprocessor
+" Include preprocessor #include
+" Define preprocessor #define
+" Macro same as Define
+" PreCondit preprocessor #if, #else, #endif, etc.
+
+exe "hi! Type" .s:fmt_none .s:fg_yellow .s:bg_none
+" *Type int, long, char, etc.
+" StorageClass static, register, volatile, etc.
+" Structure struct, union, enum, etc.
+" Typedef A typedef
+
+exe "hi! Special" .s:fmt_none .s:fg_red .s:bg_none
+" *Special any special symbol
+" SpecialChar special character in a constant
+" Tag you can use CTRL-] on this
+" Delimiter character that needs attention
+" SpecialComment special things inside a comment
+" Debug debugging statements
+
+exe "hi! Underlined" .s:fmt_none .s:fg_violet .s:bg_none
+" *Underlined text that stands out, HTML links
+
+exe "hi! Ignore" .s:fmt_none .s:fg_none .s:bg_none
+" *Ignore left blank, hidden |hl-Ignore|
+
+exe "hi! Error" .s:fmt_bold .s:fg_red .s:bg_none
+" *Error any erroneous construct
+
+exe "hi! Todo" .s:fmt_bold .s:fg_magenta.s:bg_none
+" *Todo anything that needs extra attention; mostly the
+" keywords TODO FIXME and XXX
+"
+"}}}
+" Extended highlighting "{{{
+" ---------------------------------------------------------------------
+if (g:solarized_visibility=="high")
+ exe "hi! SpecialKey" .s:fmt_revr .s:fg_red .s:bg_none
+ exe "hi! NonText" .s:fmt_bold .s:fg_red .s:bg_none
+elseif (g:solarized_visibility=="low")
+ exe "hi! SpecialKey" .s:fmt_bold .s:fg_base02 .s:bg_none
+ exe "hi! NonText" .s:fmt_bold .s:fg_base02 .s:bg_none
+else
+ exe "hi! SpecialKey" .s:fmt_bold .s:fg_base00 .s:bg_base02
+ exe "hi! NonText" .s:fmt_bold .s:fg_base00 .s:bg_none
+endif
+exe "hi! StatusLine" .s:fmt_none .s:fg_base1 .s:bg_base02 .s:fmt_revbb
+exe "hi! StatusLineNC" .s:fmt_none .s:fg_base00 .s:bg_base02 .s:fmt_revbb
+exe "hi! Visual" .s:fmt_none .s:fg_base01 .s:bg_base03 .s:fmt_revbb
+exe "hi! Directory" .s:fmt_none .s:fg_blue .s:bg_none
+exe "hi! ErrorMsg" .s:fmt_revr .s:fg_red .s:bg_none
+exe "hi! IncSearch" .s:fmt_stnd .s:fg_orange .s:bg_none
+exe "hi! Search" .s:fmt_revr .s:fg_yellow .s:bg_none
+exe "hi! MoreMsg" .s:fmt_none .s:fg_blue .s:bg_none
+exe "hi! ModeMsg" .s:fmt_none .s:fg_blue .s:bg_none
+exe "hi! LineNr" .s:fmt_none .s:fg_base01 .s:bg_base02
+exe "hi! Question" .s:fmt_bold .s:fg_cyan .s:bg_none
+if ( has("gui_running") || &t_Co > 8 )
+ exe "hi! VertSplit" .s:fmt_none .s:fg_base00 .s:bg_base00
+else
+ exe "hi! VertSplit" .s:fmt_revbb .s:fg_base00 .s:bg_base02
+endif
+exe "hi! Title" .s:fmt_bold .s:fg_orange .s:bg_none
+exe "hi! VisualNOS" .s:fmt_stnd .s:fg_none .s:bg_base02 .s:fmt_revbb
+exe "hi! WarningMsg" .s:fmt_bold .s:fg_red .s:bg_none
+exe "hi! WildMenu" .s:fmt_none .s:fg_base2 .s:bg_base02 .s:fmt_revbb
+exe "hi! Folded" .s:fmt_undb .s:fg_base0 .s:bg_base02 .s:sp_base03
+exe "hi! FoldColumn" .s:fmt_none .s:fg_base0 .s:bg_base02
+if (g:solarized_diffmode=="high")
+exe "hi! DiffAdd" .s:fmt_revr .s:fg_green .s:bg_none
+exe "hi! DiffChange" .s:fmt_revr .s:fg_yellow .s:bg_none
+exe "hi! DiffDelete" .s:fmt_revr .s:fg_red .s:bg_none
+exe "hi! DiffText" .s:fmt_revr .s:fg_blue .s:bg_none
+elseif (g:solarized_diffmode=="low")
+exe "hi! DiffAdd" .s:fmt_undr .s:fg_green .s:bg_none .s:sp_green
+exe "hi! DiffChange" .s:fmt_undr .s:fg_yellow .s:bg_none .s:sp_yellow
+exe "hi! DiffDelete" .s:fmt_bold .s:fg_red .s:bg_none
+exe "hi! DiffText" .s:fmt_undr .s:fg_blue .s:bg_none .s:sp_blue
+else " normal
+ if has("gui_running")
+exe "hi! DiffAdd" .s:fmt_bold .s:fg_green .s:bg_base02 .s:sp_green
+exe "hi! DiffChange" .s:fmt_bold .s:fg_yellow .s:bg_base02 .s:sp_yellow
+exe "hi! DiffDelete" .s:fmt_bold .s:fg_red .s:bg_base02
+exe "hi! DiffText" .s:fmt_bold .s:fg_blue .s:bg_base02 .s:sp_blue
+ else
+exe "hi! DiffAdd" .s:fmt_none .s:fg_green .s:bg_base02 .s:sp_green
+exe "hi! DiffChange" .s:fmt_none .s:fg_yellow .s:bg_base02 .s:sp_yellow
+exe "hi! DiffDelete" .s:fmt_none .s:fg_red .s:bg_base02
+exe "hi! DiffText" .s:fmt_none .s:fg_blue .s:bg_base02 .s:sp_blue
+ endif
+endif
+exe "hi! SignColumn" .s:fmt_none .s:fg_base0
+exe "hi! Conceal" .s:fmt_none .s:fg_blue .s:bg_none
+exe "hi! SpellBad" .s:fmt_curl .s:fg_none .s:bg_none .s:sp_red
+exe "hi! SpellCap" .s:fmt_curl .s:fg_none .s:bg_none .s:sp_violet
+exe "hi! SpellRare" .s:fmt_curl .s:fg_none .s:bg_none .s:sp_cyan
+exe "hi! SpellLocal" .s:fmt_curl .s:fg_none .s:bg_none .s:sp_yellow
+exe "hi! Pmenu" .s:fmt_none .s:fg_base0 .s:bg_base02 .s:fmt_revbb
+exe "hi! PmenuSel" .s:fmt_none .s:fg_base01 .s:bg_base2 .s:fmt_revbb
+exe "hi! PmenuSbar" .s:fmt_none .s:fg_base2 .s:bg_base0 .s:fmt_revbb
+exe "hi! PmenuThumb" .s:fmt_none .s:fg_base0 .s:bg_base03 .s:fmt_revbb
+exe "hi! TabLine" .s:fmt_undr .s:fg_base0 .s:bg_base02 .s:sp_base0
+exe "hi! TabLineFill" .s:fmt_undr .s:fg_base0 .s:bg_base02 .s:sp_base0
+exe "hi! TabLineSel" .s:fmt_undr .s:fg_base01 .s:bg_base2 .s:sp_base0 .s:fmt_revbbu
+exe "hi! CursorColumn" .s:fmt_none .s:fg_none .s:bg_base02
+exe "hi! CursorLine" .s:fmt_uopt .s:fg_none .s:bg_base02 .s:sp_base1
+exe "hi! ColorColumn" .s:fmt_none .s:fg_none .s:bg_base02
+exe "hi! Cursor" .s:fmt_none .s:fg_base03 .s:bg_base0
+hi! link lCursor Cursor
+exe "hi! MatchParen" .s:fmt_bold .s:fg_red .s:bg_base01
+
+"}}}
+" vim syntax highlighting "{{{
+" ---------------------------------------------------------------------
+"exe "hi! vimLineComment" . s:fg_base01 .s:bg_none .s:fmt_ital
+"hi! link vimComment Comment
+"hi! link vimLineComment Comment
+hi! link vimVar Identifier
+hi! link vimFunc Function
+hi! link vimUserFunc Function
+hi! link helpSpecial Special
+hi! link vimSet Normal
+hi! link vimSetEqual Normal
+exe "hi! vimCommentString" .s:fmt_none .s:fg_violet .s:bg_none
+exe "hi! vimCommand" .s:fmt_none .s:fg_yellow .s:bg_none
+exe "hi! vimCmdSep" .s:fmt_bold .s:fg_blue .s:bg_none
+exe "hi! helpExample" .s:fmt_none .s:fg_base1 .s:bg_none
+exe "hi! helpOption" .s:fmt_none .s:fg_cyan .s:bg_none
+exe "hi! helpNote" .s:fmt_none .s:fg_magenta.s:bg_none
+exe "hi! helpVim" .s:fmt_none .s:fg_magenta.s:bg_none
+exe "hi! helpHyperTextJump" .s:fmt_undr .s:fg_blue .s:bg_none
+exe "hi! helpHyperTextEntry".s:fmt_none .s:fg_green .s:bg_none
+exe "hi! vimIsCommand" .s:fmt_none .s:fg_base00 .s:bg_none
+exe "hi! vimSynMtchOpt" .s:fmt_none .s:fg_yellow .s:bg_none
+exe "hi! vimSynType" .s:fmt_none .s:fg_cyan .s:bg_none
+exe "hi! vimHiLink" .s:fmt_none .s:fg_blue .s:bg_none
+exe "hi! vimHiGroup" .s:fmt_none .s:fg_blue .s:bg_none
+exe "hi! vimGroup" .s:fmt_undb .s:fg_blue .s:bg_none
+"}}}
+" diff highlighting "{{{
+" ---------------------------------------------------------------------
+hi! link diffAdded Statement
+hi! link diffLine Identifier
+"}}}
+" git & gitcommit highlighting "{{{
+"git
+"exe "hi! gitDateHeader"
+"exe "hi! gitIdentityHeader"
+"exe "hi! gitIdentityKeyword"
+"exe "hi! gitNotesHeader"
+"exe "hi! gitReflogHeader"
+"exe "hi! gitKeyword"
+"exe "hi! gitIdentity"
+"exe "hi! gitEmailDelimiter"
+"exe "hi! gitEmail"
+"exe "hi! gitDate"
+"exe "hi! gitMode"
+"exe "hi! gitHashAbbrev"
+"exe "hi! gitHash"
+"exe "hi! gitReflogMiddle"
+"exe "hi! gitReference"
+"exe "hi! gitStage"
+"exe "hi! gitType"
+"exe "hi! gitDiffAdded"
+"exe "hi! gitDiffRemoved"
+"gitcommit
+"exe "hi! gitcommitSummary"
+exe "hi! gitcommitComment" .s:fmt_ital .s:fg_base01 .s:bg_none
+hi! link gitcommitUntracked gitcommitComment
+hi! link gitcommitDiscarded gitcommitComment
+hi! link gitcommitSelected gitcommitComment
+exe "hi! gitcommitUnmerged" .s:fmt_bold .s:fg_green .s:bg_none
+exe "hi! gitcommitOnBranch" .s:fmt_bold .s:fg_base01 .s:bg_none
+exe "hi! gitcommitBranch" .s:fmt_bold .s:fg_magenta .s:bg_none
+hi! link gitcommitNoBranch gitcommitBranch
+exe "hi! gitcommitDiscardedType".s:fmt_none .s:fg_red .s:bg_none
+exe "hi! gitcommitSelectedType" .s:fmt_none .s:fg_green .s:bg_none
+"exe "hi! gitcommitUnmergedType"
+"exe "hi! gitcommitType"
+"exe "hi! gitcommitNoChanges"
+"exe "hi! gitcommitHeader"
+exe "hi! gitcommitHeader" .s:fmt_none .s:fg_base01 .s:bg_none
+exe "hi! gitcommitUntrackedFile".s:fmt_bold .s:fg_cyan .s:bg_none
+exe "hi! gitcommitDiscardedFile".s:fmt_bold .s:fg_red .s:bg_none
+exe "hi! gitcommitSelectedFile" .s:fmt_bold .s:fg_green .s:bg_none
+exe "hi! gitcommitUnmergedFile" .s:fmt_bold .s:fg_yellow .s:bg_none
+exe "hi! gitcommitFile" .s:fmt_bold .s:fg_base0 .s:bg_none
+hi! link gitcommitDiscardedArrow gitcommitDiscardedFile
+hi! link gitcommitSelectedArrow gitcommitSelectedFile
+hi! link gitcommitUnmergedArrow gitcommitUnmergedFile
+"exe "hi! gitcommitArrow"
+"exe "hi! gitcommitOverflow"
+"exe "hi! gitcommitBlank"
+" }}}
+" html highlighting "{{{
+" ---------------------------------------------------------------------
+exe "hi! htmlTag" .s:fmt_none .s:fg_base01 .s:bg_none
+exe "hi! htmlEndTag" .s:fmt_none .s:fg_base01 .s:bg_none
+exe "hi! htmlTagN" .s:fmt_bold .s:fg_base1 .s:bg_none
+exe "hi! htmlTagName" .s:fmt_bold .s:fg_blue .s:bg_none
+exe "hi! htmlSpecialTagName".s:fmt_ital .s:fg_blue .s:bg_none
+exe "hi! htmlArg" .s:fmt_none .s:fg_base00 .s:bg_none
+exe "hi! javaScript" .s:fmt_none .s:fg_yellow .s:bg_none
+"}}}
+" perl highlighting "{{{
+" ---------------------------------------------------------------------
+exe "hi! perlHereDoc" . s:fg_base1 .s:bg_back .s:fmt_none
+exe "hi! perlVarPlain" . s:fg_yellow .s:bg_back .s:fmt_none
+exe "hi! perlStatementFileDesc". s:fg_cyan.s:bg_back.s:fmt_none
+
+"}}}
+" tex highlighting "{{{
+" ---------------------------------------------------------------------
+exe "hi! texStatement" . s:fg_cyan .s:bg_back .s:fmt_none
+exe "hi! texMathZoneX" . s:fg_yellow .s:bg_back .s:fmt_none
+exe "hi! texMathMatcher" . s:fg_yellow .s:bg_back .s:fmt_none
+exe "hi! texMathMatcher" . s:fg_yellow .s:bg_back .s:fmt_none
+exe "hi! texRefLabel" . s:fg_yellow .s:bg_back .s:fmt_none
+"}}}
+" ruby highlighting "{{{
+" ---------------------------------------------------------------------
+exe "hi! rubyDefine" . s:fg_base1 .s:bg_back .s:fmt_bold
+"rubyInclude
+"rubySharpBang
+"rubyAccess
+"rubyPredefinedVariable
+"rubyBoolean
+"rubyClassVariable
+"rubyBeginEnd
+"rubyRepeatModifier
+"hi! link rubyArrayDelimiter Special " [ , , ]
+"rubyCurlyBlock { , , }
+
+"hi! link rubyClass Keyword
+"hi! link rubyModule Keyword
+"hi! link rubyKeyword Keyword
+"hi! link rubyOperator Operator
+"hi! link rubyIdentifier Identifier
+"hi! link rubyInstanceVariable Identifier
+"hi! link rubyGlobalVariable Identifier
+"hi! link rubyClassVariable Identifier
+"hi! link rubyConstant Type
+"}}}
+" haskell syntax highlighting"{{{
+" ---------------------------------------------------------------------
+" For use with syntax/haskell.vim : Haskell Syntax File
+" http://www.vim.org/scripts/script.php?script_id=3034
+" See also Steffen Siering's github repository:
+" http://github.com/urso/dotrc/blob/master/vim/syntax/haskell.vim
+" ---------------------------------------------------------------------
+"
+" Treat True and False specially, see the plugin referenced above
+let hs_highlight_boolean=1
+" highlight delims, see the plugin referenced above
+let hs_highlight_delimiters=1
+
+exe "hi! cPreCondit". s:fg_orange.s:bg_none .s:fmt_none
+
+exe "hi! VarId" . s:fg_blue .s:bg_none .s:fmt_none
+exe "hi! ConId" . s:fg_yellow .s:bg_none .s:fmt_none
+exe "hi! hsImport" . s:fg_magenta.s:bg_none .s:fmt_none
+exe "hi! hsString" . s:fg_base00 .s:bg_none .s:fmt_none
+
+exe "hi! hsStructure" . s:fg_cyan .s:bg_none .s:fmt_none
+exe "hi! hs_hlFunctionName" . s:fg_blue .s:bg_none
+exe "hi! hsStatement" . s:fg_cyan .s:bg_none .s:fmt_none
+exe "hi! hsImportLabel" . s:fg_cyan .s:bg_none .s:fmt_none
+exe "hi! hs_OpFunctionName" . s:fg_yellow .s:bg_none .s:fmt_none
+exe "hi! hs_DeclareFunction" . s:fg_orange .s:bg_none .s:fmt_none
+exe "hi! hsVarSym" . s:fg_cyan .s:bg_none .s:fmt_none
+exe "hi! hsType" . s:fg_yellow .s:bg_none .s:fmt_none
+exe "hi! hsTypedef" . s:fg_cyan .s:bg_none .s:fmt_none
+exe "hi! hsModuleName" . s:fg_green .s:bg_none .s:fmt_undr
+exe "hi! hsModuleStartLabel" . s:fg_magenta.s:bg_none .s:fmt_none
+hi! link hsImportParams Delimiter
+hi! link hsDelimTypeExport Delimiter
+hi! link hsModuleStartLabel hsStructure
+hi! link hsModuleWhereLabel hsModuleStartLabel
+
+" following is for the haskell-conceal plugin
+" the first two items don't have an impact, but better safe
+exe "hi! hsNiceOperator" . s:fg_cyan .s:bg_none .s:fmt_none
+exe "hi! hsniceoperator" . s:fg_cyan .s:bg_none .s:fmt_none
+
+"}}}
+" pandoc markdown syntax highlighting "{{{
+" ---------------------------------------------------------------------
+
+"PandocHiLink pandocNormalBlock
+exe "hi! pandocTitleBlock" .s:fg_blue .s:bg_none .s:fmt_none
+exe "hi! pandocTitleBlockTitle" .s:fg_blue .s:bg_none .s:fmt_bold
+exe "hi! pandocTitleComment" .s:fg_blue .s:bg_none .s:fmt_bold
+exe "hi! pandocComment" .s:fg_base01 .s:bg_none .s:fmt_ital
+exe "hi! pandocVerbatimBlock" .s:fg_yellow .s:bg_none .s:fmt_none
+hi! link pandocVerbatimBlockDeep pandocVerbatimBlock
+hi! link pandocCodeBlock pandocVerbatimBlock
+hi! link pandocCodeBlockDelim pandocVerbatimBlock
+exe "hi! pandocBlockQuote" .s:fg_blue .s:bg_none .s:fmt_none
+exe "hi! pandocBlockQuoteLeader1" .s:fg_blue .s:bg_none .s:fmt_none
+exe "hi! pandocBlockQuoteLeader2" .s:fg_cyan .s:bg_none .s:fmt_none
+exe "hi! pandocBlockQuoteLeader3" .s:fg_yellow .s:bg_none .s:fmt_none
+exe "hi! pandocBlockQuoteLeader4" .s:fg_red .s:bg_none .s:fmt_none
+exe "hi! pandocBlockQuoteLeader5" .s:fg_base0 .s:bg_none .s:fmt_none
+exe "hi! pandocBlockQuoteLeader6" .s:fg_base01 .s:bg_none .s:fmt_none
+exe "hi! pandocListMarker" .s:fg_magenta.s:bg_none .s:fmt_none
+exe "hi! pandocListReference" .s:fg_magenta.s:bg_none .s:fmt_undr
+
+" Definitions
+" ---------------------------------------------------------------------
+let s:fg_pdef = s:fg_violet
+exe "hi! pandocDefinitionBlock" .s:fg_pdef .s:bg_none .s:fmt_none
+exe "hi! pandocDefinitionTerm" .s:fg_pdef .s:bg_none .s:fmt_stnd
+exe "hi! pandocDefinitionIndctr" .s:fg_pdef .s:bg_none .s:fmt_bold
+exe "hi! pandocEmphasisDefinition" .s:fg_pdef .s:bg_none .s:fmt_ital
+exe "hi! pandocEmphasisNestedDefinition" .s:fg_pdef .s:bg_none .s:fmt_bldi
+exe "hi! pandocStrongEmphasisDefinition" .s:fg_pdef .s:bg_none .s:fmt_bold
+exe "hi! pandocStrongEmphasisNestedDefinition" .s:fg_pdef.s:bg_none.s:fmt_bldi
+exe "hi! pandocStrongEmphasisEmphasisDefinition" .s:fg_pdef.s:bg_none.s:fmt_bldi
+exe "hi! pandocStrikeoutDefinition" .s:fg_pdef .s:bg_none .s:fmt_revr
+exe "hi! pandocVerbatimInlineDefinition" .s:fg_pdef .s:bg_none .s:fmt_none
+exe "hi! pandocSuperscriptDefinition" .s:fg_pdef .s:bg_none .s:fmt_none
+exe "hi! pandocSubscriptDefinition" .s:fg_pdef .s:bg_none .s:fmt_none
+
+" Tables
+" ---------------------------------------------------------------------
+let s:fg_ptable = s:fg_blue
+exe "hi! pandocTable" .s:fg_ptable.s:bg_none .s:fmt_none
+exe "hi! pandocTableStructure" .s:fg_ptable.s:bg_none .s:fmt_none
+hi! link pandocTableStructureTop pandocTableStructre
+hi! link pandocTableStructureEnd pandocTableStructre
+exe "hi! pandocTableZebraLight" .s:fg_ptable.s:bg_base03.s:fmt_none
+exe "hi! pandocTableZebraDark" .s:fg_ptable.s:bg_base02.s:fmt_none
+exe "hi! pandocEmphasisTable" .s:fg_ptable.s:bg_none .s:fmt_ital
+exe "hi! pandocEmphasisNestedTable" .s:fg_ptable.s:bg_none .s:fmt_bldi
+exe "hi! pandocStrongEmphasisTable" .s:fg_ptable.s:bg_none .s:fmt_bold
+exe "hi! pandocStrongEmphasisNestedTable" .s:fg_ptable.s:bg_none .s:fmt_bldi
+exe "hi! pandocStrongEmphasisEmphasisTable" .s:fg_ptable.s:bg_none .s:fmt_bldi
+exe "hi! pandocStrikeoutTable" .s:fg_ptable.s:bg_none .s:fmt_revr
+exe "hi! pandocVerbatimInlineTable" .s:fg_ptable.s:bg_none .s:fmt_none
+exe "hi! pandocSuperscriptTable" .s:fg_ptable.s:bg_none .s:fmt_none
+exe "hi! pandocSubscriptTable" .s:fg_ptable.s:bg_none .s:fmt_none
+
+" Headings
+" ---------------------------------------------------------------------
+let s:fg_phead = s:fg_orange
+exe "hi! pandocHeading" .s:fg_phead .s:bg_none.s:fmt_bold
+exe "hi! pandocHeadingMarker" .s:fg_yellow.s:bg_none.s:fmt_bold
+exe "hi! pandocEmphasisHeading" .s:fg_phead .s:bg_none.s:fmt_bldi
+exe "hi! pandocEmphasisNestedHeading" .s:fg_phead .s:bg_none.s:fmt_bldi
+exe "hi! pandocStrongEmphasisHeading" .s:fg_phead .s:bg_none.s:fmt_bold
+exe "hi! pandocStrongEmphasisNestedHeading" .s:fg_phead .s:bg_none.s:fmt_bldi
+exe "hi! pandocStrongEmphasisEmphasisHeading".s:fg_phead .s:bg_none.s:fmt_bldi
+exe "hi! pandocStrikeoutHeading" .s:fg_phead .s:bg_none.s:fmt_revr
+exe "hi! pandocVerbatimInlineHeading" .s:fg_phead .s:bg_none.s:fmt_bold
+exe "hi! pandocSuperscriptHeading" .s:fg_phead .s:bg_none.s:fmt_bold
+exe "hi! pandocSubscriptHeading" .s:fg_phead .s:bg_none.s:fmt_bold
+
+" Links
+" ---------------------------------------------------------------------
+exe "hi! pandocLinkDelim" .s:fg_base01 .s:bg_none .s:fmt_none
+exe "hi! pandocLinkLabel" .s:fg_blue .s:bg_none .s:fmt_undr
+exe "hi! pandocLinkText" .s:fg_blue .s:bg_none .s:fmt_undb
+exe "hi! pandocLinkURL" .s:fg_base00 .s:bg_none .s:fmt_undr
+exe "hi! pandocLinkTitle" .s:fg_base00 .s:bg_none .s:fmt_undi
+exe "hi! pandocLinkTitleDelim" .s:fg_base01 .s:bg_none .s:fmt_undi .s:sp_base00
+exe "hi! pandocLinkDefinition" .s:fg_cyan .s:bg_none .s:fmt_undr .s:sp_base00
+exe "hi! pandocLinkDefinitionID" .s:fg_blue .s:bg_none .s:fmt_bold
+exe "hi! pandocImageCaption" .s:fg_violet .s:bg_none .s:fmt_undb
+exe "hi! pandocFootnoteLink" .s:fg_green .s:bg_none .s:fmt_undr
+exe "hi! pandocFootnoteDefLink" .s:fg_green .s:bg_none .s:fmt_bold
+exe "hi! pandocFootnoteInline" .s:fg_green .s:bg_none .s:fmt_undb
+exe "hi! pandocFootnote" .s:fg_green .s:bg_none .s:fmt_none
+exe "hi! pandocCitationDelim" .s:fg_magenta.s:bg_none .s:fmt_none
+exe "hi! pandocCitation" .s:fg_magenta.s:bg_none .s:fmt_none
+exe "hi! pandocCitationID" .s:fg_magenta.s:bg_none .s:fmt_undr
+exe "hi! pandocCitationRef" .s:fg_magenta.s:bg_none .s:fmt_none
+
+" Main Styles
+" ---------------------------------------------------------------------
+exe "hi! pandocStyleDelim" .s:fg_base01 .s:bg_none .s:fmt_none
+exe "hi! pandocEmphasis" .s:fg_base0 .s:bg_none .s:fmt_ital
+exe "hi! pandocEmphasisNested" .s:fg_base0 .s:bg_none .s:fmt_bldi
+exe "hi! pandocStrongEmphasis" .s:fg_base0 .s:bg_none .s:fmt_bold
+exe "hi! pandocStrongEmphasisNested" .s:fg_base0 .s:bg_none .s:fmt_bldi
+exe "hi! pandocStrongEmphasisEmphasis" .s:fg_base0 .s:bg_none .s:fmt_bldi
+exe "hi! pandocStrikeout" .s:fg_base01 .s:bg_none .s:fmt_revr
+exe "hi! pandocVerbatimInline" .s:fg_yellow .s:bg_none .s:fmt_none
+exe "hi! pandocSuperscript" .s:fg_violet .s:bg_none .s:fmt_none
+exe "hi! pandocSubscript" .s:fg_violet .s:bg_none .s:fmt_none
+
+exe "hi! pandocRule" .s:fg_blue .s:bg_none .s:fmt_bold
+exe "hi! pandocRuleLine" .s:fg_blue .s:bg_none .s:fmt_bold
+exe "hi! pandocEscapePair" .s:fg_red .s:bg_none .s:fmt_bold
+exe "hi! pandocCitationRef" .s:fg_magenta.s:bg_none .s:fmt_none
+exe "hi! pandocNonBreakingSpace" . s:fg_red .s:bg_none .s:fmt_revr
+hi! link pandocEscapedCharacter pandocEscapePair
+hi! link pandocLineBreak pandocEscapePair
+
+" Embedded Code
+" ---------------------------------------------------------------------
+exe "hi! pandocMetadataDelim" .s:fg_base01 .s:bg_none .s:fmt_none
+exe "hi! pandocMetadata" .s:fg_blue .s:bg_none .s:fmt_none
+exe "hi! pandocMetadataKey" .s:fg_blue .s:bg_none .s:fmt_none
+exe "hi! pandocMetadata" .s:fg_blue .s:bg_none .s:fmt_bold
+hi! link pandocMetadataTitle pandocMetadata
+
+"}}}
+" Utility autocommand "{{{
+" ---------------------------------------------------------------------
+" In cases where Solarized is initialized inside a terminal vim session and
+" then transferred to a gui session via the command `:gui`, the gui vim process
+" does not re-read the colorscheme (or .vimrc for that matter) so any `has_gui`
+" related code that sets gui specific values isn't executed.
+"
+" Currently, Solarized sets only the cterm or gui values for the colorscheme
+" depending on gui or terminal mode. It's possible that, if the following
+" autocommand method is deemed excessively poor form, that approach will be
+" used again and the autocommand below will be dropped.
+"
+" However it seems relatively benign in this case to include the autocommand
+" here. It fires only in cases where vim is transferring from terminal to gui
+" mode (detected with the script scope s:vmode variable). It also allows for
+" other potential terminal customizations that might make gui mode suboptimal.
+"
+autocmd GUIEnter * if (s:vmode != "gui") | exe "colorscheme " . g:colors_name | endif
+"}}}
+" Highlight Trailing Space {{{
+" Experimental: Different highlight when on cursorline
+function! s:SolarizedHiTrail()
+ if g:solarized_hitrail==0
+ hi! clear solarizedTrailingSpace
+ else
+ syn match solarizedTrailingSpace "\s*$"
+ exe "hi! solarizedTrailingSpace " .s:fmt_undr .s:fg_red .s:bg_none .s:sp_red
+ endif
+endfunction
+augroup SolarizedHiTrail
+ autocmd!
+ if g:solarized_hitrail==1
+ autocmd! Syntax * call s:SolarizedHiTrail()
+ autocmd! ColorScheme * if g:colors_name == "solarized" | call s:SolarizedHiTrail() | else | augroup! s:SolarizedHiTrail | endif
+ endif
+augroup END
+" }}}
+" Menus "{{{
+" ---------------------------------------------------------------------
+" Turn off Solarized menu by including the following assignment in your .vimrc:
+"
+" let g:solarized_menu=0
+
+function! s:SolarizedOptions()
+ new "new buffer
+ setf vim "vim filetype
+ let failed = append(0, s:defaults_list)
+ let failed = append(0, s:colorscheme_list)
+ let failed = append(0, s:options_list)
+ let failed = append(0, s:lazycat_list)
+ 0 "jump back to the top
+endfunction
+if !exists(":SolarizedOptions")
+ command SolarizedOptions :call s:SolarizedOptions()
+endif
+
+function! SolarizedMenu()
+ if exists("g:loaded_solarized_menu")
+ try
+ silent! aunmenu Solarized
+ endtry
+ endif
+ let g:loaded_solarized_menu = 1
+
+ if g:colors_name == "solarized" && g:solarized_menu != 0
+
+ amenu &Solarized.&Contrast.&Low\ Contrast :let g:solarized_contrast="low" \| colorscheme solarized<CR>
+ amenu &Solarized.&Contrast.&Normal\ Contrast :let g:solarized_contrast="normal" \| colorscheme solarized<CR>
+ amenu &Solarized.&Contrast.&High\ Contrast :let g:solarized_contrast="high" \| colorscheme solarized<CR>
+ an &Solarized.&Contrast.-sep- <Nop>
+ amenu &Solarized.&Contrast.&Help:\ Contrast :help 'solarized_contrast'<CR>
+
+ amenu &Solarized.&Visibility.&Low\ Visibility :let g:solarized_visibility="low" \| colorscheme solarized<CR>
+ amenu &Solarized.&Visibility.&Normal\ Visibility :let g:solarized_visibility="normal" \| colorscheme solarized<CR>
+ amenu &Solarized.&Visibility.&High\ Visibility :let g:solarized_visibility="high" \| colorscheme solarized<CR>
+ an &Solarized.&Visibility.-sep- <Nop>
+ amenu &Solarized.&Visibility.&Help:\ Visibility :help 'solarized_visibility'<CR>
+
+ amenu &Solarized.&Background.&Toggle\ Background :ToggleBG<CR>
+ amenu &Solarized.&Background.&Dark\ Background :set background=dark \| colorscheme solarized<CR>
+ amenu &Solarized.&Background.&Light\ Background :set background=light \| colorscheme solarized<CR>
+ an &Solarized.&Background.-sep- <Nop>
+ amenu &Solarized.&Background.&Help:\ ToggleBG :help togglebg<CR>
+
+ if g:solarized_bold==0 | let l:boldswitch="On" | else | let l:boldswitch="Off" | endif
+ exe "amenu &Solarized.&Styling.&Turn\\ Bold\\ ".l:boldswitch." :let g:solarized_bold=(abs(g:solarized_bold-1)) \\| colorscheme solarized<CR>"
+ if g:solarized_italic==0 | let l:italicswitch="On" | else | let l:italicswitch="Off" | endif
+ exe "amenu &Solarized.&Styling.&Turn\\ Italic\\ ".l:italicswitch." :let g:solarized_italic=(abs(g:solarized_italic-1)) \\| colorscheme solarized<CR>"
+ if g:solarized_underline==0 | let l:underlineswitch="On" | else | let l:underlineswitch="Off" | endif
+ exe "amenu &Solarized.&Styling.&Turn\\ Underline\\ ".l:underlineswitch." :let g:solarized_underline=(abs(g:solarized_underline-1)) \\| colorscheme solarized<CR>"
+
+ amenu &Solarized.&Diff\ Mode.&Low\ Diff\ Mode :let g:solarized_diffmode="low" \| colorscheme solarized<CR>
+ amenu &Solarized.&Diff\ Mode.&Normal\ Diff\ Mode :let g:solarized_diffmode="normal" \| colorscheme solarized<CR>
+ amenu &Solarized.&Diff\ Mode.&High\ Diff\ Mode :let g:solarized_diffmode="high" \| colorscheme solarized<CR>
+
+ if g:solarized_hitrail==0 | let l:hitrailswitch="On" | else | let l:hitrailswitch="Off" | endif
+ exe "amenu &Solarized.&Experimental.&Turn\\ Highlight\\ Trailing\\ Spaces\\ ".l:hitrailswitch." :let g:solarized_hitrail=(abs(g:solarized_hitrail-1)) \\| colorscheme solarized<CR>"
+ an &Solarized.&Experimental.-sep- <Nop>
+ amenu &Solarized.&Experimental.&Help:\ HiTrail :help 'solarized_hitrail'<CR>
+
+ an &Solarized.-sep1- <Nop>
+
+ amenu &Solarized.&Autogenerate\ options :SolarizedOptions<CR>
+
+ an &Solarized.-sep2- <Nop>
+
+ amenu &Solarized.&Help.&Solarized\ Help :help solarized<CR>
+ amenu &Solarized.&Help.&Toggle\ Background\ Help :help togglebg<CR>
+ amenu &Solarized.&Help.&Removing\ This\ Menu :help solarized-menu<CR>
+
+ an 9999.77 &Help.&Solarized\ Colorscheme :help solarized<CR>
+ an 9999.78 &Help.&Toggle\ Background :help togglebg<CR>
+ an 9999.79 &Help.-sep3- <Nop>
+
+ endif
+endfunction
+
+autocmd ColorScheme * if g:colors_name != "solarized" | silent! aunmenu Solarized | else | call SolarizedMenu() | endif
+
+"}}}
+" License "{{{
+" ---------------------------------------------------------------------
+"
+" Copyright (c) 2011 Ethan Schoonover
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to deal
+" in the Software without restriction, including without limitation the rights
+" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+" copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+" THE SOFTWARE.
+"
+" vim:foldmethod=marker:foldlevel=0
+"}}}
diff --git a/.vimrc b/.vimrc
new file mode 100644
index 0000000..203becf
--- /dev/null
+++ b/.vimrc
@@ -0,0 +1,56 @@
+set tabstop=2
+set pastetoggle=<f8>
+set tw=80
+syntax on
+set ai
+set si
+set noexpandtab
+set softtabstop=2
+set shiftwidth=2
+set shiftround
+set autoindent
+set lsp=0 " space it out a little more (easier to read)
+set wildmenu " turn on wild menu
+set ruler " Always show current positions along the bottom
+set cmdheight=2 " the command bar is 2 high
+"set number " turn on line numbers
+set lz " do not redraw while running macros (much faster) (LazyRedraw)
+set incsearch
+set laststatus=2
+set smarttab " use tabs at the start of a line, spaces elsewhere
+set background=dark
+colorscheme solarized
+
+" lso colour real TAB areas blue
+highlight SomethingBad ctermbg=lightgreen
+match SomethingBad /.\%>80v\|\s\+$/
+highlight TabChar ctermbg=lightblue
+2match TabChar /\t/
+
+"set spelllang=de_de spell
+set spelllang=en_us spell
+set nospell
+
+"look for ctags in upper directories
+"let tag_dir=getcwd()
+"if match(tag_dir, "^/") == 0
+" let end_dir='/'
+" while !filereadable(tag_dir."/tags") && tag_dir!=$HOME && tag_dir!=end_dir
+" let tag_dir = substitute(tag_dir, '/[^/]\+$', "", "")
+" endwhile
+" if filereadable(tag_dir."/tags")
+" exe "set tags+=".tag_dir."/tags"
+"endif
+"elseif match(tag_dir, "^[a-zA-Z]:[\\/]") == 0
+" let end_dir=tag_dir[0].tag_dir[1]
+" while !filereadable(tag_dir."\\tags") && tag_dir!=end_dir
+" let tag_dir = substitute(tag_dir, '\\[^\\]\+$', "", "")
+" endwhile
+" if filereadable(tag_dir."\\tags")
+" exe "set tags+=".tag_dir."\\tags"
+" endif
+"endif
+
+imap <C-r> Reviewed-by: Manuel Traut <manut@linutronix.de><esc>o
+imap <C-x> Signed-off-by: Manuel Traut <manut@linutronix.de><esc>o
+imap <C-t> ----<S-Enter>Linutronix GmbH<S-Enter>Bahnhofstr. 3<S-Enter>88690 Uhldingen<S-Enter><S-Enter>fon: +49 7556 25 999 16<S-Enter>fax: +49 7556 25 999 99<esc>o
diff --git a/af.sh b/af.sh
new file mode 100755
index 0000000..c703744
--- /dev/null
+++ b/af.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Userland mode (~$USER/), (~/).
+
+# ~/.fonts is now deprecated and that
+#FONT_HOME=~/.fonts
+# ~/.local/share/fonts should be used instead
+FONT_HOME=~/.local/share/fonts
+
+echo "installing fonts at $PWD to $FONT_HOME"
+mkdir -p "$FONT_HOME/adobe-fonts/source-code-pro"
+# find "$FONT_HOME" -iname '*.ttf' -exec echo '{}' \;
+
+(git clone \
+ --branch release \
+ --depth 1 \
+ 'https://github.com/adobe-fonts/source-code-pro.git' \
+ "$FONT_HOME/adobe-fonts/source-code-pro" && \
+fc-cache -f -v "$FONT_HOME/adobe-fonts/source-code-pro")
diff --git a/config-awesome/battery-widget b/config-awesome/battery-widget
new file mode 160000
+Subproject 2bfdbf8d66b5f1c9ca08c203e6c69cf790ca6c3
diff --git a/config-awesome/brightness b/config-awesome/brightness
new file mode 160000
+Subproject b9eb82a7c33163031bf57da29f7405064c73bee
diff --git a/config-awesome/rc.lua b/config-awesome/rc.lua
new file mode 100644
index 0000000..1fc5855
--- /dev/null
+++ b/config-awesome/rc.lua
@@ -0,0 +1,556 @@
+-- Standard awesome library
+local gears = require("gears")
+local awful = require("awful")
+require("awful.autofocus")
+-- Widget and layout library
+local wibox = require("wibox")
+-- Theme handling library
+local beautiful = require("beautiful")
+-- Notification library
+local naughty = require("naughty")
+local menubar = require("menubar")
+local hotkeys_popup = require("awful.hotkeys_popup").widget
+
+-- Load Debian menu entries
+require("debian.menu")
+
+-- {{{ Error handling
+-- Check if awesome encountered an error during startup and fell back to
+-- another config (This code will only ever execute for the fallback config)
+if awesome.startup_errors then
+ naughty.notify({ preset = naughty.config.presets.critical,
+ title = "Oops, there were errors during startup!",
+ text = awesome.startup_errors })
+end
+
+-- Handle runtime errors after startup
+do
+ local in_error = false
+ awesome.connect_signal("debug::error", function (err)
+ -- Make sure we don't go into an endless error loop
+ if in_error then return end
+ in_error = true
+
+ naughty.notify({ preset = naughty.config.presets.critical,
+ title = "Oops, an error happened!",
+ text = tostring(err) })
+ in_error = false
+ end)
+end
+-- }}}
+
+-- {{{ Variable definitions
+-- Themes define colours, icons, font and wallpapers.
+beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua")
+
+-- This is used later as the default terminal and editor to run.
+terminal = "rxvt"
+editor = os.getenv("EDITOR") or "vim"
+editor_cmd = terminal .. " -e " .. editor
+
+-- Default modkey.
+-- Usually, Mod4 is the key with a logo between Control and Alt.
+-- If you do not like this or do not have such a key,
+-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
+-- However, you can use another modifier like Mod1, but it may interact with others.
+modkey = "Mod4"
+
+-- Table of layouts to cover with awful.layout.inc, order matters.
+awful.layout.layouts = {
+ awful.layout.suit.tile,
+ awful.layout.suit.floating,
+ awful.layout.suit.tile.left,
+ awful.layout.suit.tile.bottom,
+ awful.layout.suit.tile.top,
+ awful.layout.suit.fair,
+ awful.layout.suit.fair.horizontal,
+ awful.layout.suit.spiral,
+ awful.layout.suit.spiral.dwindle,
+ awful.layout.suit.max,
+ awful.layout.suit.max.fullscreen,
+ awful.layout.suit.magnifier,
+ awful.layout.suit.corner.nw,
+ -- awful.layout.suit.corner.ne,
+ -- awful.layout.suit.corner.sw,
+ -- awful.layout.suit.corner.se,
+}
+-- }}}
+
+-- {{{ Helper functions
+local function client_menu_toggle_fn()
+ local instance = nil
+
+ return function ()
+ if instance and instance.wibox.visible then
+ instance:hide()
+ instance = nil
+ else
+ instance = awful.menu.clients({ theme = { width = 250 } })
+ end
+ end
+end
+-- }}}
+
+-- {{{ Menu
+-- Create a launcher widget and a main menu
+myawesomemenu = {
+ { "hotkeys", function() return false, hotkeys_popup.show_help end},
+ { "manual", terminal .. " -e man awesome" },
+ { "edit config", editor_cmd .. " " .. awesome.conffile },
+ { "restart", awesome.restart },
+ { "quit", function() awesome.quit() end}
+}
+
+mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
+ { "Debian", debian.menu.Debian_menu.Debian },
+ { "open terminal", terminal }
+ }
+ })
+
+mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
+ menu = mymainmenu })
+
+-- Menubar configuration
+menubar.utils.terminal = terminal -- Set the terminal for applications that require it
+-- }}}
+
+-- {{{ Wibar
+-- Create a textclock widget
+mytextclock = wibox.widget.textclock()
+
+-- Keyboard Layouts
+kbdcfg = {}
+kbdcfg.cmd = "setxkbmap"
+kbdcfg.layout = { { "de", "" }, { "us", "" } }
+kbdcfg.current = 1 -- us is our default layout
+kbdcfg.widget = wibox.widget.textbox()
+kbdcfg.widget:set_text(" " .. kbdcfg.layout[kbdcfg.current][1] .. " ")
+kbdcfg.switch = function ()
+ kbdcfg.current = kbdcfg.current % #(kbdcfg.layout) + 1
+ local t = kbdcfg.layout[kbdcfg.current]
+ kbdcfg.widget:set_text(" " .. t[1] .. " ")
+ os.execute( kbdcfg.cmd .. " " .. t[1] .. " " .. t[2] )
+end
+
+
+-- Create a wibox for each screen and add it
+local taglist_buttons = awful.util.table.join(
+ awful.button({ }, 1, function(t) t:view_only() end),
+ awful.button({ modkey }, 1, function(t)
+ if client.focus then
+ client.focus:move_to_tag(t)
+ end
+ end),
+ awful.button({ }, 3, awful.tag.viewtoggle),
+ awful.button({ modkey }, 3, function(t)
+ if client.focus then
+ client.focus:toggle_tag(t)
+ end
+ end),
+ awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
+ awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
+ )
+
+local tasklist_buttons = awful.util.table.join(
+ awful.button({ }, 1, function (c)
+ if c == client.focus then
+ c.minimized = true
+ else
+ -- Without this, the following
+ -- :isvisible() makes no sense
+ c.minimized = false
+ if not c:isvisible() and c.first_tag then
+ c.first_tag:view_only()
+ end
+ -- This will also un-minimize
+ -- the client, if needed
+ client.focus = c
+ c:raise()
+ end
+ end),
+ awful.button({ }, 3, client_menu_toggle_fn()),
+ awful.button({ }, 4, function ()
+ awful.client.focus.byidx(1)
+ end),
+ awful.button({ }, 5, function ()
+ awful.client.focus.byidx(-1)
+ end))
+
+local function set_wallpaper(s)
+ -- Wallpaper
+ if beautiful.wallpaper then
+ local wallpaper = beautiful.wallpaper
+ -- If wallpaper is a function, call it with the screen
+ if type(wallpaper) == "function" then
+ wallpaper = wallpaper(s)
+ end
+ gears.wallpaper.maximized(wallpaper, s, true)
+ end
+end
+
+-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
+screen.connect_signal("property::geometry", set_wallpaper)
+
+awful.screen.connect_for_each_screen(function(s)
+ -- Wallpaper
+ set_wallpaper(s)
+
+ -- Each screen has its own tag table.
+ awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
+
+ -- Create a promptbox for each screen
+ s.mypromptbox = awful.widget.prompt()
+ -- Create an imagebox widget which will contains an icon indicating which layout we're using.
+ -- We need one layoutbox per screen.
+ s.mylayoutbox = awful.widget.layoutbox(s)
+ s.mylayoutbox:buttons(awful.util.table.join(
+ awful.button({ }, 1, function () awful.layout.inc( 1) end),
+ awful.button({ }, 3, function () awful.layout.inc(-1) end),
+ awful.button({ }, 4, function () awful.layout.inc( 1) end),
+ awful.button({ }, 5, function () awful.layout.inc(-1) end)))
+ -- Create a taglist widget
+ s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
+
+ -- Create a tasklist widget
+ s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
+
+
+ -- Create the wibox
+ s.mywibox = awful.wibar({ position = "top", screen = s })
+
+ -- Add widgets to the wibox
+ s.mywibox:setup {
+ layout = wibox.layout.align.horizontal,
+ { -- Left widgets
+ layout = wibox.layout.fixed.horizontal,
+ mylauncher,
+ s.mytaglist,
+ s.mypromptbox,
+ },
+ s.mytasklist, -- Middle widget
+ { -- Right widgets
+ layout = wibox.layout.fixed.horizontal,
+ cpuwidget,
+ kbdcfg.widget,
+ require("battery-widget") {},
+ wibox.widget.systray(),
+ mytextclock,
+ s.mylayoutbox,
+ },
+ }
+end)
+-- }}}
+
+-- {{{ Mouse bindings
+root.buttons(awful.util.table.join(
+ awful.button({ }, 3, function () mymainmenu:toggle() end),
+ awful.button({ }, 4, awful.tag.viewnext),
+ awful.button({ }, 5, awful.tag.viewprev)
+))
+-- }}}
+
+-- {{{ Key bindings
+globalkeys = awful.util.table.join(
+ awful.key({ modkey, }, "s", hotkeys_popup.show_help,
+ {description="show help", group="awesome"}),
+ awful.key({ modkey, }, "Left", awful.tag.viewprev,
+ {description = "view previous", group = "tag"}),
+ awful.key({ modkey, }, "Right", awful.tag.viewnext,
+ {description = "view next", group = "tag"}),
+ awful.key({ modkey, }, "Escape", awful.tag.history.restore,
+ {description = "go back", group = "tag"}),
+
+ awful.key({ modkey, }, "j",
+ function ()
+ awful.client.focus.byidx( 1)
+ end,
+ {description = "focus next by index", group = "client"}
+ ),
+ awful.key({ modkey, }, "k",
+ function ()
+ awful.client.focus.byidx(-1)
+ end,
+ {description = "focus previous by index", group = "client"}
+ ),
+ awful.key({ modkey, }, "w", function () mymainmenu:show() end,
+ {description = "show main menu", group = "awesome"}),
+
+ -- Layout manipulation
+ awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
+ {description = "swap with next client by index", group = "client"}),
+ awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
+ {description = "swap with previous client by index", group = "client"}),
+ awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
+ {description = "focus the next screen", group = "screen"}),
+ awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
+ {description = "focus the previous screen", group = "screen"}),
+ awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
+ {description = "jump to urgent client", group = "client"}),
+ awful.key({ modkey, }, "Tab",
+ function ()
+ awful.client.focus.history.previous()
+ if client.focus then
+ client.focus:raise()
+ end
+ end,
+ {description = "go back", group = "client"}),
+
+ -- Standard program
+ awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
+ {description = "open a terminal", group = "launcher"}),
+ awful.key({ modkey, "Control" }, "r", awesome.restart,
+ {description = "reload awesome", group = "awesome"}),
+ awful.key({ modkey, "Shift" }, "q", awesome.quit,
+ {description = "quit awesome", group = "awesome"}),
+
+ awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
+ {description = "increase master width factor", group = "layout"}),
+ awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
+ {description = "decrease master width factor", group = "layout"}),
+ awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
+ {description = "increase the number of master clients", group = "layout"}),
+ awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
+ {description = "decrease the number of master clients", group = "layout"}),
+ awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
+ {description = "increase the number of columns", group = "layout"}),
+ awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
+ {description = "decrease the number of columns", group = "layout"}),
+ awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
+ {description = "select next", group = "layout"}),
+ awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
+ {description = "select previous", group = "layout"}),
+
+ awful.key({ modkey, "Control" }, "n",
+ function ()
+ local c = awful.client.restore()
+ -- Focus restored client
+ if c then
+ client.focus = c
+ c:raise()
+ end
+ end,
+ {description = "restore minimized", group = "client"}),
+
+ -- Prompt
+ awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end,
+ {description = "run prompt", group = "launcher"}),
+ -- Menubar
+ awful.key({ modkey }, "p", function() menubar.show() end,
+ {description = "show the menubar", group = "launcher"}),
+ -- change keyboard layout
+ awful.key({ modkey }, "x", function() kbdcfg.switch() end)
+)
+
+clientkeys = awful.util.table.join(
+ awful.key({ modkey, }, "f",
+ function (c)
+ c.fullscreen = not c.fullscreen
+ c:raise()
+ end,
+ {description = "toggle fullscreen", group = "client"}),
+ awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
+ {description = "close", group = "client"}),
+ awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
+ {description = "toggle floating", group = "client"}),
+ awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
+ {description = "move to master", group = "client"}),
+ awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
+ {description = "move to screen", group = "client"}),
+ awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
+ {description = "toggle keep on top", group = "client"}),
+ awful.key({ modkey, }, "n",
+ function (c)
+ -- The client currently has the input focus, so it cannot be
+ -- minimized, since minimized clients can't have the focus.
+ c.minimized = true
+ end ,
+ {description = "minimize", group = "client"}),
+ awful.key({ modkey, }, "m",
+ function (c)
+ c.maximized = not c.maximized
+ c:raise()
+ end ,
+ {description = "maximize", group = "client"})
+)
+
+-- Bind all key numbers to tags.
+-- Be careful: we use keycodes to make it works on any keyboard layout.
+-- This should map on the top row of your keyboard, usually 1 to 9.
+for i = 1, 9 do
+ globalkeys = awful.util.table.join(globalkeys,
+ -- View tag only.
+ awful.key({ modkey }, "#" .. i + 9,
+ function ()
+ local screen = awful.screen.focused()
+ local tag = screen.tags[i]
+ if tag then
+ tag:view_only()
+ end
+ end,
+ {description = "view tag #"..i, group = "tag"}),
+ -- Toggle tag display.
+ awful.key({ modkey, "Control" }, "#" .. i + 9,
+ function ()
+ local screen = awful.screen.focused()
+ local tag = screen.tags[i]
+ if tag then
+ awful.tag.viewtoggle(tag)
+ end
+ end,
+ {description = "toggle tag #" .. i, group = "tag"}),
+ -- Move client to tag.
+ awful.key({ modkey, "Shift" }, "#" .. i + 9,
+ function ()
+ if client.focus then
+ local tag = client.focus.screen.tags[i]
+ if tag then
+ client.focus:move_to_tag(tag)
+ end
+ end
+ end,
+ {description = "move focused client to tag #"..i, group = "tag"}),
+ -- Toggle tag on focused client.
+ awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
+ function ()
+ if client.focus then
+ local tag = client.focus.screen.tags[i]
+ if tag then
+ client.focus:toggle_tag(tag)
+ end
+ end
+ end,
+ {description = "toggle focused client on tag #" .. i, group = "tag"})
+ )
+end
+
+clientbuttons = awful.util.table.join(
+ awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
+ awful.button({ modkey }, 1, awful.mouse.client.move),
+ awful.button({ modkey }, 3, awful.mouse.client.resize))
+
+-- Set keys
+root.keys(globalkeys)
+-- }}}
+
+-- {{{ Rules
+-- Rules to apply to new clients (through the "manage" signal).
+awful.rules.rules = {
+ -- All clients will match this rule.
+ { rule = { },
+ properties = { border_width = beautiful.border_width,
+ border_color = beautiful.border_normal,
+ focus = awful.client.focus.filter,
+ raise = true,
+ keys = clientkeys,
+ buttons = clientbuttons,
+ screen = awful.screen.preferred,
+ placement = awful.placement.no_overlap+awful.placement.no_offscreen
+ }
+ },
+
+ -- Floating clients.
+ { rule_any = {
+ instance = {
+ "DTA", -- Firefox addon DownThemAll.
+ "copyq", -- Includes session name in class.
+ },
+ class = {
+ "Arandr",
+ "Gpick",
+ "Kruler",
+ "MessageWin", -- kalarm.
+ "Sxiv",
+ "Wpa_gui",
+ "pinentry",
+ "veromix",
+ "xtightvncviewer"},
+
+ name = {
+ "Event Tester", -- xev.
+ },
+ role = {
+ "AlarmWindow", -- Thunderbird's calendar.
+ "pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
+ }
+ }, properties = { floating = true }},
+
+ -- Add titlebars to normal clients and dialogs
+ { rule_any = {type = { "normal", "dialog" }
+ }, properties = { titlebars_enabled = false }
+ },
+
+ -- Set Firefox to always map on the tag named "2" on screen 1.
+ -- { rule = { class = "Firefox" },
+ -- properties = { screen = 1, tag = "2" } },
+}
+-- }}}
+
+-- {{{ Signals
+-- Signal function to execute when a new client appears.
+client.connect_signal("manage", function (c)
+ -- Set the windows at the slave,
+ -- i.e. put it at the end of others instead of setting it master.
+ -- if not awesome.startup then awful.client.setslave(c) end
+
+ if awesome.startup and
+ not c.size_hints.user_position
+ and not c.size_hints.program_position then
+ -- Prevent clients from being unreachable after screen count changes.
+ awful.placement.no_offscreen(c)
+ end
+end)
+
+-- Add a titlebar if titlebars_enabled is set to true in the rules.
+client.connect_signal("request::titlebars", function(c)
+ -- buttons for the titlebar
+ local buttons = awful.util.table.join(
+ awful.button({ }, 1, function()
+ client.focus = c
+ c:raise()
+ awful.mouse.client.move(c)
+ end),
+ awful.button({ }, 3, function()
+ client.focus = c
+ c:raise()
+ awful.mouse.client.resize(c)
+ end)
+ )
+
+ awful.titlebar(c) : setup {
+ { -- Left
+ awful.titlebar.widget.iconwidget(c),
+ buttons = buttons,
+ layout = wibox.layout.fixed.horizontal
+ },
+ { -- Middle
+ { -- Title
+ align = "center",
+ widget = awful.titlebar.widget.titlewidget(c)
+ },
+ buttons = buttons,
+ layout = wibox.layout.flex.horizontal
+ },
+ { -- Right
+ awful.titlebar.widget.floatingbutton (c),
+ awful.titlebar.widget.maximizedbutton(c),
+ awful.titlebar.widget.stickybutton (c),
+ awful.titlebar.widget.ontopbutton (c),
+ awful.titlebar.widget.closebutton (c),
+ layout = wibox.layout.fixed.horizontal()
+ },
+ layout = wibox.layout.align.horizontal
+ }
+end)
+
+-- Enable sloppy focus, so that focus follows mouse.
+client.connect_signal("mouse::enter", function(c)
+ if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
+ and awful.client.focus.filter(c) then
+ client.focus = c
+ end
+end)
+
+client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
+client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
+
+-- }}}
diff --git a/icalview.pl b/icalview.pl
new file mode 100755
index 0000000..e065b0d
--- /dev/null
+++ b/icalview.pl
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+
+# vcalendar-filter is a simple filter to give plain text representations of vcards
+# Copyright (C) 2008 Martyn Smith
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This script takes a simple VCALENDAR file as input on STDIN and produces a
+# human readable text/plain representation of it on STDOUT
+#
+# It has been designed for use with mutt's auto_view config option, see the
+# README file for more details
+
+use strict;
+use warnings;
+
+use Data::ICal;
+use Text::Autoformat;
+
+my $body = eval { local $/ = undef; <> };
+my $calendar = Data::ICal->new(data => $body);
+
+# If parsing failed, try parsing as version 1.0
+$calendar = Data::ICal->new(data => $body, vcal10 => 1) unless $calendar;
+
+# If parsing failed, give up :-(
+unless ( $calendar ) {
+ print "Unable to parse vcalendar: ", $calendar->error_message, "\n";
+ print $body;
+ exit 1;
+}
+
+foreach my $entry ( @{$calendar->{entries}} ) {
+ my $properties;
+
+ foreach my $property ( keys %{$entry->properties} ) {
+ next unless defined $entry->property($property);
+ $properties->{$property} = join(', ', map { $_->decoded_value } @{$entry->property($property)});
+ if ( $property eq 'description' ) {
+ $properties->{$property} = eval qq{"$properties->{$property}"};
+
+ $properties->{$property} = autoformat $properties->{$property}, {
+ all => 1,
+ left => 15,
+ };
+ $properties->{$property} =~ s/^\s*// if defined $properties->{$property};
+ }
+ elsif ( $property =~ m{ \A dt (?: start | end ) \z }xms ) {
+ if ( $properties->{$property} =~ m{ (\d\d\d\d)(\d\d)(\d\d)T(\d\d)(\d\d)(\d\d) }xms ) {
+ $properties->{$property} = "$1-$2-$3 $4:$5";
+ }
+ }
+ }
+
+ if ( $entry->ical_entry_type eq 'VTIMEZONE' ) {
+ unless ( defined $properties->{tzid} and $properties->{tzid} =~ m{Pacific/Auckland} ) {
+ print "Timezone : ", $properties->{tzid}, "\n";
+ print "\n";
+ }
+ }
+ elsif ( $entry->ical_entry_type eq 'VEVENT' ) {
+ print '-' x 72, "\n";
+ foreach my $key ( qw(summary BR description BR location organizer dtstart dtend) ) {
+ if ( $key eq 'BR' ) {
+ print "\n";
+ next;
+ }
+ next unless defined $properties->{$key};
+ printf "%-12s: %s\n", ucfirst $key, $properties->{$key};
+ }
+ }
+ else {
+ print "WARNING: Unknown entry type: ", $entry->ical_entry_type, "\n";
+ }
+}
diff --git a/icalview.sh b/icalview.sh
new file mode 100755
index 0000000..b82c3ae
--- /dev/null
+++ b/icalview.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+/home/manut/icalview.pl 2> /dev/null