CONTRIBUTING.md (20605B)
1 # Contribution Guide 2 3 ## How to contribute 4 5 ### Issues 6 7 You can freely create an issue using the following links: 8 9 - Report and fixes for bugs and performance issues [[Here]](https://github.com/akinomyoga/ble.sh/issues/new?template=bug_report.md) 10 - Questions on usage [[Here]](https://github.com/akinomyoga/ble.sh/issues/new?template=feature_request.md) 11 - Feature request [[Here]](https://github.com/akinomyoga/ble.sh/issues/new?template=help.md) 12 - Others (suggestions, projects, discussion, complaints, news, information or anything) [[Here]](https://github.com/akinomyoga/ble.sh/issues/new?template=free_style.md) 13 14 ### Pull requests 15 16 We always welcome following types of pull requests. Any changes will be considered to be provided under the BSD 3-Clause License. 17 If you do not know whether your changes would be appropriate for merge, please feel free to create a pull request and let us talk with each other! 18 19 - Better translation to English, typo fixes 20 - Fixes, optimization, test cases 21 - New features 22 - New color themes ... We accept new themes in [`contrib`](https://github.com/akinomyoga/blesh-contrib/pulls) repository. 23 - Others 24 25 ### Wiki 26 27 You can freely edit [wiki pages](https://github.com/akinomyoga/ble.sh/wiki). 28 29 - Translations 30 - Typo fixes 31 - Create new pages 32 33 ## For package maintainers 34 35 If you are a package maintainer for a repository of Linux distribution, etc. 36 you may provide a package-specific setting by preparing 37 a file `/path/to/blesh/lib/_package.sh` (e.g. `/usr/share/blesh/lib/_package.sh`) 38 which will be sourced after the load of `ble.sh` just before sourcing user's configuration (`~/.blerc`). 39 40 - In the file, the shell variable `_ble_base_package_type=TYPE` should be 41 set up to have a repository-specific name (such as `AUR`). 42 43 - The function named `ble/base/package:TYPE/update` (where `TYPE` 44 matches with a value assigned to `_ble_base_package_type`) may be 45 provided to define a custom updating procedure. The exit status of the function can be 46 - `0` ... when the update successed 47 - `6` ... when the update was skipped because the package was up to date. 48 - `125` ... when it wants to fallback to the built-in updating procedure of `ble.sh`. 49 - Other ... when the update failed 50 51 An example `lib/_package.sh` might be 52 53 ```bash 54 _ble_base_package_type=apt 55 56 function ble/base/package:apt/update { 57 sudo apt upgrade blesh 58 } 59 ``` 60 61 You can also find a real example for AUR (Arch User Repository) [here](https://aur.archlinux.org/cgit/aur.git/tree/blesh-update.sh?h=blesh-git). 62 63 ## Summary of codebase 64 65 The core script file `ble.sh` is generated by combining the following files: 66 67 - `ble.pp` ... Basic initialiation 68 - `src/def.sh` ... Prototype definitions 69 - `src/util.sh` ... Basic utility functions 70 - `src/decode.sh` ... User-input decoder and keybindings 71 - `src/color.sh` ... Terminal graphic attributes 72 - `src/canvas.sh` ... Terminal layout engine 73 - `src/canvas.emoji.sh` ... Emoji database 74 - `src/history.sh` ... Command history management 75 - `src/edit.sh` ... Line editor 76 - `src/benchmark.sh` ... Measure processing time 77 - `lib/core-completion.sh` ... Prototype definition for completions 78 - `lib/core-syntax.sh` ... Prototype definitions for syntax analyzer 79 80 Useful features are implemented in separate modules: 81 82 - `lib/keymap.vi.sh` ... Vim mode 83 - `lib/vim-arpeggio.sh` ... `vim-arpeggio`-like plugin 84 - `lib/vim-surround.sh` ... `vim-surround`-like plugin 85 - `lib/keymap.emacs.sh` ... Emacs mode 86 - `lib/core-syntax.sh` ... Shell parser and syntax highlighting 87 - `lib/core-syntax-ctx.def` ... Definition of parser states 88 - `lib/core-complete.sh` ... Completions including `menu-complete`, `auto-complete`, `menu-filter`, `dabbrev`, `sabbrev`, etc. 89 90 The following files are initialization scripts: 91 92 - `lib/init-term.sh` ... Initialize terminal escape sequences (host-to-terminal, i.e. control sequences) 93 - `lib/init-cmap.sh` ... Initialize terminal escape sequences (terminal-to-host, i.e. key sequences) 94 - `lib/init-bind.sh` ... Initialize readline attacher 95 - `lib/init-msys1.sh` ... Workaround for MSYS1 with broken pipes 96 - `lib/init-msys1-helper.c` ... Helper C program for the workaround of broken pipes 97 98 The contrib repository contains configurations built on top of the `ble.sh` framework 99 100 - `contrib/config/*.bash` are specific configurations whose details may depend on the user's preferences. These are expected to work just by `ble-import` but at the same time serve as examples for the user's personal versions. 101 - `contrib/sample/*.bash` are examples to explain interfaces for configurations. These are just explanation of the interface so would not actually function. 102 - `contrib/airline/*.bash` are the themes for `vim-airline`. 103 - `contrib/integration/*.bash` are codes needed for the adjustments with other framework. 104 - `contrib/*.bash` are other miscellaneous configurations. Usually one needs additional configuration after `ble-import`. These files may be moved to another directory in the future. 105 106 ## Tests 107 108 Tests can be run by one of the following commands: 109 110 ```bash 111 $ make check 112 $ make check-all 113 $ bash out/ble.sh --test 114 115 ``` 116 117 Currently test coverage is very small 118 partly because the testing for interactive behavior and terminal rendering results is hard. 119 Nevertheless, the tests are defined in the following files: 120 121 - `lib/core-test.sh` ... Library for tests 122 - `lib/test-bash.sh` 123 - `lib/test-main.sh` 124 - `lib/test-util.sh` 125 - `lib/test-canvas.sh` 126 - `lib/test-edit.sh` 127 - `lib/test-complete.sh` 128 - `lib/test-syntax.sh` 129 130 ## Coding styles 131 132 These styles are not required for the initial PR as these are too complicated. 133 The maintainer(s) will apply the styles before merging. 134 Nevertheless, it would be useful to follow the styles when you are going to submit PRs many times. 135 136 ### Naming convention for functions 137 138 The function names roughly has the following structure, but the rule is ambiguous to some extent, and there are also many exceptions in the codebase. 139 140 ```ebnf 141 function_name = (namespace '/')* function_basename ; 142 143 namespace = function_basename ; 144 145 function_basename = name ext? (* namespace function *) 146 | class '.' name ext? (* class method *) 147 | class '#' name ext? (* instance method *) 148 | class '#' class '::' name ext? (* instance method (override) *) 149 | type ':' name ext? ; (* customization point *) 150 151 name = hyphenated_name extension (* public *) 152 | '.' hyphenated_name ; (* private *) 153 154 ext = '.hook' (* hook functions for blehook *) 155 | '.draw' (* function operating on DRAW_BUFF *) 156 | '.fib' (* worker for ble/util/fiberchain *) 157 | '.proc' (* callback functions *) 158 | '.impl' ; (* internal implementation *) 159 (* ... (and more extensions) *) 160 161 class = name ; 162 163 type = hyphenated_name ; 164 165 hyphenated_name = (word '-')* word ; 166 167 word = /[_a-zA-Z0-9]+/ ; 168 ``` 169 170 The function names are basically hyphenated words (such as `foo-bar-baz` instead of `foo_bar_baz`, `fooBarBaz`, or `FooBarBaz`). 171 172 **Namespace**--The function names can be prefixed by namespaces of the form `<namespace>/`. 173 Except for the functions intended to be called from the command line or the user configuration, all the function should be defined in a namespace. 174 The interface of the functions defined in a namespace is subject to change in the future. 175 A function name can also be used as the namespace name for the helper functions to implement the function. 176 For the functions defined in external modules, the following namespace should be used to avoid conflicts: 177 178 | Types | Namespace | 179 |:----------------------------------------------------|----------------------------------------| 180 | `contrib/*.bash` | `ble/contrib/<modulename>` | 181 | `contrib/config/*.bash` | `ble/contrib/config:<modulename>` | 182 | `contrib/integration/*.bash` | `ble/contrib/integration:<modulename>` | 183 | User's public config | e.g. `<user>` | 184 | User's private config | e.g. `<user>` or `my` | 185 | User's private config in Bash initialization file | e.g. `<user>`, `my` or `bashrc` | 186 | User's private config in ble.sh initialization file | e.g. `<user>`, `my` or `blerc` | 187 188 **Private**--The function basename started with `.` is considered private within the namespace. All the other functions are public. 189 190 **Method**--The function basename of the form `<class>#<name>` is considered an instance method. 191 The function basename of the form `<class>.<name>` is considered a class method. 192 The difference between the two is the latter assumes a single global state while the former assumes that an instance is specified by the first argument or by other means. 193 The way to specify the instance depends on the class. 194 For example, `ble/array#*` receives the variable name as the first argument while `ble/string#*` directly receives the string value as the first argument. 195 For `ble/textarea#*`, the target instance is selected by the shell variable `_ble_textarea_panel`. 196 The function basename of the form `<class1>#<class2>::<name>` is used to define a virtual function called by the base class `<class2>` at the side of the derived class `<class1>`. 197 198 **Customization point**--The function basename of the form `<type>:<name>` is used to provide the customization point for dynamic values. 199 This function is typically called as `<type>:"$var"` with `var` contains a value that depends on the context including the currently selected class, user configuration, etc. 200 201 **Extension**--The extension `<ext>` can be used to mark the specific types of functions. 202 203 ### Naming convention for variables 204 205 The variable names roughly have the following structure. 206 207 ```ebnf 208 local_variable_name = varname 209 | '__ble_' varname 210 | '_ble_local_' varname ; 211 212 global_variable_name = ('_' namespace)* '_' varname ; 213 214 namespace = word ; 215 varname = (word '_')* word ; 216 word = /[a-zA-Z0-9]+/ ; 217 ``` 218 219 The variable names are basically lowercase underscored words such as `foo_bar_baz` (instead of `fooBarBaz` or `FooBarBaz`). 220 Some global constants and the exported variables have all-uppercase names, but the lowercase should be basically used. 221 222 **Local variables**--The local variables that are only used in the declared function should be basically unprefixed by an underscore. 223 When the function reads/returns a value through an arbitrary name of <i>in</i>/<i>out</i> variables, 224 the local variable declared within the function should be prefixed by `__ble_` or `_ble_local_` to avoid the name conflicts between the local and in/out variables. 225 226 **Global variables**--All the global variables, except for the variables that are intended to be directly modified from the command line, should be prefixed by `_`. 227 Currently, there are no variables intended to be directly modified from the command line<sup><b>[Note 1]</b></sup>. 228 The variables defined in external modules should be namespaced by the module name. 229 The variables in modules in the `contrib` repository should have the prefix `_ble_contrib_<module_name>_` 230 231 - <sup><b>[Note 1]</b></sup> In the initial implementation of ble.sh, the ble.sh options are provided as shell variables `bleopt_*`. 232 As remnant or for the backward compatibility, the values of ble.sh options are still stored in the variables of the name `bleopt_*`, 233 but these variables for the ble.sh options will be renamed in the future. 234 235 ### Function interface 236 237 The success/failure states should be returned by the exit status. 238 239 **`ret`**--All the other values should be basically returned through shell variables. 240 This is because, if a function returned its result through the standard output, 241 the caller would need to capture the results by a command substitution which involves a fork of a subshell and thus is slow. 242 Here, the efficiency is the primary interest, so there are exceptions where the standard output can be more efficient: 243 For examples, when the output needs to be saved to a file for later use or to pass it to a different process, 244 or when the output needs to be processed by the external commands that reads the standard input. 245 The variable name to return a value should be basically `ret` unless the purpose of function is to store values. 246 When the function basename has the form `get-<name>`, one should consider retruning the result through the shell variable named `<name>`. 247 When a function returning multiple values is called from many places, the function may receive an array name as the first argument and stores the result in the specified array. 248 When the <i>out</i> variable names are specified in the arguments, they should come first in the list of the arguments. 249 250 **`opts`**--The argument position should be basically fixed (e.g., never shifted by optional arguments like `-f` or `-o name`). 251 The optional arguments can be specified by a colon-separated fields (like `SHELLOPTS` or `BASHOPTS`) 252 instead of the unix-style flags and options like `-f` and `-o optarg`. 253 This is because usually the parsing of the unix-style arguments (with or without `getopts`) is slow. 254 The local variable that receives the colon-separated option typically has the name `opts` or `*opts` (e.g. `local opts=$2`). 255 A single option has the form `name` or `name=value`, 256 where `name` should be a hyphenated words like `foo-bar-baz`. 257 The former form without the value is called a flag option. 258 One can test a flag option by `[[ :$opts: == *:flag-name:* ]]`. 259 An option of the form `name=value` can be matched by `ble/opts#extract-first-optarg`, `ble/opts#extract-last-optarg`, or `ble/opts#extract-all-optargs`. 260 The function `ble/opts#has` can be used to test if either of `name` or `name=value` is contained 261 262 **`$*`**--The functions that receive a string should not allow a variable number of arguments that are joined inside the function. 263 A variable number of arguments should be only used when each argument is really processed separatedly. 264 If necessary, the joining should be performed at the caller side. 265 This is because `IFS` in the caller context affects the joining `$*`, so the handling of `IFS` should be properly done at the caller side. 266 Another reason is for the future extension, e.g., to add another optional argument. 267 268 ### Variable declarations 269 270 Local variables should be declared by `local` (instead of `declare` or `typeset`). 271 Variables should be always initialized before referencing their values. This is because uninitialized variables can have random values when `shopt -s localvar_inherit` is turned on. 272 273 The declaration and the initialization of an array variable should be separated as far as the initializer values contain any expansions or any spaces. 274 There is a bug in Bash 3.0 that the values are separated by whitespaces even when the values are quoted. 275 When the declaration and the initialization of an array variable are made in a single command, the option `-a` needs to be specified. 276 Without `-a`, the entire list `(...)` including the surrounding parens will be treated as a scalar string in Bash 3.0. 277 278 ```bash 279 local v; v=("$var") 280 local -a v=() 281 282 # The following may not work as expected 283 # local v=() # Bash 3.0 will initialize a scalar with the value v='()' #D0184 284 # local -a v=("a b") # Bash 3.0 will split it into the two elements "a" and "b" #D0525 285 ``` 286 287 Defining local readonly variables should be avoided 288 because they will hide global variables from the utilities `ble/variable#is-global`, `ble/util/print-global-definitions`, etc. 289 Global readonly variables should never be defined. 290 The background is described in the Limitation section of README. 291 292 ### Conditional commands `[[ ... ]]` 293 294 Do not use `[ ... ]` or `test` unless it is intended to be a POSIX script. Always use `[[ ... ]]`. 295 296 Use `[[ word ]]` and `[[ ! word ]]` instead of `[[ -n word ]]` and `[[ -z word ]]`. 297 298 Use `==` instead of the operator `=` inside conditional commands. 299 300 **Quoting**--The right-hand sides of `==` and `!=` inside conditional commands `[[ ... ]]` should be properly quoted. 301 The right-hand sides of `=~` inside the conditional commands `[[ ... ]]` should be specified by a single parameter expansion 302 as `[[ word =~ $rex ]]`, or one can use `ble/string#match 'word' "$rex"` instead. 303 In other contexts, the arguments of the conditional command should not be quoted 304 unless raw special characters ``[[:space:]|&;<>\`"$]`` are contained in the argument. 305 306 **No `-eq` etc**--Basically use arithmetic commands `((expr))` 307 instead of the operators `-eq`, `-ne`, `-gt`, `-ge`, `-lt`, and `-le` of the conditional command. 308 They might be used when the test is used as a part of complicated conditions in the conditional commands. 309 For example, `[[ -f $file || $word && word -eq 0 ]]` can be used instead of `[[ -f $file ]] || { [[ $word ]] && ((word == 0)); }` becausing sticking with the arithmetic command would unnecessarily complicate the code in this case. 310 311 ### Other styles 312 313 **Function definition**--There are two forms of function definitions, the POSIX style `func()` and the ksh style `functino func`, as well as the mixed form. 314 We always use the ksh style of the function definition. 315 The reasons are that it is easier to search by the keyword `function ` and that it is protected by the aliases of the same name as the function (unless the user defines an alias with the same name as the keyword `function`). 316 The function body is always the compound command `{ ... }` (instead of any other compound commands such as `( ... )`, `for`, `if`, etc.), and the opening brace `{` is placed on the first line. 317 318 ```bash 319 function function-name { 320 : do_something 321 } 322 ``` 323 324 **`ble/util/print`**--Use `ble/util/print` instead of `echo`. Use `ble/util/put` instead of `echo -n`. 325 The control characters should be directly specified by the escape string literal `$'...'` instead of relying on the conversion by `echo -e`. 326 This is because the builtin `echo` can change its behavior depending on the shell option `shopt -s xpg_echo`, where the backslashes in the arguments might have special meaning. 327 `ble.sh` is intended to work under any possible user options. 328 329 **Quote/unquote**--The arguments where the word splitting and pathname expansions can take place need to be always quoted. 330 When the subject word of `case` statement and the right-hand sides of variable assignments 331 (including those specified to assignment builtins `declare`, `typeset`, `local`, `export`, and `readonly`) 332 contains `$*`, `${arr[*]}`, or raw special characters ``[[:space:]|&;<>\`"$]``, they need to be quoted. 333 In other contexts, the subject word of `case` and the right-hand sides of variable assignments should not be quoted. 334 In these contexts, the word splitting and pathname expansions will never happen, so the quoting is unnecessary. 335 336 337 Array subscripts are arithmetic context, so the arithmetic expansions `$((expr))` inside the array subscripts are redundant. One should simply write it as `arr[expr]` instead of `arr[$((expr))]`. 338 339 **`ble/util/assign`**--Use `ble/util/assign`, `ble/util/assign-array`, and `ble/util/assign-words` instead of `var=$(cmd)`, `mapfile -t var <<< "$(cmd)"`, and `var=($(cmd))`, respectively. 340 The command substitutions `$(...)` are slow because they involve the forks of subshells. 341 342 **External commands**--Implement it using built-in Bash features as much as possible. 343 If the same result can be obtained by built-in Bash features efficiently, do not use the external commands. 344 When the external command is used, first freeeze the path by calling `ble/bin#freeze-utility-path '<cmd>'` and call the commands through `ble/bin/<cmd>`. 345 Or save the path of the external command in a variable, and call the command through the variable as `"$_saved_cmd" args...`. 346 The POSIX commands should be basically used. If non-POSIX commands are used, a POSIX fallback should be always prepared. 347 Please combine multiple calls of external commands into a single call of the command as much as possible. 348 Usually, a single call of `sed` and `awk` are preferred over the chain of simple commands.