Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A flexible developer tool that runs processes and responds to filesystem changes

License

NotificationsYou must be signed in to change notification settings

cortesi/modd

Repository files navigation

Travis Build Status

Modd is a developer tool that triggers commands and manages daemons in responseto filesystem changes.

If you use modd, you should also look atdevd, a compact HTTP daemon for developers.Devd integrates with modd, allowing you to trigger in-browser livereload withmodd.

The repo contains a set of examplemodd.conf files that you can look at for aquick idea of what modd can do:

ExampleDescription
frontend.confA front-end project with React + Browserify + Babel. Modd and devd replace many functions of Gulp/Grunt.
go.confLive unit tests for Go.
python.confPython + Redis, with devd managing livereload.

Install

Modd is a single binary with no external dependencies, released for OSX,Windows, Linux, FreeBSD, NetBSD and OpenBSD. Go to thereleasespage, download the package foryour OS, and copy the binary to somewhere on your PATH.

Alternatively, with Go 1.17+ installed, you can installmodd directly usinggo install. Please note that CGO is required, so if you happen to have it disabled you will need to prepend theCGO_ENABLED=1 environment variable.

$ go install github.com/cortesi/modd/cmd/modd@latest

Quick start

Put this in a file calledmodd.conf:

**/*.go {    prep: go test @dirmods}

Now run modd like so:

$ modd

The first time modd is run, it will run the tests of all Go modules. Wheneverany file with the .go extension is modified, the "go test" command will be runonly on the enclosing module.

Details

On startup, modd looks for a file calledmodd.conf in the current directory.This file has a simple but powerful syntax - one or more blocks of commands,each of which can be triggered on changes to files matching a set of filepatterns. Themodd.conf file is meant to be portable, and can safely bechecked into source repositories. Functionality that users will want tocustomize (like desktop notifications) is controlled through command-lineflags.

Commands have two flavors:prep commands that run and terminate (e.g.compiling, running test suites or running linters), anddaemon commands thatrun and keep running (e.g databases or webservers). Daemons are sent a SIGHUP(by default) when their block is triggered, and are restarted if they ever exit.

Prep commands are run in order of occurrence. If any prep command exits with anerror, execution of the current block is stopped immediately. If all prepcommands succeed, any daemons in the block are restarted, also in order ofoccurrence. If multiple blocks are triggered by the same set of changes, theytoo run in order, from top to bottom.

Here's a modified version of themodd.conf file I use when hacking on devd.It runs the test suite whenever a .go file changes, builds devd whenever anon-test file is changed, and keeps a test instance running throughout.

**/*.go {    prep: go test @dirmods}# Exclude all test files of the form *_test.go**/*.go !**/*_test.go {    prep: go install ./cmd/devd    daemon +sigterm: devd -m ./tmp}

The@dirmods variable expands to a properly escaped list of all directoriescontaining changed files. When modd is first run, this includes all directoriescontaining matching files. So, this means that modd will run all tests onstartup, and then subsequently run the tests only for the affected modulewhenever there's a change. There's a corresponding@mods variable thatcontains all changed files.

Note the+sigterm flag to the daemon command. When devd receives a SIGHUP(the default signal sent by modd), it triggers a browser livereload, ratherthan exiting. This is what you want when devd is being used to serve a webproject you're hacking on, but when developing devditself, we actually wantit to exit and restart to pick up changes. We therefore tell modd to send aSIGTERM to the daemon instead, which causes devd to exit and be restarted bymodd.

By default modd interprets commands using abuilt-in POSIX-likeshell. Some external shells are also supported,and can be used by setting@shell variable in your "modd.conf" file.

File watch patterns

Modd batches up changes until there is a lull in filesystem activity - thismeans that coherent processes like compilation and rendering that touch manyfiles are likely to trigger commands only once. Patterns therefore match on abatch of changed files - when the first match in a batch is seen, the block istriggered.

Patterns and the paths they match against are always in slash-delimited form,even on Windows. Paths are cleaned and normalised being matched, with redundantcomponents removed. If the path is within the current working directory, thenormalised path is relative to the current working directory, otherwise it isabsolute. One subtlety is that this means that a pattern like./*.js willnever match, because inbound paths will not have a leading./ component - justuse*.js instead.

Quotes

File patterns can be naked or quoted strings. Quotes can be either single ordouble quotes, and the corresponding quote mark can be escaped with a backslashwithin the string:

"**/foo\"bar"

Negation

Patterns can be negated with a leading!. For quoted patterns, theexclamation mark goes outside of the quotes. So, this matches all filesrecursively, bar those with a .html extension and those in thedocsdirectory.

** !**/*.html !"docs/**"

Negations are applied after all positive patterns - that is, modd collects allfiles matching the positive patterns, then removes files matching the negationpatterns.

Default ignore list

Common nuisance files like VCS directories, swap files, and so forth areignored by default. You can list the set of ignored patterns using the-iflag to the modd command. The default ignore patterns can be disabled using thespecial+noignore flag, like so:

.git/config +noignore {    prep: echo "git config changed"}

Empty match pattern

If no match pattern is specified, prep commands run once only at startup, anddaemons are restarted if they exit, but won't ever be explicitly signalled torestart by modd.

{    prep: echo hello}

Symlinks

Modd does not implicitly traverse symlinks. To monitor a symlink, split the pathspecification and the matching pattern, like this:

mydir/symlinkdir foo.* {    prep: echo changed}

Behind the scenes, we resolve the symlinked directory as if it was specifieddirectly by the user. This means that if the symlink destination lies outside ofthe current working directory, the resulting paths for matches, exclusions andcommands will be absolute.

Syntax

File patterns support the following syntax:

TermMeaning
*any sequence of non-path-separators
**any sequence of characters, including path separators
?any single non-path-separator character
[class]any single non-path-separator character against a class of characters
{alt1,...}any of the comma-separated alternatives - to avoid conflict with the block specification, patterns with curly-braces should be enclosed in quotes

Any character with a special meaning can be escaped with a backslash (\).Character classes support the following:

ClassMeaning
[abc]any character within the set
[a-z]any character in the range
[^class]any character which doesnot match the class

Blocks

Each file match pattern specification has an associated block, which isenclosed in curly brackets. Blocks contain commands and block-scoped options.

Single-line commands don't need to be quoted:

prep: echo "I'm now rebuilding" | tee /tmp/output

Newlines can be escaped with a backslash for multi-line commands:

prep: ls \        -l \        -a

You can also enclose commands in single or double quotes, letting easilyspecify compound, multi-statement commands. These can contain anything you'dnormally put in a shell script, and the same quoting and escaping conventions apply.

prep: "    ls \        -l \        -a    echo \"hello again\"    echo \"hello yet again\""

Within commands, the@ character is treated specially, since it is the markerfor variable replacement. You can include a verbatim@ symbol b escaping itwith a backslash, and backslashes preceding the@ symbol can themselves beescaped recursively.

@foo = bar{    prep: echo "@foo"   # bar    prep: echo "\@foo"  # @foo    prep: echo "\\@foo" # \bar}

Prep commands

All prep commands in a block are run in order before any daemons are restarted.If any prep command exits with an error, execution stops.

The following variables are automatically generated for prep commands

VariableMeaning
@modsOn first run, all files matching the block patterns. On subsequent change, a list of all modified files.
@confdirThe absolute path of the directory that contains the current modd config file.
@dirmodsOn first run, all directories containing files matching the block patterns. On subsequent change, a list of all directories containing modified files.

All file names in variables are relative to the current directory, andshell-escaped for safety. All paths are in slash-delimited form on allplatforms.

Given a config file like this, modd will runeslint on all .js files whenstarted, and then after that only runeslint on files if they change:

**/*.js {    prep: eslint @mods}

By default, prep commands are executed on the initial run of modd. The+onchange option can be used to skip the initial run, and only execute whenthere is a detected change.

*.go {# only trigger on file changesprep +onchange: go test}

Daemon commands

Daemons are executed on startup, and are restarted by modd whenever they exit.When a block containing a daemon command is triggered, modd sends a signal tothe daemon process group. If the signal causes the daemon to exit, it isimmediately restarted by modd - however, it's also common for daemons to doother useful things like reloading configuration in response to signals.

The default signal used is SIGHUP, but the signal can be controlled usingmodifier flags, like so:

daemon +sigterm: mydaemon --config ./foo.conf

The following signals are supported:sighup,sigterm,sigint,sigkill,sigquit,sigusr1,sigusr2,sigwinch.

Support for signals on Windows is limited. The signal type is ignored, and alldaemons are stopped and restarted when a signal would normally be sent.

The following variables are automatically generated for prep commands

VariableMeaning
@confdirThe absolute path of the directory that contains the current modd config file.

Controlling log headers

Modd outputs a short header on the terminal to show which command is responsiblefor output. This header is calculated from the first non-whitespace line of thecommand - backslash escapes are removed from the end of the line, commentcharacters are removed from the beginning, and whitespace is stripped. Using thefact that the shell itself permits comments, you can completely control the logdisplay name.

{    # This will show as "prep: mycommand"    prep: "        mycommand \            --longoption 1 \            --longoption 2    "    # This will show as "prep: daemon 1"    prep: "        # daemon 1        mycommand \            --longoption 1 \            --longoption 2    "}

Options

The only block option at the moment isindir, which controls the executiondirectory of a block. Modd will change to this directory before executingcommands and daemons, and change back to the previous directory afterwards.

The directory specification follows the same conventions as commands, and canbe enclosed in quotes to span multiple lines.

{    indir: ./my/directory    prep: ls}

Variables

Variables are declared as follows:

@variable = value

Variables can only be declared in the global scope (i.e. not inside blocks). Allvalues are strings and follow the same semantics as commands - that is, they canhave escaped line endings, or be quoted strings. Variables are read once atstartup, and it is an error to re-declare a variable that already exists.

You can use variables in commands like so:

@dst = ./build/dst** {    prep: ls @dst}

There is a special "@shell" variable that determines which shell is used toexecute commands. Valid values aremodd (the default),bash,sh andpowershell. This variable is set as follows:

@shell = bash

Avoid using the@shell variable if you can - using the built-in shell ensuresthatmodd.conf files remain portable across platforms.

Desktop Notifications

When the-n flag is specified, modd sends anything sent tostderr from anyprep command that exits abnormally to a desktop notifier. Since modd commandsare shell scripts, you can redirect or manipulate output to entirely customisewhat gets sent to notifiers as needed.

At the moment, we supportGrowl on OSX, andlibnotify on Linux and otherUnix systems.

Growl

For Growl to work, you will need Growl itself to be running, and have thegrowlnotify command installed. Growlnotify is an additional tool that youcan download from the officialGrowlwebsite.

Libnotify

Libnotify is a general notification framework available on most Unix-likesystems. Modd uses thenotify-send command to send notifications usinglibnotify. You'll need to use your system package manager to installlibnotify.

Colour output in process logs

Some programs that have colourised output when run on the command-line don'temit colour when run under modd. Users might assume that modd is stripping thecolour from the command output, but that is not the case. Well-behaved terminalprograms check whether they are connected to a terminal, and if not, disablecolour codes in their own output. It is possible to trick a program intobelieving that a terminal is present through pseudo-terminal emulation, but thisis complex and platform dependent and is not a good fit for a simple, reliabletool like modd.

This leaves users with two options:

  • Many tools that produce colour output also have a flag to force colour when noterminal is detected, and many logging libraries with human-friendly output dothe same. The simplest solution is to work out how to force output andexplicitly specify this in your modd configuration.
  • There are platform-specific tools you can interpose between modd and thesubprocess to emulate a terminal. One example isunbuffer on Linux.

Development

The scripts used to build this package for distribution can be foundhere.

About

A flexible developer tool that runs processes and responds to filesystem changes

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp