-1

Is there a style to [xterm + bash scripts, commands] inside a custom frame?

i will wish this style, see example:

╭─────────────────────────┤text title1├────────────────────────╮
│                                                              │
│text, command, script, if else, echo,  cat, sed, any command  │
├──────────────────────────────────────────────────────────────┤
│text, command, script, if else, echo, ca t, sed, any command  │
│text, command, script, if else, echo, cat , sed, any command  │
│text, command, script, if else, echo, cat,  sed, any command  │
├──────────────────────────────────────────────────────────────┤
├─────────────────────────┤text title2├────────────────────────┤
│text, command, script, if else, echo, cat,  sed, any command  │
╰──────────────────────────────────────────────────────────────╯

font: Monospace

2 Answers 2

1

Fonts in terminal emulators are always monospace.

Producing that output in a shell script is just a matter of entering it literally, for instance as:

#! /bin/sh -
cat << 'EOF'
╭─────────────────────────┤text title1├────────────────────────╮
│                                                              │
│text, command, script, if else, echo,  cat, sed, any command  │
├──────────────────────────────────────────────────────────────┤
│text, command, script, if else, echo, ca t, sed, any command  │
│text, command, script, if else, echo, cat , sed, any command  │
│text, command, script, if else, echo, cat,  sed, any command  │
├──────────────────────────────────────────────────────────────┤
├─────────────────────────┤text title2├────────────────────────┤
│text, command, script, if else, echo, cat,  sed, any command  │
╰──────────────────────────────────────────────────────────────╯
EOF

In zsh, using the l[width][text1][text2] and r[width][text1][text2] parameter expansion flags (combined with m so they take into account the display width of characters), to do the padding and alignment:

#! /bin/zsh -
width=64
   header() print -rC1 '╭'${(ml[width/2-1][─][┤]r[width/2-1][─][├])^@}'╮'
     body() print -rC1 '|'${(ml[width/2-1]r[width/2-1])^@}'|'
    ruler() print -rC1 "├${(ml[width-2][─])}┤"
midheader() print -rC1 '├'${(ml[width/2-1][─][┤]r[width/2-1][─][├])^@}'┤'
   footer() print -rC1 "╰${(ml[width-2][─])}╯"

header 'text title1'
body '' some text ''
ruler
body '' 'more text' 'and more' ''
midheader 'text title2'
body '' 'some last text' ''
footer

Giving:

╭─────────────────────────┤text title1├────────────────────────╮
|                                                              |
|                             some                             |
|                             text                             |
|                                                              |
├──────────────────────────────────────────────────────────────┤
|                                                              |
|                           more text                          |
|                           and more                           |
|                                                              |
├─────────────────────────┤text title2├────────────────────────┤
|                                                              |
|                        some last text                        |
|                                                              |
╰──────────────────────────────────────────────────────────────╯

That assumes that you're in a locale whose charmap has those box drawing characters and that the script is encoded in that charmap and used in locales that use the same charmap.

Having the script encoded in UTF-8 and replace cat with iconv -f UTF-8 would make sure the boxes are drawn correctly in the user's locale as long as its charmap has those box drawing characters.

In zsh, you could replace the literal ╭─╮├┤╰╯│ with the corresponding $'\uXXXX' where XXXX is the character's unicode code point in hexadecimal (\u256D\u2500\u256E\u251C\u2524\u2570\u256F\u2502 respectively) which zsh will expand to the corresponding encoding in the user's locale (and fail with a "character not in range" error in those locales where those characters are not present).

Before UTF-8 was common place, the usual method to draw boxes was to tell the terminal emulator to switch to an alternate charset.

After tput smacs (set mode alternate char set; tput rmacs to switch back, though you might need a tput enacs to enable it first) in most terminals, characters such as `afgijklmnopqrstuvwxyz{|}~ become ◆▒°±␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π≠£·, and for those that don't the acsc terminfo capability give the translation. See the Line Graphics section in the terminfo(5) man page for details. Using those would make the output compatible with more terminals and locales don't use UTF-8, but is more complicated to do in a shell script without using dedicated applications that do box drawings such as dialog or tbl or terminal web browsers such as elinks or w3m which can dump a rendered form of an HTML table.

Again, using zsh makes it much easier than in bash as zsh has a builtin terminfo interface and more usable associative arrays.

The same header, body... functions in zsh using those could be written:

#! /bin/zsh -
zmodload zsh/terminfo || exit

typeset -A c=( ${(s[])terminfo[acsc]} )

# ┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│
# jklmnopqrstuvwx
width=64
((  pad = width - 2 ))
(( lpad = pad / 2 + $#terminfo[rmacs] ))
(( rpad = pad / 2 + $#terminfo[smacs] ))
 left=$terminfo[rmacs]       right=$terminfo[smacs] line=$c[q]
hleft=$c[u]$terminfo[rmacs] hright=$terminfo[smacs]$c[t]

   header() print -rC1 -- $terminfo[smacs]$c[l]${(mpl[lpad][$line][$hleft]r[rpad][$line][$hright])^@}$c[k]$terminfo[rmacs]
     body() print -rC1 -- $terminfo[smacs]$c[x]${(mpl[lpad][ ][$left]r[rpad][ ][$right])^@}$c[x]$terminfo[rmacs]
    ruler() print -rC1 -- "$terminfo[smacs]$c[t]${(mpl[pad][$line])}$c[u]$terminfo[rmacs]"
midheader() print -rC1 -- $terminfo[smacs]$c[t]${(mpl[lpad][$line][$hleft]r[rpad][$line][$hright])^@}$c[u]$terminfo[rmacs]
   footer() print -rC1 -- "$terminfo[smacs]$c[m]${(mpl[pad][$line])}$c[j]$terminfo[rmacs]"

header 'text title1'
body '' some text ''
ruler
body '' 'more text' 'and more' ''
midheader 'text title2'
body '' 'some last text' ''
footer
0

In addition to what Stéphane said, there's also already programs that draw frames around output of programs, though they're often pretty usage-specific:

cowsay:

$> echo 'Welcome to the shire. Party business only.' | cowsay
 ______________________________________
/ Welcome to the shire. Party business \
\ only.                                /
 --------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

pandoc:

$> echo 'Message for the user\nWelcome to the shire. Party business only.\nMore Text.' | pandoc -f tsv -tgfm
| Message Title                              |
|--------------------------------------------|
| Welcome to the shire. Party business only. |
| More Text.                                 |

Note that there's really not much magic involved to build something yourself.

For example, if you want to print your header

╭─────────────────────────┤text title1├────────────────────────╮

in a script, you'd do something like

print_n_chars () {
  local n=$1
  local char=$2
  printf "${char}"'%.s' $(seq 1 ${n})
}
print_title () {
  local linelength=$1
  local text="┤$2├"
  local textlength=${#text}
  local leftpad=$(( (linelength - textlength - 2) / 2 ))
  local rightpad=$(( (linelength - textlength - 2) - leftpad ))
  printf '╭%s%s%s╮\n' "$(print_n_chars ${leftpad} "─")" "${text}" "$(print_n_chars ${rightpad} "─")"
}
print_text () {
  local linelength=$1
  shift
  for line in "$@"; do
    printf "│%$((linelength - 2))s│\n" "${line}"
  done
}

title="text title1"
text='Welcome to the shire. Party business only.'
print_title 50 "${title}"
print_text 50 "${text}"
7
  • Beware length is not necessarily the same as display width as some characters have zero or double width. Commented Nov 23, 2024 at 13:58
  • print_title 125, print_text 125, text is alignment to right not center...can y check it? for any command put in text? example text= hello world $hello or read -p -r press any keys to continune..etc? Commented Nov 23, 2024 at 14:17
  • if i add many text so will be multiple variable: $text1, $text2, $text3...or $text[##] ..? Commented Nov 23, 2024 at 14:24
  • @Manuelsongokuh We're really not here to do your homework, you will need to learn how to modify things to do what you want yourself. The things you ask can trivially just be tried out. So try! Commented Nov 23, 2024 at 14:26
  • - example: print_text 125 "${text} for i in /home/* ; do ....... done ? Commented Nov 23, 2024 at 14:30

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.