A language-agnostic "shebang interpreter" that enables you to write scripts in compiled languages.

Overview

Scriptisto

Latest Version Build Status Crates.io License Libraries.io dependency status for latest release GitHub top language

Crates.io GitHub All Releases

It is tool to enable writing one file scripts in languages that require compilation, dependencies fetching or preprocessing.

It works as a "shebang" for those scripts, extracting build instructions from comments. If a script is changed, scriptisto rebuilds it and caches the result. If a script was already built, scriptisto immediately delegates to a binary with only <1 ms overhead.

Builds in Docker are available.

Advantages and use-cases are listed in the Wiki.

Demo

#!/usr/bin/env scriptisto

#include <stdio.h>
#include <glib.h>

// scriptisto-begin
// script_src: main.c
// build_cmd: clang -O2 main.c `pkg-config --libs --cflags glib-2.0` -o ./script
// scriptisto-end

int main(int argc, char *argv[]) {
  gchar* user = g_getenv("USER");
  printf("Hello, C! Current user: %s\n", user);
  return 0;
}
$ chmod +x ./script.c
$ ./script.c
Hello, C! Current user: username

Installation

Scriptisto is available as a prebuilt statically-linked standalone binary or distrubutions packages at Releases or at Crates.io.

Please proceed to the Installation for instructions.

Documentation

Proceed to our Wiki.

Disclaimer

This is not an officially supported Google product.

Comments
  • Feature request: Showing build progress indicator and/or build command output

    Feature request: Showing build progress indicator and/or build command output

    I just tried to execute the default Rust template, and it took a long time to build. The problem is, that there is no indicator of what is happening. I think, there should at least be a message like "Building XY, this could take a few seconds...").

    It's easy to add this functionality with a custom 'build_cmd' value, but I thought it would be useful to provide some feedback regarding something that potentially is confusing to end-users (end-users of a script). If they have to wait 30 seconds until something happens, then some users most likely will be confused a bit.

    A progress indicator would be ideal, but difficult to implement. An option to show a custom message before a build would also solve the problem.

    Personally, I'd like to always see the full build output, but it seems that's not possible at the moment.

    needs design 
    opened by d4h0 5
  • Executing 'bin/xy.rs' runs scriptisto itself, instead of script ('./bin/xy.rs' works as expected)

    Executing 'bin/xy.rs' runs scriptisto itself, instead of script ('./bin/xy.rs' works as expected)

    Expected Behavior

    Executing bin/xy.rs executes the target script.

    Actual Behavior

    scriptisto itself is executed.

    This works:

    [dh@arch]$ ./bin/cli.rs
    Hello, Rust! Command line options: Opt { input: None } 
    

    This doesn't work (notice the missing "./"):

    [dh@arch]$ bin/cli.rs 
    scriptisto 0.6.10
    A 'shebang-interpreter' for compiled languages
    
    USAGE:
        scriptisto [ARGS] [SUBCOMMAND]
    
    FLAGS:
        -h, --help       Prints help information
        -V, --version    Prints version information
    
    ARGS:
        <script-src>    A path to a script to run. If specified, first character must be "." or "/"
        <args>...       Additional arguments passed to a script
    
    SUBCOMMANDS:
        build       Build a script without running
        cache       Build cache operations
        help        Prints this message or the help of the given subcommand(s)
        new         Prints an example starting script in a programming language of your choice
        template    Manage custom script templates
    [dh@arch abalet.com]$ 
    

    Steps to Reproduce the Problem

    1. Run: mkdir bin
    2. Run: scriptisto new rust bin/foo.rs
    3. Run: chmod +x bin/foo.rs
    4. Run: bin/foo.rs

    Specifications

    • Version: scriptisto 0.6.10
    • Platform: Linux
    opened by d4h0 5
  • Any way to get the original script's filename/location?

    Any way to get the original script's filename/location?

    For example, in Rust we can normally write std::file!() to get the source file path/name, but this will just return something like src/main.rs because of the way the build is done. It would be nice to have a way to get the actual name/location of the original script--this is an important part of several shell scripts that I'd like to eventually replace.

    opened by grandopener 4
  • Executable not found, show-stopper failure since 0.6.13

    Executable not found, show-stopper failure since 0.6.13

    Expected Behavior

    $ scriptisto -V
    scriptisto 0.6.10
    $ for lang in c cpp elixir rust; do scriptisto new $lang > hello && chmod +x hello && ./hello; done
    Hello, C! Current user: work
    Hello, C++! Current user: work
    Hello, Elixir!
    Hello, Rust! Command line options: Opt { input: None }
    $ ./hello -i foo
    Hello, Rust! Command line options: Opt { input: Some("foo") }
    

    Actual Behavior

    $ scriptisto -V
    scriptisto 0.6.13
    $ for lang in c cpp elixir rust; do scriptisto new $lang > hello && chmod +x hello && ./hello; done
    Error: ErrorMessage { msg: "\"./hello\" is not found or not executable" }
    Error: ErrorMessage { msg: "\"./hello\" is not found or not executable" }
    Error: ErrorMessage { msg: "\"./hello\" is not found or not executable" }
    Error: ErrorMessage { msg: "\"./hello\" is not found or not executable" }
    $ ./hello -i foo
    error: Found argument '-i' which wasn't expected, or isn't valid in this context
    
    USAGE:
        scriptisto [ARGS] [SUBCOMMAND]
    
    For more information try --help
    

    Steps to Reproduce the Problem

    1. Update scriptisto to 0.6.13
    2. try to run any scriptisto-based file

    0.6.10 is not affected, and 0.6.11/12 are apparently not available.

    Specifications

    • Version: 0.6.13 (0.6.10 unaffected)
    • Platform: Linux 64 bits, cargo install
    bug 
    opened by vincentdephily 3
  • Add option to remove cache after build

    Add option to remove cache after build

    Would it be possible to add an option to remove all files except the built binary? For instance in Rust for even a simple script runs over 100MB, but the built binary is only a megabyte or two. Writing several small scripts can become very wasteful.

    For instance, a new configuration option field named clean_cache_after_build which removes all cache files except the target_bin could be added so that excessive disk space isn't wasted.

    opened by herbertjones 3
  • Cannot run scripts anymore after PATH search change

    Cannot run scripts anymore after PATH search change

    Expected Behavior

    $ scriptisto new rust >bin/foo.rs
    $ chmod +x bin/foo.rs
    $ ./bin/foo.rs
    Hello, Rust! Command line options: Opt { input: None }
    $ bin/foo.rs
    Hello, Rust! Command line options: Opt { input: None }
    

    (contrived output – both cases, with and without ./ prefix, must be fixed)

    Actual Behavior

    $ scriptisto --version # built from Git
    scriptisto 0.6.14-alpha.0
    $ scriptisto new rust >bin/foo.rs
    $ chmod +x bin/foo.rs
    $ ./bin/foo.rs
    Error: ErrorMessage { msg: "\"./bin/foo.rs\" is not found or not executable" }
    $ bin/foo.rs
    Error: ErrorMessage { msg: "\"bin/foo.rs\" is not found or not executable" }
    

    The fix for #26 has introduced this bug since bin/foo.rs isn't on the PATH. Searching the PATH doesn't solve the use cases. The first command line argument is a file path, potentially containing slashes, and not a name of an executable (which can never contain slashes). One could check it with Path::new("bin/foo.rs").exists(), if needed by the code to distinguish from subcommands.

    Specifications

    • Version: scriptisto 0.6.14-alpha.0 (built from commit f9ef3bd)
    • Platform: macOS

    Workaround

    Had to revert to 0.6.10 to at least get the ./some-script syntax to work correctly.

    bug 
    opened by AndiDog 2
  • Installation with cargo fails for version 0.6.2

    Installation with cargo fails for version 0.6.2

    Expected Behavior

    Installation should succeed without error.

    Actual Behavior

    Installation with cargo install fails with error message:

    error[E0599]: no function or associated item named `new` found for type `scrawl::editor::Editor<_>` in the current scope
       --> /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/scriptisto-0.6.2/src/templates.rs:246:46
        |
    246 |     let mut editor = scrawl::editor::Editor::new();
        |                                              ^^^ function or associated item not found in `scrawl::editor::Editor<_>`
    
    error: aborting due to previous error
    

    Steps to Reproduce the Problem

    1. Run cargo install scriptisto

    Specifications

    • Version: 0.6.2
    • Platform: Fedora Linux
    opened by jonasbb 2
  • Add

    Add "build_cmd_once"

    This will run only during the first build, before build_cmd. If we are rebuilding the binary, this won't run again. We can add "scriptisto cache invalidate" command to force it to rerun.

    Use cases:

    • Setup development environment, like virtualenv+pip for Python or "dotnet restore"
    • Fetch extra files from the web via curl
    • Prebuild something heavy that is rarely to change
    enhancement 
    opened by igor-petruk 2
  • Golang 1.16 support

    Golang 1.16 support

    The following script works. In short, nix-shell installs scriptisto (a custom Nix derivation that I made that is not available on the Nix Package Registry) and go_1_15, and then uses scriptisto to launch the script as a C++ program:

    #!/usr/bin/env nix-shell
    /*
    #!nix-shell -i scriptisto -p scriptisto go_1_15
    */
    
    // scriptisto-begin
    // script_src: main.go
    // build_once_cmd: go get github.com/fatih/color
    // build_cmd: go build -o script
    // replace_shebang_with: //
    // scriptisto-end
    
    package main
    
    import "github.com/fatih/color"
    
    func main() {
      color.Yellow("Hello, Go!")
    }
    
    

    However, if I change go_1_15 to go_1_16, then the script no longer works, and produces the following error:

    go: go.mod file not found in current directory or any parent directory; see 'go help modules'
    Error: ErrorMessage { msg: "Command \"/bin/sh\" \"-c\" \"go build -o script\" failed. Exit code: 1." }
    

    This is because since Go 1.16, the GO111MODULE default has changed from auto to on. See: https://go.dev/blog/go116-module-changes

    If I manually run export GO111MODULE=auto before executing the scriptisto program, then the program works again. It would be great if scriptisto had an option to set environment variables before compiling and executing the program, e.g. add-env: GO111MODULE=auto.

    A workaround is to use nix-shell itself to set the variable, but that can get cumbersome and may inadvertently be applied to more than one environment: https://stackoverflow.com/questions/62246831/setting-environment-variables-in-nix-via-a-shebang

    A configuration that works for Go 1.16, is to make use of the files option to create a go.mod file:

    #!/usr/bin/env nix-shell
    /*
    #!nix-shell -i scriptisto -p scriptisto go_1_16
    */
    
    // scriptisto-begin
    // script_src: main.go
    // build_cmd: go mod tidy && go build -o script
    // replace_shebang_with: //
    // files:
    //  - path: go.mod
    //    content: |
    //      module github.com/a/b
    //      go 1.17
    //      require (
    //          github.com/fatih/color v1.13.0
    //      )
    // scriptisto-end
    
    package main
    
    import "github.com/fatih/color"
    
    func main() {
      color.Yellow("Hello, Go!")
    }
    

    Related issues:

    1. https://github.com/igor-petruk/scriptisto/issues/34
    opened by W1M0R 1
  • EndOfStream error when running v0.6.13

    EndOfStream error when running v0.6.13

    Using freshest https://github.com/igor-petruk/scriptisto/releases/download/v0.6.13/scriptisto_0.6.13_amd64.deb on Ubuntu 20.04.

    ./tst --version gives

    Error: EndOfStream
    
    Cannot parse config YAML: 
    []
    

    v0.6.10 used to give:

    script 0.1.0
    
    bug 
    opened by ngirard 1
  • Fix RPM build

    Fix RPM build

    https://cloud.drone.io/igor-petruk/scriptisto/175/1/3

    +cargo install cargo-rpm --target x86_64-unknown-linux-musl

    • cargo rpm build -- 412 | error: The argument '--target ' was provided more than once, but cannot be used multiple times
    bug 
    opened by igor-petruk 0
  • Multiple shebangs are not processed with replace_shebang_with

    Multiple shebangs are not processed with replace_shebang_with

    First of all, thanks for this project!

    The following is a working example that uses nix-shell to run scriptisto as interpreter. nix-shell will install all the dependencies required to run the script (e.g. scriptisto, pkg-config, clang and glibmm) and then execute scriptisto. You can read more about that here: https://nixos.org/manual/nix/stable/command-ref/nix-shell.html#use-as-a--interpreter

    Two shebangs are used, one to specify nix-shell as the script runner, and one that configures nix-shell to use scriptisto as the interpreter. The second shebang is "wrapped" in C++ comments, to avoid compile errors. Ideally, scriptisto should have an option to indicate other shebangs that also need to be replaced with comments, e.g. other_shebangs_prefixes: #!nix-shell #!some-other-prefix.

    #!/usr/bin/env nix-shell
    /*
    #!nix-shell -i scriptisto -p scriptisto pkg-config clang_9 glibmm_2_68
    */
    
    #include <glibmm.h>
    #include <iostream>
    
    // scriptisto-begin
    // script_src: main.cpp
    // build_cmd: clang++ -std=c++17 -O2 main.cpp `pkg-config --libs --cflags glibmm-2.68` -o ./script
    // replace_shebang_with: //
    // scriptisto-end
    
    int main(int argc, char *argv[]) {
      const auto user = Glib::getenv("USER");
      std::cout << "Hello, C++! Current user: " << user << std::endl;
      return 0;
    }
    

    The Nix derivation that installs scriptisto looks like this:

    { pkgs }:
    
    pkgs.stdenv.mkDerivation rec {
    	pname = "scriptisto";
    
    	version = "0.6.14";
    
    	owner = "igor-petruk";
    
    	src = pkgs.fetchurl {
    		url = "https://github.com/${owner}/${pname}/releases/download/v${version}/${pname}.bz2";
    		sha256 = "YP00pnvADuRsuzKIe988L3zI/joHfYicaQTNT4x+Q00=";
    	};
    
    	sourceRoot = ".";
    
    	unpackCmd = ''
    		bzcat $src > ./scriptisto
    	'';
    
    	nativeBuildInputs = [
    		pkgs.autoPatchelfHook
    		pkgs.bzip2
    	];
    
    	installPhase = ''
    		runHook preInstall
    		ls -al
    		install -m755 -D scriptisto $out/bin/scriptisto
    		runHook postInstall
    	'';
    
    	meta = with pkgs.lib; {
    		license = licenses.asl20;
    		homepage = "https://github.com/igor-petruk/scriptisto";
    		description = "A language-agnostic shebang interpreter that enables you to write scripts in compiled languages.";
    		maintainers = with maintainers; [ igor-petruk ];
    	};
    }
    
    
    opened by W1M0R 1
  • Add `SCRIPTISTO_CACHE_DIR` environment variable + showcase in new Dart template, support hashing additional paths such as multiple source files or directories

    Add `SCRIPTISTO_CACHE_DIR` environment variable + showcase in new Dart template, support hashing additional paths such as multiple source files or directories

    Sorry, didn't open an issue before. Please add one if this feature isn't clear. To me, hashing more than just the script file itself is essential since many programs consist of multiple source files. This change allows listing files and directories which will trigger a rebuild if their modification time changed (same as scriptisto already does on the source script file). A new Dart template was added and used as show case for an – also new – SCRIPTISTO_CACHE_DIR environment variable, which helps the script access any further built artifacts.

    • [ ] Tests pass – Manually tested, didn't find any automated tests.
    • [ ] Appropriate changes to README are included in PR – No. Changes should be described in the Wiki once merged.
    cla: yes 
    opened by AndiDog 1
  • Eliminate data race during concurrent runs that trigger rebuild

    Eliminate data race during concurrent runs that trigger rebuild

    So far multiples runs of the script are unaware of each other and they can trigger compiler concurrently. This can lead to unpredicted behavior, especially if the build is multi-stage.

    Something like a lock file should be considered, but has to be very low cost. Preferrably no cost for the path, where the binary is already compiled.

    bug 
    opened by igor-petruk 0
Releases(v1.0.0)
Owner
Igor Petruk
Igor Petruk
Repository for the Rust Language Server (aka RLS)

Rust Language Server (RLS) The RLS provides a server that runs in the background, providing IDEs, editors, and other tools with information about Rust

The Rust Programming Language 3.6k Jan 7, 2023
The Curly programming language (now in Rust!)

Curly Curly is a functional programming language that focuses on iterators. Some of its main implementation features include sum types, iterators, lis

Curly Language 30 Jan 6, 2023
A fun and simple language with NO classes whatsoever!

This language aims to be simple, minimal, and compact. There will not be any classes whatsoever, and importing other files should be painless.

Europa Lang 22 Aug 23, 2022
Rust implementation of Namada, a sovereign proof-of-stake blockchain that enables asset-agnostic private transfers

Namada Overview Namada is a sovereign proof-of-stake blockchain, using Tendermint BFT consensus, that enables multi-asset private transfers for any na

anoma 144 Jan 2, 2023
WASM bindings for React - enables you to write and use React components in Rust

This library enables you to write and use React components in Rust, which then can be exported to JS to be reused or rendered.

Yichuan Shen 55 Dec 24, 2022
rust_arango enables you to connect with ArangoDB server, access to database, execute AQL query, manage ArangoDB in an easy and intuitive way, both async and plain synchronous code with any HTTP ecosystem you love.

rust_arango enables you to connect with ArangoDB server, access to database, execute AQL query, manage ArangoDB in an easy and intuitive way, both async and plain synchronous code with any HTTP ecosystem you love.

Foretag 3 Mar 24, 2022
plugy empowers you to construct agnostic dynamic plugin systems using Rust and WebAssembly.

plugy plugy is a plugin system designed to enable the seamless integration of Rust-based plugins into your application. It provides a runtime environm

Geoffrey Mureithi 22 Aug 12, 2023
Provides core language-agnostic functionality for LiveView Native across platforms

LiveView Native Core This repository contains an implementation of the LiveView Native core library, which is intended to handle all the details which

LiveView Native 35 Dec 27, 2022
a simple compiled language i made in rust. it uses intermediate representation (IR) instead of an abstract syntax tree (AST).

a simple compiled language i made in rust. it uses intermediate representation (IR) instead of an abstract syntax tree (AST).

null 4 Oct 3, 2022
A forth-inspired, bytecode-compiled scripting language for Anachro Powerbus

Anachro Forth (core) Anachro Forth is a forth-inspired, bytecode-compiled scripting language for Anachro Powerbus platform. Use Case The intended use

null 14 May 27, 2022
insject is a tool for poking at containers. It enables you to run an arbitrary command in a container or any mix of Linux namespaces.

Insject insject is a tool for poking at containers. It enables you to run an arbitrary command in a container or any mix of Linux namespaces. It suppo

NCC Group Plc 44 Nov 9, 2022
A Foundry plugin that enables you to plot charts within solidity.

??️ solplot A Foundry plugin that enables you to plot charts within solidity. Installation First, make sure that you have Rust installed. Then install

boredretard.eth 132 Dec 27, 2022
bevy_scriptum is a a plugin for Bevy that allows you to write some of your game logic in a scripting language

bevy_scriptum is a a plugin for Bevy that allows you to write some of your game logic in a scripting language. Currently, only Rhai is supported, but more languages may be added in the future.

Jarosław Konik 7 Jun 24, 2023
Xaynet represents an agnostic Federated Machine Learning framework to build privacy-preserving AI applications.

xaynet Xaynet: Train on the Edge with Federated Learning Want a framework that supports federated learning on the edge, in desktop browsers, integrate

XayNet 196 Dec 22, 2022
Network-agnostic, high-level game networking library for client-side prediction and server reconciliation.

WARNING: This crate currently depends on nightly rust unstable and incomplete features. crystalorb Network-agnostic, high-level game networking librar

Ernest Wong 175 Dec 31, 2022
Xaynet represents an agnostic Federated Machine Learning framework to build privacy-preserving AI applications.

xaynet Xaynet: Train on the Edge with Federated Learning Want a framework that supports federated learning on the edge, in desktop browsers, integrate

XayNet 196 Dec 22, 2022
An architecture-agnostic ELF file flattener for shellcode

Summary elfloader is a super simple loader for ELF files that generates a flat in-memory representation of the ELF. Pair this with Rust and now you ca

null 195 Dec 18, 2022
Rust bindings to bgfx, a cross-platform, graphics API agnostic

Rust bindings to bgfx, a cross-platform, graphics API agnostic, "Bring Your Own Engine/Framework" style rendering library.

Daniel Collin 65 Dec 24, 2022
API-agnostic audio plugin framework written in Rust

Because everything is better when you do it yourself - Rust VST3 and CLAP framework and plugins

Robbert van der Helm 415 Dec 27, 2022
Renderer-agnostic toolkit for Indie Game Developers

Indie Toolkit Renderer-agnostic toolkit for Indie Game Developers Features Not yet implemented: app_kit debug_kit input_kit asset_kit audio_kit Implem

null 2 May 25, 2022