packages feed

open-browser 0.3.0.1 → 0.5.1.0

raw patch · 11 files changed

Files

CHANGELOG.md view
@@ -6,6 +6,23 @@ and this project adheres to the
 [Haskell Package Versioning Policy](https://pvp.haskell.org/).
 
+## 0.5.1.0 - 2026-07-02
+
+* Fix a regression on unsupported operating systems.
+
+## 0.5.0.0 - 2026-06-22
+
+* Fix a regression on Linux operating systems, whereby `xdg-open` would not
+  return until the browser was closed.
+* Replace utility `openBrowserWithExitCode` with `openBrowserWithException`.
+
+## 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 +48,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 +58,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 +72,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,27 @@   ( main
   ) where
 
-import Web.Browser ( openBrowser )
+import Control.Exception ( Exception (..), SomeException )
+import Web.Browser ( openBrowser, openBrowserWithException )
 
 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 (Maybe SomeException)
+  tryOpenGoodUrl = openBrowserWithException "https://haskell.org/"
+  tryOpenBadUrl :: IO (Maybe SomeException)
+  tryOpenBadUrl = openBrowserWithException "example-bad-url"
+  reportResult = \case
+    Just e -> putStrLn $ "Exception: " <> displayException e
+    Nothing -> putStrLn "Nothing to report"
+  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
+  , openBrowserWithException
   ) where
 
+import           Control.Exception ( Exception (..), SomeException, try)
+import           Data.Maybe ( isNothing )
 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,28 @@ --   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 =
+  isNothing <$> (openBrowserWithException url :: IO (Maybe SomeException))
+
+-- | Exported to help with debugging. As for 'openBrowser' but returns 'Nothing'
+-- or 'Just' an exception.
+--
+-- @since 0.5.0.0
+openBrowserWithException ::
+     Exception e
+  => String
+     -- ^ URL or other item to try to open.
+  -> IO (Maybe e)
+openBrowserWithException url = try (OS.openBrowser url) >>= \case
+  Left e -> pure $ Just e
+  Right () -> pure Nothing
− 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
@@ -7,11 +7,18 @@   ( openBrowser
   ) where
 
-import Utils ( openBrowserWith )
+import           Control.Monad ( void )
+import           System.Process
+                   ( CreateProcess (..), StdStream (..), createProcess, proc )
 
 -- https://ss64.com/mac/open.html
 openBrowser ::
      String
-     -- ^ URL
-  -> IO Bool
-openBrowser url = openBrowserWith "open" [url]
+     -- ^ URL or other item to try to open.
+  -> IO ()
+openBrowser url = void $ createProcess (proc "open" [url])
+  { std_in = NoStream
+  , std_out = NoStream
+  , std_err = NoStream
+  , close_fds = True
+  }
lib/unix-like/xdg-open/Web/Browser/OS.hs view
@@ -1,31 +1,23 @@ --------------------------------------------------------------------------------
--- 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
   ) where
 
-import Utils ( openBrowserWith )
+import           Control.Monad ( void )
+import           System.Process
+                   ( CreateProcess (..), StdStream (..), createProcess, proc )
 
 -- https://ss64.com/bash/xdg-open.html
 openBrowser ::
      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 ()
+openBrowser url = void $ createProcess (proc "xdg-open" [url])
+  { std_in = NoStream
+  , std_out = NoStream
+  , std_err = NoStream
+  , close_fds = True
+  }
lib/unsupported-os/Web/Browser/OS.hs view
@@ -8,6 +8,8 @@ 
 openBrowser ::
      String
-     -- ^ URL
-  -> IO Bool
-openBrowser = const (pure False) -- Operation never succeeds
+     -- ^ URL or other item to try to open.
+  -> IO ()
+openBrowser _ =
+  -- Operation never succeeds
+  error "openBrowser: Unsupported operating system."
lib/windows/Web/Browser/OS.hs view
@@ -11,8 +11,11 @@   ( openBrowser
   ) where
 
-import System.Win32.Types
-         ( HANDLE, HINSTANCE, INT, LPCWSTR, handleToWord, nullPtr, withTString )
+import           Control.Monad ( unless )
+import           System.Win32.Types
+                   ( HANDLE, HINSTANCE, INT, LPCWSTR, handleToWord, nullPtr
+                   , withTString
+                   )
 
 type HWND = HANDLE
 
@@ -26,14 +29,16 @@ 
 openBrowser ::
      String
-     -- ^ URL
-  -> IO Bool
-openBrowser url =
-  withTString "open" $ \openStr ->
-    withTString url $ \urlStr -> exitCodeToBool <$>
+     -- ^ URL or other item to try to open.
+  -> IO ()
+openBrowser url = do
+  hinst <- withTString "open" $ \openStr ->
+    withTString url $ \urlStr ->
       c_ShellExecute nullPtr openStr urlStr nullPtr nullPtr sW_SHOWNORMAL
- where
-  exitCodeToBool hinst = handleToWord hinst > 32
+  let exitcode = fromIntegral (handleToWord hinst) :: Int
+  unless (exitcode > 32) $ error $
+       "openBrowser: ShellExecuteW \"open\" failed with exit code: "
+    <> show 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
@@ -1,86 +1,80 @@ cabal-version: 1.12
---- This file has been generated from package.yaml by hpack version 0.38.0.------ see: https://github.com/sol/hpack--name:           open-browser-version:        0.3.0.1-synopsis:       Open a web browser from Haskell-description:    Open a web browser from Haskell. Windows, macOS, Linux and BSD are supported.-category:       Web-homepage:       https://github.com/mpilgrem/open-browser-bug-reports:    https://github.com/mpilgrem/open-browser/issues-author:         rightfold-maintainer:     public@pilgrem.com-license:        BSD3-license-file:   LICENSE-build-type:     Simple-tested-with:-    GHC >= 8.4-extra-source-files:-    CHANGELOG.md-    README.md-    stack.yaml-    stack.yaml.lock--source-repository head-  type: git-  location: https://github.com/mpilgrem/open-browser--flag example-  description: Build the example application-  manual: True-  default: False--library-  hs-source-dirs:-      lib-  exposed-modules:-      Web.Browser-  build-depends:-      base ==4.*-  default-language: Haskell2010-  if os(windows)-    other-modules:-        Web.Browser.OS-    hs-source-dirs:-        lib/windows-    build-depends:-        Win32 <3-  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-    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-      else-        other-modules:-            Web.Browser.OS-        hs-source-dirs:-            lib/unsupported-os--executable open-browser-example-  main-is: Main.hs-  hs-source-dirs:-      example-  build-depends:-      base ==4.*-    , open-browser-  default-language: Haskell2010-  if !flag(example)-    buildable: False+
+-- This file has been generated from package.yaml by hpack version 0.39.6.
+--
+-- see: https://github.com/sol/hpack
+
+name:           open-browser
+version:        0.5.1.0
+synopsis:       Open a web browser from Haskell
+description:    Open a web browser from Haskell. Windows, macOS, Linux and BSD are supported.
+category:       Web
+homepage:       https://github.com/mpilgrem/open-browser
+bug-reports:    https://github.com/mpilgrem/open-browser/issues
+author:         rightfold
+maintainer:     public@pilgrem.com
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+tested-with:
+    GHC >= 8.4
+extra-source-files:
+    CHANGELOG.md
+    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/mpilgrem/open-browser
+
+flag example
+  description: Build the example application
+  manual: True
+  default: False
+
+library
+  hs-source-dirs:
+      lib
+  exposed-modules:
+      Web.Browser
+  build-depends:
+      base ==4.*
+  default-language: Haskell2010
+  if os(windows)
+    other-modules:
+        Web.Browser.OS
+    hs-source-dirs:
+        lib/windows
+    build-depends:
+        Win32 <3
+  else
+    if os(darwin)
+      other-modules:
+          Web.Browser.OS
+      hs-source-dirs:
+          lib/unix-like/open
+      build-depends:
+          process >=1.2.0.0 && <2
+    else
+      if os(linux) || os(freebsd) || os(openbsd) || os(netbsd)
+        other-modules:
+            Web.Browser.OS
+        hs-source-dirs:
+            lib/unix-like/xdg-open
+        build-depends:
+            process >=1.2.0.0 && <2
+      else
+        other-modules:
+            Web.Browser.OS
+        hs-source-dirs:
+            lib/unsupported-os
+
+executable open-browser-example
+  main-is: Main.hs
+  hs-source-dirs:
+      example
+  build-depends:
+      base ==4.*
+    , open-browser
+  default-language: Haskell2010
+  if !flag(example)
+    buildable: False
− stack.yaml
@@ -1,1 +0,0 @@-snapshot: lts-23.14 # GHC 9.8.4
− stack.yaml.lock
@@ -1,12 +0,0 @@-# 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