bug-bash
[Top][All Lists]
Advanced

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

Re: bash doesn't display tabs for tabs -- ignores tabstops.


From: Linda Walsh
Subject: Re: bash doesn't display tabs for tabs -- ignores tabstops.
Date: Wed, 24 Apr 2013 20:02:29 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.24) Gecko/20100228 Lightning/0.9 Thunderbird/2.0.0.24 Mnenhy/0.7.6.666

Greg Wooledge wrote:
> On Tue, Apr 23, 2013 at 11:42:34PM -0700, Linda Walsh wrote:
>> Was my elaboration clear enough -- ?
>>
>> It's a display issue not a content issue -- except when you cut/paste
>> from the terminal to another buffer under X.
> 
> You forgot to copy the mailing list.  Also, X has nothing to do with
> this.  This is solely between bash and the terminal.
-----
        No... It's about what *I* see, **AND**, when I copy/paste from the
terminal to another application, -- what "X" sees.

> Pasting has nothing to do with bash.  Pasting is between X and the
> terminal.  Totally separate issue.
---
        My terminal is displayed via 'X' --- X pics up
the actual characters that were echoed to the screen.  If TABS are
used, it put's TABS in the copy/paste-buffer.  If some lame application
substitutes some other character for tabs, it will pic up the wrong value.


        For the general case, I submit that it should echo HW tabs when it 
encounters
such.
> 
>> However I can think of no good reason why bash should not pay attention
>> to terminal settings and use the TAB char -- at least, as an option.
> 
> How would bash KNOW what the terminal's tabstops are set to?  It can't.
----
It uses the curses library.  The code has references through-out that look to
see what column it is in.   Bash has builtin features in the prompt-build
feature, to help it determine the correct column so it knows when to wrap your
cursor -- and it knows when to wrap output.

The same library it uses to keep track of that can tell it what the tabs
stops are -- either directly or indirectly.


> I am reluctant to speculate on this matter, but you appear to be grasping
> at straws, so I will proffer some guesswork.  Everything from here
> downward is totally guesswork and may be completely wrong.
> 
> Imagine that you're writing bash and that you want to include a feature
> that lets people edit their commands.  Some of these commands may include
> a literal tab character, even as difficult as it is to do such a thing.
----
        Imagine that you have a terminal where people paste intput from X.

Ok.. not hard at all to image where the TABS come from.  Imagine that they
can invoke a full-screen oriented editor like emacs or vim to edit a line --
and that they are used to tabbing over when indenting code.


> When the command editor is invoked, bash must reconstruct the command
> on the terminal, bearing in mind that bash knows very little *about*
> the terminal beyond the contents of $TERM and whatever it can glean
> from the system's termcap/terminfo database.
---
Yup..BINGO...

> 
> If the command to be edited contains a literal tab, bash must present
> the command on the screen in an editable format.
----
        So If a users terminal uses "." -- it would be ok for bash to display
"dot", instead of the actual character?


>  The user must be able
> to move the cursor to any part of the command, and the cursor's position
> must make sense to the user, and bash must always know where the cursor
> is in the REAL command in memory.
---
        Right -- sans-unicode, 1 char/byte -- user moves 1 char, internal edit
buffer moves 1 char...but on the screen bash expands it to 1-8 chars?


> 
> Suppose bash wrote a literal tab to the terminal when in this mode.
> The terminal may do anything with it.  The terminal may move the cursor
> to the 8th column, or the 5th column, or the 13th column, or anything.
> Bash wouldn't know where the cursor went.
---
        Uh... yeah.. it shouldn't care.  it knows that in it's internal buffer
it put out 1 character for that position.
> 
> So instead, bash does its own expansion of the tab using the standard
> 8-space tabstops that 99.9999% of the people in the world use.
---
Most people don't type in 8 spaces for a tab.  Only hard-coded, broken
computer programs.  People use variable tabs in real life -- long before
computers existed -- They put the columns where they wanted them.  You don't
see tabs expanded to 8 spaces in a word processor.  Tabs are expanded by the
hardware -- or hardware emulation.  Then software started evolving to match
the hardware -- but that was a hack.  Hardware for years has had variable tab
support -- vt102 -- it's not just linux consoles... it's emulating a much older
standard.

As for how hard it would be to find out the current tab setting?
1) allow the user to specify a tab settting in the ENV... like "duh? -- you mean
allow the user to have input into what tabs expand to?  SHOCK...if they
don't have a preference, default to 8.
2), it talks to the curses library -- through it it can find how tabs
are expanded.

Finding out the data and setting it -- can all be set in BASH SCRIPT -- But
getting BASH to reproduce tabs the way the terminal does --- has to be fixed
in BASH.


Here's a prog to read the tabs from the terminal and allow setting them
(only uniform-unidistant tabs at this point, but that's all I need -- if someone
else wants to improve on the prog -- I hereby release it to the public 
commons)...

--------------------------
#!/bin/bash
#console_codes(4) man page...
shopt -s expand_aliases
alias int='declare -i'
alias sub='function'
alias array='declare -a'
alias intArray='declare -ia'

printf -v clrallts  "\x1b[3g"
printf -v sts       "\033H"
printf -v cr        "\013"
printf -v cpr       "\x1b[6n"

function 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 () {
  printf $cr
  int pos=0 oldpos=0-1
  while ((oldpos!=pos));do
    oldpos=pos
    printf "\t"
    pos=$(getpos x)
    tabs+=($pos)
  done
  return 0
}

prompt="tty_tabs:"
int newcol=${#prompt}+1
echo -n "$prompt"
mycol=$(getpos x)
if [[ $mycol != $newcol ]]; then
  echo " Term tabset ability not detected (out=$out mycol=$mycol,
promptlen=$newcol)"
  exit -1
fi

if (($#==0)) ; then
  echo -en " <n> - set tab stop to N\r"
  get_tabs  && {
    printf "\r (cur tabs (from 1): "
    printf "%s " "address@hidden"
    printf "\n"
  }
  exit 1
fi
declare -i tab=$1;
str=""
declare -i pos=1
printf $clrallts

while ((++pos<80)) ;do
  if ((pos%tab)); then str+=" "
  else str+="$sts"
  fi
done
#echo -e "\033c"
echo  -n "$str$cr"

# vim: ts=2





reply via email to

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