Open martensjostrand opened 4 years ago
It is certainly possible to reuse https://github.com/maximbaz/spaceship-prompt/commit/815b68c70f21c5512765c87985897b98b8ed232c - check if starship has been called for the first time and pass it that information. This would prevent printing the newline after a shell initiation.
However, since starship includes the newline in PS1
it would still display the newline when issuing Ctrl+L
/clear
. Correct me if I'm wrong.
I also find this very visually distracting, particularly on clearing the screen.
VSCode integrated terminal adds more padding on top of this which I find very annoying.
How about something like this?
diff --git a/Cargo.toml b/Cargo.toml
index 4837654..17b0a3d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -59,6 +59,7 @@ open = "1.4.0"
unicode-width = "0.1.8"
textwrap = "0.12.0"
term_size = "0.3.2"
+crossterm = "0.17"
# Optional/http:
attohttpc = { version = "0.15.0", optional = true, default-features = false, features = ["tls", "form"] }
diff --git a/src/print.rs b/src/print.rs
index 369f3b3..47e4783 100644
--- a/src/print.rs
+++ b/src/print.rs
@@ -4,6 +4,7 @@ use rayon::prelude::*;
use std::fmt::{self, Debug, Write as FmtWrite};
use std::io::{self, Write};
use unicode_width::UnicodeWidthChar;
+use crossterm::cursor;
use crate::context::{Context, Shell};
use crate::module::Module;
@@ -23,7 +24,11 @@ pub fn get_prompt(context: Context) -> String {
// Write a new line before the prompt
if config.add_newline {
- writeln!(buf).unwrap();
+ if let Ok(pos) = cursor::position() {
+ if pos != (0, 0) {
+ writeln!(buf).unwrap();
+ }
+ }
}
// A workaround for a fish bug (see #739,#279). Applying it to all shells
I think this should eliminate the Ctrl+L
/clear
problem as well and handle the root
situation as well.
Note, I am not a Rust programmer. In fact, this is my first Rust code, so you can probably do better. I have only tested this using cargo run -- prompt
as I do not know how to use this binary outside of the project tree.
@Sharpeee Just a quick observation. On my machine (Linux urxvt+Bash), it takes over 1sec to render when running the patched binary as a prompt (on $PATH
).
@yuri1969 I have seen some weird behaviour as well. It works as expected when I run it through cargo
, but fails when running as stand-alone. I will look into it when I have time.
If it does not work using crossterm
, maybe there is another way to get the current cursor position?
FYI: I have moved back to a one line prompt (not because of this issue), so I will not look any more at this.
Related issue at spaceship: https://github.com/denysdovhan/spaceship-prompt/issues/462
Looks like Spaceship hasn't solved this issue either. I tried applying the patch from https://github.com/maximbaz/spaceship-prompt/commit/815b68c70f21c5512765c87985897b98b8ed232c to the current version of spaceship, but it straight-up doesn't work--it just disables the newlines altogether.
The issue that @yuri1969 brought up is also relevant here, since even if we fix the first newline (when the shell initializes), we have no way of knowing if the screen's been cleared, since that happens while the shell is still running.
It seems that at least some shells implement screen clear by just emitting a form-feed character, so there's no way in general to figure out if the screen has been cleared, because the shell doesn't have to tell us what it's doing, and starship does not read the output of the shell it's currently attached to (nor should it).
I really don't want to tie the prompt to a terminal either. While the crossterm trick is an interesting idea, we already have several terminal compatibility issues, and I the last thing I want is to make those more explicit.
So at the moment, I'm stumped. In essence, we need some way to detect if we're printing at the top of the terminal (because the shell was just launched, or because the user cleared the screen with CTRL+L, or because the user ran echo -e '\0033\0143'
, or because the VTE-based terminal received a Reset-and-Clear command, or because an xterm-based system received Esc-c......) but without being explicitly tied to a terminal type.
If we're shooting for ANSI-compatible terminals, I suppose we could try using ANSI escape codes to query the cursor position, but we'd need some way to intercept that response before it gets printed to the terminal. We do currently use ANSI color codes already, but I don't know how general the support is for the full ANSI escape code set: it might be a very different game for a terminal to support just color codes vs. a full set of ANSI control sequences.
While I see how this issue is the commonality of the others referenced and closed, and an extra empty line is annoying–I don't feel it's as significant as the first line of the prompt being missing after clearing the buffer (when you run Clear Buffer in e.g. iTerm), and may garner more attention from the community.
I.e. #1601 seems like it should be left open, even if it shares the cause of #560.
I wasn't tracking #1601 closely, but the post there mentions that zprezto doesn't have this issue, which we could potentially investigate for a solution (I had tried previously to look at how this was supposedly solved in a spaceship fork, but the patches there just caused my shell to crash and I couldn't work out why).
I have a question.. Will this bug be fixed and merged say EVER in future?
I have a question.. Will this bug be fixed and merged say EVER in future?
If you have an idea for how to address this issue, pull requests are welcome. 😊
I don't know if this is possible, but instead of adding a newline before the prompt, would it be possible to add it after any output?
@cbrnr The tricky part is that we don't control that from within starship. If this were a shell-language-based prompt, this would be much easier to do, but currently (as far as I know), detecting that output occurred would require us to write a hook into the shell init scripts, then examine that from starship (and we'd have to do this for all 10 shells we currently support, plus potentially additional ones we have support requests for like mksh
).
zsh
users can add this to their .zshrc
:
precmd() { precmd() { echo "" } }
Thanks @justaskz, this is a nice workaround which I will use (in combination with add_newline = false
).
# Put new-line inside of ($all) variable)
format = """($all
)$character"""
add_newline = false
[line_break]
disabled = true
This config successfully omits empty lines (even for clear) while also ensuring the prompt itself starts on its own line when output exists ahead of it.
See: https://starship.rs/config/#conditional-format-strings
Edit: Above snippet intentionally omits the single empty line used to separate commands. To include it anyways, use this instead:
# Put extra empty new-line inside of ($all) variable)
format = """($all
)$character"""
add_newline = false
[line_break]
disabled = true
@JJJ isn't your suggestion the same as add_newline = false
and [line_break.disabled] = false
?
It seems to be the same on windows terminal + powershell:
The issue I'm having is with add_newline = true
and [line_break.disabled] = false
, this newline specifically:
Using @JJJ 's solution did work to remove the new_line, but also removed the new_line after commands, which is important for me.
I tried to adapt @justaskz 's answer for fish shell by putting the following in my ~/.config/fish/config.fish
like this:
function fish_preexec
echo ""
end
This doesn't work.
The following also doesn't work:
function fish_prompt
echo ""
end
I understand it's a bit more complicated to solve completely within starship but could I have any workarounds for fish? Thanks!
@AnkushMalaker try this for fish? Looks like the syntax is --on-event
to hook into those events
~/.config/fish/config.fish
:
if status is-interactive
function echo_prompt --on-event fish_postexec
echo ""
end
end
With the defaults of
With starship.toml
(for example an empty starship.toml
)add_newline = false
in starship.toml
, screenshot:
Thanks for the suggestion @domsleee , unfortunately that doesn't work either. @justaskz , just to confirm, can your suggestion be used along with "new_line = true"? If not, then I assume the behaviour of suggestion by JJJ is the same.
@AnkushMalaker my solution is tested only on zsh
For ble.sh/bash users, you don't have to use add_newline = true
, instead, add bleopt prompt_ruler=empty-line
to .blerc
. This will get all the things done, including clear
and Ctrl+L
. Also see blerc.template
zsh
users can add this to their.zshrc
:precmd() { precmd() { echo "" } }
I would add that a similar approach for bash
in .bashrc
is this:
my_precmd() {
echo ''
}
export PROMPT_COMMAND=my_precmd
# By defining starship after, PROMPT_COMMAND is wrapped by the init script
eval "$(starship init bash)"
With add_newline = false
in starship config
I assume the behaviour of suggestion by JJJ is the same.
👋 I updated my snippet to include both configs (single & double breaks between commands)
zsh
users can add this to their.zshrc
:precmd() { precmd() { echo "" } }
I would add that a similar approach for
bash
in.bashrc
is this:my_precmd() { echo '' } export PROMPT_COMMAND=my_precmd # By defining starship after, PROMPT_COMMAND is wrapped by the init script eval "$(starship init bash)"
With
add_newline = false
instarship config
I found that using clear still adds a new line in zsh, so I added this alias for clear
clear="precmd() { precmd() { echo } } && clear"
Bug Report
Current Behavior
When
add_line
is enabled a new line is added at the beginning of every new terminal window/tab.Expected Behavior
Using
add_line
should not add a new line above the first line of every window / tab.Additional context/Screenshots
Environment
Relevant Shell Configuration
Starship Configuration
Possible Solution
The above if-statement from https://github.com/starship/starship/blob/master/src/print.rs#L23 could be changed into something inspired by Spaceship's solution: https://github.com/maximbaz/spaceship-prompt/commit/815b68c70f21c5512765c87985897b98b8ed232c found in https://github.com/denysdovhan/spaceship-prompt/issues/462