Giter Club home page Giter Club logo

nimcr's Introduction

Running Nim code with Shebangs

Shebangs are a tiny comment at the beginning of a file that tells the operating system what program can be used to run the contents of that file. It is typically seen in bash scripts starting with #!/bin/bash or in Python scripts as #!/usr/bin/env python. Nim however is not an interpreted language, this means that having a program that "runs" Nim files would actually mean compile and run. This was outlined in issue #66 for Nim but was closed after Araq showed how it could be achieved with flags to the compiler. However this solution is a bit lacking. Nim, being a compiled language, offers a speed benefit over many other languages. So writing scripts in Nim makes sense if you want to have a lot of scripts running on your machine. But compiling the script every time you want to run it makes no sense at all as it completely negates the speed benefit.

The solution

This project aims to be a tiny little program to solve the problem of using Nim for scripting. It takes the file passed to it through the shebang and establishes a nimcache directory in temporary storage, then it compiles the script to a hidden file next to the script itself. On subsequent runs it checks if the script file is newer than the executable (ie. been edited after the last compilation) in which case it will compile it again, reusing the same nimcache directory if it exists. This means that the very first run of a script will do the entire compilation process, subsequent runs without changes will only run the executable, and runs where the source is newer than the executable will do the compilation process but use the old nimcache. The sum of this is a great speed-benefit without losing any of the flexibility often associated with scripts in general. Simply mark the script as executable and run it!

A note on output

To make the output of a script as uniform as possible in order for it to easily pipe to other processes this program will hide the compilation output. As long as the Nim compiler completes without errors only the output of the script will be written to the terminal. In the case of a compiler failure the entire Nim compilation output along with the executed command will be written to stderr. This program will then exit with the error code of the compiler.

How to compile/run your script using nimcr

Make the first line in your nim script read as follows: #!/usr/bin/env nimcr and optionally make the script executable.

Passing options

WARNING since version 1.0.0 the syntax for passing command line options has changed in an non-backwards compatible manner. This was necessary in order to support passing options to the nim compiler as well as the actual script in a way that works across different platforms supporting shebangs.

Command line options can be specified for the nim compiler and for the actual script.

Options for the script

Options for the script are passed on the command line as you would with any other program, like so:

# Example 1: do not pass command line switches nor arguments for the script
$ ./script-using-nimcr
# Example 2: path both command line switches and arguments
$ ./script-using-nimcr -option1 -option2 positional_arg1 positional_arg2

The script will be able to access command line switches and arguments as any other nim program.

Options for the nim compiler

Options for the nim compiler can be specified by adding a specially formatted comment as second line of the script starting with #nimcr-args followed by a space then followed by command line switches and arguments to the nim compiler.

#!/usr/bin/env nimcr
#nimcr-args c --opt:size

... rest of the script

If #nimcr-args is not present as second line of the script it defaults to c -d:release.

Options automatically appended by nimcr

In order for nimcr to work and be convenient, some options are added to the execution and will throw an error or give unwanted behaviour when combined with conflicting options. These options are:

--colors:on --nimcache:<cache directory> --out:<hidden file>

nimcr's People

Contributors

0xace avatar avdn avatar dxxb avatar geotre avatar m33m33 avatar pmunch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nimcr's Issues

Breaks on Blank Line After Shebang

Just a minor detail this but it caught me out when I first tried to run nimcr as I always insert a blank line after my #shebang when scripting.

#!/usr/bin/env nimcr
echo "howdy!"

works as expected:

$: ./nimscripting.nim
howdy!

However, this:

#!/usr/bin/env nimcr

echo "howdy!"

will give an error:

$:  ./nimscripting.nim
fatal.nim(39)            sysFatal
Error: unhandled exception: index out of bounds, the container is empty [IndexError]

I don't know if it's fixable or even worth fixing, but thought it worth mentioning for anyone else whose muscle memory causes them to hit RETURN twice after typing in the #shebang line.

[You wouldn't believe how many times I switched back and forth between my version and your example script, wondering why the hell I couldn't get it to run –until I eventually spotted that extra newline!]

Bash-special characters in program arguments are not escaped

Hi, thanks for making this. Nimcr is something that I use in probably all of my Nim sources.

I'm writing a tool to parse and sort some text data and it's similar to CSV, only it's separated by | pipes (and sometimes other characters), so I've made the column separator a parameter.

Giving the pipe symbol to the script doesn't really work, though, although it's quoted:

# running via nimcr, pipe unescaped - this may be a bug in how nimcr handles the params
$ ./sort.nim -d '|' -f 9 --mergeOutputs
sh: -f: command not found
SIGPIPE: Pipe closed.

# running via nimcr, pipe escaped - works at the moment
$ ./sort.nim -d '\|' -f 9 --mergeOutputs 
[OK]

# running the resulting binary, pipe unescaped
$ ./.sort -d '|' -f 9 --mergeOutputs
[OK]

Add a way to pass arguments to the nim compiler from the command line

I recently tried to run the example of the nim-neel repo (https://github.com/Niminem/Neel) using nimcr. This failed because the nim-neel example requires you to pass --threads:on (and it also recommends passing --app:gui as well).

Currently you must edit the script to customize the arguments that are passed to the nim compiler. Thus I had to edit the example to make it work with nimcr. While this makes sense in many cases, it can also be a bit inconvenient like in this case. Another example would be if you wanted to switch between release and debug modes. It would thus be great if there was a way to pass arguments to the nim compiler through the command line as well.

One potential solution would be to let the user specify a ---nimcr-args (or perhaps --nim) argument that would be a string with the arguments that would be passed to the nim compiler. Another solution would be to assume any arguments starting with "-" and passed before the nim filename are meant for the nim compiler. That way you could do:

nimcr -d:debug my_nim_file.nim --my --script arguments

For extra safetly nimcr could check if any of those arguments is an existing file (in case there is someone crazy enough to want to run a script called "-d:debug".

Nimble install error (Windows)

There is an error when installing nimcr with nimble install nimcr1:

`...Temp\nimble_10464\githubcom_PMunchnimcr\nimcr.nim(55, 17) Error: expression 'execShellCmd("attrib +H " & exeName)' is of type 'int' and has to be discarded;`

appending discard to https://github.com/PMunch/nimcr/blob/master/nimcr.nim#L55 seems to work
(by the way, the command did indeed add a hidden attribute to the file in my test a single script :) )

spaces cause incorrect argument passing

If you call examples/testfile.nim klm "abc def" from the shell, the output will be

Hello World!
@["klm", "abc", "def"]

which is incorrect as "abc def" is not passed as a single argument to examples/.testfile.

Does not work with nim 1.6.2

Hi, I tried nimcr, but I got errors. I can use .nims extension for scripting, but wanted a script without it.

Script file script-sample:

#!/usr/bin/env nimcr

echo "Hello"
chmod +x script-sample
./script-sample
(nimcr) Error on build running command: nim c -d:release --colors:on --nimcache:/tmp/nimcache-0000000044ABFB1F --out:"/home/lz/snippets/nim/.script-sample" /home/lz/snippets/nim/script-sampleHint: used config file '/home/lz/.choosenim/toolchains/nim-1.6.2/config/nim.cfg' [Conf]
Hint: used config file '/home/lz/.choosenim/toolchains/nim-1.6.2/config/config.nims' [Conf]

........................................................
Error: invalid module name: script-sample

I renamed file to script_sample

./script_sample
(nimcr) Error on build running command: nim c -d:release --colors:on --nimcache:/tmp/nimcache-00000000D9AAFB98 --out:"/h
ome/lz/snippets/nim/.script_sample" /home/lz/snippets/nim/script_sampleHint: used config file '/home/lz/.choosenim/toolc
hains/nim-1.6.2/config/nim.cfg' [Conf]
Hint: used config file '/home/lz/.choosenim/toolchains/nim-1.6.2/config/config.nims' [Conf]

.........................................................
Error: cannot open '/home/lz/snippets/nim/script_sample.nim'

adding extra flags

Hi.
Thanks for this tool. It is very handy.
However I am using httpclient in a script and the code should be compiled with -d:ssl option.
Is there any way to config nimcr to make that option default?
Thanks

what's missing in `nim r`? maybe recommend as an alternative for nim >= 1.4 in the readme?

#!/usr/bin/env nim r --hints:off
static: echo "recompiling..." # only appears if recompiling needed
for i in 0..<10:
  echo i
chmod u+x main.nim
./main.nim # prints recompiling...
./main.nim # does not print recompiling...
# edit main.nim or its dependencies
./main.nim # prints recompiling...

note

-S may be needed on some sysmtems, see https://en.wikipedia.org/wiki/Shebang_(Unix)

eg: #!/usr/bin/env -S nim r --hints:off

New idea: Apply compile/run as debugging mode if spawned by gdb

Hey, I just had an idea:

There are times where I debug my code with gdb.

Everytime I do it I have to go and change the compilation flags.

I was considering having nimcr detect if the process was spawned by gdb and have it recompile with -g to ensure debugging information is included in the executable.

What do you think?

need complete path on shebang line to nimcr

shebang line like:
#!/home/user/.nimble/bin/nimcr "c --deadCodeElim:on --"
works.
but
#!nimcr "c --deadCodeElim:on --"
gives:
-bash: ./hello.nim: nimcr: bad interpreter: No such file or directory
nimcr is on my path. even tried copying it to /usr/bin/ same problem.

is my bash messed up?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.