aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2020-01-01 16:08:21 +1300
committerTom Ryder <tom@sanctum.geek.nz>2020-01-01 16:09:11 +1300
commit80227fc6263ca864227de8b9d8d9f93f19ad173a (patch)
treef0183af0e7fc5a73cc2427653ac7fd67a3848a2e
parentAdd trailing commas (diff)
downloaddotfiles-80227fc6263ca864227de8b9d8d9f93f19ad173a.tar.gz
dotfiles-80227fc6263ca864227de8b9d8d9f93f19ad173a.zip
Reimplement mail header importance flagging
Just for fun, write something a little more comprehensive to read in the entire mail header as a data structure, in order to add or set header fields correctly. I don't think this is totally RFC-compliant yet; I'll need to check.
-rw-r--r--vim/after/ftplugin/mail.vim17
-rw-r--r--vim/autoload/mail.vim32
-rw-r--r--vim/autoload/mail/header.vim54
-rw-r--r--vim/autoload/mail/header/field.vim39
-rw-r--r--vim/autoload/mail/importance.vim24
5 files changed, 129 insertions, 37 deletions
diff --git a/vim/after/ftplugin/mail.vim b/vim/after/ftplugin/mail.vim
index f81be691..dbb2f7c5 100644
--- a/vim/after/ftplugin/mail.vim
+++ b/vim/after/ftplugin/mail.vim
@@ -9,10 +9,14 @@ let b:undo_ftplugin .= '|delcommand SuggestStart'
SuggestStart
" Normalise quoting
-command -buffer -bar -range=% StrictQuote
+command -bar -buffer -range=% StrictQuote
\ call mail#StrictQuote(<q-line1>, <q-line2>)
let b:undo_ftplugin .= '|delcommand StrictQuote'
+command -bar -buffer -nargs=1 SetImportance
+ \ call mail#importance#Set(<f-args>)
+let b:undo_ftplugin .= '|delcommand SetImportance'
+
" Add a space to the end of wrapped lines for format-flowed mail
setlocal formatoptions+=w
let b:undo_ftplugin .= '|setlocal formatoptions<'
@@ -35,12 +39,15 @@ if exists('no_plugin_maps') || exists('no_mail_maps')
endif
" Flag messages as important/unimportant
-nnoremap <buffer> <LocalLeader>h
- \ :<C-U>call mail#FlagImportant()<CR>
+nnoremap <buffer> <LocalLeader>ih
+ \ :<C-U>SetImportance high<CR>
let b:undo_ftplugin .= '|nunmap <buffer> <LocalLeader>h'
-nnoremap <buffer> <LocalLeader>l
- \ :<C-U>call mail#FlagUnimportant()<CR>
+nnoremap <buffer> <LocalLeader>il
+ \ :<C-U>SetImportance low<CR>
let b:undo_ftplugin .= '|nunmap <buffer> <LocalLeader>l'
+nnoremap <buffer> <LocalLeader>in
+ \ :<C-U>SetImportance normal<CR>
+let b:undo_ftplugin .= '|nunmap <buffer> <LocalLeader>n'
" Quote operator
nnoremap <buffer> <expr> <LocalLeader>q
diff --git a/vim/autoload/mail.vim b/vim/autoload/mail.vim
index abed119a..cd585af4 100644
--- a/vim/autoload/mail.vim
+++ b/vim/autoload/mail.vim
@@ -1,35 +1,3 @@
-" Add a header to a mail message
-function! mail#AddHeaderField(name, body) abort
- let num = 0
- while num < line('$') && getline(num + 1) !=# ''
- let num += 1
- endwhile
- call append(num, a:name.': '.a:body)
-endfunction
-
-" Add a set of headers to a mail message
-function! mail#AddHeaderFields(fields) abort
- for name in sort(keys(a:fields))
- call mail#AddHeaderField(name, a:fields[name])
- endfor
-endfunction
-
-" Flag a message as important
-function! mail#FlagImportant() abort
- call mail#AddHeaderFields({
- \ 'Importance': 'High',
- \ 'X-Priority': 1,
- \ })
-endfunction
-
-" Flag a message as unimportant
-function! mail#FlagUnimportant() abort
- call mail#AddHeaderFields({
- \ 'Importance': 'Low',
- \ 'X-Priority': 5,
- \ })
-endfunction
-
" Move through quoted paragraphs like normal-mode `{` and `}`
function! mail#NewBlank(count, up, visual) abort
diff --git a/vim/autoload/mail/header.vim b/vim/autoload/mail/header.vim
new file mode 100644
index 00000000..8495a721
--- /dev/null
+++ b/vim/autoload/mail/header.vim
@@ -0,0 +1,54 @@
+function! mail#header#Read() abort
+ let fields = []
+ for lnum in range(1, line('$'))
+ let line = getline(lnum)
+ let matchlist = matchlist(
+ \ line,
+ \ '^\([a-zA-Z0-9-]\+\):\s*\(\_.*\)',
+ \)
+ if !empty(matchlist)
+ let field = {
+ \ 'name': matchlist[1],
+ \ 'body': matchlist[2],
+ \}
+ call add(fields, field)
+ elseif line =~ '^\s' && exists('field')
+ let field['body'] .= "\n" . line
+ elseif line ==# ''
+ break
+ else
+ throw 'Parse error'
+ endif
+ endfor
+ let header = {
+ \'fields': fields,
+ \}
+ return header
+endfunction
+
+function! mail#header#String(header) abort
+ let fields = copy(a:header['fields'])
+ return join(
+ \ map(
+ \ copy(a:header['fields']),
+ \ 'v:val[''name''] . '': '' . v:val[''body''] . "\n"'),
+ \ '',
+ \)
+endfunction
+
+function! mail#header#Write(header) abort
+ let start = 1
+ for lnum in range(1, line('$'))
+ if getline(lnum) ==# ''
+ break
+ endif
+ let end = lnum
+ endfor
+ let curpos = getpos('.')
+ if exists('end')
+ let range = join([start, end], ',')
+ execute join(['silent', range, 'delete'])
+ endif
+ silent 0 put =mail#header#String(a:header)
+ call setpos('.', curpos)
+endfunction
diff --git a/vim/autoload/mail/header/field.vim b/vim/autoload/mail/header/field.vim
new file mode 100644
index 00000000..ab3d405a
--- /dev/null
+++ b/vim/autoload/mail/header/field.vim
@@ -0,0 +1,39 @@
+function! mail#header#field#Add(header, name, body) abort
+ let new = {
+ \ 'name': a:name,
+ \ 'body': a:body,
+ \}
+ call add(a:header['fields'], new)
+endfunction
+
+function! mail#header#field#Set(header, name, body) abort
+ let fields = []
+ let new = {
+ \ 'name': a:name,
+ \ 'body': a:body,
+ \}
+ for field in a:header['fields']
+ if field['name'] ==? a:name
+ if exists('new')
+ let field = new | unlet new
+ else
+ continue
+ endif
+ endif
+ call add(fields, field)
+ endfor
+ if exists('new')
+ call add(fields, new) | unlet new
+ endif
+ let a:header['fields'] = fields
+endfunction
+
+function! mail#header#field#Clear(header, name) abort
+ let fields = []
+ for field in a:header['fields']
+ if field['name'] !=? a:name
+ call add(fields, field)
+ endif
+ endfor
+ let a:header['fields'] = fields
+endfunction
diff --git a/vim/autoload/mail/importance.vim b/vim/autoload/mail/importance.vim
new file mode 100644
index 00000000..6a5ed096
--- /dev/null
+++ b/vim/autoload/mail/importance.vim
@@ -0,0 +1,24 @@
+let s:fields = {
+ \ 'high': {
+ \ 'Importance': 'High',
+ \ 'X-Priority': '1',
+ \},
+ \ 'low': {
+ \ 'Importance': 'Low',
+ \ 'X-Priority': '5',
+ \},
+ \ 'normal': {},
+ \}
+
+function! mail#importance#Set(level) abort
+ let header = mail#header#Read()
+ let fields = s:fields[a:level]
+ for name in ['Importance', 'X-Priority']
+ if has_key(fields, name)
+ call mail#header#field#Set(header, name, fields[name])
+ else
+ call mail#header#field#Clear(header, name)
+ endif
+ endfor
+ call mail#header#Write(header)
+endfunction