Make your cool commands in terminal
Tags: bash, terminal, shell
Published: 2023-05-25 07:23:35

Hi guys,
I wanna teach you how to make cool things in your terminal and increase your productivity like a pro.

> You don't need any docker, k8s, Openshift or Golang experience for this article, we just used them as examples but you'll get the point in other cases too.

## TL;DR
Open your shell config file (e.g. `~/.zshrc` in Mac)
Write aliases commands like this `alias mycmd="cmd long long long"`

and functions like this:
```bash
mf() {
    mkdir $1 
    cd $1
    touch $2
}
```
And call it in terminal like this: `mf mydir myfile` and it will make a directory named `mydir` and file within it named `myfile`

---

## The story behind this article

As a developer, you may work with CLIs a lot, CLIs are made to be general and composable, but in some specific cases, you may want to compose them as you wish once forever!

For example, I need some specific compositions of `oc` command for everyday use.

Also, I needed 2 different VPN connections using 2 different clients, they had long commands!

Sometimes they are long, sometimes they are hard to remember, etc.

## Define aliases
There is an `alias` command available on *nix systems (Linux, Unix, MacOS, etc)

It's an alternative command which you can use to make your commands shorter.

In my case, I wanted to connect to a VPN with openfortivpn client like this:
```
sudo openfortivpn vpn.host.domain:port -u myusername -p mypassword --trusted-cert averyveryveryverylonghash
```
And another VPN using openconnect client:
```
sudo openconnect -u myusername -p mypassword vpn.host.domain:port
```

In addition to that, every company or personal project that I worked for, I used `docker-compose up --build -d` command, what does it do? doesn't matter!

For this article, we just know that these commands are the same most of the time and typing them out is cumbersome.

Long story short, shorten these commands like this:
```
alias mycmd="my very very long command"
```
But it's not permanent, it's limited to the current shell tab, to make it live forever in your system, open your shell config and write your aliases in it.

So according to this, in my system (MacOS), I followed these steps:
- Step 1: run `code ~/.zshrc` (`code` opens up VScode editor, but you can use something else such as vim or nano)
- Step 2: write this command inside the opened file and save it:
```
alias dub="docker-compose up --build -d`
```
- Step 3: you are done! open up **a new shell** and use `dub` command and it works totally the same.

And about VPNs:
```
alias ofv="sudo openfortivpn vpn.host.domain:port -u myusername -p mypassword --trusted-cert averyveryveryverylonghash"

alias opc="sudo openconnect -u myusername -p mypassword vpn.host.domain:port"
```

Another alias I defined:
```
alias ocp="oc port-forward"
```

## Define functions
Sometimes, you need to define more than one command or you need to have some placeholders in your commands to keep those parts still general purpose.

Let's say, sometimes you need some functions to do different operations and accept some inputs

### Some examples
When I want to instantiate a new Golang project, I should run these commands:
```
mkdir <my_project_name> 
cd <my_project_name>
touch main.go
go mod init <my_project_name>
```

The rest might be different but these four commands are always the same.

I also have better solutions for this part of the article, but they are not in the context of this article and it's just an example.

So, to simply those four commands and make them one, write a function like below:
```
gomake() {
    mkdir $1 
    cd $1
    touch main.go
    go mod init $1
}
```

I called this function `gomake` and I can easily access it in my shell using `gomake <my_project_name>` and it will do that 4 commands.

`$1` is a function argument, if you need more, you can access them by $2, $3, ...

Note: you can use `echo "package main\n\nfunc main() {\n\t\n}" | cat > main.go` instead of `touch main.go` in Golang projects, this command simply make `main.go` file and write
```go
package main

func main() {

}
```
in it.


Another example, using `oce <pod-name>` instead of `oc exec <pod-name> -it -- sh`
```
oce() {
    oc exec $1 -it -- sh
}
```

Another example with 2 arguments,
Sometimes I want to see the structure and some cool information about the projects (e.g. number of lines of code)
For this case, I know two commands:

`tree` command, which is a tool to show directory structure of your projects, and it's pre-installed or you may install it using `brew install tree` in mac.

`cocnt` which is a tool to count the number of lines of code, link to their github repo: https://github.com/InnoFang/code-counter

And I always forget the second! 😂 (what was it's command?)

So for helping myself remembering the second command and first command flags, I wrote this functions and named it `struct`

```
struct() {
    tree $1 -dCL $2 -I vendor
    cocnt search $1
}
```

About tree flags, `I` is used for excluding a folder (vendor in my case), `d` to show only directories, `L` for level of going inside (which we get as an argument), `C` for colorizing the output.

So I call `struct <project-path> 2` and it will print out the project with level two of directories without vendor folder.

### Just if you are wondering (Used terms)

`oc` is command used for working with Openshift clusters.

Openshift is a platform made on top of Kubernetes for container orchestrations.

Docker is a platform designed to help developers build, share, and run modern applications.

To learn more about bash functions:
https://devqa.io/create-call-bash-functions/


## Conclusion
These aliases and functions are still useful beside all modern terminal tools such as fish or warp, etc.

In addition to that, sometimes I write my own CLI tools or I use existing ones,

In case of making a project (Golang in this article), templates are so useful and good alternative.

Possibilities are endless...

Finally, I hope you enjoyed reading this article and learned something useful.