Skip to content

Commit 5d57dd0

Browse files
authored
Merge pull request #986 from akinomyoga/doc-quoting
doc: add rules for quoting
2 parents b2ab72f + 2c188ac commit 5d57dd0

File tree

2 files changed

+71
-10
lines changed

2 files changed

+71
-10
lines changed

CONTRIBUTING.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ that. Don't be disappointed if it does or doesn't happen instantly.
4242

4343
Also, please bear the following coding guidelines in mind:
4444

45-
- See the [API and naming](doc/api-and-naming.md) document for information
46-
about conventions to follow related to those topics.
45+
- See the related documents, [API and naming](doc/api-and-naming.md) and
46+
[Coding style guide](doc/styleguide.md), for information about conventions to
47+
follow related to those topics.
4748

4849
- Do not use Perl, Ruby, Python etc. to do text processing unless the
4950
command for which you are writing the completion code implies the
@@ -66,11 +67,11 @@ Also, please bear the following coding guidelines in mind:
6667
external programs, which are expensive to fork and execute, so do
6768
make full use of those:
6869

69-
`?(pattern-list)` - match zero or one occurrences of patterns
70-
`*(pattern-list)` - match zero or more occurrences of patterns
71-
`+(pattern-list)` - match one or more occurrences of patterns
72-
`@(pattern-list)` - match exactly one of the given patterns
73-
`!(pattern-list)` - match anything except one of the given patterns
70+
- `?(pattern-list)` - match zero or one occurrences of patterns
71+
- `*(pattern-list)` - match zero or more occurrences of patterns
72+
- `+(pattern-list)` - match one or more occurrences of patterns
73+
- `@(pattern-list)` - match exactly one of the given patterns
74+
- `!(pattern-list)` - match anything except one of the given patterns
7475

7576
- Following on from the last point, be sparing with the use of
7677
external processes whenever you can. Completion functions need to be
@@ -107,9 +108,10 @@ Also, please bear the following coding guidelines in mind:
107108

108109
- We want our completions to work in `posix` and `nounset` modes.
109110

110-
Unfortunately due to a bash < 5.1 bug, toggling POSIX mode interferes
111-
with keybindings and should not be done. This rules out use of
112-
process substitution which causes syntax errors in POSIX mode.
111+
Unfortunately due to a bash < 5.1 bug, toggling POSIX mode
112+
interferes with keybindings and should not be done. This rules out
113+
use of process substitution which causes syntax errors in POSIX mode
114+
of bash < 5.1.
113115

114116
Instead of toggling `nounset` mode, make sure to test whether
115117
variables are set (e.g. with `[[ -v varname ]]`) or use default

doc/styleguide.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,62 @@ it.
122122
## Function and variable names
123123

124124
See [API and naming](api-and-naming.md).
125+
126+
## Quoting of words
127+
128+
To avoid unexpected word splitting and pathname expansions, an argument of
129+
commands needs to be properly quoted when it contains shell expansions such as
130+
`$var`, `$(cmd)`, and `$((expr))`.
131+
132+
When one intentionally wants word splitting and pathname expansions, one should
133+
consider using the utility functions provided by bash-completion. To safely
134+
split a string without being affected by non-standard `IFS` and pathname
135+
expansions, use the shell function `_comp_split`. To safely obtain filenames
136+
by pathname expansions without being affected by `failglob`, etc., use the
137+
shell function `_comp_expand_glob`. Note that `_comp_expand_glob` should be
138+
always used for the pathname patterns even if the pattern does not contain
139+
shell expansions.
140+
141+
In the following contexts, the quoting to suppress word splitting and pathname
142+
expansions are not needed.
143+
144+
- The right-hand sides of variable assignments ... `v=WORD` (e.g. `v=$var`)
145+
- The arguments of conditional commands ... `[[ WORD ]]` (e.g. `[[ $var ]]`)
146+
- The argument specified to `case` statement ... `case WORD in foo) ;; esac`
147+
(e.g. `case $var in foo) ;; esac`)
148+
149+
In bash-completion, we do not quote them by default. However, there are
150+
exceptions where the quoting is still needed for other reasons.
151+
152+
- When the word *directly* contains shell special characters (space, tab,
153+
newline, or a character from ``;|&()<>\\$`'"#!~{``), these characters need to
154+
be quoted. The "*directly*" means that the special characters produced by
155+
shell expansions are excluded here. For example, when one wants to include a
156+
whitespace as a part of the value of the word, the right-hand side can be
157+
quoted as `v="a b"`.
158+
- An empty word (i.e., the word whose value is an empty string) is specified by
159+
`""`. The right-hand side of an assignment technically can be an empty
160+
string as `var=`, but we still use `var=""` there because `shellcheck`
161+
suggests that e.g. `var= cmd` is confusing with `var=cmd`.
162+
- `$*` and `${array[*]}` need to be always quoted because they can be affected
163+
by the word splitting in bash <= 4.2 even in the above contexts.
164+
- In the following contexts, double-quoting of shell expansions is needed
165+
unless the result of expansions is intentionally treated as glob patterns or
166+
regular expressions.
167+
- The right-hand sides of `==`, `!=`, and `=~` in the conditional commands
168+
... `[[ word == "$var" ]]`
169+
- The case patterns ... `case word in "$var") ;; esac`
170+
171+
Note: Here strings `cat <<<$var` are also supposed to be safe against word
172+
splitting and pathname expansions without quoting, but bash <= 4.3 has a bug
173+
[1], so they need to be quoted for as long as we support bash 4.3.
174+
175+
- [koalaman/shellcheck#1009 (comment)](https://github.com/koalaman/shellcheck/issues/1009#issuecomment-488395630)
176+
177+
There are also preferences on the type of quoting, which are though not too
178+
strict. We prefer to use double quotes over single quotes by default. When
179+
the value contains `$`, `` ` ``, `\`, and `"`, we can use single quotes to
180+
avoid backslash escaping or use the one that minimizes the use of backslash
181+
escaping. When the value contains control characters such as a tab and a
182+
newline, we do not directly include them but we use backslash escape sequences
183+
such as `\t` and `\n` in the escape string `$'...'`.

0 commit comments

Comments
 (0)