editor-open 0.2.0.0 → 0.3.0.0
raw patch · 2 files changed
+130/−84 lines, 2 filesdep +conduitdep +conduit-extradep +directoryPVP ok
version bump matches the API change (PVP)
Dependencies added: conduit, conduit-extra, directory, resourcet, transformers
API changes (from Hackage documentation)
+ Text.Editor: bracketConduit :: Template -> Producer (ResourceT IO) ByteString -> Consumer ByteString (ResourceT IO) b -> ResourceT IO (ExitCode, b)
Files
- editor-open.cabal +12/−6
- src/Text/Editor.hs +118/−78
editor-open.cabal view
@@ -1,5 +1,5 @@ name: editor-open-version: 0.2.0.0+version: 0.3.0.0 synopsis: Open the user's $EDITOR for text input. description: You know when you run @git commit@, and an editor pops open so you can enter a@@ -7,7 +7,7 @@ . This library isn't very portable. It relies on the @$EDITOR@ environment variable. The concept only exists on *nix systems.-homepage: https://notabug.org/pharpend/editor-open+homepage: https://github.com/pharpend/editor-open license: Apache-2.0 license-file: LICENSE author: Peter Harpending@@ -16,7 +16,7 @@ category: Text build-type: Simple cabal-version: >=1.10-bug-reports: https://notabug.org/pharpend/editor-open/issues/new+bug-reports: https://github.com/pharpend/editor-open/issues/new extra-source-files: README.md data-files:@@ -32,11 +32,17 @@ LambdaCase MultiWayIf OverloadedStrings+ RankNTypes build-depends: base ==4.8.* , bytestring+ , conduit >=1.2.3 && <1.3+ , conduit-extra+ , directory , process >=1.2+ , resourcet , temporary+ , transformers , unix exposed-modules: Text.Editor@@ -54,9 +60,9 @@ source-repository head type: git- location: https://notabug.org/pharpend/editor-open.git+ location: https://github.com/pharpend/editor-open.git source-repository this type: git- location: https://notabug.org/pharpend/editor-open.git- tag: 0.2.0.0+ location: https://github.com/pharpend/editor-open.git+ tag: 0.3.0.0
src/Text/Editor.hs view
@@ -27,96 +27,52 @@ module Text.Editor where +import Control.Monad.Trans.Resource+import Control.Monad.IO.Class import qualified Data.ByteString as B import Data.ByteString (ByteString) import Data.ByteString.Char8 (unpack)+import Data.Conduit+import Data.Conduit.Binary+import Data.Conduit.Process import Data.Monoid+import System.Directory (getTemporaryDirectory, removeFile)+import System.Exit (ExitCode) import System.IO import System.IO.Temp import System.Process import System.Posix --- == Porcelain functions =---- |If you don't want to use ByteString, use this function.--- --- >>> :t runUserEditorDWIM plainTemplate mempty--- ByteString--- >>> :t wrapStr <$> runUserEditorDWIM plainTemplate mempty--- String-wrapStr :: ByteString -> String-wrapStr = unpack---- |This is most likely the function you want to use. It takes a file--- type template as an argument, along with what you want displayed--- when the user opens the editor. It then runs the editor, and--- returns the version of the text that the user modified.--- --- @--- runUserEditorDWIM templ initialContents = userEditorDefault _default_editor >>= \theEditor ->--- runSpecificEditor theEditor templ initialContents--- @--- --- --- Examples:--- --- >>> :set -XOverloadedStrings--- >>> runUserEditorDWIM jsonTemplate "{\n\n}\n"--- --- This will open up the user's @$EDITOR@ configured to edit JSON, and--- with the initial text:--- --- @--- {--- }--- @--- --- There are a bunch of templates. See the "File-type extensions"--- section. It's also trivially easy to make your own templates. Say--- you want one for, I dunno, Python:--- --- @--- pythonTemplate = mkTemplate "py"--- @--- --- The argument to 'mkTemplate' should be the file extension you--- want. In that case, I used @"py"@, because Python's file extension--- is @.py@.-runUserEditorDWIM :: Template -- ^Template for the file name- -> ByteString -- ^Initial contents- -> IO ByteString -- ^Resulting ByteString-runUserEditorDWIM templ initialContents = userEditorDefault _default_editor >>= \theEditor ->- runSpecificEditor theEditor templ initialContents---- |This is the same as above, it just takes a file as an argument--- instead of the ByteString--- --- @--- runUserEditorDWIMFile templ fp = B.readFile fp >>= runUserEditorDWIM templ--- @-runUserEditorDWIMFile :: Template -- ^Template for the file name- -> FilePath -- ^File containing initial contents- -> IO ByteString -- ^Resulting ByteString-runUserEditorDWIMFile templ fp = B.readFile fp >>= runUserEditorDWIM templ---- |This is likely the simplest function here. It opens up the user's editor,--- and fetches a ByteString from it+-- |This is the function you should use. -- --- @--- runUserEditor = userEditorDefault _default_editor >>= \theEditor ->--- runSpecificEditor theEditor plainTemplate mempty--- @-runUserEditor :: IO ByteString-runUserEditor = userEditorDefault _default_editor >>= \theEditor ->- runSpecificEditor theEditor plainTemplate mempty---- |This is probably the second-simplest function.+-- 'bracketConduit' takes a 'Producer', to produce the contents of the+-- original file, and a 'Consumer' to consume them, and returns the+-- result of the consumer, along with the exit code from the editor. -- +-- If you don't know how to use conduits, see the+-- <http://www.stackage.org/package/conduit documentation> for the+-- conduit package. -- -runUserEditorWithTemplate :: Template -- ^Template for the file name- -> IO ByteString -- ^Resulting ByteString-runUserEditorWithTemplate templ = userEditorDefault _default_editor >>= \theEditor ->- runSpecificEditor theEditor templ mempty+-- If you really don't want to use conduits, you can use the strict I/O+-- functions at the bottom of the module. Be warned that those functions+-- are not very performant.+bracketConduit :: Template+ -> Producer (ResourceT IO) ByteString+ -> Consumer ByteString (ResourceT IO) b+ -> ResourceT IO (ExitCode,b)+bracketConduit template producer consumer =+ do userEditor_ <-+ liftIO (userEditorDefault _default_editor)+ systemTempDirectory <- liftIO getTemporaryDirectory+ (filePath,handle) <-+ liftIO (openBinaryTempFile systemTempDirectory template)+ connect producer (sinkHandle handle)+ liftIO (hClose handle)+ result <-+ sourceProcessWithConsumer (proc userEditor_ [filePath])+ consumer+ liftIO (removeFile filePath)+ return result -- == File-type extensions == -- @@ -273,3 +229,87 @@ -- @ _ftempl :: String _ftempl = "tmp"++-- == Bad functions =+-- +-- These are memory hogs, but exist for backwards compatibility++-- |If you don't want to use ByteString, use this function.+-- +-- >>> :t runUserEditorDWIM plainTemplate mempty+-- ByteString+-- >>> :t wrapStr <$> runUserEditorDWIM plainTemplate mempty+-- String+wrapStr :: ByteString -> String+wrapStr = unpack++-- |This is most likely the function you want to use. It takes a file+-- type template as an argument, along with what you want displayed+-- when the user opens the editor. It then runs the editor, and+-- returns the version of the text that the user modified.+-- +-- @+-- runUserEditorDWIM templ initialContents = userEditorDefault _default_editor >>= \theEditor ->+-- runSpecificEditor theEditor templ initialContents+-- @+-- +-- +-- Examples:+-- +-- >>> :set -XOverloadedStrings+-- >>> runUserEditorDWIM jsonTemplate "{\n\n}\n"+-- +-- This will open up the user's @$EDITOR@ configured to edit JSON, and+-- with the initial text:+-- +-- @+-- {+-- }+-- @+-- +-- There are a bunch of templates. See the "File-type extensions"+-- section. It's also trivially easy to make your own templates. Say+-- you want one for, I dunno, Python:+-- +-- @+-- pythonTemplate = mkTemplate "py"+-- @+-- +-- The argument to 'mkTemplate' should be the file extension you+-- want. In that case, I used @"py"@, because Python's file extension+-- is @.py@.+runUserEditorDWIM :: Template -- ^Template for the file name+ -> ByteString -- ^Initial contents+ -> IO ByteString -- ^Resulting ByteString+runUserEditorDWIM templ initialContents = userEditorDefault _default_editor >>= \theEditor ->+ runSpecificEditor theEditor templ initialContents++-- |This is the same as above, it just takes a file as an argument+-- instead of the ByteString+-- +-- @+-- runUserEditorDWIMFile templ fp = B.readFile fp >>= runUserEditorDWIM templ+-- @+runUserEditorDWIMFile :: Template -- ^Template for the file name+ -> FilePath -- ^File containing initial contents+ -> IO ByteString -- ^Resulting ByteString+runUserEditorDWIMFile templ fp = B.readFile fp >>= runUserEditorDWIM templ++-- |This is likely the simplest function here. It opens up the user's editor,+-- and fetches a ByteString from it+-- +-- @+-- runUserEditor = userEditorDefault _default_editor >>= \theEditor ->+-- runSpecificEditor theEditor plainTemplate mempty+-- @+runUserEditor :: IO ByteString+runUserEditor = userEditorDefault _default_editor >>= \theEditor ->+ runSpecificEditor theEditor plainTemplate mempty++-- |This is probably the second-simplest function.+-- +-- +runUserEditorWithTemplate :: Template -- ^Template for the file name+ -> IO ByteString -- ^Resulting ByteString+runUserEditorWithTemplate templ = userEditorDefault _default_editor >>= \theEditor ->+ runSpecificEditor theEditor templ mempty