by timz on 10/13/24, 5:15 AM with 65 comments
zsh/bash/sh, python, javascript or anything else available on your system.
Handy for replacing one-line-based package.json scripts or shell-based Makefiles.
One can also write documentation and explanations to various commands in the same `.md` file.
Most editors highlight correctly most languages in the markdown code blocks, even when you use several scripting languages.
Here is a demo .md file https://github.com/tzador/makedown/blob/main/DEMO.md
More information available in the https://github.com/tzador/makedown/blob/main/README.md
Provided the following `example.md` in the root of your project, the defined commands are available to run from any of the projects subfolders:
--- Start of example.md ---
# hello
Prints "Hello" to `stdout` using Zsh.
```zsh
echo "Hello"
```
# world
Just prints "World" to `stdout` using JavaScript.
```js
console.log("World");
```
# weather-tomorrow
Prints the weather for tomorrow to `stdout` using Zsh.
```zsh
curl wttr.in/tomorrow
```
# generate-password
Prints a random password to `stdout` using Python.
```python
import random
import string
length = 16
characters = string.ascii_letters + string.digits + string.punctuation
password = ''.join(random.choice(characters) for _ in range(length))
print(password)
```
--- End of example.md ---
You can run any of the commands from anywhere in the project,
just by typing `makedown a-command-name` or a shorter `m a-command-name`. $ makedown --help
hello - Prints "Hello" to `stdout` using Zsh.
world - Just prints "World" to `stdout` using JavaScript.
weather-tomorrow - Prints the weather for tomorrow to `stdout` using Zsh.
generate-password - Prints a random password to `stdout` using Python.
$ makedown hello
Hello
$ makedown world
World
$ m weather-tomorrow
Sunshine # prints more details actually
$ m generate-password
4444444444444444
$ m generate-password --help
Prints a random password to `stdout` using Python.
The commands have simple syntax, they start with a header with a link and stop
when the next header starts.Like so:
# [a-command-name]() A short description.
Some documentation.
```bash
some command
```
You can use other interpreters, like `python`, `node`, `ruby`, etc.You can also use a custom interpreter specified using hashbang, like:
# [run-deno-script]() Runs a script using the Deno interpreter.
Deno has to be installed on your system.
```typescript
#!/usr/bin/env deno run
const message: string = "hello, world";
console.log(message);
```
All the .md files in the current directory and all the parents are examined
when looking for commands.Would be very grateful for any suggestions or other feedback.
Thank you.
by fodkodrasz on 10/16/24, 6:43 AM
Make does:
- topological sorting based ordering of the dependency tree
- skipping of already up to date targets
- supports parallel execution of independent dependency subtrees
The webpage is totally unclear on this, and to me it looks like it only allows for a named entrypoint to some script snippets.
I'm a literal programming fan though, and this is a nice start, but i recommend clarifying the docs on this.
by djbusby on 10/15/24, 5:59 PM
I just do mine in bash (make.sh) and it runs scripts from make.d/ which are in whatever (python, js bash, PHP)
by divbzero on 10/16/24, 5:42 AM
For one of my projects, I tried something similar where I had code blocks in README.md like:
Usage
-----
`pip install bar` and import `foo`:
```python
import foo from bar
```
Run `foo.alice` with default arguments:
```python
foo.alice()
```
Run `foo.bob` while specifying `baz`:
```python
foo.bob(baz=0)
```
And a Makefile like: .PHONY: demo
demo: venv
@. .venv/bin/activate; sed -n '/^```python/,/^```/p' < README.md | sed '/^```/d' | python
.PHONY: venv
venv: .venv/bin/activate requirements.txt
@. .venv/bin/activate; pip install -qU pip
@. .venv/bin/activate; pip install -qUr requirements.txt
.venv/bin/activate:
@python3 -m venv .venv
So you could run all those README.md code blocks with: make demo
by snake_case on 10/15/24, 6:13 PM
I’m the creator of Mask[0], a very similar tool built with Rust. I was originally inspired by Maid[1], which is an older take on this idea built with Node and no longer maintained I believe.
I see this is based on Node as well, and I appreciate that it currently has zero dependencies. Nice work!
by tonnydourado on 10/16/24, 8:44 AM
by porridgeraisin on 10/13/24, 11:41 AM
by timz on 10/16/24, 6:26 AM
Thank you for all the feedback
by psibi on 10/16/24, 2:32 AM
by kitd on 10/16/24, 6:07 AM
I used XC for a bit, which does a similar thing, but have since reverted to make. The self-documenting nature of these tools can be very useful.
by rpastuszak on 10/16/24, 7:47 AM
If you have a README with a list of build tasks, it'll pull its content and give nicer names to whatever is placed in package.json scripts field.
(I'm using comments for that which feels clunky)
I don't update it often, but I still use it almost every day.
by quantadev on 10/16/24, 3:37 PM
Maybe we can make the embedded code be "format independent" or have different embedding syntax to extract the code from various forms of docs? Technically Markdown is already a special case of plain ASCII text, so that's cool. But since Emacs Org Mode (which is supported even in VSCode via a plugin) we could have a way that's compatible with Org Mode as well? Or would that be replicating existing Org Mode features too much? I'm not experienced in Org Mode other than to prove that VSCode plugin works however, so that's why I have to ask.
by perpil on 10/16/24, 2:48 AM
by Riverheart on 10/16/24, 2:34 AM
Thanks for sharing!
by qazxcvbnm on 10/16/24, 1:43 AM
by timz on 10/16/24, 1:16 PM
## [clean]() Cleans the generated files
```bash
rm -rf ./build
```
## [init]() Initializes the build folder
```bash
mkdir -p ./build
```
## [build](clean, init) Builds the project
This command depends on clean, and init, which are executed in that order beforehand.
gcc magic.c -o ./build/magic
by philsnow on 10/16/24, 3:40 AM
I like the idea and the execution. This bit though:
> makedown.sh
> npm install -g ...
> #!/usr/bin/env python
Gives me a bit of whiplash. I get wanting to use npm to install, since 1) lots of people have it installed and 2) it’s reasonably cross-platform and it seems like makedown is as well.
I don’t see a reason for it to be named makedown.sh instead of just makedown, though. Make itself doesn’t depend on sh to my knowledge, and you could have a makedown file with no shell build rules at all.
by bryanhogan on 10/16/24, 10:10 AM
Agree with the idea already stated here to use <h2> elements instead of <h1>.
by az09mugen on 10/13/24, 10:48 AM
by anthk on 10/17/24, 9:36 AM
by zahlman on 10/13/24, 2:15 PM
I assume that there is no support for the scripts having their own command-line arguments? Or how do you disambiguate?
Anyway, this seems like an interesting demo, but it's hard to imagine the use case.
by timz on 10/17/24, 10:40 PM
What would be pros and cons of implementing it in:
- bash/zsh
- keep in python
- rust/go
by timz on 10/13/24, 4:29 PM
- better --help messages with or without command - ## level 2 headers are used - the temp file is created in current folder, like that importing npm modules from current project works
by dsp_person on 10/16/24, 8:32 AM
- can capture output and be updated & displayed in the markdown doc.
- persistent kernels
by nunobrito on 10/15/24, 6:03 PM
At the same time easy to edit and easy to enhance with different build languages as needed.
by exabrial on 10/16/24, 1:09 PM
by emareg on 10/15/24, 10:19 PM
by pjc50 on 10/16/24, 11:08 AM
by cxr on 10/16/24, 2:12 AM
by mutant on 10/13/24, 6:51 AM
by donq1xote1 on 10/16/24, 7:20 AM