open-browser 0.3.0.1 → 0.4.0.0
raw patch · 11 files changed
+128/−99 lines, 11 filesdep ~processPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: process
API changes (from Hackage documentation)
+ Web.Browser: openBrowserWithExitCode :: Exception e => String -> IO (Either e (ExitCode, String, String))
Files
- CHANGELOG.md +17/−6
- example/Main.hs +26/−4
- lib/Web/Browser.hs +35/−9
- lib/unix-like/common/Utils.hs +0/−20
- lib/unix-like/open/Web/Browser/OS.hs +7/−6
- lib/unix-like/xdg-open/Web/Browser/OS.hs +8/−22
- lib/unsupported-os/Web/Browser/OS.hs +9/−5
- lib/windows/Web/Browser/OS.hs +10/−7
- open-browser.cabal +3/−7
- stack.yaml +1/−1
- stack.yaml.lock +12/−12
CHANGELOG.md view
@@ -6,6 +6,13 @@ and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). +## 0.4.0.0 - 2025-04-02 + +* On Unix-like operating systems, use Haskell to silence the opening + application or script, rather than the `sh` shell on Linux and BSD. +* Add utility `openBrowserWithExitCode`, to help with debugging failure. +* Improve Haddock documentation. + ## 0.3.0.1 - 2025-03-17 * On Windows, remove unnecessary dependency on `process`. @@ -31,8 +38,9 @@ * As released by rightfold on Hackage. This entry and prior change log is reconstructed. -* Support GHC versions before GHC 8.0. -* Add support for 32-bit Windows. +* Support GHC versions before GHC 8.0, by removing the Byte Order Mark from + source files. +* Add support for 32-bit Windows, by using the `stdcall` calling convention. ## 0.2.0.0 - 2015-07-31 @@ -40,11 +48,13 @@ ## 0.1.4.0 - 2015-07-30 -* On Linux, silence `xdg-open`. +* On Linux and BSD, silence the `xdg-open` script using the `sh` shell. ## 0.1.3.0 - 2015-07-27 -* Add support for BSD and Windows. +* Add support for BSD, using the `xdg-open` script. +* Add support for Windows, using the Win32 API and the `ccall` calling + convention. ## 0.1.2.0 - 2015-07-27 @@ -52,8 +62,9 @@ ## 0.1.1.0 - 2015-07-27 -* Add support for Linux. +* Add support for Linux, using the `xdg-open` script. +* On OS X, use the `open` application. ## 0.1.0.0 - 2015-07-25 -* Initial version. Only OS X supported. +* Initial version. Only OS X supported, using `open location` in an AppleScript.
example/Main.hs view
@@ -4,9 +4,31 @@ ( main ) where -import Web.Browser ( openBrowser ) +import Control.Exception ( Exception (..), SomeException ) +import System.Exit ( ExitCode (..) ) +import Web.Browser ( openBrowser, openBrowserWithExitCode ) main :: IO () -main = openBrowser "https://haskell.org/" >>= \case - True -> putStrLn "The operation succeeded!" - False -> putStrLn "The operation failed!" +main = do + openBrowser "https://haskell.org/" >>= \case + True -> putStrLn "The operation succeeded!" + False -> putStrLn "The operation failed!" + blankLine + putStrLn "Help with debugging:" + putStrLn "Try a good URL:" + tryOpenGoodUrl >>= reportResult + blankLine + putStrLn "Try a bad URL:" + tryOpenBadUrl >>= reportResult + where + tryOpenGoodUrl :: IO (Either SomeException (ExitCode, String, String)) + tryOpenGoodUrl = openBrowserWithExitCode "https://haskell.org/" + tryOpenBadUrl :: IO (Either SomeException (ExitCode, String, String)) + tryOpenBadUrl = openBrowserWithExitCode "example-bad-url" + reportResult = \case + Left e -> putStrLn $ "Exception: " <> displayException e + Right (ec, out, err) -> do + putStrLn $ "Exit code: " <> show ec + putStrLn $ "Standard output: " <> out + putStrLn $ "Standard error: " <> err + blankLine = putStrLn ""
lib/Web/Browser.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE LambdaCase #-} + {-| Module : Web.Browser Description : Open a web browser from Haskell @@ -11,14 +13,18 @@ module Web.Browser ( openBrowser + -- * Utilities + , openBrowserWithExitCode ) where +import Control.Exception ( Exception (..), SomeException, try) +import System.Exit ( ExitCode (..) ) import qualified Web.Browser.OS as OS --- | Seeks to open the given item. If the item is a URL or another item --- associated with a web browser (for example, it represents a local @.html@ --- file), seeks to open it in the user's preferred web browser. Returns whether --- or not the operation succeeded. +-- | Seeks to open the given item, silently. If the item is a URL or another +-- item associated with a web browser (for example, it represents a local +-- @.html@ file), seeks to open it in the user's preferred web browser. Returns +-- whether or not the operation succeeded. -- -- No checks are performed on the nature or validity of the given item. -- @@ -31,13 +37,33 @@ -- item that represents a file, equivalent to double-clicking on the file's -- icon; and -- --- * on Linux, FreeBSD, OpenBSD or NetBSD, the \'xdg-open\' application, if it --- is on the user's PATH, via \'sh\' to allow the application's output to be --- silenced. +-- * on Linux, FreeBSD, OpenBSD or NetBSD, the \'xdg-open\' script, if it +-- is on the user's PATH. -- -- On other operating systems, the operation always fails. +-- +-- @since 0.1.0.0 openBrowser :: String - -- ^ URL or other item to try to open + -- ^ URL or other item to try to open. -> IO Bool -openBrowser = OS.openBrowser +openBrowser url = tryOpenUrl >>= \case + Left _ -> pure False + Right (ec, _, _) -> pure $ ec == ExitSuccess + where + tryOpenUrl :: IO (Either SomeException (ExitCode, String, String)) + tryOpenUrl = openBrowserWithExitCode url + +-- | Exported to help with debugging. As for 'openBrowser' but returns either an +-- exception or, as a triple, the 'ExitCode' of the opening mechanism and any +-- output to the standard output and standard error channels. On failure, the +-- meaning of the exit code will depend on the operating system; for unsupported +-- operating systems, it will be 'ExitFailure' @1@. +-- +-- @since 0.4.0.0 +openBrowserWithExitCode :: + Exception e + => String + -- ^ URL or other item to try to open. + -> IO (Either e (ExitCode, String, String)) +openBrowserWithExitCode url = try $ OS.openBrowserWithExitCode url
− lib/unix-like/common/Utils.hs
@@ -1,20 +0,0 @@--------------------------------------------------------------------------------- --- For operating systems that use an application on the PATH to open the URL. --------------------------------------------------------------------------------- - -module Utils - ( openBrowserWith - ) where - -import System.Exit ( ExitCode (..) ) -import System.Process ( proc, waitForProcess, withCreateProcess ) - -openBrowserWith :: - String - -- ^ Name of relevant executable on the PATH. - -> [String] - -- ^ Arguments for executable. - -> IO Bool -openBrowserWith cmd args = - withCreateProcess (proc cmd args) $ \_ _ _ p -> - (== ExitSuccess) <$> waitForProcess p
lib/unix-like/open/Web/Browser/OS.hs view
@@ -4,14 +4,15 @@ -------------------------------------------------------------------------------- module Web.Browser.OS - ( openBrowser + ( openBrowserWithExitCode ) where -import Utils ( openBrowserWith ) +import System.Exit ( ExitCode (..) ) +import System.Process ( readProcessWithExitCode ) -- https://ss64.com/mac/open.html -openBrowser :: +openBrowserWithExitCode :: String - -- ^ URL - -> IO Bool -openBrowser url = openBrowserWith "open" [url] + -- ^ URL or other item to try to open. + -> IO (ExitCode, String, String) +openBrowserWithExitCode url = readProcessWithExitCode "open" [url] ""
lib/unix-like/xdg-open/Web/Browser/OS.hs view
@@ -1,31 +1,17 @@ -------------------------------------------------------------------------------- --- For Unix-like operating systems that provide the xdg-open application on the --- PATH. +-- For Unix-like operating systems that provide the xdg-open script on the PATH. -------------------------------------------------------------------------------- module Web.Browser.OS - ( openBrowser + ( openBrowserWithExitCode ) where -import Utils ( openBrowserWith ) +import System.Exit ( ExitCode (..) ) +import System.Process ( readProcessWithExitCode ) -- https://ss64.com/bash/xdg-open.html -openBrowser :: +openBrowserWithExitCode :: String - -- ^ URL - -> IO Bool -openBrowser url = - -- sh -c '...' - -- - -- tells the shell (sh) to execute the given string as a command, and - -- the following argument (url) is passed as a positional argument $0. - -- - -- xdg-open "$0" 2>&1 > /dev/null - -- - -- The $0 is expanded and the double quotes ensures it is treated as a single - -- argument to xdg-open. - -- - -- 2>&1 redirects standard error to standard output. - -- - -- > /dev/null discards standard output. - openBrowserWith "sh" ["-c", "xdg-open \"$0\" 2>&1 > /dev/null", url] + -- ^ URL or other item to try to open. + -> IO (ExitCode, String, String) +openBrowserWithExitCode url = readProcessWithExitCode "xdg-open" [url] ""
lib/unsupported-os/Web/Browser/OS.hs view
@@ -3,11 +3,15 @@ -------------------------------------------------------------------------------- module Web.Browser.OS - ( openBrowser + ( openBrowserWithExitCode ) where -openBrowser :: +import System.Exit ( ExitCode (..) ) + +openBrowserWithExitCode :: String - -- ^ URL - -> IO Bool -openBrowser = const (pure False) -- Operation never succeeds + -- ^ URL or other item to try to open. + -> IO (ExitCode, String, String) +openBrowserWithExitCode = + -- Operation never succeeds + const (pure (ExitFailure 1, "", "Unsupported operating system."))
lib/windows/Web/Browser/OS.hs view
@@ -8,9 +8,10 @@ -------------------------------------------------------------------------------- module Web.Browser.OS - ( openBrowser + ( openBrowserWithExitCode ) where +import System.Exit ( ExitCode (..) ) import System.Win32.Types ( HANDLE, HINSTANCE, INT, LPCWSTR, handleToWord, nullPtr, withTString ) @@ -24,16 +25,18 @@ sW_SHOWNORMAL :: INT sW_SHOWNORMAL = 1 -openBrowser :: +openBrowserWithExitCode :: String - -- ^ URL - -> IO Bool -openBrowser url = + -- ^ URL or other item to try to open. + -> IO (ExitCode, String, String) +openBrowserWithExitCode url = withTString "open" $ \openStr -> - withTString url $ \urlStr -> exitCodeToBool <$> + withTString url $ \urlStr -> exitcodeToExitCode <$> c_ShellExecute nullPtr openStr urlStr nullPtr nullPtr sW_SHOWNORMAL where - exitCodeToBool hinst = handleToWord hinst > 32 + exitcodeToExitCode hinst = + let exitcode = fromIntegral $ handleToWord hinst + in (if exitcode > 32 then ExitSuccess else ExitFailure exitcode, "", "") -- https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew foreign import ccall unsafe "windows.h ShellExecuteW"
open-browser.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: open-browser-version: 0.3.0.1+version: 0.4.0.0 synopsis: Open a web browser from Haskell description: Open a web browser from Haskell. Windows, macOS, Linux and BSD are supported. category: Web@@ -51,23 +51,19 @@ else if os(darwin) other-modules:- Utils Web.Browser.OS hs-source-dirs:- lib/unix-like/common lib/unix-like/open build-depends:- process >=1.4.3.0 && <2+ process >=1.2.0.0 && <2 else if os(linux) || os(freebsd) || os(openbsd) || os(netbsd) other-modules:- Utils Web.Browser.OS hs-source-dirs:- lib/unix-like/common lib/unix-like/xdg-open build-depends:- process >=1.4.3.0 && <2+ process >=1.2.0.0 && <2 else other-modules: Web.Browser.OS
stack.yaml view
@@ -1,1 +1,1 @@-snapshot: lts-23.14 # GHC 9.8.4 +snapshot: lts-23.17 # GHC 9.8.4
stack.yaml.lock view
@@ -1,12 +1,12 @@-# This file was autogenerated by Stack. -# You should not edit this file by hand. -# For more information, please see the documentation at: -# https://docs.haskellstack.org/en/stable/topics/lock_files - -packages: [] -snapshots: -- completed: - sha256: 1964d439d2a152be4238053f3f997a09fb348391984daab86d724975ef9a423f - size: 683814 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/14.yaml - original: lts-23.14 +# This file was autogenerated by Stack.+# You should not edit this file by hand.+# For more information, please see the documentation at:+# https://docs.haskellstack.org/en/stable/topics/lock_files++packages: []+snapshots:+- completed:+ sha256: 2763632e4c4094ce12f5ae12b22f524cdc6453b6b19007ff164a37fd9d2ea829+ size: 683819+ url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/17.yaml+ original: lts-23.17