buf[0] = 0;
if (mutt_get_field (_("Shell command: "), buf, sizeof (buf), M_CMD) == 0) {
if (!buf[0])
- m_strcpy(buf, sizeof(buf), mlua_reggets(LTK_SHELL));
+ m_strcpy(buf, sizeof(buf), ml_core.shell);
if (buf[0]) {
CLEARLINE (LINES - 1);
mutt_endwin (NULL);
return (QuadOptions[n] >> b) & 0x3;
}
-int query_quadoption2(int opt, const char *prompt)
+int query_quadoption2(int v, const char *prompt)
{
- int v = mlua_reggeti(opt);
-
switch (v) {
case M_YES:
case M_NO:
From = rfc822_parse_adrlist (NULL, p);
charset_initialize();
- mlua_initialize();
+ luaM_initialize();
/* Set standard defaults */
hash_map (ConfigOptions, mutt_set_default, 0);
if (access(buffer, F_OK) < 0)
snprintf(buffer, sizeof(buffer), "%s/.madmutt/cfg.lua", NONULL(Homedir));
if (!access(buffer, F_OK)) {
- need_pause = mlua_wrap(mutt_error, mlua_dofile(buffer));
+ need_pause = luaM_wrap(mutt_error, luaM_dofile(buffer));
}
/* }}} */
BUILT_SOURCES = lua-token.h lua-token.c
DISTCLEANFILES = $(BUILT_SOURCES)
+.cpkg.c: ; ./luapkg2c.pl -c $< > $@
+.cpkg.h: ; ./luapkg2c.pl -h $< > $@
+
noinst_LIBRARIES = liblua.a
-liblua_a_SOURCES = lib-lua.h lib-lua_priv.h \
- runtime.c madmutt.c \
+liblua_a_DEPENDENCIES = madmutt.h
+liblua_a_SOURCES = madmutt.cpkg \
+ lib-lua.h lib-lua_priv.h \
+ runtime.c \
$(BUILT_SOURCES)
noinst_HEADERS = lib-lua.h lib-lua_priv.h
# include "../config.h"
#endif
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
#include "lua-token.h"
/* possible arguments to set_quadoption() */
typedef enum quadopt_t {
- M_NO,
- M_YES,
- M_ASKNO,
- M_ASKYES
+ M_NO,
+ M_YES,
+ M_ASKNO,
+ M_ASKYES
} quadopt_t;
-void mlua_initialize(void);
-void mlua_shutdown(void);
+void luaM_initialize(void);
+void luaM_shutdown(void);
-int mlua_dofile(const char *filename);
-int mlua_wrap(void (*errfun)(const char *fmt, ...), int status);
+int luaM_dofile(const char *filename);
+int luaM_wrap(void (*errfun)(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2))),
+ int status);
-const char *mlua_reggets(enum lua_token tk);
-int mlua_reggeti(enum lua_token tk);
+quadopt_t luaM_checkquadopt(lua_State *L, int narg);
-void mlua_regsets(enum lua_token tk, const char *s);
-void mlua_regseti(enum lua_token tk, int i);
+#include "madmutt.h"
#endif
#include <lualib.h>
#include <lauxlib.h>
-typedef enum reg_type {
- REG_NIL,
- REG_INT,
- REG_STR,
-} reg_type;
-
typedef struct reg_entry {
int type;
union {
int i;
- void *p;
char *s;
};
} reg_entry;
-static inline void reg_entry_wipe(reg_entry *e) {
- switch (e->type) {
- case REG_STR:
- p_delete(&e->s);
- break;
- default:
- break;
- }
- e->type = REG_NIL;
-}
-
-#define LUA_MADMUTT "madmutt"
-int luaopen_madmutt(lua_State *L);
#endif
#ifndef MUTT_LIB_LUA_LUA_TOKEN_H
#define MUTT_LIB_LUA_LUA_TOKEN_H
-enum lua_token {
+typedef enum mlua_token {
LTK_UNKNOWN = -1,
-`tr 'a-z-/' 'A-Z__' | sed -e 's/.*/ LTK_&,/'`
+`grep_self "$0" | tr 'a-z-/' 'A-Z__' | sed -e 's/.*/ LTK_&,/'`
LTK_count,
-};
+} mlua_token;
+
+extern const char *__mlua_token[LTK_count];
__attribute__((pure))
-enum lua_token lua_which_token(const char *s, ssize_t len);
+mlua_token mlua_which_token(const char *s, ssize_t len);
#endif /* MUTT_LIB_LUA_LUA_TOKEN_H */
EOF
}
}
do_c() {
- cat <<EOF | gperf -m16 -l -t -C -F",0" -Nlua_which_token_aux
+ cat <<EOF | gperf -m16 -l -t -C -F",0" -Nmlua_which_token_aux
%{
`do_hdr`
#include "lua-token.h"
static const struct tok *
-lua_which_token_aux(const char *str, unsigned int len);
+mlua_which_token_aux(const char *str, unsigned int len);
%}
struct tok { const char *name; int val; };
%%
-`do_tokens`
+`grep_self "$0" | do_tokens`
%%
-enum lua_token lua_which_token(const char *s, ssize_t len)
+const char *__mlua_token[LTK_count] = {
+`grep_self "$0" | sed -e 's/.*/ "&",/'`
+};
+
+mlua_token mlua_which_token(const char *s, ssize_t len)
{
if (len < 0)
len = m_strlen(s);
if (len) {
- const struct tok *res = lua_which_token_aux(s, len);
+ const struct tok *res = mlua_which_token_aux(s, len);
return res ? res->val : LTK_UNKNOWN;
} else {
return LTK_UNKNOWN;
rm -f $1
case "$1" in
- *.h) grep_self "$0" | do_h > $1;;
- *.c) grep_self "$0" | do_c > $1;;
+ *.h) do_h > $1;;
+ *.c) do_c > $1;;
*) die "you must ask for the 'h' or 'c' generation";;
esac
chmod -w $1
exit 0
############ Put tokens here ############
+## bindir
+## docdir
## dotlock
## editor
## quit
## sendmail
## shell
+## sysconfdir
+## version
--- /dev/null
+#!/usr/bin/perl -w
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+# Copyright © 2007 Pierre Habouzit
+
+use strict;
+
+my %types;
+my %pkgs;
+
+#{{{ stream functions
+
+sub stream_open($) {
+ my $name = shift;
+ open FILE, $name;
+ return (file => $name, line => 0, f => \*FILE);
+}
+
+sub stream_close($) {
+ my $stream = shift;
+ close $stream->{f};
+}
+
+sub stream_getline($) {
+ my $stream = shift;
+ my $file = $stream->{f};
+ while (<$file>) {
+ ${$stream}{line}++;
+ return $_;
+ }
+ return;
+}
+
+#}}}
+
+#{{{ file:line functions
+
+sub fatal($$) {
+ my ($stream, $msg) = @_;
+ printf STDERR "%s:%d: %s\n", $stream->{file}, $stream->{line}, $msg;
+ exit 1;
+}
+
+sub get_pos($$) {
+ my ($h,$k) = @_;
+ return $h->{$k}{file}.':'.$h->{$k}{line};
+}
+
+sub put_line($$) {
+ my ($src,$inc) = @_;
+ printf "#line %d \"%s\"\n", $src->{line} + $inc, $src->{file};
+}
+
+#}}}
+
+#{{{ parsers
+
+sub parse_type($$) {
+ my ($src, $type) = @_;
+ my %t = (
+ name => $type,
+ file => $src->{file},
+ line => $src->{line},
+ );
+
+ if (defined $types{$type}) {
+ my $pos = get_pos(\%types, $type);
+ fatal($src, "already defined type: `$type' at $pos");
+ }
+
+ while (stream_getline($src)) {
+ last if (/^\s*\}\s*;\s*/);
+ if (/^\s*\.(push|kind|ctype|check)\s*=\s*(.*?)\s*;\s*$/) {
+ $t{$1} = $2;
+ if ($1 eq "kind") {
+ if ($2 =~ /^'([si])'$/) {
+ $t{kind} = $1;
+ } else {
+ fatal($src, "error: .kind should be 'i' or 's' got $2)");
+ }
+ }
+ } elsif (!/^\s*$/) {
+ fatal($src, "syntax error: unknown type directive");
+ }
+ }
+
+ for my $i ('kind', 'ctype') {
+ fatal($src, "incomplete type $type: missing .$i") unless defined $t{$i};
+ }
+ unless (defined $t{check}) {
+ if ($t{kind} eq 's') {
+ $t{check} = 'luaL_checkstring($L, $$)';
+ }
+
+ if ($t{kind} eq 'i') {
+ $t{check} = 'luaL_checkint($l, $$)';
+ }
+ }
+
+ return $types{$type} = \%t;
+}
+
+sub parse_package($$) {
+ my ($src, $pkg) = @_;
+ my %p = (
+ name => $pkg,
+ file => $src->{file},
+ line => $src->{line},
+ );
+
+ if (defined $pkgs{$pkg}) {
+ my $pos = get_pos(\%pkgs, $pkg);
+ fatal($src, "already defined package: `$pkg' at $pos");
+ }
+
+ while (stream_getline($src)) {
+ if (/^\s*\}\s*(\w+)\s*;\s*$/) {
+ $p{cname} = $1;
+ last;
+ }
+
+ if (/^\s*(.*?)\s*=\s*(.*?)\s*;\s*$/) {
+ my ($lhs, $rhs) = ($1, $2);
+ my %m = ( file => $src->{file}, line => $src->{line} );
+
+ if ($lhs =~ /^((?:const\s+)?\w+?)\s*(\w+)$/) {
+ $m{type} = $1;
+ $m{name} = $2;
+ $m{init} = $rhs;
+ push @{$p{props}}, $2;
+ } elsif ($lhs =~ /^((?:const\s+)?\w+?)\s*(\w*)\((.*)\)$/) {
+ $m{type} = $1;
+ $m{name} = $2;
+ $m{proto} = $3;
+ $m{cfun} = $rhs;
+ push @{$p{meths}}, $2;
+ } else {
+ fatal($src, "syntax error");
+ }
+
+ if (defined $p{members}{$m{name}}) {
+ my $pos = get_pos($p{members}{$m{name}}, 0);
+ fatal($src, "already defined package member: `$m{name}' at $pos");
+ }
+
+ $p{members}{$m{name}} = \%m;
+ next;
+ }
+
+ if (!/^\s*$/) {
+ fatal($src, "syntax error");
+ }
+ }
+
+ return $pkgs{$pkg} = \%p;
+}
+
+sub find_type($$) {
+ my ($ref, $typ) = @_;
+
+ if ($typ =~ /^const\s+(\w*)$/) {
+ fatal($ref, "undefined type `$1'") unless defined $types{$1};
+ return (const => 1, type => $types{$1});
+ }
+
+ fatal($ref, "undefined type `$typ'") unless defined $types{$typ};
+ return (const => 0, type => $types{$typ});
+}
+
+#}}}
+
+#{{{ dump_fun
+
+sub dump_fun($$) {
+ my ($pkg, $f) = @_;
+ my %t = find_type($f, $f->{type});
+ my $call = $f->{cfun};
+ $call =~ s/\$/var/;
+
+ print "static int luaM_${pkg}_$f->{name}(lua_State *L) {\n";
+
+ if ($f->{proto} ne "void") {
+ my $i = 1;
+ for my $tmp (split /,/,$f->{proto}) {
+ s/^\s+//;
+ s/\s+$//;
+
+ my %pt = find_type($f, $tmp);
+ my $check = $pt{type}->{check};
+ $check =~ s/\$L/L/;
+ $check =~ s/\$\$/\%d/;
+
+ put_line($pt{type}, 0);
+ printf " $pt{type}->{ctype} var$i = $check\n", $i++;
+ }
+ }
+
+ if (defined $t{type}->{push}) {
+ $call =~ s/\$\$/$t{type}->{push}/;
+ }
+
+ if ($t{type}->{kind} eq 's') {
+ if ($t{const}) {
+ put_line($f, 0);
+ print " lua_pushstring(L, $call);\n";
+ } else {
+ print " {\n";
+ put_line($f, 0);
+ print " char *s = $call;\n";
+ print " lua_pushstring(L, s);\n";
+ print " p_delete(&s);\n";
+ print " }\n";
+ }
+ }
+
+ if ($t{type}->{kind} eq 'i') {
+ put_line($f, 0);
+ print " lua_pushint(L, $call);\n";
+ }
+
+ printf " return %d;\n", ($f->{type} ne "void");
+ print "}\n";
+}
+
+#}}}
+
+#{{{ dump_struct
+
+sub dump_struct_full($) {
+ my ($pkg) = @_;
+
+ put_line($pkg, 0);
+ print "struct luaM_$pkg->{name}_t $pkg->{cname} = {\n";
+
+ foreach (@{$pkg->{props}}) {
+ my $p = $pkg->{members}{$_};
+ my %t = find_type($p, $p->{type});
+
+ if ($t{const}) {
+ put_line($p, 0);
+ print " $p->{init},\n";
+ } else {
+ print " 0,\n" if ($t{type}->{kind} eq 'i');
+ print " NULL,\n" if ($t{type}->{kind} eq 's');
+ }
+ }
+
+ print <<EOF;
+};
+
+static void $pkg->{cname}_init(void)
+{
+EOF
+
+ foreach (@{$pkg->{props}}) {
+ my $p = $pkg->{members}{$_};
+ my %t = find_type($p, $p->{type});
+ my $var = $pkg->{cname}.".".$p->{name};
+
+ next if $t{const};
+
+ put_line($p, 0);
+ print " m_strreplace(&$var, $p->{init});\n" if ($t{type}->{kind} eq 's');
+ print " $var = $p->{init};\n" if ($t{type}->{kind} eq 'i');
+ }
+ print "};\n";
+};
+
+sub dump_struct_short($) {
+ my ($pkg) = @_;
+
+ print "struct luaM_$pkg->{name}_t {\n";
+ foreach (@{$pkg->{props}}) {
+ my $p = $pkg->{members}{$_};
+ my %t = find_type($p, $p->{type});
+ print " $t{type}->{ctype} $p->{name};\n";
+ }
+ put_line($pkg, 0);
+ print <<EOF;
+};
+
+extern struct luaM_$pkg->{name}_t $pkg->{cname};
+EOF
+}
+
+#}}}
+
+#{{{ dump package
+
+sub dump_package_full($) {
+ my $pkg = shift;
+
+ dump_struct_full($pkg);
+ map { print "\n"; dump_fun($pkg->{name}, $pkg->{members}{$_}); } @{$pkg->{meths}};
+ print <<EOF;
+
+static const luaL_reg luaM_$pkg->{name}_methods[] = {
+EOF
+ map { print " { \"$_\", luaM_$pkg->{name}_$_ },\n"; } @{$pkg->{meths}};
+ print <<EOF;
+ { NULL, NULL }
+};
+
+static int luaM_$pkg->{name}_index(lua_State *L)
+{
+ const char *idx = luaL_checkstring(L, 2);
+
+ switch (mlua_which_token(idx, -1)) {
+EOF
+
+ foreach (@{$pkg->{props}}) {
+ my $p = $pkg->{members}{$_};
+ my %t = find_type($p, $p->{type});
+ my $call = $pkg->{cname}.".".$p->{name};
+
+ my $tok = $p->{name};
+ $tok =~ tr/a-z/A-Z/;
+
+ if ($t{type}->{kind} eq 's') {
+ $call = "lua_pushstring(L, $call)";
+ }
+
+ if ($t{type}->{kind} eq 'i') {
+ $call = "lua_pushinteger(L, $call)";
+ }
+
+ if (defined $t{type}->{push}) {
+ $call =~ s/\$\$/$t{type}->{push}/;
+ }
+
+ put_line($p, 0);
+ print " case LTK_$tok:\n";
+ printf " $call;\n";
+ print " return 1;\n";
+ }
+
+print <<EOF;
+ default:
+ lua_rawget(L, lua_upvalueindex(2)); /* try methods */
+ return 1;
+ }
+}
+
+static int luaM_$pkg->{name}_newindex(lua_State *L)
+{
+ const char *idx = luaL_checkstring(L, 2);
+
+ switch (mlua_which_token(idx, -1)) {
+EOF
+
+ foreach (@{$pkg->{props}}) {
+ my $p = $pkg->{members}{$_};
+ my %t = find_type($p, $p->{type});
+
+ next if ($t{const});
+
+ my $tok = $p->{name};
+ my $var = $pkg->{cname}.".".$p->{name};
+ my $check = $t{type}->{check};
+ $tok =~ tr/a-z/A-Z/;
+ $check =~ s/\$L/L/;
+ $check =~ s/\$\$/3/;
+
+ put_line($p, 0);
+ print " case LTK_$tok: \n";
+ print " m_strreplace(&$var, $check)" if ($t{type}->{kind} eq 's');
+ print " $var = $check" if ($t{type}->{kind} eq 'i');
+
+ print ";\n return 1;\n";
+ }
+
+print <<EOF;
+ default:
+ return 1;
+ }
+}
+
+int luaopen_$pkg->{name}(lua_State *L)
+{
+ int mt, methods;
+
+ $pkg->{cname}_init();
+
+ /* create methods table, add it the the table of globals */
+ luaL_openlib(L, "$pkg->{name}", luaM_$pkg->{name}_methods, 0);
+ methods = lua_gettop(L);
+
+ /* create metatable for $pkg->{name}, add it to the registry */
+ luaL_newmetatable(L, "$pkg->{name}");
+ mt = lua_gettop(L);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, mt); /* upvalue 1 */
+ lua_pushvalue(L, methods); /* upvalue 2 */
+ lua_pushcclosure(L, &luaM_$pkg->{name}_index, 2);
+ lua_rawset(L, mt); /* set mt.__index */
+
+ lua_pushliteral(L, "__newindex");
+ lua_newtable(L); /* for new members */
+ lua_pushcclosure(L, &luaM_$pkg->{name}_newindex, 1);
+ lua_rawset(L, mt); /* set mt.__newindex */
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methods); /* dup methods table */
+ lua_rawset(L, mt); /* hide metatable */
+
+ lua_setmetatable(L, methods);
+
+ lua_pop(L, 1); /* drop mt */
+ return 1; /* return methods */
+}
+
+EOF
+}
+
+sub dump_package_short($) {
+ my $pkg = shift;
+ my $upp = $pkg->{name};
+ $upp =~ tr/a-z/A-Z/;
+
+ print <<EOF;
+#ifndef MUTT_LUA_${upp}_H
+#define MUTT_LUA_${upp}_H
+
+EOF
+ dump_struct_short($pkg);
+ print <<EOF
+
+int luaopen_$pkg->{name}(lua_State *L);
+
+#endif /* MUTT_LUA_${upp}_H */
+EOF
+}
+
+#}}}
+
+sub do_c($) {
+ my %src = stream_open(shift);
+ my $resync = 1;
+
+ while (stream_getline(\%src)) {
+ if (/^\s*\@type\s+([a-zA-Z]\w*)\s*=\s*{\s*$/) {
+ parse_type(\%src, $1);
+ $resync = 1;
+ } elsif (/^\s*\@package\s+([a-zA-Z]\w*)\s+{\s*$/) {
+ dump_package_full(parse_package(\%src, $1));
+ $resync = 1;
+ } elsif (/^\s*(\@\w*)/) {
+ fatal(\%src, "syntax error: unknown directive `$1'");
+ } else {
+ next if ($resync && /^\s+$/);
+ if ($resync) {
+ put_line(\%src, 0);
+ $resync = 0;
+ }
+ print;
+ }
+ }
+ print "/* vi"."m:set ft=c: */\n";
+
+ stream_close(\%src);
+}
+
+sub do_h($) {
+ my %src = stream_open(shift);
+ my $resync = 1;
+
+ while (stream_getline(\%src)) {
+ if (/^\s*\@type\s+([a-zA-Z]\w*)\s*=\s*{\s*$/) {
+ parse_type(\%src, $1);
+ } elsif (/^\s*\@package\s+([a-zA-Z]\w*)\s+{\s*$/) {
+ dump_package_short(parse_package(\%src, $1));
+ } elsif (/^\s*(\@\w*)/) {
+ fatal(\%src, "syntax error: unknown directive `$1'");
+ }
+ }
+
+ stream_close(\%src);
+}
+
+if ($#ARGV < 1 || ($ARGV[0] ne "-h" && $ARGV[0] ne "-c")) {
+ print <<EOF;
+usage: mluapkg (-h | -c) file.pkg
+EOF
+ exit 1;
+}
+
+print <<EOF;
+/***** THIS FILE IS AUTOGENERATED DO NOT MODIFY DIRECTLY ! *****/
+EOF
+
+map { do_h($ARGV[$_]); } (1 .. $#ARGV) if ($ARGV[0] eq '-h');
+map { do_c($ARGV[$_]); } (1 .. $#ARGV) if ($ARGV[0] eq '-c');
+++ /dev/null
-/*
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * Copyright © 2007 Pierre Habouzit
- */
-
-#include <lib-lib/lib-lib.h>
-
-#include <sys/types.h>
-#include <pwd.h>
-
-#include "lib-lua_priv.h"
-
-#include "../mutt.h"
-
-/* {{{ madmutt functions */
-
-static int madmutt_pwd(lua_State *L)
-{
- char path[_POSIX_PATH_MAX];
- getcwd(path, sizeof(path));
- lua_pushstring(L, path);
- return 1;
-}
-
-static int madmutt_folder_path(lua_State *L)
-{
- lua_pushstring(L, CurrentFolder ?: "");
- return 1;
-}
-
-static int madmutt_folder_name(lua_State *L)
-{
- const char *p;
-
- if (!m_strisempty(Maildir)
- && m_strstart(CurrentFolder, Maildir, &p) && *p) {
- while (*p == '/')
- p++;
- lua_pushstring(L, p);
- } else {
- p = strchr(CurrentFolder ?: "", '/');
- lua_pushstring(L, p ? p + 1 : (CurrentFolder ?: ""));
- }
- return 1;
-}
-
-static quadopt_t quadopt_parse(const char *s)
-{
- if (!m_strcasecmp("yes", s))
- return M_YES;
- if (!m_strcasecmp("no", s))
- return M_NO;
- if (!m_strcasecmp("ask-yes", s))
- return M_ASKYES;
- if (!m_strcasecmp("ask-no", s))
- return M_ASKNO;
- return -1;
-}
-
-static int madmutt_assign(lua_State *L)
-{
- const char *idx = luaL_checkstring(L, 2);
- const char *val = luaL_checkstring(L, 3);
- int tk;
-
- switch ((tk = lua_which_token(idx, -1))) {
- char buf[STRING];
- int i;
-
- case LTK_DOTLOCK:
- case LTK_SENDMAIL:
- case LTK_SHELL:
- case LTK_EDITOR:
- _mutt_expand_path(buf, sizeof(buf), val, 0);
- val = buf;
- /* FALLTHROUGH */
-
- mlua_regsets(tk, val);
- return 0;
-
- case LTK_QUIT:
- i = quadopt_parse(val);
- if (i < 0)
- return luaL_error(L, "invalid quad option value: '%s'", val);
- mlua_regseti(tk, i);
- return 0;
-
- case LTK_UNKNOWN:
- case LTK_count:
- break;
- }
-
- return luaL_error(L, "read-only or inexistant property '%s'", idx, tk);
-}
-
-static int madmutt_get(lua_State *L)
-{
- const char *idx = luaL_checkstring(L, 2);
- enum lua_token tk = lua_which_token(idx, -1);
-
- switch (tk) {
- case LTK_DOTLOCK:
- case LTK_SENDMAIL:
- case LTK_SHELL:
- case LTK_EDITOR:
- lua_pushstring(L, mlua_reggets(tk));
- return 1;
-
- case LTK_QUIT:
- switch (mlua_reggeti(tk)) {
- case M_YES:
- lua_pushstring(L, "yes");
- return 1;
- case M_NO:
- lua_pushstring(L, "no");
- return 1;
- case M_ASKNO:
- lua_pushstring(L, "ask-no");
- return 1;
- case M_ASKYES:
- lua_pushstring(L, "ask-yes");
- return 1;
- default:
- return 0;
- }
-
- case LTK_UNKNOWN:
- case LTK_count:
- break;
- }
-
- lua_getmetatable(L, 1);
- lua_replace(L, 1);
- lua_rawget(L, 1);
- return 1;
-}
-
-static const struct luaL_Reg madmutt_module_funcs[] = {
- { "pwd", madmutt_pwd },
- /*
- ** .pp
- ** \fIThis is a read-only system property and, at runtime,
- ** specifies the current working directory of the madmutt
- ** binary.\fP
- */
- { "folder_path", madmutt_folder_path },
- /*
- ** .pp
- ** \fIThis is a read-only system property and, at runtime,
- ** specifies the full path or URI of the folder currently
- ** open (if any).\fP
- */
- { "folder_name", madmutt_folder_name },
- /*
- ** .pp
- ** \fIThis is a read-only system property and, at runtime,
- ** specifies the actual name of the folder as far as it could
- ** be detected.\fP
- ** .pp
- ** For detection, $$$folder is first taken into account
- ** and simply stripped to form the result when a match is found. For
- ** example, with $$$folder being \fTimap://host\fP and the folder is
- ** \fTimap://host/INBOX/foo\fP, $$$madmutt_folder_name will be just
- ** \fTINBOX/foo\fP.)
- ** .pp
- ** Second, if the initial portion of a name is not $$$folder,
- ** the result will be everything after the last ``/''.
- ** .pp
- ** Third and last, the result will be just the name if neither
- ** $$$folder nor a ``/'' were found in the name.
- */
-
- { "__newindex", madmutt_assign },
- { "__index", madmutt_get },
- { NULL, NULL }
-};
-
-/* }}} */
-
-/* {{{ read-only properties */
-
-static const struct {
- const char *key;
- const char *value;
-} madmutt_module_vars[] = {
- { "version", VERSION },
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies madmutt's
- ** version string.\fP
- */
- { "sysconfdir", SYSCONFDIR },
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies madmutt's
- ** subversion revision string.\fP
- */
- { "bindir", BINDIR },
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies the
- ** directory containing the madmutt binary.\fP
- */
- { "docdir", PKGDOCDIR },
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies the
- ** directory containing the madmutt documentation.\fP
- */
-#ifdef USE_HCACHE
-#if defined(HAVE_QDBM)
- { "hcache_backend", "qdbm" },
-#elif defined(HAVE_GDBM)
- { "hcache_backend", "gdbm" },
-#elif defined(HAVE_DB4)
- { "hcache_backend", "db4" },
-#else
- { "hcache_backend", "unknown" },
-#endif
- /*
- ** .pp
- ** \fIThis is a read-only system property and specifies the
- ** header chaching's database backend.\fP
- */
-#endif
-};
-
-/* }}} */
-
-/* {{{ madmutt magic properties */
-
-static void madmutt_init_editor(char *buf, ssize_t len)
-{
- m_strcpy(buf, len, getenv("VISUAL") ?: getenv("EDITOR") ?: "vi");
-}
-
-static void madmutt_init_shell(char *buf, ssize_t len)
-{
- struct passwd *pw = getpwuid(getuid());
-
- if (pw) {
- m_strcpy(buf, len, pw->pw_shell);
- _mutt_expand_path(buf, len, pw->pw_shell, 0);
- } else {
- m_strcpy(buf, len, getenv("SHELL") ?: "/bin/sh");
- }
-}
-
-static const struct {
- const char *key;
- void (*fun)(char *buf, ssize_t len);
- const char *val;
-} madmutt_module_vars2[] = {
- { "dotlock", NULL, BINDIR "/mutt_dotlock" },
- /*
- ** .pp
- ** Contains the path of the \fTmadmutt_dotlock(1)\fP binary to be used by
- ** Madmutt.
- */
- { "editor", madmutt_init_editor, NULL },
- /*
- ** .pp
- ** This variable specifies which editor is used by Madmutt.
- ** It defaults to the value of the \fT$$$VISUAL\fP, or \fT$$$EDITOR\fP, environment
- ** variable, or to the string "\fTvi\fP" if neither of those are set.
- */
- { "sendmail", NULL, SENDMAIL " -oem -oi" },
- /*
- ** .pp
- ** Specifies the program and arguments used to deliver mail sent by Madmutt.
- ** Madmutt expects that the specified program interprets additional
- ** arguments as recipient addresses.
- */
- { "shell", madmutt_init_shell, NULL },
- /*
- ** .pp
- ** Command to use when spawning a subshell. By default, the user's login
- ** shell from \fT/etc/passwd\fP is used.
- */
- { "quit", NULL, "yes" },
- /*
- ** .pp
- ** This variable controls whether ``quit'' and ``exit'' actually quit
- ** from Madmutt. If it set to \fIyes\fP, they do quit, if it is set to \fIno\fP, they
- ** have no effect, and if it is set to \fIask-yes\fP or \fIask-no\fP, you are
- ** prompted for confirmation when you try to quit.
- */
-};
-
-/* }}} */
-
-int luaopen_madmutt(lua_State *L)
-{
- int i;
-
- lua_newuserdata(L, sizeof(void*));
- luaL_newmetatable(L, "madmutt.core");
-
- luaL_openlib(L, NULL, madmutt_module_funcs, 0);
-
- for (i = 0; i < countof(madmutt_module_vars); i++) {
- lua_pushstring(L, madmutt_module_vars[i].value);
- lua_setfield(L, -2, madmutt_module_vars[i].key);
- }
-
- lua_setmetatable(L, -2);
-
- for (i = 0; i < countof(madmutt_module_vars2); i++) {
- if (madmutt_module_vars2[i].fun) {
- char buf[STRING];
- (madmutt_module_vars2[i].fun)(buf, sizeof(buf));
- lua_pushstring(L, buf);
- } else {
- lua_pushstring(L, madmutt_module_vars2[i].val);
- }
- lua_setfield(L, -2, madmutt_module_vars2[i].key);
- }
-
- lua_setglobal(L, "madmutt");
- return 1;
-}
--- /dev/null
+/*
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Copyright © 2007 Pierre Habouzit
+ */
+
+#include <lib-lib/lib-lib.h>
+#include <lib-lua/lib-lua.h>
+
+#include <sys/types.h>
+#include <pwd.h>
+
+#include "../mutt.h"
+
+static const char *madmutt_init_shell(void)
+{
+ struct passwd *pw = getpwuid(getuid());
+ return pw ? pw->pw_shell : (getenv("SHELL") ?: "/bin/sh");
+}
+
+static const char *madmutt_pwd(void)
+{
+ char path[_POSIX_PATH_MAX];
+ getcwd(path, sizeof(path));
+ return path;
+}
+
+static const char *luaM_path_post(const char *val)
+{
+ char path[PATH_MAX];
+ _mutt_expand_path(path, sizeof(path), val, 0);
+ return path;
+}
+
+@type string_t = {
+ .kind = 's';
+ .ctype = const char *;
+};
+
+@type path_t = {
+ .push = luaM_path_post($$);
+ .kind = 's';
+ .ctype = char *;
+};
+
+@type quadopt_t = {
+ .kind = 'i';
+ .check = luaM_checkquadopt($L, $$);
+ .ctype = quadopt_t;
+};
+
+@package madmutt {
+ const string_t version = VERSION;
+ const string_t sysconfdir = SYSCONFDIR;
+ const string_t bindir = BINDIR;
+ const string_t docdir = PKGDOCDIR;
+
+ path_t dotlock = BINDIR "/mutt_dotlock";
+ path_t editor = getenv("VISUAL") ?: getenv("EDITOR") ?: "vi";
+ path_t sendmail = SENDMAIL " -eom -oi";
+ path_t shell = madmutt_init_shell();
+
+ quadopt_t quit = M_YES;
+
+ const string_t pwd(void) = madmutt_pwd();
+} ml_core;
+
#include "lib-lua_priv.h"
static lua_State *L;
-static reg_entry registry[LTK_count];
-static const luaL_Reg lualibs[] = {
- {"", luaopen_base},
- {LUA_OSLIBNAME, luaopen_os},
- {LUA_LOADLIBNAME, luaopen_package},
- {LUA_TABLIBNAME, luaopen_table},
- {LUA_IOLIBNAME, luaopen_io},
- {LUA_STRLIBNAME, luaopen_string},
- {LUA_MATHLIBNAME, luaopen_math},
- {LUA_DBLIBNAME, luaopen_debug},
- {LUA_MADMUTT, luaopen_madmutt},
-};
-void mlua_initialize(void)
+void luaM_initialize(void)
{
+ static const luaL_Reg lualibs[] = {
+ {"", luaopen_base},
+ {LUA_OSLIBNAME, luaopen_os},
+ {LUA_LOADLIBNAME, luaopen_package},
+ {LUA_TABLIBNAME, luaopen_table},
+ {LUA_IOLIBNAME, luaopen_io},
+ {LUA_STRLIBNAME, luaopen_string},
+ {LUA_MATHLIBNAME, luaopen_math},
+ {LUA_DBLIBNAME, luaopen_debug},
+ {"madmutt", luaopen_madmutt},
+ };
+
int i;
L = lua_open();
}
}
-void mlua_shutdown(void)
+void luaM_shutdown(void)
{
lua_close(L);
}
-int mlua_dofile(const char *filename)
+int luaM_dofile(const char *filename)
{
return luaL_dofile(L, filename);
}
-int mlua_wrap(void (*errfun)(const char *fmt, ...), int status)
+int luaM_wrap(void (*errfun)(const char *fmt, ...), int status)
{
if (status) {
(*errfun)("-[lua]-: %s\n", lua_tostring(L, -1));
return status;
}
-const char *mlua_reggets(int tk)
-{
- if (registry[tk].type != REG_STR)
- return NULL;
- return registry[tk].s;
-}
-int mlua_reggeti(int tk)
+quadopt_t luaM_checkquadopt(lua_State *Ls, int narg)
{
- if (registry[tk].type != REG_INT)
- return -1;
- return registry[tk].i;
-}
+ const char *s;
+ int i = luaL_checkinteger(Ls, narg);
-void mlua_regsets(int tk, const char *s)
-{
- reg_entry_wipe(registry + tk);
- registry[tk].type = REG_STR;
- registry[tk].s = m_strdup(s);
+ if (i & ~3) {
+ s = lua_pushfstring(Ls, "int in [0-3] expected, got %d", i);
+ return luaL_argerror(Ls, narg, s);
+ }
+ return i;
}
-void mlua_regseti(int tk, int i)
-{
- reg_entry_wipe(registry + tk);
- registry[tk].type = REG_INT;
- registry[tk].i = i;
-}
mutt_quote_filename (f, sizeof (f), path);
snprintf(cmd, sizeof(cmd), "%s %s%s%s%s%s%s%s",
- mlua_reggets(LTK_DOTLOCK),
- flags & DL_FL_TRY ? "-t " : "",
- flags & DL_FL_UNLOCK ? "-u " : "",
- flags & DL_FL_USEPRIV ? "-p " : "",
- flags & DL_FL_FORCE ? "-f " : "",
- flags & DL_FL_UNLINK ? "-d " : "",
- flags & DL_FL_RETRY ? r : "", f);
+ ml_core.dotlock,
+ flags & DL_FL_TRY ? "-t " : "",
+ flags & DL_FL_UNLOCK ? "-u " : "",
+ flags & DL_FL_USEPRIV ? "-p " : "",
+ flags & DL_FL_FORCE ? "-f " : "",
+ flags & DL_FL_UNLINK ? "-d " : "",
+ flags & DL_FL_RETRY ? r : "", f);
return mutt_system (cmd);
}
char cmd[LONG_STRING];
mutt_endwin (NULL);
- m_quotefile_fmt(cmd, sizeof (cmd), mlua_reggets(LTK_EDITOR), data);
+ m_quotefile_fmt(cmd, sizeof (cmd), ml_core.editor, data);
if (mutt_system (cmd) == -1)
mutt_error (_("Error running \"%s\"!"), cmd);
keypad (stdscr, TRUE);
break;
}
- if (query_quadoption2(LTK_QUIT, _("Quit Madmutt?")) == M_YES) {
+ if (query_quadoption2(ml_core.quit, _("Quit Madmutt?")) == M_YES) {
int check;
oldcount = Context ? Context->msgcount : 0;
}
if ((menu->menu == MENU_MAIN)
- && (query_quadoption2(LTK_QUIT,
+ && (query_quadoption2(ml_core.quit,
_("Exit Madmutt without saving?")) == M_YES))
{
if (Context) {
mutt_endwin (Errorbuf);
}
- mlua_shutdown();
+ luaM_shutdown();
exit (0);
}
} else
#endif
{
- m_strcpy(cmd, sizeof(cmd), mlua_reggets(LTK_SENDMAIL));
+ m_strcpy(cmd, sizeof(cmd), ml_core.sendmail);
}
ps = cmd;