about summary refs log tree commit diff
path: root/pkgs/profpatsch/xdg-open/xdg-open.dhall
blob: 03f168c34775d206f527ff1888ef2239e37cb609 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
let Text/concatSep = ./imports/Prelude/Text/concatSep

let Text/concatMap = ./imports/Prelude/Text/concatMap

let List/concatMap = ./imports/Prelude/List/concatMap

let List/map = ./imports/Prelude/List/map

let
    -- TODO use library like with shell commands
    Executable =
      Text

let config = ./config.dhall

let foo =
      { match = [ "image", "png" ]
      , cmd = λ(_ : Text) → { exe = "echo", args = [ "foo" ] }
      }

let renderMime = Text/concatSep "/"

let shellEscapeCommand =
      λ(shellEscape : Text → Text) →
      λ(file : Text) →
      λ(cmd : config.Command) →
          Text/concatSep
            " "
            (   [ shellEscape cmd.exe ]
              # List/map
                  config.Arg
                  Text
                  ( λ(arg : config.Arg) →
                      merge
                        { String = λ(t : Text) → shellEscape t
                        , Variable = λ(t : Text) → t
                        }
                        arg
                  )
                  (cmd.args (config.Arg.Variable file))
            )
        : Text

let repeatText =
      λ(t : Text) →
      λ(n : Natural) →
        Natural/fold n Text (λ(t2 : Text) → t ++ t2) ""

let Lines = { indent : Natural, lines : List Text }

let prettyLines =
      λ(lines : Lines) →
        Text/concatMap
          Text
          (λ(line : Text) → repeatText " " lines.indent ++ line ++ "\n")
          lines.lines

let xdg-open =
      let mimeMatcherCase =
            λ(shellEscape2 : Text → Text) →
            λ(file2 : Text) →
            λ(m : config.MimeMatch) →
              [ "${renderMime m.match})"
              , "${shellEscapeCommand shellEscape2 file2 m.cmd}"
              , ";;"
              ]

      let mimeGlobCase =
            λ(g : config.UriMimeGlob) →
                List/concatMap
                  Text
                  Text
                  ( λ(match : Text) →
                      [ "${match})", "mime=${renderMime g.mime}", ";;" ]
                  )
                  g.glob
              : List Text

      in  λ(bins : { get-mime-type : Executable }) →
          λ(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
                              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
                              config.MimeMatch
                              Text
                              (mimeMatcherCase shellEscape "\"\$file\"")
                              (config.mimeMatcher pkgs special)
                        }}
                    esac
                    ''
              )

in  xdg-open