Skip to content

Commit

Permalink
create powershell bookmark system
Browse files Browse the repository at this point in the history
  • Loading branch information
rick3rt committed Dec 3, 2023
0 parents commit 47f4f22
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 0 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# psmarks
bashmarks inspired folder bookmark system for Powershell, with tab
autocompletion of known bookmarks

## Aliases
```
s <bookmark_name> - Saves the current directory as "bookmark_name"
g <bookmark_name> - Goes (cd) to the directory associated with "bookmark_name"
d <bookmark_name> - Deletes the bookmark
l - Lists all available bookmarks
```

## Full Commands
```powershell
Add-PSMark <bookmark_name> # add a bookmark
Remove-PSMark <bookmark_name> # remove a bookmark
Get-PSMarks # list all bookmarks
Open-PSMark # resolve a bookmark
```


## Credits
- https://github.com/stadub/PowershellScripts/tree/master/Bookmarks
- https://github.com/huyng/bashmarks
207 changes: 207 additions & 0 deletions psmarks.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
function _PSMarks_Initalize() {
$script:_marksPath = Get-ProfileDataFile bookmarks "PSMarks"
$script:_knownBookmarks = Import-PSMarkKeys
}

function Get-ProfileDataFile {
param (
[string]$file,
[string]$moduleName = $null
)
return Join-Path (Get-ProfileDir $moduleName) $file

}

function Get-ProfileDir {
param (
[string]$moduleName = $null,
[string]$profileFolder = $null
)

$profileDir = $ENV:AppData

if ( Test-Empty $moduleName ) {

if ( $script:MyInvocation.MyCommand.Name.EndsWith('.psm1') ) {
$moduleName = $script:MyInvocation.MyCommand.Name
}

if ( $script:MyInvocation.MyCommand.Name.EndsWith('.ps1') ) {
$modulePath = Split-Path -Path $script:MyInvocation.MyCommand.Path
$moduleName = Split-Path -Path $modulePath -Leaf
}
}

if ( Test-Empty $moduleName ) {
throw "Unable to read module name."
}

$scriptProfile = Merge-Path $profileDir '.ps1' 'ScriptData' $moduleName

if ( Test-Empty $profileFolder) {
$scriptProfile = Merge-Path $profileDir '.ps1' 'ScriptData' $moduleName $profileFolder

}
if ( ! (Test-Path $scriptProfile -PathType Container )) {
New-Item -Path $scriptProfile -ItemType 'Directory'
}

return $scriptProfile
}


function Test-Empty {
param (
[Parameter(Position = 0)]
[string]$string
)
return [string]::IsNullOrWhitespace($string)
}

function Merge-Path {
param (
[string]$baseDir,
[string]$path
)
$allArgs = $PsBoundParameters.Values + $args

[IO.Path]::Combine([string[]]$allArgs)
}
# ==============================================================================

function Import-PSMarks {
$_marks = @{ }
if (test-path "$script:_marksPath" -PathType leaf) {
Import-Csv $script:_marksPath | ForEach-Object { $_marks[$_.key] = $_.value }
}
return $_marks

}

function Import-PSMarkKeys {
$_marks = Import-PSMarks
# get only keys from marks
# Write-Output $_marks
# Write-Output $_marks.GetType()
return $_marks.Keys
}

function Save-PSMarks {
param (
$marks
)
$marks.getenumerator() | export-csv "$_marksPath" -notype
}


function Add-PSMark () {
Param (
[Parameter(Position = 0, Mandatory = $true)]
[Alias("Bookmark")]
$BookmarkName,
[Parameter(Position = 1, ValueFromPipeline = $True)]
[Alias("Path")]
[string]$dir = $null
)

$dir = (Get-Location).Path # get current dir
$_marks = Import-PSMarks

if ( $_marks.ContainsKey("$BookmarkName") ) {
Write-Output( "Folder bookmark ''$BookmarkName'' already exist")
return
}

$_marks["$BookmarkName"] = $dir
Save-PSMarks $_marks
Write-Output ("Location '{1}' saved to bookmark '{0}'" -f $BookmarkName, $dir)
}


function Remove-PSMark () {
Param (
[Parameter(Position = 0, Mandatory = $true)]
[Alias("Bookmark")]
[ArgumentCompleter(
{
param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)
return @($_marks) -like "$WordToComplete*"
}
)]
$BookmarkName
)

$_marks = Import-PSMarks

$_marks.Remove($BookmarkName)
Save-PSMarks $_marks
Write-Output ("Location '{0}' removed from bookmarks" -f $BookmarkName)
}


# List all available psmarks
function Get-PSMarks {
$_marks = Import-PSMarks
# $_marks.Clone()
$_marks | Format-Table -AutoSize
}

function Open-PSMark {
Param(
[Parameter(Position = 0, ValueFromPipelineByPropertyName = $True, Mandatory = $true)]
[Alias("Bookmark")]
[ArgumentCompleter(
{
param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)
return @($_marks) -like "$WordToComplete*"
}
)]
$BookmarkName
)
$_marks = Import-PSMarks
Set-Location $_marks["$BookmarkName"]
}


# autocompletion with tab
Register-ArgumentCompleter -CommandName 'Open-PSMark' -ParameterName 'BookmarkName' -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)


if ($wordToComplete) {
# Filter options matching the entered text
$filteredOptions = $Script:_knownBookmarks -like "$wordToComplete*"
$filteredOptions
}
else {
# Display all options if no text is entered
$Script:_knownBookmarks
}
}

Register-ArgumentCompleter -CommandName 'Remove-PSMark' -ParameterName 'BookmarkName' -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)


if ($wordToComplete) {
# Filter options matching the entered text
$filteredOptions = $Script:_knownBookmarks -like "$wordToComplete*"
$filteredOptions
}
else {
# Display all options if no text is entered
$Script:_knownBookmarks
}
}


# ==============================================================================
# initialize bookmark file location
_PSMarks_Initalize

# ==============================================================================
# Aliases
Set-Alias l Get-PSMarks -Scope Global
Set-Alias g Open-PSMark -Scope Global
Set-Alias s Add-PSMark -Scope Global
Set-Alias d Remove-PSMark -Scope Global

0 comments on commit 47f4f22

Please sign in to comment.