# -*- coding: utf-8 -*- # # Copyright (C) 2011-2014 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 . # # # Browse WeeChat/plugins hdata in a dedicated buffer. # (this script requires WeeChat 0.3.6 or newer) # # History: # # 2012-08-23, Sebastien Helleu : # version 0.5: add support of update in hdata # 2012-07-20, Sebastien Helleu : # version 0.4: add support of array size in hdata variables # 2012-01-02, Sebastien Helleu : # version 0.3: make script compatible with Python 3.x # 2011-12-19, Sebastien Helleu : # version 0.2: add hdata type "hashtable" # 2011-06-26, Sebastien Helleu : # version 0.1: initial version # SCRIPT_NAME = 'hdata' SCRIPT_AUTHOR = 'Sebastien Helleu ' SCRIPT_VERSION = '0.5' SCRIPT_LICENSE = 'GPL3' SCRIPT_DESC = 'Browse WeeChat/plugins hdata' SCRIPT_COMMAND = 'hdata' SCRIPT_BUFFER = 'hdata' 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: from operator import itemgetter except ImportError as message: print('Missing package(s) for %s: %s' % (SCRIPT_NAME, message)) import_ok = False hdata_buffer = '' hdata_current = ['list', '', ''] hdata_history = [] hdata_list = [] hdata_line = 0 hdata_history_line = [] def hdata_reset(): global hdata_current, hdata_history, hdata_list, hdata_line, hdata_history_line hdata_current = ['list', '', ''] hdata_history = [] hdata_list = [] hdata_line = 0 hdata_history_line = [] def hdata_buffer_input_cb(data, buffer, string): """Callback for input on hdata buffer.""" if string in ('q', 'Q'): weechat.buffer_close(buffer) return weechat.WEECHAT_RC_OK def hdata_buffer_close_cb(data, buffer): """Callback for close of hdata buffer.""" global hdata_buffer hdata_buffer = '' hdata_reset() return weechat.WEECHAT_RC_OK def hdata_set_title(): """Set buffer title.""" global hdata_buffer, hdata_current_, hdata_history if len(hdata_history) > 3: history = ['...'] + hdata_history[-3:] else: history = hdata_history[:] history.reverse() weechat.buffer_set(hdata_buffer, 'title', 'Hdata: %s | History: %s' % (str(hdata_current), str(history))) def hdata_init_buffer(): """Initialize hdata buffer.""" global hdata_buffer, hdata_current hdata_buffer = weechat.buffer_search('python', SCRIPT_BUFFER) if not hdata_buffer: hdata_buffer = weechat.buffer_new(SCRIPT_BUFFER, 'hdata_buffer_input_cb', '', 'hdata_buffer_close_cb', '') if hdata_buffer: weechat.buffer_set(hdata_buffer, 'type', 'free') hdata_set_title() weechat.buffer_set(hdata_buffer, 'key_bind_meta2-A', '/hdata **up') weechat.buffer_set(hdata_buffer, 'key_bind_meta2-B', '/hdata **down') weechat.buffer_set(hdata_buffer, 'key_bind_meta2-C', '/hdata **right') weechat.buffer_set(hdata_buffer, 'key_bind_meta2-D', '/hdata **left') weechat.buffer_set(hdata_buffer, 'key_bind_-', '/hdata **previous') weechat.buffer_set(hdata_buffer, 'key_bind_+', '/hdata **next') weechat.buffer_set(hdata_buffer, 'key_bind_meta-u', '/hdata **update') weechat.buffer_set(hdata_buffer, 'key_bind_ctrl-L', '/hdata **refresh') weechat.buffer_set(hdata_buffer, 'display', '1') def hdata_get_list(): """Get list of hdata or list of lists/vars in hdata.""" global hdata_current, hdata_list hdata_list = [] if hdata_current[0] == 'list': # get list of hdata infolist = weechat.infolist_get('hook', '', 'hdata') while weechat.infolist_next(infolist): hdata_list.append({ 'name': weechat.infolist_string(infolist, 'hdata_name'), 'plugin': weechat.infolist_string(infolist, 'plugin_name') or 'weechat', 'description': weechat.infolist_string(infolist, 'description_nls') }) weechat.infolist_free(infolist) else: # get content of a hdata hdata = weechat.hdata_get(hdata_current[1]) if hdata: list2 = [] list_lists = weechat.hdata_get_string(hdata, 'list_keys') if list_lists: for l in list_lists.split(','): list2.append({ 'name': l, 'offset': '---', 'type': 'list', 'update_allowed': 0, 'array_size': -1, 'hdata': '', 'value': weechat.hdata_get_list(hdata, l) }) list2 = sorted(list2, key=itemgetter('name')) hdata_list += list2 list2 = [] list_prevnext = [] var_prev = weechat.hdata_get_string(hdata, 'var_prev') var_next = weechat.hdata_get_string(hdata, 'var_next') list_vars = weechat.hdata_get_string(hdata, 'var_keys') if list_vars: for v in list_vars.split(','): t = weechat.hdata_get_var_type_string(hdata, v) value = '' array_size = -1 if hdata_current[2]: array_size = weechat.hdata_get_var_array_size(hdata, hdata_current[2], v) max_array_size = array_size if array_size >= 0 else 1 for i in range(0, max_array_size): v2 = '%d|%s' % (i, v) if value != '': value += ',' if t == 'char': value += str(weechat.hdata_char(hdata, hdata_current[2], v2)) elif t == 'integer': value += str(weechat.hdata_integer(hdata, hdata_current[2], v2)) elif t == 'long': value += str(weechat.hdata_long(hdata, hdata_current[2], v2)) elif t == 'string': value += weechat.hdata_string(hdata, hdata_current[2], v2) elif t == 'pointer': value += weechat.hdata_pointer(hdata, hdata_current[2], v2) elif t == 'time': value += str(weechat.hdata_time(hdata, hdata_current[2], v2)) elif t == 'hashtable': value += str(weechat.hdata_hashtable(hdata, hdata_current[2], v2)) h = { 'name': v, 'offset': weechat.hdata_get_var_offset(hdata, v), 'type': weechat.hdata_get_var_type_string(hdata, v), 'array_size': array_size, 'hdata': weechat.hdata_get_var_hdata(hdata, v), 'update_allowed': weechat.hdata_update(hdata, '', { '__update_allowed': v }), 'value': value, 'prevnext': 0 } if v == var_prev: h['prevnext'] = 1 list_prevnext.insert(0, h) elif v == var_next: h['prevnext'] = 1 list_prevnext.append(h) else: list2.append(h) list2 = sorted(list2, key=itemgetter('offset')) if list_prevnext: hdata_list += list_prevnext hdata_list += list2 def hdata_display(): global hdata_buffer, hdata_current, hdata_list, hdata_line if not hdata_list: hdata_get_list() if hdata_line >= len(hdata_list): hdata_line = 0 weechat.prnt_y(hdata_buffer, 0, 'Keys: left=back, right=select, "-"=previous, "+"=next, alt-u=update | Actions: "q"=close buffer') weechat.prnt_y(hdata_buffer, 1, '') weechat.prnt_y(hdata_buffer, 3, '%s%s' % (weechat.color('240'), '─' * 300)) y = 4 if hdata_current[0] == 'list': fmt = '%s%-30s %-12s %s' weechat.prnt_y(hdata_buffer, 2, fmt % (weechat.color('white'), 'Hdata', 'Plugin', 'Description')) for i, hdata in enumerate(hdata_list): if i == hdata_line: color = weechat.color('white,60') else: color = '' weechat.prnt_y(hdata_buffer, y, fmt % (color, hdata['name'], hdata['plugin'], hdata['description'])) y += 1 else: fmt = '%s%-34s %-5s %-13s %-1s %-5s %-30s %s' weechat.prnt_y(hdata_buffer, 2, fmt % (weechat.color('white'), 'Name', 'Ofs', 'Type', 'W', 'Array', 'Hdata', 'Value')) colors = [{ 'list': 'brown', 'prevnext': 'green', '*': 'chat' }, { 'list': 'yellow,60', 'prevnext': 'lightgreen,60', '*': 'white,60' }] for i, var in enumerate(hdata_list): if i == hdata_line: colors2 = colors[1] else: colors2 = colors[0] if var['type'] == 'list': color = colors2['list'] elif var['prevnext']: color = colors2['prevnext'] else: color = colors2['*'] str_w = 'W' if var['type'] != 'list' and var['update_allowed'] else ' ' str_array_size = str(var['array_size']) if var['array_size'] >= 0 else '' weechat.prnt_y(hdata_buffer, y, fmt % (weechat.color(color), var['name'], var['offset'], var['type'], str_w, str_array_size, var['hdata'], var['value'])) y += 1 def hdata_move(shift): """Move to another element in list.""" if hdata_current[0] == 'hdata': pointer = weechat.hdata_move(weechat.hdata_get(hdata_current[1]), hdata_current[2], shift) if pointer: hdata_current[2] = pointer hdata_get_list() hdata_set_title() hdata_display() def hdata_refresh(): global hdata_buffer hdata_get_list() weechat.buffer_clear(hdata_buffer) hdata_set_title() hdata_display() weechat.command(hdata_buffer, '/window refresh') def hdata_cmd_cb(data, buffer, args): """Callback for /hdata command.""" global hdata_buffer, hdata_current, hdata_history, hdata_list, hdata_line if not hdata_buffer: hdata_init_buffer() if hdata_buffer: if args.startswith('**'): if args == '**up': if hdata_line > 0: hdata_line -= 1 hdata_display() elif args == '**down': if hdata_line < len(hdata_list) - 1: hdata_line += 1 hdata_display() elif args == '**left': if len(hdata_history) > 0: hdata_current = hdata_history.pop() hdata_line = hdata_history_line.pop() hdata_get_list() weechat.buffer_clear(hdata_buffer) hdata_set_title() hdata_display() elif args == '**right': old_current = hdata_current[:] old_line = hdata_line go = False if hdata_current[0] == 'list': hdata = hdata_list[hdata_line] hdata_current = ['hdata', hdata['name'], ''] hdata_line = 0 go = True else: var = hdata_list[hdata_line] if var['type'] == 'list': if var['value']: hdata_current[2] = var['value'] go = True elif var['hdata']: if var['value']: if var['hdata'] != hdata_current[1]: hdata_line = 0 hdata_current[1] = var['hdata'] hdata_current[2] = var['value'] go = True if go: hdata_history.append(old_current) hdata_history_line.append(old_line) hdata_get_list() weechat.buffer_clear(hdata_buffer) hdata_set_title() hdata_display() elif args == '**previous': hdata_move(-1) elif args == '**next': hdata_move(+1) elif args == '**update': if hdata_list[hdata_line].get('update_allowed', 0): cmdline = '/hdata update %s' % weechat.string_remove_color(hdata_list[hdata_line]['value'], '') weechat.buffer_set(hdata_buffer, 'input', cmdline) weechat.buffer_set(hdata_buffer, 'input_pos', '%d' % len(cmdline)) elif args == '**refresh': hdata_refresh() else: argv = args.split(' ', 1) if argv[0] == 'update' and len(argv) > 1: if hdata_list[hdata_line].get('update_allowed', 0): weechat.hdata_update(weechat.hdata_get(hdata_current[1]), hdata_current[2], { hdata_list[hdata_line]['name']: argv[1] }) hdata_refresh() else: hdata_display() return weechat.WEECHAT_RC_OK if __name__ == '__main__' and import_ok: if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', ''): weechat.hook_command(SCRIPT_COMMAND, 'Browse WeeChat/plugins hdata in a dedicated buffer.', '', '', '', 'hdata_cmd_cb', '')