Package: coreutils;
Reported by: Linda Walsh <coreutils <at> tlinx.org>
Date: Thu, 12 Feb 2015 21:19:02 UTC
Severity: normal
Tags: notabug
Done: Assaf Gordon <assafgordon <at> gmail.com>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Linda Walsh <coreutils <at> tlinx.org> To: 19849 <at> debbugs.gnu.org Subject: bug#19849: RFE: du output uses undefined screen-tabsize: expand tabs to spaces or "-T<tabsize> option?" Date: Thu, 12 Feb 2015 13:17:35 -0800
[Message part 1 (text/plain, inline)]
I run a linux compat term that allows setting the tab size. Since most of my usage is using tabsize=2, I set the term's tabsize to such when it comes up. Programs that can display tabs in output like 'ls', 'diff', 'less(or more)', to name a few, have some type of "expand-tabs" or "-[tT]" option to expand tabs on output (or input to line up input columns). Ex: ls: -T, --tabsize=COLS assume tab stops at each COLS instead of 8 diff: -t, --expand-tabs expand tabs to spaces in output -T, --initial-tab make tabs line up by prepending a tab --tabsize=NUM tab stops every NUM (default 8) print columns (etc..). I propose 'du' gain a "-T" option like 'ls' to allow for formatted output: So instead of : 20K My layouts/linda-default.fcl 20K My layouts/new-default.fcl 0 My layouts/foo.fcl 2.2M autobackup/autobackup.20141103-042819.zip 2.3M autobackup/bak 12K configuration/Core.cfg 12K playlists/00000106.fpl 24K playlists/index.dat 2.1M pygrabber/libs 28K pygrabber/scripts 1.3M user-components/foo_AdvancedControls I could see: 20K My layouts/linda-default.fcl 20K My layouts/new-default.fcl 0 My layouts/foo.fcl 2.2M autobackup/autobackup.20141103-042819.zip 2.3M autobackup/bak 12K configuration/Core.cfg 12K playlists/00000106.fpl 24K playlists/index.dat 2.1M pygrabber/libs 28K pygrabber/scripts 1.3M user-components/foo_AdvancedControls ---- Two other readability examples from different programs follow and a description of the attachment. Of note, 'ls' defaults to explanding tabs to spaces, so it doesn't have the problem of variable expansion, but if one tells it to use '8 space/tab (example pruned from /tmp): 4.0K 0bPwr3N_7s 4.0K cyg2lin.env 4.0K prereqs.txt 4.0K 1 16K diff 4.0K rmdirs 4.0K 2 4.0K dirs 0 ssh-Y3YzuDAD5w/ 0 3173-f1.txt 4.0K do_diffs* 0 ssh-a9nNm0VQ2c/ 4.0K 5QXcX6apwV 4.0K done 0 ssh-oszB2InjXA/ 0 CPAN-Reporter-lib-1WVP/ 4.0K fZuwIWpHXO 0 ssh-pOlsxOkr0U/ 0 CPAN-Reporter-lib-wDln/ 4.0K files 0 ssh-vSPNXq8i3I/ 4.0K HUk8j_zP_d 4.0K fq22uj4fYU 0 t1 4.0K all 4.0K lnx.txt 0 veKj4PS/ 4.0K awstest.out 456K log 0 vq0XVTv/ 104K boot-cons.msg 4.0K lt.h 40K x.log 0 boot.msgs/ 4.0K meterlist 24K x.txt vs. ls' -CFhsT2: 4.0K 0bPwr3N_7s 4.0K cyg2lin.env 4.0K prereqs.txt 4.0K 1 16K diff 4.0K rmdirs 4.0K 2 4.0K dirs 0 ssh-Y3YzuDAD5w/ 0 3173-f1.txt 4.0K do_diffs* 0 ssh-a9nNm0VQ2c/ 4.0K 5QXcX6apwV 4.0K done 0 ssh-oszB2InjXA/ 0 CPAN-Reporter-lib-1WVP/ 4.0K fZuwIWpHXO 0 ssh-pOlsxOkr0U/ 0 CPAN-Reporter-lib-wDln/ 4.0K files 0 ssh-vSPNXq8i3I/ 4.0K HUk8j_zP_d 4.0K fq22uj4fYU 0 t1 4.0K all 4.0K lnx.txt 0 veKj4PS/ 4.0K awstest.out 456K log 0 vq0XVTv/ 104K boot-cons.msg 4.0K lt.h 40K x.log 0 boot.msgs/ 4.0K meterlist 24K x.txt ---- As a final short example -- something I use to print a shortened version of my current directory in my prompt: w/default -8 tabs in less: > less -x8 spwd #!/bin/bash cols() { declare size="$(stty size </dev/tty)" echo "${size#* }" } export -f cols shopt -s expand_aliases alias int=declare\ -i _e=echo _pf=printf exp=export ret=return exp __dpf__='local -a PF=( "/$1/$2/$3/../\${$[$#-1]}/\${$#}" "/$1/$2/../\${$[$#-1]}/\${$#}" "/$1/../\${$[$#-1]}/\${$#}" "/$1/../\${$#}" ".../\${$#}" "..." )' function spwd () { \ (($#)) || { _e "spwd called with null arg"; ret 1; }; \ int w=${COLUMNS:-$(cols)}/2 ;\ ( _pf -v _p "%s" "$1" ; exp IFS=/ ;\ set $_p; shift; unset IFS ;\ t="${_p#${HOME%${USER}}}" ;\ int tl=${#t} ;\ if (($#<=6 && tl<w));then ((tl<=2)) && \ { _e -En "${_p}";ret 0; } ;\ else \ eval "$__dpf__" ;\ int i pfl=${#PF[*]} ;\ for ((i=0; i<pfl; ++i)); do eval \ "_pf -v _pa %s \"${PF[i]}\"" ;\ _p="$(eval "_pf %s \"$_pa\"")" ;\ ((${#_p}<w)) && break; done ;\ fi ;\ _e -En "${_p#${HOME%${USER}}}" ) } exp -f spwd [[ ${0##*/} == spwd ]] && if (($#)) ; then spwd "$@" ; else spwd "$PWD" ; fi ------------------ But using tabsize = 2: #!/bin/bash cols() { declare size="$(stty size </dev/tty)" echo "${size#* }" } export -f cols shopt -s expand_aliases alias int=declare\ -i _e=echo _pf=printf exp=export ret=return exp __dpf__='local -a PF=( "/$1/$2/$3/../\${$[$#-1]}/\${$#}" "/$1/$2/../\${$[$#-1]}/\${$#}" "/$1/../\${$[$#-1]}/\${$#}" "/$1/../\${$#}" ".../\${$#}" "..." )' function spwd () { \ (($#)) || { _e "spwd called with null arg"; ret 1; }; \ int w=${COLUMNS:-$(cols)}/2 ;\ ( _pf -v _p "%s" "$1" ; exp IFS=/ ;\ set $_p; shift; unset IFS ;\ t="${_p#${HOME%${USER}}}" ;\ int tl=${#t} ;\ if (($#<=6 && tl<w));then ((tl<=2)) && \ { _e -En "${_p}";ret 0; } ;\ else \ eval "$__dpf__" ;\ int i pfl=${#PF[*]} ;\ for ((i=0; i<pfl; ++i)); do eval \ "_pf -v _pa %s \"${PF[i]}\"" ;\ _p="$(eval "_pf %s \"$_pa\"")" ;\ ((${#_p}<w)) && break; done ;\ fi ;\ _e -En "${_p#${HOME%${USER}}}" ) } exp -f spwd [[ ${0##*/} == spwd ]] && if (($#)) ; then spwd "$@" ; else spwd "$PWD" ; fi --------------- The attachment is a shell script shell script that allows one to display and/or set current tab settings on compatible terminals -- if you want to see what programs look like with various tab settings, it might be useful. The script assumes if it cannot read the current tab settings, then the term likely doesn't support setting them either. The script is a bit of a hack, in that if the user types input while it it trying to measure or set your tabs, it may just give up and not set them, but I have it run as part of my login script and it's rarely a problem (even works w/cygwin on windows!). (Hard to block the user's TTY input when the program requires talking to the TTY apart from the user). Thanks, Linda
[tty_tab (text/plain, inline)]
#!/bin/bash -u #console_codes(4) man page... vt100/2 et && EMCA-48 standard # (c) la walsh (2013) -- free to use and modify for personal use. # -- optionally licenced under Gnu v3 license. # v0.0.3 - try to reduce tabcols to minimal set to reproduce. # v0.0.2 - set tabs for full terminal width (try to get term width) shopt -s expand_aliases extglob alias int='declare -i' sub='function' array='declare -a' alias intArray='declare -ia' P=printf string=declare P -v clrallts "\x1b[3g" P -v sts "\033H" P -v cpr "\x1b[6n" sub getcols() { local sttyout="$(stty size </dev/tty)" int default_cols=80 if [[ -n ${COLUMNS:-""} && $COLUMNS =~ ^[0-9]+$ ]]; then default_cols=$COLUMNS; fi [[ -z ${sttyout:-""} ]] && { echo $default_cols; return 0; } int cols="${sttyout#*\ }" echo -n $[cols<2?default_cols:cols] return 0 } sub getpos () { string ans wanted=${1:-xy} int attempt=0 max_attempt=1 # in case of rare failure case # use 'attempt' value as additional # time to wait for response while : ; do ( ( P "\x1b[6n" >/dev/tty) & 2>/dev/null ) read -sd R -r -t $[2 + attempt] ans </dev/tty; ans=${ans:2}; int x=0-1 y=0-1 if ! x="${ans#*;}" y="${ans%;*}" 2>/dev/null || ((x==-1||y==-1)); then ((attempt+=1 < max_attempt)) && continue fi break; done string out="" [[ $wanted =~ x ]] && out="$x" [[ $wanted =~ y ]] && out="${out:+$x }$y" [[ $out ]] && echo -n "$out" } declare -ia tabs sub get_tabs () { P "\r" tabs=() int pos=0 oldpos=0-1 while ((oldpos!=pos));do ((pos)) && tabs+=($pos) oldpos=pos P "\t" pos=$(getpos x) done P "\r" return 0 } # Note: this sub uses ability to _read_ tabstops as _proxy_ for setting them # (i.e. it makes no sense to be able to read them if you can't set them) sub test_tabset_ability () { string prompt="tty_tab:" int newcol=${#prompt}+1 P "\r$prompt" int mycol=$(getpos x) ((mycol && mycol==newcol)) && return 0 ## return OK { P " Term tabset ability not detected mycol=${mycol:-''}," P " promptlen=$newcol)\n"; } >&2 exit -1 } sub do_help_n_display_curtabs () { P " <n> - set tab stop to N\r" intArray diffs; int last=1 cur i string eol="" get_tabs && { for ((i=0; i<${#tabs[@]}; ++i)); do cur=${tabs[i]} diffs[i]=cur-last last=cur done intArray reverse_tabs_set=() int prevtab=0-1 for ((i=${#diffs[@]}-2; i>0; --i)); do int thistab=${diffs[i]} if ((thistab!= prevtab)) ;then reverse_tabs_set+=($thistab) prevtab=thistab fi done P "current value: tty_tab " for ((i=${#reverse_tabs_set[@]}-1; i>=0; --i)); do P "%d " "${reverse_tabs_set[i]}"; done P "\r"; } get_tabs && { P "(from 1, tabs skip to column: " P "%s " "${tabs[@]}" P "\r\n" } } sub set_tabs () { int max_col=${1:-80} tabstop=${2:-"need a param for tabstop"} int tab=$tabstop pos=0 string str="" P $clrallts ## reset old tabs while ((++pos<cols)) ;do ## move across screen setting tabs str+=" " ((pos%tab)) || str+="$sts" done P "\r$str\r" } int cols=$(getcols) test_tabset_ability ## exits if no ability if (($#==0)) ; then do_help_n_display_curtabs exit 1 else set_tabs "$cols" "$@" fi # vim: ts=2 sw=2
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.