mirror of https://github.com/djcb/mu.git
Merge branch 'procmule'
This commit is contained in:
commit
f2de56d4ca
|
@ -23,7 +23,14 @@ else
|
|||
widgets=
|
||||
endif
|
||||
|
||||
SUBDIRS=m4 man src $(widgets) contrib toys
|
||||
if HAVE_GUILE
|
||||
guile=libmuguile
|
||||
else
|
||||
guile=
|
||||
endif
|
||||
|
||||
SUBDIRS=m4 man src $(widgets) $(guile) contrib toys
|
||||
|
||||
|
||||
ACLOCAL_AMFLAGS=-I m4
|
||||
|
||||
|
|
12
NEWS
12
NEWS
|
@ -1,4 +1,16 @@
|
|||
* NEWS (user visible changes)
|
||||
|
||||
* Release 0.9.7 <>
|
||||
|
||||
- enable threading (using -t/--threads) with mu find
|
||||
- don't enforce UTF-8 output, use locale (fixes issue #11)
|
||||
- add mail threading (sorta fixes issue #13)
|
||||
- add header line to --format=mutt-ab (mu cfind), (fixes issue #42)
|
||||
- terminate mu view results with a form-feed marker (use --terminate) (fixes
|
||||
issue #41)
|
||||
- search X-Label: tags (fixes issue #40)
|
||||
- added toys/muile, the mu guile shells, which allows for message stats etc.
|
||||
|
||||
|
||||
** Release 0.9.6 <2011-05-28 Sat>
|
||||
|
||||
|
|
25
TODO
25
TODO
|
@ -1,24 +1,35 @@
|
|||
* Future release
|
||||
|
||||
- [ ] mu stats
|
||||
|
||||
- [ ] config system (config file) (?)
|
||||
- [ ] don't make test mail files executable
|
||||
- [ ] add version info to output of configure, mu.log
|
||||
- [ ] make 'make check' more useful for others
|
||||
- [ ] completion for zsh
|
||||
- [ ] follow symlinks when indexing
|
||||
- [ ] better 'usage' info
|
||||
- [ ] generalize mu_str_normalize for all unicode
|
||||
- [ ] mail threads
|
||||
- [ ] check wmy (date) for begin-end
|
||||
|
||||
|
||||
- [ ] tagging rw
|
||||
|
||||
** release 0.9.7 [100%]
|
||||
|
||||
- [X] mu stats
|
||||
- [X] tagging (ro, based on X-Label)
|
||||
- [X] mail threads
|
||||
- [X] guile interface
|
||||
- [X] add version info to output of configure, mu.log
|
||||
- [X] use system locale in output
|
||||
|
||||
* Releases already done (see NEWS for features)
|
||||
|
||||
** release 0.9.6 [100%]
|
||||
|
||||
|
||||
(see NEWS)
|
||||
|
||||
** release 0.9.5 [100%]
|
||||
|
||||
(see NEWS)
|
||||
|
||||
** release 0.9.4 [100%]
|
||||
|
||||
- [X] add 'mu cfind' to find contacts
|
||||
|
@ -37,7 +48,7 @@
|
|||
- [X] xml,json,sexp output (experimental)
|
||||
- [X] check all strings are really UTF8
|
||||
- [X] add drag & drop support for attachments
|
||||
- [X] add drop & drop support for body images
|
||||
- [X] add drag & drop support for body images
|
||||
- [X] fix size value
|
||||
- [X] fix matching strange folder names
|
||||
- [X] separate exit code for 'not found' vs other errors
|
||||
|
|
27
configure.ac
27
configure.ac
|
@ -208,6 +208,27 @@ AM_CONDITIONAL(HAVE_GIO, [test "x$have_gio" = "xyes"])
|
|||
# should we build the widgets/ dir?
|
||||
AM_CONDITIONAL(BUILD_WIDGETS, [test "x$have_webkit" = "xyes" -a "x$have_gio" = "xyes"])
|
||||
|
||||
|
||||
|
||||
|
||||
# check for guile & guile-snarf
|
||||
AC_PATH_PROG(GUILE, [guile-config], [], [$PATH])
|
||||
AS_IF([test "x$GUILE" != "x"],
|
||||
[GUILE_CFLAGS=`$GUILE compile`; GUILE_LIBS=`$GUILE link`])
|
||||
AC_SUBST(GUILE_LIBS)
|
||||
AC_SUBST(GUILE_CFLAGS)
|
||||
|
||||
AC_PATH_PROG(GUILE_SNARF, [guile-snarf], [], [$PATH])
|
||||
AS_IF([test "x$GUILE_SNARF" != "x"],[
|
||||
AC_DEFINE_UNQUOTED([GUILE_SNARF], ["$GUILE_SNARF"],[Path to guile-snarf])],[
|
||||
AC_MSG_WARN([cannot find guile-snarf])])
|
||||
|
||||
AM_CONDITIONAL(HAVE_GUILE,[test "$xGUILE" != "x" -a "x$GUILE_SNARF != "x])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# check for xdg-open
|
||||
AS_IF([test "x$buildgui"="xyes"],[
|
||||
AC_PATH_PROG(XDGOPEN, [xdg-open], [], [$PATH])
|
||||
|
@ -232,9 +253,11 @@ Makefile
|
|||
src/Makefile
|
||||
src/tests/Makefile
|
||||
widgets/Makefile
|
||||
libmuguile/Makefile
|
||||
toys/Makefile
|
||||
toys/mug/Makefile
|
||||
toys/mug2/Makefile
|
||||
toys/muile/Makefile
|
||||
man/Makefile
|
||||
m4/Makefile
|
||||
contrib/Makefile
|
||||
|
@ -268,6 +291,10 @@ if test "x$have_webkit" = "xyes"; then
|
|||
echo "Webkit version : $webkit_version"
|
||||
fi
|
||||
|
||||
if test "x$GUILE" != "x"; then
|
||||
echo "Guile version : `$GUILE --version 2>&1`"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Build unit tests (glib >= 2.22) : $have_gtest"
|
||||
echo "Build 'mug' toy-ui (requires GTK+) : $buildgui"
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
## Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
##
|
||||
## 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
|
||||
## t he 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, write to the Free Software Foundation,
|
||||
## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
include $(top_srcdir)/gtest.mk
|
||||
|
||||
# enforce compiling this dir first before decending into tests/
|
||||
SUBDIRS= .
|
||||
INCLUDES=-I${top_srcdir}/src ${GUILE_CFLAGS} ${GLIB_CFLAGS}
|
||||
|
||||
# don't use -Werror, as it might break on other compilers
|
||||
# use -Wno-unused-parameters, because some callbacks may not
|
||||
# really need all the params they get
|
||||
AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement
|
||||
AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter
|
||||
|
||||
|
||||
noinst_LTLIBRARIES= \
|
||||
libmuguile.la
|
||||
|
||||
libmuguile_la_SOURCES= \
|
||||
mu-guile-msg.c \
|
||||
mu-guile-msg.h \
|
||||
mu-guile-store.c \
|
||||
mu-guile-store.h \
|
||||
mu-guile-common.c \
|
||||
mu-guile-common.h
|
||||
|
||||
libmuguile_la_LIBADD= \
|
||||
${top_builddir}/src/libmu.la \
|
||||
${GUILE_LIBS}
|
||||
|
||||
XFILES= \
|
||||
mu-guile-msg.x \
|
||||
mu-guile-store.x
|
||||
|
||||
BUILT_SOURCES=$(XFILES) $(DOCFILES)
|
||||
|
||||
|
||||
snarfcppopts= $(DEFS) $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(INCLUDES)
|
||||
SUFFIXES = .x
|
||||
.c.x:
|
||||
$(GUILE_SNARF) -o $@ $< $(snarfcppopts)
|
||||
|
||||
## Add -MG to make the .x magic work with auto-dep code.
|
||||
MKDEP = $(CC) -M -MG $(snarfcppopts)
|
||||
|
||||
|
||||
DISTCLEANFILES=$(XFILES)
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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, 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.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "mu-guile-common.h"
|
||||
|
||||
void
|
||||
mu_guile_error (const char *func_name, int status,
|
||||
const char *fmt, SCM args)
|
||||
{
|
||||
scm_error_scm (scm_from_locale_symbol ("MuError"),
|
||||
scm_from_utf8_string (func_name ? func_name : "<nameless>"),
|
||||
scm_from_utf8_string (fmt), args,
|
||||
scm_list_1 (scm_from_int (status)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
mu_guile_g_error (const char *func_name, GError *err)
|
||||
{
|
||||
scm_error_scm (scm_from_locale_symbol ("MuError"),
|
||||
scm_from_utf8_string (func_name),
|
||||
scm_from_utf8_string (err->message),
|
||||
SCM_UNDEFINED, SCM_UNDEFINED);
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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, 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.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __MU_GUILE_UTILS_H__
|
||||
#define __MU_GUILE_UTILS_H__
|
||||
|
||||
#include <libguile.h>
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param func_name
|
||||
* @param status
|
||||
* @param fmt
|
||||
* @param args
|
||||
*/
|
||||
void mu_guile_error (const char *func_name, int status,
|
||||
const char *fmt, SCM args);
|
||||
|
||||
|
||||
/**
|
||||
* display a GError as a Guile error
|
||||
*
|
||||
* @param func_name function name
|
||||
* @param err Gerror
|
||||
*/
|
||||
void mu_guile_g_error (const char *func_name, GError *err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /*__MU_GUILE_UTILS_H__*/
|
||||
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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, 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.
|
||||
**
|
||||
*/
|
||||
|
||||
#include <mu-msg.h>
|
||||
#include <mu-query.h>
|
||||
#include <mu-runtime.h>
|
||||
|
||||
#include "mu-guile-msg.h"
|
||||
#include "mu-guile-common.h"
|
||||
|
||||
struct _MuMsgWrapper {
|
||||
MuMsg *_msg;
|
||||
gboolean _unrefme;
|
||||
};
|
||||
typedef struct _MuMsgWrapper MuMsgWrapper;
|
||||
|
||||
static long MSG_TAG;
|
||||
|
||||
static int
|
||||
mu_guile_scm_is_msg (SCM scm)
|
||||
{
|
||||
return SCM_NIMP(scm) && (long) SCM_CAR (scm) == MSG_TAG;
|
||||
}
|
||||
|
||||
|
||||
SCM
|
||||
mu_guile_msg_to_scm (MuMsg *msg)
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
|
||||
g_return_val_if_fail (msg, SCM_UNDEFINED);
|
||||
|
||||
msgwrap = scm_gc_malloc (sizeof (MuMsgWrapper), "msg");
|
||||
msgwrap->_msg = msg;
|
||||
msgwrap->_unrefme = FALSE;
|
||||
|
||||
SCM_RETURN_NEWSMOB (MSG_TAG, msgwrap);
|
||||
}
|
||||
|
||||
SCM_DEFINE (msg_make_from_file, "mu:msg:make-from-file", 1, 0, 0,
|
||||
(SCM PATH),
|
||||
"Create a message object based on the message in PATH.\n")
|
||||
#define FUNC_NAME s_msg_make_from_file
|
||||
{
|
||||
MuMsg *msg;
|
||||
GError *err;
|
||||
|
||||
SCM_ASSERT (scm_is_string (PATH), PATH, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
err = NULL;
|
||||
msg = mu_msg_new_from_file (scm_to_utf8_string (PATH), NULL, &err);
|
||||
|
||||
if (err) {
|
||||
mu_guile_g_error (FUNC_NAME, err);
|
||||
g_error_free (err);
|
||||
}
|
||||
|
||||
return msg ? mu_guile_msg_to_scm (msg) : SCM_UNDEFINED;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
static SCM
|
||||
msg_str_field (SCM msg_smob, MuMsgFieldId mfid)
|
||||
{
|
||||
const char *val, *endptr;
|
||||
|
||||
MuMsgWrapper *msgwrap;
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
|
||||
|
||||
val = mu_msg_get_field_string(msgwrap->_msg, mfid);
|
||||
|
||||
if (val && !g_utf8_validate (val, -1, &endptr)) {
|
||||
//return scm_from_utf8_string("<invalid>");
|
||||
gchar *part;
|
||||
SCM scm;
|
||||
part = g_strndup (val, (endptr-val));
|
||||
scm = scm_from_utf8_string(part);
|
||||
g_free (part);
|
||||
return scm;
|
||||
} else
|
||||
return val ? scm_from_utf8_string(val) : SCM_UNSPECIFIED;
|
||||
}
|
||||
|
||||
static gint64
|
||||
msg_num_field (SCM msg_smob, MuMsgFieldId mfid)
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
|
||||
|
||||
return mu_msg_get_field_numeric(msgwrap->_msg, mfid);
|
||||
}
|
||||
|
||||
|
||||
SCM_DEFINE (msg_date, "mu:msg:date", 1, 0, 0,
|
||||
(SCM MSG),
|
||||
"Get the date (time in seconds since epoch) for MSG.\n")
|
||||
#define FUNC_NAME s_msg_date
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return scm_from_unsigned_integer
|
||||
(msg_num_field (MSG, MU_MSG_FIELD_ID_DATE));
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
|
||||
SCM_DEFINE (msg_size, "mu:msg:size", 1, 0, 0,
|
||||
(SCM MSG),
|
||||
"Get the size in bytes for MSG.\n")
|
||||
#define FUNC_NAME s_msg_size
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return scm_from_unsigned_integer
|
||||
(msg_num_field (MSG, MU_MSG_FIELD_ID_SIZE));
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
|
||||
SCM_DEFINE (msg_prio, "mu:msg:priority", 1, 0, 0,
|
||||
(SCM MSG),
|
||||
"Get the priority of MSG (low, normal or high).\n")
|
||||
#define FUNC_NAME s_msg_prio
|
||||
{
|
||||
MuMsgPrio prio;
|
||||
MuMsgWrapper *msgwrap;
|
||||
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(MSG);
|
||||
|
||||
prio = mu_msg_get_prio (msgwrap->_msg);
|
||||
|
||||
switch (prio) {
|
||||
case MU_MSG_PRIO_LOW: return scm_from_utf8_symbol("low");
|
||||
case MU_MSG_PRIO_NORMAL: return scm_from_utf8_symbol("normal");
|
||||
case MU_MSG_PRIO_HIGH: return scm_from_utf8_symbol("high");
|
||||
default:
|
||||
g_return_val_if_reached (SCM_UNDEFINED);
|
||||
}
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
struct _FlagData {
|
||||
MuMsgFlags flags;
|
||||
SCM lst;
|
||||
};
|
||||
typedef struct _FlagData FlagData;
|
||||
|
||||
|
||||
static void
|
||||
check_flag (MuMsgFlags flag, FlagData *fdata)
|
||||
{
|
||||
if (fdata->flags & flag) {
|
||||
SCM item;
|
||||
item = scm_list_1 (scm_from_utf8_symbol(mu_msg_flag_name(flag)));
|
||||
fdata->lst = scm_append_x (scm_list_2(fdata->lst, item));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SCM_DEFINE (msg_flags, "mu:msg:flags", 1, 0, 0,
|
||||
(SCM MSG),
|
||||
"Get the flags for MSG (one or or more of new, passed, replied, "
|
||||
"seen, trashed, draft, flagged, unread, signed, encrypted, "
|
||||
"has-attach).\n")
|
||||
#define FUNC_NAME s_msg_flags
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
FlagData fdata;
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(MSG);
|
||||
|
||||
fdata.flags = mu_msg_get_flags (msgwrap->_msg);
|
||||
fdata.lst = SCM_EOL;
|
||||
mu_msg_flags_foreach ((MuMsgFlagsForeachFunc)check_flag,
|
||||
&fdata);
|
||||
|
||||
return fdata.lst;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (msg_subject, "mu:msg:subject", 1, 0, 0,
|
||||
(SCM MSG), "Get the subject of MSG.\n")
|
||||
#define FUNC_NAME s_msg_subject
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return msg_str_field (MSG, MU_MSG_FIELD_ID_SUBJECT);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (msg_from, "mu:msg:from", 1, 0, 0,
|
||||
(SCM MSG), "Get the sender of MSG.\n")
|
||||
#define FUNC_NAME s_msg_from
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return msg_str_field (MSG, MU_MSG_FIELD_ID_FROM);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
struct _EachContactData {
|
||||
SCM lst;
|
||||
MuMsgContactType ctype;
|
||||
};
|
||||
typedef struct _EachContactData EachContactData;
|
||||
|
||||
static void
|
||||
contacts_to_list (MuMsgContact *contact, EachContactData *ecdata)
|
||||
{
|
||||
if (mu_msg_contact_type (contact) == ecdata->ctype) {
|
||||
SCM item;
|
||||
const char *addr, *name;
|
||||
|
||||
addr = mu_msg_contact_address(contact);
|
||||
name = mu_msg_contact_name(contact);
|
||||
|
||||
item = scm_list_1
|
||||
(scm_list_2 (
|
||||
name ? scm_from_utf8_string(name) : SCM_UNSPECIFIED,
|
||||
addr ? scm_from_utf8_string(addr) : SCM_UNSPECIFIED));
|
||||
|
||||
ecdata->lst = scm_append_x (scm_list_2(ecdata->lst, item));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static SCM
|
||||
contact_list_field (SCM msg_smob, MuMsgFieldId mfid)
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
EachContactData ecdata;
|
||||
|
||||
ecdata.lst = SCM_EOL;
|
||||
|
||||
switch (mfid) {
|
||||
case MU_MSG_FIELD_ID_TO: ecdata.ctype = MU_MSG_CONTACT_TYPE_TO; break;
|
||||
case MU_MSG_FIELD_ID_CC: ecdata.ctype = MU_MSG_CONTACT_TYPE_CC; break;
|
||||
case MU_MSG_FIELD_ID_BCC: ecdata.ctype = MU_MSG_CONTACT_TYPE_BCC; break;
|
||||
default: g_return_val_if_reached (SCM_UNDEFINED);
|
||||
}
|
||||
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
|
||||
|
||||
mu_msg_contact_foreach (msgwrap->_msg,
|
||||
(MuMsgContactForeachFunc)contacts_to_list,
|
||||
&ecdata);
|
||||
return ecdata.lst;
|
||||
}
|
||||
|
||||
|
||||
SCM_DEFINE (msg_to, "mu:msg:to", 1, 0, 0,
|
||||
(SCM MSG), "Get the list of To:-recipients of MSG.\n")
|
||||
#define FUNC_NAME s_msg_to
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return contact_list_field (MSG, MU_MSG_FIELD_ID_TO);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
|
||||
SCM_DEFINE (msg_cc, "mu:msg:cc", 1, 0, 0,
|
||||
(SCM MSG), "Get the list of Cc:-recipients of MSG.\n")
|
||||
#define FUNC_NAME s_msg_cc
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return contact_list_field (MSG, MU_MSG_FIELD_ID_CC);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (msg_bcc, "mu:msg:bcc", 1, 0, 0,
|
||||
(SCM MSG), "Get the list of Bcc:-recipients of MSG.\n")
|
||||
#define FUNC_NAME s_msg_bcc
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return contact_list_field (MSG, MU_MSG_FIELD_ID_BCC);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (msg_path, "mu:msg:path", 1, 0, 0,
|
||||
(SCM MSG), "Get the filesystem path for MSG.\n")
|
||||
#define FUNC_NAME s_msg_path
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return msg_str_field (MSG, MU_MSG_FIELD_ID_PATH);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (msg_maildir, "mu:msg:maildir", 1, 0, 0,
|
||||
(SCM MSG), "Get the maildir where MSG lives.\n")
|
||||
#define FUNC_NAME s_msg_maildir
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return msg_str_field (MSG, MU_MSG_FIELD_ID_MAILDIR);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
|
||||
SCM_DEFINE (msg_msgid, "mu:msg:message-id", 1, 0, 0,
|
||||
(SCM MSG), "Get the MSG's message-id.\n")
|
||||
#define FUNC_NAME s_msg_msgid
|
||||
{
|
||||
return msg_str_field (MSG, MU_MSG_FIELD_ID_MSGID);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (msg_body, "mu:msg:body", 1, 1, 0,
|
||||
(SCM MSG, SCM HTML), "Get the MSG's body. If HTML is #t, "
|
||||
"prefer the html-version, otherwise prefer plain text.\n")
|
||||
#define FUNC_NAME s_msg_body
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
gboolean html;
|
||||
const char *val;
|
||||
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(MSG);
|
||||
html = SCM_UNBNDP(HTML) ? FALSE : HTML == SCM_BOOL_T;
|
||||
|
||||
if (html)
|
||||
val = mu_msg_get_body_html(msgwrap->_msg);
|
||||
else
|
||||
val = mu_msg_get_body_text(msgwrap->_msg);
|
||||
|
||||
return val ? scm_from_utf8_string (val) : SCM_UNSPECIFIED;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (msg_header, "mu:msg:header", 1, 1, 0,
|
||||
(SCM MSG, SCM HEADER), "Get an arbitary HEADER from MSG.\n")
|
||||
#define FUNC_NAME s_msg_header
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
const char *header;
|
||||
const char *val;
|
||||
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
SCM_ASSERT (scm_is_string (HEADER), HEADER, SCM_ARG2, FUNC_NAME);
|
||||
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(MSG);
|
||||
header = scm_to_utf8_string (HEADER);
|
||||
val = mu_msg_get_header(msgwrap->_msg, header);
|
||||
|
||||
return val ? scm_from_utf8_string(val) : SCM_UNDEFINED;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
static SCM
|
||||
msg_string_list_field (SCM msg_smob, MuMsgFieldId mfid)
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
SCM scmlst;
|
||||
const GSList *lst;
|
||||
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
|
||||
lst = mu_msg_get_field_string_list (msgwrap->_msg, mfid);
|
||||
|
||||
for (scmlst = SCM_EOL; lst;
|
||||
lst = g_slist_next(lst)) {
|
||||
SCM item;
|
||||
item = scm_list_1 (scm_from_utf8_string((const char*)lst->data));
|
||||
scmlst = scm_append_x (scm_list_2(scmlst, item));
|
||||
}
|
||||
|
||||
return scmlst;
|
||||
}
|
||||
|
||||
|
||||
SCM_DEFINE (msg_tags, "mu:msg:tags", 1, 1, 0,
|
||||
(SCM MSG), "Get the list of tags (contents of the "
|
||||
"X-Label:-header) for MSG.\n")
|
||||
#define FUNC_NAME s_msg_tags
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return msg_string_list_field (MSG, MU_MSG_FIELD_ID_TAGS);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
|
||||
SCM_DEFINE (msg_refs, "mu:msg:references", 1, 1, 0,
|
||||
(SCM MSG), "Get the list of referenced message-ids "
|
||||
"(contents of the References: and Reply-To: headers).\n")
|
||||
#define FUNC_NAME s_msg_refs
|
||||
{
|
||||
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return msg_string_list_field (MSG, MU_MSG_FIELD_ID_REFS);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
static SCM
|
||||
msg_mark (SCM msg_smob)
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
|
||||
|
||||
msgwrap->_unrefme = TRUE;
|
||||
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
|
||||
static scm_sizet
|
||||
msg_free (SCM msg_smob)
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
|
||||
|
||||
if (msgwrap->_unrefme)
|
||||
mu_msg_unref (msgwrap->_msg);
|
||||
|
||||
return sizeof (MuMsgWrapper);
|
||||
}
|
||||
|
||||
static int
|
||||
msg_print (SCM msg_smob, SCM port, scm_print_state * pstate)
|
||||
{
|
||||
MuMsgWrapper *msgwrap;
|
||||
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
|
||||
|
||||
scm_puts ("#<msg ", port);
|
||||
|
||||
if (msg_smob == SCM_BOOL_F)
|
||||
scm_puts ("#f", port);
|
||||
else
|
||||
scm_puts (mu_msg_get_path(msgwrap->_msg),
|
||||
port);
|
||||
|
||||
scm_puts (">", port);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
define_symbols (void)
|
||||
{
|
||||
/* message priority */
|
||||
scm_c_define ("high", scm_from_int(MU_MSG_PRIO_HIGH));
|
||||
scm_c_define ("low", scm_from_int(MU_MSG_PRIO_LOW));
|
||||
scm_c_define ("normal", scm_from_int(MU_MSG_PRIO_NORMAL));
|
||||
|
||||
/* message flags */
|
||||
scm_c_define ("new", scm_from_int(MU_MSG_FLAG_NEW));
|
||||
scm_c_define ("passed", scm_from_int(MU_MSG_FLAG_PASSED));
|
||||
scm_c_define ("replied", scm_from_int(MU_MSG_FLAG_REPLIED));
|
||||
scm_c_define ("seen", scm_from_int(MU_MSG_FLAG_SEEN));
|
||||
scm_c_define ("trashed", scm_from_int(MU_MSG_FLAG_TRASHED));
|
||||
scm_c_define ("draft", scm_from_int(MU_MSG_FLAG_DRAFT));
|
||||
scm_c_define ("flagged", scm_from_int(MU_MSG_FLAG_FLAGGED));
|
||||
scm_c_define ("unread", scm_from_int(MU_MSG_FLAG_UNREAD));
|
||||
scm_c_define ("signed", scm_from_int(MU_MSG_FLAG_SIGNED));
|
||||
scm_c_define ("encrypted", scm_from_int(MU_MSG_FLAG_ENCRYPTED));
|
||||
scm_c_define ("has-attach", scm_from_int(MU_MSG_FLAG_HAS_ATTACH));
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
mu_guile_msg_init (void *data)
|
||||
{
|
||||
MSG_TAG = scm_make_smob_type ("msg", sizeof(MuMsgWrapper));
|
||||
|
||||
scm_set_smob_mark (MSG_TAG, msg_mark);
|
||||
scm_set_smob_free (MSG_TAG, msg_free);
|
||||
scm_set_smob_print (MSG_TAG, msg_print);
|
||||
|
||||
define_symbols ();
|
||||
|
||||
#include "mu-guile-msg.x"
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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, 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.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __MU_GUILE_MSG_H__
|
||||
#define __MU_GUILE_MSG_H__
|
||||
|
||||
#include <libguile.h>
|
||||
#include <mu-msg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
/**
|
||||
* register MuMsg-related functions/smobs with guile; use with
|
||||
* scm_with_guile
|
||||
*
|
||||
*/
|
||||
void *mu_guile_msg_init (void *data);
|
||||
|
||||
|
||||
/**
|
||||
* create an SCM for the MuMsg*
|
||||
*
|
||||
* @param msg a MuMsg instance
|
||||
*
|
||||
* @return an SCM for the msg
|
||||
*/
|
||||
SCM mu_guile_msg_to_scm (MuMsg *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
|
||||
#endif /*__MU_GUILE_MSG_H__*/
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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, 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.
|
||||
**
|
||||
*/
|
||||
|
||||
#include <mu-query.h>
|
||||
#include <mu-store.h>
|
||||
#include <mu-runtime.h>
|
||||
|
||||
#include "mu-guile-msg.h"
|
||||
#include "mu-guile-store.h"
|
||||
#include "mu-guile-common.h"
|
||||
|
||||
static MuQuery*
|
||||
get_query (void)
|
||||
{
|
||||
MuQuery *query;
|
||||
GError *err;
|
||||
|
||||
err = NULL;
|
||||
query = mu_query_new (mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), &err);
|
||||
if (err) {
|
||||
mu_guile_g_error ("<internal>", err);
|
||||
g_error_free (err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
static MuMsgIter*
|
||||
get_query_iter (MuQuery *query, const char* expr)
|
||||
{
|
||||
MuMsgIter *iter;
|
||||
GError *err;
|
||||
|
||||
err = NULL;
|
||||
iter = mu_query_run (query, expr,
|
||||
FALSE, MU_MSG_FIELD_ID_NONE, TRUE, &err);
|
||||
if (err) {
|
||||
mu_guile_g_error ("<internal>", err);
|
||||
g_error_free (err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
SCM_DEFINE (store_foreach, "mu:store:foreach", 1, 1, 0,
|
||||
(SCM FUNC, SCM EXPR),
|
||||
"Call FUNC for each message in the store, or, if EXPR is specified, "
|
||||
"for each message matching EXPR.\n")
|
||||
#define FUNC_NAME s_store_foreach
|
||||
{
|
||||
MuQuery *query;
|
||||
MuMsgIter *iter;
|
||||
int count;
|
||||
const char* expr;
|
||||
|
||||
SCM_ASSERT (scm_procedure_p (FUNC), FUNC, SCM_ARG1, FUNC_NAME);
|
||||
SCM_ASSERT (scm_is_string (EXPR) || EXPR == SCM_UNSPECIFIED,
|
||||
EXPR, SCM_ARG2, FUNC_NAME);
|
||||
|
||||
query = get_query ();
|
||||
if (!query)
|
||||
return SCM_UNSPECIFIED;
|
||||
|
||||
expr = SCM_UNBNDP(EXPR) ? NULL : scm_to_utf8_string(EXPR);
|
||||
|
||||
iter = get_query_iter (query, expr);
|
||||
if (!iter)
|
||||
return SCM_UNSPECIFIED;
|
||||
|
||||
for (count = 0; !mu_msg_iter_is_done(iter); mu_msg_iter_next (iter)) {
|
||||
|
||||
SCM msgsmob;
|
||||
MuMsg *msg;
|
||||
GError *err;
|
||||
|
||||
err = NULL;
|
||||
msg = mu_msg_iter_get_msg (iter, &err);
|
||||
if (err) {
|
||||
mu_guile_g_error (FUNC_NAME, err);
|
||||
g_error_free (err);
|
||||
continue;
|
||||
}
|
||||
|
||||
msgsmob = mu_guile_msg_to_scm (mu_msg_ref(msg));
|
||||
scm_call_1 (FUNC, msgsmob);
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
mu_query_destroy (query);
|
||||
|
||||
return scm_from_int (count);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
void*
|
||||
mu_guile_store_init (void *data)
|
||||
{
|
||||
#include "mu-guile-store.x"
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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, 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.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __MU_GUILE_STORE_H__
|
||||
#define __MU_GUILE_STORE_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
/**
|
||||
* initialize mu:store functions
|
||||
*
|
||||
*/
|
||||
void *mu_guile_store_init (void *data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#endif /*__MU_GUILE_STORE_H__*/
|
|
@ -99,7 +99,6 @@ GSList* mu_msg_file_get_str_list_field (MuMsgFile *self,
|
|||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* get a numeric value for this message -- the return value should be
|
||||
* cast into the actual type, e.g., time_t, MuMsgPrio etc.
|
||||
|
|
88
src/mu-msg.c
88
src/mu-msg.c
|
@ -521,25 +521,19 @@ fill_contact (MuMsgContact *self, InternetAddress *addr,
|
|||
|
||||
|
||||
static void
|
||||
address_list_foreach (InternetAddressList *addrlist,
|
||||
MuMsgContactType ctype,
|
||||
MuMsgContactForeachFunc func,
|
||||
gpointer user_data)
|
||||
address_list_foreach (InternetAddressList *addrlist, MuMsgContactType ctype,
|
||||
MuMsgContactForeachFunc func, gpointer user_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!addrlist)
|
||||
return;
|
||||
|
||||
for (i = 0; i != internet_address_list_length(addrlist); ++i) {
|
||||
|
||||
for (i = 0; addrlist && i != internet_address_list_length(addrlist);
|
||||
++i) {
|
||||
|
||||
MuMsgContact contact;
|
||||
if (!fill_contact(&contact,
|
||||
internet_address_list_get_address (addrlist, i),
|
||||
ctype)) {
|
||||
MU_WRITE_LOG ("ignoring contact");
|
||||
ctype))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(func)(&contact, user_data))
|
||||
break;
|
||||
|
@ -547,30 +541,25 @@ address_list_foreach (InternetAddressList *addrlist,
|
|||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
get_contacts_from (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
gpointer user_data)
|
||||
addresses_foreach (const char* addrs, MuMsgContactType ctype,
|
||||
MuMsgContactForeachFunc func, gpointer user_data)
|
||||
{
|
||||
InternetAddressList *lst;
|
||||
|
||||
/* we go through this whole excercise of trying to get a *list*
|
||||
* of 'From:' address (usually there is only one...), because
|
||||
* internet_address_parse_string has the nice side-effect of
|
||||
* splitting in names and addresses for us */
|
||||
lst = internet_address_list_parse_string (
|
||||
g_mime_message_get_sender (msg->_file->_mime_msg));
|
||||
InternetAddressList *addrlist;
|
||||
|
||||
if (lst) {
|
||||
address_list_foreach (lst, MU_MSG_CONTACT_TYPE_FROM,
|
||||
func, user_data);
|
||||
g_object_unref (G_OBJECT(lst));
|
||||
}
|
||||
if (!addrs)
|
||||
return;
|
||||
|
||||
addrlist = internet_address_list_parse_string (addrs);
|
||||
if (addrlist) {
|
||||
address_list_foreach (addrlist, ctype, func, user_data);
|
||||
g_object_unref (addrlist);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
msg_contact_foreach_file (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
int i;
|
||||
|
@ -583,11 +572,10 @@ mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func,
|
|||
{GMIME_RECIPIENT_TYPE_BCC, MU_MSG_CONTACT_TYPE_BCC},
|
||||
};
|
||||
|
||||
g_return_if_fail (func && msg);
|
||||
|
||||
/* first, get the from address(es) */
|
||||
get_contacts_from (msg, func, user_data);
|
||||
|
||||
/* sender */
|
||||
addresses_foreach (g_mime_message_get_sender (msg->_file->_mime_msg),
|
||||
MU_MSG_CONTACT_TYPE_FROM, func, user_data);
|
||||
|
||||
/* get to, cc, bcc */
|
||||
for (i = 0; i != G_N_ELEMENTS(ctypes); ++i) {
|
||||
InternetAddressList *addrlist;
|
||||
|
@ -598,6 +586,38 @@ mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
msg_contact_foreach_doc (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
addresses_foreach (mu_msg_get_from (msg),
|
||||
MU_MSG_CONTACT_TYPE_FROM, func, user_data);
|
||||
addresses_foreach (mu_msg_get_to (msg),
|
||||
MU_MSG_CONTACT_TYPE_TO, func, user_data);
|
||||
addresses_foreach (mu_msg_get_cc (msg),
|
||||
MU_MSG_CONTACT_TYPE_CC, func, user_data);
|
||||
addresses_foreach (mu_msg_get_bcc (msg),
|
||||
MU_MSG_CONTACT_TYPE_BCC, func, user_data);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (msg);
|
||||
g_return_if_fail (func);
|
||||
|
||||
if (msg->_doc)
|
||||
msg_contact_foreach_doc (msg, func, user_data);
|
||||
else if (msg->_file)
|
||||
msg_contact_foreach_file (msg, func, user_data);
|
||||
else
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
cmp_str (const char* s1, const char *s2)
|
||||
{
|
||||
|
|
|
@ -77,7 +77,7 @@ MuMsg *mu_msg_new_from_doc (XapianDocument* doc, GError **err)
|
|||
* @return the message with its reference count increased, or NULL in
|
||||
* case of error.
|
||||
*/
|
||||
MuMsg * mu_msg_ref (MuMsg *msg);
|
||||
MuMsg *mu_msg_ref (MuMsg *msg);
|
||||
|
||||
/**
|
||||
* decrease the reference count for this message. if the reference
|
||||
|
@ -305,7 +305,7 @@ MuMsgPrio mu_msg_get_prio (MuMsg *msg);
|
|||
*
|
||||
* @return the timestamp or 0 in case of error
|
||||
*/
|
||||
time_t mu_msg_get_timestamp (MuMsg *msg);
|
||||
time_t mu_msg_get_timestamp (MuMsg *msg);
|
||||
|
||||
|
||||
|
||||
|
@ -334,10 +334,6 @@ const char* mu_msg_get_header (MuMsg *self, const char *header);
|
|||
*/
|
||||
const GSList* mu_msg_get_references (MuMsg *msg);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* get the list of tags (ie., X-Label)
|
||||
*
|
||||
|
|
|
@ -222,29 +222,36 @@ struct _MuQuery {
|
|||
MuSizeRangeProcessor _size_range_processor;
|
||||
};
|
||||
|
||||
static bool
|
||||
set_query (MuQuery *mqx, Xapian::Query& q, const char* searchexpr,
|
||||
GError **err) {
|
||||
static const Xapian::Query
|
||||
get_query (MuQuery *mqx, const char* searchexpr, GError **err)
|
||||
{
|
||||
Xapian::Query query;
|
||||
char *preprocessed;
|
||||
|
||||
preprocessed = mu_query_preprocess (searchexpr);
|
||||
|
||||
try {
|
||||
q = mqx->_qparser.parse_query
|
||||
(searchexpr,
|
||||
query = mqx->_qparser.parse_query
|
||||
(preprocessed,
|
||||
Xapian::QueryParser::FLAG_BOOLEAN |
|
||||
Xapian::QueryParser::FLAG_PURE_NOT |
|
||||
Xapian::QueryParser::FLAG_WILDCARD |
|
||||
Xapian::QueryParser::FLAG_AUTO_SYNONYMS |
|
||||
Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE);
|
||||
|
||||
return true;
|
||||
g_free (preprocessed);
|
||||
return query;
|
||||
|
||||
} MU_XAPIAN_CATCH_BLOCK;
|
||||
|
||||
/* some error occured */
|
||||
g_set_error (err, 0, MU_ERROR_QUERY, "parse error in query '%s'",
|
||||
searchexpr);
|
||||
|
||||
return false;
|
||||
} catch (...) {
|
||||
/* some error occured */
|
||||
g_set_error (err, 0, MU_ERROR_QUERY, "parse error in query '%s'",
|
||||
searchexpr);
|
||||
g_free (preprocessed);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
add_prefix (MuMsgFieldId mfid, Xapian::QueryParser* qparser)
|
||||
{
|
||||
|
@ -343,17 +350,6 @@ mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads,
|
|||
sortfieldid == MU_MSG_FIELD_ID_NONE,
|
||||
NULL);
|
||||
try {
|
||||
Xapian::Query query;
|
||||
char *preprocessed;
|
||||
|
||||
preprocessed = mu_query_preprocess (searchexpr);
|
||||
|
||||
if (!set_query(self, query, preprocessed, err)) {
|
||||
g_free (preprocessed);
|
||||
return NULL;
|
||||
}
|
||||
g_free (preprocessed);
|
||||
|
||||
Xapian::Enquire enq (self->_db);
|
||||
|
||||
/* note, when our result will be *threaded*, we sort
|
||||
|
@ -361,7 +357,13 @@ mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads,
|
|||
if (!threads && sortfieldid != MU_MSG_FIELD_ID_NONE)
|
||||
enq.set_sort_by_value ((Xapian::valueno)sortfieldid,
|
||||
ascending ? true : false);
|
||||
enq.set_query(query);
|
||||
|
||||
if (!mu_str_is_empty(searchexpr)) /* NULL or "" */
|
||||
enq.set_query(get_query (self, searchexpr, err));
|
||||
else
|
||||
enq.set_query(Xapian::Query::MatchAll);
|
||||
|
||||
|
||||
enq.set_cutoff(0,0);
|
||||
|
||||
return mu_msg_iter_new (
|
||||
|
@ -379,17 +381,7 @@ mu_query_as_string (MuQuery *self, const char *searchexpr, GError **err)
|
|||
g_return_val_if_fail (searchexpr, NULL);
|
||||
|
||||
try {
|
||||
Xapian::Query query;
|
||||
char *preprocessed;
|
||||
|
||||
preprocessed = mu_query_preprocess (searchexpr);
|
||||
|
||||
if (!set_query(self, query, preprocessed, err)) {
|
||||
g_free (preprocessed);
|
||||
return NULL;
|
||||
}
|
||||
g_free (preprocessed);
|
||||
|
||||
Xapian::Query query (get_query(self, searchexpr, err));
|
||||
return g_strdup(query.get_description().c_str());
|
||||
|
||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(NULL);
|
||||
|
|
|
@ -68,7 +68,7 @@ char* mu_query_version (MuQuery *store)
|
|||
* manpage, or http://xapian.org/docs/queryparser.html
|
||||
*
|
||||
* @param self a valid MuQuery instance
|
||||
* @param expr the search expression
|
||||
* @param expr the search expression or "" to match all messages
|
||||
* @param threads calculate message-threads
|
||||
* @param sortfield the field id to sort by or MU_MSG_FIELD_ID_NONE if
|
||||
* sorting is not desired
|
||||
|
|
|
@ -78,45 +78,6 @@ typedef enum _MuRuntimePath MuRuntimePath;
|
|||
const char* mu_runtime_path (MuRuntimePath path);
|
||||
|
||||
|
||||
/**
|
||||
* get the mu home directory (typically, ~/.mu); this can only be
|
||||
* called after mu_runtime_init and before mu_runtime_uninit
|
||||
*
|
||||
* @return mu home directory as a string which should be not be
|
||||
* modified, or NULL in case of error.
|
||||
*/
|
||||
const char* mu_runtime_mu_home_dir (void);
|
||||
|
||||
/**
|
||||
* get the xapian directory (typically, ~/.mu/xapian/); this can only
|
||||
* be called after mu_runtime_init and before mu_runtime_uninit
|
||||
*
|
||||
* @return the xapian directory as a string which should be not be
|
||||
* modified, or NULL in case of error.
|
||||
*/
|
||||
const char* mu_runtime_xapian_dir (void);
|
||||
|
||||
|
||||
/**
|
||||
* get the mu bookmarks file (typically, ~/.mu/bookmarks); this can
|
||||
* only be called after mu_runtime_init and before mu_runtime_uninit
|
||||
*
|
||||
* @return the bookmarks file as a string which should be not be
|
||||
* modified, or NULL in case of error.
|
||||
*/
|
||||
const char* mu_runtime_bookmarks_file (void);
|
||||
|
||||
/**
|
||||
* get the mu contacts cache file name (typically,
|
||||
* ~/.mu/contacts.cache); this can only be called after
|
||||
* mu_runtime_init and before mu_runtime_uninit
|
||||
*
|
||||
* @return the contacts cache file name as a string which should be not be
|
||||
* modified, or NULL in case of error.
|
||||
*/
|
||||
const char* mu_runtime_contacts_cache_file (void);
|
||||
|
||||
|
||||
/**
|
||||
* get the mu configuration options (ie., the parsed command line
|
||||
* parameters)
|
||||
|
|
|
@ -443,7 +443,6 @@ mu_str_subject_normalize (const gchar* str)
|
|||
gchar *last_colon;
|
||||
g_return_val_if_fail (str, NULL);
|
||||
|
||||
/* FIXME: improve this */
|
||||
last_colon = g_strrstr (str, ":");
|
||||
if (!last_colon)
|
||||
return str;
|
||||
|
|
|
@ -150,6 +150,7 @@ test_mu_query_01 (void)
|
|||
{ "foo:pepernoot", 0 },
|
||||
{ "funky", 1 },
|
||||
{ "fünkÿ", 1 },
|
||||
{ "", 13 }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -28,3 +28,7 @@ if BUILD_WIDGETS
|
|||
SUBDIRS += mug2
|
||||
endif
|
||||
|
||||
# for muile, we need guile
|
||||
if HAVE_GUILE
|
||||
SUBDIRS += muile
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
## Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
##
|
||||
## 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
|
||||
## t he 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, write to the Free Software Foundation,
|
||||
## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
include $(top_srcdir)/gtest.mk
|
||||
|
||||
# enforce compiling this dir first before decending into tests/
|
||||
INCLUDES=-I${top_srcdir} -I${top_srcdir}/src ${GUILE_CFLAGS} ${GLIB_CFLAGS}
|
||||
|
||||
# don't use -Werror, as it might break on other compilers
|
||||
# use -Wno-unused-parameters, because some callbacks may not
|
||||
# really need all the params they get
|
||||
AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement
|
||||
AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter
|
||||
|
||||
noinst_PROGRAMS= \
|
||||
muile
|
||||
|
||||
muile_SOURCES= \
|
||||
muile.cc
|
||||
|
||||
muile_LDFLAGS= \
|
||||
${top_builddir}/libmuguile/libmuguile.la
|
|
@ -0,0 +1,84 @@
|
|||
* README
|
||||
|
||||
** What is muile?
|
||||
|
||||
`muile' is a little experiment/toy using the equally mu guile bindings, to be
|
||||
found in libmuguile/ in the top-level source directory.
|
||||
|
||||
`guile'[1] is an interpreter/library for the Scheme programming language[2],
|
||||
specifically meant for extending other programs. It is, in fact, the
|
||||
official GNU language for doing so.
|
||||
|
||||
The combination of mu + guile is called `muile', and allows you to write
|
||||
little Scheme-programs to query the mu-database, or inspect individual
|
||||
messages. It is still in an experimental stage, but useful already.
|
||||
|
||||
** How do I get it?
|
||||
|
||||
The git-version and the future 0.9.7 version of mu will automatically build
|
||||
muile if you have guile. I've been using guile 2.x from git, but installing
|
||||
the 'guile-1.8-dev' package (Ubuntu/Debian) should do the trick (I did not
|
||||
test with 1.8 though).
|
||||
|
||||
Then, configure mu. The configure output should tell you about whether guile
|
||||
was found (and where). If it's found, build mu, and toys/muile should be
|
||||
created, as well.
|
||||
|
||||
** What can I do with it?
|
||||
|
||||
Go to toys/muile and start muile. You'll end up with a guile-shell where you
|
||||
can type scheme [1], it looks something like this (for guile 2.x):
|
||||
|
||||
,----
|
||||
| scheme@(guile-user)>
|
||||
`----
|
||||
|
||||
Now, let's load a message (of course, replace with a message on your system):
|
||||
|
||||
,----
|
||||
| scheme@(guile-user)> (define msg (mu:msg:make-from-file "/home/djcb/Maildir/cur/12131e7b20a2:2,S"))
|
||||
`----
|
||||
|
||||
This defines a variable 'msg', which holds some message on your file
|
||||
system. It's now easy to inspect this message:
|
||||
|
||||
,----
|
||||
| scheme@(guile-user)> (define msg (mu:msg:make-from-file "/home/djcb/Maildir/cur/12131e7b20a2:2,S"))
|
||||
`----
|
||||
|
||||
Now, we can inspect this message a bit:
|
||||
,----
|
||||
| scheme@(guile-user)> (mu:msg:subject msg)
|
||||
| $1 = "See me in bikini :-)"
|
||||
| scheme@(guile-user)> (mu:msg:flags msg)
|
||||
| $2 = (attach unread)
|
||||
`----
|
||||
|
||||
and so on. Note, it's probably easiest to explore the various mu: methods
|
||||
using autocompletion; to enable that make sure you have
|
||||
|
||||
(use-modules (ice-9 readline))
|
||||
(activate-readline)
|
||||
|
||||
in your ~/.guile configuration.
|
||||
|
||||
** Can I do some statistics on my messages?
|
||||
|
||||
Yes you can. It's pretty easy in guile. See the mu:stats functions.
|
||||
|
||||
|
||||
|
||||
|
||||
[1] http://www.gnu.org/s/guile/
|
||||
[2] http://en.wikipedia.org/wiki/Scheme_(programming_language)
|
||||
|
||||
# Local Variables:
|
||||
# mode: org; org-startup-folded: nil
|
||||
# End:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
;;
|
||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;;
|
||||
;; 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, 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.
|
||||
|
||||
;; some guile/scheme functions to get various statistics of my mu
|
||||
;; message store.
|
||||
|
||||
;; note, this is a rather inefficient way to calculate the number; for
|
||||
;; demonstration purposes only
|
||||
(define* (mu:stats:count #:optional (EXPR ""))
|
||||
"Count the total number of messages. If the optional EXPR is
|
||||
provided, only count the messages that match it.\n"
|
||||
(mu:store:foreach (lambda(msg) #f) EXPR))
|
||||
|
||||
(define* (mu:stats:average FUNC #:optional (EXPR ""))
|
||||
"Count the average of the result of applying FUNC on all
|
||||
messages. If the optional EXPR is provided, only consider the messages
|
||||
that match it.\n"
|
||||
(let* ((sum 0)
|
||||
(n (mu:store:foreach
|
||||
(lambda(msg) (set! sum (+ sum (FUNC msg)))) EXPR)))
|
||||
(if (= n 0) 0 (exact->inexact (/ sum n)))))
|
||||
|
||||
(define* (mu:stats:average-size #:optional (EXPR ""))
|
||||
"Calculate the average message size. If the optional EXPR is
|
||||
provided, only consider the messages that match it.\n"
|
||||
(mu:stats:average (lambda(msg) (mu:msg:size msg)) EXPR))
|
||||
|
||||
(define* (mu:stats:average-recipient-number #:optional (EXPR ""))
|
||||
"Calculate the average number of recipients (To: + CC: + Bcc:). If
|
||||
the optional EXPR is provided, only consider the messages that match
|
||||
it.\n"
|
||||
(mu:stats:average (lambda(msg)
|
||||
(+(length (mu:msg:to msg))
|
||||
(length (mu:msg:cc msg))
|
||||
(length (mu:msg:bcc msg)))) EXPR))
|
||||
|
||||
(define* (mu:stats:frequency FUNC #:optional (EXPR ""))
|
||||
"FUNC is a function that takes a Msg, and returns the frequency of
|
||||
the different values this function returns. If FUNC returns a list,
|
||||
update the frequency table for each element of this list. If the
|
||||
optional EXPR is provided, only consider messages that match it.\n"
|
||||
(let ((table '()))
|
||||
(mu:store:foreach
|
||||
(lambda(msg)
|
||||
;; note, if val is not already a list, turn it into a list
|
||||
;; then, take frequency for each element in the list
|
||||
(let* ((val (FUNC msg)) (vals (if (list? val) val (list val))))
|
||||
(for-each
|
||||
(lambda (val)
|
||||
(let ((freq (assoc-ref table val)))
|
||||
(set! table (assoc-set! table val
|
||||
(+ 1 (if (eq? freq #f) 0 freq)))))) vals))) EXPR)
|
||||
table))
|
||||
|
||||
|
||||
(define* (mu:stats:per-weekday #:optional (EXPR ""))
|
||||
"Count the total number of messages for each weekday (0-6 for
|
||||
Sun..Sat). If the optional EXPR is provided, only count the messages
|
||||
that match it. The result is a list of pairs (weekday . frequency).\n"
|
||||
(let* ((stats (mu:stats:frequency
|
||||
(lambda (msg) (tm:wday (localtime (mu:msg:date msg)))) EXPR)))
|
||||
(sort stats (lambda(a b) (< (car a) (car b)))))) ;; in order of weekday
|
||||
|
||||
(define* (mu:stats:per-month #:optional (EXPR ""))
|
||||
"Count the total number of messages for each month (0-11 for
|
||||
Jan..Dec). If the optional EXPR is provided, only count the messages
|
||||
that match it. The result is a list of pairs (month . frequency).\n"
|
||||
(let* ((stats (mu:stats:frequency
|
||||
(lambda (msg) (tm:mon (localtime (mu:msg:date msg)))) EXPR)))
|
||||
(sort stats (lambda(a b) (< (car a) (car b)))))) ;; in order of month
|
||||
|
||||
(define* (mu:stats:per-hour #:optional (EXPR ""))
|
||||
"Count the total number of messages for each weekday (0-6 for
|
||||
Sun..Sat). If the optional EXPR is provided, only count the messages
|
||||
that match it. The result is a list of pairs (weekday . frequency).\n"
|
||||
(let* ((stats (mu:stats:frequency
|
||||
(lambda (msg) (tm:hour (localtime (mu:msg:date msg)))) EXPR)))
|
||||
(sort stats (lambda(a b) (< (car a) (car b)))))) ;; in order of hour
|
||||
|
||||
|
||||
(define* (mu:stats:per-year #:optional (EXPR ""))
|
||||
"Count the total number of messages for each year since 1970. If the
|
||||
optional EXPR is provided, only count the messages that match it. The
|
||||
result is a list of pairs (year . frequency).\n"
|
||||
(let* ((stats (mu:stats:frequency
|
||||
(lambda (msg) (+ 1900 (tm:year (localtime (mu:msg:date msg)))))
|
||||
EXPR)))
|
||||
(sort stats (lambda(a b) (< (car a) (car b)))))) ;; in order of year
|
||||
|
||||
|
||||
(define* (mu:stats:top-n FUNC N #:optional (EXPR ""))
|
||||
"Get the Top-N frequency of the result of FUNC applied on each
|
||||
message. If the optional EXPR is provided, only consider the messages
|
||||
that match it."
|
||||
(let* ((freq (mu:stats:frequency FUNC EXPR))
|
||||
(top (sort freq (lambda (a b) (< (cdr b) (cdr a) )))))
|
||||
(list-head top (min (length freq) N))))
|
||||
|
||||
(define* (mu:stats:top-n-to #:optional (N 10) (EXPR ""))
|
||||
"Get the Top-N To:-recipients. If the optional N is not provided,
|
||||
use 10. If the optional EXPR is provided, only consider the messages
|
||||
that match it."
|
||||
(mu:stats:top-n
|
||||
(lambda (msg) (mu:msg:to msg)) N EXPR))
|
||||
|
||||
(define* (mu:stats:top-n-from #:optional (N 10) (EXPR ""))
|
||||
"Get the Top-N senders (From:). If the optional N is not provided,
|
||||
use 10. If the optional EXPR is provided, only consider the messages
|
||||
that match it."
|
||||
(mu:stats:top-n
|
||||
(lambda (msg) (mu:msg:from msg)) N EXPR))
|
||||
|
||||
(define* (mu:stats:top-n-subject #:optional (N 10) (EXPR ""))
|
||||
"Get the Top-N subjects. If the optional N is not provided,
|
||||
use 10. If the optional EXPR is provided, only consider the messages
|
||||
that match it."
|
||||
(mu:stats:top-n
|
||||
(lambda (msg) (mu:msg:subject msg)) N EXPR))
|
||||
|
||||
(define (mu:stats:table pairs)
|
||||
"display a list of PAIRS in a table-like fashion"
|
||||
(let ((maxlen 0))
|
||||
(for-each ;; find the widest in the first col
|
||||
(lambda (pair)
|
||||
(set! maxlen
|
||||
(max maxlen (string-length (format #f "~s " (car pair)))))) pairs)
|
||||
(for-each
|
||||
(lambda (pair)
|
||||
(let ((first (format #f "~s" (car pair)))
|
||||
(second (format #f "~s" (cdr pair))))
|
||||
(display (format #f "~A~v_~A\n"
|
||||
first (- maxlen (string-length first)) second))))
|
||||
pairs)))
|
||||
|
||||
(define (mu:stats:plot pairs)
|
||||
"plot a table using gnuplot"
|
||||
;; create a tmpfile with the data...
|
||||
(let* ((datafile (tmpnam))
|
||||
(output (open datafile (logior O_CREAT O_WRONLY) #O0644)))
|
||||
(for-each
|
||||
(lambda (pair) (display (format #f "~A ~A\n" (car pair) (cdr pair)) output))
|
||||
pairs)
|
||||
(close-output-port output)
|
||||
;; now, display it.
|
||||
(system (format #f "gnuplot -p -e 'plot \"~A\" w boxes fs pattern 2'" datafile))))
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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, 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.
|
||||
**
|
||||
*/
|
||||
|
||||
#include <mu-runtime.h>
|
||||
|
||||
#include <libguile.h>
|
||||
#include <libmuguile/mu-guile-msg.h>
|
||||
#include <libmuguile/mu-guile-store.h>
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
mu_runtime_init ("/home/djcb/.mu");
|
||||
|
||||
scm_with_guile (&mu_guile_msg_init, NULL);
|
||||
scm_with_guile (&mu_guile_store_init, NULL);
|
||||
|
||||
scm_shell (argc, argv);
|
||||
|
||||
mu_runtime_uninit ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue