[
  {
    "path": ".gitattributes",
    "content": "# Set default behaviour, in case users don't have core.autocrlf set.\n* text=auto\n\n# Explicitly declare text files we want to always be normalized and converted\n# to native line endings on checkout.\n*.md            text\n*.gitattributes text\n\n# Declare files that will always have CRLF line endings on checkout.\n*.ps1    text  eol=crlf\n*.psm1   text  eol=crlf\n*.psd1   text  eol=crlf\n*.psc1   text  eol=crlf\n*.ps1xml text  eol=crlf\n*.clixml text  eol=crlf\n*.xml    text  eol=crlf\n*.txt    text  eol=crlf\n\n# Denote all files that are truly binary and should not be mergeable.\n*.dll binary\n*.exe binary"
  },
  {
    "path": ".gitignore",
    "content": "z\npublish.ps1\n"
  },
  {
    "path": "FUNDING.yml",
    "content": "ko_fi: badmotorfinger\n\n"
  },
  {
    "path": "LICENSE",
    "content": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <https://unlicense.org>\n"
  },
  {
    "path": "Makefile",
    "content": "readme:\n\t@groff -man -Tascii z.1 | col -bx\n\n.PHONY: readme\n"
  },
  {
    "path": "README",
    "content": "qweqwe\nZ(1)                             User Commands                            Z(1)\n\n\n\nNAME\n       z - jump around\n\nSYNOPSIS\n       z [-chlrtx] [regex1 regex2 ... regexn]\n\nAVAILABILITY\n       bash, zsh\n\nDESCRIPTION\n       Tracks your most used directories, based on 'frecency'.\n\n       After  a  short  learning  phase, z will take you to the most 'frecent'\n       directory that matches ALL of the regexes given on the command line.\n\nOPTIONS\n       -c     restrict matches to subdirectories of the current directory\n\n       -h     show a brief help message\n\n       -l     list only\n\n       -r     match by rank only\n\n       -t     match by recent access only\n\n       -x     remove the current directory from the datafile\n\nEXAMPLES\n       z foo         cd to most frecent dir matching foo\n\n       z foo bar     cd to most frecent dir matching foo and bar\n\n       z -r foo      cd to highest ranked dir matching foo\n\n       z -t foo      cd to most recently accessed dir matching foo\n\n       z -l foo      list all dirs matching foo (by frecency)\n\nNOTES\n   Installation:\n       Put something like this in your $HOME/.bashrc or $HOME/.zshrc:\n\n              . /path/to/z.sh\n\n       cd around for a while to build up the db.\n\n       PROFIT!!\n\n       Optionally:\n              Set $_Z_CMD to change the command name (default z).\n              Set $_Z_DATA to change the datafile (default $HOME/.z).\n              Set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.\n              Set $_Z_NO_PROMPT_COMMAND to handle PROMPT_COMMAND/precmd  your-\n              self.\n              Set $_Z_EXCLUDE_DIRS to an array of directories to exclude.\n              (These  settings  should  go  in .bashrc/.zshrc before the lines\n              added above.)\n              Install   the   provided   man   page   z.1    somewhere    like\n              /usr/local/man/man1.\n\n   Aging:\n       The rank of directories maintained by z undergoes aging based on a sim-\n       ple formula. The rank of each entry is incremented  every  time  it  is\n       accessed.  When  the  sum  of ranks is greater than 6000, all ranks are\n       multiplied by 0.99. Entries with a rank lower than 1 are forgotten.\n\n   Frecency:\n       Frecency is a portmanteau of 'recent' and 'frequency'. It is a weighted\n       rank  that  depends on how often and how recently something occurred. As\n       far as I know, Mozilla came up with the term.\n\n       To z, a directory that has low ranking but has been  accessed  recently\n       will  quickly  have  higher rank than a directory accessed frequently a\n       long time ago.\n\n       Frecency is determined at runtime.\n\n   Common:\n       When multiple directories match all queries, and they all have a common\n       prefix, z will cd to the shortest matching directory, without regard to\n       priority.  This has been in effect, if  undocumented,  for  quite  some\n       time, but should probably be configurable or reconsidered.\n\n   Tab Completion:\n       z  supports tab completion. After any number of arguments, press TAB to\n       complete on directories that match each argument. Due to limitations of\n       the  completion  implementations,  only  the last argument will be com-\n       pleted in the shell.\n\n       Internally, z decides you've requested a completion if the  last  argu-\n       ment  passed  is  an  absolute  path to an existing directory. This may\n       cause unexpected behavior if the last argument to z begins with /.\n\nENVIRONMENT\n       A function _z() is defined.\n\n       The contents of the variable $_Z_CMD is aliased to _z 2>&1. If not set,\n       $_Z_CMD defaults to z.\n\n       The  environment  variable $_Z_DATA can be used to control the datafile\n       location. If it is not defined, the location defaults to $HOME/.z.\n\n       The environment variable $_Z_NO_RESOLVE_SYMLINKS can be set to  prevent\n       resolving  of  symlinks.  If  it  is  not  set,  symbolic links will be\n       resolved when added to the datafile.\n\n       In bash, z prepends a command to the PROMPT_COMMAND  environment  vari-\n       able  to  maintain its database. In zsh, z appends a function _z_precmd\n       to the precmd_functions array.\n\n       The environment variable $_Z_NO_PROMPT_COMMAND can be set if  you  want\n       to handle PROMPT_COMMAND or precmd yourself.\n\n       The  environment  variable  $_Z_EXCLUDE_DIRS  can be set to an array of\n       directories to exclude from tracking. $HOME is always excluded.  Direc-\n       tories must be full paths without trailing slashes.\n\nFILES\n       Data  is  stored  in  $HOME/.z.  This  can be overridden by setting the\n       $_Z_DATA environment variable. When initialized, z will raise an  error\n       if this path is a directory, and not function correctly.\n\n       A man page (z.1) is provided.\n\nSEE ALSO\n       regex(7), pushd, popd, autojump, cdargs\n\n       Please file bugs at https://github.com/rupa/z/\n\n\n\nz                                January 2013                             Z(1)\n"
  },
  {
    "path": "README.md",
    "content": "---\n\n## Fuel the Codecraft\n\nTime is finite. The system endures, but only in bursts of stolen hours. Feature requests gather like stardust—brilliant, infinite, out of reach.\nInvoke /coffee to recharge the core and rekindle the forge. Your signal boosts morale. ☕⚡\n\n[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/C0C8K83RC)\n---\n\n## Invoke: `z`\n\nHarness the echoes of your own movement—`z` learns as you roam.  \nWith each `cd`, it maps your path, shaping memory into motion.  \nA PowerShell-native port of the legendary [*z*](https://github.com/rupa/z) from the Bash realms.\n\n[Install it from the PowerShell Gallery](https://www.powershellgallery.com/packages/z/) and let your history guide your future.\n\n## Origins of the Script\n\nSince the cycle of June 2013, this utility has been forged through hours of iteration—tweaked, refined, and honed to align with PowerShell's rhythm. Born from necessity, it became a tool of mastery, accelerating my traversal through the filesystem—a realm I once wandered daily.\n\nThere are no unit tests yet (one day, perhaps), but its true purpose was never perfection. It was time. Time saved. Knowledge gained.\n\nIts mission is simple: bypass the burden of full pathnames and leap to [frecent](https://developer.mozilla.org/en-US/docs/Mozilla/Tech/Places/Frecency_algorithm) locations with speed and grace.\nStable. Swift. Battle-tested.\nMay it serve you as it has served me.\n\n![ExampleUsage]\n\n## Examples\n\nOnce installed, begin the ritual—`cd` into a few directories. Let the system observe. Let the memory form.\n\n`cd foo`\n\n`cd HKLM:\\software\\Microsoft\\Office`\n\n`cd 'C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\Temporary ASP.NET Files'`\n\nBased on the examples above, try executing some of these commands.\n\n\tz foo\t\t\t\tcd to most frecent folder matching foo\n\t\n\tz temp\t\t\t\tcd to most frecent folder matching `Temporary ASP.NET Files`\n\n\tz foo -o r\t\t\tcd to highest ranked folder matching foo\n\n\tz foo -o f\t\t\tcd to highest frecency folder matching foo\n\t\n\tz foo -o t\t\t\tcd to the most recently accessed folder matching foo\n\t\n\tz -l foo\t\t\tlist all dirs matching regex foo\n\t\n\tz -l\t\t\t\tlist all entries\n\n\tz office\t\t\tcd to most frecent folder matching office in drive HKLM (The registry)\n\t\n\tz -x\t\t\t\tremove the current directory from the datafile\n\t\n\tz -clean\t\t\tdelete inaccessible paths from the datafile\n\t\n\tz c:\\windows\t\t\tgo to c:\\windows and log in the datafile (works with any valid path)\n\t\n\tz c<TAB>\t\t\texpand entries in the datafile which match 'c'\n\nOK, back to normal writing style.\n\n## Limitations\n\nBelow is a list of features which have not yet been ported from the original `z` bash script...yet.\n\n* Specifying two separate regex's and matching on both, i.e. `z foo bar`\n* Does not have the ability to restrict searches to sub-directories of the current directory\n\n## Added sugar\n\n* Tab completion support (will not currently work if you have PowerTab installed)\n\n* Works with registry paths such as `HKLM\\Software\\....` and NetBIOS paths such as `\\\\server\\share`.\n\n* Executing `pushd` will record the current directory for use with `z`.\n\n## Planned Features\n\n[See the issue listing](https://github.com/vincpa/z/issues)\n\n## PowerShell installation\n\n### The easy way using PowerShellGet\n\nFor those with Windows 10, you can issue a `Install-Module z -AllowClobber` command.\n\nFor those running the latest version of PowerShell `PowerShellGet\\Install-Module z -Scope CurrentUser -Force -AllowClobber`\n\nFor those with Windows Vista or 7 who are using PowerShell version 3 or 4, you'll need to install [PackageManagement](http://go.microsoft.com/fwlink/?LinkID=746217&clcid=0x409) first before executing `Install-Module z -AllowClobber`.\n\nSee the module listing in the [official PowerShell gallary](https://www.powershellgallery.com/packages/z/)\n\nOnce complete, run the command `Import-Module z`. For ease of use I recomend placing this command in your [PowerShell startup profile](https://technet.microsoft.com/en-us/library/bb613488(v=vs.85).aspx). Typically `$env:USERPROFILE\\Documents\\WindowsPowerShell\\Microsoft.PowerShell_profile.ps1`\n\n### The hard way\n\nDownload the `z.psm1` file and save it to your PowerShell module directory. The default location for this is `$env:USERPROFILE\\Documents\\WindowsPowerShell\\Modules` (relative to your Documents folder). You can also extract it to another directory listed in your `$env:PSModulePath`. The full installation path should be `$env:USERPROFILE\\Documents\\WindowsPowerShell\\Modules\\z\\z.psm1`.\n\nAssuming you want `z` to be avilable in every PowerShell session, open your profile script located at `$env:USERPROFILE\\Documents\\WindowsPowerShell\\Microsoft.PowerShell_profile.ps1` and add the following line.\n\n`Import-Module z`\n\nIf the file `Microsoft.PowerShell_profile.ps1` does not exist, you can simply create it and it will be executed the next time a PowerShell session starts.\n\n## Running z\n\nOnce the module is installed and has been imported in to your session you can start jumping around. Remember, you need to build up the DB of directories first so be sure to `cd` around your file system. You can also use `z` as an alternative to the `cd` command.\n\n[ExampleUsage]: https://raw.githubusercontent.com/vincpa/z/master/example_usage.gif\n"
  },
  {
    "path": "z.1",
    "content": ".TH \"Z\" \"1\" \"January 2013\" \"z\" \"User Commands\"\n.SH\nNAME\nz \\- jump around\n.SH\nSYNOPSIS\nz [\\-chlrtx] [regex1 regex2 ... regexn]\n.SH\nAVAILABILITY\nbash, zsh\n.SH\nDESCRIPTION\nTracks your most used directories, based on 'frecency'.\n.P\nAfter a short learning phase, \\fBz\\fR will take you to the most 'frecent'\ndirectory that matches ALL of the regexes given on the command line.\n.SH\nOPTIONS\n.TP\n\\fB\\-c\\fR\nrestrict matches to subdirectories of the current directory\n.TP\n\\fB\\-h\\fR\nshow a brief help message\n.TP\n\\fB\\-l\\fR\nlist only\n.TP\n\\fB\\-r\\fR\nmatch by rank only\n.TP\n\\fB\\-t\\fR\nmatch by recent access only\n.TP\n\\fB\\-x\\fR\nremove the current directory from the datafile\n.SH EXAMPLES\n.TP 14\n\\fBz foo\\fR\ncd to most frecent dir matching foo\n.TP 14\n\\fBz foo bar\\fR\ncd to most frecent dir matching foo and bar\n.TP 14\n\\fBz -r foo\\fR\ncd to highest ranked dir matching foo\n.TP 14\n\\fBz -t foo\\fR\ncd to most recently accessed dir matching foo\n.TP 14\n\\fBz -l foo\\fR\nlist all dirs matching foo (by frecency)\n.SH\nNOTES\n.SS\nInstallation:\n.P\nPut something like this in your \\fB$HOME/.bashrc\\fR or \\fB$HOME/.zshrc\\fR:\n.RS\n.P\n\\fB. /path/to/z.sh\\fR\n.RE\n.P\n\\fBcd\\fR around for a while to build up the db.\n.P\nPROFIT!!\n.P\nOptionally:\n.RS\nSet \\fB$_Z_CMD\\fR to change the command name (default \\fBz\\fR).\n.RE\n.RS\nSet \\fB$_Z_DATA\\fR to change the datafile (default \\fB$HOME/.z\\fR).\n.RE\n.RS\nSet \\fB$_Z_NO_RESOLVE_SYMLINKS\\fR to prevent symlink resolution.\n.RE\n.RS\nSet \\fB$_Z_NO_PROMPT_COMMAND\\fR to handle \\fBPROMPT_COMMAND/precmd\\fR yourself.\n.RE\n.RS\nSet \\fB$_Z_EXCLUDE_DIRS\\fR to an array of directories to exclude.\n.RE\n.RS\n(These settings should go in .bashrc/.zshrc before the lines added above.)\n.RE\n.RS\nInstall the provided man page \\fBz.1\\fR somewhere like \\fB/usr/local/man/man1\\fR.\n.RE\n.SS\nAging:\nThe rank of directories maintained by \\fBz\\fR undergoes aging based on a simple\nformula. The rank of each entry is incremented every time it is accessed. When\nthe sum of ranks is greater than 6000, all ranks are multiplied by 0.99. Entries\nwith a rank lower than 1 are forgotten.\n.SS\nFrecency:\nFrecency is a portmanteau of 'recent' and 'frequency'. It is a weighted rank\nthat depends on how often and how recently something occurred. As far as I\nknow, Mozilla came up with the term.\n.P\nTo \\fBz\\fR, a directory that has low ranking but has been accessed recently\nwill quickly have higher rank than a directory accessed frequently a long time\nago.\n.P\nFrecency is determined at runtime.\n.SS\nCommon:\nWhen multiple directories match all queries, and they all have a common prefix,\n\\fBz\\fR will cd to the shortest matching directory, without regard to priority.\nThis has been in effect, if undocumented, for quite some time, but should\nprobably be configurable or reconsidered.\n.SS\nTab Completion:\n\\fBz\\fR supports tab completion. After any number of arguments, press TAB to\ncomplete on directories that match each argument. Due to limitations of the\ncompletion implementations, only the last argument will be completed in the\nshell.\n.P\nInternally, \\fBz\\fR decides you've requested a completion if the last argument\npassed is an absolute path to an existing directory. This may cause unexpected\nbehavior if the last argument to \\fBz\\fR begins with \\fB/\\fR.\n.SH\nENVIRONMENT\nA function \\fB_z()\\fR is defined.\n.P\nThe contents of the variable \\fB$_Z_CMD\\fR is aliased to \\fB_z 2>&1\\fR. If not\nset, \\fB$_Z_CMD\\fR defaults to \\fBz\\fR.\n.P\nThe environment variable \\fB$_Z_DATA\\fR can be used to control the datafile\nlocation. If it is not defined, the location defaults to \\fB$HOME/.z\\fR.\n.P\nThe environment variable \\fB$_Z_NO_RESOLVE_SYMLINKS\\fR can be set to prevent\nresolving of symlinks. If it is not set, symbolic links will be resolved when\nadded to the datafile.\n.P\nIn bash, \\fBz\\fR prepends a command to the \\fBPROMPT_COMMAND\\fR environment\nvariable to maintain its database. In zsh, \\fBz\\fR appends a function\n\\fB_z_precmd\\fR to the \\fBprecmd_functions\\fR array.\n.P\nThe environment variable \\fB$_Z_NO_PROMPT_COMMAND\\fR can be set if you want to\nhandle \\fBPROMPT_COMMAND\\fR or \\fBprecmd\\fR yourself.\n.P\nThe environment variable \\fB$_Z_EXCLUDE_DIRS\\fR can be set to an array of\ndirectories to exclude from tracking. \\fB$HOME\\fR is always excluded.\nDirectories must be full paths without trailing slashes.\n.SH\nFILES\nData is stored in \\fB$HOME/.z\\fR. This can be overridden by setting the\n\\fB$_Z_DATA\\fR environment variable. When initialized, \\fBz\\fR will raise an\nerror if this path is a directory, and not function correctly.\n.P\nA man page (\\fBz.1\\fR) is provided.\n.SH\nSEE ALSO\nregex(7), pushd, popd, autojump, cdargs\n.P\nPlease file bugs at https://github.com/rupa/z/\n"
  },
  {
    "path": "z.psd1",
    "content": "﻿#\r\n# Module manifest for module 'z'\r\n#\r\n# Generated by: Vince Panuccio\r\n#\r\n# Generated on: 24/5/2024\r\n#\r\n\r\n@{\r\n\r\n# Script module or binary module file associated with this manifest.\r\nRootModule = 'z.psm1'\r\n\r\n#ModuleToProcess = 'z.psm1'\r\n\r\n# Version number of this module.\r\nModuleVersion = '1.1.15'\r\n\r\n# ID used to uniquely identify this module\r\nGUID = 'bc198554-ae1f-4ab6-84ce-5d3a41b74553'\r\n\r\n# Author of this module\r\nAuthor = 'Vince Panuccio'\r\n\r\n# Description of the functionality provided by this module\r\nDescription = 'z lets you quickly navigate the file system in PowerShell based on your cd command history. It''s a port of the z bash shell script'\r\n\r\n# Minimum version of the Windows PowerShell engine required by this module\r\nPowerShellVersion = '3.0'\r\n\r\nFileList = 'z.psm1'\r\n\r\n# Functions to export from this module\r\nFunctionsToExport = @('z', 'cdX', 'popdX', 'pushdX')\r\n\r\n# Aliases to export from this module\r\nAliasesToExport = '*'\r\n\r\n# Variables to export from this module\r\nVariablesToExport = 'Z_UsePushLocation'\r\n\r\n# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.\r\nPrivateData = @{\r\n\r\n    PSData = @{\r\n\r\n        # Tags applied to this module. These help with module discovery in online galleries.\r\n        Tags = @('z', 'directory', 'popd', 'pushd', 'jump')\r\n\r\n        # A URL to the license for this module.\r\n        # LicenseUri = ''\r\n\r\n        # A URL to the main website for this project.\r\n        ProjectUri = 'https://github.com/vincpa/z'\r\n\r\n        # A URL to an icon representing this module.\r\n        # IconUri = ''\r\n\r\n        # ReleaseNotes of this module\r\n        ReleaseNotes = 'Add support for XDG_CACHE_HOME'\r\n\r\n    } # End of PSData hashtable\r\n\r\n} # End of PrivateData hashtable\r\n\r\n\r\n\r\n# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.\r\n# DefaultCommandPrefix = ''\r\n\r\n}\r\n"
  },
  {
    "path": "z.psm1",
    "content": "﻿if (![String]::IsNullOrWhiteSpace($env:XDG_CACHE_HOME)) {\r\n    $cdHistoryDir = Join-Path -Path $env:XDG_CACHE_HOME -ChildPath 'powershell-z'\r\n    if (!(Test-Path $cdHistoryDir)) {\r\n        New-Item -ItemType Directory -Path $cdHistoryDir -Force | Out-Null\r\n    }\r\n    $cdHistory = Join-Path -Path $cdHistoryDir -ChildPath 'cdHistory'\r\n} elseif (![String]::IsNullOrWhiteSpace($env:HOME)) {\r\n    $cdHistory = Join-Path -Path $env:HOME -ChildPath '.cdHistory'\r\n} else {\r\n    $cdHistory = Join-Path -Path $env:USERPROFILE -ChildPath '.cdHistory'\r\n}\r\n\r\n# The user can set $Z_UsePushLocation to $true to configure z to use Push-location, which allows to use popd/Pop-Location to go back to the previous location.\r\n# Setting or $Z_UsePushLocation to $false will use Set-Location instead.\r\n\r\nif ($null -eq $Z_UsePushLocation)\r\n{\r\n    # Set default behaviour to use Push-Location\r\n    $Z_UsePushLocation = $true;\r\n}\r\n\r\nfunction z {\r\n<#\r\n\r\n.SYNOPSIS\r\n\r\n   Tracks your most used directories, based on 'frecency'. This is done by storing your CD command history and ranking it over time.\r\n\r\n.DESCRIPTION\r\n\r\n    After  a  short  learning  phase, z will take you to the most 'frecent'\r\n    directory that matches the regex given on the command line.\r\n\r\n.PARAMETER JumpPath\r\n\r\nA un-escaped regular expression of the directory name to jump to. Character escaping will be done internally.\r\n\r\n.PARAMETER Option\r\n\r\nFrecency - Match by frecency (default)\r\nRank - Match by rank only\r\nTime - Match by recent access only\r\n\r\n.PARAMETER OnlyCurrentDirectory\r\n\r\nRestrict matches to subdirectories of the current directory\r\n\r\n.PARAMETER Listfiles\r\n\r\nList only, don't navigate to the directory\r\n\r\n.PARAMETER $Remove\r\n\r\nRemove the current directory from the datafile\r\n\r\n.PARAMETER $Clean\r\n\r\nClean up all history entries that cannot be resolved\r\n\r\n.NOTES\r\n\r\nCurrent PowerShell implementation is very crude and does not yet support all of the options of the original z bash script.\r\nAlthough tracking of frequently used directories is obtained through the continued use of the \"cd\" command, the Windows registry is also scanned for frequently accessed paths.\r\n\r\n.LINK\r\n\r\n   https://github.com/vincpa/z\r\n\r\n.EXAMPLE\r\n\r\nCD to the most frecent directory matching 'foo'\r\n\r\nz foo\r\n\r\n.EXAMPLE\r\n\r\nCD to the most recently accessed directory matching 'foo'\r\n\r\nz foo -o Time\r\n\r\n#>\r\n    param(\r\n    [Parameter(Position=0)]\r\n    [string]\r\n    ${JumpPath},\r\n\r\n    [ValidateSet(\"Time\", \"T\", \"Frecency\", \"F\", \"Rank\", \"R\")]\r\n    [Alias('o')]\r\n    [string]\r\n    $Option = 'Frecency',\r\n\r\n    [Alias('c')]\r\n    [switch]\r\n    $OnlyCurrentDirectory = $null,\r\n\r\n    [Alias('l')]\r\n    [switch]\r\n    $ListFiles = $null,\r\n\r\n    [Alias('x')]\r\n    [switch]\r\n    $Remove = $null,\r\n\r\n    [Alias('d')]\r\n    [switch]\r\n    $Clean = $null,\r\n\r\n    [Alias('p')]\r\n    [switch]\r\n    $Push = $false\r\n)\r\n\r\n    if (((-not $Clean) -and (-not $Remove) -and (-not $ListFiles)) -and [string]::IsNullOrWhiteSpace($JumpPath)) { Get-Help z; return; }\r\n\r\n    # If a valid path is passed in to z, treat it like the normal cd command\r\n    if (-not $ListFiles -and -not [string]::IsNullOrWhiteSpace($JumpPath) -and (Test-Path $JumpPath)) {\r\n        if ($Push -or $Z_UsePushLocation) {\r\n            pushdX $JumpPath\r\n        } else {\r\n            cdX $JumpPath\r\n        }\r\n        return;\r\n    }\r\n\r\n    if ((Test-Path $cdHistory)) {\r\n        if ($Remove) {\r\n        Save-CdCommandHistory $Remove\r\n        } elseif ($Clean) {\r\n            Cleanup-CdCommandHistory\r\n        } else {\r\n\r\n            # This causes conflicts with the -Remove parameter. Not sure whether to remove registry entry.\r\n            #$mruList = Get-MostRecentDirectoryEntries\r\n\r\n            $providerRegex = $null\r\n\r\n            If ($OnlyCurrentDirectory) {\r\n                $providerRegex = (Get-FormattedLocation).replace('\\','\\\\')\r\n                if (-not $providerRegex.EndsWith('\\\\')) {\r\n                    $providerRegex += '\\\\'\r\n                }\r\n                $providerRegex += '.*?'\r\n            } else {\r\n                $providerRegex = Get-CurrentSessionProviderDrives ((Get-PSProvider).Drives | select -ExpandProperty Name)\r\n            }\r\n\r\n            $list = @()\r\n\r\n            $global:history |\r\n                ? { Get-DirectoryEntryMatchPredicate -path $_.Path -jumpPath $JumpPath -ProviderRegex $providerRegex } | Get-ArgsFilter -Option $Option |\r\n                % { if ($ListFiles -or (Test-Path $_.Path.FullName)) {$list += $_} }\r\n\r\n            if ($ListFiles) {\r\n\r\n                $newList = $list | % { New-Object PSObject -Property  @{Rank = $_.Rank; Path = $_.Path.FullName; LastAccessed = [DateTime]$_.Time } }\r\n                Format-Table -InputObject $newList -AutoSize\r\n\r\n            } else {\r\n\r\n                if ($list.Length -eq 0) {\r\n                    # It's not found in the history file, perhaps it's still a valid directory. Let's check.\r\n                    if ((Test-Path $JumpPath)) {\r\n                        if ($Push -or $Z_UsePushLocation) {\r\n                            pushdX $JumpPath\r\n                        } else {\r\n                            cdX $JumpPath\r\n                        }\r\n                    } else {\r\n                        Write-Host \"$JumpPath Not found\"\r\n                    }\r\n\r\n                } else {\r\n                    if ($list.Length -gt 1) {\r\n                        $entry = $list | Sort-Object -Descending { $_.Score } | select -First 1\r\n\r\n                    } else {\r\n                        $entry = $list[0]\r\n                    }\r\n\r\n                    if ($Push -or $Z_UsePushLocation) {\r\n                        Push-Location $entry.Path.FullName\r\n                    } else {\r\n                        Set-Location $entry.Path.FullName\r\n                    }\r\n                    Save-CdCommandHistory $Remove\r\n                }\r\n            }\r\n        }\r\n    } else {\r\n        Save-CdCommandHistory $Remove\r\n    }\r\n}\r\n\r\nfunction pushdX\r\n{\r\n    [CmdletBinding(DefaultParameterSetName='Path', SupportsTransactions=$true, HelpUri='http://go.microsoft.com/fwlink/?LinkID=113370')]\r\n    param(\r\n        [Parameter(ParameterSetName='Path', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]\r\n        [string]\r\n        ${Path},\r\n\r\n        [Parameter(ParameterSetName='LiteralPath', ValueFromPipelineByPropertyName=$true)]\r\n        [Alias('PSPath')]\r\n        [string]\r\n        ${LiteralPath},\r\n\r\n        [switch]\r\n        ${PassThru},\r\n\r\n        [Parameter(ValueFromPipelineByPropertyName=$true)]\r\n        [string]\r\n        ${StackName})\r\n\r\n    begin\r\n    {\r\n        try {\r\n            $outBuffer = $null\r\n            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))\r\n            {\r\n                $PSBoundParameters['OutBuffer'] = 1\r\n            }\r\n            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Push-Location', [System.Management.Automation.CommandTypes]::Cmdlet)\r\n            $scriptCmd = {& $wrappedCmd @PSBoundParameters }\r\n            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)\r\n            $steppablePipeline.Begin($PSCmdlet)\r\n        } catch {\r\n            throw\r\n        }\r\n    }\r\n\r\n    process\r\n    {\r\n        try {\r\n            $steppablePipeline.Process($_)\r\n            Save-CdCommandHistory # Build up the DB.\r\n        } catch {\r\n            throw\r\n        }\r\n    }\r\n\r\n    end\r\n    {\r\n        try {\r\n            $steppablePipeline.End()\r\n        } catch {\r\n            throw\r\n        }\r\n    }\r\n}\r\n\r\nfunction popdX {\r\n    [CmdletBinding(SupportsTransactions=$true, HelpUri='http://go.microsoft.com/fwlink/?LinkID=113369')]\r\n    param(\r\n        [switch]\r\n        ${PassThru},\r\n\r\n        [Parameter(ValueFromPipelineByPropertyName=$true)]\r\n        [string]\r\n        ${StackName})\r\n\r\n    begin\r\n    {\r\n        try {\r\n            $outBuffer = $null\r\n            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))\r\n            {\r\n                $PSBoundParameters['OutBuffer'] = 1\r\n            }\r\n            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\\Pop-Location', [System.Management.Automation.CommandTypes]::Cmdlet)\r\n            $scriptCmd = {& $wrappedCmd @PSBoundParameters }\r\n            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)\r\n            $steppablePipeline.Begin($PSCmdlet)\r\n        } catch {\r\n            throw\r\n        }\r\n    }\r\n\r\n    process\r\n    {\r\n        try {\r\n            $steppablePipeline.Process($_)\r\n        } catch {\r\n            throw\r\n        }\r\n    }\r\n\r\n    end\r\n    {\r\n        try {\r\n            $steppablePipeline.End()\r\n        } catch {\r\n            throw\r\n        }\r\n    }\r\n    <#\r\n\r\n    .ForwardHelpTargetName Microsoft.PowerShell.Management\\Pop-Location\r\n    .ForwardHelpCategory Cmdlet\r\n\r\n    #>\r\n}\r\n\r\n# A wrapper function around the existing Set-Location Cmdlet.\r\nfunction cdX\r\n{\r\n    [CmdletBinding(DefaultParameterSetName='Path', SupportsTransactions=$true, HelpUri='http://go.microsoft.com/fwlink/?LinkID=113397')]\r\n    param(\r\n        [Parameter(ParameterSetName='Path', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]\r\n        [string]\r\n        ${Path},\r\n\r\n        [Parameter(ParameterSetName='LiteralPath', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]\r\n        [Alias('PSPath')]\r\n        [string]\r\n        ${LiteralPath},\r\n\r\n        [switch]\r\n        ${PassThru},\r\n\r\n        [Parameter(ParameterSetName='Stack', ValueFromPipelineByPropertyName=$true)]\r\n        [string]\r\n        ${StackName})\r\n\r\n    begin\r\n    {\r\n        $outBuffer = $null\r\n        if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))\r\n        {\r\n            $PSBoundParameters['OutBuffer'] = 1\r\n        }\r\n\r\n        $PSBoundParameters['ErrorAction'] = 'Stop'\r\n\r\n        $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Set-Location', [System.Management.Automation.CommandTypes]::Cmdlet)\r\n        $scriptCmd = {& $wrappedCmd @PSBoundParameters }\r\n\r\n        $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)\r\n        $steppablePipeline.Begin($PSCmdlet)\r\n    }\r\n\r\n    process\r\n    {\r\n        $steppablePipeline.Process($_)\r\n\r\n        Save-CdCommandHistory # Build up the DB.\r\n    }\r\n\r\n    end\r\n    {\r\n        $steppablePipeline.End()\r\n    }\r\n}\r\n\r\nfunction Get-DirectoryEntryMatchPredicate {\r\n    Param(\r\n        [Parameter(\r\n        ValueFromPipeline=$true,\r\n        ValueFromPipelineByPropertyName=$true)]\r\n        $Path,\r\n\r\n        [Parameter(\r\n        ValueFromPipeline=$true,\r\n        ValueFromPipelineByPropertyName=$true)]\r\n        [string] $JumpPath,\r\n\r\n        $ProviderRegex\r\n    )\r\n\r\n    if ($Path -ne $null) {\r\n\r\n        $null = .{\r\n            $providerMatches = [System.Text.RegularExpressions.Regex]::Match($Path.FullName, $ProviderRegex).Success\r\n        }\r\n\r\n        if ($providerMatches) {\r\n            \r\n            # Allows matching of entire names. Remove the first two characters, added by PowerShell when the user presses the TAB key.\r\n            if ($JumpPath.StartsWith('.\\')) {\r\n                $JumpPath = $JumpPath.Substring(2).TrimEnd('\\')\r\n            }\r\n\r\n            [System.Text.RegularExpressions.Regex]::Match($Path.Name, [System.Text.RegularExpressions.Regex]::Escape($JumpPath), [System.Text.RegularExpressions.RegexOptions]::IgnoreCase).Success\r\n        }\r\n    }\r\n}\r\n\r\nfunction Get-CurrentSessionProviderDrives([System.Collections.ArrayList] $ProviderDrives) {\r\n\r\n    if($IsLinux -Or $IsMacOS) {\r\n        # Always only '/' which needs escaped to work in a regex\r\n        '\\/'\r\n    } elseif ($ProviderDrives -ne $null -and $ProviderDrives.Length -gt 0) {\r\n        Get-ProviderDrivesRegex $ProviderDrives\r\n    } else {\r\n\r\n        # The FileSystemProvider supports \\\\ and X:\\ paths.\r\n        # An ideal solution would be to ask the provider if a path is supported.\r\n        # Supports drives such as C:\\ and also UNC \\\\\r\n        if ((Get-Location).Provider.ImplementingType.Name -eq 'FileSystemProvider') {\r\n            '(?i)^(((' + [String]::Concat( ((Get-Location).Provider.Drives.Name | % { $_ + '|' }) ).TrimEnd('|') + '):\\\\)|(\\\\{1,2})).*?'\r\n        } else {\r\n            Get-ProviderDrivesRegex (Get-Location).Provider.Drives\r\n        }\r\n    }\r\n}\r\n\r\nfunction Get-ProviderDrivesRegex([System.Collections.ArrayList] $ProviderDrives) {\r\n    \r\n    # UNC paths get special treatment. Allows one to 'z foo -ProviderDrives \\\\' and specify '\\\\' as the drive.\r\n    if ($ProviderDrives -contains '\\\\') {\r\n        $ProviderDrives.('\\\\')\r\n    }\r\n\r\n    if ($ProviderDrives.Count -eq 0) {\r\n        '(?i)^(\\\\{1,2}).*?'\r\n    } else {\r\n        $uncRootPathRegex = '|(\\\\{1,2})'\r\n        '(?i)^((' + [String]::Concat( ($ProviderDrives | % { $_ + '|' }) ).TrimEnd('|') + '):\\\\)' + $uncRootPathRegex + '.*?'\r\n    }\r\n}\r\n\r\nfunction Get-Frecency($rank, $time) {\r\n\r\n    # Last access date/time\r\n    $dx = (Get-Date).Subtract((New-Object System.DateTime -ArgumentList $time)).TotalSeconds\r\n\r\n    if( $dx -lt 3600 ) { return $rank*4 }\r\n\r\n    if( $dx -lt 86400 ) { return $rank*2 }\r\n\r\n    if( $dx -lt 604800 ) { return $rank/2 }\r\n\r\n    return $rank/4\r\n}\r\n\r\nfunction Cleanup-CdCommandHistory() {\r\n\r\n    try {\r\n\r\n        for($i = 0; $i -lt $global:history.Length; $i++) {\r\n\r\n            $line = $global:history[$i]\r\n\r\n            if ($line -ne $null) {\r\n                $testDir = $line.Path.FullName\r\n                if (-not [string]::IsNullOrWhiteSpace($testDir) -and !(Test-Path $testDir)) {\r\n                    $global:history[$i] = $null\r\n                    Write-Host \"Removed inaccessible path $testDir\" -ForegroundColor Yellow\r\n                }\r\n            }\r\n        }\r\n        Remove-Old-History\r\n        WriteHistoryToDisk\r\n    } catch {\r\n        Write-Host $_.Exception.ToString() -ForegroundColor Red\r\n    }\r\n}\r\n\r\n\r\nfunction Remove-Old-History() {\r\n    if ($global:history.Length -gt 1000) {\r\n        $global:history | ? { $_ -ne $null } | % {$i = 0} {\r\n\r\n            $lineObj = $_\r\n            $lineObj.Rank = $lineObj.Rank * 0.99\r\n\r\n            # If it's been accessed in the last 14 days it can stay\r\n            # or\r\n            # If it's rank is greater than 20 and been accessed in the last 30 days it can stay\r\n            if ($lineObj.Age -lt 1209600 -or ($lineObj.Rank -ge 5 -and $lineObj.Age -lt 2592000)) {\r\n              #$global:history[$i] = ConvertTo-DirectoryEntry (ConvertTo-TextualHistoryEntry $lineObj.Rank $lineObj.Path.FullName $lineObj.Time)\r\n            } else {\r\n              Write-Host \"Removing old item: Rank:\" $lineObj.Rank \"Age:\" ($lineObj.Age/60/60) \"Path:\" $lineObj.Path.FullName -ForegroundColor Yellow\r\n              $global:history[$i] = $null\r\n            }\r\n            $i++;\r\n        }\r\n    }\r\n}\r\n\r\n\r\nfunction Save-CdCommandHistory($removeCurrentDirectory = $false) {\r\n\r\n    $currentDirectory = Get-FormattedLocation\r\n\r\n    try {\r\n\r\n        $foundDirectory = $false\r\n        $runningTotal = 0\r\n\r\n        for($i = 0; $i -lt $global:history.Length; $i++) {\r\n\r\n            $line = $global:history[$i]\r\n\r\n            $canIncreaseRank = $true;\r\n\r\n            $rank = $line.Rank;\r\n\r\n            if (-not $foundDirectory) {\r\n\r\n                $rank = $line.Rank\r\n\r\n                if ($line.Path.FullName -eq $currentDirectory) {\r\n\r\n                    $foundDirectory = $true\r\n\r\n                    if ($removeCurrentDirectory) {\r\n                        $canIncreaseRank = $false\r\n                        $global:history[$i] = $null\r\n                        Write-Host \"Removed entry $currentDirectory\" -ForegroundColor Green\r\n\r\n                    } else {\r\n                        $rank++\r\n                        Update-HistoryEntryUsageTime $global:history[$i]\r\n                    }\r\n                }\r\n            }\r\n\r\n            if ($canIncreaseRank) {\r\n                $runningTotal += $rank\r\n            }\r\n        }\r\n\r\n        if (-not $foundDirectory -and $removeCurrentDirectory) {\r\n            Write-Host \"Current directory not found in CD history data file\" -ForegroundColor Red\r\n        } else {\r\n\r\n            if (-not $foundDirectory) {\r\n                Save-HistoryEntry 1 $currentDirectory\r\n                $runningTotal += 1\r\n            }\r\n            Remove-Old-History\r\n        }\r\n\r\n        WriteHistoryToDisk\r\n\r\n    } catch {\r\n        Write-Host $_.Exception.ToString() -ForegroundColor Red\r\n    }\r\n}\r\n\r\nfunction WriteHistoryToDisk() {\r\n  $newList = GetAllHistoryAsText $global:history\r\n  Set-Content -Value $newList -Path $cdHistory -Encoding UTF8\r\n}\r\n\r\nfunction GetAllHistoryAsText($history) {\r\n    return $history | ? { $_ -ne $null } | % { ConvertTo-TextualHistoryEntry $_.Rank $_.Path.FullName $_.Time }\r\n}\r\n\r\nfunction Get-FormattedLocation() {\r\n    if ((Get-Location).Provider.ImplementingType.Name -eq 'FileSystemProvider' -and (Get-Location).Path.Contains('FileSystem::\\\\')) {\r\n        Get-Location | select -ExpandProperty ProviderPath # The registry provider does return a path which z understands. In other words, I'm too lazy.\r\n    } else {\r\n        Get-Location | select -ExpandProperty Path\r\n    }\r\n}\r\n\r\nfunction Format-Rank($rank) {\r\n    return $rank.ToString(\"000#.00\", [System.Globalization.CultureInfo]::InvariantCulture);\r\n}\r\n\r\nfunction Save-HistoryEntry($rank, $directory) {\r\n    $entry = ConvertTo-TextualHistoryEntry $rank $directory\r\n    $global:history += ConvertTo-DirectoryEntry $entry\r\n}\r\n\r\nfunction Update-HistoryEntryUsageTime($historyEntry) {\r\n    $historyEntry.Rank++\r\n    $historyEntry.Time = (Get-Date).Ticks\r\n}\r\n\r\nfunction ConvertTo-TextualHistoryEntry($rank, $directory, $lastAccessedTicks) {\r\n    if ($lastAccessedTicks -eq $null) {\r\n        $lastAccessedTicks = (Get-Date).Ticks\r\n    }\r\n\r\n    (Format-Rank $rank) + $lastAccessedTicks + $directory\r\n}\r\n\r\nfunction ConvertTo-DirectoryEntry {\r\n    Param(\r\n        [Parameter(\r\n        Position=0,\r\n        Mandatory=$true,\r\n        ValueFromPipeline=$true,\r\n        ValueFromPipelineByPropertyName=$true)]\r\n        [String]$line\r\n    )\r\n\r\n    Process {\r\n\r\n        $null = .{\r\n\r\n            $pathValue = $line.Substring(25)\r\n\r\n            try {\r\n                $fileName = [System.IO.Path]::GetFileName($pathValue);\r\n                \r\n                # GetFileName() does not work with registry paths\r\n                if ($fileName -eq '') {\r\n                    $lastPathSeparator = $pathValue.LastIndexOf('\\');\r\n                    if ($lastPathSeparator -ge 0) {\r\n                        $pathValue = $pathValue.TrimEnd('\\');\r\n                        $fileName = $pathValue.Substring( + 1);\r\n                    }\r\n                }\r\n            } catch [System.ArgumentException] { }\r\n\r\n            $time = [long]::Parse($line.Substring(7, 18), [Globalization.CultureInfo]::InvariantCulture)\r\n        }\r\n\r\n        @{\r\n          Rank=GetRankFromLine $line;\r\n          Time=$time;\r\n          Path=@{ Name = $fileName; FullName = $pathValue };\r\n          Age=(Get-Date).Subtract((New-Object System.DateTime -ArgumentList $time)).TotalSeconds;\r\n        }\r\n    }\r\n}\r\n\r\nfunction GetRankFromLine([String]$line) {\r\n    $null = .{ $rankStr = $line.Substring(0, 7) }\r\n    [double]::Parse($rankStr, [Globalization.CultureInfo]::InvariantCulture)\r\n}\r\n\r\nfunction Get-MostRecentDirectoryEntries {\r\n\r\n    $mruEntries = (Get-Item -Path HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\TypedPaths | % { $item = $_; $_.GetValueNames() | % { $item.GetValue($_) } })\r\n\r\n    $mruEntries | % { ConvertTo-TextualHistoryEntry 1 $_ }\r\n}\r\n\r\nfunction Get-ArgsFilter {\r\n    Param(\r\n        [Parameter(ValueFromPipeline=$true)]\r\n        [Hashtable]$historyEntry,\r\n\r\n        [string]\r\n        $Option = 'Frecency'\r\n    )\r\n\r\n    Process {\r\n\r\n        if ($Option -in ('Frecency', 'F')) {\r\n            $_['Score'] = (Get-Frecency $_.Rank $_.Time);\r\n        } elseif ($Option -in ('Time', 'T')) {\r\n            $_['Score'] = $_.Time;\r\n        } elseif ($Option -in ('Rank', 'R')) {\r\n            $_['Score'] = $_.Rank;\r\n        }\r\n\r\n        return $_;\r\n    }\r\n}\r\n\r\n<#\r\n\r\n.ForwardHelpTargetName Set-Location\r\n.ForwardHelpCategory Cmdlet\r\n\r\n#>\r\n\r\n# Get cdHistory and hydrate a in-memory collection\r\n$global:history = @()\r\nif ((Test-Path -Path $cdHistory)) {\r\n  $global:history += Get-Content -Path $cdHistory -Encoding UTF8 | ? { (-not [String]::IsNullOrWhiteSpace($_)) } | ConvertTo-DirectoryEntry\r\n}\r\n\r\n$orig_cd = (Get-Alias -Name 'cd').Definition\r\n$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {\r\n    set-item alias:cd -value $orig_cd\r\n}\r\n\r\n#Override the existing CD command with the wrapper in order to log 'cd' commands.\r\nSet-item alias:cd -Value 'cdX'\r\n\r\nSet-Alias -Name pushd -Value pushdX -Force -Option AllScope -Scope Global\r\nSet-Alias -Name popd -Value popdX -Force -Option AllScope -Scope Global\r\n\r\nExport-ModuleMember -Function z, cdX, pushdX, popdX -Alias cd, pushd\r\n\r\n# Tab Completion\r\n$completion_RunningService = {\r\n    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)\r\n\r\n    $global:history | Sort-Object { $_.Rank } -Descending | Where-Object { $_.Path.Name -like \"*$wordToComplete*\" } |\r\n        ForEach-Object { New-Object System.Management.Automation.CompletionResult (\"'{0}'\" -f $_.Path.FullName), $_.Path.FullName, 'ParameterName', ('{0} ({1})' -f $_.Path.Name, $_.Path.FullName) }\r\n}\r\n\r\nif (Get-Command -ErrorAction Ignore -Name 'Register-ArgumentCompleter') {\r\n    Register-ArgumentCompleter -CommandName 'z' -ParameterName 'JumpPath' -ScriptBlock $completion_RunningService\r\n} else {\r\n    if (-not $global:options) { $global:options = @{CustomArgumentCompleters = @{};NativeArgumentCompleters = @{}}}\r\n\r\n    $global:options['CustomArgumentCompleters']['z:JumpPath'] = $Completion_RunningService\r\n\r\n    $function:tabexpansion2 = $function:tabexpansion2 -replace 'End(\\r\\n|\\n){','End { if ($null -ne $options) { $options += $global:options} else {$options = $global:options}'\r\n}"
  },
  {
    "path": "z.sh",
    "content": "# Copyright (c) 2009 rupa deadwyler under the WTFPL license\n\n# maintains a jump-list of the directories you actually use\n#\n# INSTALL:\n#   * put something like this in your .bashrc/.zshrc:\n#     . /path/to/z.sh\n#   * cd around for a while to build up the db\n#   * PROFIT!!\n#   * optionally:\n#     set $_Z_CMD in .bashrc/.zshrc to change the command (default z).\n#     set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z).\n#     set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.\n#     set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.\n#     set $_Z_EXCLUDE_DIRS to an array of directories to exclude.\n#\n# USE:\n#   * z foo     # cd to most frecent dir matching foo\n#   * z foo bar # cd to most frecent dir matching foo and bar\n#   * z -r foo  # cd to highest ranked dir matching foo\n#   * z -t foo  # cd to most recently accessed dir matching foo\n#   * z -l foo  # list matches instead of cd\n#   * z -c foo  # restrict matches to subdirs of $PWD\n\n[ -d \"${_Z_DATA:-$HOME/.z}\" ] && {\n    echo \"ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory.\"\n}\n\n_z() {\n\n local datafile=\"${_Z_DATA:-$HOME/.z}\"\n\n # bail out if we don't own ~/.z (we're another user but our ENV is still set)\n [ -f \"$datafile\" -a ! -O \"$datafile\" ] && return\n\n # add entries\n if [ \"$1\" = \"--add\" ]; then\n  shift\n\n  # $HOME isn't worth matching\n  [ \"$*\" = \"$HOME\" ] && return\n\n  # don't track excluded dirs\n  local exclude\n  for exclude in \"${_Z_EXCLUDE_DIRS[@]}\"; do\n   [ \"$*\" = \"$exclude\" ] && return\n  done\n\n  # maintain the file\n  local tempfile\n  tempfile=\"$datafile.$RANDOM\"\n  while read line; do\n   [ -d \"${line%%\\|*}\" ] && echo $line\n  done < \"$datafile\" | awk -v path=\"$*\" -v now=\"$(date +%s)\" -F\"|\" '\n   BEGIN {\n    rank[path] = 1\n    time[path] = now\n   }\n   $2 >= 1 {\n    if( $1 == path ) {\n     rank[$1] = $2 + 1\n     time[$1] = now\n    } else {\n     rank[$1] = $2\n     time[$1] = $3\n    }\n    count += $2\n   }\n   END {\n    if( count > 6000 ) {\n     for( i in rank ) print i \"|\" 0.99*rank[i] \"|\" time[i] # aging\n    } else for( i in rank ) print i \"|\" rank[i] \"|\" time[i]\n   }\n  ' 2>/dev/null >| \"$tempfile\"\n  if [ $? -ne 0 -a -f \"$datafile\" ]; then\n   env rm -f \"$tempfile\"\n  else\n   env mv -f \"$tempfile\" \"$datafile\" || env rm -f \"$tmpfile\"\n  fi\n\n # tab completion\n elif [ \"$1\" = \"--complete\" ]; then\n  while read line; do\n   [ -d \"${line%%\\|*}\" ] && echo $line\n  done < \"$datafile\" | awk -v q=\"$2\" -F\"|\" '\n   BEGIN {\n    if( q == tolower(q) ) nocase = 1\n    split(substr(q,3),fnd,\" \")\n   }\n   {\n    if( nocase ) {\n     for( i in fnd ) tolower($1) !~ tolower(fnd[i]) && $1 = \"\"\n    } else {\n     for( i in fnd ) $1 !~ fnd[i] && $1 = \"\"\n    }\n    if( $1 ) print $1\n   }\n  ' 2>/dev/null\n\n else\n  # list/go\n  while [ \"$1\" ]; do case \"$1\" in\n   --) while [ \"$1\" ]; do shift; local fnd=\"$fnd $1\";done;;\n   -*) local opt=${1:1}; while [ \"$opt\" ]; do case ${opt:0:1} in\n        c) local fnd=\"^$PWD $fnd\";;\n        h) echo \"${_Z_CMD:-z} [-chlrtx] args\" >&2; return;;\n        x) sed -i \"\\:^${PWD}|.*:d\" \"$datafile\";;\n        l) local list=1;;\n        r) local typ=\"rank\";;\n        t) local typ=\"recent\";;\n       esac; opt=${opt:1}; done;;\n    *) local fnd=\"$fnd $1\";;\n  esac; local last=$1; shift; done\n  [ \"$fnd\" -a \"$fnd\" != \"^$PWD \" ] || local list=1\n\n  # if we hit enter on a completion just go there\n  case \"$last\" in\n   # completions will always start with /\n   /*) [ -z \"$list\" -a -d \"$last\" ] && cd \"$last\" && return;;\n  esac\n\n  # no file yet\n  [ -f \"$datafile\" ] || return\n\n  local cd\n  cd=\"$(while read line; do\n   [ -d \"${line%%\\|*}\" ] && echo $line\n  done < \"$datafile\" | awk -v t=\"$(date +%s)\" -v list=\"$list\" -v typ=\"$typ\" -v q=\"$fnd\" -F\"|\" '\n   function frecent(rank, time) {\n    dx = t-time\n    if( dx < 3600 ) return rank*4\n    if( dx < 86400 ) return rank*2\n    if( dx < 604800 ) return rank/2\n    return rank/4\n   }\n   function output(files, toopen, override) {\n    if( list ) {\n     cmd = \"sort -n >&2\"\n     for( i in files ) if( files[i] ) printf \"%-10s %s\\n\", files[i], i | cmd\n     if( override ) printf \"%-10s %s\\n\", \"common:\", override > \"/dev/stderr\"\n    } else {\n     if( override ) toopen = override\n     print toopen\n    }\n   }\n   function common(matches) {\n    # shortest match\n    for( i in matches ) {\n     if( matches[i] && (!short || length(i) < length(short)) ) short = i\n    }\n    if( short == \"/\" ) return\n    # shortest match must be common to each match. escape special characters in\n    # a copy when testing, so we can return the original.\n    clean_short = short\n    gsub(/[\\(\\)\\[\\]\\|]/, \"\\\\\\\\&\", clean_short)\n    for( i in matches ) if( matches[i] && i !~ clean_short ) return\n    return short\n   }\n   BEGIN { split(q, a, \" \"); oldf = noldf = -9999999999 }\n   {\n    if( typ == \"rank\" ) {\n     f = $2\n    } else if( typ == \"recent\" ) {\n     f = $3-t\n    } else f = frecent($2, $3)\n    wcase[$1] = nocase[$1] = f\n    for( i in a ) {\n     if( $1 !~ a[i] ) delete wcase[$1]\n     if( tolower($1) !~ tolower(a[i]) ) delete nocase[$1]\n    }\n    if( wcase[$1] && wcase[$1] > oldf ) {\n     cx = $1\n     oldf = wcase[$1]\n    } else if( nocase[$1] && nocase[$1] > noldf ) {\n     ncx = $1\n     noldf = nocase[$1]\n    }\n   }\n   END {\n    if( cx ) {\n     output(wcase, cx, common(wcase))\n    } else if( ncx ) output(nocase, ncx, common(nocase))\n   }\n  ')\"\n  [ $? -gt 0 ] && return\n  [ \"$cd\" ] && cd \"$cd\"\n fi\n}\n\nalias ${_Z_CMD:-z}='_z 2>&1'\n\n[ \"$_Z_NO_RESOLVE_SYMLINKS\" ] || _Z_RESOLVE_SYMLINKS=\"-P\"\n\nif compctl &> /dev/null; then\n [ \"$_Z_NO_PROMPT_COMMAND\" ] || {\n  # zsh populate directory list, avoid clobbering any other precmds\n  if [ \"$_Z_NO_RESOLVE_SYMLINKS\" ]; then\n    _z_precmd() {\n      _z --add \"${PWD:a}\"\n    }\n  else\n    _z_precmd() {\n      _z --add \"${PWD:A}\"\n    }\n  fi\n  precmd_functions+=(_z_precmd)\n }\n # zsh tab completion\n _z_zsh_tab_completion() {\n  local compl\n  read -l compl\n  reply=(${(f)\"$(_z --complete \"$compl\")\"})\n }\n compctl -U -K _z_zsh_tab_completion _z\nelif complete &> /dev/null; then\n # bash tab completion\n complete -o filenames -C '_z --complete \"$COMP_LINE\"' ${_Z_CMD:-z}\n [ \"$_Z_NO_PROMPT_COMMAND\" ] || {\n  # bash populate directory list. avoid clobbering other PROMPT_COMMANDs.\n  grep -q \"_z --add\" <<< \"$PROMPT_COMMAND\" || {\n   PROMPT_COMMAND='_z --add \"$(pwd '$_Z_RESOLVE_SYMLINKS' 2>/dev/null)\" 2>/dev/null;'\"$PROMPT_COMMAND\"\n  }\n }\nfi\n"
  }
]