diff --git a/scm/mu-scm-repl.scm b/scm/mu-scm-repl.scm index 6cd8efe7..89f7248a 100644 --- a/scm/mu-scm-repl.scm +++ b/scm/mu-scm-repl.scm @@ -21,6 +21,7 @@ ;; after printing UNIX-CONNECT:\n on stdout (let ((socket-path (getenv "MU_SCM_SOCKET_PATH"))) (when socket-path + (info "listening on domain socket ~a" socket-path) (format #t "~a\n" socket-path) (run-server (make-unix-domain-server-socket #:path socket-path)))) diff --git a/scm/mu-scm-store.cc b/scm/mu-scm-store.cc index bd96e2be..928f93fd 100644 --- a/scm/mu-scm-store.cc +++ b/scm/mu-scm-store.cc @@ -127,7 +127,8 @@ to_sort_field_id(SCM field, const char *func, int pos) const auto sym{from_scm(scm_symbol_to_string(field), func, pos)}; if (const auto field_opt{field_from_name(sym)}; !field_opt) { - throw ScmError{ScmError::Id::WrongType, func, pos, field, "sort-field-symbol"}; + throw ScmError{ScmError::Id::WrongType, func, pos, field, + "sort-field-symbol"}; } else return field_opt->id; } @@ -144,7 +145,8 @@ subr_cc_store_mfind(SCM store_scm, SCM query_scm, SCM related_scm, SCM skip_dups const auto skip_dups(from_scm(skip_dups_scm, func, 4)); if (!scm_is_false(sort_field_scm) && !scm_is_symbol(sort_field_scm)) - throw ScmError{ScmError::Id::WrongType, func, 5, sort_field_scm, "#f or sort-field-symbol"}; + throw ScmError{ScmError::Id::WrongType, func, 5, sort_field_scm, + "#f or sort-field-symbol"}; const auto sort_field_id = to_sort_field_id(sort_field_scm, func, 5); const auto reverse(from_scm(reverse_scm, func, 6)); diff --git a/scm/mu-scm.cc b/scm/mu-scm.cc index ac016045..40718c20 100644 --- a/scm/mu-scm.cc +++ b/scm/mu-scm.cc @@ -64,6 +64,46 @@ init_options(const Options& opts) scm_c_define("%options", scm_opts); } +static void +init_misc() +{ + scm_define(make_symbol("level-critical"), to_scm(G_LOG_LEVEL_CRITICAL)); + scm_define(make_symbol("level-warning"), to_scm(G_LOG_LEVEL_WARNING)); + scm_define(make_symbol("level-info"), to_scm(G_LOG_LEVEL_INFO)); + scm_define(make_symbol("level-debug"), to_scm(G_LOG_LEVEL_DEBUG)); +} + +static SCM +subr_cc_log(SCM level_scm, SCM str_scm) try { + constexpr auto func{"cc-log"}; + + const auto level{static_cast(from_scm(level_scm, func, 1))}; + if (level != G_LOG_LEVEL_CRITICAL && level != G_LOG_LEVEL_WARNING && + level != G_LOG_LEVEL_INFO && level != G_LOG_LEVEL_DEBUG) + throw ScmError{ScmError::Id::WrongType, func, 1, level_scm, "level"}; + + const auto str{from_scm(str_scm, func, 2)}; + + g_log("mu-scm", level, "%s", str.c_str()); + + return SCM_UNSPECIFIED; + +} catch (const ScmError& err) { + err.throw_scm(); +} + +static void +init_subrs() +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" + scm_c_define_gsubr("cc-log", 2/*req*/, 0/*opt*/, 0/*rst*/, + reinterpret_cast(subr_cc_log)); +#pragma GCC diagnostic pop +} + + + static const Result make_mu_scm_path(const std::string& fname) { @@ -157,8 +197,6 @@ maybe_remove_socket_path() } } - - static void prepare_shell(const Options& opts, StrVec& args) { @@ -186,6 +224,9 @@ init_module_mu(void* data) const ModMuData& conf{*reinterpret_cast(data)}; init_options(conf.opts); + init_misc(); + init_subrs(); + init_store(conf.store); init_message(); init_mime(); diff --git a/scm/mu-scm.hh b/scm/mu-scm.hh index 7d017016..840a76bb 100644 --- a/scm/mu-scm.hh +++ b/scm/mu-scm.hh @@ -227,6 +227,10 @@ namespace Mu::Scm { return scm_from_bool(val); else if constexpr (std::is_same_v) return scm_from_size_t(val); + else if constexpr (std::is_same_v) + return scm_from_int(val); + else if constexpr (std::is_same_v) + return scm_from_int(static_cast(val)); else if constexpr (std::is_same_v) return scm_from_int64(val); else if constexpr (std::is_same_v) diff --git a/scm/mu-scm.scm b/scm/mu-scm.scm index 679162a4..182a46b3 100644 --- a/scm/mu-scm.scm +++ b/scm/mu-scm.scm @@ -21,6 +21,7 @@ :use-module (system foreign) :use-module (rnrs bytevectors) :use-module (ice-9 optargs) + :use-module (ice-9 format) :use-module (ice-9 binary-ports) #:export ( ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -100,11 +101,16 @@ %options ;; %preferences + ;; logging + debug + info + warning + critical + ;; helpers string->time time->string)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Helpers @@ -637,3 +643,43 @@ UTC time. (let ((t (if utc? (gmtime time-t) (localtime time-t)))) (strftime format t)) #f))) + + +;; Logging to mu's log + +(define (mlog level frmstr . args) + "Log to the mu logger. + +LEVEL is the logging-level, a symbol one of: + debug, info, warning, critical + +FRMSTR is a format string like `(format)', and the ARGS are the parameters for +that format string." + (let ((msg (if (null? args) + frmstr + (apply format #f frmstr args)))) + (cc-log level msg))) + +(define (info frm . args) + "Log a message at info level to the mu logger. +FRM is the format string and ARGS are its arguments, see `(format)' for details +on the precise format." + (apply mlog level-info frm args)) + +(define (warning frm . args) + "Log a message at warning level to the mu logger. +FRM is the format string and ARGS are its arguments, see `(format)' for details +on the precise format." + (apply mlog level-warning frm args)) + +(define (critical frm . args) + "Log a message at critical level to the mu logger. +FRM is the format string and ARGS are its arguments, see `(format)' for details +on the precise format." + (apply mlog level-critical frm args)) + +(define (debug frm . args) + "Log a message at debug level to the mu logger. +FRM is the format string and ARGS are its arguments, see `(format)' for details +on the precise format." + (apply mlog level-debug frm args)) diff --git a/scm/mu-scm.texi b/scm/mu-scm.texi index 14e4598e..57fe4727 100644 --- a/scm/mu-scm.texi +++ b/scm/mu-scm.texi @@ -939,6 +939,26 @@ their default values. @node Helpers @section Helpers +@deffn {Scheme Procedure} debug frm . args +@end deffn + +@deffn {Scheme Procedure} info frm . args +@end deffn + +@deffn {Scheme Procedure} warning frm . args +@end deffn + +@deffn {Scheme Procedure} critical frm . args +@end deffn + +Log using @t{mu}'s logging facilities at the given level (debug, info, warning +or critical). @code{frm} and @code{args} are expected to be a format string and +its arguments, respectively, according to Guile's @code{format} function. + +Note: where the log output exactly appears (i.e., log-file, journal, console, +nowhere) dependis on the particulars of the system and how mu was started; see +the @t{mu (1)} man-page for details on the latter. + @deffn {Scheme Procedure} string->time timestr [#:utc? (assoc-ref %preferences 'utc?)] @end deffn Convert some ISO-8601-style time-string to a seconds-since-epoch @t{time_t}