about summary refs log tree commit diff
path: root/pkgs/profpatsch/xdg-open
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/profpatsch/xdg-open')
-rw-r--r--pkgs/profpatsch/xdg-open/config.dhall414
-rw-r--r--pkgs/profpatsch/xdg-open/default.nix4
-rw-r--r--pkgs/profpatsch/xdg-open/types.dhall50
-rw-r--r--pkgs/profpatsch/xdg-open/xdg-open.dhall124
4 files changed, 374 insertions, 218 deletions
diff --git a/pkgs/profpatsch/xdg-open/config.dhall b/pkgs/profpatsch/xdg-open/config.dhall
index a3586dda..45ef45d1 100644
--- a/pkgs/profpatsch/xdg-open/config.dhall
+++ b/pkgs/profpatsch/xdg-open/config.dhall
@@ -1,161 +1,261 @@
-let Mime = List Text
-
-let
-    -- TODO use library like with shell commands
-    Executable =
-      Text
-
-let Arg = < String : Text | Variable : Text >
-
-let CommandTemplate =
-      λ(templates : Type) → { exe : Executable, args : templates → List Arg }
-
-let Command = CommandTemplate Arg
-
-let mime =
-      { text =
-        { html = [ "text", "html" ]
-        , gemini = [ "text", "gemini" ]
-        , gopher = [ "text", "gopher" ]
-        , xml = [ "text", "xml" ]
-        , any = [ "text", "*" ]
-        }
-      , mail-address = [ "special", "mailaddress" ]
-      , torrent = [ "application", "x-bittorrent" ]
-      , irc = [ "x-scheme-handler", "irc" ]
-      , file = [ "x-scheme-handler", "file" ]
-      , image =
-        { gif = [ "image", "gif" ]
-        , svg = [ "image", "svg+xml" ]
-        , any = [ "image", "*" ]
-        }
-      , pdf = [ "application", "pdf" ]
-      , pgp-key = [ "application", "pgp-keys" ]
-      , directory = [ "inode", "directory" ]
-      , any = [ "*" ]
-      }
-
-let renderMime = λ(m : Mime) → 32
-
-let
-    -- Handler of an uri glob. Mime maps the uri to a file handler. Transparent is a command which, when run, returns a mimetype of the file.
-    UriGlobHandler =
-      < Transparent : Command | Mime : Mime >
-
-let UriMimeGlob = { desc : Text, glob : List Text, handler : UriGlobHandler }
-
-let Special =
-      { open-in-editor : Command
-      , open-in-browser : Command
-      , fetch-http-url-mime : Command
-      , compose-mail-to : Command
-      , exec-in-terminal-emulator : ∀(args : Command) → Command
-      , dmenu-list-binaries-and-exec : Command
-      }
-
-let uriMimeGlobs
-    : Special → List UriMimeGlob
-    = λ(special : Special) →
-        [ { desc = "http link"
-          , glob = [ "http://*", "https://*" ]
-          , handler =
-              let TODO = UriGlobHandler.Transparent special.fetch-http-url-mime
-
-              in  UriGlobHandler.Mime mime.text.html
-          }
-        , { desc = "gemini link"
-          , glob = [ "gemini://*" ]
-          , handler = UriGlobHandler.Mime mime.text.gemini
-          }
-        , { desc = "gemini link"
-          , glob = [ "gopher://*", "gophers://*" ]
-          , handler = UriGlobHandler.Mime mime.text.gopher
-          }
-        , { glob = [ "mailto:*" ]
-          , desc = "mail address"
-          , handler = UriGlobHandler.Mime mime.mail-address
-          }
-        , { glob = [ "magnet:*" ]
-          , desc = "bittorrent magnet link"
-          , handler = UriGlobHandler.Mime mime.torrent
-          }
-        , { desc = "irc channel"
-          , glob = [ "irc:*" ]
-          , handler = UriGlobHandler.Mime mime.irc
-          }
-        , { desc = "local file"
-          , glob = [ "file://*" ]
-          , handler = UriGlobHandler.Mime mime.file
-          }
-        ]
-
-let MimeMatch = { match : Mime, cmd : Command }
-
-let mimeMatcher =
-      λ(pkgs : { package : Text, binary : Text } → Executable) →
-      λ(special : Special) →
-        let pkgSame =
-              λ(packageAndBinaryName : Text) →
-                pkgs
-                  { package = packageAndBinaryName
-                  , binary = packageAndBinaryName
-                  }
+let types = ./types.dhall
 
-        let wrapCommand =
-              λ(wrapper : Command) →
-              λ(cmd : Command) →
-                { exe = wrapper.exe
-                , args =
-                    λ(template : Arg) →
-                        wrapper.args template
-                      # [ Arg.String cmd.exe ]
-                      # cmd.args template
-                }
+let Executable = types.Executable
+
+let Special = types.Special
+
+let Command = types.Command
+
+let Arg = types.Arg
+
+let Mime = types.Mime
+
+let UriGlobHandler = types.UriGlobHandler
+
+let UriMimeGlob = types.UriMimeGlob
+
+let MimeMatch = types.MimeMatch
+
+in  λ(pkgs : { package : Text, binary : Text } → Executable) →
+    λ(special : Special) →
+      let mime =
+            let pkgSame =
+                  λ(packageAndBinaryName : Text) →
+                    pkgs
+                      { package = packageAndBinaryName
+                      , binary = packageAndBinaryName
+                      }
+
+            let wrapCommand =
+                  λ(wrapper : Command) →
+                  λ(cmd : Command) →
+                    { exe = wrapper.exe
+                    , args =
+                        λ(template : Arg) →
+                            wrapper.args template
+                          # [ Arg.String cmd.exe ]
+                          # cmd.args template
+                    }
+
+            let
+                -- An executable that takes as its one argument the file to run
+                oneArg =
+                  λ(exe : Executable) → { exe, args = λ(file : Arg) → [ file ] }
 
-        let oneArg =
-              λ(exe : Executable) → { exe, args = λ(file : Arg) → [ file ] }
-
-        let m = λ(match : Mime) → λ(cmd : Command) → { match, cmd }
-
-        in    [ { match = mime.mail-address, cmd = special.compose-mail-to }
-              , { match = mime.text.html, cmd = special.open-in-browser }
-              , { match = mime.text.gemini, cmd = oneArg (pkgSame "lagrange") }
-              , { match = mime.text.gopher, cmd = oneArg (pkgSame "lagrange") }
-              , { match = mime.text.xml, cmd = special.open-in-browser }
-              , { match = mime.text.any, cmd = special.open-in-editor }
-              , { match = mime.image.gif, cmd = special.open-in-browser }
-              , { match = mime.image.svg, cmd = oneArg (pkgSame "inkscape") }
-              , { match = mime.image.any, cmd = oneArg (pkgSame "imv") }
-              , { match = mime.pdf, cmd = oneArg (pkgSame "zathura") }
-              , { match = mime.pgp-key
-                , cmd =
-                  { exe = pkgs { package = "gnupg", binary = "gpg" }
-                  , args =
-                      λ(file : Arg) →
-                        [ Arg.String "--import"
-                        , Arg.String "--import-options"
-                        , Arg.String "show-only"
-                        , file
-                        ]
+            in  { text =
+                  { html =
+                    { mime = [ "text", "html" ], cmd = special.compose-mail-to }
+                  , gemini =
+                    { mime = [ "text", "gemini" ]
+                    , cmd = oneArg (pkgSame "lagrange")
+                    }
+                  , gopher =
+                    { mime = [ "text", "gopher" ]
+                    , cmd = oneArg (pkgSame "lagrange")
+                    }
+                  , xml =
+                    { mime = [ "text", "xml" ], cmd = special.open-in-browser }
+                  , any =
+                    { mime = [ "text", "any" ], cmd = special.open-in-editor }
                   }
+                , mail-address =
+                  { mime = [ "special", "mailaddress" ]
+                  , cmd = special.compose-mail-to
+                  }
+                , torrent =
+                  { mime = [ "application", "x-bittorrent" ]
+                  , cmd = special.notify "No xdg-open handler for the torrent"
+                  }
+                , irc =
+                  { mime = [ "x-scheme-handler", "irc" ]
+                  , cmd = special.notify "No xdg-open handler for the irc link"
+                  }
+                , file =
+                  { mime = [ "x-scheme-handler", "file" ]
+                  , cmd =
+                      special.notify
+                        "No xdg-open handler for the x-scheme-handler/file"
+                  }
+                , image =
+                  { gif =
+                    { mime = [ "image", "gif" ], cmd = special.open-in-browser }
+                  , svg =
+                    { mime = [ "image", "svg+xml" ]
+                    , cmd = oneArg (pkgSame "inkscape")
+                    }
+                  , any =
+                    { mime = [ "image", "*" ], cmd = oneArg (pkgSame "imv") }
+                  }
+                , pdf =
+                  { mime = [ "application", "pdf" ]
+                  , cmd = oneArg (pkgSame "zathura")
+                  }
+                , pgp-key =
+                  { mime = [ "application", "pgp-keys" ]
+                  , cmd =
+                    { exe = pkgs { package = "gnupg", binary = "gpg" }
+                    , args =
+                        λ(file : Arg) →
+                          [ Arg.String "--import"
+                          , Arg.String "--import-options"
+                          , Arg.String "show-only"
+                          , file
+                          ]
+                    }
+                  }
+                , directory =
+                  { mime = [ "inode", "directory" ]
+                  , cmd =
+                      special.exec-in-terminal-emulator
+                        (oneArg (pkgSame "ranger"))
+                  }
+                , any =
+                  { mime = [ "*" ], cmd = special.dmenu-list-binaries-and-exec }
                 }
-              , { match = mime.directory
-                , cmd =
-                    special.exec-in-terminal-emulator
-                      (oneArg (pkgSame "ranger"))
-                }
-              , { match = mime.any, cmd = special.dmenu-list-binaries-and-exec }
-              ]
-            : List MimeMatch
-
-in  { mimeMatcher
-    , uriMimeGlobs
-    , UriMimeGlob
-    , Executable
-    , Command
-    , UriGlobHandler
-    , MimeMatch
-    , Special
-    , Mime
-    , Arg
-    }
+
+      let matchOrder =
+            [ mime.text.html
+            , mime.text.gemini
+            , mime.text.gopher
+            , mime.text.xml
+            , mime.text.any
+            , mime.mail-address
+            , mime.torrent
+            , mime.irc
+            , mime.file
+            , mime.image.gif
+            , mime.image.svg
+            , mime.image.any
+            , mime.pdf
+            , mime.pgp-key
+            , mime.directory
+            , mime.any
+            ]
+
+      let uriMimeGlobs
+          : List UriMimeGlob
+          = [ { desc = "http link"
+              , glob = [ "http://*", "https://*" ]
+              , schema-prefix = [ "http", "https" ]
+              , handler =
+                  let TODO =
+                        UriGlobHandler.Transparent special.fetch-http-url-mime
+
+                  in  UriGlobHandler.Mime mime.text.html.mime
+              }
+            , { desc = "gemini link"
+              , glob = [ "gemini://*" ]
+              , schema-prefix = [ "gemini" ]
+              , handler = UriGlobHandler.Mime mime.text.gemini.mime
+              }
+            , { desc = "gemini link"
+              , glob = [ "gopher://*", "gophers://*" ]
+              , schema-prefix = [ "gopher", "gophers" ]
+              , handler = UriGlobHandler.Mime mime.text.gopher.mime
+              }
+            , { glob = [ "mailto:*" ]
+              , desc = "mail address"
+              , schema-prefix = [ "mailto" ]
+              , handler = UriGlobHandler.Mime mime.mail-address.mime
+              }
+            , { glob = [ "magnet:*" ]
+              , desc = "bittorrent magnet link"
+              , schema-prefix = [ "magnet" ]
+              , handler = UriGlobHandler.Mime mime.torrent.mime
+              }
+            , { desc = "irc channel"
+              , glob = [ "irc:*", "ircs:*" ]
+              , schema-prefix = [ "irc", "ircs" ]
+              , handler = UriGlobHandler.Mime mime.irc.mime
+              }
+            , { desc = "local file"
+              , glob = [ "file://*" ]
+              , schema-prefix = [ "file" ]
+              , handler = UriGlobHandler.Mime mime.file.mime
+              }
+            ]
+
+      let mimeMatcher =
+            let pkgSame =
+                  λ(packageAndBinaryName : Text) →
+                    pkgs
+                      { package = packageAndBinaryName
+                      , binary = packageAndBinaryName
+                      }
+
+            let wrapCommand =
+                  λ(wrapper : Command) →
+                  λ(cmd : Command) →
+                    { exe = wrapper.exe
+                    , args =
+                        λ(template : Arg) →
+                            wrapper.args template
+                          # [ Arg.String cmd.exe ]
+                          # cmd.args template
+                    }
+
+            let oneArg =
+                  λ(exe : Executable) → { exe, args = λ(file : Arg) → [ file ] }
+
+            let m = λ(match : Mime) → λ(cmd : Command) → { match, cmd }
+
+            in    [ { match = mime.mail-address.mime
+                    , cmd = special.compose-mail-to
+                    }
+                  , { match = mime.text.html.mime
+                    , cmd = special.open-in-browser
+                    }
+                  , { match = mime.text.gemini.mime
+                    , cmd = oneArg (pkgSame "lagrange")
+                    }
+                  , { match = mime.text.gopher.mime
+                    , cmd = oneArg (pkgSame "lagrange")
+                    }
+                  , { match = mime.text.xml.mime
+                    , cmd = special.open-in-browser
+                    }
+                  , { match = mime.text.any.mime, cmd = special.open-in-editor }
+                  , { match = mime.image.gif.mime
+                    , cmd = special.open-in-browser
+                    }
+                  , { match = mime.image.svg.mime
+                    , cmd = oneArg (pkgSame "inkscape")
+                    }
+                  , { match = mime.image.any.mime
+                    , cmd = oneArg (pkgSame "imv")
+                    }
+                  , { match = mime.pdf.mime, cmd = oneArg (pkgSame "zathura") }
+                  , { match = mime.pgp-key.mime
+                    , cmd =
+                      { exe = pkgs { package = "gnupg", binary = "gpg" }
+                      , args =
+                          λ(file : Arg) →
+                            [ Arg.String "--import"
+                            , Arg.String "--import-options"
+                            , Arg.String "show-only"
+                            , file
+                            ]
+                      }
+                    }
+                  , { match = mime.directory.mime
+                    , cmd =
+                        special.exec-in-terminal-emulator
+                          (oneArg (pkgSame "ranger"))
+                    }
+                  , { match = mime.any.mime
+                    , cmd = special.dmenu-list-binaries-and-exec
+                    }
+                  ]
+                : List MimeMatch
+
+      in  { mimeMatcher
+          , uriMimeGlobs
+          , UriMimeGlob
+          , Executable
+          , Command
+          , UriGlobHandler
+          , MimeMatch
+          , Special
+          , Mime
+          , Arg
+          }
diff --git a/pkgs/profpatsch/xdg-open/default.nix b/pkgs/profpatsch/xdg-open/default.nix
index 89114b92..2b265318 100644
--- a/pkgs/profpatsch/xdg-open/default.nix
+++ b/pkgs/profpatsch/xdg-open/default.nix
@@ -54,6 +54,8 @@ let
     args = file: [ file ];
   };
 
+
+
   open-in-browser = {
     exe = bins.firefox;
     args = file: [ file ];
@@ -117,6 +119,7 @@ let
       , fetch-http-url-mime : Command
       , open-in-browser : Command
       , open-in-editor : Command
+      , notify : Text -> Command
       }
     )
 → Text
@@ -125,6 +128,7 @@ let
       main = "xdg-open.dhall";
       files = [
         "config.dhall"
+        "types.dhall"
         "imports/Prelude/Text/concatSep"
         "imports/Prelude/Text/concatMap"
         "imports/Prelude/Text/concat"
diff --git a/pkgs/profpatsch/xdg-open/types.dhall b/pkgs/profpatsch/xdg-open/types.dhall
new file mode 100644
index 00000000..74e55d32
--- /dev/null
+++ b/pkgs/profpatsch/xdg-open/types.dhall
@@ -0,0 +1,50 @@
+let Mime = List Text
+
+let
+    -- TODO use library like with shell commands
+    Executable =
+      Text
+
+let Arg = < String : Text | Variable : Text >
+
+let CommandTemplate =
+      λ(templates : Type) → { exe : Executable, args : templates → List Arg }
+
+let Command = CommandTemplate Arg
+
+let Special =
+      { open-in-editor : Command
+      , open-in-browser : Command
+      , fetch-http-url-mime : Command
+      , compose-mail-to : Command
+      , exec-in-terminal-emulator : ∀(args : Command) → Command
+      , dmenu-list-binaries-and-exec : Command
+      , notify : ∀(message : Text) → Command
+      }
+
+let
+    -- Handler of an uri glob. Mime maps the uri to a file handler. Transparent is a command which, when run, returns a mimetype of the file.
+    UriGlobHandler =
+      < Transparent : Command | Mime : Mime >
+
+let UriMimeGlob =
+      { desc : Text
+      , -- less specific than glob, used by firefox to refer to the schema
+        schema-prefix : List Text
+      , -- schema shell glob to check whether a link corresponds to the schema
+        glob : List Text
+      , handler : UriGlobHandler
+      }
+
+let MimeMatch = { match : Mime, cmd : Command }
+
+in  { Mime
+    , Executable
+    , Arg
+    , CommandTemplate
+    , Command
+    , Special
+    , UriGlobHandler
+    , UriMimeGlob
+    , MimeMatch
+    }
diff --git a/pkgs/profpatsch/xdg-open/xdg-open.dhall b/pkgs/profpatsch/xdg-open/xdg-open.dhall
index 30cf45e0..5090f8f1 100644
--- a/pkgs/profpatsch/xdg-open/xdg-open.dhall
+++ b/pkgs/profpatsch/xdg-open/xdg-open.dhall
@@ -11,28 +11,28 @@ let
     Executable =
       Text
 
-let config = ./config.dhall
+let types = ./types.dhall
 
 let renderMime = Text/concatSep "/"
 
 let shellEscapeCommand =
       λ(shellEscape : Text → Text) →
       λ(file : Text) →
-      λ(cmd : config.Command) →
+      λ(cmd : types.Command) →
           Text/concatSep
             " "
             (   [ shellEscape cmd.exe ]
               # List/map
-                  config.Arg
+                  types.Arg
                   Text
-                  ( λ(arg : config.Arg) →
+                  ( λ(arg : types.Arg) →
                       merge
                         { String = λ(t : Text) → shellEscape t
                         , Variable = λ(t : Text) → t
                         }
                         arg
                   )
-                  (cmd.args (config.Arg.Variable file))
+                  (cmd.args (types.Arg.Variable file))
             )
         : Text
 
@@ -54,7 +54,7 @@ let xdg-open =
       let mimeMatcherCase =
             λ(shellEscape2 : Text → Text) →
             λ(file2 : Text) →
-            λ(m : config.MimeMatch) →
+            λ(m : types.MimeMatch) →
               [ "${renderMime m.match})"
               , "${shellEscapeCommand shellEscape2 file2 m.cmd}"
               , ";;"
@@ -63,17 +63,17 @@ let xdg-open =
       let mimeGlobCase =
             λ(shellEscape2 : Text → Text) →
             λ(file2 : Text) →
-            λ(g : config.UriMimeGlob) →
+            λ(g : types.UriMimeGlob) →
                 List/concatMap
                   Text
                   Text
                   ( λ(match : Text) →
                       merge
                         { Mime =
-                            λ(mime : config.Mime) →
+                            λ(mime : types.Mime) →
                               [ "${match})", "mime=${renderMime mime}", ";;" ]
                         , Transparent =
-                            λ(cmd : config.Command) →
+                            λ(cmd : types.Command) →
                               [ "${match})"
                               , "mime=\"\$(${shellEscapeCommand
                                                shellEscape2
@@ -91,57 +91,59 @@ let xdg-open =
           λ(write-dash : Text → Text → Executable) →
           λ(shellEscape : Text → Text) →
           λ(pkgs : { package : Text, binary : Text } → Executable) →
-          λ(special : config.Special) →
-            write-dash
-              "xdg-open"
-              (     ''
-                    # TODO: --dry-run to display what would be opened and why
-
-                    # partially taken from
-                    # https://github.com/march-linux/mimi/blob/master/xdg-open
-
-                    set -e
-                    file="$1"
-                    mime=
-
-                    # match on protocols
-                    # if you want to match files reliably, start with file://
-                    case "$file" in
-                    ${prettyLines
-                        { indent = 2
-                        , lines =
-                            List/concatMap
-                              config.UriMimeGlob
-                              Text
-                              (mimeGlobCase shellEscape "\"\$file\"")
-                              (config.uriMimeGlobs special)
-                        }}
-                      *)
-                        # it’s a file
-
-                        # strip possible protocol
-                        file=''
-                ++  "\$"
-                ++  ''
-                    {file#file://}
-                        mime=$(file -E --brief --mime-type "$file") \
-                        || (echo "$mime" 1>&2; exit 1)
-                        # ^ echo the error message of file
-                        ;;
-                    esac
-
-                    case "$mime" in
-                    ${prettyLines
-                        { indent = 2
-                        , lines =
-                            List/concatMap
-                              config.MimeMatch
-                              Text
-                              (mimeMatcherCase shellEscape "\"\$file\"")
-                              (config.mimeMatcher pkgs special)
-                        }}
-                    esac
-                    ''
-              )
+          λ(special : types.Special) →
+            let config = ./config.dhall pkgs special
+
+            in  write-dash
+                  "xdg-open"
+                  (     ''
+                        # TODO: --dry-run to display what would be opened and why
+
+                        # partially taken from
+                        # https://github.com/march-linux/mimi/blob/master/xdg-open
+
+                        set -e
+                        file="$1"
+                        mime=
+
+                        # match on protocols
+                        # if you want to match files reliably, start with file://
+                        case "$file" in
+                        ${prettyLines
+                            { indent = 2
+                            , lines =
+                                List/concatMap
+                                  types.UriMimeGlob
+                                  Text
+                                  (mimeGlobCase shellEscape "\"\$file\"")
+                                  config.uriMimeGlobs
+                            }}
+                          *)
+                            # it’s a file
+
+                            # strip possible protocol
+                            file=''
+                    ++  "\$"
+                    ++  ''
+                        {file#file://}
+                            mime=$(file -E --brief --mime-type "$file") \
+                            || (echo "$mime" 1>&2; exit 1)
+                            # ^ echo the error message of file
+                            ;;
+                        esac
+
+                        case "$mime" in
+                        ${prettyLines
+                            { indent = 2
+                            , lines =
+                                List/concatMap
+                                  types.MimeMatch
+                                  Text
+                                  (mimeMatcherCase shellEscape "\"\$file\"")
+                                  config.mimeMatcher
+                            }}
+                        esac
+                        ''
+                  )
 
 in  xdg-open