2

I've been working on a bold function as a proof-of-concept and a challenge to myself. I am trying to input text (e.g.foo) and have it print to standard output as it's bold counterpart (foo).

Context:

I've been using echo and basing it off of my PROMPT variable in my theme file. I am not using any frameworks.

The theme uses codes like %B%n%b to bold the username (%n), but I don't know how to replace that %n with user input ($1). Any Help?

Edit: Attempted Code

echo '%B'"$1"'%b'

-tried with and without quotes in various locations, as well as with sub-shell ({})

2 Answers2

1

%B and %b are examples of prompt sequences, and usually can only be used for formatting prompts. For normal scripting, you can use the tput command to achieve what you want:

echo "$(tput bold)$1$(tput sgr0)"

Alternatively, you could output the ECMA-48 ("ANSI") escape codes directly. I wouldn't recommend this though, because it's less portable across terminals. (It's quite hard, nowadays in the 21st century, to encounter a terminal that doesn't implement ECMA-48 and the basic ECMA-48 SGR features like boldface, but since you are challenging yourself to learn this, you should learn that terminals do not have the guarantee of understanding exactly the same control sequences as one another. You should also learn that there still remain a few terminal emulators where boldface is a colour change and not a font weight change.)

echo $'\e[1m'"$1"$'\e[22m'

Notice the use of Korn-style quoting for the control sequences. In the general case, the echo command may or may not itself interpret \e sequences if not Korn-style quoted and such escape sequences work differently in different shells, or even different versions of the same shell; and conversely not all shells understand Korn-style quoting. See "Why is printf better than echo?" for the whole tale and why echo is not a good idea if you are addressing anything other than a single specific (version of a) shell.

printf '\e[1m%s\e[22m' "$1"

Notice that SGR 0 (corresponding to \e[0m, which is what tput sgr0 also usually nowadays emits) turns off everything, which may not be what you want if you are also using underlining, italics, colours, reverse video, or other graphic renditions. To turn off boldface specifically, SGR 22 is the graphic rendition code, which turns off boldface and faint, restoring "medium" font weight. (The Set Graphic Rendition control sequence lets you set four font weights: bold, demibold, medium, and light.)

Since you are using the Z shell, you can also use its own built-in print command instead of using echo or printf at all. The built-in print can be told to understand Z shell prompt expansion sequences:

print -P '%B'"$1"'%b'

Of course, your $1 string must not contain other expansion sequences itself, nor indeed any SGR control sequences for changing boldface. And this won't give you the challenge of learning tput and how terminfo capabilities work.

JdeBP
  • 68,745
1

% parameter expansion flag can be used:

echo "${(%):-%B}$1${(%):-%b}"

zsh has a print builtin which has -P to perform prompt expansions (Note: if $1 contains prompt sequences, they will be interpreted as such):

print -P -- "%B$1%b"

You may want to print all arguments instead of just the first positional parameter (use $@/$*).

You may want to print nothing (not even a newline) if no parameters were given (print only if $# is greater than zero, or use + parameter expansion & tell print to output columns).

You may want to disable echo-like interpretation of backslash escapes (print -r).

print_bold() {
  local IFS=' '
  print -rC1 -- ${1+"${(%):-%B}$*${(%):-%b}"}
}

"$*" expands to positional parameters separated by first character of IFS (which is a space by default, but has been set explicitly above).

guest
  • 2,134