19

I know I may save position using tput sc, but how can I read it's position to the variable? I need the number of row. I don't want to use curses/ncurses.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
ciembor
  • 7,189
  • 13
  • 59
  • 100
  • 2
    possible duplicate of [How to get the cursor position in bash?](http://stackoverflow.com/questions/2575037/how-to-get-the-cursor-position-in-bash) – dogbane Dec 01 '11 at 14:56
  • 2
    I can't expect that the user has bash. He may use csh or etc. – ciembor Dec 01 '11 at 15:24

1 Answers1

24

At ANSI compatible terminals, printing the sequence ESC[6n will report the cursor position to the application as (as though typed at the keyboard) ESC[n;mR, where n is the row and m is the column.

Example:

~$ echo -e "\033[6n"

EDITED:

You should make sure you are reading the keyboard input. The terminal will "type" just the ESC[n;mR sequence (no ENTER key). In bash you can use something like:

echo -ne "\033[6n"            # ask the terminal for the position
read -s -d\[ garbage          # discard the first part of the response
read -s -d R foo              # store the position in bash variable 'foo'
echo -n "Current position: "
echo "$foo"                   # print the position

Explanation: the -d R (delimiter) argument will make read stop at the char R instead of the default record delimiter (ENTER). This will store ESC[n;m in $foo. The cut is using [ as delimiter and picking the second field, letting n;m (row;column).

I don't know about other shells. Your best shot is some oneliner in Perl, Python or something. In Perl you can start with the following (untested) snippet:

~$ perl -e '$/ = "R";' -e 'print "\033[6n";my $x=<STDIN>;my($n, $m)=$x=~m/(\d+)\;(\d+)/;print "Current position: $m, $n\n";'

For example, if you enter:

~$ echo -e "z033[6n"; cat > foo.txt

Press [ENTER] a couple times and then [CRTL]+[D]. Then try:

~$ cat -v foo.txt
^[[47;1R

The n and m values are 47 and 1. Check the wikipedia article on ANSI escape codes for more information.

Before the Internet, in the golden days of the BBS, old farts like me had a lot of fun with these codes.

Paulo Scardine
  • 73,447
  • 11
  • 124
  • 153
  • 3
    Hmm... it always returns me `;1R`. – ciembor Dec 02 '11 at 19:32
  • @ciembor, that's because the text is echoed to the terminal, which in turn might interpret the escape sequence and cut off things. – Lloeki Dec 19 '13 at 19:35
  • 1
    I've just edited the bash example a little. For example using `-s` with `read` so that it doesn't echo the response to the screen. The first two lines now "silently" store the position in `foo`. – Aaron McDaid Jun 26 '15 at 09:43
  • In the example after perl oneline. It is supposed to be "\033[6n" instead of "z033[6n" right ? – deepakchethan May 06 '19 at 15:57
  • @deepakchethan good catch! In the Brazilian keyboard layout `\ ` and `z` are side by side. – Paulo Scardine May 06 '19 at 17:22
  • How can you know which positions are allowed, i.e. how many "rows" / "columns" are there on the screen? – Jay May 29 '20 at 09:06