jaromail

a commandline tool to easily and privately handle your e-mail
git clone git://parazyd.org/jaromail.git
Log | Files | Refs | Submodules | README

commit c51e6d280ed3ed6d2661845bf493e40aefb9ca4a
parent fff5fc4be3da3d8037e20ce594ec774349594036
Author: Jaromil <jaromil@dyne.org>
Date:   Tue, 17 Jan 2017 19:02:14 +0100

included zuper as a submodule

Diffstat:
A.gitmodules | 3+++
Mbuild/install-gnu.sh | 1+
Msrc/jaro | 2++
Dsrc/zlibs/zuper | 629-------------------------------------------------------------------------------
Dsrc/zlibs/zuper.init | 16----------------
Asrc/zuper | 1+
6 files changed, 7 insertions(+), 645 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/zuper"] + path = src/zuper + url = https://github.com/dyne/zuper diff --git a/build/install-gnu.sh b/build/install-gnu.sh @@ -34,6 +34,7 @@ mkdir -p $JARO_LIBEXEC/{bin,zlibs} cp $srcdir/src/jaro $JARO_LIBEXEC/bin cp -ra $srcdir/build/gnu/* $JARO_LIBEXEC/bin cp -r $srcdir/src/zlibs/* $JARO_LIBEXEC/zlibs/ +cp -r $srcdir/src/zuper/{zuper,zuper.init} $JARO_LIBEXEC/zlibs for l in `ls $JARO_LIBEXEC/zlibs/ | grep '.zwc$'`; do rm -f $l diff --git a/src/jaro b/src/jaro @@ -194,11 +194,13 @@ if [ -d $WORKDIR/zlibs ]; then # if testing from source load uncompiled libs if [ "$WORKDIR" = "../src" ]; then for z in `find $WORKDIR/zlibs -type f`; do + [[ "$z" =~ "zuper" ]] && continue func "Loading zlib: ${z}" source ${z} done else for z in `find $WORKDIR/zlibs -type f | grep -v '.zwc$'`; do + [[ "$z" =~ "zuper" ]] && continue func "Loading zlib: ${z}" source ${z} done diff --git a/src/zlibs/zuper b/src/zlibs/zuper @@ -1,629 +0,0 @@ -#!/usr/bin/env zsh -# -# Zuper - Zsh Ultimate Programmer's Extensions Refurbished -# -# Copyright (C) 2015 Dyne.org Foundation -# -# Zuper is designed, written and maintained by Denis Roio <jaromil@dyne.org> -# -# This source code is free software; you can redistribute it and/or -# modify it under the terms of the GNU Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This source code is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# Please refer to the GNU Public License for more details. -# -# You should have received a copy of the GNU Public License along with -# this source code; if not, write to: -# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - -########################## -typeset -aU vars -typeset -aU arrs -typeset -aU maps - -vars=(DEBUG QUIET LOG) -arrs=(req freq) - -vars+=(zuper_version) -zuper_version=0.2 - -# Messaging function with pretty coloring -autoload colors -colors - -vars+=(last_act last_func last_notice) - -function _msg() { - local msg="$2" - command -v gettext 1>/dev/null 2>/dev/null && msg="$(gettext -s "$2")" - for i in $(seq 3 ${#}); - do - msg=${(S)msg//::$(($i - 2))*::/$*[$i]} - done - - local command="print -P" - local progname="$fg[magenta]${TOMBEXEC##*/}$reset_color" - local message="$fg_bold[normal]$fg_no_bold[normal]$msg$reset_color" - local -i returncode - - case "$1" in - inline) - command+=" -n"; pchars=" > "; pcolor="yellow" - ;; - message) - last_act="$msg" - pchars=" . "; pcolor="white"; message="$fg_no_bold[$pcolor]$msg$reset_color" - ;; - verbose) - last_func="$msg" - pchars="[D]"; pcolor="blue" - ;; - success) - last_notice="$msg" - pchars="(*)"; pcolor="green"; message="$fg_no_bold[$pcolor]$msg$reset_color" - ;; - warning) - pchars="[W]"; pcolor="yellow"; message="$fg_no_bold[$pcolor]$msg$reset_color" - ;; - failure) - pchars="[E]"; pcolor="red"; message="$fg_no_bold[$pcolor]$msg$reset_color" - returncode=1 - ;; - print) - progname="" - ;; - *) - pchars="[F]"; pcolor="red" - message="Developer oops! Usage: _msg MESSAGE_TYPE \"MESSAGE_CONTENT\"" - returncode=127 - zerr - ;; - esac - ${=command} "${progname} $fg_bold[$pcolor]$pchars$reset_color ${message}$color[reset_color]" >&2 - - # write the log if its configured - [[ "$LOG" = "" ]] || { - touch $LOG || return $? - ${=command} "${progname} $fg_bold[$pcolor]$pchars$reset_color ${message}$color[reset_color]" >> $LOG - } - - return $returncode -} - -function _message say act() { - local notice="message" - [[ "$1" = "-n" ]] && shift && notice="inline" - [[ $QUIET = 1 ]] || _msg "$notice" $@ - return 0 -} - -function _verbose xxx func() { - [[ $DEBUG = 1 ]] && _msg verbose $@ - return 0 -} - -function _success yes notice() { - [[ $QUIET = 1 ]] || _msg success $@ - return 0 -} - -function _warning no warn warning() { - [[ $QUIET = 1 ]] || _msg warning $@ - return 0 -} - -function _failure fatal die error() { - # typeset -i exitcode=${exitv:-1} - [[ $QUIET = 1 ]] || _msg failure $@ - return 1 -} - -function _print() { - [[ $QUIET = 1 ]] || _msg print $@ - return 0 -} - - -fn() { - fun="$@" - req=() - freq=() - func "$fun" -} - -zerr() { - error "error in: ${fun:-$last_notice}" - [[ "$last_func" = "" ]] || warn "called in: $last_func" - [[ "$last_act" = "" ]] || warn "called in: $last_act" - [[ "$last_notice" = "" ]] || warn "called in: $last_notice" - # [[ "$fun" = "" ]] || warn "called in: $fun" - TRAPEXIT() { - error "error reported, operation aborted." - } - return 1 -} - - -ckreq reqck() { - err=0 - for v in $req; do - [[ "${(P)v}" = "" ]] && { - warn "required setting is blank: $v" - err=1 - } - done - - [[ $err = 1 ]] && return $err - - for f in $freq; do - # exists and has size greater than zero - [[ -s $f ]] || { - warn "required file empty: $f" - err=1 - } - done - [[ $err == 1 ]] && zerr - return $err -} - -zdump() { - fn zdump - [[ ${#vars} -gt 0 ]] && { - print "Global variables:" - for _v in $vars; do - print " $_v = \t ${(P)_v}" - done - } - [[ ${#arrs} -gt 0 ]] && { - print "Global arrays:" - for _a in $arrs; do - print " $_a \t ( ${(P)_a} )" - done - } - [[ ${#maps} -gt 0 ]] && { - print "Global maps:" - for _m in $maps; do - print " $_m [key] \t ( ${(Pk)_m} )" - print " $_m [val] \t ( ${(Pv)_m} )" - done - } -} - -# handy wrappers for throw/catch execution of blocks where we need the -# program to exit on any error (non-zero) returned by any function -throw() { function TRAPZERR() { zerr; return 1 } } -catch() { function TRAPZERR() { } } - -########################## -# Endgame handling - -arrs+=(destruens) -destruens=() - -# Trap functions for the endgame event -TRAPINT() { endgame INT; return $? } -# TRAPEXIT() { endgame EXIT; return $? } -TRAPHUP() { endgame HUP; return $? } -TRAPQUIT() { endgame QUIT; return $? } -TRAPABRT() { endgame ABORT; return $? } -TRAPKILL() { endgame KILL; return $? } -# TRAPPIPE() { endgame PIPE; return $? } -TRAPTERM() { endgame TERM; return $? } -TRAPSTOP() { endgame STOP; return $? } -# TRAPZERR() { func "function returns non-zero." } - - -endgame() { - fn "endgame $*" - - # execute all no matter what - TRAPZERR() { } - - # process registered destructors - for d in $destruens; do - fn "destructor: $d" - $d - done - return 0 -} - -# Register endgame() to be called at exit. -# unlike TRAPEXIT, the zshexit() hook is not called when functions exit. -zshexit() { endgame EXIT; return $? } - -########################## -# Temp file handling - -vars+=(ztmpfile) -# ztmp() fills in $ztmpfile global. Caller must copy that variable as -# it will be overwritten at every call. -ztmp() { - fn ztmp - - ztmpfile=`mktemp` - tmpfiles+=($ztmpfile) -} - -# All tempfiles are freed in endgame() -_ztmp_destructor() { - fn _ztmp_destructor - - for f in $tmpfiles; do - func "removed $f" - rm -f "$f" - done - tmpfiles=() -} - -arrs+=(tmpfiles) -destruens+=(_ztmp_destructor) - -# tokenizer, works only with one char length delimiters -# saves everything in global array tok=() -arrs+=(tok) -strtok() { - fn "strtok $*" - _string="$1" - _delim="$2" - req=(_string _delim) - ckreq || return $? - - tok=() - f=0 - for c in {1..${#_string}}; do - if [[ "${_string[(e)$c]}" == "$_delim" ]]; then - # check if not empty - t=${_string[(e)$(($f + 1)),$(($c - 1))]} - [[ "$t" == "" ]] || tok+=($t) - # save last found - f=$c - fi - done - # add last token - t=${_string[(e)$(($f + 1)),$c]} - [[ "$t" == "" ]] || tok+=($t) -} - -# optional: define zkv=1 on source - -[[ "$zkv" = "" ]] || { - - ########################## - # Key/Value file storage using ZSh associative maps - - zmodload zsh/system - - # load a map from a file - # map must be already instantiated with typeset -A by called - # name of map is defined inside the file - function zkv.load() { - fn "zkv-load $*" - - file=$1 - [[ "$file" = "" ]] && { - error "zkv-open() missing argument: file-path" - zerr - return 1 } - [[ -r "$file" ]] || { - error "zkv-open() file not found $file" - zerr - return 1 } - [[ -s "$file" ]] || { - error "zkv-open() file is empty" - zerr - return 1 } - - source $file - } - - # save a map in a file - # $1 = name of the map associative array - # $2 = full path to the file - function zkv.save() { - fn "zkv.save $*" - - _map=$1 - _path=$2 - [[ "$_path" = "" ]] && { - error "zkv.save() missing argument: map-name path-to-file" - zerr - return 1 - } - [[ -r $_path ]] && { - func "zkv.close() overwriting $_path" - func "backup turd left behind: ${_path}~" - mv $_path $_path~ - } - touch $_path - - # wondering about http://www.zsh.org/mla/users/2015/msg00286.html - # meanwhile solved using a double array, wasting a full map memcpy - _karr=(${(Pk)_map}) - _varr=(${(Pv)_map}) - _num="${#_karr}" - for c in {1..$_num}; do - # can also be cat here, however for speed we use builtins - # switch to cat if compatibility is an issue - sysread -o 1 <<EOF >> $_path -$_map+=("${_karr[$c]}" "${(v)_varr[$c]}") -EOF - done - func "$_num key/values stored in $_path" - } - -} - -# optional: define restful=1 on source - -[[ "$restful" = "" ]] || { - - ######## - # Restful API client - # there is a clear zsh optimization here in get/set kv - # using zsh/tcp instead of spawning curl - # and perhaps querying with one call using ?recursive - - zmodload zsh/net/tcp - - function restful.put() { - # $1 = hostname - # $2 = port - # $3 = path - # $4 = key - # $5 = value - - fn "restful.put $*" - - # to check if the http service is running is up to the caller - - _host=${1} # ip address - _port=${2} - _path=${3} - _k="$4" # key name - _v="$5" # value - - req=(_host _k _v) - ckreq || return $? - - if ztcp $_host $_port; then - - - # TODO: work out various parsers, this one works with consul.io - - _fd=$REPLY - # func "tcp open on fd $fd" - cat <<EOF >& $_fd -PUT ${_path}${_k} HTTP/1.1 -User-Agent: Zuper/$zuper_version -Host: ${_host}:${_port} -Accept: */* -Content-Length: ${#_v} -Content-Type: application/x-www-form-urlencoded - -EOF - - print -n "$_v" >& $_fd - - sysread -i $_fd _res - - # close connection - ztcp -c $_fd - - [[ "$_res" =~ "true" ]] || { - warn "failed PUT on restful key/value" - warn "endpoint: ${_host}:${_port}${_path}" - warn "resource: $_k = $_v" - print - "$_res" - zerr - return 1 - } - - else - error "cannot connect to restful service: $_host:$_port" - zerr - return 1 - fi - - return 0 - - } - - restful.get() { - fn "restful.get $*" - - _host=${1} - _port=${2} - _path=${3} - _k=$4 # key name - - req=(_host _k) - ckreq || return $? - - _k=$1 - - ztcp $_host $_port || { - zerr - return 1 - } - - _fd=$REPLY - - # TODO: work out various parsers, this one works with consul.io - - cat <<EOF >& $_fd -GET ${_path}${_k} HTTP/1.1 -User-Agent: Zuper/$zuper_version -Host: $_host:$_port -Accept: */* - -EOF - sysread -i $_fd -o 1 | awk -F: ' -/"Value":/ { gsub(/"|}]/,"",$7) ; print $7 }' | base64 -d - - # close connection - ztcp -c $_fd - - return 0 - - } - -} - -# {{{ Helpers -[[ "$helpers" = "" ]] || { - - function helper.isfound isfound() { - command -v $1 1>/dev/null 2>/dev/null - return $? - } - - # remote leading and trailing spaces in a string taken from stdin - function helper.trim trim() { - sed -e 's/^[[:space:]]*//g ; s/[[:space:]]*\$//g' - } - - zmodload zsh/mapfile - # faster substitute for cat - function helper.printfile printfile() { - print ${mapfile[$1]} - } - - # extract all emails found in a text from stdin - # outputs them one per line - function helper.extract-emails extract_emails() { - awk '{ for (i=1;i<=NF;i++) - if ( $i ~ /[[:alnum:]]@[[:alnum:]]/ ) { - gsub(/<|>|,/ , "" , $i); print $i } }' - } - - - zmodload zsh/regex - # takes a string as argument, returns success if is an email - function helper.isemail isemail() { - [[ "$1" -regex-match "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" ]] && return 0 - - return 1 - } - - # takes a numeric argument and prints out a human readable size - function helper.human-size human_size() { - [[ $1 -gt 0 ]] || { - error "human_size() called with invalid argument" - return 1 - } - - # we use the binary operation for speed - # shift right 10 is divide by 1024 - - # gigabytes - [[ $1 -gt 1073741824 ]] && { - print -n "$(( $1 >> 30 )) GB" - return 0 - } - - # megabytes - [[ $1 -gt 1048576 ]] && { - print -n "$(( $1 >> 20 )) MB" - return 0 - } - # kilobytes - [[ $1 -gt 1024 ]] && { - print -n "$(( $1 >> 10 )) KB" - return 0 - } - # bytes - print -n "$1 Bytes" - return 0 - } - - - # strips out all html/xml tags (everything between < >) - function helper.html-strip xml_strip html_strip() { sed 's/<[^>]\+>//g' } - - # changes stdin string special chars to be shown in html - function helper.excape-html escape_html() { - sed -e ' -s/\&/\&amp;/g -s/>/\&gt;/g -s/</\&lt;/g -s/"/\&quot;/g -' - } - -} - -# }}} Helpers - -# {{{ Config - -# This is not a full config parser, but its a mechanism to read single -# sections of configuration files that are separated using various -# syntax methods. The only method supported is now org-mode whose -# sections start with #+ . It fills in the global array -# $config_section which can be read out to a file or interpreted in -# memory, whatever syntax it may contain. - -vars+=(config_section_type) -arrs+=(config_section) -config_section_type=org-mode - -config.section.type() { - fn config.section.type - _type=$1 - req=(_type) - ckreq || return $? - - case $_type in - org-mode) - config_section_type=org-mode - ;; - *) - error "Unknown config type:$_type" - return 1 - ;; - esac - - act "$_type config section parser initialized" - return 0 - -} - -# fills in contents of section in array config_section -config.section.read() { - fn config.section.read - _file=$1 - _section=$2 - req=(_file _section) - freq=($_file) - ckreq || return $? - - case $config_section_type in - org-mode) - _contents=`awk ' -BEGIN { found=0 } -/^#\+ '"$_section"'/ { found=1; next } -/^#\+/ { if(found==1) exit 0 } -/^$/ { next } -{ if(found==1) print $0 } -' $_file` - - ;; - *) - error "Unknown config type:$_type" - ;; - esac - - config_section=() - for c in ${(f)_contents}; do - config_section+=("$c") - done - return 0 - -} - -# }}} diff --git a/src/zlibs/zuper.init b/src/zlibs/zuper.init @@ -1,16 +0,0 @@ -########################## -# Zuper Init - -# initialize globals only after sourcing everything -# since zlibs may contain more variable declarations -for v in $vars; do - typeset -h $v -done -for a in $arrs; do - typeset -a $a -done -func "Zuper $zuper_version initialized" -func "${#vars} global variables registered" -func "${#arrs} global arrays registered" - - diff --git a/src/zuper b/src/zuper @@ -0,0 +1 @@ +Subproject commit a0dc5b43502d41bf94fb781bcd7815ed4a37d8ae