Problem
Have you ever wanted to search for GIFs from the terminal?
Perhaps it's just me, but I do a lot in the terminal, from writing code and debugging programs to searching and browsing the web (via ddgr
+ !bangs).
When I am reviewing Pull Requests (via gh
or glab
), I often like to post a funny GIF as a comment when I'm approving the PR (hopefully to leave the collaborator with a smile).
Initially, I did this by going to a site, like giphy.com, then searching for a GIF, then several clicks later, I got a GIF URL that I can copy/paste into the terminal. This obviously broke my workflow.
Solution
The second iteration of this used ddgr
, a command-line interface for DuckDuckGo. Using the !gif
or !giphy
bang (e.g. ddgr --no-prompt '!gif yay'
) did save me a few steps as it takes me right to Giphy's search results where I can get a GIF URL with a few clicks. However, because this still requires a browser, it doesn't work for all the times I work on remote development servers (e.g. GCP Always Free Compute Engine, Raspberry Pi ...etc).
I needed a different solution that was completely in the terminal.
I couldn't find a dependency-free* CLI utility that really suit my needs. So, I decided to write a dependency-free CLI utility that allows you to search for GIFs from giphy.com and return a URL.
And it fits in a tweet.
Here it is:
$ giphy() { [ -z "${1}" ] && return 1 || curl -fsSL https://giphy.com/search/${1} | rg -oP "(?<=gifs: ).*?(?=,$)" | jq ".[$(echo $(( $RANDOM % 25 )) )] | .images.original.url" | tr -d '"'; };
Let's break it down:
-
[ -z "${1}" ] && return 1 || ...
: this is kind of a ternary operation in Bash. If the 1st argument is empty, then return non-zero exit code, otherwise ... -
curl -fsSL https://giphy.com/search/${1}
: this is pretty straight-forward. We usecurl
to query the site. -
rg -oP "(?<=gifs: ).*?(?=,$)"
: this uses Positive Lookbehind (?<=...
) and Positive Lookahead (?=...
) Regular Expressions (see this for more info) to match the text that is betweengifs:
and,
at the end of the same line in the HTML response. This is where we have a JSON list of 25 GIFs from the 1st results page. -
jq ".[$(echo $(( $RANDOM % 25 )) )] | .images.original.url"
: here we usejq ".[] | .images.original.url"
to parse the JSON list and get at the URL we need. The$(echo $(( $RANDOM % 25 )) )
is a Bash way of picking a random number between 0 and 25. Another way we could do this isshuf -i 0-25 -n 1
(seeshuf
manual pages for more info). -
tr -d '"'
: finally, we trim the double-quotes from the URL.
That's it. Now, we can compose this utility with other tools to spread smiles, like $ gh pr review --approve --comment -b "![yay]($(giphy yay))"
Conclusion
This is why I love the terminal. It gives me the freedom and flexibility to creatively solve a problem and re-use it in composable ways. Check out this blog post for additional reading on the merits of CLIs.
I am, by no means, a Bash or Regular Expressions expert and I am sure there are many opportunities for improvement here. So, feel free to leave your ideas, thoughts, suggestions for improvements, or GIFs in the comments section below!
Also, contributions are welcome on the GitHub repo: https://github.com/pbnj/giphy-cli
Happy coding!
Footnotes
* My Bash one-liner is not 100% dependency-free. It requires curl
, rg
for a consistent grep utility between macOS & Linux, & jq
for command-line JSON parsing. Most GIF CLI utilities I found required system dependencies and entire development toolchains (e.g. ffmpeg
, python3
, dotnet
, ...etc).
Top comments (0)