Skip to content

wtetsu/gaze

Repository files navigation

gaze logo
Gaze is gazing at you

Test Go Report Card Maintainability codecov Go Reference

What is Gaze?

👁️Gaze runs a command, right after you save a file.

It greatly helps you to focus on writing code! gaze02


Setting up Gaze is easy.

gaze .

Then, invoke your favorite editor on another terminal and edit it!

vi a.py

Installation

Brew (for macOS)

brew install gaze

Or, download binary

Usage examples

  • Modify a.py -> 👁️Runs python a.py
  • Modify a.rb -> 👁️Runs rubocop
  • Modify a.js -> 👁️Runs npm run lint
  • Modify a.go -> 👁️Runs make build
  • Modify Dockerfile -> 👁️Runs docker build
  • And so forth...

Software development often requires us to repeatedly execute the same command manually.

For example, when writing a simple Python script, you may create a.py file, write a few lines of code, and run python a.py. If the result isn't what you expected, you edit a.py and run python a.py again.

Again and again...

As a result, you may find yourself constantly switching between the editor and terminal, typing the same command repeatedly.

This can be frustrating and a waste of time and energy🙄


👁️Gaze runs a command for you, right after you save a file.

Why Gaze? (Features)

Gaze is designed as a CLI tool that accelerates your coding.

  • 📦 Easy to use, out-of-the-box
  • ⚡ Super quick reaction
  • 🌎 Language-agnostic, editor-agnostic
  • 🔧 Flexible configuration
  • 💻 Multiplatform (macOS, Windows, Linux)
  • 📝 Create-and-rename file actions handling
  • 🔍 Advanced options for more control
    • -r: restart (useful for server applications)
    • -t 2000: timeout (useful if you sometimes write infinite loops)
  • 🚀 Optimal parallel handling

Gaze was developed for supporting daily coding.

Even though there are already many "update-and-run" type of tools, I would say Gaze is the best for quick coding because all the technical design decisions have been made for that purpose.

How to use Gaze

The top priority of the Gaze's design is "easy to invoke".

gaze .

Then, switch to another terminal and run vi a.py. Gaze executes a.py in response to your file modifications.

Other examples

Gaze at one file.

gaze a.py

Specify files with pattern matching (*, **, ?, {, })

gaze "*.py"
gaze "src/**/*.rb"
gaze "{aaa,bbb}/*.{rb,py}"

Specify an arbitrary command by -c option.

gaze "src/**/*.js" -c "eslint {{file}}"

Kill the previous one before launching a new process. This is useful if you are writing a server.

gaze -r server.py

Kill an ongoing process after 1000(ms). This is useful if you love infinite loops.

gaze -t 1000 complicated.py

Specify multiple commands in quotations, separated by newlines.

gaze "*.cpp" -c "gcc {{file}} -o a.out
ls -l a.out
./a.out"

Output when a.cpp was updated.

[gcc a.cpp -o a.out](1/3)

[ls -l a.out](2/3)
-rwxr-xr-x 1 user group 42155 Mar  3 00:31 a.out

[./a.out](3/3)
hello, world!

If a certain command exited with non-zero, Gaze doesn't invoke the next command.

[gcc a.cpp -o a.out](1/3)
a.cpp: In function 'int main()':
a.cpp:5:28: error: expected ';' before '}' token
   printf("hello, world!\n")
                            ^
                            ;
 }
 ~
exit status 1

Configuration

Gaze is Language-agnostic.

For convenience, it has useful default configurations for some major languages (e.g. Go, Python, Ruby, JavaScript, Rust, and so forth)

Thanks to the default configurations, the command below is valid.

gaze a.py

The above command is equivalent to gaze a.py -c 'python "{{file}}"'.

You can display the default YAML configuration by gaze -y.

commands:
  - ext: .go
    cmd: go run "{{file}}"
  - ext: .py
    cmd: python "{{file}}"
  - ext: .rb
    cmd: ruby "{{file}}"
  - ext: .js
    cmd: node "{{file}}"
  - ext: .d
    cmd: dmd -run "{{file}}"
  - ext: .groovy
    cmd: groovy "{{file}}"
  - ext: .php
    cmd: php "{{file}}"
  - ext: .java
    cmd: java "{{file}}"
  - ext: .kts
    cmd: kotlinc -script "{{file}}"
  - ext: .rs
    cmd: |
      rustc "{{file}}" -o"{{base0}}.out"
      ./"{{base0}}.out"
  - ext: .cpp
    cmd: |
      gcc "{{file}}" -o"{{base0}}.out"
      ./"{{base0}}.out"
  - ext: .ts
    cmd: |
      tsc "{{file}}" --out "{{base0}}.out"
      node ./"{{base0}}.out"
  - re: ^Dockerfile$
    cmd: docker build -f "{{file}}" .

Note:

  • To specify both ext and re for one cmd is prohibited
  • cmd can have multiple commands. Use vertical line(|) to write multiple commands

If you want to customize it, please set up your own configuration file.

gaze -y > ~/.gaze.yml
vi ~/.gaze.yml

Gaze searches a configuration file according to its priority rule.

  1. A file specified by -f option
  2. ~/.config/gaze/gaze.yml
  3. ~/.gaze.yml
  4. (Default)

Options:

Usage: gaze [options...] file(s)

Options:
  -c  Command(s) to run when files are changed.
  -r  Restart mode. Sends SIGTERM to the ongoing process before invoking the next command.
  -t  Timeout(ms). Sends SIGTERM to the ongoing process after the specified time has elapsed.
  -f  Specify a YAML configuration file.
  -v  Verbose mode. Displays additional information.
  -q  Quiet mode. Suppresses normal output.
  -y  Displays the default YAML configuration.
  -h  Displays help.
  --color    Color mode (0:plain, 1:colorful).
  --version  Display version information.

Examples:
  gaze .
  gaze main.go
  gaze a.rb b.rb
  gaze -c make "**/*.c"
  gaze -c "eslint {{file}}" "src/**/*.js"
  gaze -r server.py
  gaze -t 1000 complicated.py

For more information: https://github.com/wtetsu/gaze

Command format

You can write Mustache templates for commands.

gaze -c "echo {{file}} {{ext}} {{abs}}" .
Parameter Example
{{file}} src/mod1/main.py
{{ext}} .py
{{base}} main.py
{{base0}} main
{{dir}} src/mod1
{{abs}} /my/proj/src/mod1/main.py

Third-party data