packages feed

mdoc-0.3.0.0: src/Mdoc/Examples/Pass.hs

-- |
--
-- Module      : Mdoc.Examples.Pass
-- Copyright   : (c) 2026 Patrick Brisbin
-- License     : AGPL-3
-- Maintainer  : pbrisbin@gmail.com
-- Stability   : experimental
-- Portability : POSIX
module Mdoc.Examples.Pass
  ( pass1
  ) where

import Mdoc.Prelude

import Mdoc.Data.Named
import Mdoc.Data.Page (setPrologue)
import Mdoc.Syntax
import Options.Applicative
import Options.Applicative.Mdoc

pass1 :: Named
pass1 =
  mempty
    & (<> getPage passOpt)
    & setPrologue
      ( Mdoc
          [ MacroLine Nm []
          , TextLine "is a very simple password store that keeps passwords inside"
          , MacroLine Xr ["gpg2", "1"]
          , TextLine "encrypted files inside a simple directory tree residing at"
          , MacroLine Pa ["~/.password-store", "."]
          , TextLine
              "The pass utility provides a series of commands for manipulating the password store, allowing the user to add, remove, edit, synchronize, generate, and manipulate passwords."
          , MacroLine Pp []
          , TextLine "If no COMMAND is specified, COMMAND defaults to either"
          , MacroLine Cm ["show"]
          , TextLine "or"
          , MacroLine Cm ["ls", ","]
          , TextLine "depending on the type of specifier in ARGS. Alternatively, if"
          , MacroLine Ar ["PASSWORD_STORE_ENABLE_EXTENSIONS"]
          , TextLine "is set to \"true\", and the file"
          , MacroLine Pa [".extensions/COMMAND.bash"]
          , TextLine
              "exists inside the password store and is executable, then it is sourced into the environment, passing any arguments and environment variables. Extensions existing in a system- wide directory, only installable by the administrator, are always enabled."
          , MacroLine Pp []
          , TextLine "Otherwise COMMAND must be one of the valid commands listed below."
          , MacroLine Pp []
          , TextLine
              "Several of the commands below rely on or provide additional functionality if the password store directory is also a git repository. If the password store directory is a git repository, all password store modification commands will cause a corresponding git commit. Sub- directories may be separate nested git repositories, and pass will use the inner-most directory relative to the current password. See the"
          , MacroLine Ar ["EXTENDED", "GIT", "EXAMPLE"]
          , TextLine "section for a detailed description using init and"
          , MacroLine Xr ["git", "1"]
          , MacroLine Pp []
          , TextLine "The"
          , MacroLine Cm ["init"]
          , TextLine
              "command must be run before other commands in order to initialize the password store with the correct gpg key id. Passwords are encrypted using the gpg key set with"
          , MacroLine Cm ["init", "."]
          , MacroLine Pp []
          , TextLine
              "There is a corresponding bash completion script for use with tab completing password names in"
          , MacroLine Xr ["bash", "1", "."]
          ]
      )
    & name "pass" "stores, retrieves, generates, and synchronizes passwords securely"

{- FOURMOLU_DISABLE -}
passOpt :: Parser ()
passOpt = void $ subparser (mconcat
  [ command "init"    $ info initOpt   $ progDesc "Initialize new password storage and use gpg-id for encryption. Multiple gpg-ids may be specified, in order to encrypt each password with multiple ids. This command must be run first before a password store can be used. If the specified gpg-id is different from the key used in any existing files, these files will be reencrypted to use the new id. Note that use of gpg-agent(1) is recommended so that the batch decryption does not require as much user intervention. If --path or -p is specified, along with an argument, a specific gpg-id or set of gpg-ids is assigned for that specific sub folder of the password store. If only one gpg-id is given, and it is an empty string, then the current .gpg-id file for the specified sub-folder (or root if unspecified) is removed."
  , command "ls"      $ info lsOpt     $ progDesc "List names of passwords inside the tree at subfolder by using the tree(1) program. This command is alternatively named list."
  , command "grep"    $ info grepOpt   $ progDesc "Searches inside each decrypted password file for search-string, and displays line containing matched string along with filename. Uses grep(1) for matching. GREPOPTIONS are passed to grep(1) as-is. (Note: the GREP_OPTIONS environment variable functions as well.)"
  , command "find"    $ info findOpt   $ progDesc "List names of passwords inside the tree that match pass-names by using the tree(1) program. This command is alternatively named search."
  , command "show"    $ info showOpt   $ progDesc "Decrypt and print a password named pass-name. If --clip or -c is specified, do not print the password but instead copy the first (or otherwise specified) line to the clipboard using xclip(1) or wl-clipboard(1) and then restore the clipboard after 45 (or PASSWORD_STORE_CLIP_TIME) seconds. If --qrcode or -q is specified, do not print the password but instead display a QR code using qrencode(1) either to the terminal or graphically if supported."
  , command "help"    $ info (pure ()) $ progDesc "Show usage message."
  , command "version" $ info (pure ()) $ progDesc "Show version information."
  ])

initOpt :: Parser ()
initOpt = void $ (,)
  <$> optional (option (str @Text) (short 'p' <> long "path" <> metavar "sub-folder"))
  <*> argument (str @Text) (metavar "gpg-id")

lsOpt :: Parser ()
lsOpt = void $ argument (str @Text) (metavar "subfolder") -- sic

grepOpt :: Parser ()
grepOpt = void $ (,)
  <$> optional (argument (str @Text) (metavar "GREPOPTIONS"))
  <*> argument (str @Text) (metavar "search-string")

findOpt :: Parser ()
findOpt = void $ some1 $ argument (str @Text) (metavar "pass-names")

showOpt :: Parser ()
showOpt = void $ (,,)
  <$> optional (option (str @Text) (short 'c' <> long "clip" <> metavar "line-number"))
  <*> optional (option (str @Text) (short 'q' <> long "qrcode" <> metavar "line-number"))
  <*> argument (str @Text) (metavar "pass-name")
{- FOURMOLU_ENABLE -}