SBT-like features in the Haskell build ecosystem - scala

I've been using Scala with SBT quite a bit lately. The REPL loop of has a handy feature: ~ COMMAND, meaning perform COMMAND for every source file change in the project. For instance:
~ test
and
~ compile
are terrifically useful for rapid development. I wonder, does anyone know of something similar for Haskell, a cabal shell, maybe?

You can get something like this very easily using inotifywait.
Just fire up a terminal in your project directory and run something like this:
$ while inotifywait -qq -r -e modify .; do cabal build && ./dist/build/tests/tests; done
This also works for any other language; just insert the build commands of your choice.

You can script ghci to both define your own commands, and augment existing commands. To do this:
define a ~/.ghci file
write a macro using :def to replace e.g. :reload
More info on GHCi :def commands is here.

The ghcid project provides something limited to ~ :reload. It provides a few extra features (format to a fixed number of lines, persist warnings from previously loaded files), but not the generality of running any command.

Related

Write coffeescript cake file in literate coffee

I would like to write a Cakefile in litcoffee (as in Cakefile.litcoffee), is there a way to do that?
It appears that cake does not do any literate checking when it finds and runs your Cakefile. You can of course add this behaviour if you are so inclined.
I would still try running cake -l and adding a #!/usr/bin/env coffee -l shebang to your file, you never know, right?
Barring the above, for what it's worth, I've had success using Grunt with litcoffee using this incantation.

How can I run a .clj Clojure file I created?

I wrote a small "hello world" program on Linux to get started with the language.
Now I'd like to run it and see what it outputs.
How can I run this code?
What command should I run?
FWIW, I'm interpreting the question here as specifically asking how to run a single file, like a script, versus as a part of a compiled project.
Obviously though, there's a relationship between how and why you would want to run a single file, and how you would want to build a full project, so I weigh that in some as well.
Best choice: the clj tooling
Docs are here:
https://clojure.org/guides/deps_and_cli
This is an official part of the Clojure project, which by itself is a pretty good reason to go this route. However, it has a couple of advantages over the other solutions here:
cleaner dependency resolution model, via deps.edn
also resolve dependencies via git references!
~/.clojure/deps.edn seems to do a better job of cleanly providing reusable functionality via its aliass than ~/.lein/profiles.clj
if you need to load your code in a repl, clj won't choke on a borked src file, like lein repl does
Simply
clj your-code-file.clj
Or if you have dependencies
clj -Sdeps '{:deps {clj-time {:mvn/version "0.14.2"}}}' -M your-code-file.clj
Works well as a shebang in scripts as well!
#!clj -Sdeps '{:deps {clj-time {:mvn/version "0.14.2"}}} -M
(ns my-crazy-script!
(:require ...))
...
I recommend installing with homebrew, which now works on both Mac and Linux. If you're on Windows I'd recommend using the WSL+brew.
The one advantage I see of lein (see below) tooling over clj generally is that lein handles a little more of the process of building and packaging your code base, when you get to that point.
However, there are other ways of handing that (see pack, uberdeps or cambada), and the advantages of clj mentioned above outweigh IMHO.
Babashka
If you are trying to run a single file, as apposed to an entire project, there's a good chance your in "scripting territory".
Unfortunately, the JVM takes a while to boot up, as does Clojure itself.
Via the magic of GraalVM and the SCI, Babashka is able to support most of the Clojure language with blazing fast startup times.
It also comes with quite a few "batteries included" for typical scripting tasks, making it a perfect complement to clj when you want fast-executing, short lived processes.
Once you install it you can simply bb you-code-file.clj, or use #!bb in your shebang.
See the docs for more usage instructions:
https://babashka.org/
With lein & lein-exec
If you prefer lein tooling, or have a ~/.lein/profiles.clj file handy already and don't want to invest in learning clj/deps.edn, you can consider looking at lein-exec.
If you already have a project.clj set up with dependencies, you can of course run lein run -m <yer-namespace>[/<yer-main-fn>].
As mentioned above, the one advantage of lein over clj is that it is a complete build tool, and can make jars/uberjars for you with lein jar or lein uberjar, do deploys and such.
For ClojureScript
I'd recommend http://planck-repl.org/. It now supports (bootstrapped) quick launching of ClojureScript scripts without having to fire up the JVM or Clojure.
Like babashka, this makes it great for scripting.
However, I find babashka both more powerful and more natural for scripting, so I'd start there unless you have a particular reason for wanting to use Cljs (more familiarity with JS/node, need of certain cljs libraries, etc).
For more substantial projects (beyond scripting), you may want to look at Shadlow-CLJS, for its ease of incorporating vanilla JS projects.
And FWIW, Shadow nicely integrates with both deps and lein, and has it's own built in hode code reloading, like figwheel.
With java
You can, of course, as has been suggested in another answer, use
java -cp clojure.jar clojure.main file.clj
But you don't see that in the wild too often, because it's a pain to have to find the path to your clojure.jar and manually composing classpaths for dependencies sucks.
But, you know, to each their own.
You can run script with following command:
java -cp clojure.jar clojure.main file.clj
but it's better to use leiningen, especially when you'll start to add dependencies to your project. lein provides number of commands to run your code (with all necessary dependencies), pack code into archive with lein jar, or create complete, independent archives with lein uberjar that you can run with:
java -jar your_app.jar
command
P.S. You can read how to use lein in following article - it describes base tasks & configurations
Once you've installed lein and the lein-exec plugin, running the .clj file you've created is as simple as
lein exec hello.clj
In case you're passing command line arguments like
lein exec hello.clj arg1 arg2 arg3
you can access them in the 'foo' function in your hello.clj like
(foo *command-line-args*)
For a single clj file you can add,
#!/usr/bin/env java -cp /path/to/clojure-1.2.0.jar clojure.main
to the top of the file and make it executable or you can use leiningen which is a clojure build tool it will create a single jar that has everything packed, then you can just do,
java -jar cool_app.jar
if you just want to execute a single file, how about piping it to the repl like:
cat $PATH_TO_FILE | lein repl
For running a single file through command line use the following commands:
clj -m (NameSpace name)
ex: clj -m Sample
Or if you want to run through repl:
(load-file filelocation)
ex:
(load-file "Sample.clj")
Drip is probably now the best answer to this question (see Drip's wiki for details on using Drip with Clojure).
Cake was incorporated into Leiningen and has since been superseded as the most stable implementation of Clojure automation by Drip - see this answer to a similar question here.
I really like writing small .clj scripts, but sometimes those scripts have dependencies that need to be installed. Since none of the other answers cover that case, I provide an example here. This example is a single-file script that requires the permutations function from the math.combinatorics library.
Cumbersome Mac-only solution
#!/usr/bin/env clj -Sdeps {:deps,{org.clojure/math.combinatorics,{:mvn/version,"0.1.6"}}} -M
; Explanation for the shebang:
; -Sdeps Specify deps in EDN format
; , Clojure interprets commas as whitespace. Without the commas, the EDN is
; broken up into multiple arguments and the command fails. On the
; command line you can use single quotes around the EDN string, but
; Mac shebangs don't support quoting around arguments.
; -M Run the program as a "main" function
(ns foo
(:use [clojure.math.combinatorics :only (permutations)]))
(dorun (map #(println (apply str %)) (permutations "abcde")))
Linux-only solution
#!/usr/bin/env -S clj -Sdeps '{:deps {org.clojure/math.combinatorics {:mvn/version "0.1.6"}}}' -M
; Explanation for the shebang:
; env -S Allow multiple arguments to be passed to the following command
; -Sdeps Specify deps in EDN format
; -M Run the program as a "main" function
(ns foo
(:use [clojure.math.combinatorics :only (permutations)]))
(dorun (map #(println (apply str %)) (permutations "abcde")))
Portable solution (Linux and Mac)
See the planck docs for an explanation. It's very clever!
#!/usr/bin/env bash
"exec" "clj" "-Sdeps" "{:deps {org.clojure/math.combinatorics {:mvn/version \"0.1.6\"}}}" "-M" "$0" "$#"
(ns foo
(:use [clojure.math.combinatorics :only (permutations)]))
(dorun (map #(println (apply str %)) (permutations "abcde")))
I had similar issue in running a specific clojure script file out of a clojure project using lein. Then I found a shortcut, thought of sharing the same.
In project.clj file, you can toggle the clojure script file name ( which has main method of course). Following is the statement for this.
:main ^:skip-aot conv.newconv ; here conv is namespace and newconv is the file name .
Note: I am new to clojure and I am not sure why '^:skip-aot` is used, I have not checked that.
Note: This methodology, does not require any plugin to be installed nor any jar file need to be generated. This only requires to change a name in project file.
Assumption: Your clojure project has multiple clojure files, each having main method. I am assuming this is created for testing purpose only. My solution will work for this specific scenario.
Install clojure from the below official link according to your OS
https://clojure.org/guides/install_clojure
Now we can easily execute files by below command tested on mac only. Other complicated steps aren't required now I think.
write a sample print statement in your file hello-world.clj
(println "Hello world")
Run your program with the below command in terminal
clj -M hello-world.clj
It will output
Hello world
Tested on Clojure Version: 1.11.1.1200

How to make sphinx look for modules in virtualenv while building html?

I want to build html docs using a virtualenv instead of the native environment on my machine.
I've entered the virtualenv but when I run make html I get errors saying the module can't be imported - I know the errors are due to the module being unavailable in my native environment.
How can I specify which environment should be used when searching for docs (eg the virtualenv)?
The problem is correctly spotted by Mathijs.
$ which sphinx-build
/usr/local/bin/sphinx-build
I solved this issue installing sphinx itself in the virtual environment.
With the environment activated:
$ source /home/migonzalvar/envs/myenvironment/bin/activate
$ pip install sphinx
$ which sphinx-build
/home/migonzalvar/envs/myenvironment/bin/sphinx-build
It seems neat enough.
The problem here is that make html uses the sphinx-build command as a normal shell command, which explicitly specifies which Python interpreter to use in the first line of the file (ie. #!/usr/bin/python). If Python gets invoked in this way, it will not use your virtual environment.
A quick and dirty way around this is by explicitly calling the sphinx-build Python script from an interpreter. In the Makefile, this can be achieved by changing SPHINXBUILD to the following:
SPHINXBUILD = python <absolute_path_to_sphinx-build-file>/sphinx-build
If you do not want to modify your Makefile you can also pass this parameter from the command line, as follows:
make html SPHINXBUILD='python <path_to_sphinx>/sphinx-build'
Now if you execute make build from within your VirtualEnv environment, it should use the Python interpreter from within your environment and you should see Sphinx finding all the goodies it requires.
I am well aware that this is not a neat solution, as a Makefile like this should not assume any specific location for the sphinx-build file, so any suggestions for a more suitable solution are warmly welcomed.
I had the same problem, but I couldn't use the accepted solution because I didn't use the Makefile. I was calling sphinx-build from within a custom python build file. What I really wanted to do was to call sphinx-build with the exact same environment that I was calling my python build script with. Fiddling with paths was too complicated and error prone, so I ended up with what seems to me like an elegant solution, which is to "manually" load the console script entry point and call it:
from pkg_resources import load_entry_point
cmd = load_entry_point('Sphinx', 'console_scripts', 'sphinx-build')
cmd(['sphinx-build', basepath, destpath])

What is ltmain.sh, and why does automake say it is missing? What is a good auto (make/conf/etc) generator?

I just want to develop a C app in linux with the auto(make/conf/...) stuff automatically generated. I tried generating it with ede and anjuta, but it doesn't seem to generate Makefile.am. So, I tried running automake, and it says "ltmain.sh" isn't found. Is there some easy to generate the basic build files for linux C/C++ apps. What is the standard practice? Do most people write these files themselves?
Generating a really trivial set of autotool files is pretty easy. Here's a (really basic) example. After you run these, you should get a copy of ltmain.sh in the directory, and you'll be all set to run the configure script:
$ mkdir sample
$ cd sample
$ echo 'int main( void ) { return 0; }' > foo.c
$ echo 'bin_PROGRAMS = foo' > Makefile.am
$ autoscan
$ mv configure.scan configure.ac
$ # edit configure.ac, add AM_INIT_AUTOMAKE([foreign])
$ # and LT_INIT, set project name and bug-report-address
$ autoreconf -ivf
Note that in this example, libtool really isn't necessary since
the example is just building a simple app. But you asked about
ltmain.sh, and that's a libtool thing so LT_INIT is needed to
address that portion of the question. If you want to build
a library, change bin_PROGRAMS to lib_LTLIBRARIES.
EDE can work with your Automake files in two different ways. If you write your own automake files, it will read them, and tweak them via the UI.
If you prefer, you can have EDE do the whole thing for you. First, create your first C file, then when it is on disk, do:
M-x ede-new RET Automake RET
then from the project/project options menu, add a target, like "program".
If you fill in your C file, you can then choose Project->Build->build currentproject from the menu, and it will create and setup everything needed for Automake to do it's thing, in addition to running all the misc automake commands needed.
Lastly, there is a 'run' option somewhere to run your program.
I'd consider not using autoconf and automake at all -- their complexity outweighs their benefit, particularly if you're targeting only Linux.
Note that "git", for example, doesn't use them at all; instead it simply has a moderately-complex (but comprehensible) Makefile.

How to split a Scala script into multiple files

Used as a scripting language, does Scala have some sort of include directive, or is there a way to launch a script from an other script ?
The scala command has the :load filename command to load a Scala file interactively. Alternatively the scala command's -i filename argument can be used to preload the file.
As of beginning of 2013, there seems to be no built-in support for multiple-file scripts.
There's one guy that implemented #include support for non-interactive scala scripts, by assembling and compiling the files in a prior stage (have not tried it yet).
Here is the blog post about it:
http://www.crosson.org/2012/01/simplifying-scala-scripts-adding.html
And the git repository:
https://github.com/dacr/bootstrap
I hope this, or something along the lines, get official some day, since the -i filename scala switch seems to apply only for the interactive console.
Until then a proper scripting language, like Ruby, might still remain the best option.
Ammonite is an option. It implements scala (plus extensions) including import in scripts.