Skip to main content

Interactive bookmarks menu v2

· 4 min read
Carlos Angulo Mascarell
Senior Platform Engineer

In this post, I am going to improve the interactive bookmark I created in a previous post.

Requirements

Improvements introduced

  1. Add one directory layer
  2. 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 nameRepository
cangulo-actionscangulo.nuke.prcommitsvalidations
cangulo-actionscangulo.nuke.releasecreator
cangulo-actionsworkflows
cangulo-nugetscangulo.changelog
cangulo-nugetscangulo.changelog.github.io
cangulo-nugetscangulo.common.testing
old-projectscangulo.build
old-projectscangulo.cicd
old-projectscangulo.cicd-gh-action
tempsany 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

goal

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:

  1. 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

  1. 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 |
  1. 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' |

jq-updated

Problem: columns are not aligned (see oldprojects row)

  1. In order to align the jq output before piping it to fzf, I use the column -t command. Reference
cat $BOOKMARKS_FILE |
jq -r '["NAME", "PATH"], (.[] |
[.name,.path]) |
@tsv' |
column -t |
fzf --tac

column

  1. Once a bookmark is selected, the full row is returned. I

fzf_return_full_row

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.

trim-selection

  1. I have created the function lsf to list the current directories using fzf, navigate to the one selected and execute a command provided as first parameter $1. In our case code.
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:

  1. Define your bookmarks in a json file following the name,path model
  2. In your profile, append its path in the $BOOKMARKS_FILE variable
  3. Append the functions listBookmarks and lsf.
  4. 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.

lsf_faster_navigation

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 Senior Platform Engineer. I build and evolve Internal Developer Platforms — golden paths, self-service tooling, and paved roads spanning AWS governance, CI/CD standardization, and developer enablement — so engineering teams ship faster, safer, and more autonomously, with less cognitive load. My core stack is AWS, Terraform, and GitHub Actions, and I'm an AWS Certified Solutions Architect. I care deeply about paved roads, productivity, and documenting implementations so knowledge scales with the team (yes, I'm an engineer who likes to document 🧑‍💻).

You can check my experience here.

Personal Blog - cangulo.github.io GitHub - Carlos Angulo Mascarell - cangulo
LinkedIn - Carlos Angulo Mascarell

Did you like it? Share It!


Comments