GNU bug report logs - #19849
RFE: du output uses undefined screen-tabsize: expand tabs to spaces or "-T<tabsize> option?"

Previous Next

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.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 19849 in the body.
You can then email your comments to 19849 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-coreutils <at> gnu.org:
bug#19849; Package coreutils. (Thu, 12 Feb 2015 21:19:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Linda Walsh <coreutils <at> tlinx.org>:
New bug report received and forwarded. Copy sent to bug-coreutils <at> gnu.org. (Thu, 12 Feb 2015 21:19:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Linda Walsh <coreutils <at> tlinx.org>
To: bug-coreutils <at> gnu.org
Subject: 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


Information forwarded to bug-coreutils <at> gnu.org:
bug#19849; Package coreutils. (Mon, 04 Jan 2016 01:57:01 GMT) Full text and rfc822 format available.

Message #8 received at 19849 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Linda Walsh <coreutils <at> tlinx.org>, 19849 <at> debbugs.gnu.org
Subject: Re: bug#19849: RFE: du output uses undefined screen-tabsize: expand
 tabs to spaces or "-T<tabsize> option?"
Date: Mon, 4 Jan 2016 01:56:32 +0000
tag 19849 notabug
close 19849
stop

On 12/02/15 21:17, Linda Walsh wrote:
> 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

> I could see:
> 
> 20K     My layouts/linda-default.fcl
> 20K     My layouts/new-default.fcl
> 0       My layouts/foo.fcl

I think of the single tab output by du, as providing
standard separation, with very rough alignment.
One can then adjust alignment easily outside of of du.

For example:

$ du -h | expand
20K     My layouts/linda-default.fcl
20K     My layouts/new-default.fcl
0       My layouts/foo.fcl

Or more sophisticated right alignment and number processing with:

$ du -B1 *.patch | numfmt --format=%6.1f --to=iec
 20.0K My layouts/linda-default.fcl
 20.0K My layouts/new-default.fcl
   0.0 My layouts/foo.fcl

thanks,
Pádraig




Added tag(s) notabug. Request was from Assaf Gordon <assafgordon <at> gmail.com> to control <at> debbugs.gnu.org. (Tue, 23 Oct 2018 01:46:02 GMT) Full text and rfc822 format available.

bug closed, send any further explanations to 19849 <at> debbugs.gnu.org and Linda Walsh <coreutils <at> tlinx.org> Request was from Assaf Gordon <assafgordon <at> gmail.com> to control <at> debbugs.gnu.org. (Tue, 23 Oct 2018 01:46:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 20 Nov 2018 12:24:07 GMT) Full text and rfc822 format available.

This bug report was last modified 6 years and 211 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.