Commit d0d8945
Changed files (3)
modules
modules/core/shell.nix → modules/core/shell/default.nix
@@ -1,41 +1,52 @@
{den, ...}: {
den.aspects.core.includes = [den.aspects.core.shell];
den.aspects.core.shell = {
- nixos = {pkgs, ...}: let
- in {
- environment.systemPackages = [pkgs.nur.repos.hpcesia.flyline];
+ nixos = {
+ pkgs,
+ lib,
+ ...
+ }: {
+ # Flyline right prompt support. RPS1 wiring is upstream PR #7673;
+ # multi-line right prompts are a local extension.
+ nixpkgs.overlays = [
+ (final: prev: {
+ starship = prev.starship.overrideAttrs (old: {
+ patches =
+ (old.patches or []) ++ [./starship-flyline-rps1.patch];
+ });
+ })
+ ];
+
+ environment.systemPackages = [
+ pkgs.starship
+ pkgs.nur.repos.hpcesia.flyline
+ ];
+
+ environment.etc."starship.toml".source = ./starship.toml;
+
+ environment.variables.STARSHIP_CONFIG = "/etc/starship.toml";
programs.bash = {
enable = true;
completion.enable = true;
+ promptInit = "";
interactiveShellInit = ''
enable -f ${pkgs.nur.repos.hpcesia.flyline}/lib/libflyline.so flyline
flyline mouse --mode disabled
flyline set-cursor --backend terminal
- '';
- promptInit = ''
- # Provide a nice prompt if the terminal supports it.
- if [ "$TERM" != "dumb" ] || [ -n "$INSIDE_EMACS" ]; then
- PROMPT_COLOR="1;31m"
- ((UID)) && PROMPT_COLOR="1;32m"
- # Show the hostname only when connected via SSH.
- SSH_HOST=""
- [ -n "$SSH_CONNECTION" ] && SSH_HOST="@$HOSTNAME"
- if [ -n "$INSIDE_EMACS" ]; then
- # Emacs term mode doesn't support xterm title escape sequence (\e]0;)
- PS1="\[\033[$PROMPT_COLOR\]\u$SSH_HOST\[\033[0m\]: \[\033[1;34m\]\w\[\033[0m\]\n\[\033[$PROMPT_COLOR\]\\$\[\033[0m\] "
- else
- PS1="\[\033[$PROMPT_COLOR\]\u$SSH_HOST\[\033[0m\]: \[\033[1;34m\]\w\[\033[0m\]\n\[\033[$PROMPT_COLOR\]\\$\[\033[0m\] "
- PS1="\[\e]0;\u@\h: \w\a\]$PS1"
- fi
- if test "$TERM" = "xterm"; then
- PS1="\[\033]2;\h:\u:\w\007\]$PS1"
- fi
- # To separate previous command output
- PROMPT_RULER="\e[90m─\e[0m"
- PS1_FINAL="\[\033[$PROMPT_COLOR\]\u@\h\\$\[\033[0m\] "
- PROMPT_RULER_FINAL="empty-line"
+ flyline create-prompt-widget custom \
+ --name STARSHIP_TRANSIENT \
+ --command '${lib.getExe pkgs.starship} prompt --profile transient' \
+ --block
+ PS1_FINAL=STARSHIP_TRANSIENT
+
+ RPS1_FINAL=""
+
+ PROMPT_RULER="empty-line"
+
+ if [ "$TERM" != "dumb" ]; then
+ eval "$(${lib.getExe pkgs.starship} init bash)"
fi
'';
};
@@ -51,9 +62,9 @@
}
if [[ ";''${PROMPT_COMMAND[*]:-};" != *";__ix_history_flush;"* ]]; then
if [[ "$(declare -p PROMPT_COMMAND 2>&1)" == "declare -a"* ]]; then
- PROMPT_COMMAND=(__ix_history_flush "''${PROMPT_COMMAND[@]}")
+ PROMPT_COMMAND=("''${PROMPT_COMMAND[@]}" __ix_history_flush)
else
- PROMPT_COMMAND="__ix_history_flush''${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
+ PROMPT_COMMAND="''${PROMPT_COMMAND:+$PROMPT_COMMAND;}__ix_history_flush"
fi
fi
@@ -71,9 +82,9 @@
}
if [[ ";''${PROMPT_COMMAND[*]:-};" != *";__ix_fix_term_size;"* ]]; then
if [[ "$(declare -p PROMPT_COMMAND 2>&1)" == "declare -a"* ]]; then
- PROMPT_COMMAND=(__ix_fix_term_size "''${PROMPT_COMMAND[@]}")
+ PROMPT_COMMAND=("''${PROMPT_COMMAND[@]}" __ix_fix_term_size)
else
- PROMPT_COMMAND="__ix_fix_term_size''${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
+ PROMPT_COMMAND="''${PROMPT_COMMAND:+$PROMPT_COMMAND;}__ix_fix_term_size"
fi
fi
'';
modules/core/shell/starship-flyline-rps1.patch
@@ -0,0 +1,115 @@
+diff --git a/src/context.rs b/src/context.rs
+--- a/src/context.rs
++++ b/src/context.rs
+@@ -63,6 +63,9 @@ pub struct Context<'a> {
+ /// Which prompt to print (main, right, ...)
+ pub target: Target,
+
++ /// Whether the right prompt is allowed to span multiple lines
++ pub multiline: bool,
++
+ /// Width of terminal, or zero if width cannot be detected.
+ pub width: usize,
+
+@@ -178,6 +181,7 @@ impl<'a> Context<'a> {
+ repo: OnceLock::new(),
+ shell,
+ target,
++ multiline: false,
+ width,
+ env,
+ #[cfg(test)]
+@@ -207,6 +211,12 @@ impl<'a> Context<'a> {
+ self
+ }
+
++ /// Allow the right prompt to span multiple lines
++ pub fn with_multiline(mut self, multiline: bool) -> Self {
++ self.multiline = multiline;
++ self
++ }
++
+ // Tries to retrieve home directory from a table in testing mode or else retrieves it from the os
+ pub fn get_home(&self) -> Option<PathBuf> {
+ home_dir(&self.env)
+diff --git a/src/init/starship.bash b/src/init/starship.bash
+--- a/src/init/starship.bash
++++ b/src/init/starship.bash
+@@ -78,9 +78,14 @@ starship_precmd() {
+ STARSHIP_START_TIME=""
+ fi
+ PS1="$(::STARSHIP:: prompt "${ARGS[@]}")"
++ local nlns=${PS1//[!$'\n']}
+ if [[ ${BLE_ATTACHED-} ]]; then
+- local nlns=${PS1//[!$'\n']}
+ bleopt prompt_rps1="$nlns$(::STARSHIP:: prompt --right "${ARGS[@]}")"
++ elif [[ ${FLYLINE_VERSION-} ]]; then
++ local rps1 rnlns
++ rps1="$(::STARSHIP:: prompt --right --multiline "${ARGS[@]}")"
++ rnlns=${rps1//[!$'\n']}
++ RPS1="${nlns:${#rnlns}}$rps1"
+ fi
+ STARSHIP_PREEXEC_READY=true # Signal that we can safely restart the timer
+ }
+diff --git a/src/main.rs b/src/main.rs
+--- a/src/main.rs
++++ b/src/main.rs
+@@ -127,6 +127,9 @@ enum Commands {
+ /// Print the right prompt (instead of the standard left prompt)
+ #[clap(long)]
+ right: bool,
++ /// Allow the right prompt to span multiple lines
++ #[clap(long, requires = "right")]
++ multiline: bool,
+ /// Print the prompt with the specified profile name (instead of the standard left prompt)
+ #[clap(long, conflicts_with = "right")]
+ profile: Option<String>,
+@@ -227,6 +230,7 @@ fn main() {
+ Commands::Prompt {
+ properties,
+ right,
++ multiline,
+ profile,
+ continuation,
+ } => {
+@@ -236,7 +240,7 @@ fn main() {
+ (_, _, true) => Target::Continuation,
+ (_, _, _) => Target::Main,
+ };
+- print::prompt(properties, target);
++ print::prompt(properties, target, multiline);
+ }
+ Commands::Module {
+ name,
+diff --git a/src/print.rs b/src/print.rs
+--- a/src/print.rs
++++ b/src/print.rs
+@@ -69,8 +69,8 @@ fn test_grapheme_aware_width() {
+ assert_eq!(11, "\x1B[35;6mnormal text".width_graphemes());
+ }
+
+-pub fn prompt(args: Properties, target: Target) {
+- let context = Context::new(args, target);
++pub fn prompt(args: Properties, target: Target, multiline: bool) {
++ let context = Context::new(args, target).with_multiline(multiline);
+ let stdout = io::stdout();
+ let mut handle = stdout.lock();
+
+@@ -143,7 +143,7 @@ pub fn get_prompt(context: &Context) -> String {
+ );
+
+ let module_strings = root_module.ansi_strings_for_width(Some(context.width));
+- if config.add_newline && context.target != Target::Continuation {
++ if config.add_newline && !matches!(context.target, Target::Continuation | Target::Right) {
+ // continuation prompts normally do not include newlines, but they can
+ writeln!(buf).unwrap();
+ }
+@@ -153,7 +153,7 @@ pub fn get_prompt(context: &Context) -> String {
+ wrap_colorseq_for_shell(AnsiStrings(&module_strings).to_string(), context.shell);
+ write!(buf, "{shell_wrapped_output}").unwrap();
+
+- if context.target == Target::Right {
++ if context.target == Target::Right && !context.multiline {
+ // right prompts generally do not allow newlines
+ buf = buf.replace('\n', "");
+ }
modules/core/shell/starship.toml
@@ -0,0 +1,61 @@
+"$schema" = 'https://starship.rs/config-schema.json'
+
+format = """
+$username\
+$hostname\
+[: ](white)\
+$directory\
+$line_break\
+$character
+"""
+
+right_format = """
+$nix_shell\
+$time\
+$line_break\
+[<](white)
+"""
+
+add_newline = false
+
+[profiles]
+transient = "$username$hostname$character"
+
+[username]
+disabled = false
+show_always = true
+style_user = "green bold"
+style_root = "red bold"
+format = '[$user]($style)'
+
+[hostname]
+disabled = false
+ssh_only = false
+style = "yellow bold"
+format = '[@$hostname]($style)'
+
+[directory]
+disabled = false
+style = "blue"
+read_only_style = "red"
+read_only = "[ro]"
+format = '[$path]($style)[$read_only]($read_only_style)'
+
+[character]
+disabled = false
+success_symbol = "[\\$](bold green)"
+error_symbol = "[\\$](bold red)"
+format = "$symbol "
+
+[nix_shell]
+disabled = false
+heuristic = true
+symbol = "nix"
+format = "[$symbol\\[$name\\]]($style) "
+
+[time]
+disabled = false
+format = "[ $time]($style)"
+time_format = "%R"
+utc_time_offset = "local"
+style = "dimmed white"