When writing the following Haskell script (saved in Main.hs),
module Main where
main :: IO ()
main = do
input <- readFile "input.txt"
print $ countWords input
-- Counts the number of words per line
countWords input = map (length . words) (lines input)
I have to repeat the following process again and again:
-
save the script file;
-
run
stack build --exec Code0101
orstack build && stack exec Code0101
-
edit the file;
-
back to step 1 ...
I need a tool to automate this process, and let me concentrate on coding.
ghcid
ndmitchell/ghcid can reload your script
after file changed, and run script via the --test
argument.
Install with stack install ghcid
and open an editor in the left window,
run ghcid --test "main"
in the right window and that's all.
For a bare Haskell script (instead of files in a stack project),
and a system level ghci
is installed, you need start it with
ghcid "--command=stack ghci solutions19.hs" --test main
.
It is much faster than entr
and watchman
but only for Haskell.
See ghcid for the win! for details.
entr
entr is a tool running arbitrary commands when files change.
Download its source codes (entr-4.1.tar.gz) from its website, extract and install:
./configure
make test
sudo make install
Now open your editor in the left window, run
ls *.hs | entr -r stack build --exec Code0101
in the right window and that's all.
With the -r
option, you can press SPACE to terminate the current running
command (here it's stack build
and restart it immediately as if a file change
event had occurred. See man entr
for details.
Press q
to quit the watcher.
See stack build --file-watch-post=
The following scenario is running a PySpark project pv-current, which contains several Python scripts, on a remote host cdh1. You can copy the project folder onto cdh1, edit the scripts there. But the vim on cdh1 is very primitive. You can't comment/uncomment block codes, copy/paste from clipboard, ...
You can edit the file with your local vim with vi scp://cdh1/docs/pv-current/main.py
.
But when can want to edit another file, you have to quit the editor and run
another command. Meanwhile you have no local copy of the modified version.
With entr
you can easily edit the local files with all benefits of a local editor
and sync them automatically to remote host once the file changes are saved:
ls *.py | entr -c rsync -av *.py cdh1:~/docs/pypv
Here the rsync
command runs quickly so there's no need to use -r
option.
The -c
option clears the screen every time the command (rsync
) is invoked.
Note: rsync
must be installed on the remote server, or the rsync
command
will fail: rsync error: remote command not found (code 127).
watchman
watchman watch file changes and run some actions when watching file changes.
sudo apt install libtool
git clone https://github.com/facebook/watchman.git
cd watchman
git checkout v4.9.0 # the latest stable release
./autogen.sh
./configure
make
sudo make install
pip install pywatchman
However watchman is very complicated.
So there's a watchman-make
shipped with watchman to make thing easier.
Now it's incompatible with Python3, but you can fix it like this:
search basestring
in $(which watchman-make), and replace the line
if isinstance(values, basestring):
with:
if pywatchman.compat.PYTHON3:
STRING_TYPES = (str, bytes)
else:
STRING_TYPES = (str, unicode)
if isinstance(values, STRING_TYPES):
Run the following command in the project root folder:
watchman-make -p '*.hs' --make='stack build && stack exec' -t 'Code0101'
and open an editor.
Now every time you change the *.hs file and save, stack
will build and run.
But you have to delete the watch manually:
watchman watch-del "/home/leo/docs/bookSourceCodes/Haskell-Data-Analysis-Cookbook"
Ref:
-
[watchman-make not working on python3](https://github.com/facebook/watchman/issues/631(
Note:
schell/steeloverseer is another candidate.
But after I ran stack install steeloverseer
on Ubuntu 16.04,
the following error raised:
/tmp/stack11108/steeloverseer-2.0.2.0/app/Main.hs:258:5: error:
• The constructor ‘FSNotify.Added’ should have 3 arguments, but has been given 2
• In the pattern: FSNotify.Added path _
In a case alternative:
FSNotify.Added path _ -> S.yield (FileAdded (go cwd path))
In the second argument of ‘S.for’, namely
‘(\case
FSNotify.Added path _ -> S.yield (FileAdded (go cwd path))
FSNotify.Modified path _ -> S.yield (FileModified (go cwd path))
FSNotify.Removed _ _ -> pure ())’
|
258 | FSNotify.Added path _ -> S.yield (FileAdded (go cwd path))
| ^^^^^^^^^^^^^^^^^^^^^^^^
Looks like API incompatible.
inotify
See note "两台 Linux 主机上文件夹间远程同步" for details.
watchdog
Watchdog is a Python library.