diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fc3da7..d323a53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,17 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Fixed +### Added -- `\Seen` flag when moving a message -- Attachments arg for reply and forward commands [#109] -- Vim doc [#117] +- Add ability to change account in with the Vim plugin [#91] +- Add possibility to make Himalaya default email app [#160] [[#161](https://github.com/soywod/himalaya/pull/161)] ### Changed - [**BREAKING**] Short version of reply `--all` arg is now `-A` to avoid conflicts with `--attachment|-a` - Template management [#80] +### Fixed + +- `\Seen` flag when moving a message +- Attachments arg for reply and forward commands [#109] +- Vim doc [#117] + ### Removed - `Content-Type` from templates [#146] @@ -82,20 +87,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Improve config compatibility on Windows [#111](https://github.com/soywod/himalaya/pull/111) +- Improve config compatibility on Windows [[#111](https://github.com/soywod/himalaya/pull/111)] - Vim table containing emoji [#122] ## [0.2.6] - 2021-04-17 ### Added -- Insecure TLS option [#84] [#103](https://github.com/soywod/himalaya/pull/103) [#105](https://github.com/soywod/himalaya/pull/105) -- Completion subcommands [#99](https://github.com/soywod/himalaya/pull/99) -- Vim flags to enable telescope preview and to choose picker [#97](https://github.com/soywod/himalaya/pull/97) +- Insecure TLS option [#84] [#103](https://github.com/soywod/himalaya/pull/103) [[#105](https://github.com/soywod/himalaya/pull/105)] +- Completion subcommands [[#99](https://github.com/soywod/himalaya/pull/99)] +- Vim flags to enable telescope preview and to choose picker [[#97](https://github.com/soywod/himalaya/pull/97)] ### Changed -- Make `install.sh` POSIX compliant [#53](https://github.com/soywod/himalaya/pull/53) +- Make `install.sh` POSIX compliant [[#53](https://github.com/soywod/himalaya/pull/53)] ### Fixed @@ -265,6 +270,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#86]: https://github.com/soywod/himalaya/issues/86 [#87]: https://github.com/soywod/himalaya/issues/87 [#89]: https://github.com/soywod/himalaya/issues/89 +[#91]: https://github.com/soywod/himalaya/issues/91 [#95]: https://github.com/soywod/himalaya/issues/95 [#96]: https://github.com/soywod/himalaya/issues/96 [#100]: https://github.com/soywod/himalaya/issues/100 @@ -286,3 +292,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#141]: https://github.com/soywod/himalaya/issues/141 [#144]: https://github.com/soywod/himalaya/issues/144 [#146]: https://github.com/soywod/himalaya/issues/146 +[#160]: https://github.com/soywod/himalaya/issues/160 diff --git a/src/config/model.rs b/src/config/model.rs index 6ea3699..b25647b 100644 --- a/src/config/model.rs +++ b/src/config/model.rs @@ -210,16 +210,16 @@ impl Config { pub fn find_account_by_name(&self, name: Option<&str>) -> Result<&Account> { match name { - Some(name) => self - .accounts - .get(name) - .ok_or_else(|| format!("Cannot find account `{}`", name).into()), - None => self + Some("") | None => self .accounts .iter() .find(|(_, account)| account.default.unwrap_or(false)) .map(|(_, account)| account) .ok_or_else(|| "Cannot find default account".into()), + Some(name) => self + .accounts + .get(name) + .ok_or_else(|| format!("Cannot find account `{}`", name).into()), } } diff --git a/src/msg/model.rs b/src/msg/model.rs index 5267ee0..cea52f9 100644 --- a/src/msg/model.rs +++ b/src/msg/model.rs @@ -4,7 +4,7 @@ use log::warn; use mailparse::{self, MailHeaderMap}; use rfc2047_decoder; use serde::{ - ser::{self, SerializeStruct}, + ser::{self, SerializeStruct, Serializer}, Serialize, }; use std::{borrow::Cow, fmt, fs, path::PathBuf, result}; @@ -101,23 +101,13 @@ impl<'a> Attachments { // Readable message #[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] pub struct ReadableMsg { pub content: String, + #[serde(serialize_with = "bool_to_int")] pub has_attachment: bool, } -// impl Serialize for ReadableMsg { -// fn serialize(&self, serializer: S) -> result::Result -// where -// S: ser::Serializer, -// { -// let mut state = serializer.serialize_struct("ReadableMsg", 2)?; -// state.serialize_field("content", &self.content)?; -// state.serialize_field("hasAttachment", if self.has_attachment { &1 } else { &0 })?; -// state.end() -// } -// } - impl fmt::Display for ReadableMsg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { writeln!(f, "{}", self.content) @@ -660,3 +650,15 @@ impl fmt::Display for Msgs<'_> { writeln!(f, "\n{}", Table::render(&self.0)) } } + +// Custom bool to int serializer + +fn bool_to_int(t: &bool, s: S) -> std::result::Result +where + S: Serializer, +{ + match t { + true => s.serialize_u8(1), + false => s.serialize_u8(0), + } +} diff --git a/vim/autoload/himalaya/account.vim b/vim/autoload/himalaya/account.vim new file mode 100644 index 0000000..27c8f9e --- /dev/null +++ b/vim/autoload/himalaya/account.vim @@ -0,0 +1,11 @@ +" Account + +let s:curr_account = "" + +function! himalaya#account#curr() + return s:curr_account +endfunction + +function! himalaya#account#set(account) + let s:curr_account = a:account +endfunction diff --git a/vim/autoload/himalaya/mbox.vim b/vim/autoload/himalaya/mbox.vim index 788423d..99de826 100644 --- a/vim/autoload/himalaya/mbox.vim +++ b/vim/autoload/himalaya/mbox.vim @@ -1,23 +1,6 @@ let s:dir = expand(":h") let s:cli = function("himalaya#shared#cli#call") -" Pagination - -let s:curr_page = 0 -function! himalaya#mbox#curr_page() - return s:curr_page -endfunction - -function! himalaya#mbox#prev_page() - let s:curr_page = max([0, s:curr_page - 1]) - call himalaya#msg#list() -endfunction - -function! himalaya#mbox#next_page() - let s:curr_page = s:curr_page + 1 - call himalaya#msg#list() -endfunction - " Pickers function! s:telescope_picker(cb, mboxes) @@ -39,16 +22,36 @@ function! s:native_picker(cb, mboxes) call function(a:cb)(a:mboxes[choice]) endfunction +" Pagination + +let s:curr_page = 0 + +function! himalaya#mbox#curr_page() + return s:curr_page +endfunction + +function! himalaya#mbox#prev_page() + let s:curr_page = max([0, s:curr_page - 1]) + call himalaya#msg#list() +endfunction + +function! himalaya#mbox#next_page() + let s:curr_page = s:curr_page + 1 + call himalaya#msg#list() +endfunction + " Mailbox let s:curr_mbox = "INBOX" + function! himalaya#mbox#curr_mbox() return s:curr_mbox endfunction function! himalaya#mbox#pick(cb) try - let mboxes = map(s:cli("mailboxes", [], "Fetching mailboxes", 0), "v:val.name") + let account = himalaya#account#curr() + let mboxes = map(s:cli("--account %s mailboxes", [shellescape(account)], "Fetching mailboxes", 0), "v:val.name") if exists("g:himalaya_mailbox_picker") let picker = g:himalaya_mailbox_picker diff --git a/vim/autoload/himalaya/msg.vim b/vim/autoload/himalaya/msg.vim index e8ce202..2f55a11 100644 --- a/vim/autoload/himalaya/msg.vim +++ b/vim/autoload/himalaya/msg.vim @@ -9,18 +9,21 @@ let s:draft = "" function! s:format_msg_for_list(msg) let msg = copy(a:msg) - - let flag_new = index(msg.flags, "Seen") == -1 ? "N" : " " + let flag_new = index(msg.flags, "Seen") == -1 ? "✷" : " " let flag_flagged = index(msg.flags, "Flagged") == -1 ? " " : "!" - let flag_replied = index(msg.flags, "Answered") == -1 ? " " : "R" - let msg.flags = printf("%s%s%s", flag_new, flag_replied, flag_flagged) - + let flag_replied = index(msg.flags, "Answered") == -1 ? " " : "↵" + let msg.flags = printf("%s %s %s", flag_new, flag_replied, flag_flagged) return msg endfunction -function! himalaya#msg#list_with(mbox, page, should_throw) +function! himalaya#msg#list_with(account, mbox, page, should_throw) let pos = getpos(".") - let msgs = s:cli("--mailbox %s list --page %d", [shellescape(a:mbox), a:page], printf("Fetching %s messages", a:mbox), a:should_throw) + let msgs = s:cli( + \"--account %s --mailbox %s list --page %d", + \[shellescape(a:account), shellescape(a:mbox), a:page], + \printf("Fetching %s messages", a:mbox), + \a:should_throw, + \) let msgs = map(msgs, "s:format_msg_for_list(v:val)") let buftype = stridx(bufname("%"), "Himalaya messages") == 0 ? "file" : "edit" execute printf("silent! %s Himalaya messages [%s] [page %d]", buftype, a:mbox, a:page + 1) @@ -34,11 +37,13 @@ function! himalaya#msg#list_with(mbox, page, should_throw) call setpos('.', pos) endfunction -function! himalaya#msg#list() +function! himalaya#msg#list(...) try + call himalaya#account#set(a:0 > 0 ? a:1 : "") + let account = himalaya#account#curr() let mbox = himalaya#mbox#curr_mbox() let page = himalaya#mbox#curr_page() - call himalaya#msg#list_with(mbox, page, 1) + call himalaya#msg#list_with(account, mbox, page, 1) catch if !empty(v:exception) redraw | call himalaya#shared#log#err(v:exception) @@ -50,8 +55,14 @@ function! himalaya#msg#read() try let pos = getpos(".") let s:msg_id = s:get_focused_msg_id() + let account = himalaya#account#curr() let mbox = himalaya#mbox#curr_mbox() - let msg = s:cli("--mailbox %s read %d", [shellescape(mbox), s:msg_id], printf("Fetching message %d", s:msg_id), 0) + let msg = s:cli( + \"--account %s --mailbox %s read %d", + \[shellescape(account), shellescape(mbox), s:msg_id], + \printf("Fetching message %d", s:msg_id), + \0, + \) let attachment = msg.hasAttachment ? " []" : "" execute printf("silent! edit Himalaya read message [%d]%s", s:msg_id, attachment) setlocal modifiable @@ -72,7 +83,8 @@ endfunction function! himalaya#msg#write() try let pos = getpos(".") - let msg = s:cli("template new", [], "Fetching new template", 0) + let account = himalaya#account#curr() + let msg = s:cli("--account %s template new", [shellescape(account)], "Fetching new template", 0) silent! edit Himalaya write call append(0, split(substitute(msg.template, "\r", "", "g"), "\n")) silent execute "$d" @@ -90,9 +102,15 @@ endfunction function! himalaya#msg#reply() try let pos = getpos(".") + let account = himalaya#account#curr() let mbox = himalaya#mbox#curr_mbox() let msg_id = stridx(bufname("%"), "Himalaya messages") == 0 ? s:get_focused_msg_id() : s:msg_id - let msg = s:cli("--mailbox %s template reply %d", [shellescape(mbox), msg_id], "Fetching reply template", 0) + let msg = s:cli( + \"--account %s --mailbox %s template reply %d", + \[shellescape(account), shellescape(mbox), msg_id], + \"Fetching reply template", + \0, + \) execute printf("silent! edit Himalaya reply [%d]", msg_id) call append(0, split(substitute(msg.template, "\r", "", "g"), "\n")) silent execute "$d" @@ -110,9 +128,15 @@ endfunction function! himalaya#msg#reply_all() try let pos = getpos(".") + let account = himalaya#account#curr() let mbox = himalaya#mbox#curr_mbox() let msg_id = stridx(bufname("%"), "Himalaya messages") == 0 ? s:get_focused_msg_id() : s:msg_id - let msg = s:cli("--mailbox %s template reply %d --all", [shellescape(mbox), msg_id], "Fetching reply all template", 0) + let msg = s:cli( + \"--account %s --mailbox %s template reply %d --all", + \[shellescape(account), shellescape(mbox), msg_id], + \"Fetching reply all template", + \0 + \) execute printf("silent! edit Himalaya reply all [%d]", msg_id) call append(0, split(substitute(msg.template, "\r", "", "g"), "\n")) silent execute "$d" @@ -130,9 +154,15 @@ endfunction function! himalaya#msg#forward() try let pos = getpos(".") + let account = himalaya#account#curr() let mbox = himalaya#mbox#curr_mbox() let msg_id = stridx(bufname("%"), "Himalaya messages") == 0 ? s:get_focused_msg_id() : s:msg_id - let msg = s:cli("--mailbox %s template forward %d", [shellescape(mbox), msg_id], "Fetching forward template", 0) + let msg = s:cli( + \"--account %s --mailbox %s template forward %d", + \[shellescape(account), shellescape(mbox), msg_id], + \"Fetching forward template", + \0 + \) execute printf("silent! edit Himalaya forward [%d]", msg_id) call append(0, split(substitute(msg.template, "\r", "", "g"), "\n")) silent execute "$d" @@ -155,9 +185,15 @@ function! himalaya#msg#_copy(target_mbox) try let pos = getpos(".") let msg_id = stridx(bufname("%"), "Himalaya messages") == 0 ? s:get_focused_msg_id() : s:msg_id + let account = himalaya#account#curr() let source_mbox = himalaya#mbox#curr_mbox() - let msg = s:cli("--mailbox %s copy %d %s", [shellescape(source_mbox), msg_id, shellescape(a:target_mbox)], "Copying message", 1) - call himalaya#msg#list_with(source_mbox, himalaya#mbox#curr_page(), 1) + let msg = s:cli( + \"--account %s --mailbox %s copy %d %s", + \[shellescape(account), shellescape(source_mbox), msg_id, shellescape(a:target_mbox)], + \"Copying message", + \1, + \) + call himalaya#msg#list_with(account, source_mbox, himalaya#mbox#curr_page(), 1) call setpos('.', pos) catch if !empty(v:exception) @@ -177,9 +213,15 @@ function! himalaya#msg#_move(target_mbox) redraw | echo if choice != "y" | return | endif let pos = getpos(".") + let account = himalaya#account#curr() let source_mbox = himalaya#mbox#curr_mbox() - let msg = s:cli("--mailbox %s move %d %s", [shellescape(source_mbox), msg_id, shellescape(a:target_mbox)], "Moving message", 1) - call himalaya#msg#list_with(source_mbox, himalaya#mbox#curr_page(), 1) + let msg = s:cli( + \"--account %s --mailbox %s move %d %s", + \[shellescape(account), shellescape(source_mbox), msg_id, shellescape(a:target_mbox)], + \"Moving message", + \1, + \) + call himalaya#msg#list_with(account, source_mbox, himalaya#mbox#curr_page(), 1) call setpos('.', pos) catch if !empty(v:exception) @@ -195,9 +237,15 @@ function! himalaya#msg#delete() range redraw | echo if choice != "y" | return | endif let pos = getpos(".") + let account = himalaya#account#curr() let mbox = himalaya#mbox#curr_mbox() - let msg = s:cli("--mailbox %s delete %s", [shellescape(mbox), msg_ids], "Deleting message(s)", 1) - call himalaya#msg#list_with(mbox, himalaya#mbox#curr_page(), 1) + let msg = s:cli( + \"--account %s --mailbox %s delete %s", + \[shellescape(account), shellescape(mbox), msg_ids], + \"Deleting message(s)", + \1, + \) + call himalaya#msg#list_with(account, mbox, himalaya#mbox#curr_page(), 1) call setpos('.', pos) catch if !empty(v:exception) @@ -214,15 +262,26 @@ endfunction function! himalaya#msg#draft_handle() try + let account = himalaya#account#curr() while 1 let choice = input("(s)end, (d)raft, (q)uit or (c)ancel? ") let choice = tolower(choice)[0] redraw | echo if choice == "s" - return s:cli("send -- %s", [shellescape(s:draft)], "Sending message", 0) + return s:cli( + \"--account %s send -- %s", + \[shellescape(account), shellescape(s:draft)], + \"Sending message", + \0, + \) elseif choice == "d" - return s:cli("--mailbox Drafts save -- %s", [shellescape(s:draft)], "Saving draft", 0) + return s:cli( + \"--account %s --mailbox Drafts save -- %s", + \[shellescape(account), shellescape(s:draft)], + \"Saving draft", + \0, + \) elseif choice == "q" return elseif choice == "c" @@ -238,9 +297,15 @@ endfunction function! himalaya#msg#attachments() try + let account = himalaya#account#curr() let mbox = himalaya#mbox#curr_mbox() let msg_id = stridx(bufname("%"), "Himalaya messages") == 0 ? s:get_focused_msg_id() : s:msg_id - let msg = s:cli("--mailbox %s attachments %d", [shellescape(mbox), msg_id], "Downloading attachments", 0) + let msg = s:cli( + \"--account %s --mailbox %s attachments %d", + \[shellescape(account), shellescape(mbox), msg_id], + \"Downloading attachments", + \0 + \) call himalaya#shared#log#info(msg) catch if !empty(v:exception) diff --git a/vim/ftplugin/himalaya-msg-list.vim b/vim/ftplugin/himalaya-msg-list.vim index 9231211..de5abc2 100644 --- a/vim/ftplugin/himalaya-msg-list.vim +++ b/vim/ftplugin/himalaya-msg-list.vim @@ -1,4 +1,3 @@ -setlocal bufhidden=wipe setlocal buftype=nofile setlocal cursorline setlocal nomodifiable diff --git a/vim/lua/himalaya/mbox.lua b/vim/lua/himalaya/mbox.lua index 9fff03a..1a13a2d 100644 --- a/vim/lua/himalaya/mbox.lua +++ b/vim/lua/himalaya/mbox.lua @@ -10,7 +10,8 @@ local previewers = require('telescope.previewers') local function preview_command(entry, bufnr) vim.api.nvim_buf_call(bufnr, function() local page = 0 -- page 0 for preview - local success, output = pcall(vim.fn['himalaya#msg#list_with'], entry.value, page, true) + local account = pcall(vim.fn['himalaya#account#curr']) + local success, output = pcall(vim.fn['himalaya#msg#list_with'], account, entry.value, page, true) if not (success) then vim.cmd('redraw') vim.bo.modifiable = true diff --git a/vim/plugin/himalaya.vim b/vim/plugin/himalaya.vim index 1f88db9..b3ebbfe 100644 --- a/vim/plugin/himalaya.vim +++ b/vim/plugin/himalaya.vim @@ -8,4 +8,4 @@ if !executable("himalaya") throw "Himalaya CLI not found, see https://github.com/soywod/himalaya#installation" endif -command! Himalaya call himalaya#msg#list() +command! -nargs=* Himalaya call himalaya#msg#list() diff --git a/vim/syntax/himalaya-msg-list.vim b/vim/syntax/himalaya-msg-list.vim index c94f3ba..9cccd1d 100644 --- a/vim/syntax/himalaya-msg-list.vim +++ b/vim/syntax/himalaya-msg-list.vim @@ -9,7 +9,7 @@ syntax match hym_subject /^|.\{-}|.\{-}|.\{-}|/ contains=hym_uid,hym syntax match hym_sender /^|.\{-}|.\{-}|.\{-}|.\{-}|/ contains=hym_uid,hym_flags,hym_subject,hym_sep syntax match hym_date /^|.\{-}|.\{-}|.\{-}|.\{-}|.\{-}|/ contains=hym_uid,hym_flags,hym_subject,hym_sender,hym_sep syntax match hym_head /.*\%1l/ contains=hym_sep -syntax match hym_unseen /^|.\{-}|N.*$/ contains=hym_sep +syntax match hym_unseen /^|.\{-}|✷.*$/ contains=hym_sep highlight hym_head term=bold,underline cterm=bold,underline gui=bold,underline highlight hym_unseen term=bold cterm=bold gui=bold