Adding password manager for my own good
This commit is contained in:
parent
bdf505f52f
commit
310dfd47eb
3 changed files with 61 additions and 0 deletions
|
@ -24,6 +24,9 @@ import qualified Solarized as S
|
|||
import qualified Scratchpad as R
|
||||
import qualified XMonad.StackSet as W
|
||||
|
||||
-- Custom (in libs)
|
||||
import Password (passPrompt)
|
||||
|
||||
modify :: XConfig l -> XConfig l
|
||||
modify conf = conf
|
||||
{ modMask = mod4Mask -- Use the "Win" key for the mod key
|
||||
|
@ -57,6 +60,7 @@ modify conf = conf
|
|||
, ("M-p n", switchProjectPrompt promptConfig)
|
||||
, ("M-p r", renameProjectPrompt promptConfig)
|
||||
, ("M-p s", shellPrompt promptConfig)
|
||||
, ("M-d", passPrompt promptConfig)
|
||||
-- Scratchpads
|
||||
, ("M-p p", namedScratchpadAction R.pads "htop")
|
||||
]
|
||||
|
|
56
lib/Password.hs
Normal file
56
lib/Password.hs
Normal file
|
@ -0,0 +1,56 @@
|
|||
-- Initially from
|
||||
-- https://github.com/MasseR/xmonad-masser/blob/master/src/XMonad/Password.hs
|
||||
|
||||
module Password (passGeneratePrompt, passPrompt) where
|
||||
|
||||
import Control.Monad.Trans (liftIO)
|
||||
import Data.Function (on)
|
||||
import Data.List (foldl', scanl', sort, sortBy)
|
||||
import System.Directory (getHomeDirectory)
|
||||
import System.FilePath.Posix (dropExtension, takeExtension, (</>))
|
||||
import System.Posix.Env (getEnv)
|
||||
import XMonad.Core
|
||||
import XMonad.Prompt
|
||||
import XMonad.Util.Run (runProcessWithInput)
|
||||
|
||||
newtype Pass = Pass { passLabel :: String }
|
||||
|
||||
-- Rosetta code levenshtein
|
||||
levenshtein :: String -> String -> Int
|
||||
levenshtein s1 s2 = last $ foldl' transform [0..length s1] s2
|
||||
where
|
||||
transform [] _ = []
|
||||
transform ns@(n:ns1) c = scanl' calc (n+1) $ zip3 s1 ns ns1
|
||||
where
|
||||
calc z (c1, x, y) = minimum [y+1, z+1, x + (fromEnum (c1 /= c) * 2)]
|
||||
|
||||
instance XPrompt Pass where
|
||||
showXPrompt p = passLabel p <> ": "
|
||||
commandToComplete _ = id
|
||||
nextCompletion _ = getNextCompletion
|
||||
|
||||
passGeneratePrompt :: XPConfig -> X ()
|
||||
passGeneratePrompt _ = return () -- Not implemented
|
||||
|
||||
passPrompt :: XPConfig -> X ()
|
||||
passPrompt = mkPassPrompt "Select password" selectPassword
|
||||
|
||||
mkPassPrompt :: String -> (String -> X ()) -> XPConfig -> X ()
|
||||
mkPassPrompt label f conf = do
|
||||
-- I'm just sorting here, but could use some kind of fuzzy matching instead, but it requires a bit more effort
|
||||
passwords <- sort <$> liftIO getPasswords
|
||||
-- Other change, use infixof instead of prefixof
|
||||
mkXPrompt (Pass label) conf (\input -> pure (sortBy (compare `on` levenshtein input) . filter (consumes input) $ passwords)) f
|
||||
where
|
||||
consumes [] _ = True -- everything consumed
|
||||
consumes (_:_) [] = False -- all not consumed
|
||||
consumes (a:xs) (a':ys) | a == a' = consumes xs ys
|
||||
| otherwise = consumes (a:xs) ys
|
||||
getPasswords = do
|
||||
passwordStoreDir <- (</> "pass") <$> getHomeDirectory
|
||||
files <- runProcessWithInput "find" [ passwordStoreDir, "-type", "f", "-name", "*.gpg", "-printf", "%p\n"] []
|
||||
return . lines $ files
|
||||
|
||||
selectPassword :: String -> X ()
|
||||
selectPassword pass = spawn $ "gpg --decrypt " ++ pass ++ " | /home/eeva/.nix-profile/bin/copy"
|
||||
|
|
@ -17,6 +17,7 @@ import XMonad.Layout.ResizableTile (ResizableTall(..))
|
|||
import XMonad.Layout.Spacing
|
||||
import XMonad.Layout.ToggleLayouts (toggleLayouts)
|
||||
|
||||
|
||||
import XMonad.Util.EZConfig
|
||||
import qualified Solarized as S
|
||||
|
||||
|
|
Loading…
Reference in a new issue