1

Still learning shell scripting and ZSH. But was wondering if someone knew how to create an array of simple objects think, json type objects/hashes, and then print the properties of each object in column format in different colors.

I want to create a specific function in my zsh plugin that prints to my terminal in a very precise way.

Open questions:

1.) How to print specific strings in different colors

2.) How to define arrays of basic objects with multiple key/value pairs

The following pseudo code will hopefully clarify what I am trying to do.

function display-collection() {
  collection=(
    {param1: foo1, param2: bar1, param3: baz1 }
    {param1: foo2, param2: bar2, param3: baz2 }
    {param1: foo3, param2: bar3, param3: baz3 }
    {param1: foo4, param2: bar4, param3: baz4 }
    {param1: foo5, param2: bar5, param3: baz5 }
    {param1: foo6, param2: bar6, param3: baz6 }
  )
  print -l $collection
}

Make the above function spit out the contents to the terminal in color

foo1 (RED TEXT) bar1 (DEFAULT COLOR) baz1 (YELLOW COLOR)
foo2 (RED TEXT) bar2 (DEFAULT COLOR) baz2 (YELLOW COLOR)
foo3 (RED TEXT) bar3 (DEFAULT COLOR) baz3 (YELLOW COLOR)
foo4 (RED TEXT) bar4 (DEFAULT COLOR) baz4 (YELLOW COLOR)
foo5 (RED TEXT) bar5 (DEFAULT COLOR) baz5 (YELLOW COLOR)
foo6 (RED TEXT) bar6 (DEFAULT COLOR) baz6 (YELLOW COLOR)

In other words column text like this with each column color coorindated the foo values would be red, the bar values would be default and the baz values would be yellow

foo1 bar1 baz1
foo2 bar2 baz2
foo3 bar3 baz3
foo4 bar4 baz4
foo5 bar5 baz5
foo6 bar6 baz6

Bonus points if I can format the alignment to be nice ordered columns, with arbitrary delimiters/separators.

foo1       : bar1                = baz1
string1    : some string         = another string
string2    : some longer string  = another longer string
helloworld : This is a function  = it prints helloworld
Gordon Potter
  • 5,802
  • 9
  • 42
  • 60

1 Answers1

5

Question #1: see this StackOverflow question. A Google search for "colored function output linux" gives a bunch of links which I'm assuming you've read (because you did search prior to asking this question, right..?). What's your specific issue with colored output?


Question #2: Is a simple array not enough? Your example:

param1: foo1, param2: bar1, param3: baz1
param1: foo2, param2: bar2, param3: baz2

This appears to always have param1 in the 1st, 4th, 7th (ie, 1+3Nth position). param2 in 2+3Nth, and param3 in 3+3Nth. Inserting param1: into your data-structure seems awfully redundant.
A 1-dimensional array would fit this; it's just a matter of printing.

Chapter 2 of 'A Users Guide to the Z-Shell', section 2.4.1, "Arrays", is about Arrays in zsh.

I would create a function specifically to print an array.

function print-array-collection() {
    autoload -Uz colors && colors # See Note 3.
    local array_name=$1

    local array_length=${#${(P)${array_name}}}
    for (( i = 1; i < $array_length; i+=3 )) do
        print -P %{${fg[red]}%}${(P)${array_name}[i]}%{$reset_color             %}${(P)${array_name}[i+1]} %{${fg[yellow]}%}${(P)${array_name}[i+2]}%{$reset_color%}
    done
}

Notes:

  1. Here is how the array is passed into the function.
  2. This answer should explain the loop.
  3. The zsh color module provides an easier way to type the colors than the ANSII escape codes.
  4. Use print -P because it'll expand the prompt sequences. Read the section on print in man zshbuiltins for more information.

Here's a sample:

Screenshot of the function, etc.


Bonus Questions: Setting the delimiters should be pretty easy (insert another variable in the print -P statement.

Tab-delimitation is probably not too difficult. Printing the longest item in the array can be done using the majestic-looking:

 print ${array[(r)${(l.${#${(O@)array//?/X}[1]}..?.)}]}

which is taken from Chapter 5, paragraph 1, of the 'A Users guide to the Z-Shell'. The length of a variable can be determined using the ${#${variable}} syntax (as done in the function above). I'll leave the rest to you ;)

Community
  • 1
  • 1
simont
  • 68,704
  • 18
  • 117
  • 136
  • Thank you. After about a few hours of hacking and reading and googling I learned about fg command. Also, interestingly I came to similar approach as your print array collection function. That last example on printing the delimiters is inscrutable to my eyes. Sigh, I guess I will never be great at shell scripting. But thanks for the detailed response. Very helpful. – Gordon Potter Sep 21 '13 at 08:13
  • @GordonPotter A lot of the `zsh` stuff is *very*, uh, unintelligible at first, second and third glance. The `man zsh*` pages are very helpful, once you sort of figure out what you're looking for. [This page](http://grml.org/zsh/zsh-lovers.html) shows things you can accomplish in zsh scripts. If you've got specific questions ask here! The zsh ones are often fun to spend a couple hours attempting when I'm bored. – simont Sep 21 '13 at 08:44