]> git.rmz.io Git - dotfiles.git/blob - weechat/ruby/colorizer.rb
mpd: add extended m3u playlist plugin support
[dotfiles.git] / weechat / ruby / colorizer.rb
1 # vim: set noet nosta sw=4 ts=4 :
2 #
3 # Colorizer
4 # Michael B. Hix <m@hix.io>
5 # http://code.hix.io/projects/colorizer
6 #
7 # Color certain parts of text in certain buffers based on rules.
8 #
9
10 #
11 # Options:
12 #
13 # plugins.var.ruby.colorizer.buffer_regex
14 # Buffers with names matching this regex are colorized. All buffers are
15 # colorized if this option is empty.
16 #
17 # plugins.var.ruby.colorizer.rule.count
18 # This is the maximum number of rules to load.
19 #
20 # plugins.var.ruby.colorizer.rule.X
21 # X is zero or a positive integer. Rules are strings consisting of a regular
22 # expression followed immediately by a slash and a Weechat color name. The
23 # regular expressions are case-insensitive.
24 #
25 # Text matching the regular expression is colored with the given color. The
26 # last match "wins" and overlapping matches are not detected.
27 #
28 # For example: "strelka|mongrel2/lightgreen"
29 #
30
31 #
32 # Changelog:
33 #
34 # 0.1: Initial release.
35 #
36
37 SCRIPT_NAME = 'colorizer'
38 SCRIPT_AUTHOR = 'Michael B. Hix'
39 SCRIPT_DESC = 'Colorize text in buffers based on rules.'
40 SCRIPT_VERSION = '0.1'
41 SCRIPT_LICENSE = 'BSD'
42
43 # A default coloring rule.
44 #
45 DEFAULT_RULE = {
46 :value => '',
47 :description => 'A colorizing rule of the form: <regular_expression>/<weechat_color_name> Empty rules are ignored.',
48 }.freeze
49
50 # Configuration defaults are supplied and set for the user if they're not already set.
51 #
52 DEFAULTS = {
53 'rule.0' => DEFAULT_RULE,
54 'rule.1' => DEFAULT_RULE,
55 'rule.2' => DEFAULT_RULE,
56 'rule.3' => DEFAULT_RULE,
57 'rule.4' => DEFAULT_RULE,
58 'rule.count' => {
59 :value => 10,
60 :description => 'The maximum number of rules to look for in your config.',
61 },
62 'buffer_regex' => {
63 :value => '',
64 :description => 'Only colorize text in buffers with names that match this regex. Leaving this empty matches all buffer names.',
65 },
66 }.freeze
67
68 ########################################################################
69 ### I N I T
70 ########################################################################
71
72 def weechat_init
73 Weechat.register SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', ''
74
75 Weechat.hook_modifier( 'weechat_print', 'colorize_cb', '' )
76
77 DEFAULTS.each_pair do |option, opts|
78 value = opts[:value]
79 description = opts[:description]
80
81 cur_value = Weechat.config_get_plugin( option )
82
83 if cur_value.nil? || cur_value.empty?
84 Weechat.config_set_plugin( option, value.to_s )
85 end
86
87 Weechat.config_set_desc_plugin( option, description )
88 end
89
90 parse_config
91
92 Weechat.hook_config( "plugins.var.ruby.#{SCRIPT_NAME}.*", 'config_cb', '' )
93
94 return Weechat::WEECHAT_RC_OK
95 end
96
97 ################################################################################
98 ### U T I L I T I E S
99 ################################################################################
100
101 # Provide a way to print legible stack traces.
102 #
103 def pp_error( e, message = '' )
104 return unless e.is_a? Exception
105 unless message.nil? or message.empty?
106 Weechat.print( '', '%s%s' % [Weechat.prefix('error'), message] )
107 end
108 Weechat.print( '', '%s%s: %s' % [Weechat.prefix( 'error' ), SCRIPT_NAME, e.to_s] )
109 e.backtrace.each do |line|
110 Weechat.print( '', '%s%s' % [Weechat.prefix( 'error' ), line] )
111 end
112 end
113
114 # Re-build rules and any regular expressions when the config changes.
115 #
116 def parse_config
117 rules = {}
118 count = Weechat::config_get_plugin( 'rule.count' ).to_i ||
119 DEFAULTS['rule.count']
120
121 count.times do |i|
122 key = "rule.#{i}"
123 next unless Weechat::config_is_set_plugin( key )
124
125 conf = Weechat::config_get_plugin( key )
126 regex,color,_ = conf.split( /(?<!\\)\//, 3 )
127
128 next if regex.nil? or regex.empty? or color.nil? or color.empty?
129
130 begin
131 rules[/(#{regex})/i] = color
132 rescue Exception => e
133 pp_error( e, 'There was a problem with rule %d:' % [i] )
134 end
135 end
136
137 @rules = rules
138
139 begin
140 @buffer_regex = /#{Weechat::config_get_plugin( 'buffer_regex' )}/i
141 rescue Exception => e
142 pp_error( e, 'There was a problem with buffer_regex:' )
143 end
144 end
145
146 ################################################################################
147 ### C A L L B A C K S
148 ################################################################################
149
150 # Handle configuration changes.
151 #
152 def config_cb( data, option, value )
153 parse_config
154 return Weechat::WEECHAT_RC_OK
155 end
156
157 # Handle message printing.
158 #
159 def colorize_cb( data, modifier, modifier_data, message )
160 _,buffer,_ = modifier_data.split( ';' )
161 return message unless @buffer_regex =~ buffer
162
163 reset = Weechat.color( 'reset' )
164 @rules.each do |reg, color_str|
165 color = Weechat.color( color_str )
166 message.gsub!( reg, '%s\1%s' % [color,reset] )
167 end
168
169 return message
170 end
171
172 __END__
173 __LICENSE__
174
175 Copyright (c) 2014 Michael B. Hix
176 All rights reserved.
177
178 Redistribution and use in source and binary forms, with or without
179 modification, are permitted provided that the following conditions are met:
180
181 1. Redistributions of source code must retain the above copyright notice,
182 this list of conditions and the following disclaimer.
183
184 2. Redistributions in binary form must reproduce the above copyright notice,
185 this list of conditions and the following disclaimer in the documentation
186 and/or other materials provided with the distribution.
187
188 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
189 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
192 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
193 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
194 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
195 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
196 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
197 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
198 POSSIBILITY OF SUCH DAMAGE.