From 5fc412e4448a45476a51bad16c84086a550136f1 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Tue, 21 Jun 2016 09:11:20 +0200 Subject: [PATCH 01/18] Move all function definitions to inc/ --- Makefile | 28 +- inc/vimcat_functions.sh | 100 +++++ inc/vimpager_functions.sh | 824 ++++++++++++++++++++++++++++++++++++++ vimcat | 97 +---- vimpager | 822 +------------------------------------ 5 files changed, 949 insertions(+), 922 deletions(-) create mode 100644 inc/vimcat_functions.sh create mode 100644 inc/vimpager_functions.sh diff --git a/Makefile b/Makefile index 10e2278..e2a6548 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ all: ${PROGRAMS:=-vertag-stamp} standalone/vimpager standalone/vimcat docs @git describe >$<-version.txt 2>/dev/null \ || sed -n '/^[0-9][0-9.]* [0-9-]*:$$/{s/ .*//;p;q;}' ChangeLog_$<.yml >$<-version.txt -standalone/vimpager: vimpager vimpager-version.txt ${SRC:=.uu} inc/* Makefile +standalone/vimpager: vimpager vimpager-version.txt ${SRC:=.uu} inc/bundled_scripts.sh inc/do_uudecode.sh inc/prologue.sh inc/vimpager_functions.sh Makefile @echo building $@ @${MKPATH} ${@D} @sed \ @@ -50,6 +50,10 @@ standalone/vimpager: vimpager vimpager-version.txt ${SRC:=.uu} inc/* Makefile -e 'r inc/prologue.sh' \ -e d \ -e '}' \ + -e '/^ *\. .*inc\/vimpager_functions.sh"$$/{' \ + -e 'r inc/vimpager_functions.sh' \ + -e d \ + -e '}' \ -e 's/^\( *\)# EXTRACT BUNDLED SCRIPTS HERE$$/\1extract_bundled_scripts/' \ -e 's|^version=.*|version="'"`cat vimpager-version.txt`"' (standalone, shell=\$$(command -v \$$POSIX_SHELL))"|' \ -e 's!^\( *\)runtime=.*$$!\1runtime='\''\$$tmp/runtime'\''!' \ @@ -63,7 +67,7 @@ standalone/vimpager: vimpager vimpager-version.txt ${SRC:=.uu} inc/* Makefile @sed -n '/^# END OF BUNDLED SCRIPTS$$/,$$p' vimpager >> $@ @chmod +x $@ -standalone/vimcat: vimcat autoload/vimcat.vim vimcat-version.txt inc/prologue.sh Makefile +standalone/vimcat: vimcat autoload/vimcat.vim inc/prologue.sh inc/vimcat_functions.sh Makefile vimcat-version.txt @echo building $@ @${MKPATH} ${@D} @nlinit=`echo 'nl="'; echo '"'`; eval "$$nlinit"; \ @@ -79,6 +83,10 @@ standalone/vimcat: vimcat autoload/vimcat.vim vimcat-version.txt inc/prologue.sh -e 'r inc/prologue.sh' \ -e d \ -e '}' \ + -e '/^ *\. .*inc\/vimcat_functions.sh"$$/{' \ + -e 'r inc/vimcat_functions.sh' \ + -e d \ + -e '}' \ vimcat > $@ @cp $@ $@.work @awk '/^[ ]*(if|for|while)/ { print $$1 }' $@ \ @@ -89,7 +97,7 @@ standalone/vimcat: vimcat autoload/vimcat.vim vimcat-version.txt inc/prologue.sh @sed -e 's/vimcat#\([^ ]*\)(/\1(/g' autoload/vimcat.vim >> $@ @chmod +x $@ -vimcat.uu: vimcat vimcat-version.txt +vimcat.uu: vimcat inc/prologue.sh inc/vimcat_functions.sh Makefile vimcat-version.txt @echo uuencoding vimcat @echo 'vimcat_script() {' > $@ @printf "\t(cat <<'EOF') | do_uudecode > bin/vimcat\n" >> $@ @@ -99,6 +107,10 @@ vimcat.uu: vimcat vimcat-version.txt -e 'r inc/prologue.sh' \ -e d \ -e '}' \ + -e '/^ *\. .*inc\/vimcat_functions.sh"$$/{' \ + -e 'r inc/vimcat_functions.sh' \ + -e d \ + -e '}' \ vimcat > $@.work @uuencode $@.work vimcat >> $@ @echo EOF >> $@ @@ -173,9 +185,11 @@ install: docs vimpager.configured vimcat.configured echo ${INSTALLCONF} vimpagerrc "$${SYSCONFDIR}/vimpagerrc"; \ ${INSTALLCONF} vimpagerrc "$${SYSCONFDIR}/vimpagerrc" -%.configured: % %-version.txt +%.configured: % %-version.txt inc/%_functions.sh @echo configuring $< @POSIX_SHELL="`scripts/find_shell`"; \ + BASE='${@F}'; \ + BASE=$${BASE%.configured}; \ if [ '${PREFIX}' = /usr ]; then \ vimpagerrc=/etc/vimpagerrc; \ else \ @@ -184,11 +198,15 @@ install: docs vimpager.configured vimcat.configured sed -e '1{ s|.*|#!'"$$POSIX_SHELL"'|; }' \ -e 's|\$$POSIX_SHELL|'"$$POSIX_SHELL|" \ -e '/^ *\. .*inc\/prologue.sh"$$/d' \ - -e 's|^version=.*|version="'"`cat $<-version.txt`"' (configured, shell='"$$POSIX_SHELL"')"|' \ + -e 's|^version=.*|version="'"`cat $$BASE-version.txt`"' (configured, shell='"$$POSIX_SHELL"')"|' \ -e '/^# FIND REAL PARENT DIRECTORY$$/,/^# END OF FIND REAL PARENT DIRECTORY$$/d' \ -e 's!^\( *\)runtime=.*!\1runtime='\''${PREFIX}/share/vimpager'\''!' \ -e 's!^\( *\)vimcat=.*!\1vimcat='\''${PREFIX}/bin/vimcat'\''!' \ -e 's!^\( *\)system_vimpagerrc=.*!\1system_vimpagerrc='\'"$$vimpagerrc"\''!' \ + -e '/^\. .*inc\/'"$$BASE"'_functions.sh"$$/{' \ + -e "r inc/$${BASE}_functions.sh" \ + -e d \ + -e '}' \ $< > $@ @chmod +x $@ diff --git a/inc/vimcat_functions.sh b/inc/vimcat_functions.sh new file mode 100644 index 0000000..2f74cb5 --- /dev/null +++ b/inc/vimcat_functions.sh @@ -0,0 +1,100 @@ +# Function definitions for vimcat. + +quit() { + ( + kill "$vim_pid" >/dev/null 2>&1 + do_sleep 100 + kill -9 "$vim_pid" >/dev/null 2>&1 + + kill "$pipeline_pid" >/dev/null 2>&1 + do_sleep 100 + kill -9 "$pipeline_pid" >/dev/null 2>&1 + + kill "$tail_pid" >/dev/null 2>&1 + do_sleep 100 + kill -9 "$tail_pid" >/dev/null 2>&1 + + cd "${tmp_dir%/*}" 2>/dev/null # some systems cannot remove CWD + + rm -rf "$tmp_dir" 2>/dev/null # rm -rf "" shows error on OpenBSD + ) & + exit "$@" +} + +do_sleep() { + _ms=${1:-100} + "$vim" -NEsnR -i NONE -u NONE +"sleep $_ms m" +q >/dev/null 2>&1 +} + +usage() { + cat <<'EOF' +Usage: vimcat [OPTION]... [FILE | -]... +Display FILE(s) in the terminal with (n)vim syntax highlighting using ANSI escape codes. + +With no FILE, or when FILE is -, read standard input. + + -h, --help, --usage This help screen. + -v, --version Show version information and exit. + -n Print with line numbers. + -s Squeeze multiple blank lines into one. + -o FILE | - Output ANSI highlighted text to FILE or standard output. + --cmd COMMAND Run (n)vim COMMAND before initialization. + -c COMMAND Run (n)vim COMMAND after initialization. + -u FILE Use FILE as the vimrc. + -x  Give debugging output on stderr. + +Examples: + vimcat program.py # output program.py with highlighting to terminal + +Project homepage: <http://github.com/rkitover/vimpager> +and documentation: <https://github.com/rkitover/vimpager/blob/master/markdown/vimcat.md> +or available locally via: man vimcat +EOF +} + +write_chunks() { + cd "$chunks_dir" + rm -f -- * + split -b 4096 - + touch PIPELINE_DONE +} + +start_pipeline() { + if [ -n "$pipeline" ]; then + pipeline="$pipeline | write_chunks" + else + pipeline=write_chunks + fi + cat -- "$pipeline_start" | (eval "$pipeline" <&3 & echo $! > "$tmp_dir/pipeline_pid") 3<&0 + pipeline_pid=$(cat "$tmp_dir/pipeline_pid") +} + +start_highlight_job() { + # INSERT VIMCAT_DEBUG PREPARATION HERE + set -- -NE -i NONE -n \ + --cmd "set runtimepath^=$runtime" \ + --cmd "call vimcat#Init({ 'rc': '$vimcatrc' })" \ + --cmd visual \ + ${extra_cmd:+--cmd "$extra_cmd"} \ + ${extra_c:+-c "$extra_c"} \ + -c "call vimcat#Run(\"$dest_file\", ${line_numbers:-0}, \"$chunks_dir\", \"$pipeline_start\")" + + [ -n "$vimcatrc" ] && set -- "$@" -u "$vimcatrc" + + if [ "${VIMCAT_DEBUG:-0}" -eq 0 ]; then + ("$vim" "$@" /dev/null 2>&1; touch "$tmp_dir/vim_done") & + vim_pid=$! + else + "$vim" "$@" &2 + quit 1 + ;; + *) + break + ;; + esac + done + + find_tmp_directory + + trap "quit 1" PIPE HUP INT QUIT ILL TRAP KILL BUS TERM + + detect_term_size + + expand_config_vars + + find_vim_executable + + find_vimpagerrc_files + + read_vim_settings + + parse_pstree + + # if no args, assume stdin + if [ $# -eq 0 ]; then + set -- - + # turn off man/perldoc support for > 1 arg + elif [ $# -gt 1 ]; then + is_man= + is_perldoc= + is_doc= + force_strip_ansi= + fi + + file_idx=1 + + for file in "$@"; do + if [ "$file" = - ]; then + filename=stdin + else + if [ ! -r "$file" ]; then + echo "$0: cannot read file '$file'" >&2 + quit 1 + fi + + filename=$(resolve_path "$file") + fi + + set_key orig_file_names $file_idx "$filename" + + # $file still holds the orginal file name. $filename will be + # the encoded version of $file. $tempfile is the path under + # $tmp if the file is to be opend from there instead of the + # original location. If $tempfile is empty the file is to be + # opened as $file. + filename=$(encode_filename "$filename") + tempfile= + + case "$(echo "$file" | tr 'A-Z' 'a-z')" in + *.gz) + filename=${filename%.??} + tempfile=$tmp/$filename + gunzip -c -- "$file" > "$tempfile" + + ;; + *.bz2) + filename=${filename%.??2} + tempfile=$tmp/$filename + bunzip2 -c -- "$file" > "$tempfile" + ;; + *.xz) + filename=${filename%.??} + tempfile=$tmp/$filename + xzcat -c -- "$file" > "$tempfile" + ;; + *.z) + filename=${filename%.?} + tempfile=$tmp/$filename + uncompress -c -- "$file" > "$tempfile" + ;; + *) + if [ "$file" = - ]; then + tempfile=$tmp/$filename + cat -- "$file" > "$tempfile" + fi + ;; + esac + + # check for ANSI codes and strip if not using ansiesc + if head -100 "${tempfile:-$file}" | grep -Eq "$ANSI_RE"; then + if [ -z "$ansiesc_available" -o -n "$force_strip_ansi" ]; then + ansi_filter "${tempfile:-$file}" > "$tmp/$filename.work" + tempfile=$tmp/$filename + mv -f -- "$tempfile.work" "$tempfile" + else + echo 'call vimpager_utils#DoAnsiEsc()' >> "$tmp/$file_idx.vim" + set_key ansi_files "$file_idx" yes + fi + fi + + # squeeze blank lines if option was specified, Ubuntu man with /usr/bin/pager does this + if [ "${squeeze_blank_lines:-0}" -eq 1 ]; then + sed -e '/^[ ]*$/{ + N + /^[ ]*\n[ ]*$/D + }' < "${tempfile:-$file}" > "$tmp/$filename.work" + tempfile=$tmp/$filename + mv -f -- "$tempfile.work" "$tempfile" + fi + + # dumb man detection when the pstree heuristic fails + if [ -z "$is_doc" ] && head -12 "${tempfile:-$file}" | grep -Eq '^N(.)?A(.)?M(.)?E(.)?[ \t]*$'; then + is_man=1 + is_doc=1 + fi + + # if it's a man page, remove starting blank lines, or the C syntax highlighting fails + # and write out ft command for vim + if [ -n "$is_doc" ]; then + ansi_filter "${tempfile:-$file}" | overstrike_filter | awk ' + BEGIN { skipblank=1 } + /^[ ]*$/ { if (!skipblank) print } + /[^ ]/ { skipblank=0; print } + ' > "$tmp/$filename.work" + tempfile=$tmp/$filename + mv -f -- "$tempfile.work" "$tempfile" + + if [ -n "$is_man" ]; then + echo 'set ft=man' >> "$tmp/$file_idx.vim" + elif [ -n "$is_perldoc" ]; then + echo 'set ft=perldoc' >> "$tmp/$file_idx.vim" + fi + fi + + # if file is zero length, or one blank line (cygwin), and is only arg, exit + if [ ! -s "${tempfile:-$file}" \ + -a $# -eq 1 \ + -o "$(cat "${tempfile:-$file}")" = "" \ + -a "$(wc -l < "${tempfile:-$file}")" -eq 1 ]; then + + quit 0 + fi + + set_key files $file_idx "$(resolve_path "${tempfile:-$file}")" + + file_idx=$((file_idx + 1)) + done + + file_count=$# + + set -- + i=1 + while [ $i -le $file_count ]; do + set -- "$@" "$(get_key files $i)" + i=$((i + 1)) + done + + if [ "${no_pass_thru:-0}" -ne 1 ] && fits_on_screen "$@"; then + cat_files=1 + fi + + page_files "$@" + + quit $? +} + +find_tmp_directory() { + # Find and create the temporary directory used by vimpager. Set the $tmp variable. + mkdir_options="-m 700" + + if [ -n "$win32" ]; then + # Use the real TEMP directory on windows in case we are + # using a native vim/gvim + # TEMP can be /tmp sometimes too + + tmp=$(resolve_path "$TEMP") + + # chmod doesn't work here, even in /tmp sometimes + mkdir_options= + else + # ... and /tmp otherwise + tmp=/tmp + fi + + # Create a safe directory in which we place all other tempfiles. + tmp=$tmp/vimpager_$$ + if ! mkdir $mkdir_options "$tmp"; then + echo "ERROR: Could not create temporary directory $tmp" >&2 + quit 1 + fi +} + +detect_term_size() { + # Detect the terminal size and set the variables $cols and $lines. If necessary $no_pass_thru is set. + if command -v tput >/dev/null; then + # this is the only way it works on some versions of Cygwin + + # 2>/dev/null makes tput not work, so don't do that + # we are just going to hope that tput errors don't happen + tput cols > "$tmp/cols" + tput lines > "$tmp/lines" + + cols=$(cat "$tmp/cols") + lines=$(cat "$tmp/lines") + + rm -f -- "$tmp/cols" "$tmp/lines" + fi + + # msys has no tput, this doesn't work on Cygwin by the way + if [ -z "$cols" ] && command -v bash >/dev/null; then + cols=$(bash -i -c 'echo $COLUMNS') + lines=$(bash -i -c 'echo $LINES') + fi + + # If we are unable to detect lines/columns, maximize + # the window. + if [ -z "$cols" ]; then + cols=999 + lines=999 + no_pass_thru=1 # force loading vimpager + fi +} + +find_vimpagerrc_files() { + # This function will find the system and the user vimpagerrc file and set the variables $system_vimrc and $vimrc. + + # determine location of rc file + i=1 + OLDIFS=$IFS + IFS=' +' + for var in $(IFS=$OLDIFS; "$tvim" -NEnR -i NONE ${vimrc:+-u "$vimrc"} +'call writefile(["", "VAL:" . $VIM, "VAL:" . $MYVIMRC], "/dev/stderr")' +q &1 >/dev/null); do + case "$var" in + VAL:*) + case $i in + 1) + vim_dir=${var#VAL:} + ;; + 2) + user_vimrc=${var#VAL:} + user_vimrc_dir=${user_vimrc%/*} + break + ;; + esac + i=$((i + 1)) + ;; + esac + done + IFS=$OLDIFS + + # find system vimrc + system_vimrc=$("$tvim" --version | sed -n '/system vimrc file: "/{ + s|\$VIM|'"$vim_dir"'| + s/.*: "\([^"]*\).*/\1/p + q + }') + + # find the users vimpagerrc + if [ -n "$vimrc" ]; then + # The vimrc file was given on the command line. + : + elif [ -n "$VIMPAGER_RC" ]; then + vimrc=$VIMPAGER_RC + # check for vimpagerrc in same dir as vimrc in case it is set in VIMINIT + elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/.vimpagerrc" ]; then + vimrc=$user_vimrc_dir/.vimpagerrc + elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/_vimpagerrc" ]; then + vimrc=$user_vimrc_dir/_vimpagerrc + elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/vimpagerrc" ]; then + vimrc=$user_vimrc_dir/vimpagerrc + # check standard paths, according to :h initialization + elif [ -r ~/.vimpagerrc ]; then + vimrc=~/.vimpagerrc + elif [ -r ~/.vim/vimpagerrc ]; then + vimrc=~/.vim/vimpagerrc + elif [ -r ~/_vimpagerrc ]; then + vimrc=~/_vimpagerrc + elif [ -r ~/vimfiles/vimpagerrc ]; then + vimrc=~/vimfiles/vimpagerrc + elif [ -r "$vim_dir/_vimpagerrc" ]; then + vimrc=$vim_dir/_vimpagerrc + # try the user's ~/.vimrc + elif [ -n "$user_vimrc" ]; then + : + # if no user vimrc, then check for a global /etc/vimpagerrc + elif [ -n "$system_vimpagerrc" -a -f "$system_vimpagerrc" ]; then + : + # check a couple of common places for the standalone version + elif [ -f /usr/local/etc/vimpagerrc ]; then + vimrc=/usr/local/etc/vimpagerrc + elif [ -f /etc/vimpagerrc ]; then + vimrc=/etc/vimpagerrc + fi +} + +read_vim_settings() { + # Read settings from the vimpagerrc file and possibly set $use_gvim, $ansiesc_available, $disable_x11 and $no_pass_thru. + i=1 + OLDIFS=$IFS + IFS=' +' + for var in $(IFS=$OLDIFS; "$tvim" -NEnR ${vimrc:+-u "$vimrc"} -i NONE --cmd 'let g:vimpager = { "enabled": 1 }' +' + if !exists("g:vimpager.gvim") + if !exists("g:vimpager_use_gvim") + let g:vimpager.gvim = 0 + else + let g:vimpager.gvim = g:vimpager_use_gvim + endif + endif + + if !exists("g:vimpager.X11") + if !exists("g:vimpager_disable_x11") + let g:vimpager.X11 = 1 + else + let g:vimpager.X11 = !g:vimpager_disable_x11 + endif + endif + + if !exists("g:vimpager.passthrough") + if !exists("g:vimpager_passthrough") + let g:vimpager.passthrough = 1 + else + let g:vimpager.passthrough = g:vimpager_passthrough + endif + endif + + let g:use_ansiesc = 0 + + if has("conceal") && (!exists("g:vimpager.ansiesc") || g:vimpager.ansiesc == 1) && (!exists("g:vimpager_disable_ansiesc") || g:vimpager_disable_ansiesc == 0) + let g:use_ansiesc = 1 + endif + + call writefile([""] + map([g:vimpager.gvim, g:vimpager.X11, g:vimpager.passthrough, g:use_ansiesc], "\"VAL:\".v:val"), "/dev/stderr") + quit + ' &1 >/dev/null); do + case "$var" in + VAL:*) + case $i in + 1) + [ "${var#VAL:}" -eq 1 ] && use_gvim=1 + ;; + 2) + [ "${var#VAL:}" -eq 0 ] && disable_x11=1 + ;; + 3) + [ "${var#VAL:}" -eq 0 ] && no_pass_thru=1 + ;; + 4) + [ "${var#VAL:}" -ne 0 ] && ansiesc_available=1 + break + ;; + esac + i=$((i + 1)) + ;; + esac + done + IFS=$OLDIFS +} + +find_vim_executable() { + # Find the vim executable to use. Set $vim_cmd and $gui. + if [ -n "$win32" ]; then + # msys/cygwin may be using a native vim, and if we're not in a real + # console the native vim will not work, so we have to use gvim. + + if [ "x$TERM" != "xdumb" -a "x$TERM" != "xcygwin" -a "x$TERM" != "x" ]; then + if command -v vim >/dev/null | grep -Eq '^/(cygdrive/)?[a-z]/'; then + use_gvim=1 + fi + fi + fi + + tvim=vim + + if [ -n "$EDITOR" -a -z "$VIMPAGER_VIM" ]; then + case "${EDITOR##*/}" in + *vim*) + export VIMPAGER_VIM=$EDITOR + ;; + esac + fi + + if [ -n "$VIMPAGER_VIM" ]; then + case "${VIMPAGER_VIM##*/}" in + vim*) + tvim=$VIMPAGER_VIM + ;; + nvim*) + tvim=$VIMPAGER_VIM + ;; + gvim*|mvim*) + use_gvim=1 + gvim=$VIMPAGER_VIM + ;; + esac + fi + + if [ -n "$use_gvim" ]; then + # determine if this is an ssh session and/or $DISPLAY is set + if [ -n "$osx" ]; then + if [ -z "$SSH_CONNECTION" ] && command -v mvim >/dev/null; then + vim_cmd=${gvim:-mvim} + gui=1 + else + vim_cmd=$tvim + fi + elif [ -n "$cygwin" ]; then + if command -v gvim >/dev/null; then + if [ -n "$SSH_CONNECTION" ]; then + vim_cmd=$tvim + # The Cygwin gvim uses X + elif win32_native gvim; then + if [ -z "$DISPLAY" ]; then + vim_cmd=$tvim + else + vim_cmd=${gvim:-gvim} + gui=1 + fi + else + vim_cmd=${gvim:-gvim} + gui=1 + fi + else + vim_cmd=$tvim + fi + elif [ -n "$msys" ]; then + if [ -z "$SSH_CONNECTION" ] && command -v gvim >/dev/null; then + vim_cmd=${gvim:-gvim} + gui=1 + else + vim_cmd=$tvim + fi + elif [ -z "$DISPLAY" ]; then + vim_cmd=$tvim + else + if command -v gvim >/dev/null; then + vim_cmd=${gvim:-gvim} + gui=1 + else + vim_cmd=$tvim + fi + fi + else + vim_cmd=${vim_cmd:-${tvim:-vim}} + fi + + if [ ! -n "$gui" -a -n "$disable_x11" ]; then + vim_cmd="$vim_cmd -X" + fi +} + +parse_pstree() { + # Parse the process tree and set $is_man, $is_doc, $is_perldoc, $force_strip_ansi and $extra_cmd. + ptree=$(do_ptree) + + # Check if called from man, perldoc or pydoc + if echo "$ptree" | grep -Eq '([ \t]+|/)(man|[Pp]y(thon|doc)[0-9.]*|[Rr](uby|i)[0-9.]*)([ \t]|$)'; then + is_man=1 + is_doc=1 + force_strip_ansi=1 + elif echo "$ptree" | grep -Eq '([ \t]+|/)perl(doc)?([0-9.]*)?([ \t]|$)'; then + is_perldoc=1 + is_doc=1 + force_strip_ansi=1 + fi + + extra_cmd="${extra_cmd:+$extra_cmd | }let g:vimpager.ptree=[$(echo "$ptree" | awk '{ print "\"" $2 "\"" }' | tr '\n' ',')] | call remove(g:vimpager.ptree, -1) | let g:vimpager_ptree = g:vimpager.ptree" +} + +expand_config_vars() { + eval runtime=\"$runtime\" + eval vimcat=\"$vimcat\" + eval system_vimpagerrc=\"$system_vimpagerrc\" +} + +resolve_path() { + if [ -n "$_have_cygpath" ]; then + cygpath -w "$1" | tr '\\' '/' + else + echo "$1" + fi +} + +quit() { + rm -f gvim.exe.stackdump # for a cygwin bug + cd "${tmp%/*}" 2>/dev/null # some systems cannot remove CWD + rm -rf "$tmp" 2>/dev/null # rm -rf "" shows error on OpenBSD + exit "$@" +} + +usage() { + cat <<'EOF' +Usage: vimpager [OPTION]... [FILE | -]... +Display FILE(s) in (n)vim with a pager emulating less. + +With no FILE, or when FILE is -, read standard input. + + -h, --help, --usage Show this help screen and exit. + -v, --version Show version information and exit. + +G, + Go to the end of the file. + -N, --LINE-NUMBERS Show line numbers. + -s Squeeze multiple blank lines into one. + --cmd COMMAND Run (n)vim COMMAND before initialization. + -c COMMAND Run (n)vim COMMAND after initialization. + -u FILE Use FILE as the vimrc. + -x  Give debugging output on stderr. + +Examples: + vimpager program.py # view program.py in the pager + PAGER=vimpager man 3 sprintf # view man page for sprintf(3) + +Project homepage and documentation: <http://github.com/rkitover/vimpager> +or available locally via: man vimpager +Press ',h' for a summary of keystrokes in the program. +EOF +} + +awk() { + command "$_awk" "$@" +} + +sed() { + command "$_sed" "$@" +} + +grep() { + case "$1" in + -Eq) + # we only check for -Eq when it's the only option + case "$2" in + -*) + command "$_grep" "$@" + ;; + *) + if [ "${_have_grep_E_q:-0}" -eq 1 ]; then + command "$_grep" "$@" + else + shift + awk_grep_E_q "$@" + fi + ;; + esac + ;; + *) + command "$_grep" "$@" + ;; + esac +} + +awk_grep_E_q() { + _pat=$(printf '%s' "$1" | sed -e 's!/!\\/!g') + shift + awk ' + BEGIN { exit_val = 1 } + /'"$_pat"'/ { exit_val = 0; exit(exit_val) } + END { exit(exit_val) } + ' "$@" +} + +head() { + _lines= + case "$1" in + -[0-9]*) + _lines=${1#-} + shift + esac + + if [ -z "$_lines" ]; then + command "$_head" "$@" + elif [ "$_head_syntax" = "new" ]; then + command "$_head" -n $_lines -- "$@" + elif [ -z "$_head_no_double_dash" ]; then + command "$_head" -$_lines -- "$@" + else + command "$_head" -$_lines "$@" + fi +} + +# We are escaping only slashes (because they are special in file paths) and +# percent (because it is our escape char). This makes it possible to encode +# the path to the original file in the basename of the temporary file. +encode_filename() { + echo "$@" | sed -e 's|%|%25|g' -e 's|/|%2F|g' +} + +# emulate arrays +set_key() { + eval "$1_$2=\"$3\"" +} + +get_key() { + eval "echo \"\${$1_$2}\"" +} + +# this actually runs vim or gvim, or vimcat, or just cats the file +page_files() { + # EXTRACT BUNDLED SCRIPTS HERE + + if [ -n "$cat_files" ]; then + i=1 + for cur_file in "$@"; do + orig_file=$(get_key orig_file_names $i) + + if [ $# -gt 1 ]; then + if [ $i -gt 1 ]; then + printf '\n' + fi + printf '==> %s <==\n\n' "$orig_file" + fi + + if [ -n "$(get_key ansi_files $i)" ]; then + cat "$cur_file" + _exit_status=$? + else + "$POSIX_SHELL" ${trace:+-x} "$vimcat" ${vimrc:+-u "$vimrc"} \ + --cmd "set rtp^=$runtime | let vimpager={ 'enabled': 1 }" \ + ${extra_cmd:+--cmd "$extra_cmd"} \ + -c 'silent! source '"$tmp/$i"'.vim' \ + ${extra_c:+-c "$extra_c"} \ + "$cur_file" /dev/null +} + +win32_native() { + if [ "x$(get_key _win32_native "$1")" = x1 ]; then + return 0 + else + if [ -n "$msys" -o -n "$cygwin" ]; then + if command -v "$1" > /dev/null | grep -Eq '^/(cygdrive/)?[a-z]/'; then + set_key _win32_native "$1" 1 + return 0 + else + set_key _win32_native "$1" 0 + return 1 + fi + else + set_key _win32_native "$1" 0 + return 1 + fi + fi + return 1 +} + +ansi_filter() { + sed -e 's/'"$ANSI_RE"'//g' "$@" +} + +# Even /bin/sed on Solaris handles UTF-8 characters correctly, so we can safely +# use sed for this. +overstrike_filter() { + sed 's/.//g' "$@" +} + +fits_on_screen() { + [ $# -eq 0 ] && set -- - + + # First remove overstrikes and ANSI codes with sed + ansi_filter "$@" | overstrike_filter | \ + awk ' + { + if (NR == 1) { + lines = total_lines - 2 - (num_files - 1) * file_sep_lines + + if (num_files - 1) + lines -= first_file_sep_lines + + total_cols += 0 # coerce to number + } + + col = 0 + + for (pos = 1; pos <= length($0); pos++) { + c = substr($0, pos, 1) + + # handle tabs + if (c == "\t") + col += 8 - (col % 8) + else + col++ + + if (col > total_cols) { + if (!--lines) exit(1) + col = 1 + } + } + + if (!--lines) exit(1) + } + ' num_files=$# total_lines=$lines total_cols=$cols file_sep_lines=3 first_file_sep_lines=2 - +} + +# vim: sw=4 et tw=0: diff --git a/vimcat b/vimcat index 4d0e42c..2c84297 100755 --- a/vimcat +++ b/vimcat @@ -33,102 +33,7 @@ else exit 1 fi -quit() { - ( - kill "$vim_pid" >/dev/null 2>&1 - do_sleep 100 - kill -9 "$vim_pid" >/dev/null 2>&1 - - kill "$pipeline_pid" >/dev/null 2>&1 - do_sleep 100 - kill -9 "$pipeline_pid" >/dev/null 2>&1 - - kill "$tail_pid" >/dev/null 2>&1 - do_sleep 100 - kill -9 "$tail_pid" >/dev/null 2>&1 - - cd "${tmp_dir%/*}" 2>/dev/null # some systems cannot remove CWD - - rm -rf "$tmp_dir" 2>/dev/null # rm -rf "" shows error on OpenBSD - ) & - exit "$@" -} - -do_sleep() { - _ms=${1:-100} - "$vim" -NEsnR -i NONE -u NONE +"sleep $_ms m" +q >/dev/null 2>&1 -} - -usage() { - cat <<'EOF' -Usage: vimcat [OPTION]... [FILE | -]... -Display FILE(s) in the terminal with (n)vim syntax highlighting using ANSI escape codes. - -With no FILE, or when FILE is -, read standard input. - - -h, --help, --usage This help screen. - -v, --version Show version information and exit. - -n Print with line numbers. - -s Squeeze multiple blank lines into one. - -o FILE | - Output ANSI highlighted text to FILE or standard output. - --cmd COMMAND Run (n)vim COMMAND before initialization. - -c COMMAND Run (n)vim COMMAND after initialization. - -u FILE Use FILE as the vimrc. - -x  Give debugging output on stderr. - -Examples: - vimcat program.py # output program.py with highlighting to terminal - -Project homepage: <http://github.com/rkitover/vimpager> -and documentation: <https://github.com/rkitover/vimpager/blob/master/markdown/vimcat.md> -or available locally via: man vimcat -EOF -} - -write_chunks() { - cd "$chunks_dir" - rm -f -- * - split -b 4096 - - touch PIPELINE_DONE -} - -start_pipeline() { - if [ -n "$pipeline" ]; then - pipeline="$pipeline | write_chunks" - else - pipeline=write_chunks - fi - cat -- "$pipeline_start" | (eval "$pipeline" <&3 & echo $! > "$tmp_dir/pipeline_pid") 3<&0 - pipeline_pid=$(cat "$tmp_dir/pipeline_pid") -} - -start_highlight_job() { - # INSERT VIMCAT_DEBUG PREPARATION HERE - set -- -NE -i NONE -n \ - --cmd "set runtimepath^=$runtime" \ - --cmd "call vimcat#Init({ 'rc': '$vimcatrc' })" \ - --cmd visual \ - ${extra_cmd:+--cmd "$extra_cmd"} \ - ${extra_c:+-c "$extra_c"} \ - -c "call vimcat#Run(\"$dest_file\", ${line_numbers:-0}, \"$chunks_dir\", \"$pipeline_start\")" - - [ -n "$vimcatrc" ] && set -- "$@" -u "$vimcatrc" - - if [ "${VIMCAT_DEBUG:-0}" -eq 0 ]; then - ("$vim" "$@" /dev/null 2>&1; touch "$tmp_dir/vim_done") & - vim_pid=$! - else - "$vim" "$@" &2 - quit 1 - ;; - *) - break - ;; - esac - done - - find_tmp_directory - - trap "quit 1" PIPE HUP INT QUIT ILL TRAP KILL BUS TERM - - detect_term_size - - expand_config_vars - - find_vim_executable - - find_vimpagerrc_files - - read_vim_settings - - parse_pstree - - # if no args, assume stdin - if [ $# -eq 0 ]; then - set -- - - # turn off man/perldoc support for > 1 arg - elif [ $# -gt 1 ]; then - is_man= - is_perldoc= - is_doc= - force_strip_ansi= - fi - - file_idx=1 - - for file in "$@"; do - if [ "$file" = - ]; then - filename=stdin - else - if [ ! -r "$file" ]; then - echo "$0: cannot read file '$file'" >&2 - quit 1 - fi - - filename=$(resolve_path "$file") - fi - - set_key orig_file_names $file_idx "$filename" - - # $file still holds the orginal file name. $filename will be - # the encoded version of $file. $tempfile is the path under - # $tmp if the file is to be opend from there instead of the - # original location. If $tempfile is empty the file is to be - # opened as $file. - filename=$(encode_filename "$filename") - tempfile= - - case "$(echo "$file" | tr 'A-Z' 'a-z')" in - *.gz) - filename=${filename%.??} - tempfile=$tmp/$filename - gunzip -c -- "$file" > "$tempfile" - - ;; - *.bz2) - filename=${filename%.??2} - tempfile=$tmp/$filename - bunzip2 -c -- "$file" > "$tempfile" - ;; - *.xz) - filename=${filename%.??} - tempfile=$tmp/$filename - xzcat -c -- "$file" > "$tempfile" - ;; - *.z) - filename=${filename%.?} - tempfile=$tmp/$filename - uncompress -c -- "$file" > "$tempfile" - ;; - *) - if [ "$file" = - ]; then - tempfile=$tmp/$filename - cat -- "$file" > "$tempfile" - fi - ;; - esac - - # check for ANSI codes and strip if not using ansiesc - if head -100 "${tempfile:-$file}" | grep -Eq "$ANSI_RE"; then - if [ -z "$ansiesc_available" -o -n "$force_strip_ansi" ]; then - ansi_filter "${tempfile:-$file}" > "$tmp/$filename.work" - tempfile=$tmp/$filename - mv -f -- "$tempfile.work" "$tempfile" - else - echo 'call vimpager_utils#DoAnsiEsc()' >> "$tmp/$file_idx.vim" - set_key ansi_files "$file_idx" yes - fi - fi - - # squeeze blank lines if option was specified, Ubuntu man with /usr/bin/pager does this - if [ "${squeeze_blank_lines:-0}" -eq 1 ]; then - sed -e '/^[ ]*$/{ - N - /^[ ]*\n[ ]*$/D - }' < "${tempfile:-$file}" > "$tmp/$filename.work" - tempfile=$tmp/$filename - mv -f -- "$tempfile.work" "$tempfile" - fi - - # dumb man detection when the pstree heuristic fails - if [ -z "$is_doc" ] && head -12 "${tempfile:-$file}" | grep -Eq '^N(.)?A(.)?M(.)?E(.)?[ \t]*$'; then - is_man=1 - is_doc=1 - fi - - # if it's a man page, remove starting blank lines, or the C syntax highlighting fails - # and write out ft command for vim - if [ -n "$is_doc" ]; then - ansi_filter "${tempfile:-$file}" | overstrike_filter | awk ' - BEGIN { skipblank=1 } - /^[ ]*$/ { if (!skipblank) print } - /[^ ]/ { skipblank=0; print } - ' > "$tmp/$filename.work" - tempfile=$tmp/$filename - mv -f -- "$tempfile.work" "$tempfile" - - if [ -n "$is_man" ]; then - echo 'set ft=man' >> "$tmp/$file_idx.vim" - elif [ -n "$is_perldoc" ]; then - echo 'set ft=perldoc' >> "$tmp/$file_idx.vim" - fi - fi - - # if file is zero length, or one blank line (cygwin), and is only arg, exit - if [ ! -s "${tempfile:-$file}" \ - -a $# -eq 1 \ - -o "$(cat "${tempfile:-$file}")" = "" \ - -a "$(wc -l < "${tempfile:-$file}")" -eq 1 ]; then - - quit 0 - fi - - set_key files $file_idx "$(resolve_path "${tempfile:-$file}")" - - file_idx=$((file_idx + 1)) - done - - file_count=$# - - set -- - i=1 - while [ $i -le $file_count ]; do - set -- "$@" "$(get_key files $i)" - i=$((i + 1)) - done - - if [ "${no_pass_thru:-0}" -ne 1 ] && fits_on_screen "$@"; then - cat_files=1 - fi - - page_files "$@" - - quit $? -} - -find_tmp_directory() { - # Find and create the temporary directory used by vimpager. Set the $tmp variable. - mkdir_options="-m 700" - - if [ -n "$win32" ]; then - # Use the real TEMP directory on windows in case we are - # using a native vim/gvim - # TEMP can be /tmp sometimes too - - tmp=$(resolve_path "$TEMP") - - # chmod doesn't work here, even in /tmp sometimes - mkdir_options= - else - # ... and /tmp otherwise - tmp=/tmp - fi - - # Create a safe directory in which we place all other tempfiles. - tmp=$tmp/vimpager_$$ - if ! mkdir $mkdir_options "$tmp"; then - echo "ERROR: Could not create temporary directory $tmp" >&2 - quit 1 - fi -} - -detect_term_size() { - # Detect the terminal size and set the variables $cols and $lines. If necessary $no_pass_thru is set. - if command -v tput >/dev/null; then - # this is the only way it works on some versions of Cygwin - - # 2>/dev/null makes tput not work, so don't do that - # we are just going to hope that tput errors don't happen - tput cols > "$tmp/cols" - tput lines > "$tmp/lines" - - cols=$(cat "$tmp/cols") - lines=$(cat "$tmp/lines") - - rm -f -- "$tmp/cols" "$tmp/lines" - fi - - # msys has no tput, this doesn't work on Cygwin by the way - if [ -z "$cols" ] && command -v bash >/dev/null; then - cols=$(bash -i -c 'echo $COLUMNS') - lines=$(bash -i -c 'echo $LINES') - fi - - # If we are unable to detect lines/columns, maximize - # the window. - if [ -z "$cols" ]; then - cols=999 - lines=999 - no_pass_thru=1 # force loading vimpager - fi -} - -find_vimpagerrc_files() { - # This function will find the system and the user vimpagerrc file and set the variables $system_vimrc and $vimrc. - - # determine location of rc file - i=1 - OLDIFS=$IFS - IFS=' -' - for var in $(IFS=$OLDIFS; "$tvim" -NEnR -i NONE ${vimrc:+-u "$vimrc"} +'call writefile(["", "VAL:" . $VIM, "VAL:" . $MYVIMRC], "/dev/stderr")' +q &1 >/dev/null); do - case "$var" in - VAL:*) - case $i in - 1) - vim_dir=${var#VAL:} - ;; - 2) - user_vimrc=${var#VAL:} - user_vimrc_dir=${user_vimrc%/*} - break - ;; - esac - i=$((i + 1)) - ;; - esac - done - IFS=$OLDIFS - - # find system vimrc - system_vimrc=$("$tvim" --version | sed -n '/system vimrc file: "/{ - s|\$VIM|'"$vim_dir"'| - s/.*: "\([^"]*\).*/\1/p - q - }') - - # find the users vimpagerrc - if [ -n "$vimrc" ]; then - # The vimrc file was given on the command line. - : - elif [ -n "$VIMPAGER_RC" ]; then - vimrc=$VIMPAGER_RC - # check for vimpagerrc in same dir as vimrc in case it is set in VIMINIT - elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/.vimpagerrc" ]; then - vimrc=$user_vimrc_dir/.vimpagerrc - elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/_vimpagerrc" ]; then - vimrc=$user_vimrc_dir/_vimpagerrc - elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/vimpagerrc" ]; then - vimrc=$user_vimrc_dir/vimpagerrc - # check standard paths, according to :h initialization - elif [ -r ~/.vimpagerrc ]; then - vimrc=~/.vimpagerrc - elif [ -r ~/.vim/vimpagerrc ]; then - vimrc=~/.vim/vimpagerrc - elif [ -r ~/_vimpagerrc ]; then - vimrc=~/_vimpagerrc - elif [ -r ~/vimfiles/vimpagerrc ]; then - vimrc=~/vimfiles/vimpagerrc - elif [ -r "$vim_dir/_vimpagerrc" ]; then - vimrc=$vim_dir/_vimpagerrc - # try the user's ~/.vimrc - elif [ -n "$user_vimrc" ]; then - : - # if no user vimrc, then check for a global /etc/vimpagerrc - elif [ -n "$system_vimpagerrc" -a -f "$system_vimpagerrc" ]; then - : - # check a couple of common places for the standalone version - elif [ -f /usr/local/etc/vimpagerrc ]; then - vimrc=/usr/local/etc/vimpagerrc - elif [ -f /etc/vimpagerrc ]; then - vimrc=/etc/vimpagerrc - fi -} - -read_vim_settings() { - # Read settings from the vimpagerrc file and possibly set $use_gvim, $ansiesc_available, $disable_x11 and $no_pass_thru. - i=1 - OLDIFS=$IFS - IFS=' -' - for var in $(IFS=$OLDIFS; "$tvim" -NEnR ${vimrc:+-u "$vimrc"} -i NONE --cmd 'let g:vimpager = { "enabled": 1 }' +' - if !exists("g:vimpager.gvim") - if !exists("g:vimpager_use_gvim") - let g:vimpager.gvim = 0 - else - let g:vimpager.gvim = g:vimpager_use_gvim - endif - endif - - if !exists("g:vimpager.X11") - if !exists("g:vimpager_disable_x11") - let g:vimpager.X11 = 1 - else - let g:vimpager.X11 = !g:vimpager_disable_x11 - endif - endif - - if !exists("g:vimpager.passthrough") - if !exists("g:vimpager_passthrough") - let g:vimpager.passthrough = 1 - else - let g:vimpager.passthrough = g:vimpager_passthrough - endif - endif - - let g:use_ansiesc = 0 - - if has("conceal") && (!exists("g:vimpager.ansiesc") || g:vimpager.ansiesc == 1) && (!exists("g:vimpager_disable_ansiesc") || g:vimpager_disable_ansiesc == 0) - let g:use_ansiesc = 1 - endif - - call writefile([""] + map([g:vimpager.gvim, g:vimpager.X11, g:vimpager.passthrough, g:use_ansiesc], "\"VAL:\".v:val"), "/dev/stderr") - quit - ' &1 >/dev/null); do - case "$var" in - VAL:*) - case $i in - 1) - [ "${var#VAL:}" -eq 1 ] && use_gvim=1 - ;; - 2) - [ "${var#VAL:}" -eq 0 ] && disable_x11=1 - ;; - 3) - [ "${var#VAL:}" -eq 0 ] && no_pass_thru=1 - ;; - 4) - [ "${var#VAL:}" -ne 0 ] && ansiesc_available=1 - break - ;; - esac - i=$((i + 1)) - ;; - esac - done - IFS=$OLDIFS -} - -find_vim_executable() { - # Find the vim executable to use. Set $vim_cmd and $gui. - if [ -n "$win32" ]; then - # msys/cygwin may be using a native vim, and if we're not in a real - # console the native vim will not work, so we have to use gvim. - - if [ "x$TERM" != "xdumb" -a "x$TERM" != "xcygwin" -a "x$TERM" != "x" ]; then - if command -v vim >/dev/null | grep -Eq '^/(cygdrive/)?[a-z]/'; then - use_gvim=1 - fi - fi - fi - - tvim=vim - - if [ -n "$EDITOR" -a -z "$VIMPAGER_VIM" ]; then - case "${EDITOR##*/}" in - *vim*) - export VIMPAGER_VIM=$EDITOR - ;; - esac - fi - - if [ -n "$VIMPAGER_VIM" ]; then - case "${VIMPAGER_VIM##*/}" in - vim*) - tvim=$VIMPAGER_VIM - ;; - nvim*) - tvim=$VIMPAGER_VIM - ;; - gvim*|mvim*) - use_gvim=1 - gvim=$VIMPAGER_VIM - ;; - esac - fi - - if [ -n "$use_gvim" ]; then - # determine if this is an ssh session and/or $DISPLAY is set - if [ -n "$osx" ]; then - if [ -z "$SSH_CONNECTION" ] && command -v mvim >/dev/null; then - vim_cmd=${gvim:-mvim} - gui=1 - else - vim_cmd=$tvim - fi - elif [ -n "$cygwin" ]; then - if command -v gvim >/dev/null; then - if [ -n "$SSH_CONNECTION" ]; then - vim_cmd=$tvim - # The Cygwin gvim uses X - elif win32_native gvim; then - if [ -z "$DISPLAY" ]; then - vim_cmd=$tvim - else - vim_cmd=${gvim:-gvim} - gui=1 - fi - else - vim_cmd=${gvim:-gvim} - gui=1 - fi - else - vim_cmd=$tvim - fi - elif [ -n "$msys" ]; then - if [ -z "$SSH_CONNECTION" ] && command -v gvim >/dev/null; then - vim_cmd=${gvim:-gvim} - gui=1 - else - vim_cmd=$tvim - fi - elif [ -z "$DISPLAY" ]; then - vim_cmd=$tvim - else - if command -v gvim >/dev/null; then - vim_cmd=${gvim:-gvim} - gui=1 - else - vim_cmd=$tvim - fi - fi - else - vim_cmd=${vim_cmd:-${tvim:-vim}} - fi - - if [ ! -n "$gui" -a -n "$disable_x11" ]; then - vim_cmd="$vim_cmd -X" - fi -} - -parse_pstree() { - # Parse the process tree and set $is_man, $is_doc, $is_perldoc, $force_strip_ansi and $extra_cmd. - ptree=$(do_ptree) - - # Check if called from man, perldoc or pydoc - if echo "$ptree" | grep -Eq '([ \t]+|/)(man|[Pp]y(thon|doc)[0-9.]*|[Rr](uby|i)[0-9.]*)([ \t]|$)'; then - is_man=1 - is_doc=1 - force_strip_ansi=1 - elif echo "$ptree" | grep -Eq '([ \t]+|/)perl(doc)?([0-9.]*)?([ \t]|$)'; then - is_perldoc=1 - is_doc=1 - force_strip_ansi=1 - fi - - extra_cmd="${extra_cmd:+$extra_cmd | }let g:vimpager.ptree=[$(echo "$ptree" | awk '{ print "\"" $2 "\"" }' | tr '\n' ',')] | call remove(g:vimpager.ptree, -1) | let g:vimpager_ptree = g:vimpager.ptree" -} - -expand_config_vars() { - eval runtime=\"$runtime\" - eval vimcat=\"$vimcat\" - eval system_vimpagerrc=\"$system_vimpagerrc\" -} - # special handling to rewrite cygwin/msys paths to windows POSIX paths if [ -n "$win32" ] && command -v cygpath >/dev/null; then _have_cygpath=1 fi -resolve_path() { - if [ -n "$_have_cygpath" ]; then - cygpath -w "$1" | tr '\\' '/' - else - echo "$1" - fi -} - -quit() { - rm -f gvim.exe.stackdump # for a cygwin bug - cd "${tmp%/*}" 2>/dev/null # some systems cannot remove CWD - rm -rf "$tmp" 2>/dev/null # rm -rf "" shows error on OpenBSD - exit "$@" -} - -usage() { - cat <<'EOF' -Usage: vimpager [OPTION]... [FILE | -]... -Display FILE(s) in (n)vim with a pager emulating less. - -With no FILE, or when FILE is -, read standard input. - - -h, --help, --usage Show this help screen and exit. - -v, --version Show version information and exit. - +G, + Go to the end of the file. - -N, --LINE-NUMBERS Show line numbers. - -s Squeeze multiple blank lines into one. - --cmd COMMAND Run (n)vim COMMAND before initialization. - -c COMMAND Run (n)vim COMMAND after initialization. - -u FILE Use FILE as the vimrc. - -x  Give debugging output on stderr. - -Examples: - vimpager program.py # view program.py in the pager - PAGER=vimpager man 3 sprintf # view man page for sprintf(3) - -Project homepage and documentation: <http://github.com/rkitover/vimpager> -or available locally via: man vimpager -Press ',h' for a summary of keystrokes in the program. -EOF -} - if command -v gawk >/dev/null; then _awk=gawk elif command -v nawk >/dev/null; then @@ -654,10 +69,6 @@ else quit 1 fi -awk() { - command "$_awk" "$@" -} - if command -v gsed >/dev/null; then _sed=gsed elif [ -x /usr/xpg4/bin/sed ]; then @@ -669,11 +80,6 @@ else quit 1 fi -sed() { - command "$_sed" "$@" -} - - if command -v ggrep >/dev/null; then _grep=ggrep elif [ -x /usr/xpg4/bin/grep ]; then @@ -690,40 +96,6 @@ if [ -z "$(echo foo | "$_grep" -Eq foo >/dev/null 2>&1)" -a $? -eq 0 ]; then _have_grep_E_q=1 fi -grep() { - case "$1" in - -Eq) - # we only check for -Eq when it's the only option - case "$2" in - -*) - command "$_grep" "$@" - ;; - *) - if [ "${_have_grep_E_q:-0}" -eq 1 ]; then - command "$_grep" "$@" - else - shift - awk_grep_E_q "$@" - fi - ;; - esac - ;; - *) - command "$_grep" "$@" - ;; - esac -} - -awk_grep_E_q() { - _pat=$(printf '%s' "$1" | sed -e 's!/!\\/!g') - shift - awk ' - BEGIN { exit_val = 1 } - /'"$_pat"'/ { exit_val = 0; exit(exit_val) } - END { exit(exit_val) } - ' "$@" -} - if command -v ghead >/dev/null; then _head=ghead else @@ -738,202 +110,10 @@ else fi fi -head() { - _lines= - case "$1" in - -[0-9]*) - _lines=${1#-} - shift - esac - - if [ -z "$_lines" ]; then - command "$_head" "$@" - elif [ "$_head_syntax" = "new" ]; then - command "$_head" -n $_lines -- "$@" - elif [ -z "$_head_no_double_dash" ]; then - command "$_head" -$_lines -- "$@" - else - command "$_head" -$_lines "$@" - fi -} - -# We are escaping only slashes (because they are special in file paths) and -# percent (because it is our escape char). This makes it possible to encode -# the path to the original file in the basename of the temporary file. -encode_filename() { - echo "$@" | sed -e 's|%|%25|g' -e 's|/|%2F|g' -} - -# emulate arrays -set_key() { - eval "$1_$2=\"$3\"" -} - -get_key() { - eval "echo \"\${$1_$2}\"" -} - -# this actually runs vim or gvim, or vimcat, or just cats the file -page_files() { - # EXTRACT BUNDLED SCRIPTS HERE - - if [ -n "$cat_files" ]; then - i=1 - for cur_file in "$@"; do - orig_file=$(get_key orig_file_names $i) - - if [ $# -gt 1 ]; then - if [ $i -gt 1 ]; then - printf '\n' - fi - printf '==> %s <==\n\n' "$orig_file" - fi - - if [ -n "$(get_key ansi_files $i)" ]; then - cat "$cur_file" - _exit_status=$? - else - "$POSIX_SHELL" ${trace:+-x} "$vimcat" ${vimrc:+-u "$vimrc"} \ - --cmd "set rtp^=$runtime | let vimpager={ 'enabled': 1 }" \ - ${extra_cmd:+--cmd "$extra_cmd"} \ - -c 'silent! source '"$tmp/$i"'.vim' \ - ${extra_c:+-c "$extra_c"} \ - "$cur_file" /dev/null -} - -win32_native() { - if [ "x$(get_key _win32_native "$1")" = x1 ]; then - return 0 - else - if [ -n "$msys" -o -n "$cygwin" ]; then - if command -v "$1" > /dev/null | grep -Eq '^/(cygdrive/)?[a-z]/'; then - set_key _win32_native "$1" 1 - return 0 - else - set_key _win32_native "$1" 0 - return 1 - fi - else - set_key _win32_native "$1" 0 - return 1 - fi - fi - return 1 -} - # this is compatible with osed ANSI_RE='\[[;?]*[0-9.;]*[A-Za-z]' -ansi_filter() { - sed -e 's/'"$ANSI_RE"'//g' "$@" -} - -# Even /bin/sed on Solaris handles UTF-8 characters correctly, so we can safely -# use sed for this. -overstrike_filter() { - sed 's/.//g' "$@" -} - -fits_on_screen() { - [ $# -eq 0 ] && set -- - - - # First remove overstrikes and ANSI codes with sed - ansi_filter "$@" | overstrike_filter | \ - awk ' - { - if (NR == 1) { - lines = total_lines - 2 - (num_files - 1) * file_sep_lines - - if (num_files - 1) - lines -= first_file_sep_lines - - total_cols += 0 # coerce to number - } - - col = 0 - - for (pos = 1; pos <= length($0); pos++) { - c = substr($0, pos, 1) - - # handle tabs - if (c == "\t") - col += 8 - (col % 8) - else - col++ - - if (col > total_cols) { - if (!--lines) exit(1) - col = 1 - } - } - - if (!--lines) exit(1) - } - ' num_files=$# total_lines=$lines total_cols=$cols file_sep_lines=3 first_file_sep_lines=2 - -} - +. "$project_dir/inc/vimpager_functions.sh" # INCLUDE BUNDLED SCRIPTS HERE # END OF BUNDLED SCRIPTS From df7c0316f4386163df3a7004ed4b24b47cd26032 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Tue, 21 Jun 2016 16:15:48 +0200 Subject: [PATCH 02/18] Add some tests for vimpager shell functions --- test/helpers.bash | 1 + test/vimpager-functions.bats | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 test/vimpager-functions.bats diff --git a/test/helpers.bash b/test/helpers.bash index c7d05c5..dcb039b 100644 --- a/test/helpers.bash +++ b/test/helpers.bash @@ -1,6 +1,7 @@ #!/usr/bin/env bash fixtures=$BATS_TEST_DIRNAME/fixtures +src=${BATS_TEST_DIRNAME%/*} status_ok() { [ "$status" -eq 0 ] diff --git a/test/vimpager-functions.bats b/test/vimpager-functions.bats new file mode 100644 index 0000000..39620e6 --- /dev/null +++ b/test/vimpager-functions.bats @@ -0,0 +1,67 @@ +#!/usr/bin/env bats + +load helpers + +. "$src/inc/vimpager_functions.sh" + +@test 'find_tmp_directory sets $tmp' { + [[ -z "$tmp" ]] + find_tmp_directory + [[ "$tmp" = /* ]] +} + +@test 'detect_term_size sets $cols and $lines' { + # detect_term_size will write files to $tmp (assuming it is a direcotry) + tmp=$BATS_TMPDIR + [[ -z "$cols" ]] + [[ -z "$lines" ]] + detect_term_size + [[ "$cols" =~ [0-9]+ ]] + [[ "$lines" =~ [0-9]+ ]] +} + +@test 'read_vim_settings may set $use_gvim, $ansiesc_available, $disable_x11 and $no_pass_thru' { + [[ -z "$use_gvim" ]] + [[ -z "$ansiesc_available" ]] + [[ -z "$disable_x11" ]] + [[ -z "$no_pass_thru" ]] + read_vim_settings + [[ "$use_gvim" -eq 1 || -z "$use_gvim" ]] + [[ "$ansiesc_available" -eq 1 || -z "$ansiesc_available" ]] + [[ "$disable_x11" -eq 1 || -z "$disable_x11" ]] + [[ "$no_pass_thru" -eq 1 || -z "$no_pass_thru" ]] +} + +@test 'find_vim_executable sets $tvim and $vim_cmd' { + [[ -z "$tvim" ]] + [[ -z "$vim_cmd" ]] + find_vim_executable + [[ -n "$tvim" ]] + [[ -n "$vim_cmd" ]] +} + +@test "quit returns arguments as return codes" { + run quit 42 + [[ "$status" -eq 42 ]] + no_output + run quit + status_ok + no_output +} + +@test 'quit cleans up the $tmp direcotry' { + tmp=$BATS_TMPDIR/quit-test + mkdir "$tmp" + touch "$tmp/some-file" + run quit 1 + [[ ! -e "$tmp/some-file" ]] + [[ ! -e "$tmp" ]] +} + +@test "usage prints the help message" { + unset -f sed + run usage + [[ "$output" = "$(sed 's/\r//' "$fixtures/vimpager-help.txt")" ]] + status_ok +} +# vim: filetype=sh et sw=4 sts=4 : From 79d7bbc7cd2b36d9e17cb6e2d66598886fe746a6 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Tue, 21 Jun 2016 18:23:19 +0200 Subject: [PATCH 03/18] Add some tests for vimcat shell functions --- test/vimcat-functions.bats | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 test/vimcat-functions.bats diff --git a/test/vimcat-functions.bats b/test/vimcat-functions.bats new file mode 100644 index 0000000..5842016 --- /dev/null +++ b/test/vimcat-functions.bats @@ -0,0 +1,46 @@ +#!/usr/bin/env bats + +load helpers + +. "$src/inc/vimcat_functions.sh" + +@test "quit returns arguments as return codes" { + run quit 42 + [[ "$status" -eq 42 ]] + no_output + run quit + status_ok + no_output +} + +@test 'quit cleans up the $tmp direcotry' { + tmp_dir=$BATS_TMPDIR/quit-test + mkdir "$tmp_dir" + touch "$tmp_dir/some-file" + run quit 1 + [[ ! -e "$tmp_dir/some-file" ]] + [[ ! -e "$tmp_dir" ]] +} + +@test 'quit kills $vim_pid, $pipeline_pid and $tail_pid' { + sleep 100000 & + vim_pid=$! + sleep 200000 & + pipeline_pid=$! + sleep 300000 & + tail_pid=$! + run jobs + [[ ${#lines[@]} -eq 3 ]] + run quit 1 + sleep 1 + run jobs + no_output +} + +@test "usage prints the help message" { + run usage + [[ "$output" = "$(sed 's/\r//' "$fixtures/vimcat-help.txt")" ]] + status_ok +} + +# vim: filetype=sh et sw=4 sts=4 : From 4dfd5efe5a26895608ead9b7201b81f12dbfabd1 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Tue, 21 Jun 2016 18:31:14 +0200 Subject: [PATCH 04/18] Move function common to vim{pager,cat} to a seperate file --- Makefile | 22 +++++++++++++++++++--- inc/common_functions.sh | 10 ++++++++++ inc/vimcat_functions.sh | 7 ------- inc/vimpager_functions.sh | 5 +---- vimcat | 1 + vimpager | 1 + 6 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 inc/common_functions.sh diff --git a/Makefile b/Makefile index e2a6548..4cff0c2 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,10 @@ standalone/vimpager: vimpager vimpager-version.txt ${SRC:=.uu} inc/bundled_scrip -e 'r inc/vimpager_functions.sh' \ -e d \ -e '}' \ + -e '/^ *\. .*inc\/common_functions.sh"$$/{' \ + -e 'r inc/common_functions.sh' \ + -e d \ + -e '}' \ -e 's/^\( *\)# EXTRACT BUNDLED SCRIPTS HERE$$/\1extract_bundled_scripts/' \ -e 's|^version=.*|version="'"`cat vimpager-version.txt`"' (standalone, shell=\$$(command -v \$$POSIX_SHELL))"|' \ -e 's!^\( *\)runtime=.*$$!\1runtime='\''\$$tmp/runtime'\''!' \ @@ -67,7 +71,7 @@ standalone/vimpager: vimpager vimpager-version.txt ${SRC:=.uu} inc/bundled_scrip @sed -n '/^# END OF BUNDLED SCRIPTS$$/,$$p' vimpager >> $@ @chmod +x $@ -standalone/vimcat: vimcat autoload/vimcat.vim inc/prologue.sh inc/vimcat_functions.sh Makefile vimcat-version.txt +standalone/vimcat: vimcat autoload/vimcat.vim inc/prologue.sh inc/vimcat_functions.sh inc/common_functions.sh Makefile vimcat-version.txt @echo building $@ @${MKPATH} ${@D} @nlinit=`echo 'nl="'; echo '"'`; eval "$$nlinit"; \ @@ -87,6 +91,10 @@ standalone/vimcat: vimcat autoload/vimcat.vim inc/prologue.sh inc/vimcat_functio -e 'r inc/vimcat_functions.sh' \ -e d \ -e '}' \ + -e '/^ *\. .*inc\/common_functions.sh"$$/{' \ + -e 'r inc/common_functions.sh' \ + -e d \ + -e '}' \ vimcat > $@ @cp $@ $@.work @awk '/^[ ]*(if|for|while)/ { print $$1 }' $@ \ @@ -97,7 +105,7 @@ standalone/vimcat: vimcat autoload/vimcat.vim inc/prologue.sh inc/vimcat_functio @sed -e 's/vimcat#\([^ ]*\)(/\1(/g' autoload/vimcat.vim >> $@ @chmod +x $@ -vimcat.uu: vimcat inc/prologue.sh inc/vimcat_functions.sh Makefile vimcat-version.txt +vimcat.uu: vimcat vimcat-version.txt inc/vimcat_functions.sh inc/common_functions.sh inc/prologue.sh Makefile @echo uuencoding vimcat @echo 'vimcat_script() {' > $@ @printf "\t(cat <<'EOF') | do_uudecode > bin/vimcat\n" >> $@ @@ -111,6 +119,10 @@ vimcat.uu: vimcat inc/prologue.sh inc/vimcat_functions.sh Makefile vimcat-versio -e 'r inc/vimcat_functions.sh' \ -e d \ -e '}' \ + -e '/^ *\. .*inc\/common_functions.sh"$$/{' \ + -e 'r inc/common_functions.sh' \ + -e d \ + -e '}' \ vimcat > $@.work @uuencode $@.work vimcat >> $@ @echo EOF >> $@ @@ -185,7 +197,7 @@ install: docs vimpager.configured vimcat.configured echo ${INSTALLCONF} vimpagerrc "$${SYSCONFDIR}/vimpagerrc"; \ ${INSTALLCONF} vimpagerrc "$${SYSCONFDIR}/vimpagerrc" -%.configured: % %-version.txt inc/%_functions.sh +%.configured: % %-version.txt inc/%_functions.sh inc/common_functions.sh @echo configuring $< @POSIX_SHELL="`scripts/find_shell`"; \ BASE='${@F}'; \ @@ -207,6 +219,10 @@ install: docs vimpager.configured vimcat.configured -e "r inc/$${BASE}_functions.sh" \ -e d \ -e '}' \ + -e '/^ *\. .*inc\/common_functions.sh"$$/{' \ + -e 'r inc/common_functions.sh' \ + -e d \ + -e '}' \ $< > $@ @chmod +x $@ diff --git a/inc/common_functions.sh b/inc/common_functions.sh new file mode 100644 index 0000000..7958d1b --- /dev/null +++ b/inc/common_functions.sh @@ -0,0 +1,10 @@ +# Function definitions common for vimpager and vimcat. + +squeeze_blank_lines() { + sed '/^[ ]*$/{ + N + /^[ ]*\n[ ]*$/D + }' +} + +# vim: sw=4 et tw=0: diff --git a/inc/vimcat_functions.sh b/inc/vimcat_functions.sh index 2f74cb5..07d0365 100644 --- a/inc/vimcat_functions.sh +++ b/inc/vimcat_functions.sh @@ -90,11 +90,4 @@ start_highlight_job() { fi } -squeeze_blank_lines() { - sed '/^[ ]*$/{ - N - /^[ ]*\n[ ]*$/D - }' -} - # vim: sw=4 et tw=0: diff --git a/inc/vimpager_functions.sh b/inc/vimpager_functions.sh index e37cb7b..d022f95 100644 --- a/inc/vimpager_functions.sh +++ b/inc/vimpager_functions.sh @@ -171,10 +171,7 @@ main() { # squeeze blank lines if option was specified, Ubuntu man with /usr/bin/pager does this if [ "${squeeze_blank_lines:-0}" -eq 1 ]; then - sed -e '/^[ ]*$/{ - N - /^[ ]*\n[ ]*$/D - }' < "${tempfile:-$file}" > "$tmp/$filename.work" + squeeze_blank_lines < "${tempfile:-$file}" > "$tmp/$filename.work" tempfile=$tmp/$filename mv -f -- "$tempfile.work" "$tempfile" fi diff --git a/vimcat b/vimcat index 2c84297..a8be296 100755 --- a/vimcat +++ b/vimcat @@ -34,6 +34,7 @@ else fi . "$project_dir/inc/vimcat_functions.sh" +. "$project_dir/inc/common_functions.sh" # if no args and stdin is on a terminal, pretend we're cat and wait on stdin. if [ $# -eq 0 -a -t 0 ]; then diff --git a/vimpager b/vimpager index 41d874f..67f4298 100755 --- a/vimpager +++ b/vimpager @@ -114,6 +114,7 @@ fi ANSI_RE='\[[;?]*[0-9.;]*[A-Za-z]' . "$project_dir/inc/vimpager_functions.sh" +. "$project_dir/inc/common_functions.sh" # INCLUDE BUNDLED SCRIPTS HERE # END OF BUNDLED SCRIPTS From 7c07c6ee1aa4f6fd464766155371333b58b8e43a Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 22 Jun 2016 09:06:41 +0200 Subject: [PATCH 05/18] Add test for functions common to vim{pager,cat} --- test/common-functions.bats | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test/common-functions.bats diff --git a/test/common-functions.bats b/test/common-functions.bats new file mode 100644 index 0000000..6746479 --- /dev/null +++ b/test/common-functions.bats @@ -0,0 +1,35 @@ +#!/usr/bin/env bats + +load helpers + +. "$src/inc/common_functions.sh" + +@test "squeeze_blank_lines" { + tmp_function () { + ( + echo The first line is normal + echo The second as well + echo # an empty line + echo Another text line + echo # empty line + echo # empty line + echo third line with text + echo more text + echo ' ' # some blanks + echo ' ' # some tabs + echo last line + ) | squeeze_blank_lines + } + run tmp_function + status_ok + [[ "$(wc -l <<<"$output")" -eq 9 ]] + [[ "${#lines[@]}" -eq 7 ]] + [[ "${lines[0]}" = 'The first line is normal' ]] + [[ "${lines[1]}" = 'The second as well' ]] + [[ "${lines[2]}" = 'Another text line' ]] + [[ "${lines[3]}" = 'third line with text' ]] + [[ "${lines[4]}" = 'more text' ]] + [[ "${lines[5]}" = ' ' ]] + [[ "${lines[6]}" = 'last line' ]] +} +# vim: filetype=sh et sw=4 sts=4 : From 823d2254abd363806a08776bd6684a9442e45b26 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 22 Jun 2016 23:55:00 +0200 Subject: [PATCH 06/18] Add simple test for vimpager output --- test/vimpager-output.bats | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 test/vimpager-output.bats diff --git a/test/vimpager-output.bats b/test/vimpager-output.bats new file mode 100644 index 0000000..eba830c --- /dev/null +++ b/test/vimpager-output.bats @@ -0,0 +1,12 @@ +#!/usr/bin/env bats + +load helpers + +@test "vimpager cats files if stdout is not a terminal" { + run ./vimpager uganda.txt + status_ok + [[ "${lines[0]}" = '*uganda.txt* For Vim version 7.4. Last change: 2013 Jul 06' ]] + [[ "$(sed -n '10{p;q;}' <<<"$output")" = 'Vim is Charityware. You can use and copy it as much as you like, but you are' ]] +} + +# vim: filetype=sh et sw=4 sts=4 : From 2fda4529f2628f47c62114539a2b47f8a5611f21 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Fri, 24 Jun 2016 00:34:41 +0200 Subject: [PATCH 07/18] Move further code from vimpager into functions --- inc/vimpager_functions.sh | 92 +++++++++++++++++++++++++++++++++++++++ vimpager | 86 ++++-------------------------------- 2 files changed, 101 insertions(+), 77 deletions(-) diff --git a/inc/vimpager_functions.sh b/inc/vimpager_functions.sh index d022f95..7806931 100644 --- a/inc/vimpager_functions.sh +++ b/inc/vimpager_functions.sh @@ -1,5 +1,7 @@ # Function definitions for vimpager. +# this is compatible with osed +ANSI_RE='\[[;?]*[0-9.;]*[A-Za-z]' main() { # if no args and no stdin, display usage @@ -818,4 +820,94 @@ fits_on_screen() { ' num_files=$# total_lines=$lines total_cols=$cols file_sep_lines=3 first_file_sep_lines=2 - } +set_system_vars() { + case "$(uname -s)" in + Linux) linux=1 ;; + SunOS) solaris=1 ;; + Darwin) osx=1; bsd=1 ;; + CYGWIN*) cygwin=1; win32=1 ;; + MINGW*) msys=1; win32=1 ;; + MSYS*) msys=1; win32=1 ;; + OpenBSD) openbsd=1; bsd=1 ;; + FreeBSD) freebsd=1; bsd=1 ;; + NetBSD) netbsd=1; bsd=1 ;; + *) bsd=1 ;; + esac +} + +check_for_cygpath() { + # special handling to rewrite cygwin/msys paths to windows POSIX paths + if [ -n "$win32" ] && command -v cygpath >/dev/null; then + _have_cygpath=1 + fi +} + +select_awk_executable() { + if command -v gawk >/dev/null; then + _awk=gawk + elif command -v nawk >/dev/null; then + _awk=nawk + elif command -v mawk >/dev/null; then + _awk=mawk + elif [ -x /usr/xpg4/bin/awk ]; then + _awk=/usr/xpg4/bin/awk + elif command -v awk >/dev/null; then + _awk=awk + else + echo "ERROR: No awk found!" >&2 + quit 1 + fi +} + +select_sed_executable() { + if command -v gsed >/dev/null; then + _sed=gsed + elif [ -x /usr/xpg4/bin/sed ]; then + _sed=/usr/xpg4/bin/sed + elif command -v sed >/dev/null; then + _sed=sed + else + echo "ERROR: No sed found!" >&2 + quit 1 + fi +} + +select_grep_executable() { + if command -v ggrep >/dev/null; then + _grep=ggrep + elif [ -x /usr/xpg4/bin/grep ]; then + _grep=/usr/xpg4/bin/grep + elif command -v grep >/dev/null; then + _grep=grep + else + echo "ERROR: No grep found!" >&2 + quit 1 + fi +} + +check_for_grep_q() { + # check that grep -Eq works + if [ -z "$(echo foo | "$_grep" -Eq foo >/dev/null 2>&1)" -a $? -eq 0 ]; then + _have_grep_E_q=1 + fi +} + +select_head_executable() { + if command -v ghead >/dev/null; then + _head=ghead + else + _head=head + fi +} + +select_head_syntax() { + if [ "$(echo xx | head -n 1 2>/dev/null)" = "xx" ]; then + _head_syntax=new + else + if ! head -1 -- "$0" >/dev/null 2>&1; then + _head_no_double_dash=1 + fi + fi +} + # vim: sw=4 et tw=0: diff --git a/vimpager b/vimpager index 67f4298..6b81871 100755 --- a/vimpager +++ b/vimpager @@ -36,88 +36,20 @@ runtime='$project_dir' vimcat='$project_dir/vimcat' system_vimpagerrc='$project_dir/vimpagerrc' -case "$(uname -s)" in - Linux) linux=1 ;; - SunOS) solaris=1 ;; - Darwin) osx=1; bsd=1 ;; - CYGWIN*) cygwin=1; win32=1 ;; - MINGW*) msys=1; win32=1 ;; - MSYS*) msys=1; win32=1 ;; - OpenBSD) openbsd=1; bsd=1 ;; - FreeBSD) freebsd=1; bsd=1 ;; - NetBSD) netbsd=1; bsd=1 ;; - *) bsd=1 ;; -esac - -# special handling to rewrite cygwin/msys paths to windows POSIX paths -if [ -n "$win32" ] && command -v cygpath >/dev/null; then - _have_cygpath=1 -fi - -if command -v gawk >/dev/null; then - _awk=gawk -elif command -v nawk >/dev/null; then - _awk=nawk -elif command -v mawk >/dev/null; then - _awk=mawk -elif [ -x /usr/xpg4/bin/awk ]; then - _awk=/usr/xpg4/bin/awk -elif command -v awk >/dev/null; then - _awk=awk -else - echo "ERROR: No awk found!" >&2 - quit 1 -fi - -if command -v gsed >/dev/null; then - _sed=gsed -elif [ -x /usr/xpg4/bin/sed ]; then - _sed=/usr/xpg4/bin/sed -elif command -v sed >/dev/null; then - _sed=sed -else - echo "ERROR: No sed found!" >&2 - quit 1 -fi - -if command -v ggrep >/dev/null; then - _grep=ggrep -elif [ -x /usr/xpg4/bin/grep ]; then - _grep=/usr/xpg4/bin/grep -elif command -v grep >/dev/null; then - _grep=grep -else - echo "ERROR: No grep found!" >&2 - quit 1 -fi - -# check that grep -Eq works -if [ -z "$(echo foo | "$_grep" -Eq foo >/dev/null 2>&1)" -a $? -eq 0 ]; then - _have_grep_E_q=1 -fi - -if command -v ghead >/dev/null; then - _head=ghead -else - _head=head -fi - -if [ "$(echo xx | head -n 1 2>/dev/null)" = "xx" ]; then - _head_syntax=new -else - if ! head -1 -- "$0" >/dev/null 2>&1; then - _head_no_double_dash=1 - fi -fi - -# this is compatible with osed -ANSI_RE='\[[;?]*[0-9.;]*[A-Za-z]' - . "$project_dir/inc/vimpager_functions.sh" . "$project_dir/inc/common_functions.sh" # INCLUDE BUNDLED SCRIPTS HERE # END OF BUNDLED SCRIPTS +set_system_vars +check_for_cygpath +select_awk_executable +select_sed_executable +select_grep_executable +check_for_grep_q +select_head_executable +select_head_syntax + main "$@" # Copyright (c) 2016, Rafael Kitover and From 6e6de159b9baae672f2436006095ed661fc41382 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 29 Jun 2016 03:08:46 +0200 Subject: [PATCH 08/18] Move further code from vimcat into functions --- inc/vimcat_functions.sh | 226 ++++++++++++++++++++++++++++++++++++++++ vimcat | 215 ++------------------------------------ 2 files changed, 233 insertions(+), 208 deletions(-) diff --git a/inc/vimcat_functions.sh b/inc/vimcat_functions.sh index 07d0365..f865147 100644 --- a/inc/vimcat_functions.sh +++ b/inc/vimcat_functions.sh @@ -90,4 +90,230 @@ start_highlight_job() { fi } +select_vim_executable() { + if command -v vim >/dev/null; then + vim=vim + elif command -v nvim >/dev/null; then + vim=nvim + else + echo "$0: neither vim nor nvim found, vim or nvim is required for vimcat" >&2 + exit 1 + fi +} + +parse_command_line_options_1() { + # if no args and no stdin, display usage + if [ $# -eq 0 -a -t 0 ]; then + usage + quit 0 + fi + + # check for -h before main option parsing, this is much faster + for arg in "$@"; do + case "$arg" in + "-h"|"--help"|"-help"|"--usage"|"-usage") + usage + quit 0 + ;; + "-v"|"--version"|"-version") + echo "vimcat $version" + quit 0 + ;; + "-x") + set -x + ;; + esac + done +} + +find_tmp_directory() { + tmp_dir=/tmp + mkdir_options="-m 700" + + case "$(uname -s)" in + MINGW*|MSYS*) + if [ -n "$temp" ]; then + # MSYS2 is a little tricky, we're gonna stick to the user's private temp + # the -m mode switch to mkdir doesn't work + tmp_dir=$(cygpath --unix "$temp") + mkdir_options= + fi + ;; + esac + + tmp_dir=$tmp_dir/vimcat_$$ +} + +create_tmp_directory() { + if ! mkdir $mkdir_options "$tmp_dir"; then + echo "Could not create temporary directory $tmp_dir" >&2 + exit 1 + fi +} + +install_trap() { + trap 'quit 1' PIPE HUP INT QUIT ILL TRAP KILL BUS TERM +} + +create_fifo() { + tmp_file_in=$tmp_dir/vimcat_in.txt + out_fifo=$tmp_dir/vimcat_out.fifo + + case $(uname -s) in + SunOS*|CYGWIN*|MINGW*|MSYS*) + # the fifo streaming doesn't work on windows and solaris + touch "$out_fifo" + ;; + *) + mkfifo "$out_fifo" + ;; + esac +} + +main() { + # check for arguments + while [ $# -gt 0 ] ; do + case "$1" in + "-c") + shift + if [ -z "$extra_c" ]; then + extra_c=$1 + else + extra_c="$extra_c | $1" + fi + shift + ;; + "--cmd") + shift + if [ -z "$extra_cmd" ]; then + extra_cmd=$1 + else + extra_cmd="$extra_cmd | $1" + fi + shift + ;; + "-u") + shift + vimcatrc=$1 + shift + ;; + "-o") + shift + output_file=$1 + shift + ;; + "-s") + shift + squeeze_blank_lines=1 + ;; + "-n") + shift + line_numbers=1 + ;; + "-x") + # xtrace should already be set by the first option parsing + shift + ;; + "--") + shift + break + ;; + -) + break + ;; + -*) + echo "$0: bad option '$1', see --help for usage." >&2 + quit 1 + ;; + *) + break + ;; + esac + done + + # Just pass through if not on a tty, unless -o was given + if [ -z "$output_file" ]; then + if [ ! -t 1 ]; then + exec cat "$@" + fi + fi + + if [ -z "$vimcatrc" ]; then + if [ -f ~/.vimcatrc ]; then + vimcatrc=~/.vimcatrc + else + vimcatrc= + fi + fi + + if [ $# -eq 0 ]; then + set -- - + fi + + if [ -n "$output_file" -a $# -gt 1 ]; then + echo "$0: -o can only be used with one input file or stdin." >&2 + quit 1 + fi + + chunks_dir=$tmp_dir/chunks + mkdir "$chunks_dir" + + i=1 + for file in "$@" + do + if [ $# -ge 2 ]; then + if [ $i -gt 1 ]; then + printf '\n' + fi + printf "==> %s <==\n\n" "$file" + fi + + pipeline= + pipeline_start=$file + + if [ "${squeeze_blank_lines:-0}" -eq 1 ]; then + pipeline=squeeze_blank_lines + fi + + exit_code=0 + + # Check that the file is readable + if [ "$file" != - ]; then + if [ ! -r "$file" ]; then + echo "$0: Cannot read file: $file" >&2 + exit_code=1 + fi + + [ ! -s "$file" ] && continue + fi + + if [ -z "$output_file" -o "$output_file" = "-" ]; then + dest_file=$out_fifo + + tail -f "$out_fifo" & + tail_pid=$! + else + dest_file=$output_file + printf '' > "$dest_file" + fi + + start_highlight_job + start_pipeline + while [ ! -f "$tmp_dir/vim_done" ]; do + do_sleep 50 + done + + if [ -n "$tail_pid" ]; then + # if it's not a fifo where this doesn't work, tail needs some time to catch up + [ ! -p "$out_fifo" ] && do_sleep 1100 + + kill $tail_pid >/dev/null 2>&1 + fi + + i=$((i + 1)) + done + + quit $exit_code +} + # vim: sw=4 et tw=0: diff --git a/vimcat b/vimcat index a8be296..81afea3 100755 --- a/vimcat +++ b/vimcat @@ -24,217 +24,16 @@ project_dir=`dirname "$link"` version="$(cd "$project_dir" && git describe 2>/dev/null) (git)" || version="$version_tag (checkout)" runtime=$project_dir -if command -v vim >/dev/null; then - vim=vim -elif command -v nvim >/dev/null; then - vim=nvim -else - echo "$0: neither vim nor nvim found, vim or nvim is required for vimcat" >&2 - exit 1 -fi - . "$project_dir/inc/vimcat_functions.sh" . "$project_dir/inc/common_functions.sh" -# if no args and stdin is on a terminal, pretend we're cat and wait on stdin. -if [ $# -eq 0 -a -t 0 ]; then - exec cat -fi - -# check for -h before main option parsing, this is much faster -for arg in "$@"; do - case "$arg" in - "-h"|"--help"|"-help"|"--usage"|"-usage") - usage - quit 0 - ;; - "-v"|"--version"|"-version") - echo "vimcat $version" - quit 0 - ;; - "-x") - set -x - ;; - esac -done - -tmp_dir=/tmp -mkdir_options="-m 700" - -case "$(uname -s)" in - MINGW*|MSYS*) - if [ -n "$temp" ]; then - # MSYS2 is a little tricky, we're gonna stick to the user's private temp - # the -m mode switch to mkdir doesn't work - tmp_dir=$(cygpath --unix "$temp") - mkdir_options= - fi - ;; -esac - -tmp_dir=$tmp_dir/vimcat_$$ - -if ! mkdir $mkdir_options "$tmp_dir"; then - echo "Could not create temporary directory $tmp_dir" >&2 - exit 1 -fi - -trap 'quit 1' PIPE HUP INT QUIT ILL TRAP KILL BUS TERM -tmp_file_in=$tmp_dir/vimcat_in.txt -out_fifo=$tmp_dir/vimcat_out.fifo - -case $(uname -s) in - SunOS*|CYGWIN*|MINGW*|MSYS*) - # the fifo streaming doesn't work on windows and solaris - touch "$out_fifo" - ;; - *) - mkfifo "$out_fifo" - ;; -esac - -# check for arguments -while [ $# -gt 0 ] ; do - case "$1" in - "-c") - shift - if [ -z "$extra_c" ]; then - extra_c=$1 - else - extra_c="$extra_c | $1" - fi - shift - ;; - "--cmd") - shift - if [ -z "$extra_cmd" ]; then - extra_cmd=$1 - else - extra_cmd="$extra_cmd | $1" - fi - shift - ;; - "-u") - shift - vimcatrc=$1 - shift - ;; - "-o") - shift - output_file=$1 - shift - ;; - "-s") - shift - squeeze_blank_lines=1 - ;; - "-n") - shift - line_numbers=1 - ;; - "-x") - # xtrace should already be set by the first option parsing - shift - ;; - "--") - shift - break - ;; - -) - break - ;; - -*) - echo "$0: bad option '$1', see --help for usage." >&2 - quit 1 - ;; - *) - break - ;; - esac -done - -# Just pass through if not on a tty, unless -o was given -if [ -z "$output_file" ]; then - if [ ! -t 1 ]; then - exec cat "$@" - fi -fi - -if [ -z "$vimcatrc" ]; then - if [ -f ~/.vimcatrc ]; then - vimcatrc=~/.vimcatrc - else - vimcatrc= - fi -fi - -if [ $# -eq 0 ]; then - set -- - -fi - -if [ -n "$output_file" -a $# -gt 1 ]; then - echo "$0: -o can only be used with one input file or stdin." >&2 - quit 1 -fi - -chunks_dir=$tmp_dir/chunks -mkdir "$chunks_dir" - -i=1 -for file in "$@" -do - if [ $# -ge 2 ]; then - if [ $i -gt 1 ]; then - printf '\n' - fi - printf "==> %s <==\n\n" "$file" - fi - - pipeline= - pipeline_start=$file - - if [ "${squeeze_blank_lines:-0}" -eq 1 ]; then - pipeline=squeeze_blank_lines - fi - - exit_code=0 - - # Check that the file is readable - if [ "$file" != - ]; then - if [ ! -r "$file" ]; then - echo "$0: Cannot read file: $file" >&2 - exit_code=1 - fi - - [ ! -s "$file" ] && continue - fi - - if [ -z "$output_file" -o "$output_file" = "-" ]; then - dest_file=$out_fifo - - tail -f "$out_fifo" & - tail_pid=$! - else - dest_file=$output_file - printf '' > "$dest_file" - fi - - start_highlight_job - start_pipeline - while [ ! -f "$tmp_dir/vim_done" ]; do - do_sleep 50 - done - - if [ -n "$tail_pid" ]; then - # if it's not a fifo where this doesn't work, tail needs some time to catch up - [ ! -p "$out_fifo" ] && do_sleep 1100 - - kill $tail_pid >/dev/null 2>&1 - fi - - i=$((i + 1)) -done +select_vim_executable +parse_command_line_options_1 "$@" +find_tmp_directory +create_tmp_directory +install_trap +create_fifo -quit $exit_code +main "$@" # vim: sw=4 et ft=sh From c7179f64ead8351c8c19f9ea5ecb530d41392aa9 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 29 Jun 2016 09:33:40 +0200 Subject: [PATCH 09/18] Rename $tmp_dir to $tmp in vimcat --- inc/vimcat_functions.sh | 30 +++++++++++++++--------------- test/vimcat-functions.bats | 10 +++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/inc/vimcat_functions.sh b/inc/vimcat_functions.sh index f865147..06fb681 100644 --- a/inc/vimcat_functions.sh +++ b/inc/vimcat_functions.sh @@ -14,9 +14,9 @@ quit() { do_sleep 100 kill -9 "$tail_pid" >/dev/null 2>&1 - cd "${tmp_dir%/*}" 2>/dev/null # some systems cannot remove CWD + cd "${tmp%/*}" 2>/dev/null # some systems cannot remove CWD - rm -rf "$tmp_dir" 2>/dev/null # rm -rf "" shows error on OpenBSD + rm -rf "$tmp" 2>/dev/null # rm -rf "" shows error on OpenBSD ) & exit "$@" } @@ -65,8 +65,8 @@ start_pipeline() { else pipeline=write_chunks fi - cat -- "$pipeline_start" | (eval "$pipeline" <&3 & echo $! > "$tmp_dir/pipeline_pid") 3<&0 - pipeline_pid=$(cat "$tmp_dir/pipeline_pid") + cat -- "$pipeline_start" | (eval "$pipeline" <&3 & echo $! > "$tmp/pipeline_pid") 3<&0 + pipeline_pid=$(cat "$tmp/pipeline_pid") } start_highlight_job() { @@ -82,11 +82,11 @@ start_highlight_job() { [ -n "$vimcatrc" ] && set -- "$@" -u "$vimcatrc" if [ "${VIMCAT_DEBUG:-0}" -eq 0 ]; then - ("$vim" "$@" /dev/null 2>&1; touch "$tmp_dir/vim_done") & + ("$vim" "$@" /dev/null 2>&1; touch "$tmp/vim_done") & vim_pid=$! else "$vim" "$@" &2 + if ! mkdir $mkdir_options "$tmp"; then + echo "Could not create temporary directory $tmp" >&2 exit 1 fi } @@ -156,8 +156,8 @@ install_trap() { } create_fifo() { - tmp_file_in=$tmp_dir/vimcat_in.txt - out_fifo=$tmp_dir/vimcat_out.fifo + tmp_file_in=$tmp/vimcat_in.txt + out_fifo=$tmp/vimcat_out.fifo case $(uname -s) in SunOS*|CYGWIN*|MINGW*|MSYS*) @@ -255,7 +255,7 @@ main() { quit 1 fi - chunks_dir=$tmp_dir/chunks + chunks_dir=$tmp/chunks mkdir "$chunks_dir" i=1 @@ -299,7 +299,7 @@ main() { start_highlight_job start_pipeline - while [ ! -f "$tmp_dir/vim_done" ]; do + while [ ! -f "$tmp/vim_done" ]; do do_sleep 50 done diff --git a/test/vimcat-functions.bats b/test/vimcat-functions.bats index 5842016..2fde1fa 100644 --- a/test/vimcat-functions.bats +++ b/test/vimcat-functions.bats @@ -14,12 +14,12 @@ load helpers } @test 'quit cleans up the $tmp direcotry' { - tmp_dir=$BATS_TMPDIR/quit-test - mkdir "$tmp_dir" - touch "$tmp_dir/some-file" + tmp=$BATS_TMPDIR/quit-test + mkdir "$tmp" + touch "$tmp/some-file" run quit 1 - [[ ! -e "$tmp_dir/some-file" ]] - [[ ! -e "$tmp_dir" ]] + [[ ! -e "$tmp/some-file" ]] + [[ ! -e "$tmp" ]] } @test 'quit kills $vim_pid, $pipeline_pid and $tail_pid' { From 04d74c60b5aaacf455ef7ced91794dca3a441fb1 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 29 Jun 2016 09:46:28 +0200 Subject: [PATCH 10/18] Unify create_tmp_directory() --- inc/common_functions.sh | 8 ++++++++ inc/vimcat_functions.sh | 7 ------- inc/vimpager_functions.sh | 6 ++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/inc/common_functions.sh b/inc/common_functions.sh index 7958d1b..c41bb09 100644 --- a/inc/common_functions.sh +++ b/inc/common_functions.sh @@ -7,4 +7,12 @@ squeeze_blank_lines() { }' } +create_tmp_directory() { + if ! mkdir $mkdir_options "$tmp"; then + echo "ERROR: Could not create temporary directory $tmp" >&2 + rm -rf "$tmp" 2>/dev/null # rm -rf "" shows error on OpenBSD + exit 1 + fi +} + # vim: sw=4 et tw=0: diff --git a/inc/vimcat_functions.sh b/inc/vimcat_functions.sh index 06fb681..c5bd4ae 100644 --- a/inc/vimcat_functions.sh +++ b/inc/vimcat_functions.sh @@ -144,13 +144,6 @@ find_tmp_directory() { tmp=$tmp/vimcat_$$ } -create_tmp_directory() { - if ! mkdir $mkdir_options "$tmp"; then - echo "Could not create temporary directory $tmp" >&2 - exit 1 - fi -} - install_trap() { trap 'quit 1' PIPE HUP INT QUIT ILL TRAP KILL BUS TERM } diff --git a/inc/vimpager_functions.sh b/inc/vimpager_functions.sh index 7806931..8b2b48c 100644 --- a/inc/vimpager_functions.sh +++ b/inc/vimpager_functions.sh @@ -80,6 +80,8 @@ main() { find_tmp_directory + create_tmp_directory + trap "quit 1" PIPE HUP INT QUIT ILL TRAP KILL BUS TERM detect_term_size @@ -254,10 +256,6 @@ find_tmp_directory() { # Create a safe directory in which we place all other tempfiles. tmp=$tmp/vimpager_$$ - if ! mkdir $mkdir_options "$tmp"; then - echo "ERROR: Could not create temporary directory $tmp" >&2 - quit 1 - fi } detect_term_size() { From ec397c7c493826c2b03280044b0d27c3370272a2 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 29 Jun 2016 09:56:11 +0200 Subject: [PATCH 11/18] Unify system detection --- inc/common_functions.sh | 19 +++++++++++++++++++ inc/vimcat_functions.sh | 35 ++++++++++++----------------------- inc/vimpager_functions.sh | 17 +---------------- vimcat | 1 + 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/inc/common_functions.sh b/inc/common_functions.sh index c41bb09..8e07358 100644 --- a/inc/common_functions.sh +++ b/inc/common_functions.sh @@ -15,4 +15,23 @@ create_tmp_directory() { fi } +set_system_vars() { + case "$(uname -s)" in + Linux) linux=1;; + SunOS) solaris=1;; + Darwin) osx=1 bsd=1;; + CYGWIN*) cygwin=1 win32=1;; + MINGW*) msys=1 win32=1;; + MSYS*) msys=1 win32=1;; + OpenBSD) openbsd=1 bsd=1;; + FreeBSD) freebsd=1 bsd=1;; + NetBSD) netbsd=1 bsd=1;; + *) bsd=1;; + esac +} + +install_trap() { + trap 'quit 1' PIPE HUP INT QUIT ILL TRAP KILL BUS TERM +} + # vim: sw=4 et tw=0: diff --git a/inc/vimcat_functions.sh b/inc/vimcat_functions.sh index c5bd4ae..75b7f08 100644 --- a/inc/vimcat_functions.sh +++ b/inc/vimcat_functions.sh @@ -130,37 +130,26 @@ find_tmp_directory() { tmp=/tmp mkdir_options="-m 700" - case "$(uname -s)" in - MINGW*|MSYS*) - if [ -n "$temp" ]; then - # MSYS2 is a little tricky, we're gonna stick to the user's private temp - # the -m mode switch to mkdir doesn't work - tmp=$(cygpath --unix "$temp") - mkdir_options= - fi - ;; - esac + if [ -n "$msys" -a -n "$temp" ]; then + # MSYS2 is a little tricky, we're gonna stick to the user's private temp + # the -m mode switch to mkdir doesn't work + tmp=$(cygpath --unix "$temp") + mkdir_options= + fi tmp=$tmp/vimcat_$$ } -install_trap() { - trap 'quit 1' PIPE HUP INT QUIT ILL TRAP KILL BUS TERM -} - create_fifo() { tmp_file_in=$tmp/vimcat_in.txt out_fifo=$tmp/vimcat_out.fifo - case $(uname -s) in - SunOS*|CYGWIN*|MINGW*|MSYS*) - # the fifo streaming doesn't work on windows and solaris - touch "$out_fifo" - ;; - *) - mkfifo "$out_fifo" - ;; - esac + if [ -n "$solaris" -o -n "$win32" ]; then + # the fifo streaming doesn't work on windows and solaris + touch "$out_fifo" + else + mkfifo "$out_fifo" + fi } main() { diff --git a/inc/vimpager_functions.sh b/inc/vimpager_functions.sh index 8b2b48c..4f69ee6 100644 --- a/inc/vimpager_functions.sh +++ b/inc/vimpager_functions.sh @@ -82,7 +82,7 @@ main() { create_tmp_directory - trap "quit 1" PIPE HUP INT QUIT ILL TRAP KILL BUS TERM + install_trap detect_term_size @@ -818,21 +818,6 @@ fits_on_screen() { ' num_files=$# total_lines=$lines total_cols=$cols file_sep_lines=3 first_file_sep_lines=2 - } -set_system_vars() { - case "$(uname -s)" in - Linux) linux=1 ;; - SunOS) solaris=1 ;; - Darwin) osx=1; bsd=1 ;; - CYGWIN*) cygwin=1; win32=1 ;; - MINGW*) msys=1; win32=1 ;; - MSYS*) msys=1; win32=1 ;; - OpenBSD) openbsd=1; bsd=1 ;; - FreeBSD) freebsd=1; bsd=1 ;; - NetBSD) netbsd=1; bsd=1 ;; - *) bsd=1 ;; - esac -} - check_for_cygpath() { # special handling to rewrite cygwin/msys paths to windows POSIX paths if [ -n "$win32" ] && command -v cygpath >/dev/null; then diff --git a/vimcat b/vimcat index 81afea3..6e5a4e8 100755 --- a/vimcat +++ b/vimcat @@ -27,6 +27,7 @@ runtime=$project_dir . "$project_dir/inc/vimcat_functions.sh" . "$project_dir/inc/common_functions.sh" +set_system_vars select_vim_executable parse_command_line_options_1 "$@" find_tmp_directory From 110cb364accf6f147c7070eb94522b33113bee7e Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 29 Jun 2016 10:16:29 +0200 Subject: [PATCH 12/18] Unify find_tmp_directory() --- inc/common_functions.sh | 38 ++++++++++++++++++++++++++++++++++ inc/vimcat_functions.sh | 17 +++------------ inc/vimpager_functions.sh | 40 +++--------------------------------- test/common-functions.bats | 6 ++++++ test/vimpager-functions.bats | 6 ------ 5 files changed, 50 insertions(+), 57 deletions(-) diff --git a/inc/common_functions.sh b/inc/common_functions.sh index 8e07358..1d8c80c 100644 --- a/inc/common_functions.sh +++ b/inc/common_functions.sh @@ -34,4 +34,42 @@ install_trap() { trap 'quit 1' PIPE HUP INT QUIT ILL TRAP KILL BUS TERM } +check_for_cygpath() { + # special handling to rewrite cygwin/msys paths to windows POSIX paths + if [ -n "$win32" ] && command -v cygpath >/dev/null; then + _have_cygpath=1 + fi +} + +resolve_path() { + if [ -n "$_have_cygpath" ]; then + cygpath --unix "$1" + else + echo "$1" + fi +} + +find_tmp_directory() { + # Find and create the temporary directory used by vimpager. Set the $tmp and $mkdir_options variable. + mkdir_options='-m 700' + # Default to /tmp + tmp=/tmp + + if [ -n "$win32" ]; then + # Use the real TEMP directory on windows in case we are + # using a native vim/gvim + # TEMP can be /tmp sometimes too + tmp=$(resolve_path "$TEMP") + if [ -n "$msys" -a -n "$temp" ]; then + # MSYS2 is a little tricky, we're gonna stick to the user's private temp + tmp=$(resolve_path "$temp") + fi + # chmod doesn't work here, even in /tmp sometimes + mkdir_options= + fi + + # Add a final component to the path, all other temp files should be placed in this directory. + tmp=$tmp/${prog}_$$ +} + # vim: sw=4 et tw=0: diff --git a/inc/vimcat_functions.sh b/inc/vimcat_functions.sh index 75b7f08..16dcf8c 100644 --- a/inc/vimcat_functions.sh +++ b/inc/vimcat_functions.sh @@ -1,5 +1,8 @@ # Function definitions for vimcat. +# the name of this program +prog=vimcat + quit() { ( kill "$vim_pid" >/dev/null 2>&1 @@ -126,20 +129,6 @@ parse_command_line_options_1() { done } -find_tmp_directory() { - tmp=/tmp - mkdir_options="-m 700" - - if [ -n "$msys" -a -n "$temp" ]; then - # MSYS2 is a little tricky, we're gonna stick to the user's private temp - # the -m mode switch to mkdir doesn't work - tmp=$(cygpath --unix "$temp") - mkdir_options= - fi - - tmp=$tmp/vimcat_$$ -} - create_fifo() { tmp_file_in=$tmp/vimcat_in.txt out_fifo=$tmp/vimcat_out.fifo diff --git a/inc/vimpager_functions.sh b/inc/vimpager_functions.sh index 4f69ee6..4de6475 100644 --- a/inc/vimpager_functions.sh +++ b/inc/vimpager_functions.sh @@ -1,5 +1,8 @@ # Function definitions for vimpager. +# the name of this program +prog=vimpager + # this is compatible with osed ANSI_RE='\[[;?]*[0-9.;]*[A-Za-z]' @@ -236,28 +239,6 @@ main() { quit $? } -find_tmp_directory() { - # Find and create the temporary directory used by vimpager. Set the $tmp variable. - mkdir_options="-m 700" - - if [ -n "$win32" ]; then - # Use the real TEMP directory on windows in case we are - # using a native vim/gvim - # TEMP can be /tmp sometimes too - - tmp=$(resolve_path "$TEMP") - - # chmod doesn't work here, even in /tmp sometimes - mkdir_options= - else - # ... and /tmp otherwise - tmp=/tmp - fi - - # Create a safe directory in which we place all other tempfiles. - tmp=$tmp/vimpager_$$ -} - detect_term_size() { # Detect the terminal size and set the variables $cols and $lines. If necessary $no_pass_thru is set. if command -v tput >/dev/null; then @@ -541,14 +522,6 @@ expand_config_vars() { eval system_vimpagerrc=\"$system_vimpagerrc\" } -resolve_path() { - if [ -n "$_have_cygpath" ]; then - cygpath -w "$1" | tr '\\' '/' - else - echo "$1" - fi -} - quit() { rm -f gvim.exe.stackdump # for a cygwin bug cd "${tmp%/*}" 2>/dev/null # some systems cannot remove CWD @@ -818,13 +791,6 @@ fits_on_screen() { ' num_files=$# total_lines=$lines total_cols=$cols file_sep_lines=3 first_file_sep_lines=2 - } -check_for_cygpath() { - # special handling to rewrite cygwin/msys paths to windows POSIX paths - if [ -n "$win32" ] && command -v cygpath >/dev/null; then - _have_cygpath=1 - fi -} - select_awk_executable() { if command -v gawk >/dev/null; then _awk=gawk diff --git a/test/common-functions.bats b/test/common-functions.bats index 6746479..05af7aa 100644 --- a/test/common-functions.bats +++ b/test/common-functions.bats @@ -32,4 +32,10 @@ load helpers [[ "${lines[5]}" = ' ' ]] [[ "${lines[6]}" = 'last line' ]] } + +@test 'find_tmp_directory sets $tmp' { + [[ -z "$tmp" ]] + find_tmp_directory + [[ "$tmp" = /* ]] +} # vim: filetype=sh et sw=4 sts=4 : diff --git a/test/vimpager-functions.bats b/test/vimpager-functions.bats index 39620e6..2f6d87a 100644 --- a/test/vimpager-functions.bats +++ b/test/vimpager-functions.bats @@ -4,12 +4,6 @@ load helpers . "$src/inc/vimpager_functions.sh" -@test 'find_tmp_directory sets $tmp' { - [[ -z "$tmp" ]] - find_tmp_directory - [[ "$tmp" = /* ]] -} - @test 'detect_term_size sets $cols and $lines' { # detect_term_size will write files to $tmp (assuming it is a direcotry) tmp=$BATS_TMPDIR From c9db96b4a43dc51c0fdbf6b505843e47607517a1 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 29 Jun 2016 10:26:56 +0200 Subject: [PATCH 13/18] Add test for set_system_vars() --- test/common-functions.bats | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/common-functions.bats b/test/common-functions.bats index 05af7aa..c2b0819 100644 --- a/test/common-functions.bats +++ b/test/common-functions.bats @@ -38,4 +38,14 @@ load helpers find_tmp_directory [[ "$tmp" = /* ]] } + +@test "set_system_vars sets at least one system variable" { + [[ -z "$linux" && -z "$solaris" && -z "$osx" && -z "$bsd" && \ + -z "$cygwin" && -z "$win32" && -z "$msys" && -z "$openbsd" && \ + -z "$freebsd" && -z "$netbsd" ]] + set_system_vars + [[ "$linux" -eq 1 || "$solaris" -eq 1 || "$osx" -eq 1 || "$bsd" -eq 1 || \ + "$cygwin" -eq 1 || "$win32" -eq 1 || "$msys" -eq 1 || \ + "$openbsd" -eq 1 || "$freebsd" -eq 1 || "$netbsd" -eq 1 ]] +} # vim: filetype=sh et sw=4 sts=4 : From ea1240ac3944b9c201f4e15416364452440ca6bf Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Wed, 29 Jun 2016 16:37:35 +0200 Subject: [PATCH 14/18] Set language to generic for travis The project language is set to "generic" because the ruby specific setup is not needed. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 68d910d..49b9f9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +language: generic sudo: required dist: trusty From ade017b9a839ec581822f88f338a0e13e74c73dd Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Wed, 29 Jun 2016 15:22:31 -0400 Subject: [PATCH 15/18] remove CRs more portably in tests Use tr -d '\015' to remove CRs instead of sed 's/\r//', many versions of sed do not understand \r. --- test/vimcat-functions.bats | 2 +- test/vimpager-functions.bats | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/vimcat-functions.bats b/test/vimcat-functions.bats index 2fde1fa..86040f6 100644 --- a/test/vimcat-functions.bats +++ b/test/vimcat-functions.bats @@ -39,7 +39,7 @@ load helpers @test "usage prints the help message" { run usage - [[ "$output" = "$(sed 's/\r//' "$fixtures/vimcat-help.txt")" ]] + [[ "$output" = "$(tr -d '\015' < "$fixtures/vimcat-help.txt")" ]] status_ok } diff --git a/test/vimpager-functions.bats b/test/vimpager-functions.bats index 2f6d87a..4aa62e2 100644 --- a/test/vimpager-functions.bats +++ b/test/vimpager-functions.bats @@ -53,9 +53,8 @@ load helpers } @test "usage prints the help message" { - unset -f sed run usage - [[ "$output" = "$(sed 's/\r//' "$fixtures/vimpager-help.txt")" ]] + [[ "$output" = "$(tr -d '\015' < "$fixtures/vimpager-help.txt")" ]] status_ok } # vim: filetype=sh et sw=4 sts=4 : From 6f4f74aa7e440c23e48fb88ec19b7830687e2205 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Wed, 29 Jun 2016 13:59:54 -0400 Subject: [PATCH 16/18] fix weird test fail on OpenBSD In quit() for both vimpager and vimcat, change `exit "$@"` to `exit "${1:-0}"` so that the default is zero explicitly and quit() doesn't fail if called with more than one argument. For some reason on OpenBSD `quit` for vimpager was returning 1. --- inc/vimcat_functions.sh | 2 +- inc/vimpager_functions.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/vimcat_functions.sh b/inc/vimcat_functions.sh index 16dcf8c..889a17c 100644 --- a/inc/vimcat_functions.sh +++ b/inc/vimcat_functions.sh @@ -21,7 +21,7 @@ quit() { rm -rf "$tmp" 2>/dev/null # rm -rf "" shows error on OpenBSD ) & - exit "$@" + exit "${1:-0}" } do_sleep() { diff --git a/inc/vimpager_functions.sh b/inc/vimpager_functions.sh index 4de6475..b92d72a 100644 --- a/inc/vimpager_functions.sh +++ b/inc/vimpager_functions.sh @@ -526,7 +526,7 @@ quit() { rm -f gvim.exe.stackdump # for a cygwin bug cd "${tmp%/*}" 2>/dev/null # some systems cannot remove CWD rm -rf "$tmp" 2>/dev/null # rm -rf "" shows error on OpenBSD - exit "$@" + exit "${1:-0}" } usage() { From 6e99b90fd5a345f46616469e0123fdd1b2dcf185 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Thu, 30 Jun 2016 10:19:05 +0200 Subject: [PATCH 17/18] Test `make install` on travis --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 49b9f9b..df89971 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,5 +29,12 @@ script: - lintian --profile debian -i --fail-on-warnings -EvIL +pedantic ../vimpager*.changes - make all - make test + - | + set -e + sudo make install + [[ "$(which vimpager)" == /usr/local/bin/vimpager ]] + [[ "$(which vimcat)" == /usr/local/bin/vimcat ]] + vimpager -v + vimcat -v # vim: sw=4 From a8648e618fc95ebc5a47ac184a608d58734b9890 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Thu, 30 Jun 2016 10:37:02 +0200 Subject: [PATCH 18/18] Clean up sed commands in the makefile --- Makefile | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 4cff0c2..5a632f1 100644 --- a/Makefile +++ b/Makefile @@ -46,23 +46,23 @@ standalone/vimpager: vimpager vimpager-version.txt ${SRC:=.uu} inc/bundled_scrip @echo building $@ @${MKPATH} ${@D} @sed \ - -e '/^ *\. .*inc\/prologue.sh"$$/{' \ + -e '/^\. .*inc\/prologue.sh"$$/{' \ -e 'r inc/prologue.sh' \ -e d \ -e '}' \ - -e '/^ *\. .*inc\/vimpager_functions.sh"$$/{' \ + -e '/^\. .*inc\/vimpager_functions.sh"$$/{' \ -e 'r inc/vimpager_functions.sh' \ -e d \ -e '}' \ - -e '/^ *\. .*inc\/common_functions.sh"$$/{' \ + -e '/^\. .*inc\/common_functions.sh"$$/{' \ -e 'r inc/common_functions.sh' \ -e d \ -e '}' \ -e 's/^\( *\)# EXTRACT BUNDLED SCRIPTS HERE$$/\1extract_bundled_scripts/' \ - -e 's|^version=.*|version="'"`cat vimpager-version.txt`"' (standalone, shell=\$$(command -v \$$POSIX_SHELL))"|' \ - -e 's!^\( *\)runtime=.*$$!\1runtime='\''\$$tmp/runtime'\''!' \ - -e 's!^\( *\)vimcat=.*$$!\1vimcat='\''\$$runtime/bin/vimcat'\''!' \ - -e 's!^\( *\)system_vimpagerrc=.*$$!\1system_vimpagerrc='\'\''!' \ + -e 's!^version=.*!version="'"`cat vimpager-version.txt`"' (standalone, shell=\$$(command -v \$$POSIX_SHELL))"!' \ + -e 's!^runtime=.*$$!runtime='\''\$$tmp/runtime'\''!' \ + -e 's!^vimcat=.*$$!vimcat='\''\$$runtime/bin/vimcat'\''!' \ + -e 's!^system_vimpagerrc=.*$$!system_vimpagerrc='\'\''!' \ -e '/^# INCLUDE BUNDLED SCRIPTS HERE$$/{ q; }' \ vimpager > $@ @cat inc/do_uudecode.sh >> $@ @@ -87,11 +87,11 @@ standalone/vimcat: vimcat autoload/vimcat.vim inc/prologue.sh inc/vimcat_functio -e 'r inc/prologue.sh' \ -e d \ -e '}' \ - -e '/^ *\. .*inc\/vimcat_functions.sh"$$/{' \ + -e '/^\. .*inc\/vimcat_functions.sh"$$/{' \ -e 'r inc/vimcat_functions.sh' \ -e d \ -e '}' \ - -e '/^ *\. .*inc\/common_functions.sh"$$/{' \ + -e '/^\. .*inc\/common_functions.sh"$$/{' \ -e 'r inc/common_functions.sh' \ -e d \ -e '}' \ @@ -111,15 +111,15 @@ vimcat.uu: vimcat vimcat-version.txt inc/vimcat_functions.sh inc/common_function @printf "\t(cat <<'EOF') | do_uudecode > bin/vimcat\n" >> $@ @sed \ -e 's|^version=.*|version="'"`cat vimcat-version.txt`"' (bundled, shell=\$$(command -v \$$POSIX_SHELL))"|' \ - -e '/^ *\. .*inc\/prologue.sh"$$/{' \ + -e '/^\. .*inc\/prologue.sh"$$/{' \ -e 'r inc/prologue.sh' \ -e d \ -e '}' \ - -e '/^ *\. .*inc\/vimcat_functions.sh"$$/{' \ + -e '/^\. .*inc\/vimcat_functions.sh"$$/{' \ -e 'r inc/vimcat_functions.sh' \ -e d \ -e '}' \ - -e '/^ *\. .*inc\/common_functions.sh"$$/{' \ + -e '/^\. .*inc\/common_functions.sh"$$/{' \ -e 'r inc/common_functions.sh' \ -e d \ -e '}' \ @@ -212,14 +212,14 @@ install: docs vimpager.configured vimcat.configured -e '/^ *\. .*inc\/prologue.sh"$$/d' \ -e 's|^version=.*|version="'"`cat $$BASE-version.txt`"' (configured, shell='"$$POSIX_SHELL"')"|' \ -e '/^# FIND REAL PARENT DIRECTORY$$/,/^# END OF FIND REAL PARENT DIRECTORY$$/d' \ - -e 's!^\( *\)runtime=.*!\1runtime='\''${PREFIX}/share/vimpager'\''!' \ - -e 's!^\( *\)vimcat=.*!\1vimcat='\''${PREFIX}/bin/vimcat'\''!' \ - -e 's!^\( *\)system_vimpagerrc=.*!\1system_vimpagerrc='\'"$$vimpagerrc"\''!' \ + -e 's!^runtime=.*!runtime='\''${PREFIX}/share/vimpager'\''!' \ + -e 's!^vimcat=.*!vimcat='\''${PREFIX}/bin/vimcat'\''!' \ + -e 's!^system_vimpagerrc=.*!system_vimpagerrc='\'"$$vimpagerrc"\''!' \ -e '/^\. .*inc\/'"$$BASE"'_functions.sh"$$/{' \ -e "r inc/$${BASE}_functions.sh" \ -e d \ -e '}' \ - -e '/^ *\. .*inc\/common_functions.sh"$$/{' \ + -e '/^\. .*inc\/common_functions.sh"$$/{' \ -e 'r inc/common_functions.sh' \ -e d \ -e '}' \