XMonad Loves password-store

I'm a big fan on password-store, a simple command line password-manager which encrypts your passwords via GnuPG in separate files. It's simple, easy to use, and very extensible.

While it has completion on the command line, it falls short in the XMonad prompt. Igor Babuschkin recently wrote some code to implement a prompt for password-store in XMonad. This works fine for flat directories, but doesn't complete passwords in directory-hierarchies.

Using his code as a basis, I applied my marginal Haskell skills and expanded the code to work with nested directories:

import System.Environment
import System.FilePath.Posix
import System.FilePath.Find
import XMonad.Prompt
import System.Directory

data Pass = Pass

instance XPrompt Pass where
  showXPrompt       Pass = "Pass: "
  commandToComplete _ c  = c
  nextCompletion      _  = getNextCompletion

passPrompt :: XPConfig -> X ()
passPrompt c = do
  li <- io getPasswords
  mkXPrompt Pass c (mkComplFunFromList li) selectPassword

selectPassword :: String -> X ()
selectPassword s = spawn $ "pass -c " ++ s

getPasswords :: IO [String]
getPasswords = do
  home <- getEnv "HOME"
  let passwordStore = home </> ".password-store"
  entries <- find System.FilePath.Find.always (fileName ~~? "*.gpg") $
    passwordStore
  return $ map ((makeRelative passwordStore) . dropExtension) entries 

One drawback is the dependency on System.FilePath.Find (from filemanip) - you have to install this package via cabal or similar.

After integrating this into your xmonad.hs, bind passPrompt myXPConfig to some key.