Coder Social home page Coder Social logo

mask's Introduction

Welcome!

I'm Jacob Deichert and I'm a software developer from Nanaimo, BC. Thanks for coming to check out my work.

๐Ÿงฐ Most of my experience is based around Node, Go, TypeScript, React and Svelte. For side projects, my favourite stack currently is Rust for the backend (using my custom framework built on top of hyper) and Solid on the frontend. I've also been experimenting with WebAssembly and I'm looking forward to releasing another project soon.

๐Ÿ›  I enjoy building dev tools and automating things. Mask is a CLI task runner which uses a markdown file to define commands. Svelvet was an experiment in building an esm-based compiler for Svelte.

๐Ÿงช This year I'm hoping to get into IoT and embedded development with Rust.

๐Ÿ“˜ I sometimes write about things on my blog.

๐Ÿ‘‹ You can reach me at [email protected]

mask's People

Contributors

8mobius8 avatar atty303 avatar brumhard avatar cherusk avatar drsensor avatar felipesere avatar jacobdeichert avatar jpal91 avatar jrop avatar lovejia2022 avatar lsampras avatar nicoder avatar simonsan avatar tensor-programming avatar twitu avatar vladimyr 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mask's Issues

Don't needlessly add default optional flags to commands with no source/scripts

Commands with children often don't have script logic themselves so they really don't need the default option flags like verbose.

## services

This command has no script but we still add a default
`verbose` flag to it for no reason...

### services start <service_name>

~~~bash
echo "Starting service $service_name"
~~~

Support README.md

One of the main benefits of using a markdown based task runner is that we can embed our tasks into the README.md and CONTRIBUTING.md files, giving us documentation and tasks side by side.

maid supports these as default configs, it would be nice for mask to support these too.

Interactive experience

As you can tell by the other issues I've opened, I really like mask.

One idea I had was to have a sort of interactive installer or tutorial that people could write in markdown.

So a blog post could have this at the top:

This post is available as an interactive tutorial.
Run curl https://example.com/bootstrap-mac.mask.md | mask -i --maskfile- to get started.

Then it would just work from top to bottom. It would display the markdown for a step rendered with something like mdcat as a library. The user would see the code block or commands. It would then prompt for all flag and parameter values. The user would have the option to execute the step or skip to the next one.

This one is more ambitious so if this is not something you want, I can fork mask and build it there. Though it does only require one additional global flag.

This could be useful for tutorials, posts, and even project readme's. I do find it odd that as a whole we have a lot of readme's and documentation that is not executable. Mask is the closest thing I've seen to that concept.

Default target

Make runs the first target automatically if the target is unspecified.

This would be a useful feature especially when switching between projects.

Alternatively, mask could support a syntax like this:

## \_default

~~~sh
$MASK build
~~~

## build

~~~sh
echo "Running build"
sleep 10
echo "Build Complete"
~~~

Then, if no subcommand is specified and a _default or default command exists, it will be used.

Though the issue with the above is

  1. It is rather verbose
  2. Passing arguments and keeping those in sync with the default command is difficult.

So a solution to the above issue is that aliases could be supported:

## build//\_default

~~~sh
echo "Running build"
sleep 10
echo "Build Complete"
~~~

This proposal relies on my hidden command proposal and alias proposal.

Having an explicit default rather than taking the first command specified appears to be the best approach. For projects that do not implement a default command, an error is displayed. For those that do, mask in any folder will do something useful.

Bash completion

Add bash auto completion that parses the markdown file and provides a list of commands (headings) that can be executed
Related to #17

Support optional (non-required) positional arguments

Required arguments use the round brackets like (required_arg) so optional args can probably use square brackets [optional_arg].

## say [phrase]

~~~sh
if [[ $phrase != "" ]]; then
    echo "$phrase"
else
    echo "๐Ÿ˜ถ"
fi
~~~

Add tests!

This will be the next thing I do.

Should have full integration tests against a variety of maskfile layouts and command structures.

feature: interpreter conform syntax highlighting

Could go hand in hand with introducing another suffix than .md for differentiating, I can imagine .mask. The suffix could allow for a custom syntax highlighting scheme of editors.

Find it annoying to look at the .md highlighting for the different interpreters, especially for more demanding maskfiles.

Hence, this feature request is about properly highlighting of interpreter code stretches in
`~~~interpreter

Publish to homebrew?

Wow, this project looks great. I used to use maid, and was bummed to see that it doesn't appear to be actively maintained anymore. It might lower the barrier to entry a bit for mask if it offered a brew formula, so I thought I'd create an issue and bring up the idea.

Extraction with --extract

Additional possibilities:

  • Go templates
  • Lua
  • Rego
  • YAML

Regarding YAML, that one is tricky because it could represent any data.
I don't know why, but the large majority of Kubernetes blog posts are a bunch of "now paste this block of YAML into kubectl apply"
Because mask already handles parsing the markdown, it would be useful to have mask extract those strings. For example something like the following would be useful:

mask --extract deployment document.md | kapp apply -a demo -f- -y

The same could be useful for docker-compose.yml examples, CI config, and even viewing the contents of a runnable target.

Perhaps a general extraction tool would be better suited as another project (especially for documents that don't follow the structure of a maskfile). Still, having the ability to view the code of a target before running a task would be a useful feature from the terminal.

โœจ Concurrently run multiple commands in parallel via single command definition

@jakedeichert This is such a elegant step up from package.json scripts, you my friend are awesome!

Problem

Concurrently run multiple commands in parallel via one single mask command definition.

Example

Using npm-run-all --parallel in my package.json

"scripts": {
	"watch": "del dist; npm-run-all --silent --parallel watch:*",
	"watch:nodemon": "wait-for-change dist/index.js && delay 0.1 && nodemon dist/index.js",
	"watch:tsc": "tsc --watch --preserveWatchOutput",
},

I've tried all the alternative's at the bottom of your README.md and I haven't been able to find something that has implemented this feature.

So far mask is the best I've come across, then just shortly after.

Thanks friend! =]

Forwarding arguments?

I'm not sure if this feature would be useful or necessary at all, and honestly this may just stem from my bash inexperience, but I'm having trouble forwarding (if this is the correct expression) arguments to a command that is run by mask.

For simplicity sake, say you are building a binary with cmake and attempting to run the output:

Binary usage is such:
$ ./HelloWorld -n <NAME> -l <LANG>

My mask script looks like this:

## standalone

> Builds and runs the standalone executable (cli) portion of the project

**OPTIONS**
* run
    * flags: -r --run
    * type: boolean
    * desc: Run the standalone executable after building

* args
    * flags: -a --args
    * type: string
    * desc: The args to pass to the executable when it is run (flag will be ignored if run is not also passed). If not provided the default will be '--help'.

```bash
INPUT_ARGS=${args:-"--help"}
cmake -S standalone -B build/standalone
cmake --build build/standalone

[[ "$run" == "true" ]] && ./build/standalone/HelloWorld $INPUT_ARGS
\```
(^ Ignore this backslash, it was the only way I could get this block to close)

But I'm getting errors from Mask regarding unexpected arguments (-n flag):

$ mask standalone -r -a "-n Tony"
error: Found argument '-n' which wasn't expected, or isn't valid in this context

USAGE:
    mask standalone --args <args> --run

For more information try --help

Please let me know if I'm doing something wrong or if this is indeed expected behavior, and whether there can be option to forward remaining args "inside" the mask command.

Edit: Sorry for the edit, I fat fingered control + enter to submit this too soon.
Edit2: I'm bad at formatting.

Example with sub-command does not work

The "stop all" yet requires a service name:

$ mask services stop all
error: The following required arguments were not provided:
    <service_name>

USAGE:
    mask services stop [FLAGS] <service_name> [SUBCOMMAND]
$ mask services stop foo all
Stopping everything

In order to make it work, the "stop all" sub-command has to be at the same level as the "stop"

### services stop (service_name)
### services stop all

But then the help is listing them as separated (not nested) commands:

$ mask services -h
mask-services 
Commands related to starting, stopping, and restarting services

USAGE:
    mask services <SUBCOMMAND>

FLAGS:
    -h, --help    Prints help information

SUBCOMMANDS:
    help        Prints this message or the help of the given subcommand(s)
    start       Start a service.
    stop        Stop a service.
    stop all    Stop everything.

Allow defining options that apply to children commands

## services

**OPTIONS:**
* port
    * flags: -p --port
    * type: string
    * desc: Which port to serve on


### services start <service_name>

> Start or restart a service.

Child command would have the parent's `port` variable in scope.

~~~bash
echo "Starting service $service_name on $port"
~~~

Support infinite positional args

Maybe something like my cmd (files...).

Not sure what format to inject the environment variable string as though. Perhaps just comma separated? name1,name2,name3

## services start (services...)

~~~sh
echo "Starting all services: '$services'"
~~~
mask services start api proxy email
# Starting all services: 'api,proxy,email'

Let user specify default/fallback value for named flags

I want to specify parameters list and default for option.

For instance.
When make command "formatter" from csv to json or tsv, with default no-convert,I want to specify following:

## formatter
**OPTIONS**
* target
    * flags: -t --target
    * type: string
    * desc: Which port to serve on
    * list: csv, json, tsv
    * default: csv

Allow specifying an external maskfile.md to use

Right now mask looks for a maskfile or maskfile.md in the current directory.

We should add a --maskfile <path> option so that mask can refer to another maskfile.md at the given path.

Perhaps it should also look for maskfiles in parent directories until it finds one?

Example use case:
Sometimes i'm working in a subdir of a monorepo project. Being able to put a maskfile at root of the monorepo would be nice if I could call mask from any location in that tree.

Subcommand not recognized if followed by a # HEADER line

For example, mask foo --help on

# Header 1

## foo

### foo A

```sh
echo A
```

### foo B

```sh
echo B
```

# foo B is not found as a subcommand if this line is present

prints

mask-foo 


USAGE:
    mask foo <SUBCOMMAND>

FLAGS:
    -h, --help    Prints help information

SUBCOMMANDS:
    A       
    help    Prints this message or the help of the given subcommand(s)

Bug: 0.7.0 will not compile with latest from rustup

I just updated using rustup and noticed that I'm behind in mask versions. So, I went to update and this is what I get:

error[E0432]: unresolved import self::std::hint
--> /Users/raguay/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/inline_lazy.rs:13:16
|
13 | use self::std::hint::unreachable_unchecked;
| ^^^^ Could not find hint in std

error: aborting due to previous error

error: Could not compile lazy_static.

I'm not a rust programmer, so I'm not sure how to fix this. Has anyone else seen it? Dropping back to using maid until I can get mask to build again โ˜น๏ธ.

Cargo test fails on `env_var_mask:works_from_any_dir`

failures:

---- env_var_mask::works_from_any_dir stdout ----
thread 'env_var_mask::works_from_any_dir' panicked at 'Unexpected stdout, failed var.contains("tests passed")
โ””โ”€โ”€ var as str: 

command=`"/home/twitu/Code/mask/target/debug/mask" "--maskfile" "/tmp/.tmpgB48C0/maskfile.md" "ci"`
code=127
stdout=``````
stderr=```bash: mask: command not found

If I understand correctly it's failing simply because mask executable is not installed $PATH. I tried running this after doing cargo install mask and the test passed.

Should a source code test depend on the executable being installed externally? If this is the desired behaviour it could be mentioned in the README somewhere that the executable should be installed before running tests.

Mask version: 7c31651
Cargo version: 1.43.0
OS: Ubuntu 20.04
Terminal: zsh

Combine mask + a given maskfile into a standalone binary

It should be able to take a maskfile and turn it into a standalone rust binary... not sure how possible this even is. The maskfile would need to be embedded into the mask binary or something.

This would create an easy way to make general cli programs that can be distributed to a team.

Don't add a command for a heading that has no code blocks

When a heading has no code blocks AND its child headings have no code blocks, then we shouldn't create a command for it.

Example:

# MY COMMANDS

## Docs

Just some documentation.

## cmd
~~~bash
echo something
~~~

Current Behaviour

mask -h

mask 0.8.0

USAGE:
    mask [OPTIONS] <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --maskfile <maskfile>    Path to a different maskfile you want to use

SUBCOMMANDS:
    Docs        
    cmd

Desired Behaviour

mask -h

mask 0.8.0

USAGE:
    mask [OPTIONS] <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --maskfile <maskfile>    Path to a different maskfile you want to use

SUBCOMMANDS:
    cmd

Support shorter flag syntax

Currently adding a flag is quite verbose:

## purchase (price)

> Calculate the total price of something.

**OPTIONS**
* tax
    * flags: -t --tax
    * type: number
    * desc: What's the tax?

~~~sh
TAX=${tax:-1} # Fallback to 1 if not supplied
echo "Total: $(($price * $TAX))"
~~~

We end needing to write out the flag name twice and use 4 lines.
I'd like to propose support for a shorter readable syntax:

## purchase (price)

> Calculate the total price of something.

**OPTIONS**
* flags: -t --tax |number| What's the tax?

~~~sh
TAX=${tax:-1} # Fallback to 1 if not supplied
echo "Total: $(($price * $TAX))"
~~~

If no type is specified, the |number| part can be omitted.

--list flag

It would be useful if mask --list printing a list of available commands.

Command alias proposal

Subcommand aliases can be specified by separating the command name with "//".
So # command (arg) becomes # command//c (arg)

This is an idea from #51.

Why two slashes?

  1. One forward slash doesn't visually provide enough distinction
  2. I also considered # command [c] (arg) but having a space makes it look like a subcommand and it is easier to accidentally create a markdown link: # command [c](arg)

"cd" command does not work in mask

Hi there, great tool.

I have a very weird issue with mask. I defined really simple maskfile:

# Common Tasks
easy tedious task management

## go
> go to common folders

### go work 
> go to work folder

~~~sh
echo "changing dir..."
cd $HOME/projects/work
~~~

after launching `mask go work` I'm still in current folder. I tried changing interpreter (sh, bash, zsh), interpolation, removing variables at all with no avail. I guess that must be something trivial I'm missing.

Mac OS X 11.2.3
zsh 5.8 (x86_64-apple-darwin20.0)
mask 0.10.0

Bug: mask doesn't pass exit code

Just noticed that mask command doesn't forward the exit code. This make this kind of task impossible:

## start
> Run project

```sh
mask check && mask compile && \
node dist/index.js
# this โ˜๏ธ line will always be executed regardless the compile & check process fail or success
# it should not be executed when check or compile process fail
```

Allow entering negative numbers

Clap by default doesn't allow arg values to start with a hyphen.

This becomes problematic for number values...

$ mask add 2 -3
error: Found argument '-3' which wasn't expected, or isn't valid in this context

USAGE:
    mask add [FLAGS] <a> <b>

For more information try --help

There's two settings:

And this is the caveat:

NOTE: Use this setting with caution as it silences certain circumstances which would otherwise be an error (such as accidentally forgetting to specify a value for leading option). It is preferred to set this on a per argument basis, via Arg::allow_hyphen_values

Maybe after #3 is done, we can enable this option only for number args?

Use deno for typescript and ts code blocks

Deno is a secure TypeScript runtime written in rust.

I propose that typescript code blocks use Deno to execute.
It handles dependency fetching and compiling TypeScript to JavaScript automatically. This means a maskfile.md can be self contained, there is no need to run an npm install to make the JavaScript blocks function.

Because Deno requires permission flags to operate, there would need to be a way to provide permission arguments to the deno run invocation.

Add `number` type to options for input validation purposes

The port option below has type: number which would allow us to validate the input is correct.

Note that even though we can at least validate it, it still gets turned into an environment variable which is just a string. The benefit here is that the script can assume it's always a number and cast it as such.

## serve

**OPTIONS:**
* port
    * flags: -p --port
    * type: number
    * desc: Which port to serve on

~~~node
const port = Number(process.env.port);
console.log(port * 2)
~~~

Support for musl

Add support for musl linked executable for distributions that use it (ie. Alpine). I would think this would be done by adding another asset on release that would be named
mask-vX.XX.X-x86_64-unknown-linux-musl.zip or something like it.

I have limited knowledge of rust, but seems like this could be achieved by adding another release job in .github/workflows/release.yml that could make use of an Alpine to build and target. I believe cargo needs use the target x86_64-unknown-linux-musl.

Prettier readme

Are you fine with making the readme markdown Prettier compliant?

It mostly wants to remove extra whitespace, use "`" over "~" and prefer "-" over "*". I can make a separate PR for that. It would make contributing changes easier.

Arguments don't work in Powershell

I'm using Mask on Windows 10 and have a task in my maskfile.md that accepts an argument, however this seems to be empty when tested in the script. I've tested both the legacy Powershell that ships with the system (some flavour of 5.1) and the current preview release of the modern Powershell and in both cases Powershell will just output an empty line.

OS: Windows 10 21313.1000
Shell: Powershell 5.1.21313.100, Powershell 7.2.0-preview.3

# Powershell example
## powershell legacy (value)
> 5.1.21313.100
~~~powershell
Get-Host | Select-Object Version
Write-Output "${value}"
~~~

## powershell modern (value)
> 7.2.0-preview.3
~~~pwsh
Get-Host | Select-Object Version
Write-Output "${value}"
~~~

Windows support?

Currently, this is unknown. I'm pretty sure the executor logic will need to be adjusted for Windows.

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.