Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Use real terminal size for show (fix #7295 and #4513) #7297

Merged
merged 5 commits into from
Jun 18, 2014

Conversation

simonster
Copy link
Member

Replaces tty_rows()/tty_cols() with tty_size(), which (through Terminals) calls uv_tty_get_winsize() to get the terminal size.

The reason for the change is that uv_tty_get_winsize() gives both the rows and columns, so if we wanted to keep tty_rows()/tty_cols(), we'd have to call uv_tty_get_winsize() once for each, even though they are nearly always used together. AFAIK none of the methods whose signatures I've changed were ever exported, but this could still break some packages.

I am assuming that calling uv_tty_get_winsize() is not expensive enough that it's worth registering a SIGWINCH handler and only updating the numbers on window resize, as readline used to do. My Linux system can do >10^6 calls to tty_size() per second, which seems plenty fast to me. Given how cheap the call is, it may not even be worth replacing tty_rows()/tty_cols(). Of course other platforms may be different.

@simonster simonster changed the title RFC: Fix #7295, #4513 RFC: Use terminal size for printing (fix #7295 and #4513) Jun 17, 2014
@simonster simonster changed the title RFC: Use terminal size for printing (fix #7295 and #4513) RFC: Use real terminal size for show (fix #7295 and #4513) Jun 17, 2014
@@ -596,6 +596,7 @@ function check_metadata()
end

function warnbanner(msg...; label="[ WARNING ]", prefix="")
cols = Base.tty_size()[1]
warn(prefix="", Base.cpad(label,Base.tty_cols(),"="))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still using tty_cols. Is that intended?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, looks like I didn't finish making those changes. I'll fix.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Jun 18, 2014

The only way to get this info for Mintty is through SIGWICH, or by sending a VT100 sequence to poll for it (currently we just hardcode a size)

@simonster
Copy link
Member Author

AFAIK SIGWINCH only tells you that the terminal size has changed, not what it is. In any case, if uv_tty_get_winsize() is broken, then that seems like it should be fixed in libuv and not here. Using the real terminal size where uv_tty_get_winsize() works seems better than assuming all terminals are 80x25, which is what we do now.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Jun 18, 2014

Mintty isn't a tty, its a pipe. And the libuv folks have mostly ignored my PR so far

@ivarne
Copy link
Sponsor Member

ivarne commented Jun 18, 2014

Deprecation?

These functions are definitely used by packages, and printing methods are typically not well tested.

Replaces tty_rows()/tty_cols() with tty_size(), which calls
uv_tty_get_winsize() to get the terminal size
I realized that the REPL uses size without try, so if it might fail on
a normal system would probably already know about it.
These were never exported, but there are a decent number of packages
that use them.
@simonster
Copy link
Member Author

Added deprecation warnings (not using @deprecate, since that would export them) and removed the try, since I realized that if the libuv call errors the REPL would be broken in various ways anyway.

@johnmyleswhite
Copy link
Member

This PR makes me so happy.

@johnmyleswhite
Copy link
Member

FWIW, here's a place where you'd want to get just one dimension of the size: https://github.com/JuliaStats/DataFrames.jl/blob/master/src/dataframe/io.jl#L1079

@simonster
Copy link
Member Author

I'm not entirely set on the API change, since I don't think performance matters here, but there is some logic to returning both the rows and the columns since that's what the syscall gives us.

@johnmyleswhite
Copy link
Member

I'm not opposed to it. Just noting that there are cases where you only want 1 of the 2. Was originally thinking you'd support a Base.tty_size(1) style interface.

@simonster
Copy link
Member Author

We could do that too (or even keep Base.tty_rows()/Base.tty_cols()), but Base.tty_size()[1] seems concise enough.

function tty_rows()
depwarn("tty_rows() is deprecated, use tty_size() instead", :tty_rows)
tty_size()[1]
end
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this be done with

@deprecate tty_rows() tty_size()[1]

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my first thought, but @deprecate calls export tty_rows, which seems undesirable since tty_rows was not previously exported.

@JeffBezanson
Copy link
Sponsor Member

Ok ready to merge I think?

simonster added a commit that referenced this pull request Jun 18, 2014
RFC: Use real terminal size for show (fix #7295 and #4513)
@simonster simonster merged commit 9e1eda9 into master Jun 18, 2014
@simonster simonster deleted the sjk/tty_size branch June 18, 2014 17:34
@stevengj
Copy link
Member

Does this still allow you to override the TTY size using the LINES and COLUMNS environment variables? That's important for IJulia (because the display is has nothing to do with the tty in which julia is running).

@vtjnash
Copy link
Sponsor Member

vtjnash commented Jun 19, 2014

Shouldn't ijulia be making it's own Terminal type?

@stevengj
Copy link
Member

@vtjnash, I'm not sure exactly what you're proposing. The IJulia interface is not really a "terminal" in the usual sense, and the current tty_size code seems oriented towards REPL.outstream returning a TTYTerminal, which doesn't seem applicable here.

Couldn't tty_size simply fall back to get(ENV, "LINES", 24), get(ENV, "COLUMNS", 80) rather than simply (24, 80) as it does now?

@simonster
Copy link
Member Author

That would be fine with me.

stevengj added a commit to JuliaLang/IJulia.jl that referenced this pull request Jun 19, 2014
simonster added a commit that referenced this pull request Jun 19, 2014
Ref #7297

We really need a better solution for this generally (see #4117/#5709)
but I suppose reinstating `ENV` as fallback is easy for now.
@vtjnash
Copy link
Sponsor Member

vtjnash commented Jun 20, 2014

ah, yes. tty_size should probably allow overloading in that case:

tty_size() = isdefined(Base, :active_repl) ? tty_size(REPL.outstream(Base.active_repl)) : tty_size(TextTerminals)
tty_size(os::Terminals.TTYTerminal) = size(os)
tty_size(::Any) = tty_size(TextTerminals)
tty_size(::Type{TextTerminals}) = (get(ENV, "LINES", 24), get(ENV, "COLUMNS", 80)

@StefanKarpinski
Copy link
Sponsor Member

Using the environment for that may not be the best approach in the longer term but for now that seems ok. I guess an advantage of using the environment is that it propagates to child processes.

@simonster
Copy link
Member Author

As discussed in #4117/#5709, what we really want is to find a way to get the terminal size to show that isn't a hack. One possibility is to make tty_size operate on the IO with a fallback to 80x24, which is logical if the IO is a TTY, but then IJulia etc. need to implement their own IO to set tty_size. I'm also not sure it makes sense to tie the other output formatting parameters discussed in #5709 to an IO. We could also start passing show something that isn't an IO, but that would presumably break a lot of things.

@JeffBezanson
Copy link
Sponsor Member

There might be an argument for passing show a kind of "formatting object", which is an IO that wraps another IO object, but also holds info about how to print things. That may be the only way to tame the complexity of print settings (size, output limiting, compact/full, etc.) without either global state, or passing around extra arguments everywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants