turtle icon indicating copy to clipboard operation
turtle copied to clipboard

Make open command multi-platform

Open jmfayard opened this issue 3 years ago • 7 comments

Describe the problem

It's often useful to open an URL from a script, for example if the other needs to install something.

It's not trivial though, you have to use open on Mac, xdg-open on Linux, something else on Windows

Describe your solution

https://github.com/jmfayard/my-kotlin-scipts/blob/main/scripts/goto.main.kts#L86-L93

Checklist

jmfayard avatar Aug 05 '22 05:08 jmfayard

I actually included the Mac open command initially, as I use it a lot. However, I wasn't sure how to handle commands that are different on different platforms.

Currently, Turtle was only really "designed" with Mac in mind, I haven't tested using it on Windows or Linux. I wasn't sure how likely it was someone would run a program that uses Turtle with the same commands on multiple platforms. I.e. whether Turtle's built-in commands needed to be cross-platform, vs having Turtle commands that actually match the underlying shell commands.

I do like the idea of being able to just run 'open(...)' and it run the appropriate commands. Therefore, I think adding this is a great idea!

We might need to consider having CI run tests on Linux and Windows as well, although no idea how to check those commands work!

lordcodes avatar Aug 05 '22 09:08 lordcodes

The only way to test that a browser opens is to try it. It's good to have open() available. You could have xdgOpen() as well. But for something so common that opening an URL it would be good to have a dedicated multiplatform command

jmfayard avatar Aug 05 '22 09:08 jmfayard

You could handle multiple platforms this way:

fun main() {
    // default : all commands available
    shellRun<All> {
        git.clone("https://github.com/lordcodes/turtle")
    }
    // a few core abstractions that work everywhere
    shellRun<Multiplatform> {
        openUrl("http://example.com")
    }
    // access to Mac specific things
    shellRun<Mac> {
        brew("install", "wget")
    }
    // access to Linux specific things
    shellRun<Linux> {
        aptGet("install", "wget")
    }
}

fun <Platform> shellRun(workingDirectory: File? = null, script: ShellScript.() -> String): String =
    ShellScript(workingDirectory).script()

sealed interface Platform {
    object All: Platform            // all commands
    object Multiplatform: Platform  // abstractions that work everywhere
    object Unix: Platform           // Linux + Mac
    object Linux: Platform          // Linux only
    object Mac: Platform            // Mac only
    object Windows: Platform        // Windows only
}

jmfayard avatar Aug 05 '22 10:08 jmfayard

Now that is a very interesting idea.

lordcodes avatar Aug 05 '22 11:08 lordcodes

I think it's too complex though. Since there are subclasses of commands like GitCommands, FileCommands, ... we would have a matrix of (All, Multiplatform, Unix, Linux, Mac, Windows) x (GitCommands, FileCommands, ...)

so I would scale my request down to have simply

shellRun { multiplatform.openUrl("http://example.com") }

and whoever wants to add a new command can do this in MultiplatformCommands

jmfayard avatar Aug 06 '22 00:08 jmfayard

Fair enough. May as well just add the command like any other then. Not sure the 'MultiplatformCommands' grouping adds much and breaks from the currently technique of grouping commands by functionality.

lordcodes avatar Aug 06 '22 00:08 lordcodes

@jmfayard The open command for Mac is already available in the API via: files.openFile(...).

lordcodes avatar Aug 06 '22 00:08 lordcodes