From 9dbb881e8d59f6c17a934e8ba54724dbd5d2c36b Mon Sep 17 00:00:00 2001 From: Gaute Hope Date: Wed, 3 Apr 2019 15:50:12 +0200 Subject: reply, forward: use lynx (or configurable program) to convert HTML parts to text when quoting --- src/compose_message.cc | 3 ++- src/config.cc | 2 ++ src/message_thread.cc | 62 ++++++++++++++++++++++++++++++++++++++++++++ src/message_thread.hh | 1 + src/modes/edit_message.cc | 2 +- src/modes/forward_message.cc | 2 +- src/modes/reply_message.cc | 2 +- src/utils/cmd.cc | 57 ++++++++++++++++++++++++++++++++++++++-- src/utils/cmd.hh | 10 +++---- 9 files changed, 130 insertions(+), 11 deletions(-) diff --git a/src/compose_message.cc b/src/compose_message.cc index 9633008..a139e92 100644 --- a/src/compose_message.cc +++ b/src/compose_message.cc @@ -157,7 +157,7 @@ namespace Astroid { sf << s.rdbuf (); s.close (); if (account->signature_separate) { - md_body_content += "-- \n"; + md_body_content += "-- \n"; } md_body_content += sf.str (); } @@ -228,6 +228,7 @@ namespace Astroid { contentStream = g_mime_stream_mem_new_with_buffer(_html.c_str(), _html.size()); } + g_spawn_close_pid (pid); } catch (Glib::SpawnError &ex) { LOG (error) << "cm: md: failed to spawn markdown processor: " << ex.what (); diff --git a/src/config.cc b/src/config.cc index 3830ace..0b71440 100644 --- a/src/config.cc +++ b/src/config.cc @@ -235,6 +235,8 @@ namespace Astroid { default_config.put ("editor.markdown_processor", "cmark"); default_config.put ("editor.markdown_on", false); // default + default_config.put ("mail.reply.quote_processor", "w3m -dump -T text/html"); // e.g. lynx -dump + /* mail composition */ default_config.put ("mail.reply.quote_line", "Excerpts from %1's message of %2:"); // %1 = author, %2 = pretty_verbose_date default_config.put ("mail.reply.mailinglist_reply_to_sender", true); diff --git a/src/message_thread.cc b/src/message_thread.cc index a9c7712..fee5295 100644 --- a/src/message_thread.cc +++ b/src/message_thread.cc @@ -11,6 +11,7 @@ # include "message_thread.hh" # include "chunk.hh" # include "utils/utils.hh" +# include "utils/cmd.hh" # include "utils/date_utils.hh" # include "utils/address.hh" # include "utils/ustring_utils.hh" @@ -367,6 +368,67 @@ namespace Astroid { return body; } + ustring Message::quote () { + if (missing_content) { + LOG (warn) << "message: missing content, no text."; + return ""; + } + + ustring body; + + function< void (refptr) > app_body = + [&] (refptr c) + { + /* check if we're the preferred sibling */ + bool use = false; + + if (c->siblings.size() >= 1) { + if (c->is_content_type ("text", "plain") || c->is_content_type ("text", "html")) { + use = true; + } else { + /* check if there are any other preferred */ + if (all_of (c->siblings.begin (), + c->siblings.end (), + [](refptr c) { return !(c->is_content_type ("text", "plain") || c->is_content_type("text", "html")); })) { + use = true; // no + } else { + use = false; + } + } + } else { + use = true; + } + + if (use) { + if (c->viewable && (c->is_content_type ("text", "plain") || c->is_content_type ("text", "html"))) { + /* will output html if HTML part */ + if (c->is_content_type ("text", "html")) { + ustring quote_cmd = astroid->config ().get("mail.reply.quote_processor"); + + if (!quote_cmd.empty()) { + ustring h = c->viewable_text (false); + ustring _stdout, _stderr; + Cmd::pipe (quote_cmd, h, _stdout, _stderr); + + body += _stdout; + } + + } else { + body += c->viewable_text (false); + } + } + + for_each (c->kids.begin(), + c->kids.end (), + app_body); + } + }; + + app_body (root); + + return body; + } + vector> Message::attachments () { /* return a flat vector of attachments */ diff --git a/src/message_thread.hh b/src/message_thread.hh index f3b6ee3..4bee766 100644 --- a/src/message_thread.hh +++ b/src/message_thread.hh @@ -68,6 +68,7 @@ namespace Astroid { std::vector tags; ustring plain_text (bool fallback_html = false); + ustring quote (); std::vector> attachments (); refptr get_chunk_by_id (int id); diff --git a/src/modes/edit_message.cc b/src/modes/edit_message.cc index f5a4d50..e0fa3bc 100644 --- a/src/modes/edit_message.cc +++ b/src/modes/edit_message.cc @@ -1258,7 +1258,7 @@ namespace Astroid { if (tmpfile.fail()) { LOG (error) << "em: error: could not create tmpfile!"; - throw runtime_error ("em: coult not create tmpfile!"); + throw runtime_error ("em: could not create tmpfile!"); } tmpfile.close (); diff --git a/src/modes/forward_message.cc b/src/modes/forward_message.cc index 8343b42..e1b55c2 100644 --- a/src/modes/forward_message.cc +++ b/src/modes/forward_message.cc @@ -67,7 +67,7 @@ namespace Astroid { quoted << "Cc: " << AddressList(msg->cc()).str () << endl; quoted << endl; - string vt = msg->plain_text (false); + string vt = msg->quote (); quoted << vt; body = ustring(quoted.str()); diff --git a/src/modes/reply_message.cc b/src/modes/reply_message.cc index 915c18e..6fae745 100644 --- a/src/modes/reply_message.cc +++ b/src/modes/reply_message.cc @@ -56,7 +56,7 @@ namespace Astroid { quoted << quoting_a.raw () << endl; - string vt = msg->plain_text (false); + string vt = msg->quote (); stringstream sstr (vt); while (sstr.good()) { string line; diff --git a/src/utils/cmd.cc b/src/utils/cmd.cc index 49c2983..a9dba49 100644 --- a/src/utils/cmd.cc +++ b/src/utils/cmd.cc @@ -8,6 +8,7 @@ using std::endl; using std::string; + namespace bfs = boost::filesystem; namespace Astroid { @@ -44,9 +45,8 @@ namespace Astroid { ustring c = (!undo ? cmd : undo_cmd); LOG (info) << "cmd: running: " << c; - string _stdout; - string _stderr; int exit; + string _stdout, _stderr; string _cmd = c; try { @@ -71,6 +71,7 @@ namespace Astroid { return (exit == 0); } + ustring Cmd::substitute (const ustring _cmd) { ustring ncmd = _cmd; @@ -82,6 +83,58 @@ namespace Astroid { return ncmd; } + + bool Cmd::pipe (ustring cmd, const ustring& _stdin, ustring& _stdout, ustring &_stderr) { + LOG (info) << "cmd: running: " << cmd; + + try { + int pid; + int stdin; + int stdout; + int stderr; + std::vector args = Glib::shell_parse_argv (cmd); + + Glib::spawn_async_with_pipes ("", + args, + Glib::SPAWN_DO_NOT_REAP_CHILD | + Glib::SPAWN_SEARCH_PATH, + sigc::slot (), + &pid, + &stdin, + &stdout, + &stderr + ); + + refptr ch_stdin; + refptr ch_stdout; + refptr ch_stderr; + ch_stdin = Glib::IOChannel::create_from_fd (stdin); + ch_stdout = Glib::IOChannel::create_from_fd (stdout); + ch_stderr = Glib::IOChannel::create_from_fd (stderr); + + ch_stdin->write (_stdin); + ch_stdin->close (); + + ch_stderr->read_to_end (_stderr); + ch_stderr->close (); + + if (!_stderr.empty ()) { + LOG (error) << "cmd: " << _stderr; + } + + ch_stdout->read_to_end (_stdout); + ch_stdout->close (); + + g_spawn_close_pid (pid); + + } catch (Glib::SpawnError &ex) { + LOG (error) << "cmd: failed to execute: '" << cmd << "': " << ex.what (); + return false; + } + + + return true; + } } diff --git a/src/utils/cmd.hh b/src/utils/cmd.hh index cc28c02..c65e9cf 100644 --- a/src/utils/cmd.hh +++ b/src/utils/cmd.hh @@ -1,11 +1,7 @@ # pragma once # include "astroid.hh" - -# include -# include -# include -# include +# include namespace Astroid { class Cmd { @@ -25,8 +21,12 @@ namespace Astroid { ustring undo_cmd; int execute (bool undo); /* currently only in sync */ + int execute (bool undo, std::string& _stdout, std::string& _stderr); /* currently only in sync */ ustring substitute (ustring); + + public: + static bool pipe (ustring cmd, const ustring& _stdin, ustring& _stdout, ustring& _stderr); }; } -- cgit v1.2.3