Feature Suggestion: Self-bootstrapping scripts
See original GitHub issueI was thinking if there was a way to make the scripts I write more standalone in a sense that I could share it with someone without either having to explain how to install kotlin&kscript or producing a binary they can’t read/edit. Much like you can do today with shell/python scripts.
I believe I have found a fairly practical way to achieve this: by wrapping an existing script with a specific header and footer it can be made into a valid shell script and kotlin script at the same time. No unpacking step needed! See example below.
That means original script can be rewritten once, replacing it, and further iteration can happen with the bootsrapping footer in place.
IntelliJ support is available for both kotlin and bash parts of the script with kscript --idea script.kts
thanks to the intellij’s language injection feature.
Having the modifying happen only once also has the benefit that the shell code despite being auto-generated is ok to modify, as it won’t be overwritten. See example below where I choose to propagate the script file name to kotlin.
So I was thinking, that it would be great to have this built into kscript
on an “opt-in” basis, e.g.
kscript --bootstrapify script.kts
^ prepends/appends things to script.kts making it shareable
P.S.: Happy to work on a PR if this seems ok to add
Example of self-bootstrapping script.kts: (try opening with kscript --idea
to see how IDE experience is uncompromised; installing “BashSupport” pluging may be required for bash support)
#!/bin/bash
//usr/bin/env cat << '__EOF_KOTLIN' >/dev/null
import org.intellij.lang.annotations.Language
println("Hello from kotlin!")
if (System.console() == null) {
print(generateSequence(::readLine).joinToString("\n") + " | ")
}
println("${System.getenv("KSCRIPT_FILE")} ${args.toList().joinToString(" ")}")
//DEPS org.jetbrains:annotations-java5:16.0.2
@Language("sh")
private val __SHELL_BOOTSTRAP = """
__EOF_KOTLIN
function in_path() { command -v "$1" >/dev/null 2>&1; }
in_path kscript || {
function echo_and_eval() { echo "$ $@" 1>&2; eval "$@" 1>&2; }
in_path sdk || {
curl "https://get.sdkman.io" | bash 1>&2 && \
echo_and_eval source "$"SDKMAN_DIR/bin/sdkman-init.sh
}
in_path kotlin || echo_and_eval sdk install kotlin
in_path gradle || echo_and_eval sdk install gradle
echo_and_eval sdk install kscript
}
export KSCRIPT_FILE="$0";
kscript $0 "$@";
exit $?
"""
Issue Analytics
- State:
- Created 5 years ago
- Comments:5 (3 by maintainers)
It’s nice to see it that short! Will use the latest one as the template when implementing then
I was thinking it should maybe say the opposite (or just don’t say either way), as we’ll never overwrite custom changes there. There are some things that can be only done in bash, capturing script name being one example.
I think in-place replacement is the only right way - we should encourage people to not duplicate their script to a new file as much as we can. Without clear guidance I can imagine thinking this is basically just another flavor of
--package
and redirecting output to a new file is expected of me.Seems pretty clear, if a bit long. I’ll go with it then
yeah, meant to say the script itself, not stdin 😃 we’re on the same page here
Closing as the implementation is now merged