Merge pull request #45728 from Ma27/nixos/weechat-module

nixos/weechat: add module
This commit is contained in:
Timo Kaufmann 2018-09-07 17:19:46 +02:00 committed by GitHub
commit e326c0156d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 385 additions and 40 deletions

View file

@ -671,6 +671,8 @@ overrides = super: self: rec {
plugins = with availablePlugins; [ python perl ];
}
}</programlisting>
If the <literal>configure</literal> function returns an attrset without the <literal>plugins</literal>
attribute, <literal>availablePlugins</literal> will be used automatically.
</para>
<para>
@ -704,6 +706,55 @@ overrides = super: self: rec {
}; }
</programlisting>
</para>
<para>
WeeChat allows to set defaults on startup using the <literal>--run-command</literal>.
The <literal>configure</literal> method can be used to pass commands to the program:
<programlisting>weechat.override {
configure = { availablePlugins, ... }: {
init = ''
/set foo bar
/server add freenode chat.freenode.org
'';
};
}</programlisting>
Further values can be added to the list of commands when running
<literal>weechat --run-command "your-commands"</literal>.
</para>
<para>
Additionally it's possible to specify scripts to be loaded when starting <literal>weechat</literal>.
These will be loaded before the commands from <literal>init</literal>:
<programlisting>weechat.override {
configure = { availablePlugins, ... }: {
scripts = with pkgs.weechatScripts; [
weechat-xmpp weechat-matrix-bridge wee-slack
];
init = ''
/set plugins.var.python.jabber.key "val"
'':
};
}</programlisting>
</para>
<para>
In <literal>nixpkgs</literal> there's a subpackage which contains derivations for
WeeChat scripts. Such derivations expect a <literal>passthru.scripts</literal> attribute
which contains a list of all scripts inside the store path. Furthermore all scripts
have to live in <literal>$out/share</literal>. An exemplary derivation looks like this:
<programlisting>{ stdenv, fetchurl }:
stdenv.mkDerivation {
name = "exemplary-weechat-script";
src = fetchurl {
url = "https://scripts.tld/your-scripts.tar.gz";
sha256 = "...";
};
passthru.scripts = [ "foo.py" "bar.lua" ];
installPhase = ''
mkdir $out/share
cp foo.py $out/share
cp bar.lua $out/share
'';
}</programlisting>
</para>
</section>
<section xml:id="sec-citrix">
<title>Citrix Receiver</title>

View file

@ -406,6 +406,7 @@
./services/misc/taskserver
./services/misc/tzupdate.nix
./services/misc/uhub.nix
./services/misc/weechat.nix
./services/misc/xmr-stak.nix
./services/misc/zookeeper.nix
./services/monitoring/apcupsd.nix

View file

@ -0,0 +1,56 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.weechat;
in
{
options.services.weechat = {
enable = mkEnableOption "weechat";
root = mkOption {
description = "Weechat state directory.";
type = types.str;
default = "/var/lib/weechat";
};
sessionName = mkOption {
description = "Name of the `screen' session for weechat.";
default = "weechat-screen";
type = types.str;
};
binary = mkOption {
description = "Binary to execute (by default \${weechat}/bin/weechat).";
example = literalExample ''
''${pkgs.weechat}/bin/weechat-headless
'';
default = "${pkgs.weechat}/bin/weechat";
};
};
config = mkIf cfg.enable {
users = {
groups.weechat = {};
users.weechat = {
createHome = true;
group = "weechat";
home = cfg.root;
isSystemUser = true;
};
};
systemd.services.weechat = {
environment.WEECHAT_HOME = cfg.root;
serviceConfig = {
User = "weechat";
Group = "weechat";
RemainAfterExit = "yes";
};
script = "exec ${pkgs.screen}/bin/screen -Dm -S ${cfg.sessionName} ${cfg.binary}";
wantedBy = [ "multi-user.target" ];
wants = [ "network.target" ];
};
};
meta.doc = ./weechat.xml;
}

View file

@ -0,0 +1,61 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="module-services-weechat">
<title>WeeChat</title>
<para><link xlink:href="https://weechat.org/">WeeChat</link> is a fast and extensible IRC client.</para>
<section><title>Basic Usage</title>
<para>
By default, the module creates a
<literal><link xlink:href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</link></literal> unit
which runs the chat client in a detached
<literal><link xlink:href="https://www.gnu.org/software/screen/">screen</link></literal> session.
</para>
<para>
This can be done by enabling the <literal>weechat</literal> service:
<programlisting>
{ ... }:
{
<link linkend="opt-services.weechat.enable">services.weechat.enable</link> = true;
}
</programlisting>
</para>
<para>
The service is managed by a dedicated user
named <literal>weechat</literal> in the state directory
<literal>/var/lib/weechat</literal>.
</para>
</section>
<section><title>Re-attaching to WeeChat</title>
<para>
WeeChat runs in a screen session owned by a dedicated user. To explicitly
allow your another user to attach to this session, the <literal>screenrc</literal> needs to be tweaked
by adding <link xlink:href="https://www.gnu.org/software/screen/manual/html_node/Multiuser.html#Multiuser">multiuser</link> support:
<programlisting>
{
<link linkend="opt-programs.screen.screenrc">programs.screen.screenrc</link> = ''
multiuser on
acladd normal_user
'';
}
</programlisting>
Now, the session can be re-attached like this:
<programlisting>
screen -r weechat-screen
</programlisting>
</para>
<para>
<emphasis>The session name can be changed using <link linkend="opt-services.weechat.sessionName">services.weechat.sessionName.</link></emphasis>
</para>
</section>
</chapter>

View file

@ -0,0 +1,110 @@
diff --git a/src/core/wee-command.c b/src/core/wee-command.c
index 91c3c068d..8105e4171 100644
--- a/src/core/wee-command.c
+++ b/src/core/wee-command.c
@@ -8345,10 +8345,20 @@ command_exec_list (const char *command_list)
void
command_startup (int plugins_loaded)
{
+ int i;
+
if (plugins_loaded)
{
command_exec_list (CONFIG_STRING(config_startup_command_after_plugins));
- command_exec_list (weechat_startup_commands);
+ if (weechat_startup_commands)
+ {
+ for (i = 0; i < weelist_size (weechat_startup_commands); i++)
+ {
+ command_exec_list (
+ weelist_string (
+ weelist_get (weechat_startup_commands, i)));
+ }
+ }
}
else
command_exec_list (CONFIG_STRING(config_startup_command_before_plugins));
diff --git a/src/core/weechat.c b/src/core/weechat.c
index f74598ad5..ff2e539d1 100644
--- a/src/core/weechat.c
+++ b/src/core/weechat.c
@@ -60,6 +60,7 @@
#include "wee-eval.h"
#include "wee-hdata.h"
#include "wee-hook.h"
+#include "wee-list.h"
#include "wee-log.h"
#include "wee-network.h"
#include "wee-proxy.h"
@@ -102,7 +103,8 @@ int weechat_no_gnutls = 0; /* remove init/deinit of gnutls */
/* (useful with valgrind/electric-f.)*/
int weechat_no_gcrypt = 0; /* remove init/deinit of gcrypt */
/* (useful with valgrind) */
-char *weechat_startup_commands = NULL; /* startup commands (-r flag) */
+struct t_weelist *weechat_startup_commands = NULL; /* startup commands */
+ /* (option -r) */
/*
@@ -152,9 +154,13 @@ weechat_display_usage ()
" -h, --help display this help\n"
" -l, --license display WeeChat license\n"
" -p, --no-plugin don't load any plugin at startup\n"
- " -r, --run-command <cmd> run command(s) after startup\n"
- " (many commands can be separated by "
- "semicolons)\n"
+ " -P, --plugins <plugins> load only these plugins at startup\n"
+ " (see /help weechat.plugin.autoload)\n"
+ " -r, --run-command <cmd> run command(s) after startup;\n"
+ " many commands can be separated by "
+ "semicolons,\n"
+ " this option can be given multiple "
+ "times\n"
" -s, --no-script don't load any script at startup\n"
" --upgrade upgrade WeeChat using session files "
"(see /help upgrade in WeeChat)\n"
@@ -276,9 +282,10 @@ weechat_parse_args (int argc, char *argv[])
{
if (i + 1 < argc)
{
- if (weechat_startup_commands)
- free (weechat_startup_commands);
- weechat_startup_commands = strdup (argv[++i]);
+ if (!weechat_startup_commands)
+ weechat_startup_commands = weelist_new ();
+ weelist_add (weechat_startup_commands, argv[++i],
+ WEECHAT_LIST_POS_END, NULL);
}
else
{
@@ -616,6 +623,8 @@ weechat_shutdown (int return_code, int crash)
free (weechat_home);
if (weechat_local_charset)
free (weechat_local_charset);
+ if (weechat_startup_commands)
+ weelist_free (weechat_startup_commands);
if (crash)
abort ();
diff --git a/src/core/weechat.h b/src/core/weechat.h
index 9420ff415..cbb565a03 100644
--- a/src/core/weechat.h
+++ b/src/core/weechat.h
@@ -96,6 +96,8 @@
/* name of environment variable with an extra lib dir */
#define WEECHAT_EXTRA_LIBDIR "WEECHAT_EXTRA_LIBDIR"
+struct t_weelist;
+
/* global variables and functions */
extern int weechat_headless;
extern int weechat_debug_core;
@@ -112,7 +114,7 @@ extern char *weechat_local_charset;
extern int weechat_plugin_no_dlclose;
extern int weechat_no_gnutls;
extern int weechat_no_gcrypt;
-extern char *weechat_startup_commands;
+extern struct t_weelist *weechat_startup_commands;
extern void weechat_term_check ();
extern void weechat_shutdown (int return_code, int crash);

View file

@ -12,7 +12,8 @@
, tclSupport ? true, tcl
, extraBuildInputs ? []
, configure ? { availablePlugins, ... }: { plugins = builtins.attrValues availablePlugins; }
, runCommand }:
, runCommand, buildEnv
}:
let
inherit (pythonPackages) python;
@ -29,12 +30,12 @@ let
weechat =
assert lib.all (p: p.enabled -> ! (builtins.elem null p.buildInputs)) plugins;
stdenv.mkDerivation rec {
version = "2.1";
version = "2.2";
name = "weechat-${version}";
src = fetchurl {
url = "http://weechat.org/files/src/weechat-${version}.tar.bz2";
sha256 = "0fq68wgynv2c3319gmzi0lz4ln4yrrk755y5mbrlr7fc1sx7ffd8";
sha256 = "0p4nhh7f7w4q77g7jm9i6fynndqlgjkc9dk5g1xb4gf9imiisqlg";
};
outputs = [ "out" "man" ] ++ map (p: p.name) enabledPlugins;
@ -69,6 +70,13 @@ let
done
'';
# remove when bumping to the latest version.
# This patch basically rebases `fcf7469d7664f37e94d5f6d0b3fe6fce6413f88c`
# from weechat upstream to weechat-2.2.
patches = [
./aggregate-commands.patch
];
meta = {
homepage = http://www.weechat.org/;
description = "A fast, light and extensible chat client";
@ -78,38 +86,38 @@ let
on https://nixos.org/nixpkgs/manual/#sec-weechat .
'';
license = stdenv.lib.licenses.gpl3;
maintainers = with stdenv.lib.maintainers; [ lovek323 garbas the-kenny lheckemann ];
maintainers = with stdenv.lib.maintainers; [ lovek323 garbas the-kenny lheckemann ma27 ];
platforms = stdenv.lib.platforms.unix;
};
};
in if configure == null then weechat else
let
perlInterpreter = perl;
config = configure {
availablePlugins = let
simplePlugin = name: {pluginFile = "${weechat.${name}}/lib/weechat/plugins/${name}.so";};
in rec {
python = {
pluginFile = "${weechat.python}/lib/weechat/plugins/python.so";
withPackages = pkgsFun: (python // {
extraEnv = ''
export PYTHONHOME="${pythonPackages.python.withPackages pkgsFun}"
'';
});
};
perl = (simplePlugin "perl") // {
availablePlugins = let
simplePlugin = name: {pluginFile = "${weechat.${name}}/lib/weechat/plugins/${name}.so";};
in rec {
python = {
pluginFile = "${weechat.python}/lib/weechat/plugins/python.so";
withPackages = pkgsFun: (python // {
extraEnv = ''
export PATH="${perlInterpreter}/bin:$PATH"
export PYTHONHOME="${pythonPackages.python.withPackages pkgsFun}"
'';
};
tcl = simplePlugin "tcl";
ruby = simplePlugin "ruby";
guile = simplePlugin "guile";
lua = simplePlugin "lua";
});
};
perl = (simplePlugin "perl") // {
extraEnv = ''
export PATH="${perlInterpreter}/bin:$PATH"
'';
};
tcl = simplePlugin "tcl";
ruby = simplePlugin "ruby";
guile = simplePlugin "guile";
lua = simplePlugin "lua";
};
inherit (config) plugins;
config = configure { inherit availablePlugins; };
plugins = config.plugins or (builtins.attrValues availablePlugins);
pluginsDir = runCommand "weechat-plugins" {} ''
mkdir -p $out/plugins
@ -117,13 +125,29 @@ in if configure == null then weechat else
ln -s $plugin $out/plugins
done
'';
in (writeScriptBin "weechat" ''
#!${stdenv.shell}
export WEECHAT_EXTRA_LIBDIR=${pluginsDir}
${lib.concatMapStringsSep "\n" (p: lib.optionalString (p ? extraEnv) p.extraEnv) plugins}
exec ${weechat}/bin/weechat "$@"
'') // {
name = weechat.name;
unwrapped = weechat;
meta = weechat.meta;
init = let
init = builtins.replaceStrings [ "\n" ] [ ";" ] (config.init or "");
mkScript = drv: lib.flip map drv.scripts (script: "/script load ${drv}/share/${script}");
scripts = builtins.concatStringsSep ";" (lib.foldl (scripts: drv: scripts ++ mkScript drv)
[ ] (config.scripts or []));
in "${scripts}\n${init}";
mkWeechat = bin: (writeScriptBin bin ''
#!${stdenv.shell}
export WEECHAT_EXTRA_LIBDIR=${pluginsDir}
${lib.concatMapStringsSep "\n" (p: lib.optionalString (p ? extraEnv) p.extraEnv) plugins}
exec ${weechat}/bin/${bin} "$@" --run-command "${init}"
'') // {
inherit (weechat) name meta;
unwrapped = weechat;
};
in buildEnv {
name = "weechat-bin-env";
paths = [
(mkWeechat "weechat")
(mkWeechat "weechat-headless")
];
}

View file

@ -0,0 +1,13 @@
{ callPackage, luaPackages, pythonPackages }:
{
weechat-xmpp = callPackage ./weechat-xmpp {
inherit (pythonPackages) pydns;
};
weechat-matrix-bridge = callPackage ./weechat-matrix-bridge {
inherit (luaPackages) cjson;
};
wee-slack = callPackage ./wee-slack { };
}

View file

@ -0,0 +1,29 @@
{ stdenv, fetchFromGitHub }:
stdenv.mkDerivation rec {
name = "wee-slack-${version}";
version = "2.1.1";
src = fetchFromGitHub {
repo = "wee-slack";
owner = "wee-slack";
rev = "v${version}";
sha256 = "05caackz645aw6kljmiihiy7xz9jld8b9blwpmh0cnaihavgj1wc";
};
passthru.scripts = [ "wee_slack.py" ];
installPhase = ''
mkdir -p $out/share
cp wee_slack.py $out/share/wee_slack.py
'';
meta = with stdenv.lib; {
homepage = https://github.com/wee-slack/wee-slack;
license = licenses.mit;
maintainers = with maintainers; [ ma27 ];
description = ''
A WeeChat plugin for Slack.com. Synchronizes read markers, provides typing notification, search, etc..
'';
};
}

View file

@ -25,6 +25,8 @@ stdenv.mkDerivation {
--replace "__NIX_LIB_PATH__" "$out/lib/?.so"
'';
passthru.scripts = [ "olm.lua" "matrix.lua" ];
installPhase = ''
mkdir -p $out/{share,lib}

View file

@ -25,6 +25,8 @@ stdenv.mkDerivation {
})
];
passthru.scripts = [ "jabber.py" ];
meta = with stdenv.lib; {
description = "A fork of the jabber plugin for weechat";
homepage = "https://github.com/sleduc/weechat-xmpp";

View file

@ -292,6 +292,8 @@ mapAliases ({
vimprobable2Wrapper = vimprobable2; # added 2015-01
virtviewer = virt-viewer; # added 2015-12-24
vorbisTools = vorbis-tools; # added 2016-01-26
weechat-xmpp = weechatScripts.weechat-xmpp; # added 2018-09-06
weechat-matrix-bridge = weechatScripts.weechat-matrix-bridge; # added 2018-09-06
wineStaging = wine-staging; # added 2018-01-08
winusb = woeusb; # added 2017-12-22
wireguard = wireguard-tools; # added 2018-05-19

View file

@ -19199,13 +19199,7 @@ with pkgs;
guile = guile_2_0;
};
weechat-matrix-bridge = callPackage ../applications/networking/instant-messengers/weechat-matrix-bridge {
inherit (luaPackages) cjson;
};
weechat-xmpp = callPackage ../applications/networking/instant-messengers/weechat-xmpp {
inherit (pythonPackages) pydns;
};
weechatScripts = callPackage ../applications/networking/irc/weechat/scripts { };
westonLite = weston.override {
pango = null;