about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--fish/.config/fish/functions/sys.fish3
-rwxr-xr-xgit/.gitconfig2
-rw-r--r--weechat/.weechat/alias.conf2
-rw-r--r--weechat/.weechat/autosort.conf2
-rw-r--r--weechat/.weechat/irc.conf57
-rw-r--r--weechat/.weechat/perl/colorize_lines.pl61
-rw-r--r--weechat/.weechat/plugins.conf4
l---------weechat/.weechat/python/autoload/topicdiff_alt.py1
-rw-r--r--weechat/.weechat/python/autosort.py149
-rw-r--r--weechat/.weechat/python/topicdiff_alt.py70
10 files changed, 231 insertions, 120 deletions
diff --git a/fish/.config/fish/functions/sys.fish b/fish/.config/fish/functions/sys.fish
new file mode 100644
index 0000000..d193bf9
--- /dev/null
+++ b/fish/.config/fish/functions/sys.fish
@@ -0,0 +1,3 @@
+function sys
+	systemctl $argv
+end
diff --git a/git/.gitconfig b/git/.gitconfig
index a92402c..cb3867a 100755
--- a/git/.gitconfig
+++ b/git/.gitconfig
@@ -28,3 +28,5 @@
 	smtpuser = ben
 [alias]
 	lol = log --oneline --graph --decorate --all
+[rerere]
+	enabled = true
diff --git a/weechat/.weechat/alias.conf b/weechat/.weechat/alias.conf
index 6d6334e..c066fd7 100644
--- a/weechat/.weechat/alias.conf
+++ b/weechat/.weechat/alias.conf
@@ -23,6 +23,7 @@ CL = "buffer clear"
 CLOSE = "buffer close"
 CS = "quote chanserv"
 EXIT = "quit"
+factor = "/exec -sh -o factor $1 | cut -d" " -f 2,3 | tr " " ",""
 flip = "/exec -o flip table $*"
 HS = "quote hostserv"
 IG = "ignore"
@@ -51,6 +52,7 @@ T = "topic"
 tf = "/msg $channel (ノಥ益ಥ)ノ彡┻━┻"
 UB = "unban"
 UMODE = "mode $nick"
+unscramble = "/exec -sh -o curl -s "http://anagramica.com/best/$*" | jq -r '.best[0]'"
 V = "command core version"
 W = "who"
 WC = "window merge"
diff --git a/weechat/.weechat/autosort.conf b/weechat/.weechat/autosort.conf
index 923dff9..cd11d47 100644
--- a/weechat/.weechat/autosort.conf
+++ b/weechat/.weechat/autosort.conf
@@ -11,10 +11,12 @@
 
 [sorting]
 case_sensitive = off
+debug_log = off
 replacements = ""
 rules = ""
 signal_delay = 5
 signals = "buffer_opened buffer_merged buffer_unmerged buffer_renamed"
+sort_limit = 100
 sort_on_config_change = on
 
 [v3]
diff --git a/weechat/.weechat/irc.conf b/weechat/.weechat/irc.conf
index 5e773d7..ede276a 100644
--- a/weechat/.weechat/irc.conf
+++ b/weechat/.weechat/irc.conf
@@ -121,7 +121,7 @@ autorejoin = off
 autorejoin_delay = 30
 away_check = 0
 away_check_max_nicks = 25
-capabilities = "account-notify,away-notify,cap-notify,chghost,extended-join,invite-notify,multi-prefix,server-time,userhost-in-names"
+capabilities = "account-notify,away-notify,cap-notify,chghost,extended-join,invite-notify,multi-prefix,server-time,userhost-in-names,sasl"
 command = ""
 command_delay = 0
 connection_timeout = 60
@@ -181,7 +181,7 @@ tilde.local_hostname
 tilde.usermode
 tilde.command = "/oper root ${sec.data.tildenetoper}; /msg operserv login ${sec.data.pass}"
 tilde.command_delay
-tilde.autojoin = "#meta,#chaos,#secret-sudoers,#opers,#team,#sudoers,#YourTilde,#bots,#music,#politics,#gopher,#tildeverse,#idlerpg,#tilderadio,#minecraft,#tildelinux,#slbr,#cosmic,#institute,#.tilde,#tildetel,#dcss,#center,#thunix,#theasylum,#minetest,#aussie,#uucp,#projects,#hamradio,#vim,#black,#pink,#modded,#red,#admin,#vh7,#cervezafria,#~ :10:20,:57:60"
+tilde.autojoin = "#meta,#chaos,#opers,#secret-sudoers,#team,#sudoers,#yourtilde,#bots,#music,#politics,#gopher,#tildeverse,#idlerpg,#tilderadio,#minecraft,#tildelinux,#slbr,#cosmic,#institute,#.tilde,#tildetel,#dcss,#center,#thunix,#theasylum,#minetest,#aussie,#uucp,#projects,#hamradio,#vim,#black,#pink,#modded,#admin,#vh7,#cervezafria,#~ :10:20,:57:60"
 tilde.autorejoin
 tilde.autorejoin_delay
 tilde.connection_timeout
@@ -222,7 +222,7 @@ hashbang.local_hostname
 hashbang.usermode
 hashbang.command = "/oper benharri x"
 hashbang.command_delay
-hashbang.autojoin = "#!,#!social,#!os,#!politics,#!support,#!git,#!opers"
+hashbang.autojoin = "#!opers,#!git,#!support,#!politics,#!os,#!social,#!"
 hashbang.autorejoin
 hashbang.autorejoin_delay
 hashbang.connection_timeout
@@ -263,7 +263,7 @@ town.local_hostname
 town.usermode
 town.command
 town.command_delay
-town.autojoin = "#tildetown,#bots,#dumpsterfire,#tildemush,#counting,#movienight,#counting-meta,#heavy,#quiet,#counting-anarchy,#soup,#alc"
+town.autojoin = "#tildetown,#bots,#dumpsterfire,#tildemush,#counting,#movienight,#counting-meta,#heavy,#quiet,#counting-anarchy,#soup,#alc,#queer"
 town.autorejoin
 town.autorejoin_delay
 town.connection_timeout
@@ -345,7 +345,7 @@ sdf.local_hostname
 sdf.usermode
 sdf.command
 sdf.command_delay
-sdf.autojoin = "#sdf,#gopher,#anonradio,#helpdesk"
+sdf.autojoin = "#sdf,#gopher,#anonradio,#helpdesk :kick:20:75"
 sdf.autorejoin
 sdf.autorejoin_delay
 sdf.connection_timeout
@@ -468,7 +468,7 @@ freenode.local_hostname
 freenode.usermode
 freenode.command
 freenode.command_delay
-freenode.autojoin = "#weechat,##oodnet,#lobsters,#lobsters-boil,#gitea,#mastodon,#pleroma,#pleroma-offtopic,#oragono,#weechat-android,#git,#tilde.team,#sr.ht,#cmpwn,#gopherproject,#bitreich-en,#bitbot,#bitreich-de 6:10"
+freenode.autojoin = "#weechat,##oodnet,#lobsters,#lobsters-boil,#gitea,#mastodon,#pleroma,#pleroma-offtopic,#oragono,#weechat-android,#git,#tilde.team,#sr.ht,#cmpwn,#gopherproject,#bitreich-en,#bitbot,#bitreich-de,#ircv3,#gophernicus,##jan6 6:10"
 freenode.autorejoin
 freenode.autorejoin_delay
 freenode.connection_timeout
@@ -563,7 +563,7 @@ inspircd.msg_part
 inspircd.msg_quit
 inspircd.notify
 inspircd.split_msg_max_length
-slashnet.addresses = "concrete.slashnet.org"
+slashnet.addresses = "irc.slashnet.org"
 slashnet.proxy
 slashnet.ipv6
 slashnet.ssl = off
@@ -673,7 +673,7 @@ red.local_hostname
 red.usermode
 red.command
 red.command_delay
-red.autojoin
+red.autojoin = "#red"
 red.autorejoin
 red.autorejoin_delay
 red.connection_timeout
@@ -686,3 +686,44 @@ red.msg_part
 red.msg_quit
 red.notify
 red.split_msg_max_length
+ctrl-c.addresses = "ctrl-c.club"
+ctrl-c.proxy
+ctrl-c.ipv6
+ctrl-c.ssl
+ctrl-c.ssl_cert
+ctrl-c.ssl_priorities
+ctrl-c.ssl_dhkey_size
+ctrl-c.ssl_fingerprint
+ctrl-c.ssl_verify
+ctrl-c.password
+ctrl-c.capabilities
+ctrl-c.sasl_mechanism
+ctrl-c.sasl_username
+ctrl-c.sasl_password
+ctrl-c.sasl_key
+ctrl-c.sasl_timeout
+ctrl-c.sasl_fail
+ctrl-c.autoconnect
+ctrl-c.autoreconnect
+ctrl-c.autoreconnect_delay
+ctrl-c.nicks
+ctrl-c.nicks_alternate
+ctrl-c.username
+ctrl-c.realname
+ctrl-c.local_hostname
+ctrl-c.usermode
+ctrl-c.command
+ctrl-c.command_delay
+ctrl-c.autojoin = "#chat"
+ctrl-c.autorejoin
+ctrl-c.autorejoin_delay
+ctrl-c.connection_timeout
+ctrl-c.anti_flood_prio_high
+ctrl-c.anti_flood_prio_low
+ctrl-c.away_check
+ctrl-c.away_check_max_nicks
+ctrl-c.msg_kick
+ctrl-c.msg_part
+ctrl-c.msg_quit
+ctrl-c.notify
+ctrl-c.split_msg_max_length
diff --git a/weechat/.weechat/perl/colorize_lines.pl b/weechat/.weechat/perl/colorize_lines.pl
index a3ba09a..6b0decd 100644
--- a/weechat/.weechat/perl/colorize_lines.pl
+++ b/weechat/.weechat/perl/colorize_lines.pl
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010-2018 by Nils Görs <weechatter@arcor.de>
+# Copyright (c) 2010-2019 by Nils Görs <weechatter@arcor.de>
 # Copyleft (ɔ) 2013 by oakkitten
 #
 # colors the channel text with nick color and also highlight the whole line
@@ -19,6 +19,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # history:
+# 3.7: new option "alternate_color" (https://github.com/weechat/scripts/issues/333) (idea by snuffkins)
 # 3.6: new option "own_lines_color" (idea by Linkandzelda)
 #    : add help about "localvar" to option
 # 3.5: new options "highlight_words" and "highlight_words_color" (idea by jokrebel)
@@ -84,7 +85,7 @@
 
 use strict;
 my $PRGNAME     = "colorize_lines";
-my $VERSION     = "3.6";
+my $VERSION     = "3.7";
 my $AUTHOR      = "Nils Görs <weechatter\@arcor.de>";
 my $LICENCE     = "GPL3";
 my $DESCR       = "Colorize users' text in chat area with their nick color, including highlights";
@@ -100,19 +101,21 @@ my %config = ("buffers"                 => "all",       # all, channel, query
               "ignore_tags"             => "irc_ctcp",
               "highlight_words"         => "off",       # on, off
               "highlight_words_color"   => "black,darkgray",
+              "alternate_color"         => "",
 );
 
 my %help_desc = ("buffers"                  => "Buffer type affected by the script (all/channel/query, default: all)",
                  "blacklist_buffers"        => "Comma-separated list of channels to be ignored (e.g. freenode.#weechat,*.#python)",
-                 "lines"                    => "Apply nickname color to the lines (off/on/nicks). The latter will limit highlighting to nicknames in option 'nicks'. You can use a localvar to color all lines with a given color (eg: /buffer set localvar_set_colorize_lines *yellow)",
-                 "highlight"                => "Apply highlight color to the highlighted lines (off/on/nicks). The latter will limit highlighting to nicknames in option 'nicks'",
+                 "lines"                    => "Apply nickname color to the lines (off/on/nicks). The latter will limit highlighting to nicknames in option 'nicks'. You can use a localvar to color all lines with a given color (eg: /buffer set localvar_set_colorize_lines *yellow). You'll have enable this option to use alternate_color.",
+                 "highlight"                => "Apply highlight color to the highlighted lines (off/on/nicks). The latter will limit highlighting to nicknames in option 'nicks'. Options 'weechat.color.chat_highlight' and 'weechat.color.chat_highlight_bg' will be used as colors.",
                  "nicks"                    => "Comma-separater list of nicks (e.g. freenode.cat,*.dog) OR file name starting with '/' (e.g. /file.txt). In the latter case, nicknames will get loaded from that file inside weechat folder (e.g. from ~/.weechat/file.txt). Nicknames in file are newline-separated (e.g. freenode.dog\\n*.cat)",
-                 "own_lines"                => "Apply nickname color to own lines (off/on/only). The latter turns off all other kinds of coloring altogether",
-                 "own_lines_color"          => "this color will be used for own messages. Set an empty value to use weechat.color.chat_nick_self",
+                 "own_lines"                => "Apply nickname color to own lines (off/on/only). The latter turns off all other kinds of coloring altogether. This option has an higher priority than alternate_color option.",
+                 "own_lines_color"          => "this color will be used for own messages. Set an empty value to use weechat.color.chat_nick_self option",
                  "tags"                     => "Comma-separated list of tags to accept (see /debug tags)",
                  "ignore_tags"              => "Comma-separated list of tags to ignore (see /debug tags)",
                  "highlight_words"          => "highlight word(s) in text, matching word(s) in weechat.look.highlight",
-                 "highlight_words_color"    => "color for highlight word in text (fg:bg)",
+                 "highlight_words_color"    => "color for highlight word in text (format: fg,bg)",
+                 "alternate_color"          => "alternate between two colors for messages (format: fg,bg:fg,bg)",
 );
 
 my @ignore_tags_array;
@@ -165,19 +168,26 @@ sub colorize_cb
 
     my $color = "";
     my $my_nick = weechat::buffer_get_string($buf_ptr, "localvar_nick");
-    my $channel_color = weechat::color( get_localvar_colorize_lines($buf_ptr) );
+    my $channel_color = weechat::color( get_localvar($buf_ptr,"localvar_colorize_lines") );
+    my $alternate_last = get_localvar($buf_ptr,"localvar_colorize_lines_alternate");
+    my ($alternate_color1,$alternate_color2) = split(/:/,$config{alternate_color},2) if ( $config{alternate_color} ne "");
+
+#    weechat::print("","a: $alternate_color1");
+#    weechat::print("","b: $alternate_color2");
 
     if ($my_nick eq $nick)
     {
         # it's our own line
         # process only if own_lines is "on" or "only" (i.e. not "off")
-        return $string if ($config{own_lines} eq "off") && not ($channel_color);
+        return $string if ($config{own_lines} eq "off") && not ($channel_color) && ( $config{alternate_color} eq "" );
 
         $color = weechat::color($config{own_lines_color});
         $color = weechat::color("chat_nick_self") if ($config{own_lines_color} eq "");
-
         $color = $channel_color if ($channel_color) && ($config{own_lines} eq "off");
 
+        $color = get_alternate_color($buf_ptr,$alternate_last,$alternate_color1,$alternate_color2) if ( $config{alternate_color} ne "" ) &&
+        ( $config{own_lines} eq "off" );
+
     } else {
         # it's someone else's line
         # don't process is own_lines are "only"
@@ -195,7 +205,7 @@ sub colorize_cb
             weechat::string_has_highlight_regex($right_nocolor, weechat::config_string(weechat::config_get("weechat.look.highlight_regex"))) ||
             weechat::string_has_highlight_regex($right_nocolor, weechat::buffer_get_string($buf_ptr, "highlight_regex"))
            )) {
-            # that's definitely a highlight! get a hilight color
+            # that's definitely a highlight! get a highlight color
             # and replace the first occurance of coloring, that'd be nick color
             $color = weechat::color('chat_highlight');
             $right =~ s/\31[^\31 ]+?\Q$nick/$color$nick/ if ($action);
@@ -207,6 +217,8 @@ sub colorize_cb
            ) {
             $color = weechat::info_get('irc_nick_color', $nick);
             $color = $channel_color if ($channel_color); 
+
+            $color = get_alternate_color($buf_ptr,$alternate_last,$alternate_color1,$alternate_color2) if ( $config{alternate_color} ne "");
         } else {
             # oh well
             return $string if ($config{highlight_words} ne "on");
@@ -244,6 +256,7 @@ sub colorize_cb
             }
             }
     ######################################## inject colors and go!
+
     my $out = "";
     if ($action) {
         # remove the first color reset - after * nick
@@ -260,11 +273,31 @@ sub colorize_cb
     return $out;
 }
 
-sub get_localvar_colorize_lines
+sub get_localvar
 {
-    my ( $buf_ptr ) = @_;
+    my ( $buf_ptr,$localvar ) = @_;
+    return weechat::buffer_get_string($buf_ptr, "$localvar");
+}
 
-    return weechat::buffer_get_string($buf_ptr, "localvar_colorize_lines");
+sub set_localvar
+{
+    my ( $buf_ptr,$value ) = @_;
+    weechat::buffer_set($buf_ptr, "localvar_set_colorize_lines_alternate", "$value");
+}
+
+sub get_alternate_color
+{
+    my ( $buf_ptr, $alternate_last,$alternate_color1,$alternate_color2 ) = @_;
+    my $color;
+    if (($alternate_last eq "") or ($alternate_last eq "0"))
+    {
+        $color = weechat::color($alternate_color1);
+        set_localvar($buf_ptr,"1");
+    } else {
+        $color = weechat::color($alternate_color2);
+        set_localvar($buf_ptr,"0");
+    }
+    return $color;
 }
 #################################################################################################### config
 
diff --git a/weechat/.weechat/plugins.conf b/weechat/.weechat/plugins.conf
index e1aac68..c9e2d1a 100644
--- a/weechat/.weechat/plugins.conf
+++ b/weechat/.weechat/plugins.conf
@@ -27,6 +27,7 @@ lua.matrix.timeout = "5"
 lua.matrix.typing_notices = "on"
 lua.matrix.user = "ben"
 perl.check_license = "off"
+perl.colorize_lines.alternate_color = ""
 perl.colorize_lines.blacklist_buffers = ""
 perl.colorize_lines.buffers = "all"
 perl.colorize_lines.highlight = "on"
@@ -68,7 +69,7 @@ python.buffer_autoclose.age_limit = "30"
 python.buffer_autoclose.ignore = ""
 python.buffer_autoclose.interval = "1"
 python.check_license = "off"
-python.completion.replace_values = "shrug=>¯\_(ツ)_/¯;;wiki=>https://tilde.team/wiki/;;lenny=>( ͡° ͜ʖ ͡°);;byobu=>https://superuser.com/a/423397/866501;;huh=>(-_-)ゞ゛;;tablefix=>┬─┬ノ( º _ ºノ);;weedoc=>https://weechat.org/files/doc/stable/weechat_user.en.html;;weekeys=>https://weechat.org/files/doc/stable/weechat_user.en.html#key_bindings;;denko=>(´・ω・`);;yuno=>ლ(́ಠ◞益◟ಠ‵ლ);;tf=>(ノಥ益ಥ)ノ彡┻━┻;;tb=>┬─┬ノ( º _ ºノ)"
+python.completion.replace_values = "shrug=>¯\_(ツ)_/¯;;wiki=>https://tilde.team/wiki/;;sword=>o()xxxx[{::::::::::::::::::::::::::::::::::>;;lenny=>( ͡° ͜ʖ ͡°);;byobu=>https://superuser.com/a/423397/866501;;huh=>(-_-)ゞ゛;;tablefix=>┬─┬ノ( º _ ºノ);;weedoc=>https://weechat.org/files/doc/stable/weechat_user.en.html;;weekeys=>https://weechat.org/files/doc/stable/weechat_user.en.html#key_bindings;;denko=>(´・ω・`);;yuno=>ლ(́ಠ◞益◟ಠ‵ლ);;tf=>(ノಥ益ಥ)ノ彡┻━┻;;tb=>┬─┬ノ( º _ ºノ);;ducc=>・゜゜・。。・゜゜\_o< QUACK!"
 python.go.auto_jump = "off"
 python.go.buffer_number = "on"
 python.go.color_name = "black,cyan"
@@ -120,6 +121,7 @@ lua.matrix.read_receipts = "Send read receipts. Note that not sending them will
 lua.matrix.timeout = "Time in seconds until a connection is assumed to be timed out (default: "5")"
 lua.matrix.typing_notices = "Send typing notices when you type (default: "on")"
 lua.matrix.user = "Your homeserver username (default: "")"
+perl.colorize_lines.alternate_color = "alternate between two colors for messages (format: fg,bg:fg,bg)"
 perl.colorize_lines.blacklist_buffers = "Comma-separated list of channels to be ignored (e.g. freenode.#weechat,*.#python)"
 perl.colorize_lines.buffers = "Buffer type affected by the script (all/channel/query, default: all)"
 perl.colorize_lines.highlight = "Apply highlight color to the highlighted lines (off/on/nicks). The latter will limit highlighting to nicknames in option 'nicks'"
diff --git a/weechat/.weechat/python/autoload/topicdiff_alt.py b/weechat/.weechat/python/autoload/topicdiff_alt.py
deleted file mode 120000
index 0dd2926..0000000
--- a/weechat/.weechat/python/autoload/topicdiff_alt.py
+++ /dev/null
@@ -1 +0,0 @@
-../topicdiff_alt.py
\ No newline at end of file
diff --git a/weechat/.weechat/python/autosort.py b/weechat/.weechat/python/autosort.py
index 08a6c5b..46a840c 100644
--- a/weechat/.weechat/python/autosort.py
+++ b/weechat/.weechat/python/autosort.py
@@ -25,6 +25,11 @@
 
 #
 # Changelog:
+# 3.4:
+#   * Fix rate-limit of sorting to prevent high CPU load and lock-ups.
+#   * Fix bug in parsing empty arguments for info hooks.
+#   * Add debug_log option to aid with debugging.
+#   * Correct a few typos.
 # 3.3:
 #   * Fix the /autosort debug command for unicode.
 #   * Update the default rules to work better with Slack.
@@ -71,14 +76,17 @@ import weechat
 
 SCRIPT_NAME     = 'autosort'
 SCRIPT_AUTHOR   = 'Maarten de Vries <maarten@de-vri.es>'
-SCRIPT_VERSION  = '3.3'
+SCRIPT_VERSION  = '3.4'
 SCRIPT_LICENSE  = 'GPL3'
 SCRIPT_DESC     = 'Flexible automatic (or manual) buffer sorting based on eval expressions.'
 
 
-config = None
-hooks  = []
-timer  = None
+config             = None
+hooks              = []
+signal_delay_timer = None
+sort_limit_timer   = None
+sort_queued        = False
+
 
 # Make sure that unicode, bytes and str are always available in python2 and 3.
 # For python 2, str == bytes
@@ -147,12 +155,12 @@ def decode_rules(blob):
 def decode_helpers(blob):
 	parsed = json.loads(blob)
 	if not isinstance(parsed, dict):
-		log('Malformed helpers, expected a JSON encoded dictonary but got a {0}. No helpers have been loaded. Please fix the setting manually.'.format(type(parsed)))
+		log('Malformed helpers, expected a JSON encoded dictionary but got a {0}. No helpers have been loaded. Please fix the setting manually.'.format(type(parsed)))
 		return {}
 
 	for key, value in parsed.items():
 		if not isinstance(value, (str, unicode)):
-			log('Helper "{0}" is not a string but a {1}. No helpers have been loaded. Please fix seting manually.'.format(key, type(value)))
+			log('Helper "{0}" is not a string but a {1}. No helpers have been loaded. Please fix setting manually.'.format(key, type(value)))
 			return {}
 	return parsed
 
@@ -180,6 +188,7 @@ class Config:
 	})
 
 	default_signal_delay = 5
+	default_sort_limit   = 100
 
 	default_signals = 'buffer_opened buffer_merged buffer_unmerged buffer_renamed'
 
@@ -196,14 +205,18 @@ class Config:
 		self.helpers          = {}
 		self.signals          = []
 		self.signal_delay     = Config.default_signal_delay,
+		self.sort_limit       = Config.default_sort_limit,
 		self.sort_on_config   = True
+		self.debug_log        = False
 
 		self.__case_sensitive = None
 		self.__rules          = None
 		self.__helpers        = None
 		self.__signals        = None
 		self.__signal_delay   = None
+		self.__sort_limit     = None
 		self.__sort_on_config = None
+		self.__debug_log      = None
 
 		if not self.config_file:
 			log('Failed to initialize configuration file "{0}".'.format(self.filename))
@@ -273,6 +286,14 @@ class Config:
 			'', '', '', '', '', ''
 		)
 
+		self.__sort_limit = weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'sort_limit', 'integer',
+			'Minimum delay in milliseconds to wait after sorting before signals can trigger a sort again. This is effectively a rate limit on sorting. Keeping signal_delay low while setting this higher can reduce excessive sorting without a long initial delay.',
+			'', 0, 1000, str(Config.default_sort_limit), str(Config.default_sort_limit), 0,
+			'', '', '', '', '', ''
+		)
+
 		self.__sort_on_config = weechat.config_new_option(
 			self.config_file, self.sorting_section,
 			'sort_on_config_change', 'boolean',
@@ -281,6 +302,14 @@ class Config:
 			'', '', '', '', '', ''
 		)
 
+		self.__debug_log = weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'debug_log', 'boolean',
+			'If enabled, print more debug messages. Not recommended for normal usage.',
+			'', 0, 0, 'off', 'off', 0,
+			'', '', '', '', '', ''
+		)
+
 		if weechat.config_read(self.config_file) != weechat.WEECHAT_RC_OK:
 			log('Failed to load configuration file.')
 
@@ -302,7 +331,9 @@ class Config:
 		self.helpers        = decode_helpers(helpers_blob)
 		self.signals        = signals_blob.split()
 		self.signal_delay   = weechat.config_integer(self.__signal_delay)
+		self.sort_limit     = weechat.config_integer(self.__sort_limit)
 		self.sort_on_config = weechat.config_boolean(self.__sort_on_config)
+		self.debug_log      = weechat.config_boolean(self.__debug_log)
 
 	def save_rules(self, run_callback = True):
 		''' Save the current rules to the configuration. '''
@@ -317,10 +348,12 @@ def pad(sequence, length, padding = None):
 	''' Pad a list until is has a certain length. '''
 	return sequence + [padding] * max(0, (length - len(sequence)))
 
-
 def log(message, buffer = 'NULL'):
 	weechat.prnt(buffer, 'autosort: {0}'.format(message))
 
+def debug(message, buffer = 'NULL'):
+	if config.debug_log:
+		weechat.prnt(buffer, 'autosort: debug: {0}'.format(message))
 
 def get_buffers():
 	''' Get a list of all the buffers in weechat. '''
@@ -396,18 +429,23 @@ def split_args(args, expected, optional = 0):
 		raise HumanReadableError('Expected at least {0} arguments, got {1}.'.format(expected, len(split)))
 	return split[:-1] + pad(split[-1].split(' ', optional), optional + 1, '')
 
-def do_sort():
+def do_sort(verbose = False):
+	start = perf_counter()
+
 	hdata, buffers = get_buffers()
 	buffers = merge_buffer_list(buffers)
 	buffers = sort_buffers(hdata, buffers, config.rules, config.helpers, config.case_sensitive)
 	apply_buffer_order(buffers)
 
+	elapsed = perf_counter() - start
+	if verbose:
+		log("Finished sorting buffers in {0:.4f} seconds.".format(elapsed))
+	else:
+		debug("Finished sorting buffers in {0:.4f} seconds.".format(elapsed))
+
 def command_sort(buffer, command, args):
 	''' Sort the buffers and print a confirmation. '''
-	start = perf_counter()
-	do_sort()
-	elapsed = perf_counter() - start
-	log("Finished sorting buffers in {0:.4f} seconds.".format(elapsed))
+	do_sort(True)
 	return weechat.WEECHAT_RC_OK
 
 def command_debug(buffer, command, args):
@@ -429,7 +467,7 @@ def command_debug(buffer, command, args):
 		fullname = ensure_str(fullname)
 		result = [ensure_str(x) for x in result]
 		log('{0}: {1}'.format(fullname, result))
-	log('Computing evalutaion results took {0:.4f} seconds.'.format(elapsed))
+	log('Computing evaluation results took {0:.4f} seconds.'.format(elapsed))
 
 	return weechat.WEECHAT_RC_OK
 
@@ -574,7 +612,7 @@ def command_helper_swap(buffer, command, args):
 	return weechat.WEECHAT_RC_OK
 
 def call_command(buffer, command, args, subcommands):
-	''' Call a subccommand from a dictionary. '''
+	''' Call a subcommand from a dictionary. '''
 	subcommand, tail = pad(args.split(' ', 1), 2, '')
 	subcommand = subcommand.strip()
 	if (subcommand == ''):
@@ -591,21 +629,78 @@ def call_command(buffer, command, args, subcommands):
 	log('{0}: command not found'.format(' '.join(command)))
 	return weechat.WEECHAT_RC_ERROR
 
-def on_signal(*args, **kwargs):
-	global timer
-	''' Called whenever the buffer list changes. '''
-	if timer is not None:
-		weechat.unhook(timer)
-		timer = None
-	weechat.hook_timer(config.signal_delay, 0, 1, "on_timeout", "")
+def on_signal(data, signal, signal_data):
+	global signal_delay_timer
+	global sort_queued
+
+	# If the sort limit timeout is started, we're in the hold-off time after sorting, just queue a sort.
+	if sort_limit_timer is not None:
+		if sort_queued:
+			debug('Signal {0} ignored, sort limit timeout is active and sort is already queued.'.format(signal))
+		else:
+			debug('Signal {0} received but sort limit timeout is active, sort is now queued.'.format(signal))
+		sort_queued = True
+		return weechat.WEECHAT_RC_OK
+
+	# If the signal delay timeout is started, a signal was recently received, so ignore this signal.
+	if signal_delay_timer is not None:
+		debug('Signal {0} ignored, signal delay timeout active.'.format(signal))
+		return weechat.WEECHAT_RC_OK
+
+	# Otherwise, start the signal delay timeout.
+	debug('Signal {0} received, starting signal delay timeout of {1} ms.'.format(signal, config.signal_delay))
+	weechat.hook_timer(config.signal_delay, 0, 1, "on_signal_delay_timeout", "")
 	return weechat.WEECHAT_RC_OK
 
-def on_timeout(pointer, remaining_calls):
-	global timer
-	timer = None
+def on_signal_delay_timeout(pointer, remaining_calls):
+	""" Called when the signal_delay_timer triggers. """
+	global signal_delay_timer
+	global sort_limit_timer
+	global sort_queued
+
+	signal_delay_timer = None
+
+	# If the sort limit timeout was started, we're still in the no-sort period, so just queue a sort.
+	if sort_limit_timer is not None:
+		debug('Signal delay timeout expired, but sort limit timeout is active, sort is now queued.')
+		sort_queued = True
+		return weechat.WEECHAT_RC_OK
+
+	# Time to sort!
+	debug('Signal delay timeout expired, starting sort.')
 	do_sort()
+
+	# Start the sort limit timeout if not disabled.
+	if config.sort_limit > 0:
+		debug('Starting sort limit timeout of {0} ms.'.format(config.sort_limit))
+		sort_limit_timer = weechat.hook_timer(config.sort_limit, 0, 1, "on_sort_limit_timeout", "")
+
 	return weechat.WEECHAT_RC_OK
 
+def on_sort_limit_timeout(pointer, remainin_calls):
+	""" Called when de sort_limit_timer triggers. """
+	global sort_limit_timer
+	global sort_queued
+
+	# If no signal was received during the timeout, we're done.
+	if not sort_queued:
+		debug('Sort limit timeout expired without receiving a signal.')
+		sort_limit_timer = None
+		return weechat.WEECHAT_RC_OK
+
+	# Otherwise it's time to sort.
+	debug('Signal received during sort limit timeout, starting queued sort.')
+	do_sort()
+	sort_queued = False
+
+	# Start the sort limit timeout again if not disabled.
+	if config.sort_limit > 0:
+		debug('Starting sort limit timeout of {0} ms.'.format(config.sort_limit))
+		sort_limit_timer = weechat.hook_timer(config.sort_limit, 0, 1, "on_sort_limit_timeout", "")
+
+	return weechat.WEECHAT_RC_OK
+
+
 def apply_config():
 	# Unhook all signals and hook the new ones.
 	for hook in hooks:
@@ -614,6 +709,7 @@ def apply_config():
 		hooks.append(weechat.hook_signal(signal, 'on_signal', ''))
 
 	if config.sort_on_config:
+		debug('Sorting because configuration changed.')
 		do_sort()
 
 def on_config_changed(*args, **kwargs):
@@ -624,7 +720,7 @@ def on_config_changed(*args, **kwargs):
 	return weechat.WEECHAT_RC_OK
 
 def parse_arg(args):
-	if not args: return None, None
+	if not args: return '', None
 
 	result  = ''
 	escaped = False
@@ -643,10 +739,11 @@ def parse_args(args, max = None):
 	result = []
 	i = 0
 	while max is None or i < max:
+		i += 1
 		arg, args = parse_arg(args)
 		if arg is None: break
 		result.append(arg)
-		i += 1
+		if args is None: break
 	return result, args
 
 def on_info_replace(pointer, name, arguments):
diff --git a/weechat/.weechat/python/topicdiff_alt.py b/weechat/.weechat/python/topicdiff_alt.py
deleted file mode 100644
index c76fa22..0000000
--- a/weechat/.weechat/python/topicdiff_alt.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import weechat
-import diff_match_patch
-import re
-
-weechat.register('topicdiff_alt', 'Juerd <#####@juerd.nl>', '1.01', 'PD', "Announce topic with changes highlighted", '', '')
-
-def topic(data, tags, msg):
-    server = tags.split(",")[0]
-
-    match = re.search(r':(\S+)\s+TOPIC\s+(\S+)\s+:(.*)', msg)
-
-    if not match:
-        return weechat.WEECHAT_RC_ERROR
-
-    usermask, channel, newtopic = match.groups()
-    nick, host = usermask.split("!", 1)
-
-    buffer = weechat.buffer_search("irc", server + "." + channel)
-    weechat.prnt("", server + "." + channel)
-
-    if not buffer:
-        return weechat.WEECHAT_RC_ERROR
-
-    oldtopic = weechat.buffer_get_string(buffer, "title")
-    if oldtopic == None:
-        oldtopic = ""
-
-    dmp = diff_match_patch.diff_match_patch()
-    diff = dmp.diff_main(oldtopic, newtopic)
-    dmp.diff_cleanupEfficiency(diff)
-
-    topic = ""
-
-    color_reset = weechat.color("reset")
-    color_ins = weechat.color(weechat.config_get_plugin("color_ins"))
-    color_del = weechat.color(weechat.config_get_plugin("color_del"))
-
-    for chunk in diff:
-        changed, text = chunk
-
-        topic += "%s%s%s" % (
-            # 0 (unchanged), 1 (added), -1 (removed)
-            ["", color_ins, color_del][changed],
-            text,
-            ["", color_reset, color_reset][changed]
-        )
-
-    weechat.prnt_date_tags(buffer, 0, "irc_topicdiff",
-        "%s%s%s%s has changed topic for %s%s%s: %s" % (
-        weechat.prefix("network"),
-        weechat.color(weechat.info_get("irc_nick_color", nick)) \
-            if weechat.config_boolean("irc.look.color_nicks_in_server_messages") \
-            else weechat.color("chat_nick"),
-        nick,
-        color_reset,
-        weechat.color("chat_channel"),
-        channel,
-        color_reset,
-        topic
-    ))
-
-    return weechat.WEECHAT_RC_OK
-
-weechat.hook_signal("*,irc_in_topic", "topic", "")
-
-if not weechat.config_is_set_plugin("color_ins"):
-    weechat.config_set_plugin("color_ins", "lightcyan")
-
-if not weechat.config_is_set_plugin("color_del"):
-    weechat.config_set_plugin("color_del", "darkgray")