DEV Community

Cover image for Dotfiles - Shell Config
Michael Currin
Michael Currin

Posted on

Dotfiles - Shell Config

Content for Bash config ~/.bashrc or ZSH config ~/.zshrc

See my full Shell config file on GitHub.

OS flags

For any values in configs or aliases which are OS-specific, I found it useful to determine the OS with logic once-off and then reuse the flags.

IS_MAC=false
IS_LINUX=false

case "$(uname -s)" in
  Darwin*)
    IS_MAC=true
    ;;
  Linux*)
    IS_LINUX=true
    ;;
esac
Enter fullscreen mode Exit fullscreen mode

That lets me then use the variable to perform OS-specific behavior. Here I add a Brew-installed Ruby gems path to the PATH value, just for macOS.

if [[ "$IS_MAC" == 'true' ]]; then
  export PATH="/usr/local/opt/ruby/bin:$PATH"
fi
Enter fullscreen mode Exit fullscreen mode

Setting PATH the smart way

Part of the standard setup of packages like Ruby, Go and Node is to add a directory to your shell PATH variable so that executables can be found.

If I want to check the directory exists first, I could do this:

if [ -d '/usr/local/opt/ruby/bin' ];
  export PATH="/usr/local/opt/ruby/bin:$PATH"
fi
Enter fullscreen mode Exit fullscreen mode

But I got tired of having that long syntax. So I made a function to do that, which I call like this:

prepend_path() {
  if [ -d "$1" ]; then
    export PATH="$1:$PATH"
  fi
}
Enter fullscreen mode Exit fullscreen mode

Usage:

# Ruby gems
prepend_path /usr/local/opt/ruby/bin

# Go packages.
# Traditional path is '/usr/local/go/bin' or '/usr/bin'.
# I created ~/.local to use that rather.
prepend_path ~/.local/go/bin
Enter fullscreen mode Exit fullscreen mode

Executing local packages

When working on Node projects, you normally have to run a script like this in the shell:

$ ./node_modules/.bin/eslint
Enter fullscreen mode Exit fullscreen mode

I'd rather just run this:

$ eslint
Enter fullscreen mode Exit fullscreen mode

To get that behavior, I decided to add ./node_modules/.bin to my PATH variable.

prepend_path_always() {
  export PATH="$1:$PATH"
}

prepend_path_always './node_modules/.bin'
Enter fullscreen mode Exit fullscreen mode

Note that the values in PATH are read from left to right, so you must make sure your local packages are read before any global packages. In case you have say eslint installed locally and globally.

View the PATH

Here is what my PATH value looks like.

$ split_path
/home/michael/.local/go/bin
/home/michael/.deno/bin
./node_modules/.bin
/home/michael/.local/bin
...
Enter fullscreen mode Exit fullscreen mode

Note that the PATH value normally looks like this with colon separators, making it hard to read.

/home/michael/.local/go/bin:/home/michael/.deno/bin:...
Enter fullscreen mode Exit fullscreen mode

So I created an alias called split_path which makes that more human-readable.

More about aliases in the next post in this series...

Top comments (7)

Collapse
 
rhamdeew profile image
Rail

Thank you, interesting post!

But I think it is better to run the binary from node_modules like this:

npx run eslint
Enter fullscreen mode Exit fullscreen mode
Collapse
 
michaelcurrin profile image
Michael Currin

Thanks for the tip. Npx is nice for scaffolding create apps but I didn't know it works for local packages.

According to this post I can just do a command without run.

blog.scottlogic.com/2018/04/05/npx...

npx eslint

Do you know if it respects the arguments?
Like if I wanted to run

eslint .
# OR
eslint --help

Can I do that with npx? Like

npx eslint --help
Collapse
 
rhamdeew profile image
Rail

Yes, you can)

Example:

run hexo version

npx hexo version
➜ npx hexo version
(node:90786) [DEP0061] DeprecationWarning: fs.SyncWriteStream is deprecated.
hexo: 3.9.0
hexo-cli: 2.0.0
os: Darwin 19.5.0 darwin x64
http_parser: 2.8.0
node: 10.16.3
v8: 6.8.275.32-node.54
uv: 1.28.0
zlib: 1.2.11
brotli: 1.0.7
ares: 1.15.0
modules: 64
nghttp2: 1.39.2
napi: 4
openssl: 1.1.1c
icu: 64.2
unicode: 12.1
cldr: 35.1
tz: 2019a

run hexo version --debug

npx hexo version --debug
➜ npx hexo version --debug
08:32:18.567 DEBUG Writing database to /Users/rail/Work/blogs/hmdwme_hexo/db.json
08:32:18.577 DEBUG Hexo version: 3.9.0
08:32:18.577 DEBUG Working directory: ~/Work/blogs/hmdwme_hexo/
08:32:18.626 DEBUG Config loaded: ~/Work/blogs/hmdwme_hexo/_config.yml
08:32:18.638 DEBUG Plugin loaded: hexo-all-minifier
08:32:18.639 DEBUG Plugin loaded: hexo-generator-archive
08:32:18.640 DEBUG Plugin loaded: hexo-generator-category
08:32:18.643 DEBUG Plugin loaded: hexo-generator-feed
08:32:18.644 DEBUG Plugin loaded: hexo-generator-index
08:32:18.645 DEBUG Plugin loaded: hexo-generator-sitemap
08:32:18.646 DEBUG Plugin loaded: hexo-generator-tag
08:32:18.647 DEBUG Plugin loaded: hexo-renderer-ejs
08:32:18.651 DEBUG Plugin loaded: hexo-renderer-marked
08:32:18.719 DEBUG Plugin loaded: hexo-renderer-stylus
08:32:18.754 DEBUG Plugin loaded: hexo-server
08:32:18.826 DEBUG Plugin loaded: hexo-deployer-git
(node:90673) [DEP0061] DeprecationWarning: fs.SyncWriteStream is deprecated.
08:32:18.839 DEBUG Script loaded: themes/hmdw/scripts/fancybox.js
hexo: 3.9.0
hexo-cli: 2.0.0
os: Darwin 19.5.0 darwin x64
http_parser: 2.8.0
node: 10.16.3
v8: 6.8.275.32-node.54
uv: 1.28.0
zlib: 1.2.11
brotli: 1.0.7
ares: 1.15.0
modules: 64
nghttp2: 1.39.2
napi: 4
openssl: 1.1.1c
icu: 64.2
unicode: 12.1
cldr: 35.1
tz: 2019a
08:32:18.842 DEBUG Database saved
Thread Thread
 
michaelcurrin profile image
Michael Currin

Thanks

Collapse
 
michaelcurrin profile image
Michael Currin

Also my alias approach only works from the root. Does npx run from git root when run from anywhere?

Thread Thread
 
rhamdeew profile image
Rail • Edited

I tried different options to learn how it works.

package.json located in /srv/projects/awesome-project/frontend/web/

gulp located in /srv/projects/awesome-project/frontend/web/node_modules/gulp/bin/

Run npx gulp --tasks

1) on /srv/projects/awesome-project/frontend/web/

[08:38:32] Tasks for /srv/projects/awesome-project/frontend/web/gulpfile.js
[08:38:32] ├── js
[08:38:32] ├── css
[08:38:32] └─┬ build
[08:38:32]   └─┬ <parallel>
[08:38:32]     ├── js
[08:38:32]     └── css

2) on /srv/projects/awesome-project/frontend

Of course it doesn't work.

[08:38:36] Local gulp not found in /srv/projects/awesome-project/frontend
[08:38:36] Try running: npm install gulp

3) on /srv/projects/awesome-project/frontend/web/js

[08:38:49] Working directory changed to /srv/projects/awesome-project/frontend/web
[08:38:52] Tasks for /srv/projects/awesome-project/frontend/web/gulpfile.js
[08:38:52] ├── js
[08:38:52] ├── css
[08:38:52] └─┬ build
[08:38:52]   └─┬ <parallel>
[08:38:52]     ├── js
[08:38:52]     └── css

4) on /srv/projects/awesome-project/frontend/web/js/dist

[08:39:07] Working directory changed to /srv/projects/awesome-project/frontend/web
[08:39:10] Tasks for /srv/projects/awesome-project/frontend/web/gulpfile.js
[08:39:10] ├── js
[08:39:10] ├── css
[08:39:10] └─┬ build
[08:39:10]   └─┬ <parallel>
[08:39:10]     ├── js
[08:39:10]     └── css

Result - npx searches for the node_modules directory in the parent directories and tries to run the binary from there.

Thread Thread
 
michaelcurrin profile image
Michael Currin

Neat