From: Ben Beltran Date: Sat, 20 Oct 2012 18:14:07 +0000 (-0500) Subject: Add weechat, ack, git and nethack X-Git-Url: https://git.r.bdr.sh/rbdr/dotfiles/commitdiff_plain/f853d479d6e699499bee610ea8584b7e09f89cb3?hp=--cc Add weechat, ack, git and nethack --- f853d479d6e699499bee610ea8584b7e09f89cb3 diff --git a/ackrc b/ackrc new file mode 100644 index 0000000..40587f7 --- /dev/null +++ b/ackrc @@ -0,0 +1,13 @@ +--type-add=html=.haml +--type-add=css=.sass,.scss,.less +--type-add=js=.rjs,.coffee +--type-add=ruby=.erb +--ignore-dir=vendor +--ignore-dir=log +--ignore-dir=tmp +--ignore-dir=doc +--ignore-dir=public/system +--sort-files +--color +--follow +--group diff --git a/gitconfig b/gitconfig new file mode 100644 index 0000000..3be84db --- /dev/null +++ b/gitconfig @@ -0,0 +1,7 @@ +[user] + name = Ben Beltran + email = ben@nsovocal.com +[core] + editor = vim +[color] + diff = auto diff --git a/nethackrc b/nethackrc new file mode 100644 index 0000000..2d8fc44 --- /dev/null +++ b/nethackrc @@ -0,0 +1,6 @@ +OPTIONS=color +OPTIONS=catname:Pure +OPTIONS=dogname:Juan +OPTIONS=horsename:Juan +OPTIONS=!DECgraphics +OPTIONS=IBMgraphics diff --git a/vim/.netrwhist b/vim/.netrwhist index ac734e4..6e853d2 100644 --- a/vim/.netrwhist +++ b/vim/.netrwhist @@ -1,4 +1,5 @@ let g:netrw_dirhistmax =10 -let g:netrw_dirhist_cnt =2 +let g:netrw_dirhist_cnt =3 let g:netrw_dirhist_1='/Users/benbeltran/.newsbeuter' let g:netrw_dirhist_2='/Users/benbeltran/.vim' +let g:netrw_dirhist_3='/Users/benbeltran/.dotfiles/tmux-powerline' diff --git a/weechat/alias.conf b/weechat/alias.conf new file mode 100644 index 0000000..81df71a --- /dev/null +++ b/weechat/alias.conf @@ -0,0 +1,37 @@ +# +# alias.conf -- weechat v0.3.8 +# + +[cmd] +AAWAY = "allserv /away" +AME = "allchan /me" +AMSG = "allchan /msg *" +ANICK = "allserv /nick" +BYE = "quit" +C = "buffer clear" +CHAT = "dcc chat" +CL = "buffer clear" +CLOSE = "buffer close" +EXIT = "quit" +IG = "ignore" +J = "join" +K = "kick" +KB = "kickban" +LEAVE = "part" +M = "msg" +MUB = "unban *" +N = "names" +Q = "query" +REDRAW = "window refresh" +SAY = "msg *" +SIGNOFF = "quit" +T = "topic" +UB = "unban" +V = "command core version" +W = "who" +WC = "window merge" +WI = "whois" +WII = "whois $1 $1" +WW = "whowas" + +[completion] diff --git a/weechat/aspell.conf b/weechat/aspell.conf new file mode 100644 index 0000000..e122f1c --- /dev/null +++ b/weechat/aspell.conf @@ -0,0 +1,17 @@ +# +# aspell.conf -- weechat v0.3.8 +# + +[look] +color = lightred + +[check] +commands = "ame,amsg,away,command,cycle,kick,kickban,me,msg,notice,part,query,quit,topic" +default_dict = "" +during_search = off +real_time = off +word_min_length = 2 + +[dict] + +[option] diff --git a/weechat/buffers.conf b/weechat/buffers.conf new file mode 100644 index 0000000..8cb4586 --- /dev/null +++ b/weechat/buffers.conf @@ -0,0 +1,56 @@ +# +# buffers.conf -- weechat v0.3.8 +# + +[color] +current_bg = red +current_fg = lightcyan +default_bg = default +default_fg = default +hotlist_highlight_bg = default +hotlist_highlight_fg = magenta +hotlist_low_bg = default +hotlist_low_fg = white +hotlist_message_bg = default +hotlist_message_fg = yellow +hotlist_private_bg = default +hotlist_private_fg = lightgreen +none_channel_bg = default +none_channel_fg = default +number = lightgreen +number_char = lightgreen +queries_default_bg = default +queries_default_fg = default +queries_highlight_bg = default +queries_highlight_fg = default +queries_message_bg = default +queries_message_fg = default +whitelist_default_bg = default +whitelist_default_fg = default +whitelist_highlight_bg = default +whitelist_highlight_fg = default +whitelist_low_bg = default +whitelist_low_fg = default +whitelist_message_bg = default +whitelist_message_fg = default +whitelist_private_bg = default +whitelist_private_fg = default + +[look] +core_to_front = off +detach = 0 +hide_merged_buffers = none +immune_detach_buffers = "" +indenting = off +indenting_number = on +jump_prev_next_visited_buffer = off +name_crop_suffix = "+" +name_size_max = 0 +number_char = "." +prefix = off +prefix_empty = on +short_names = on +show_lag = off +show_number = on +sort = number +whitelist_buffers = "" diff --git a/weechat/iset.conf b/weechat/iset.conf new file mode 100644 index 0000000..33fb1f1 --- /dev/null +++ b/weechat/iset.conf @@ -0,0 +1,27 @@ +# +# iset.conf -- weechat v0.3.8 +# + +[color] +bg_selected = red +help_default_value = green +help_option_name = white +help_text = default +option = default +option_selected = white +type = brown +type_selected = yellow +value = cyan +value_selected = lightcyan +value_undef = green +value_undef_selected = lightgreen + +[help] +show_help_bar = on +show_help_extra_info = on +show_plugin_description = on + +[look] +scroll_horiz = 10 +show_current_line = on +value_search_char = "=" diff --git a/weechat/logger.conf b/weechat/logger.conf new file mode 100644 index 0000000..dfc8c91 --- /dev/null +++ b/weechat/logger.conf @@ -0,0 +1,24 @@ +# +# logger.conf -- weechat v0.3.8 +# + +[look] +backlog = 20 + +[color] +backlog_end = darkgray +backlog_line = darkgray + +[file] +auto_log = on +flush_delay = 120 +info_lines = off +mask = "$plugin.$name.weechatlog" +name_lower_case = on +path = "%h/logs/" +replacement_char = "_" +time_format = "%Y-%m-%d %H:%M:%S" + +[level] + +[mask] diff --git a/weechat/perl/autoload/beep.pl b/weechat/perl/autoload/beep.pl new file mode 120000 index 0000000..0cc452e --- /dev/null +++ b/weechat/perl/autoload/beep.pl @@ -0,0 +1 @@ +../beep.pl \ No newline at end of file diff --git a/weechat/perl/autoload/buffers.pl b/weechat/perl/autoload/buffers.pl new file mode 120000 index 0000000..445dc3c --- /dev/null +++ b/weechat/perl/autoload/buffers.pl @@ -0,0 +1 @@ +../buffers.pl \ No newline at end of file diff --git a/weechat/perl/autoload/chanmon.pl b/weechat/perl/autoload/chanmon.pl new file mode 120000 index 0000000..0a72383 --- /dev/null +++ b/weechat/perl/autoload/chanmon.pl @@ -0,0 +1 @@ +../chanmon.pl \ No newline at end of file diff --git a/weechat/perl/autoload/iset.pl b/weechat/perl/autoload/iset.pl new file mode 120000 index 0000000..2746e0d --- /dev/null +++ b/weechat/perl/autoload/iset.pl @@ -0,0 +1 @@ +../iset.pl \ No newline at end of file diff --git a/weechat/perl/beep.pl b/weechat/perl/beep.pl new file mode 100644 index 0000000..69096c2 --- /dev/null +++ b/weechat/perl/beep.pl @@ -0,0 +1,257 @@ +# +# Copyright (C) 2006-2012 Sebastien Helleu +# Copyright (C) 2011 Nils Görs +# Copyright (C) 2011 ArZa +# +# 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 . +# +# +# Beep (terminal bell) and/or run command on highlight/private message or new DCC. +# +# History: +# 2012-06-05, ldvx: +# version 1.1: Added wildcard support for whitelist_nicks. +# 2012-05-09, ldvx : +# version 1.0: Added beep_pv_blacklist, beep_highlight_blacklist, blacklist_nicks, +# and wildcard support for blacklist_nicks. +# 2012-05-02, ldvx : +# version 0.9: fix regex for nick in tags, add options "whitelist_channels" +# and "bell_always" +# 2012-04-19, ldvx : +# version 0.8: add whitelist, trigger, use hook_process for commands, +# rename option "beep_command" to "beep_command_pv", add help for options +# 2011-04-16, ArZa : +# version 0.7: fix default beep command +# 2011-03-11, nils_2 : +# version 0.6: add additional command options for dcc and highlight +# 2011-03-09, nils_2 : +# version 0.5: add option for beep command and dcc +# 2009-05-02, Sebastien Helleu : +# version 0.4: sync with last API changes +# 2008-11-05, Sebastien Helleu : +# version 0.3: conversion to WeeChat 0.3.0+ +# 2007-08-10, Sebastien Helleu : +# version 0.2: upgraded licence to GPL 3 +# 2006-09-02, Sebastien Helleu : +# version 0.1: initial release + +use strict; +my $SCRIPT_NAME = "beep"; +my $VERSION = "1.1"; + +# default values in setup file (~/.weechat/plugins.conf) +my %options_default = ('beep_pv' => ['on', 'beep on private message'], + 'beep_pv_whitelist' => ['off', 'turn whitelist for private messages on or off'], + 'beep_pv_blacklist' => ['off', 'turn blacklist for private messages on or off'], + 'beep_highlight' => ['on', 'beep on highlight'], + 'beep_highlight_whitelist' => ['off', 'turn whitelist for highlights on or off'], + 'beep_highlight_blacklist' => ['off', 'turn blacklist for highlights on or off'], + 'beep_dcc' => ['on', 'beep on dcc'], + 'beep_trigger_pv' => ['', 'word that will trigger execution of beep_command_pv (it empty, anything will trigger)'], + 'beep_trigger_highlight' => ['', 'word that will trigger execution of beep_command_highlight (if empty, anything will trigger)'], + 'beep_command_pv' => ['$bell', 'command for beep on private message, special value "$bell" is allowed, as well as "$bell;command"'], + 'beep_command_highlight' => ['$bell', 'command for beep on highlight, special value "$bell" is allowed, as well as "$bell;command"'], + 'beep_command_dcc' => ['$bell', 'command for beep on dcc, special value "$bell" is allowed, as well as "$bell;command"'], + 'beep_command_timeout' => ['30000', 'timeout for command run (in milliseconds, 0 = never kill (not recommended))'], + 'whitelist_nicks' => ['', 'comma-separated list of "server.nick": if not empty, only these nicks will trigger execution of commands (example: "freenode.nick1,freenode.nick2")'], + 'blacklist_nicks' => ['', 'comma-separated list of "server.nick": if not empty, these nicks will not be able to trigger execution of commands. Cannot be used in conjuction with whitelist (example: "freenode.nick1,freenode.nick2")'], + 'whitelist_channels' => ['', 'comma-separated list of "server.#channel": if not empty, only these channels will trigger execution of commands (example: "freenode.#weechat,freenode.#channel2")'], + 'bell_always' => ['', 'use $bell on private messages and/or highlights regardless of trigger and whitelist settings (example: "pv,highlight")'], +); +my %options = (); + +weechat::register($SCRIPT_NAME, "FlashCode ", $VERSION, + "GPL3", "Beep (terminal bell) and/or run command on highlight/private message or new DCC", "", ""); +init_config(); + +weechat::hook_config("plugins.var.perl.$SCRIPT_NAME.*", "toggle_config_by_set", ""); +weechat::hook_print("", "", "", 1, "pv_and_highlight", ""); +weechat::hook_signal("irc_dcc", "dcc", ""); + +sub pv_and_highlight +{ + my ($data, $buffer, $date, $tags, $displayed, $highlight, $prefix, $message) = @_; + + # return if message is filtered + return weechat::WEECHAT_RC_OK if ($displayed != 1); + + # return if nick in message is own nick + my $nick = ""; + $nick = $2 if ($tags =~ m/(^|,)nick_([^,]*)(,|$)/); + return weechat::WEECHAT_RC_OK if (weechat::buffer_get_string($buffer, "localvar_nick") eq $nick); + + # highlight + if ($highlight) + { + # Always print visual bel, regardless of whitelist and trigger settings + # beep_command_highlight does not need to contain $bell + if ($options{bell_always} =~ m/(^|,)highlight(,|$)/) + { + print STDERR "\a"; + } + # Channels whitelist for highlights + if ($options{beep_highlight} eq "on") + { + if ($options{whitelist_channels} ne "") + { + my $serverandchannel = weechat::buffer_get_string($buffer, "localvar_server"). "." . + weechat::buffer_get_string($buffer, "localvar_channel"); + if ($options{beep_trigger_highlight} eq "" or $message =~ m/\b$options{beep_trigger_highlight}\b/) + { + if ($options{whitelist_channels} =~ /(^|,)$serverandchannel(,|$)/) + { + beep_exec_command($options{beep_command_highlight}); + } + # What if we are highlighted and we're in a PM? For now, do nothing. + } + } + else + { + # Execute $bell and/or command with trigger and whitelist/blacklist settings + beep_trigger_whitelist_blacklist($buffer, $message, $nick, $options{beep_trigger_highlight}, + $options{beep_highlight_whitelist}, $options{beep_highlight_blacklist}, + $options{beep_command_highlight}); + } + } + } + # private message + elsif (weechat::buffer_get_string($buffer, "localvar_type") eq "private" and $tags =~ m/(^|,)notify_private(,|$)/) + { + # Always print visual bel, regardless of whitelist and trigger settings + # beep_command_pv does not need to contain $bell + if ($options{bell_always} =~ m/(^|,)pv(,|$)/) + { + print STDERR "\a"; + } + # Execute $bell and/or command with trigger and whitelist/blacklist settings + if ($options{beep_pv} eq "on") + { + beep_trigger_whitelist_blacklist($buffer, $message, $nick, $options{beep_trigger_pv}, + $options{beep_pv_whitelist}, $options{beep_pv_blacklist}, + $options{beep_command_pv}); + } + } + return weechat::WEECHAT_RC_OK; +} + +sub dcc +{ + beep_exec_command($options{beep_command_dcc}) if ($options{beep_dcc} eq "on"); + return weechat::WEECHAT_RC_OK; +} + +sub beep_trigger_whitelist_blacklist +{ + my ($buffer, $message, $nick, $trigger, $whitelist, $blacklist, $command) = @_; + + if ($trigger eq "" or $message =~ m/\b$trigger\b/) + { + my $serverandnick = weechat::buffer_get_string($buffer, "localvar_server").".".$nick; + if ($whitelist eq "on" and $options{whitelist_nicks} ne "") + { + # What to do if there's a wildcard in the whitelit + if ($options{whitelist_nicks} =~ m/\*/ and + match_in_wild_card($serverandnick, $options{whitelist_nicks})) + { + beep_exec_command($command); + } + # What to do if there's no wildcard in the whitelist + elsif ($options{whitelist_nicks} =~ /(^|,)$serverandnick(,|$)/) + { + beep_exec_command($command); + } + } + elsif ($blacklist eq "on" and $options{blacklist_nicks} ne "") + { + # What to do if there's a wildcard in the blacklist + if ($options{blacklist_nicks} =~ m/\*/ and + !match_in_wild_card($serverandnick, $options{blacklist_nicks})) + { + beep_exec_command($command); + } + # What to do if there's no wildcard in the blacklist + elsif ($options{blacklist_nicks} !~ /(^|,)$serverandnick(,|$)/) + { + beep_exec_command($command); + } + } + # What to do if we are not using whitelist of blacklist feature + elsif ($whitelist eq "off" and $blacklist eq "off") + { + beep_exec_command($command); + } + } +} + +sub beep_exec_command +{ + my $command = $_[0]; + if ($command =~ /^\$bell/) + { + print STDERR "\a"; + ($command) = $command =~ /^\$bell;(.+)$/; + } + weechat::hook_process($command, $options{beep_command_timeout}, "my_process", "") if ($command); +} + +sub match_in_wild_card +{ + my ($serverandnick, $white_or_black) = @_; + my $nick_iter; + my @array_of_nicks = split(",", $white_or_black); + + foreach $nick_iter (@array_of_nicks) + { + $nick_iter =~ s/\*/[^,]*/g; + if ($serverandnick =~ /$nick_iter/) + { + return 1; + } + } + return 0; +} + +sub my_process +{ + return weechat::WEECHAT_RC_OK; +} + +sub toggle_config_by_set +{ + my ($pointer, $name, $value) = @_; + $name = substr($name, length("plugins.var.perl.".$SCRIPT_NAME."."), length($name)); + $options{$name} = $value; + return weechat::WEECHAT_RC_OK; +} + +sub init_config +{ + my $version = weechat::info_get("version_number", "") || 0; + foreach my $option (keys %options_default) + { + if (!weechat::config_is_set_plugin($option)) + { + weechat::config_set_plugin($option, $options_default{$option}[0]); + $options{$option} = $options_default{$option}[0]; + } + else + { + $options{$option} = weechat::config_get_plugin($option); + } + if ($version >= 0x00030500) + { + weechat::config_set_desc_plugin($option, $options_default{$option}[1]." (default: \"".$options_default{$option}[0]."\")"); + } + } +} diff --git a/weechat/perl/buffers.pl b/weechat/perl/buffers.pl new file mode 100644 index 0000000..36cab01 --- /dev/null +++ b/weechat/perl/buffers.pl @@ -0,0 +1,998 @@ +# +# Copyright (C) 2008-2012 Sebastien Helleu +# Copyright (C) 2011-2012 Nils G +# +# 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 . +# +# +# Display sidebar with list of buffers. +# +# History: +# +# 2012-06-02, nils_2 : +# v3.5: add values "server|channel|private|all|keepserver|none" to option "hide_merged_buffers" (suggested by dominikh). +# 2012-05-25, nils_2 : +# v3.4: add new option "show_lag". +# 2012-04-07, Sebastien Helleu : +# v3.3: fix truncation of wide chars in buffer name (option name_size_max) (bug #36034) +# 2012-03-15, nils_2 : +# v3.2: add new option "detach"(weechat >= 0.3.8) +# add new option "immune_detach_buffers" (requested by Mkaysi) +# add new function buffers_whitelist add|del|reset (suggested by FiXato) +# add new function buffers_detach add|del|reset +# 2012-03-09, Sebastien Helleu : +# v3.1: fix reload of config file +# 2012-01-29, nils_2 : +# v3.0: fix: buffers did not update directly during window_switch (reported by FiXato) +# 2012-01-29, nils_2 : +# v2.9: add options "name_size_max" and "name_crop_suffix" +# 2012-01-08, nils_2 : +# v2.8: fix indenting for option "show_number off" +# fix unset of buffer activity in hotlist when buffer was moved with mouse +# add buffer with free content and core buffer sorted first (suggested by nyuszika7h) +# add options queries_default_fg/bg and queries_message_fg/bg (suggested by FiXato) +# add clicking with left button on current buffer will do a jump_previously_visited_buffer (suggested by FiXato) +# add clicking with right button on current buffer will do a jump_next_visited_buffer +# add additional informations in help texts +# add default_fg and default_bg for whitelist channels +# internal changes (script is now 3Kb smaller) +# 2012-01-04, Sebastien Helleu : +# v2.7: fix regex lookup in whitelist buffers list +# 2011-12-04, nils_2 : +# v2.6: add own config file (buffers.conf) +# add new behavior for indenting (under_name) +# add new option to set different color for server buffers and buffers with free content +# 2011-10-30, nils_2 : +# v2.5: add new options "show_number_char" and "color_number_char", +# add help-description for options +# 2011-08-24, Sebastien Helleu : +# v2.4: add mouse support +# 2011-06-06, nils_2 : +# v2.3: added: missed option "color_whitelist_default" +# 2011-03-23, Sebastien Helleu : +# v2.2: fix color of nick prefix with WeeChat >= 0.3.5 +# 2011-02-13, nils_2 : +# v2.1: add options "color_whitelist_*" +# 2010-10-05, Sebastien Helleu : +# v2.0: add options "sort" and "show_number" +# 2010-04-12, Sebastien Helleu : +# v1.9: replace call to log() by length() to align buffer numbers +# 2010-04-02, Sebastien Helleu : +# v1.8: fix bug with background color and option indenting_number +# 2010-04-02, Helios : +# v1.7: add indenting_number option +# 2010-02-25, m4v : +# v1.6: add option to hide empty prefixes +# 2010-02-12, Sebastien Helleu : +# v1.5: add optional nick prefix for buffers like IRC channels +# 2009-09-30, Sebastien Helleu : +# v1.4: remove spaces for indenting when bar position is top/bottom +# 2009-06-14, Sebastien Helleu : +# v1.3: add option "hide_merged_buffers" +# 2009-06-14, Sebastien Helleu : +# v1.2: improve display with merged buffers +# 2009-05-02, Sebastien Helleu : +# v1.1: sync with last API changes +# 2009-02-21, Sebastien Helleu : +# v1.0: remove timer used to update bar item first time (not needed any more) +# 2009-02-17, Sebastien Helleu : +# v0.9: fix bug with indenting of private buffers +# 2009-01-04, Sebastien Helleu : +# v0.8: update syntax for command /set (comments) +# 2008-10-20, Jiri Golembiovsky : +# v0.7: add indenting option +# 2008-10-01, Sebastien Helleu : +# v0.6: add default color for buffers, and color for current active buffer +# 2008-09-18, Sebastien Helleu : +# v0.5: fix color for "low" level entry in hotlist +# 2008-09-18, Sebastien Helleu : +# v0.4: rename option "show_category" to "short_names", +# remove option "color_slash" +# 2008-09-15, Sebastien Helleu : +# v0.3: fix bug with priority in hotlist (var not defined) +# 2008-09-02, Sebastien Helleu : +# v0.2: add color for buffers with activity and config options for +# colors, add config option to display/hide categories +# 2008-03-15, Sebastien Helleu : +# v0.1: script creation +# +# Help about settings: +# display all settings for script (or use iset.pl script to change settings): +# /set buffers* +# show help text for option buffers.look.whitelist_buffers: +# /help buffers.look.whitelist_buffers +# +# Mouse-support (standard key bindings): +# left mouse-button: +# - click on a buffer to switch to selected buffer +# - click on current buffer will do action jump_previously_visited_buffer +# - drag a buffer and drop it on another position will move the buffer to position +# right mouse-button: +# - click on current buffer will do action jump_next_visited_buffer +# - moving buffer to the left/right will close buffer. +# + +use strict; +use Encode qw( decode encode ); +# -------------------------------[ internal ]------------------------------------- +my $version = "3.5"; + +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 +my %options; +my %hotlist_level = (0 => "low", 1 => "message", 2 => "private", 3 => "highlight"); +my @whitelist_buffers = (); +my @immune_detach_buffers= (); +my @buffers_focus = (); +my %buffers_timer = (); +my %Hooks = (); + +# --------------------------------[ init ]-------------------------------------- +weechat::register("buffers", "Sebastien Helleu ", $version, + "GPL3", "Sidebar with list of buffers", "", ""); +my $weechat_version = weechat::info_get("version_number", "") || 0; + +buffers_config_init(); +buffers_config_read(); + +weechat::bar_item_new("buffers", "build_buffers", ""); +weechat::bar_new("buffers", "0", "0", "root", "", "left", "horizontal", + "vertical", "0", "0", "default", "default", "default", "1", + "buffers"); +weechat::hook_signal("buffer_*", "buffers_signal_buffer", ""); +weechat::hook_signal("window_switch", "buffers_signal_buffer", ""); +weechat::hook_signal("hotlist_*", "buffers_signal_hotlist", ""); +weechat::bar_item_update("buffers"); +if ($weechat_version >= 0x00030600) +{ + weechat::hook_focus("buffers", "buffers_focus_buffers", ""); + weechat::hook_hsignal("buffers_mouse", "buffers_hsignal_mouse", ""); + weechat::key_bind("mouse", \%mouse_keys); +} + +weechat::hook_command( $cmd_buffers_whitelist, + "add/del current buffer to/from buffers whitelist", + "[add] || [del] || [reset]", + + " add: add current buffer in configuration file\n". + " del: delete current buffer from configuration file\n". + "reset: reset all buffers from configuration file (no confirmation!)\n\n". + "Examples:\n". + "/$cmd_buffers_whitelist add\n", + "add %-||". + "del %-||". + "reset %-", + "buffers_cmd_whitelist", ""); + +weechat::hook_command( $cmd_buffers_detach, + "add/del current buffer to/from buffers detach", + "[add] || [del] || [reset]", + + " add: add current buffer in configuration file\n". + " del: delete current buffer from configuration file\n". + "reset: reset all buffers from configuration file (no confirmation!)\n\n". + "Examples:\n". + "/$cmd_buffers_detach add\n", + "add %-||". + "del %-||". + "reset %-", + "buffers_cmd_detach", ""); + +if ($weechat_version >= 0x00030800) +{ + weechat::hook_config("buffers.look.detach", "hook_timer_detach", ""); +} + + weechat::hook_config("buffers.look.show_lag", "hook_timer_lag", ""); + +# -------------------------------- [ command ] -------------------------------- +sub buffers_cmd_whitelist +{ +my ( $data, $buffer, $args ) = @_; + $args = lc($args); + my $buffers_whitelist = weechat::config_string( weechat::config_get("buffers.look.whitelist_buffers") ); + return weechat::WEECHAT_RC_OK if ( $buffers_whitelist eq "" and $args eq "del" or $buffers_whitelist eq "" and $args eq "reset" ); + my @buffers_list = split( /,/, $buffers_whitelist ); + # get buffers name + my $infolist = weechat::infolist_get("buffer", weechat::current_buffer(), ""); + weechat::infolist_next($infolist); + my $buffers_name = weechat::infolist_string($infolist, "name"); + weechat::infolist_free($infolist); + return weechat::WEECHAT_RC_OK if ( $buffers_name eq "" ); # should never happen + + if ( $args eq "add" ) + { + return weechat::WEECHAT_RC_OK if ( grep /^$buffers_name$/, @buffers_list ); # check if buffer already in list + push @buffers_list,( $buffers_name ); + my $buffers_list = &create_whitelist(\@buffers_list); + weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), $buffers_list,1 ); + weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" added to buffers whitelist"); + } + elsif ( $args eq "del" ) + { + return weechat::WEECHAT_RC_OK unless ( grep /^$buffers_name$/, @buffers_list ); # check if buffer is in list + @buffers_list = grep {$_ ne $buffers_name} @buffers_list; # delete entry + my $buffers_list = &create_whitelist(\@buffers_list); + weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), $buffers_list,1 ); + weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" deleted from buffers whitelist"); + } + elsif ( $args eq "reset" ) + { + return weechat::WEECHAT_RC_OK if ( $buffers_whitelist eq "" ); + weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), "",1 ); + weechat::print(weechat::current_buffer(), "buffers whitelist is empty, now..."); + } + return weechat::WEECHAT_RC_OK; +} +sub buffers_cmd_detach +{ +my ( $data, $buffer, $args ) = @_; + $args = lc($args); + my $immune_detach_buffers = weechat::config_string( weechat::config_get("buffers.look.immune_detach_buffers") ); + return weechat::WEECHAT_RC_OK if ( $immune_detach_buffers eq "" and $args eq "del" or $immune_detach_buffers eq "" and $args eq "reset" ); + my @buffers_list = split( /,/, $immune_detach_buffers ); + # get buffers name + my $infolist = weechat::infolist_get("buffer", weechat::current_buffer(), ""); + weechat::infolist_next($infolist); + my $buffers_name = weechat::infolist_string($infolist, "name"); + weechat::infolist_free($infolist); + return weechat::WEECHAT_RC_OK if ( $buffers_name eq "" ); # should never happen + + if ( $args eq "add" ) + { + return weechat::WEECHAT_RC_OK if ( grep /^$buffers_name$/, @buffers_list ); # check if buffer already in list + push @buffers_list,( $buffers_name ); + my $buffers_list = &create_whitelist(\@buffers_list); + weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), $buffers_list,1 ); + weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" added to immune detach buffers"); + } + elsif ( $args eq "del" ) + { + return weechat::WEECHAT_RC_OK unless ( grep /^$buffers_name$/, @buffers_list ); # check if buffer is in list + @buffers_list = grep {$_ ne $buffers_name} @buffers_list; # delete entry + my $buffers_list = &create_whitelist(\@buffers_list); + weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), $buffers_list,1 ); + weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" deleted from immune detach buffers"); + } + elsif ( $args eq "reset" ) + { + return weechat::WEECHAT_RC_OK if ( $immune_detach_buffers eq "" ); + weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), "",1 ); + weechat::print(weechat::current_buffer(), "immune detach buffers is empty, now..."); + } + return weechat::WEECHAT_RC_OK; +} +sub create_whitelist +{ + my @buffers_list = @{$_[0]}; + my $buffers_list = ""; + foreach (@buffers_list) + { + $buffers_list .= $_ .","; + } + chop $buffers_list; # remove last "," + return $buffers_list; +} + +# -------------------------------- [ config ] -------------------------------- +sub hook_timer_detach +{ + my $detach = $_[2]; + if ( $detach eq 0 ) + { + weechat::unhook($Hooks{timer_detach}) if $Hooks{timer_detach}; + $Hooks{timer_detach} = ""; + } + else + { + weechat::unhook($Hooks{timer_detach}) if $Hooks{timer_detach}; + $Hooks{timer_detach} = weechat::hook_timer( weechat::config_integer( $options{"detach"}) * 1000, 60, 0, "buffers_signal_buffer", ""); + } + weechat::bar_item_update("buffers"); + return weechat::WEECHAT_RC_OK; +} + +sub hook_timer_lag +{ + my $lag = $_[2]; + if ( $lag eq 0 ) + { + weechat::unhook($Hooks{timer_lag}) if $Hooks{timer_lag}; + $Hooks{timer_lag} = ""; + } + else + { + weechat::unhook($Hooks{timer_lag}) if $Hooks{timer_lag}; + $Hooks{timer_lag} = weechat::hook_timer( weechat::config_integer(weechat::config_get("irc.network.lag_refresh_interval")) * 1000, 0, 0, "buffers_signal_hotlist", ""); + } + weechat::bar_item_update("buffers"); + return weechat::WEECHAT_RC_OK; +} + +sub buffers_config_read +{ + return weechat::config_read($buffers_config_file) if ($buffers_config_file ne ""); +} +sub buffers_config_write +{ + return weechat::config_write($buffers_config_file) if ($buffers_config_file ne ""); +} +sub buffers_config_reload_cb +{ + my ($data,$config_file) = ($_[0], $_[1]); + return weechat::config_reload($config_file) +} +sub buffers_config_init +{ + $buffers_config_file = weechat::config_new($BUFFERS_CONFIG_FILE_NAME,"buffers_config_reload_cb",""); + return if ($buffers_config_file eq ""); + +my %default_options_color = +("color_current_fg" => ["current_fg", "color", "foreground color for current buffer", "", 0, 0,"lightcyan", "lightcyan", 0, "", "","buffers_signal_config", "", "", ""], + "color_current_bg" => ["current_bg", "color", "background color for current buffer", "", 0, 0,"red", "red", 0, "", "","buffers_signal_config", "", "", ""], + "color_default_fg" => ["default_fg", "color", "default foreground color for buffer name", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "color_default_bg" => ["default_bg", "color", "default background color for buffer name", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "color_hotlist_highlight_fg" => ["hotlist_highlight_fg", "color", "change foreground color of buffer name if a highlight messaged received","", 0, 0,"magenta", "magenta", 0, "", "","buffers_signal_config", "", "", ""], + "color_hotlist_highlight_bg" => ["hotlist_highlight_bg", "color", "change background color of buffer name if a highlight messaged received", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "color_hotlist_low_fg" => ["hotlist_low_fg", "color", "change foreground color of buffer name if a low message received", "", 0, 0,"white", "white", 0, "", "","buffers_signal_config", "", "", ""], + "color_hotlist_low_bg" => ["hotlist_low_bg", "color", "change background color of buffer name if a low message received", "", 0, 0, + "default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "color_hotlist_message_fg" => ["hotlist_message_fg", "color", "change foreground color of buffer name if a normal message received", "", 0, 0,"yellow", "yellow", 0, "", "","buffers_signal_config", "", "", ""], + "color_hotlist_message_bg" => ["hotlist_message_bg", "color", "change background color of buffer name if a normal message received", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "color_hotlist_private_fg" => ["hotlist_private_fg", "color", "change foreground color of buffer name if a private message received", "", 0, 0,"lightgreen", "lightgreen", 0, "", "","buffers_signal_config", "", "", ""], + "color_hotlist_private_bg" => ["hotlist_private_bg", "color", "change background color of buffer name if a private message received", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "color_number" => ["number", "color", "color for buffer number", "", 0, 0,"lightgreen", "lightgreen", 0, "", "","buffers_signal_config", "", "", ""], + "color_number_char" => ["number_char", "color", "color for buffer number char", "", 0, 0,"lightgreen", "lightgreen", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_default_fg" => ["whitelist_default_fg", "color", "default foreground color for whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_default_bg" => ["whitelist_default_bg", "color", "default background color for whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_low_fg" => ["whitelist_low_fg", "color", "low color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_low_bg" => ["whitelist_low_bg", "color", "low color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_message_fg" => ["whitelist_message_fg", "color", "message color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_message_bg" => ["whitelist_message_bg", "color", "message color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_private_fg" => ["whitelist_private_fg", "color", "private color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_private_bg" => ["whitelist_private_bg", "color", "private color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_highlight_fg" => ["whitelist_highlight_fg", "color", "highlight color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_whitelist_highlight_bg" => ["whitelist_highlight_bg", "color", "highlight color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""], + "color_none_channel_fg" => ["none_channel_fg", "color", "foreground color for none channel buffer (e.g.: core/server/plugin buffer)", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "color_none_channel_bg" => ["none_channel_bg", "color", "background color for none channel buffer (e.g.: core/server/plugin buffer)", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "queries_default_fg" => ["queries_default_fg", "color", "foreground color for query buffer without message", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "queries_default_bg" => ["queries_default_bg", "color", "background color for query buffer without message", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "queries_message_fg" => ["queries_message_fg", "color", "foreground color for query buffer with unread message", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "queries_message_bg" => ["queries_message_bg", "color", "background color for query buffer with unread message", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "queries_highlight_fg" => ["queries_highlight_fg", "color", "foreground color for query buffer with unread highlight", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], + "queries_highlight_bg" => ["queries_highlight_bg", "color", "background color for query buffer with unread highlight", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""], +); + +my %default_options_look = +( + "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", "", "", ""], + "indenting" => ["indenting", "integer", "use indenting for channel and query buffers. This option only takes effect if bar is left/right positioned", "off|on|under_name", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""], + "indenting_number" => ["indenting_number", "boolean", "use indenting for numbers. This option only takes effect if bar is left/right positioned", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""], + "short_names" => ["short_names", "boolean", "display short names (remove text before first \".\" in buffer name)", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""], + "show_number" => ["show_number", "boolean", "display channel number in front of buffername", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""], + "show_number_char" => ["number_char", "string", "display a char after channel number", "", 0, 0,".", ".", 0, "", "", "buffers_signal_config", "", "", ""], + "show_prefix" => ["prefix", "boolean", "show your prefix for channel", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""], + "show_prefix_empty" => ["prefix_empty", "boolean", "use a placeholder for channels without prefix", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""], + "sort" => ["sort", "integer", "sort buffer-list by \"number\" or \"name\"", "number|name", 0, 0,"number", "number", 0, "", "", "buffers_signal_config", "", "", ""], + "core_to_front" => ["core_to_front", "boolean", "core buffer and buffers with free content will be listed first. Take only effect if buffer sort is by name", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""], + "jump_prev_next_visited_buffer" => ["jump_prev_next_visited_buffer", "boolean", "jump to previously or next visited buffer if you click with left/right mouse button on currently visiting buffer", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""], + "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", "", "", ""], +); + # section "color" + my $section_color = weechat::config_new_section($buffers_config_file,"color", 0, 0, "", "", "", "", "", "", "", "", "", ""); + if ($section_color eq "") + { + weechat::config_free($buffers_config_file); + return; + } + foreach my $option (keys %default_options_color) + { + $options{$option} = weechat::config_new_option($buffers_config_file, $section_color, + $default_options_color{$option}[0],$default_options_color{$option}[1],$default_options_color{$option}[2], + $default_options_color{$option}[3],$default_options_color{$option}[4],$default_options_color{$option}[5], + $default_options_color{$option}[6],$default_options_color{$option}[7],$default_options_color{$option}[8], + $default_options_color{$option}[9],$default_options_color{$option}[10],$default_options_color{$option}[11], + $default_options_color{$option}[12],$default_options_color{$option}[13],$default_options_color{$option}[14]); + } + + # section "look" + my $section_look = weechat::config_new_section($buffers_config_file,"look", 0, 0, "", "", "", "", "", "", "", "", "", ""); + if ($section_look eq "") + { + weechat::config_free($buffers_config_file); + return; + } + foreach my $option (keys %default_options_look) + { + $options{$option} = weechat::config_new_option($buffers_config_file, $section_look, + $default_options_look{$option}[0],$default_options_look{$option}[1],$default_options_look{$option}[2], + $default_options_look{$option}[3],$default_options_look{$option}[4],$default_options_look{$option}[5], + $default_options_look{$option}[6],$default_options_look{$option}[7],$default_options_look{$option}[8], + $default_options_look{$option}[9],$default_options_look{$option}[10],$default_options_look{$option}[11], + $default_options_look{$option}[12],$default_options_look{$option}[13],$default_options_look{$option}[14]); + } +} + +sub build_buffers +{ + my $str = ""; + + # get bar position (left/right/top/bottom) + my $position = "left"; + my $option_position = weechat::config_get("weechat.bar.buffers.position"); + if ($option_position ne "") + { + $position = weechat::config_string($option_position); + } + + # read hotlist + my %hotlist; + my $infolist = weechat::infolist_get("hotlist", "", ""); + while (weechat::infolist_next($infolist)) + { + $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")} = + weechat::infolist_integer($infolist, "priority"); + } + weechat::infolist_free($infolist); + + # read buffers list + @buffers_focus = (); + my @buffers; + my @current1 = (); + my @current2 = (); + my $old_number = -1; + my $max_number = 0; + my $max_number_digits = 0; + my $active_seen = 0; + $infolist = weechat::infolist_get("buffer", "", ""); + while (weechat::infolist_next($infolist)) + { + my $buffer; + my $number = weechat::infolist_integer($infolist, "number"); + if ($number ne $old_number) + { + @buffers = (@buffers, @current2, @current1); + @current1 = (); + @current2 = (); + $active_seen = 0; + } + if ($number > $max_number) + { + $max_number = $number; + } + $old_number = $number; + my $active = weechat::infolist_integer($infolist, "active"); + if ($active) + { + $active_seen = 1; + } + $buffer->{"pointer"} = weechat::infolist_pointer($infolist, "pointer"); + $buffer->{"number"} = $number; + $buffer->{"active"} = $active; + $buffer->{"current_buffer"} = weechat::infolist_integer($infolist, "current_buffer"); + $buffer->{"plugin_name"} = weechat::infolist_string($infolist, "plugin_name"); + $buffer->{"name"} = weechat::infolist_string($infolist, "name"); + $buffer->{"short_name"} = weechat::infolist_string($infolist, "short_name"); + $buffer->{"full_name"} = $buffer->{"plugin_name"}.".".$buffer->{"name"}; + $buffer->{"type"} = weechat::buffer_get_string($buffer->{"pointer"},"localvar_type"); +# weechat::print("",$buffer->{"type"}); + + unless( grep {$_ eq $buffer->{"name"}} @immune_detach_buffers ) + { + my $detach_time = weechat::config_integer( $options{"detach"}); + my $current_time = time(); + # set timer for buffers with no hotlist action + $buffers_timer{$buffer->{"pointer"}} = $current_time + if ( not exists $hotlist{$buffer->{"pointer"}} + and $buffer->{"type"} eq "channel" + and not exists $buffers_timer{$buffer->{"pointer"}} + and $detach_time > 0); + + # check for detach + unless ( $buffer->{"current_buffer"} eq 0 + and not exists $hotlist{$buffer->{"pointer"}} + 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 ) + { + if ($active_seen) + { + push(@current2, $buffer); + } + else + { + push(@current1, $buffer); + } + } + } + else + { + if ($active_seen) + { + push(@current2, $buffer); + } + else + { + push(@current1, $buffer); + } + } + + } # while end + + + if ($max_number >= 1) + { + $max_number_digits = length(int($max_number)); + } + @buffers = (@buffers, @current2, @current1); + weechat::infolist_free($infolist); + + # sort buffers by number, name or shortname + my %sorted_buffers; + if (1) + { + my $number = 0; + for my $buffer (@buffers) + { + my $key; + if (weechat::config_integer( $options{"sort"} ) eq 1) # number = 0; name = 1 + { + my $name = $buffer->{"name"}; + $name = $buffer->{"short_name"} if (weechat::config_boolean( $options{"short_names"} ) eq 1); + if (weechat::config_integer($options{"name_size_max"}) >= 1){ + $name = encode("UTF-8", substr(decode("UTF-8", $name), 0, weechat::config_integer($options{"name_size_max"}))); + } + if ( weechat::config_boolean($options{"core_to_front"}) eq 1) + { + if ( (weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "channel" ) and ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "private") ) + { + my $type = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type"); + if ( $type eq "" and $name ne "weechat") + { + $name = " " . $name + }else + { + $name = " " . $name; + } + } + } + $key = sprintf("%s%08d", lc($name), $buffer->{"number"}); + } + else + { + $key = sprintf("%08d", $number); + } + $sorted_buffers{$key} = $buffer; + $number++; + } + } + + # build string with buffers + $old_number = -1; + foreach my $key (sort keys %sorted_buffers) + { + my $buffer = $sorted_buffers{$key}; + + if ( weechat::config_string($options{"hide_merged_buffers"}) eq "server" ) + { + # buffer type "server" or merged with core? + if ( ($buffer->{"type"} eq "server" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) ) + { + next; + } + } + if ( weechat::config_string($options{"hide_merged_buffers"}) eq "channel" ) + { + # buffer type "channel" or merged with core? + if ( ($buffer->{"type"} eq "channel" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) ) + { + next; + } + } + if ( weechat::config_string($options{"hide_merged_buffers"}) eq "private" ) + { + # buffer type "private" or merged with core? + if ( ($buffer->{"type"} eq "private" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) ) + { + next; + } + } + if ( weechat::config_string($options{"hide_merged_buffers"}) eq "keepserver" ) + { + if ( ($buffer->{"type"} ne "server" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) ) + { + next; + } + } + if ( weechat::config_string($options{"hide_merged_buffers"}) eq "all" ) + { + if ( ! $buffer->{"active"} ) + { + next; + } + } + + push(@buffers_focus, $buffer); # buffer > buffers_focus, for mouse support + my $color = ""; + my $bg = ""; + + $color = weechat::config_color( $options{"color_default_fg"} ); + $bg = weechat::config_color( $options{"color_default_bg"} ); + + if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "private" ) + { + if ( (weechat::config_color($options{"queries_default_bg"})) ne "default" || (weechat::config_color($options{"queries_default_fg"})) ne "default" ) + { + $bg = weechat::config_color( $options{"queries_default_bg"} ); + $color = weechat::config_color( $options{"queries_default_fg"} ); + } + } + # check for core and buffer with free content + if ( (weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "channel" ) and ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "private") ) + { + $color = weechat::config_color( $options{"color_none_channel_fg"} ); + $bg = weechat::config_color( $options{"color_none_channel_bg"} ); + } + # default whitelist buffer? + if (grep {$_ eq $buffer->{"name"}} @whitelist_buffers) + { + $color = weechat::config_color( $options{"color_whitelist_default_fg"} ); + $bg = weechat::config_color( $options{"color_whitelist_default_bg"} ); + } + + $color = "default" if ($color eq ""); + + # color for channel and query buffer + if (exists $hotlist{$buffer->{"pointer"}}) + { + delete $buffers_timer{$buffer->{"pointer"}}; + # check if buffer is in whitelist buffer + if (grep {$_ eq $buffer->{"name"}} @whitelist_buffers) + { + $bg = weechat::config_color( $options{"color_whitelist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} ); + $color = weechat::config_color( $options{"color_whitelist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"} ); + } + elsif ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "private" ) + { + # queries_default_fg/bg and buffers.color.queries_message_fg/bg + if ( (weechat::config_color($options{"queries_highlight_fg"})) ne "default" || + (weechat::config_color($options{"queries_highlight_bg"})) ne "default" || + (weechat::config_color($options{"queries_message_fg"})) ne "default" || + (weechat::config_color($options{"queries_message_bg"})) ne "default" ) + { + if ( ($hotlist{$buffer->{"pointer"}}) == 2 ) + { + $bg = weechat::config_color( $options{"queries_message_bg"} ); + $color = weechat::config_color( $options{"queries_message_fg"} ); + } + + elsif ( ($hotlist{$buffer->{"pointer"}}) == 3 ) + { + $bg = weechat::config_color( $options{"queries_highlight_bg"} ); + $color = weechat::config_color( $options{"queries_highlight_fg"} ); + } + }else + { + $bg = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} ); + $color = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"} ); + } + }else + { + $bg = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} ); + $color = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"} ); + } + } + + if ($buffer->{"current_buffer"}) + { + $color = weechat::config_color( $options{"color_current_fg"} ); + $bg = weechat::config_color( $options{"color_current_bg"} ); + } + my $color_bg = ""; + $color_bg = weechat::color(",".$bg) if ($bg ne ""); + + # create channel number for output + if ( weechat::config_boolean( $options{"show_number"} ) eq 1 ) # on + { + if (( weechat::config_boolean( $options{"indenting_number"} ) eq 1) + && (($position eq "left") || ($position eq "right"))) + { + $str .= weechat::color("default").$color_bg + .(" " x ($max_number_digits - length(int($buffer->{"number"})))); + } + if ($old_number ne $buffer->{"number"}) + { + $str .= weechat::color( weechat::config_color( $options{"color_number"} ) ) + .$color_bg + .$buffer->{"number"} + .weechat::color("default") + .$color_bg + .weechat::color( weechat::config_color( $options{"color_number_char"} ) ) + .weechat::config_string( $options{"show_number_char"} ) + .$color_bg; + } + else + { + my $indent = ""; + $indent = ((" " x length($buffer->{"number"}))." ") if (($position eq "left") || ($position eq "right")); + $str .= weechat::color("default") + .$color_bg + .$indent; + } + } + + if (( weechat::config_integer( $options{"indenting"} ) ne 0 ) # indenting NOT off + && (($position eq "left") || ($position eq "right"))) + { + my $type = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type"); + if (($type eq "channel") || ($type eq "private")) + { + if ( weechat::config_integer( $options{"indenting"} ) eq 1 ) + { + $str .= " "; + } + elsif ( (weechat::config_integer($options{"indenting"}) eq 2) and (weechat::config_integer($options{"indenting_number"}) eq 0) ) #under_name + { + if ( weechat::config_boolean( $options{"show_number"} ) eq 0 ) + { + $str .= " "; + }else + { + $str .= ( (" " x ( $max_number_digits - length($buffer->{"number"}) ))." " ); + } + } + } + } + if (weechat::config_boolean( $options{"show_prefix"} ) eq 1) + { + my $nickname = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_nick"); + if ($nickname ne "") + { + # with version >= 0.3.2, this infolist will return only nick + # with older versions, whole nicklist is returned for buffer, and this can be very slow + my $infolist_nick = weechat::infolist_get("nicklist", $buffer->{"pointer"}, "nick_".$nickname); + if ($infolist_nick ne "") + { + my $version = weechat::info_get("version_number", ""); + $version = 0 if ($version eq ""); + while (weechat::infolist_next($infolist_nick)) + { + if ((weechat::infolist_string($infolist_nick, "type") eq "nick") + && (weechat::infolist_string($infolist_nick, "name") eq $nickname)) + { + my $prefix = weechat::infolist_string($infolist_nick, "prefix"); + if (($prefix ne " ") or (weechat::config_boolean( $options{"show_prefix_empty"} ) eq 1)) + { + # with version >= 0.3.5, it is now a color name (for older versions: option name with color) + if (int($version) >= 0x00030500) + { + $str .= weechat::color(weechat::infolist_string($infolist_nick, "prefix_color")); + } + else + { + $str .= weechat::color(weechat::config_color( + weechat::config_get( + weechat::infolist_string($infolist_nick, "prefix_color")))); + } + $str .= $prefix; + } + last; + } + } + weechat::infolist_free($infolist_nick); + } + } + } + $str .= weechat::color($color) . weechat::color(",".$bg); + + if (weechat::config_boolean( $options{"short_names"} ) eq 1) + { + if (weechat::config_integer($options{"name_size_max"}) >= 1) # check max_size of buffer name + { + $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"})); + } + else + { + $str .= $buffer->{"short_name"}; + } + } + else + { + if (weechat::config_integer($options{"name_size_max"}) >= 1) # check max_size of buffer name + { + $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"})); + } + else + { + $str .= $buffer->{"name"}; + } + } + if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "server" and weechat::config_boolean($options{"show_lag"}) eq 1) + { + my $color_lag = weechat::config_color(weechat::config_get("irc.color.item_lag_finished")); + my $min_lag = weechat::config_integer(weechat::config_get("irc.network.lag_min_show")); + my $infolist_server = weechat::infolist_get("irc_server","",$buffer->{"short_name"}); + weechat::infolist_next($infolist_server); + my $lag = (weechat::infolist_integer($infolist_server, "lag")); + weechat::infolist_free($infolist_server); + if ( int($lag) > int($min_lag) ) + { + $lag = $lag / 1000; + $str .= weechat::color("default") . " (" . weechat::color($color_lag) . $lag . weechat::color("default") . ")"; + } + } + $str .= "\n"; + $old_number = $buffer->{"number"}; + } + + return $str; +} + +sub buffers_signal_buffer +{ +my ($data, $signal, $signal_data) = @_; + # check for buffer_switch and set the detach time or remove detach time + if ($weechat_version >= 0x00030800) + { + if ($signal eq "buffer_switch") + { + my $pointer = weechat::hdata_get_list (weechat::hdata_get("buffer"), "gui_buffer_last_displayed"); # get switched buffer + my $current_time = time(); + if ( weechat::buffer_get_string($pointer, "localvar_type") eq "channel") + { + $buffers_timer{$pointer} = $current_time; + } + else + { + delete $buffers_timer{$pointer}; + } + } + if ($signal eq "buffer_opened") + { + my $current_time = time(); + $buffers_timer{$signal_data} = $current_time; + } + if ($signal eq "buffer_closing") + { + delete $buffers_timer{$signal_data}; + } + } + + weechat::bar_item_update("buffers"); + return weechat::WEECHAT_RC_OK; +} + +sub buffers_signal_hotlist +{ + weechat::bar_item_update("buffers"); + return weechat::WEECHAT_RC_OK; +} + + +sub buffers_signal_config_whitelist +{ + @whitelist_buffers = (); + @whitelist_buffers = split( /,/, weechat::config_string( $options{"look_whitelist_buffers"} ) ); + weechat::bar_item_update("buffers"); + return weechat::WEECHAT_RC_OK; +} +sub buffers_signal_config_immune_detach_buffers +{ + @immune_detach_buffers = (); + @immune_detach_buffers = split( /,/, weechat::config_string( $options{"immune_detach_buffers"} ) ); + weechat::bar_item_update("buffers"); + return weechat::WEECHAT_RC_OK; +} + +sub buffers_signal_config +{ + weechat::bar_item_update("buffers"); + return weechat::WEECHAT_RC_OK; +} + +# called when mouse click occured in buffers item: this callback returns buffer +# hash according to line of item where click occured +sub buffers_focus_buffers +{ + my %info = %{$_[1]}; + my $item_line = int($info{"_bar_item_line"}); + undef my $hash; + if (($info{"_bar_item_name"} eq "buffers") && ($item_line >= 0) && ($item_line <= $#buffers_focus)) + { + $hash = $buffers_focus[$item_line]; + } + else + { + $hash = {}; + my $hash_focus = $buffers_focus[0]; + foreach my $key (keys %$hash_focus) + { + $hash->{$key} = "?"; + } + } + return $hash; +} + +# called when a mouse action is done on buffers item, to execute action +# possible actions: jump to a buffer or move buffer in list (drag & drop of buffer) +sub buffers_hsignal_mouse +{ + my ($data, $signal, %hash) = ($_[0], $_[1], %{$_[2]}); + my $current_buffer = weechat::buffer_get_integer(weechat::current_buffer(), "number"); # get current buffer number + + if ( $hash{"_key"} eq "button1" ) # left mouse button + { + if ($hash{"number"} eq $hash{"number2"}) + { + if ( weechat::config_integer($options{"jump_prev_next_visited_buffer"}) eq 1 ) + { + if ( $current_buffer eq $hash{"number"} ) + { + weechat::command("","/input jump_previously_visited_buffer"); + } + else + { + weechat::command("", "/buffer ".$hash{"full_name"}); + } + } + else + { + weechat::command("", "/buffer ".$hash{"full_name"}); + } + } + else + { + move_buffer(%hash); + } + } + elsif ( ($hash{"_key"} eq "button2") && (weechat::config_integer($options{"jump_prev_next_visited_buffer"}) eq 1) )# right mouse button + { + if ( $current_buffer eq $hash{"number2"} ) + { + weechat::command("","/input jump_next_visited_buffer"); + } + } + else + { + move_buffer(%hash); + } +} +sub move_buffer +{ + my %hash = @_; + my $number2 = $hash{"number2"}; + if ($number2 eq "?") + { + # if number 2 is not known (end of gesture outside buffers list), then set it + # according to mouse gesture + $number2 = "999999"; + $number2 = "1" if (($hash{"_key"} =~ /gesture-left/) || ($hash{"_key"} =~ /gesture-up/)); + } + my $ptrbuf = weechat::current_buffer(); + weechat::command($hash{"pointer"}, "/buffer move ".$number2); +} diff --git a/weechat/perl/chanmon.pl b/weechat/perl/chanmon.pl new file mode 100644 index 0000000..18544de --- /dev/null +++ b/weechat/perl/chanmon.pl @@ -0,0 +1,1116 @@ +# +# chanmon.pl - Channel Monitoring for weechat 0.3.0 +# Version 2.3.1 +# +# Add 'Channel Monitor' buffer/bar that you can position to show IRC channel +# messages in a single location without constantly switching buffers +# i.e. In a seperate window beneath the main channel buffer +# +# Usage: +# /chanmon [help] | [monitor [channel [server]]] | [dynmon] | [clean default|orphan|all] +# Command wrapper for chanmon commands +# +# /chmonitor [channel] [server] is used to toggle a channel monitoring on and off, this +# can be used in the channel buffer for the channel you wish to toggle, or be given +# with arguments e.g. /monitor #weechat freenode +# +# /dynmon is used to toggle 'Dynamic Channel Monitoring' on and off, this +# will automagically stop monitoring the current active buffer, without +# affecting regular settings (Default is off) +# +# /chanclean default|orphan|all will clean the config section of default 'on' entries, +# channels you are no longer joined, or both +# +# /set plugins.var.perl.chanmon.alignment +# The config setting "alignment" can be changed to; +# "channel", "schannel", "nchannel", "channel,nick", "schannel,nick", "nchannel,nick" +# to change how the monitor appears +# The 'channel' value will show: "#weechat" +# The 'schannel' value will show: "6" +# The 'nchannel' value will show: "6:#weechat" +# +# /set plugins.var.perl.chanmon.short_names +# Setting this to 'on' will trim the network name from chanmon, ala buffers.pl +# +# /set plugins.var.perl.chanmon.merge_private +# Setting this to 'on' will merge private messages to chanmon's display +# +# /set plugins.var.perl.chanmon.color_buf +# This turns colored buffer names on or off, you can also set a single fixed color by using a weechat color name. +# This *must* be a valid color name, or weechat will likely do unexpected things :) +# +# /set plugins.var.perl.chanmon.show_aways +# Toggles showing the Weechat away messages +# +# /set plugins.var.perl.chanmon.logging +# Toggles logging status for chanmon buffer (default: off) +# +# /set plugins.var.perl.chanmon.output +# Changes where output method of chanmon; takes either "bar" or "buffer" (default; buffer) +# /set plugins.var.perl.chanmon.bar_lines +# Changes the amount of lines the output bar will hold. +# (Only appears once output has been set to bar, defaults to 10) +# +# /set plugins.var.perl.chanmon.nick_prefix +# /set plugins.var.perl.chanmon.nick_suffix +# Sets the prefix and suffix chars in the chanmon buffer +# (Defaults to <> if nothing set, and blank if there is) +# +# servername.#channel +# servername is the internal name for the server (set when you use /server add) +# #channel is the channel name, (where # is whatever channel type that channel happens to be) +# +# Ideal set up: +# Split the layout 70/30 (or there abouts) horizontally and load +# Optionally, make the status and input lines only show on active windows +# +# /window splith 70 --> open the chanmon buffer +# /set weechat.bar.status.conditions "active" +# /set weechat.bar.input.conditions "active" + +# History: +# 2012-04-15, KenjiE20 : +# v2.3.1: -fix: Colour tags in bar timestamp string, bar error fixes from highmon +# 2012-02-28, KenjiE20 : +# v2.3: -feature: Added merge_private option to display private messages (default: off) +# 2010-12-22, KenjiE20 : +# v2.2: -change: Use API instead of config to find channel colours, ready for 0.3.4 and 256 colours +# 2010-12-05, KenjiE20 : +# v2.1.3: -change: /monitor is now /chmonitor to avoid command conflicts (thanks m4v) +# (/chanmon monitor remains the same) +# -fix: Add command list to inbuilt help +# 2010-09-30, KenjiE20 : +# v2.1.2: -fix: logging config was not correctly toggling back on (thanks to sleo for noticing) +# 2010-09-20, m4v : +# v2.1.1: -fix: chanmon wasn't detecting buffers displayed on more than one window +# 2010-08-27, KenjiE20 : +# v2.1: -feature: Add 'nchannel' option to alignment to display buffer and name +# 2010-04-25, KenjiE20 : +# v2.0: Release as version 2.0 +# 2010-04-24, KenjiE20 : +# -fix: No longer using hard-coded detection for ACTION and +# TOPIC messages. Use config settings for ACTION printing +# 2010-04-15, KenjiE20 : +# v1.9: Rewrite for v2.0 +# -feature: /monitor takes arguments +# -feature: Added /chanclean for config cleanup +# -feature: Buffer logging option (default: off) +# -feature: Selectable output (Bar/Buffer (default)) +# -feature: /chanmon is now a command wrapper for all commands +# /help chanmon gives command help +# /chanmon help gives config help +# -code change: Made more subs to shrink the code down in places +# -fix: Stop chanmon attempting to double load/hook +# 2010-02-10, m4v : +# v1.7.1: -fix: chanmon was leaking infolists, changed how chanmon +# detects if the buffer is displayed or not. +# 2010-01-25, KenjiE20 : +# v1.7: -fixture: Let chanmon be aware of nick_prefix/suffix +# and allow custom prefix/suffix for chanmon buffer +# (Defaults to <> if nothing set, and blank if there is) +# -fix: Make dynamic monitoring aware of multiple windows +# rather than just the active buffer +# (Thanks to m4v for these) +# 2009-09-07, KenjiE20 : +# v1.6: -feature: colored buffer names +# -change: chanmon version sync +# 2009-09-05, KenjiE20 : +# v1.5: -fix: disable buffer highlight +# 2009-09-02, KenjiE20 : +# v.1.4.1 -change: Stop unsightly text block on '/help' +# 2009-08-10, KenjiE20 : +# v1.4: -feature: In-client help added +# -fix: Added missing help entries +# Fix remaining ugly vars +# 2009-07-09, KenjiE20 : +# v.1.3.3 -fix: highlight on the channel monitor when someone /me highlights +# 2009-07-04, KenjiE20 : +# v.1.3.2 -fix: use new away_info tag instead of ugly regexp for away detection +# -code: cleanup old raw callback arguement variables to nice neat named ones +# 2009-07-04, KenjiE20 : +# v.1.3.1 -feature(tte): Hide /away messages by default, change 'show_aways' to get them back +# 2009-07-01, KenjiE20 : +# v.1.3 -feature(tte): Mimic buffers.pl 'short_names' +# 2009-06-29, KenjiE20 : +# v.1.2.1 -fix: let the /monitor message respect the alignment setting +# 2009-06-19, KenjiE20 : +# v.1.2 -feature(tte): Customisable alignment +# Thanks to 'FreakGaurd' for the idea +# 2009-06-14, KenjiE20 : +# v.1.1.2 -fix: don't assume chanmon buffer needs creating +# fixes crashing with /upgrade +# 2009-06-13, KenjiE20 : +# v.1.1.1 -code: change from True/False to on/off for weechat consistency +# Settings WILL NEED to be changed manually from previous versions +# 2009-06-13, KenjiE20 : +# v1.1: -feature: Dynamic Channel Monitoring, +# don't display messages from active channel buffer +# defaults to Disabled +# Thanks to 'sjohnson' for the idea +# -fix: don't set config entries for non-channels +# -fix: don't assume all channels are # +# 2009-06-12, KenjiE20 : +# v1.0.1: -fix: glitch with tabs in IRC messages +# 2009-06-10, KenjiE20 : +# v1.0: Initial Public Release + +# Copyright (c) 2009 by KenjiE20 +# +# 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 . +# + +@bar_lines = (); +@bar_lines_time = (); +# Replicate info earlier for in-client help +$chanmonhelp = weechat::color("bold")."/chanmon [help] | [monitor [channel [server]]] | [dynmon] | [clean default|orphan|all]".weechat::color("-bold")." +Command wrapper for chanmon commands + +".weechat::color("bold")."/chmonitor [channel] [server]".weechat::color("-bold")." is used to toggle a channel monitoring on and off, this + can be used in the channel buffer for the channel you wish to toggle, or be given with arguments e.g. /monitor #weechat freenode + +".weechat::color("bold")."/dynmon".weechat::color("-bold")." is used to toggle 'Dynamic Channel Monitoring' on and off, this will automagically stop monitoring the current active buffer, without affecting regular settings (Default is off) + +".weechat::color("bold")."/chanclean".weechat::color("-bold")." default|orphan|all will clean the config section of default 'on' entries, channels you are no longer joined, or both + +".weechat::color("bold")."/set plugins.var.perl.chanmon.alignment".weechat::color("-bold")." + The config setting \"alignment\" can be changed to; + \"channel\", \"schannel\", \"nchannel\", \"channel,nick\", \"schannel,nick\", \"nchannel,nick\" + to change how the monitor appears + The 'channel' value will show: \"#weechat\" + The 'schannel' value will show: \"6\" + The 'nchannel' value will show: \"6:#weechat\" + +".weechat::color("bold")."/set plugins.var.perl.chanmon.short_names".weechat::color("-bold")." + Setting this to 'on' will trim the network name from chanmon, ala buffers.pl + +".weechat::color("bold")."/set plugins.var.perl.chanmon.merge_private".weechat::color("-bold")." + Setting this to 'on' will merge private messages to chanmon's display + +".weechat::color("bold")."/set plugins.var.perl.chanmon.color_buf".weechat::color("-bold")." + This turns colored buffer names on or off, you can also set a single fixed color by using a weechat color name. + This ".weechat::color("bold")."must".weechat::color("-bold")." be a valid color name, or weechat will likely do unexpected things :) + +".weechat::color("bold")."/set plugins.var.perl.chanmon.show_aways".weechat::color("-bold")." + Toggles showing the Weechat away messages + +".weechat::color("bold")."/set plugins.var.perl.chanmon.logging".weechat::color("-bold")." + Toggles logging status for chanmon buffer (default: off) + +".weechat::color("bold")."/set plugins.var.perl.chanmon.output".weechat::color("-bold")." + Changes where output method of chanmon; takes either \"bar\" or \"buffer\" (default; buffer) +".weechat::color("bold")."/set plugins.var.perl.chanmon.bar_lines".weechat::color("-bold")." + Changes the amount of lines the output bar will hold. + (Only appears once output has been set to bar, defaults to 10) + +".weechat::color("bold")."/set plugins.var.perl.chanmon.nick_prefix".weechat::color("-bold")." +".weechat::color("bold")."/set plugins.var.perl.chanmon.nick_suffix".weechat::color("-bold")." + Sets the prefix and suffix chars in the chanmon buffer + (Defaults to <> if nothing set, and blank if there is) + +".weechat::color("bold")."servername.#channel".weechat::color("-bold")." + servername is the internal name for the server (set when you use /server add) + #channel is the channel name, (where # is whatever channel type that channel happens to be) + +".weechat::color("bold")."Ideal set up:".weechat::color("-bold")." +Split the layout 70/30 (or there abouts) horizontally and load +Optionally, make the status and input lines only show on active windows + +".weechat::color("bold")."/window splith 70 --> open the chanmon buffer".weechat::color("-bold")." +".weechat::color("bold")."/set weechat.bar.status.conditions \"active\"".weechat::color("-bold")." +".weechat::color("bold")."/set weechat.bar.input.conditions \"active\"".weechat::color("-bold"); +# Print verbose help +sub print_help +{ + weechat::print("", "\t".weechat::color("bold")."Chanmon Help".weechat::color("-bold")."\n\n"); + weechat::print("", "\t".$chanmonhelp); + return weechat::WEECHAT_RC_OK; +} + +# Bar item build +sub chanmon_bar_build +{ + # Get max lines + $max_lines = weechat::config_get_plugin("bar_lines"); + $max_lines = $max_lines ? $max_lines : 10; + $str = ''; + $align_num = 0; + $count = 0; + # Keep lines within max + while ($#bar_lines > $max_lines) + { + shift(@bar_lines); + shift(@bar_lines_time); + } + # So long as we have some lines, build a string + if (@bar_lines) + { + # Build loop + foreach(@bar_lines) + { + # Find max align needed + $prefix_num = (index(weechat::string_remove_color($_, ""), " | ")); + $align_num = $prefix_num if ($prefix_num > $align_num); + } + foreach(@bar_lines) + { + # Get align for this line + $prefix_num = (index(weechat::string_remove_color($_, ""), " | ")); + + # Make string + $str = $str.$bar_lines_time[$count]." ".(" " x ($align_num - $prefix_num)).$_."\n"; + # Increment count for sync with time list + $count++; + } + } + return $str; +} + +# Make a new bar +sub chanmon_bar_open +{ + # Make the bar item + weechat::bar_item_new("chanmon", "chanmon_bar_build", ""); + + $chanmon_bar = weechat::bar_new ("chanmon", "off", 100, "root", "", "bottom", "vertical", "vertical", 0, 0, "default", "cyan", "default", "on", "chanmon"); + + return weechat::WEECHAT_RC_OK; +} +# Close bar +sub chanmon_bar_close +{ + # Find if bar exists + $chanmon_bar = weechat::bar_search("chanmon"); + # If is does, close it + if ($chanmon_bar ne "") + { + weechat::bar_remove($chanmon_bar); + } + + # Find if bar item exists + $chanmon_bar_item = weechat::bar_item_search("chanmon_bar"); + # If is does, close it + if ($chanmon_bar_item ne "") + { + weechat::bar_remove($chanmon_bar_item); + } + + @bar_lines = (); + return weechat::WEECHAT_RC_OK; +} + +# Make a new buffer +sub chanmon_buffer_open +{ + # Search for pre-existing buffer + $chanmon_buffer = weechat::buffer_search("perl", "chanmon"); + + # Make a new buffer + if ($chanmon_buffer eq "") + { + $chanmon_buffer = weechat::buffer_new("chanmon", "chanmon_buffer_input", "", "chanmon_buffer_close", ""); + } + + # Turn off notify, highlights + if ($chanmon_buffer ne "") + { + weechat::buffer_set($chanmon_buffer, "notify", "0"); + weechat::buffer_set($chanmon_buffer, "highlight_words", "-"); + weechat::buffer_set($chanmon_buffer, "title", "Channel Monitor"); + # Set no_log + if (weechat::config_get_plugin("logging") eq "off") + { + weechat::buffer_set($chanmon_buffer, "localvar_set_no_log", "1"); + } + } + return weechat::WEECHAT_RC_OK; +} +# Buffer input has no action +sub chanmon_buffer_input +{ + return weechat::WEECHAT_RC_OK; +} +# Close up +sub chanmon_buffer_close +{ + $chanmon_buffer = ""; + return weechat::WEECHAT_RC_OK; +} + +# Chanmon command wrapper +sub chanmon_command_cb +{ + $data = $_[0]; + $buffer = $_[1]; + $args = $_[2]; + my $cmd = ''; + my $arg = ''; + + if ($args ne "") + { + # Split argument up + @arg_array = split(/ /,$args); + # Take first as command + $cmd = shift(@arg_array); + # Rebuild string to pass to subs + if (@arg_array) + { + $arg = join(" ", @arg_array); + } + } + + # Help command + if ($cmd eq "" || $cmd eq "help") + { + print_help(); + } + # /monitor command + elsif ($cmd eq "monitor") + { + chanmon_toggle($data, $buffer, $arg); + } + # /dynmon command + elsif ($cmd eq "dynmon") + { + chanmon_dyn_toggle(); + } + # /chanclean command + elsif ($cmd eq "clean") + { + chanmon_config_clean($data, $buffer, $arg); + } + return weechat::WEECHAT_RC_OK; +} + +# Clean up config entries +sub chanmon_config_clean +{ + $data = $_[0]; + $buffer = $_[1]; + $args = $_[2]; + + # Don't do anything if bad option given + if ($args ne "default" && $args ne "orphan" && $args ne "all") + { + weechat::print("", "\tchanmon.pl: Unknown option"); + return weechat::WEECHAT_RC_OK; + } + + @chans = (); + # Load an infolist of chanmon options + $infolist = weechat::infolist_get("option", "", "*chanmon*"); + while (weechat::infolist_next($infolist)) + { + $name = weechat::infolist_string($infolist, "option_name"); + $name =~ s/perl\.chanmon\.(\w*)\.([#&\+!])(.*)/$1.$2$3/; + if ($name =~ /^(.*)\.([#&\+!])(.*)$/) + { + $action = 0; + # Clean up all 'on's + if ($args eq "default" || $args eq "all") + { + # If value in config is "on" + if (weechat::config_get_plugin($name) eq "on") + { + # Unset and if successful flag as changed + $rc = weechat::config_unset_plugin($name); + if ($rc eq weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED) + { + $action = 1; + } + } + } + # Clean non joined + if ($args eq "orphan" || $args eq "all") + { + # If we can't find the buffer for this entry + if (weechat::buffer_search("irc", $name) eq "") + { + # Unset and if successful flag as changed + $rc = weechat::config_unset_plugin($name); + if ($rc eq weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED) + { + $action = 1; + } + } + } + # Add changed entry names to list + push (@chans, $name) if ($action); + } + } + weechat::infolist_free($infolist); + # If channels were cleaned from config + if (@chans) + { + # If only one entry + if (@chans == 1) + { + $str = "\tchanmon.pl: Cleaned ".@chans." entry from the config:"; + } + else + { + $str = "\tchanmon.pl: Cleaned ".@chans." entries from the config:"; + } + # Build a list of channels + foreach(@chans) + { + $str = $str." ".$_; + } + # Print what happened + weechat::print("",$str); + } + # Config seemed to be clean + else + { + weechat::print("", "\tchanmon.pl: No entries removed"); + } + return weechat::WEECHAT_RC_OK; +} + +# Check config elements +sub chanmon_config_init +{ + # Alignment default + if (!(weechat::config_is_set_plugin ("alignment"))) + { + weechat::config_set_plugin("alignment", "channel"); + } + if (weechat::config_get_plugin("alignment") eq "") + { + weechat::config_set_plugin("alignment", "none"); + } + + # Dynmon default + if (!(weechat::config_is_set_plugin ("dynamic"))) + { + weechat::config_set_plugin("dynamic", "off"); + } + + # Short name default + if (!(weechat::config_is_set_plugin ("short_names"))) + { + weechat::config_set_plugin("short_names", "off"); + } + + # Coloured names default + if (!(weechat::config_is_set_plugin ("color_buf"))) + { + weechat::config_set_plugin("color_buf", "on"); + } + + # Away message default + if (!(weechat::config_is_set_plugin ("show_aways"))) + { + weechat::config_set_plugin("show_aways", "off"); + } + + # chanmon log default + if (!(weechat::config_is_set_plugin ("logging"))) + { + weechat::config_set_plugin("logging", "off"); + } + + # Output default + if (!(weechat::config_is_set_plugin ("output"))) + { + weechat::config_set_plugin("output", "buffer"); + } + + # Private message merging + if (!(weechat::config_is_set_plugin ("merge_private"))) + { + weechat::config_set_plugin("merge_private", "off"); + } + + # Check for exisiting prefix/suffix chars, and setup accordingly + $prefix = weechat::config_get("irc.look.nick_prefix"); + $prefix = weechat::config_string($prefix); + $suffix = weechat::config_get("irc.look.nick_suffix"); + $suffix = weechat::config_string($suffix); + + if (!(weechat::config_is_set_plugin("nick_prefix"))) + { + if ($prefix eq "" && $suffix eq "") + { + weechat::config_set_plugin("nick_prefix", "<"); + } + else + { + weechat::config_set_plugin("nick_prefix", ""); + } + } + + if (!(weechat::config_is_set_plugin("nick_suffix"))) + { + if ($prefix eq "" && $suffix eq "") + { + weechat::config_set_plugin("nick_suffix", ">"); + } + else + { + weechat::config_set_plugin("nick_suffix", ""); + } + } +} + +# Get config updates +sub chanmon_config_cb +{ + $point = $_[0]; + $name = $_[1]; + $value = $_[2]; + + $name =~ s/^plugins\.var\.perl\.chanmon\.//; + + # Set logging on buffer + if ($name eq "logging") + { + # Search for pre-existing buffer + $chanmon_buffer = weechat::buffer_search("perl", "chanmon"); + if ($value eq "off") + { + weechat::buffer_set($chanmon_buffer, "localvar_set_no_log", "1"); + } + else + { + weechat::buffer_set($chanmon_buffer, "localvar_del_no_log", ""); + } + } + # Output changer + elsif ($name eq "output") + { + if ($value eq "bar") + { + # Search for pre-existing buffer + $chanmon_buffer = weechat::buffer_search("perl", "chanmon"); + # Close if it exists + if ($chanmon_buffer ne "") + { + weechat::buffer_close($chanmon_buffer) + } + + # Output bar lines default + if (!(weechat::config_is_set_plugin ("bar_lines"))) + { + weechat::config_set_plugin("bar_lines", "10"); + } + # Make a bar if doesn't exist + chanmon_bar_open(); + } + elsif ($value eq "buffer") + { + # If a bar exists, close it + chanmon_bar_close(); + # Open buffer + chanmon_buffer_open(); + } + + } + return weechat::WEECHAT_RC_OK; +} + +# Toggle dynamic monitoring on/off +sub chanmon_dyn_toggle +{ + if (weechat::config_get_plugin("dynamic") eq "off") + { + weechat::config_set_plugin("dynamic", "on"); + chanmon_print("Dynamic Channel Monitoring Enabled"); + return weechat::WEECHAT_RC_OK; + } + elsif (weechat::config_get_plugin("dynamic") eq "on") + { + weechat::config_set_plugin("dynamic", "off"); + chanmon_print("Dynamic Channel Monitoring Disabled"); + return weechat::WEECHAT_RC_OK; + } +} + +# Set up weechat hooks / commands +sub chanmon_hook +{ + weechat::hook_print("", "", "", 0, "chanmon_new_message", ""); + weechat::hook_command("chmonitor", "Toggles monitoring for a channel", "[channel [server]]", " channel: What channel to toggle monitoring for\n server: Internal server name, if channel is on more than one server", "%(irc_channels) %(irc_servers)", "chanmon_toggle", ""); + weechat::hook_command("dynmon", "Toggles 'dynamic' monitoring (auto-disable monitoring for current channel)", "", "", "", "chanmon_dyn_toggle", ""); + weechat::hook_command("chanclean", "Chanmon config clean up", "default|orphan|all", " default: Cleans all config entries with the default \"on\" value\n orphan: Cleans all config entries for channels you aren't currently joined\n all: Does both defaults and orphan", "default|orphan|all", "chanmon_config_clean", ""); + + weechat::hook_command("chanmon", "Chanmon help", "[help] | [monitor [channel [server]]] | [dynmon] | [clean default|orphan|all]", " help: Print help for chanmon\n monitor: Toggles monitoring for a channel (/chmonitor)\n dynmon: Toggles 'dynamic' monitoring (auto-disable monitoring for current channel) (/dynmon)\n clean: Chanmon config clean up (/chanclean)", "help || monitor %(irc_channels) %(irc_servers) || dynmon || clean default|orphan|all", "chanmon_command_cb", ""); + + weechat::hook_config("plugins.var.perl.chanmon.*", "chanmon_config_cb", ""); +} + +# Main body, Callback for hook_print +sub chanmon_new_message +{ + my $net = ""; + my $chan = ""; + my $nick = ""; + my $outstr = ""; + my $window_displayed = ""; + my $dyncheck = "0"; + +# DEBUG point +# $string = "\t"."0: ".$_[0]." 1: ".$_[1]." 2: ".$_[2]." 3: ".$_[3]." 4: ".$_[4]." 5: ".$_[5]." 6: ".$_[6]." 7: ".$_[7]; +# weechat::print("", "\t".$string); + + $cb_datap = $_[0]; + $cb_bufferp = $_[1]; + $cb_date = $_[2]; + $cb_tags = $_[3]; + $cb_disp = $_[4]; + $cb_high = $_[5]; + $cb_prefix = $_[6]; + $cb_msg = $_[7]; + + # Only work on messages and topic notices + if ($cb_tags =~ /irc_privmsg/ || $cb_tags =~ /irc_topic/) + { + # Check buffer name is an IRC channel or private message when enabled + $bufname = weechat::buffer_get_string($cb_bufferp, 'name'); + if ($bufname =~ /(.*)\.([#&\+!])(.*)/ || (weechat::config_get_plugin("merge_private") eq "on" && $cb_tags =~ /notify_private/)) + { + # Are we running on this channel + if (weechat::config_get_plugin($bufname) ne "off" && $cb_disp eq "1") + { + # Are we running dynamically + if (weechat::config_get_plugin("dynamic") eq "on") + { + # Check if this buffer is shown in a window somewhere + $window_displayed = weechat::buffer_get_integer($cb_bufferp, "num_displayed"); + if ($window_displayed ne 0) + { + # Stop running + return weechat::WEECHAT_RC_OK; + } + } + + # Format nick + # Line isn't action or topic notify + if (!($cb_tags =~ /irc_action/) && !($cb_tags =~ /irc_topic/)) + { + # Highlight + if ($cb_high eq "1") + { + # Strip nick colour + $uncolnick = weechat::string_remove_color($cb_prefix, ""); + # Format nick + $nick = " ".weechat::config_get_plugin("nick_prefix").weechat::color("chat_highlight").$uncolnick.weechat::color("reset").weechat::config_get_plugin("nick_suffix"); + } + # Normal line + else + { + # Format nick + $nick = " ".weechat::config_get_plugin("nick_prefix").$cb_prefix.weechat::color("reset").weechat::config_get_plugin("nick_suffix"); + } + } + # Topic line + elsif ($cb_tags =~ /irc_topic/) + { + + $nick = " ".$cb_prefix.weechat::color("reset"); + } + # Action line + else + { + # Highlight + if ($cb_high eq "1") + { + $uncolnick = weechat::string_remove_color($cb_prefix, ""); + $nick = weechat::color("chat_highlight").$uncolnick.weechat::color("reset"); + } + # Normal line + else + { + $nick = $cb_prefix.weechat::color("reset"); + } + } + # Send to output + chanmon_print ($cb_msg, $cb_bufferp, $nick); + } + } + } + # Special outgoing ACTION & away_info catcher + elsif ($cb_tags eq "" || $cb_tags =~ /away_info/ && weechat::config_get_plugin("show_aways") eq "on" ) + { + # Check buffer name is an IRC channel or private message when enabled + $bufname = weechat::buffer_get_string($cb_bufferp, 'name'); + if ($bufname =~ /(.*)\.([#&\+!])(.*)/ || (weechat::config_get_plugin("merge_private") eq "on" && $cb_tags =~ /notify_private/)) + { + # Are we running dynamically + if (weechat::config_get_plugin("dynamic") eq "on") + { + # Check if this buffer is shown in a window somewhere + $window_displayed = weechat::buffer_get_integer($cb_bufferp, "num_displayed"); + if ($window_displayed eq 1) + { + # Stop running + return weechat::WEECHAT_RC_OK; + } + } + + $net = $1; + $mynick = weechat::info_get("irc_nick", $net); + if ($cb_msg =~ $mynick) + { + $action_colour = weechat::color(weechat::config_string(weechat::config_get("weechat.color.chat_prefix_action"))); + $action_prefix = weechat::config_string(weechat::config_get("weechat.look.prefix_action")); + $nick_self_colour = weechat::color(weechat::config_string(weechat::config_get("weechat.color.chat_nick_self"))); + $nick = $action_colour.$action_prefix.$nick_self_colour.$nick.weechat::color("reset"); + # Send to output + chanmon_print ($cb_msg, $cb_bufferp, $nick); + } + } + } + return weechat::WEECHAT_RC_OK; +} + +# Output formatter and printer takes (msg bufpointer nick) +sub chanmon_print +{ + $cb_msg = $_[0]; + my $cb_bufferp = $_[1] if ($_[1]); + my $nick = $_[2] if ($_[2]); + + #Normal channel message + if ($cb_bufferp && $nick) + { + # Format buffer name + $bufname = format_buffer_name($cb_bufferp); + + # If alignment is #channel | nick msg + if (weechat::config_get_plugin("alignment") eq "channel") + { + $nick =~ s/\s(.*)/$1/; + # Build string + $outstr = $bufname."\t".$nick." ".$cb_msg; + } + # or if it is channel number | nick msg + elsif (weechat::config_get_plugin("alignment") eq "schannel") + { + $nick =~ s/\s(.*)/$1/; + # Use channel number instead + $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').weechat::color("reset"); + # Build string + $outstr = $bufname."\t".$nick." ".$cb_msg; + } + # or if it is number:#channel | nick msg + elsif (weechat::config_get_plugin("alignment") eq "nchannel") + { + $nick =~ s/\s(.*)/$1/; + # Place channel number in front of formatted name + $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').":".weechat::color("reset").$bufname; + # Build string + $outstr = $bufname."\t".$nick." ".$cb_msg; + } + # or if it is #channel nick | msg + elsif (weechat::config_get_plugin("alignment") eq "channel,nick") + { + # Build string + $outstr = $bufname.":".$nick."\t".$cb_msg; + } + # or if it is channel number nick | msg + elsif (weechat::config_get_plugin("alignment") eq "schannel,nick") + { + # Use channel number instead + $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').weechat::color("reset"); + # Build string + $outstr = $bufname.":".$nick."\t".$cb_msg; + } + # or if it is number:#channel nick | msg + elsif (weechat::config_get_plugin("alignment") eq "nchannel,nick") + { + # Place channel number in front of formatted name + $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').":".weechat::color("reset").$bufname; + # Build string + $outstr = $bufname.":".$nick."\t".$cb_msg; + } + # or finally | #channel nick msg + else + { + # Build string + $outstr = "\t".$bufname.":".$nick." ".$cb_msg; + } + } + # chanmon channel toggle message + elsif ($cb_bufferp && !$nick) + { + # Format buffer name + $bufname = format_buffer_name($cb_bufferp); + + # If alignment is #channel * | * + if (weechat::config_get_plugin("alignment") =~ /channel/) + { + # If it's actually channel number * | * + if (weechat::config_get_plugin("alignment") =~ /schannel/) + { + # Use channel number instead + $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').weechat::color("reset"); + } + # Or if it's actually number:#channel * | * + if (weechat::config_get_plugin("alignment") =~ /nchannel/) + { + # Place channel number in front of formatted name + $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').":".weechat::color("reset").$bufname; + } + $outstr = $bufname."\t".$cb_msg; + } + # or if alignment is | * + else + { + $outstr = $bufname.": ".$cb_msg; + } + } + # chanmon dynmon + elsif (!$cb_bufferp && !$nick) + { + $outstr = "\t".$cb_msg; + } + + # Send string to buffer + if (weechat::config_get_plugin("output") eq "buffer") + { + # Search for and confirm buffer + $chanmon_buffer = weechat::buffer_search("perl", "chanmon"); + # Print + weechat::print($chanmon_buffer, $outstr); + } + elsif (weechat::config_get_plugin("output") eq "bar") + { + # Add time string + use POSIX qw(strftime); + $time = strftime(weechat::config_string(weechat::config_get("weechat.look.buffer_time_format")), localtime); + # Colourise + if ($time =~ /\$\{\w+\}/) # Coloured string + { + while ($time =~ /\$\{(\w+)\}/) + { + $color = weechat::color($1); + $time =~ s/\$\{\w+\}/$color/; + } + } + else # Default string + { + $colour = weechat::color(weechat::config_string(weechat::config_get("weechat.color.chat_time_delimiters"))); + $reset = weechat::color("reset"); + $time =~ s/(\d*)(.)(\d*)/$1$colour$2$reset$3/g; + } + # Push updates to bar lists + push (@bar_lines_time, $time); + + # Change tab char + $delim = weechat::color(weechat::config_string(weechat::config_get("weechat.color.chat_delimiters")))." | ".weechat::color("reset"); + $outstr =~ s/\t/$delim/; + + push (@bar_lines, $outstr); + # Trigger update + weechat::bar_item_update("chanmon"); + } +} + +# Start the output display +sub chanmon_start +{ + if (weechat::config_get_plugin("output") eq "buffer") + { + chanmon_buffer_open(); + } + elsif (weechat::config_get_plugin("output") eq "bar") + { + chanmon_bar_open(); + } +} + +# Takes two optional args (channel server), toggles monitoring on/off +sub chanmon_toggle +{ + $data = $_[0]; + $buffer = $_[1]; + $args = $_[2]; + + # Check if we've been told what channel to act on + if ($args ne "") + { + # Split argument up + @arg_array = split(/ /,$args); + # Check if a server was given + if ($arg_array[1]) + { + # Find matching + $bufp = weechat::buffer_search("irc", $arg_array[1].".".$arg_array[0]); + } + else + { + $found_chans = 0; + # Loop through defined servers + $infolist = weechat::infolist_get("buffer", "", ""); + while (weechat::infolist_next($infolist)) + { + # Only interesting in IRC buffers + if (weechat::infolist_string($infolist, "plugin_name") eq "irc") + { + # Find buffers that maych + $sname = weechat::infolist_string($infolist, "short_name"); + if ($sname eq $arg_array[0]) + { + $found_chans++; + $bufp = weechat::infolist_pointer($infolist, "pointer"); + } + } + } + weechat::infolist_free($infolist); + # If the infolist found more than one channel, halt as we need to know which one + if ($found_chans > 1) + { + weechat::print("", "Channel name is not unique, please define server"); + return weechat::WEECHAT_RC_OK; + } + } + # Something didn't return right + if ($bufp eq "") + { + weechat::print("", "Could not find buffer"); + return weechat::WEECHAT_RC_OK; + } + } + else + { + # Get pointer from where we are + $bufp = weechat::current_buffer(); + } + # Get buffer name + $bufname = weechat::buffer_get_string($bufp, 'name'); + # Test if buffer is an IRC channel + if ($bufname =~ /(.*)\.([#&\+!])(.*)/) + { + if (weechat::config_get_plugin($bufname) eq "off") + { + # If currently off, set on + weechat::config_set_plugin($bufname, "on"); + + # Send to output formatter + chanmon_print("Channel Monitoring Enabled", $bufp); + return weechat::WEECHAT_RC_OK; + } + elsif (weechat::config_get_plugin($bufname) eq "on" || weechat::config_get_plugin($bufname) eq "") + { + # If currently on, set off + weechat::config_set_plugin($bufname, "off"); + + # Send to output formatter + chanmon_print("Channel Monitoring Disabled", $bufp); + return weechat::WEECHAT_RC_OK; + } + } +} + +# Takes a buffer pointer and returns a formatted name +sub format_buffer_name +{ + $cb_bufferp = $_[0]; + $bufname = weechat::buffer_get_string($cb_bufferp, 'name'); + + # Set colour from buffer name + if (weechat::config_get_plugin("color_buf") eq "on") + { + # Determine what colour to use + $color = weechat::info_get("irc_nick_color", $bufname); + if (!$color) + { + $color = 0; + @char_array = split(//,$bufname); + foreach $char (@char_array) + { + $color += ord($char); + } + $color %= 10; + $color = sprintf "weechat.color.chat_nick_color%02d", $color+1; + $color = weechat::config_get($color); + $color = weechat::config_string($color); + $color = weechat::color($color); + } + + # Private message just show network + if (weechat::config_get_plugin("merge_private") eq "on" && weechat::buffer_get_string($cb_bufferp, "localvar_type") eq "private") + { + $bufname = weechat::buffer_get_string($cb_bufferp, "localvar_server"); + } + # Format name to short or 'nicename' + elsif (weechat::config_get_plugin("short_names") eq "on") + { + $bufname = weechat::buffer_get_string($cb_bufferp, 'short_name'); + } + else + { + $bufname =~ s/(.*)\.([#&\+!])(.*)/$1$2$3/; + } + + # Build a coloured string + $bufname = $color.$bufname.weechat::color("reset"); + } + # User set colour name + elsif (weechat::config_get_plugin("color_buf") ne "off") + { + # Private message just show network + if (weechat::config_get_plugin("merge_private") eq "on" && weechat::buffer_get_string($cb_bufferp, "localvar_type") eq "private") + { + $bufname = weechat::buffer_get_string($cb_bufferp, "localvar_server"); + } + # Format name to short or 'nicename' + elsif (weechat::config_get_plugin("short_names") eq "on") + { + $bufname = weechat::buffer_get_string($cb_bufferp, 'short_name'); + } + else + { + $bufname =~ s/(.*)\.([#&\+!])(.*)/$1$2$3/; + } + + $color = weechat::config_get_plugin("color_buf"); + $bufname = weechat::color($color).$bufname.weechat::color("reset"); + } + # Stick with default colour + else + { + # Private message just show network + if (weechat::config_get_plugin("merge_private") eq "on" && weechat::buffer_get_string($cb_bufferp, "localvar_type") eq "private") + { + $bufname = weechat::buffer_get_string($cb_bufferp, "localvar_server"); + } + # Format name to short or 'nicename' + elsif (weechat::config_get_plugin("short_names") eq "on") + { + $bufname = weechat::buffer_get_string($cb_bufferp, 'short_name'); + } + else + { + $bufname =~ s/(.*)\.([#&\+!])(.*)/$1$2$3/; + } + } + + return $bufname; +} + +# Check result of register, and attempt to behave in a sane manner +if (!weechat::register("chanmon", "KenjiE20", "2.3.1", "GPL3", "Channel Monitor", "", "")) +{ + # Double load + weechat::print ("", "\tChanmon is already loaded"); + return weechat::WEECHAT_RC_OK; +} +else +{ + # Start everything + chanmon_hook(); + chanmon_config_init(); + chanmon_start(); +} \ No newline at end of file diff --git a/weechat/perl/iset.pl b/weechat/perl/iset.pl new file mode 100644 index 0000000..4fb8124 --- /dev/null +++ b/weechat/perl/iset.pl @@ -0,0 +1,1196 @@ +# +# Copyright (C) 2008-2012 Sebastien Helleu +# Copyright (C) 2010-2012 Nils Görs +# +# 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 . +# +# Set WeeChat and plugins options interactively. +# +# History: +# +# 2012-03-17, Sebastien Helleu : +# version 2.5: fix check of sections when creating config file +# 2012-03-09, Sebastien Helleu : +# version 2.4: fix reload of config file +# 2012-02-02, nils_2 : +# version 2.3: fixed: refresh problem with new search results and cursor was outside window. +# : add: new option "current_line" in title bar +# version 2.2: fixed: refresh error when toggling plugins description +# 2011-11-05, nils_2 : +# version 2.1: use own config file (iset.conf), fix own help color (used immediately) +# 2011-10-16, nils_2 : +# version 2.0: add support for left-mouse-button and more sensitive mouse gesture (for integer/color options) +# add help text for mouse support +# 2011-09-20, Sebastien Helleu : +# version 1.9: add mouse support, fix iset buffer, fix errors on first load under FreeBSD +# 2011-07-21, nils_2 : +# version 1.8: added: option "show_plugin_description" (alt+p) +# fixed: typos in /help iset (lower case for alt+'x' keys) +# 2011-05-29, nils_2 : +# version 1.7: added: version check for future needs +# added: new option (scroll_horiz) and usage of scroll_horiz function (weechat >= 0.3.6 required) +# fixed: help_bar did not pop up immediately using key-shortcut +# 2011-02-19, nils_2 : +# version 1.6: added: display of all possible values in help bar (show_help_extra_info) +# fixed: external user options never loaded when starting iset first time +# 2011-02-13, Sebastien Helleu : +# version 1.5: use new help format for command arguments +# 2011-02-03, nils_2 : +# version 1.4: fixed: restore value filter after /upgrade using buffer local variable. +# 2011-01-14, nils_2 : +# version 1.3: added function to search for values (option value_search_char). +# code optimization. +# 2010-12-26, Sebastien Helleu : +# version 1.2: improve speed of /upgrade when iset buffer is open, +# restore filter used after /upgrade using buffer local variable, +# use /iset filter argument if buffer is open. +# 2010-11-21, drubin : +# version 1.1.1: fix bugs with cursor position +# 2010-11-20, nils_2 : +# version 1.1: cursor position set to value +# 2010-08-03, Sebastien Helleu : +# version 1.0: move misplaced call to infolist_free() +# 2010-02-02, rettub : +# version 0.9: turn all the help stuff off if option 'show_help_bar' is 'off', +# new key binding - to toggle help_bar and help stuff on/off +# 2010-01-30, nils_2 : +# version 0.8: fix error when option does not exist +# 2010-01-24, Sebastien Helleu : +# version 0.7: display iset bar only on iset buffer +# 2010-01-22, nils_2 and drubin: +# version 0.6: add description in a bar, fix singular/plural bug in title bar, +# fix selected line when switching buffer +# 2009-06-21, Sebastien Helleu : +# version 0.5: fix bug with iset buffer after /upgrade +# 2009-05-02, Sebastien Helleu : +# version 0.4: sync with last API changes +# 2009-01-04, Sebastien Helleu : +# version 0.3: open iset buffer when /iset command is executed +# 2009-01-04, Sebastien Helleu : +# version 0.2: use null values for options, add colors, fix refresh bugs, +# use new keys to reset/unset options, sort options by name, +# display number of options in buffer's title +# 2008-11-05, Sebastien Helleu : +# version 0.1: first official version +# 2008-04-19, Sebastien Helleu : +# script creation + +use strict; + +my $PRGNAME = "iset"; +my $VERSION = "2.5"; +my $DESCR = "Interactive Set for configuration options"; +my $AUTHOR = "Sebastien Helleu "; +my $LICENSE = "GPL3"; +my $LANG = "perl"; +my $ISET_CONFIG_FILE_NAME = "iset"; + +my $iset_config_file; +my $iset_buffer = ""; +my $wee_version_number = 0; +my @iset_focus = (); +my @options_names = (); +my @options_types = (); +my @options_values = (); +my @options_is_null = (); +my $option_max_length = 0; +my $current_line = 0; +my $filter = "*"; +my $description = ""; +my $options_name_copy = ""; +my $iset_filter_title = ""; + +my %options_iset; + +my %mouse_keys = ("\@chat(perl.$PRGNAME):button1" => "hsignal:iset_mouse", + "\@chat(perl.$PRGNAME):button2*" => "hsignal:iset_mouse", + "\@chat(perl.$PRGNAME):wheelup" => "/repeat 5 /iset **up", + "\@chat(perl.$PRGNAME):wheeldown" => "/repeat 5 /iset **down"); + + +sub iset_title +{ + if ($iset_buffer ne "") + { + my $current_line_text = ""; + $current_line_text = ($current_line + 1) . "/" if (weechat::config_boolean($options_iset{"show_current_line"}) == 1); + $iset_filter_title = "Filter: " if ($iset_filter_title eq ""); + $filter = "*" if ($filter eq ""); + my $postfix = "s"; + my $option_txt = " option"; + my $opt_txt = $option_txt; + $opt_txt = $option_txt.$postfix if (@options_names > 1); + my $show_plugin_descr_txt = ""; + $show_plugin_descr_txt = " (plugins description hidden)" if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 0); + weechat::buffer_set($iset_buffer, "title", + "Interactive set (iset.pl v$VERSION) | " + .$iset_filter_title.weechat::color("yellow").$filter.weechat::color("default")." | " + .$current_line_text.@options_names.$opt_txt . $show_plugin_descr_txt); + } +} + +sub iset_filter +{ + $filter = $_[0]; + $filter = "$1.*" if ($filter =~ /f (.*)/); + $filter = "*.$1.*" if ($filter =~ /s (.*)/); + if ((substr($filter, 0, 1) ne "*") && (substr($filter, -1, 1) ne "*")) + { + $filter = "*".$filter."*"; + } + if ($iset_buffer ne "") + { + weechat::buffer_set($iset_buffer, "localvar_set_iset_filter", $filter); + } +} + +sub iset_buffer_input +{ + my ($data, $buffer, $string) = ($_[0], $_[1], $_[2]); + + my $string2 = substr($string, 0, 1); + if ($string2 eq weechat::config_string($options_iset{"value_search_char"})) + { + $filter = substr($string, 1); + iset_get_values($filter); + $iset_filter_title = "Filter (by value): "; + if ($iset_buffer ne "") + { + weechat::buffer_set($iset_buffer, "localvar_set_iset_filter", $filter); + } + } + else + { + $iset_filter_title = ""; + iset_filter($string); + iset_get_options(); + } + weechat::buffer_clear($buffer); + iset_title($iset_filter_title); + $current_line = 0; + iset_refresh(); + return weechat::WEECHAT_RC_OK; +} + +sub iset_buffer_close +{ + $iset_buffer = ""; + + return weechat::WEECHAT_RC_OK; +} + +sub iset_init +{ + $current_line = 0; + $iset_buffer = weechat::buffer_search($LANG, $PRGNAME); + if ($iset_buffer eq "") + { + $iset_buffer = weechat::buffer_new($PRGNAME, "iset_buffer_input", "", "iset_buffer_close", ""); + } + else + { + my $new_filter = weechat::buffer_get_string($iset_buffer, "localvar_iset_filter"); + $filter = $new_filter if ($new_filter ne ""); + } + if ($iset_buffer ne "") + { + weechat::buffer_set($iset_buffer, "type", "free"); + iset_title(); + weechat::buffer_set($iset_buffer, "key_bind_ctrl-L", "/iset **refresh"); + weechat::buffer_set($iset_buffer, "key_bind_meta2-A", "/iset **up"); + weechat::buffer_set($iset_buffer, "key_bind_meta2-B", "/iset **down"); + weechat::buffer_set($iset_buffer, "key_bind_meta2-23~", "/iset **left"); + weechat::buffer_set($iset_buffer, "key_bind_meta2-24~" , "/iset **right"); + weechat::buffer_set($iset_buffer, "key_bind_meta- ", "/iset **toggle"); + weechat::buffer_set($iset_buffer, "key_bind_meta-+", "/iset **incr"); + weechat::buffer_set($iset_buffer, "key_bind_meta--", "/iset **decr"); + weechat::buffer_set($iset_buffer, "key_bind_meta-imeta-r", "/iset **reset"); + weechat::buffer_set($iset_buffer, "key_bind_meta-imeta-u", "/iset **unset"); + weechat::buffer_set($iset_buffer, "key_bind_meta-ctrl-J", "/iset **set"); + weechat::buffer_set($iset_buffer, "key_bind_meta-ctrl-M", "/iset **set"); + weechat::buffer_set($iset_buffer, "key_bind_meta-meta2-1~", "/iset **scroll_top"); + weechat::buffer_set($iset_buffer, "key_bind_meta-meta2-4~", "/iset **scroll_bottom"); + weechat::buffer_set($iset_buffer, "key_bind_meta-v", "/iset **toggle_help"); + weechat::buffer_set($iset_buffer, "key_bind_meta-p", "/iset **toggle_show_plugin_desc"); + weechat::buffer_set($iset_buffer, "localvar_set_iset_filter", $filter); + } +} + +sub iset_get_options +{ + @iset_focus = (); + + @options_names = (); + @options_types = (); + @options_values = (); + @options_is_null = (); + $option_max_length = 0; + my %options_internal = (); + my $i = 0; + my $key; + my $iset_struct; + my %iset_struct; + + my $infolist = weechat::infolist_get("option", "", $filter); + while (weechat::infolist_next($infolist)) + { + $key = sprintf("%08d", $i); + my $name = weechat::infolist_string($infolist, "full_name"); + next if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 0 and index ($name, "plugins.desc.") != -1); + my $type = weechat::infolist_string($infolist, "type"); + my $value = weechat::infolist_string($infolist, "value"); + my $is_null = weechat::infolist_integer($infolist, "value_is_null"); + + $options_internal{$name}{"type"} = $type; + $options_internal{$name}{"value"} = $value; + $options_internal{$name}{"is_null"} = $is_null; + $option_max_length = length($name) if (length($name) > $option_max_length); + + $iset_struct{$key} = $options_internal{$name}; + push(@iset_focus, $iset_struct{$key}); + $i++; + } + weechat::infolist_free($infolist); + + foreach my $name (sort keys %options_internal) + { + push(@options_names, $name); + push(@options_types, $options_internal{$name}{"type"}); + push(@options_values, $options_internal{$name}{"value"}); + push(@options_is_null, $options_internal{$name}{"is_null"}); + } +} + +sub iset_get_values +{ + my $var_value = $_[0]; + @options_names = (); + @options_types = (); + @options_values = (); + @options_is_null = (); + $option_max_length = 0; + my %options_internal = (); + my $i = 0; + my $infolist = weechat::infolist_get("option", "", "*"); + $var_value =~ tr/[a-z][0-9].=-_!//cd; # kill meta chars + $var_value = lc($var_value); + while (weechat::infolist_next($infolist)) + { + my $name = weechat::infolist_string($infolist, "full_name"); + next if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 0 and index ($name, "plugins.desc.") != -1); + my $type = weechat::infolist_string($infolist, "type"); + my $value = weechat::infolist_string($infolist, "value"); + my $is_null = weechat::infolist_integer($infolist, "value_is_null"); + if (lc($value) =~ m/$var_value/) + { + $options_internal{$name}{"type"} = $type; + $options_internal{$name}{"value"} = $value; + $options_internal{$name}{"is_null"} = $is_null; + $option_max_length = length($name) if (length($name) > $option_max_length); + } + $i++; + } + weechat::infolist_free($infolist); + foreach my $name (sort keys %options_internal) + { + push(@options_names, $name); + push(@options_types, $options_internal{$name}{"type"}); + push(@options_values, $options_internal{$name}{"value"}); + push(@options_is_null, $options_internal{$name}{"is_null"}); + } + weechat::buffer_set($iset_buffer, "localvar_set_iset_filter", $var_value); +} + +sub iset_refresh_line +{ + if ($iset_buffer ne "") + { + my $y = $_[0]; + if ($y <= $#options_names) + { + return if (! defined($options_types[$y])); + my $format = sprintf("%%s%%-%ds %%s %%-7s %%s %%s%%s%%s", $option_max_length); + my $around = ""; + $around = "\"" if ((!$options_is_null[$y]) && ($options_types[$y] eq "string")); + + my $color1 = weechat::color(weechat::config_color($options_iset{"color_option"})); + my $color2 = weechat::color(weechat::config_color($options_iset{"color_type"})); + my $color3 = ""; + if ($options_is_null[$y]) + { + $color3 = weechat::color(weechat::config_color($options_iset{"color_value_undef"})); + } + else + { + $color3 = weechat::color(weechat::config_color($options_iset{"color_value"})); + } + if ($y == $current_line) + { + $color1 = weechat::color(weechat::config_color($options_iset{"color_option_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"})); + $color2 = weechat::color(weechat::config_color($options_iset{"color_type_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"})); + if ($options_is_null[$y]) + { + $color3 = weechat::color(weechat::config_color($options_iset{"color_value_undef_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"})); + } + else + { + $color3 = weechat::color(weechat::config_color($options_iset{"color_value_selected"}).",".weechat::config_color($options_iset{"color_bg_selected"})); + } + } + my $value = $options_values[$y]; + $value = "(undef)" if ($options_is_null[$y]); + my $strline = sprintf($format, + $color1, $options_names[$y], + $color2, $options_types[$y], + $color3, $around, $value, $around); + weechat::print_y($iset_buffer, $y, $strline); + } + } +} + +sub iset_refresh +{ + iset_title(); + if (($iset_buffer ne "") && ($#options_names >= 0)) + { + foreach my $y (0 .. $#options_names) + { + iset_refresh_line($y); + } + } + + weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1); +} + +sub iset_full_refresh +{ + $iset_buffer = weechat::buffer_search($LANG, $PRGNAME); + if ($iset_buffer ne "") + { + weechat::buffer_clear($iset_buffer); + # search for "*" in $filter. + if ($filter =~ m/\*/) + { + iset_get_options(); + } + else + { + iset_get_values($filter); + $iset_filter_title = "Filter (by value): "; + } + if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 1) + { + iset_set_current_line($current_line); + }else + { + $current_line = $#options_names if ($current_line > $#options_names); + } + iset_refresh(); + weechat::command($iset_buffer, "/window refresh"); + } +} + +sub iset_set_current_line +{ + my $new_current_line = $_[0]; + my $old_current_line = $current_line; + $current_line = $new_current_line; + $current_line = $#options_names if ($current_line > $#options_names); + if ($old_current_line != $current_line) + { + iset_refresh_line($old_current_line); + iset_refresh_line($current_line); + weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1); + } +} + +sub iset_signal_window_scrolled_cb +{ + my ($data, $signal, $signal_data) = ($_[0], $_[1], $_[2]); + if ($iset_buffer ne "") + { + my $infolist = weechat::infolist_get("window", $signal_data, ""); + if (weechat::infolist_next($infolist)) + { + if (weechat::infolist_pointer($infolist, "buffer") eq $iset_buffer) + { + my $old_current_line = $current_line; + my $new_current_line = $current_line; + my $start_line_y = weechat::infolist_integer($infolist, "start_line_y"); + my $chat_height = weechat::infolist_integer($infolist, "chat_height"); + $new_current_line += $chat_height if ($new_current_line < $start_line_y); + $new_current_line -= $chat_height if ($new_current_line >= $start_line_y + $chat_height); + $new_current_line = $start_line_y if ($new_current_line < $start_line_y); + $new_current_line = $start_line_y + $chat_height - 1 if ($new_current_line >= $start_line_y + $chat_height); + iset_set_current_line($new_current_line); + } + } + weechat::infolist_free($infolist); + } + + return weechat::WEECHAT_RC_OK; +} + +sub iset_get_window_number +{ + if ($iset_buffer ne "") + { + my $window = weechat::window_search_with_buffer($iset_buffer); + return "-window ".weechat::window_get_integer ($window, "number")." " if ($window ne ""); + } + return ""; +} + +sub iset_check_line_outside_window +{ + if ($iset_buffer ne "") + { + undef my $infolist; + if ($wee_version_number >= 0x00030500) + { + my $window = weechat::window_search_with_buffer($iset_buffer); + $infolist = weechat::infolist_get("window", $window, "") if $window; + } + else + { + $infolist = weechat::infolist_get("window", "", "current"); + } + if ($infolist) + { + if (weechat::infolist_next($infolist)) + { + my $start_line_y = weechat::infolist_integer($infolist, "start_line_y"); + my $chat_height = weechat::infolist_integer($infolist, "chat_height"); + my $window_number = ""; + if ($wee_version_number >= 0x00030500) + { + $window_number = "-window ".weechat::infolist_integer($infolist, "number")." "; + } + if ($start_line_y > $current_line) + { + weechat::command($iset_buffer, "/window scroll ".$window_number."-".($start_line_y - $current_line)); + } + else + { + if ($start_line_y <= $current_line - $chat_height) + { + weechat::command($iset_buffer, "/window scroll ".$window_number."+".($current_line - $start_line_y - $chat_height + 1)); + } + } + } + weechat::infolist_free($infolist); + } + } +} + +sub iset_get_option_name_index +{ + my $option_name = $_[0]; + my $index = 0; + while ($index <= $#options_names) + { + return -1 if ($options_names[$index] gt $option_name); + return $index if ($options_names[$index] eq $option_name); + $index++; + } + return -1; +} + +sub iset_config_cb +{ + my ($data, $option_name, $value) = ($_[0], $_[1], $_[2]); + + if ($iset_buffer ne "") + { + return weechat::WEECHAT_RC_OK if (weechat::info_get("weechat_upgrading", "") eq "1"); + + my $index = iset_get_option_name_index($option_name); + if ($index >= 0) + { + # refresh info about changed option + my $infolist = weechat::infolist_get("option", "", $option_name); + if ($infolist) + { + weechat::infolist_next($infolist); + if (weechat::infolist_fields($infolist)) + { + $options_types[$index] = weechat::infolist_string($infolist, "type"); + $options_values[$index] = weechat::infolist_string($infolist, "value"); + $options_is_null[$index] = weechat::infolist_integer($infolist, "value_is_null"); + iset_refresh_line($index); + iset_title($iset_filter_title) if ($option_name eq "iset.look.show_current_line"); + } + else + { + iset_full_refresh(); + } + weechat::infolist_free($infolist); + } + } + else + { + iset_full_refresh() if ($option_name ne "weechat.bar.isetbar.hidden"); + } + } + + return weechat::WEECHAT_RC_OK; +} + +sub iset_set_option +{ + my $option = weechat::config_get($_[0]); + weechat::config_option_set($option, $_[1], 1) if ($option ne ""); +} + +sub iset_reset_option +{ + my $option = weechat::config_get($_[0]); + weechat::config_option_reset($option, 1) if ($option ne ""); +} + +sub iset_unset_option +{ + my $option = weechat::config_get($_[0]); + weechat::config_option_unset($option) if ($option ne ""); + weechat::buffer_clear($iset_buffer); + iset_refresh(); +} + + +sub iset_cmd_cb +{ + my ($data, $buffer, $args) = ($_[0], $_[1], $_[2]); + my $filter_set = 0; + if (($args ne "") && (substr($args, 0, 2) ne "**")) + { + if (substr($args, 0, 1) eq weechat::config_string($options_iset{"value_search_char"})) + { + my $var_value = substr($args, 1); # cut value_search_char + if ($iset_buffer ne "") + { + weechat::buffer_clear($iset_buffer); + weechat::command($iset_buffer, "/window refresh"); + } + iset_init(); + iset_get_values($var_value); + iset_refresh(); + weechat::buffer_set($iset_buffer, "display", "1"); + $iset_filter_title = "Filter (by value): "; + $filter = $var_value; + iset_title($iset_filter_title); + return weechat::WEECHAT_RC_OK; + } + else + { + iset_filter($args); + $filter_set = 1; + my $ptrbuf = weechat::buffer_search($LANG, $PRGNAME); + if ($ptrbuf eq "") + { + iset_init(); + iset_get_options(); + iset_full_refresh(); + weechat::buffer_set(weechat::buffer_search($LANG, $PRGNAME), "display", "1"); + return weechat::WEECHAT_RC_OK; + } + } + } + + if ($iset_buffer eq "") + { + iset_init(); + iset_get_options(); + iset_refresh(); + } + else + { + iset_full_refresh() if ($filter_set); + } + + if ($args eq "") + { + weechat::buffer_set($iset_buffer, "display", "1"); + } + else + { + if ($args eq "**refresh") + { + iset_full_refresh(); + } + if ($args eq "**up") + { + if ($current_line > 0) + { + $current_line--; + iset_refresh_line($current_line + 1); + iset_refresh_line($current_line); + iset_check_line_outside_window(); + } + } + if ($args eq "**down") + { + if ($current_line < $#options_names) + { + $current_line++; + iset_refresh_line($current_line - 1); + iset_refresh_line($current_line); + iset_check_line_outside_window(); + } + } + if ($args eq "**left" && $wee_version_number >= 0x00030600) + { + weechat::command($iset_buffer, "/window scroll_horiz ".iset_get_window_number()."-".weechat::config_integer($options_iset{"scroll_horiz"})."%"); + } + if ($args eq "**right" && $wee_version_number >= 0x00030600) + { + weechat::command($iset_buffer, "/window scroll_horiz ".iset_get_window_number().weechat::config_integer($options_iset{"scroll_horiz"})."%"); + } + if ($args eq "**scroll_top") + { + my $old_current_line = $current_line; + $current_line = 0; + iset_refresh_line ($old_current_line); + iset_refresh_line ($current_line); + weechat::command($iset_buffer, "/window scroll_top ".iset_get_window_number()); + } + if ($args eq "**scroll_bottom") + { + my $old_current_line = $current_line; + $current_line = $#options_names; + iset_refresh_line ($old_current_line); + iset_refresh_line ($current_line); + weechat::command($iset_buffer, "/window scroll_bottom ".iset_get_window_number()); + } + if ($args eq "**toggle") + { + if ($options_types[$current_line] eq "boolean") + { + iset_set_option($options_names[$current_line], "toggle"); + } + } + if ($args eq "**incr") + { + if (($options_types[$current_line] eq "integer") + || ($options_types[$current_line] eq "color")) + { + iset_set_option($options_names[$current_line], "++1"); + } + } + if ($args eq "**decr") + { + if (($options_types[$current_line] eq "integer") + || ($options_types[$current_line] eq "color")) + { + iset_set_option($options_names[$current_line], "--1"); + } + } + if ($args eq "**reset") + { + iset_reset_option($options_names[$current_line]); + } + if ($args eq "**unset") + { + iset_unset_option($options_names[$current_line]); + } + if ($args eq "**toggle_help") + { + if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1) + { + weechat::config_option_set($options_iset{"show_help_bar"},0,1); + iset_show_bar(0); + } + else + { + weechat::config_option_set($options_iset{"show_help_bar"},1,1); + iset_show_bar(1); + } + } + if ($args eq "**toggle_show_plugin_desc") + { + if (weechat::config_boolean($options_iset{"show_plugin_description"}) == 1) + { + weechat::config_option_set($options_iset{"show_plugin_description"},0,1); + iset_full_refresh(); + iset_check_line_outside_window(); + } + else + { + weechat::config_option_set($options_iset{"show_plugin_description"},1,1); + iset_full_refresh(); + iset_check_line_outside_window(); + } + } + if ($args eq "**set") + { + my $quote = ""; + my $value = $options_values[$current_line]; + if ($options_is_null[$current_line]) + { + $value = "null"; + } + else + { + $quote = "\"" if ($options_types[$current_line] eq "string"); + } + weechat::buffer_set($iset_buffer, "input", "/set ".$options_names[$current_line]." ".$quote.$value.$quote); + weechat::command($iset_buffer, "/input move_beginning_of_line"); + weechat::command($iset_buffer, "/input move_next_word"); + weechat::command($iset_buffer, "/input move_next_word"); + weechat::command($iset_buffer, "/input move_next_char"); + weechat::command($iset_buffer, "/input move_next_char") if ($quote ne ""); + } + } + weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1); + return weechat::WEECHAT_RC_OK; +} + +sub iset_get_help +{ + my ($redraw) = ($_[0]); + + return '' if (weechat::config_boolean($options_iset{"show_help_bar"}) == 0); + + if (not defined $options_names[$current_line]) + { + return "No option selected. Set a new filter using command line (use '*' to see all options)"; + } + if ($options_name_copy eq $options_names[$current_line] and not defined $redraw) + { + return $description; + } + $options_name_copy = $options_names[$current_line]; + my $optionlist =""; + $optionlist = weechat::infolist_get("option", "", $options_names[$current_line]); + weechat::infolist_next($optionlist); + my $full_name = weechat::infolist_string($optionlist,"full_name"); + my $option_desc = ""; + my $option_default_value = ""; + my $option_range = ""; + my $possible_values = ""; + my $re = qq(\Q$full_name); + if (grep (/^$re$/,$options_names[$current_line])) + { + $option_desc = weechat::infolist_string($optionlist, "description_nls"); + $option_desc = weechat::infolist_string($optionlist, "description") if ($option_desc eq ""); + $option_desc = "No help found" if ($option_desc eq ""); + $option_default_value = weechat::infolist_string($optionlist, "default_value"); + $possible_values = weechat::infolist_string($optionlist, "string_values") if (weechat::infolist_string($optionlist, "string_values") ne ""); + if ((weechat::infolist_string($optionlist, "type") eq "integer") && ($possible_values eq "")) + { + $option_range = weechat::infolist_integer($optionlist, "min") + ." .. ".weechat::infolist_integer($optionlist, "max"); + } + } + weechat::infolist_free($optionlist); + iset_title(); + + $description = weechat::color(weechat::config_color($options_iset{"color_help_option_name"})).$options_names[$current_line] + .weechat::color("bar_fg").": " + .weechat::color(weechat::config_color($options_iset{"color_help_text"})).$option_desc; + + # show additional infos like default value and possible values + + if (weechat::config_boolean($options_iset{"show_help_extra_info"}) == 1) + { + $description .= + weechat::color("bar_delim")." [" + .weechat::color("bar_fg")."default: " + .weechat::color("bar_delim")."\"" + .weechat::color(weechat::config_color($options_iset{"color_help_default_value"})).$option_default_value + .weechat::color("bar_delim")."\""; + if ($option_range ne "") + { + $description .= weechat::color("bar_fg").", values: ".$option_range; + } + if ($possible_values ne "") + { + $possible_values =~ s/\|/", "/g; # replace '|' to '", "' + $description .= weechat::color("bar_fg").", values: ". "\"" . $possible_values . "\""; + + } + $description .= weechat::color("bar_delim")."]"; + } + return $description; +} + +sub iset_check_condition_isetbar_cb +{ + my ($data, $modifier, $modifier_data, $string) = ($_[0], $_[1], $_[2], $_[3]); + my $buffer = weechat::window_get_pointer($modifier_data, "buffer"); + if ($buffer ne "") + { + if ((weechat::buffer_get_string($buffer, "plugin") eq $LANG) + && (weechat::buffer_get_string($buffer, "name") eq $PRGNAME)) + { + return "1"; + } + } + return "0"; +} + +sub iset_show_bar +{ + my $show = $_[0]; + my $barhidden = weechat::config_get("weechat.bar.isetbar.hidden"); + if ($barhidden) + { + if ($show) + { + if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1) + { + if (weechat::config_boolean($barhidden)) + { + weechat::config_option_set($barhidden, 0, 1); + } + } + } + else + { + if (!weechat::config_boolean($barhidden)) + { + weechat::config_option_set($barhidden, 1, 1); + } + } + } +} + +sub iset_signal_buffer_switch_cb +{ + my $buffer_pointer = $_[2]; + my $show_bar = 0; + $show_bar = 1 if (weechat::buffer_get_integer($iset_buffer, "num_displayed") > 0); + iset_show_bar($show_bar); + iset_check_line_outside_window() if ($buffer_pointer eq $iset_buffer); + return weechat::WEECHAT_RC_OK; +} + +sub iset_item_cb +{ + return iset_get_help(); +} + +sub iset_upgrade_ended +{ + iset_full_refresh(); +} + +sub iset_end +{ + # when script is unloaded, we hide bar + iset_show_bar(0); +} + +# -------------------------------[ mouse support ]------------------------------------- + +sub hook_focus_iset_cb +{ + my %info = %{$_[1]}; + my $bar_item_line = int($info{"_bar_item_line"}); + undef my $hash; + if (($info{"_buffer_name"} eq $PRGNAME) && $info{"_buffer_plugin"} eq $LANG && ($bar_item_line >= 0) && ($bar_item_line <= $#iset_focus)) + { + $hash = $iset_focus[$bar_item_line]; + } + else + { + $hash = {}; + my $hash_focus = $iset_focus[0]; + foreach my $key (keys %$hash_focus) + { + $hash->{$key} = "?"; + } + } + return $hash; +} + +# _chat_line_y contains selected line +sub iset_hsignal_mouse_cb +{ + my ($data, $signal, %hash) = ($_[0], $_[1], %{$_[2]}); + + if ($hash{"_buffer_name"} eq $PRGNAME && ($hash{"_buffer_plugin"} eq $LANG)) + { + if ($hash{"_key"} eq "button1") + { + $current_line = $hash{"_chat_line_y"}; + iset_refresh_line($current_line); + iset_refresh(); + } + elsif ($hash{"_key"} eq "button2") + { + if ($options_types[$hash{"_chat_line_y"}] eq "boolean") + { + iset_set_option($options_names[$hash{"_chat_line_y"}], "toggle"); + $current_line = $hash{"_chat_line_y"}; + iset_refresh_line($current_line); + iset_refresh(); + } + elsif ($options_types[$hash{"_chat_line_y"}] eq "string") + { + $current_line = $hash{"_chat_line_y"}; + iset_refresh_line($current_line); + iset_refresh(); + weechat::command("", "/$PRGNAME **set"); + } + } + elsif ($hash{"_key"} eq "button2-gesture-left" or $hash{"_key"} eq "button2-gesture-left-long") + { + if ($options_types[$hash{"_chat_line_y"}] eq "integer" or ($options_types[$hash{"_chat_line_y"}] eq "color")) + { + $current_line = $hash{"_chat_line_y"}; + iset_refresh_line($current_line); + iset_refresh(); + my $distance = distance($hash{"_chat_line_x"},$hash{"_chat_line_x2"}); + weechat::command("", "/repeat $distance /$PRGNAME **decr"); + } + } + elsif ($hash{"_key"} eq "button2-gesture-right" or $hash{"_key"} eq "button2-gesture-right-long") + { + if ($options_types[$hash{"_chat_line_y"}] eq "integer" or ($options_types[$hash{"_chat_line_y"}] eq "color")) + { + $current_line = $hash{"_chat_line_y"}; + iset_refresh_line($current_line); + iset_refresh(); + my $distance = distance($hash{"_chat_line_x"},$hash{"_chat_line_x2"}); + weechat::command("", "/repeat $distance /$PRGNAME **incr"); + } + } + } +} +sub distance +{ + my ($x1,$x2) = ($_[0], $_[1]); + my $distance; + $distance = $x1 - $x2; + $distance = abs($distance); + if ($distance > 0) + { + use integer; + $distance = $distance / 3; + $distance = 1 if ($distance == 0); + } + elsif ($distance == 0) + { + $distance = 1; + } + return $distance; +} + +# -----------------------------------[ config ]--------------------------------------- + +sub iset_config_init +{ + $iset_config_file = weechat::config_new($ISET_CONFIG_FILE_NAME,"iset_config_reload_cb",""); + return if ($iset_config_file eq ""); + + # section "color" + my $section_color = weechat::config_new_section($iset_config_file,"color", 0, 0, "", "", "", "", "", "", "", "", "", ""); + if ($section_color eq "") + { + weechat::config_free($iset_config_file); + return; + } + $options_iset{"color_option"} = weechat::config_new_option( + $iset_config_file, $section_color, + "option", "color", "Color for option name in iset buffer", "", 0, 0, + "default", "default", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_option_selected"} = weechat::config_new_option( + $iset_config_file, $section_color, + "option_selected", "color", "Color for selected option name in iset buffer", "", 0, 0, + "white", "white", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_type"} = weechat::config_new_option( + $iset_config_file, $section_color, + "type", "color", "Color for option type (integer, boolean, string)", "", 0, 0, + "brown", "brown", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_type_selected"} = weechat::config_new_option( + $iset_config_file, $section_color, + "type_selected", "color", "Color for selected option type (integer, boolean, string)", "", 0, 0, + "yellow", "yellow", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_value"} = weechat::config_new_option( + $iset_config_file, $section_color, + "value", "color", "Color for option value", "", 0, 0, + "cyan", "cyan", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_value_selected"} = weechat::config_new_option( + $iset_config_file, $section_color, + "value_selected", "color", "Color for selected option value", "", 0, 0, + "lightcyan", "lightcyan", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_value_undef"} = weechat::config_new_option( + $iset_config_file, $section_color, + "value_undef", "color", "Color for option value undef", "", 0, 0, + "green", "green", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_value_undef_selected"} = weechat::config_new_option( + $iset_config_file, $section_color, + "value_undef_selected", "color", "Color for selected option value undef", "", 0, 0, + "lightgreen", "lightgreen", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_bg_selected"} = weechat::config_new_option( + $iset_config_file, $section_color, + "bg_selected", "color", "Background color for current selected option", "", 0, 0, + "red", "red", 0, "", "", "full_refresh_cb", "", "", ""); + $options_iset{"color_help_option_name"} = weechat::config_new_option( + $iset_config_file, $section_color, + "help_option_name", "color", "Color for option name in help-bar", "", 0, 0, + "white", "white", 0, "", "", "bar_refresh", "", "", ""); + $options_iset{"color_help_text"} = weechat::config_new_option( + $iset_config_file, $section_color, + "help_text", "color", "Color for option description in help-bar", "", 0, 0, + "default", "default", 0, "", "", "bar_refresh", "", "", ""); + $options_iset{"color_help_default_value"} = weechat::config_new_option( + $iset_config_file, $section_color, + "help_default_value", "color", "Color for default option value in help-bar", "", 0, 0, + "green", "green", 0, "", "", "bar_refresh", "", "", ""); + + # section "help" + my $section_help = weechat::config_new_section($iset_config_file,"help", 0, 0, "", "", "", "", "", "", "", "", "", ""); + if ($section_help eq "") + { + weechat::config_free($iset_config_file); + return; + } + $options_iset{"show_help_bar"} = weechat::config_new_option( + $iset_config_file, $section_help, + "show_help_bar", "boolean", "Show help bar", "", 0, 0, + "on", "on", 0, "", "", "toggle_help_cb", "", "", ""); + $options_iset{"show_help_extra_info"} = weechat::config_new_option( + $iset_config_file, $section_help, + "show_help_extra_info", "boolean", "Show additional information in help bar (default value, max./min. value) ", "", 0, 0, + "on", "on", 0, "", "", "", "", "", ""); + $options_iset{"show_plugin_description"} = weechat::config_new_option( + $iset_config_file, $section_help, + "show_plugin_description", "boolean", "Show plugin description in iset buffer", "", 0, 0, + "on", "on", 0, "", "", "full_refresh_cb", "", "", ""); + + # section "look" + my $section_look = weechat::config_new_section($iset_config_file, "look", 0, 0, "", "", "", "", "", "", "", "", "", ""); + if ($section_look eq "") + { + weechat::config_free($iset_config_file); + return; + } + $options_iset{"value_search_char"} = weechat::config_new_option( + $iset_config_file, $section_look, + "value_search_char", "string", "Trigger char to tell iset to search for value instead of option (for example: =red)", "", 0, 0, + "=", "=", 0, "", "", "", "", "", ""); + $options_iset{"scroll_horiz"} = weechat::config_new_option( + $iset_config_file, $section_look, + "scroll_horiz", "integer", "scroll content of iset buffer n%", "", 1, 100, + "10", "10", 0, "", "", "", "", "", ""); + $options_iset{"show_current_line"} = weechat::config_new_option( + $iset_config_file, $section_look, + "show_current_line", "boolean", "show current line in title bar.", "", 0, 0, + "on", "on", 0, "", "", "", "", "", ""); +} + +sub iset_config_reload_cb +{ + my ($data,$config_file) = ($_[0], $_[1]); + return weechat::config_reload($config_file) +} + +sub iset_config_read +{ + return weechat::config_read($iset_config_file) if ($iset_config_file ne ""); +} + +sub iset_config_write +{ + return weechat::config_write($iset_config_file) if ($iset_config_file ne ""); +} + +sub full_refresh_cb +{ + iset_full_refresh(); + return weechat::WEECHAT_RC_OK; +} + +sub bar_refresh +{ + iset_get_help(1); + weechat::bar_item_update("isetbar_help") if (weechat::config_boolean($options_iset{"show_help_bar"}) == 1); + return weechat::WEECHAT_RC_OK; +} + +sub toggle_help_cb +{ + my $value = weechat::config_boolean($options_iset{"show_help_bar"}); + iset_show_bar($value); + return weechat::WEECHAT_RC_OK; +} + +# -----------------------------------[ main ]----------------------------------------- + +weechat::register($PRGNAME, $AUTHOR, $VERSION, $LICENSE, + $DESCR, "iset_end", ""); + +$wee_version_number = weechat::info_get("version_number", "") || 0; + +iset_config_init(); +iset_config_read(); + +weechat::hook_command($PRGNAME, "Interactive set", "f || s
|| [=]", + "f file : show options for a file\n". + "s section : show options for a section\n". + "text : show options with 'text' in name\n". + weechat::config_string($options_iset{"value_search_char"})."text : show options with 'text' in value\n\n". + "Keys for iset buffer:\n". + "f11,f12 : move iset content left/right\n". + "up,down : move one option up/down\n". + "pgup,pdwn : move one page up/down\n". + "home,end : move to first/last option\n". + "ctrl+'L' : refresh options and screen\n". + "alt+space : toggle boolean on/off\n". + "alt+'+' : increase value (for integer or color)\n". + "alt+'-' : decrease value (for integer or color)\n". + "alt+'i',alt+'r': reset value of option\n". + "alt+'i',alt+'u': unset option\n". + "alt+enter : set new value for option (edit it with command line)\n". + "text,enter : set a new filter using command line (use '*' to see all options)\n". + "alt+'v' : toggle help bar on/off\n". + "alt+'p' : toggle option \"show_plugin_description\" on/off\n". + "\n". + "standard mouse actions:\n". + "wheel up / wheel down : move option up/down\n". + "left-mouse-button : select an option from list\n". + "right-mouse-button : toggle boolean (on/off) or set a new value for option (edit it with command line)\n". + "right-mouse-button + gesture left/right: increase/decrease value (for integer or color)\n". + "\n". + "Examples:\n". + " show options for file 'weechat'\n". + " /iset f weechat\n". + " show options for file 'irc'\n". + " /iset f irc\n". + " show options for section 'look'\n". + " /iset s look\n". + " show all options with text 'nicklist' in name\n". + " /iset nicklist\n". + " show all values which contain 'red'. '" . weechat::config_string($options_iset{"value_search_char"}) . "' is a trigger char.\n". + " /iset ". weechat::config_string($options_iset{"value_search_char"}) ."red\n", + "", "iset_cmd_cb", ""); +weechat::hook_signal("upgrade_ended", "iset_upgrade_ended", ""); +weechat::hook_signal("window_scrolled", "iset_signal_window_scrolled_cb", ""); +weechat::hook_signal("buffer_switch", "iset_signal_buffer_switch_cb",""); +weechat::bar_item_new("isetbar_help", "iset_item_cb", ""); +weechat::bar_new("isetbar", "on", "0", "window", "", "top", "horizontal", + "vertical", "3", "3", "default", "cyan", "default", "1", + "isetbar_help"); +weechat::hook_modifier("bar_condition_isetbar", "iset_check_condition_isetbar_cb", ""); +weechat::hook_config("*", "iset_config_cb", ""); +$iset_buffer = weechat::buffer_search($LANG, $PRGNAME); +iset_init() if ($iset_buffer ne ""); + +if ($wee_version_number >= 0x00030600) +{ + weechat::hook_focus("chat", "hook_focus_iset_cb", ""); + weechat::hook_hsignal($PRGNAME."_mouse", "iset_hsignal_mouse_cb", ""); + weechat::key_bind("mouse", \%mouse_keys); +} diff --git a/weechat/plugins.conf b/weechat/plugins.conf new file mode 100644 index 0000000..70d1c69 --- /dev/null +++ b/weechat/plugins.conf @@ -0,0 +1,63 @@ +# +# plugins.conf -- weechat v0.3.8 +# + +[var] +fifo.fifo = "on" +guile.check_license = "on" +lua.check_license = "on" +perl.beep.beep_command_dcc = "growlnotify -m 'Someone sent you DCC' IRC DCC" +perl.beep.beep_command_highlight = "growlnotify -m 'Someone mentioned your name on weechat' IRC Highlight" +perl.beep.beep_command_pv = "growlnotify -m 'Someone sent you a private message' IRC Private Message" +perl.beep.beep_command_timeout = "30000" +perl.beep.beep_dcc = "on" +perl.beep.beep_highlight = "on" +perl.beep.beep_highlight_blacklist = "off" +perl.beep.beep_highlight_whitelist = "off" +perl.beep.beep_pv = "on" +perl.beep.beep_pv_blacklist = "off" +perl.beep.beep_pv_whitelist = "off" +perl.beep.beep_trigger_highlight = "" +perl.beep.beep_trigger_pv = "" +perl.beep.bell_always = "" +perl.beep.blacklist_nicks = "" +perl.beep.whitelist_channels = "" +perl.beep.whitelist_nicks = "" +perl.chanmon.alignment = "nchannel" +perl.chanmon.bar_lines = "10" +perl.chanmon.color_buf = "on" +perl.chanmon.dynamic = "off" +perl.chanmon.logging = "off" +perl.chanmon.merge_private = "on" +perl.chanmon.nick_prefix = "<" +perl.chanmon.nick_suffix = ">" +perl.chanmon.output = "bar" +perl.chanmon.short_names = "on" +perl.chanmon.show_aways = "off" +perl.check_license = "on" +python.check_license = "on" +python.screen_away.away_suffix = "[away]" +python.screen_away.command_on_attach = "" +python.screen_away.command_on_detach = "" +python.screen_away.interval = "5" +python.screen_away.message = "Detached from tmux" +tcl.check_license = "on" + +[desc] +perl.beep.beep_command_dcc = "command for beep on dcc, special value "$bell" is allowed, as well as "$bell;command" (default: "$bell")" +perl.beep.beep_command_highlight = "command for beep on highlight, special value "$bell" is allowed, as well as "$bell;command" (default: "$bell")" +perl.beep.beep_command_pv = "command for beep on private message, special value "$bell" is allowed, as well as "$bell;command" (default: "$bell")" +perl.beep.beep_command_timeout = "timeout for command run (in milliseconds, 0 = never kill (not recommended)) (default: "30000")" +perl.beep.beep_dcc = "beep on dcc (default: "on")" +perl.beep.beep_highlight = "beep on highlight (default: "on")" +perl.beep.beep_highlight_blacklist = "turn blacklist for highlights on or off (default: "off")" +perl.beep.beep_highlight_whitelist = "turn whitelist for highlights on or off (default: "off")" +perl.beep.beep_pv = "beep on private message (default: "on")" +perl.beep.beep_pv_blacklist = "turn blacklist for private messages on or off (default: "off")" +perl.beep.beep_pv_whitelist = "turn whitelist for private messages on or off (default: "off")" +perl.beep.beep_trigger_highlight = "word that will trigger execution of beep_command_highlight (if empty, anything will trigger) (default: "")" +perl.beep.beep_trigger_pv = "word that will trigger execution of beep_command_pv (it empty, anything will trigger) (default: "")" +perl.beep.bell_always = "use $bell on private messages and/or highlights regardless of trigger and whitelist settings (example: "pv,highlight") (default: "")" +perl.beep.blacklist_nicks = "comma-separated list of "server.nick": if not empty, these nicks will not be able to trigger execution of commands. Cannot be used in conjuction with whitelist (example: "freenode.nick1,freenode.nick2") (default: "")" +perl.beep.whitelist_channels = "comma-separated list of "server.#channel": if not empty, only these channels will trigger execution of commands (example: "freenode.#weechat,freenode.#channel2") (default: "")" +perl.beep.whitelist_nicks = "comma-separated list of "server.nick": if not empty, only these nicks will trigger execution of commands (example: "freenode.nick1,freenode.nick2") (default: "")" diff --git a/weechat/python/autoload/screen_away.py b/weechat/python/autoload/screen_away.py new file mode 120000 index 0000000..e485b70 --- /dev/null +++ b/weechat/python/autoload/screen_away.py @@ -0,0 +1 @@ +../screen_away.py \ No newline at end of file diff --git a/weechat/python/autoload/upside_down.py b/weechat/python/autoload/upside_down.py new file mode 120000 index 0000000..fb007ad --- /dev/null +++ b/weechat/python/autoload/upside_down.py @@ -0,0 +1 @@ +../upside_down.py \ No newline at end of file diff --git a/weechat/python/autoload/weeget.py b/weechat/python/autoload/weeget.py new file mode 100644 index 0000000..8622ef6 --- /dev/null +++ b/weechat/python/autoload/weeget.py @@ -0,0 +1,980 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2009-2012 Sebastien Helleu +# +# 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 . +# + +# +# WeeChat scripts manager. +# (this script requires WeeChat >= 0.3.0 and python >= 2.6) +# +# History: +# +# 2012-03-09, Sebastien Helleu : +# version 1.8: fix reload of config file +# 2012-02-27, Sebastien Helleu : +# version 1.7: add support of scheme scripts +# 2012-02-05, Sebastien Helleu : +# version 1.6: use URL transfer from API (for WeeChat >= 0.3.7) +# 2012-01-03, Sebastien Helleu : +# version 1.5: make script compatible with Python 3.x +# 2011-03-25, Sebastien Helleu : +# version 1.4: add completion with installed scripts for action "remove" +# 2011-03-10, Sebastien Helleu : +# 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 : +# version 1.2: use new help format for command arguments +# 2010-11-08, Sebastien Helleu : +# 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 : +# version 1.0: add action "listinstalled" for command /weeget +# 2010-01-25, Sebastien Helleu : +# version 0.9: fix "running" status of scripts with /weeget check +# 2009-09-30, Sebastien Helleu : +# 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 : +# version 0.7: update weechat site with new URL +# 2009-05-02, Sebastien Helleu : +# version 0.6: sync with last API changes +# 2009-04-15, Sebastien Helleu : +# version 0.5: display missing module(s) when import failed +# 2009-04-11, Sebastien Helleu : +# version 0.4: use new completion for command arguments +# 2009-04-07, Sebastien Helleu : +# 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 : +# version 0.2: add author's mail in script description +# 2009-04-05, Sebastien Helleu : +# version 0.1: initial release +# + +SCRIPT_NAME = "weeget" +SCRIPT_AUTHOR = "Sebastien Helleu " +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 + 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 [|] || show