Compare commits
173 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2e878ec30f | ||
|
726ce78de7 | ||
|
51e7644bb1 | ||
|
985b0046c4 | ||
|
38f269c660 | ||
|
f6b61410c0 | ||
|
42e50f66c8 | ||
|
c5012d0190 | ||
|
14421bd791 | ||
|
7af1f75c5e | ||
|
320609fceb | ||
|
9e70d61133 | ||
|
354c304b19 | ||
|
a6a2d961ae | ||
|
7f9a31f8d8 | ||
|
758fa92f05 | ||
|
555beb1add | ||
|
2d145e24e9 | ||
|
b2140d5ec6 | ||
|
7a022bccf3 | ||
|
55cd329ebd | ||
|
879422d09f | ||
|
1fb7cc4337 | ||
|
f2ccef5b36 | ||
|
2e68b71743 | ||
|
28deb39d86 | ||
|
33a3fd706b | ||
|
ddc6440177 | ||
|
c4585291f3 | ||
|
9a27140e7e | ||
|
cb06f0aa70 | ||
|
e45247d4aa | ||
|
a50ad7007e | ||
|
41172fcc8f | ||
|
9f0c37e2ac | ||
|
0a6e3925dc | ||
|
7d3927b025 | ||
|
49eed4f283 | ||
|
3d47083fcf | ||
|
e516a60169 | ||
|
d1c26b9ac1 | ||
|
85efe41ad9 | ||
|
80ab935cf6 | ||
|
86f20e34b7 | ||
|
d113e87c96 | ||
|
9f06b1a8c6 | ||
|
8a14c0e3d5 | ||
|
c086796573 | ||
|
05cdcdaa12 | ||
|
8ceed901d5 | ||
|
76fbd2104b | ||
|
9cc3bf124c | ||
|
986fec8090 | ||
|
ea15c44c7e | ||
|
febd9e354b | ||
|
13d74bb4f1 | ||
|
ab3857e3bd | ||
|
e5da0aa249 | ||
|
bbb8afea4d | ||
|
e078dd2b91 | ||
|
9fd3f1df64 | ||
|
1005ceeec8 | ||
|
56eab89caa | ||
|
186d9ff6a0 | ||
|
23ce0e6b85 | ||
|
6392674f70 | ||
|
222a95793b | ||
|
269627deec | ||
|
1238b67abe | ||
|
5cc417485a | ||
|
971a83ea3a | ||
|
14dc823cca | ||
|
599faf3830 | ||
|
0d096350b0 | ||
|
24e7ceaaf7 | ||
|
f1ad8a5655 | ||
|
c0f58127bb | ||
|
6689117e5d | ||
|
a28d594d5f | ||
|
bccefb0061 | ||
|
9194295c64 | ||
|
8146667ea1 | ||
|
2019caa899 | ||
|
357ea3778a | ||
|
f377dfb16e | ||
|
f77b400dc9 | ||
|
03662dd404 | ||
|
b8a4aba3c2 | ||
|
685442bbcc | ||
|
16b543114b | ||
|
7791e3ca0f | ||
|
1152cc3cf7 | ||
|
b4048f3f12 | ||
|
11cd18e179 | ||
|
05f35415a6 | ||
|
ec9087f0d2 | ||
|
5a9a68be2b | ||
|
97f9676754 | ||
|
83c77f8df3 | ||
|
04cf154b3e | ||
|
4085bc461e | ||
|
8e548e766e | ||
|
d908e8b362 | ||
|
9250d036dc | ||
|
ea57d157c7 | ||
|
95b9cb1469 | ||
|
ff89a1154b | ||
|
9f31a5e969 | ||
|
664e55ad1e | ||
|
7b7d31a1bf | ||
|
ba0e7150cb | ||
|
2048e4303e | ||
|
327cba75c9 | ||
|
ee869a9584 | ||
|
f57e37eb68 | ||
|
2463cd6cc9 | ||
|
860a7de899 | ||
|
236e3c7eca | ||
|
cf7d25e3d1 | ||
|
d25d6a0106 | ||
|
9b7a9ccd17 | ||
|
38622845a8 | ||
|
0289532f18 | ||
|
2fcd0a765b | ||
|
48848fd17c | ||
|
84685a451b | ||
|
12ea4dd75f | ||
|
63c402912a | ||
|
0c2a580041 | ||
|
eac5ad8022 | ||
|
9f3aa6ead9 | ||
|
c19c08a775 | ||
|
a0e9bb0c05 | ||
|
d134dfd145 | ||
|
f6996a1595 | ||
|
1c672bf8cb | ||
|
87545c8f9a | ||
|
111a00e1f0 | ||
|
6f0cfaddb1 | ||
|
5f815c7f98 | ||
|
c4429de7d5 | ||
|
d35fa94ffc | ||
|
7759cba46f | ||
|
efd984e01d | ||
|
ef66310b27 | ||
|
3e9afe28c3 | ||
|
ef04df597b | ||
|
e7e85ddff3 | ||
|
b2326bf75e | ||
|
9b86dcced8 | ||
|
2bbf6eed2e | ||
|
ff37895ea4 | ||
|
39e0607bcb | ||
|
748fdcfab3 | ||
|
c52a73598e | ||
|
755eb0d02f | ||
|
b1861f9fab | ||
|
b280139595 | ||
|
cb29b2f984 | ||
|
2d5506cb36 | ||
|
986191210a | ||
|
0d1f488365 | ||
|
7eea26c7b4 | ||
|
d879ae1fe0 | ||
|
382217eebf | ||
|
ba2d901cc2 | ||
|
36db2227c7 | ||
|
7cf9ea708d | ||
|
7f9419cda0 | ||
|
47be547cfa | ||
|
21cafb3c34 | ||
|
ea6bbd058f | ||
|
f44385ced3 |
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Thanks for contributing to b3bp! As part of your PR, have you:
|
||||||
|
|
||||||
|
- [ ] Added an item in [CHANGELOG.md](https://github.com/kvz/bash3boilerplate/blob/HEAD/CHANGELOG.md) with attribution?
|
||||||
|
- [ ] Added your name to the [README.md](https://github.com/kvz/bash3boilerplate/blob/HEAD/README.md#authors)
|
||||||
|
- [ ] Linted your code? (`make test` should do the trick)
|
||||||
|
|
||||||
|
If so, great! Feel free to replace this message with a description of your work and hit submit!
|
5
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
groups:
|
||||||
|
production-dependencies:
|
||||||
|
dependency-type: 'production'
|
||||||
|
development-dependencies:
|
||||||
|
dependency-type: 'development'
|
30
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
name: b3bp CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 18.x
|
||||||
|
- name: Install
|
||||||
|
run: |
|
||||||
|
corepack yarn
|
||||||
|
- name: Lint
|
||||||
|
env:
|
||||||
|
SHELLCHECK_SEVERITY: warning
|
||||||
|
run: |
|
||||||
|
corepack yarn lint
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
corepack yarn test
|
28
.gitignore
vendored
@ -1,25 +1,5 @@
|
|||||||
npm-debug.log
|
.yarn
|
||||||
node_modules
|
|
||||||
|
|
||||||
test/scenario/templater/break.cfg
|
|
||||||
|
|
||||||
website/index.md
|
|
||||||
website/_site/
|
|
||||||
website/_vendor/
|
|
||||||
|
|
||||||
website/changelog.md
|
|
||||||
|
|
||||||
website/faq.md
|
|
||||||
|
|
||||||
website/.jekyll-metadata
|
|
||||||
|
|
||||||
env.sh
|
|
||||||
|
|
||||||
website/main.sh
|
|
||||||
website/assets/build
|
|
||||||
website/.lanyon
|
|
||||||
website/.lanyon/vendor/bin
|
|
||||||
website/.lanyon/bin
|
|
||||||
assets/build
|
assets/build
|
||||||
.lanyon
|
env.sh
|
||||||
.lanyon/bin
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
3
.shellcheckrc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
external-sources=true
|
||||||
|
shell=bash
|
||||||
|
color=always
|
42
.travis.yml
@ -1,42 +0,0 @@
|
|||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: linux
|
|
||||||
sudo: false
|
|
||||||
language: node_js
|
|
||||||
node_js: 6
|
|
||||||
- os: osx
|
|
||||||
language: node_js
|
|
||||||
node_js: 6
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- secure: BeM6mpPEATdeFcAr/222QBZ9vRkZtU2WOi9QQy3mxsuDbWfM8RxYESIEJLipyhW9kXGoe6HGMqm4Kz9B/c4jrzeSXPpKnW7mIfnyqN+hhq1ctW9qPSqodu+fYNhdDxXh5wylml7hnIJzU70vFGrFknZRE2FYk5XvyHg2ImIKDJw=
|
|
||||||
- secure: RJ5UpdXms9QkraylZ11OBfmcRrmKnb254Yj0yCDAvZmg+n+3jSTwMgGvPY8Ih8X/R1JeW3VTtFDkJXXPnjjfpNg1M91u4CAEUOMPciCudYcoF6GKb8psnOzneTTX5M7zuJSzknGdpv/foldxiPYxiY5Hn5bfjmikhAEl+QX/R0Y=
|
|
||||||
- secure: BXf2buPt/DA09M5ZUdp/LpOWtUuz1mfCBopLyxvHv3Sl3ln+Az57wWsM2+Re+77lUOgihR2f6lXYfNUmQuSUo157rZPunQCqM/DJhK69KhREEB6SJDaJF3FVlnGla+Cwwb1IQUtMopqX9pBYD7w/zyWQFJCi20O57JEVIdfZZS8=
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- debian-sid
|
|
||||||
packages:
|
|
||||||
- shellcheck
|
|
||||||
install: npm install # <-- yarn still messes up nested bins: https://github.com/yarnpkg/yarn/issues/760
|
|
||||||
before_install:
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then which gsed || brew install gnu-sed; fi
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then which gtimeout || brew install coreutils;
|
|
||||||
fi
|
|
||||||
- bash --version
|
|
||||||
- awk --version
|
|
||||||
before_cache:
|
|
||||||
- rm -f ./node_modules/.bin/which # <-- workaround for https://github.com/travis-ci/travis-ci/issues/5092
|
|
||||||
cache:
|
|
||||||
apt: true
|
|
||||||
directories:
|
|
||||||
- .lanyon
|
|
||||||
script: test/acceptance.sh
|
|
||||||
deploy:
|
|
||||||
skip_cleanup: true
|
|
||||||
provider: script
|
|
||||||
script: website/.lanyon/bin/deploy
|
|
||||||
on:
|
|
||||||
branch: master
|
|
||||||
condition: $TRAVIS_OS_NAME = linux
|
|
8
.vscode/bash3boilerplate.code-workspace
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": ".."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
1
.yarnrc.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
nodeLinker: node-modules
|
211
CHANGELOG.md
@ -1,98 +1,175 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## master
|
Here's is a combined todo/done list. You can see what todos are planned for the upcoming release, as well as ideas that may/may not make into a release in `Ideas`.
|
||||||
|
|
||||||
Released: Unreleased. [Commit log](https://github.com/kvz/bash3boilerplate/compare/v2.2.0...master)
|
## Ideas
|
||||||
|
|
||||||
|
Unplanned.
|
||||||
|
|
||||||
|
- [ ] Better style guide checking (#84)
|
||||||
|
|
||||||
|
## main
|
||||||
|
|
||||||
|
Released: TBA.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/2.7.2...main).
|
||||||
|
|
||||||
|
- [ ]
|
||||||
|
|
||||||
|
## 2.7.2
|
||||||
|
|
||||||
|
Released: 2023-08-29
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v2.4.1...2.7.2).
|
||||||
|
|
||||||
|
- [x] Upgrade and cleanup node dependencies
|
||||||
|
- [x] Remove lanyon-based website in favor of simple redirect to github for bash3boilerplate.sh
|
||||||
|
- [x] Make tests pass again
|
||||||
|
- [x] Make linting and style checking separate actions
|
||||||
|
- [x] Add feature to edit/update comments in ini file (#132, @rfuehrer)
|
||||||
|
- [x] Upgrade to `lanyon@0.1.16`
|
||||||
|
- [x] Capture correct error_code in err_report (#124, @eval)
|
||||||
|
- [x] Enhanced ini file handling: create new file, create new sections, handle default section, read key from given section (@rfuehrer)
|
||||||
|
|
||||||
|
## v2.4.2
|
||||||
|
|
||||||
|
Released: 2019-11-07.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v2.4.1...v2.4.2).
|
||||||
|
|
||||||
|
- [x] Upgrade to `lanyon@0.1.16`
|
||||||
|
- [x] Capture correct error_code in err_report (#124, @eval)
|
||||||
|
- [x] Enhanced ini file handling: create new file, create new sections, handle default section, read key from given section (@rfuehrer)
|
||||||
|
|
||||||
|
## v2.4.1
|
||||||
|
|
||||||
|
Released: 2019-11-07.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v2.3.0...v2.4.1).
|
||||||
|
|
||||||
|
- [x] Upgrade to `lanyon@0.1.7`
|
||||||
|
- [x] Allow counting how many times an argument is used (@genesiscloud)
|
||||||
|
- [x] Fix typos in megamount (thanks @gsaponaro)
|
||||||
|
- [x] Enable color in screen or tmux (#92, @gmasse)
|
||||||
|
- [x] Change `egrep` to `grep -E` in test and lib scripts to comply with ShellCheck (#92, @gmasse)
|
||||||
|
- [x] Fix typo in FAQ (#92, @gmasse)
|
||||||
|
- [x] Fix Travis CI failure on src/templater.sh (@gmasse)
|
||||||
|
- [x] Add magic variable which contains full command invocation
|
||||||
|
- [x] More contrasted alert and emergency colors (#111 @gmeral)
|
||||||
|
- [x] Add support for repeatable arguments (@genesiscloud)
|
||||||
|
- [x] Fix remaining warnings with shellcheck v0.7.0 (#107, @genesiscloud)
|
||||||
|
|
||||||
|
## v2.4.0
|
||||||
|
|
||||||
|
Released: 2016-12-21.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v2.3.0...v2.4.0).
|
||||||
|
|
||||||
|
- [x] Upgrade to `lanyon@0.0.143`
|
||||||
|
|
||||||
|
## v2.3.0
|
||||||
|
|
||||||
|
Released: 2016-12-21.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v2.2.0...v2.3.0).
|
||||||
|
|
||||||
|
- [x] Add magic variable `__i_am_main_script` to distinguish if b3bp is being sourced or called directly (#45, @zbeekman)
|
||||||
|
- [x] Add style checks for tab characters and trailing whitespace (@zbeekman)
|
||||||
|
- [x] Add backtracing to help localize errors (#44, @zbeekman)
|
||||||
|
- [x] Additional FAQ entries (#47, suggested by @gdevenyi, implemented by @zbeekman)
|
||||||
|
- [x] Ensure that shifting over `--` doesn't throw an errexit error (#21, @zbeekman)
|
||||||
|
- [x] Add Pull Request template (#83)
|
||||||
|
|
||||||
## v2.2.0
|
## v2.2.0
|
||||||
|
|
||||||
Released: 2016-12-21. [Commit log](https://github.com/kvz/bash3boilerplate/compare/v2.1.0...v2.2.0)
|
Released: 2016-12-21.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v2.1.0...v2.2.0).
|
||||||
|
|
||||||
- README and FAQ improvements (#66, @mstreuhofer)
|
- [x] README and FAQ improvements (#66, @mstreuhofer)
|
||||||
- Add support for sourcing b3bp (#61, @mstreuhofer)
|
- [x] Add support for sourcing b3bp (#61, @mstreuhofer)
|
||||||
- Upgrade all Node.js dependencies for development (#78)
|
- [x] Upgrade all Node.js dependencies for development (#78)
|
||||||
- Switch to http://lanyon.io for static site building, add a new logo
|
- [x] Switch to http://lanyon.io for static site building, add a new logo
|
||||||
- Cleanup environment variables (#58, @mstreuhofer)
|
- [x] Cleanup environment variables (#58, @mstreuhofer)
|
||||||
- Support multi-line logs (#57, @mstreuhofer)
|
- [x] Support multi-line logs (#57, @mstreuhofer)
|
||||||
- Run shellcheck as part of the acceptance test (#79, @mstreuhofer)
|
- [x] Run shellcheck as part of the acceptance test (#79, @mstreuhofer)
|
||||||
- Brace all variables, used `[[` instead of `[` (#33, #76, @mstreuhofer)
|
- [x] Brace all variables, used `[[` instead of `[` (#33, #76, @mstreuhofer)
|
||||||
- Add automatic usage validation for required args (#22, #65, @mstreuhofer)
|
- [x] Add automatic usage validation for required args (#22, #65, @mstreuhofer)
|
||||||
- Remove all usage of eval (@mstreuhofer)
|
- [x] Remove all usage of eval (@mstreuhofer)
|
||||||
- Get rid of awk, sed & egrep usage (#71, @mstreuhofer)
|
- [x] Get rid of awk, sed & egrep usage (#71, @mstreuhofer)
|
||||||
- Fix auto-color-off code (#69, #70, @mstreuhofer)
|
- [x] Fix auto-color-off code (#69, #70, @mstreuhofer)
|
||||||
- Use shellcheck to find and fix unclean code (#68, #80, @mstreuhofer)
|
- [x] Use shellcheck to find and fix unclean code (#68, #80, @mstreuhofer)
|
||||||
- Allow for multiline opt description in `__usage` (#7, @mstreuhofer)
|
- [x] Allow for multiline opt description in `__usage` (#7, @mstreuhofer)
|
||||||
- Allow `__usage` and `__helptext` to be defined before sourcing `main.sh` thus makeing b3bp behave like a library (@mstreuhofer)
|
- [x] Allow `__usage` and `__helptext` to be defined before sourcing `main.sh` thus makeing b3bp behave like a library (@mstreuhofer)
|
||||||
- Add the same License text to each script header (@mstreuhofer)
|
- [x] Add the same License text to each script header (@mstreuhofer)
|
||||||
|
|
||||||
## v2.1.0
|
## v2.1.0
|
||||||
|
|
||||||
Released: 2016-11-08. [Commit log](https://github.com/kvz/bash3boilerplate/compare/v2.0.0...v2.1.0)
|
Released: 2016-11-08.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v2.0.0...v2.1.0).
|
||||||
|
|
||||||
- Cleanup b3bp variables (adds prefixes across the board) (thanks @mstreuhofer)
|
- [x] Cleanup b3bp variables (adds prefixes across the board) (thanks @mstreuhofer)
|
||||||
- Add multi-line logging support (thanks @mstreuhofer)
|
- [x] Add multi-line logging support (thanks @mstreuhofer)
|
||||||
- Mangle long-option names to allow dashes (thanks @zbeekman)
|
- [x] Mangle long-option names to allow dashes (thanks @zbeekman)
|
||||||
- Remove OS detection altogether (#38, thx @zbeekman)
|
- [x] Remove OS detection altogether (#38, thx @zbeekman)
|
||||||
- Offer the main template for download as http://bash3boilerplate.sh/main.sh
|
- [x] Offer the main template for download as http://bash3boilerplate.sh/main.sh
|
||||||
- Better OS detection (#38, thx @moviuro)
|
- [x] Better OS detection (#38, thx @moviuro)
|
||||||
- Improve README copy (#34, thx galaktos)
|
- [x] Improve README copy (#34, thx galaktos)
|
||||||
- Fix unquoted variable access within (#34 thx galaktos)
|
- [x] Fix unquoted variable access within (#34 thx galaktos)
|
||||||
- For delete-key-friendliness, bundle the commandline definition block along with its parser
|
- [x] For delete-key-friendliness, bundle the commandline definition block along with its parser
|
||||||
- Less verbose header comments
|
- [x] Less verbose header comments
|
||||||
- For delete-key-friendliness, don't crash on undeclared help vars
|
- [x] For delete-key-friendliness, don't crash on undeclared help vars
|
||||||
- Introduce `errtrace`, which is on by default (BREAKING)
|
- [x] Introduce `errtrace`, which is on by default (BREAKING)
|
||||||
- Add a configurable `helptext` that is left alone by the parses and allows you to have a richer help
|
- [x] Add a configurable `helptext` that is left alone by the parses and allows you to have a richer help
|
||||||
- Add a simple documentation website
|
- [x] Add a simple documentation website
|
||||||
- Add best practice of using `__double_underscore_prefixed_vars` to indicate global variables that are solely controlled inside your script
|
- [x] Add best practice of using `__double_underscore_prefixed_vars` to indicate global variables that are solely controlled inside your script
|
||||||
- Make license more permissive by not requiring distribution of the LICENSE file if the copyright & attribution comments are left intact
|
- [x] Make license more permissive by not requiring distribution of the LICENSE file if the copyright & attribution comments are left intact
|
||||||
- Respect `--no-color` by setting the `NO_COLOR` flag in `main.sh` (#25, thx @gdevenyi)
|
- [x] Respect `--no-color` by setting the `NO_COLOR` flag in `main.sh` (#25, thx @gdevenyi)
|
||||||
- Split out changelog into separate file
|
- [x] Split out changelog into separate file
|
||||||
- Added a [FAQ](./FAQ.md) (#15, #14, thanks @rouson)
|
- [x] Added a [FAQ](./FAQ.md) (#15, #14, thanks @rouson)
|
||||||
- Fix Travis OSX testing (before, it would silently pass failures) (#10)
|
- [x] Fix Travis OSX testing (before, it would silently pass failures) (#10)
|
||||||
- Enable dashes in long, GNU style options, as well as numbers (thanks @zbeekman)
|
- [x] Enable dashes in long, GNU style options, as well as numbers (thanks @zbeekman)
|
||||||
|
|
||||||
## v2.0.0
|
## v2.0.0
|
||||||
|
|
||||||
Released: 2016-02-17. [Commit log](https://github.com/kvz/bash3boilerplate/compare/v1.2.1...v2.0.0)
|
Released: 2016-02-17.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v1.2.1...v2.0.0).
|
||||||
|
|
||||||
- Add tests for `templater` and follow Library export best practices
|
- [x] Add tests for `templater` and follow Library export best practices
|
||||||
- Add tests for `ini_val` and follow Library export best practices
|
- [x] Add tests for `ini_val` and follow Library export best practices
|
||||||
- Add tests for `parse_url` and follow Library export best practices
|
- [x] Add tests for `parse_url` and follow Library export best practices
|
||||||
- Add tests for `megamount` and follow Library export best practices
|
- [x] Add tests for `megamount` and follow Library export best practices
|
||||||
- Remove `bump` from `src` (BREAKING)
|
- [x] Remove `bump` from `src` (BREAKING)
|
||||||
- Remove `semver` from `src` (BREAKING)
|
- [x] Remove `semver` from `src` (BREAKING)
|
||||||
|
|
||||||
## v1.2.1
|
## v1.2.1
|
||||||
|
|
||||||
Released: 2016-02-17. [Commit log](https://github.com/kvz/bash3boilerplate/compare/v1.2.0...v1.2.1)
|
Released: 2016-02-17.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v1.2.0...v1.2.1).
|
||||||
|
|
||||||
- Add Travis CI automated testing for OSX (thanks @zbeekman)
|
- [x] Add Travis CI automated testing for OSX (thanks @zbeekman)
|
||||||
|
|
||||||
## v1.2.0
|
## v1.2.0
|
||||||
|
|
||||||
Released: 2016-02-16. [Commit log](https://github.com/kvz/bash3boilerplate/compare/v1.1.0...v1.2.0)
|
Released: 2016-02-16.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v1.1.0...v1.2.0).
|
||||||
|
|
||||||
- Allow disabling colors via `NO_COLOR` environment variable
|
- [x] Allow disabling colors via `NO_COLOR` environment variable
|
||||||
- Enable `errexit`, `nounset` and `pipefail` options at the top of the script already
|
- [x] Enable `errexit`, `nounset` and `pipefail` options at the top of the script already
|
||||||
- More refined colors (thanks @arathai)
|
- [x] More refined colors (thanks @arathai)
|
||||||
- Add a changelog to the README
|
- [x] Add a changelog to the README
|
||||||
- Add `__os` magic var (limited to discovering OSX and defaulting to Linux for now)
|
- [x] Add `__os` magic var (limited to discovering OSX and defaulting to Linux for now)
|
||||||
- Add `__base` magic var (`main`, if the source script is `main.sh`)
|
- [x] Add `__base` magic var (`main`, if the source script is `main.sh`)
|
||||||
- Enable long, GNU style options (thanks @zbeekman)
|
- [x] Enable long, GNU style options (thanks @zbeekman)
|
||||||
- Add Travis CI automated testing for Linux
|
- [x] Add Travis CI automated testing for Linux
|
||||||
|
|
||||||
## v1.1.0
|
## v1.1.0
|
||||||
|
|
||||||
Released: 2015-06-29. [Commit log](https://github.com/kvz/bash3boilerplate/compare/v1.0.3...v1.1.0)
|
Released: 2015-06-29.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/v1.0.3...v1.1.0).
|
||||||
|
|
||||||
- Add `ALLOW_REMAINDERS` configuration to templater
|
- [x] Add `ALLOW_REMAINDERS` configuration to templater
|
||||||
- Fix typo: 'debugmdoe' to 'debugmode' (thanks @jokajak)
|
- [x] Fix typo: 'debugmdoe' to 'debugmode' (thanks @jokajak)
|
||||||
- Use `${BASH_SOURCE[0]}` for `__file` instead of `${0}`
|
- [x] Use `${BASH_SOURCE[0]}` for `__file` instead of `${0}`
|
||||||
|
|
||||||
## v1.0.3
|
## v1.0.3
|
||||||
|
|
||||||
Released: 2014-11-02. [Commit log](https://github.com/kvz/bash3boilerplate/compare/5db569125319a89b9561b434db84e4d91faefb63...v1.0.3)
|
Released: 2014-11-02.
|
||||||
|
[Diff](https://github.com/kvz/bash3boilerplate/compare/5db569125319a89b9561b434db84e4d91faefb63...v1.0.3).
|
||||||
|
|
||||||
- Add `ini_val`, `megamount`, `parse_url`
|
- [x] Add `ini_val`, `megamount`, `parse_url`
|
||||||
- Add re-usable libraries in `./src`
|
- [x] Add re-usable libraries in `./src`
|
||||||
- Use npm as an additional distribution channel
|
- [x] Use npm as an additional distribution channel
|
||||||
|
79
FAQ.md
@ -1,21 +1,22 @@
|
|||||||
[This document is formatted with GitHub-Flavored Markdown. ]:#
|
[This document is formatted with GitHub-Flavored Markdown. ]: #
|
||||||
[For better viewing, including hyperlinks, read it online at ]:#
|
[For better viewing, including hyperlinks, read it online at ]: #
|
||||||
[https://github.com/kvz/bash3boilerplate/blob/master/FAQ.md ]:#
|
[https://github.com/kvz/bash3boilerplate/blob/HEAD/FAQ.md ]: #
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
* [What is a CLI](#what-is-a-cli)?
|
- [What is a CLI](#what-is-a-cli)?
|
||||||
* [How do I incorporate BASH3 Boilerplate into my own project](#how-do-i-incorporate-bash3-boilerplate-into-my-own-project)?
|
- [How do I incorporate BASH3 Boilerplate into my own project](#how-do-i-incorporate-bash3-boilerplate-into-my-own-project)?
|
||||||
* [How do I add a command-line flag](#how-do-i-add-a-command-line-flag)?
|
- [How do I add a command-line flag](#how-do-i-add-a-command-line-flag)?
|
||||||
* [How do I access the value of a command-line argument](#how-do-i-access-the-value-of-a-command-line-argument)?
|
- [How do I access the value of a command-line argument](#how-do-i-access-the-value-of-a-command-line-argument)?
|
||||||
* [What is a magic variable](#what-is-a-magic-variable)?
|
- [What is a magic variable](#what-is-a-magic-variable)?
|
||||||
* [How do I submit an issue report](#how-do-i-submit-an-issue-report)?
|
- [How do I submit an issue report](#how-do-i-submit-an-issue-report)?
|
||||||
* [How can I contribute to this project](#how-can-i-contribute-to-this-project)?
|
- [How can I contribute to this project](#how-can-i-contribute-to-this-project)?
|
||||||
* [Why are you typing BASH in all caps](#why-are-you-typing-bash-in-all-caps)?
|
- [Why are you typing BASH in all caps](#why-are-you-typing-bash-in-all-caps)?
|
||||||
* [How can I locally develop and preview the b3bp website](#how-can-i-locally-develop-and-preview-the-b3bp-website)?
|
- [You are saying you are portable, but why won't b3bp code run in dash / busybox / posh / ksh / mksh / zsh](#you-are-saying-you-are-portable-but-why-wont-b3bp-code-run-in-dash--busybox--posh--ksh--mksh--zsh)?
|
||||||
* [You are saying you are portable, but why won't b3bp code run in dash / busybox / posh / ksh / mksh / zsh](#you-are-saying-you-are-portable-but-why-wont-b3bp-code-run-in-dash--busybox--posh--ksh--mksh--zsh)?
|
- [How do I do Operating System detection](#how-do-i-do-operating-system-detection)?
|
||||||
* [How do I do Operating System detection](#how-do-i-do-operating-system-detection)?
|
- [How do I access a potentially unset (environment) variable](#how-do-i-access-a-potentially-unset-environment-variable)?
|
||||||
* [How do I access a potentially unset (environment) variable](#how-do-i-access-a-potentially-unset-environment-variable)?
|
- [How can I detect or trap CTRL-C and other signals](#how-can-i-detect-or-trap-ctrl-c-and-other-signals)?
|
||||||
|
- [How can I get the PID of my running script](how-can-i-get-the-pid-of-my-running-script)?
|
||||||
|
|
||||||
<!--more-->
|
<!--more-->
|
||||||
|
|
||||||
@ -53,12 +54,12 @@ source main.sh
|
|||||||
1. Copy the line from the `main.sh` [read block](https://github.com/kvz/bash3boilerplate/blob/v2.1.0/main.sh#L109-L115) that most resembles the desired behavior and paste the line into the same block.
|
1. Copy the line from the `main.sh` [read block](https://github.com/kvz/bash3boilerplate/blob/v2.1.0/main.sh#L109-L115) that most resembles the desired behavior and paste the line into the same block.
|
||||||
1. Edit the single-character (e.g., `-d`) and, if present, the multi-character (e.g., `--debug`) versions of the flag in the copied line.
|
1. Edit the single-character (e.g., `-d`) and, if present, the multi-character (e.g., `--debug`) versions of the flag in the copied line.
|
||||||
1. Omit the `[arg]` text in the copied line, if the desired flag takes no arguments.
|
1. Omit the `[arg]` text in the copied line, if the desired flag takes no arguments.
|
||||||
1. Omit or edit the text after `Default:` to set or not set default values, respectively.
|
1. Omit or edit the text after `Default=` to set or not set default values, respectively.
|
||||||
1. Omit the `Required.` text, if the flag is optional.
|
1. Omit the `Required.` text, if the flag is optional.
|
||||||
|
|
||||||
## How do I access the value of a command-line argument?
|
## How do I access the value of a command-line argument?
|
||||||
|
|
||||||
To find out the value of an argument, append the corresponding single-character flag to the text `$arg_`. For example, if the [read block]
|
To find out the value of an argument, append the corresponding single-character flag to the text `$arg_`. For example, if the [read block]
|
||||||
contains the line
|
contains the line
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -81,7 +82,7 @@ Please visit our [Issues](https://github.com/kvz/bash3boilerplate/issues) page.
|
|||||||
|
|
||||||
## How can I contribute to this project?
|
## How can I contribute to this project?
|
||||||
|
|
||||||
Please fork this repository. After that, create a branch containing your suggested changes and submit a pull request based on the master branch
|
Please fork this repository. After that, create a branch containing your suggested changes and submit a pull request based on the main branch
|
||||||
of <https://github.com/kvz/bash3boilerplate/>. We are always more than happy to accept your contributions!
|
of <https://github.com/kvz/bash3boilerplate/>. We are always more than happy to accept your contributions!
|
||||||
|
|
||||||
## Why are you typing BASH in all caps?
|
## Why are you typing BASH in all caps?
|
||||||
@ -92,29 +93,6 @@ This project's name, however, is "BASH3 Boilerplate". It is a reference to
|
|||||||
only for crafting webpages.
|
only for crafting webpages.
|
||||||
Somewhat inconsistent – but true to Unix ancestry – the abbreviation for our project is "b3bp".
|
Somewhat inconsistent – but true to Unix ancestry – the abbreviation for our project is "b3bp".
|
||||||
|
|
||||||
## How can I locally develop and preview the b3bp website?
|
|
||||||
|
|
||||||
You should have a working Node.js >=10 and Ruby >=2 install on your workstation. When that is the case, you can run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run start
|
|
||||||
```
|
|
||||||
|
|
||||||
This will install and start all required services and automatically open a webbrowser that reloads as soon as you make any changes to the source.
|
|
||||||
|
|
||||||
The source mainly consists of:
|
|
||||||
|
|
||||||
- `./README.md` (Front page)
|
|
||||||
- `./FAQ.md` (FAQ page)
|
|
||||||
- `./CHANGELOG.md` (changelog page)
|
|
||||||
- `./website/_layouts/default.html` (the design in which all pages are rendered)
|
|
||||||
- `./website/assets/app.js` (main JS file)
|
|
||||||
- `./website/assets/style.css` (main CSS file)
|
|
||||||
|
|
||||||
The rest is dark magic from which you should probably steer clear. : )
|
|
||||||
|
|
||||||
Any changes should be proposed as PRs. Anything added to `master` is automatically deployed using a combination of Travis CI and GitHub Pages.
|
|
||||||
|
|
||||||
## You are saying you are portable, but why won't b3bp code run in dash / busybox / posh / ksh / mksh / zsh?
|
## You are saying you are portable, but why won't b3bp code run in dash / busybox / posh / ksh / mksh / zsh?
|
||||||
|
|
||||||
When we say _portable_, we mean across Bash versions. Bash is widespread and most systems
|
When we say _portable_, we mean across Bash versions. Bash is widespread and most systems
|
||||||
@ -172,3 +150,22 @@ NAME3=${NAME3:-Damian}; echo ${NAME3} # echos Damian, $NAME3 is set to Damian
|
|||||||
```
|
```
|
||||||
|
|
||||||
This subject is briefly touched on as well in the [Safety and Portability section under point 5](README.md#safety-and-portability). b3bp currently uses [method 1](https://github.com/kvz/bash3boilerplate/blob/v2.1.0/main.sh#L252) when we want to access a variable that could be undeclared, and [method 3](https://github.com/kvz/bash3boilerplate/blob/v2.1.0/main.sh#L31) when we also want to set a default to an undeclared variable, because we feel it is more readable than method 2. We feel `:=` is easily overlooked, and not very beginner friendly. Method 3 seems more explicit in that regard in our humble opinion.
|
This subject is briefly touched on as well in the [Safety and Portability section under point 5](README.md#safety-and-portability). b3bp currently uses [method 1](https://github.com/kvz/bash3boilerplate/blob/v2.1.0/main.sh#L252) when we want to access a variable that could be undeclared, and [method 3](https://github.com/kvz/bash3boilerplate/blob/v2.1.0/main.sh#L31) when we also want to set a default to an undeclared variable, because we feel it is more readable than method 2. We feel `:=` is easily overlooked, and not very beginner friendly. Method 3 seems more explicit in that regard in our humble opinion.
|
||||||
|
|
||||||
|
## How can I detect or trap Ctrl-C and other signals?
|
||||||
|
|
||||||
|
You can trap [Unix signals](https://en.wikipedia.org/wiki/Unix_signal) like [Ctrl-C](https://en.wikipedia.org/wiki/Control-C) with code similar to:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# trap ctrl-c and call ctrl_c()
|
||||||
|
trap ctrl_c INT
|
||||||
|
|
||||||
|
function ctrl_c() {
|
||||||
|
echo "** Trapped CTRL-C"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See http://mywiki.wooledge.org/SignalTrap for a list of signals, examples, and an in depth discussion.
|
||||||
|
|
||||||
|
## How can I get the PID of my running script?
|
||||||
|
|
||||||
|
The PID of a running script is contained in the `${$}` variable. This is _not_ the pid of any subshells. With Bash 4 you can get the PID of your subshell with `${BASHPID}`. For a comprehensive list of Bash built in variables see, e.g., http://www.tldp.org/LDP/abs/html/internalvariables.html
|
||||||
|
25
Makefile
@ -3,6 +3,9 @@
|
|||||||
#
|
#
|
||||||
# https://www.npmjs.com/package/fakefile
|
# https://www.npmjs.com/package/fakefile
|
||||||
#
|
#
|
||||||
|
# Please do not edit this file directly, but propose changed upstream instead:
|
||||||
|
# https://github.com/kvz/fakefile/blob/main/Makefile
|
||||||
|
#
|
||||||
# This Makefile offers convience shortcuts into any Node.js project that utilizes npm scripts.
|
# This Makefile offers convience shortcuts into any Node.js project that utilizes npm scripts.
|
||||||
# It functions as a wrapper around the actual listed in `package.json`
|
# It functions as a wrapper around the actual listed in `package.json`
|
||||||
# So instead of typing:
|
# So instead of typing:
|
||||||
@ -25,10 +28,26 @@
|
|||||||
# OSX users will have to install bash-completion
|
# OSX users will have to install bash-completion
|
||||||
# (http://davidalger.com/development/bash-completion-on-os-x-with-brew/)
|
# (http://davidalger.com/development/bash-completion-on-os-x-with-brew/)
|
||||||
|
|
||||||
|
ifeq ($(shell test -e ./yarn.lock && echo -n yes),yes)
|
||||||
|
RUNNER=yarn
|
||||||
|
INSTALLER=yarn install
|
||||||
|
else
|
||||||
|
RUNNER=npm run
|
||||||
|
INSTALLER=npm install
|
||||||
|
endif
|
||||||
|
|
||||||
define npm_script_targets
|
define npm_script_targets
|
||||||
TARGETS := $(shell node -e 'for (var k in require("./package.json").scripts) {console.log(k.replace(/:/g, "-"));}')
|
TARGETS := $(shell \
|
||||||
|
node -e 'for (var k in require("./package.json").scripts) {console.log(k.replace(/:/g, "-"));}'
|
||||||
|
| grep -v -E "^install$$"
|
||||||
|
)
|
||||||
$$(TARGETS):
|
$$(TARGETS):
|
||||||
npm run $(subst -,:,$(MAKECMDGOALS))
|
$(RUNNER) $(shell \
|
||||||
|
node -e 'for (var k in require("./package.json").scripts) {console.log(k.replace(/:/g, "-"), k);}'
|
||||||
|
| grep -E "^$(MAKECMDGOALS)\s"
|
||||||
|
| head -n1
|
||||||
|
| awk '{print $$2}'
|
||||||
|
)
|
||||||
|
|
||||||
.PHONY: $$(TARGETS)
|
.PHONY: $$(TARGETS)
|
||||||
endef
|
endef
|
||||||
@ -37,4 +56,4 @@ $(eval $(call npm_script_targets))
|
|||||||
|
|
||||||
# These npm run scripts are available, without needing to be mentioned in `package.json`
|
# These npm run scripts are available, without needing to be mentioned in `package.json`
|
||||||
install:
|
install:
|
||||||
npm run install
|
$(INSTALLER)
|
||||||
|
80
README.md
@ -1,19 +1,17 @@
|
|||||||
[](https://travis-ci.org/kvz/bash3boilerplate)
|
[This document is formatted with GitHub-Flavored Markdown. ]: #
|
||||||
|
[For better viewing, including hyperlinks, read it online at ]: #
|
||||||
|
[https://github.com/kvz/bash3boilerplate/blob/HEAD/README.md]: #
|
||||||
|
|
||||||
[This document is formatted with GitHub-Flavored Markdown. ]:#
|
- [Overview](#overview)
|
||||||
[For better viewing, including hyperlinks, read it online at ]:#
|
- [Goals](#goals)
|
||||||
[https://github.com/kvz/bash3boilerplate/blob/master/README.md]:#
|
- [Features](#features)
|
||||||
|
- [Installation](#installation)
|
||||||
* [Overview](#overview)
|
- [Changelog](#changelog)
|
||||||
* [Goals](#goals)
|
- [Frequently Asked Questions](#frequently-asked-questions)
|
||||||
* [Features](#features)
|
- [Best Practices](#best-practices)
|
||||||
* [Installation](#installation)
|
- [Who uses b3bp](#who-uses-b3bp)
|
||||||
* [Changelog](#changelog)
|
- [Authors](#authors)
|
||||||
* [Frequently Asked Questions](#frequently-asked-questions)
|
- [License](#license)
|
||||||
* [Best Practices](#best-practices)
|
|
||||||
* [Who uses b3bp](#who-uses-b3bp)
|
|
||||||
* [Authors](#authors)
|
|
||||||
* [License](#license)
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@ -21,10 +19,10 @@
|
|||||||
|
|
||||||
When hacking up Bash scripts, there are often things such as logging or command-line argument parsing that:
|
When hacking up Bash scripts, there are often things such as logging or command-line argument parsing that:
|
||||||
|
|
||||||
- You need every time
|
- You need every time
|
||||||
- Come with a number of pitfalls you want to avoid
|
- Come with a number of pitfalls you want to avoid
|
||||||
- Keep you from your actual work
|
- Keep you from your actual work
|
||||||
|
|
||||||
Here's an attempt to bundle those things in a generalized way so that
|
Here's an attempt to bundle those things in a generalized way so that
|
||||||
they are reusable as-is in most scripts.
|
they are reusable as-is in most scripts.
|
||||||
|
|
||||||
@ -32,7 +30,7 @@ We call it "BASH3 Boilerplate" or b3bp for short.
|
|||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
Delete-Key-**Friendly**. Instead of introducing packages, includes, compilers, etc., we propose using [`main.sh`](http://bash3boilerplate.sh/main.sh) as a base and removing the parts you don't need.
|
Delete-Key-**Friendly**. Instead of introducing packages, includes, compilers, etc., we propose using [`main.sh`](https://bash3boilerplate.sh/main.sh) as a base and removing the parts you don't need.
|
||||||
While this may feel a bit archaic at first, it is exactly the strength of Bash scripts that we should want to embrace.
|
While this may feel a bit archaic at first, it is exactly the strength of Bash scripts that we should want to embrace.
|
||||||
|
|
||||||
**Portable**. We are targeting Bash 3 (OSX still ships
|
**Portable**. We are targeting Bash 3 (OSX still ships
|
||||||
@ -47,7 +45,7 @@ dependency.
|
|||||||
- Configuration by environment variables
|
- Configuration by environment variables
|
||||||
- Simple command-line argument parsing that requires no external dependencies. Definitions are parsed from help info, ensuring there will be no duplication
|
- Simple command-line argument parsing that requires no external dependencies. Definitions are parsed from help info, ensuring there will be no duplication
|
||||||
- Helpful magic variables like `__file` and `__dir`
|
- Helpful magic variables like `__file` and `__dir`
|
||||||
- Logging that supports colors and is compatible with [Syslog Severity levels](http://en.wikipedia.org/wiki/Syslog#Severity_levels), as well as the [twelve-factor](http://12factor.net/) guidelines
|
- Logging that supports colors and is compatible with [Syslog Severity levels](https://en.wikipedia.org/wiki/Syslog#Severity_levels), as well as the [twelve-factor](https://12factor.net/) guidelines
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -58,7 +56,7 @@ There are three different ways to install b3bp:
|
|||||||
Use curl or wget to download the source and save it as your script. Then you can start deleting the unwanted bits, and adding your own logic.
|
Use curl or wget to download the source and save it as your script. Then you can start deleting the unwanted bits, and adding your own logic.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wget http://bash3boilerplate.sh/main.sh
|
wget https://bash3boilerplate.sh/main.sh
|
||||||
vim main.sh
|
vim main.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -95,15 +93,14 @@ As of `v1.0.3`, b3bp offers some nice re-usable libraries in `./src`. In order t
|
|||||||
|
|
||||||
### Function packaging
|
### Function packaging
|
||||||
|
|
||||||
It is nice to have a Bash package that can not only be used in the terminal, but also invoked as a command line function. In order to achieve this, the exporting of your functionality *should* follow this pattern:
|
It is nice to have a Bash package that can not only be used in the terminal, but also invoked as a command line function. In order to achieve this, the exporting of your functionality _should_ follow this pattern:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
|
if [[ "${BASH_SOURCE[0]}" = "${0}" ]]; then
|
||||||
export -f my_script
|
|
||||||
else
|
|
||||||
my_script "${@}"
|
my_script "${@}"
|
||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
export -f my_script
|
||||||
```
|
```
|
||||||
|
|
||||||
This allows a user to `source` your script or invoke it as a script.
|
This allows a user to `source` your script or invoke it as a script.
|
||||||
@ -116,7 +113,7 @@ $ source my_script.sh
|
|||||||
$ my_script some more args --blah
|
$ my_script some more args --blah
|
||||||
```
|
```
|
||||||
|
|
||||||
(taken from the [bpkg](https://raw.githubusercontent.com/bpkg/bpkg/master/README.md) project)
|
(taken from the [bpkg](https://raw.githubusercontent.com/bpkg/bpkg/HEAD/README.md) project)
|
||||||
|
|
||||||
### Scoping
|
### Scoping
|
||||||
|
|
||||||
@ -126,9 +123,11 @@ $ my_script some more args --blah
|
|||||||
|
|
||||||
### Coding style
|
### Coding style
|
||||||
|
|
||||||
1. Use two spaces for tabs.
|
1. Use two spaces for tabs, do not use tab characters.
|
||||||
|
1. Do not introduce whitespace at the end of lines or on blank lines as they obfuscate version control diffs.
|
||||||
1. Use long options (`logger --priority` vs `logger -p`). If you are on the CLI, abbreviations make sense for efficiency. Nevertheless, when you are writing reusable scripts, a few extra keystrokes will pay off in readability and avoid ventures into man pages in the future, either by you or your collaborators. Similarly, we prefer `set -o nounset` over `set -u`.
|
1. Use long options (`logger --priority` vs `logger -p`). If you are on the CLI, abbreviations make sense for efficiency. Nevertheless, when you are writing reusable scripts, a few extra keystrokes will pay off in readability and avoid ventures into man pages in the future, either by you or your collaborators. Similarly, we prefer `set -o nounset` over `set -u`.
|
||||||
1. Use a single equal sign when checking `if [ "${NAME}" = "Kevin" ]`; double or triple signs are not needed.
|
1. Use a single equal sign when checking `if [[ "${NAME}" = "Kevin" ]]`; double or triple signs are not needed.
|
||||||
|
1. Use the new bash builtin test operator (`[[ ... ]]`) rather than the old single square bracket test operator or explicit call to `test`.
|
||||||
|
|
||||||
### Safety and Portability
|
### Safety and Portability
|
||||||
|
|
||||||
@ -136,34 +135,41 @@ $ my_script some more args --blah
|
|||||||
1. Use `set`, rather than relying on a shebang like `#!/usr/bin/env bash -e`, since that is neutralized when someone runs your script as `bash yourscript.sh`.
|
1. Use `set`, rather than relying on a shebang like `#!/usr/bin/env bash -e`, since that is neutralized when someone runs your script as `bash yourscript.sh`.
|
||||||
1. Use `#!/usr/bin/env bash`, as it is more portable than `#!/bin/bash`.
|
1. Use `#!/usr/bin/env bash`, as it is more portable than `#!/bin/bash`.
|
||||||
1. Use `${BASH_SOURCE[0]}` if you refer to current file, even if it is sourced by a parent script. In other cases, use `${0}`.
|
1. Use `${BASH_SOURCE[0]}` if you refer to current file, even if it is sourced by a parent script. In other cases, use `${0}`.
|
||||||
1. Use `:-` if you want to test variables that could be undeclared. For instance, with `if [ "${NAME:-}" = "Kevin" ]`, `$NAME` will evaluate to `Kevin` if the variable is empty. The variable itself will remain unchanged. The syntax to assign a default value is `${NAME:=Kevin}`.
|
1. Use `:-` if you want to test variables that could be undeclared. For instance, with `if [[ "${NAME:-}" = "Kevin" ]]`, `$NAME` will evaluate to `Kevin` if the variable is empty. The variable itself will remain unchanged. The syntax to assign a default value is `${NAME:=Kevin}`.
|
||||||
|
|
||||||
## Who uses b3bp?
|
## Who uses b3bp?
|
||||||
|
|
||||||
- [Transloadit](https://transloadit.com)
|
- [Transloadit](https://transloadit.com)
|
||||||
- [OpenCoarrays](http://www.opencoarrays.org)
|
- [OpenCoarrays](https://www.opencoarrays.org)
|
||||||
- [Sourcery Institute](http://www.sourceryinstitute.org)
|
- [Sourcery Institute](https://www.sourceryinstitute.org)
|
||||||
- [Computational Brain Anatomy Laboratory](http://cobralab.ca/)
|
- [Computational Brain Anatomy Laboratory](https://cobralab.ca/)
|
||||||
|
- [Genesis Cloud](https://genesiscloud.com/)
|
||||||
|
|
||||||
We are looking for endorsements! Are you also using b3bp? [Let us know](https://github.com/kvz/bash3boilerplate/issues/new?title=I%20use%20b3bp) and get listed.
|
We are looking for endorsements! Are you also using b3bp? [Let us know](https://github.com/kvz/bash3boilerplate/issues/new?title=I%20use%20b3bp) and get listed.
|
||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
- [Kevin van Zonneveld](http://kvz.io)
|
- [Kevin van Zonneveld](https://kvz.io)
|
||||||
- [Izaak Beekman](https://izaakbeekman.com/)
|
- [Izaak Beekman](https://izaakbeekman.com/)
|
||||||
- [Manuel Streuhofer](https://github.com/mstreuhofer)
|
- [Manuel Streuhofer](https://github.com/mstreuhofer)
|
||||||
- [Alexander Rathai](mailto:Alexander.Rathai@gmail.com)
|
- [Alexander Rathai](mailto:Alexander.Rathai@gmail.com)
|
||||||
- [Dr. Damian Rouson](http://www.sourceryinstitute.org/) (documentation, feedback)
|
- [Dr. Damian Rouson](https://www.sourceryinstitute.org/) (documentation, feedback)
|
||||||
- [@jokajak](https://github.com/jokajak) (documentation)
|
- [@jokajak](https://github.com/jokajak) (documentation)
|
||||||
- [Gabriel A. Devenyi](http://staticwave.ca/) (feedback)
|
- [Gabriel A. Devenyi](https://staticwave.ca/) (feedback)
|
||||||
- [@bravo-kernel](https://github.com/bravo-kernel) (feedback)
|
- [@bravo-kernel](https://github.com/bravo-kernel) (feedback)
|
||||||
- [@skanga](https://github.com/skanga) (feedback)
|
- [@skanga](https://github.com/skanga) (feedback)
|
||||||
- [galaktos](https://www.reddit.com/user/galaktos) (feedback)
|
- [galaktos](https://www.reddit.com/user/galaktos) (feedback)
|
||||||
- [@moviuro](https://github.com/moviuro) (feedback)
|
- [@moviuro](https://github.com/moviuro) (feedback)
|
||||||
|
- [Giovanni Saponaro](https://github.com/gsaponaro) (feedback)
|
||||||
|
- [Germain Masse](https://github.com/gmasse)
|
||||||
|
- [A. G. Madi](https://github.com/warpengineer)
|
||||||
|
- [Lukas Stockner](mailto:oss@genesiscloud.com)
|
||||||
|
- [Gert Goet](https://github.com/eval)
|
||||||
|
- [@rfuehrer](https://github.com/rfuehrer)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright (c) 2013 Kevin van Zonneveld and [contributors](https://github.com/kvz/bash3boilerplate#authors).
|
Copyright (c) 2013 Kevin van Zonneveld and [contributors](https://github.com/kvz/bash3boilerplate#authors).
|
||||||
Licensed under [MIT](https://raw.githubusercontent.com/kvz/bash3boilerplate/master/LICENSE).
|
Licensed under [MIT](https://raw.githubusercontent.com/kvz/bash3boilerplate/HEAD/LICENSE).
|
||||||
You are not obligated to bundle the LICENSE file with your b3bp projects as long
|
You are not obligated to bundle the LICENSE file with your b3bp projects as long
|
||||||
as you leave these references intact in the header comments of your source files.
|
as you leave these references intact in the header comments of your source files.
|
||||||
|
1
docs/CNAME
Normal file
@ -0,0 +1 @@
|
|||||||
|
bash3boilerplate.sh
|
15
docs/index.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta
|
||||||
|
http-equiv="refresh"
|
||||||
|
content="0;url=https://github.com/kvz/bash3boilerplate"
|
||||||
|
/>
|
||||||
|
<title>Redirecting...</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
If you are not redirected,
|
||||||
|
<a href="https://github.com/kvz/bash3boilerplate">click here</a>.
|
||||||
|
</body>
|
||||||
|
</html>
|
52
example.sh
@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
# LOG_LEVEL=7 ./example.sh -f /tmp/x -d (change this for your script)
|
# LOG_LEVEL=7 ./example.sh -f /tmp/x -d (change this for your script)
|
||||||
#
|
#
|
||||||
# Based on a template by BASH3 Boilerplate v2.2.0
|
# Based on a template by BASH3 Boilerplate v2.3.0
|
||||||
# http://bash3boilerplate.sh/#authors
|
# http://bash3boilerplate.sh/#authors
|
||||||
#
|
#
|
||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
@ -27,6 +27,7 @@
|
|||||||
# - We do not bash-expand defaults, so setting '~/app' as a default will not resolve to ${HOME}.
|
# - We do not bash-expand defaults, so setting '~/app' as a default will not resolve to ${HOME}.
|
||||||
# you can use bash variables to work around this (so use ${HOME} instead)
|
# you can use bash variables to work around this (so use ${HOME} instead)
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
read -r -d '' __usage <<-'EOF' || true # exits non-zero when EOF encountered
|
read -r -d '' __usage <<-'EOF' || true # exits non-zero when EOF encountered
|
||||||
-f --file [arg] Filename to process. Required.
|
-f --file [arg] Filename to process. Required.
|
||||||
-t --temp [arg] Location of tempfile. Default="/tmp/bar"
|
-t --temp [arg] Location of tempfile. Default="/tmp/bar"
|
||||||
@ -35,8 +36,11 @@ read -r -d '' __usage <<-'EOF' || true # exits non-zero when EOF encountered
|
|||||||
-h --help This page
|
-h --help This page
|
||||||
-n --no-color Disable color output
|
-n --no-color Disable color output
|
||||||
-1 --one Do just one thing
|
-1 --one Do just one thing
|
||||||
|
-i --input [arg] File to process. Can be repeated.
|
||||||
|
-x Specify a flag. Can be repeated.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
read -r -d '' __helptext <<-'EOF' || true # exits non-zero when EOF encountered
|
read -r -d '' __helptext <<-'EOF' || true # exits non-zero when EOF encountered
|
||||||
This is Bash3 Boilerplate's help text. Feel free to add any description of your
|
This is Bash3 Boilerplate's help text. Feel free to add any description of your
|
||||||
program or elaborate more on command-line arguments. This section is not
|
program or elaborate more on command-line arguments. This section is not
|
||||||
@ -47,13 +51,35 @@ EOF
|
|||||||
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/main.sh"
|
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/main.sh"
|
||||||
|
|
||||||
|
|
||||||
|
### Signal trapping and backtracing
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
function __b3bp_cleanup_before_exit () {
|
||||||
|
info "Cleaning up. Done"
|
||||||
|
}
|
||||||
|
trap __b3bp_cleanup_before_exit EXIT
|
||||||
|
|
||||||
|
# requires `set -o errtrace`
|
||||||
|
__b3bp_err_report() {
|
||||||
|
local error_code=${?}
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
error "Error in ${__file} in function ${1} on line ${2}"
|
||||||
|
exit ${error_code}
|
||||||
|
}
|
||||||
|
# Uncomment the following line for always providing an error backtrace
|
||||||
|
# trap '__b3bp_err_report "${FUNCNAME:-.}" ${LINENO}' ERR
|
||||||
|
|
||||||
|
|
||||||
### Command-line argument switches (like -d for debugmode, -h for showing helppage)
|
### Command-line argument switches (like -d for debugmode, -h for showing helppage)
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# debug mode
|
# debug mode
|
||||||
if [[ "${arg_d:?}" = "1" ]]; then
|
if [[ "${arg_d:?}" = "1" ]]; then
|
||||||
set -o xtrace
|
set -o xtrace
|
||||||
|
PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
|
||||||
LOG_LEVEL="7"
|
LOG_LEVEL="7"
|
||||||
|
# Enable error backtracing
|
||||||
|
trap '__b3bp_err_report "${FUNCNAME:-.}" ${LINENO}' ERR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# verbose mode
|
# verbose mode
|
||||||
@ -83,13 +109,13 @@ fi
|
|||||||
### Runtime
|
### Runtime
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
function cleanup_before_exit () {
|
# shellcheck disable=SC2154
|
||||||
info "Cleaning up. Done"
|
info "__i_am_main_script: ${__i_am_main_script}"
|
||||||
}
|
# shellcheck disable=SC2154
|
||||||
trap cleanup_before_exit EXIT
|
|
||||||
|
|
||||||
info "__file: ${__file}"
|
info "__file: ${__file}"
|
||||||
|
# shellcheck disable=SC2154
|
||||||
info "__dir: ${__dir}"
|
info "__dir: ${__dir}"
|
||||||
|
# shellcheck disable=SC2154
|
||||||
info "__base: ${__base}"
|
info "__base: ${__base}"
|
||||||
info "OSTYPE: ${OSTYPE}"
|
info "OSTYPE: ${OSTYPE}"
|
||||||
|
|
||||||
@ -97,14 +123,24 @@ info "arg_f: ${arg_f}"
|
|||||||
info "arg_d: ${arg_d}"
|
info "arg_d: ${arg_d}"
|
||||||
info "arg_v: ${arg_v}"
|
info "arg_v: ${arg_v}"
|
||||||
info "arg_h: ${arg_h}"
|
info "arg_h: ${arg_h}"
|
||||||
|
if [[ -n "${arg_i:-}" ]]; then
|
||||||
|
info "arg_i: ${#arg_i[@]}"
|
||||||
|
for input_file in "${arg_i[@]}"; do
|
||||||
|
info " - ${input_file}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
info "arg_i: 0"
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC2015
|
||||||
|
[[ -n "${arg_x:-}" ]] && info "arg_x: ${#arg_x[@]}" || info "arg_x: 0"
|
||||||
|
|
||||||
info "$(echo -e "multiple lines example - line #1\nmultiple lines example - line #2\nimagine logging the output of 'ls -al /path/'")"
|
info "$(echo -e "multiple lines example - line #1\\nmultiple lines example - line #2\\nimagine logging the output of 'ls -al /path/'")"
|
||||||
|
|
||||||
# All of these go to STDERR, so you can use STDOUT for piping machine readable information to other software
|
# All of these go to STDERR, so you can use STDOUT for piping machine readable information to other software
|
||||||
debug "Info useful to developers for debugging the application, not useful during operations."
|
debug "Info useful to developers for debugging the application, not useful during operations."
|
||||||
info "Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required."
|
info "Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required."
|
||||||
notice "Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required."
|
notice "Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required."
|
||||||
warning "Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time. This is a debug message"
|
warning "Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time."
|
||||||
error "Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time."
|
error "Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time."
|
||||||
critical "Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection."
|
critical "Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection."
|
||||||
alert "Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection."
|
alert "Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection."
|
||||||
|
183
main.sh
@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
# LOG_LEVEL=7 ./main.sh -f /tmp/x -d (change this for your script)
|
# LOG_LEVEL=7 ./main.sh -f /tmp/x -d (change this for your script)
|
||||||
#
|
#
|
||||||
# Based on a template by BASH3 Boilerplate v2.2.0
|
# Based on a template by BASH3 Boilerplate vv2.7.2
|
||||||
# http://bash3boilerplate.sh/#authors
|
# http://bash3boilerplate.sh/#authors
|
||||||
#
|
#
|
||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
@ -27,11 +27,18 @@ set -o pipefail
|
|||||||
# set -o xtrace
|
# set -o xtrace
|
||||||
|
|
||||||
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
|
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
|
||||||
|
__i_am_main_script="0" # false
|
||||||
|
|
||||||
if [[ "${__usage+x}" ]]; then
|
if [[ "${__usage+x}" ]]; then
|
||||||
|
if [[ "${BASH_SOURCE[1]}" = "${0}" ]]; then
|
||||||
|
__i_am_main_script="1" # true
|
||||||
|
fi
|
||||||
|
|
||||||
__b3bp_external_usage="true"
|
__b3bp_external_usage="true"
|
||||||
__b3bp_tmp_source_idx=1
|
__b3bp_tmp_source_idx=1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
__i_am_main_script="1" # true
|
||||||
[[ "${__usage+x}" ]] && unset -v __usage
|
[[ "${__usage+x}" ]] && unset -v __usage
|
||||||
[[ "${__helptext+x}" ]] && unset -v __helptext
|
[[ "${__helptext+x}" ]] && unset -v __helptext
|
||||||
fi
|
fi
|
||||||
@ -40,6 +47,8 @@ fi
|
|||||||
__dir="$(cd "$(dirname "${BASH_SOURCE[${__b3bp_tmp_source_idx:-0}]}")" && pwd)"
|
__dir="$(cd "$(dirname "${BASH_SOURCE[${__b3bp_tmp_source_idx:-0}]}")" && pwd)"
|
||||||
__file="${__dir}/$(basename "${BASH_SOURCE[${__b3bp_tmp_source_idx:-0}]}")"
|
__file="${__dir}/$(basename "${BASH_SOURCE[${__b3bp_tmp_source_idx:-0}]}")"
|
||||||
__base="$(basename "${__file}" .sh)"
|
__base="$(basename "${__file}" .sh)"
|
||||||
|
# shellcheck disable=SC2034,SC2015
|
||||||
|
__invocation="$(printf %q "${__file}")$( (($#)) && printf ' %q' "$@" || true)"
|
||||||
|
|
||||||
# Define the environment variables (and their defaults) that this script depends on
|
# Define the environment variables (and their defaults) that this script depends on
|
||||||
LOG_LEVEL="${LOG_LEVEL:-6}" # 7 = debug -> 0 = emergency
|
LOG_LEVEL="${LOG_LEVEL:-6}" # 7 = debug -> 0 = emergency
|
||||||
@ -54,28 +63,28 @@ function __b3bp_log () {
|
|||||||
shift
|
shift
|
||||||
|
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
local color_debug="\x1b[35m"
|
local color_debug="\\x1b[35m"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
local color_info="\x1b[32m"
|
local color_info="\\x1b[32m"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
local color_notice="\x1b[34m"
|
local color_notice="\\x1b[34m"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
local color_warning="\x1b[33m"
|
local color_warning="\\x1b[33m"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
local color_error="\x1b[31m"
|
local color_error="\\x1b[31m"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
local color_critical="\x1b[1;31m"
|
local color_critical="\\x1b[1;31m"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
local color_alert="\x1b[1;33;41m"
|
local color_alert="\\x1b[1;37;41m"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
local color_emergency="\x1b[1;4;5;33;41m"
|
local color_emergency="\\x1b[1;4;5;37;41m"
|
||||||
|
|
||||||
local colorvar="color_${log_level}"
|
local colorvar="color_${log_level}"
|
||||||
|
|
||||||
local color="${!colorvar:-${color_error}}"
|
local color="${!colorvar:-${color_error}}"
|
||||||
local color_reset="\x1b[0m"
|
local color_reset="\\x1b[0m"
|
||||||
|
|
||||||
if [[ "${NO_COLOR:-}" = "true" ]] || [[ "${TERM:-}" != "xterm"* ]] || [[ ! -t 2 ]]; then
|
if [[ "${NO_COLOR:-}" = "true" ]] || { [[ "${TERM:-}" != "xterm"* ]] && [[ "${TERM:-}" != "screen"* ]]; } || [[ ! -t 2 ]]; then
|
||||||
if [[ "${NO_COLOR:-}" != "false" ]]; then
|
if [[ "${NO_COLOR:-}" != "false" ]]; then
|
||||||
# Don't use colors on pipes or non-recognized terminals
|
# Don't use colors on pipes or non-recognized terminals
|
||||||
color=""; color_reset=""
|
color=""; color_reset=""
|
||||||
@ -135,6 +144,8 @@ function help () {
|
|||||||
-h --help This page
|
-h --help This page
|
||||||
-n --no-color Disable color output
|
-n --no-color Disable color output
|
||||||
-1 --one Do just one thing
|
-1 --one Do just one thing
|
||||||
|
-i --input [arg] File to process. Can be repeated.
|
||||||
|
-x Specify a flag. Can be repeated.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# shellcheck disable=SC2015
|
# shellcheck disable=SC2015
|
||||||
@ -178,34 +189,45 @@ while read -r __b3bp_tmp_line; do
|
|||||||
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "0"
|
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "0"
|
||||||
fi
|
fi
|
||||||
__b3bp_tmp_opts="${__b3bp_tmp_opts:-}${__b3bp_tmp_opt}"
|
__b3bp_tmp_opts="${__b3bp_tmp_opts:-}${__b3bp_tmp_opt}"
|
||||||
|
|
||||||
|
if [[ "${__b3bp_tmp_line}" =~ ^Can\ be\ repeated\. ]] || [[ "${__b3bp_tmp_line}" =~ \.\ *Can\ be\ repeated\. ]]; then
|
||||||
|
# remember that this option can be repeated
|
||||||
|
printf -v "__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}" '%s' "1"
|
||||||
|
else
|
||||||
|
printf -v "__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}" '%s' "0"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ "${__b3bp_tmp_opt:-}" ]] || continue
|
[[ "${__b3bp_tmp_opt:-}" ]] || continue
|
||||||
|
|
||||||
if [[ "${__b3bp_tmp_line}" =~ (^|\.\ *)Default= ]]; then
|
if [[ "${__b3bp_tmp_line}" =~ ^Default= ]] || [[ "${__b3bp_tmp_line}" =~ \.\ *Default= ]]; then
|
||||||
# ignore default value if option does not have an argument
|
# ignore default value if option does not have an argument
|
||||||
__b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}"
|
__b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}"
|
||||||
|
|
||||||
if [[ "${!__b3bp_tmp_varname}" != "0" ]]; then
|
if [[ "${!__b3bp_tmp_varname}" != "0" ]]; then
|
||||||
|
# take default
|
||||||
__b3bp_tmp_init="${__b3bp_tmp_line##*Default=}"
|
__b3bp_tmp_init="${__b3bp_tmp_line##*Default=}"
|
||||||
|
# strip double quotes from default argument
|
||||||
__b3bp_tmp_re='^"(.*)"$'
|
__b3bp_tmp_re='^"(.*)"$'
|
||||||
if [[ "${__b3bp_tmp_init}" =~ ${__b3bp_tmp_re} ]]; then
|
if [[ "${__b3bp_tmp_init}" =~ ${__b3bp_tmp_re} ]]; then
|
||||||
__b3bp_tmp_init="${BASH_REMATCH[1]}"
|
__b3bp_tmp_init="${BASH_REMATCH[1]}"
|
||||||
else
|
else
|
||||||
|
# strip single quotes from default argument
|
||||||
__b3bp_tmp_re="^'(.*)'$"
|
__b3bp_tmp_re="^'(.*)'$"
|
||||||
if [[ "${__b3bp_tmp_init}" =~ ${__b3bp_tmp_re} ]]; then
|
if [[ "${__b3bp_tmp_init}" =~ ${__b3bp_tmp_re} ]]; then
|
||||||
__b3bp_tmp_init="${BASH_REMATCH[1]}"
|
__b3bp_tmp_init="${BASH_REMATCH[1]}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${__b3bp_tmp_line}" =~ (^|\.\ *)Required\. ]]; then
|
if [[ "${__b3bp_tmp_line}" =~ ^Required\. ]] || [[ "${__b3bp_tmp_line}" =~ \.\ *Required\. ]]; then
|
||||||
# remember that this option requires an argument
|
# remember that this option requires an argument
|
||||||
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "2"
|
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "2"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf -v "arg_${__b3bp_tmp_opt:0:1}" '%s' "${__b3bp_tmp_init}"
|
# Init var with value unless it is an array / a repeatable
|
||||||
|
__b3bp_tmp_varname="__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}"
|
||||||
|
[[ "${!__b3bp_tmp_varname}" = "0" ]] && printf -v "arg_${__b3bp_tmp_opt:0:1}" '%s' "${__b3bp_tmp_init}"
|
||||||
done <<< "${__usage:-}"
|
done <<< "${__usage:-}"
|
||||||
|
|
||||||
# run getopts only if options were specified in __usage
|
# run getopts only if options were specified in __usage
|
||||||
@ -218,7 +240,7 @@ if [[ "${__b3bp_tmp_opts:-}" ]]; then
|
|||||||
|
|
||||||
# start parsing command line
|
# start parsing command line
|
||||||
set +o nounset # unexpected arguments will cause unbound variables
|
set +o nounset # unexpected arguments will cause unbound variables
|
||||||
# to be dereferenced
|
# to be dereferenced
|
||||||
# Overwrite $arg_<flag> defaults with the actual CLI options
|
# Overwrite $arg_<flag> defaults with the actual CLI options
|
||||||
while getopts "${__b3bp_tmp_opts}" __b3bp_tmp_opt; do
|
while getopts "${__b3bp_tmp_opts}" __b3bp_tmp_opt; do
|
||||||
[[ "${__b3bp_tmp_opt}" = "?" ]] && help "Invalid use of script: ${*} "
|
[[ "${__b3bp_tmp_opt}" = "?" ]] && help "Invalid use of script: ${*} "
|
||||||
@ -226,41 +248,68 @@ if [[ "${__b3bp_tmp_opts:-}" ]]; then
|
|||||||
if [[ "${__b3bp_tmp_opt}" = "-" ]]; then
|
if [[ "${__b3bp_tmp_opt}" = "-" ]]; then
|
||||||
# OPTARG is long-option-name or long-option=value
|
# OPTARG is long-option-name or long-option=value
|
||||||
if [[ "${OPTARG}" =~ .*=.* ]]; then
|
if [[ "${OPTARG}" =~ .*=.* ]]; then
|
||||||
# --key=value format
|
# --key=value format
|
||||||
__b3bp_tmp_long_opt=${OPTARG/=*/}
|
__b3bp_tmp_long_opt=${OPTARG/=*/}
|
||||||
# Set opt to the short option corresponding to the long option
|
# Set opt to the short option corresponding to the long option
|
||||||
__b3bp_tmp_varname="__b3bp_tmp_opt_long2short_${__b3bp_tmp_long_opt//-/_}"
|
__b3bp_tmp_varname="__b3bp_tmp_opt_long2short_${__b3bp_tmp_long_opt//-/_}"
|
||||||
printf -v "__b3bp_tmp_opt" '%s' "${!__b3bp_tmp_varname}"
|
printf -v "__b3bp_tmp_opt" '%s' "${!__b3bp_tmp_varname}"
|
||||||
OPTARG=${OPTARG#*=}
|
OPTARG=${OPTARG#*=}
|
||||||
else
|
else
|
||||||
# --key value format
|
# --key value format
|
||||||
# Map long name to short version of option
|
# Map long name to short version of option
|
||||||
__b3bp_tmp_varname="__b3bp_tmp_opt_long2short_${OPTARG//-/_}"
|
__b3bp_tmp_varname="__b3bp_tmp_opt_long2short_${OPTARG//-/_}"
|
||||||
printf -v "__b3bp_tmp_opt" '%s' "${!__b3bp_tmp_varname}"
|
printf -v "__b3bp_tmp_opt" '%s' "${!__b3bp_tmp_varname}"
|
||||||
# Only assign OPTARG if option takes an argument
|
# Only assign OPTARG if option takes an argument
|
||||||
__b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt}"
|
__b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt}"
|
||||||
printf -v "OPTARG" '%s' "${@:OPTIND:${!__b3bp_tmp_varname}}"
|
__b3bp_tmp_varvalue="${!__b3bp_tmp_varname}"
|
||||||
# shift over the argument if argument is expected
|
[[ "${__b3bp_tmp_varvalue}" != "0" ]] && __b3bp_tmp_varvalue="1"
|
||||||
((OPTIND+=__b3bp_tmp_has_arg_${__b3bp_tmp_opt}))
|
printf -v "OPTARG" '%s' "${@:OPTIND:${__b3bp_tmp_varvalue}}"
|
||||||
|
# shift over the argument if argument is expected
|
||||||
|
((OPTIND+=__b3bp_tmp_varvalue))
|
||||||
fi
|
fi
|
||||||
# we have set opt/OPTARG to the short value and the argument as OPTARG if it exists
|
# we have set opt/OPTARG to the short value and the argument as OPTARG if it exists
|
||||||
fi
|
fi
|
||||||
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
|
|
||||||
__b3bp_tmp_default="${!__b3bp_tmp_varname}"
|
|
||||||
|
|
||||||
__b3bp_tmp_value="${OPTARG}"
|
__b3bp_tmp_value="${OPTARG}"
|
||||||
if [[ -z "${OPTARG}" ]] && [[ "${__b3bp_tmp_default}" = "0" ]]; then
|
|
||||||
__b3bp_tmp_value="1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf -v "${__b3bp_tmp_varname}" '%s' "${__b3bp_tmp_value}"
|
__b3bp_tmp_varname="__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}"
|
||||||
debug "cli arg ${__b3bp_tmp_varname} = (${__b3bp_tmp_default}) -> ${!__b3bp_tmp_varname}"
|
if [[ "${!__b3bp_tmp_varname}" != "0" ]]; then
|
||||||
|
# repeatables
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
if [[ -z "${OPTARG}" ]]; then
|
||||||
|
# repeatable flags, they increcemnt
|
||||||
|
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
|
||||||
|
debug "cli arg ${__b3bp_tmp_varname} = (${__b3bp_tmp_default}) -> ${!__b3bp_tmp_varname}"
|
||||||
|
# shellcheck disable=SC2004
|
||||||
|
__b3bp_tmp_value=$((${!__b3bp_tmp_varname} + 1))
|
||||||
|
printf -v "${__b3bp_tmp_varname}" '%s' "${__b3bp_tmp_value}"
|
||||||
|
else
|
||||||
|
# repeatable args, they get appended to an array
|
||||||
|
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}[@]"
|
||||||
|
debug "cli arg ${__b3bp_tmp_varname} append ${__b3bp_tmp_value}"
|
||||||
|
declare -a "${__b3bp_tmp_varname}"='("${!__b3bp_tmp_varname}" "${__b3bp_tmp_value}")'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# non-repeatables
|
||||||
|
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
|
||||||
|
__b3bp_tmp_default="${!__b3bp_tmp_varname}"
|
||||||
|
|
||||||
|
if [[ -z "${OPTARG}" ]]; then
|
||||||
|
__b3bp_tmp_value=$((__b3bp_tmp_default + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf -v "${__b3bp_tmp_varname}" '%s' "${__b3bp_tmp_value}"
|
||||||
|
|
||||||
|
debug "cli arg ${__b3bp_tmp_varname} = (${__b3bp_tmp_default}) -> ${!__b3bp_tmp_varname}"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
set -o nounset # no more unbound variable references expected
|
set -o nounset # no more unbound variable references expected
|
||||||
|
|
||||||
shift $((OPTIND-1))
|
shift $((OPTIND-1))
|
||||||
|
|
||||||
[[ "${1:-}" = "--" ]] && shift
|
if [[ "${1:-}" = "--" ]] ; then
|
||||||
|
shift
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
@ -302,13 +351,34 @@ if [[ "${__b3bp_external_usage:-}" = "true" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
### Signal trapping and backtracing
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
function __b3bp_cleanup_before_exit () {
|
||||||
|
info "Cleaning up. Done"
|
||||||
|
}
|
||||||
|
trap __b3bp_cleanup_before_exit EXIT
|
||||||
|
|
||||||
|
# requires `set -o errtrace`
|
||||||
|
__b3bp_err_report() {
|
||||||
|
local error_code=${?}
|
||||||
|
error "Error in ${__file} in function ${1} on line ${2}"
|
||||||
|
exit ${error_code}
|
||||||
|
}
|
||||||
|
# Uncomment the following line for always providing an error backtrace
|
||||||
|
# trap '__b3bp_err_report "${FUNCNAME:-.}" ${LINENO}' ERR
|
||||||
|
|
||||||
|
|
||||||
### Command-line argument switches (like -d for debugmode, -h for showing helppage)
|
### Command-line argument switches (like -d for debugmode, -h for showing helppage)
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# debug mode
|
# debug mode
|
||||||
if [[ "${arg_d:?}" = "1" ]]; then
|
if [[ "${arg_d:?}" = "1" ]]; then
|
||||||
set -o xtrace
|
set -o xtrace
|
||||||
|
PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
|
||||||
LOG_LEVEL="7"
|
LOG_LEVEL="7"
|
||||||
|
# Enable error backtracing
|
||||||
|
trap '__b3bp_err_report "${FUNCNAME:-.}" ${LINENO}' ERR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# verbose mode
|
# verbose mode
|
||||||
@ -338,11 +408,7 @@ fi
|
|||||||
### Runtime
|
### Runtime
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
function cleanup_before_exit () {
|
info "__i_am_main_script: ${__i_am_main_script}"
|
||||||
info "Cleaning up. Done"
|
|
||||||
}
|
|
||||||
trap cleanup_before_exit EXIT
|
|
||||||
|
|
||||||
info "__file: ${__file}"
|
info "__file: ${__file}"
|
||||||
info "__dir: ${__dir}"
|
info "__dir: ${__dir}"
|
||||||
info "__base: ${__base}"
|
info "__base: ${__base}"
|
||||||
@ -353,13 +419,34 @@ info "arg_d: ${arg_d}"
|
|||||||
info "arg_v: ${arg_v}"
|
info "arg_v: ${arg_v}"
|
||||||
info "arg_h: ${arg_h}"
|
info "arg_h: ${arg_h}"
|
||||||
|
|
||||||
info "$(echo -e "multiple lines example - line #1\nmultiple lines example - line #2\nimagine logging the output of 'ls -al /path/'")"
|
# shellcheck disable=SC2015
|
||||||
|
if [[ -n "${arg_i:-}" ]] && declare -p arg_i 2> /dev/null | grep -q '^declare \-a'; then
|
||||||
|
info "arg_i:"
|
||||||
|
for input_file in "${arg_i[@]}"; do
|
||||||
|
info " - ${input_file}"
|
||||||
|
done
|
||||||
|
elif [[ -n "${arg_i:-}" ]]; then
|
||||||
|
info "arg_i: ${arg_i}"
|
||||||
|
else
|
||||||
|
info "arg_i: 0"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2015
|
||||||
|
if [[ -n "${arg_x:-}" ]] && declare -p arg_x 2> /dev/null | grep -q '^declare \-a'; then
|
||||||
|
info "arg_x: ${#arg_x[@]}"
|
||||||
|
elif [[ -n "${arg_x:-}" ]]; then
|
||||||
|
info "arg_x: ${arg_x}"
|
||||||
|
else
|
||||||
|
info "arg_x: 0"
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "$(echo -e "multiple lines example - line #1\\nmultiple lines example - line #2\\nimagine logging the output of 'ls -al /path/'")"
|
||||||
|
|
||||||
# All of these go to STDERR, so you can use STDOUT for piping machine readable information to other software
|
# All of these go to STDERR, so you can use STDOUT for piping machine readable information to other software
|
||||||
debug "Info useful to developers for debugging the application, not useful during operations."
|
debug "Info useful to developers for debugging the application, not useful during operations."
|
||||||
info "Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required."
|
info "Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required."
|
||||||
notice "Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required."
|
notice "Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required."
|
||||||
warning "Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time. This is a debug message"
|
warning "Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time."
|
||||||
error "Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time."
|
error "Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time."
|
||||||
critical "Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection."
|
critical "Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection."
|
||||||
alert "Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection."
|
alert "Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection."
|
||||||
|
54
package.json
@ -1,47 +1,29 @@
|
|||||||
{
|
{
|
||||||
"name": "bash3boilerplate",
|
"name": "bash3boilerplate",
|
||||||
"description": "Copypastable templates to write better bash scripts",
|
"description": "Copypastable templates to write better bash scripts",
|
||||||
"version": "2.2.0",
|
"version": "2.7.2",
|
||||||
|
"packageManager": "yarn@3.6.0+sha224.19e47520fa56c6146388fdeb438d9dcf6630c3f277a2e1180995c3bb",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18",
|
||||||
|
"yarn": "3.6.0"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:production": "LANYON_ENV=production lanyon build",
|
"lint:shellcheck": "shellcheck --severity=${SHELLCHECK_SEVERITY:-info} $(find . -name '*.sh' -maxdepth 2)",
|
||||||
"build": "lanyon build",
|
"lint:style": "test/style.pl $(find . -name '*.sh' -maxdepth 2)",
|
||||||
"deploy": "lanyon deploy",
|
"lint": "npm-run-all -l 'lint:**'",
|
||||||
"encrypt": "lanyon encrypt",
|
"release:major": "env SEMANTIC=major yarn release",
|
||||||
"install": "lanyon postinstall",
|
"release:minor": "env SEMANTIC=minor yarn release",
|
||||||
"lint": "shellcheck --shell=bash $(find . -name '*.sh' -maxdepth 2)",
|
"release:patch": "env SEMANTIC=patch yarn release",
|
||||||
"release:major": "env SEMANTIC=major npm run release",
|
"release": "npm version ${SEMANTIC:-patch} -m \"Release %s\" && yarn version:replace && git commit main.sh src/*.sh -m 'Update version' && git push && git push --tags -f && npm publish",
|
||||||
"release:minor": "env SEMANTIC=minor npm run release",
|
"test:debug:main:repeated": "env LOG_LEVEL=7 test/acceptance.sh main-repeated",
|
||||||
"release:patch": "env SEMANTIC=patch npm run release",
|
"test:update": "env SAVE_FIXTURES=true yarn test",
|
||||||
"release": "npm version ${SEMANTIC:-patch} -m \"Release %s\" && npm run version:replace && git commit main.sh src/*.sh -m 'Update version' && git push && git push --tags && npm publish",
|
|
||||||
"save:fixtures": "cross-env SAVE_FIXTURES=true npm run test",
|
|
||||||
"serve:production": "LANYON_ENV=production lanyon serve",
|
|
||||||
"start:production": "npm-run-all build:production serve:production",
|
|
||||||
"start": "lanyon start",
|
|
||||||
"test": "test/acceptance.sh",
|
"test": "test/acceptance.sh",
|
||||||
"upgrade:modules": "next-update --keep true --tldr",
|
|
||||||
"version:current": "node -e 'console.log(require(\"./package.json\").version)'",
|
"version:current": "node -e 'console.log(require(\"./package.json\").version)'",
|
||||||
"version:replace": "replace 'v\\d+\\.\\d+\\.\\d+' \"v$(npm run --silent version:current)\" main.sh src/*.sh"
|
"version:replace": "replace 'v\\d+\\.\\d+\\.\\d+' \"v$(npm run --silent version:current)\" main.sh src/*.sh"
|
||||||
},
|
},
|
||||||
"lanyon": {
|
|
||||||
"projectDir": "website",
|
|
||||||
"prebuild": "./_scripts/inject.sh",
|
|
||||||
"contentScandir": "../",
|
|
||||||
"contentIgnore": [
|
|
||||||
"website/*.md",
|
|
||||||
"website/main.sh"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"fsevents": "*"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browser-sync": "2.18.5",
|
"fakefile": "1.1.0",
|
||||||
"cross-env": "3.1.3",
|
"npm-run-all": "4.1.5",
|
||||||
"fakefile": "0.0.8",
|
"replace": "1.2.2"
|
||||||
"lanyon": "0.0.47",
|
|
||||||
"next-update": "1.5.1",
|
|
||||||
"npm-run-all": "3.1.2",
|
|
||||||
"replace": "^0.3.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,18 +7,19 @@
|
|||||||
#
|
#
|
||||||
# Limitations:
|
# Limitations:
|
||||||
#
|
#
|
||||||
# - All keys inside the .ini file must be unique, regardless of the use of sections
|
# - All keys inside a section of the .ini file must be unique
|
||||||
|
# - Optional comment parameter for the creation of new entries
|
||||||
#
|
#
|
||||||
# Usage as a function:
|
# Usage as a function:
|
||||||
#
|
#
|
||||||
# source ini_val.sh
|
# source ini_val.sh
|
||||||
# ini_val data.ini connection.host 127.0.0.1
|
# ini_val data.ini connection.host 127.0.0.1 "Host name or IP address"
|
||||||
#
|
#
|
||||||
# Usage as a command:
|
# Usage as a command:
|
||||||
#
|
#
|
||||||
# ini_val.sh data.ini connection.host 127.0.0.1
|
# ini_val.sh data.ini connection.host 127.0.0.1 "Host name or IP address"
|
||||||
#
|
#
|
||||||
# Based on a template by BASH3 Boilerplate v2.1.0
|
# Based on a template by BASH3 Boilerplate vv2.7.2
|
||||||
# http://bash3boilerplate.sh/#authors
|
# http://bash3boilerplate.sh/#authors
|
||||||
#
|
#
|
||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
@ -30,47 +31,81 @@ function ini_val() {
|
|||||||
local file="${1:-}"
|
local file="${1:-}"
|
||||||
local sectionkey="${2:-}"
|
local sectionkey="${2:-}"
|
||||||
local val="${3:-}"
|
local val="${3:-}"
|
||||||
local delim=" = "
|
local comment="${4:-}"
|
||||||
|
local delim="="
|
||||||
|
local comment_delim=";"
|
||||||
local section=""
|
local section=""
|
||||||
local key=""
|
local key=""
|
||||||
|
local current=""
|
||||||
|
# add default section
|
||||||
|
local section_default="default"
|
||||||
|
|
||||||
|
if [[ ! -f "${file}" ]]; then
|
||||||
|
# touch file if not exists
|
||||||
|
touch "${file}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Split on . for section. However, section is optional
|
# Split on . for section. However, section is optional
|
||||||
IFS='.' read -r section key <<< "${sectionkey}"
|
IFS='.' read -r section key <<< "${sectionkey}"
|
||||||
if [ -z "${key}" ]; then
|
if [[ ! "${key}" ]]; then
|
||||||
key="${section}"
|
key="${section}"
|
||||||
section=""
|
# default section if not given
|
||||||
|
section="${section_default}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local current
|
# get current value (if exists)
|
||||||
current=$(awk -F "${delim}" "/^${key}${delim}/ {for (i=2; i<NF; i++) printf \$i \" \"; print \$NF}" "${file}")
|
current=$(sed -En "/^\[/{h;d;};G;s/^${key}([[:blank:]]*)${delim}(.*)\n\[${section}\]$/\2/p" "${file}"|awk '{$1=$1};1')
|
||||||
|
# get current comment (if exists)
|
||||||
|
current_comment=$(sed -En "/^\[${section}\]/,/^\[.*\]/ s|^(${comment_delim}\[${key}\])(.*)|\2|p" "${file}"|awk '{$1=$1};1')
|
||||||
|
|
||||||
if [ -z "${val}" ]; then
|
if ! grep -q "\[${section}\]" "${file}"; then
|
||||||
|
# create section if not exists (empty line to seperate new section for better readability)
|
||||||
|
echo >> "${file}"
|
||||||
|
echo "[${section}]" >> "${file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "${val}" ]]; then
|
||||||
# get a value
|
# get a value
|
||||||
echo "${current}"
|
echo "${current}"
|
||||||
else
|
else
|
||||||
# set a value
|
# set a value
|
||||||
if [ -z "${current}" ]; then
|
if [[ ! "${section}" ]]; then
|
||||||
# doesn't exist yet, add
|
# if no section is given, propagate the default section
|
||||||
|
section=${section_default}
|
||||||
if [ -z "${section}" ]; then
|
|
||||||
# no section was given, add to bottom of file
|
|
||||||
echo "${key}${delim}${val}" >> "${file}"
|
|
||||||
else
|
|
||||||
# add to section
|
|
||||||
sed -i.bak -e "/\[${section}\]/a ${key}${delim}${val}" "${file}"
|
|
||||||
# this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
|
|
||||||
rm -f "${file}.bak"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# replace existing
|
|
||||||
sed -i.bak -e "/^${key}${delim}/s/${delim}.*/${delim}${val}/" "${file}"
|
|
||||||
# this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
|
|
||||||
rm -f "${file}.bak"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ ! "${comment}" ]]; then
|
||||||
|
# if no comment given, keep old comment
|
||||||
|
comment="${current_comment}"
|
||||||
|
fi
|
||||||
|
# maintenance area
|
||||||
|
# a) remove comment if new given / respect section
|
||||||
|
sed -i.bak "/^\[${section}\]/,/^\[.*\]/ s|^\(${comment_delim}\[${key}\] \).*$||" "${file}"
|
||||||
|
# b) remove old key / respect section
|
||||||
|
sed -i.bak "/^\[${section}\]/,/^\[.*\]/ s|^\(${key}=\).*$||" "${file}"
|
||||||
|
# c) remove all empty lines in ini file
|
||||||
|
sed -i.bak '/^[[:space:]]*$/d' "${file}"
|
||||||
|
# d) insert line break before every section for better readability
|
||||||
|
sed -i.bak $'s/^\\[/\\\n\\[/g' "${file}"
|
||||||
|
|
||||||
|
# add to section
|
||||||
|
if [[ ! "${comment}" ]]; then
|
||||||
|
# add new key/value _without_ comment
|
||||||
|
RET="/\\[${section}\\]/a\\
|
||||||
|
${key}${delim}${val}"
|
||||||
|
else
|
||||||
|
# add new key/value _with_ preceeding comment
|
||||||
|
RET="/\\[${section}\\]/a\\
|
||||||
|
${comment_delim}[${key}] ${comment}\\
|
||||||
|
${key}${delim}${val}"
|
||||||
|
fi
|
||||||
|
sed -i.bak -e "${RET}" "${file}"
|
||||||
|
# this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
|
||||||
|
rm -f "${file}.bak"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
|
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
|
||||||
export -f ini_val
|
export -f ini_val
|
||||||
else
|
else
|
||||||
ini_val "${@}"
|
ini_val "${@}"
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
# This file:
|
# This file:
|
||||||
#
|
#
|
||||||
# - Takes a URL (smb, nfs, afs) and tries to mount it at a given target directory
|
# - Takes a URL (smb, nfs, afs) and tries to mount it at a given target directory
|
||||||
# - Forceully unmounts any active mount at the target directory first
|
# - Forcefully unmounts any active mount at the target directory first
|
||||||
# - Displays the mounts contents for verification
|
# - Displays the mount's contents for verification
|
||||||
#
|
#
|
||||||
# Depends on:
|
# Depends on:
|
||||||
#
|
#
|
||||||
@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
# megamount.sh smb://janedoe:abc123@192.168.0.1/documents /mnt/documents
|
# megamount.sh smb://janedoe:abc123@192.168.0.1/documents /mnt/documents
|
||||||
#
|
#
|
||||||
# Based on a template by BASH3 Boilerplate v2.1.0
|
# Based on a template by BASH3 Boilerplate vv2.7.2
|
||||||
# http://bash3boilerplate.sh/#authors
|
# http://bash3boilerplate.sh/#authors
|
||||||
#
|
#
|
||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
@ -53,13 +53,13 @@ function megamount () {
|
|||||||
|
|
||||||
(umount -lf "${target}" || umount -f "${target}") > /dev/null 2>&1 || true
|
(umount -lf "${target}" || umount -f "${target}") > /dev/null 2>&1 || true
|
||||||
mkdir -p "${target}"
|
mkdir -p "${target}"
|
||||||
if [ "${proto}" = "smb://" ]; then
|
if [[ "${proto}" = "smb://" ]]; then
|
||||||
mount -t cifs --verbose -o "username=${user},password=${pass},hard" "//${host}/${path}" "${target}"
|
mount -t cifs --verbose -o "username=${user},password=${pass},hard" "//${host}/${path}" "${target}"
|
||||||
elif [ "${proto}" = "afp://" ]; then
|
elif [[ "${proto}" = "afp://" ]]; then
|
||||||
# start syslog-ng
|
# start syslog-ng
|
||||||
# afpfsd || echo "Unable to run afpfsd. Does /dev/log exist?" && exit 1
|
# afpfsd || echo "Unable to run afpfsd. Does /dev/log exist?" && exit 1
|
||||||
mount_afp "${url}" "${target}"
|
mount_afp "${url}" "${target}"
|
||||||
elif [ "${proto}" = "nfs://" ]; then
|
elif [[ "${proto}" = "nfs://" ]]; then
|
||||||
mount -t nfs --verbose -o "vers=3,nolock,soft,intr,rsize=32768,wsize=32768" "${host}:/${path}" "${target}"
|
mount -t nfs --verbose -o "vers=3,nolock,soft,intr,rsize=32768,wsize=32768" "${host}:/${path}" "${target}"
|
||||||
else
|
else
|
||||||
echo "ERR: Unknown protocol: '${proto}'"
|
echo "ERR: Unknown protocol: '${proto}'"
|
||||||
@ -70,7 +70,7 @@ function megamount () {
|
|||||||
ls -al "${target}/"
|
ls -al "${target}/"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
|
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
|
||||||
export -f megamount
|
export -f megamount
|
||||||
else
|
else
|
||||||
megamount "${@}"
|
megamount "${@}"
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#
|
#
|
||||||
# parse_url.sh 'http://johndoe:abc123@example.com:8080/index.html'
|
# parse_url.sh 'http://johndoe:abc123@example.com:8080/index.html'
|
||||||
#
|
#
|
||||||
# Based on a template by BASH3 Boilerplate v2.1.0
|
# Based on a template by BASH3 Boilerplate vv2.7.2
|
||||||
# http://bash3boilerplate.sh/#authors
|
# http://bash3boilerplate.sh/#authors
|
||||||
#
|
#
|
||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
@ -40,26 +40,26 @@ function parse_url() {
|
|||||||
local port
|
local port
|
||||||
local path
|
local path
|
||||||
|
|
||||||
proto="$(echo "$parse" | grep :// | sed -e's,^\(.*://\).*,\1,g')"
|
proto="$(echo "${parse}" | grep :// | sed -e's,^\(.*://\).*,\1,g')"
|
||||||
url="${parse/$proto/}"
|
url="${parse/${proto}/}"
|
||||||
userpass="$(echo "$url" | grep @ | cut -d@ -f1)"
|
userpass="$(echo "${url}" | grep @ | cut -d@ -f1)"
|
||||||
user="$(echo "$userpass" | grep : | cut -d: -f1)"
|
user="$(echo "${userpass}" | grep : | cut -d: -f1)"
|
||||||
pass="$(echo "$userpass" | grep : | cut -d: -f2)"
|
pass="$(echo "${userpass}" | grep : | cut -d: -f2)"
|
||||||
hostport="$(echo "${url/$userpass@/}" | cut -d/ -f1)"
|
hostport="$(echo "${url/${userpass}@/}" | cut -d/ -f1)"
|
||||||
host="$(echo "$hostport" | grep : | cut -d: -f1)"
|
host="$(echo "${hostport}" | grep : | cut -d: -f1)"
|
||||||
port="$(echo "$hostport" | grep : | cut -d: -f2)"
|
port="$(echo "${hostport}" | grep : | cut -d: -f2)"
|
||||||
path="$(echo "$url" | grep / | cut -d/ -f2-)"
|
path="$(echo "${url}" | grep / | cut -d/ -f2-)"
|
||||||
|
|
||||||
[ -z "${user}" ] && user="${userpass}"
|
[[ ! "${user}" ]] && user="${userpass}"
|
||||||
[ -z "${host}" ] && host="${hostport}"
|
[[ ! "${host}" ]] && host="${hostport}"
|
||||||
if [ -z "${port}" ]; then
|
if [[ ! "${port}" ]]; then
|
||||||
[ "${proto}" = "http://" ] && port="80"
|
[[ "${proto}" = "http://" ]] && port="80"
|
||||||
[ "${proto}" = "https://" ] && port="443"
|
[[ "${proto}" = "https://" ]] && port="443"
|
||||||
[ "${proto}" = "mysql://" ] && port="3306"
|
[[ "${proto}" = "mysql://" ]] && port="3306"
|
||||||
[ "${proto}" = "redis://" ] && port="6379"
|
[[ "${proto}" = "redis://" ]] && port="6379"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${need}" ]; then
|
if [[ "${need}" ]]; then
|
||||||
echo "${!need}"
|
echo "${!need}"
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
@ -76,7 +76,7 @@ function parse_url() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
|
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
|
||||||
export -f parse_url
|
export -f parse_url
|
||||||
else
|
else
|
||||||
parse_url "${@}"
|
parse_url "${@}"
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#
|
#
|
||||||
# ALLOW_REMAINDERS=1 templater.sh input.cfg output.cfg
|
# ALLOW_REMAINDERS=1 templater.sh input.cfg output.cfg
|
||||||
#
|
#
|
||||||
# Based on a template by BASH3 Boilerplate v2.1.0
|
# Based on a template by BASH3 Boilerplate vv2.7.2
|
||||||
# http://bash3boilerplate.sh/#authors
|
# http://bash3boilerplate.sh/#authors
|
||||||
#
|
#
|
||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
@ -30,32 +30,37 @@ function templater() {
|
|||||||
templateSrc="${1:-}"
|
templateSrc="${1:-}"
|
||||||
templateDst="${2:-}"
|
templateDst="${2:-}"
|
||||||
|
|
||||||
if [ ! -f "${templateSrc}" ]; then
|
if [[ ! -f "${templateSrc}" ]]; then
|
||||||
echo "ERROR: Template source '${templateSrc}' needs to exist"
|
echo "ERROR: Template source '${templateSrc}' needs to exist"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if [ ! -n "${templateDst}" ]; then
|
if [[ ! "${templateDst}" ]]; then
|
||||||
echo "ERROR: Template destination '${templateDst}' needs to be specified"
|
echo "ERROR: Template destination '${templateDst}' needs to be specified"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp -f "${templateSrc}" "${templateDst}"
|
if [[ "$(command -v perl)" ]]; then
|
||||||
for var in $(env |awk -F= '{print $1}' |egrep '^[A-Z0-9_]+$'); do
|
perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1} ? $ENV{$1} : "\${$1}")/eg' < "${templateSrc}" > "${templateDst}"
|
||||||
sed -i.bak -e "s#\${${var}}#${!var}#g" "${templateDst}"
|
else
|
||||||
# this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
|
cp -f "${templateSrc}" "${templateDst}"
|
||||||
rm -f "${templateDst}.bak"
|
|
||||||
done
|
for var in $(env |awk -F= '{print $1}' |grep -E '^(_[A-Z0-9_]+|[A-Z0-9][A-Z0-9_]*)$'); do
|
||||||
|
sed -i.bak -e "s#\${${var}}#${!var//#/\\#/}#g" "${templateDst}"
|
||||||
|
# this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
|
||||||
|
rm -f "${templateDst}.bak"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
# cat "${templateDst}"
|
# cat "${templateDst}"
|
||||||
|
|
||||||
# shellcheck disable=SC2016
|
# shellcheck disable=SC2016
|
||||||
if grep '${' "${templateDst}" && [ "${ALLOW_REMAINDERS}" = "0" ]; then
|
if grep '${' "${templateDst}" && [[ "${ALLOW_REMAINDERS}" = "0" ]]; then
|
||||||
echo "ERROR: Unable to replace the above template vars"
|
echo "ERROR: Unable to replace the above template vars"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
|
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
|
||||||
export -f templater
|
export -f templater
|
||||||
else
|
else
|
||||||
templater "${@}"
|
templater "${@}"
|
||||||
|
@ -41,12 +41,12 @@ __accptstTmpDir=$(mktemp -d "${__sysTmpDir}/${__base}.XXXXXX")
|
|||||||
function cleanup_before_exit () { rm -r "${__accptstTmpDir:?}"; }
|
function cleanup_before_exit () { rm -r "${__accptstTmpDir:?}"; }
|
||||||
trap cleanup_before_exit EXIT
|
trap cleanup_before_exit EXIT
|
||||||
|
|
||||||
cmdSed=sed
|
cmdSed="sed"
|
||||||
cmdTimeout=timeout
|
cmdTimeout="timeout"
|
||||||
|
|
||||||
if [[ "${OSTYPE}" == "darwin"* ]]; then
|
if [[ "${OSTYPE}" = "darwin"* ]]; then
|
||||||
cmdSed=gsed
|
cmdSed="gsed"
|
||||||
cmdTimeout=gtimeout
|
cmdTimeout="gtimeout"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! "$(command -v ${cmdSed})" ]]; then
|
if [[ ! "$(command -v ${cmdSed})" ]]; then
|
||||||
@ -59,11 +59,11 @@ if [[ ! "$(command -v ${cmdTimeout})" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
__node="$(which node)"
|
__node="$(command -v node)"
|
||||||
__arch="amd64"
|
__arch="amd64"
|
||||||
|
|
||||||
# explicitly setting NO_COLOR to false will make b3bp ignore TERM
|
# explicitly setting NO_COLOR to false will make b3bp ignore TERM
|
||||||
# not being "xterm*" and STDERR not being connected to a terminal
|
# not being "xterm*" or "screen*" and STDERR not being connected to a terminal
|
||||||
# it's the opposite of NO_COLOR="true" - it forces color, no matter what
|
# it's the opposite of NO_COLOR="true" - it forces color, no matter what
|
||||||
export NO_COLOR="false"
|
export NO_COLOR="false"
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ while IFS=$'\n' read -r scenario; do
|
|||||||
-e "s@${USER:-travis}@{user}@g" "${curFile}" \
|
-e "s@${USER:-travis}@{user}@g" "${curFile}" \
|
||||||
-e "s@travis@{user}@g" "${curFile}" \
|
-e "s@travis@{user}@g" "${curFile}" \
|
||||||
-e "s@kvz@{user}@g" "${curFile}" \
|
-e "s@kvz@{user}@g" "${curFile}" \
|
||||||
-e "s@{root}/node_modules/\.bin/node@{node}@g" "${curFile}" \
|
-e "s@{root}/node_modules/\\.bin/node@{node}@g" "${curFile}" \
|
||||||
-e "s@{home}/build/{user}/fre{node}@{node}@g" "${curFile}" \
|
-e "s@{home}/build/{user}/fre{node}@{node}@g" "${curFile}" \
|
||||||
-e "s@${HOSTNAME}@{hostname}@g" "${curFile}" \
|
-e "s@${HOSTNAME}@{hostname}@g" "${curFile}" \
|
||||||
-e "s@${__arch}@{arch}@g" "${curFile}" \
|
-e "s@${__arch}@{arch}@g" "${curFile}" \
|
||||||
@ -148,7 +148,7 @@ while IFS=$'\n' read -r scenario; do
|
|||||||
"${curFile}"
|
"${curFile}"
|
||||||
fi
|
fi
|
||||||
if grep -q 'ACCPTST:STDIO_REPLACE_REMOTE_EXEC' "${curFile}"; then
|
if grep -q 'ACCPTST:STDIO_REPLACE_REMOTE_EXEC' "${curFile}"; then
|
||||||
egrep -v 'remote-exec\): [ a-zA-Z]' "${curFile}" > "${__sysTmpDir}/accptst-filtered.txt"
|
grep -Ev 'remote-exec\): [ a-zA-Z]' "${curFile}" > "${__sysTmpDir}/accptst-filtered.txt"
|
||||||
mv "${__sysTmpDir}/accptst-filtered.txt" "${curFile}"
|
mv "${__sysTmpDir}/accptst-filtered.txt" "${curFile}"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@ -177,10 +177,10 @@ while IFS=$'\n' read -r scenario; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if ! diff --strip-trailing-cr "${__dir}/fixture/${scenario}.${typ}" "${curFile}"; then
|
if ! diff --strip-trailing-cr "${__dir}/fixture/${scenario}.${typ}" "${curFile}"; then
|
||||||
echo -e "\n\n==> MISMATCH OF: ${scenario}.${typ} ---^"
|
echo -e "\\n\\n==> MISMATCH OF: ${scenario}.${typ} ---^"
|
||||||
echo -e "\n\n==> EXPECTED STDIO: "
|
echo -e "\\n\\n==> EXPECTED STDIO: "
|
||||||
cat "${__dir}/fixture/${scenario}.stdio" || true
|
cat "${__dir}/fixture/${scenario}.stdio" || true
|
||||||
echo -e "\n\n==> ACTUAL STDIO: "
|
echo -e "\\n\\n==> ACTUAL STDIO: "
|
||||||
cat "${__accptstTmpDir}/${scenario}.stdio" || true
|
cat "${__accptstTmpDir}/${scenario}.stdio" || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@ -193,20 +193,26 @@ done <<< "$(find "${__dir}/scenario" -type f -iname 'run.sh')"
|
|||||||
|
|
||||||
[[ "${1:-}" ]] && exit 0
|
[[ "${1:-}" ]] && exit 0
|
||||||
|
|
||||||
# finally do some shellcheck linting
|
# Ensure correct syntax with all available bashes
|
||||||
if [[ "$(command -v shellcheck)" ]]; then
|
|
||||||
echo "==> Shellcheck"
|
# shellcheck disable=SC2230
|
||||||
|
# "command -v" is not a substitute for "which -a"
|
||||||
|
while IFS=$'\n' read -r bash; do
|
||||||
|
if [[ "${bash:-}" = "" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
echo "==> ${bash} -n $(${bash} -c 'echo "(${BASH_VERSION})"')"
|
||||||
pushd "${__root}" > /dev/null
|
pushd "${__root}" > /dev/null
|
||||||
|
|
||||||
failed="false"
|
failed="false"
|
||||||
|
|
||||||
while IFS=$'\n' read -r file; do
|
while IFS=$'\n' read -r file; do
|
||||||
[[ "${file}" =~ ^\./node_modules/ ]] && continue
|
[[ "${file}" =~ ^\./node_modules/ ]] && continue
|
||||||
[[ "${file}" =~ ^\./website/\.lanyon/ ]] && continue
|
|
||||||
|
|
||||||
echo -n " ${file}.. "
|
echo -n " ${file}.. "
|
||||||
|
|
||||||
if ! shellcheck --shell=bash --external-sources "${file}" >> "${__accptstTmpDir}/shellcheck.err"; then
|
if ! "${bash}" -n "${file}" 2>> "${__accptstTmpDir}/${bash//\//.}.err"; then
|
||||||
echo "✗"
|
echo "✗"
|
||||||
failed="true"
|
failed="true"
|
||||||
continue
|
continue
|
||||||
@ -218,9 +224,9 @@ if [[ "$(command -v shellcheck)" ]]; then
|
|||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
|
|
||||||
if [[ "${failed}" = "true" ]]; then
|
if [[ "${failed}" = "true" ]]; then
|
||||||
cat "${__accptstTmpDir}/shellcheck.err"
|
cat "${__accptstTmpDir}/${bash//\//.}.err"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
done <<< "$(which -a bash 2>/dev/null)"
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
1
test/fixture/double-source.exitcode
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
25
test/fixture/double-source.stdio
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
ACCPTST:STDIO_REPLACE_DATETIMES
|
||||||
|
{datetime} UTC [35m[ debug][0m cli arg arg_f = () -> {tmpdir}/x
|
||||||
|
{datetime} UTC [32m[ info][0m __i_am_main_script: 0
|
||||||
|
{datetime} UTC [32m[ info][0m __file: {root}/example.sh
|
||||||
|
{datetime} UTC [32m[ info][0m __dir: {root}
|
||||||
|
{datetime} UTC [32m[ info][0m __base: example
|
||||||
|
{datetime} UTC [32m[ info][0m OSTYPE: {OSTYPE}
|
||||||
|
{datetime} UTC [32m[ info][0m arg_f: {tmpdir}/x
|
||||||
|
{datetime} UTC [32m[ info][0m arg_d: 0
|
||||||
|
{datetime} UTC [32m[ info][0m arg_v: 0
|
||||||
|
{datetime} UTC [32m[ info][0m arg_h: 0
|
||||||
|
{datetime} UTC [32m[ info][0m arg_i: 0
|
||||||
|
{datetime} UTC [32m[ info][0m arg_x: 0
|
||||||
|
{datetime} UTC [32m[ info][0m multiple lines example - line #1
|
||||||
|
{datetime} UTC [32m[ info][0m multiple lines example - line #2
|
||||||
|
{datetime} UTC [32m[ info][0m imagine logging the output of 'ls -al /path/'
|
||||||
|
{datetime} UTC [35m[ debug][0m Info useful to developers for debugging the application, not useful during operations.
|
||||||
|
{datetime} UTC [32m[ info][0m Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required.
|
||||||
|
{datetime} UTC [34m[ notice][0m Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required.
|
||||||
|
{datetime} UTC [33m[ warning][0m Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time.
|
||||||
|
{datetime} UTC [31m[ error][0m Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time.
|
||||||
|
{datetime} UTC [1;31m[ critical][0m Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection.
|
||||||
|
{datetime} UTC [1;37;41m[ alert][0m Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection.
|
||||||
|
{datetime} UTC [1;4;5;37;41m[emergency][0m A "panic" condition usually affecting multiple apps/servers/sites. At this level it would usually notify all tech staff on call.
|
||||||
|
{datetime} UTC [32m[ info][0m Cleaning up. Done
|
@ -2,23 +2,41 @@
|
|||||||
exists
|
exists
|
||||||
127.0.0.1
|
127.0.0.1
|
||||||
nginx, nodejs
|
nginx, nodejs
|
||||||
|
|
||||||
--> command: Replace three values in-place and show result
|
--> command: Replace three values in-place and show result
|
||||||
orphan = no more
|
|
||||||
|
[default]
|
||||||
|
orphan=no more
|
||||||
|
|
||||||
[connection]
|
[connection]
|
||||||
host = 192.168.0.1
|
host=192.168.0.1
|
||||||
|
|
||||||
[software]
|
[software]
|
||||||
packages = vim
|
packages=vim
|
||||||
|
|
||||||
|
[comment]
|
||||||
|
;[command] got this new comment
|
||||||
|
command=works like a chame
|
||||||
|
;[new_command] last addition will be moved downwards again after next command
|
||||||
|
new_command=commented too
|
||||||
--> function: Read 3 values
|
--> function: Read 3 values
|
||||||
exists
|
exists
|
||||||
127.0.0.1
|
127.0.0.1
|
||||||
nginx, nodejs
|
nginx, nodejs
|
||||||
|
|
||||||
--> function: Replace three values in-place and show result
|
--> function: Replace three values in-place and show result
|
||||||
orphan = no more
|
|
||||||
|
[default]
|
||||||
|
orphan=no more
|
||||||
|
|
||||||
[connection]
|
[connection]
|
||||||
host = 192.168.0.1
|
host=192.168.0.1
|
||||||
|
|
||||||
[software]
|
[software]
|
||||||
packages = vim
|
packages=vim
|
||||||
|
|
||||||
|
[comment]
|
||||||
|
;[command] got this new comment
|
||||||
|
command=works like a chame
|
||||||
|
;[new_command] last addition will be moved downwards again after next command
|
||||||
|
new_command=commented too
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
ACCPTST:STDIO_REPLACE_DATETIMES
|
ACCPTST:STDIO_REPLACE_DATETIMES
|
||||||
{datetime} UTC [35m[ debug][0m cli arg arg_f = () -> {tmpdir}/x
|
{datetime} UTC [35m[ debug][0m cli arg arg_f = () -> {tmpdir}/x
|
||||||
|
{datetime} UTC [32m[ info][0m __i_am_main_script: 1
|
||||||
{datetime} UTC [32m[ info][0m __file: {root}/main.sh
|
{datetime} UTC [32m[ info][0m __file: {root}/main.sh
|
||||||
{datetime} UTC [32m[ info][0m __dir: {root}
|
{datetime} UTC [32m[ info][0m __dir: {root}
|
||||||
{datetime} UTC [32m[ info][0m __base: main
|
{datetime} UTC [32m[ info][0m __base: main
|
||||||
@ -8,15 +9,17 @@ ACCPTST:STDIO_REPLACE_DATETIMES
|
|||||||
{datetime} UTC [32m[ info][0m arg_d: 0
|
{datetime} UTC [32m[ info][0m arg_d: 0
|
||||||
{datetime} UTC [32m[ info][0m arg_v: 0
|
{datetime} UTC [32m[ info][0m arg_v: 0
|
||||||
{datetime} UTC [32m[ info][0m arg_h: 0
|
{datetime} UTC [32m[ info][0m arg_h: 0
|
||||||
|
{datetime} UTC [32m[ info][0m arg_i: 0
|
||||||
|
{datetime} UTC [32m[ info][0m arg_x: 0
|
||||||
{datetime} UTC [32m[ info][0m multiple lines example - line #1
|
{datetime} UTC [32m[ info][0m multiple lines example - line #1
|
||||||
{datetime} UTC [32m[ info][0m multiple lines example - line #2
|
{datetime} UTC [32m[ info][0m multiple lines example - line #2
|
||||||
{datetime} UTC [32m[ info][0m imagine logging the output of 'ls -al /path/'
|
{datetime} UTC [32m[ info][0m imagine logging the output of 'ls -al /path/'
|
||||||
{datetime} UTC [35m[ debug][0m Info useful to developers for debugging the application, not useful during operations.
|
{datetime} UTC [35m[ debug][0m Info useful to developers for debugging the application, not useful during operations.
|
||||||
{datetime} UTC [32m[ info][0m Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required.
|
{datetime} UTC [32m[ info][0m Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required.
|
||||||
{datetime} UTC [34m[ notice][0m Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required.
|
{datetime} UTC [34m[ notice][0m Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required.
|
||||||
{datetime} UTC [33m[ warning][0m Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time. This is a debug message
|
{datetime} UTC [33m[ warning][0m Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time.
|
||||||
{datetime} UTC [31m[ error][0m Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time.
|
{datetime} UTC [31m[ error][0m Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time.
|
||||||
{datetime} UTC [1;31m[ critical][0m Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection.
|
{datetime} UTC [1;31m[ critical][0m Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection.
|
||||||
{datetime} UTC [1;33;41m[ alert][0m Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection.
|
{datetime} UTC [1;37;41m[ alert][0m Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection.
|
||||||
{datetime} UTC [1;4;5;33;41m[emergency][0m A "panic" condition usually affecting multiple apps/servers/sites. At this level it would usually notify all tech staff on call.
|
{datetime} UTC [1;4;5;37;41m[emergency][0m A "panic" condition usually affecting multiple apps/servers/sites. At this level it would usually notify all tech staff on call.
|
||||||
{datetime} UTC [32m[ info][0m Cleaning up. Done
|
{datetime} UTC [32m[ info][0m Cleaning up. Done
|
||||||
|
@ -9,8 +9,11 @@ ACCPTST:STDIO_REPLACE_DATETIMES
|
|||||||
-h --help This page
|
-h --help This page
|
||||||
-n --no-color Disable color output
|
-n --no-color Disable color output
|
||||||
-1 --one Do just one thing
|
-1 --one Do just one thing
|
||||||
|
-i --input [arg] File to process. Can be repeated.
|
||||||
|
-x Specify a flag. Can be repeated.
|
||||||
|
|
||||||
This is Bash3 Boilerplate's help text. Feel free to add any description of your
|
This is Bash3 Boilerplate's help text. Feel free to add any description of your
|
||||||
program or elaborate more on command-line arguments. This section is not
|
program or elaborate more on command-line arguments. This section is not
|
||||||
parsed and will be added as-is to the help.
|
parsed and will be added as-is to the help.
|
||||||
|
|
||||||
|
{datetime} UTC [32m[ info][0m Cleaning up. Done
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
ACCPTST:STDIO_REPLACE_DATETIMES
|
ACCPTST:STDIO_REPLACE_DATETIMES
|
||||||
{datetime} UTC [ debug] cli arg arg_f = () -> {tmpdir}/x
|
{datetime} UTC [ debug] cli arg arg_f = () -> {tmpdir}/x
|
||||||
|
{datetime} UTC [ info] __i_am_main_script: 1
|
||||||
{datetime} UTC [ info] __file: {root}/main.sh
|
{datetime} UTC [ info] __file: {root}/main.sh
|
||||||
{datetime} UTC [ info] __dir: {root}
|
{datetime} UTC [ info] __dir: {root}
|
||||||
{datetime} UTC [ info] __base: main
|
{datetime} UTC [ info] __base: main
|
||||||
@ -8,13 +9,15 @@ ACCPTST:STDIO_REPLACE_DATETIMES
|
|||||||
{datetime} UTC [ info] arg_d: 0
|
{datetime} UTC [ info] arg_d: 0
|
||||||
{datetime} UTC [ info] arg_v: 0
|
{datetime} UTC [ info] arg_v: 0
|
||||||
{datetime} UTC [ info] arg_h: 0
|
{datetime} UTC [ info] arg_h: 0
|
||||||
|
{datetime} UTC [ info] arg_i: 0
|
||||||
|
{datetime} UTC [ info] arg_x: 0
|
||||||
{datetime} UTC [ info] multiple lines example - line #1
|
{datetime} UTC [ info] multiple lines example - line #1
|
||||||
{datetime} UTC [ info] multiple lines example - line #2
|
{datetime} UTC [ info] multiple lines example - line #2
|
||||||
{datetime} UTC [ info] imagine logging the output of 'ls -al /path/'
|
{datetime} UTC [ info] imagine logging the output of 'ls -al /path/'
|
||||||
{datetime} UTC [ debug] Info useful to developers for debugging the application, not useful during operations.
|
{datetime} UTC [ debug] Info useful to developers for debugging the application, not useful during operations.
|
||||||
{datetime} UTC [ info] Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required.
|
{datetime} UTC [ info] Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required.
|
||||||
{datetime} UTC [ notice] Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required.
|
{datetime} UTC [ notice] Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required.
|
||||||
{datetime} UTC [ warning] Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time. This is a debug message
|
{datetime} UTC [ warning] Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time.
|
||||||
{datetime} UTC [ error] Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time.
|
{datetime} UTC [ error] Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time.
|
||||||
{datetime} UTC [ critical] Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection.
|
{datetime} UTC [ critical] Should be corrected immediately, but indicates failure in a primary system, an example is a loss of a backup ISP connection.
|
||||||
{datetime} UTC [ alert] Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection.
|
{datetime} UTC [ alert] Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection.
|
||||||
|
1
test/fixture/main-repeated.exitcode
Normal file
@ -0,0 +1 @@
|
|||||||
|
0
|
9
test/fixture/main-repeated.stdio
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
ACCPTST:STDIO_REPLACE_DATETIMES
|
||||||
|
{datetime} UTC [32m[ info][0m arg_i:
|
||||||
|
{datetime} UTC [32m[ info][0m - simple_input
|
||||||
|
{datetime} UTC [32m[ info][0m - input_in_quotes
|
||||||
|
{datetime} UTC [32m[ info][0m - input with spaces
|
||||||
|
{datetime} UTC [32m[ info][0m - input with "quotes"
|
||||||
|
{datetime} UTC [32m[ info][0m - last_input
|
||||||
|
{datetime} UTC [32m[ info][0m arg_x: 3
|
||||||
|
{datetime} UTC [32m[ info][0m arg_x: 4
|
@ -153,3 +153,17 @@ ACCPTST:STDIO_REPLACE_DATETIMES
|
|||||||
{datetime} UTC [ info] arg_b: do-b
|
{datetime} UTC [ info] arg_b: do-b
|
||||||
{datetime} UTC [ info] arg_c: do-c
|
{datetime} UTC [ info] arg_c: do-c
|
||||||
{datetime} UTC [ info] arg_d: argd
|
{datetime} UTC [ info] arg_d: argd
|
||||||
|
# test for issue #108
|
||||||
|
{datetime} UTC [ info] arg_0: 1
|
||||||
|
{datetime} UTC [ info] arg_1: 0
|
||||||
|
{datetime} UTC [ info] arg_2: 0
|
||||||
|
{datetime} UTC [ info] arg_3: arg3
|
||||||
|
{datetime} UTC [ info] arg_4: value
|
||||||
|
{datetime} UTC [ info] arg_5: arg5
|
||||||
|
{datetime} UTC [ info] arg_6:
|
||||||
|
{datetime} UTC [ info] arg_7:
|
||||||
|
{datetime} UTC [ info] arg_8: arg8
|
||||||
|
{datetime} UTC [ info] arg_a: do-a
|
||||||
|
{datetime} UTC [ info] arg_b: do-b
|
||||||
|
{datetime} UTC [ info] arg_c: do-c
|
||||||
|
{datetime} UTC [ info] arg_d: argd
|
||||||
|
15
test/scenario/double-source/run.sh
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -o pipefail
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
# set -o xtrace
|
||||||
|
|
||||||
|
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
__root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
|
||||||
|
|
||||||
|
export LOG_LEVEL=7
|
||||||
|
|
||||||
|
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
||||||
|
|
||||||
|
# shellcheck source=example.sh
|
||||||
|
source "${__root}/example.sh" -f /tmp/x
|
@ -1,7 +1,8 @@
|
|||||||
orphan = exists
|
[default]
|
||||||
|
orphan=exists
|
||||||
|
|
||||||
[connection]
|
[connection]
|
||||||
host = 127.0.0.1
|
host=127.0.0.1
|
||||||
|
|
||||||
[software]
|
[software]
|
||||||
packages = nginx, nodejs
|
packages=nginx, nodejs
|
||||||
|
12
test/scenario/ini_val/run.sh
Normal file → Executable file
@ -6,8 +6,6 @@ set -o nounset
|
|||||||
|
|
||||||
# Set magic variables for current FILE & DIR
|
# Set magic variables for current FILE & DIR
|
||||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
|
||||||
__base="$(basename "${__file}" .sh)"
|
|
||||||
__root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
|
__root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
|
||||||
|
|
||||||
# echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
# echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
||||||
@ -19,11 +17,16 @@ echo "--> command: Read 3 values"
|
|||||||
bash "${__root}/src/ini_val.sh" ./dummy.ini orphan
|
bash "${__root}/src/ini_val.sh" ./dummy.ini orphan
|
||||||
bash "${__root}/src/ini_val.sh" ./dummy.ini connection.host
|
bash "${__root}/src/ini_val.sh" ./dummy.ini connection.host
|
||||||
bash "${__root}/src/ini_val.sh" ./dummy.ini software.packages
|
bash "${__root}/src/ini_val.sh" ./dummy.ini software.packages
|
||||||
|
bash "${__root}/src/ini_val.sh" ./dummy.ini comment.command
|
||||||
|
|
||||||
echo "--> command: Replace three values in-place and show result"
|
echo "--> command: Replace three values in-place and show result"
|
||||||
bash "${__root}/src/ini_val.sh" ./dummy.ini orphan "no more"
|
bash "${__root}/src/ini_val.sh" ./dummy.ini orphan "no more"
|
||||||
bash "${__root}/src/ini_val.sh" ./dummy.ini connection.host "192.168.0.1"
|
bash "${__root}/src/ini_val.sh" ./dummy.ini connection.host "192.168.0.1"
|
||||||
bash "${__root}/src/ini_val.sh" ./dummy.ini software.packages "vim"
|
bash "${__root}/src/ini_val.sh" ./dummy.ini software.packages "vim"
|
||||||
|
|
||||||
|
bash "${__root}/src/ini_val.sh" ./dummy.ini comment.command "commented" "this key is commented"
|
||||||
|
bash "${__root}/src/ini_val.sh" ./dummy.ini comment.new_command "commented too" "last addition will be moved downwards again after next command"
|
||||||
|
bash "${__root}/src/ini_val.sh" ./dummy.ini comment.command "works like a chame" "got this new comment"
|
||||||
cat dummy.ini
|
cat dummy.ini
|
||||||
rm -f dummy.ini
|
rm -f dummy.ini
|
||||||
|
|
||||||
@ -37,10 +40,15 @@ echo "--> function: Read 3 values"
|
|||||||
ini_val ./dummy.ini orphan
|
ini_val ./dummy.ini orphan
|
||||||
ini_val ./dummy.ini connection.host
|
ini_val ./dummy.ini connection.host
|
||||||
ini_val ./dummy.ini software.packages
|
ini_val ./dummy.ini software.packages
|
||||||
|
ini_val ./dummy.ini comment.command
|
||||||
|
|
||||||
echo "--> function: Replace three values in-place and show result"
|
echo "--> function: Replace three values in-place and show result"
|
||||||
ini_val ./dummy.ini orphan "no more"
|
ini_val ./dummy.ini orphan "no more"
|
||||||
ini_val ./dummy.ini connection.host "192.168.0.1"
|
ini_val ./dummy.ini connection.host "192.168.0.1"
|
||||||
ini_val ./dummy.ini software.packages "vim"
|
ini_val ./dummy.ini software.packages "vim"
|
||||||
|
|
||||||
|
ini_val ./dummy.ini comment.command "commented" "this key is commited"
|
||||||
|
ini_val ./dummy.ini comment.new_command "commented too" "last addition will be moved downwards again after next command"
|
||||||
|
ini_val ./dummy.ini comment.command "works like a chame" "got this new comment"
|
||||||
cat dummy.ini
|
cat dummy.ini
|
||||||
rm -f dummy.ini
|
rm -f dummy.ini
|
||||||
|
@ -9,4 +9,4 @@ __root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
|
|||||||
|
|
||||||
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
||||||
|
|
||||||
env LOG_LEVEL=8 bash "${__root}/main.sh" -f /tmp/x
|
env LOG_LEVEL=7 bash "${__root}/main.sh" -f /tmp/x
|
||||||
|
@ -9,4 +9,4 @@ __root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
|
|||||||
|
|
||||||
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
||||||
|
|
||||||
env LOG_LEVEL=8 NO_COLOR=true bash "${__root}/main.sh" -f /tmp/x
|
env LOG_LEVEL=7 NO_COLOR=true bash "${__root}/main.sh" -f /tmp/x
|
||||||
|
19
test/scenario/main-repeated/run.sh
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# set -o pipefail
|
||||||
|
# set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
# set -o xtrace
|
||||||
|
|
||||||
|
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
__root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
|
||||||
|
|
||||||
|
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
||||||
|
|
||||||
|
(
|
||||||
|
env LOG_LEVEL="${LOG_LEVEL:-6}" bash "${__root}/main.sh" -f dummy -i simple_input -i "input_in_quotes" -i "input with spaces" -i "input with \"quotes\"" -i last_input
|
||||||
|
) 2>&1 |grep arg_i -A 5
|
||||||
|
|
||||||
|
(
|
||||||
|
env LOG_LEVEL="${LOG_LEVEL:-6}" bash "${__root}/main.sh" -x -f dummy -x -x
|
||||||
|
env LOG_LEVEL="${LOG_LEVEL:-6}" bash "${__root}/main.sh" -f dummy -xxxx
|
||||||
|
) 2>&1 |grep arg_x
|
@ -22,6 +22,8 @@ read -r -d '' __usage <<-'EOF' || true # exits non-zero when EOF encountered
|
|||||||
More description.
|
More description.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
export __usage
|
||||||
|
|
||||||
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
|
||||||
|
|
||||||
# shellcheck source=main.sh
|
# shellcheck source=main.sh
|
||||||
|
@ -56,3 +56,9 @@ echo "# complain about nothing"
|
|||||||
source "${__root}/main.sh" -3 arg3 -4 arg4 -5 arg5 -8 arg8 -d argd
|
source "${__root}/main.sh" -3 arg3 -4 arg4 -5 arg5 -8 arg8 -d argd
|
||||||
for argument in ${!arg_*}; do info "${argument}: ${!argument}"; done
|
for argument in ${!arg_*}; do info "${argument}: ${!argument}"; done
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo "# test for issue #108"
|
||||||
|
(
|
||||||
|
source "${__root}/main.sh" -3 arg3 -5 arg5 -8 arg8 -d argd --four value --zero
|
||||||
|
for argument in ${!arg_*}; do info "${argument}: ${!argument}"; done
|
||||||
|
)
|
||||||
|
@ -5,12 +5,18 @@ set -o nounset
|
|||||||
# set -o xtrace
|
# set -o xtrace
|
||||||
|
|
||||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||||
|
__base="$(basename "${__file}" .sh)"
|
||||||
|
|
||||||
__root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
|
__root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
|
||||||
|
|
||||||
|
__templaterTmpFile=$(mktemp "${TMPDIR:-/tmp}/${__base}.XXXXXX")
|
||||||
|
function cleanup_before_exit () { rm "${__templaterTmpFile:?}"; }
|
||||||
|
trap cleanup_before_exit EXIT
|
||||||
|
|
||||||
echo "--"
|
echo "--"
|
||||||
env TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./app.template.cfg ./app.cfg
|
env TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./app.template.cfg "${__templaterTmpFile}"
|
||||||
cat app.cfg
|
cat "${__templaterTmpFile}"
|
||||||
rm -f app.cfg
|
|
||||||
|
|
||||||
echo "--"
|
echo "--"
|
||||||
export TARGET_HOST="127.0.0.1"
|
export TARGET_HOST="127.0.0.1"
|
||||||
@ -18,16 +24,13 @@ export TARGET_HOST="127.0.0.1"
|
|||||||
# shellcheck source=src/templater.sh
|
# shellcheck source=src/templater.sh
|
||||||
source "${__root}/src/templater.sh"
|
source "${__root}/src/templater.sh"
|
||||||
|
|
||||||
templater ./app.template.cfg ./app.cfg
|
templater ./app.template.cfg "${__templaterTmpFile}"
|
||||||
cat app.cfg
|
cat "${__templaterTmpFile}"
|
||||||
rm -f app.cfg
|
|
||||||
|
|
||||||
echo "--"
|
echo "--"
|
||||||
env ALLOW_REMAINDERS="1" TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./break.template.cfg ./break.cfg
|
env ALLOW_REMAINDERS="1" TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./break.template.cfg "${__templaterTmpFile}"
|
||||||
cat break.cfg
|
cat "${__templaterTmpFile}"
|
||||||
rm -f break.cfg
|
|
||||||
|
|
||||||
echo "--"
|
echo "--"
|
||||||
env TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./break.template.cfg ./break.cfg
|
env TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./break.template.cfg "${__templaterTmpFile}"
|
||||||
cat break.cfg
|
cat "${__templaterTmpFile}"
|
||||||
rm -f break.cfg
|
|
||||||
|
45
test/style.pl
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
die "usage: $0 <file>\n" if (not @ARGV);
|
||||||
|
|
||||||
|
my $rc = 0;
|
||||||
|
my $file = shift;
|
||||||
|
|
||||||
|
open(my $fh, '<', $file) or die "Cannot open \`$file' for read: $!\n";
|
||||||
|
while (<$fh>) {
|
||||||
|
next if (/^\s*#/);
|
||||||
|
|
||||||
|
my $errors = 0;
|
||||||
|
|
||||||
|
# remove everything between single quotes
|
||||||
|
# this will remove too much in case of: echo "var='$var'"
|
||||||
|
# and thus miss an opportunity to complain later on
|
||||||
|
# also it mangles the input line irreversible
|
||||||
|
s/'[^']+'/'___'/g;
|
||||||
|
|
||||||
|
# highlight unbraced variables--
|
||||||
|
# unless properly backslash'ed
|
||||||
|
$errors += s/((?:^|[^\\]))(((\\\\)+)?\$\w)/$1\033[31m$2\033[0m/g;
|
||||||
|
|
||||||
|
# highlight single square brackets
|
||||||
|
$errors += s/((?:^|\s+))\[([^\[].+[^\]])\](\s*(;|&&|\|\|))/$1\033[31m\[\033[0m$2\033[31m\]\033[0m$3/g;
|
||||||
|
|
||||||
|
# highlight double equal sign
|
||||||
|
$errors += s/(\[\[.*)(==)(.*\]\])/$1\033[31m$2\033[0m$3/g;
|
||||||
|
|
||||||
|
# highlight tabs mixed with whitespace at beginning of lines
|
||||||
|
$errors += s/^( *)(\t+ *)/\033[31m\[$2\]\033[0m/;
|
||||||
|
|
||||||
|
# highlight trailing whitespace
|
||||||
|
$errors += s/([ \t]+)$/\033[31m\[$1\]\033[0m/;
|
||||||
|
|
||||||
|
next if (not $errors);
|
||||||
|
print "${file}[$.]: $_";
|
||||||
|
$rc = 1;
|
||||||
|
}
|
||||||
|
close($fh);
|
||||||
|
|
||||||
|
exit $rc;
|
@ -1 +0,0 @@
|
|||||||
{rules: {}}
|
|
@ -1 +0,0 @@
|
|||||||
bash3boilerplate.sh
|
|
@ -1,4 +0,0 @@
|
|||||||
title: BASH3 Boilerplate
|
|
||||||
|
|
||||||
gems:
|
|
||||||
- jekyll-redirect-from
|
|
@ -1,84 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
{% if page.url == "/" %}
|
|
||||||
<title>{{page.title}}</title>
|
|
||||||
{% else %}
|
|
||||||
<title>{{page.title}} | {{site.title}}</title>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<meta name="keywords" content="bash, template, scripting, command-line">
|
|
||||||
<meta name="description" content="BASH3 Boilerplate">
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700' rel='stylesheet' type='text/css'>
|
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
||||||
<link rel="stylesheet" href="{{site.lanyon_assets.app.css}}" media="screen" charset="utf-8">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<div id="header-overlay"></div>
|
|
||||||
<a href="/">
|
|
||||||
<span id="logo"></span>
|
|
||||||
</a>
|
|
||||||
<div id="menu">
|
|
||||||
<i class="material-icons">menu</i>
|
|
||||||
<ul id="menu-items">
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<span id="more">
|
|
||||||
<i class="material-icons">expand_more</i>
|
|
||||||
</span>
|
|
||||||
</header>
|
|
||||||
<section id="content">
|
|
||||||
{% if page.url == "/" %}
|
|
||||||
<div class="Social">
|
|
||||||
<iframe src="http://ghbtns.com/github-btn.html?user=kvz&repo=bash3boilerplate&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"></iframe>
|
|
||||||
<a href="https://travis-ci.org/kvz/bash3boilerplate"><img src="https://travis-ci.org/kvz/bash3boilerplate.svg" alt="Build Status"></a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{{content}}
|
|
||||||
|
|
||||||
{% if page.url == "/" %}
|
|
||||||
<h2 id="activity-feed">On GitHub</h2>
|
|
||||||
<p>
|
|
||||||
BASH3 Boilerplate is a friendly group of folks further developing our
|
|
||||||
re-usable templates as we go.
|
|
||||||
We'd love to hear what you think <a href="https://github.com/kvz/bash3boilerplate">on GitHub</a>.
|
|
||||||
Here's what's been going on recently.
|
|
||||||
</p>
|
|
||||||
<div class="on-the-githubs" data-event-source="repos/kvz/bash3boilerplate">Loading...</div>
|
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
|
||||||
<script src="//kvz.github.io/on-the-githubs/js/jquery.on-the-githubs.min.js"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
$('.on-the-githubs').onthegithubs();
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="Social">
|
|
||||||
<iframe src="http://ghbtns.com/github-btn.html?user=kvz&repo=bash3boilerplate&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"></iframe>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<small>
|
|
||||||
<hr />
|
|
||||||
Website design based on
|
|
||||||
the wonderful <a href="http://apex.run">apex.run</a>
|
|
||||||
with <a href="https://twitter.com/tjholowaychuk/status/744909762865696769">the author's consent</a>.
|
|
||||||
</small>
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/bash.min.js"></script>
|
|
||||||
<script async src="{{site.lanyon_assets.app.js}}"></script>
|
|
||||||
<script>
|
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
||||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
|
||||||
|
|
||||||
ga('create', 'UA-63083-13', 'auto');
|
|
||||||
ga('send', 'pageview');
|
|
||||||
</script>
|
|
||||||
</html>
|
|
@ -1,76 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# This file:
|
|
||||||
#
|
|
||||||
# - Injects markdown files into the ./website directory
|
|
||||||
# - Changes them a little to make them more suitable for Jekyll building
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
#
|
|
||||||
# ./inject.sh
|
|
||||||
#
|
|
||||||
# Based on a template by BASH3 Boilerplate v2.0.0
|
|
||||||
# http://bash3boilerplate.sh/#authors
|
|
||||||
#
|
|
||||||
# The MIT License (MIT)
|
|
||||||
# Copyright (c) 2013 Kevin van Zonneveld and contributors
|
|
||||||
# You are not obligated to bundle the LICENSE file with your b3bp projects as long
|
|
||||||
# as you leave these references intact in the header comments of your source files.
|
|
||||||
|
|
||||||
# Exit on error. Append || true if you expect an error.
|
|
||||||
set -o errexit
|
|
||||||
# Exit on error inside any functions or subshells.
|
|
||||||
set -o errtrace
|
|
||||||
# Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR
|
|
||||||
set -o nounset
|
|
||||||
# Catch the error in case mysqldump fails (but gzip succeeds) in `mysqldump |gzip`
|
|
||||||
set -o pipefail
|
|
||||||
# Turn on traces, useful while debugging but commented out by default
|
|
||||||
# set -o xtrace
|
|
||||||
|
|
||||||
# Set magic variables for current file, directory, os, etc.
|
|
||||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
|
||||||
__base="$(basename "${__file}" .sh)"
|
|
||||||
__root="$(cd "$(dirname "$(dirname "${__dir}")")" && pwd)"
|
|
||||||
|
|
||||||
pushd "${__root}"
|
|
||||||
# Offer the main template for download as http://bash3boilerplate.sh/main.sh
|
|
||||||
cp -v main.sh website/
|
|
||||||
|
|
||||||
for doc in "README" "FAQ" "CHANGELOG"; do
|
|
||||||
targetName="$(echo "${doc}" | awk '{print tolower($0)}')"
|
|
||||||
permalink="/${targetName}/"
|
|
||||||
subtitle="$(tr '[:lower:]' '[:upper:]' <<< "${targetName:0:1}")${targetName:1} | "
|
|
||||||
redirectFrom="/${doc}.md/"
|
|
||||||
backLink="\n\n<a href=\"/\">« Home</a>"
|
|
||||||
if [[ "${doc}" = "README" ]]; then
|
|
||||||
targetName="index"
|
|
||||||
permalink="/"
|
|
||||||
subtitle=""
|
|
||||||
redirectFrom="nothing"
|
|
||||||
backLink=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat <<EOF > "website/${targetName}.md"
|
|
||||||
---
|
|
||||||
layout: default
|
|
||||||
permalink: ${permalink}
|
|
||||||
redirect_from: ${redirectFrom}
|
|
||||||
title: ${subtitle}BASH3 Boilerplate – Template for writing better Bash scripts
|
|
||||||
warning: This page is generated by ${__base}.sh based on ${doc}.md, please don't edit ${targetName}.md directly.
|
|
||||||
---
|
|
||||||
EOF
|
|
||||||
# If '<!--more-->' exists, only inject what comes after it, so you can have e.g. a ToC or buildbuttons
|
|
||||||
# on GitHub, without that also rendering in the site (site may have its own ToC rendering for instance)
|
|
||||||
if grep '<!--more-->' "${doc}.md"; then
|
|
||||||
sed -n -e '/<!--more-->/,$p' "${doc}.md" | tail -n +2 >> "website/${targetName}.md"
|
|
||||||
else
|
|
||||||
cat "${doc}.md" >> "website/${targetName}.md"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Add a "<- Back Home" link, if any
|
|
||||||
echo -e $backLink >> "website/${targetName}.md"
|
|
||||||
|
|
||||||
echo "--> written website/${targetName}.md"
|
|
||||||
done
|
|
||||||
popd
|
|
@ -1,13 +0,0 @@
|
|||||||
require('./main.js')
|
|
||||||
require('./style.css')
|
|
||||||
require('./syntax.css')
|
|
||||||
|
|
||||||
// check if HMR is enabled
|
|
||||||
if (module.hot) {
|
|
||||||
module.hot.accept('./main.js', function () {
|
|
||||||
require('./main.js');
|
|
||||||
});
|
|
||||||
module.hot.accept('./style.css', function () {
|
|
||||||
require('./style.css');
|
|
||||||
});
|
|
||||||
}
|
|
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 563 KiB |
Before Width: | Height: | Size: 349 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 543 KiB |
Before Width: | Height: | Size: 345 KiB |
@ -1,55 +0,0 @@
|
|||||||
// Backgrounds.
|
|
||||||
// var backgrounds = [1,2,3,4,5,6]
|
|
||||||
var backgrounds = [1]
|
|
||||||
|
|
||||||
// Highlighting.
|
|
||||||
hljs.initHighlighting()
|
|
||||||
|
|
||||||
// Storage.
|
|
||||||
var store = window.sessionStorage
|
|
||||||
|
|
||||||
// Background.
|
|
||||||
var background = store.getItem('background')
|
|
||||||
|
|
||||||
if (!background) {
|
|
||||||
var i = Math.random() * backgrounds.length | 0
|
|
||||||
background = backgrounds[i]
|
|
||||||
console.log('setting background to %s', background)
|
|
||||||
store.setItem('background', background)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Body class for background.
|
|
||||||
var el = document.getElementById('header-overlay')
|
|
||||||
el.style.backgroundImage = 'url(/assets/images/' + background + '.jpg)'
|
|
||||||
|
|
||||||
// Attach class to #menu element depending on page offset.
|
|
||||||
document.addEventListener('DOMContentLoaded', chooseMenuColor)
|
|
||||||
window.onscroll = chooseMenuColor
|
|
||||||
|
|
||||||
function chooseMenuColor() {
|
|
||||||
var menuElement = document.getElementById('menu')
|
|
||||||
var menuTopOffset = 45
|
|
||||||
Math.floor(window.innerHeight * .20) < window.pageYOffset + menuTopOffset ?
|
|
||||||
menuElement.classList.remove('over-header') :
|
|
||||||
menuElement.classList.add('over-header')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function $get(selector) { return document.querySelector(selector) }
|
|
||||||
function $all(selector) {
|
|
||||||
return Array.prototype.slice.call(document.querySelectorAll(selector))
|
|
||||||
}
|
|
||||||
|
|
||||||
var container = $get('#menu-items')
|
|
||||||
|
|
||||||
// if (location.pathname !== '/') {
|
|
||||||
// var li = document.createElement('li');
|
|
||||||
// li.innerHTML = '<a href="/">« Home</a>';
|
|
||||||
// container.appendChild(li);
|
|
||||||
// }
|
|
||||||
|
|
||||||
$all('#content h2').forEach(function(el) {
|
|
||||||
var li = document.createElement('li');
|
|
||||||
li.innerHTML = '<a href="#' + el.id + '">' + el.innerHTML + '</a>';
|
|
||||||
container.appendChild(li);
|
|
||||||
})
|
|
@ -1,345 +0,0 @@
|
|||||||
|
|
||||||
body {
|
|
||||||
font: 16px/1.625 "Open Sans", "Helvetica Neue", "Helvetica", Arial, sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
color: #656a71;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header-overlay {
|
|
||||||
background: #131313 50% 100% no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
height: 20vh;
|
|
||||||
width: 100%;
|
|
||||||
opacity: 0;
|
|
||||||
-webkit-animation-name: overlay;
|
|
||||||
animation-name: overlay;
|
|
||||||
-webkit-animation-duration: 5s;
|
|
||||||
animation-duration: 5s;
|
|
||||||
-webkit-animation-delay: 1s;
|
|
||||||
animation-delay: 1s;
|
|
||||||
-webkit-animation-fill-mode: forwards;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes overlay {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: .25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes overlay {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: .25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body.background-1 #header-overlay {
|
|
||||||
background-image: url(images/1.jpg);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.background-4 #header-overlay {
|
|
||||||
background-image: url(images/1.jpg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#logo {
|
|
||||||
display: block;
|
|
||||||
background: url(images/b3bp-logo.png) center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: contain;
|
|
||||||
width: 180px;
|
|
||||||
height: 120px;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -100px;
|
|
||||||
margin-top: -60px;
|
|
||||||
-webkit-animation-name: logo;
|
|
||||||
animation-name: logo;
|
|
||||||
-webkit-animation-duration: 2s;
|
|
||||||
animation-duration: 2s;
|
|
||||||
-webkit-animation-fill-mode: forwards;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes logo {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes logo {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#more {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 10px;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -6px;
|
|
||||||
color: white;
|
|
||||||
opacity: 0;
|
|
||||||
-webkit-animation-name: move;
|
|
||||||
animation-name: move;
|
|
||||||
-webkit-animation-duration: 3s;
|
|
||||||
animation-duration: 3s;
|
|
||||||
-webkit-animation-delay: 3s;
|
|
||||||
animation-delay: 3s;
|
|
||||||
-webkit-animation-fill-mode: forwards;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
-webkit-animation-timing-function: cubic-bezier(0.86, 0, 0.07, 1);
|
|
||||||
animation-timing-function: cubic-bezier(0.86, 0, 0.07, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes move {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
bottom: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
opacity: 1;
|
|
||||||
bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
90% {
|
|
||||||
opacity: 1;
|
|
||||||
bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 0;
|
|
||||||
bottom: -10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes move {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
bottom: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
opacity: 1;
|
|
||||||
bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
90% {
|
|
||||||
opacity: 1;
|
|
||||||
bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 0;
|
|
||||||
bottom: -10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#content {
|
|
||||||
padding: 100px 0;
|
|
||||||
max-width: 650px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu {
|
|
||||||
position: fixed;
|
|
||||||
top: 35px;
|
|
||||||
right: 35px;
|
|
||||||
cursor: pointer;
|
|
||||||
background: transparent;
|
|
||||||
color: black;
|
|
||||||
padding: 7px;
|
|
||||||
border-radius: 1px;
|
|
||||||
line-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu.over-header {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu i {
|
|
||||||
font-size: 19px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu:hover #menu-items {
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu-items {
|
|
||||||
line-height: 1.7;
|
|
||||||
opacity: 0;
|
|
||||||
position: fixed;
|
|
||||||
visibility: hidden;
|
|
||||||
margin: 0;
|
|
||||||
padding: 20px;
|
|
||||||
font-size: 12px;
|
|
||||||
background: white;
|
|
||||||
color: #121212;
|
|
||||||
top: 67px;
|
|
||||||
right: 35px;
|
|
||||||
border-radius: 1px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu-items li a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu-items li {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu-items li a {
|
|
||||||
color: #4C4C4C;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, h2, h3, h4 {
|
|
||||||
font-weight: 600;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
color: #3b444f;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 { font-size: 2em; /* 2*16 = 32 */ }
|
|
||||||
h2 { font-size: 1.5em; /* 1.5*16 = 24 */ }
|
|
||||||
h3 { font-size: 1.17em; /* 1.17*16 = 18.72 */ }
|
|
||||||
h4 { font-size: 1em; /* 1*16 = 16 */ }
|
|
||||||
h5 { font-size: 0.83em; /* 0.83*16 = 13.28 */ }
|
|
||||||
h6 { font-size: 0.75em; /* 0.75*16 = 12 */ }
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
/*margin-top: 75px;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
h1::before {
|
|
||||||
/*display: block;
|
|
||||||
content: ' ';
|
|
||||||
border-top: 1px dotted #eee;
|
|
||||||
width: 35%;
|
|
||||||
margin: 0 auto 75px auto;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin-top: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p > code,
|
|
||||||
li > code {
|
|
||||||
border: 1px solid #eee;
|
|
||||||
padding: 2px 10px;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: .75rem;
|
|
||||||
color: #555;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
background: #131313;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #55A1E1;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1px;
|
|
||||||
border: none;
|
|
||||||
height: 1px;
|
|
||||||
/* Set the hr color */
|
|
||||||
color: gainsboro; /* old IE */
|
|
||||||
background-color: gainsboro; /* Modern Browsers */
|
|
||||||
}
|
|
||||||
|
|
||||||
.Social {
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.Social > * {
|
|
||||||
display: inline;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.on-the-githubs {
|
|
||||||
-webkit-margin-before: 1em;
|
|
||||||
-webkit-margin-after: 1em;
|
|
||||||
}
|
|
||||||
.on-the-githubs:after {
|
|
||||||
content: '';
|
|
||||||
display: table;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
.on-the-githubs > li {
|
|
||||||
list-style-type: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
/*height: 26px;*/
|
|
||||||
position: relative;
|
|
||||||
border-bottom: 1px solid rgba(gainsboro, 0.3);
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.on-the-githubs > li:after {
|
|
||||||
content: '';
|
|
||||||
display: table;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.on-the-githubs > li p {
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 16px;
|
|
||||||
margin: 0 2px;
|
|
||||||
padding: 0;
|
|
||||||
display: inline-block;
|
|
||||||
float: left;
|
|
||||||
overflow: hidden;
|
|
||||||
max-width: 80%;
|
|
||||||
}
|
|
||||||
.on-the-githubs > li abbr {
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 16px;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
float: left;
|
|
||||||
text-align: right;
|
|
||||||
/*display: none*/
|
|
||||||
}
|
|
||||||
.on-the-githubs > li a {
|
|
||||||
font-weight: normal;
|
|
||||||
/*text-decoration: underline;*/
|
|
||||||
}
|
|
||||||
.on-the-githubs > li img {
|
|
||||||
float: left;
|
|
||||||
margin: 0 2px 0 0;
|
|
||||||
border-radius: 10px;
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
|
|
||||||
pre {
|
|
||||||
border-top-color: #ddd;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: .75rem;
|
|
||||||
overflow-x: auto;
|
|
||||||
line-height: 1.3;
|
|
||||||
padding: 1.5rem;
|
|
||||||
background: #fff;
|
|
||||||
color: #333;
|
|
||||||
overflow-x: auto;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
border-bottom-color: #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
XCode style (c) Angel Garcia <angelgarcia.mail@gmail.com>
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
.hljs {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-comment,
|
|
||||||
.hljs-quote {
|
|
||||||
color: #006a00;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-keyword,
|
|
||||||
.hljs-selector-tag,
|
|
||||||
.hljs-literal {
|
|
||||||
color: #aa0d91;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-name {
|
|
||||||
color: #008;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-variable,
|
|
||||||
.hljs-template-variable {
|
|
||||||
color: #660;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-string {
|
|
||||||
color: #c41a16;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-regexp,
|
|
||||||
.hljs-link {
|
|
||||||
color: #080;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-title,
|
|
||||||
.hljs-tag,
|
|
||||||
.hljs-symbol,
|
|
||||||
.hljs-bullet,
|
|
||||||
.hljs-number,
|
|
||||||
.hljs-meta {
|
|
||||||
color: #1c00cf;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-section,
|
|
||||||
.hljs-class .hljs-title,
|
|
||||||
.hljs-type,
|
|
||||||
.hljs-attr,
|
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-builtin-name,
|
|
||||||
.hljs-params {
|
|
||||||
color: #5c2699;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-attribute,
|
|
||||||
.hljs-subst {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-formula {
|
|
||||||
background-color: #eee;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-addition {
|
|
||||||
background-color: #baeeba;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-deletion {
|
|
||||||
background-color: #ffc8bd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-selector-id,
|
|
||||||
.hljs-selector-class {
|
|
||||||
color: #9b703f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-doctag,
|
|
||||||
.hljs-strong {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-emphasis {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|