Subject: [alpine-devel] Shell scripting guidelines

From: Gemsbokella <[email-masked]>
Date: Sat, 05 Nov 2016 15:06:28 -0400

Hi! I think it's about time we make official shell scripting guidelines. First of all, we need a mainter of such set of rules. The process of accepting new rules should be of course democratic but there needs to be someone (or a group) that compiles those rules. Any volunteers? I guess I could do it if no one else is interested.

In my opinion, it would be ideal to have 3 sets of rules. Style guide, preferences guide which mandates requirements of the actual script (`set -u`, POSIX-sh), and so called "dealing with a specific task" [WIP name] that advises programmers how to deal with a task (e.g., user input)

I hear there's already a few established rules (courtesy of <[email-masked]>)

"
* Follow POSIX-sh standard, avoid “bashisms”. But we are pragmatic, so if some non-POSIX feature is supported by all commonly used shells (Busybox ash, dash, zsh, bash, …) and it has substantial benefits, then it’s okay to use it (for example `local` and `${var/pattern/replacement}`). Actually, in the case of `local`, you should always prefer it over polluting global namespace. I should also note that Alpine uses Busybox ash as default shell.
* Use `set -e` and if possible also `set -u` (called at the top of the script) in newly created scripts. Unfortunately this is not a common practice in existing scripts (yet) and it already caused a lot trouble…
* Prefer lower_case for names of variables and functions, except global constants and environment variables.
* We don’t usually use curly braces around variables if they are not needed.
* Use tabs for indentation, not spaces (and better to avoid spaces alignment, because it sooner or later ends as a mess).
"
If you like my "3 set of rules" idea, you end up with this:

===Style===
* Use tabs for indentation
* Avoid spaces alignment
* No curly braces around variables if they are not needed
* lower_case names of variables and functions, except for global constants and environment variables

===Preferences===
* Follow POSIX-sh standard, if non-POSIX is supported by common shells and offers better solution it is OK to use it
* Use `set -e` and if possible also `set -u`
* `local` is preffered over polluting global namespace

===Dealing with specific tasks===
-none-

There are a few problems we need to discuss (I'd appreciate your opinions):
* User input
* License
* printf vs echo

Question 1: User input is very hard to get right, especially in shell scripts. How to deal with invalid input? Ask again? Exit?
Opinion 1: I personally ask the user again. Another common practise is just to quit the script which, frankly, is not a very good solution.

Question 2: Prefered license for shell scripts
Opinion 2: GPLv2, GPLv3 or BSD would suit the scripts just fine.

Question 3: printf vs echo
Opinion 3: 99% of the time echo (https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo). I think we should accept this as a rule ASAP.

#TODO:
Find a better name for "dealing with specific tasks"

So, what do you think? Is this even a good idea?

---

From: [email-masked]
Date: Sat, 5 Nov 2016 20:50:23 +0100

Disclaimer: I am not involved in Alpine-specific scripting at all.

Nevertheless I have a lot to do with shell scripting and came with time
to some conclusions. They are of course influenced by a personal taste
but mostly reflect the experience, through generations of shells.

Here follows my 2 cents:

I find all the cited recommendations reasonable, besides a single one.

> * Use tabs for indentation

Sorry, my stance is "tabs are harmful":

 - they are invisible so you never know without extra tricks
   whether and how many spaces/tabs are there
 - they are interpreted differently by different editors and
   in different situations
 - they can not be reliably cut&pasted (because they are
   often visualised via some spaces)
 - they do not provide reliable indentation (because of varying
   interpretation by viewers/editors)
 - the classical interpretaion of 8 positions gives inefficient
   (and inflexible) large indentation, easily leading to long lines
   or/and line wrapping

   Depending on the script contents, a smaller indentation
   (say, 4 or sometimes even 2 positions) can remain easy to read and
   at the same time prevent moving the indented lines out of sight.

In other words tabs are PITA. Thanks for listening.

> Opinion 1: I personally ask the user again. Another common practise is just to quit the script which, frankly, is not a very good solution.

Depends on the situation. IMHO dangerous operations should become canceled
if the user can not spell the answer, otherwise you expose your script
among others to the user-in-a-hurry-typeahead or unintended multiline
cut-n-paste.

Otherwise to give the user a new chance after a typo is of course nice
and useful.

> Opinion 3: 99% of the time echo (https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo). I think we should accept this as a rule ASAP.

Echo is just a very old artefact, it exists historically but should
be never used, due to its various and uncorrectable flaws.

OTOH as long as there is a common library which e.g. defines echo
via printf, making it deterministic, then it is as good as any
other in-house shell function, if treated as such. I.e. you do not
have to clean away all "echo"s from the scripts, if the scripts
happen to rely on a function library.

Hope these notes help somehow.

Regards,
Rune

---
Unsubscribe:  [email-masked]
Help:         [email-masked]
---

---

From: Cág <[email-masked]>
Date: Sat, 05 Nov 2016 20:03:09 +0000

[email-masked] wrote:

> [snip]

The thing is, this is defined in most of traditional coding
style guides, at least applying to C, though I reckon for
scripts too. Hence the traditional "tab=8 spaces" in vi.

Cág

---

---

From: Alba Pompeo <[email-masked]>
Date: Sat, 5 Nov 2016 18:07:51 -0200

http://www.etalabs.net/sh_tricks.html

---

---

From: Cág <[email-masked]>
Date: Sat, 05 Nov 2016 20:18:18 +0000

> http://www.etalabs.net/sh_tricks.html

I'm afraid there's nothing concerning indentation in the
given link. Anyway thanks for it, a good read.

Cág

---

---

From: [email-masked]
Date: Sat, 5 Nov 2016 21:10:26 +0100

Oh by the way

> * We don’t usually use curly braces around variables if they are not needed.

It is prudent to always put quotation marks around variable substitutions
(like, no $ outside "").

Even if you know with certainty that the value can not contain white
space because of how the script is written _now_, you may sometimes have
got it wrong.

Then later someone can rewrite parts of the script without being aware
of this assumed constraint (unless you document the assumption? which
probably takes more effort than adding "").

There are cases where a substitution is _meant_ to yield several words,
this is of course a different situation and a useful hack, given
the limited array handling facilities in Bourne sh.

Cheers,
Rune

---