4

in school we have been assigned a homework in which we are suppose to print an ascii art into a terminal window. A input is data in format [x_coordinate, y_coordinate, char_ascii_value] (there is no data for coordinates where shouldn't be print any character). I don't have any trouble actually doing it but I guess I am simply too lazy to go into for cycle and print an empty space every time there is no data for character, then go to another line in terminal and do the same, etc.

So I was thinking that, there must be an easier way! Since we are allowed to work only with commands which are in POSIX, is there any command that allows you to move cursor to specific position in terminal?

I ran into the command named tput and tput cup does exactly what I need but I am not quite sure if tput cup is in POSIX.

P.S. Please don't take this like some kind of cheating. I am just trying to find a way to make my life easier instead of brainless writing code.

  • 1
    POSIX doesn't handle that. But there is a standards committee that does - that's ANSI. And yeah, anything that can write to stdout can do it. tput is POSIX, but it might just be the least standardized of their listed tools. Basically you can do: printf \\33\[ ?[ABCD], where ? is a number for how many cursor positions you want to move - A goes up, B down, C right, D left. And use \\337 or \\338 for saving/restoring current cursor state respectively. – mikeserv Jun 17 '15 at 17:23
  • The arguments to tput allowed by POSIX don't include anything that does absolute or relative cursor motion. I think you'll need to write C code, using the curses or terminfo libraries, if you want to do that. – Mark Plotnick Jun 17 '15 at 17:26
  • @MarkPlotnick - the arguments to tput are not constrained by POSIX. In fact, they're deliberately unspecified: The tput utility shall display terminal-dependent information. The manner in which this information is retrieved is unspecified. The information displayed shall clear the terminal screen, initialize the user's terminal, or reset the user's terminal, depending on the operand given. The exact consequences of displaying this information are unspecified. – mikeserv Jun 17 '15 at 17:30
  • 1
    There's an ANSI escape sequence to specify an absolute position, \\33\[r;cH where r is the desired row and c the desired column, both starting at 1. It's widely supported but isn't POSIX. – Stephen Kitt Jun 17 '15 at 17:32
  • And another for retrieving the current position is \\33\[6n. – mikeserv Jun 17 '15 at 17:34
5

As mikeserv explains, POSIX doesn't specify tput cup. POSIX does specify tput but only minimally. That said, tput cup is widely supported!

The standardised way of positioning the cursor is using ANSI escape sequences. To position the cursor you'd use something like

printf "\33[%d;%dH%s" "$Y" "$X" "$CHAR"

which will print $CHAR at line $Y and column $X. A more complete solution would be

printf "\337\33[%d;%dH%s\338" "$Y" "$X" "$CHAR"

which will restore the cursor position.

2

tput is left vague and minimal in POSIX because there is a more detailed specification in X/Open Curses:

There appears to be no direct link to an HTML version of the latter (in particular the command-line tput), but it is more detailed (about twice as long). Quoting from the description in X/Open Curses:

7319 When XCURSES is supported, this description for the tput utility replaces that in the XC
7320 specification.
7321 The tput utility uses the terminfo database to make the values of terminal-dependen
7322 capabilities and information available to the shell (see sh in the XCU specification); to clear
7323 initialize, or reset the terminal; or to return the long name of the requested terminal type. Th
7324 tput utility outputs a string if the capability attribute (capname) is of type string, or an integer i
7325 the attribute is of type integer. If the attribute is of type boolean, tput simply sets the exit statu
7326 (0 for TRUE if the terminal has the capability, 1 for FALSE if it does not), and produces n
7327 output.

the program will retrieve any value from the terminal database. Most of the platforms which you use provide an implementation of X/Open Curses. The fine details may differ, of course. On some platforms you may encounter a version of tput which uses termcap names rather than terminfo. But you are not likely to encounter that on an assignment using "POSIX", and in any case, you can accomplish the same goal, using a slightly different vocabulary.

However, neither curses nor ANSI escape sequences are part of POSIX. Escape sequences are standardized in ECMA-48:

As a rule, POSIX does not overlap much with other standards (you will find most exceptions to that rule versus the C standard). Likewise, X/Open Curses does not overlap much with ECMA-48: the form and content of escape sequences are not detailed in that document.

Strictly speaking, you cannot do your assignment using only POSIX. You can only do this using POSIX plus the usual assortment of related standards for which there is an implementation on your system.

The reason for applications such as tput (and libraries such as curses) is to provide a layer to hide details and inconsistencies across implementations. POSIX only goes so far, and omits most of the interesting features of an operating system, e.g., user management, security, and of course managing terminals. Even with escape sequences, there are several ways to move the cursor on various terminals. Here are a few terminfo summaries of those:

   carriage_return           cr     cr   carriage return (P*)
                                         (P*)

   column_address            hpa    ch   horizontal position
                                         #1, absolute (P)

   cursor_address            cup    cm   move to row #1 col-
                                         umns #2

   cursor_down               cud1   do   down one line

   cursor_home               home   ho   home cursor (if no
                                         cup)

   cursor_left               cub1   le   move left one space

   cursor_mem_address        mrcup  CM   memory relative cur-
                                         sor addressing, move
                                         to row #1 columns #2

   cursor_right              cuf1   nd   non-destructive

   cursor_to_ll              ll     ll   last line, first
                                         column (if no cup)

   cursor_up                 cuu1   up   up one line
                                         space (move right
                                         one space)

   parm_left_cursor          cub    LE   move #1 characters
                                         to the left (P)

   parm_right_cursor         cuf    RI   move #1 characters
                                         to the right (P*)

   restore_cursor            rc     rc   restore cursor to
                                         position of last

   row_address               vpa    cv   vertical position #1
                                         absolute (P)

   save_cursor               sc     sc   save current cursor
                                         position (P)

   tab                       ht     ta   tab to next 8-space
                                         hardware tab stop

                                         save_cursor

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.