github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/docs/commands/open.md (about) 1 # `open` 2 3 > Open a file with a preferred handler 4 5 ## Description 6 7 `open` is a smart tool for reading files: 8 9 1. It will read a file from disk or a HTTP(S) endpoints 10 2. Detect the file type via file extension or HTTP header `Content-Type` 11 3. It intelligently writes to STDOUT 12 - If STDOUT is a TTY it will perform any transformations to render to the 13 terminal (eg using inlining images) 14 - If STDOUT is a pipe then it will write a byte stream with the relevant 15 data-type 16 4. If there are no open handlers then it will fallback to the systems default. 17 eg `open` (on macOS, Linux), `open-xdg` (X11), etc. 18 19 ## Usage 20 21 ``` 22 open filename[.gz]|uri -> <stdout> 23 ``` 24 25 ## Examples 26 27 ``` 28 » open https://api.github.com/repos/lmorg/murex/issues -> foreach issue { out "$issue[number]: $issue[title]" } 29 ``` 30 31 ## Detail 32 33 ### File Extensions 34 35 Supported file extensions are listed in `config` under the app and key names of 36 **shell**, **extensions**. 37 38 Unsupported file extensions are defaulted to generic, `*`. 39 40 Files with a `.gz` extension are assumed to be gzipped and thus are are 41 automatically expanded. 42 43 ### MIME Types 44 45 The `Content-Type` HTTP header is compared against a list of MIME types, which 46 are stored in `config` under the app and key names of **shell**, **mime-types**. 47 48 There is a little bit of additional logic to determine the Murex data-type to 49 use should the MIME type not appear in `config`, as seen in the following code: 50 51 ```go 52 package lang 53 54 import ( 55 "regexp" 56 "strings" 57 58 "github.com/lmorg/murex/lang/types" 59 ) 60 61 var rxMimePrefix = regexp.MustCompile(`^([-0-9a-zA-Z]+)/.*$`) 62 63 // MimeToMurex gets the murex data type for a corresponding MIME 64 func MimeToMurex(mimeType string) string { 65 mime := strings.Split(mimeType, ";")[0] 66 mime = strings.TrimSpace(mime) 67 mime = strings.ToLower(mime) 68 69 // Find a direct match. This is only used to pick up edge cases, eg text files used as images. 70 dt := mimes[mime] 71 if dt != "" { 72 return dt 73 } 74 75 // No direct match found. Fall back to prefix. 76 prefix := rxMimePrefix.FindStringSubmatch(mime) 77 if len(prefix) != 2 { 78 return types.Generic 79 } 80 81 switch prefix[1] { 82 case "text", "i-world", "message": 83 return types.String 84 85 case "audio", "music", "video", "image", "model": 86 return types.Binary 87 88 case "application": 89 if strings.HasSuffix(mime, "+json") { 90 return types.Json 91 } 92 return types.Generic 93 94 default: 95 // Mime type not recognized so lets just make it a generic. 96 return types.Generic 97 } 98 99 } 100 ``` 101 102 ### HTTP User Agent 103 104 `open`'s user agent is the same as `get` and `post` and is configurable via 105 `config` under they app **http** 106 107 ``` 108 » config -> [http] 109 { 110 "cookies": { 111 "Data-Type": "json", 112 "Default": { 113 "example.com": { 114 "name": "value" 115 }, 116 "www.example.com": { 117 "name": "value" 118 } 119 }, 120 "Description": "Defined cookies to send, ordered by domain.", 121 "Dynamic": false, 122 "Global": false, 123 "Value": { 124 "example.com": { 125 "name": "value" 126 }, 127 "www.example.com": { 128 "name": "value" 129 } 130 } 131 }, 132 "default-https": { 133 "Data-Type": "bool", 134 "Default": false, 135 "Description": "If true then when no protocol is specified (`http://` nor `https://`) then default to `https://`.", 136 "Dynamic": false, 137 "Global": false, 138 "Value": false 139 }, 140 "headers": { 141 "Data-Type": "json", 142 "Default": { 143 "example.com": { 144 "name": "value" 145 }, 146 "www.example.com": { 147 "name": "value" 148 } 149 }, 150 "Description": "Defined HTTP request headers to send, ordered by domain.", 151 "Dynamic": false, 152 "Global": false, 153 "Value": { 154 "example.com": { 155 "name": "value" 156 }, 157 "www.example.com": { 158 "name": "value" 159 } 160 } 161 }, 162 "insecure": { 163 "Data-Type": "bool", 164 "Default": false, 165 "Description": "Ignore certificate errors.", 166 "Dynamic": false, 167 "Global": false, 168 "Value": false 169 }, 170 "redirect": { 171 "Data-Type": "bool", 172 "Default": true, 173 "Description": "Automatically follow redirects.", 174 "Dynamic": false, 175 "Global": false, 176 "Value": true 177 }, 178 "timeout": { 179 "Data-Type": "int", 180 "Default": 10, 181 "Description": "Timeout in seconds for `get` and `getfile`.", 182 "Dynamic": false, 183 "Global": false, 184 "Value": 10 185 }, 186 "user-agent": { 187 "Data-Type": "str", 188 "Default": "murex/1.7.0000 BETA", 189 "Description": "User agent string for `get` and `getfile`.", 190 "Dynamic": false, 191 "Global": false, 192 "Value": "murex/1.7.0000 BETA" 193 } 194 } 195 ``` 196 197 ### Open Flags 198 199 If the `open` builtin falls back to using the systems default (like `open-xdg`) 200 then the only thing that gets passed is the path being opened. If the path is 201 stdin then a temporary file will be created. If you want to pass command line 202 flags to `open-xdg` (for example), then you need to call that command directly. 203 In the case of macOS and some Linux systems, that might look like: 204 205 ``` 206 exec open --flags filename 207 ``` 208 209 ## See Also 210 211 * [`*` (generic)](../types/generic.md): 212 generic (primitive) 213 * [`config`](../commands/config.md): 214 Query or define Murex runtime settings 215 * [`exec`](../commands/exec.md): 216 Runs an executable 217 * [`fexec` ](../commands/fexec.md): 218 Execute a command or function, bypassing the usual order of precedence. 219 * [`foreach`](../commands/foreach.md): 220 Iterate through an array 221 * [`get`](../commands/get.md): 222 Makes a standard HTTP request and returns the result as a JSON object 223 * [`getfile`](../commands/getfile.md): 224 Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. 225 * [`openagent`](../commands/openagent.md): 226 Creates a handler function for `open` 227 * [`out`](../commands/out.md): 228 Print a string to the STDOUT with a trailing new line character 229 * [`post`](../commands/post.md): 230 HTTP POST request with a JSON-parsable return 231 232 <hr/> 233 234 This document was generated from [builtins/core/open/open_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/open/open_doc.yaml).