Skip to content
Browse files

update themes

  • Loading branch information...
1 parent e206e4c commit 26edda802382df9aab30d31c8c87019913d6cc32 @mrtazz committed Jul 22, 2013
Showing with 1,333 additions and 995 deletions.
  1. +210 −10 perl/buffers.pl
  2. +1 −0 python/autoload/buffer_autoclose.py
  3. +1 −0 python/autoload/theme.py
  4. +0 −980 python/autoload/weeget.py
  5. +128 −0 python/buffer_autoclose.py
  6. +16 −5 python/go.py
  7. +977 −0 python/theme.py
View
220 perl/buffers.pl
@@ -20,6 +20,14 @@
#
# History:
#
+# 2012-10-18, nils_2@freenode.#weechat:
+# v3.8: add option "mark_inactive", to mark buffers you are not in (idea by xrdodrx)
+# : add wildcard "*" for immune_detach_buffers (idea by StarWeaver)
+# : add new options "detach_query" and "detach_free_content" (idea by StarWeaver)
+# 2012-10-06, Nei <anti.teamidiot.de>:
+# v3.7: call menu on right mouse if menu script is loaded.
+# 2012-10-06, nils_2 <weechatter@arcor.de>:
+# v3.6: add new option "hotlist_counter" (idea by torque).
# 2012-06-02, nils_2 <weechatter@arcor.de>:
# v3.5: add values "server|channel|private|all|keepserver|none" to option "hide_merged_buffers" (suggested by dominikh).
# 2012-05-25, nils_2 <weechatter@arcor.de>:
@@ -126,15 +134,15 @@
use strict;
use Encode qw( decode encode );
# -------------------------------[ internal ]-------------------------------------
-my $version = "3.5";
+my $version = "3.8";
my $BUFFERS_CONFIG_FILE_NAME = "buffers";
my $buffers_config_file;
my $cmd_buffers_whitelist= "buffers_whitelist";
my $cmd_buffers_detach = "buffers_detach";
my %mouse_keys = ("\@item(buffers):button1*" => "hsignal:buffers_mouse", # catch all left mouse button gestures
- "\@item(buffers):button2" => "hsignal:buffers_mouse"); # catch right mouse button
+ "\@item(buffers):button2*" => "hsignal:buffers_mouse"); # catch all right mouse button gestures
my %options;
my %hotlist_level = (0 => "low", 1 => "message", 2 => "private", 3 => "highlight");
my @whitelist_buffers = ();
@@ -158,6 +166,8 @@
weechat::hook_signal("buffer_*", "buffers_signal_buffer", "");
weechat::hook_signal("window_switch", "buffers_signal_buffer", "");
weechat::hook_signal("hotlist_*", "buffers_signal_hotlist", "");
+weechat::hook_signal("window_switch", "buffers_signal_buffer", "");
+#weechat::hook_command_run("/input switch_active_*", "buffers_signal_buffer", "");
weechat::bar_item_update("buffers");
if ($weechat_version >= 0x00030600)
{
@@ -179,7 +189,6 @@
"del %-||".
"reset %-",
"buffers_cmd_whitelist", "");
-
weechat::hook_command( $cmd_buffers_detach,
"add/del current buffer to/from buffers detach",
"[add] || [del] || [reset]",
@@ -381,6 +390,7 @@ sub buffers_config_init
my %default_options_look =
(
+ "hotlist_counter" => ["hotlist_counter","boolean","show number of message for the buffer (this option needs WeeChat >= 0.3.5). The relevant option for notification is \"weechat.look.buffer_notify_default\"","",0,0,"off","off",0,"","","buffers_signal_config","","",""],
"show_lag" => ["show_lag","boolean","show lag behind servername. This option is using \"irc.color.item_lag_finished\", \"irc.network.lag_min_show\" and \"irc.network.lag_refresh_interval\"","",0,0,"off","off",0,"","","buffers_signal_config","","",""],
"look_whitelist_buffers" => ["whitelist_buffers", "string", "comma separated list of buffers for using a differnt color scheme (for example: freenode.#weechat,freenode.#weechat-fr)", "", 0, 0,"", "", 0, "", "", "buffers_signal_config_whitelist", "", "", ""],
"hide_merged_buffers" => ["hide_merged_buffers", "integer", "hide merged buffers. The value determines which merged buffers should be hidden, keepserver meaning 'all except server buffers'. Other values correspondent to the buffer type.", "server|channel|private|keepserver|all|none", 0, 0,"none", "none", 0, "", "", "buffers_signal_config", "", "", ""],
@@ -397,7 +407,10 @@ sub buffers_config_init
"name_size_max" => ["name_size_max","integer","maximum size of buffer name. 0 means no limitation","",0,256,0,0,0, "", "", "buffers_signal_config", "", "", ""],
"name_crop_suffix" => ["name_crop_suffix","string","contains an optional char(s) that is appended when buffer name is shortened","",0,0,"+","+",0,"","","buffers_signal_config", "", "", ""],
"detach" => ["detach", "integer","detach channel from buffers list after a specific period of time (in seconds) without action (weechat ≥ 0.3.8 required)", "", 0, 31536000,0, "number", 0, "", "", "buffers_signal_config", "", "", ""],
- "immune_detach_buffers" => ["immune_detach_buffers", "string", "comma separated list of buffers which will not get detached automatically. Good with e.g. BitlBee", "", 0, 0,"", "", 0, "", "", "buffers_signal_config_immune_detach_buffers", "", "", ""],
+ "immune_detach_buffers"=> ["immune_detach_buffers", "string", "Comma seperated list of buffers to NOT automatically detatch. Allows \"*\" wildcard. Ex: \"BitlBee,freenode.*\"", "", 0, 0,"", "", 0, "", "", "buffers_signal_config_immune_detach_buffers", "", "", ""],
+ "detach_query" => ["detach_query", "boolean", "query buffer will be detachted", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
+ "detach_free_content" => ["detach_free_content", "boolean", "buffers with free content will be detached (Ex: iset, chanmon)", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
+ "mark_inactive" => ["mark_inactive", "boolean", "if option is \"on\", inactive buffers (those you are not in) will have parentesis around them. An inactive buffer will not be detached.", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
);
# section "color"
my $section_color = weechat::config_new_section($buffers_config_file,"color", 0, 0, "", "", "", "", "", "", "", "", "", "");
@@ -453,6 +466,17 @@ sub build_buffers
{
$hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")} =
weechat::infolist_integer($infolist, "priority");
+ if ( weechat::config_boolean( $options{"hotlist_counter"} ) eq 1 and $weechat_version >= 0x00030500)
+ {
+ $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_00"} =
+ weechat::infolist_integer($infolist, "count_00"); # low message
+ $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_01"} =
+ weechat::infolist_integer($infolist, "count_01"); # channel message
+ $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_02"} =
+ weechat::infolist_integer($infolist, "count_02"); # private message
+ $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_03"} =
+ weechat::infolist_integer($infolist, "count_03"); # highlight message
+ }
}
weechat::infolist_free($infolist);
@@ -498,7 +522,25 @@ sub build_buffers
$buffer->{"type"} = weechat::buffer_get_string($buffer->{"pointer"},"localvar_type");
# weechat::print("",$buffer->{"type"});
- unless( grep {$_ eq $buffer->{"name"}} @immune_detach_buffers )
+ # check if buffer is active (or maybe a /part, /kick channel)
+ if ($buffer->{"type"} eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1)
+ {
+ my $server = weechat::buffer_get_string($buffer->{"pointer"},"localvar_server");
+ my $channel = weechat::buffer_get_string($buffer->{"pointer"},"localvar_channel");
+ my $infolist_channel = weechat::infolist_get("irc_channel","",$server.",".$channel);
+ if ($infolist_channel)
+ {
+ weechat::infolist_next($infolist_channel);
+ $buffer->{"nicks_count"} = weechat::infolist_integer($infolist_channel,"nicks_count");
+ }else
+ {
+ $buffer->{"nicks_count"} = 0;
+ }
+ weechat::infolist_free($infolist_channel);
+ }
+
+ my $result = check_immune_detached_buffers($buffer->{"name"}); # checking for wildcard
+ unless ($result)
{
my $detach_time = weechat::config_integer( $options{"detach"});
my $current_time = time();
@@ -509,14 +551,38 @@ sub build_buffers
and not exists $buffers_timer{$buffer->{"pointer"}}
and $detach_time > 0);
+ $buffers_timer{$buffer->{"pointer"}} = $current_time
+ if (weechat::config_boolean($options{"detach_query"}) eq 1
+ and not exists $hotlist{$buffer->{"pointer"}}
+ and $buffer->{"type"} eq "private"
+ and not exists $buffers_timer{$buffer->{"pointer"}}
+ and $detach_time > 0);
+
+ $detach_time = 0
+ if (weechat::config_boolean($options{"detach_query"}) eq 0
+ and $buffer->{"type"} eq "private");
+
+ # free content buffer
+ $buffers_timer{$buffer->{"pointer"}} = $current_time
+ if (weechat::config_boolean($options{"detach_free_content"}) eq 1
+ and not exists $hotlist{$buffer->{"pointer"}}
+ and $buffer->{"type"} eq ""
+ and not exists $buffers_timer{$buffer->{"pointer"}}
+ and $detach_time > 0);
+ $detach_time = 0
+ if (weechat::config_boolean($options{"detach_free_content"}) eq 0
+ and $buffer->{"type"} eq "");
+
+ $detach_time = 0 if (weechat::config_boolean($options{"mark_inactive"}) eq 1 and defined $buffer->{"nicks_count"} and $buffer->{"nicks_count"} == 0);
+
# check for detach
unless ( $buffer->{"current_buffer"} eq 0
and not exists $hotlist{$buffer->{"pointer"}}
- and $buffer->{"type"} eq "channel"
+# and $buffer->{"type"} eq "channel"
and exists $buffers_timer{$buffer->{"pointer"}}
and $detach_time > 0
and $weechat_version >= 0x00030800
- and $current_time - $buffers_timer{$buffer->{"pointer"}} >= $detach_time )
+ and $current_time - $buffers_timer{$buffer->{"pointer"}} >= $detach_time)
{
if ($active_seen)
{
@@ -528,7 +594,7 @@ sub build_buffers
}
}
}
- else
+ else # buffer in "immune_detach_buffers"
{
if ($active_seen)
{
@@ -539,7 +605,6 @@ sub build_buffers
push(@current1, $buffer);
}
}
-
} # while end
@@ -806,6 +871,11 @@ sub build_buffers
}
}
}
+ if ($buffer->{"type"} eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1 and $buffer->{"nicks_count"} == 0)
+ {
+ $str .= "(";
+ }
+
$str .= weechat::color($color) . weechat::color(",".$bg);
if (weechat::config_boolean( $options{"short_names"} ) eq 1)
@@ -814,10 +884,14 @@ sub build_buffers
{
$str .= encode("UTF-8", substr(decode("UTF-8", $buffer->{"short_name"}), 0, weechat::config_integer($options{"name_size_max"})));
$str .= weechat::color(weechat::config_color( $options{"color_number_char"})).weechat::config_string($options{"name_crop_suffix"}) if (length($buffer->{"short_name"}) > weechat::config_integer($options{"name_size_max"}));
+ $str .= add_inactive_parentless($buffer->{"type"},$buffer->{"nicks_count"});
+ $str .= add_hotlist_count($buffer->{"pointer"},%hotlist);
}
else
{
$str .= $buffer->{"short_name"};
+ $str .= add_inactive_parentless($buffer->{"type"},$buffer->{"nicks_count"});
+ $str .= add_hotlist_count($buffer->{"pointer"},%hotlist);
}
}
else
@@ -826,10 +900,14 @@ sub build_buffers
{
$str .= encode("UTF-8", substr(decode("UTF-8", $buffer->{"name"},), 0, weechat::config_integer($options{"name_size_max"})));
$str .= weechat::color(weechat::config_color( $options{"color_number_char"})).weechat::config_string($options{"name_crop_suffix"}) if (length($buffer->{"name"}) > weechat::config_integer($options{"name_size_max"}));
+ $str .= add_inactive_parentless($buffer->{"type"},$buffer->{"nicks_count"});
+ $str .= add_hotlist_count($buffer->{"pointer"},%hotlist);
}
else
{
$str .= $buffer->{"name"};
+ $str .= add_inactive_parentless($buffer->{"type"},$buffer->{"nicks_count"});
+ $str .= add_hotlist_count($buffer->{"pointer"},%hotlist);
}
}
if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "server" and weechat::config_boolean($options{"show_lag"}) eq 1)
@@ -853,10 +931,100 @@ sub build_buffers
return $str;
}
+sub add_inactive_parentless
+{
+my ($buf_type, $buf_nicks_count) = @_;
+my $str = "";
+ if ($buf_type eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1 and $buf_nicks_count == 0)
+ {
+ $str .= weechat::color(weechat::config_color( $options{"color_number_char"}));
+ $str .= ")";
+ }
+return $str;
+}
+
+sub add_hotlist_count
+{
+my ($bufpointer,%hotlist) = @_;
+
+return "" if ( weechat::config_boolean( $options{"hotlist_counter"} ) eq 0 or ($weechat_version < 0x00030500)); # off
+my $col_number_char = weechat::color(weechat::config_color( $options{"color_number_char"}) );
+my $str = " ".$col_number_char."(";
+
+# 0 = low level
+if (defined $hotlist{$bufpointer."_count_00"})
+{
+ my $bg = weechat::config_color( $options{"color_hotlist_low_bg"} );
+ my $color = weechat::config_color( $options{"color_hotlist_low_fg"} );
+ $str .= weechat::color($bg).
+ weechat::color($color).
+ $hotlist{$bufpointer."_count_00"} if ($hotlist{$bufpointer."_count_00"} ne "0");
+}
+
+# 1 = message
+if (defined $hotlist{$bufpointer."_count_01"})
+{
+ my $bg = weechat::config_color( $options{"color_hotlist_message_bg"} );
+ my $color = weechat::config_color( $options{"color_hotlist_message_fg"} );
+ if ($str =~ /[0-9]$/)
+ {
+ $str .= ",".
+ weechat::color($bg).
+ weechat::color($color).
+ $hotlist{$bufpointer."_count_01"} if ($hotlist{$bufpointer."_count_01"} ne "0");
+ }else
+ {
+ $str .= weechat::color($bg).
+ weechat::color($color).
+ $hotlist{$bufpointer."_count_01"} if ($hotlist{$bufpointer."_count_01"} ne "0");
+ }
+}
+# 2 = private
+if (defined $hotlist{$bufpointer."_count_02"})
+{
+ my $bg = weechat::config_color( $options{"color_hotlist_private_bg"} );
+ my $color = weechat::config_color( $options{"color_hotlist_private_fg"} );
+ if ($str =~ /[0-9]$/)
+ {
+ $str .= ",".
+ weechat::color($bg).
+ weechat::color($color).
+ $hotlist{$bufpointer."_count_02"} if ($hotlist{$bufpointer."_count_02"} ne "0");
+ }else
+ {
+ $str .= weechat::color($bg).
+ weechat::color($color).
+ $hotlist{$bufpointer."_count_02"} if ($hotlist{$bufpointer."_count_02"} ne "0");
+ }
+}
+# 3 = highlight
+if (defined $hotlist{$bufpointer."_count_03"})
+{
+ my $bg = weechat::config_color( $options{"color_hotlist_highlight_bg"} );
+ my $color = weechat::config_color( $options{"color_hotlist_highlight_fg"} );
+ if ($str =~ /[0-9]$/)
+ {
+ $str .= ",".
+ weechat::color($bg).
+ weechat::color($color).
+ $hotlist{$bufpointer."_count_03"} if ($hotlist{$bufpointer."_count_03"} ne "0");
+ }else
+ {
+ $str .= weechat::color($bg).
+ weechat::color($color).
+ $hotlist{$bufpointer."_count_03"} if ($hotlist{$bufpointer."_count_03"} ne "0");
+ }
+}
+$str .= $col_number_char. ")";
+
+$str = "" if (weechat::string_remove_color($str, "") eq " ()"); # remove color and check for buffer with no messages
+return $str;
+}
+
sub buffers_signal_buffer
{
my ($data, $signal, $signal_data) = @_;
- # check for buffer_switch and set the detach time or remove detach time
+ # check for buffer_switch and set or remove detach time
if ($weechat_version >= 0x00030800)
{
if ($signal eq "buffer_switch")
@@ -979,9 +1147,28 @@ sub buffers_hsignal_mouse
}
else
{
+ my $infolist = weechat::infolist_get("hook", "", "command,menu");
+ my $has_menu_command = weechat::infolist_next($infolist);
+ weechat::infolist_free($infolist);
+
+ if ( $has_menu_command && $hash{"_key"} =~ /button2/ )
+ {
+ if ($hash{"number"} eq $hash{"number2"})
+ {
+ weechat::command($hash{"pointer"}, "/menu buffer1 $hash{short_name} $hash{number}");
+ }
+ else
+ {
+ weechat::command($hash{"pointer"}, "/menu buffer2 $hash{short_name}/$hash{short_name2} $hash{number} $hash{number2}")
+ }
+ }
+ else
+ {
move_buffer(%hash);
+ }
}
}
+
sub move_buffer
{
my %hash = @_;
@@ -996,3 +1183,16 @@ sub move_buffer
my $ptrbuf = weechat::current_buffer();
weechat::command($hash{"pointer"}, "/buffer move ".$number2);
}
+
+sub check_immune_detached_buffers
+{
+ my ($buffername) = @_;
+ foreach ( @immune_detach_buffers ){
+ my $immune_buffer = weechat::string_mask_to_regex($_);
+ if ($buffername =~ /^$immune_buffer$/i)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
View
1 python/autoload/buffer_autoclose.py
View
1 python/autoload/theme.py
View
980 python/autoload/weeget.py
@@ -1,980 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2009-2012 Sebastien Helleu <flashcode@flashtux.org>
-#
-# 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/>.
-#
-
-#
-# WeeChat scripts manager.
-# (this script requires WeeChat >= 0.3.0 and python >= 2.6)
-#
-# History:
-#
-# 2012-03-09, Sebastien Helleu <flashcode@flashtux.org>:
-# version 1.8: fix reload of config file
-# 2012-02-27, Sebastien Helleu <flashcode@flashtux.org>:
-# version 1.7: add support of scheme scripts
-# 2012-02-05, Sebastien Helleu <flashcode@flashtux.org>:
-# version 1.6: use URL transfer from API (for WeeChat >= 0.3.7)
-# 2012-01-03, Sebastien Helleu <flashcode@flashtux.org>:
-# version 1.5: make script compatible with Python 3.x
-# 2011-03-25, Sebastien Helleu <flashcode@flashtux.org>:
-# version 1.4: add completion with installed scripts for action "remove"
-# 2011-03-10, Sebastien Helleu <flashcode@flashtux.org>:
-# version 1.3: add script extension in script name completion and a new
-# completion with tags for actions "list" and "listinstalled"
-# 2011-02-13, Sebastien Helleu <flashcode@flashtux.org>:
-# version 1.2: use new help format for command arguments
-# 2010-11-08, Sebastien Helleu <flashcode@flashtux.org>:
-# version 1.1: get python 2.x binary for hook_process (fix problem
-# when python 3.x is default python version, requires
-# WeeChat >= 0.3.4)
-# 2010-02-22, Blake Winton <bwinton@latte.ca>:
-# version 1.0: add action "listinstalled" for command /weeget
-# 2010-01-25, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.9: fix "running" status of scripts with /weeget check
-# 2009-09-30, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.8: fix bugs and add missing info in "/weeget show",
-# display warning if url for plugins.xml.gz is old site
-# 2009-09-07, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.7: update weechat site with new URL
-# 2009-05-02, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.6: sync with last API changes
-# 2009-04-15, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.5: display missing module(s) when import failed
-# 2009-04-11, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.4: use new completion for command arguments
-# 2009-04-07, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.3: fix bug with install/upgrade when weeget is updated with
-# other scripts: ensure that weeget is always the last
-# installed script
-# 2009-04-07, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.2: add author's mail in script description
-# 2009-04-05, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.1: initial release
-#
-
-SCRIPT_NAME = "weeget"
-SCRIPT_AUTHOR = "Sebastien Helleu <flashcode@flashtux.org>"
-SCRIPT_VERSION = "1.8"
-SCRIPT_LICENSE = "GPL3"
-SCRIPT_DESC = "WeeChat scripts manager"
-
-SCRIPT_COMMAND = "weeget"
-
-import_ok = True
-
-try:
- import weechat
-except ImportError:
- print("This script must be run under WeeChat.")
- print("Get WeeChat now at: http://www.weechat.org/")
- import_ok = False
-
-try:
- import sys, os, stat, time, gzip, hashlib, xml.dom.minidom
-except ImportError as message:
- print("Missing package(s) for %s: %s" % (SCRIPT_NAME, message))
- import_ok = False
-
-CONFIG_FILE_NAME = "wg"
-
-SCRIPT_EXTENSION = {
- "perl" : "pl",
- "python": "py",
- "ruby" : "rb",
- "lua" : "lua",
- "tcl" : "tcl",
- "guile" : "scm",
-}
-
-# timeout for download of plugins.xml.gz
-TIMEOUT_UPDATE = 60 * 1000
-
-# timeout for download of a script
-TIMEOUT_SCRIPT = 60 * 1000
-
-# config file and options
-wg_config_file = ""
-wg_config_option = {}
-
-# action (install, remove, ..) and arguments
-wg_action = ""
-wg_action_args = ""
-
-# loaded scripts
-wg_loaded_scripts = {}
-
-# hook process and stdout
-wg_hook_process = { "update": "", "script": "" }
-wg_stdout = { "update": "", "script": "" }
-
-# scripts read from plugins.xml.gz
-wg_scripts = {}
-
-# list of script to install, and script currently installing
-wg_scripts_to_install = []
-wg_current_script_install = {}
-
-# =================================[ config ]=================================
-
-def wg_config_init():
- """
- Initialization of configuration file.
- Sections: color, scripts.
- """
- global wg_config_file, wg_config_option
- wg_config_file = weechat.config_new(CONFIG_FILE_NAME,
- "wg_config_reload_cb", "")
- if wg_config_file == "":
- return
-
- # section "color"
- section_color = weechat.config_new_section(
- wg_config_file, "color", 0, 0, "", "", "", "", "", "", "", "", "", "")
- if section_color == "":
- weechat.config_free(wg_config_file)
- return
- wg_config_option["color_script"] = weechat.config_new_option(
- wg_config_file, section_color,
- "script", "color", "Color for script names", "", 0, 0,
- "cyan", "cyan", 0, "", "", "", "", "", "")
- wg_config_option["color_installed"] = weechat.config_new_option(
- wg_config_file, section_color,
- "installed", "color", "Color for \"installed\" indicator", "", 0, 0,
- "yellow", "yellow", 0, "", "", "", "", "", "")
- wg_config_option["color_running"] = weechat.config_new_option(
- wg_config_file, section_color,
- "running", "color", "Color for \"running\" indicator", "", 0, 0,
- "lightgreen", "lightgreen", 0, "", "", "", "", "", "")
- wg_config_option["color_obsolete"] = weechat.config_new_option(
- wg_config_file, section_color,
- "obsolete", "color", "Color for \"obsolete\" indicator", "", 0, 0,
- "lightmagenta", "lightmagenta", 0, "", "", "", "", "", "")
- wg_config_option["color_unknown"] = weechat.config_new_option(
- wg_config_file, section_color,
- "unknown", "color", "Color for \"unknown status\" indicator", "", 0, 0,
- "lightred", "lightred", 0, "", "", "", "", "", "")
- wg_config_option["color_language"] = weechat.config_new_option(
- wg_config_file, section_color,
- "language", "color", "Color for language names", "", 0, 0,
- "lightblue", "lightblue", 0, "", "", "", "", "", "")
-
- # section "scripts"
- section_scripts = weechat.config_new_section(
- wg_config_file, "scripts", 0, 0, "", "", "", "", "", "", "", "", "", "")
- if section_scripts == "":
- weechat.config_free(wg_config_file)
- return
- wg_config_option["scripts_url"] = weechat.config_new_option(
- wg_config_file, section_scripts,
- "url", "string", "URL for file with list of plugins", "", 0, 0,
- "http://www.weechat.org/files/plugins.xml.gz",
- "http://www.weechat.org/files/plugins.xml.gz", 0, "", "", "", "", "", "")
- wg_config_option["scripts_dir"] = weechat.config_new_option(
- wg_config_file, section_scripts,
- "dir", "string", "Local cache directory for" + SCRIPT_NAME, "", 0, 0,
- "%h/" + SCRIPT_NAME, "%h/" + SCRIPT_NAME, 0, "", "", "", "", "", "")
- wg_config_option["scripts_cache_expire"] = weechat.config_new_option(
- wg_config_file, section_scripts,
- "cache_expire", "integer", "Local cache expiration time, in minutes "
- "(-1 = never expires, 0 = always expires)", "",
- -1, 60*24*365, "60", "60", 0, "", "", "", "", "", "")
-
-def wg_config_reload_cb(data, config_file):
- """ Reload configuration file. """
- return weechat.config_reload(config_file)
-
-def wg_config_read():
- """ Read configuration file. """
- global wg_config_file
- return weechat.config_read(wg_config_file)
-
-def wg_config_write():
- """ Write configuration file. """
- global wg_config_file
- return weechat.config_write(wg_config_file)
-
-def wg_config_color(color):
- """ Get a color from configuration. """
- global wg_config_option
- option = wg_config_option.get("color_" + color, "")
- if option == "":
- return ""
- return weechat.color(weechat.config_string(option))
-
-def wg_config_get_dir():
- """ Return weeget directory, with expanded WeeChat home dir. """
- global wg_config_option
- return weechat.config_string(
- wg_config_option["scripts_dir"]).replace("%h",
- weechat.info_get("weechat_dir", ""))
-
-def wg_config_create_dir():
- """ Create weeget directory. """
- dir = wg_config_get_dir()
- if not os.path.isdir(dir):
- os.makedirs(dir, mode=0o700)
-
-def wg_config_get_cache_filename():
- """ Get local cache filename, based on URL. """
- global wg_config_option
- return wg_config_get_dir() + os.sep + \
- os.path.basename(weechat.config_string(wg_config_option["scripts_url"]))
-
-# =============================[ download file ]==============================
-
-def wg_download_file(url, filename, timeout, callback, callback_data):
- """Download a file with an URL. Return hook_process created."""
- version = weechat.info_get("version_number", "") or 0
- if int(version) >= 0x00030700:
- return weechat.hook_process_hashtable("url:%s" % url,
- { "file_out": filename },
- timeout,
- callback, callback_data)
- else:
- script = [ "import sys",
- "try:",
- " if sys.version_info >= (3,):",
- " import urllib.request",
- " response = urllib.request.urlopen('%s')" % url,
- " else:",
- " import urllib2",
- " response = urllib2.urlopen(urllib2.Request('%s'))" % url,
- " f = open('%s', 'wb')" % filename,
- " f.write(response.read())",
- " response.close()",
- " f.close()",
- "except Exception as e:",
- " print('error:' + str(e))" ]
- return weechat.hook_process("python -c \"%s\"" % "\n".join(script),
- timeout,
- callback, callback_data)
-
-# ================================[ scripts ]=================================
-
-def wg_search_script_by_name(name):
- """
- Search a script in list by name.
- Name can be short name ('weeget') or full name ('weeget.py').
- """
- global wg_scripts
- for id, script in wg_scripts.items():
- if script["name"] == name or script["full_name"] == name:
- return script
- return None
-
-def wg_get_loaded_scripts():
- """
- Get python dictionary with loaded scripts.
- Keys are filenames and values are path to script, for example:
- 'weeget.py': '/home/xxx/.weechat/python/weeget.py'
- """
- global wg_loaded_scripts
- wg_loaded_scripts = {}
- for language in SCRIPT_EXTENSION.keys():
- infolist = weechat.infolist_get(language + "_script", "", "")
- while weechat.infolist_next(infolist):
- filename = weechat.infolist_string(infolist, "filename")
- if filename != "":
- wg_loaded_scripts[os.path.basename(filename)] = filename
- weechat.infolist_free(infolist)
-
-def wg_is_local_script_loaded(filename):
- """ Check if a script filename (like 'python/weeget.py') is loaded. """
- global wg_loaded_scripts
- filename2 = filename
- if filename2.startswith("autoload/"):
- filename2 = filename2[9:]
- for name, path in wg_loaded_scripts.items():
- if path.endswith(filename) or path.endswith(filename2):
- return True
- return False
-
-def wg_get_local_script_status(script):
- """
- Check if a script is installed.
- 'script' is a dictionary retrieved from scripts xml list.
- """
- global wg_loaded_scripts
- status = { "installed": "", "obsolete": "", "running": "" }
- local_dir = weechat.info_get("weechat_dir", "") + os.sep + script["language"]
- local_name = local_dir + os.sep + "autoload" + os.sep + script["full_name"]
- if not os.path.isfile(local_name):
- local_name = local_dir + os.sep + script["full_name"]
- if os.path.isfile(local_name):
- status["installed"] = "1"
- f = open(local_name, "rb")
- md5 = hashlib.md5()
- md5.update(f.read())
- f.close()
- local_md5 = md5.hexdigest()
- if local_md5 != script["md5sum"]:
- status["obsolete"] = "1"
- if script["full_name"] in wg_loaded_scripts.keys():
- status["running"] = "1"
- return status
-
-def wg_get_local_scripts():
- """
- Get list of all local scripts (in languages and autoload dirs).
- Return a dictionary with language as key and list of paths as value,
- with autoloaded scripts at beginning of list, for example:
- { 'perl': [ 'autoload/buffers.pl',
- 'autoload/weetris.pl',
- 'beep.pl',
- 'launcher.pl' ],
- 'python': [ 'autoload/weeget.py',
- 'go.py',
- 'vdm.py' ]
- }
- """
- files = {}
- for language in SCRIPT_EXTENSION.keys():
- files[language] = []
- autoloaded_files = []
- rootdir = weechat.info_get("weechat_dir", "") + os.sep + language
- for root, dirs, listfiles in os.walk(rootdir):
- if root == rootdir:
- files[language] = listfiles
- elif root == rootdir + os.sep + "autoload":
- autoloaded_files = listfiles
- for file in autoloaded_files:
- if file in files[language]:
- files[language].remove(file)
- files[language].insert(0, "autoload" + os.sep + file)
- return files
-
-def wg_get_local_scripts_status():
- """
- Return list of all local scripts with status (unknown/obsolete/running).
- For example:
- [ 'perl/weetris.pl': { 'unknown': '', 'obsolete': '1', 'running': '' },
- 'python/weeget.py': { 'unknown': '', 'obsolete': '', 'running': '1' }
- ]
- """
- local_scripts_status = []
- local_scripts = wg_get_local_scripts()
- if len(local_scripts) > 0:
- for language, files in local_scripts.items():
- for file in files:
- script_status = { "unknown": "", "obsolete": "", "running": "" }
- name_with_ext = os.path.basename(file)
- script = wg_search_script_by_name(os.path.basename(file))
- if script == None:
- script_status["unknown"] = "1"
- else:
- status = wg_get_local_script_status(script)
- if status["obsolete"]:
- script_status["obsolete"] = "1"
- if wg_is_local_script_loaded(file):
- script_status["running"] = "1"
- local_scripts_status.append((language + os.sep + file,
- script_status))
- return local_scripts_status
-
-def wg_search_scripts(search):
- """ Search word in scripts, return list of matching scripts. """
- global wg_scripts
- if search == "":
- return wg_scripts
- scripts_matching = {}
- for id, script in wg_scripts.items():
- if script["name"].lower().find(search) >= 0 \
- or script["language"].lower().find(search) >= 0 \
- or script["desc_en"].lower().find(search) >= 0 \
- or script["desc_fr"].lower().find(search) >= 0 \
- or script["tags"].lower().find(search) >= 0:
- scripts_matching[id] = script
- return scripts_matching
-
-def wg_list_scripts(search, installed=False):
- """
- List all scripts (with optional search string).
- If installed == True, then list only installed scripts.
- For each script, display status (installed/running/new version available),
- name of script, language and description.
- For example:
- ir buffers pl Sidebar with list of buffers.
- i N go py Quick jump to buffers.
- i weetris pl Tetris-like game.
- """
- global wg_scripts
- search = search.strip().lower()
- scripts_matching = wg_search_scripts(search)
- if len(scripts_matching) == 0:
- weechat.prnt("", "%s: no script found" % SCRIPT_NAME)
- else:
- weechat.prnt("", "")
- if search != "":
- if installed:
- weechat.prnt("", "Scripts installed matching \"%s\":" % search)
- else:
- weechat.prnt("", "Scripts for WeeChat %s matching \"%s\":"
- % (weechat.info_get("version", ""),
- search))
- else:
- if installed:
- weechat.prnt("", "Scripts installed:")
- else:
- weechat.prnt("", "Scripts for WeeChat %s:"
- % weechat.info_get("version", ""))
- sorted_scripts = sorted(scripts_matching.items(),
- key=lambda s: s[1]["name"])
- length_max_name = 0
- for item in sorted_scripts:
- length = len(item[1]["name"])
- if length > length_max_name:
- length_max_name = length
- str_format = "%%s%%s%%s%%s%%s%%s%%s %%s%%-%ds %%s%%-3s %%s%%s" \
- % length_max_name
- for item in sorted_scripts:
- script = item[1]
- str_installed = " "
- str_running = " "
- str_obsolete = " "
- status = wg_get_local_script_status(script)
- if installed and not status["installed"]:
- continue
- if status["installed"]:
- str_installed = "i"
- if status["running"]:
- str_running = "r"
- if status["obsolete"]:
- str_obsolete = "N"
- weechat.prnt("", str_format
- % (wg_config_color("installed"),
- str_installed,
- wg_config_color("running"),
- str_running,
- wg_config_color("obsolete"),
- str_obsolete,
- weechat.color("chat"),
- wg_config_color("script"),
- script["name"],
- wg_config_color("language"),
- SCRIPT_EXTENSION[script["language"]],
- weechat.color("chat"),
- script["desc_en"]))
-
-def wg_show_script(name):
- """
- Show detailed info about a script (in repository).
- For example:
- Script: weeget.py, version 0.7, license: GPL3
- Author: Sebastien Helleu <flashcode [at] flashtux [dot] org>
- Status: installed, running
- Date: added: 2009-04-05, updated: 2009-09-07
- URL: http://www.weechat.org/files/scripts/weeget.py
- MD5: 4b0458dd5cc5c9a09ba8078f89830869
- Desc: Scripts manager.
- Tags: scripts
- Requires: python 2.5
- Min: 0.3.0
- """
- if len(wg_scripts) == 0:
- return
- script = wg_search_script_by_name(name)
- if script == None:
- weechat.prnt("", "%s: script \"%s%s%s\" not found"
- % (SCRIPT_NAME,
- wg_config_color("script"),
- name,
- weechat.color("chat")))
- else:
- weechat.prnt("", "")
- weechat.prnt("", " Script: %s%s%s, version %s, license: %s"
- % (wg_config_color("script"),
- script["full_name"],
- weechat.color("chat"),
- script["version"],
- script["license"]))
- weechat.prnt("", " Author: %s <%s>" % (script["author"], script["mail"]))
- status = wg_get_local_script_status(script)
- str_status = "not installed"
- if status["installed"]:
- str_status = "installed"
- if status["running"]:
- str_status += ", running"
- else:
- str_status += ", not running"
- if status["obsolete"]:
- str_status += " (new version available)"
- weechat.prnt("", " Status: %s" % str_status)
- date_added = script.get("added", "")[:10]
- str_updated = script.get("updated", "")
- if str_updated != "":
- date_updated = script["updated"][:10]
- if date_updated == "0000-00-00" or date_updated == date_added:
- str_updated = ""
- if str_updated != "":
- weechat.prnt("", " Date: added: %s, updated: %s"
- % (date_added, date_updated))
- else:
- weechat.prnt("", " Date: added: %s" % date_added)
- weechat.prnt("", " URL: %s" % script.get("url", ""))
- weechat.prnt("", " MD5: %s" % script.get("md5sum", ""))
- weechat.prnt("", " Desc: %s" % script.get("desc_en", ""))
- weechat.prnt("", " Tags: %s" % script.get("tags", ""))
- str_requires = script.get("requirements", "")
- if str_requires == "":
- str_requires = "(nothing)"
- weechat.prnt("", "Requires: %s" % str_requires)
- vmin = script.get("min_weechat", "")
- vmax = script.get("max_weechat", "")
- if vmin != "":
- weechat.prnt("", " Min: %s" % vmin)
- if vmax != "":
- weechat.prnt("", " Max: %s" % vmax)
-
-def wg_install_next_script():
- """
- Install first script in list wg_scripts_to_install and remove it from
- list.
- """
- global wg_scripts, wg_scripts_to_install, wg_current_script_install
- global wg_hook_process
- if len(wg_scripts) == 0:
- return
- # be sure weeget is ALWAYS last script to install/update
- # otherwise we'll lose end of list when weeget is unloaded by WeeChat
- if SCRIPT_NAME in wg_scripts_to_install:
- wg_scripts_to_install.remove(SCRIPT_NAME)
- wg_scripts_to_install.append(SCRIPT_NAME)
- # loop until a script is installed, or end if list is empty
- while len(wg_scripts_to_install) > 0:
- name = wg_scripts_to_install.pop(0)
- script = wg_search_script_by_name(name)
- if script == None:
- weechat.prnt("", "%s: script \"%s%s%s\" not found"
- % (SCRIPT_NAME,
- wg_config_color("script"),
- name,
- weechat.color("chat")))
- else:
- status = wg_get_local_script_status(script)
- if status["installed"] and not status["obsolete"]:
- weechat.prnt("",
- "%s: script \"%s%s%s\" is already "
- "installed and up to date"
- % (SCRIPT_NAME,
- wg_config_color("script"),
- script["full_name"],
- weechat.color("chat")))
- else:
- weechat.prnt("", "%s: downloading \"%s%s%s\"..."
- % (SCRIPT_NAME,
- wg_config_color("script"),
- script["full_name"],
- weechat.color("chat")))
- if wg_hook_process["script"] != "":
- weechat.unhook(wg_hook_process["script"])
- wg_hook_process["script"] = ""
- wg_current_script_install = script
- filename = wg_config_get_dir() + os.sep + script["full_name"]
- wg_hook_process["script"] = wg_download_file(script["url"], filename, TIMEOUT_SCRIPT,
- "wg_process_script_cb", "")
- # this function will be called again when script will be
- # downloaded
- return
-
-def wg_install_scripts(names):
- """ Install scripts. """
- global wg_scripts_to_install
- for name in names.split(" "):
- wg_scripts_to_install.append(name)
- wg_install_next_script()
-
-def wg_process_script_cb(data, command, rc, stdout, stderr):
- """ Callback when reading a script from website. """
- global wg_hook_process, wg_stdout, wg_current_script_install, wg_loaded_scripts
- if stdout != "":
- wg_stdout["script"] += stdout
- if stderr != "":
- wg_stdout["script"] += stderr
- if int(rc) >= 0:
- if wg_stdout["script"].startswith("error:"):
- weechat.prnt("", "%s%s: error downloading script (%s)"
- % (weechat.prefix("error"), SCRIPT_NAME,
- wg_stdout["update"][6:].strip()))
- else:
- # ask C plugin to install/load script
- weechat.hook_signal_send(wg_current_script_install["language"] + "_script_install",
- weechat.WEECHAT_HOOK_SIGNAL_STRING,
- wg_config_get_dir() + os.sep + wg_current_script_install["full_name"])
- wg_hook_process["script"] = ""
- wg_install_next_script()
- return weechat.WEECHAT_RC_OK
-
-def wg_check_scripts():
- """
- Check status of local script(s).
- For each script found, display status (unknown/running/new version available).
- For example:
- r python/autoload/vdm.py
- ?r python/autoload/dummy.py
- rN python/shell.py
- perl/buffers.pl
- """
- local_scripts_status = wg_get_local_scripts_status()
- if len(local_scripts_status) == 0:
- return
- weechat.prnt("", "")
- weechat.prnt("", "Local scripts:")
- for file, status in local_scripts_status:
- str_unknown = " "
- str_running = " "
- str_obsolete = " "
- if status["unknown"]:
- str_unknown = "?"
- if status["running"]:
- str_running = "r"
- if status["obsolete"]:
- str_obsolete = "N"
- weechat.prnt("", "%s%s%s%s%s%s%s %s%s%s%s"
- % (wg_config_color("unknown"), str_unknown,
- wg_config_color("running"), str_running,
- wg_config_color("obsolete"), str_obsolete,
- weechat.color("chat"),
- os.path.dirname(file),
- os.sep,
- wg_config_color("script"),
- os.path.basename(file)))
-
-def wg_upgrade_scripts():
- """ Upgrade scripts. """
- global wg_scripts, wg_scripts_to_install
- if len(wg_scripts) == 0:
- return
- scripts_to_upgrade = []
- for id, script in wg_scripts.items():
- status = wg_get_local_script_status(script)
- if status["installed"] and status["obsolete"]:
- scripts_to_upgrade.append(script["name"])
- if len(scripts_to_upgrade) == 0:
- weechat.prnt("", "%s: all scripts are up to date" % SCRIPT_NAME)
- else:
- wg_scripts_to_install.extend(scripts_to_upgrade)
- wg_install_next_script()
-
-def wg_remove_scripts(names):
- """ Remove scripts. """
- if len(wg_scripts) == 0:
- return
- list_names = names.split(" ")
- scripts_to_remove = {}
- for language in SCRIPT_EXTENSION.keys():
- scripts_to_remove[language] = []
- for name in list_names:
- script = wg_search_script_by_name(name)
- if script == None:
- weechat.prnt("", "%s: script \"%s%s%s\" not found"
- % (SCRIPT_NAME,
- wg_config_color("script"),
- name,
- weechat.color("chat")))
- else:
- if script["full_name"] not in scripts_to_remove[script["language"]]:
- scripts_to_remove[script["language"]].append(script["full_name"])
- for language in SCRIPT_EXTENSION.keys():
- if len(scripts_to_remove[language]) > 0:
- # ask C plugin to remove script file(s)
- weechat.hook_signal_send(language + "_script_remove",
- weechat.WEECHAT_HOOK_SIGNAL_STRING,
- ",".join(scripts_to_remove[language]))
-
-# ==================================[ xml ]===================================
-
-def wg_execute_action():
- """ Execute action. """
- global wg_action, wg_action_args, wg_loaded_scripts
- if wg_action != "":
- wg_get_loaded_scripts()
- if wg_action == "list":
- wg_list_scripts(wg_action_args)
- elif wg_action == "listinstalled":
- wg_list_scripts(wg_action_args, installed=True)
- elif wg_action == "show":
- wg_show_script(wg_action_args)
- elif wg_action == "install":
- wg_install_scripts(wg_action_args)
- elif wg_action == "check":
- wg_check_scripts()
- elif wg_action == "upgrade":
- wg_upgrade_scripts()
- elif wg_action == "remove":
- wg_remove_scripts(wg_action_args)
- else:
- weechat.prnt("", "%s%s: unknown action \"%s\""
- % (weechat.prefix("error"), SCRIPT_NAME, wg_action))
-
- # reset action
- wg_action = ""
- wg_action_args = ""
- wg_loaded_scripts = {}
-
-def wg_check_version(script):
- """ Check if a script is designed for current running WeeChat version."""
- version = weechat.info_get("version", "")
- version = version.split("-", 1)[0]
- vmin = script.get("min_weechat", "")
- vmax = script.get("max_weechat", "")
- if vmin != "" and version < vmin:
- return False
- if vmax != "" and version > vmax:
- return False
- return True
-
-def wg_parse_xml():
- """
- Parse XML scripts list and return dictionary with list, with key 'id'.
- Example of item return in dictionary :
- '119': { 'name' : 'weeget',
- 'version' : '0.1',
- 'url' : 'http://www.weechat.org/files/scripts/weeget.py',
- 'language' : 'python',
- 'license' : 'GPL3',
- 'md5sum' : 'd500714fc19b0e10cc4e339e70739e4ad500714fc19b0e10cc4e339e70739e4a',
- 'tags' : 'scripts',
- 'desc_en' : 'Scripts manager.',
- 'desc_fr' : 'Gestionnaire de scripts.',
- 'requirements': 'python 2.5',
- 'min_weechat' : '0.3.0',
- 'max_weechat' : '',
- 'author' : 'FlashCode',
- 'mail' : 'flashcode [at] flashtux [dot] org',
- 'added' : '2009-04-05 22:39:18',
- 'updated' : '0000-00-00 00:00:00' }
- """
- global wg_scripts, wg_action, wg_action_args
- wg_scripts = {}
- try:
- f = gzip.open(wg_config_get_cache_filename(), "rb")
- string = f.read()
- f.close()
- except:
- weechat.prnt("", "%s%s: unable to read xml file"
- % (weechat.prefix("error"), SCRIPT_NAME))
- else:
- try:
- dom = xml.dom.minidom.parseString(string)
- except:
- weechat.prnt("",
- "%s%s: unable to parse xml list of scripts"
- % (weechat.prefix("error"), SCRIPT_NAME))
- # discard action
- wg_action = ""
- wg_action_args = ""
- else:
- for scriptNode in dom.getElementsByTagName("plugin"):
- id = scriptNode.getAttribute("id")
- script = {}
- for node in scriptNode.childNodes:
- if node.nodeType == node.ELEMENT_NODE:
- if node.firstChild != None:
- nodename = node.nodeName
- value = node.firstChild.data
- if sys.version_info < (3,):
- # python 2.x: convert unicode to str (in python 3.x, id and text are already strings)
- nodename = nodename.encode("utf-8")
- value = value.encode("utf-8")
- script[nodename] = value
- if script["language"] in SCRIPT_EXTENSION:
- script["full_name"] = script["name"] + "." + SCRIPT_EXTENSION[script["language"]]
- if wg_check_version(script):
- wg_scripts[id] = script
- wg_execute_action()
-
-def wg_process_update_cb(data, command, rc, stdout, stderr):
- """ Callback when reading XML cache file from website. """
- global wg_hook_process, wg_stdout, wg_scripts
- if stdout != "":
- wg_stdout["update"] += stdout
- if stderr != "":
- wg_stdout["update"] += stderr
- if int(rc) >= 0:
- if wg_stdout["update"].startswith("error:"):
- weechat.prnt("", "%s%s: error downloading scripts (%s)"
- % (weechat.prefix("error"), SCRIPT_NAME,
- wg_stdout["update"][6:].strip()))
- else:
- weechat.prnt("", "%s: scripts downloaded" % SCRIPT_NAME)
- wg_parse_xml()
- wg_hook_process["update"] = ""
- return weechat.WEECHAT_RC_OK
-
-def wg_update_cache():
- """ Download list of scripts and update local cache. """
- global wg_config_option, wg_hook_process, wg_stdout
- # get data from website, via hook_process
- if wg_hook_process["update"] != "":
- weechat.unhook(wg_hook_process["update"])
- wg_hook_process["update"] = ""
- weechat.prnt("", "%s: downloading list of scripts..." % SCRIPT_NAME)
- wg_stdout["update"] = ""
- wg_config_create_dir()
- url = weechat.config_string(wg_config_option["scripts_url"])
- filename = wg_config_get_cache_filename()
- wg_hook_process["update"] = wg_download_file(url, filename, TIMEOUT_UPDATE,
- "wg_process_update_cb", "")
-
-def wg_read_scripts(download_list=True):
- """ Read scripts list (download list if needed and asked). """
- global wg_scripts
- cache_file = wg_config_get_cache_filename()
- if os.path.isfile(cache_file):
- # check if local cache file is too old
- cache_expire = weechat.config_integer(wg_config_option["scripts_cache_expire"]) * 60
- if cache_expire >= 0:
- diff_time = time.time() - os.stat(cache_file)[stat.ST_MTIME]
- if download_list and diff_time >= cache_expire:
- os.unlink(cache_file)
- wg_scripts.clear()
- if len(wg_scripts) > 0:
- wg_execute_action()
- else:
- if os.path.isfile(cache_file):
- wg_parse_xml()
- elif download_list:
- wg_update_cache()
-
-# ================================[ command ]=================================
-
-def wg_cmd(data, buffer, args):
- """ Callback for /weeget command. """
- global wg_action, wg_action_args
- if args == "":
- weechat.command("", "/help %s" % SCRIPT_COMMAND)
- return weechat.WEECHAT_RC_OK
- argv = args.strip().split(" ", 1)
- if len(argv) == 0:
- return weechat.WEECHAT_RC_OK
-
- wg_action = ""
- wg_action_args = ""
-
- # check arguments
- if len(argv) < 2:
- if argv[0] == "show" or \
- argv[0] == "install" or \
- argv[0] == "remove":
- weechat.prnt("", "%s: too few arguments for action \"%s\""
- % (SCRIPT_NAME, argv[0]))
- return weechat.WEECHAT_RC_OK
-
- # execute asked action
- if argv[0] == "update":
- wg_update_cache()
- else:
- wg_action = argv[0]
- wg_action_args = ""
- if len(argv) > 1:
- wg_action_args = argv[1]
- wg_read_scripts()
-
- return weechat.WEECHAT_RC_OK
-
-def wg_completion_scripts_cb(data, completion_item, buffer, completion):
- """ Complete with known script names, for command '/weeget'. """
- global wg_scripts
- wg_read_scripts(download_list=False)
- if len(wg_scripts) > 0:
- for id, script in wg_scripts.items():
- weechat.hook_completion_list_add(completion, script["full_name"],
- 0, weechat.WEECHAT_LIST_POS_SORT)
- return weechat.WEECHAT_RC_OK
-
-def wg_completion_scripts_installed_cb(data, completion_item, buffer, completion):
- """ Complete with names of scripts installed, for command '/weeget'. """
- global wg_scripts
- wg_read_scripts(download_list=False)
- if len(wg_scripts) > 0:
- for id, script in wg_scripts.items():
- status = wg_get_local_script_status(script)
- if status["installed"]:
- weechat.hook_completion_list_add(completion, script["full_name"],
- 0, weechat.WEECHAT_LIST_POS_SORT)
- return weechat.WEECHAT_RC_OK
-
-def wg_completion_scripts_tags_cb(data, completion_item, buffer, completion):
- """ Complete with known tags, for command '/weeget'. """
- global wg_scripts
- wg_read_scripts(download_list=False)
- if len(wg_scripts) > 0:
- for id, script in wg_scripts.items():
- if script["tags"]:
- for tag in script["tags"].split(","):
- weechat.hook_completion_list_add(completion, tag,
- 0, weechat.WEECHAT_LIST_POS_SORT)
- return weechat.WEECHAT_RC_OK
-
-# ==================================[ main ]==================================
-
-if __name__ == "__main__" and import_ok:
- if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE,
- SCRIPT_DESC, "wg_unload_script", ""):
- wg_config_init()
- wg_config_read()
- if weechat.config_string(wg_config_option["scripts_url"]).find("weechat.flashtux.org") >= 0:
- weechat.prnt("", "%sWarning: old site still used in URL for plugins.xml.gz, you should do: /unset wg.scripts.url"
- % weechat.prefix("error"))
- str_installed = wg_config_color("installed") + "i" + weechat.color("chat")
- str_unknown = wg_config_color("unknown") + "?" + weechat.color("chat")
- str_running = wg_config_color("running") + "r" + weechat.color("chat")
- str_obsolete = wg_config_color("obsolete") + "N" + weechat.color("chat")
- weechat.hook_command(SCRIPT_COMMAND,
- "WeeChat scripts manager",
- "list|listinstalled [<text>|<tag>] || show <script>"
- " || install|remove <script> [<script>...] || check|update|upgrade",
- " list: list scripts (search text if given)\n"
- "listinstalled: list installed scripts (search text if given)\n"
- " show: show detailed information about a script (in repository)\n"
- " install: install/upgrade script(s)\n"
- " check: check if local scripts needs upgrade\n"
- " update: update local scripts cache\n"
- " upgrade: upgrade all local scripts if they are obsolete\n"
- " remove: remove script(s)\n\n"
- "Indicators in lists (first column):\n"
- " " + str_installed + " script is installed\n"
- " " + str_unknown + " unknown script\n"
- " " + str_running + " script is running (loaded)\n"
- " " + str_obsolete + " script is obsolete (new version available)\n\n"
- "Examples:\n"
- " /" + SCRIPT_COMMAND + " list => list all scripts\n"
- " /" + SCRIPT_COMMAND + " list game => list all scripts with text/tag \"game\"\n"
- " /" + SCRIPT_COMMAND + " install beep.pl => install script beep.pl\n"
- " /" + SCRIPT_COMMAND + " remove beep.pl => remove script beep.pl",
- "list %(weeget_scripts_tags)"
- " || listinstalled %(weeget_scripts_tags)"
- " || show %(weeget_scripts)"
- " || install %(weeget_scripts)|%*"
- " || remove %(weeget_scripts_installed)|%*"
- " || check"
- " || update"
- " || upgrade",
- "wg_cmd", "")
- weechat.hook_completion("weeget_scripts", "list of scripts in repository",
- "wg_completion_scripts_cb", "")
- weechat.hook_completion("weeget_scripts_installed", "list of scripts installed",
- "wg_completion_scripts_installed_cb", "")
- weechat.hook_completion("weeget_scripts_tags", "tags of scripts in repository",
- "wg_completion_scripts_tags_cb", "")
-
-# ==================================[ end ]===================================
-
-def wg_unload_script():
- """ Function called when script is unloaded. """
- wg_config_write()
- return weechat.WEECHAT_RC_OK
View
128 python/buffer_autoclose.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009 by xt <xt@bash.no>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# (this script requires WeeChat 0.3.0 or newer)
+#
+# History:
+# 2009-12-15, xt
+# version 0.3: moved around some control structures to not be as noisy
+# 2009-12-02, xt
+# version 0.2: bugfix, more printing
+# 2009-12-01, xt <xt@bash.no>
+# version 0.1: initial release
+
+import weechat as w
+import time
+
+SCRIPT_NAME = "buffer_autoclose"
+SCRIPT_AUTHOR = "xt <xt@bash.no>"
+SCRIPT_VERSION = "0.3"
+SCRIPT_LICENSE = "GPL3"
+SCRIPT_DESC = "Automatically close inactive private message buffers"
+
+settings = {
+ 'interval': '1', # How often in minutes to check
+ 'age_limit': '30', # How old in minutes before auto close
+ 'ignore': '', # Buffers to ignore (use full name: server.buffer_name)
+}
+
+if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE,
+ SCRIPT_DESC, "", ""):
+ for option, default_value in settings.iteritems():
+ if not w.config_is_set_plugin(option):
+ w.config_set_plugin(option, default_value)
+ w.hook_timer(\
+ int(w.config_get_plugin('interval')) * 1000 * 60,
+ 0,
+ 0,
+ "close_time_cb",
+ '')
+
+
+def get_all_buffers():
+ '''Returns list with pointers of all open buffers.'''
+ buffers = []
+ infolist = w.infolist_get('buffer', '', '')
+ while w.infolist_next(infolist):
+ buffer_type = w.buffer_get_string(w.infolist_pointer(infolist, 'pointer'), 'localvar_type')
+ if buffer_type == 'private': # we only close private message buffers for now
+ buffers.append(w.infolist_pointer(infolist, 'pointer'))
+ w.infolist_free(infolist)
+ return buffers
+
+def get_last_line_date(buffer):
+ date = '1970-01-01 01:00:00'
+ infolist = w.infolist_get('buffer_lines', buffer, '')
+ while w.infolist_prev(infolist):
+ date = w.infolist_time(infolist, 'date')
+ if date != '1970-01-01 01:00:00':
+ # Some lines like "Day changed to" message doesn't have date
+ # set so loop until we find a message that does
+ break
+ w.infolist_free(infolist)
+ return date
+
+def is_in_hotlist(buffer):
+ ''' Returns true if buffer is in hotlist, false if not'''
+
+ hotlist = w.infolist_get('hotlist', '', '')
+ found = False
+ while w.infolist_next(hotlist):
+ thebuffer = w.infolist_pointer(hotlist, 'buffer_pointer')
+ if thebuffer == buffer:
+ found = True
+ name = w.buffer_get_string(thebuffer, 'short_name')
+ break
+
+ w.infolist_free(hotlist)
+ return found
+
+def close_time_cb(buffer, args):
+ ''' Callback for check for inactivity and close '''
+
+ for buffer in get_all_buffers():
+ name = w.buffer_get_string(buffer, 'name')
+
+
+ date = get_last_line_date(buffer)
+ date = time.mktime(time.strptime(date, '%Y-%m-%d %H:%M:%S'))
+ now = time.time()
+ seconds_old = now - date
+ if seconds_old > int(w.config_get_plugin('age_limit'))*60:
+ if is_in_hotlist(buffer):
+ #w.prnt('', '%s: Not closing buffer: %s: it is in hotlist' %(SCRIPT_NAME, name))
+ continue
+ if name in w.config_get_plugin('ignore').split(','):
+ #w.prnt('', '%s: Not closing buffer: %s: it is in ignore list' %(SCRIPT_NAME, name))
+ continue
+ if buffer == w.current_buffer():
+ # Never close current buffer
+ #w.prnt('', '%s: Not closing buffer: %s: it is in currently active' %(SCRIPT_NAME, name))
+ continue
+ if len(w.buffer_get_string(buffer, 'input')):
+ # Don't close buffers with text on input line
+ #w.prnt('', '%s: Not closing buffer: %s: it has input' %(SCRIPT_NAME, name))
+ continue
+
+ w.prnt('', '%s: Closing buffer: %s' %(SCRIPT_NAME, name))
+ w.command(buffer, '/buffer close')
+ #else:
+ # w.prnt('', '%s: Not closing buffer: %s: it is too new: %s' %(SCRIPT_NAME, name, seconds_old))
+
+ return w.WEECHAT_RC_OK
View
21 python/go.py
@@ -23,6 +23,10 @@
# (this script requires WeeChat 0.3.0 or newer)
#
# History:
+# 2012-11-26, Nei <anti.teamidiot.de>
+# version 1.9: add auto_jump option to automatically go to buffer when it is uniquely selected
+# 2012-09-17, Sebastien Helleu <flashcode@flashtux.org>:
+# version 1.8: fix jump to non-active merged buffers (jump with buffer name instead of number)
# 2012-01-03 nils_2 <weechatter@arcor.de>
# version 1.7: add option use_core_instead_weechat (requested by k-man and _rane)
# 2012-01-03, Sebastien Helleu <flashcode@flashtux.org>:
@@ -66,7 +70,7 @@
SCRIPT_NAME = "go"
SCRIPT_AUTHOR = "Sebastien Helleu <flashcode@flashtux.org>"
-SCRIPT_VERSION = "1.7"
+SCRIPT_VERSION = "1.9"
SCRIPT_LICENSE = "GPL3"
SCRIPT_DESC = "Quick jump to buffers"
@@ -82,6 +86,7 @@
"short_name" : "off",
"sort_by_activity" : "off",
"use_core_instead_weechat" : "off",
+ "auto_jump" : "off",
}
# hooks management
@@ -178,11 +183,11 @@ def go_now(buffer, args):
# Prefer buffer that matches at beginning
for index in range(len(buffers)):
if re.search(r"^#?" + re.escape(args), buffers[index]["name"]):
- weechat.command(buffer, "/buffer " + str(buffers[index]["number"]))
+ weechat.command(buffer, "/buffer " + str(buffers[index]["full_name"]))
return None
# Otherwise, just take first buffer in list
if len(buffers) > 0:
- weechat.command(buffer, "/buffer " + str(buffers[0]["number"]))
+ weechat.command(buffer, "/buffer " + str(buffers[0]["full_name"]))
def go_cmd(data, buffer, args):
""" Command "/go": just hook what we need """
@@ -211,14 +216,18 @@ def get_matching_buffers(input):
if weechat.config_get_plugin("use_core_instead_weechat") == "on" and name == "weechat":
name = "core"
number = weechat.infolist_integer(infolist, "number")
+ full_name = weechat.infolist_string(infolist, "full_name")
+ if not full_name:
+ full_name = "%s.%s" % (weechat.infolist_string(infolist, "plugin_name"),
+ weechat.infolist_string(infolist, "name"))
pointer = weechat.infolist_pointer(infolist, "pointer")
matching = name.lower().find(input) >= 0
if not matching and input[-1] == ' ':
matching = name.lower().endswith(input.strip())
if not matching and input.isdigit():
matching = str(number).startswith(input)
if len(input) == 0 or matching:
- list.append({"number": number, "name": name, "pointer": pointer})
+ list.append({"number": number, "name": name, "full_name": full_name, "pointer": pointer})
if len(input) == 0 and pointer == weechat.current_buffer():
buffers_pos = len(list) - 1
weechat.infolist_free(infolist)
@@ -283,6 +292,8 @@ def input_modifier(data, modifier, modifier_data, string):
old_buffers = buffers
buffers = get_matching_buffers(input)
if buffers != old_buffers and len(input) > 0:
+ if len(buffers) == 1 and weechat.config_string_to_boolean(weechat.config_get_plugin('auto_jump')):
+ weechat.command(modifier_data, "/wait 1ms /input return")
buffers_pos = 0
old_input = input
names = buffers_to_string(buffers, buffers_pos, input.strip())
@@ -314,7 +325,7 @@ def command_run_input(data, buffer, command):
# switch to selected buffer (if any)
go_end(buffer)
if len(buffers) > 0:
- weechat.command(buffer, "/buffer " + str(buffers[buffers_pos]["number"]))
+ weechat.command(buffer, "/buffer " + str(buffers[buffers_pos]["full_name"]))
return weechat.WEECHAT_RC_OK_EAT
return weechat.WEECHAT_RC_OK
View
977 python/theme.py
@@ -0,0 +1,977 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2011 Sebastien Helleu <flashcode@flashtux.org>
+#
+# 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/>.
+#
+
+#
+# WeeChat theme manager.
+# (this script requires WeeChat 0.3.5 or newer)
+#
+# History:
+#
+# 2011-09-28, Sebastien Helleu <flashcode@flashtux.org>:
+# version 0.1: dev snapshot
+# 2011-02-22, Sebastien Helleu <flashcode@flashtux.org>:
+# start dev
+#
+
+SCRIPT_NAME = 'theme'
+SCRIPT_AUTHOR = 'Sebastien Helleu <flashcode@flashtux.org>'
+SCRIPT_VERSION = '0.1-dev'
+SCRIPT_LICENSE = 'GPL3'
+SCRIPT_DESC = 'WeeChat theme manager'
+
+SCRIPT_COMMAND = 'theme'
+
+import_weechat_ok = True
+import_other_ok = True
+
+try:
+ import weechat
+except ImportError:
+ import_weechat_ok = False
+
+try:
+ import sys
+ import os
+ import re
+ import datetime
+ import time
+except ImportError as e:
+ print('Missing package(s) for %s: %s' % (SCRIPT_NAME, e))
+ import_other_ok = False
+
+THEME_CONFIG_FILE_NAME = "theme"
+
+COLOR_ATTRIBUTES = ('*', '_', '!')
+
+# config file and options
+theme_config_file = ""
+theme_config_option = {}
+
+theme_bars = 'input|nicklist|status|title'
+theme_plugins = 'weechat|alias|aspell|charset|fifo|irc|logger|relay|rmodifier|xfer'
+
+theme_options_include_re = (
+ r'^weechat\.bar\.(%s)\.color.*' % theme_bars,
+ r'^weechat\.look\.buffer_time_format$',
+ r'^(%s)\.color\..*' % theme_plugins,
+ r'^(%s)\.look\..*color.*' % theme_plugins,
+)
+
+theme_options_exclude_re = (
+ r'^weechat.look.color_pairs_auto_reset$',
+ r'^weechat.look.color_real_white$',
+ r'^weechat.look.color_basic_force_bold$',
+ r'^irc\.look\.',
+)
+
+# =================================[ config ]=================================
+
+def theme_config_init():
+ """Initialization of configuration file. Sections: ???."""
+ global theme_config_file, theme_config_option
+ theme_config_file = weechat.config_new(THEME_CONFIG_FILE_NAME,
+ 'theme_config_reload_cb', '')
+ if not theme_config_file:
+ return
+
+ # section "color"
+ section_color = weechat.config_new_section(
+ theme_config_file, 'color', 0, 0, '', '', '', '', '', '', '', '', '', '')
+ if not section_color:
+ weechat.config_free(theme_config_file)
+ return
+ theme_config_option['color_script'] = weechat.config_new_option(
+ theme_config_file, section_color,
+ 'script', 'color', 'Color for script names', '', 0, 0,
+ 'cyan', 'cyan', 0, '', '', '', '', '', '')
+ theme_config_option['color_installed'] = weechat.config_new_option(
+ theme_config_file, section_color,
+ 'installed', 'color', 'Color for "installed" indicator', '', 0, 0,
+ 'yellow', 'yellow', 0, '', '', '', '', '', '')
+ theme_config_option['color_running'] = weechat.config_new_option(
+ theme_config_file, section_color,
+ 'running', 'color', 'Color for "running" indicator', '', 0, 0,
+ 'lightgreen', 'lightgreen', 0, '', '', '', '', '', '')
+ theme_config_option['color_obsolete'] = weechat.config_new_option(
+ theme_config_file, section_color,
+ 'obsolete', 'color', 'Color for "obsolete" indicator', '', 0, 0,
+ 'lightmagenta', 'lightmagenta', 0, '', '', '', '', '', '')
+ theme_config_option['color_unknown'] = weechat.config_new_option(
+ theme_config_file, section_color,
+ 'unknown', 'color', 'Color for "unknown status" indicator', '', 0, 0,
+ 'lightred', 'lightred', 0, '', '', '', '', '', '')
+ theme_config_option['color_language'] = weechat.config_new_option(
+ theme_config_file, section_color,
+ 'language', 'color', 'Color for language names', '', 0, 0,
+ 'lightblue', 'lightblue', 0, '', '', '', '', '', '')
+
+ # section "themes"
+ section_themes = weechat.config_new_section(
+ theme_config_file, 'themes', 0, 0, '', '', '', '', '', '', '', '', '', '')
+ if not section_themes:
+ weechat.config_free(theme_config_file)
+ return
+ theme_config_option['themes_url'] = weechat.config_new_option(
+ theme_config_file, section_themes,
+ 'url', 'string', 'URL for file with list of themes', '', 0, 0,
+ 'http://www.weechat.org/files/themes.json.gz',
+ 'http://www.weechat.org/files/themes.json.gz', 0, '', '', '', '', '', '')
+ theme_config_option['themes_cache_expire'] = weechat.config_new_option(
+ theme_config_file, section_themes,
+ 'cache_expire', 'integer', 'Local cache expiration time, in minutes '
+ '(-1 = never expires, 0 = always expires)', '',
+ -1, 60*24*365, '60', '60', 0, '', '', '', '', '', '')
+ theme_config_option['themes_dir'] = weechat.config_new_option(
+ theme_config_file, section_themes,
+ 'dir', 'string', 'Local directory for themes', '', 0, 0,
+ '%h/themes', '%h/themes', 0, '', '', '', '', '', '')
+
+def theme_config_reload_cb(data, config_file):
+ """Reload configuration file."""
+ return weechat.config_read(config_file)
+
+def theme_config_read():
+ """Read configuration file."""
+ global theme_config_file
+ return weechat.config_read(theme_config_file)
+
+def theme_config_write():
+ """Write configuration file."""
+ global theme_config_file
+ return weechat.config_write(theme_config_file)
+
+def theme_config_color(color):
+ """Get a color from configuration."""
+ global theme_config_option
+ option = theme_config_option.get('color_%s' % color, '')
+ if not option:
+ return ''
+ return weechat.color(weechat.config_string(option))
+
+def theme_config_get_dir():
+ """Return themes directory, with expanded WeeChat home dir."""
+ global theme_config_option
+ return weechat.config_string(
+ theme_config_option['themes_dir']).replace('%h',
+ weechat.info_get('weechat_dir', ''))
+
+def theme_config_get_backup():
+ """Return name of backup theme (by default "~/.weechat/themes/_backup.theme")."""
+ return '%s/_backup.theme' % theme_config_get_dir()
+
+def theme_config_get_undo():
+ """Return name of undo file (by default "~/.weechat/themes/_undo.theme")."""
+ return '%s/_undo.theme' % theme_config_get_dir()
+
+def theme_config_create_dir():
+ """Create "themes" directory."""
+ directory = theme_config_get_dir()
+ if not os.path.isdir(directory):
+ os.makedirs(directory, mode=0700)
+
+def theme_config_get_cache_filename():
+ """Get local cache filename, based on URL."""
+ global theme_config_option
+ return '%s/%s' % (theme_config_get_dir(),
+ os.path.basename(weechat.config_string(theme_config_option['scripts_url'])))
+
+# =================================[ themes ]=================================
+
+class Theme:
+
+ def __init__(self, filename=None):
+ self.filename = filename
+ self.props = {}
+ self.listprops = []
+ self.options = {}
+ self.theme_ok = True
+ if self.filename:
+ self.theme_ok = self.load(self.filename)
+ else:
+ self.init_weechat()
+ self.nick_prefixes = self._get_nick_prefixes()
+
+ def isok(self):
+ return self.theme_ok
+
+ def _option_is_used(self, option):
+ global theme_options_include_re, theme_options_exclude_re
+ for regex in theme_options_exclude_re:
+ if re.search(regex, option):
+ return False
+ for regex in theme_options_include_re:
+ if re.search(regex, option):
+ return True
+ return False
+
+ def _get_nick_prefixes(self):
+ """Get dict with nick prefixes."""
+ prefixes = {}
+ for prefix in self.options.get('irc.color.nick_prefixes', '').split(';'):
+ values = prefix.split(':', 1)
+ if len(values) == 2:
+ prefixes[values[0]] = values[1]
+ return prefixes
+
+ def _get_attr_color(self, color):
+ """Return tuple with attributes and color."""
+ m = re.match('([*_!]*)(.*)', color)
+ if m:
+ return m.group(1), m.group(2)
+ return '', color
+
+ def _get_color_without_alias(self, color):
+ """Return color without alias (color can be "fg", "fg,bg" or "fg:bg")."""
+ pos = color.find(',')
+ if pos < 0:
+ pos = color.find(':')
+ if pos > 0:
+ fg = color[0:pos]
+ bg = color[pos + 1:]
+ else:
+ fg = color
+ bg = ''
+ attr, col = self._get_attr_color(fg)
+ fg = '%s%s' % (attr, self.palette.get(col, col))
+ attr, col = self._get_attr_color(bg)
+ bg = '%s%s' % (attr, self.palette.get(col, col))
+ if bg:
+ return '%s%s%s' % (fg, color[pos:pos + 1], bg)
+ return fg
+
+ def _replace_color_alias(self, match):
+ value = match.group()[2:-1]
+ if value in self.palette:
+ value = self.palette[value]
+ return '${%s}' % value
+
+ def init_weechat(self):
+ """Initialize theme using current WeeChat options (aliases are replaced with their values from palette)."""
+ # get palette options
+ self.palette = {}
+ infolist = weechat.infolist_get('option', '', 'weechat.palette.*')
+ while weechat.infolist_next(infolist):
+ option_name = weechat.infolist_string(infolist, 'option_name')
+ value = weechat.infolist_string(infolist, 'value')
+ self.palette[value] = option_name
+ weechat.infolist_free(infolist)
+ # get color options (replace aliases by values from palette)
+ self.options = {}
+ infolist = weechat.infolist_get('option', '', '')
+ while weechat.infolist_next(infolist):
+ full_name = weechat.infolist_string(infolist, 'full_name')
+ if self._option_is_used(full_name):
+ value = weechat.infolist_string(infolist, 'value')
+ self.options[full_name] = self._get_color_without_alias(value)
+ weechat.infolist_free(infolist)
+ # replace aliases in chat_nick_colors
+ option = 'weechat.color.chat_nick_colors'
+ colors = []
+ for color in self.options.get(option, '').split(','):
+ colors.append(self._get_color_without_alias(color))
+ if colors:
+ self.options[option] = ','.join(colors)
+ # replace aliases in buffer_time_format
+ option = 'weechat.look.buffer_time_format'
+ if option in self.options:
+ value = re.compile(r'\$\{[^\}]+\}').sub(self._replace_color_alias, self.options[option])
+ if value:
+ self.options[option] = value
+ # build dict with nick prefixes (and replace alisases)
+ prefixes = []
+ option = 'irc.color.nick_prefixes'
+ for prefix in self.options.get(option, '').split(';'):
+ values = prefix.split(':', 1)
+ if len(values) == 2:
+ prefixes.append('%s:%s' % (values[0], self._get_color_without_alias(values[1])))
+ if prefixes:
+ self.options[option] = ';'.join(prefixes)
+ # delete palette
+ del self.palette
+
+ def prnt(self, message):
+ try:
+ weechat.prnt('', message)
+ except:
+ print(message)
+
+ def prnt_error(self, message):
+ try:
+ weechat.prnt('', '%s%s' % (weechat.prefix('error'), message))
+ except:
+ print(message)
+
+ def load(self, filename):
+ self.options = {}
+ try:
+ lines = open(filename, 'rb').readlines()
+ for line in lines:
+ line = str(line.strip().decode('utf-8'))
+ if line.startswith('#'):
+ m = re.match('^# \\$([A-Za-z]+): (.*)', line)
+ if m:
+ self.props[m.group(1)] = m.group(2)
+ self.listprops.append(m.group(1))
+ else:
+ items = line.split('=', 1)
+ if len(items) == 2:
+ value = items[1].strip()
+ if value.startswith('"') and value.endswith('"'):
+ value = value[1:-1]
+ self.options[items[0].strip()] = value
+ return True
+ except:
+ self.prnt('Error loading theme "%s"' % filename)
+ return False
+
+ def save(self, filename):
+ names = self.options.keys()
+ names.sort()
+ try:
+ f = open(filename, 'w')
+ version = weechat.info_get('version', '')
+ pos = version.find('-')
+ if pos > 0:
+ version = version[0:pos]
+ header = ('#',
+ '# -- WeeChat theme --',
+ '# $name: %s' % os.path.basename(filename),
+ '# $date: %s' % datetime.date.today(),
+ '# $weechat: %s' % version,
+ '# $script: %s.py %s' % (SCRIPT_NAME, SCRIPT_VERSION),
+ '#\n')
+ f.write('\n'.join(header))
+ for option in names:
+ f.write('%s = "%s"\n' % (option, self.options[option]))
+ f.close()
+ self.prnt('Theme saved to "%s"' % filename)
+ except:
+ self.prnt_error('Error writing theme to "%s"' % filename)
+ raise
+
+ def show(self, header):
+ """Display content of theme."""
+ names = self.options.keys()
+ names.sort()
+ self.prnt('')
+ self.prnt(header)
+ for name in names:
+ self.prnt(' %s %s= %s%s' % (name, weechat.color('chat_delimiters'),
+ weechat.color('chat_value'), self.options[name]))
+
+ def info(self, header):
+ """Display info about theme."""
+ self.prnt('')
+ self.prnt(header)
+ for prop in self.listprops:
+ self.prnt(' %s: %s%s' % (prop, weechat.color('chat_value'), self.props[prop]))
+ numerrors = 0
+ for name in self.options:
+ if not weechat.config_get(name):
+ numerrors += 1
+ if numerrors == 0:
+ text = 'all OK'
+ else:
+ text = 'WARNING: %d option(s) not found in your WeeChat' % numerrors
+ self.prnt(' options: %s%d%s (%s)' % (weechat.color('chat_value'), len(self.options), weechat.color('reset'), text))
+
+ def install(self):
+ try:
+ numset = 0
+ numerrors = 0
+ for name in self.options:
+ option = weechat.config_get(name)
+ if option:
+ if weechat.config_option_set(option, self.options[name], 1) == weechat.WEECHAT_CONFIG_OPTION_SET_ERROR:
+ self.prnt_error('Error setting option "%s" to value "%s" (running an old WeeChat?)' % (name, self.options[name]))
+ numerrors += 1
+ else:
+ numset += 1
+ else:
+ self.prnt('Warning: option not found: "%s" (running an old WeeChat?)' % name)
+ numerrors += 1
+ errors = ''
+ if numerrors > 0:
+ errors = ', %d error(s)' % numerrors
+ if self.filename:
+ self.prnt('Theme "%s" installed (%d options set%s)' % (self.filename, numset, errors))
+ else:
+ self.prnt('Theme installed (%d options set%s)' % (numset, errors))
+ except:
+ if self.filename:
+ self.prnt_error('Failed to install theme "%s"' % self.filename)
+ else:
+ self.prnt_error('Failed to install theme')
+
+ def nick_prefix_color(self, prefix):
+ """Get color for a nick prefix."""
+ modes = 'qaohv'
+ prefixes = '~&@%+'
+ pos = prefixes.find(prefix)
+ if pos < 0:
+ return ''
+ while pos < len(modes):
+ if modes[pos] in self.nick_prefixes:
+ return self.nick_prefixes[modes[pos]]
+ pos += 1
+ return self.nick_prefixes.get('*', '')
+
+# =============================[ themes / html ]==============================
+
+class HtmlTheme(Theme):
+
+ def __init__(self, filename=None, chat_width=85, chat_height=25, prefix_width=10, nicklist_width=10):
+ Theme.__init__(self, filename)
+ self.chat_width = chat_width
+ self.chat_height = chat_height
+ self.prefix_width = prefix_width
+ self.nicklist_width = nicklist_width
+
+ def html_color(self, index):
+ """Return HTML color with index in table of 256 colors."""
+ terminal_colors = \
+ '000000cd000000cd00cdcd000000cdcd00cd00cdcde5e5e54d4d4dff000000ff00ffff000000ffff00ff00ffffffffff' \
+ '00000000002a0000550000800000aa0000d4002a00002a2a002a55002a80002aaa002ad400550000552a005555005580' \
+ '0055aa0055d400800000802a0080550080800080aa0080d400aa0000aa2a00aa5500aa8000aaaa00aad400d40000d42a' \
+ '00d45500d48000d4aa00d4d42a00002a002a2a00552a00802a00aa2a00d42a2a002a2a2a2a2a552a2a802a2aaa2a2ad4' \
+ '2a55002a552a2a55552a55802a55aa2a55d42a80002a802a2a80552a80802a80aa2a80d42aaa002aaa2a2aaa552aaa80' \
+ '2aaaaa2aaad42ad4002ad42a2ad4552ad4802ad4aa2ad4d455000055002a5500555500805500aa5500d4552a00552a2a' \
+ '552a55552a80552aaa552ad455550055552a5555555555805555aa5555d455800055802a5580555580805580aa5580d4' \
+ '55aa0055aa2a55aa5555aa8055aaaa55aad455d40055d42a55d45555d48055d4aa55d4d480000080002a800055800080' \
+ '8000aa8000d4802a00802a2a802a55802a80802aaa802ad480550080552a8055558055808055aa8055d480800080802a' \
+ '8080558080808080aa8080d480aa0080aa2a80aa5580aa8080aaaa80aad480d40080d42a80d45580d48080d4aa80d4d4' \
+ 'aa0000aa002aaa0055aa0080aa00aaaa00d4aa2a00aa2a2aaa2a55aa2a80aa2aaaaa2ad4aa5500aa552aaa5555aa5580' \
+ 'aa55aaaa55d4aa8000aa802aaa8055aa8080aa80aaaa80d4aaaa00aaaa2aaaaa55aaaa80aaaaaaaaaad4aad400aad42a' \
+ 'aad455aad480aad4aaaad4d4d40000d4002ad40055d40080d400aad400d4d42a00d42a2ad42a55d42a80d42aaad42ad4' \
+ 'd45500d4552ad45555d45580d455aad455d4d48000d4802ad48055d48080d480aad480d4d4aa00d4aa2ad4aa55d4aa80' \
+ 'd4aaaad4aad4d4d400d4d42ad4d455d4d480d4d4aad4d4d40808081212121c1c1c2626263030303a3a3a4444444e4e4e' \
+ '5858586262626c6c6c7676768080808a8a8a9494949e9e9ea8a8a8b2b2b2bcbcbcc6c6c6d0d0d0dadadae4e4e4eeeeee'
+ color = terminal_colors[index*6:(index*6)+6]
+ #if color in ('000000', 'e5e5e5'): # keep black or 'default' (gray)
+ # return color
+ r = int(color[0:2], 16)
+ g = int(color[2:4], 16)
+ b = int(color[4:6], 16)
+ r = min(r * (1.5 - (r / 510.0)), 255)
+ g = min(g * (1.5 - (r / 510.0)), 255)
+ b = min(b * (1.5 - (r / 510.0)), 255)
+ return '%02x%02x%02x' % (r, g, b)
+
+ def html_style(self, fg, bg):
+ """Return HTML style with WeeChat fg and bg colors."""
+ weechat_basic_colors = {
+ 'default': 7, 'black': 0, 'darkgray': 8, 'red': 1, 'lightred': 9,
+ 'green': 2, 'lightgreen': 10, 'brown': 3, 'yellow': 11, 'blue': 4,
+ 'lightblue': 12, 'magenta': 5, 'lightmagenta': 13, 'cyan': 6,
+ 'lightcyan': 14, 'gray': 7, 'white': 15 }
+ delim = max(fg.find(','), fg.find(':'))
+ if delim > 0:
+ bg = fg[delim + 1:]
+ fg = fg[0:delim]
+ bold = ''
+ underline = ''
+ reverse = False
+ while fg[0] in COLOR_ATTRIBUTES:
+ if fg[0] == '*':
+ bold = '; font-weight: bold'
+ elif fg[0] == '_':
+ underline = '; text-decoration: underline'
+