Skip to main content

Interactive bookmarks menu v2

ยท 4 min read
Carlos Angulo Mascarell

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

Did you like it? Share It!


Comments