This commit is contained in:
Geoffrey Frogeye 2018-08-13 12:20:09 +02:00
parent fe27b3b960
commit 86bc146125
6 changed files with 380 additions and 37 deletions

View file

@ -22,7 +22,7 @@ URxvt*scrollBar: false
! Font declaration ! Font declaration
URxvt.font: xft:DejaVu Sans Mono for Powerline:size=12:antialias=true URxvt.font: xft:DejaVu Sans Mono for Powerline:size=12:antialias=true,xft:Symbola:size=12:antialias=true
! Font spacing ! Font spacing
URxvt.letterSpace: 0 URxvt.letterSpace: 0

64
bashrc
View file

@ -43,6 +43,9 @@ alias rm='rm -Iv --one-file-system'
alias free='free -m' alias free='free -m'
alias df='df -h' alias df='df -h'
alias dmesg='dmesg --ctime' alias dmesg='dmesg --ctime'
alias ffmpeg='ffmpeg -hide_banner'
alias ffprobe='ffprobe -hide_banner'
alias ffplay='ffplay -hide_banner'
# Frequent mistakes # Frequent mistakes
alias sl=ls alias sl=ls
@ -62,31 +65,48 @@ alias tracefiles="strace -f -t -e trace=file"
alias n='urxvtc &' alias n='urxvtc &'
# Superseding commands with better ones if they are present # Superseding commands with better ones if they are present
function vi() { function _do_rank() { # executables... -- arguments...
if which vim &> /dev/null; then for ex in "$@"
alias vi='vim' do
fi [ "$ex" == "--" ] && break
vim "$@" if which "$ex" &> /dev/null
then
for al in "$@"
do
shift
[ "$al" == "--" ] && break
alias "$al"="$ex"
done
"$ex" "$@"
return $?
fi
done
for ex in "$@"
do
[ "$al" == "--" ] && break
if -z "$list"
then
list=$ex
else
list=$list, $ex
fi
done
echo "Not installed: $list"
} }
function pass() {
if which gopass &> /dev/null; then function _install_rank() { # executables...
alias pass='gopass' for ex in "$@"
fi do
gopass "$@" list=$@
} alias "$ex"="_do_rank $list --"
function wol() { done
if which wakeonlan &> /dev/null; then
alias wol='wakeonlan'
fi
wakeonlan "$@"
}
function mutt() {
if which neomutt &> /dev/null; then
alias mutt='neomutt'
fi
neomutt "$@"
} }
_install_rank nvim vim vi
_install_rank gopass pass
_install_rank wakeonlan wol
_install_rank neomutt mutt
# SHELL CUSTOMIZATION # SHELL CUSTOMIZATION
complete -cf sudo complete -cf sudo

141
scripts/mel Executable file
View file

@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""
Meh mail client
"""
import notmuch
import logging
import coloredlogs
import colorama
import datetime
import os
import progressbar
import time
colorama.init()
coloredlogs.install(level='DEBUG', fmt='%(levelname)s %(message)s')
log = logging.getLogger()
log.debug("Loading database")
db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE)
# TODO Open read-only when needed
log.debug("Database loaded")
def get_location(msg):
path = msg.get_filename()
path = os.path.dirname(path)
base = db.get_path()
assert path.startswith(base)
path = path[len(base):]
_, mailbox, folder, state = path.split('/')
assert state in {'cur', 'tmp', 'new'}
return (mailbox, folder, state)
MAILBOX_COLORS = dict()
def get_mailbox_color(mailbox):
if mailbox not in MAILBOX_COLORS:
colorfile = os.path.join(db.get_path(), mailbox, 'color')
assert os.path.isfile(colorfile)
with open(colorfile, 'r') as f:
colorStr = f.read()
colorStr = colorStr[1:] if colorStr[0] == '#' else colorStr
R = int(colorStr[0:2], 16)
G = int(colorStr[2:4], 16)
B = int(colorStr[4:6], 16)
MAILBOX_COLORS[mailbox] = '\x1b[38;2;{};{};{}m'.format(R, G, B)
return MAILBOX_COLORS[mailbox]
def format_date(date):
now = datetime.datetime.now()
midnight = datetime.datetime(year=now.year, month=now.month, day=now.day)
if date > midnight:
return date.strftime('%H:%M:%S')
else:
return date.strftime('%d/%m/%y')
def print_msg(msg):
line = ""
tags = set(msg.get_tags())
mailbox, folder, state = get_location(msg)
line += get_mailbox_color(mailbox)
# Date
date = datetime.datetime.fromtimestamp(msg.get_date())
line += format_date(date)
# Icons
line += " "
def tags2col1(tag1, tag2, both, first, second, none):
nonlocal line
if tag1 in tags:
if tag2 in tags:
line += both
else:
line += first
else:
if tag2 in tags:
line += second
else:
line += none
tags2col1('spam', 'draft', '??', '💥', '📝', ' ')
tags2col1('attachment', 'encrypted', '🔐', '📎', '🔑', ' ')
tags2col1('unread', 'flagged', '🏁', '🏳 ', '🏴', ' ')
tags2col1('sent', 'replied', '?', '↑', '↪', ' ')
# TODO To: / From:
# Subject
line += " "
line += msg.get_header("subject")
line += colorama.Style.RESET_ALL
print(line)
def retag_msg(msg):
msg.freeze()
mailbox, folder, state = get_location(msg)
# Search-friendly folder name
if folder.startswith('INBOX.'):
folder = folder[6:]
folder = folder.upper()
msg.remove_all_tags()
if folder.startswith('JUNK') or folder.startswith('SPAM'):
msg.add_tag('spam')
if folder.startswith('DRAFT'):
msg.add_tag('draft')
if folder.startswith('INBOX'):
msg.add_tag('inbox')
# TODO 'sent' tag
# Save
msg.thaw()
msg.tags_to_maildir_flags()
def applyMsgs(queryStr, function, useProgressbar=False):
query = notmuch.Query(db, queryStr)
query.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
msgs = query.search_messages()
if useProgressbar:
nbMsgs = query.count_messages()
iterator = progressbar.progressbar(msgs, max_value=nbMsgs)
else:
iterator = msgs
for msg in iterator:
function(msg)
applyMsgs('tag:inbox', print_msg)
# applyMsgs('tag:spam', print_msg)
# applyMsgs('tag:unread', print_msg)
# applyMsgs('from:geoffrey@frogeye.fr', print_msg)
# applyMsgs('*', retag_msg, useProgressbar=True)

176
scripts/melConf Executable file
View file

@ -0,0 +1,176 @@
#!/usr/bin/env python3
"""
Meh mail client conf generator for other things
"""
import configparser
import os
import sys
# TODO Find config file from XDG
# TODO Alias adresses
# TODO Signature file
# TODO Write ~/.mail/[mailbox]/color file if required by sth?
# Certificate file
configPath = os.path.join(os.path.expanduser('~'), '.config', 'mel.conf')
config = configparser.ConfigParser()
config.read(configPath)
SERVER_DEFAULTS = {
"imap": {"port": 143, "starttls": True},
"smtp": {"port": 587, "starttls": True},
}
SERVER_ITEMS = {"host", "port", "user", "pass", "starttls"}
# Reading sections
accounts = dict()
for name in config.sections():
if not name.islower():
continue
section = config[name]
data = dict()
for server in SERVER_DEFAULTS.keys():
for item in SERVER_ITEMS:
key = server + item
try:
val = section.get(key) or section.get(item) or SERVER_DEFAULTS[server][item]
except KeyError:
raise KeyError("{}.{}".format(name, key))
if isinstance(val, str):
if val == "True":
val = True
elif val == "False":
val = False
elif val.isnumeric():
val = int(val)
data[key] = val
for key in section.keys():
if key in SERVER_ITEMS:
continue
data[key] = section[key]
data["name"] = name
data["storage"] = os.path.join(config['GLOBAL']['storage'], name)
data["storageInbox"] = os.path.join(data["storage"], "INBOX")
storageFull = os.path.expanduser(data["storage"])
os.makedirs(storageFull, exist_ok=True)
accounts[name] = data
# OfflineIMAP
OFFLINEIMAP_BEGIN = """[general]
# List of accounts to be synced, separated by a comma.
accounts = {}
maxsyncaccounts = {}
stocktimeout = 60
pythonfile = ~/.config/offlineimap.py
[mbnames]
enabled = yes
filename = ~/.mutt/mailboxes
header = "mailboxes "
peritem = "+%(accountname)s/%(foldername)s"
sep = " "
footer = "\\n"
"""
OFFLINEIMAP_ACCOUNT = """[Account {name}]
localrepository = {name}-local
remoterepository = {name}-remote
autorefresh = 0.5
quick = 10
utf8foldernames = yes
postsynchook = ~/.mutt/postsync
[Repository {name}-local]
type = Maildir
localfolders = {storage}
[Repository {name}-remote]
type = IMAP
{secconf}
keepalive = 60
holdconnectionopen = yes
remotehost = {imaphost}
remoteport = {imapport}
remoteuser = {imapuser}
remotepass = {imappass}
"""
offlineIMAPstr = OFFLINEIMAP_BEGIN.format(','.join(accounts), len(accounts))
for name, account in accounts.items():
if account["imapstarttls"]:
secconf = "ssl = no"
else:
secconf = "sslcacertfile = /etc/ssl/certs/ca-certificates.crt"
offlineIMAPstr += OFFLINEIMAP_ACCOUNT.format(**account, secconf=secconf)
# TODO Write
# mbsync
MBSYNC_ACCOUNT = """IMAPAccount {name}
Host {imaphost}
User {imapuser}
Pass "{imappass}"
{secconf}
IMAPStore {name}-remote
Account {name}
MaildirStore {name}-local
Subfolders Verbatim
Path {storage}/
Inbox {storageInbox}/
Channel {name}
Master :{name}-remote:
Slave :{name}-local:
Patterns *
Create Both
SyncState *
"""
mbsyncStr = ""
for name, account in accounts.items():
if account["imapstarttls"]:
secconf = "SSLType STARTTLS"
else:
secconf = "SSLType IMAPS"
mbsyncStr += MBSYNC_ACCOUNT.format(**account, secconf=secconf)
msbsyncFilepath = os.path.join(os.path.expanduser('~'), '.mbsyncrc')
with open(msbsyncFilepath, 'w') as f:
f.write(mbsyncStr)
# msmtp
MSMTP_BEGIN = """defaults
protocol smtp
auth on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
"""
MSMTP_ACCOUNT = """account {name}
from {from}
user {smtpuser}
password {smtppass}
host {smtphost}
port {smtpport}
tls on
"""
msmtpStr = MSMTP_BEGIN
for name, account in accounts.items():
msmtpStr += MSMTP_ACCOUNT.format(**account)
msbsyncFilepath = os.path.join(os.path.expanduser('~'), '.msmtprc')
with open(msbsyncFilepath, 'w') as f:
f.write(msmtpStr)

View file

@ -146,20 +146,26 @@ do
done <<< "$(find "$dir" -type f -iname "*.png")" done <<< "$(find "$dir" -type f -iname "*.png")"
# SVG (requires svgo) # # SVG (requires scour)
while read image # while read image
do # do
if [ -z "$image" ]; then continue; fi # if [ -z "$image" ]; then continue; fi
echo Processing $image # echo Processing $image
#
# temp=$(mktemp --suffix .svg)
# scour --quiet "$image" "$temp" --no-line-breaks
# echo "→ Optimize done"
#
# replaceImg "$temp" "$image"
#
# done <<< "$(find "$dir" -type f -iname "*.svg")"
temp=$(mktemp --suffix .svg) # NOTE Explicitely disabled since:
cp "$image" "$temp" # - I only have ~50 MiB of SVG in TOTAL
svgo --quiet --config $HOME/.config/optiSvgo.yml "$temp" # - Most conversions are not image losseless
echo "→ Optimize done" # - Even when they are losseless, they are mostly worthless
# - I might want to keep editor data and/or ids for some of them
replaceImg "$temp" "$image" # So rather use scour explicitely when needed
done <<< "$(find "$dir" -type f -iname "*.svg")"
cleandev cleandev

2
vimrc
View file

@ -52,7 +52,7 @@ else
endif endif
Plug 'zchee/deoplete-jedi' Plug 'zchee/deoplete-jedi'
Plug 'python-mode/python-mode', { 'branch': 'develop' } " Plug 'python-mode/python-mode', { 'branch': 'develop' }
Plug 'junegunn/fzf', {'do': './install --bin'} Plug 'junegunn/fzf', {'do': './install --bin'}
Plug 'junegunn/fzf.vim' Plug 'junegunn/fzf.vim'
Plug 'ervandew/supertab' Plug 'ervandew/supertab'