Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactive processing of commands #9

Open
romanofski opened this issue Oct 3, 2022 · 3 comments
Open

Interactive processing of commands #9

romanofski opened this issue Oct 3, 2022 · 3 comments
Assignees

Comments

@romanofski
Copy link
Member

This is an alternate approach from #8 in that the processing and building of a ProcessConfig is build by the library itself. It will hide all interactive processing. The library will have to ask purebred for needed information in order to do that.

@frasertweedale
Copy link
Member

I think this approach might be the better one. We should defer policy questions question "where to create temporary files" to the application. Otherwise purebred-mailcap has to decide it, and I don't think that's good for portability, maintainability or separation of concerns.

Idea A: commands and continuations

Maybe the API comes in the form of commands and continuations. For example (rough idea)

data MailcapCommandStdin = NoStdin | BodyOnStdin
data MailcapCommandPrepResult
  = NeedContentType (ContentType -> MailcapCommandPrepResult)
  | NeedBodyFile (FilePath -> MailcapCommandPrepResult)
  | NeedNamedParameter String {- param name -} (String -> MailcapCommandPrepResult)
  | NeedPartFiles ([(FilePath, ContentType)] -> MailcapCommandPrepResult)
  | NeedSubpartCount (Int -> MailcapCommandPrepResult)
  | Done String {- shell command -} MailcapCommandStdin

And a function to start the processing:

prepCommand :: Entry -> MailcapCommandPrepResult

Idea B: action record

We could pass a record of actions which purebred-mailcap executes as required. For example:

data MailcapCommandPrepActions = MailcapCommandPrepActions
  { getBodyFile :: IO FilePath
  , getSubpartFile :: IO [(FilePath, ContentType)]
  , getSubpartCount :: Int
  , getContentType :: ContentType
  , getNamedParameter :: String -> B.ByteString
  }

prepCommand :: Entry -> MailcapCommandPrepActions -> IO (String {- command -}, MailcapCommandStdin)

Note that we don't have to use IO directly and in fact it would facilitate interop if we abstract over
the action context. So:

data MailcapCommandPrepActions m = MailcapCommandPrepActions
  { getBodyFile :: m FilePath
  , getSubpartFile :: m [(FilePath, ContentType)]
  , getSubpartCount :: Int
  , getContentType :: ContentType
  , getNamedParameter :: String -> B.ByteString
  }

prepCommand :: Entry -> MailcapCommandPrepActions m -> m (String {- command -}, MailcapCommandStdin)

In purebred we would likely instantiate m at (MonadError Error m, MonadIO m) => m

Notes about cleanup

We also have to consider how to handle cleaning up the temp files. I don't think purebred-mailcap should
handle clean-up. It is a policy decision of the application. We should facilitate cleanup by returning to the
application a summary of the files used. So we might end up with a result type like:

data MailcapCommand = MailcapCommand
  String -- ^ command
  MailcapCommandStdin -- ^ what the command expects on stdin
  [FilePath]  -- ^ list of file names used due to substitution

@frasertweedale frasertweedale self-assigned this Oct 5, 2022
@frasertweedale
Copy link
Member

I'll tackle this (idea B)

@romanofski
Copy link
Member Author

@frasertweedale Thanks! Just a heads up to refrain from refactorings please, since I'm still working on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants