πΎ Archived View for bbs.geminispace.org βΊ u βΊ clseibold βΊ 11916 captured on 2023-12-28 at 16:48:56. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
Re: "How to open files and URLs with the preferred application..."
I think linux has like xdg or some crap like that, but of course it's not guaranteed to be on all linux systems, afaik. Windows, mac, Haiku, and other OSs usually will have an API for it because those OSs actually value the developer's ability to actually do things in a mostly standard way so that devs don't have to think about 5 million different edge cases and 5 million different ways to do something.
(xdg is not enforced/guaranteed on a linux system, whereas Haiku and Windows APIs *are* guaranteed to always work because they are part of an actual OS and not some fluid ever-changing OS-like ecosystem)
Nov 21 Β· 5 weeks ago
π skyjake Β· Nov 21 at 16:17:
Yeah, AFAIK there isn't a cross-platform solution for this, unless you're using SDL (2.0.14+) where you can find `SDL_OpenURL` that is very helpful.
In general, opening files can be done via file:// URLs, so you'll probably just need a way to open URLs in a default program.
In addition to SDL_OpenURL, as a fallback Lagrange tries:
Why urlopen.bat? It's been a while, but I think it was because on Windows Lagrange is built on the MSYS2 runtime, so it is a predominantly *nix like environment, and the most reliable way that I found to do the URL opening was to run a native Windows cmd.exe and run the `open` shell command inside that.
π°οΈ lufte Β· Nov 21 at 17:20:
Thanks for the tips guys, I guess I'll start with xdg-open and move from here. Sorry if I touched a nerve there clseibold ;)
πΊ gemalaya Β· Nov 21 at 18:13:
Never tried this one but there's open-python:
https://pypi.org/project/open-python/
π clseibold Β· Nov 21 at 18:13:
@lufte It's fine :D
For Haiku, if you want a more "native" API, there's docs on launching apps from Haiku here: https://www.haiku-os.org/blog/nephele/2023-07-12_launching_apps_on_haiku/
Haiku is very message-oriented (even moreso than Windows, afaik), so it looks like it relies on BMessage to open the default app of a file:
The indirect way involves opening a file that the application supports and having the mimetype plus the registrar figure out where to forward this to. This can be done by launching a new application or by forwarding it to a running application via a BMessage. (This is also how βopenβ in the Terminal works, it will open each argument as a document to open. Unlike xdg-open this supports opening multiple files at once.)
π clseibold Β· Nov 21 at 18:20:
@lufte For the filetypes on Windows, there is AssocQueryString.
Don't let the terrible Win32 MSDN docs scare you too much, it's simpler than the docs make it look, lol. Here's an example usage from StackOverflow:
β https://stackoverflow.com/a/17773402
However, the above will only give you what the application is. To actually open the application, I believe you need to then use another Win32 API call, but I don't know which one.
More simply, you could also just call ShellExecute, although I wouldn't recommend this:
β https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew
Finally, for macOS, there are APIs in the Launch Services stuff (whatever that is, lol). Here's the docs for LSOpenCFURLRef, which is likely what you want, and this is for macOS 10.0+:
β https://developer.apple.com/documentation/coreservices/1442850-lsopencfurlref
There is also a deprecated LSCopyDefaultApplicationURLForURL which is just for macOS 10.10 through 12.0:
β https://developer.apple.com/documentation/coreservices/1448824-lscopydefaultapplicationurlforur
π°οΈ lufte Β· Nov 21 at 22:30:
Taking notes here. The implementation from open-python looks simple enough too.
π clseibold Β· Nov 21 at 22:46:
@lufte I do have to say that when starting subprocesses like this, one does need to consider security. For example, the Python subprocess.call() and subprocess.run() functions can take a Shell argument that, when set to true, calls into the shell, which can be vulnerable to command injection (which is similar to sql injection, but for shell commands). It's the same for C's system() and exec() functions too.
There are also performance implications with subprocesses. Subprocesses are heavier and take more resources than API calls.
π² sloum Β· Nov 22 at 04:16:
While not perfect, you can usually detect the OS in use from an env var (again, not always relioable but pretty good) and then switch on the OS using xdg-open on linux, open on osx, etc. (providing a fallback as just downloading the file when a program is not available or there is not a handler for a filetype).
π» mediocregopher Β· Nov 22 at 07:19:
If a Linux system doesn't have xdg-open, is there some alternative URL opener it might have? I've only ever seen xdg-open...
π clseibold Β· Nov 22 at 08:00:
@sloum I never thought about detecting the OS with an environment variable. Usually I do it with compile-time statements (Odin's `when ODIN_OS == .Windows {`), or with the language's runtime variables (I think Golang does it this way).
π clseibold Β· Nov 22 at 08:03:
@mediocregopher I believe gnome-open is also a thing, but I am not experienced in doing that type of stuff in linux, so I don't know much about it, lol. Xdg-open is very common in linux, so it's probably just fine to use it. Don't mind my bitterness towards linux too much, I just hate that Unix's potential went to waste with Linux's unstandardized and frantic approach :D
Update: Apparently xdg-open is just a wrapper around multiple desktop environments, including gnome-open and `gio open`. Does anyone know if xdg-open requires a DE to work, or if it also works in terminal-only environments?
Update 2: I've also found an exo-open which is the gnome-open equivalent for XFCE. KDE uses kde-open. All three (exo-open, kde-open, and gio) are wrapped with xdg-open.
π» mediocregopher Β· Nov 22 at 08:37:
@clseibold thank you for doing my research for me :) I'll remain contented with xdg-open then.
re: working in a terminal-only environment, I can't think one would.... what the behavior even be? Run a process as a background job in the current shell?
π clseibold Β· Nov 22 at 09:32:
@mediocregopher Personally, I would expect that a system where you can specify default applications for different filetypes and URIs be standardized in the OS APIs, and that a cli `open` command would call out to this API and open the file/URI with that default application as a subprocess of the shell. I believe this is essentially what macOS does (macOS does have an `open` command), and it's also what Windows does, and Haiku afaik. Because it would be a part of the OS, it would work in a terminal-only environment and a graphical environment, and there'd be one standard across all variants/extensions of the OS.
π² sloum Β· Nov 22 at 21:15:
@clseibold Yes, most languages will have some module for OS detection. You can check against `$OSTYPE`, which I believe should be available for pretty much every major system. Subprocessing out to `uname` can also be useful for this purpose. I can't remember which I did... my use case was in a makefile (for gnu make, since bsd make does not support if statements). So I think it makes sense in a makefile (again, targeting a non-bsd system) but may not have the same use case in a more full featured language/environment.
How to open files and URLs with the preferred application in multiple operating systems? Not really related to Gemini, but I need to implement a way in my Gemini client to open unsupported URLs and files on their proper apps, mostly on Linux but ideally in other systems as well. Fellows who have written their own clients, how did you do it?