weechat/doc/en/weechat_dev.en.asciidoc

1096 lines
40 KiB
Plaintext
Raw Normal View History

2014-02-02 09:49:59 +01:00
= WeeChat developer's guide
:author: Sébastien Helleu
:email: flashcode@flashtux.org
:lang: en
:toc2:
:toclevels: 3
:max-width: 100%
This manual documents WeeChat chat client, it is part of WeeChat.
Latest version of this document can be found on this page:
2014-12-13 09:16:09 +01:00
https://weechat.org/doc
[[introduction]]
== Introduction
WeeChat (Wee Enhanced Environment for Chat) is a free chat client, fast and
light, designed for many operating systems.
This manual documents WeeChat internals:
* repositories
* coding rules
* core internals
* plugin internals
* how to contribute to WeeChat.
[[repositories]]
== Repositories
WeeChat repositories are on GitHub organization "weechat":
https://github.com/weechat
List of repositories:
weechat::
core repository with source code and documentation
scripts::
the 'official' scripts submitted on weechat.org
weechat.org::
source of WeeChat web site: https://weechat.org/
weercd::
IRC testing server
qweechat::
Qt remote GUI for WeeChat.
This manual documents only 'weechat' repository.
[[overview]]
=== Overview
The main WeeChat directories are:
[width="100%",cols="1v,5",options="header"]
|===
2015-03-07 15:16:37 +01:00
| Directory | Description
| src/ | Root of sources
| core/ | Core functions: entry point, internal structures
| gui/ | Functions for buffers, windows, ... (used by all interfaces)
| curses/ | Curses interface
| plugins/ | Plugin and scripting API
| alias/ | Alias plugin
| aspell/ | Aspell plugin
| charset/ | Charset plugin
| exec/ | Exec plugin
| fifo/ | Fifo plugin (FIFO pipe used to remotely send commands to WeeChat)
| irc/ | IRC (Internet Relay Chat) plugin
| logger/ | Logger plugin (write messages displayed to files)
| relay/ | Relay plugin (irc proxy + relay for remote interfaces)
| script/ | Scripts manager
| python/ | Python scripting API
| perl/ | Perl scripting API
| ruby/ | Ruby scripting API
| lua/ | Lua scripting API
| tcl/ | Tcl scripting API
| guile/ | Guile (scheme) scripting API
| javascript/ | Javascript scripting API
| trigger/ | Trigger plugin
| xfer/ | Xfer plugin (IRC DCC file/chat)
| tests/ | Tests
| unit/ | Unit tests
| core/ | Unit tests for core functions
| doc/ | Documentation
| po/ | Translations files (gettext)
| debian/ | Debian packaging
|===
[[sources]]
=== Sources
[[sources_core]]
==== Core
2014-02-02 09:49:59 +01:00
WeeChat "core" is located in following directories:
* 'src/core/': core functions (for data manipulation)
* 'src/gui/': functions about interface (buffers, windows, ...)
[width="100%",cols="1v,5",options="header"]
|===
| Path/file | Description
| core/ | Core functions: entry point, internal structures
| weechat.c | Main functions: command line options, startup
| wee-arraylist.c | Array lists
2014-02-02 09:49:59 +01:00
| wee-backtrace.c | Display a backtrace after a crash
| wee-command.c | WeeChat core commands
2014-02-02 09:49:59 +01:00
| wee-completion.c | Default completions
| wee-config-file.c | Configuration file management
| wee-config.c | Configuration options for WeeChat core (file weechat.conf)
| wee-debug.c | Some debug functions
2014-02-02 09:49:59 +01:00
| wee-eval.c | Evaluation of expressions with references to internal vars
| wee-hashtable.c | Hashtables
| wee-hdata.c | Hdata (direct access to data using hashtables)
| wee-hook.c | Hooks
2014-02-02 09:49:59 +01:00
| wee-infolist.c | Infolists (lists with objects data)
| wee-input.c | Input of commands/text
| wee-list.c | Sorted lists
| wee-log.c | Write to WeeChat log file (weechat.log)
2014-02-02 09:49:59 +01:00
| wee-network.c | Network functions (connection to servers/proxies)
| wee-proxy.c | Proxy management
| wee-secure.c | Secured data options (file sec.conf)
| wee-string.c | Functions on strings
| wee-upgrade-file.c | Internal upgrade system
| wee-upgrade.c | Upgrade for WeeChat core (buffers, lines, history, ...)
| wee-url.c | URL transfer (using libcurl)
| wee-utf8.c | UTF-8 functions
| wee-util.c | Some other functions
| wee-version.c | Functions for WeeChat version
| gui/ | Functions for buffers, windows, ... (used by all interfaces)
| gui-bar-item.c | Bar items
| gui-bar-window.c | Bar windows
| gui-bar.c | Bars
| gui-buffer.c | Buffers
| gui-chat.c | Chat functions (display message, ...)
| gui-color.c | Color functions
2014-02-02 09:49:59 +01:00
| gui-completion.c | Completion on command line
| gui-cursor.c | Cursor mode (free movement of cursor)
| gui-filter.c | Filters
| gui-focus.c | Functions about focus (for cursor mode and mouse)
2014-02-02 09:49:59 +01:00
| gui-history.c | Commands/text saved in buffers
| gui-hotlist.c | Hotlist management (list of buffers with activity)
| gui-input.c | Input functions (input bar)
| gui-key.c | Keyboard functions
| gui-layout.c | Layout
| gui-line.c | Lines in buffers
| gui-mouse.c | Mouse
| gui-nicklist.c | Nicklist in buffers
| gui-window.c | Windows
| curses/ | Curses interface
| gui-curses-bar-window.c | Display in bar windows
| gui-curses-chat.c | Display in chat area (messages)
| gui-curses-color.c | Color functions
| gui-curses-key.c | Keyboard functions (default keys, read of input)
| gui-curses-main.c | WeeChat main loop (waiting for keyboard/network events)
| gui-curses-mouse.c | Mouse
| gui-curses-term.c | Functions about terminal
| gui-curses-window.c | Windows
| main.c | Entry point
|===
[[sources_plugins]]
==== Plugins
[width="100%",cols="1v,5",options="header"]
|===
| Path/file | Description
| plugins/ | Root of plugins
| plugin.c | Plugins management (load/unload dynamic C libraries)
| plugin-api.c | Extra functions for plugin API (wrapper around WeeChat core functions)
| plugin-config.c | Plugin configuration options (file plugins.conf)
| plugin-script.c | Common functions used by script plugins
| plugin-script-api.c | Script API functions: wrappers around some plugin API functions
| plugin-script-callback.c | Callback management for scripts
| weechat-plugin.h | Header designed to be distributed with WeeChat plugins, in order to compile them
| alias/ | Alias plugin
| alias.c | Main alias functions
| alias-config.c | Alias config options (file alias.conf)
| alias-info.c | Alias info/infolists/hdata
| aspell/ | Aspell plugin
| weechat-aspell.c | Main aspell functions
| weechat-aspell-bar-item.c | Aspell bar items
| weechat-aspell-command.c | Aspell commands
| weechat-aspell-completion.c | Aspell completions
| weechat-aspell-config.c | Aspell config options (file aspell.conf)
| weechat-aspell-info.c | Aspell info/infolists/hdata
| weechat-aspell-speller.c | Spellers management
| charset/ | Charset plugin
| charset.c | Charset functions
| exec/ | Exec plugin
| exec.c | Main exec functions
| exec-buffer.c | Exec buffer
| exec-command.c | Exec commands
| exec-completion.c | Exec completions
| exec-config.c | Exec config options (file exec.conf)
| fifo/ | Fifo plugin
| fifo.c | Main fifo functions
| fifo-info.c | Fifo info/infolists/hdata
| guile/ | Guile (scheme) plugin
| weechat-guile.c | Main guile functions (load/unload scripts, execute guile code)
| weechat-guile-api.c | Guile scripting API functions
| irc/ | IRC (Internet Relay Chat) plugin
| irc.c | Main IRC functions
| irc-bar-item.c | IRC bar items
| irc-buffer.c | IRC buffers
| irc-channel.c | IRC channels
2014-02-02 09:49:59 +01:00
| irc-color.c | IRC colors
| irc-command.c | IRC commands
| irc-completion.c | IRC completions
| irc-config.c | IRC config options (file irc.conf)
| irc-ctcp.c | IRC CTCP
| irc-debug.c | IRC debug functions
| irc-ignore.c | IRC Ignore
| irc-info.c | IRC info/infolists/hdata
| irc-input.c | Input of commands/text
| irc-message.c | Functions to manipulate IRC messages
| irc-mode.c | Functions about channel/nick modes
| irc-msgbuffer.c | Target buffer for IRC messages
| irc-nick.c | IRC nicks
| irc-notify.c | IRC notify lists
| irc-protocol.c | IRC protocol (RFCs 1459/2810/2811/2812/2813)
| irc-raw.c | IRC raw buffer
| irc-redirect.c | Redirection of IRC command output
| irc-sasl.c | SASL authentication with IRC server
2014-02-02 09:49:59 +01:00
| irc-server.c | I/O communication with IRC server
| irc-upgrade.c | Save/restore of IRC data when upgrading WeeChat
2015-03-07 15:16:37 +01:00
| javascript/ | Javascript plugin
| weechat-js.cpp | Main javascript functions (load/unload scripts, execute javascript code)
| weechat-js-api.cpp | Javascript scripting API functions
| weechat-js-v8.cpp | Javascript v8 functions
| logger/ | Logger plugin
| logger.c | Main logger functions
| logger-buffer.c | Logger buffer list management
| logger-config.c | Logger config options (file logger.conf)
| logger-info.c | Logger info/infolists/hdata
2014-02-02 09:49:59 +01:00
| logger-tail.c | Functions to get last lines of a file
| lua/ | Lua plugin
| weechat-lua.c | Main lua functions (load/unload scripts, execute lua code)
| weechat-lua-api.c | Lua scripting API functions
| perl/ | Perl plugin
| weechat-perl.c | Main perl functions (load/unload scripts, execute perl code)
| weechat-perl-api.c | Perl scripting API functions
| python/ | Python plugin
| weechat-python.c | Main python functions (load/unload scripts, execute python code)
| weechat-python-api.c | Python scripting API functions
| relay/ | Relay plugin (IRC proxy and relay for remote interfaces)
| relay.c | Main relay functions
| relay-buffer.c | Relay buffer
| relay-client.c | Clients of relay
| relay-command.c | Relay commands
| relay-completion.c | Relay completions
| relay-config.c | Relay config options (file relay.conf)
| relay-info.c | Relay info/infolists/hdata
| relay-network.c | Network functions for relay
| relay-raw.c | Relay raw buffer
| relay-server.c | Relay server
2014-02-02 09:49:59 +01:00
| relay-upgrade.c | Save/restore of relay data when upgrading WeeChat
| relay-websocket.c | WebSocket server functions (RFC 6455)
| irc/ | IRC proxy
| relay-irc.c | Main IRC proxy functions
2014-02-02 09:49:59 +01:00
| weechat/ | Relay for remote interfaces
| relay-weechat.c | Relay for remote interfaces (main functions)
| relay-weechat-msg.c | Send binary messages to clients
| relay-weechat-nicklist.c | Nicklist functions
| relay-weechat-protocol.c | Read commands from clients
| ruby/ | Ruby plugin
| weechat-ruby.c | Main ruby functions (load/unload scripts, execute ruby code)
| weechat-ruby-api.c | Ruby scripting API functions
| script/ | Scripts manager
| script.c | Main functions for scripts manager
2014-02-02 09:49:59 +01:00
| script-action.c | Actions on scripts (load/unload, install/remove, ...)
| script-buffer.c | Buffer for scripts manager
| script-command.c | Commands for scripts manager
| script-completion.c | Completions for scripts manager
| script-config.c | Config options for scripts manager (file script.conf)
| script-info.c | Script manager info/infolists/hdata
| script-repo.c | Download and read repository file
| tcl/ | Tcl plugin
| weechat-tcl.c | Main tcl functions (load/unload scripts, execute tcl code)
| weechat-tcl-api.c | Tcl scripting API functions
| trigger/ | Trigger plugin
| trigger.c | Main trigger functions
| trigger-buffer.c | Trigger buffer
| trigger-callback.c | Trigger callbacks
| trigger-command.c | Trigger commands
| trigger-completion.c | Trigger completions
| trigger-config.c | Trigger config options (file trigger.conf)
| xfer/ | Xfer plugin (IRC DCC file/chat)
| xfer.c | Main xfer functions
| xfer-buffer.c | Xfer buffer
2014-02-02 09:49:59 +01:00
| xfer-chat.c | DCC chat
| xfer-command.c | Xfer commands
| xfer-completion.c | Xfer completions
| xfer-config.c | Xfer config options (file xfer.conf)
2014-02-02 09:49:59 +01:00
| xfer-dcc.c | DCC file transfer
| xfer-file.c | File functions for xfer
| xfer-info.c | Xfer info/infolists/hdata
| xfer-network.c | Network functions for xfer
2014-02-02 09:49:59 +01:00
| xfer-upgrade.c | Save/restore of xfer data when upgrading WeeChat
|===
[[sources_tests]]
==== Tests
[width="100%",cols="1v,5",options="header"]
|===
| Path/file | Description
| tests/ | Root of tests
| tests.cpp | Program used to run tests
| unit/ | Root of unit tests
| core/ | Root of unit tests for core
| test-arraylist.cpp | Tests: arraylists
| test-eval.cpp | Tests: evaluation of expressions
| test-hashtble.cpp | Tests: hashtables
| test-hdata.cpp | Tests: hdata
| test-infolist.cpp | Tests: infolists
| test-list.cpp | Tests: lists
| test-string.cpp | Tests: strings
| test-url.cpp | Tests: URLs
| test-utf8.cpp | Tests: UTF-8
| test-util.cpp | Tests: utility functions
|===
[[documentation_translations]]
=== Documentation / translations
Documentation files:
[width="100%",cols="1v,5",options="header"]
|===
| Path/file | Description
| doc/ | Documentation
| asciidoc.conf | Asciidoc configuration file (some macros)
| asciidoc.css | Asciidoc style
| docgen.py | Python script to build files in 'autogen/' directory (see below)
| XX/ | Documentation for language XX (languages: en, fr, de, it, ...)
| weechat.1.XX.asciidoc | Man page (`man weechat`)
| weechat_quickstart.XX.asciidoc | Quickstart guide
| weechat_user.XX.asciidoc | User's guide
| weechat_faq.XX.asciidoc | FAQ
| weechat_plugin_api.XX.asciidoc | Plugin API reference
| weechat_scripting.XX.asciidoc | Scripting guide
| weechat_tester.XX.asciidoc | Tester's guide
| weechat_dev.XX.asciidoc | Developer's guide (this document)
| weechat_relay_protocol.XX.asciidoc | Relay protocol (for remote interfaces)
| cmdline_options.XX.asciidoc | Command-line options (file included in man page and user's guide)
| autogen/ | Files auto-built with script docgen.py
| user/ | Files auto-built for user's guide (do *NEVER* update manually!)
| plugin_api/ | Files auto-built for plugin API (do *NEVER* update manually!)
|===
2014-02-02 09:49:59 +01:00
Translations for WeeChat and plugins are done with gettext, files are in 'po/'
directory:
[width="100%",cols="1v,5",options="header"]
|===
| Path/file | Description
| po/ | Translation files (gettext)
2013-01-07 10:31:32 +01:00
| XX.po | Translations for language XX (fr, de, it, ...), base language is English
| weechat.pot | Template for translations (auto-built)
|===
[[coding_rules]]
== Coding rules
[[coding_general_rules]]
=== General rules
* In source code, your comments, variable names, .. must be written in English
2014-02-02 09:49:59 +01:00
*only* (no other language is allowed).
* Use a copyright header in each new source file with:
** short description of file (one line),
** date,
** name,
** e-mail,
** license.
Example in C:
[source,C]
----
/*
* weechat.c - core functions for WeeChat
*
2015-01-01 09:23:23 +01:00
* Copyright (C) 2015 Your Name <your@email.com>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat 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.
*
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
----
[[coding_c_style]]
=== C style
Some basic rules you *must* follow when you write C code:
* Use 4 spaces for indentation. Don't use tabs, they are evil.
* Try to not exceed 80 chars by line, except if this is needed to increase
readability.
2012-12-13 18:51:44 +01:00
* Use comments `/* comment */` (not C99-style comments like `// comment`).
2014-02-02 09:49:59 +01:00
* Add a comment before any function, to explain what it does (always use a
multi-line comment, even if description is very short).
2012-12-13 18:51:44 +01:00
Example:
[source,C]
----
/*
2012-12-13 18:51:44 +01:00
* Checks if a string with boolean value is valid.
*
* Returns:
* 1: boolean value is valid
* 0: boolean value is NOT valid
*/
2012-12-13 18:51:44 +01:00
int
foo ()
{
int i;
/* one line comment */
i = 1;
/*
2012-12-13 18:51:44 +01:00
* multi-line comment: this is a very long description about next block
* of code
*/
i = 2;
printf ("%d\n", i);
}
----
* Use explicit variable names, for example "nicks_count" instead of "n" or "nc".
2013-01-07 10:31:32 +01:00
Exception: in `for` loops, where variables like "i" or "n" are OK.
* Initialize local variables after declaration, in body of function, example:
[source,C]
----
void
foo ()
{
int nick_count, buffer_count;
nick_count = 0;
buffer_count = 1;
/* ... */
}
----
2013-01-07 10:31:32 +01:00
* Use parentheses to explicitly show how expression is evaluated, even if
2014-02-02 09:49:59 +01:00
they are not required, for example: write `x + (y * z)` instead of `x + y * z`.
* Place curly brackets `{ }` alone on lines, and indent them with number of
spaces used for line above opening curly bracket (the `if` in example):
[source,C]
----
if (nicks_count == 1)
{
/* something */
}
----
* Use empty lines to separate many different blocks inside functions, and if
possible add a comment for each one, like this:
[source,C]
----
/*
2012-12-13 18:51:44 +01:00
* Sends a message from out queue.
*/
void
irc_server_outqueue_send (struct t_irc_server *server)
{
/* ... */
/* send signal with command that will be sent to server */
irc_server_send_signal (server, "irc_out",
server->outqueue[priority]->command,
server->outqueue[priority]->message_after_mod,
NULL);
tags_to_send = irc_server_get_tags_to_send (server->outqueue[priority]->tags);
irc_server_send_signal (server, "irc_outtags",
server->outqueue[priority]->command,
server->outqueue[priority]->message_after_mod,
(tags_to_send) ? tags_to_send : "");
if (tags_to_send)
free (tags_to_send);
/* send command */
irc_server_send (server, server->outqueue[priority]->message_after_mod,
strlen (server->outqueue[priority]->message_after_mod));
server->last_user_message = time_now;
/* start redirection if redirect is set */
if (server->outqueue[priority]->redirect)
{
irc_redirect_init_command (server->outqueue[priority]->redirect,
server->outqueue[priority]->message_after_mod);
}
/* ... */
}
----
* Indent the `if` conditions, and use parentheses around conditions with an
operator (not needed for single boolean), like this:
[source,C]
----
if (something)
{
/* something */
}
else
{
/* something else */
}
if (my_boolean1 && my_boolean2 && (i == 10)
&& ((buffer1 != buffer2) || (window1 != window2)))
{
/* something */
}
else
{
/* something else */
}
----
* Indent the `switch` statements like this:
[source,C]
----
switch (string[0])
{
case 'A': /* first case */
foo ("abc", "def");
break;
case 'B': /* second case */
bar (1, 2, 3);
break;
default: /* other cases */
baz ();
break;
}
----
2014-02-02 09:49:59 +01:00
* Use `typedef` for function prototypes but not for structures:
[source,C]
----
typedef int (t_hook_callback_fd)(void *data, int fd);
struct t_hook_fd
{
t_hook_callback_fd *callback; /* fd callback */
int fd; /* socket or file descriptor */
int flags; /* fd flags (read,write,..) */
int error; /* contains errno if error occurred */
/* with fd */
};
/* ... */
struct t_hook_fd *new_hook_fd;
new_hook_fd = malloc (sizeof (*new_hook_fd));
----
* This Lisp code can be used in your '~/.emacs.el' to indent properly if you are
using Emacs as text editor:
[source,lisp]
----
(add-hook 'c-mode-common-hook '(lambda ()
(c-toggle-hungry-state t)
(c-set-style "k&r")
(setq c-basic-offset 4
c-tab-always-indent t)
(c-set-offset 'case-label '+)))
----
[[coding_python_style]]
=== Python style
See http://www.python.org/dev/peps/pep-0008/
[[core_internals]]
== Core internals
[[naming_convention]]
=== Naming convention
[[naming_convention_files]]
==== Files
File names are composed by letters and hyphens, with format: 'xxx-yyyyy.[ch]',
2014-02-02 09:49:59 +01:00
where 'xxx' is directory/component (can be abbreviation) and 'yyyyy' a name for
the file.
The main file of a directory may have same name as directory, for example
'irc.c' in irc plugin.
Examples:
[width="100%",cols="1l,5",options="header"]
|===
| Directory | Files
| src/core/ | weechat.c, wee-backtrace.c, wee-command.c, ...
| src/gui/ | gui-bar.c, gui-bar-item.c, gui-bar-window.c, ...
| src/gui/curses/ | gui-curses-bar.c, gui-curses-bar-window.c, gui-curses-chat.c, ...
| src/plugins/ | plugin.c, plugin-api.c, plugin-config.c, plugin-script.c, ...
| src/plugins/irc/ | irc.c, irc-bar-item.c, irc-buffer.c, ...
| src/plugins/python/ | weechat-python.c, weechat-python-api.c, ...
|===
The headers of C files have same name as file, for example 'wee-command.h' for
file 'wee-command.c'.
[[naming_convention_structures]]
==== Structures
Structures have name 't_X_Y' or 't_X_Y_Z':
* 'X': directory/component (can be abbreviation)
* 'Y': end of file name
* 'Z': name for structure (optional)
Example: an IRC nick (from 'src/plugins/irc/irc-nick.h'):
[source,C]
----
struct t_irc_nick
{
char *name; /* nickname */
char *host; /* full hostname */
char *prefixes; /* string with prefixes enabled for nick */
char prefix[2]; /* current prefix (higher prefix set in */
/* prefixes) */
int away; /* 1 if nick is away */
char *color; /* color for nickname in chat window */
struct t_irc_nick *prev_nick; /* link to previous nick on channel */
struct t_irc_nick *next_nick; /* link to next nick on channel */
};
----
[[naming_convention_variables]]
==== Variables
Global variables (outside functions) have name 'X_Y_Z':
* 'X': directory/component (can be abbreviation)
* 'Y': end of file name
* 'Z': name for variable
Exception are variables for "last" node of a list, name is 'last_X' (where
'X' is name of variable, using singular form).
Example: windows (from 'src/gui/gui-window.c'):
[source,C]
----
struct t_gui_window *gui_windows = NULL; /* first window */
struct t_gui_window *last_gui_window = NULL; /* last window */
struct t_gui_window *gui_current_window = NULL; /* current window */
----
There is no naming convention for local variables (in functions). The only
2014-02-02 09:49:59 +01:00
recommendation is that name is explicit (not too short). +
Nevertheless, pointers to structures are often named 'ptr_xxxx', for example a
pointer on a 'struct t_gui_buffer *' will be: '*ptr_buffer'.
[[naming_convention_functions]]
==== Functions
Naming convention for functions is the same as
2014-02-02 09:49:59 +01:00
<<naming_convention_variables,variables>>.
Example: creation of a new window (from 'src/gui/gui-window.c'):
[source,C]
----
/*
2012-12-13 18:51:44 +01:00
* Creates a new window.
*
* Returns pointer to new window, NULL if error.
*/
struct t_gui_window *
gui_window_new (struct t_gui_window *parent_window, struct t_gui_buffer *buffer,
int x, int y, int width, int height,
int width_pct, int height_pct)
{
/* ... */
return new_window;
}
----
[[single_thread]]
=== Single thread
WeeChat is single threaded. That means every part of code should execute very
fast, and that calls to functions like `sleep` are *strictly forbidden* (it is
true for WeeChat core, but also C plugins and scripts).
If for some reasons you have to sleep a while, use `hook_timer` with a callback.
[[doubly_linked_lists]]
=== Doubly linked lists
Most of WeeChat linked lists are doubly linked lists: each node has pointer to
previous and next node.
Example: list of buffers (from 'src/gui/gui-buffer.h'):
[source,C]
----
struct t_gui_buffer
{
/* data */
/* ... */
struct t_gui_buffer *prev_buffer; /* link to previous buffer */
struct t_gui_buffer *next_buffer; /* link to next buffer */
};
----
Then the two list pointers, to the head and tail of list:
[source,C]
----
struct t_gui_buffer *gui_buffers = NULL; /* first buffer */
struct t_gui_buffer *last_gui_buffer = NULL; /* last buffer */
----
[[color_codes_in_strings]]
=== Color codes in strings
WeeChat uses own color codes in strings to display attributes (bold,
underline, ...) and colors on screen.
All attributes/colors are prefixed with a char in string, which can be:
* '0x19': color code (followed by color code(s))
* '0x1A': set attribute (followed by attribute on one char)
* '0x1B': remove attribute (followed by attribute on one char)
* '0x1C': reset (nothing after)
Allowed attributes are (one or more chars):
* `*`: bold
* `!`: reverse
* `/`: italic
* `_`: underline
* `|`: keep attributes
Possible colors are:
* standard color: optional attributes + number on 2 digits
* extended color: `@` + optional attributes + number on 5 digits
In following table, these conventions are used:
* `STD`: standard color (2 digits)
* `(A)STD`: standard color with optional attributes (attributes + 2 digits)
* `EXT`: extended color (`@` + 5 digits)
* `(A)EXT`: extended color with optional attributes (`@` + attributes + 5 digits)
* `ATTR`: one attribute char (`*`, `!`, `/`, `_` or `|`)
All combinations are summarized in this table:
2014-02-02 09:49:59 +01:00
[width="100%",cols="4,2,2,8",options="header"]
|===
| Code | Example | Areas | Description
| hex[19] + STD | hex[19]`01` | chat + bars | Set attributes and color using option, see table below
| hex[19] + EXT | hex[19]`@00001` | chat | Set color with a ncurses pair (used only on `/color` buffer)
| hex[19] + "F" + (A)STD | hex[19]`F*05` | chat + bars | Set foreground (WeeChat color)
| hex[19] + "F" + (A)EXT | hex[19]`F@00214` | chat + bars | Set foreground (extended color)
| hex[19] + "B" + STD | hex[19]`B05` | chat + bars | Set background (WeeChat color)
| hex[19] + "B" + EXT | hex[19]`B@00124` | chat + bars | Set background (extended color)
| hex[19] + "*" + (A)STD | hex[19]`*05` | chat + bars | Set foreground (WeeChat color)
| hex[19] + "*" + (A)EXT | hex[19]`*@00214` | chat + bars | Set foreground (extended color)
| hex[19] + "*" + (A)STD + "," + STD | hex[19]`*08,05` | chat + bars | Set foreground/background (WeeChat colors)
| hex[19] + "*" + (A)STD + "," + EXT | hex[19]`*01,@00214` | chat + bars | Set foreground (WeeChat color) and background (extended color)
| hex[19] + "*" + (A)EXT + "," + STD | hex[19]`*@00214,05` | chat + bars | Set foreground (extended color) and background (WeeChat color)
| hex[19] + "*" + (A)EXT + "," + EXT | hex[19]`*@00214,@00017` | chat + bars | Set foreground/background (extended colors)
| hex[19] + "b" + "F" | hex[19]`bF` | bars | Set bar foreground color
| hex[19] + "b" + "D" | hex[19]`bD` | bars | Set bar delimiter color
| hex[19] + "b" + "B" | hex[19]`bB` | bars | Set bar background color
| hex[19] + "b" + "_" | hex[19]`b_` | input bar | Start input char (used only in item "input_text")
| hex[19] + "b" + "-" | hex[19]`b-` | input bar | Start input hidden char (used only in item "input_text")
2014-01-17 09:41:01 +01:00
| hex[19] + "b" + "#" | hex[19]`b#` | input bar | Move cursor char (used only in item "input_text")
| hex[19] + "b" + "i" | hex[19]`bi` | bars | Start item
| hex[19] + "b" + "l" (lower L) | hex[19]`bl` | bars | Start line item
2014-02-02 09:49:59 +01:00
| hex[19] + "E" | hex[19]`E` | chat + bars | Emphasize text _(WeeChat ≥ 0.4.2)_
| hex[19] + hex[1C] | hex[19]hex[1C] | chat + bars | Reset color (keep attributes)
| hex[1A] + ATTR | hex[1A]`*` | chat + bars | Set attribute
| hex[1B] + ATTR | hex[1B]`*` | chat + bars | Remove attribute
| hex[1C] | hex[1C] | chat + bars | Reset attributes and color
|===
2014-02-02 09:49:59 +01:00
Color codes using options (see 't_gui_color_enum', in file
'src/gui/gui-color.h'):
2014-02-02 09:49:59 +01:00
[width="70%",cols="^1m,10",options="header"]
|===
| Code | Option
| 00 | weechat.color.separator
| 01 | weechat.color.chat
| 02 | weechat.color.chat_time
| 03 | weechat.color.chat_time_delimiters
| 04 | weechat.color.chat_prefix_error
| 05 | weechat.color.chat_prefix_network
| 06 | weechat.color.chat_prefix_action
| 07 | weechat.color.chat_prefix_join
| 08 | weechat.color.chat_prefix_quit
| 09 | weechat.color.chat_prefix_more
| 10 | weechat.color.chat_prefix_suffix
| 11 | weechat.color.chat_buffer
| 12 | weechat.color.chat_server
| 13 | weechat.color.chat_channel
| 14 | weechat.color.chat_nick
| 15 | weechat.color.chat_nick_self
| 16 | weechat.color.chat_nick_other
| 17 | _(not used any more since WeeChat 0.3.4)_
| 18 | _(not used any more since WeeChat 0.3.4)_
| 19 | _(not used any more since WeeChat 0.3.4)_
| 20 | _(not used any more since WeeChat 0.3.4)_
| 21 | _(not used any more since WeeChat 0.3.4)_
| 22 | _(not used any more since WeeChat 0.3.4)_
| 23 | _(not used any more since WeeChat 0.3.4)_
| 24 | _(not used any more since WeeChat 0.3.4)_
| 25 | _(not used any more since WeeChat 0.3.4)_
| 26 | _(not used any more since WeeChat 0.3.4)_
| 27 | weechat.color.chat_host
| 28 | weechat.color.chat_delimiters
| 29 | weechat.color.chat_highlight
| 30 | weechat.color.chat_read_marker
| 31 | weechat.color.chat_text_found
| 32 | weechat.color.chat_value
| 33 | weechat.color.chat_prefix_buffer
2014-02-02 09:49:59 +01:00
| 34 | weechat.color.chat_tags _(WeeChat ≥ 0.3.6)_
| 35 | weechat.color.chat_inactive_window _(WeeChat ≥ 0.3.6)_
| 36 | weechat.color.chat_inactive_buffer _(WeeChat ≥ 0.3.6)_
| 37 | weechat.color.chat_prefix_buffer_inactive_buffer _(WeeChat ≥ 0.3.6)_
| 38 | weechat.color.chat_nick_offline _(WeeChat ≥ 0.3.9)_
| 39 | weechat.color.chat_nick_offline_highlight _(WeeChat ≥ 0.3.9)_
| 40 | weechat.color.chat_nick_prefix _(WeeChat ≥ 0.4.1)_
| 41 | weechat.color.chat_nick_suffix _(WeeChat ≥ 0.4.1)_
| 42 | weechat.color.emphasis _(WeeChat ≥ 0.4.2)_
| 43 | weechat.color.chat_day_change _(WeeChat ≥ 0.4.2)_
|===
WeeChat colors are:
2014-02-02 09:49:59 +01:00
[width="70%",cols="^1m,6",options="header"]
|===
| Code | Color
| 00 | Default (terminal foreground/background)
| 01 | Black
| 02 | Dark gray
| 03 | Dark red
| 04 | Light red
| 05 | Dark green
| 06 | Light green
| 07 | Brown
| 08 | Yellow
| 09 | Dark blue
| 10 | Light blue
| 11 | Dark magenta
| 12 | Light magenta
| 13 | Dark cyan
| 14 | Light cyan
| 15 | Gray
| 16 | White
|===
Examples of color codes:
2014-02-02 09:49:59 +01:00
[width="70%",cols="1,2",options="header"]
|===
| Code | Description
| hex[19]`01` | Color of option "01" (chat text)
| hex[19]`*08,03` | Yellow on red
| hex[19]`*@00214` | Orange (extended color 214)
| hex[19]`*@*_00214,@00017` | Bold underlined orange (214) on dark blue (17)
| hex[1A]`_` | Set underline
| hex[1B]`_` | Remove underline
| hex[1C] | Reset attributes and color
|===
[[plugin_internals]]
== Plugin internals
The file 'src/plugins/weechat-plugin.h' defines and exports all functions
2014-02-02 09:49:59 +01:00
available in the API.
A structure called 't_weechat_plugin' is used to store info about plugin
(filename, name, author, description, ...) and all API functions, as pointers
to WeeChat functions.
2014-02-02 09:49:59 +01:00
Then some macros are defined to call these functions.
For example, function 'hook_timer' is defined in structure 't_weechat_plugin'
like this:
[source,C]
----
struct t_hook *(*hook_timer) (struct t_weechat_plugin *plugin,
long interval,
int align_second,
int max_calls,
int (*callback)(void *data,
int remaining_calls),
void *callback_data);
----
And the macro used to call this function is:
[source,C]
----
#define weechat_hook_timer(__interval, __align_second, __max_calls, \
__callback, __data) \
weechat_plugin->hook_timer(weechat_plugin, __interval, \
__align_second, __max_calls, \
__callback, __data)
----
So in a plugin, the call to function will be for example:
[source,C]
----
server->hook_timer_sasl = weechat_hook_timer (timeout * 1000,
0, 1,
&irc_server_timer_sasl_cb,
server);
----
[[contribute]]
== Contribute to WeeChat
[[git_repository]]
=== Git repository
Git repository is at this URL: https://github.com/weechat/weechat
Any patch for bug or new feature must be done on master branch, preferred way is
a GitHub pull request. A patch can also be sent by e-mail (made with `git diff`
or `git format-patch`).
Format of commit message is the following (to close a GitHub issue):
----
component: fix a problem (closes #123)
----
For a Savannah bug:
----
component: fix a problem (bug #12345)
----
Where 'component' is one of following:
* WeeChat core: 'core' (files in root directory, 'po/' and 'src/',
except 'src/plugins/')
* documentation files: 'doc' (files in directory 'doc/')
* name of a plugin: 'irc', 'python', 'relay', ... (files in directory
'src/plugins/')
Some rules to follow:
2013-01-07 10:31:32 +01:00
* use only English
* use infinitive form of verb
* if commit is related to something in tracker, write it in parenthesis after
the message, with this format:
** GitHub: closes #123
** Savannah: bug #12345, task #12345, patch #12345
Examples of commit messages:
----
irc: add command /unquiet (closes #36)
core: add callback "nickcmp" for nick comparison in buffers
irc: fix freeze when reading on socket with SSL enabled (bug #35097)
ruby: add detection of ruby version 1.9.3 in cmake
python: fix crash when unloading a script without pointer to interpreter
2013-01-07 10:31:32 +01:00
core: update Japanese translations (patch #7783)
----
[[translations]]
=== Translations
[[gettext]]
==== Gettext
Gettext files are in directory 'po/'.
2014-02-02 09:49:59 +01:00
If you want to initialize a new language, use command `msginit`. For example to
create a file which is ready to translate to Dutch:
----
$ cd po
$ msginit -i weechat.pot -l nl_NL -o nl.po
----
2014-02-02 09:49:59 +01:00
Base language for WeeChat is English, so you must of course perfectly understand
English in order to translate to your language.
When done, you *have* to check your file with script 'msgcheck.py'
(https://github.com/flashcode/msgcheck):
----
$ msgcheck.py xx.po
----
[[build_autogen_files]]
===== Build auto-generated files
Files in directory 'doc/XX/autogen/' are auto-generated by script 'doc/docgen.py'.
Copy this python script to your python directory (for example '~/.weechat/python').
Then you can load this script in your WeeChat, and setup path to your '/doc' directory:
----
/python load docgen.py
/set plugins.var.python.docgen.path "~/src/weechat/doc"
----
Then create this alias to build files:
----
2015-03-07 15:16:37 +01:00
/alias doc /perl unload; /python unload; /ruby unload; /lua unload; /tcl unload; /guile unload; /javascript unload; /python load docgen.py; /wait 1ms /docgen
----
2014-02-02 09:49:59 +01:00
And use command `/doc` to build all files, for all languages.
[IMPORTANT]
When using command `/doc`, be sure all C plugins (irc, charset, ...) are loaded,
2014-02-02 09:49:59 +01:00
because files are built using data currently in memory.
[[asciidoc]]
==== Asciidoc
2014-02-02 09:49:59 +01:00
Asciidoc files are in directory 'doc/XX/' where 'XX' is language (en, fr, de,
it, ...).
2014-02-02 09:49:59 +01:00
First make a copy of an English asciidoc file (in directory 'doc/en/'), then
work on it.
The translations missing in files are indicated by this string:
----
// TRANSLATION MISSING
----
You must translate whole file except links and special keywords for notes,
warnings, ... These words must be kept unchanged:
----
[[link_name]]
<<link_name>>
[NOTE]
[TIP]
[IMPORTANT]
[WARNING]
[CAUTION]
----
When there is a name after `<<link_name>>`, then you must translate it:
----
<<link_name,this text must be translated>>
----