In this post, I am going to improve the interactive bookmark I created in a previous post.
Requirements
- Linux (I'm using Elementary OS, a Ubuntu-based distro, try it!)
- fzf command-line fuzzy finder
- Remember to add execution permissions to the scripts through
chmod +x
- This article improves the interactive bookmark menu implemented in the previous post: Create an interactive bookmarks menu in your terminal
Improvements introduced
- Add one directory layer
- Open VS Code in the repository
Add one directory layer
I have a global path for all the repositories I clone locally, it is /home/cangulo/repos
. As I have a lot, I grouped them into folders per organization or custom name.
Organization/ custom name | Repository |
---|---|
cangulo-actions | cangulo.nuke.prcommitsvalidations |
cangulo-actions | cangulo.nuke.releasecreator |
cangulo-actions | workflows |
cangulo-nugets | cangulo.changelog |
cangulo-nugets | cangulo.changelog.github.io |
cangulo-nugets | cangulo.common.testing |
old-projects | cangulo.build |
old-projects | cangulo.cicd |
old-projects | cangulo.cicd-gh-action |
temps | any temporary repository |
The organization / custom name will be the first layer, while the repositories are the second one. Next is the folder structure:
โโโ cangulo-actions
โย ย โโโ cangulo.nuke.prcommitsvalidations
โย ย โโโ cangulo.nuke.releasecreator
โย ย โโโ workflows
โโโ cangulo-nugets
โย ย โโโ cangulo.changelog
โย ย โโโ cangulo.changelog.github.io
โย ย โโโ cangulo.common.testing
โโโ old-projects
โย ย โโโ cangulo.build
โย ย โโโ cangulo.cicd
โย ย โโโ cangulo.cicd-gh-action
โโโ temp
โโโ dotnet-docker
โโโ gsd
Open VS Code in the repository
Once I choose a repository, I would like to open it using VS Code.
Demo
Implementation
listBookmarks() {
local selectedBookmark=$(
cat $BOOKMARKS_FILE |
jq -r '["NAME", "PATH"], (.[] |
[.name,.path]) |
@tsv' |
column -t |
fzf --tac
)
if [[ -n $selectedBookmark ]]; then
local bookmarkPath=$(
echo $selectedBookmark |
tr -s ' ' |
cut -f2 -d ' '
)
cd $bookmarkPath
lsf "code"
else
cd $LOCAL_REPOS
fi
}
export listBookmarks
lsf() {
local command=$1
local chosenDir=$(ls | fzf)
if [[ -n $chosenDir ]]; then
cd $chosenDir
if [[ -n $command ]]; then
eval "\$command ."
fi
fi
}
export lsf
listBookmarks function
Let me write down the changes introduced:
- Bookmarks now have two properties: name and path.
{
"name": "Actions",
"path": "/home/cangulo/repos/cangulo-actions"
},
- name: string to identify the organization / custom name folder. Without spaces. e.g. for cangulo-actions -> Actions
- path: full path to first layer directories mentioned before.
Full Bookmark file
[
{
"name": "Actions",
"path": "/home/cangulo/repos/cangulo-actions"
},
{
"name": "Nugets",
"path": "/home/cangulo/repos/cangulo-nugets"
},
{
"name": "oldprojects",
"path": "/home/cangulo/repos/old-projects"
},
{
"name": "temp",
"path": "/home/cangulo/repos/temp"
}
]
bookmarks
- The path to the bookmarks file is set in the environment variable
$BOOKMARKS_FILE
. We don't have it hardcoded in the function.
cat $BOOKMARKS_FILE |
- I now use
jq
to query both attributes(.[] | [.name,.path])
and output them in the columns["NAME", "PATH"]
as a tab-separated-value@tsv
:
cat $BOOKMARKS_FILE |
jq -r '["NAME", "PATH"], (.[] |
[.name,.path]) |
@tsv' |
Problem: columns are not aligned (see oldprojects row)
- In order to align the
jq
output before piping it tofzf
, I use thecolumn -t
command. Reference
cat $BOOKMARKS_FILE |
jq -r '["NAME", "PATH"], (.[] |
[.name,.path]) |
@tsv' |
column -t |
fzf --tac
- Once a bookmark is selected, the full row is returned. I
Then, I have to extract the path. First, I delete the repeated spaces (tr -s ' '
). Secondly, I choose the second column(cut -f2 -d ' '
). The -d ' '
parameter is to set columns delimiter to a whitespace.
- I have created the function
lsf
to list the current directories usingfzf
, navigate to the one selected and execute a command provided as first parameter$1
. In our casecode
.
lsf() {
local command=$1
local chosenDir=$(ls | fzf)
if [[ -n $chosenDir ]]; then
cd $chosenDir
if [[ -n $command ]]; then
eval "\$command ."
fi
fi
}
Please note the eval "\$command ."
statement for executing the command provided.
Adding this to your Terminal Profile
You can add this into your Bash / Zsh profile. You can follow the next steps:
- Define your bookmarks in a json file following the name,path model
- In your profile, append its path in the
$BOOKMARKS_FILE
variable - Append the functions
listBookmarks
andlsf
. - Append a call to the
listBookmarks
function at the end of the profile, so every time you open a terminal it execute it.
lsf function
I just want to mention you can use the lsf
function separately to make navigation through directories faster. Also, remember it accepts as a parameter a command to execute in the directory selected. Give it a try and add import it in your profile.
Final Notes
Do you see any other improvement to include? What commands would you provide when using lsf
? Share them in the comments below.
About me
I'm a Software Engineer with experience as Developer and DevOps. The technologies I have worked with are DotNet, Terraform and AWS. For the last one, I have the Developer Associate certification. I define myself as a challenge-seeker person and team player. I simply give it all to deliver high-quality solutions. On the other hand, I like to analyze and improve processes, promote productivity and document implementations (yes, I'm a developer that likes to document ๐งโ๐ป).
You can check my experience here.
Personal Blog - cangulo.github.io
GitHub - Carlos Angulo Mascarell - cangulo
LinkedIn - Carlos Angulo Mascarell
Twitter - @AnguloMascarell