about summary refs log tree commit diff
path: root/pkgs/profpatsch/xdg-open
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2021-05-12 23:05:28 +0200
committerProfpatsch <mail@profpatsch.de>2021-05-12 23:42:13 +0200
commit0d1737778cf81304ec37cea2a1c0e934bb84e601 (patch)
tree85dd4f2de036adb61fcd18ddb66aa2ad08d49c56 /pkgs/profpatsch/xdg-open
parent08bb67826b793e57b8ec17627ba2a52478567700 (diff)
pkgs/profpatsch/xdg-open: prepare for adding firefox handler support
This diff is a bit bad cause of whitespace changes, but effectively
this copies all handlers into the mime handler definitions and
duplicates them for now.

We want to use the same config to generate a firefox mime handler
file.
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