Shell – How to make source-highlight colorize .dotfiles by default

colorsdot-filesfunctionshell-scriptsource-highlight

Normally when I cat a file like this

enter image description here

it's hard to read without colorizing.

I've managed to get cat to use source-highlight like this:

cdc() {
  for fn in "$@"; do
    source-highlight --out-format=esc -o STDOUT -i $fn 2>/dev/null || /bin/cat $fn
  done; }; alias cat='cdc'

which now produces the following for a recognized file extension – .sh in this case:

enter image description here

However without the .sh, e.g. if the file is just called .bash_functions the colorizing doesn't happen – because the file extension is not known.

Is there any way I can get color-highlight to color dot files (files that begin with a dot) as sh colors ?

btw this builds on top of How can i colorize cat output including unknown filetypes in b&w?

man source-higlight shows the following but I'm not clear what to do:

...
--outlang-def=filename
      output language definition file

--outlang-map=filename
      output language map file (default=`outlang.map')

--data-dir=path
      directory where language definition files and language maps are searched for.   If  not  specified
      these files are searched for in the current directory and in the data dir installation directory

--output-dir=path
      output directory

--lang-def=filename
      language definition file

--lang-map=filename
      language map file  (default=`lang.map')

--show-lang-elements=filename
      prints the language elements that are defined

      in the language definition file

--infer-lang
      force to infer source script language (overriding given language specification)

Best Answer

Define your cdc function as

cdc() {
    for fn do
        if [[ "${fn##*/}" == .* ]]
        then
            source-highlight --src-lang=sh --out-format=esc -i "$fn"
        else
            source-highlight               --out-format=esc -i "$fn"
        fi 2> /dev/null  ||  /bin/cat "$fn"
    done
}
  • for fn do is short for for fn in "$@"; do.
  • ${fn##*/} looks at the value of $fn and removes everything from the beginning up through (and including) the last /.  I.e., if $fn is a full pathname, this will be just the filename part.
  • [[ (the_above) == .* ]] checks whether the filename matches the .* glob/wildcard pattern; i.e., whether the filename begins with a ..  Note that this usage of == works only inside [[ … ]]; it does not work inside [ … ].
  • So, if $fn is a “dot file”, run source-highlight with the --src-lang=sh option.

    • You should always put shell variable references in double quotes unless you have a good reason not to, and you’re sure you know what you’re doing.  Unix/Linux filenames can contain spaces.  If you had a file named foo bar, and you said /bin/cat "foo bar", cat would display the contents of the file foo bar.  But, if you said cdc "foo bar" (with the current version of your cdc function), you would run source-highlight with -i foo bar, which would look for a file called foo and generally make a mess of things.  And so it would fail, and your function would try /bin/cat foo bar, which would likewise fail.  Using "$fn" makes this work for filenames that contain spaces.
    • The cp program requires you to specify, on the argument list, the name of the file or directory you want it to write to.  This is one of the few exceptions to the rule that most programs write to standard output by default (unless you specify otherwise).  You don’t need to say -o STDOUT, and I wonder why the author(s) of the program even made it possible for you to specify that.

    And, yes, I realize that you just copied all of that from the answer to your other question.

  • Obviously, if $fn is not a dot file, just run source-highlight the normal way, and let it check for an extension.
  • Note that the 2> /dev/null and the || /bin/cat "$fn" can be done for the if … then … else … fi block in its entirety; they don’t have to be repeated for each branch.

Hmm.  My version of source-highlight (3.1.7) has a --src-lang=LANGUAGE option (-s LANGUAGE, as used by yaegashi, for short).  I just noticed that it isn’t in the source-highlight man page excerpt you included in your question.  So, obviously, if your version of source-highlight doesn’t support that option, my answer won’t work for you.  (And, of course, neither will yaegashi’s.)  If that’s the case, you should see if you can install version 3.1.7 (or compatible) of source-highlight.