[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: having bash display real tabs for tab characters...

From: Linda Walsh
Subject: Re: having bash display real tabs for tab characters...
Date: Thu, 11 Jul 2013 21:59:33 -0700
User-agent: Thunderbird

Eric Blake wrote:
On 07/11/2013 04:06 PM, Linda Walsh wrote:
Revisiting this...

Chet Ramey wrote:
On 4/25/13 8:45 AM, Greg Wooledge wrote:

If you think Bash is misbehaving, submit a patch, or wait for Chet to
comment on one of these threads.
I don't plan to comment or make any changes.  The demand for this
feature seems vanishingly small.
        It's not a feature to use simply echo output.  Bash implemented
a feature of tab expansion because tabs can be variably set.  While this
makes it's editing function consistent in terms of handling line wrap-around,
it doesn't make it consistent with the user's text as displayed on the screen
when they use 'echo' or 'printf' or display it with non-bash utils (cat
more-less, vim, perl...etc.

        That bash does tab expansion is already an "added feature"
to compensate for terminals that have variable tabs.  I would characterize
the current tab-expansion feature as a hack to compensate for the difficulties
in implementing other solutions.  That doesn't mean I'm saying Chet should
try to fix it.  As you say, it's me that wants it to really work rather than
be patched over, so I should figure out what's needed to make it work.

        Off hand, I'm thinking (besides keeping the current fixed expansion),
along the lines of 1st of 'descriptive' -- allowing a TABSET env var to hold
a current setting of tabs -- though that might be preceded by a simple ability
to set stops to something other than 8 which would likely serve 99% of the
people.  Secondly, bash could use the curses database to figure out if the
current terminal supported variable tabs; and/or simply try it.

My current bash script for dealing w/tabs, if invoked just tries
detecting the standard tab get/set function.  Only using
windows command.com window, I was able to get a term that DIDN'T work:

Ishtar:/> tty_tab
tty_tab: Term tabset ability not detected (out='' mycol='', promptlen=9)

But running on xfce's Terminal, konsole, xterm, and SecureCRT (in linux
mode) it prints out fixed tabstops... not sure what it would do if detected
variable, as I didn't implement that ability in it's set machinery.

I.e. some of this, beyond my needs, I likely wouldn't implement unless
there was demand.

FWIW, my existing tab detect and print (and set) script is attached.

If you run it on a term that supports tabs and reading their positions,
it should print something like:

tty_tab: <n>   - set tab stop to N
current value: tty_tab 8
(from 1, tabs skip to column: 9 17 25 33 41 49 57 65 73 80

(or for set @ 2):

tty_tab: <n>   - set tab stop to N
current value: tty_tab 2
(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

I take it that invitation for patches is still open....
simplest would be fixed size w/env var setting...

#!/bin/bash  -u
#console_codes(4) man page... vt100/2 et && EMCA-48 standard
# Original author la walsh (2013) -- free to use and modify for personal use.

# 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 

shopt -s expand_aliases extglob
alias int='declare -i'
alias sub='function'
alias array='declare -a'
alias intArray='declare -ia'
alias P=printf

P -v clrallts  "\x1b[3g"
P -v sts       "\033H"
P -v cr        "\013"
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
        if [[ -z ${sttyout:-""} ]]; then 
                echo $default_cols; return 0;fi
        int cols="${sttyout#*\ }"
        echo $[cols<2?default_cols:cols]
        return 0

sub getpos () {
  local wanted=${1:-xy}
  local ans x y
 ( (sleep .01 && echo -en "\x1b[6n" >/dev/tty) & 2>/dev/null )  
  read  -sd R -r -t 2 ans </dev/tty; 
  declare ans=${ans:2}; x=${ans#*;}; y=${ans%;*} ; 
  declare -g out=""
  [[ $wanted =~ x ]] && out="$x"
  [[ $wanted =~ y ]] && out="${out:+$x }$y"
  [[ $out ]] && echo "$out"

declare -iga tabs

sub get_tabs () {
  P $cr
  int pos=0 oldpos=0-1
  while ((oldpos!=pos));do
                ((pos)) && tabs+=($pos)
    P "\t"
    pos=$(getpos x)
        P "\r"
  return 0

sub test_tabset_ability () {
        int newcol=${#prompt}+1
        P "\r$prompt"
        mycol=$(getpos x)

        if [[ $mycol != $newcol ]]; then
                        P " Term tabset ability not detected (out=${out:-''} 
                        P " promptlen=$newcol)\n"
                ) >&2
                exit -1 

sub do_help_n_display_curtabs () {      
  P " <n>   - set tab stop to N"
        P "\r"
        intArray diffs;
        int last=1
        int cur i
        local eol=""
        get_tabs && {
                for ((i=0; i<address@hidden; ++i)); do
                intArray reverse_tabs_set=()
                int prevtab=-1
                for ((address@hidden; i>0; --i)); do
                        int thistab=${diffs[i]}
                        if ((thistab!= prevtab)) ;then 
                P "current value: tty_tab "
                for ((address@hidden; i>=0; --i)); do
                        P "%d " "${reverse_tabs_set[i]}"
                P "\r";
  get_tabs  && {
    P "(from 1, tabs skip to column: "
    P "%s " "address@hidden"
                P "\n"

sub set_tabs () {
        int max_col=${1:-80}                    ## #columns on screen
        int tabstop=${2:-"need a param for tabstop"}
        int tab=$tabstop
        int pos=0
        P $clrallts                                     ## reset old tabs
        while ((++pos<cols)) ;do        ## move across screen setting tabs
                str+=" "
                ((pos%tab)) || str+="$sts"
        #echo -e "\033c"
        P "\r$str$cr"
        P ""

int cols=$(getcols)

test_tabset_ability                             ## exits if no ability

if (($#==0)) ; then
  exit 1
        set_tabs "$cols" "$@"

# vim: ts=2 sw=2

reply via email to

[Prev in Thread] Current Thread [Next in Thread]