├── .gitattributes
├── .github
├── alfons-banner.png
├── alfons-logo-64x.png
├── alfons-logo.svg
├── dependency-graph
├── dependency-graph.png
└── workflows
│ └── main.yml
├── .gitignore
├── Alfons.moon
├── Alfons.yue
├── LICENSE
├── README.md
├── alfons.lua
├── alfons
├── env.moon
├── file.moon
├── getopt.moon
├── help.moon
├── init.moon
├── look.moon
├── parser.moon
├── provide.moon
├── setfenv.moon
├── tasks
│ ├── fetch.lua
│ ├── fetch.moon
│ ├── teal.lua
│ └── teal.moon
├── version.moon
└── wildcard.moon
├── bin
├── alfons.moon
├── completion.bash
├── completion.fish
└── completion.zsh
├── docs
├── README.md
├── api.md
├── arguments.md
├── autocompletion.md
├── branding.md
├── build.md
├── documenting.md
├── environment.md
├── loading.md
├── provide.md
├── recipes.md
├── teal.md
├── tutorial.md
└── watch.md
├── rock-dev.yml
├── rock.yml
├── rockspecs
├── alfons-4.0-1.rockspec
├── alfons-4.0.1-1.rockspec
├── alfons-4.0.2-1.rockspec
├── alfons-4.1-1.rockspec
├── alfons-4.1.1-1.rockspec
├── alfons-4.1.3-1.rockspec
├── alfons-4.1.4-1.rockspec
├── alfons-4.2-1.rockspec
├── alfons-4.2.1-1.rockspec
├── alfons-4.2.2-1.rockspec
├── alfons-4.3-1.rockspec
├── alfons-4.4-1.rockspec
├── alfons-4.4.1-1.rockspec
├── alfons-5.0.0-1.rockspec
├── alfons-5.0.1-1.rockspec
├── alfons-5.0.2-1.rockspec
├── alfons-5.1-1.rockspec
├── alfons-5.2-1.rockspec
├── alfons-5.2.1-1.rockspec
├── alfons-5.2.2-1.rockspec
├── alfons-5.3-1.rockspec
├── alfons-5.3.1-1.rockspec
├── alfons-dev-5.0.2-1.rockspec
├── alfons-dev-5.1-1.rockspec
├── alfons-dev-5.2-1.rockspec
└── alfons-dev-5.2.1-1.rockspec
└── test
├── alfons
├── dusubalf.moon
├── graph-proof
│ ├── a.moon
│ ├── b.moon
│ ├── c.moon
│ ├── d.moon
│ ├── e.moon
│ ├── f.moon
│ └── main.moon
├── lua.lua
├── main.moon
├── predet.moon
├── predet2.moon
├── sidea.moon
├── sideb.moon
├── storea.moon
├── storeb.moon
├── subalf.moon
├── teal-table.tl
└── teal.tl
├── graph-proof.moon
├── lua.moon
├── predet.moon
├── runString.moon
├── store.moon
└── teal.moon
/.gitattributes:
--------------------------------------------------------------------------------
1 | alfons.lua linguist-generated
2 | test/alfons/lua.lua -linguist-detectable
--------------------------------------------------------------------------------
/.github/alfons-banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daelvn/alfons/18d688f0755445134e41829a70e3296b39fed82c/.github/alfons-banner.png
--------------------------------------------------------------------------------
/.github/alfons-logo-64x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daelvn/alfons/18d688f0755445134e41829a70e3296b39fed82c/.github/alfons-logo-64x.png
--------------------------------------------------------------------------------
/.github/alfons-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/dependency-graph:
--------------------------------------------------------------------------------
1 | 5Zhbb5swFMc/DdL2sCrYQNLXptlFWrVJeVj76MIJeDWYOaYh+/Qz5RAuVm9LIlL1JfL54+PL//xMLBw6T8sviuXJlYxAOGQSlQ69dAiZudT8VsK2FrzArYVY8aiWOsKS/wUUJ6gWPIJ1r6OWUmie98VQZhmEuqcxpeSm320lRX/WnMVgCcuQCVv9xSOd4LbItNW/Ao+TZmY3OK+fpKzpjDtZJyySm45EFw6dKyl13UrLOYjKu8aXOu/zI093C1OQ6ZckzKa+t7xmf+5W6Tc/F/yKFsEnHOWeiQI3/CFlPPuIS9bbxgez+rxq5kqGsDamXmwSrmGZs7CSN6b4Rkt0KkzkmuYtC+9iJYss+lFowTNAHScEpaF8dCfuzh/DFcgUtNqaLphAG0uRKbeJN50KoZR0iuOhxpCJeDdya5tpoHOvcHFm2QWRoQhDqXQiY5kxsWjViwdroBp1YqK2z3cpc7TqN2i9xSPBCi37BkPJ9XWVfuZjdIODVe3LshtsmyAz2+0kVeFNM14VtGkPUZNX76/a1NMlMx7IQoXwhFcEDzFTMejnyLQRUCCY5vf9dRy8oMQ6Fswqcb+Az5yGA1BPJn3qd/FY1J+/FeoPSC/dk0pM/Sm5mbl9oQWTM9cjM3+Kv/3XWzCoYH12cIxBEXeL+v+6Ugv+29HhH77yR4e/uZ+8K/q9Y9E/Ku+exXs4Ou+ed2q803fIu38U3smwtsOiHZl33+I9Gp13d+jJbGzeyVvh/QTu9IHzsjs92fM87VXRwMIeRseeBKeGvWt5cqLYHxDf6Qvx3ff6s1dlpha+q9HxtW4px8PXhO2nsvqfsP3eSBf/AA==
--------------------------------------------------------------------------------
/.github/dependency-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daelvn/alfons/18d688f0755445134e41829a70e3296b39fed82c/.github/dependency-graph.png
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: CI
4 |
5 | # Controls when the action will run. Triggers the workflow on push or pull request
6 | # events but only for the master branch
7 | on:
8 | push:
9 | branches: [master]
10 | pull_request:
11 | branches: [master]
12 |
13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
14 | jobs:
15 | # This workflow contains a single job called "build"
16 | build:
17 | # The type of runner that the job will run on
18 | runs-on: ubuntu-latest
19 |
20 | # Steps represent a sequence of tasks that will be executed as part of the job
21 | steps:
22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
23 | - uses: actions/checkout@v2
24 |
25 | # Install glibc and yaml
26 | - name: Install libyaml
27 | run: |
28 | sudo apt install libyaml-dev
29 |
30 | # Lua
31 | - name: Install Lua/LuaJIT
32 | uses: leafo/gh-actions-lua@v8.0.0
33 | with:
34 | luaVersion: 5.1
35 |
36 | - name: Install LuaRocks
37 | uses: leafo/gh-actions-luarocks@v4
38 | with:
39 | # The version of LuaRocks to install, must be available on https://luarocks.github.io/luarocks/releases/
40 | luaRocksVersion: 3.5.0
41 |
42 | # Runs a single command using the runners shell
43 | - name: Install dependencies
44 | run: |
45 | luarocks install moonscript
46 | luarocks install filekit
47 | luarocks install lpath
48 | luarocks install ansikit
49 | luarocks install http
50 | luarocks install rockbuild
51 | luarocks install amalg
52 |
53 | # Compile MoonScript
54 | - name: Compile
55 | run: |
56 | moonc alfons/
57 | moonc bin/
58 |
59 | # Pack into single script
60 | - name: Pack
61 | run: |
62 | amalg.lua -o alfons.lua -s bin/alfons.lua alfons.setfenv alfons.env alfons.file alfons.getopt alfons.provide alfons.version alfons.init alfons.look
63 |
64 | # Runs a set of commands using the runners shell
65 | - name: rockbuild -m
66 | run: |
67 | rockbuild -m "$GITHUB_SHA"
68 |
69 | # Upload artifacts
70 | - uses: actions/upload-artifact@v2
71 | with:
72 | name: alfons
73 | path: alfons.lua
74 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
--------------------------------------------------------------------------------
/Alfons.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | --- @task make Install a local version of a version
3 | --- @option make [v] Current version
4 | make: => sh "rockbuild -m --delete #{@v}" if @v
5 | --- @task release Create and upload a release of Alfons using %{magenta}`rockbuild`%{reset}.
6 | --- @option release [v] Current version
7 | release: => sh "rockbuild -m -t #{@v} u" if @v
8 | --- @task compile Compile all MoonScript files
9 | compile: =>
10 | sh "moonc #{file}" for file in wildcard "alfons/**.moon"
11 | sh "moonc bin/alfons.moon"
12 | --- @task clean Clean all built files
13 | clean: =>
14 | show "Cleaning files"
15 | for file in wildcard "**.lua"
16 | continue if (file\match "alfons.lua") and not (file\match "bin")
17 | continue if (file\match "tasks")
18 | delete file
19 | --- @task pack Pack an Alfons build using amalg.lua
20 | --- @option pack [output o] Output file (Default: %{green}"alfons.lua"%{reset})
21 | --- @option pack [entry s] Entry file (Default: %{green}"bin/alfons.lua"%{reset})
22 | pack: =>
23 | show "Packing using amalg.lua"
24 | @o or= @output or "alfons.lua"
25 | @s or= @entry or "bin/alfons.lua"
26 | modules = for file in wildcard "./alfons/*.moon" do "alfons.#{filename file}"
27 | tasks = for file in wildcard "./alfons/tasks/*.moon" do "alfons.tasks.#{filename file}"
28 | show "amalg.lua -o #{@o} -s #{@s} #{table.concat modules, ' '} #{table.concat tasks, ' '}"
29 | sh "amalg.lua -o #{@o} -s #{@s} #{table.concat modules, ' '} #{table.concat tasks, ' '}"
30 | --- @task produce Generate %{green}`alfons.lua`%{reset}
31 | produce: =>
32 | tasks.compile!
33 | tasks.pack!
34 | tasks.clean!
35 | --- @task test Run an Alfons test
36 | --- @option test [n] Name of the test to run
37 | test: => sh "moon test/#{@n or ''}.moon"
38 | -- dummy tasks
39 | hello: => print "hello!"
40 | shello: => sh "echo 'hello!'"
41 | args: =>
42 | inspect = require "inspect"
43 | print inspect args
44 | print inspect @
45 | print inspect store
46 | print inspect calls!
47 | reargs: => tasks.args!
48 | wild: =>
49 | for file in wildcard "./**.moon"
50 | print file
51 | where: =>
52 | inspect = require 'inspect'
53 | print inspect debug.getinfo 1
54 | cmdread: =>
55 | show cmdread "echo 'hi'"
56 | reduce: =>
57 | t = {1, 2, 3}
58 | reduced = reduce t, ((acc, e) ->
59 | print 'accv', acc.v
60 | print 'e', e
61 | return {v: acc.v + e}
62 | ), { v: 0 }
63 | show reduced.v
64 |
--------------------------------------------------------------------------------
/Alfons.yue:
--------------------------------------------------------------------------------
1 | tasks:
2 | test: => "Hello from Yuescript!" |> show
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Alfons 5
2 |
3 |
4 | 
5 | 
6 | 
7 |
8 |
9 |
10 |
11 | > Alfons 5 is a rewrite of the original Alfons, written to be much more modular and usable. For the old Alfons 3, see the [`three`](https://github.com/daelvn/alfons/tree/three) GitHub branch.
12 |
13 | Alfons is a task runner to help you manage your project. It's inspired by the worst use cases of Make (this means using `make` instead of shell scripts), it will read an Alfonsfile, extract the exported functions and run the tasks in order. I would tell you that there is no real reason to use this thing, but it's becoming surprisingly useful, so actually try it out.
14 |
15 | > [!TIP]
16 | > Check out the 5.2 update!
17 | > Shell autocompletions, help messages, Taskfile documentations and extra environment functions have been added.
18 |
19 | ## Table of contents
20 |
21 | - [Alfons 5](#alfons-5)
22 | - [Table of contents](#table-of-contents)
23 | - [Changelog](#changelog)
24 | - [5.3](#53)
25 | - [5.2](#52)
26 | - [5](#5)
27 | - [4.4](#44)
28 | - [4.3](#43)
29 | - [4.2](#42)
30 | - [4.1](#41)
31 | - [Usage](#usage)
32 | - [Defining tasks](#defining-tasks)
33 | - [Calling tasks](#calling-tasks)
34 | - [Arguments](#arguments)
35 | - [Migrating from Alfons 3](#migrating-from-alfons-3)
36 | - [Missing functions](#missing-functions)
37 | - [Importable tasks](#importable-tasks)
38 | - [Installing](#installing)
39 | - [Extra features](#extra-features)
40 | - [Projects using Alfons](#projects-using-alfons)
41 | - [License](#license)
42 | - [Goodbye?](#goodbye)
43 |
44 | ## Changelog
45 |
46 | ### 5.3
47 |
48 | - **5.3.1** (02.09.2024) Fixed argument parser bug. `alfons --a --b` is now `a = true; b = true` instead of `a = "--b"`.
49 | - **5.3** (09.08.2024) Added [Yuescript](https://yuescript.org) support. Added a few functions.
50 |
51 | - **Yuescript support.** You can now use `Alfons.yue` files (or any taskfile that ends in `.yue`) to load in Yuescript tasks.
52 | - **Additions to the environment.**
53 | - `values`: Get the values of a table as an array
54 | - `entries`: Turns a table into an array of key-value tuples
55 | - `fromEntries`: Reverses the process of `entries`
56 |
57 | ### 5.2
58 |
59 | - **5.2.2** (09.08.2024) Fixed the `reduce` implementation
60 | - **5.2** (08.06.2024) Implemented Taskfile documentation, help messages and autocompletion
61 |
62 | - **Taskfile documentation.** You can now document your Taskfiles for automatic help messages and shell completion.
63 | - Check [the documentation](docs/documenting.md) for more info.
64 | - **Help messages.** You can now display a help message with `--help`, or even get help for a specific task with `--help [task]`.
65 | - This help message can be automatically generated from the detected tasks in the Taskfile.
66 | - It works best when you document your Taskfile, so you can add descriptions and options.
67 | - **Shell autocompletion.** Shell autocompletion is now available in Zsh, Bash and Fish flavors.
68 | - The Zsh and Fish flavors are by far the most complete, since Zsh's and Fish's completion systems are slightly more capable.
69 | - Bash is only able to list tasks, and sometimes options or flags for those tasks. Use Zsh.
70 | - Check [the documentation](docs/autocompletion.md) for more info and install instructions.
71 | - **Additions to the environment.**
72 | - `lines`: Split a string into lines
73 | - `split`: Split any string by any pattern
74 | - `sanitize`: Neutralizes pattern magic characters in strings
75 | - `keys`: Get the keys of a table as an array
76 | - `slice`: Creates a slice of an array
77 | - `map`, `reduce`, `filter` do to arrays what you would expect
78 | - `contains` has been rewritten
79 |
80 | ### 5
81 |
82 | - **5.0.2** (23.01.2023) Rolled back test mode
83 | - **5.0.1** (23.01.2023) Fixed rockspec dependencies
84 | - **5.0** (23.01.2023) Switched out [filekit](https://github.com/daelvn/filekit) in favor of [lpath](https://github.com/starwing/lpath).
85 |
86 | I am back to life and filekit errored on me. Filekit is terribly inefficient anyway and I don't know why I ever made it. Now I am using an actually good filesystem library. It's a breaking change, though.
87 |
88 | - **Compatibility with ComputerCraft has been removed.** Alfons 5 is not compatible with it.
89 | - **Replaced filekit with lpath**
90 | - `fs` in the environment no longer points to `filekit`, but to `path.fs`
91 | - `path`, `fsinfo` and `env` have been added to the environment, corresponding to `path`, `path.info` and `path.env` respectively.
92 | - Additions to the environment
93 | - `safeOpen`: Open IO handles safely
94 | - `listAll`: Returns a list of all files and directories recursively.
95 | - `copy`: Recursive file copy
96 | - `delete`: Recursive delete
97 | - `isEmpty`: Checks if a directory is empty
98 | - Changes to the environment
99 | - All FS operations don't deal in absolute paths anymore
100 | - `wildcard` and `iwildcard` may exhibit slightly different behavior.
101 |
102 | ### 4.4
103 |
104 | - **4.4** (04.02.2021) Added [`exists`](docs/environment.md) and **Experimental Teal Support**.
105 |
106 | Some critical bugs in the loading of taskfiles and the invocation of tasks have been fixed.
107 |
108 | ### 4.3
109 |
110 | - **4.3** (26.01.2021) Added [`calls`](docs/arguments.md#calls) and [`npairs`](docs/provide.md#npairs).
111 |
112 | ### 4.2
113 |
114 | - **4.2** (02.10.2020) Internal overhaul.
115 |
116 | Alfons 4.2 changes the whole way that Alfons works on the inside. Please refer to [Loading](docs/loading.md) and [API](docs/api.md) for the most notable work.
117 |
118 | ### 4.1
119 |
120 | - **4.1.4** (12.09.2020) - Bugfix on `default` task.
121 | - **4.1.3** (11.09.2020) - Funny Homestuck Number update. Fix `inotify` dependency.
122 | - **4.1.2** (29.08.2020) - More bugfixes
123 | - **4.1.1** (27.08.2020) - Bugfixes
124 | - **4.1** (27.08.2020) - Added [`uses`](docs/arguments.md)
125 |
126 | ## Usage
127 |
128 | Run `alfons` in a directory with an `Alfons.lua` or `Alfons.moon` file. Using MoonScript (obviously) requires installing MoonScript via LuaRocks.
129 |
130 | To see the documentation, check out the [`docs/`](docs/) folder of this repo.
131 |
132 | To get started using Alfons, check out the [Tutorial](docs/tutorial.md) or the [Recipes](docs/recipes.md).
133 |
134 | ### Defining tasks
135 |
136 | Tasks are obtained by either returning a table `{tasks={}}` where the empty table is a list of named functions, or by exporting globals. The preferred mode for Lua is exporting globals, and the preferred mode for MoonScript is returning a table, although both work in both languages.
137 |
138 | **Lua:**
139 |
140 | ```lua
141 | -- Exporting globals
142 | function always(self) print(self.name) end
143 | -- Returning table
144 | return { tasks = {
145 | always = function(self) print(self.name) end
146 | }}
147 | ```
148 |
149 | **MoonScript**
150 |
151 | ```moon
152 | -- Exporting globals
153 | export always ==> print @name
154 | -- Returning table
155 | tasks:
156 | always: => @name
157 | ```
158 |
159 | ### Calling tasks
160 |
161 | From the command line, simply pass the name of the task you wish to run. Alternatively, use `tasks.TASK` to call `TASK` if it's loaded.
162 |
163 | **Lua:**
164 |
165 | ```lua
166 | function test (self)
167 | print("I am " .. self.name .. " and " .. self.caller .. " called me.")
168 | end
169 |
170 | function call (self)
171 | tasks.test{caller = self.name}
172 | end
173 | ```
174 |
175 | **MoonScript:**
176 |
177 | ```moon
178 | tasks:
179 | test: => print "I am #{@name} and #{@caller} called me."
180 | call: => tasks.test caller: @name
181 | ```
182 |
183 | ### Arguments
184 |
185 | Arguments are passed in the `self` table of every function, which contains a field called `name` which is, well, uh, its own name. You can also use the `args` table to see the whole tree of arguments. Feel free to play with and abuse this!
186 |
187 | ### Migrating from Alfons 3
188 |
189 | Some functions are either not implemented or not yet ported.
190 |
191 | #### Missing functions
192 |
193 | `moonc`, `git`, `clone` and `toflags` do not exist anymore. The first three may be implemented at a later time, and the last won't be implemented due to the changes in Alfons' argument system. For now, you will have to use their command-line counterparts, so `moonc file` becomes `sh "moonc #{file}"` and such.
194 |
195 | #### Importable tasks
196 |
197 | `fetch`/`fetchs` is now just `fetch`, and `ms-compile` has been removed and will probably not come back. Write a compile task manually. This should work as a dropin replacement:
198 |
199 | **Lua:**
200 |
201 | ```lua
202 | compile = function()
203 | for file in wildcard "**.moon" do sh "moonc ".. file end
204 | end
205 | ```
206 |
207 | **MoonScript:**
208 |
209 | ```moon
210 | compile: => sh "moonc #{file}" for file in wildcard "**.moon"
211 | ```
212 |
213 | ## Installing
214 |
215 | ~~Since this is not upstream yet, you can't install through the LuaRocks server. However, you can install Alfons using itself.~~
216 |
217 | Alfons 4 is now available on LuaRocks!
218 |
219 | ```sh
220 | $ luarocks install alfons
221 | ```
222 |
223 | ### Extra features
224 |
225 | The preincluded task `fetch` depends on [lua-http](https://github.com/daurnimator/lua-http) to be used. The `watch` function depends on [linotify](https://github.com/hoelzro/linotify) and will not work on platforms other than Linux.
226 |
227 | ```sh
228 | $ luarocks install http # lua-http
229 | $ luarocks install inotify # linotify
230 | ```
231 |
232 | ## Projects using Alfons
233 |
234 | - [Moonbuild](https://github.com/natnat-mc/moonbuild) by the one and only [Codinget](https://github.com/natnat-mc)
235 | - [awlua](https://github.com/Le0Developer/awluas) by [Le0Developer](https://github.com/Le0Developer)
236 | - [VNDS-LOVE](https://github.com/ajusa/VNDS-LOVE) by [ajusa](https://github.com/ajusa)
237 |
238 | Thanks for using the project \<3.
239 |
240 | ## License
241 |
242 | Throwing it to the public domain. Check out the [license](https://github.com/daelvn/alfons/blob/rewrite/LICENSE.md).
243 |
244 | ## Goodbye?
245 |
246 | goodbye.
247 |
--------------------------------------------------------------------------------
/alfons/env.moon:
--------------------------------------------------------------------------------
1 | -- alfons.env
2 | -- Loading and custom environment
3 | import style from require "ansikit.style"
4 | setfenv or= require "alfons.setfenv"
5 | path = require "path"
6 | fs or= require "path.fs"
7 | env = require "path.env"
8 | fsinfo = require "path.info"
9 | unpack or= table.unpack
10 |
11 | -- forward-declare environment
12 | local ENVIRONMENT
13 |
14 | -- environment for alfons files
15 | ENVIRONMENT = {
16 | :_VERSION
17 | :assert, :error, :pcall, :xpcall
18 | :tonumber, :tostring
19 | :select, :type, :pairs, :ipairs, :next, :unpack
20 | :require
21 | :print, :style -- from ansikit
22 | :io, :math, :string, :table, :os
23 | :fs -- fs is either CC/fs or lpath.fs
24 | :path, :env, :fsinfo -- lpath, lpath.env and lpath.info respectively
25 | }
26 |
27 | -- load in environment
28 | -- loadEnv content:string, env:table -> fn:function | nil, err:string
29 | loadEnv = (content, env) ->
30 | local fn
31 | switch _VERSION
32 | -- use loadstring on 5.1
33 | when "Lua 5.1"
34 | fn, err = loadstring content
35 | unless fn
36 | return nil, "Could not load Alfonsfile content (5.1): #{err}"
37 | setfenv fn, env
38 | -- use load otherwise
39 | when "Lua 5.2", "Lua 5.3", "Lua 5.4"
40 | fn, err = load content, "Alfons", "t", env
41 | unless fn
42 | return nil, "Could not load Alfonsfile content (5.2+): #{err}"
43 | -- return
44 | return fn
45 |
46 | {
47 | :ENVIRONMENT
48 | :loadEnv
49 | }
--------------------------------------------------------------------------------
/alfons/file.moon:
--------------------------------------------------------------------------------
1 | -- alfons.file
2 | -- Gets the contents of a taskfile
3 | safeOpen = (path, mode) ->
4 | a, b = io.open path, mode
5 | return a and a or {error: b}
6 |
7 | readMoon = (file) ->
8 | local content
9 | with safeOpen file, "r"
10 | -- check that we could open correctly
11 | if .error
12 | return nil, "Could not open #{file}: #{.error}"
13 | -- read and compile
14 | import to_lua from require "moonscript.base"
15 | content, err = to_lua \read "*a"
16 | -- check that we could compile correctly
17 | unless content
18 | return nil, "Could not read or parse #{file}: #{err}"
19 | \close!
20 | -- return
21 | return content
22 |
23 | readFile = (file) ->
24 | local content
25 | with safeOpen file, "r"
26 | -- check that we could open correctly
27 | if .error
28 | return nil, "Could not open #{file}: #{.error}"
29 | -- read and compile
30 | content = \read "*a"
31 | -- check that we could compile correctly
32 | unless content
33 | return nil, "Could not read #{file}: #{content}"
34 | \close!
35 | -- return
36 | return content
37 |
38 | readLua = readFile
39 |
40 | -- REQUIRES "tl" MODULE
41 | readTeal = (file) ->
42 | local content
43 | with safeOpen file, "r"
44 | -- check that we could open correctly
45 | if .error
46 | return nil, "Could not open #{file}: #{.error}"
47 | -- read and compile
48 | import init_env, gen from require "tl"
49 | gwe = init_env true, false -- lax:true, compat:false
50 | content = gen (\read "*a"), gwe
51 | -- check that we could compile correctly
52 | unless content
53 | return nil, "Could not read #{file}: #{content}"
54 | \close!
55 | -- return
56 | return content
57 |
58 | -- REQUIRES "yue" MODULE
59 | readYue = (file) ->
60 | local content
61 | with safeOpen file, "r"
62 | -- check that we could open correctly
63 | if .error
64 | return nil, "Could not open #{file}: #{.error}"
65 | -- read and compile
66 | import to_lua from require "yue"
67 | content = to_lua \read "*a"
68 | -- check that we could compile correctly
69 | unless content
70 | return nil, "Could not read #{file}: #{content}"
71 | \close!
72 | -- return
73 | return content
74 |
75 | { :readMoon, :readLua, :readTeal, :readYue, :readFile }
76 |
--------------------------------------------------------------------------------
/alfons/getopt.moon:
--------------------------------------------------------------------------------
1 | -- alfons.getopt
2 | -- Alfons needs its own getopt because of how it calls tasks.
3 | getopt = (argl) ->
4 | args = {
5 | commands: {}
6 | }
7 | flags = {
8 | stop: false
9 | command: false
10 | wait: false
11 | }
12 | push = (o, v) ->
13 | if flags.command
14 | args[flags.command][o] = v
15 | else
16 | args[o] = v
17 | -- loop args
18 | for arg in *argl
19 | -- stop parsing
20 | if arg == "--"
21 | flags.stop = true
22 | -- add to args if stopped
23 | if flags.stop
24 | table.insert args, arg
25 | continue
26 | -- set as value for last if waiting
27 | if flags.wait
28 | -- test next arg
29 | if arg\match "^%-%-"
30 | -- next argument is another long flag
31 | -- set waiting flag to current arg, wait for next value
32 | push (flags.wait\gsub "%-", "_"), true
33 | flags.wait = arg\match "^%-%-([a-za-z0-9%-_]+)"
34 | else
35 | -- next argument is not a long flag
36 | -- proceed normally
37 | push (flags.wait\gsub "%-", "_"), arg
38 | flags.wait = false
39 | continue
40 | -- change command
41 | unless arg\match "^%-%-?"
42 | args[arg] = {}
43 | flags.command = arg
44 | table.insert args.commands, arg
45 | continue
46 | -- add short opt
47 | if flag = arg\match "^%-(%w)$"
48 | flags.wait = flag
49 | continue
50 | -- add multiple flags
51 | if flagl = arg\match "^%-(%w+)$"
52 | for chr in flagl\gmatch "."
53 | push chr, true
54 | continue
55 | -- add option with value
56 | if arg\match "^%-%-?([a-za-z0-9%-_]+)=(.+)$"
57 | opt, value = arg\match "^%-%-?([a-zA-Z0-9%-_]+)=(.+)"
58 | push (opt\gsub "%-", "_"), value
59 | continue
60 | -- add option with next value
61 | if opt = arg\match "^%-%-([a-zA-Z0-9%-_]+)$"
62 | flags.wait = opt\gsub "%-", "_"
63 | -- push if waiting
64 | if flags.wait
65 | push (flags.wait\gsub "%-", "_"), true
66 | -- return result
67 | args
68 |
69 | --
70 | { :getopt }
71 |
--------------------------------------------------------------------------------
/alfons/help.moon:
--------------------------------------------------------------------------------
1 | -- alfons.help
2 | -- Displays help messages
3 | import style from require "ansikit.style"
4 | import map, reduce from require "alfons.provide"
5 | unpack or= table.unpack
6 |
7 | Node = (type, content, options) ->
8 | node = { :type, :content }
9 | if options then for k, v in pairs options do node[k] = v
10 | return node
11 | Paragraph = (content) -> Node 'paragraph', content
12 | Columns = (options, content) -> Node 'columns', content, options
13 | Row = (content) -> Node 'row', content
14 | Cell = (content, options) -> Node 'cell', content, options
15 | Cells = (arr) -> map arr, (cell) -> Cell cell[2], cell[1]
16 | Spacer = (length) -> Node 'spacer', '', :length
17 |
18 | -- sections: {
19 | -- { type: 'paragraph', content: 'Options:' }
20 | -- { type: 'columns', padding: 2, content: {
21 | -- { type: 'row', content: {
22 | -- { type: 'cell', }
23 | -- }}
24 | -- } }
25 | -- }
26 | generateHelp = (sections, options={}) ->
27 | final = ""
28 | for section in *sections
29 | final ..= string.rep ' ', options.padding or 0
30 | switch section.type
31 | when 'paragraph'
32 | final ..= (style section.content) .. '\n'
33 | when 'spacer'
34 | final ..= string.rep '\n', section.length or 1
35 | when 'columns'
36 | -- find maximum width of each column
37 | columns = section.content
38 | lengths = {}
39 | for row_index, row in ipairs columns
40 | for cell_index, cell in ipairs row.content
41 | lengths[cell_index] = 0 unless lengths[cell_index]
42 | if (string.len cell.content) > lengths[cell_index]
43 | lengths[cell_index] = string.len cell.content
44 | -- recursively generate section
45 | for row_index, row in ipairs columns
46 | final ..= string.rep ' ', section.padding
47 | for cell_index, cell in ipairs row.content
48 | cell_length = (string.len cell.content)
49 | needed_length = lengths[cell_index]
50 | content = style (cell.color or '') .. (cell.content .. (string.rep ' ', needed_length - cell_length))
51 | final ..= content .. ' '
52 | final ..= '\n'
53 | return final
54 |
55 | {
56 | :Node, :Paragraph, :Spacer, :Columns, :Row, :Cell, :Cells,
57 | :generateHelp
58 | }
59 |
--------------------------------------------------------------------------------
/alfons/init.moon:
--------------------------------------------------------------------------------
1 | -- alfons.init
2 | -- API for running taskfiles
3 | import ENVIRONMENT, loadEnv from require "alfons.env"
4 | import getopt from require "alfons.getopt"
5 | import look from require "alfons.look"
6 | provide = require "alfons.provide"
7 | unpack or= table.unpack
8 |
9 | -- forward-declare all locals
10 | local *
11 |
12 | -- util
13 | sanitize = (pattern) -> pattern\gsub "[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0" if pattern
14 |
15 | -- prefix for modules
16 | -- FIXME roll back from test
17 | --PREFIX = "test.alfons."
18 | PREFIX = "alfons.tasks."
19 |
20 | -- initialize a new environment
21 | initEnv = (run, base=ENVIRONMENT, genv, modname="main", pretty=false, debug_mode=false) ->
22 | -- create table to be the actual environment
23 | env, envmt = {}, {}
24 | env.tasks, tasksmt = {}, {}
25 | setmetatable env, envmt
26 | setmetatable env.tasks, tasksmt
27 | if debug_mode
28 | base.debug = debug
29 | -- set envmt.__index to access environment and provided functions
30 | envmt.__index = (k) =>
31 | if genv and k == "__ran"
32 | return (getmetatable genv[modname]).__ran
33 | elseif genv and k == "store"
34 | return (getmetatable genv).store
35 | else
36 | base[k] or provide[k]
37 | -- set envmt.__newindex to get new tasks
38 | envmt.__newindex = (k, v) =>
39 | error "Task '#{k}' is not a function." if "function" != type v
40 | @tasks[k] = (t={}) -> run k, v, t
41 | -- set tasksmt.__index to give friendly messages
42 | tasksmt.__index = (k) => (rawget @, k) or do
43 | for scope, t in pairs genv
44 | for name, task in pairs t.tasks
45 | return task if k == name
46 | -- else
47 | if pretty
48 | provide.printError "Task '#{k}' does not exist."
49 | os.exit 1
50 | else
51 | error "Task '#{k}' does not exist."
52 | -- set __ran value to 0
53 | envmt.__ran = 0
54 | return env
55 |
56 | -- runs a taskfile
57 | runString = (content, environment=ENVIRONMENT, runAlways=true, child=0, genv={}, rqueue={}, pretty=false, debug_mode=false) ->
58 | return nil, "Taskfile content must be a string" unless "string" == type content
59 | -- if content has no newlines and starts with 'alfons.tasks', use look.
60 | local modname
61 | if (not content\match "\n") and (content\match "^#{sanitize PREFIX}")
62 | modname = content
63 | content, contentErr = look content
64 | if contentErr then return nil, contentErr
65 | else
66 | modname = "main"
67 | -- if modname already exists, return genv[modname]
68 | return genv[modname] if genv[modname]
69 | -- add run function
70 | -- run a single task with the proper arguments
71 | run = (name, task, argl) ->
72 | (getmetatable genv[modname]).__ran += 1
73 | --print "ran tasks for #{modname}", (getmetatable genv[modname]).__ran
74 | self = setmetatable {}, __index: argl
75 | self.name = name
76 | self.task = -> run name, task, argl
77 | callstack = (getmetatable genv).store.callstack
78 | table.insert callstack, name
79 | if (('function' != type task) and ('table' != type task))
80 | provide.printError "Task #{name} is not callable. Please check that it is a function."
81 | provide.printError "The task may be running on its own without calling it."
82 | os.exit 1
83 | -- Create error reporter
84 | errorHandler = (err) ->
85 | rewrite = err\gsub "%[string \"Alfons\"%]", "Taskfile (#{modname}:#{child})"
86 | provide.printError "Error in task `#{name}`:\n #{rewrite}"
87 | provide.printError " Callstack:\n (root)"
88 | provide.printError " " .. table.concat callstack, '\n '
89 | os.exit 1
90 | ret = xpcall (() -> task self), errorHandler
91 | table.remove callstack, #callstack
92 | return ret
93 | -- reset genv metatable
94 | setmetatable genv, {store: {callstack: {}}} unless getmetatable genv
95 | -- initialize environment
96 | env = initEnv run, environment, genv, modname, pretty, debug_mode
97 | genv[modname] = env
98 | -- load file
99 | alf, alfErr = loadEnv content, env
100 | if alfErr then return nil, "Could not load Taskfile #{child}: #{alfErr}"
101 | -- return with wrapper
102 | return (...) ->
103 | -- argument handling
104 | argl = {...}
105 | args = getopt argl
106 | rawset env, "args", args
107 | -- add utils
108 | rawset env, "uses", (cmdmd) -> provide.contains (args.commands or {}), cmdmd
109 | rawset env, "exists", (wants) ->
110 | for scope, t in pairs genv
111 | for name, task in pairs t.tasks
112 | return true if wants == name
113 | return false
114 | rawset env, "calls", (cmdmd) ->
115 | -- get currently running task
116 | callstack = (getmetatable genv).store.callstack
117 | current = callstack[#callstack]
118 | -- iterate command list and grab non-existing tasks
119 | on = false
120 | subcommands = {}
121 | i = 0
122 | for cmd in *args.commands
123 | i += 1
124 | if on
125 | break if rawget env.tasks, cmd
126 | subcommands[#subcommands+1] = cmd
127 | args.commands[i] = nil
128 | else
129 | on = true if cmd == current
130 | -- remove taken commands
131 | args.commands = [e for i, e in provide.npairs args.commands]
132 | -- return
133 | return subcommands
134 | -- run
135 | list = alf args
136 | tasks = list and (list.tasks and list.tasks or {}) or {}
137 | -- wrap tasks and put into environment
138 | for k, v in pairs tasks do env.tasks[k] = (t={}) -> run k, v, t
139 | -- add finalize tasks to the queue
140 | if fintask = (rawget env.tasks, "finalize")
141 | rqueue[#rqueue+1] = fintask
142 | -- add function for subloading
143 | rawset env, "load", (mod) ->
144 | -- add prefix to mod
145 | -- TODO add configurable prefix
146 | mod = PREFIX .. mod
147 | -- avoid mutual loading
148 | return genv[mod] if genv[mod]
149 | -- wrap
150 | subalf, subalfErr = runString mod, env, runAlways, child+1, genv, rqueue
151 | if subalfErr then error subalfErr
152 | subenv = subalf unpack argl
153 | -- add tasks to main task table
154 | -- direction: down/below
155 | --tasksmt = getmetatable env.tasks
156 | --fallback = tasksmt.__index
157 | --tasksmt.__index = (k) => (rawget @, k) or subenv.tasks[k] or fallback k
158 | tasksmt = getmetatable env.tasks
159 | tasksmt.__index = (k) => (rawget @, k) or do
160 | for scope, t in pairs genv
161 | for name, task in pairs t.tasks
162 | return task if k == name
163 | -- else
164 | if pretty
165 | provide.printError "Task '#{k}' does not exist."
166 | os.exit 1
167 | else
168 | error "Task '#{k}' does not exist."
169 | -- make the main tasks table accessible to the subloaded task table
170 | -- direction: up/above
171 | --subtasksmt = getmetatable subenv.tasks
172 | --subfallback = subtasksmt.__index
173 | --subtasksmt.__index = (k) => (rawget @, k) or env.tasks[k] or subfallback k
174 | subtasksmt = getmetatable subenv.tasks
175 | subtasksmt.__index = (k) => (rawget @, k) or do
176 | for scope, t in pairs genv
177 | for name, task in pairs t.tasks
178 | return task if k == name
179 | -- else
180 | if pretty
181 | provide.printError "Task '#{k}' does not exist."
182 | os.exit 1
183 | else
184 | error "Task '#{k}' does not exist."
185 | -- run always task
186 | if runAlways and (rawget env.tasks, "always")
187 | (rawget env.tasks, "always")!
188 | (getmetatable genv[modname]).__ran -= 1
189 | -- add trigger for default and finalize tasks
190 | rawset env, "finalize", ->
191 | -- default
192 | for scope, t in pairs genv
193 | --print "ran for #{scope}", t.__ran
194 | (rawget t.tasks, "default")! if (rawget t.tasks, "default") and t.__ran < 1
195 | -- finalize
196 | rqueue[i]! for i=#rqueue, 1, -1
197 | -- return
198 | return env
199 |
200 | { :runString, :initEnv }
201 |
--------------------------------------------------------------------------------
/alfons/look.moon:
--------------------------------------------------------------------------------
1 | -- alfons.look
2 | -- Gets the path for a module, specifically tailored for Alfons
3 | import readMoon, readLua from require "alfons.file"
4 | Path = require "path"
5 |
6 | sanitize = (pattern="") -> pattern\gsub "[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0"
7 |
8 | dirsep, pathsep, wildcard = package.config\match "^(.)\n(.)\n(.)"
9 | modsep = "%."
10 | swildcard = sanitize wildcard
11 |
12 | makeLook = (gpath=package.path) ->
13 | -- generate lists of paths
14 | paths = [path for path in gpath\gmatch "[^#{pathsep}]+"]
15 | moonpaths = [path\gsub "%.lua$", ".moon" for path in gpath\gmatch "[^#{pathsep}]+"]
16 | -- return
17 | (name) ->
18 | mod = name\gsub modsep, dirsep
19 | file = false
20 | for path in *paths
21 | pt = path\gsub swildcard, mod
22 | file = pt if Path.exists pt
23 | for path in *moonpaths
24 | pt = path\gsub swildcard, mod
25 | file = pt if Path.exists pt
26 | --
27 | if file
28 | read = (file\match "%.lua$") and readLua or readMoon
29 | content, contentErr = read file
30 | if content
31 | return content
32 | else
33 | return nil, contentErr
34 | else
35 | return nil, "#{name} not found."
36 |
37 | { :makeLook, look: makeLook! }
--------------------------------------------------------------------------------
/alfons/parser.moon:
--------------------------------------------------------------------------------
1 | -- alfons.parser
2 | -- Parses comments and other information in a taskfile
3 | import lines, sanitize, map, filter, split, slice, keys from require "alfons.provide"
4 | import style from require "ansikit.style"
5 |
6 | printerr = (t) -> io.stderr\write t .. "\n"
7 | errors = (code, msg) ->
8 | printerr style "%{red}#{msg}"
9 | os.exit code
10 | --# Comments #--
11 | -- Comments are untied from the code itself, to avoid having to
12 | -- parse every language with comment ASTs, with MoonScript does
13 | -- not even support (Yuescript does, though?).
14 | -- As such, comments must include directives in them to know
15 | -- what tasks they are referring to. Here is the documentation
16 | -- for that.
17 | --
18 | -- == Describing a task ==
19 | -- --- @task task_name Description
20 | -- --- @task compile Compiles the code.
21 | -- == Describing task option ==
22 | -- --- @option task_name [argument] Description
23 | -- --- @option release [version v] Version of the release.
24 | -- --- @option status [info i] Shows status information.
25 | -- == Enabling flags for a task ==
26 | -- --- @flag task_name flags
27 | -- --- @flag * hide
28 | -- = Builtin flags =
29 | -- hide - Hides the task from autocompletion and help
30 |
31 | parseDirective = (directive) ->
32 | return false unless directive\match "^@"
33 | operation = directive\match "^@([a-z]+)"
34 | rest = directive\match "^@[a-z]+%s+(.+)"
35 | switch operation
36 | when "task"
37 | parts = split rest, '%s+'
38 | name = parts[1]
39 | description = table.concat (slice parts, 2), ' '
40 | return "task", name, { :description, options: {} }
41 | when "flag"
42 | parts = split rest, '%s+'
43 | name, flag = parts[1], parts[2]
44 | return (name == '*' and "flag" or "task-flag"), name, flag
45 | when "option"
46 | parts = split rest, '%s+'
47 | task = parts[1]
48 | option_names, option_values, description = {}, {}, ""
49 | in_option_names, in_option_values, maybe_description, in_description = false, false, false, false
50 | for part in *parts[2,]
51 | stripped_part = part\match "([^%[%]%<%>]+)"
52 | -- realize where we are IN
53 | if not in_option_names and part\match "^%["
54 | in_option_names = true
55 | if not in_option_values and part\match "^%<"
56 | in_option_values = true
57 | if maybe_description and not part\match "^%<"
58 | maybe_description = false
59 | in_description = true
60 | -- add part depending in area
61 | if in_option_names
62 | table.insert option_names, stripped_part
63 | if in_option_values
64 | -- set as optional if ends with ?
65 | part_object = value: stripped_part
66 | if stripped_part\match '%?$'
67 | part_object =
68 | value: (stripped_part\match "([^%?]+)%?$"),
69 | optional: true
70 | table.insert option_values, part_object
71 | if in_description
72 | description ..= part .. " "
73 | -- realize where we are OUT
74 | if in_option_names and part\match "%]$"
75 | in_option_names = false
76 | maybe_description = true
77 | if in_option_values and part\match "%>$"
78 | in_option_values = false
79 | in_description = true
80 | return "option", task, { :option_names, :option_values, :description }
81 |
82 | -- Parses all comments starting with a certain marker '---'
83 | parseComments = (content, marker = '---') ->
84 | comment_lines = filter (lines content), (line) ->
85 | line\match "^%s-#{sanitize marker}%s+"
86 | directives = map comment_lines, (line) ->
87 | line\match "#{sanitize marker}%s+(.+)"
88 | state =
89 | tasks: {}
90 | flags: {}
91 | map directives, (directive) ->
92 | operation, key, value = parseDirective directive
93 | switch operation
94 | when "task"
95 | state.tasks[key] = value
96 | when "flag"
97 | table.insert state.flags, value
98 | when "task-flag"
99 | unless state.tasks[key]
100 | state.tasks[key] = {}
101 | if "table" == type state.tasks[key].flags
102 | table.insert state.tasks[key].flags, value
103 | else
104 | state.tasks[key].flags = {value}
105 | when "option"
106 | unless state.tasks[key]
107 | state.tasks[key] = {}
108 | state.tasks[key].options[value.option_names[1]] = {
109 | names: value.option_names,
110 | values: value.option_values,
111 | description: value.description,
112 | }
113 | return state
114 |
115 | { :parseComments }
116 |
--------------------------------------------------------------------------------
/alfons/provide.moon:
--------------------------------------------------------------------------------
1 | -- alfons.provide
2 | -- Functions provided to the environment
3 | import style from require "ansikit.style"
4 | import listAll, glob, iglob from require "alfons.wildcard"
5 | Path = require "path"
6 | fs = require "path.fs"
7 | unpack or= table.unpack
8 | printerr = (t) -> io.stderr\write t .. "\n"
9 |
10 | -- try loading inotify, which is an optional dependancy
11 | inotify = do
12 | ok, inotify = pcall -> require "inotify"
13 | ok and inotify or nil
14 |
15 | --# io #--
16 | -- prints (...) -> nil
17 | -- Print + style
18 | prints = (...) -> printerr unpack [style arg for arg in *{...}]
19 |
20 | -- printError (text:string) -> nil
21 | -- Prints an error
22 | printError = (text) -> printerr style "%{red}#{text}"
23 |
24 | -- safeOpen (path:string, mode:string) -> io | table
25 | -- Filekit's safeOpen
26 | safeOpen = (path, mode) ->
27 | a, b = io.open path, mode
28 | return a and a or {error: b}
29 |
30 | -- safePopen (path:string, mode:string) -> io | table
31 | safePopen = (path, mode) ->
32 | return {error: "io.popen is not available"} unless io.popen
33 | handle = io.popen path, mode
34 | return handle or {error: "Could not io.popen #{path}"}
35 |
36 | -- readfile (file:string) -> string
37 | -- Returns the contents of a file
38 | readfile = (file) ->
39 | with safeOpen file, "r"
40 | if .error
41 | error .error
42 | else
43 | contents = \read "*a"
44 | \close!
45 | return contents
46 |
47 | -- writefile (file:string, content:string) -> nil
48 | -- Writes into a file
49 | writefile = (file, content) ->
50 | with safeOpen file, "w"
51 | if .error
52 | error .error
53 | else
54 | \write content
55 | \close!
56 |
57 | -- serialize (t:table) -> string
58 | -- Quick and dirty serialize function
59 | serialize = (t) ->
60 | full = "return {\n"
61 | for k, v in pairs t
62 | full ..= " ['#{k}'] = '#{v}',"
63 | full ..= "}"
64 | return full
65 |
66 | -- ask (str:string) -> string
67 | -- Gets input from the user, with a prompt (optionally styled).
68 | ask = (str) ->
69 | io.write style str
70 | return io.read!
71 |
72 | -- show (str:string) -> nil
73 | -- Displays a message, but fancy
74 | show = (str) -> prints "%{cyan}:%{white} #{str}"
75 |
76 | -- env {string:string}
77 | -- Proxy table to os.getenv
78 | env = setmetatable {}, __index: (i) => os.getenv i
79 |
80 | --# commands #--
81 | -- cmd (str:string) -> number
82 | -- os.execute
83 | cmd = os.execute
84 | sh = cmd
85 |
86 | -- cmdfail (str:string) -> nil
87 | -- os.execute, but quits on fail
88 | cmdfail = (str) ->
89 | code = cmd str
90 | os.exit code unless code == 0
91 | shfail = cmdfail
92 |
93 | -- cmdread (cmd:string) -> string
94 | -- opens a command and returns its output or error message
95 | cmdread = (cmd, raw) ->
96 | with safePopen cmd, "r"
97 | if .error
98 | error .error
99 | return .error
100 | else
101 | contents = \read "*a"
102 | \close!
103 | return contents
104 | shread = cmdread
105 |
106 | --# path #--
107 | basename = (file) -> file\match "(.+)%..+" -- basename (file:string) -> string
108 | filename = Path.stem -- filename (file:string) -> string
109 | extension = Path.suffix -- extension (file:string) -> string
110 | pathname = Path.parent -- pathname (file:string) -> string
111 | isAbsolute = (path) -> path\match "^/" -- isAbsolute (path:string) -> string
112 |
113 | --# fs #--
114 | -- wildcard (path:string) -> function (iterator)
115 | -- Implements old wildcard behavior
116 | wildcard = iglob
117 |
118 | -- iwildcard (paths:table) -> function (iterator)
119 | -- Multiple fs.iglob paths
120 | iwildcard = (paths) ->
121 | all = {}
122 | for path in *paths
123 | for globbed in iglob path
124 | table.insert all, globbed
125 | --
126 | i, n = 0, #all
127 | ->
128 | i += 1
129 | return all[i] if i <= n
130 |
131 | -- isEmpty (path:string) -> boolean
132 | -- Checks if a directory is empty
133 | isEmpty = (path) ->
134 | return false unless Path.isdir path
135 | return 0 == #(listAll path)
136 |
137 | -- delete (loc:string)
138 | -- Recursive delete
139 | delete = (loc) ->
140 | return unless Path.exists loc
141 | if Path.isfile loc or isEmpty loc
142 | --print "DELFILE #{loc}"
143 | fs.remove loc
144 | else
145 | --print "DELDIR #{loc}"
146 | for node in fs.dir loc
147 | --print "SUBDEL #{node}"
148 | continue if node\match "%.%."
149 | --delete Path loc, node
150 | delete node
151 | fs.remove loc
152 |
153 | -- copy (source:string, target:string)
154 | -- Recursive copy
155 | copy = (fr, to) ->
156 | error "copy $ #{fr} does not exist" unless Path.exists fr
157 | if Path.isdir fr
158 | error "copy $ #{to} already exists" if Path.exists to
159 | fs.mkdir to
160 | for node in fs.dir fr
161 | --copy (Path fr, node), (Path to, node)
162 | copy node, (Path to, (Path.name node))
163 | elseif Path.isfile fr
164 | fs.copy fr, to
165 |
166 | -- glob (glob:string) -> (path:string) -> boolean
167 | -- Curried fs.matchGlob
168 | -- NOTE deleted in 5.0
169 | --glob = (glob) -> (path) -> fs.matchGlob (fs.fromGlob glob), path
170 |
171 | -- build (iter:function, fn:function) -> nil
172 | -- Compares last modification times with a cache, and if the file was
173 | -- modified, it passes the file to fn.
174 | build = (iter, fn) ->
175 | -- get modification times
176 | times = {}
177 | if Path.exists ".alfons"
178 | prints "%{cyan}:%{white} using .alfons"
179 | times = dofile ".alfons"
180 | times = {k, tonumber v for k, v in pairs times}
181 | --
182 | for file in iter
183 | mtime = fs.mtime file
184 | if times[file]
185 | -- previously built
186 | fn file if mtime > times[file]
187 | times[file] = mtime
188 | else
189 | -- never built before
190 | fn file
191 | times[file] = mtime
192 | -- write back to file
193 | writefile ".alfons", serialize times
194 |
195 | -- EVENTS {string:string}
196 | EVENTS = {
197 | access: "IN_ACCESS" -- "accessed"}
198 | change: "IN_ATTRIB" -- "changed"}
199 | write: "IN_CLOSE_WRITE" -- "written into"}
200 | shut: "IN_CLOSE_NOWRITE" -- "closed without writing"}
201 | close: "IN_CLOSE" -- "closed"}
202 | create: "IN_CREATE" -- "created"}
203 | delete: "IN_DELETE" -- "deleted"}
204 | destruct: "IN_DELETE_SELF" -- "deleted"}
205 | modify: "IN_MODIFY" -- "modified"}
206 | migrate: "IN_MOVE_SELF" -- "migrated"}
207 | move: "IN_MOVE" -- "moved"}
208 | movein: "IN_MOVED_TO" -- "moved here"}
209 | moveout: "IN_MOVED_FROM" -- "moved from here"}
210 | open: "IN_OPEN" -- "opened"}
211 | all: "IN_ALL_EVENTS" -- "updated"}
212 | }
213 |
214 | -- do not export this
215 | -- https://stackoverflow.com/a/32387452
216 | bit_band = (a, b) ->
217 | result, bitval = 0, 1
218 | while a > 0 and b > 0
219 | if a % 2 == 1 and b % 2 == 1
220 | result = result + bitval
221 | bitval = bitval * 2
222 | a = math.floor a/2
223 | b = math.floor b/2
224 | return result
225 |
226 | -- watch1 (iter:function, evf:table/string, fn:function) -> nil
227 | -- Uses inotify to watch for events specified in the event table.
228 | -- evf == "live" -> {"write", "movein", "modify", "create", "migrate"}
229 | -- watch1 = (iter, evf, fn) ->
230 | -- handle = inotify.init!
231 | -- -- do equivalents
232 | -- if evf == "live"
233 | -- evf = {"write", "movein", "create"}
234 | -- --handles = {}
235 | -- -- get file list
236 | -- files = {file, true for file in iter}
237 | -- prints "%{cyan}:%{white} Watching for:"
238 | -- for file, _ in pairs files
239 | -- prints " - %{green}#{file}"
240 | -- -- get directories
241 | -- dirs = {}
242 | -- for file, _ in pairs files
243 | -- parent = pathname file
244 | -- dirs[parent] = true unless dirs[parent]
245 | -- prints "%{cyan}:%{white} inotify directories:"
246 | -- for dir, _ in pairs dirs
247 | -- prints " - %{blue}#{dir}"
248 | -- events = [inotify[EVENTS[ev]] for ev in *evf]
249 | -- -- add file watchers
250 | -- -- note: you can only add dirs here
251 | -- watchers = {}
252 | -- for dir, _ in pairs dirs
253 | -- -- create a main watcher
254 | -- watchers[dir] = handle\addwatch dir, unpack events
255 | -- reversed = {v, k for k, v in pairs watchers}
256 | -- -- now loop
257 | -- while true
258 | -- events = handle\read!
259 | -- break unless events -- error?
260 | -- -- iterate fetched events
261 | -- for ev in *events
262 | -- -- get full path
263 | -- full = reversed[ev.wd] .. (ev.name or "")
264 | -- -- get action names
265 | -- actions = {}
266 | -- for action, evt in pairs EVENTS
267 | -- continue if action == "all"
268 | -- if 0 != bit_band ev.mask, inotify[evt]
269 | -- table.insert actions, action
270 | -- -- execute fn
271 | -- prints "%{cyan}:%{white} Triggered %{magenta}#{table.concat actions, ', '}%{white}: %{yellow}#{full}"
272 | -- fn full
273 | -- -- close it
274 | -- handle\close!
275 |
276 | -- watch (dirs:{string}, exclude:{string}, evf:{string}, pred:(file -> boolean), fn:(file -> nil)) -> nil
277 | watch = (dirs, exclude, evf, pred, fn) ->
278 | error "Could not load inotify" unless inotify
279 | handle = inotify.init!
280 | -- do equivalents
281 | if evf == "live"
282 | evf = {"write", "movein"}
283 | -- convert all into absolute
284 | cdir = Path.cwd!
285 | for i, dir in ipairs dirs
286 | unless isAbsolute dir
287 | --dirs[i] = fs.reduce fs.combine cdir, dir
288 | dirs[i] = Path cdir, dir
289 | for i, dir in ipairs exclude
290 | unless isAbsolute dir
291 | --exclude[i] = fs.reduce fs.combine cdir, dir
292 | exclude[i] = Path cdir, dir
293 | -- recurse into subdirectories
294 | for i, dir in ipairs dirs
295 | for ii, subdir in ipairs listAll dir
296 | doBreak = false
297 | for exclusion in *exclude
298 | doBreak = true if subdir\match "^#{exclusion}"
299 | continue if doBreak
300 | table.insert dirs, subdir if Path.isdir subdir
301 | -- print dirs
302 | prints "%{cyan}:%{white} Watching for:"
303 | for dir in *dirs
304 | prints " - %{green}#{dir}"
305 | -- get events
306 | events = [inotify[EVENTS[ev]] for ev in *evf]
307 | -- add create to event list
308 | -- evf -> full event list
309 | -- uevf -> user event list
310 | uevf = {k, v for k, v in pairs evf}
311 | unless contains evf, "create"
312 | table.insert evf, "create"
313 | table.insert events, inotify.IN_CREATE
314 | -- add watchers
315 | watchers = {}
316 | for dir in *dirs
317 | watchers[dir] = handle\addwatch dir, unpack events
318 | reversed = {v, k for k, v in pairs watchers}
319 | -- now iterate
320 | while true
321 | evts = handle\read!
322 | break unless evts -- error?
323 | -- iterate fetched events
324 | for ev in *evts
325 | -- get full path
326 | full = Path reversed[ev.wd], (ev.name or "")
327 | -- if dir, add watcher
328 | if (Path.isdir full) and (bit_band ev.mask, inotify.IN_CREATE) and not watchers[full]
329 | prints "%{cyan}:%{white} Added to watchlist: %{green}#{full}"
330 | watchers[full] = handle\addwatch full, unpack events
331 | reversed[watchers[full]] = full
332 | -- get action names
333 | actions = {}
334 | for action, evt in pairs EVENTS
335 | continue if action == "all"
336 | if 0 != bit_band ev.mask, inotify[evt]
337 | table.insert actions, action if contains uevf, action
338 | -- skip if we have no matching actions
339 | continue if #actions == 0
340 | -- check that it passes predicate
341 | continue unless pred full, actions
342 | -- execute fn
343 | prints "%{cyan}:%{white} Triggered %{magenta}#{table.concat actions, ', '}%{white}: %{yellow}#{full}"
344 | fn full, actions
345 | -- close it
346 | handle\close!
347 | --watch {"."}, {".git"}, "live", (glob "*.moon"), => sh "moonc #{@}"
348 |
349 | -- npairs (table) -> -> number, *
350 | -- ipairs, but does not stop if nil is found
351 | npairs = (t) ->
352 | keys = [k for k, v in pairs t when "number" == type k]
353 | table.sort keys
354 | i = 0
355 | n = #keys
356 | ->
357 | i += 1
358 | return keys[i], t[keys[i]] if i <= n
359 |
360 |
361 | --# utils #--
362 |
363 | -- lines (string) -> [string]
364 | -- Split a string into lines
365 | lines = (str) -> [line for line in str\gmatch "[^\r\n]+"]
366 |
367 | -- split (str:string, re:pattern, plain:boolean, n:number) -> [string]
368 | -- str - String to split
369 | -- re - Pattern to split the text by
370 | -- plain - Whether to treat `re` as plaintext or a Lua pattern (defaults to false)
371 | -- n - Maximum matches (defaults to none)
372 | -- https://github.com/lunarmodules/Penlight/blob/master/lua/pl/utils.lua
373 | split = (str, re, plain, n) ->
374 | i1, ls = 1, {}
375 | if not re then re = '%s+'
376 | if re == '' then return { str }
377 | while true
378 | i2, i3 = string.find str, re, i1, plain
379 | if not i2
380 | last = string.sub str, i1
381 | if last != '' then table.insert ls, last
382 | if #ls == 1 and ls[1] == ''
383 | return {}
384 | else
385 | return ls
386 |
387 | table.insert ls, string.sub str, i1, i2-1
388 |
389 | if n and #ls == n then
390 | ls[#ls] = string.sub str, i1
391 | return ls
392 |
393 | i1 = i3+1
394 |
395 | -- filter (arr:[*], predicate:((value:*, key:*) -> boolean)) -> [*]
396 | -- Filters a table using a predicate
397 | filter = (arr, predicate) -> [v for k, v in ipairs arr when predicate v, k]
398 |
399 | -- map (arr:[*], predicate:((value: *, key: *) -> *)) -> [*]
400 | -- Normal map over a table
401 | map = (arr, predicate) -> [predicate v, k for k, v in ipairs arr]
402 |
403 | -- reduce (arr:[*], predicate:((accum:*, value: *) -> *), initial:*) -> *
404 | -- reduce/foldl
405 | reduce = (arr, predicate, initial) ->
406 | accumulator = initial or arr[1]
407 | start = initial and 1 or 2
408 | i = start
409 | while i <= #arr
410 | accumulator = predicate accumulator, arr[i]
411 | i += 1
412 | return accumulator
413 |
414 | -- slice (arr:[*], start:number?, end:number?) -> [*]
415 | -- Creates a slice of an array
416 | slice = (arr, start, _end) ->
417 | if not start and not _end return arr
418 | if start and not _end return [v for v in *arr[start,]]
419 | if not start and _end return [v for v in *arr[,_end]]
420 | return [v for v in *arr[start,_end]]
421 |
422 | -- contains (arr:[*], value:*) -> boolean
423 | -- Check if an array contains a value
424 | contains = (arr, value) -> for v in *arr
425 | return true if v == value
426 |
427 | -- keys (tbl:{*:*}) -> [*]
428 | -- Returns all the keys of a table
429 | keys = (tbl) -> [k for k, v in pairs tbl]
430 |
431 | -- values (tbl:{*:*}) -> [*]
432 | -- Returns all the values of a table
433 | values = (tbl) -> [v for k, v in pairs tbl]
434 |
435 | -- entries (tbl:{*:*}) -> [*,*][]
436 | -- Returns the keys and values of a table as an array of [key, value]s
437 | entries = (tbl) -> [{k, v} for k, v in pairs tbl]
438 |
439 | -- fromEntries (entries:[*,*]) -> {*:*}
440 | -- Turns an array of entries like [key, value]s into a table
441 | fromEntries = (arr) -> {k, v for {k, v} in ipairs arr}
442 |
443 | -- sanitize (string) -> string
444 | -- Pattern-escapes a string
445 | sanitize = (pattern="") -> pattern\gsub "[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0"
446 |
447 | {
448 | :contains
449 | :prints, :printError
450 | :readfile, :writefile, :serialize
451 | :cmd, :cmdfail, :sh, :shfail, :cmdread, :shread
452 | :wildcard, :iwildcard, :glob
453 | :basename, :filename, :extension, :pathname
454 | :build, :watch
455 | :env, :ask, :show
456 | :npairs
457 | :listAll, :safeOpen, :safePopen
458 | :isEmpty, :delete, :copy
459 | :lines, :split, :filter, :map, :reduce
460 | :slice, :keys, :values, :contains
461 | :entries, :fromEntries
462 | :sanitize
463 | }
464 |
--------------------------------------------------------------------------------
/alfons/setfenv.moon:
--------------------------------------------------------------------------------
1 | -- alfons.setfenv
2 | -- Provides setfenv for 5.1
3 | return setfenv or (fn, env) ->
4 | i = 1
5 | while true
6 | name = debug.getupvalue fn, i
7 | if name == "_ENV"
8 | debug.upvaluejoin fn, i, (-> env), 1
9 | elseif not name then break
10 | i += 1
11 | return fn
--------------------------------------------------------------------------------
/alfons/tasks/fetch.lua:
--------------------------------------------------------------------------------
1 | return {
2 | tasks = {
3 | fetch = function(self)
4 | local http = require("http.request")
5 | local headers, stream = assert((http.new_from_uri(self.url)):go())
6 | local body = assert(stream:get_body_as_string())
7 | if "200" ~= headers:get(":status") then
8 | return error(body)
9 | else
10 | return body
11 | end
12 | end
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/alfons/tasks/fetch.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | fetch: =>
3 | http = require "http.request"
4 | headers, stream = assert (http.new_from_uri @url)\go!
5 | body = assert stream\get_body_as_string!
6 | if "200" != headers\get ":status"
7 | error body
8 | else
9 | return body
--------------------------------------------------------------------------------
/alfons/tasks/teal.lua:
--------------------------------------------------------------------------------
1 | return {
2 | tasks = {
3 | always = function(self)
4 | load("fetch")
5 | if not (store.teal_auto == true) then
6 | tasks.install()
7 | return tasks.typings({
8 | modules = store.typings
9 | })
10 | end
11 | end,
12 | install = function(self)
13 | if exists("teal_preinstall") then
14 | prints("%{cyan}Teal:%{white} Running pre-install hook.")
15 | tasks.teal_preinstall()
16 | end
17 | prints("%{cyan}Teal:%{white} Installing dependencies.")
18 | local _list_0 = store.dependencies
19 | for _index_0 = 1, #_list_0 do
20 | local dep = _list_0[_index_0]
21 | prints("%{green}+ " .. tostring(dep))
22 | sh("luarocks install " .. tostring(dep))
23 | end
24 | if exists("teal_postinstall") then
25 | prints("%{cyan}Teal:%{white} Running post-install hook.")
26 | return tasks.teal_postinstall()
27 | end
28 | end,
29 | build = function(self)
30 | if exists("teal_prebuild") then
31 | prints("%{cyan}Teal:%{white} Running pre-build hook.")
32 | tasks.teal_prebuild()
33 | end
34 | prints("%{cyan}Teal:%{white} Building project.")
35 | sh("tl build")
36 | if exists("teal_postbuild") then
37 | prints("%{cyan}Teal:%{white} Running post-build hook.")
38 | return tasks.teal_postbuild()
39 | end
40 | end,
41 | typings = function(self)
42 | local json = require("dkjson")
43 | local fetchdefs
44 | fetchdefs = function(mod)
45 | prints("%{cyan}Teal:%{white} Fetching type definitions for " .. tostring(mod) .. ".")
46 | local unjson = tasks.fetch({
47 | url = "https://api.github.com/repos/teal-language/teal-types/contents/types/" .. tostring(mod)
48 | })
49 | local files = json.decode(unjson)
50 | for _index_0 = 1, #files do
51 | local _continue_0 = false
52 | repeat
53 | local file = files[_index_0]
54 | if not (file.type == "file") then
55 | _continue_0 = true
56 | break
57 | end
58 | local name = file.name
59 | local def = tasks.fetch({
60 | url = "https://raw.githubusercontent.com/teal-language/teal-types/master/types/" .. tostring(mod) .. "/" .. tostring(name)
61 | })
62 | writefile(name, def)
63 | _continue_0 = true
64 | until true
65 | if not _continue_0 then
66 | break
67 | end
68 | end
69 | end
70 | local mod = self.m or self.module
71 | local mods = self.modules
72 | if mod then
73 | return fetchdefs(mod)
74 | elseif mods then
75 | local _list_0 = mods
76 | for _index_0 = 1, #_list_0 do
77 | local md = _list_0[_index_0]
78 | fetchdefs(md)
79 | end
80 | end
81 | end
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/alfons/tasks/teal.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | -- always
3 | always: =>
4 | load "fetch"
5 | unless store.teal_auto == true
6 | tasks.install!
7 | tasks.typings modules: store.typings
8 | -- install dependencies
9 | install: =>
10 | -- pre-install hook
11 | if exists "teal_preinstall"
12 | prints "%{cyan}Teal:%{white} Running pre-install hook."
13 | tasks.teal_preinstall!
14 | -- install
15 | prints "%{cyan}Teal:%{white} Installing dependencies."
16 | for dep in *store.dependencies
17 | prints "%{green}+ #{dep}"
18 | sh "luarocks install #{dep}"
19 | -- post-install hook
20 | if exists "teal_postinstall"
21 | prints "%{cyan}Teal:%{white} Running post-install hook."
22 | tasks.teal_postinstall!
23 | -- build teal
24 | build: =>
25 | -- pre-install hook
26 | if exists "teal_prebuild"
27 | prints "%{cyan}Teal:%{white} Running pre-build hook."
28 | tasks.teal_prebuild!
29 | -- install
30 | prints "%{cyan}Teal:%{white} Building project."
31 | sh "tl build"
32 | -- post-install hook
33 | if exists "teal_postbuild"
34 | prints "%{cyan}Teal:%{white} Running post-build hook."
35 | tasks.teal_postbuild!
36 | -- download typings
37 | typings: =>
38 | -- import
39 | json = require "dkjson" -- uses dkjson
40 | -- define helper
41 | fetchdefs = (mod) ->
42 | prints "%{cyan}Teal:%{white} Fetching type definitions for #{mod}."
43 | unjson = tasks.fetch url: "https://api.github.com/repos/teal-language/teal-types/contents/types/#{mod}"
44 | files = json.decode unjson
45 | for file in *files
46 | continue unless file.type == "file"
47 | name = file.name
48 | def = tasks.fetch url: "https://raw.githubusercontent.com/teal-language/teal-types/master/types/#{mod}/#{name}"
49 | writefile name, def
50 | -- get arguments
51 | mod = @m or @module
52 | mods = @modules
53 | if mod -- individual
54 | fetchdefs mod
55 | elseif mods -- multiple
56 | fetchdefs md for md in *mods
--------------------------------------------------------------------------------
/alfons/version.moon:
--------------------------------------------------------------------------------
1 | VERSION: "5.3.1"
2 |
--------------------------------------------------------------------------------
/alfons/wildcard.moon:
--------------------------------------------------------------------------------
1 | -- alfons.wildcard
2 | -- Reimplements the old filekit wildcard behavior
3 | Path = require "path"
4 | fs = require "path.fs"
5 |
6 | -- listAll (dir:string) -> [string]
7 | -- Filekit's listAll
8 | listAll = (dir) -> [node for node in fs.scandir dir]
9 |
10 | -- Turns a glob into a Lua pattern
11 | -- @tparam string glob Path with globs
12 | -- @treturn string Lua pattern
13 | fromGlob = (glob) ->
14 | sanitize = (pattern) -> pattern\gsub "[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0" if pattern
15 | saglob = sanitize glob
16 | with saglob
17 | mid = \gsub "%%%*%%%*", ".*"
18 | mid = mid\gsub "%%%*", "[^/]*"
19 | mid = mid\gsub "%%%?", "." -- TODO this should be [^/]
20 | --print "==> #{mid}"
21 | return "#{mid}$"
22 |
23 | -- TODO alias this to testGlob
24 | -- TODO compile the glob here, dont make the user do it
25 | --- Matches a compiled glob with a string
26 | -- @tparam string glob Compiled glob
27 | -- @tparam string path Path to compare to
28 | -- @treturn boolean Whether it matches or not
29 | matchGlob = (glob, path) -> nil != path\match glob
30 |
31 | --- Returns a list of paths matched by the globs
32 | -- @tparam string path Path with globs
33 | -- @treturn table Table of globbed files
34 | glob = (path, all={}) ->
35 | -- Return if there is nothing to glob
36 | return path unless path\match "%*"
37 | -- Get full paths
38 | --currentpath = Path.cwd!
39 | --fullpath = Path currentpath, path
40 | currentpath = "."
41 | fullpath = path
42 | -- Create a correct listing
43 | correctpath = ""
44 | for i=1, #fullpath
45 | if (fullpath\sub i, i) == (currentpath\sub i, i)
46 | correctpath ..= currentpath\sub i, i
47 | -- Create glob
48 | toglob = fromGlob fullpath
49 | -- Iterate files
50 | for node in *listAll correctpath
51 | --print node, toglob
52 | table.insert all, node if node\match toglob
53 | -- Return
54 | return all
55 |
56 | --- Glob as an iterator
57 | -- @tparam string path Path with globs
58 | -- @treturn function Iterator
59 | iglob = (path) ->
60 | globbed = glob path
61 | i = 0
62 | n = #globbed
63 | return ->
64 | i += 1
65 | if i <= n then return globbed[i]
66 |
67 | {
68 | :listAll
69 | :fromGlob, :matchGlob, :glob, :iglob
70 | }
--------------------------------------------------------------------------------
/bin/alfons.moon:
--------------------------------------------------------------------------------
1 | -- alfons 5.0
2 | -- Task execution with Lua and MoonScript
3 | -- By daelvn
4 | import VERSION from require "alfons.version"
5 | import style from require "ansikit.style"
6 | Path = require "path"
7 | unpack or= table.unpack
8 | printerr = (t) -> io.stderr\write t .. "\n"
9 |
10 | -- utils
11 | prints = (...) -> printerr unpack [style arg for arg in *{...}]
12 | printError = (text) -> printerr style "%{red}#{text}"
13 | errors = (code, msg) ->
14 | printerr style "%{red}#{msg}"
15 | os.exit code
16 | removeColorCodes = (str) -> str\gsub "%%{[a-z ]-}", ""
17 |
18 | -- get arguments
19 | import getopt from require "alfons.getopt"
20 | args = getopt {...}
21 |
22 | -- List known tasks for autocompletion
23 | ZSH_LIST_TASKS = not not args.zsh_list
24 | BASH_LIST_TASKS = not not args.bash_list
25 | LIST_TASKS = ZSH_LIST_TASKS or BASH_LIST_TASKS or not not args.list
26 |
27 | -- Read task description/arguments of a task for autocompletion
28 | ZSH_LIST_OPTIONS = args.zsh_list_options
29 | BASH_LIST_OPTIONS = args.bash_list_options
30 | LIST_OPTIONS = ZSH_LIST_OPTIONS or BASH_LIST_OPTIONS or args.list_options
31 |
32 | -- Get task argument type for autocompletion
33 | ZSH_GET_OPTION_TYPE = args.zsh_get_option_type
34 | GET_OPTION_TYPE = ZSH_GET_OPTION_TYPE or args.get_option_type
35 |
36 | COMPLETING = LIST_TASKS or LIST_OPTIONS or GET_OPTION_TYPE
37 |
38 | -- Show help message
39 | HELP = args.help
40 |
41 | -- With debug in environment
42 | INCLUDE_DEBUG = args.include_debug
43 |
44 | -- introduction
45 | unless COMPLETING
46 | prints "%{bold blue}Alfons #{VERSION}"
47 |
48 | -- Optionally accept a custom file
49 | FILE = do
50 | if args.f then args.f
51 | elseif args.file then args.file
52 | elseif Path.exists "Alfons.lua" then "Alfons.lua"
53 | elseif Path.exists "Alfons.moon" then "Alfons.moon"
54 | elseif Path.exists "Alfons.tl" then "Alfons.tl"
55 | elseif Path.exists "Alfons.yue" then "Alfons.yue"
56 | else errors 1, "No Taskfile found."
57 |
58 | -- Also accept a custom language
59 | LANGUAGE = do
60 | if FILE\match "moon$" then "moon"
61 | elseif FILE\match "lua$" then "lua"
62 | elseif FILE\match "tl$" then "teal"
63 | elseif FILE\match "yue$" then "yue"
64 | elseif args.type then args.type
65 | else errors 1, "Cannot resolve format for Taskfile."
66 |
67 | unless COMPLETING
68 | printerr "Using #{FILE} (#{LANGUAGE})"
69 |
70 | -- Load string
71 | import readMoon, readLua, readTeal, readYue from require "alfons.file"
72 | content, contentErr = switch LANGUAGE
73 | when "moon" then readMoon FILE
74 | when "lua" then readLua FILE
75 | when "teal" then readTeal FILE
76 | when "yue" then readYue FILE
77 | else errors 1, "Cannot resolve format '#{LANGUAGE}' for Taskfile."
78 | unless content then errors 1, contentErr
79 |
80 | -- Run the taskfile
81 | import runString from require "alfons.init"
82 | alfons, alfonsErr = runString content, nil, true, 0, {}, {}, true, INCLUDE_DEBUG
83 | unless alfons then errors 1, alfonsErr
84 | env = alfons ...
85 |
86 | -- If we have to list tasks, print them and exit
87 | import contains from require "alfons.provide"
88 |
89 | if ZSH_LIST_TASKS
90 | import readFile from require "alfons.file"
91 | import parseComments from require "alfons.parser"
92 | -- Read the file (since MoonScript compiler deletes comments)
93 | raw_content = readFile FILE
94 | -- Parse the content
95 | state = parseComments raw_content
96 | -- Return
97 | tasks = ["#{task_name}:#{removeColorCodes task.description or ''}" for task_name, task in pairs state.tasks when not (task.flag and contains task.flag, 'hide')]
98 | for task in *tasks do print task
99 | undocumented_tasks = [k for k, v in pairs env.tasks when not state.tasks[k]]
100 | for task in *undocumented_tasks
101 | sanitized_task = removeColorCodes task
102 | print sanitized_task
103 | os.exit!
104 |
105 | if LIST_TASKS
106 | import readFile from require "alfons.file"
107 | import parseComments from require "alfons.parser"
108 | -- Read the file (since MoonScript compiler deletes comments)
109 | raw_content = readFile FILE
110 | -- Parse the content
111 | state = parseComments raw_content
112 | -- Return
113 | tasks = ["#{task_name} " for task_name, task in pairs state.tasks when not (task.flag and contains task.flag, 'hide')]
114 | for task in *tasks do io.write task
115 | undocumented_tasks = [k for k, v in pairs env.tasks when not state.tasks[k]]
116 | for task in *undocumented_tasks
117 | io.write task .. ' '
118 | os.exit!
119 |
120 | -- If we have to list the options, print them and exit
121 | if LIST_OPTIONS
122 | import readFile from require "alfons.file"
123 | import parseComments from require "alfons.parser"
124 | list_options = ZSH_LIST_OPTIONS or LIST_OPTIONS
125 | -- argument needs to be a task
126 | if 'string' != type list_options
127 | errors 2, "Error: --list-options must be used with a task name."
128 | -- Read the file (since MoonScript compiler deletes comments)
129 | raw_content = readFile FILE
130 | -- Parse the content
131 | state = parseComments raw_content
132 | -- Access task
133 | task = state.tasks[list_options]
134 | if not task or (task.flags and contains task.flags, "hide")
135 | errors 2, "Error: Task '#{list_options}' does not exist."
136 | -- Helpers
137 | formatOptionName = (name) -> ((string.len name) > 1) and ('--' .. name) or ('-' .. name)
138 | formatOptionValues = (option) -> (table.concat (
139 | for value in *option.values
140 | value.value
141 | ), ' ')
142 | -- Print arguments
143 | for option_name, option in pairs task.options
144 | for name in *option.names
145 | if ZSH_LIST_OPTIONS
146 | print "#{formatOptionName name}\\:'#{removeColorCodes option.description}'"
147 | else
148 | io.write (formatOptionName name) .. ' '
149 |
150 | ZSH_OPTION_TYPES =
151 | file: '_files'
152 | path: '_path_files'
153 | user: '_users'
154 | group: '_groups'
155 |
156 | -- Retrieve option type, if asked
157 | if GET_OPTION_TYPE
158 | import readFile from require "alfons.file"
159 | import parseComments from require "alfons.parser"
160 | task_name, raw_option = GET_OPTION_TYPE\match "([^;]+)::([^;]+)"
161 | needed_option = raw_option\gsub '%-', ''
162 | -- argument needs to be a task
163 | if 'string' != type GET_OPTION_TYPE
164 | errors 2, "Error: --get-option-type must be used with a task name and option in the format `task;option`."
165 | -- Read the file (since MoonScript compiler deletes comments)
166 | raw_content = readFile FILE
167 | -- Parse the content
168 | state = parseComments raw_content
169 | -- Access task
170 | task = state.tasks[task_name]
171 | if not task or (task.flags and contains task.flags, "hide")
172 | errors 2, "Error: Task '#{task_name}' does not exist."
173 | -- Find matching option
174 | for option_name, option in pairs task.options
175 | if contains option.names, needed_option
176 | for value in *option.values
177 | print ZSH_OPTION_TYPES[value.value] or ""
178 | os.exit!
179 |
180 | -- If we have to show the help message, print that and exit
181 | if HELP
182 | import readFile from require "alfons.file"
183 | import parseComments from require "alfons.parser"
184 | import Paragraph, Spacer, Columns, Row, Cells, generateHelp from require "alfons.help"
185 | -- Read the file (since MoonScript compiler deletes comments)
186 | raw_content = readFile FILE
187 | -- Parse the content
188 | state = parseComments raw_content
189 | -- Helper generators
190 | Option = (command, description) -> (Row Cells {
191 | { {color: '%{bold green}'}, command }
192 | { {}, description }
193 | })
194 | Task = (command, description) -> (Row Cells {
195 | { {color: '%{bold cyan}'}, command }
196 | { {}, description }
197 | })
198 | formatOptions = (option) -> (table.concat (
199 | for name in *option.names
200 | ((string.len name) > 1) and ('--' .. name) or ('-' .. name)
201 | ), ' ') .. ' ' .. (table.concat (
202 | for option_value in *option.values
203 | option_value.optional and "[#{option_value.value}]" or "<#{option_value.value}>"
204 | ), ' ')
205 |
206 | -- Create help message
207 | help_message = {
208 | (Paragraph 'Built-in options:')
209 | (Columns {padding: 2}, {
210 | (Option '--help [task]', 'Displays this help message, or for a specific task')
211 | (Option '--file -f ', 'Loads a custom Taskfile')
212 | (Option '--list', 'Lists all the tasks available for the loaded Taskfile')
213 | (Option '--list-options ', 'Lists all the options available to a task')
214 | })
215 | }
216 | -- If everything is hidden, just print and exit
217 | if state.flags.hide
218 | print generateHelp help_message
219 | os.exit!
220 | -- If we are asking help for a certain task, add that
221 | extra_message = {}
222 | if HELP != true
223 | task = state.tasks[HELP]
224 | if not task or (task.flags and contains task.flags, "hide")
225 | errors 2, "Error: Task '#{HELP}' does not exist."
226 | -- NOTE: We are purposefully replacing the original
227 | help_message = {
228 | (Paragraph "%{bold cyan}#{HELP} %{reset}- #{task.description}")
229 | (Columns {padding: 2}, (
230 | for option_name, option in pairs task.options
231 | Option (formatOptions option), option.description
232 | ))
233 | }
234 | -- Include tasks
235 | if HELP == true
236 | all_tasks = [k for k, v in pairs env.tasks]
237 | undocumented_tasks = [k for k, v in pairs env.tasks when not state.tasks[k]]
238 | extra_message = {
239 | (Spacer!)
240 | (Paragraph 'Loaded tasks: (Use %{magenta}`alfons --help task`%{reset} to know more about said task)')
241 | (Columns {padding: 2}, [(
242 | Task task_name, task.description
243 | ) for task_name, task in pairs state.tasks when not (task.flags and contains task.flags, 'hide')])
244 | (Spacer!)
245 | (Paragraph 'Undocumented tasks:')
246 | (Paragraph " %{cyan}#{table.concat undocumented_tasks, ' '}")
247 | }
248 | -- Add rest to help message
249 | for section in *extra_message
250 | table.insert help_message, section
251 | -- Display and exit
252 | print generateHelp help_message
253 | os.exit!
254 |
255 | -- run tasks, and teardown after each of them
256 | for command in *args.commands
257 | env.tasks[command] args[command]
258 | (rawget env.tasks, "teardown") if rawget env.tasks, "teardown"
259 |
260 | -- finalize
261 | env.finalize!
262 |
--------------------------------------------------------------------------------
/bin/completion.bash:
--------------------------------------------------------------------------------
1 | # alfons completion -*- shell-script -*-
2 |
3 | _alfons_completions() {
4 | local cur prev opts
5 | COMPREPLY=()
6 | cur="${COMP_WORDS[COMP_CWORD]}"
7 | prev="${COMP_WORDS[COMP_CWORD-1]}"
8 | opts="--help --file -f --bash-list --bash-list-options"
9 |
10 | echo "cur: ${cur}\nprev: ${prev}" >> /tmp/alfons.log
11 |
12 | tasks=($(compgen -W "$(alfons --bash-list)" -- "$cur"))
13 | if [[ ${COMP_CWORD} -gt 1 ]] ; then
14 | task_options=($(compgen -W "$(alfons --bash-list-options $prev)" -- "$cur"))
15 | COMPREPLY+=( "${task_options[@]}" )
16 | fi
17 | COMPREPLY+=( "${tasks[@]}" )
18 | }
19 |
20 | complete -o nosort -F _alfons_completions alfons
21 |
22 | # ex: filetype=sh
23 |
--------------------------------------------------------------------------------
/bin/completion.fish:
--------------------------------------------------------------------------------
1 | # clear completions
2 | complete -e alfons
3 |
4 | # remove file completion
5 | complete -c alfons -f
6 |
7 | # simple completions for --help --list --zsh-list --bash-list
8 | complete -c alfons -l help -d 'Show help'
9 | complete -c alfons -l list -d 'List tasks'
10 | complete -c alfons -l zsh-list -d 'List tasks (zsh/fish completion)'
11 | complete -c alfons -l bash-list -d 'List tasks (bash completion)'
12 |
13 | # complete -f and --file with paths
14 | complete -c alfons -s f -l file -r -F -d 'Use a specific task file'
15 |
16 | # function to find the used taskfile
17 | function __alfons_find_taskfile
18 | set -l taskfile ''
19 | set -l next 0
20 | for arg in (commandline -o)
21 | if [ $next = 1 ]
22 | set taskfile "$arg"
23 | break
24 | end
25 | if [ "$arg" = "-f" ]; or [ "$arg" = "--file" ]
26 | set next 1
27 | end
28 | end
29 | echo "$taskfile"
30 | end
31 |
32 | # function to get the command invocation for alfons with the taskfile
33 | function __alfons_invoke
34 | set -l taskfile (__alfons_find_taskfile)
35 | echo alfons
36 | if [ -n "$taskfile" ]
37 | echo -f
38 | echo "$taskfile"
39 | end
40 | end
41 |
42 | # function to complete the available tasks in the taskfile
43 | function __alfons_complete_tasks
44 | set -l alfons (__alfons_invoke)
45 | $alfons --zsh-list 2>/dev/null | sed s/:/\t/
46 | end
47 |
48 | # function to list the available tasks in the taskfile
49 | function __alfons_list_tasks
50 | set -l alfons (__alfons_invoke)
51 | $alfons --list 2>/dev/null | sed 's/ /\n/g'
52 | end
53 |
54 | # function to list the available options for all tasks
55 | function __alfons_list_all_options
56 | set -l alfons (__alfons_invoke)
57 | for task in ($alfons --list 2>/dev/null | sed 's/ /\n/g')
58 | for option in ($alfons --list-options "$task" 2>/dev/null | sed 's/ /\n/g')
59 | echo "$task::$option"
60 | end
61 | end
62 | end
63 |
64 | # function to find the currently selected task
65 | function __alfons_selected_task
66 | set -l skip 0
67 | set -l task ''
68 | set -l first 1
69 | for arg in (commandline -o)
70 | if [ $first = 1 ]; or [ $skip = 1 ]
71 | set skip 0
72 | set first 0
73 | continue
74 | end
75 | if [ "$arg" = --list ]
76 | continue
77 | end
78 | if [ "$arg" = -f ]; or [ "$arg" = --file ]; or [ "$arg" = --help ]
79 | set skip 1
80 | set task ''
81 | else if [ (string sub -s1 -e1 -- "$arg") = '-' ]
82 | set skip 1
83 | else
84 | set task "$arg"
85 | end
86 | end
87 | echo "$task"
88 | end
89 |
90 | # function to complete options for the selected task
91 | function __alfons_complete_options
92 | set -l alfons (__alfons_invoke)
93 | set -l task (__alfons_selected_task)
94 | for option in ($alfons --zsh-list-options $task 2>/dev/null)
95 | set -l parts (string split -m1 -- '\:' "$option")
96 | printf '%s' $parts[1]
97 | if [ -n "$parts[2]" ]
98 | printf '\t'
99 | string sub -s2 -e-2 -- "$parts[2]"
100 | else
101 | echo
102 | end
103 | end
104 |
105 | end
106 |
107 | # function to check if we are in an option
108 | function __alfons_get_option
109 | set -l args (commandline -o)
110 | if [ (string sub -s1 -e1 -- "$args[-1]") = '-' ]
111 | printf '%s' "$args[-1]"
112 | end
113 | end
114 |
115 | # function to actually complete files if option asks for it
116 | function __alfons_needs_option
117 | set -l task (__alfons_selected_task)
118 | if [ -z "$task" ]
119 | return 1
120 | end
121 | set -l option (__alfons_get_option)
122 | if [ -z "$option" ]
123 | return 1
124 | end
125 | set -l alfons (__alfons_invoke)
126 | set -l type ($alfons --zsh-get-option-type "$task::$option" 2>/dev/null)
127 | for arg in $argv
128 | if [ "$type" = "$arg" ]
129 | return 0
130 | end
131 | end
132 | return 1
133 | end
134 |
135 | # complete the available tasks for the selected taskfile
136 | complete -c alfons -n '[ -z (__alfons_get_option) ]' -a '(__alfons_complete_tasks)' -d 'Run the task'
137 |
138 | # complete the help function with the available tasks
139 | complete -c alfons -l help -f -r -a '(__alfons_complete_tasks)' -d 'Show help for a task'
140 |
141 | # complete the list-options / zsh-list-options / bash-list-options function with the available tasks
142 | complete -c alfons -l list-options -f -r -a '(__alfons_list_tasks)' -d 'List options for a task'
143 | complete -c alfons -l zsh-list-options -f -r -a '(__alfons_list_tasks)' -d 'List options for a task (zsh/fish completion)'
144 | complete -c alfons -l bash-list-options -f -r -a '(__alfons_list_tasks)' -d 'List options for a task (bash completion)'
145 |
146 | # complete the get-option-type / zsh-get-option-type function
147 | complete -c alfons -l get-option-type -f -r -a '(__alfons_list_all_options)' -d 'Get the type of an option'
148 | complete -c alfons -l zsh-get-option-type -f -r -a '(__alfons_list_all_options)' -d 'Get the type of an option (zsh/fish completion)'
149 |
150 | # complete the task options for the selected task
151 | complete -c alfons -n '[ -n (__alfons_selected_task) ]; and [ -z (__alfons_get_option) ]' -a '(__alfons_complete_options)' -d 'Options for the task'
152 |
153 | # complete files if task option asks for file
154 | complete -c alfons -n '__alfons_needs_option _files _path_files' -F
155 |
156 | # complete users/groups if task option asks for it
157 | complete -c alfons -n '__alfons_needs_option _users' -a '(__fish_complete_users)'
158 | complete -c alfons -n '__alfons_needs_option _groups' -a '(__fish_complete_groups)'
--------------------------------------------------------------------------------
/bin/completion.zsh:
--------------------------------------------------------------------------------
1 | #compdef alfons
2 |
3 | _alfons() {
4 | local state
5 |
6 | _arguments \
7 | '--help[Show help message or help for a task]:help:->help' \
8 | '(--file -f)'{--file=,-f}"[Taskfile to use]:taskfile:_files" \
9 | '--zsh-list[List loaded tasks]' \
10 | '--zsh-list-options[List loaded tasks for an option (ZSH)]' \
11 | '--zsh-get-option-type[Get option completion for an option (ZSH)]' \
12 | '*:Tasks:->task'
13 |
14 | case "$state" in
15 | task)
16 | # Task values
17 | taskvals="$(alfons --zsh-get-option-type ${words[-3]}::${words[-2]})"
18 | if [[ ! $(echo $taskvals | sed s/\n//g | sed s/\ //g) == "" ]]; then
19 | _arguments "*:Values for ${words[-2]}:$taskvals"
20 | fi
21 | # Task options
22 | taskopts=($(alfons --zsh-list-options ${words[-2]}))
23 | _arguments "*:Task options:(($taskopts))"
24 | # Tasks
25 | tasks=("${(@f)$(alfons --zsh-list)}")
26 | _describe -t tasks 'Tasks' tasks
27 | return 0
28 | ;;
29 | esac
30 | }
31 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Alfons 4 Documentation
2 |
3 | - [Tutorial](tutorial.md)
4 | - [Recipes](recipes.md)
5 | - [Arguments](arguments.md)
6 | - [Functions](provide.md)
7 | - [Environment](environment.md)
8 | - [Loading](loading.md)
9 | - [Teal support](teal.md)
10 | - [API](api.md)
11 | - [`build`](build.md)
12 | - [`watch`](watch.md)
--------------------------------------------------------------------------------
/docs/api.md:
--------------------------------------------------------------------------------
1 | # Alfons API
2 |
3 | Starting with 4.2, Alfons provides an API to embed Alfons functionality in your programs.
4 |
5 | ## Contents
6 | - [Alfons API](#alfons-api)
7 | - [Contents](#contents)
8 | - [Installation](#installation)
9 | - [alfons.env](#alfonsenv)
10 | - [alfons.file](#alfonsfile)
11 | - [alfons.getopt](#alfonsgetopt)
12 | - [Argument parsing](#argument-parsing)
13 | - [alfons.look](#alfonslook)
14 | - [alfons.provide](#alfonsprovide)
15 | - [alfons.setfenv](#alfonssetfenv)
16 | - [alfons.version](#alfonsversion)
17 | - [alfons.help](#alfonshelp)
18 | - [alfons.parser](#alfonsparser)
19 | - [alfons.init](#alfonsinit)
20 | - [initEnv](#initenv)
21 | - [runString](#runstring)
22 | - [Understanding the global environment](#understanding-the-global-environment)
23 | - [Creating your own alfons clone](#creating-your-own-alfons-clone)
24 | - [Arguments](#arguments)
25 | - [Loading](#loading)
26 | - [Running](#running)
27 | - [Executing tasks](#executing-tasks)
28 | - [Finalize](#finalize)
29 | - [Finish](#finish)
30 |
31 | ## Installation
32 |
33 | You need to install the development rock instead of the upstream one. For that, follow these steps:
34 |
35 | ```sh
36 | # Clone project
37 | $ git clone https://github.com/daelvn/alfons.git
38 | # Install dependencies
39 | $ luarocks install moonscript
40 | $ luarocks install rockbuild
41 | $ luarocks install amalg
42 | # Create the runnable file
43 | $ alfons produce
44 | # Build the rockspec locally
45 | $ rockbuild -f rock-dev.yml -m --delete 4.4 # or change the version if you want
46 | ```
47 |
48 | If there is enough demand, I'll upload the dev rockspec to LuaRocks with every release in form of an `alfons-extra` package or similar.
49 |
50 | The rock also installs optional dependencies for Alfons like `http` or `linotify`. If you do not wish to install them, feel free to edit the development rockframe.
51 |
52 | ## alfons.env
53 |
54 | `alfons.env` provides the default environment table (`ENVIRONMENT`), which does not include the functions in `alfons.provide`, and a function called `loadEnv` which takes a string of Lua code and a table, and will load the Lua code with the table as its environment. This function uses different mechanisms on different versions, due to `loadstring` being deprecated.
55 |
56 | ## alfons.file
57 |
58 | Contains a generic function `readFile` that reads a file content and loads it, an alias `readLua`, and then `readMoon` which compiles MoonScript content from a file before returning the Lua value, and `readTeal` for a Teal equivalent.
59 | ## alfons.getopt
60 |
61 | Contains a single function, `getopt`, which takes a list of arguments, and returns a table of parsed options.
62 |
63 | ### Argument parsing
64 |
65 | See [arguments.md](arguments.md)
66 |
67 | ## alfons.look
68 |
69 | `alfons.look` introduces a `require`-style module lookup function that instead of running them and returning its results, it returns the contents of the file. It returns a table with a function `makeLook`, which takes a package path (defaults to `package.path`) and returns a lookup function. This function takes a module name and returns the contents of the file found, or `nil` and an error otherwise.
70 |
71 | ## alfons.provide
72 |
73 | `provide` includes all the helper functions used in Taskfiles.
74 |
75 | See [Functions](provide.md).
76 |
77 | ## alfons.setfenv
78 |
79 | Returns a function (not a table). The function is simply a reimplementation of setfenv for Lua 5.2+
80 |
81 | ## alfons.version
82 |
83 | Returns a table with a field `VERSION` which contains the current Alfons version.
84 |
85 | ## alfons.help
86 |
87 | Contains functions to generate help messages, including a column formatter.
88 |
89 | ## alfons.parser
90 |
91 | Contains the comment parser for documenting Taskfiles.
92 |
93 | ## alfons.init
94 |
95 | Provides the main functions required to run a Taskfile.
96 |
97 | ### initEnv
98 |
99 | `initEnv` takes a `run` function (see below), a base environment (defaults to `alfons.env`'s `ENVIRONMENT`), a private global environment table (referred to as `genv`), and a module name (defaults to `main`). It returns an environment ready to use in Taskfiles. This function is internal and should not really be used, so I will not explain it.
100 |
101 | ### runString
102 |
103 | `runString` takes:
104 |
105 | 1. either a string of Lua code or a module to perform lookup on (using `alfons.look`) as its first argument.
106 | 2. Then it takes a base environment (defaults to `alfons.env`'s `ENVIRONMENT`)
107 | 3. A boolean flag `runAlways` which determines whether the `always` task should be run or not.
108 | 4. A numeric `child` argument (actually unused) that determines how deep into the loaded Taskfiles you are (defaults to `0` for the main file and increments for children taskfiles when `load` is called).
109 | 5. A `genv`, where the tasks for all modules are neatly stored. Although you can set a starting value for this table (defaults to an empty one), you will not be able to access it again (unless you create the table before passing it and store the reference).
110 | 6. A reverse queue `rqueue` that determines the order in which the `default`, `teardown` and `finalize` tasks should be run. This queue should be reversed before running each task in it.
111 | 7. A boolean value that determines whether to pretty-print errors or not.
112 |
113 | It loads the contents of the Taskfile without executing it.
114 |
115 | It returns either the environment table (for accessing tasks and `store`) if it was already loaded or a function for running the Taskfile with arguments. These arguments will be processed by `alfons.getopt`.
116 |
117 | The function returned adds the `args` function to the environment, local to each taskfile. It also adds the function `uses`, for checking the argument list for commands.
118 |
119 | It runs the Alfons file and loads all tasks to `env.tasks`, where `env` represents the environment table. It wraps all tasks in a `run` function, which essentially pre-passes the name of the task (`@name`), and the task itself (`@task`).
120 |
121 | It also adds the `load` function to load taskfiles inside taskfiles.
122 |
123 | It runs the `always` task if the `runAlways` argument is enabled (defaults to `true`).
124 |
125 | Then it adds a trigger to run the `default` and `finalize` tasks.
126 |
127 | Finally, it returns the environment of the taskfile. It looks something like this, irrelevant parts skipped for convenience. These are the only things you will need to know.
128 |
129 | ```lua
130 | env = {
131 | tasks = {}, -- table to access all tasks
132 | store = {}, -- global storage
133 | finalize = function() end -- calls the `default` and `finalize` tasks.
134 | }
135 | ```
136 |
137 | ### Understanding the global environment
138 |
139 | In the last section we mentioned `genv` and how you could initially set its value but not access it later. Lets look at its structure.
140 |
141 | ```lua
142 | genv = {
143 | ["main"] = {} -- this is main's environment
144 | ["fetch"] = {} -- environment for a subtaskfile
145 | }
146 | = {
147 | store = {} -- global storage is here
148 | }
149 | ```
150 |
151 | Task lookup in the `env.tasks` table happens by looking at all the loaded taskfiles in `genv`. By adding more fields to `genv` initially, you can pre-load taskfiles without really loading them.
152 |
153 | The global storage is in `genv`'s metatable, which you can also preload values at.
154 |
155 | ### Creating your own alfons clone
156 |
157 | `bin/alfons.moon` is written in just a few lines of code, let's write a simplified version of it:
158 |
159 | #### Arguments
160 |
161 | First, lets get the list of tasks that we should run:
162 |
163 | ```moon
164 | import getopt from require "alfons.getopt"
165 | args = getopt {...}
166 | ```
167 |
168 | #### Loading
169 |
170 | The official program supports custom taskfile locations, but for the sake of simplicity, we'll skip that and only allow loading `Alfons.lua`.
171 |
172 | ```moon
173 | import readLua from require "alfons.file"
174 | content, contentErr = readLua "Alfons.lua"
175 | unless content then error contentErr
176 | ```
177 |
178 | #### Running
179 |
180 | This is a straightforward step to get the environment.
181 |
182 | ```moon
183 | import runString from require "alfons.init"
184 | alfons, alfonsErr = runString content
185 | unless alfons then error alfonsErr
186 | env = alfons ...
187 | ```
188 |
189 | #### Executing tasks
190 |
191 | Now we need to run the tasks we have been asked for, with their respective arguments, and run `teardown` after each of them.
192 |
193 | ```moon
194 | for command in *args.commands
195 | env.tasks[command] args[command] if env.tasks[command]
196 | (rawget env.tasks, "teardown") if rawget env.tasks, "teardown"
197 | ```
198 |
199 | #### Finalize
200 |
201 | Finally, simply call the trigger to run `default` tasks if no other task in each taskfile has been run, and `finalize` tasks.
202 |
203 | ```moon
204 | env.finalize!
205 | ```
206 |
207 | #### Finish
208 |
209 | And just like that, we have implemented Alfons! It is a pretty simple tool, despite the looks of it, really.
210 |
--------------------------------------------------------------------------------
/docs/arguments.md:
--------------------------------------------------------------------------------
1 | # Arguments
2 |
3 | Arguments can be a bit weird due to the nature of tasks. This is different from how it used to be in Alfons 3.
4 |
5 | Arguments that do not start with a hyphen (`-`) will be considered to be tasks to run. Every task will get its own set of arguments, passed after the task was called. Options in the format `-x` will be set as `{x = }`. Flags in the format `-ab` will be set as `{a = true, b = true}`. Options in the format `--abc` will be set as `{abc = }`.
6 |
7 | Let's see this with an example. This is our Alfonsfile:
8 |
9 | **MoonScript**
10 |
11 | ```moon
12 | tasks:
13 | first: => print @a
14 | second: => print @b
15 | ```
16 |
17 | **Lua**
18 |
19 | ```lua
20 | function first(self) print(self.a) end
21 | function second(self) print(self.b) end
22 | ```
23 |
24 | And if we call it like this, we will get the following output:
25 |
26 | ```sh
27 | $ alfons first -a Hello second -b World!
28 | Hello
29 | World!
30 | ```
31 |
32 | The tasks don't have access to other tasks' arguments in their `self` variable. However, you can access the whole argument table with `args`. This makes the following snippet equivalent.
33 |
34 | **MoonScript**
35 |
36 | ```moon
37 | tasks:
38 | first: => print args.first.a
39 | second: => print args.second.b
40 | ```
41 |
42 | **Lua**
43 |
44 | ```lua
45 | function first(self) print(args.first.a) end
46 | function second(self) print(args.second.b) end
47 | ```
48 |
49 | ## Uses
50 |
51 | When running from the command line, a new function is provided (`uses`) that is effectively a shortcut for `contains args.commands, "task"`. It will check if another task was called. The task does not have to exist. You can use this for "subtasks", like `alfons docs serve`, instead of having to do `alfons docs --serve`, which is considerably *uglier*.
52 |
53 | **MoonScript**
54 |
55 | ```moon
56 | tasks:
57 | task: =>
58 | if uses "subtask"
59 | print "subtask was called!"
60 | ```
61 |
62 | **Lua**
63 |
64 | ```lua
65 | function task()
66 | if uses "subtask" then
67 | print "subtask was called!"
68 | end
69 | end
70 | ```
71 |
72 | **Result**
73 |
74 | ```
75 | $ alfons task subtask
76 | subtask was called!
77 | ```
78 |
79 | ## Argument parsing
80 |
81 | Using `getopt`, you get a table `args` which contains the following information:
82 |
83 | ### Commands
84 |
85 | Commands are the tasks to be executed in Alfons. They can be found at the following places:
86 |
87 | `getopt {"task1"}` or `alfons task1`
88 |
89 | ```lua
90 | args = {
91 | task1 = {}, -- task arguments go here, name of field varies.
92 | commands = { "task1" } -- in order of use.
93 | }
94 | ```
95 |
96 | ### Flags
97 |
98 | Flags are arguments without a value. They are all set to `true`.
99 |
100 | `getopt {"task", "-a"}` or `alfons task -a`
101 |
102 | ```lua
103 | args = {
104 | task = {
105 | ["a"] = true
106 | },
107 | commands = { "task" }
108 | }
109 | ```
110 |
111 | ### Options
112 |
113 | Options are arguments with a value. They are all set to their value.
114 |
115 | `getopt {"task", "--opt", "value"}` or `getopt {"task", "--opt=value"}` or `alfons task --opt value` or `alfons task --opt=value`
116 |
117 | ```lua
118 | args = {
119 | task = {
120 | ["opt"] = "value"
121 | },
122 | commands = { "task" }
123 | }
124 | ```
125 |
126 | ### Interpreting arguments
127 |
128 | - `--` alone passes the arguments that come after it as they are.
129 | - `x` will be treated as a **command** and all arguments after it are arguments to it.
130 | - `-x` will be paired with the argument after it as an **option** unless it is last in the list, in which case it is just a **flag**.
131 | - `-abc` represents three **flags**: `a`, `b` and `c`.
132 | - `--xa` will be paired with the next argument as an **option** unless it is last in the list, in which case it is just a **flag**.
133 | - `--xa=val` uses `val` as a value to an **option** `xa`.
--------------------------------------------------------------------------------
/docs/autocompletion.md:
--------------------------------------------------------------------------------
1 | # Autocompletion
2 |
3 | Alfons 5.2 introduced dynamic shell autocompletion. That means that on most shells (but especially Zsh), you will get completions for tasks, task options and maybe even task values.
4 |
5 | ## Bash
6 |
7 | The Bash completion script is very poor. This is because Bash's autocompletion is very poor. It will list the available tasks, and if it can detect a task, also suggest the options for that task.
8 |
9 | ### Installing
10 |
11 | ```
12 | # cp bin/completion.bash /etc/bash_completion.d/alfons
13 | ```
14 |
15 | ## Zsh
16 |
17 | Zsh will autocomplete tasks, task options, and for certain task options, also suggest values.
18 |
19 | If a task option has a value of ``, ``, `` or ``, it will use Zsh's internal resolvers to complete suggestions.
20 |
21 | ### Installing
22 |
23 | Move the completion file to anywhere in your `$FPATH`.
24 |
25 | ```sh
26 | # Oh my Zsh!
27 | $ cp bin/completion.zsh $HOME/.oh-my-zsh/completions/_alfons
28 | # Hopefully cross platform
29 | $ sudo cp bin/completion.zsh /usr/share/zsh/functions/Completion/_alfons
30 | ```
31 |
32 | ## Fish
33 |
34 | Fish will autocomplete arguments, tasks, task options and will suggest values for some task option types (same as zsh).
35 |
36 | It will use the currently selected taskfile (according to -f / --file) for the completion.
37 |
38 | ### Installing
39 |
40 | Move the completion file to your `$fish_complete_path` (typically `~/.config/fish/completions`), under the name `alfons.fish`.
41 |
42 | ```sh
43 | # Create the completion directory if it doesnt exist
44 | $ mkdir -p $HOME/.config/fish/completions
45 | # Add the completion file, with the correct name, so that fish finds it
46 | $ cp bin/completion.fish $HOME/.config/fish/completions/alfons.fish
47 | ```
--------------------------------------------------------------------------------
/docs/branding.md:
--------------------------------------------------------------------------------
1 | # Branding
2 |
3 | The Alfons Gradient goes, left to right, `#ffca05` to `#faac18`.
4 | The Alfons logo is a Bold, Oblique "A" in Cantarell font, with an arrow that comes from the middle and outwards to the left.
5 |
6 |
--------------------------------------------------------------------------------
/docs/build.md:
--------------------------------------------------------------------------------
1 | # build
2 |
3 | `build` takes an iterator and a function. It gets all the files from the iterator,
4 | checks their modification time, compares it to a cache, and passes the filename to the function if the file was modified.
5 |
6 | ## Behavior
7 |
8 | The cache is stored in an `.alfons` file. If it does not exist, then all filenames will be passed to the function, and then stored in cache. If it does exist, then the comparison happens.
9 |
10 | ## Examples
11 |
12 | ### Compiling MoonScript
13 |
14 | ```lua
15 | compile = function(self)
16 | build((wildcard "**.moon"), function(file)
17 | sh "moonc " .. file
18 | end)
19 | end
20 | ```
21 |
22 | ```moon
23 | tasks:
24 | compile: =>
25 | build (wildcard "**.moon"), -> sh "moonc #{file}"
26 | ```
27 |
--------------------------------------------------------------------------------
/docs/documenting.md:
--------------------------------------------------------------------------------
1 | # Documenting
2 |
3 | In Alfons 5.2, a new feature was implemented to document your own Taskfiles. Previously, there was no way to generate a help message, or to have shell completion. Thanks to the docstrings, and a little bit of magic, this is now possible.
4 |
5 | ## Docstrings
6 |
7 | Docstrings are comments in the Taskfile that begin with `---`. These are followed by a tag (`@task`, `@argument`, `@flag`) that determines how the rest of the comment will be parsed.
8 |
9 | The docstrings are untied from the actual code since it needs to be language-agnostic, and there are many ways within a single language to define tasks. As such, the tasks displayed in the new help message are a mix between documented tasks, and undocumented tasks read from the Taskfile.
10 |
11 | ## Declaring a task
12 |
13 | `--- @task name Description of the task.`
14 |
15 | A task is declared using the docstring above.
16 |
17 | ## Declaring an option for a task
18 |
19 | `--- @option task [long s] Description of the option.`
20 | `--- @option task [long s] Description of the flag (no value).`
21 |
22 | The docstring above has several parts. First, the name of the task that you are referencing. Then, between square brackets, you have to put all the forms of the option, the long preferrably first. Between the angle brackets, you can put each of the expected values. Everything that comes afterward is the description of the option.
23 |
24 | ## Flagging
25 |
26 | `--- @flag * hide`
27 | `--- @flag task hide`
28 |
29 | As of right now, the only flag available is `hide`, which makes either all tasks (`*`) or a task invisible to autocompletion and the help message.
30 |
--------------------------------------------------------------------------------
/docs/environment.md:
--------------------------------------------------------------------------------
1 | # Environment
2 |
3 | This is the environment being passed to Alfonsfiles, along with everything on `provide`.
4 |
5 | ```moon
6 | -- environment for alfons files
7 | ENVIRONMENT = {
8 | :_VERSION
9 | :assert, :error, :pcall, :xpcall
10 | :tonumber, :tostring
11 | :select, :type, :pairs, :ipairs, :next, :unpack
12 | :require
13 | :print, :style -- from ansikit
14 | :io, :math, :string, :table, :os
15 | :fs -- fs is either CC/fs or lpath.fs
16 | :path, :env, :fsinfo -- lpath, lpath.env and lpath.info respectively
17 | }
18 | ```
19 |
20 | ## Accessing tasks
21 |
22 | Any defined task can be called using the `tasks` table. Just do `task.name!` to call it or pass a table if you want to use arguments. You can access any task, anywhere; it is allowed to call tasks from taskfiles you included, and those taskfiles will be able to use tasks of the parent taskfile. Metatable magic is used to that "local" tasks are always preferred over tasks from other taskfiles.
23 |
24 | You can check if a task exists by using the `exists` function, that takes a string (the requested task name).
25 |
26 | ### Global tasks
27 |
28 | The `tasks` table can only access tasks that are at the same level or below it (subtasks). Because of how Alfons' internals work, it is possible to access higher tasks. As of 4.4, you can do this via the magic table `gtasks`. It appears to be empty, but indexing it will return the first task that has the same name. To check if a task exists globally, use `gexists` (takes a string, the requested task name).
29 |
30 | ```moon
31 | tasks:
32 | always: => gtasks.example!
33 | ```
34 |
35 | ## Store
36 |
37 | `store` is a table shared across all tables that you can use to pass data to other taskfiles or generally just create configuration fields.
38 |
39 | ### Callstack
40 |
41 | Starting in Alfons 4.3, a new predefined field in `store` named `callstack` contains a stack of the currently executing functions. Peeking the stack (`store.callstack[#store.callstack]`) will return the function that is currently being executed, and should be equivalent to `@name`. This was necessary to implement [`calls`](docs/provide.md#calls).
42 |
--------------------------------------------------------------------------------
/docs/loading.md:
--------------------------------------------------------------------------------
1 | # Loading other taskfiles
2 |
3 | You can load other taskfiles using `load`, which takes a taskfile *module path* and loads it. They are loaded such as to the main taskfile, there is no distinction between them, and it can access the subtasks just as well as its own.
4 |
5 | ## Placement
6 |
7 | Trying to use a task `project.taskfile` will look for a module `alfons.tasks.project.taskfile`. We implemented our own path search function that uses `package.path`, so it should load them identically to how `require` does. We needed to implement this function since taskfiles are loaded using the content string, and require would pre-load it.
8 |
9 | As such, you can place your tasks in a local directory `alfons/tasks/`, or anywhere on your Lua path. You can also create LuaRocks rockspecs that supply their own taskfiles in that module path.
10 |
11 | ## Loading
12 |
13 | You should always (eheheh) load your taskfiles in the `always` task.
14 |
15 | ```lua
16 | function always()
17 | load "fetch"
18 | end
19 |
20 | function default()
21 | print(tasks.fetch("https://example.com"))
22 | end
23 | ```
24 |
25 | ```moon
26 | tasks:
27 | always: => load "fetch"
28 | default: => print tasks.fetch "https://example.com"
29 | ```
30 |
31 | ## Scope
32 |
33 | Your tasks will automatically be available from all other taskfiles that have been loaded and the main one.
34 |
35 | 
36 |
37 | Rather than writing a linear stream of code here to display what I mean, I decided to just use a graph. These are all loaded taskfiles.
38 |
39 | The main taskfile is able to access all of its children's tasks. `a` is not only able to access the main tasks and tasks from `d` and `e`, but also from *every other* taskfile that has been loaded.
40 |
41 | This does not hold true for the `always` task, where it will depend on loading order, but since the rest of the tasks are called only once all taskfiles have been loaded, tasks that are not `always` can access any other task.
--------------------------------------------------------------------------------
/docs/provide.md:
--------------------------------------------------------------------------------
1 | # Functions
2 |
3 | This is the documentation for the functions provided in the Alfons environment.
4 |
5 | To see the documentation for `build` and `watch`, check out their respective markdown files.
6 |
7 | ## Table of Contents
8 |
9 | - [Functions](#functions)
10 | - [Table of Contents](#table-of-contents)
11 | - [Tables](#tables)
12 | - [npairs](#npairs)
13 | - [env](#env)
14 | - [keys](#keys)
15 | - [values](#values)
16 | - [entries](#entries)
17 | - [fromEntries](#fromentries)
18 | - [Arrays](#arrays)
19 | - [map](#map)
20 | - [reduce](#reduce)
21 | - [filter](#filter)
22 | - [slice](#slice)
23 | - [contains](#contains)
24 | - [Strings](#strings)
25 | - [lines](#lines)
26 | - [split](#split)
27 | - [sanitize](#sanitize)
28 | - [IO](#io)
29 | - [prints](#prints)
30 | - [printError](#printerror)
31 | - [safeOpen](#safeopen)
32 | - [safePopen](#safepopen)
33 | - [readfile](#readfile)
34 | - [writefile](#writefile)
35 | - [serialize](#serialize)
36 | - [ask](#ask)
37 | - [show](#show)
38 | - [cmd](#cmd)
39 | - [cmdfail](#cmdfail)
40 | - [cmdread](#cmdread)
41 | - [FS](#fs)
42 | - [isEmpty](#isempty)
43 | - [delete](#delete)
44 | - [copy](#copy)
45 | - [wildcard](#wildcard)
46 | - [iwildcard](#iwildcard)
47 | - [listAll](#listall)
48 | - [Path](#path)
49 | - [basename](#basename)
50 | - [extension](#extension)
51 | - [filename](#filename)
52 | - [pathname](#pathname)
53 | - [load](#load)
54 | - [style](#style)
55 | - [Importable](#importable)
56 | - [fetch](#fetch)
57 |
58 | ## Tables
59 |
60 | ### npairs
61 |
62 | Exactly like [ipairs](https://www.lua.org/manual/5.4/manual.html#pdf-ipairs), but it does not stop after a `nil` value.
63 |
64 | ### env
65 |
66 | If you run Alfons as:
67 |
68 | ```sh
69 | $ TEST=5 alfons
70 | ```
71 |
72 | You can access `TEST` by using `env.TEST`.
73 |
74 | ### keys
75 |
76 | `keys (table:{*:*}) -> [*]`
77 |
78 | Returns all the keys in a table.
79 |
80 | ### values
81 |
82 | `values (table:{*:*}) -> [*]`
83 |
84 | Returns all the values in a table.
85 |
86 | ### entries
87 |
88 | `entries (table:{*:*}) -> [{*,*}]`
89 |
90 | Returns an array of `{key, value}` tuples made from the keys and values of a table.
91 |
92 | ### fromEntries
93 |
94 | `fromEntries (entries:[{*,*}]) -> {*:*}`
95 |
96 | Reverses the process of `entries`.
97 |
98 | ## Arrays
99 |
100 | ### map
101 |
102 | `map (arr:[*], predicate:(value:*, key:*) -> *) -> [*]`
103 |
104 | Maps over an array.
105 |
106 | ### reduce
107 |
108 | `reduce (arr:[*], predicate:(accumulator:*, value:*) -> *, initial: *?) -> *`
109 |
110 | Reduces an array to a single value using an accumulator. Equivalent to `foldl`.
111 |
112 | ### filter
113 |
114 | `filter (arr:[*], predicate:(value:*, key: *) -> boolean) -> [*]`
115 |
116 | Creates a new array with only the values that pass the predicate.
117 |
118 | ### slice
119 |
120 | `slice (arr:[*], start:number?, end:number?) -> [*]`
121 |
122 | Creates a slice of an array that starts at `start` and ends at `end`.
123 |
124 | ### contains
125 |
126 | `contains (arr:[*], value:*) -> boolean`
127 |
128 | Checks if an array contains a certain value.
129 |
130 | ## Strings
131 |
132 | ### lines
133 |
134 | `lines (string) -> [string]`
135 |
136 | Splits a string into lines.
137 |
138 | ### split
139 |
140 | `split (str:string, re:string, plain:boolean, matches:number) -> [string]`
141 |
142 | Splits a string `str` into parts by a pattern `re`, which is interpreted as a Lua pattern except if the `plain` flag is set to true. Additionally, a maximum number of matches can be set with the `matches` argument.
143 |
144 | ### sanitize
145 |
146 | `sanitize (string) -> string`
147 |
148 | Makes sure that a string is safe to use in patterns without magic characters.
149 |
150 | ## IO
151 |
152 | ### prints
153 |
154 | `prints (...) -> nil`
155 |
156 | `print` and `style` (from [ansikit](https://git.daelvn.com/ansikit)) together.
157 |
158 | ### printError
159 |
160 | `printError (text:string) -> nil`
161 |
162 | Prints a string in red.
163 |
164 | ### safeOpen
165 |
166 | `safeOpen (file:string, mode:string) -> io | {["error"]:string}`
167 |
168 | Returns a table with an error string if the file could not be opened properly.
169 |
170 | ### safePopen
171 |
172 | `safePopen (command:string, mode:string) -> io | {["error"]:string}`
173 |
174 | Equivalent to `safeOpen`, but for `io.popen`.
175 |
176 | ### readfile
177 |
178 | `readfile (file:string) -> string`
179 |
180 | Takes a filename and returns its contents.
181 |
182 | ### writefile
183 |
184 | `writefile (file:string, content:string) -> nil`
185 |
186 | Takes a filename and a string, and writes the string to it.
187 |
188 | ### serialize
189 |
190 | `serialize (t:table) -> string`
191 |
192 | Quick table serializing, not useful in most cases. Used in `build`.
193 |
194 | ### ask
195 |
196 | `ask (str:string) -> string`
197 |
198 | Gets input from the user, with a prompt (optionally styled).
199 |
200 | ### show
201 |
202 | `show (str:string) -> nil`
203 |
204 | Displays a message, but fancy.
205 |
206 | ### cmd
207 |
208 | `cmd (str:string) -> number`
209 |
210 | `cmd`/`sh` as an alias to `os.execute`.
211 |
212 | ### cmdfail
213 |
214 | `cmdfail (str:string) -> nil`
215 |
216 | `cmdfail`/`shfail` is a wrapper around `os.execute` that will exit the program with the code returned by `os.execute` if it is not 0. For example, trying to run a program that does not exist will exit alfons with code 127.
217 |
218 | ### cmdread
219 |
220 | `cmdread (command:string) -> string`
221 |
222 | `cmdread` uses `safePopen` (`io.popen`) to execute a command and return all of its output. If `popen` did not work, it returns the error as a string.
223 |
224 | ## FS
225 |
226 | ### isEmpty
227 |
228 | `isEmpty (dir:string) -> boolean`
229 |
230 | Checks if a directory is empty
231 |
232 | ### delete
233 |
234 | `delete (path:string)`
235 |
236 | Deletes a file or folder recursively.
237 |
238 | ### copy
239 |
240 | `copy (fr:string, to:string)`
241 |
242 | Copies a file or folder recursively.
243 |
244 | ### wildcard
245 |
246 | `wildcard (path:string) -> function (iterator)`
247 |
248 | Iterable globbing that lets you do things such as:
249 |
250 | ```moon
251 | compileall: =>
252 | for file in wildcard "*.moon"
253 | sh "moonc #{file}"
254 | ```
255 |
256 | ### iwildcard
257 |
258 | `iwildcard (paths:table) -> function (iterator)`
259 |
260 | A wrapper around `wildcard`, that lets you use several globs.
261 |
262 | ```moon
263 | seeall: =>
264 | for file in iwildcard {"*.moon", "*.lua"}
265 | sh "cat #{file}"
266 | ```
267 |
268 | ### listAll
269 |
270 | `listAll (path:string) -> [string]`
271 |
272 | Returns a list of all nodes in `path` recursively.
273 |
274 | ## Path
275 |
276 | ### basename
277 |
278 | `basename (file:string) -> string`
279 |
280 | Returns everything but the extension of a file.
281 |
282 | ### extension
283 |
284 | `extension (file:string) -> string`
285 |
286 | Returns only the extension of a file without the dot.
287 |
288 | ### filename
289 |
290 | `filename (file:string) -> string`
291 |
292 | Returns only the filename without extension and parent path. `/home/daelvn/test.txt` becomes `test`.
293 |
294 | ### pathname
295 |
296 | `pathname (file:string) -> string`
297 |
298 | Returns the parent path of a file or folder.
299 |
300 | ### load
301 |
302 | `load (name)` imports tasks defined in `alfons.tasks.name` and lets you access them from the tasks table, so you can run them from the command line and from other tasks. You can create your own LuaRocks modules which export something as `alfons.tasks.*` to add custom tasks, or just create a local folder `alfons/tasks/` and it will load from them too.
303 |
304 | Please look at [Loading](loading.md) for more detailed documentatin.
305 |
306 | ### style
307 |
308 | As it is imported/defined from Alfons, it is now available to the environment. You can now use the [`style` function from Ansikit](https://git.daelvn.com/ansikit/module/style/#style) in Alfons.
309 |
310 | ```moon
311 | tasks
312 | pretty: => print style "%{blue}#{@name}"
313 | ```
314 |
315 | ## Importable
316 |
317 | These are tasks that can be imported with `load "task"`.
318 |
319 | ### fetch
320 |
321 | `fetch` will return the contents of a URL over HTTP. It uses [lua-http](https://github.com/daurnimator/lua-http)
322 |
323 | ```sh
324 | $ luarocks install http
325 | ```
326 |
327 | The task gets an URL, and simply returns the contents as a string:
328 |
329 | ```lua
330 | function always ()
331 | load "fetch"
332 | end
333 | function printurl (self)
334 | print(tasks.fetch{url="https://example.com"})
335 | end
336 | ```
337 |
338 | ```moon
339 | tasks:
340 | always: => load "fetch"
341 | printurl: => print tasks.fetch url: "https://example.com"
342 | ```
343 |
344 | If you need to write the contents to a file, you can use `writefile`:
345 |
346 | ```lua
347 | function always ()
348 | load "fetch"
349 | end
350 | function download (self)
351 | writefile(self.file, tasks.fetch{url = self.url})
352 | end
353 | function main (self)
354 | tasks.download{url="https://example.com", file="index.html"}
355 | end
356 | ```
357 |
358 | ```moon
359 | tasks:
360 | always: =>
361 | load "fetch"
362 | download: =>
363 | writefile @file, tasks.fetch url: @url
364 | main: =>
365 | tasks.download url:"https://example.com", file: "index.html"
366 | ```
367 |
--------------------------------------------------------------------------------
/docs/recipes.md:
--------------------------------------------------------------------------------
1 | # Recipes
2 |
3 | ## Amalg.lua
4 |
5 | Requires [amalg.lua](rockbuild -m -t #{@v} u)
6 |
7 | ### Pack
8 |
9 | ```lua
10 | function pack(self)
11 | show("Packing using amalg.lua")
12 | -- options
13 | self.o = self.o or self.output or "out.lua"
14 | self.s = self.s or self.entry or "src/main.lua"
15 | -- collect modules
16 | local modules = {}
17 | for file in wildcard "src/*.lua" do modules[#modules+1] = "src." .. filename(file) end
18 | -- pack
19 | sh("amalg.lua -o " .. self.o .. " -s " .. self.s .. " " .. table.concat(modules, " "))
20 | ```
21 |
22 | ```moon
23 | pack: =>
24 | show "Packing using amalg.lua"
25 | @o or= @output or "alfons.lua"
26 | @s or= @entry or "bin/alfons.lua"
27 | modules = for file in wildcard "alfons/*.moon" do "alfons.#{filename file}"
28 | sh "amalg.lua -o #{@o} -s #{@s} #{table.concat modules, ' '}"
29 | ```
30 |
31 | ## Rockbuild
32 |
33 | Requires [rockbuild](https://github.com/daelvn/rockbuild)
34 |
35 | ### Make
36 |
37 | ```lua
38 | function make(self)
39 | if self.v
40 | sh("rockbuild -m --delete " .. v)
41 | end
42 | end
43 | ```
44 |
45 | ### Release
46 |
47 | ```lua
48 | function release(self)
49 | if self.v
50 | sh("rockbuild -m -t " .. v .. " u")
51 | end
52 | end
53 | ```
54 |
55 | ## MoonScript
56 |
57 | ### Compile
58 |
59 | ```moon
60 | compile: => for file in wildcard "**.moon"
61 | sh "moonc #{file}" unless file == "Alfons.moon"
62 | ```
63 |
64 | ### Build
65 |
66 | ```moon
67 | build: => build (wildcard "**.moon"), (file) -> sh "moonc #{file}"
68 | ```
69 |
70 | ### Watch
71 |
72 | Requires `inotify` LuaRocks package.
73 |
74 | ```moon
75 | -- WATCH dirs, exclude, mode, match, process
76 | watch: => watch {"."}, {".git"}, "live", (glob "*.moon"), (file, ev) -> sh "moonc #{file}"
77 | ```
78 |
79 | ### Clean
80 |
81 | ```moon
82 | clean: => delete file for file in wildcard "**.lua"
83 | ```
84 |
--------------------------------------------------------------------------------
/docs/teal.md:
--------------------------------------------------------------------------------
1 | # Teal support
2 |
3 | > **WARNING:** Teal support is **experimental** and relies on the Teal Compiler API that is subject to change. Use this at your own risk. It may be deprecated at any moment. To use, install the `tl` rock.
4 |
5 | ## Taskfiles
6 |
7 | Taskfiles can be written in Teal, and you can use an `Alfons.tl` file just as you would an `Alfons.lua` or an `Alfons.moon` file. You may have some trouble with `tl check` warning you about unknown variables like `tasks` or `store`, as well as the many functions that are not specified as types. Teal support is **experimental** and it will still take time to accomodate Alfons to the type system.
8 |
9 | ### Defining a taskfile
10 |
11 | While you can just define it as a Lua taskfile, feel free to use this template if you really, really care about types. Remember that you must declare your functions as globals!
12 |
13 | ```lua
14 | -- This definition is optional. Feel free to use `self:table`
15 | -- instead.
16 | -- If you are from the Teal team, and know how to include this
17 | -- type automatically, let me know!
18 | local record Self
19 | metamethod __index: {string:any}
20 | name: string
21 | task: function -- it takes nothing and returns nothing
22 | end
23 |
24 | global function always(self:Self)
25 | print(self.name)
26 | end
27 | ```
28 |
29 | ## Teal plugin
30 |
31 | The `alfons-teal` rock (included in this repo but installed separately) provides a `teal` plugin that you can use via `load` (see more [here](loading.md)). The functionality for that plugin is described here.
32 |
33 | This plugin exports the following commands, which you should not overwrite: **`install`, `build`, `typings`**.
34 |
35 | ### Installing LuaRocks dependencies
36 |
37 | > **WARNING:** LuaRocks does **not** have an official updated API, so this task resorts to running `sh "luarocks install dependency"`. LuaRocks must therefore be a command available in your PATH. If you are a LuaRocks developer and know how to fix this, PRs welcome!
38 |
39 | Upon calling the `install` task, it will install all dependencies from `store.dependencies`, which must be a list of strings, each a valid LuaRocks package. You can make it execute automatically by doing `store.teal_auto = true`.
40 |
41 | ```lua
42 | global function always()
43 | load "teal"
44 | store.dependencies = {"tl", "busted"}
45 | end
46 | ```
47 |
48 | ### Building
49 |
50 | The `build` task is simply a wrapper for `tl build`, since I figured that implementing this as an Alfons plugin would be way overkill.
51 |
52 | ### Hooks
53 |
54 | The `teal` plugin can run several kinds of hooks:
55 |
56 | - Pre-install (`teal_preinstall`)
57 | - Post-install (`teal_postinstall`)
58 | - Pre-build (`teal_prebuild`)
59 | - Post-build (`teal_postbuild`)
60 |
61 | Simply define these tasks, and they will be run accordingly!
62 |
63 | ### Downloading typings.
64 |
65 | > **WARNING:** This task requires the `dkjson` and `http` packages, which you must install before using this. Otherwise, there would be no way of fetching the content.
66 |
67 | The `alfons-teal` can download type definitions from the [teal-types](//github.com/teal-language/teal-types) repository and into your current working directory, using the `typings` task.
68 |
69 | ### CLI
70 |
71 | You can do this from the CLI by just loading the `teal` plugin and doing:
72 |
73 | ```
74 | $ alfons typings -m
75 | ```
76 |
77 | ### Taskfile
78 |
79 | When you call `tasks.typings()`, it will automatically try to use `store.typings` (a list of strings) as a source for what rocks to fetch type definitions for. You can make it do this automatically by setting `store.teal_auto` to `true`.
80 |
81 | ```lua
82 | -- Lua
83 | tasks.typings{ modules = {"..."} }
84 | -- MoonScript
85 | tasks.typings modules: {"..."}
86 | ```
87 |
88 | ## Showcase
89 |
90 | This is a short "tutorial" on how to use the `teal` plugin.
91 |
92 | ### Loading
93 |
94 | Like any other module, you put the load declaration in the `always` task.
95 |
96 | ```lua
97 | global function always()
98 | load "teal"
99 | end
100 | ```
101 |
102 | ### Defining dependencies
103 |
104 | Simply set `store.dependencies` to a table containing strings, each a valid LuaRocks package before calling the `tasks.install()` tasks in the Taskfile (or `alfons install` in the command-line). You can make it do this automatically every time you open Alfons by setting `store.teal_auto = true`.
105 |
106 | ### Building
107 |
108 | `alfons build` (or `tasks.build()`) becomes an alias to `tl build` on the command-line.
109 |
110 | ### Downloading type definitions
111 |
112 | See [Downloading typings](#downloading-typings).
113 |
114 | ### Declaring hooks
115 |
116 | To define a hook, simply define another global function with the names specified in [Hooks](#hooks).
117 |
118 | ```lua
119 | global function always()
120 | store.install = false
121 | load "teal"
122 | end
123 |
124 | global function teal_postinstall()
125 | prints "Dependencies installed!"
126 | end
127 | ```
--------------------------------------------------------------------------------
/docs/tutorial.md:
--------------------------------------------------------------------------------
1 | # Alfons for The Inexperienced Alfonsnsner
2 |
3 | Hello, traveller! In this tutorial, I will be assuming this is your first time using Alfons. I will make it as easy to follow as possible. Put on your best programming socks and follow me into this deep abyss that Alfons represents.
4 |
5 | - [Alfons for The Inexperienced Alfonsnsner](#alfons-for-the-inexperienced-alfonsnsner)
6 | - [Installing](#installing)
7 | - [Familiarizing with the interface](#familiarizing-with-the-interface)
8 | - [Taskfiles](#taskfiles)
9 | - [Two tasks?!?!?!](#two-tasks)
10 | - [Introspection](#introspection)
11 | - [Task arguments](#task-arguments)
12 | - [Calling other tasks](#calling-other-tasks)
13 | - [Storing data](#storing-data)
14 | - [Exploring](#exploring)
15 |
16 | ## Installing
17 |
18 | The proper way of installing Alfons is through LuaRocks. If you're on Linux, you're smart enough to know how to install LuaRocks. If you're on Windows, may a higher force save you. If you're on neither, I'm sorry.
19 |
20 | ```
21 | $ luarocks install alfons
22 | ```
23 |
24 | Of course, the fancy way of installing Alfons would be through Alfons! But Alfons is not a package manager... yet. Stay tuned for Alfons 27.
25 |
26 | Make sure that Alfons is installed ok and most importantly, that I didn't fuck up the build. If you get this message, you're good to go.
27 |
28 | ```
29 | $ alfons
30 | Alfons 4.2
31 | No Taskfile found.
32 | ```
33 |
34 | ## Familiarizing with the interface
35 |
36 | When Alfons is run, it looks for `Alfons.lua` first, and then `Alfons.moon`. That's right, Alfons works with both Lua and MoonScript (as long as you have MoonScript installed). I know, I know, MoonScript sucks, that's why I'm writing this tutorial for Lua only. No, I'm not dropping MoonScript support.
37 |
38 | If you want to change the file used, you can pass an `-f` or `--file` option to Alfons, and it will use that instead. Unless the file ends in `lua` or `moon`, you will have to tell it the type of language it is using the `--type` option, which accept values `moon` and `lua`.
39 |
40 | ```
41 | $ alfons --file example.txt --type lua
42 | Alfons 4.2
43 | Using example.txt (lua)
44 | Could not open example.txt: example.txt: No such file or directory
45 | ```
46 |
47 | ## Taskfiles
48 |
49 | Now, the moment we were all waiting for. What does this piece of garbage _actually_ do? It just runs defined and named snippets of code. Tasks, if you will. It runs tasks. It takes the names of the tasks you want to run, and runs them. You can make tasks depend on other tasks. You can have tasks for practically anything. We put them in a Taskfile. We will be using `Alfons.lua`. Create that file and then just put this in it:
50 |
51 | ```lua
52 | function hello()
53 | print("Hello, world!")
54 | end
55 | ```
56 |
57 | Now, when you run Alfons, nothing will happen. We need to tell it to run your task. This is quite simple, just do `alfons hello`:
58 |
59 | ```
60 | $ alfons hello
61 | Alfons 4.2
62 | Using Alfons.lua (lua)
63 | Hello, world!
64 | ```
65 |
66 | Good! You got your first taskfile running.
67 |
68 | ## Two tasks?!?!?!
69 |
70 | Let's say, hypothetically, that you wanted a task to build and another to clean. Let's say, hypothetically, that Alfons could do that. Just kidding, of course it can. The only thing it can't do is bring back my kids. Just write as many functions as you'd like right beside each other. The order is actually irrelevant.
71 |
72 | ```lua
73 | function build()
74 | writefile("build.txt", "build information here")
75 | end
76 |
77 | function clean()
78 | delete("build.txt")
79 | end
80 | ```
81 |
82 | Here there are two functions that you might not recognize. You can read about `writefile` [here](provide.md#writefile) and `fs` [here](provide.md#delete). It's recommended that you familiarize yourself with the functions that come with Alfons as they will make your life much easier.
83 |
84 | Now you can just call them one after each other: `alfons build clean`
85 |
86 | ## Introspection
87 |
88 | All functions accept a single argument called `self`. Admittedly it's a bit empty and underused, but it does an honest job. It contains a field `name` with the name of the task, in case you're procedurally generating them or something. It also contains a field `task` that contains the task itself, if you want to call it recursively. That function takes a table of arguments instead of varargs.
89 |
90 | ```lua
91 | function myself(self)
92 | print("I am " .. self.name)
93 | end
94 | ```
95 |
96 | ## Task arguments
97 |
98 | Now, for a spin, you can make a task take arguments, like flags and options. To see specifically how they are parsed, look at [this manual page](arguments.md). The arguments can be anything you want, and they will be passed as a table to the functions through the `self` table. Write a task like this:
99 |
100 | ```lua
101 | function word(self)
102 | print("My favorite word is " .. self.word)
103 | end
104 | ```
105 |
106 | Now, if you call it with the `word` option, it will speak back to you!
107 |
108 | ```
109 | $ alfons word --word oboe
110 | Alfons 4.2
111 | Using Alfons.lua (lua)
112 | My favorite word is oboe
113 | ```
114 |
115 | ## Calling other tasks
116 |
117 | Writing many tasks is fun until you start to have to reuse code. You could still make local functions, there's nothing stopping you from doing that, I promise, but chances are that at one point you will want to call another task. In Lua, I _think_ you might be able to call the function directly? It won't have the `name` and `task` fields that's for sure. I also think it won't count towards the total tasks-run number. For your own protection, please use the following method, which is just the `tasks` table:
118 |
119 | ```lua
120 | function main()
121 | tasks.another()
122 | end
123 |
124 | function another()
125 | print "It worked!"
126 | end
127 | ```
128 |
129 | Now just run `alfons main` and try it out!
130 |
131 | ## Storing data
132 |
133 | A way to store data and make it available to all tasks at any given time is using the `store` table. It's just a normal table, but available across every Taskfile that you load.
134 |
135 | ```lua
136 | function stores()
137 | store.field = true
138 | end
139 |
140 | function gets()
141 | print(store.field)
142 | end
143 | ```
144 |
145 | Running `alfons stores gets` will get you `true`!
146 |
147 | ## Exploring
148 |
149 | Those are pretty much the basics to Alfons. From here, it's just exploring! Check out the [Recipes](recipes.md) page for some cool tasks for Alfons.
150 |
--------------------------------------------------------------------------------
/docs/watch.md:
--------------------------------------------------------------------------------
1 | # watch
2 |
3 | Watch uses `inotify` to listen for filesystem events and call the function with the path and event name. Its signature is this:
4 |
5 | `watch (dirs:{string}, exclude:{string}, evf:{string}, pred:(file -> boolean), fn:(file -> nil)) -> nil`
6 |
7 | ## dirs
8 |
9 | `dirs` is a list of directories to watch files in.
10 |
11 | ## exclude
12 |
13 | `exclude` is a list of directories to exclude from the first list. If you have `.` in the first, you might want to exclude `.git`, for example.
14 |
15 | ## evf
16 |
17 | List of events to listen for. This is the full list. Check the [inotify manpage](https://linux.die.net/man/7/inotify) for more info. Optionally you can pass a string instead of a table, accepting only one value as of now; `"live"`, which is equivalent to `{"write", "movein", "create"}`
18 |
19 | ```moon
20 | EVENTS = {
21 | access: "IN_ACCESS"
22 | change: "IN_ATTRIB"
23 | write: "IN_CLOSE_WRITE"
24 | shut: "IN_CLOSE_NOWRITE"
25 | close: "IN_CLOSE"
26 | create: "IN_CREATE"
27 | delete: "IN_DELETE"
28 | destruct: "IN_DELETE_SELF"
29 | modify: "IN_MODIFY"
30 | migrate: "IN_MOVE_SELF"
31 | move: "IN_MOVE"
32 | movein: "IN_MOVED_TO"
33 | moveout: "IN_MOVED_FROM"
34 | open: "IN_OPEN"
35 | all: "IN_ALL_EVENT"
36 | }
37 | ```
38 |
39 | ## pred
40 |
41 | The predicate function, which takes in a filename and the triggered event list(as separate arguments), and should return a boolean deciding whether to accept the event or not.
42 |
43 | ## fn
44 |
45 | The processor function, which takes the filename and triggered event list, and is basically what should do things like compiling and such.
46 |
47 | ## Examples
48 |
49 | ### Watching MoonScript files
50 |
51 | ```moon
52 | tasks:
53 | compile: =>
54 | watch {"."}, {".git"}, "live", (glob "*.moon"), (file, ev) -> sh "moonc #{file}"
55 | ```
--------------------------------------------------------------------------------
/rock-dev.yml:
--------------------------------------------------------------------------------
1 | package: alfons-dev
2 | source:
3 | url: git://github.com/daelvn/alfons
4 | description:
5 | summary: Unpacked Alfons modules for development
6 | detailed: >
7 | The normal 'alfons' package is bundled, making all
8 | modules unavailable. 'alfons-dev' installs them
9 | without bundling.
10 | homepage: https://github.com/daelvn/alfons
11 | dependencies:
12 | - lpath
13 | - ansikit
14 | - lua >= 5.1
15 | - inotify
16 | - http
17 | build:
18 | type: builtin
19 | modules:
20 | alfons.tasks.fetch: alfons/tasks/fetch.lua
21 | alfons.tasks.teal: alfons/tasks/teal.lua
22 | alfons.setfenv: alfons/setfenv.lua
23 | alfons.env: alfons/env.lua
24 | alfons.file: alfons/file.lua
25 | alfons.getopt: alfons/getopt.lua
26 | alfons.provide: alfons/provide.lua
27 | alfons.wildcard: alfons/wildcard.lua
28 | alfons.version: alfons/version.lua
29 | alfons.look: alfons/look.lua
30 | alfons.init: alfons/init.lua
31 | alfons.help: alfons/help.lua
32 | alfons.parser: alfons/parser.lua
33 | install:
34 | bin:
35 | alfons: bin/alfons.lua
36 |
--------------------------------------------------------------------------------
/rock.yml:
--------------------------------------------------------------------------------
1 | package: alfons
2 | source:
3 | url: git://github.com/daelvn/alfons
4 | description:
5 | summary: Small program to run tasks for your project
6 | detailed: >
7 | alfons is a small script utility that lets you run tasks
8 | from a file (Lua or MoonScript), to better manage your
9 | project with tasks such as clean, compile, etc. To run
10 | tasks from a MoonScript file, you will need the
11 | moonscript rock.
12 | homepage: https://github.com/daelvn/alfons
13 | dependencies:
14 | - lpath
15 | - ansikit
16 | - lua >= 5.1
17 | build:
18 | type: builtin
19 | modules:
20 | alfons.tasks.fetch: alfons/tasks/fetch.lua
21 | install:
22 | bin:
23 | alfons: alfons.lua
24 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.0-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.0",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.0-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.0.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.0.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.0.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.0.2-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.0.2",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.0.2-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.1.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.1.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.1.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.1.3-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.1.3",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.1.3-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.1.4-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.1.4",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.1.4-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.2-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.2",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.2-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.2.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.2.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.2.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.2.2-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.2.2",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.2.2-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.3-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.3",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.3-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.4-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.4",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.4-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-4.4.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v4.4.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "4.4.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.0.0-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "filekit >= 1.3",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.0.0",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.0.0-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.0.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "lpath",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.0.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.0.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.0.2-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "lpath",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.0.2",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.0.2-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "lpath",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.2-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "lpath",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.2",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.2-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.2.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "lpath",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.2.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.2.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.2.2-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "lpath",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.2.2",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.2.2-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.3-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "lpath",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.3",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.3-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-5.3.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua"
9 | },
10 | type = "builtin"
11 | }
12 | dependencies = {
13 | "lpath",
14 | "ansikit",
15 | "lua >= 5.1"
16 | }
17 | description = {
18 | detailed = "alfons is a small script utility that lets you run tasks from a file (Lua or MoonScript), to better manage your project with tasks such as clean, compile, etc. To run tasks from a MoonScript file, you will need the moonscript rock.\n",
19 | homepage = "https://github.com/daelvn/alfons",
20 | summary = "Small program to run tasks for your project"
21 | }
22 | package = "alfons"
23 | rockspec_format = "3.0"
24 | source = {
25 | tag = "v5.3.1",
26 | url = "git://github.com/daelvn/alfons"
27 | }
28 | version = "5.3.1-1"
29 |
--------------------------------------------------------------------------------
/rockspecs/alfons-dev-5.0.2-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "bin/alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.env"] = "alfons/env.lua",
9 | ["alfons.file"] = "alfons/file.lua",
10 | ["alfons.getopt"] = "alfons/getopt.lua",
11 | ["alfons.init"] = "alfons/init.lua",
12 | ["alfons.look"] = "alfons/look.lua",
13 | ["alfons.provide"] = "alfons/provide.lua",
14 | ["alfons.setfenv"] = "alfons/setfenv.lua",
15 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua",
16 | ["alfons.tasks.teal"] = "alfons/tasks/teal.lua",
17 | ["alfons.version"] = "alfons/version.lua",
18 | ["alfons.wildcard"] = "alfons/wildcard.lua"
19 | },
20 | type = "builtin"
21 | }
22 | dependencies = {
23 | "lpath",
24 | "ansikit",
25 | "lua >= 5.1",
26 | "inotify",
27 | "http"
28 | }
29 | description = {
30 | detailed = "The normal 'alfons' package is bundled, making all modules unavailable. 'alfons-dev' installs them without bundling.\n",
31 | homepage = "https://github.com/daelvn/alfons",
32 | summary = "Unpacked Alfons modules for development"
33 | }
34 | package = "alfons-dev"
35 | rockspec_format = "3.0"
36 | source = {
37 | tag = "v5.0.2",
38 | url = "git://github.com/daelvn/alfons"
39 | }
40 | version = "5.0.2-1"
41 |
--------------------------------------------------------------------------------
/rockspecs/alfons-dev-5.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "bin/alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.env"] = "alfons/env.lua",
9 | ["alfons.file"] = "alfons/file.lua",
10 | ["alfons.getopt"] = "alfons/getopt.lua",
11 | ["alfons.init"] = "alfons/init.lua",
12 | ["alfons.look"] = "alfons/look.lua",
13 | ["alfons.provide"] = "alfons/provide.lua",
14 | ["alfons.setfenv"] = "alfons/setfenv.lua",
15 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua",
16 | ["alfons.tasks.teal"] = "alfons/tasks/teal.lua",
17 | ["alfons.version"] = "alfons/version.lua",
18 | ["alfons.wildcard"] = "alfons/wildcard.lua"
19 | },
20 | type = "builtin"
21 | }
22 | dependencies = {
23 | "lpath",
24 | "ansikit",
25 | "lua >= 5.1",
26 | "inotify",
27 | "http"
28 | }
29 | description = {
30 | detailed = "The normal 'alfons' package is bundled, making all modules unavailable. 'alfons-dev' installs them without bundling.\n",
31 | homepage = "https://github.com/daelvn/alfons",
32 | summary = "Unpacked Alfons modules for development"
33 | }
34 | package = "alfons-dev"
35 | rockspec_format = "3.0"
36 | source = {
37 | tag = "v5.1",
38 | url = "git://github.com/daelvn/alfons"
39 | }
40 | version = "5.1-1"
41 |
--------------------------------------------------------------------------------
/rockspecs/alfons-dev-5.2-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "bin/alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.env"] = "alfons/env.lua",
9 | ["alfons.file"] = "alfons/file.lua",
10 | ["alfons.getopt"] = "alfons/getopt.lua",
11 | ["alfons.help"] = "alfons/help.lua",
12 | ["alfons.init"] = "alfons/init.lua",
13 | ["alfons.look"] = "alfons/look.lua",
14 | ["alfons.parser"] = "alfons/parser.lua",
15 | ["alfons.provide"] = "alfons/provide.lua",
16 | ["alfons.setfenv"] = "alfons/setfenv.lua",
17 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua",
18 | ["alfons.tasks.teal"] = "alfons/tasks/teal.lua",
19 | ["alfons.version"] = "alfons/version.lua",
20 | ["alfons.wildcard"] = "alfons/wildcard.lua"
21 | },
22 | type = "builtin"
23 | }
24 | dependencies = {
25 | "lpath",
26 | "ansikit",
27 | "lua >= 5.1",
28 | "inotify",
29 | "http"
30 | }
31 | description = {
32 | detailed = "The normal 'alfons' package is bundled, making all modules unavailable. 'alfons-dev' installs them without bundling.\n",
33 | homepage = "https://github.com/daelvn/alfons",
34 | summary = "Unpacked Alfons modules for development"
35 | }
36 | package = "alfons-dev"
37 | rockspec_format = "3.0"
38 | source = {
39 | tag = "v5.2",
40 | url = "git://github.com/daelvn/alfons"
41 | }
42 | version = "5.2-1"
43 |
--------------------------------------------------------------------------------
/rockspecs/alfons-dev-5.2.1-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | install = {
3 | bin = {
4 | alfons = "bin/alfons.lua"
5 | }
6 | },
7 | modules = {
8 | ["alfons.env"] = "alfons/env.lua",
9 | ["alfons.file"] = "alfons/file.lua",
10 | ["alfons.getopt"] = "alfons/getopt.lua",
11 | ["alfons.help"] = "alfons/help.lua",
12 | ["alfons.init"] = "alfons/init.lua",
13 | ["alfons.look"] = "alfons/look.lua",
14 | ["alfons.parser"] = "alfons/parser.lua",
15 | ["alfons.provide"] = "alfons/provide.lua",
16 | ["alfons.setfenv"] = "alfons/setfenv.lua",
17 | ["alfons.tasks.fetch"] = "alfons/tasks/fetch.lua",
18 | ["alfons.tasks.teal"] = "alfons/tasks/teal.lua",
19 | ["alfons.version"] = "alfons/version.lua",
20 | ["alfons.wildcard"] = "alfons/wildcard.lua"
21 | },
22 | type = "builtin"
23 | }
24 | dependencies = {
25 | "lpath",
26 | "ansikit",
27 | "lua >= 5.1",
28 | "inotify",
29 | "http"
30 | }
31 | description = {
32 | detailed = "The normal 'alfons' package is bundled, making all modules unavailable. 'alfons-dev' installs them without bundling.\n",
33 | homepage = "https://github.com/daelvn/alfons",
34 | summary = "Unpacked Alfons modules for development"
35 | }
36 | package = "alfons-dev"
37 | rockspec_format = "3.0"
38 | source = {
39 | tag = "v5.2.1",
40 | url = "git://github.com/daelvn/alfons"
41 | }
42 | version = "5.2.1-1"
43 |
--------------------------------------------------------------------------------
/test/alfons/dusubalf.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | dusubloaded: => print @name
3 | dusubcallup: =>
4 | print @name
5 | tasks.subbelow!
6 | dusubcalltop: =>
7 | print @name
8 | tasks.subcallup!
--------------------------------------------------------------------------------
/test/alfons/graph-proof/a.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | always: =>
3 | load "graph-proof.d"
4 | load "graph-proof.e"
5 | a: => print @name
6 | doa: =>
7 | tasks.a!
8 | tasks.b!
9 | tasks.c!
10 | tasks.d!
11 | tasks.e!
12 | tasks.f!
--------------------------------------------------------------------------------
/test/alfons/graph-proof/b.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | b: => print @name
3 | dob: =>
4 | tasks.a!
5 | tasks.b!
6 | tasks.c!
7 | tasks.d!
8 | tasks.e!
9 | tasks.f!
--------------------------------------------------------------------------------
/test/alfons/graph-proof/c.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | always: => load "graph-proof.f"
3 | c: => print @name
4 | doc: =>
5 | tasks.a!
6 | tasks.b!
7 | tasks.c!
8 | tasks.d!
9 | tasks.e!
10 | tasks.f!
--------------------------------------------------------------------------------
/test/alfons/graph-proof/d.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | d: => print @name
3 | dod: =>
4 | tasks.a!
5 | tasks.b!
6 | tasks.c!
7 | tasks.d!
8 | tasks.e!
9 | tasks.f!
--------------------------------------------------------------------------------
/test/alfons/graph-proof/e.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | e: => print @name
3 | doe: =>
4 | tasks.a!
5 | tasks.b!
6 | tasks.c!
7 | tasks.d!
8 | tasks.e!
9 | tasks.f!
--------------------------------------------------------------------------------
/test/alfons/graph-proof/f.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | f: => print @name
3 | dof: =>
4 | tasks.a!
5 | tasks.b!
6 | tasks.c!
7 | tasks.d!
8 | tasks.e!
9 | tasks.f!
--------------------------------------------------------------------------------
/test/alfons/graph-proof/main.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | always: =>
3 | load "graph-proof.a"
4 | load "graph-proof.b"
5 | load "graph-proof.c"
6 | main: => print @name
--------------------------------------------------------------------------------
/test/alfons/lua.lua:
--------------------------------------------------------------------------------
1 | function always()
2 | print "Hello from Lua!"
3 | load "subalf"
4 | end
5 |
6 | function runTask()
7 | print "Running from Lua!"
8 | end
9 |
10 | function fromMoon()
11 | tasks.subloaded()
12 | end
--------------------------------------------------------------------------------
/test/alfons/main.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | always: => load "subalf"
3 | hello: => print @name
4 | shello: => sh "echo 'Hello from sh!'"
5 | execute: =>
6 | print @name
7 | tasks.subloaded!
--------------------------------------------------------------------------------
/test/alfons/predet.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | always: => load "predet2"
3 | first: => print @name
4 | default: => print @name
5 | finalize: => print @name
--------------------------------------------------------------------------------
/test/alfons/predet2.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | second: => print @name
3 | default: => print @name .. "2"
4 | finalize: => print @name .. "2"
--------------------------------------------------------------------------------
/test/alfons/sidea.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | always: => load "sideb"
3 | helloa: => print @name
--------------------------------------------------------------------------------
/test/alfons/sideb.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | always: => load "sidea"
3 | hellob: => print @name
--------------------------------------------------------------------------------
/test/alfons/storea.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | always: =>
3 | store.test = "Hello World!"
4 | load "storeb"
--------------------------------------------------------------------------------
/test/alfons/storeb.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | test: => print store.test
--------------------------------------------------------------------------------
/test/alfons/subalf.moon:
--------------------------------------------------------------------------------
1 | tasks:
2 | subloaded: => print @name
3 | subdirect: => print @name
4 | subbelow: => print @name
5 | subcallup: =>
6 | print @name
7 | tasks.hello!
8 | subdual: =>
9 | print @name
10 | load "dusubalf"
--------------------------------------------------------------------------------
/test/alfons/teal-table.tl:
--------------------------------------------------------------------------------
1 | return { tasks = {
2 | always = function()
3 | print "Hello from Teal!"
4 | load "subalf"
5 | end,
6 | runTask = function()
7 | print "Running from Teal!"
8 | end,
9 | fromMoon = function()
10 | tasks.subloaded()
11 | end
12 | }}
--------------------------------------------------------------------------------
/test/alfons/teal.tl:
--------------------------------------------------------------------------------
1 | global function always()
2 | print "Hello from Teal!"
3 | load "subalf"
4 | end
5 |
6 | global function runTask()
7 | print "Running from Teal!"
8 | end
9 |
10 | global function fromMoon()
11 | tasks.subloaded()
12 | end
--------------------------------------------------------------------------------
/test/graph-proof.moon:
--------------------------------------------------------------------------------
1 | import runString from require "alfons"
2 | import readMoon from require "alfons.file"
3 | inspect = require "inspect"
4 |
5 | -- testing the graph in docs/loading.md
6 | alfons, err = runString readMoon "test/alfons/graph-proof/main.moon"
7 | error err if err
8 | env = alfons!
9 |
10 | print "-> (main)"
11 | env.tasks.a!
12 | env.tasks.b!
13 | env.tasks.c!
14 | env.tasks.d!
15 | env.tasks.e!
16 | env.tasks.f!
17 | print "-> a"
18 | env.tasks.doa!
19 | print "-> b"
20 | env.tasks.dob!
21 | print "-> c"
22 | env.tasks.doc!
23 | print "-> d"
24 | env.tasks.dod!
25 | print "-> e"
26 | env.tasks.doe!
27 | print "-> f"
28 | env.tasks.dof!
--------------------------------------------------------------------------------
/test/lua.moon:
--------------------------------------------------------------------------------
1 | import runString from require "alfons"
2 | import readLua from require "alfons.file"
3 | inspect = require "inspect"
4 |
5 | -- testing lua taskfiles
6 | alfons, err = runString readLua "test/alfons/lua.lua"
7 | error err if err
8 | env = alfons!
9 |
10 | env.tasks.runTask!
11 | env.tasks.fromMoon!
--------------------------------------------------------------------------------
/test/predet.moon:
--------------------------------------------------------------------------------
1 | import runString from require "alfons"
2 | import readMoon from require "alfons.file"
3 | inspect = require "inspect"
4 |
5 | -- testing default and finalize tasks
6 | alfons, err = runString readMoon "test/alfons/predet.moon"
7 | error err if err
8 | env = alfons!
9 |
10 | -- check count
11 | print env.__ran -- 0
12 | env.tasks.first!
13 | print env.__ran -- 1
14 | -- reset
15 | alfons, err = runString readMoon "test/alfons/predet.moon"
16 | env = alfons!
17 | print "---"
18 |
19 | -- finalize (2 defaults and 2 finalizes)
20 | env.finalize!
21 | -- reset
22 | alfons, err = runString readMoon "test/alfons/predet.moon"
23 | env = alfons!
24 | print "---"
25 |
26 | -- finalize, one default
27 | env.tasks.first!
28 | env.finalize!
29 | -- reset
30 | alfons, err = runString readMoon "test/alfons/predet.moon"
31 | env = alfons!
32 | print "---"
33 |
34 | -- finalize, another default
35 | env.tasks.second!
36 | env.finalize!
37 | -- reset
38 | alfons, err = runString readMoon "test/alfons/predet.moon"
39 | env = alfons!
40 | print "---"
--------------------------------------------------------------------------------
/test/runString.moon:
--------------------------------------------------------------------------------
1 | import runString from require "alfons"
2 | import readMoon from require "alfons.file"
3 | inspect = require "inspect"
4 |
5 | -- testing depths
6 | print "== TESTING DEPTHS =="
7 | alfons, err = runString readMoon "test/alfons/main.moon"
8 | error err if err
9 | env = alfons!
10 |
11 | -- Always is nowalready run
12 | --env.tasks.always!
13 |
14 | -- normal task in main
15 | env.tasks.hello!
16 | print "---"
17 | -- call task once-below main from task in main
18 | env.tasks.execute!
19 | print "---"
20 | -- call task once-below main directly
21 | env.tasks.subdirect!
22 | print "---"
23 | -- call task once-below main directly which calls a task once-above it (in main)
24 | env.tasks.subcallup!
25 | print "---"
26 | -- loads a taskfile (twice-below main) from a taskfile once-below main
27 | env.tasks.subdual!
28 | print "---"
29 | -- calls a task twice-below main
30 | env.tasks.dusubloaded!
31 | print "---"
32 | -- calls a task twice-below main which calls a task once-below main
33 | env.tasks.dusubcallup!
34 | print "---"
35 | -- calls a task twice-below main which calls a task once-below main, which
36 | -- calls a task in main
37 | env.tasks.dusubcalltop!
38 | print "---"
39 |
40 | -- testing load
41 | print "== TESTING LOAD =="
42 | alfons, err = runString readMoon "test/alfons/sidea.moon"
43 | error err if err
44 | env = alfons!
45 |
46 | env.tasks.helloa!
47 | env.tasks.hellob!
--------------------------------------------------------------------------------
/test/store.moon:
--------------------------------------------------------------------------------
1 | import runString from require "alfons"
2 | import readMoon from require "alfons.file"
3 | inspect = require "inspect"
4 |
5 | -- testing store table
6 | alfons, err = runString readMoon "test/alfons/storea.moon"
7 | error err if err
8 | env = alfons!
9 |
10 | env.tasks.test!
--------------------------------------------------------------------------------
/test/teal.moon:
--------------------------------------------------------------------------------
1 | import runString from require "alfons"
2 | import readTeal from require "alfons.file"
3 |
4 | -- testing teal taskfiles
5 | print "teal (globals)"
6 | alfons, err = runString readTeal "test/alfons/teal.tl"
7 | error err if err
8 | env = alfons!
9 |
10 | env.tasks.runTask!
11 | env.tasks.fromMoon!
12 |
13 | --
14 | print "teal (table)"
15 | alfons, err = runString readTeal "test/alfons/teal-table.tl"
16 | error err if err
17 | env = alfons!
18 |
19 | env.tasks.runTask!
20 | env.tasks.fromMoon!
--------------------------------------------------------------------------------