packages feed

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 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