Piping println() through an external pager program (more, less)

T

Thomas Kellerer

Hi,

I have a console application ("commandline") that is writing text to the console
using System.out.println (I'm *not* referring to the "Java Console" that is
started when an applet is started)

I would like to support paging of the output, but I can't find a way to do it.

My first approach was to try to find the current size of the console, but this
does not seem to be possible in a cross-platform manner (in pure Java)

So I thought I could simply write my output to a spawned "pager" process ("print
ln() | more") but I can't get this to work either.

I tried the example from http://mindprod.com/jgloss/exec.html and even though
the output is shown on screen, the pager (in my case "more" under Windows) does
not kick in and I don't see the prompt to press enter to see the next page.

I tried several combinations of using Process.getInputStream() and
Process.getOutputStream() (and mingling with System.out and System.in) but
either I can't see the output or the output is not paged.

Any ideas?

Thanks
Thomas
 
J

John B. Matthews

Thomas Kellerer said:
I have a console application ("commandline") that is writing text to
the console using System.out.println (I'm *not* referring to the
"Java Console" that is started when an applet is started)

I would like to support paging of the output, but I can't find a way
to do it.

My first approach was to try to find the current size of the console,
but this does not seem to be possible in a cross-platform manner (in
pure Java)

So I thought I could simply write my output to a spawned "pager"
process ("print ln() | more") but I can't get this to work either.

I tried the example from http://mindprod.com/jgloss/exec.html and
even though the output is shown on screen, the pager (in my case
"more" under Windows) does not kick in and I don't see the prompt to
press enter to see the next page.

I tried several combinations of using Process.getInputStream() and
Process.getOutputStream() (and mingling with System.out and
System.in) but either I can't see the output or the output is not
paged.

Why not pipe the output of CommandLine to `more` or less`?

$ java CommandLine | more

You can always execute a process containing such a command, or have the
user invoke a suitable shell/batch command.
 
T

Thomas Kellerer

John B. Matthews wrote on 14.03.2009 18:58:
Why not pipe the output of CommandLine to `more` or less`?

$ java CommandLine | more

Thanks for the answer

Piping from the commandline is not possible because the application is
interactive. The user can enter commands and the output of the commands should
be be paged if the user wants that.

Thomas
 
J

Joshua Cranmer

Thomas said:
I would like to support paging of the output, but I can't find a way to
do it.

This is typically done using a special terminal support library called
"curses" or one of its derivatives. Googling "Java curses" would prove
helpful.
So I thought I could simply write my output to a spawned "pager" process
("print ln() | more") but I can't get this to work either.

Runtime.exec() is not a shell. Even if the piping would work, the more
program would not recognize the Java caller as a terminal and would
therefore merely act like the program cat.
Any ideas?

From your later comments, it seems you most want to look into a Java
curses library.
 
M

Mark Space

Thomas said:
Thanks for the answer

Piping from the commandline is not possible because the application is
interactive. The user can enter commands and the output of the commands
should be be paged if the user wants that.


You'll almost certainly need some JNI calls to determine the screen
size.. and to detect when it changes too.

Command line programs that are interactive and work "like windows" are
passe at this point, imo. I'm not surprised Sun has not invested any
effort into making them convenient to do in Java.

Have you considered C/C++ and native libs? Any given OS is likely to
support several types of command windows -- good luck actually getting
them all working.

I'd require the user to support and run a GUI so Swing/AWT can be used.
Anything else is just too far beyond the pale these days. Even
servers, I've run into configuration tools that required
X-Windows/KDE/etc. The IT folks who do servers I talk to say the same
-- GUI required for servers these days. And probably have been required
for at least 5 years or so. Tell you customer to get with the program,
or make do with an inferior product, or be prepared to pay a lot to make
up the difference.
 
J

Jon Gomez

Mark said:
You'll almost certainly need some JNI calls to determine the screen
size.. and to detect when it changes too.

Alternatively, the user could supply arguments to the program to
manually set the screen size. Maybe not a very self-adapting solution,
but "portable".
Command line programs that are interactive and work "like windows" are
passe at this point, imo. I'm not surprised Sun has not invested any
effort into making them convenient to do in Java.

I guess I have a different opinion, but I respect yours.
Have you considered C/C++ and native libs? Any given OS is likely to
support several types of command windows -- good luck actually getting
them all working.

I'd require the user to support and run a GUI so Swing/AWT can be used.
Anything else is just too far beyond the pale these days. Even
servers, I've run into configuration tools that required
X-Windows/KDE/etc. The IT folks who do servers I talk to say the same
-- GUI required for servers these days. And probably have been required
for at least 5 years or so. Tell you customer to get with the program,
or make do with an inferior product, or be prepared to pay a lot to make
up the difference.

Sounds quite annoying. I would prefer servers for which you can alter
..conf files directly :), but I imagine they may not have any choice.

Jon.
 
T

Thomas Kellerer

Hi,

Mark Space, 14.03.2009 20:41:
Command line programs that are interactive and work "like windows" are
passe at this point, imo. I'm not surprised Sun has not invested any
effort into making them convenient to do in Java.
I'm not trying to simulate a windowing environment on the text console, all I want to do is give the user the ability to page through the result of a SQL statement.
Fn fact my application does have a Swing GUI, but sometimes there is no way of having an X-Window (e.g. when using SSH where you can't forward the necessary ports.
Have you considered C/C++ and native libs? Any given OS is likely to
support several types of command windows -- good luck actually getting
them all working.
No, as I want a portable Java only solution

Thomas
 
T

Thomas Kellerer

Jon Gomez, 17.03.2009 02:45:
Alternatively, the user could supply arguments to the program to
manually set the screen size. Maybe not a very self-adapting solution,
but "portable".

Yes, that's probably where I end up. Not nice, but workable.

I actually do have a solution for windows (parsing the output of the mode command) but I haven't found a solution for *nix. Parsing the output of the stty command does not seem to work as the spawned process is probably not associated with a terminal

I tried to retrieve the screen size from within a shell script because interactively $LINES and $COLUMNS are available (echo $LINES shows the correct value) but when trying to retrieve them using System.getenv() it returns null. I guess my workaround will be to pass those variables as System properties in my shell script starting the application. This will not reflect changes the user does to the window while my app is running but it's a good starting point.

Thanks
Thomas
 
A

Andreas Leitgeb

Thomas Kellerer said:
I would like to support paging [portions] of the output
[of an interactive program], but I can't find a way to do it.

from skimming through this thread, I have the impression you're
not yet satisfied with the answers so far.

Here's another one:
I had a slightly related problem of doing tty-stuff in a Java
text("console")-app, where I needed to turn off the tty-echo,
and the new password-api wasn't an Option.

This was like how I got "stty" to see the console:
String sttyCmd= on ? "echo" : "-echo";
Runtime.getRuntime().exec(new String [] {
"sh", "-c", "stty "+sttyCmd+" </dev/tty"
}).waitFor();

If you redirect output and error the same way to the same device,
then I'd expect that you could even start "less" this way. (It may
suffice redirecting only stdout for less to make it use the tty
and feed the data per stdin, but I'd recommend saving all the data
in a file first, and then starting less with the filename as argument
and stdin,out,err all tied to /dev/tty. In that case, make sure, you
use a tmpfilename that doesn't contain shell-meta characters, or you
will need to quote them for the shell.)

Sorry, not a really platform-agnostic answer, either, but you
seemed to already have a solution for windows, anyway
 
L

Lew

Thomas said:
Fn fact my application does have a Swing GUI, but sometimes there is no
way of having an X-Window (e.g. when using SSH where you can't forward
the necessary ports.

Are you speaking of firewall settings and such?
 
A

Andreas Leitgeb

Lew said:
Are you speaking of firewall settings and such?

Firewall settings cannot prohibit specifically X11-forwarding
with ssh (but only ssh as a whole). That notwithstanding,
a slow connection can make X11-forwarding impractically slow.
 
L

Lew

Andreas said:
Firewall settings cannot prohibit specifically X11-forwarding
with ssh (but only ssh as a whole). That notwithstanding,
a slow connection can make X11-forwarding impractically slow.

I was speaking to the OP's suggestion of scenarios "when using SSH where you
can't forward the necessary ports". I would like to know under what
circumstances that would pertain. "Impractically slow" may be a problem but
doesn't fit the OP's description.
 
T

Thomas Kellerer

Andreas Leitgeb, 17.03.2009 14:30:
Firewall settings cannot prohibit specifically X11-forwarding
with ssh (but only ssh as a whole). That notwithstanding,
a slow connection can make X11-forwarding impractically slow.
Hmm I am not at all knowledgable with ssh, X-servers and firewalls, so I might be mistaken.

But I do have a customer where I'm allowed to log into their system using ssh but I cannot open an X11 session. I'm not sure what the cause is.

Another solution would be to use port-forwarding to get to their database through my putty, but that is apparently blocked by their firewall as well. I can't comment on that, as I have no idea about firewall configuration and things like that.

But I guess this is off-topic here ;)

Thomas
 
A

Andreas Leitgeb

Lew said:
I was speaking to the OP's suggestion of scenarios "when using SSH where you
can't forward the necessary ports". I would like to know under what
circumstances that would pertain. "Impractically slow" may be a problem but
doesn't fit the OP's description.

It is possible that the administrators of some target machine have disabled
X11-forwarding (and also any other type of port-forwarding) per system's
/etc/ssh/sshd_config. (That looks more in sync to OP's description)

Another case: putty on a windows machine but no X11-emulation software
(and no permission to install/use one, either).

Is your curiosity satisfied now?
 
J

Jon Gomez

Thomas said:
Hmm I am not at all knowledgable with ssh, X-servers and firewalls, so I
might be mistaken.

But I do have a customer where I'm allowed to log into their system
using ssh but I cannot open an X11 session. I'm not sure what the cause is.
Another solution would be to use port-forwarding to get to their
database through my putty, but that is apparently blocked by their
firewall as well. I can't comment on that, as I have no idea about
firewall configuration and things like that.

But I guess this is off-topic here ;)

Thomas

So you can use SSH but not with port forwarding?

A quick Google search found this:

http://www.trilead.com/Products/Trilead_SSH_for_Java/

It claims is to be a pure Java implementation of a library for SSH,
distributed for free under a BSD-style license.

Maybe you can use something like this to create a standard connection
through SSH, run whatever shell commands on the remote host and read in
the results, without having to set up port forwarding.

Jon.
 
T

Thomas Kellerer

Jon Gomez, 17.03.2009 16:24:
So you can use SSH but not with port forwarding?

A quick Google search found this:

http://www.trilead.com/Products/Trilead_SSH_for_Java/

It claims is to be a pure Java implementation of a library for SSH,
distributed for free under a BSD-style license.

Maybe you can use something like this to create a standard connection
through SSH, run whatever shell commands on the remote host and read in
the results, without having to set up port forwarding.

Thanks for the answer but these are two different problems which do not relate directly to each other.

The application where I want to do the paging does not relate to the customer. It was just an example that I am in a situation where I can't use a GUI at all :)

Regards
Thomas
 
M

Martin Gregorie

Firewall settings cannot prohibit specifically X11-forwarding with ssh
(but only ssh as a whole). That notwithstanding, a slow connection can
make X11-forwarding impractically slow.

Some ssh clients, e.g. PuTTY which is text-only, won't accept X11
forwarding.

Have you looked at Jcurses <http://sourceforge.net/projects/javacurses> ?

I've not used it, but it seems to allow Java programs to output the
escape sequences needed to control the text terminal its being run from.
Its documentation is minimal, but AFAICT it accesses either /etc/termcap
or the terminfo database to get the escape sequences. Termcap and
Terminfo terminal definitions contain the terminal screen size specified
as characters wide and lines deep. Its probably overkill for what the OP
wants but is worth a look.
 
M

Martin Gregorie

I was speaking to the OP's suggestion of scenarios "when using SSH where
you can't forward the necessary ports". I would like to know under what
circumstances that would pertain. "Impractically slow" may be a problem
but doesn't fit the OP's description.

PuTTY is a commonly used Windows client that won't accept X11 forwarding
because it is text only. If the OP's workplace uses it, that's a pretty
good reason for not using a GUI.

To the OP - can you use VNC? The VNC client runs on many OSes including
Windows and does accept X11 port forwarding.
 
A

Andreas Leitgeb

Martin Gregorie said:
PuTTY is a commonly used Windows client that won't accept X11 forwarding
because it is text only.
If you had some X11-emulation on your Windows machine, then putty also
would do X11-forwarding. But this is entirely irrelevant to the actual
problem.

I also wrote a more-to-the-point answer for how one can connect
an external console app through Runtime.exec() to the current tty.
(its Message-ID: slrngruvbm.4ch.avl @ gamma.logic.tuwien.ac.at
without the spaces.)
but the OP hasn't yet commented on it. (perhaps he missed it?)
 
J

Jon Gómez

Martin Gregorie wrote:
[...]
I've not used it, but it seems to allow Java programs to output the
escape sequences needed to control the text terminal its being run from.
Its documentation is minimal, but AFAICT it accesses either /etc/termcap
or the terminfo database to get the escape sequences. Termcap and
Terminfo terminal definitions contain the terminal screen size specified
as characters wide and lines deep. Its probably overkill for what the OP
wants but is worth a look.

I looked at the source for version 0.9.5. It has native code for
accessing the console using "curses" and "conio" in the directory
/jcurses/src/native/.

Looking for and at the terminfo database, though, sounds like an
interesting idea. That might work for what he wants.

Jon.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top