If you have a large amount of output to a command line interface, how do you navigate upward to see the information that has already scrolled off the screen?
Is there common commands for this across various command line interfaces?
Related
Under Ubuntu 14.04, I'm writing a script that output a lot of text (several commands...), and I would like to keep one or more lines always on top of the terminal screen to display what's running title.
In other words, I try to reduce terminal vertical scroll zone and write in that non-scrolling zone.
How can I do that? I saw similar stuff using a loop catching output line by line, but I'm unable to find a way to tell the system to print from let's say line 2 or 3.
Thanks for your answers,
Nicolas
Nic, it appears this does quite nicely.
http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
I am trying to create a program which will have live updates from some data source. And I also want to wait for user input just like a normal terminal. Right now, whenever there is update, I will print the content and print the prompt message for input again which create something like this:
Enter command >
This is a live update message
Enter command >
This is a multi-line li......
......ve update message
Enter command > quit
Bye bye!
The problem is that for every live message I received, I will print it and the "Enter command >" will be displayed again again and again, which is not desired. I want the live update to be update on the main part of the terminal, while the "Enter command >" always stay at the bottom
The closest package I can found on Github is https://github.com/gizak/termui but most of the examples inside is trying to display text, gauge and graphs. So I am not quite sure how to get started.
Is there any package or example of the termui package to achieve this? Thank you.
With github.com/gizak/termui you're heading in the correct direction.
To understand why you can't get that
I want the live update to be update on the main part of the terminal, while the "Enter command >" always stay at the bottom
part sorted out, a little excursion to the history of computing is due. ;-)
The thing is, the mode your teminal emulator¹ works by default originated
in how computers would communicate to the operator in the era which predated
alphanumeric displays — they would print their responses using a line printer. Now think of it: a line printer works like this: it prints whatever is sent to it on a roll of paper. What was output, was output.
The new output always appears physically below the older.
When alphanumeric displays (screens) came into existence they
naturally continued to support this mode:
the line text to be output was rendered at the bottom of the screen
with the text above it scrolled upwards.
That's what you see in your typical terminal emulator all the time when you're working in the command line of a shell (such as bash) running by the emulator window.
This, default, work mode of a terminal is called "canonical" or "cooked".
Then came more advanced displays, for which it was possible to change
individual positions on the screen — identified by their column and
row numbers.
This changed the paradigm of how the information was output: the concept
of a so-called "full-screen application" was born.
Typical examples of them are text editors such as Vim and Emacs.
To support full-screen text output, terminals (and terminal emulators)
were adapted by implementing certain extensions to their protocols.
A full-screen application first requests the terminal to switch into another
mode called "raw", in which the terminal sends most of what is input by the
user directly to the program running on the terminal.
The program handles this input and orders the terminal where and what
to draw.
You can read this good summary
of the distinction between the both modes.
As you are supposedly suspecting by now, to be able to keep some block
of information at a certain fixed place of the terminal's text screen,
you want your program to be a full-screen program and use the terminal's
raw mode and its special commands allowing you to directly modify
text at certain character cells.
Now the problem is that different terminals (and terminal emulators)
have different commands to do that, so there exist libraries to isolate
the programs from these gory details. They rely on the special "terminal
information databases" to figure out what capabilities a terminal has
and how to make it do what the program asks.
See man terminfo for more background.
The most widely known such library (written in C) is called ncurses,
and there exist native solutions for Go with supposedly the most visible
one being github.com/nsf/termbox-go.
The github.com/gizak/termui makes use of termbox-go but for you it might
suffice to use the latter directly.
¹ Chances are very high you're not sitting at
a real hardware terminal
connected to a UNIX® machine but are rather working in a GUI application
such as GNOME Terminal or xterm or Termial.app etc.
These are not "terminals" per se but are rather
terminal emulators —
that is, pieces of software emulating a hardware terminal.
Under Ubuntu 14.04, I'm writing a script that output a lot of text (several commands...), and I would like to keep one or more lines always on top of the terminal screen to display what's running title.
In other words, I try to reduce terminal vertical scroll zone and write in that non-scrolling zone.
How can I do that? I saw similar stuff using a loop catching output line by line, but I'm unable to find a way to tell the system to print from let's say line 2 or 3.
Thanks for your answers,
Nicolas
Nic, it appears this does quite nicely.
http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
In Vim, executing zz in normal mode will take the line the cursor is currently on, and move that line, together with the cursor, to the vertical center of the current window.
Is there a way to replicate this behavior in bash, to move the current command prompt to the vertical center of the screen, and scroll the command buffer along with it?
I am posting on StackOverflow instead of Unix/Linux because I am open to solutions that require writing custom code if bash does not natively support this.
Vim controls the entire area of the screen. Bash is only responsible for the input line. It has no idea about the contents of the rest of the screen, which is/was under control of other programs, and cannot reposition it.
Note that the contents of the screen nornally cannot be read by a program running on it. The only way to know what's on the screen is to start from a clean state and account for every single character and terminal command printed. Vim does just that; Bash does not and can not.
n.m. has already explained that bash itself cannot do it. However, you still might be able to send commands directly to the underlying terminal to achieve an effect similar to what you want. For example, assuming that your bash input line is somewhere below the middle of the screen, the following will scroll down by sending a couple of empty lines and then putting you into the middle of the screen:
declare -i L; declare -i M; L=`tput lines`/2; M=$L-1; for (( c=1; c<=$L; c++ )); do echo; done; tput cup $M
Note that this doesn't work when your somewhere in the upper half of the screen (it will put you into the middle of the screen, but will not scroll back).
For more info see man tput and man terminfo.
I have been reading a lot of the questions here on vim. I can't locate something that I want to do with vim but I am sure its possible.
I like vim(I am still new at it) using tabs and I have adjusted my vimrc so that H & L keys take me back and forth between tabs.
I was hoping to find a way to be able to use tab commands to open up a tab as output, so that if I am writing something in my case Ruby and I want to test it I could run it and flip to a new tab with the output. Or flip a tab to an interactive console to test code. This is possible?
As an aside is it possible to expand tabs to views so if I had two tabs open say script and output I could :spx or similar and have tabs come to split screen.
You can load the ruby output into a vim window in a couple of ways. One way would be to open a new split window and then load output of command:
" vimscript command to open new split window
wincmd n
" run ruby command and insert output at line 1
1,1!ruby foo.rb
alternatively you could get view the output on a new tab with a single window:
tabnew
1,1!ruby foo.rb
I know it's not the answer you want, but use buffers and ditch the tabs. I have a screencast going over how to use splits to manage your window.
http://lococast.net/archives/111
As for the ruby output, that seems like it might be covered here:
https://superuser.com/questions/133886/vim-displaying-code-output-in-a-new-window-a-la-textmate
In answer to your question about opening up a tab as output, I don't think there's any built in way to do this. There's the RunView plugin (see my answers to this question and this one), but I don't think that it supports using a separate tab (it works with a split window: what I think you refer to when you say 'view').
Regarding an interactive console: no, this is not possible. See :help design-not.
As for general use of Vim, try to get used to the idea of buffers and the fact that each 'view' (my term), whether it be a split window, a tab or whatever is just a means of looking at a particular buffer. You can have multiple views on a single buffer, so you can have a source file vertical split with two headers in one tab and the same source file vertically split with another header and a different bit of the same source file in another tab. This is very powerful once you get used to it. The Ctrl-W keyboard shortcuts are your friend (e.g. Ctrl-W, h to go left one window).
As for changing a tab into a split window, I don't think there's a direct way to do this (how would Vim know which tabs you wanted to join?). You can break a split into a tab with Ctrl-W + T, but to go back you'd have to create a couple of mappings. This is off the top of my head but something like this might work:
command! TakeThis let takebufnr = bufnr("")<CR>
command! SplitTaken exe 'split #' . takebufnr<CR>
nmap ,t :TakeThis<CR>
nmap ,s :SplitTaken<CR>
Then press ,t on the buffer you want to grab and ,s on the one you want to split with the 'taken' buffer.