--- a/gitconfig Tue Aug 17 15:20:33 2021 -0400
+++ b/gitconfig Mon Aug 23 11:51:18 2021 -0400
@@ -8,6 +8,7 @@
excludesfile = ~/.gitignore
[alias]
+ mainbranch = "!f() { git branch | grep -P ' (master|main)$' | sed -Ee 's/.* //'; }; f"
tags = tag -l
branches = branch -a
remotes = remote -v
@@ -33,9 +34,6 @@
ci = commit
cm = commit -m
- rom = rebase origin/master
- rec = rebase --continue
-
d = diff
di = diff --cached
dl = "!f() { git diff \"$@\" | nvim -R -c 'set ft=diff' -; }; f"
@@ -84,7 +82,7 @@
fuu = "!sh -c 'git fu && git uu' -"
fuo = "!sh -c 'git fo && git uo' -"
- fuom = "!sh -c 'git co master && git fo && git uo' -"
+ fuom = "!sh -c 'git co $(git mainbranch) && git fo && git uo' -"
addremove = !git add . && git add -u
addrem = !git addremove
--- a/lispwords Tue Aug 17 15:20:33 2021 -0400
+++ b/lispwords Mon Aug 23 11:51:18 2021 -0400
@@ -121,6 +121,7 @@
; stumpwm
(3 defcommand)
+(1 when-let-window)
; adopt
(2 define-interface)
@@ -140,3 +141,4 @@
; boots
(1 event-case)
+
--- a/psqlrc Tue Aug 17 15:20:33 2021 -0400
+++ b/psqlrc Mon Aug 23 11:51:18 2021 -0400
@@ -10,3 +10,4 @@
\setenv PAGER less
\setenv LESS -iS
+
--- a/stumpwmrc Tue Aug 17 15:20:33 2021 -0400
+++ b/stumpwmrc Mon Aug 23 11:51:18 2021 -0400
@@ -7,7 +7,7 @@
;;;; Config -------------------------------------------------------------------
(set-prefix-key (kbd "C-space"))
-(redirect-all-output (data-dir-file "debug" "log"))
+(defvar *redirected* (redirect-all-output (data-dir-file "debug" "log")))
(setf *mouse-focus-policy* :click
*message-window-gravity* :center
@@ -144,6 +144,10 @@
"Find and return a fresh list of all windows that match `query` under `window-match-p`."
(remove-if-not (lambda (w) (window-match-p query w)) (all-windows)))
+(defmacro when-let-window ((symbol title-query) &body body)
+ `(when-let ((,symbol (find-window `(:title ,(ppcre:create-scanner ,title-query)))))
+ ,@body))
+
;;;; Posture ------------------------------------------------------------------
(defparameter *posture-thread* nil)
@@ -402,10 +406,17 @@
(run-shell-command (format nil "mark ~A" thing)))
(defcommand toggle-zoom-mute () ()
- (when-let ((win (find-window `(:title ,(ppcre:create-scanner "^Zoom Meeting.*")))))
+ (when-let-window (win "^Zoom Meeting.*")
(focus-window win t) ; Zoom stupidly won't accept the shortcut unless it's in focus
(meta (kbd "M-a"))))
+(defcommand end-zoom () ()
+ (when-let-window (win "^Zoom Meeting.*")
+ (kill-window win))
+ (sleep 2)
+ (when-let-window (win "^Zoom -.*")
+ (kill-window win)))
+
;;;; Terminal Fonts -----------------------------------------------------------
(defcommand reload-terminal-font-size ()
@@ -473,8 +484,8 @@
(run-or-raise "gcontrol" '(:class "Gnome-control-center")))
(defcommand zoom () ()
- (when-let ((window (find-window `(:title ,(ppcre:create-scanner "^Zoom Meeting.*")))))
- (focus-window window t)))
+ (when-let-window (w "^Zoom Meeting.*")
+ (focus-window w t)))
;;;; Timers -------------------------------------------------------------------
@@ -547,6 +558,7 @@
("H-o" "files")
("H-z" "zoom")
("XF86Launch8" "toggle-zoom-mute")
+ ("H-XF86Launch8" "end-zoom")
("H-q" "exec lock-screen")
("H-y" "screenshot")
("H-g" "gcontrol")
--- a/weechat/alias.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/alias.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- alias.conf
+# WeeChat -- alias.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
--- a/weechat/autosort.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/autosort.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,18 +1,24 @@
#
-# weechat -- autosort.conf
+# WeeChat -- autosort.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
[sorting]
case_sensitive = off
-group_irc = on
+debug_log = off
replacements = "[]"
rules = "[["core", 0], ["irc", 2], ["*", 1], ["irc.irc_raw", 0], ["irc.server", 1]]"
+signal_delay = 5
signals = "buffer_opened buffer_merged buffer_unmerged buffer_renamed"
+sort_limit = 100
sort_on_config_change = on
+
+[v3]
+helpers = "{"core_first": "${if:${buffer.full_name}!=core.weechat}", "irc_raw_first": "${if:${buffer.full_name}!=irc.irc_raw}", "irc_raw_last": "${if:${buffer.full_name}==irc.irc_raw}", "hashless_name": "${info:autosort_replace,#,,${info:autosort_escape,${buffer.name}}}", "script_or_plugin": "${if:${script_name}?${script_name}:${plugin}}"}"
+rules = "["${core_first}", "${info:autosort_order,${info:autosort_escape,${script_or_plugin}},core,*,irc,bitlbee,matrix,slack}", "${script_or_plugin}", "${irc_raw_first}", "${server}", "${info:autosort_order,${type},server,*,channel,private}", "${hashless_name}", "${buffer.full_name}"]"
--- a/weechat/buflist.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/buflist.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- buflist.conf
+# WeeChat -- buflist.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
@@ -21,6 +21,7 @@
nick_prefix_empty = on
signals_refresh = ""
sort = "number,-active"
+use_items = 1
[format]
buffer = "${format_number}${indent}${format_nick_prefix}${color_hotlist}${format_name}"
@@ -37,3 +38,4 @@
name = "${name}"
nick_prefix = "${color_nick_prefix}${nick_prefix}"
number = "${color:green}${number}${if:${number_displayed}?.: }"
+tls_version = " ${color:default}(${if:${tls_version}==TLS1.3?${color:green}:${if:${tls_version}==TLS1.2?${color:yellow}:${color:red}}}${translate:${tls_version}}${color:default})"
--- a/weechat/charset.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/charset.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- charset.conf
+# WeeChat -- charset.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
--- a/weechat/exec.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/exec.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- exec.conf
+# WeeChat -- exec.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
@@ -12,6 +12,7 @@
[command]
default_options = ""
purge_delay = 0
+shell = "${env:SHELL}"
[color]
flag_finished = lightred
--- a/weechat/fifo.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/fifo.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- fifo.conf
+# WeeChat -- fifo.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
--- a/weechat/fset.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/fset.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,15 +1,16 @@
#
-# weechat -- fset.conf
+# WeeChat -- fset.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
[look]
+auto_refresh = "*"
auto_unmark = off
condition_catch_set = "${count} >= 1"
export_help_default = on
--- a/weechat/logger.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/logger.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- logger.conf
+# WeeChat -- logger.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
@@ -19,6 +19,7 @@
[file]
auto_log = on
+color_lines = off
flush_delay = 120
fsync = off
info_lines = off
--- a/weechat/python.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/python.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- python.conf
+# WeeChat -- python.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
--- a/weechat/python/autoload/autosort.py Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/python/autoload/autosort.py Mon Aug 23 11:51:18 2021 -0400
@@ -1,860 +1,1 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013-2014 Maarten de Vries <maarten@de-vri.es>
-#
-# 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/>.
-#
-
-#
-# Autosort automatically keeps your buffers sorted and grouped by server.
-# You can define your own sorting rules. See /help autosort for more details.
-#
-# http://github.com/de-vri.es/weechat-autosort
-#
-
-#
-# Changelog:
-# 2.5:
-# * Fix handling unicode buffer names.
-# * Add hint to set irc.look.server_buffer to independent and buffers.look.indenting to on.
-# 2.4:
-# * Make script python3 compatible.
-# 2.3:
-# * Fix sorting items without score last (regressed in 2.2).
-# 2.2:
-# * Add configuration option for signals that trigger a sort.
-# * Add command to manually trigger a sort (/autosort sort).
-# * Add replacement patterns to apply before sorting.
-# 2.1:
-# * Fix some minor style issues.
-# 2.0:
-# * Allow for custom sort rules.
-#
-
-
-import weechat
-import re
-import json
-
-SCRIPT_NAME = 'autosort'
-SCRIPT_AUTHOR = 'Maarten de Vries <maarten@de-vri.es>'
-SCRIPT_VERSION = '2.5'
-SCRIPT_LICENSE = 'GPL3'
-SCRIPT_DESC = 'Automatically or manually keep your buffers sorted and grouped by server.'
-
-
-config = None
-hooks = []
-
-class HumanReadableError(Exception):
- pass
-
-
-def parse_int(arg, arg_name = 'argument'):
- ''' Parse an integer and provide a more human readable error. '''
- arg = arg.strip()
- try:
- return int(arg)
- except ValueError:
- raise HumanReadableError('Invalid {0}: expected integer, got "{1}".'.format(arg_name, arg))
-
-
-class Pattern:
- ''' A simple glob-like pattern for matching buffer names. '''
-
- def __init__(self, pattern):
- ''' Construct a pattern from a string. '''
- escaped = False
- char_class = 0
- chars = ''
- regex = ''
- for c in pattern:
- if escaped and char_class:
- escaped = False
- chars += re.escape(c)
- elif escaped:
- escaped = False
- regex += re.escape(c)
- elif c == '\\':
- escaped = True
- elif c == '*' and not char_class:
- regex += '[^.]*'
- elif c == '?' and not char_class:
- regex += '[^.]'
- elif c == '[' and not char_class:
- char_class = 1
- chars = ''
- elif c == '^' and char_class and not chars:
- chars += '^'
- elif c == ']' and char_class and chars not in ('', '^'):
- char_class = False
- regex += '[' + chars + ']'
- elif c == '-' and char_class:
- chars += '-'
- elif char_class:
- chars += re.escape(c)
- else:
- regex += re.escape(c)
-
- if char_class:
- raise ValueError("unmatched opening '['")
- if escaped:
- raise ValueError("unexpected trailing '\\'")
-
- self.regex = re.compile('^' + regex + '$')
- self.pattern = pattern
-
- def match(self, input):
- ''' Match the pattern against a string. '''
- return self.regex.match(input)
-
-
-class FriendlyList(object):
- ''' A list with human readable errors. '''
-
- def __init__(self):
- self.__data = []
-
- def raw(self):
- return self.__data
-
- def append(self, value):
- ''' Add a rule to the list. '''
- self.__data.append(value)
-
- def insert(self, index, value):
- ''' Add a rule to the list. '''
- if not 0 <= index <= len(self): raise HumanReadableError('Index out of range: expected an integer in the range [0, {0}], got {1}.'.format(len(self), index))
- self.__data.insert(index, value)
-
- def pop(self, index):
- ''' Remove a rule from the list and return it. '''
- if not 0 <= index < len(self): raise HumanReadableError('Index out of range: expected an integer in the range [0, {0}), got {1}.'.format(len(self), index))
- return self.__data.pop(index)
-
- def move(self, index_a, index_b):
- ''' Move a rule to a new position in the list. '''
- self.insert(index_b, self.pop(index_a))
-
- def swap(self, index_a, index_b):
- ''' Swap two elements in the list. '''
- self[index_a], self[index_b] = self[index_b], self[index_a]
-
- def __len__(self):
- return len(self.__data)
-
- def __getitem__(self, index):
- if not 0 <= index < len(self): raise HumanReadableError('Index out of range: expected an integer in the range [0, {0}), got {1}.'.format(len(self), index))
- return self.__data[index]
-
- def __setitem__(self, index, value):
- if not 0 <= index < len(self): raise HumanReadableError('Index out of range: expected an integer in the range [0, {0}), got {1}.'.format(len(self), index))
- self.__data[index] = value
-
- def __iter__(self):
- return iter(self.__data)
-
-
-class RuleList(FriendlyList):
- ''' A list of rules to test buffer names against. '''
- rule_regex = re.compile(r'^(.*)=\s*([+-]?[^=]*)$')
-
- def __init__(self, rules):
- ''' Construct a RuleList from a list of rules. '''
- super(RuleList, self).__init__()
- for rule in rules: self.append(rule)
-
- def get_score(self, name, rules):
- ''' Get the sort score of a partial name according to a rule list. '''
- for rule in self:
- if rule[0].match(name): return rule[1]
- return 999999999
-
- def encode(self):
- ''' Encode the rules for storage. '''
- return json.dumps(list(map(lambda x: (x[0].pattern, x[1]), self)))
-
- @staticmethod
- def decode(blob):
- ''' Parse rules from a string blob. '''
- result = []
-
- try:
- decoded = json.loads(blob)
- except ValueError:
- log('Invalid rules: expected JSON encoded list of pairs, got "{0}".'.format(blob))
- return [], 0
-
- for rule in decoded:
- # Rules must be a pattern,score pair.
- if len(rule) != 2:
- log('Invalid rule: expected (pattern, score), got "{0}". Rule ignored.'.format(rule))
- continue
-
- # Rules must have a valid pattern.
- try:
- pattern = Pattern(rule[0])
- except ValueError as e:
- log('Invalid pattern: {0} in "{1}". Rule ignored.'.format(e, rule[0]))
- continue
-
- # Rules must have a valid score.
- try:
- score = int(rule[1])
- except ValueError as e:
- log('Invalid score: expected an integer, got "{0}". Rule ignored.'.format(score))
- continue
-
- result.append((pattern, score))
-
- return RuleList(result)
-
- @staticmethod
- def parse_rule(arg):
- ''' Parse a rule argument. '''
- arg = arg.strip()
- match = RuleList.rule_regex.match(arg)
- if not match:
- raise HumanReadableError('Invalid rule: expected "<pattern> = <score>", got "{0}".'.format(arg))
-
- pattern = match.group(1).strip()
- try:
- pattern = Pattern(pattern)
- except ValueError as e:
- raise HumanReadableError('Invalid pattern: {0} in "{1}".'.format(e, pattern))
-
- score = parse_int(match.group(2), 'score')
- return (pattern, score)
-
-
-def decode_replacements(blob):
- ''' Decode a replacement list encoded as JSON. '''
- result = FriendlyList()
- try:
- decoded = json.loads(blob)
- except ValueError:
- log('Invalid replacement list: expected JSON encoded list of pairs, got "{0}".'.format(blob))
- return [], 0
-
- for replacement in decoded:
- # Replacements must be a (string, string) pair.
- if len(replacement) != 2:
- log('Invalid replacement pattern: expected (pattern, replacement), got "{0}". Replacement ignored.'.format(rule))
- continue
- result.append(replacement)
-
- return result
-
-
-def encode_replacements(replacements):
- ''' Encode a list of replacement patterns as JSON. '''
- return json.dumps(replacements.raw())
-
-
-class Config:
- ''' The autosort configuration. '''
-
- default_rules = json.dumps([
- ('core', 0),
- ('irc', 2),
- ('*', 1),
-
- ('irc.irc_raw', 0),
- ('irc.server', 1),
- ])
-
- default_replacements = '[]'
- default_signals = 'buffer_opened buffer_merged buffer_unmerged buffer_renamed'
-
- def __init__(self, filename):
- ''' Initialize the configuration. '''
-
- self.filename = filename
- self.config_file = weechat.config_new(self.filename, '', '')
- self.sorting_section = None
-
- self.case_sensitive = False
- self.group_irc = True
- self.rules = []
- self.replacements = []
- self.signals = []
- self.sort_on_config = True
-
- self.__case_sensitive = None
- self.__group_irc = None
- self.__rules = None
- self.__replacements = None
- self.__signals = None
- self.__sort_on_config = None
-
- if not self.config_file:
- log('Failed to initialize configuration file "{0}".'.format(self.filename))
- return
-
- self.sorting_section = weechat.config_new_section(self.config_file, 'sorting', False, False, '', '', '', '', '', '', '', '', '', '')
-
- if not self.sorting_section:
- log('Failed to initialize section "sorting" of configuration file.')
- weechat.config_free(self.config_file)
- return
-
- self.__case_sensitive = weechat.config_new_option(
- self.config_file, self.sorting_section,
- 'case_sensitive', 'boolean',
- 'If this option is on, sorting is case sensitive.',
- '', 0, 0, 'off', 'off', 0,
- '', '', '', '', '', ''
- )
-
- self.__group_irc = weechat.config_new_option(
- self.config_file, self.sorting_section,
- 'group_irc', 'boolean',
- 'If this option is on, the script pretends that IRC channel/private buffers are renamed to "irc.server.{network}.{channel}" rather than "irc.{network}.{channel}".' +
- 'This ensures that these buffers are grouped with their respective server buffer.',
- '', 0, 0, 'on', 'on', 0,
- '', '', '', '', '', ''
- )
-
- self.__rules = weechat.config_new_option(
- self.config_file, self.sorting_section,
- 'rules', 'string',
- 'An ordered list of sorting rules encoded as JSON. See /help autosort for commands to manipulate these rules.',
- '', 0, 0, Config.default_rules, Config.default_rules, 0,
- '', '', '', '', '', ''
- )
-
- self.__replacements = weechat.config_new_option(
- self.config_file, self.sorting_section,
- 'replacements', 'string',
- 'An ordered list of replacement patterns to use on buffer name components, encoded as JSON. See /help autosort for commands to manipulate these replacements.',
- '', 0, 0, Config.default_replacements, Config.default_replacements, 0,
- '', '', '', '', '', ''
- )
-
- self.__signals = weechat.config_new_option(
- self.config_file, self.sorting_section,
- 'signals', 'string',
- 'The signals that will cause autosort to resort your buffer list. Seperate signals with spaces.',
- '', 0, 0, Config.default_signals, Config.default_signals, 0,
- '', '', '', '', '', ''
- )
-
- self.__sort_on_config = weechat.config_new_option(
- self.config_file, self.sorting_section,
- 'sort_on_config_change', 'boolean',
- 'Decides if the buffer list should be sorted when autosort configuration changes.',
- '', 0, 0, 'on', 'on', 0,
- '', '', '', '', '', ''
- )
-
- if weechat.config_read(self.config_file) != weechat.WEECHAT_RC_OK:
- log('Failed to load configuration file.')
-
- if weechat.config_write(self.config_file) != weechat.WEECHAT_RC_OK:
- log('Failed to write configuration file.')
-
- self.reload()
-
- def reload(self):
- ''' Load configuration variables. '''
-
- self.case_sensitive = weechat.config_boolean(self.__case_sensitive)
- self.group_irc = weechat.config_boolean(self.__group_irc)
-
- rules_blob = weechat.config_string(self.__rules)
- replacements_blob = weechat.config_string(self.__replacements)
- signals_blob = weechat.config_string(self.__signals)
-
- self.rules = RuleList.decode(rules_blob)
- self.replacements = decode_replacements(replacements_blob)
- self.signals = signals_blob.split()
- self.sort_on_config = weechat.config_boolean(self.__sort_on_config)
-
- def save_rules(self, run_callback = True):
- ''' Save the current rules to the configuration. '''
- weechat.config_option_set(self.__rules, RuleList.encode(self.rules), run_callback)
-
- def save_replacements(self, run_callback = True):
- ''' Save the current replacement patterns to the configuration. '''
- weechat.config_option_set(self.__replacements, encode_replacements(self.replacements), run_callback)
-
-
-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 get_buffers():
- ''' Get a list of all the buffers in weechat. '''
- buffers = []
-
- buffer_list = weechat.infolist_get('buffer', '', '')
-
- while weechat.infolist_next(buffer_list):
- name = weechat.infolist_string (buffer_list, 'full_name')
- number = weechat.infolist_integer(buffer_list, 'number')
-
- # Buffer is merged with one we already have in the list, skip it.
- if number <= len(buffers):
- continue
- buffers.append(name)
-
- weechat.infolist_free(buffer_list)
- return buffers
-
-
-def preprocess(buffer, config):
- '''
- Preprocess a buffers names.
- '''
- if not config.case_sensitive:
- buffer = buffer.lower()
-
- for replacement in config.replacements:
- buffer = buffer.replace(replacement[0], replacement[1])
-
- buffer = buffer.split('.')
- if config.group_irc and len(buffer) >= 2 and buffer[0] == 'irc' and buffer[1] not in ('server', 'irc_raw'):
- buffer.insert(1, 'server')
-
- return buffer
-
-
-def buffer_sort_key(rules):
- ''' Create a sort key function for a buffer list from a rule list. '''
- def key(buffer):
- result = []
- name = ''
- for word in preprocess(buffer.decode('utf-8'), config):
- name += ('.' if name else '') + word
- result.append((rules.get_score(name, rules), word))
- return result
-
- return key
-
-
-def apply_buffer_order(buffers):
- ''' Sort the buffers in weechat according to the order in the input list. '''
- for i, buffer in enumerate(buffers):
- weechat.command('', '/buffer swap {0} {1}'.format(buffer, i + 1))
-
-
-def split_args(args, expected, optional = 0):
- ''' Split an argument string in the desired number of arguments. '''
- split = args.split(' ', expected - 1)
- if (len(split) < expected):
- raise HumanReadableError('Expected at least {0} arguments, got {1}.'.format(expected, len(split)))
- return split[:-1] + pad(split[-1].split(' ', optional), optional + 1, '')
-
-
-def command_sort(buffer, command, args):
- ''' Sort the buffers and print a confirmation. '''
- on_buffers_changed()
- log("Finished sorting buffers.", buffer)
- return weechat.WEECHAT_RC_OK
-
-
-def command_rule_list(buffer, command, args):
- ''' Show the list of sorting rules. '''
- output = 'Sorting rules:\n'
- for i, rule in enumerate(config.rules):
- output += ' {0}: {1} = {2}\n'.format(i, rule[0].pattern, rule[1])
- if not len(config.rules):
- output += ' No sorting rules configured.\n'
- log(output, buffer)
-
- return weechat.WEECHAT_RC_OK
-
-
-def command_rule_add(buffer, command, args):
- ''' Add a rule to the rule list. '''
- rule = RuleList.parse_rule(args)
-
- config.rules.append(rule)
- config.save_rules()
- command_rule_list(buffer, command, '')
-
- return weechat.WEECHAT_RC_OK
-
-
-def command_rule_insert(buffer, command, args):
- ''' Insert a rule at the desired position in the rule list. '''
- index, rule = split_args(args, 2)
- index = parse_int(index, 'index')
- rule = RuleList.parse_rule(rule)
-
- config.rules.insert(index, rule)
- config.save_rules()
- command_rule_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_rule_update(buffer, command, args):
- ''' Update a rule in the rule list. '''
- index, rule = split_args(args, 2)
- index = parse_int(index, 'index')
- rule = RuleList.parse_rule(rule)
-
- config.rules[index] = rule
- config.save_rules()
- command_rule_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_rule_delete(buffer, command, args):
- ''' Delete a rule from the rule list. '''
- index = args.strip()
- index = parse_int(index, 'index')
-
- config.rules.pop(index)
- config.save_rules()
- command_rule_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_rule_move(buffer, command, args):
- ''' Move a rule to a new position. '''
- index_a, index_b = split_args(args, 2)
- index_a = parse_int(index_a, 'index')
- index_b = parse_int(index_b, 'index')
-
- config.rules.move(index_a, index_b)
- config.save_rules()
- command_rule_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_rule_swap(buffer, command, args):
- ''' Swap two rules. '''
- index_a, index_b = split_args(args, 2)
- index_a = parse_int(index_a, 'index')
- index_b = parse_int(index_b, 'index')
-
- config.rules.swap(index_a, index_b)
- config.save_rules()
- command_rule_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_list(buffer, command, args):
- ''' Show the list of sorting rules. '''
- output = 'Replacement patterns:\n'
- for i, pattern in enumerate(config.replacements):
- output += ' {0}: {1} -> {2}\n'.format(i, pattern[0], pattern[1])
- if not len(config.replacements):
- output += ' No replacement patterns configured.'
- log(output, buffer)
-
- return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_add(buffer, command, args):
- ''' Add a rule to the rule list. '''
- pattern, replacement = split_args(args, 1, 1)
-
- config.replacements.append((pattern, replacement))
- config.save_replacements()
- command_replacement_list(buffer, command, '')
-
- return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_insert(buffer, command, args):
- ''' Insert a rule at the desired position in the rule list. '''
- index, pattern, replacement = split_args(args, 2, 1)
- index = parse_int(index, 'index')
-
- config.replacements.insert(index, (pattern, replacement))
- config.save_replacements()
- command_replacement_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_update(buffer, command, args):
- ''' Update a rule in the rule list. '''
- index, pattern, replacement = split_args(args, 2, 1)
- index = parse_int(index, 'index')
-
- config.replacements[index] = (pattern, replacement)
- config.save_replacements()
- command_replacement_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_delete(buffer, command, args):
- ''' Delete a rule from the rule list. '''
- index = args.strip()
- index = parse_int(index, 'index')
-
- config.replacements.pop(index)
- config.save_replacements()
- command_replacement_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_move(buffer, command, args):
- ''' Move a rule to a new position. '''
- index_a, index_b = split_args(args, 2)
- index_a = parse_int(index_a, 'index')
- index_b = parse_int(index_b, 'index')
-
- config.replacements.move(index_a, index_b)
- config.save_replacements()
- command_replacement_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_swap(buffer, command, args):
- ''' Swap two rules. '''
- index_a, index_b = split_args(args, 2)
- index_a = parse_int(index_a, 'index')
- index_b = parse_int(index_b, 'index')
-
- config.replacements.swap(index_a, index_b)
- config.save_replacements()
- command_replacement_list(buffer, command, '')
- return weechat.WEECHAT_RC_OK
-
-
-
-
-def call_command(buffer, command, args, subcommands):
- ''' Call a subccommand from a dictionary. '''
- subcommand, tail = pad(args.split(' ', 1), 2, '')
- subcommand = subcommand.strip()
- if (subcommand == ''):
- child = subcommands.get(' ')
- else:
- command = command + [subcommand]
- child = subcommands.get(subcommand)
-
- if isinstance(child, dict):
- return call_command(buffer, command, tail, child)
- elif callable(child):
- return child(buffer, command, tail)
-
- log('{0}: command not found'.format(' '.join(command)))
- return weechat.WEECHAT_RC_ERROR
-
-
-def on_buffers_changed(*args, **kwargs):
- ''' Called whenever the buffer list changes. '''
- buffers = get_buffers()
- buffers.sort(key=buffer_sort_key(config.rules))
- apply_buffer_order(buffers)
- return weechat.WEECHAT_RC_OK
-
-
-def on_config_changed(*args, **kwargs):
- ''' Called whenever the configuration changes. '''
- config.reload()
-
- # Unhook all signals and hook the new ones.
- for hook in hooks:
- weechat.unhook(hook)
- for signal in config.signals:
- hooks.append(weechat.hook_signal(signal, 'on_buffers_changed', ''))
-
- if config.sort_on_config:
- on_buffers_changed()
-
- return weechat.WEECHAT_RC_OK
-
-
-def on_autosort_command(data, buffer, args):
- ''' Called when the autosort command is invoked. '''
- try:
- return call_command(buffer, ['/autosort'], args, {
- ' ': command_sort,
- 'sort': command_sort,
-
- 'rules': {
- ' ': command_rule_list,
- 'list': command_rule_list,
- 'add': command_rule_add,
- 'insert': command_rule_insert,
- 'update': command_rule_update,
- 'delete': command_rule_delete,
- 'move': command_rule_move,
- 'swap': command_rule_swap,
- },
- 'replacements': {
- ' ': command_replacement_list,
- 'list': command_replacement_list,
- 'add': command_replacement_add,
- 'insert': command_replacement_insert,
- 'update': command_replacement_update,
- 'delete': command_replacement_delete,
- 'move': command_replacement_move,
- 'swap': command_replacement_swap,
- },
- 'sort': on_buffers_changed,
- })
- except HumanReadableError as e:
- log(e, buffer)
- return weechat.WEECHAT_RC_ERROR
-
-
-command_description = r'''
-NOTE: For the best effect, you may want to consider setting the option irc.look.server_buffer to independent and buffers.look.indenting to on.
-
-# Commands
-
-## Miscellaneous
-/autosort sort
-Manually trigger the buffer sorting.
-
-
-## Sorting rules
-
-/autosort rules list
-Print the list of sort rules.
-
-/autosort rules add <pattern> = <score>
-Add a new rule at the end of the list.
-
-/autosort rules insert <index> <pattern> = <score>
-Insert a new rule at the given index in the list.
-
-/autosort rules update <index> <pattern> = <score>
-Update a rule in the list with a new pattern and score.
-
-/autosort rules delete <index>
-Delete a rule from the list.
-
-/autosort rules move <index_from> <index_to>
-Move a rule from one position in the list to another.
-
-/autosort rules swap <index_a> <index_b>
-Swap two rules in the list
-
-
-## Replacement patterns
-
-/autosort replacements list
-Print the list of replacement patterns.
-
-/autosort replacements add <pattern> <replacement>
-Add a new replacement pattern at the end of the list.
-
-/autosort replacements insert <index> <pattern> <replacement>
-Insert a new replacement pattern at the given index in the list.
-
-/autosort replacements update <index> <pattern> <replacement>
-Update a replacement pattern in the list.
-
-/autosort replacements delete <index>
-Delete a replacement pattern from the list.
-
-/autosort replacements move <index_from> <index_to>
-Move a replacement pattern from one position in the list to another.
-
-/autosort replacements swap <index_a> <index_b>
-Swap two replacement pattern in the list
-
-
-# Introduction
-Autosort is a weechat script to automatically keep your buffers sorted.
-The sort order can be customized by defining your own sort rules,
-but the default should be sane enough for most people.
-It can also group IRC channel/private buffers under their server buffer if you like.
-
-Autosort first turns buffer names into a list of their components by splitting on them on the period character.
-For example, the buffer name "irc.server.freenode" is turned into ['irc', 'server', 'freenode'].
-The list of buffers is then lexicographically sorted.
-
-To facilitate custom sort orders, it is possible to assign a score to each component individually before the sorting is done.
-Any name component that did not get a score assigned will be sorted after those that did receive a score.
-Components are always sorted on their score first and on their name second.
-Lower scores are sorted first.
-
-## Automatic or manual sorting
-By default, autosort will automatically sort your buffer list whenever a buffer is opened, merged, unmerged or renamed.
-This should keep your buffers sorted in almost all situations.
-However, you may wish to change the list of signals that cause your buffer list to be sorted.
-Simply edit the "autosort.sorting.signals" option to add or remove any signal you like.
-If you remove all signals you can still sort your buffers manually with the "/autosort sort" command.
-To prevent all automatic sorting, "autosort.sorting.sort_on_config_change" should also be set to off.
-
-## Grouping IRC buffers
-In weechat, IRC channel/private buffers are named "irc.<network>.<#channel>",
-and IRC server buffers are named "irc.server.<network>".
-This does not work very well with lexicographical sorting if you want all buffers for one network grouped together.
-That is why autosort comes with the "autosort.sorting.group_irc" option,
-which secretly pretends IRC channel/private buffers are called "irc.server.<network>.<#channel>".
-The buffers are not actually renamed, autosort simply pretends they are for sorting purposes.
-
-## Replacement patterns
-Sometimes you may want to ignore some characters for sorting purposes.
-On Freenode for example, you may wish to ignore the difference between channels starting with a double or a single hash sign.
-To do so, simply add a replacement pattern that replaces ## with # with the following command:
-/autosort replacements add ## #
-
-Replacement patterns do not support wildcards or special characters at the moment.
-
-## Sort rules
-You can assign scores to name components by defining sort rules.
-The first rule that matches a component decides the score.
-Further rules are not examined.
-Sort rules use the following syntax:
-<glob-pattern> = <score>
-
-You can use the "/autosort rules" command to show and manipulate the list of sort rules.
-
-
-Allowed special characters in the glob patterns are:
-
-Pattern | Meaning
---------|--------
-* | Matches a sequence of any characters except for periods.
-? | Matches a single character, but not a period.
-[a-z] | Matches a single character in the given regex-like character class.
-[^ab] | A negated regex-like character class.
-\* | A backslash escapes the next characters and removes its special meaning.
-\\ | A literal backslash.
-
-
-## Example
-As an example, consider the following rule list:
-0: core = 0
-1: irc = 2
-2: * = 1
-
-3: irc.server.*.#* = 1
-4: irc.server.*.* = 0
-
-Rule 0 ensures the core buffer is always sorted first.
-Rule 1 sorts IRC buffers last and rule 2 puts all remaining buffers in between the two.
-
-Rule 3 and 4 would make no sense with the group_irc option off.
-With the option on though, these rules will sort private buffers before regular channel buffers.
-Rule 3 matches channel buffers and assigns them a higher score,
-while rule 4 matches the buffers that remain and assigns them a lower score.
-The same effect could also be achieved with a single rule:
-irc.server.*.[^#]* = 0
-'''
-
-command_completion = 'sort||rules list|add|insert|update|delete|move|swap||replacements list|add|insert|update|delete|move|swap'
-
-
-if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
- config = Config('autosort')
-
- weechat.hook_config('autosort.*', 'on_config_changed', '')
- weechat.hook_command('autosort', command_description, '', '', command_completion, 'on_autosort_command', 'NULL')
- on_config_changed()
+../autosort.py
\ No newline at end of file
--- a/weechat/python/autoload/brows.py Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/python/autoload/brows.py Mon Aug 23 11:51:18 2021 -0400
@@ -15,7 +15,7 @@
try:
import weechat
except ImportError:
- print 'This is a weechat script, what are you doing, run it in weechat, jesus'
+ print('This is a weechat script, what are you doing, run it in weechat, jesus')
import_ok = False
weechat_version = 0
--- a/weechat/python/autoload/colon_complete.py Tue Aug 17 15:20:33 2021 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-SCRIPT_NAME='coloncomplete'
-SCRIPT_AUTHOR='Steve Losh <steve@stevelosh.com>'
-SCRIPT_VERSION='1.0'
-SCRIPT_LICENSE='MIT/X11'
-SCRIPT_DESC='Add a colon after nick completion when all the previous words in the input are also nicks.'
-
-EXTRA_NICKS = ['all', 'backend', 'clojerks', 'ops', 'support']
-
-import_ok=True
-
-try:
- import weechat
-except ImportError:
- print 'This script must be run under WeeChat'
- print 'You can obtain a copy of WeeChat, for free, at http://www.weechat.org'
- import_ok=False
-
-weechat_version=0
-
-def get_nicks(buffer, prefix=''):
- channel = weechat.buffer_get_string(buffer, 'localvar_channel')
- server = weechat.buffer_get_string(buffer, 'localvar_server')
- prefix = prefix.lower()
-
- matches = []
-
- infolist = weechat.infolist_get('irc_nick', '', '%s,%s' % (server, channel))
- while weechat.infolist_next(infolist):
- nick = weechat.infolist_string(infolist, 'name')
- if nick != 'localhost' and nick.lower().startswith(prefix):
- matches.append(nick)
- weechat.infolist_free(infolist)
-
- for nick in EXTRA_NICKS:
- if nick.lower().startswith(prefix):
- matches.append(nick)
-
- return matches
-
-def completer(data, buffer, command):
- cb = weechat.current_buffer()
- if command == "/input complete_next":
- line = weechat.buffer_get_string(cb, "input")
- words = line.split(' ')
- prefix = words[-1]
- if prefix and words and all([s.endswith(':') for s in words[:-1] if s]):
- nicks = get_nicks(cb, prefix)
- if len(nicks) == 1:
- for _ in range(len(prefix)):
- weechat.command(buffer, "/input delete_previous_char")
- weechat.command(buffer, "/input insert " + nicks[-1] + ":\\x20")
- elif len(nicks) > 1:
- l = min(len(nick) for nick in nicks)
- for i in range(len(prefix), l):
- if len(set(nick[i] for nick in nicks)) > 1:
- break
- else:
- weechat.command(buffer, "/input insert " + nicks[0][i])
-
- for nick in nicks:
- weechat.prnt(cb, "==> " + nick)
- return weechat.WEECHAT_RC_OK_EAT
-
- return weechat.WEECHAT_RC_OK
-
-if __name__ == "__main__" and import_ok:
- if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
- weechat_version = weechat.info_get("version_number", "") or 0
- weechat.hook_command_run('/input complete*', 'completer', '')
--- a/weechat/python/autoload/editor.py Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/python/autoload/editor.py Mon Aug 23 11:51:18 2021 -0400
@@ -16,7 +16,7 @@
try:
import weechat
except ImportError:
- print 'This is a weechat script, what are you doing, run it in weechat, jesus'
+ print('This is a weechat script, what are you doing, run it in weechat, jesus')
import_ok = False
weechat_version = 0
@@ -33,9 +33,8 @@
# Reopen, because most editors do atomic write-tmp+rename saves which
# fucks with Python here.
tf.file.close()
- tf = file(tf.name)
-
- return tf.read()
+ with open(tf.name) as tf2:
+ return tf2.read()
def editor(data, buffer, args):
suffix = args or "tmp"
--- a/weechat/python/autoload/quotes.py Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/python/autoload/quotes.py Mon Aug 23 11:51:18 2021 -0400
@@ -18,7 +18,7 @@
try:
import weechat
except ImportError:
- print 'This is a weechat script, what are you doing, run it in weechat, jesus'
+ print('This is a weechat script, what are you doing, run it in weechat, jesus')
import_ok = False
weechat_version = 0
--- a/weechat/python/autoload/sanitize_jira.py Tue Aug 17 15:20:33 2021 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-import re, weechat, subprocess
-
-SCRIPT_NAME = 'sanitize_jira'
-SCRIPT_AUTHOR = 'Steve Losh <steve@stevelosh.com>'
-SCRIPT_VERSION = '0.0.1'
-SCRIPT_LICENSE = 'MIT'
-SCRIPT_DESC = 'clean up the garbage jirabot sends to channels into something readable'
-
-weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', '')
-
-weechat.hook_line('*', '', 'nick_Jira_Cloud', 'sanitize_jira', '')
-
-first_line_re = re.compile(
- r'(?P<link>https://[^/]+/browse/[^?]+)[?]atlOrigin=[^ ]+ [(](?P<title>.+)[)]'
-)
-
-detail_line_re = re.compile(
- r'''Status: \x1a\x01[*](?P<status>[^*]+)[*]\x1b\x01.*Type: \x1a\x01[*](?P<type>[^*]+)[*]\x1b\x01.*Assignee: \x1a\x01[*](?P<assignee>[^*]+)[*]\x1b\x01.*Priority: \x1a\x01[*](?P<priority>[^*]+)[*]\x1b\x01'''
-)
-
-def sanitize_jira(data, line):
- if 'sign up for an Atlassian account to view this link' in line['message']:
- return {'message': ' '}
-
- m = first_line_re.search(line['message'])
- if m:
- return {'message': '%s | %s' % (m.group('title'), m.group('link'))}
-
- m = detail_line_re.search(line['message'])
- if m:
- return {'message': '%s / %s / %s' % (m.group('type'), m.group('status'), m.group('assignee'))}
-
- return {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/python/autosort.py Mon Aug 23 11:51:18 2021 -0400
@@ -0,0 +1,1075 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2013-2017 Maarten de Vries <maarten@de-vri.es>
+#
+# 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/>.
+#
+
+#
+# Autosort automatically keeps your buffers sorted and grouped by server.
+# You can define your own sorting rules. See /help autosort for more details.
+#
+# https://github.com/de-vri-es/weechat-autosort
+#
+
+#
+# Changelog:
+# 3.9:
+# * Remove `buffers.pl` from recommended settings.
+# 3,8:
+# * Fix relative sorting on script name in default rules.
+# * Document a useful property of stable sort algorithms.
+# 3.7:
+# * Make default rules work with bitlbee, matrix and slack.
+# 3.6:
+# * Add more documentation on provided info hooks.
+# 3.5:
+# * Add ${info:autosort_escape,...} to escape arguments for other info hooks.
+# 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.
+# 3.2:
+# * Fix python3 compatiblity.
+# 3.1:
+# * Use colors to format the help text.
+# 3.0:
+# * Switch to evaluated expressions for sorting.
+# * Add `/autosort debug` command.
+# * Add ${info:autosort_replace,from,to,text} to replace substrings in sort rules.
+# * Add ${info:autosort_order,value,first,second,third} to ease writing sort rules.
+# * Make tab completion context aware.
+# 2.8:
+# * Fix compatibility with python 3 regarding unicode handling.
+# 2.7:
+# * Fix sorting of buffers with spaces in their name.
+# 2.6:
+# * Ignore case in rules when doing case insensitive sorting.
+# 2.5:
+# * Fix handling unicode buffer names.
+# * Add hint to set irc.look.server_buffer to independent and buffers.look.indenting to on.
+# 2.4:
+# * Make script python3 compatible.
+# 2.3:
+# * Fix sorting items without score last (regressed in 2.2).
+# 2.2:
+# * Add configuration option for signals that trigger a sort.
+# * Add command to manually trigger a sort (/autosort sort).
+# * Add replacement patterns to apply before sorting.
+# 2.1:
+# * Fix some minor style issues.
+# 2.0:
+# * Allow for custom sort rules.
+#
+
+
+import json
+import math
+import re
+import sys
+import time
+import weechat
+
+SCRIPT_NAME = 'autosort'
+SCRIPT_AUTHOR = 'Maarten de Vries <maarten@de-vri.es>'
+SCRIPT_VERSION = '3.9'
+SCRIPT_LICENSE = 'GPL3'
+SCRIPT_DESC = 'Flexible automatic (or manual) buffer sorting based on eval expressions.'
+
+
+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
+# For python 3, str == unicode
+if sys.version_info[0] >= 3:
+ unicode = str
+
+def ensure_str(input):
+ '''
+ Make sure the given type if the correct string type for the current python version.
+ That means bytes for python2 and unicode for python3.
+ '''
+ if not isinstance(input, str):
+ if isinstance(input, bytes):
+ return input.encode('utf-8')
+ if isinstance(input, unicode):
+ return input.decode('utf-8')
+ return input
+
+
+if hasattr(time, 'perf_counter'):
+ perf_counter = time.perf_counter
+else:
+ perf_counter = time.clock
+
+def casefold(string):
+ if hasattr(string, 'casefold'): return string.casefold()
+ # Fall back to lowercasing for python2.
+ return string.lower()
+
+def list_swap(values, a, b):
+ values[a], values[b] = values[b], values[a]
+
+def list_move(values, old_index, new_index):
+ values.insert(new_index, values.pop(old_index))
+
+def list_find(collection, value):
+ for i, elem in enumerate(collection):
+ if elem == value: return i
+ return None
+
+class HumanReadableError(Exception):
+ pass
+
+def parse_int(arg, arg_name = 'argument'):
+ ''' Parse an integer and provide a more human readable error. '''
+ arg = arg.strip()
+ try:
+ return int(arg)
+ except ValueError:
+ raise HumanReadableError('Invalid {0}: expected integer, got "{1}".'.format(arg_name, arg))
+
+def decode_rules(blob):
+ parsed = json.loads(blob)
+ if not isinstance(parsed, list):
+ log('Malformed rules, expected a JSON encoded list of strings, but got a {0}. No rules have been loaded. Please fix the setting manually.'.format(type(parsed)))
+ return []
+
+ for i, entry in enumerate(parsed):
+ if not isinstance(entry, (str, unicode)):
+ log('Rule #{0} is not a string but a {1}. No rules have been loaded. Please fix the setting manually.'.format(i, type(entry)))
+ return []
+
+ return parsed
+
+def decode_helpers(blob):
+ parsed = json.loads(blob)
+ if not isinstance(parsed, dict):
+ 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 setting manually.'.format(key, type(value)))
+ return {}
+ return parsed
+
+class Config:
+ ''' The autosort configuration. '''
+
+ default_rules = json.dumps([
+ '${core_first}',
+ '${info:autosort_order,${info:autosort_escape,${script_or_plugin}},core,*,irc,bitlbee,matrix,slack}',
+ '${script_or_plugin}',
+ '${irc_raw_first}',
+ '${server}',
+ '${info:autosort_order,${type},server,*,channel,private}',
+ '${hashless_name}',
+ '${buffer.full_name}',
+ ])
+
+ default_helpers = json.dumps({
+ 'core_first': '${if:${buffer.full_name}!=core.weechat}',
+ 'irc_raw_first': '${if:${buffer.full_name}!=irc.irc_raw}',
+ 'irc_raw_last': '${if:${buffer.full_name}==irc.irc_raw}',
+ 'hashless_name': '${info:autosort_replace,#,,${info:autosort_escape,${buffer.name}}}',
+ 'script_or_plugin': '${if:${script_name}?${script_name}:${plugin}}',
+ })
+
+ default_signal_delay = 5
+ default_sort_limit = 100
+
+ default_signals = 'buffer_opened buffer_merged buffer_unmerged buffer_renamed'
+
+ def __init__(self, filename):
+ ''' Initialize the configuration. '''
+
+ self.filename = filename
+ self.config_file = weechat.config_new(self.filename, '', '')
+ self.sorting_section = None
+ self.v3_section = None
+
+ self.case_sensitive = False
+ self.rules = []
+ 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))
+ return
+
+ self.sorting_section = weechat.config_new_section(self.config_file, 'sorting', False, False, '', '', '', '', '', '', '', '', '', '')
+ self.v3_section = weechat.config_new_section(self.config_file, 'v3', False, False, '', '', '', '', '', '', '', '', '', '')
+
+ if not self.sorting_section:
+ log('Failed to initialize section "sorting" of configuration file.')
+ weechat.config_free(self.config_file)
+ return
+
+ self.__case_sensitive = weechat.config_new_option(
+ self.config_file, self.sorting_section,
+ 'case_sensitive', 'boolean',
+ 'If this option is on, sorting is case sensitive.',
+ '', 0, 0, 'off', 'off', 0,
+ '', '', '', '', '', ''
+ )
+
+ weechat.config_new_option(
+ self.config_file, self.sorting_section,
+ 'rules', 'string',
+ 'Sort rules used by autosort v2.x and below. Not used by autosort anymore.',
+ '', 0, 0, '', '', 0,
+ '', '', '', '', '', ''
+ )
+
+ weechat.config_new_option(
+ self.config_file, self.sorting_section,
+ 'replacements', 'string',
+ 'Replacement patterns used by autosort v2.x and below. Not used by autosort anymore.',
+ '', 0, 0, '', '', 0,
+ '', '', '', '', '', ''
+ )
+
+ self.__rules = weechat.config_new_option(
+ self.config_file, self.v3_section,
+ 'rules', 'string',
+ 'An ordered list of sorting rules encoded as JSON. See /help autosort for commands to manipulate these rules.',
+ '', 0, 0, Config.default_rules, Config.default_rules, 0,
+ '', '', '', '', '', ''
+ )
+
+ self.__helpers = weechat.config_new_option(
+ self.config_file, self.v3_section,
+ 'helpers', 'string',
+ 'A dictionary helper variables to use in the sorting rules, encoded as JSON. See /help autosort for commands to manipulate these helpers.',
+ '', 0, 0, Config.default_helpers, Config.default_helpers, 0,
+ '', '', '', '', '', ''
+ )
+
+ self.__signals = weechat.config_new_option(
+ self.config_file, self.sorting_section,
+ 'signals', 'string',
+ 'A space separated list of signals that will cause autosort to resort your buffer list.',
+ '', 0, 0, Config.default_signals, Config.default_signals, 0,
+ '', '', '', '', '', ''
+ )
+
+ self.__signal_delay = weechat.config_new_option(
+ self.config_file, self.sorting_section,
+ 'signal_delay', 'integer',
+ 'Delay in milliseconds to wait after a signal before sorting the buffer list. This prevents triggering many times if multiple signals arrive in a short time. It can also be needed to wait for buffer localvars to be available.',
+ '', 0, 1000, str(Config.default_signal_delay), str(Config.default_signal_delay), 0,
+ '', '', '', '', '', ''
+ )
+
+ 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',
+ 'Decides if the buffer list should be sorted when autosort configuration changes.',
+ '', 0, 0, 'on', 'on', 0,
+ '', '', '', '', '', ''
+ )
+
+ 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.')
+
+ if weechat.config_write(self.config_file) != weechat.WEECHAT_RC_OK:
+ log('Failed to write configuration file.')
+
+ self.reload()
+
+ def reload(self):
+ ''' Load configuration variables. '''
+
+ self.case_sensitive = weechat.config_boolean(self.__case_sensitive)
+
+ rules_blob = weechat.config_string(self.__rules)
+ helpers_blob = weechat.config_string(self.__helpers)
+ signals_blob = weechat.config_string(self.__signals)
+
+ self.rules = decode_rules(rules_blob)
+ 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. '''
+ weechat.config_option_set(self.__rules, json.dumps(self.rules), run_callback)
+
+ def save_helpers(self, run_callback = True):
+ ''' Save the current helpers to the configuration. '''
+ weechat.config_option_set(self.__helpers, json.dumps(self.helpers), run_callback)
+
+
+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. '''
+ hdata = weechat.hdata_get('buffer')
+ buffer = weechat.hdata_get_list(hdata, "gui_buffers");
+
+ result = []
+ while buffer:
+ number = weechat.hdata_integer(hdata, buffer, 'number')
+ result.append((number, buffer))
+ buffer = weechat.hdata_pointer(hdata, buffer, 'next_buffer')
+ return hdata, result
+
+class MergedBuffers(list):
+ """ A list of merged buffers, possibly of size 1. """
+ def __init__(self, number):
+ super(MergedBuffers, self).__init__()
+ self.number = number
+
+def merge_buffer_list(buffers):
+ '''
+ Group merged buffers together.
+ The output is a list of MergedBuffers.
+ '''
+ if not buffers: return []
+ result = {}
+ for number, buffer in buffers:
+ if number not in result: result[number] = MergedBuffers(number)
+ result[number].append(buffer)
+ return result.values()
+
+def sort_buffers(hdata, buffers, rules, helpers, case_sensitive):
+ for merged in buffers:
+ for buffer in merged:
+ name = weechat.hdata_string(hdata, buffer, 'name')
+
+ return sorted(buffers, key=merged_sort_key(rules, helpers, case_sensitive))
+
+def buffer_sort_key(rules, helpers, case_sensitive):
+ ''' Create a sort key function for a list of lists of merged buffers. '''
+ def key(buffer):
+ extra_vars = {}
+ for helper_name, helper in sorted(helpers.items()):
+ expanded = weechat.string_eval_expression(helper, {"buffer": buffer}, {}, {})
+ extra_vars[helper_name] = expanded if case_sensitive else casefold(expanded)
+ result = []
+ for rule in rules:
+ expanded = weechat.string_eval_expression(rule, {"buffer": buffer}, extra_vars, {})
+ result.append(expanded if case_sensitive else casefold(expanded))
+ return result
+
+ return key
+
+def merged_sort_key(rules, helpers, case_sensitive):
+ buffer_key = buffer_sort_key(rules, helpers, case_sensitive)
+ def key(merged):
+ best = None
+ for buffer in merged:
+ this = buffer_key(buffer)
+ if best is None or this < best: best = this
+ return best
+ return key
+
+def apply_buffer_order(buffers):
+ ''' Sort the buffers in weechat according to the given order. '''
+ for i, buffer in enumerate(buffers):
+ weechat.buffer_set(buffer[0], "number", str(i + 1))
+
+def split_args(args, expected, optional = 0):
+ ''' Split an argument string in the desired number of arguments. '''
+ split = args.split(' ', expected - 1)
+ if (len(split) < expected):
+ 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(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. '''
+ do_sort(True)
+ return weechat.WEECHAT_RC_OK
+
+def command_debug(buffer, command, args):
+ hdata, buffers = get_buffers()
+ buffers = merge_buffer_list(buffers)
+
+ # Show evaluation results.
+ log('Individual evaluation results:')
+ start = perf_counter()
+ key = buffer_sort_key(config.rules, config.helpers, config.case_sensitive)
+ results = []
+ for merged in buffers:
+ for buffer in merged:
+ fullname = weechat.hdata_string(hdata, buffer, 'full_name')
+ results.append((fullname, key(buffer)))
+ elapsed = perf_counter() - start
+
+ for fullname, result in results:
+ fullname = ensure_str(fullname)
+ result = [ensure_str(x) for x in result]
+ log('{0}: {1}'.format(fullname, result))
+ log('Computing evaluation results took {0:.4f} seconds.'.format(elapsed))
+
+ return weechat.WEECHAT_RC_OK
+
+def command_rule_list(buffer, command, args):
+ ''' Show the list of sorting rules. '''
+ output = 'Sorting rules:\n'
+ for i, rule in enumerate(config.rules):
+ output += ' {0}: {1}\n'.format(i, rule)
+ if not len(config.rules):
+ output += ' No sorting rules configured.\n'
+ log(output )
+
+ return weechat.WEECHAT_RC_OK
+
+
+def command_rule_add(buffer, command, args):
+ ''' Add a rule to the rule list. '''
+ config.rules.append(args)
+ config.save_rules()
+ command_rule_list(buffer, command, '')
+
+ return weechat.WEECHAT_RC_OK
+
+
+def command_rule_insert(buffer, command, args):
+ ''' Insert a rule at the desired position in the rule list. '''
+ index, rule = split_args(args, 2)
+ index = parse_int(index, 'index')
+
+ config.rules.insert(index, rule)
+ config.save_rules()
+ command_rule_list(buffer, command, '')
+ return weechat.WEECHAT_RC_OK
+
+
+def command_rule_update(buffer, command, args):
+ ''' Update a rule in the rule list. '''
+ index, rule = split_args(args, 2)
+ index = parse_int(index, 'index')
+
+ config.rules[index] = rule
+ config.save_rules()
+ command_rule_list(buffer, command, '')
+ return weechat.WEECHAT_RC_OK
+
+
+def command_rule_delete(buffer, command, args):
+ ''' Delete a rule from the rule list. '''
+ index = args.strip()
+ index = parse_int(index, 'index')
+
+ config.rules.pop(index)
+ config.save_rules()
+ command_rule_list(buffer, command, '')
+ return weechat.WEECHAT_RC_OK
+
+
+def command_rule_move(buffer, command, args):
+ ''' Move a rule to a new position. '''
+ index_a, index_b = split_args(args, 2)
+ index_a = parse_int(index_a, 'index')
+ index_b = parse_int(index_b, 'index')
+
+ list_move(config.rules, index_a, index_b)
+ config.save_rules()
+ command_rule_list(buffer, command, '')
+ return weechat.WEECHAT_RC_OK
+
+
+def command_rule_swap(buffer, command, args):
+ ''' Swap two rules. '''
+ index_a, index_b = split_args(args, 2)
+ index_a = parse_int(index_a, 'index')
+ index_b = parse_int(index_b, 'index')
+
+ list_swap(config.rules, index_a, index_b)
+ config.save_rules()
+ command_rule_list(buffer, command, '')
+ return weechat.WEECHAT_RC_OK
+
+
+def command_helper_list(buffer, command, args):
+ ''' Show the list of helpers. '''
+ output = 'Helper variables:\n'
+
+ width = max(map(lambda x: len(x) if len(x) <= 30 else 0, config.helpers.keys()))
+
+ for name, expression in sorted(config.helpers.items()):
+ output += ' {0:>{width}}: {1}\n'.format(name, expression, width=width)
+ if not len(config.helpers):
+ output += ' No helper variables configured.'
+ log(output)
+
+ return weechat.WEECHAT_RC_OK
+
+
+def command_helper_set(buffer, command, args):
+ ''' Add/update a helper to the helper list. '''
+ name, expression = split_args(args, 2)
+
+ config.helpers[name] = expression
+ config.save_helpers()
+ command_helper_list(buffer, command, '')
+
+ return weechat.WEECHAT_RC_OK
+
+def command_helper_delete(buffer, command, args):
+ ''' Delete a helper from the helper list. '''
+ name = args.strip()
+
+ del config.helpers[name]
+ config.save_helpers()
+ command_helper_list(buffer, command, '')
+ return weechat.WEECHAT_RC_OK
+
+
+def command_helper_rename(buffer, command, args):
+ ''' Rename a helper to a new position. '''
+ old_name, new_name = split_args(args, 2)
+
+ try:
+ config.helpers[new_name] = config.helpers[old_name]
+ del config.helpers[old_name]
+ except KeyError:
+ raise HumanReadableError('No such helper: {0}'.format(old_name))
+ config.save_helpers()
+ command_helper_list(buffer, command, '')
+ return weechat.WEECHAT_RC_OK
+
+
+def command_helper_swap(buffer, command, args):
+ ''' Swap two helpers. '''
+ a, b = split_args(args, 2)
+ try:
+ config.helpers[b], config.helpers[a] = config.helpers[a], config.helpers[b]
+ except KeyError as e:
+ raise HumanReadableError('No such helper: {0}'.format(e.args[0]))
+
+ config.helpers.swap(index_a, index_b)
+ config.save_helpers()
+ command_helper_list(buffer, command, '')
+ return weechat.WEECHAT_RC_OK
+
+def call_command(buffer, command, args, subcommands):
+ ''' Call a subcommand from a dictionary. '''
+ subcommand, tail = pad(args.split(' ', 1), 2, '')
+ subcommand = subcommand.strip()
+ if (subcommand == ''):
+ child = subcommands.get(' ')
+ else:
+ command = command + [subcommand]
+ child = subcommands.get(subcommand)
+
+ if isinstance(child, dict):
+ return call_command(buffer, command, tail, child)
+ elif callable(child):
+ return child(buffer, command, tail)
+
+ log('{0}: command not found'.format(' '.join(command)))
+ return weechat.WEECHAT_RC_ERROR
+
+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_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:
+ weechat.unhook(hook)
+ for signal in config.signals:
+ 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):
+ ''' Called whenever the configuration changes. '''
+ config.reload()
+ apply_config()
+
+ return weechat.WEECHAT_RC_OK
+
+def parse_arg(args):
+ if not args: return '', None
+
+ result = ''
+ escaped = False
+ for i, c in enumerate(args):
+ if not escaped:
+ if c == '\\':
+ escaped = True
+ continue
+ elif c == ',':
+ return result, args[i+1:]
+ result += c
+ escaped = False
+ return result, None
+
+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)
+ if args is None: break
+ return result, args
+
+def on_info_escape(pointer, name, arguments):
+ result = ''
+ for c in arguments:
+ if c == '\\':
+ result += '\\\\'
+ elif c == ',':
+ result += '\\,'
+ else:
+ result +=c
+ return result
+
+def on_info_replace(pointer, name, arguments):
+ arguments, rest = parse_args(arguments, 3)
+ if rest or len(arguments) < 3:
+ log('usage: ${{info:{0},old,new,text}}'.format(name))
+ return ''
+ old, new, text = arguments
+
+ return text.replace(old, new)
+
+def on_info_order(pointer, name, arguments):
+ arguments, rest = parse_args(arguments)
+ if len(arguments) < 1:
+ log('usage: ${{info:{0},value,first,second,third,...}}'.format(name))
+ return ''
+
+ value = arguments[0]
+ keys = arguments[1:]
+ if not keys: return '0'
+
+ # Find the value in the keys (or '*' if we can't find it)
+ result = list_find(keys, value)
+ if result is None: result = list_find(keys, '*')
+ if result is None: result = len(keys)
+
+ # Pad result with leading zero to make sure string sorting works.
+ width = int(math.log10(len(keys))) + 1
+ return '{0:0{1}}'.format(result, width)
+
+
+def on_autosort_command(data, buffer, args):
+ ''' Called when the autosort command is invoked. '''
+ try:
+ return call_command(buffer, ['/autosort'], args, {
+ ' ': command_sort,
+ 'sort': command_sort,
+ 'debug': command_debug,
+
+ 'rules': {
+ ' ': command_rule_list,
+ 'list': command_rule_list,
+ 'add': command_rule_add,
+ 'insert': command_rule_insert,
+ 'update': command_rule_update,
+ 'delete': command_rule_delete,
+ 'move': command_rule_move,
+ 'swap': command_rule_swap,
+ },
+ 'helpers': {
+ ' ': command_helper_list,
+ 'list': command_helper_list,
+ 'set': command_helper_set,
+ 'delete': command_helper_delete,
+ 'rename': command_helper_rename,
+ 'swap': command_helper_swap,
+ },
+ })
+ except HumanReadableError as e:
+ log(e)
+ return weechat.WEECHAT_RC_ERROR
+
+def add_completions(completion, words):
+ for word in words:
+ weechat.hook_completion_list_add(completion, word, 0, weechat.WEECHAT_LIST_POS_END)
+
+def autosort_complete_rules(words, completion):
+ if len(words) == 0:
+ add_completions(completion, ['add', 'delete', 'insert', 'list', 'move', 'swap', 'update'])
+ if len(words) == 1 and words[0] in ('delete', 'insert', 'move', 'swap', 'update'):
+ add_completions(completion, map(str, range(len(config.rules))))
+ if len(words) == 2 and words[0] in ('move', 'swap'):
+ add_completions(completion, map(str, range(len(config.rules))))
+ if len(words) == 2 and words[0] in ('update'):
+ try:
+ add_completions(completion, [config.rules[int(words[1])]])
+ except KeyError: pass
+ except ValueError: pass
+ else:
+ add_completions(completion, [''])
+ return weechat.WEECHAT_RC_OK
+
+def autosort_complete_helpers(words, completion):
+ if len(words) == 0:
+ add_completions(completion, ['delete', 'list', 'rename', 'set', 'swap'])
+ elif len(words) == 1 and words[0] in ('delete', 'rename', 'set', 'swap'):
+ add_completions(completion, sorted(config.helpers.keys()))
+ elif len(words) == 2 and words[0] == 'swap':
+ add_completions(completion, sorted(config.helpers.keys()))
+ elif len(words) == 2 and words[0] == 'rename':
+ add_completions(completion, sorted(config.helpers.keys()))
+ elif len(words) == 2 and words[0] == 'set':
+ try:
+ add_completions(completion, [config.helpers[words[1]]])
+ except KeyError: pass
+ return weechat.WEECHAT_RC_OK
+
+def on_autosort_complete(data, name, buffer, completion):
+ cmdline = weechat.buffer_get_string(buffer, "input")
+ cursor = weechat.buffer_get_integer(buffer, "input_pos")
+ prefix = cmdline[:cursor]
+ words = prefix.split()[1:]
+
+ # If the current word isn't finished yet,
+ # ignore it for coming up with completion suggestions.
+ if prefix[-1] != ' ': words = words[:-1]
+
+ if len(words) == 0:
+ add_completions(completion, ['debug', 'helpers', 'rules', 'sort'])
+ elif words[0] == 'rules':
+ return autosort_complete_rules(words[1:], completion)
+ elif words[0] == 'helpers':
+ return autosort_complete_helpers(words[1:], completion)
+ return weechat.WEECHAT_RC_OK
+
+command_description = r'''{*white}# General commands{reset}
+
+{*white}/autosort {brown}sort{reset}
+Manually trigger the buffer sorting.
+
+{*white}/autosort {brown}debug{reset}
+Show the evaluation results of the sort rules for each buffer.
+
+
+{*white}# Sorting rule commands{reset}
+
+{*white}/autosort{brown} rules list{reset}
+Print the list of sort rules.
+
+{*white}/autosort {brown}rules add {cyan}<expression>{reset}
+Add a new rule at the end of the list.
+
+{*white}/autosort {brown}rules insert {cyan}<index> <expression>{reset}
+Insert a new rule at the given index in the list.
+
+{*white}/autosort {brown}rules update {cyan}<index> <expression>{reset}
+Update a rule in the list with a new expression.
+
+{*white}/autosort {brown}rules delete {cyan}<index>
+Delete a rule from the list.
+
+{*white}/autosort {brown}rules move {cyan}<index_from> <index_to>{reset}
+Move a rule from one position in the list to another.
+
+{*white}/autosort {brown}rules swap {cyan}<index_a> <index_b>{reset}
+Swap two rules in the list
+
+
+{*white}# Helper variable commands{reset}
+
+{*white}/autosort {brown}helpers list
+Print the list of helper variables.
+
+{*white}/autosort {brown}helpers set {cyan}<name> <expression>
+Add or update a helper variable with the given name.
+
+{*white}/autosort {brown}helpers delete {cyan}<name>
+Delete a helper variable.
+
+{*white}/autosort {brown}helpers rename {cyan}<old_name> <new_name>
+Rename a helper variable.
+
+{*white}/autosort {brown}helpers swap {cyan}<name_a> <name_b>
+Swap the expressions of two helper variables in the list.
+
+
+{*white}# Info hooks{reset}
+Autosort comes with a number of info hooks to add some extra functionality to regular weechat eval strings.
+Info hooks can be used in eval strings in the form of {cyan}${{info:some_hook,arguments}}{reset}.
+
+Commas and backslashes in arguments to autosort info hooks (except for {cyan}${{info:autosort_escape}}{reset}) must be escaped with a backslash.
+
+{*white}${{info:{brown}autosort_replace{white},{cyan}pattern{white},{cyan}replacement{white},{cyan}source{white}}}{reset}
+Replace all occurrences of {cyan}pattern{reset} with {cyan}replacement{reset} in the string {cyan}source{reset}.
+Can be used to ignore certain strings when sorting by replacing them with an empty string.
+
+For example: {cyan}${{info:autosort_replace,cat,dog,the dog is meowing}}{reset} expands to "the cat is meowing".
+
+{*white}${{info:{brown}autosort_order{white},{cyan}value{white},{cyan}option0{white},{cyan}option1{white},{cyan}option2{white},{cyan}...{white}}}
+Generate a zero-padded number that corresponds to the index of {cyan}value{reset} in the list of options.
+If one of the options is the special value {brown}*{reset}, then any value not explicitly mentioned will be sorted at that position.
+Otherwise, any value that does not match an option is assigned the highest number available.
+Can be used to easily sort buffers based on a manual sequence.
+
+For example: {cyan}${{info:autosort_order,${{server}},freenode,oftc,efnet}}{reset} will sort freenode before oftc, followed by efnet and then any remaining servers.
+Alternatively, {cyan}${{info:autosort_order,${{server}},freenode,oftc,*,efnet}}{reset} will sort any unlisted servers after freenode and oftc, but before efnet.
+
+{*white}${{info:{brown}autosort_escape{white},{cyan}text{white}}}{reset}
+Escape commas and backslashes in {cyan}text{reset} by prepending them with a backslash.
+This is mainly useful to pass arbitrary eval strings as arguments to other autosort info hooks.
+Otherwise, an eval string that expands to something with a comma would be interpreted as multiple arguments.
+
+For example, it can be used to safely pass buffer names to {cyan}${{info:autosort_replace}}{reset} like so:
+{cyan}${{info:autosort_replace,##,#,${{info:autosort_escape,${{buffer.name}}}}}}{reset}.
+
+
+{*white}# Description
+Autosort is a weechat script to automatically keep your buffers sorted. The sort
+order can be customized by defining your own sort rules, but the default should
+be sane enough for most people. It can also group IRC channel/private buffers
+under their server buffer if you like.
+
+Autosort uses a stable sorting algorithm, meaning that you can manually move buffers
+to change their relative order, if they sort equal with your rule set.
+
+{*white}# Sort rules{reset}
+Autosort evaluates a list of eval expressions (see {*default}/help eval{reset}) and sorts the
+buffers based on evaluated result. Earlier rules will be considered first. Only
+if earlier rules produced identical results is the result of the next rule
+considered for sorting purposes.
+
+You can debug your sort rules with the `{*default}/autosort debug{reset}` command, which will
+print the evaluation results of each rule for each buffer.
+
+{*brown}NOTE:{reset} The sort rules for version 3 are not compatible with version 2 or vice
+versa. You will have to manually port your old rules to version 3 if you have any.
+
+{*white}# Helper variables{reset}
+You may define helper variables for the main sort rules to keep your rules
+readable. They can be used in the main sort rules as variables. For example,
+a helper variable named `{cyan}foo{reset}` can be accessed in a main rule with the
+string `{cyan}${{foo}}{reset}`.
+
+{*white}# Automatic or manual sorting{reset}
+By default, autosort will automatically sort your buffer list whenever a buffer
+is opened, merged, unmerged or renamed. This should keep your buffers sorted in
+almost all situations. However, you may wish to change the list of signals that
+cause your buffer list to be sorted. Simply edit the `{cyan}autosort.sorting.signals{reset}`
+option to add or remove any signal you like.
+
+If you remove all signals you can still sort your buffers manually with the
+`{*default}/autosort sort{reset}` command. To prevent all automatic sorting, the option
+`{cyan}autosort.sorting.sort_on_config_change{reset}` should also be disabled.
+
+{*white}# Recommended settings
+For the best visual effect, consider setting the following options:
+ {*white}/set {cyan}irc.look.server_buffer{reset} {brown}independent{reset}
+
+This setting allows server buffers to be sorted independently, which is
+needed to create a hierarchical tree view of the server and channel buffers.
+
+If you are using the {*default}buflist{reset} plugin you can (ab)use Unicode to draw a tree
+structure with the following setting (modify to suit your need):
+ {*white}/set {cyan}buflist.format.indent {brown}"${{color:237}}${{if:${{buffer.next_buffer.local_variables.type}}=~^(channel|private)$?├─:└─}}"{reset}
+'''
+
+command_completion = '%(plugin_autosort) %(plugin_autosort) %(plugin_autosort) %(plugin_autosort) %(plugin_autosort)'
+
+info_replace_description = (
+ 'Replace all occurrences of `pattern` with `replacement` in the string `source`. '
+ 'Can be used to ignore certain strings when sorting by replacing them with an empty string. '
+ 'See /help autosort for examples.'
+)
+info_replace_arguments = 'pattern,replacement,source'
+
+info_order_description = (
+ 'Generate a zero-padded number that corresponds to the index of `value` in the list of options. '
+ 'If one of the options is the special value `*`, then any value not explicitly mentioned will be sorted at that position. '
+ 'Otherwise, any value that does not match an option is assigned the highest number available. '
+ 'Can be used to easily sort buffers based on a manual sequence. '
+ 'See /help autosort for examples.'
+)
+info_order_arguments = 'value,first,second,third,...'
+
+info_escape_description = (
+ 'Escape commas and backslashes in `text` by prepending them with a backslash. '
+ 'This is mainly useful to pass arbitrary eval strings as arguments to other autosort info hooks. '
+ 'Otherwise, an eval string that expands to something with a comma would be interpreted as multiple arguments.'
+ 'See /help autosort for examples.'
+)
+info_escape_arguments = 'text'
+
+
+if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
+ config = Config('autosort')
+
+ colors = {
+ 'default': weechat.color('default'),
+ 'reset': weechat.color('reset'),
+ 'black': weechat.color('black'),
+ 'red': weechat.color('red'),
+ 'green': weechat.color('green'),
+ 'brown': weechat.color('brown'),
+ 'yellow': weechat.color('yellow'),
+ 'blue': weechat.color('blue'),
+ 'magenta': weechat.color('magenta'),
+ 'cyan': weechat.color('cyan'),
+ 'white': weechat.color('white'),
+ '*default': weechat.color('*default'),
+ '*black': weechat.color('*black'),
+ '*red': weechat.color('*red'),
+ '*green': weechat.color('*green'),
+ '*brown': weechat.color('*brown'),
+ '*yellow': weechat.color('*yellow'),
+ '*blue': weechat.color('*blue'),
+ '*magenta': weechat.color('*magenta'),
+ '*cyan': weechat.color('*cyan'),
+ '*white': weechat.color('*white'),
+ }
+
+ weechat.hook_config('autosort.*', 'on_config_changed', '')
+ weechat.hook_completion('plugin_autosort', '', 'on_autosort_complete', '')
+ weechat.hook_command('autosort', command_description.format(**colors), '', '', command_completion, 'on_autosort_command', '')
+ weechat.hook_info('autosort_escape', info_escape_description, info_escape_arguments, 'on_info_escape', '')
+ weechat.hook_info('autosort_replace', info_replace_description, info_replace_arguments, 'on_info_replace', '')
+ weechat.hook_info('autosort_order', info_order_description, info_order_arguments, 'on_info_order', '')
+
+ apply_config()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/python/colon_complete.py Mon Aug 23 11:51:18 2021 -0400
@@ -0,0 +1,69 @@
+SCRIPT_NAME='coloncomplete'
+SCRIPT_AUTHOR='Steve Losh <steve@stevelosh.com>'
+SCRIPT_VERSION='1.0'
+SCRIPT_LICENSE='MIT/X11'
+SCRIPT_DESC='Add a colon after nick completion when all the previous words in the input are also nicks.'
+
+EXTRA_NICKS = ['all', 'backend', 'clojerks', 'ops', 'support']
+
+import_ok=True
+
+try:
+ import weechat
+except ImportError:
+ print 'This script must be run under WeeChat'
+ print 'You can obtain a copy of WeeChat, for free, at http://www.weechat.org'
+ import_ok=False
+
+weechat_version=0
+
+def get_nicks(buffer, prefix=''):
+ channel = weechat.buffer_get_string(buffer, 'localvar_channel')
+ server = weechat.buffer_get_string(buffer, 'localvar_server')
+ prefix = prefix.lower()
+
+ matches = []
+
+ infolist = weechat.infolist_get('irc_nick', '', '%s,%s' % (server, channel))
+ while weechat.infolist_next(infolist):
+ nick = weechat.infolist_string(infolist, 'name')
+ if nick != 'localhost' and nick.lower().startswith(prefix):
+ matches.append(nick)
+ weechat.infolist_free(infolist)
+
+ for nick in EXTRA_NICKS:
+ if nick.lower().startswith(prefix):
+ matches.append(nick)
+
+ return matches
+
+def completer(data, buffer, command):
+ cb = weechat.current_buffer()
+ if command == "/input complete_next":
+ line = weechat.buffer_get_string(cb, "input")
+ words = line.split(' ')
+ prefix = words[-1]
+ if prefix and words and all([s.endswith(':') for s in words[:-1] if s]):
+ nicks = get_nicks(cb, prefix)
+ if len(nicks) == 1:
+ for _ in range(len(prefix)):
+ weechat.command(buffer, "/input delete_previous_char")
+ weechat.command(buffer, "/input insert " + nicks[-1] + ":\\x20")
+ elif len(nicks) > 1:
+ l = min(len(nick) for nick in nicks)
+ for i in range(len(prefix), l):
+ if len(set(nick[i] for nick in nicks)) > 1:
+ break
+ else:
+ weechat.command(buffer, "/input insert " + nicks[0][i])
+
+ for nick in nicks:
+ weechat.prnt(cb, "==> " + nick)
+ return weechat.WEECHAT_RC_OK_EAT
+
+ return weechat.WEECHAT_RC_OK
+
+if __name__ == "__main__" and import_ok:
+ if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
+ weechat_version = weechat.info_get("version_number", "") or 0
+ weechat.hook_command_run('/input complete*', 'completer', '')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/python/sanitize_jira.py Mon Aug 23 11:51:18 2021 -0400
@@ -0,0 +1,33 @@
+import re, weechat, subprocess
+
+SCRIPT_NAME = 'sanitize_jira'
+SCRIPT_AUTHOR = 'Steve Losh <steve@stevelosh.com>'
+SCRIPT_VERSION = '0.0.1'
+SCRIPT_LICENSE = 'MIT'
+SCRIPT_DESC = 'clean up the garbage jirabot sends to channels into something readable'
+
+weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', '')
+
+weechat.hook_line('*', '', 'nick_Jira_Cloud', 'sanitize_jira', '')
+
+first_line_re = re.compile(
+ r'(?P<link>https://[^/]+/browse/[^?]+)[?]atlOrigin=[^ ]+ [(](?P<title>.+)[)]'
+)
+
+detail_line_re = re.compile(
+ r'''Status: \x1a\x01[*](?P<status>[^*]+)[*]\x1b\x01.*Type: \x1a\x01[*](?P<type>[^*]+)[*]\x1b\x01.*Assignee: \x1a\x01[*](?P<assignee>[^*]+)[*]\x1b\x01.*Priority: \x1a\x01[*](?P<priority>[^*]+)[*]\x1b\x01'''
+)
+
+def sanitize_jira(data, line):
+ if 'sign up for an Atlassian account to view this link' in line['message']:
+ return {'message': ' '}
+
+ m = first_line_re.search(line['message'])
+ if m:
+ return {'message': '%s | %s' % (m.group('title'), m.group('link'))}
+
+ m = detail_line_re.search(line['message'])
+ if m:
+ return {'message': '%s / %s / %s' % (m.group('type'), m.group('status'), m.group('assignee'))}
+
+ return {}
--- a/weechat/relay.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/relay.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- relay.conf
+# WeeChat -- relay.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
@@ -27,14 +27,20 @@
[network]
allow_empty_password = off
allowed_ips = ""
+auth_timeout = 60
bind_address = ""
clients_purge_delay = 0
compression_level = 6
ipv6 = on
max_clients = 5
+nonce_size = 16
password = ""
+password_hash_algo = "*"
+password_hash_iterations = 100000
ssl_cert_key = "%h/ssl/relay.pem"
ssl_priorities = "NORMAL:-VERS-SSL3.0"
+totp_secret = ""
+totp_window = 0
websocket_allowed_origins = ""
[irc]
@@ -45,4 +51,9 @@
backlog_tags = "irc_privmsg"
backlog_time_format = "[%H:%M] "
+[weechat]
+commands = ""
+
[port]
+
+[path]
--- a/weechat/ruby.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/ruby.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- ruby.conf
+# WeeChat -- ruby.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
--- a/weechat/script.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/script.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- script.conf
+# WeeChat -- script.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
@@ -50,6 +50,7 @@
[scripts]
autoload = on
cache_expire = 60
+download_enabled = on
download_timeout = 30
hold = ""
path = "%h/script"
--- a/weechat/trigger.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/trigger.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- trigger.conf
+# WeeChat -- trigger.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
--- a/weechat/urlgrab.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/urlgrab.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- urlgrab.conf
+# WeeChat -- urlgrab.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
--- a/weechat/weechat.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/weechat.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- weechat.conf
+# WeeChat -- weechat.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
@@ -35,6 +35,7 @@
buffer_search_regex = off
buffer_search_where = prefix_message
buffer_time_format = "%H:%M"
+buffer_time_same = ""
color_basic_force_bold = off
color_inactive_buffer = off
color_inactive_message = on
@@ -71,6 +72,7 @@
hotlist_sort = group_time_asc
hotlist_suffix = ""
hotlist_unique_numbers = on
+hotlist_update_on_buffer_switch = on
input_cursor_scroll = 20
input_share = none
input_share_overwrite = off
@@ -89,6 +91,7 @@
mouse_timer_delay = 100
nick_color_force = ""
nick_color_hash = djb2
+nick_color_hash_salt = ""
nick_color_stop_chars = "_|["
nick_prefix = ""
nick_suffix = ""
@@ -111,6 +114,7 @@
prefix_network = "--"
prefix_quit = "✘"
prefix_same_nick = ""
+prefix_same_nick_middle = ""
prefix_suffix = "|"
quote_nick_prefix = "<"
quote_nick_suffix = ">"
@@ -118,6 +122,7 @@
read_marker = line
read_marker_always_show = on
read_marker_string = "─"
+read_marker_update_on_buffer_switch = on
save_config_on_exit = off
save_config_with_fsync = off
save_layout_on_exit = all
@@ -231,7 +236,8 @@
[network]
connection_timeout = 60
-gnutls_ca_file = "/etc/ssl/certs/ca-certificates.crt"
+gnutls_ca_system = on
+gnutls_ca_user = ""
gnutls_handshake_timeout = 30
proxy_curl = ""
@@ -242,8 +248,16 @@
path = "%h/plugins"
save_config_on_unload = on
+[signal]
+sighup = "${if:${info:weechat_headless}?/reload:/quit -yes}"
+sigquit = "/quit -yes"
+sigterm = "/quit -yes"
+sigusr1 = ""
+sigusr2 = ""
+
[bar]
buffers.color_bg = default
+buffers.color_bg_inactive = default
buffers.color_delim = default
buffers.color_fg = default
buffers.conditions = ""
@@ -258,6 +272,7 @@
buffers.size_max = 0
buffers.type = root
buflist.color_bg = default
+buflist.color_bg_inactive = default
buflist.color_delim = default
buflist.color_fg = default
buflist.conditions = ""
@@ -272,6 +287,7 @@
buflist.size_max = 25
buflist.type = root
fset.color_bg = default
+fset.color_bg_inactive = default
fset.color_delim = cyan
fset.color_fg = default
fset.conditions = "${buffer.full_name} == fset.fset"
@@ -286,6 +302,7 @@
fset.size_max = 3
fset.type = window
input.color_bg = default
+input.color_bg_inactive = default
input.color_delim = green
input.color_fg = default
input.conditions = ""
@@ -300,6 +317,7 @@
input.size_max = 0
input.type = window
nicklist.color_bg = default
+nicklist.color_bg_inactive = default
nicklist.color_delim = cyan
nicklist.color_fg = default
nicklist.conditions = "nicklist"
@@ -314,6 +332,7 @@
nicklist.size_max = 0
nicklist.type = window
status.color_bg = green
+status.color_bg_inactive = default
status.color_delim = 0
status.color_fg = 0
status.conditions = ""
@@ -328,6 +347,7 @@
status.size_max = 0
status.type = window
title.color_bg = green
+title.color_bg_inactive = default
title.color_delim = cyan
title.color_fg = 16
title.conditions = ""
@@ -345,6 +365,11 @@
[layout]
[notify]
+python.slack.10xgenomics.&cloud-alerts-pagerduty = highlight
+python.slack.10xgenomics.&cloud-sumo-prod-support-alerts = highlight
+python.slack.10xgenomics.&lacework-10xdev = highlight
+python.slack.10xgenomics.&lacework-10xprod = highlight
+python.slack.10xgenomics.&testing1234 = highlight
[filter]
irc_smart = on;*;irc_smart_filter;*
@@ -381,6 +406,8 @@
ctrl-Y = "/input clipboard_paste"
meta-meta-OP = "/bar scroll buflist * b"
meta-meta-OQ = "/bar scroll buflist * e"
+meta-meta2-11~ = "/bar scroll buflist * b"
+meta-meta2-12~ = "/bar scroll buflist * e"
meta-meta2-1~ = "/window scroll_top"
meta-meta2-23~ = "/bar scroll nicklist * yb"
meta-meta2-24~ = "/bar scroll nicklist * ye"
@@ -406,6 +433,7 @@
meta-< = "/input jump_previously_visited_buffer"
meta-= = "/filter toggle"
meta-> = "/input jump_next_visited_buffer"
+meta-B = "/buflist toggle"
meta-OA = "/input history_global_previous"
meta-OB = "/input history_global_next"
meta-OC = "/input move_next_word"
@@ -418,6 +446,10 @@
meta-Ob = "/input history_global_next"
meta-Oc = "/input move_next_word"
meta-Od = "/input move_previous_word"
+meta2-11^ = "/bar scroll buflist * -100%"
+meta2-11~ = "/bar scroll buflist * -100%"
+meta2-12^ = "/bar scroll buflist * +100%"
+meta2-12~ = "/bar scroll buflist * +100%"
meta2-15~ = "/bar scroll nicklist * y-100%"
meta2-17~ = "/bar scroll nicklist * y+100%"
meta2-18~ = "/window -1"
@@ -426,8 +458,12 @@
meta2-1;3B = "/buffer +1"
meta2-1;3C = "/buffer +1"
meta2-1;3D = "/buffer -1"
+meta2-1;3P = "/bar scroll buflist * b"
+meta2-1;3Q = "/bar scroll buflist * e"
meta2-1;5A = "/input history_global_previous"
meta2-1;5B = "/input history_global_next"
+meta2-1;5P = "/bar scroll buflist * -100%"
+meta2-1;5Q = "/bar scroll buflist * +100%"
meta2-1;9A = "/buffer move -1"
meta2-1;9B = "/buffer move +1"
meta2-1~ = "/input move_beginning_of_line"
@@ -601,6 +637,11 @@
meta2-B = "/cursor move down"
meta2-C = "/cursor move right"
meta2-D = "/cursor move left"
+@chat(python.*):D = "hsignal:slack_cursor_delete"
+@chat(python.*):L = "hsignal:slack_cursor_linkarchive"
+@chat(python.*):M = "hsignal:slack_cursor_message"
+@chat(python.*):R = "hsignal:slack_cursor_reply"
+@chat(python.*):T = "hsignal:slack_cursor_thread"
@item(buffer_nicklist):K = "/window ${_window_number};/kickban ${nick}"
@item(buffer_nicklist):b = "/window ${_window_number};/ban ${nick}"
@item(buffer_nicklist):k = "/window ${_window_number};/kick ${nick}"
@@ -622,6 +663,7 @@
@chat(fset.fset):button2* = "hsignal:fset_mouse"
@chat(fset.fset):wheeldown = "/fset -down 5"
@chat(fset.fset):wheelup = "/fset -up 5"
+@chat(python.*):button2 = "hsignal:slack_mouse"
@chat(script.scripts):button1 = "/window ${_window_number};/script go ${_chat_line_y}"
@chat(script.scripts):button2 = "/window ${_window_number};/script go ${_chat_line_y};/script installremove -q ${script_name_with_extension}"
@chat(script.scripts):wheeldown = "/script down 5"
--- a/weechat/xfer.conf Tue Aug 17 15:20:33 2021 -0400
+++ b/weechat/xfer.conf Mon Aug 23 11:51:18 2021 -0400
@@ -1,10 +1,10 @@
#
-# weechat -- xfer.conf
+# WeeChat -- xfer.conf
#
# WARNING: It is NOT recommended to edit this file by hand,
# especially if WeeChat is running.
#
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
#
# For more info, see: https://weechat.org/doc/quickstart
#
@@ -31,7 +31,8 @@
own_ip = ""
port_range = ""
send_ack = on
-speed_limit = 0
+speed_limit_recv = 0
+speed_limit_send = 0
timeout = 300
[file]
@@ -43,5 +44,6 @@
auto_resume = on
convert_spaces = on
download_path = "%h/xfer"
+download_temporary_suffix = ".part"
upload_path = "~"
use_nick_in_filename = on