Util-Linux package development
 help / color / mirror / Atom feed
From: Linda Walsh <lkml@tlinx.org>
To: util-linux@vger.kernel.org
Subject: bug: column assumes tabs every 8 columns & ttywidth=80
Date: Tue, 31 May 2016 15:36:11 -0700	[thread overview]
Message-ID: <574E11DB.2010501@tlinx.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 1560 bytes --]

In util-linux2.25, the "column" command isn't written for Linux using a
Linux-console (among others).  It assumes 8-column
fixed-width tabs and screen width of 80).

The Linux-console (or any emulator) and terminals supporting
the EMCA-48 standard (vt-100-emulating terms, as well as "xterm")
can have tabs set to arbitrary spacing.

Attached is a bash-script that can show current tab settings
as well as set them to a new value.

It only supports setting tabs to fixed-width, but there is nothing
preventing tabs from being set to variable width expansions.

Ex:
>  tty_tab 8
>  tty_tab
(from 1, tabs skip to column: 9 17 25 33 41 49 57 65 73 80
>  tty_tab 2
>  tty_tab
(from 1, tabs skip to column: 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 
33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 80

Suggestions to fix column (or other progs that deal
w/the console and use tabs):

1) allow -i (-t is taken) to specify width of terminal tab expansion
   -i 8 (default)
   -i 4 (some like 4-column indents)
   -i 2 (and some use 2 to keep down line length).  I've seen "1" used
   as a tabsize in javascript files...

1a) (low priority) -- have "-i" take a list of numbers, like
   -i 18 36 44 54
    (might be reasonable for /etc/fstab?) -- any tabs beyond the
     last would use the last specified interval (in above case, "10")
2) --no-tabs
    A "Don't use tabs" option for lining up columns, use spaces.
    AFAIK, spaces are a fixed size on tty's.

----

There's a tab-set program in the ncurses-utils as well called 'tabs'.










[-- Attachment #2: tty_tab --]
[-- Type: text/plain, Size: 3364 bytes --]

#!/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	my=declare				sub=function
alias int='my -i'				array='my -a' intArray='my -ia' 	string=my
my _Pt=$(type -t P)
[[ $_Pt && $_Pt == function ]] && unset -f P
alias P=printf
unset _Pt

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:=0-80}		
	int 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


                 reply	other threads:[~2016-05-31 22:45 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=574E11DB.2010501@tlinx.org \
    --to=lkml@tlinx.org \
    --cc=util-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox