2
3
mirror of https://github.com/sammy-ette/Hilbish synced 2025-08-10 02:52:03 +00:00

Compare commits

...

838 Commits

Author SHA1 Message Date
eb630b2de0
chore: change back release to moonflower 2025-06-16 17:16:45 -04:00
548de98551
chore: merge from 3.0 branch 2025-06-16 17:16:21 -04:00
49f2bae9e1
feat: add yarn library (#355) 2025-06-15 16:25:07 -04:00
5ca858d112
feat: move readline to golibs (#356) 2025-06-15 15:47:53 -04:00
1bb433dc64
feat: add processors api (#343)
* feat: add processors api

* fix: make processor work properly, implement in exec code

* feat: add names to processors, allow skipping based on name

* feat: add opt to skip processors

* feat: allow processors to set if history should be saved
2025-06-10 18:23:24 -04:00
aec17d1077
chore: merge 2025-05-30 12:28:26 -04:00
049b517b88
feat: emit hilbish.cd on fs.cd (closes #350) 2025-05-30 12:27:57 -04:00
35272ce1ac
feat: implement alias and display for completion groups of type list (#347) 2025-05-04 20:48:56 -04:00
Nadiyar
0036932693
docs: improve existing lunacolors guide (#331)
* docs: extend the lunacolors guide

* docs: add lunacolors change to CHANGELOG

---------

Co-authored-by: sammyette <torchedsammy@gmail.com>
2025-05-04 20:41:19 -04:00
e676c095c2
fix: dont refresh log on regex search error 2025-04-24 12:08:12 -04:00
ef4c925e37
fix: alias resolution for continued input with quotes 2025-04-24 11:27:43 -04:00
80d72a29bb
feat: return values returned by bait hooks (closes #297) 2025-04-23 20:12:05 -04:00
0854b5a769
fix!: don't define hilbish.completion, without the s at the end
the interface is hilbish.completions (s at the end)
2025-04-23 19:36:50 -04:00
2ca99fe831
fix!: get/set env variables via env table (#294)
this removes the old "virtual global table" which allows
getting environment variables via just their names in lua.

this means:
an environment variable (like TERM) would need to be accessed
via the `env` table instead of just using TERM in lua.

`TERM` -> `env.TERM`
they can also be set via `env.VARIABLE = 'value'
2025-04-23 19:33:09 -04:00
8793a733a6
chore: change ver info to 3.0 2025-04-23 19:31:11 -04:00
6827940466
chore: remove print and fix formatting 2025-04-17 22:36:29 -04:00
fde615ff3f
chore: merge 2025-04-17 22:34:23 -04:00
d002c82271
fix: hilbish.run return exitCode instead of runner output table 2025-04-17 22:34:17 -04:00
f64229b52c
fix: set autoflush to true by default for sinks, and flush when reading from sinks (closes #344) 2025-04-17 22:33:50 -04:00
James Dugan
3d5766ac33
fix: hilbish.sink.readAll() function now reads data that doesn't end in a newline (#345) 2025-04-17 22:06:21 -04:00
60edfc00ee
chore: delete some unneeded code and files 2025-04-03 09:08:27 -04:00
6cd294373c
feat: add abbreviations (#340) 2025-04-03 08:45:02 -04:00
02c89b99dd
refactor: decouple sh use in core exec code (#337) 2025-04-03 00:38:35 -04:00
fe4e972fbe
chore: update version info 2025-04-03 00:37:17 -04:00
e4a9e06d2a
chore: merge (again) 2025-04-02 11:12:13 -04:00
487b5fa4f8
ci: checkout with submodules 2025-04-02 11:12:09 -04:00
sammy-ette
946e8e7228 docs: [ci] generate new docs 2025-04-02 15:09:45 +00:00
04206b6a14
docs: upload docs 2025-04-02 11:09:18 -04:00
9ea2a2f332
chore: merge 2025-04-02 11:08:54 -04:00
sammy-ette
364cb1ca2e
fix: add . to dataDir as fallback 2025-04-02 11:08:41 -04:00
sammy-ette
2ba878713c docs: [ci] generate new docs 2025-04-02 14:55:27 +00:00
2678ec723e
fix: push docs 2025-04-02 10:55:11 -04:00
dbf2d80863
fix: remove unused vars for other targets 2025-04-02 10:51:53 -04:00
fab98bc613
feat: search XDG_DATA_DIRS for hilbish files 2025-04-02 10:49:25 -04:00
sammy-ette
7b16cde540 docs: [ci] generate new docs 2025-04-02 13:42:07 +00:00
4150001d8b
fix: make lua implemented hilbish interfaces documented (#335)
* fix: make lua implemented hilbish interfaces documented

* fix: signature link in table of contents

* fix: reduce function list to match in go generated docs

* fix: toc appending

* docs: enable docs for hilbish.messages

* feat: add description gen, and more spacing between param listing

* docs: add more detailed documentation for lua modules

* docs: update hilbish.messages docs

* fix: add description for lua doc'd modules, remove duplicate docs

* docs: add back hilbish.jobs doc

* feat: generate toc for lua modules

* fix: add table heading

* ci: add lua docgen

* docs: put dirs.old doc on 1 line
2025-04-02 09:41:37 -04:00
32ed0d2348
docs: add a bit of extra info in the getting started doc 2025-03-14 18:45:56 -04:00
8731b1a7d1
chore: revert "chore: revert "chore: add 2.4 motd (work in progress)""
revertception
This reverts commit 7fc3f4a569405c86675978341a0c008069b994b9.
2024-12-29 21:44:05 -04:00
4743222044
chore: forward master in sync to v2.3.4 2024-12-28 19:58:00 -04:00
14a600f922
chore: bump version related things 2024-12-28 19:56:17 -04:00
13e6d180f8
fix: use global env variables when executing 2024-12-28 19:53:26 -04:00
CelestialCrafter
836f941e16
fix: handle completion info check error (#330)
* fix: handle completion info check error
fixes Rosettea/Hilbish#329

* make changelog more descriptive
2024-12-28 19:53:19 -04:00
a02cd1d7ef
fix: use global env variables when executing 2024-12-28 19:50:06 -04:00
c969f5ed15
feat: complete hint text on right arrow (#328) 2024-12-22 12:09:57 -04:00
CelestialCrafter
36ce05e85a
fix: handle completion info check error (#330)
* fix: handle completion info check error
fixes Rosettea/Hilbish#329

* make changelog more descriptive
2024-11-22 20:20:43 -04:00
ac7c97442e
chore: bump for bugfix release 2024-11-04 06:54:09 -04:00
7fc3f4a569
chore: revert "chore: add 2.4 motd (work in progress)"
This reverts commit e6b88816fdb3a827ac09b1f7f2f2be178b3ca421.
2024-11-04 06:51:31 -04:00
dbb45a1947
chore: revert "chore: bump to 2.4"
This reverts commit db851cf4f833de11dc72fc20821919ff45028391.
2024-11-04 06:51:20 -04:00
3da150bb64
chore: merge 2024-11-03 23:24:32 -04:00
46968e632b
fix: bump golua (closes #326) 2024-11-03 23:24:18 -04:00
ShalokShalom
1e01580d8f
docs: add info about runner mode (#325) 2024-08-31 18:05:24 -04:00
edbc758c67
docs: use only 1 screenshot 2024-08-31 16:50:58 -04:00
TorchedSammy
824f5bd06d docs: [ci] generate new docs 2024-08-16 19:26:30 +00:00
a7ba2fdf1a
fix: add newline at the end of input if in an unfinished heredoc (#322)
and define (or fix) the behavior of input ending with a slash
it will now add a newline at the end of input always
2024-08-16 15:26:10 -04:00
e6b88816fd
chore: add 2.4 motd (work in progress) 2024-08-16 15:25:35 -04:00
db851cf4f8
chore: bump to 2.4 2024-08-16 15:23:55 -04:00
fc6a9a33e1
chore: update dependencies (fixes #318) 2024-08-15 12:38:35 -04:00
0582fbd30c
chore: prepare v2.3.2 2024-07-30 19:26:35 -04:00
137efe5c62
fix: motd typo 2024-07-30 19:24:57 -04:00
72324c27de
fix: command path searching 2024-07-30 17:57:59 -04:00
ea233facc8
fix: get absolute path in fs.cd function 2024-07-27 14:28:09 -04:00
19feda919e
chore: update changelog 2024-07-27 14:27:54 -04:00
e4df61f020
fix(nature/tips): cleanup tips display 2024-07-27 14:19:53 -04:00
54b85b1c99
fix: add 2.3 motd 2024-07-27 14:10:21 -04:00
ddf5117fd9
chore: bump version 2024-07-26 18:08:43 -04:00
5b46158008
fix(commands/cd): use absolute paths to cd 2024-07-26 18:08:26 -04:00
a41a5504f4
fix(nature/tips): opt typo 2024-07-26 18:07:55 -04:00
Nathan J Helmig
35a8d0eaa4
feat: adds some friendly tips (#315)
Co-authored-by: Nathan Helmig <nathanhelmig@pop-os.attlocal.net>
2024-07-21 19:02:46 -04:00
8a1614ab59
ci: use wildcard for refs on branch name 2024-07-20 10:24:56 -04:00
cc43cb2d6e
fix: make website build on tag pushes 2024-07-20 10:19:22 -04:00
1ba0dd183c
blog: add v2.3 release blog 2024-07-20 10:14:16 -04:00
44d63a398a
chore: update changelog 2024-07-20 10:03:36 -04:00
92448eec67
ci: add workflow dispatch to website 2024-07-20 09:57:51 -04:00
4e882b376b
chore: update version info 2024-07-20 09:36:42 -04:00
5f8d942f0a
fix: reuse shell runner instance (#312) 2024-07-20 09:31:57 -04:00
41e5e3f789
feat: commanders can exit via ctrl c (#313) 2024-07-19 18:46:46 -04:00
826b0789cb
docs: promote midnight edition on main readme 2024-07-19 17:43:49 -04:00
bfa3b55542
chore: merge 2024-07-19 09:51:12 -04:00
f7e66bb957
docs: bump version requirement 2024-07-19 09:48:40 -04:00
d7ab887234
feat: allow builds for unix (#311) 2024-07-19 09:48:01 -04:00
youkwhd
b24fc4a422
fix: check if no command passed to exec (#310)
* fix: check if no command passed to exec

* docs: add exec fixes

* chore: remove extra space
2024-07-10 10:04:15 -04:00
0e4b95d9b9
fix: make -S flag set absolute path to hilbish 2024-06-25 16:48:32 -04:00
38d036d96f
fix: history navigation going out of bounds 2024-06-14 08:23:20 -04:00
4c61c551aa
fix: menu refreshes
now there's no flicker *and* its not bugged with
leaving the text on exit
2024-05-13 22:10:28 -04:00
ff6e08902f
fix(greenhouse): reset at end and beginning of line to fix colors leaking to other lines 2024-05-03 19:06:17 -04:00
bbd5637e9b
ci: update all actions (#302) 2024-05-03 12:47:24 -04:00
TorchedSammy
d46c079afb docs: [ci] generate new docs 2024-04-28 01:29:33 +00:00
42ab856e45
feat(commander): add function to return all commanders (closes #266) 2024-04-27 21:29:06 -04:00
TorchedSammy
478e3020b1 docs: [ci] generate new docs 2024-04-28 01:04:12 +00:00
a20123fc24
feat: allow hilbish.run to take a table of files to use for output (#291) 2024-04-27 21:03:54 -04:00
fb9d30520a
fix(greenhouse): draws/updates after exit by resize 2024-04-27 13:52:07 -04:00
521298733e
chore: update changelog 2024-04-27 10:52:00 -04:00
f8a391e24f
chore: bump version 2024-04-27 10:49:26 -04:00
James Dugan
aa376f9b14
feat: cat implementation now uses chunk reading (#290) 2024-04-20 19:04:24 -04:00
16b39fe157
fix: call highlighter and hinter from global table (closes #289) 2024-04-19 07:54:46 -04:00
40c3cecabb
chore: merge branch 2024-04-16 12:09:18 -04:00
ce99209f0d
chore: update version info 2024-04-16 12:09:14 -04:00
d1dbb84c16
fix(readline): flickering on line refresh (#288) 2024-04-16 11:56:57 -04:00
5b84718021
chore: merge 2024-04-16 10:43:07 -04:00
3d727e6411
fix: check for altHistory in sequence handling
fixes a panic
2024-04-16 10:34:24 -04:00
7d487bfc98
refactor: remove metatables protecting hilbish api and opts (#287) 2024-04-11 18:16:45 -04:00
11fc1edd94
fix: only halt in error clause 2024-04-06 18:52:55 -04:00
b416264138
fix: tty checks (#284) 2024-04-06 18:37:16 -04:00
11323a70aa
feat: add page keys to greenhouse 2023-12-30 16:16:59 -04:00
db32fd7a87
chore: remove unused label 2023-12-26 12:53:19 -04:00
017702ea0d
fix(greenhouse): remove goro usage 2023-12-26 12:52:39 -04:00
30830ed6ed
chore: prepare v2.2.1 2023-12-26 12:33:57 -04:00
7932fa677f
fix(hilbish.goro): attempt to recover panic 2023-12-26 12:32:32 -04:00
c1b78a8ea7
fix: remove debug print 2023-12-26 10:13:35 -04:00
3128ef7934
feat: merry christmas! 2023-12-26 00:18:30 -04:00
c3394f7046
ci: update go release action 2023-12-26 00:18:27 -04:00
b1f957e98f
website: add 2.2 release blog 2023-12-26 00:13:50 -04:00
f788c9374c
website: fix up home page contents 2023-12-26 00:13:35 -04:00
b7602b0bbe
chore: update changelog 2023-12-25 23:29:53 -04:00
7b84faabf9
chore: merge from upstream 2023-12-25 23:09:31 -04:00
8fdae6c1d7
refactor: doc improvements (again) (#260) 2023-12-25 22:08:29 -05:00
190ed5b2dc
chore: update motd for 2.2 2023-12-24 19:04:08 -04:00
9d5f5abef4
feat: add pprof 2023-12-18 21:31:04 -04:00
a0513c0a05
chore: merge 2023-12-06 22:21:11 -04:00
1d64a57e24
fix: return if runner did not return table 2023-12-06 22:20:41 -04:00
TorchedSammy
1a4585aa7a docs: [ci] generate new docs 2023-12-02 15:17:32 +00:00
60fd4c3b4c
fix: correction to completion documentation
i added an s even though there's no s.
to account for others making the same mistake, i added both.
hilbish.completion and hilbish.completions will work, but
hilbish.completion without s will be removed at a major update.
2023-12-02 11:11:28 -04:00
29e14c1aee
feat: native modules (#257) 2023-11-11 19:39:31 -05:00
Super
ee1ed077b9
fix: infinite loop when navigating history without any history (#268)
fixes #252
2023-11-02 17:50:36 -04:00
78eb657897
feat: hilbish native pager (#240) 2023-10-25 00:41:53 -04:00
a5b6fc8eda
fix: return cmdstr in alias resolve instead of nothing 2023-09-30 23:25:15 -04:00
4421869b85
fix: check length of args in aliases resolve
this shouldnt be a problem.. but ... what
2023-09-30 23:21:00 -04:00
6d07d8db53
chore: merge from upstream 2023-09-30 19:53:38 -04:00
483e5f6dbe
fix(hilbish.completions): return prefix on the call function (from #263) 2023-09-30 19:52:33 -04:00
83492e4e69
docs: fix odd sentence in runner-mode docs 2023-09-27 20:31:27 -04:00
4fcd310048
chore: merge from upstream 2023-09-09 13:53:22 -04:00
db8e87e5dd
fix: compare lower case strings in contains function
this fixes file completion on windows.
2023-09-09 13:53:09 -04:00
ba04fb2af7
feat: allow numbered substitutions in aliases (#258) 2023-09-09 13:51:58 -04:00
caff604d95
ci: stop using deprecated method of setting branch name 2023-07-10 22:42:04 -04:00
2b9059f726
ci: add missing quote 2023-07-10 22:38:22 -04:00
00c967d7c1
ci: fix branch name 2023-07-10 22:38:13 -04:00
TorchedSammy
ab26b82a9f docs: [ci] generate new docs 2023-07-11 01:57:00 +00:00
f540fc2c04
feat: show go version hilbish was compiled with 2023-07-10 21:56:35 -04:00
c6c81ddece
feat: add notification/message interface (#239)
details in #219
2023-07-10 19:03:30 -04:00
3eae0f07be
feat: add fuzzy searching for completion and history search (#247)
* feat: add fuzzy searching for completion and history search

* feat: add fuzzy opt for fuzzy history searching

* chore: add fuzzy opt to changelog
2023-07-10 00:06:29 -04:00
cbc5e81c9d
feat: show indexes on cdr list and change home to tilde (#253)
* feat: show indexes on cdr list and change home to tilde

* fix: remove underline in cdr help page
2023-07-09 18:43:21 -04:00
TorchedSammy
6729ecddea docs: [ci] generate new docs 2023-04-15 14:36:56 +00:00
485306fbe2
docs: clarify use of highlighter function 2023-04-15 10:36:21 -04:00
480d4de750
ci: set baseurl properly 2023-04-14 01:25:14 -04:00
d7dde44a0c
ci: (attempt to) fix base url on non-master versions 2023-04-14 01:23:24 -04:00
237b306eb8
ci: fix branch name var 2023-04-14 00:52:45 -04:00
bd01b478d5
website: add more info for runner mode 2023-04-14 00:40:41 -04:00
a37f8e3b30
ci: output website builds from other branches to different dirs 2023-04-14 00:40:13 -04:00
9c6d6c4f31
website: fix wording on features main page 2023-04-14 00:24:19 -04:00
2dbd201e1e
refactor: website/branding cleanup (#250)
* website: add padding to home page

* docs: slight touch ups to readme

* website: reword/reformat content on home and getting started page

* website: fix docs page layout

- the sidenav for doc pages looks the same as the navbar.
- it will be hidden by default on mobile.
- sidenav looks like the navbar on mobile and is more
seamless in general

* docs: update description, logo, dont center badges

* docs: fix badges

* website: fix padding

* website: add borders, add margins for sidenav

* website: update description on homepage

* website: add margins for blog list

* chore: use new logo

* docs: use logo and text combined for readme

* docs: make logo bigger

* website: use combined logo and text asset

* docs: remove hilbish-text asset

* website: fix navbar expand button

* website: add more padding on doc pages

* website(blog): add post about website improvements

* website(blog): add post about website improvements

* website: add more detail on the install page

* website: add screenshots section

* docs: fix up screenshots section

* docs: remove toc and image alignment
2023-04-14 00:04:52 -04:00
3dd834fcdf
fix: merge patch releases with master (#248)
my absolutely terrible april fools release was made on a separate branch. this pr merges the fixes on master so history can be synced up. (and mainly to get the 2.1.2 blog post)
2023-04-10 12:38:30 -04:00
659d1e0c4e
website(blog): add v2.1.1 release blog 2023-04-01 18:16:13 -04:00
TorchedSammy
0379e302ac docs: [ci] generate new docs 2023-03-25 21:42:46 +00:00
d577b3c958
feat: sink enhancements (#241)
* feat: add read method to sinks

* feat: add manual flush method for sinks

* fix: add flush as sink method and fix arg amount for read

* feat: add pipe property to sinks to see if stdin sink is a pipe

* feat: add method autoFlush to toggle/change automatic flushing

* chore: update changelog
2023-03-25 17:42:25 -04:00
3d0fffd49a
chore: merge from upstream 2023-02-19 15:12:34 -04:00
013fa30658
fix: correct job management commands to call with colon 2023-02-19 15:11:55 -04:00
crumb
4e37e8ca47
fix: replace sed with vgrep (#238) 2023-02-18 20:02:52 -04:00
26c8f28034
chore: bump version to 2.2 2023-02-18 12:30:15 -04:00
6be65c04a6
website(blog/v2.1): link to release in blog 2023-02-10 17:11:44 -04:00
7bfd7b12c4
fix(commands/doc): only highlight real headings 2023-02-10 17:03:03 -04:00
d48a66e393
docs: update changelog 2023-02-10 16:59:44 -04:00
d873f04f70
website(blog): add v2.1 release blog 2023-02-09 17:16:12 -04:00
7961a441ad
chore: update release name 2023-02-07 18:27:33 -04:00
TorchedSammy
c55cd345ba docs: [ci] generate new docs 2023-02-07 22:19:24 +00:00
9e1ec1641c
docs: fix return types for functions (closes #229) 2023-02-07 18:18:03 -04:00
2911257eb9
docs: cleanup completions doc to better fit 80 col terminals 2023-02-07 17:42:16 -04:00
f2ee600c28
fix: check for 0 length slice when splitting input for completions 2023-02-07 15:49:11 -04:00
61914f8dc7
docs: add docs for sink type (closes #233) 2023-02-07 15:39:22 -04:00
6dbb39d404
chore: change motd for 2.1 (closes #237) 2023-02-07 10:46:47 -04:00
890f10e176
docs: update runner-mode doc (closes #230) 2023-02-07 10:46:29 -04:00
6b27d14f45
fix: check for error on resolving symlink 2023-02-07 10:42:36 -04:00
efc69ab769
fix: resolve symlinks for completions
1k commits milestone!! 🎉
2023-02-06 17:54:27 -04:00
cdd07a4981
fix(commands/doc): run stat in pcall 2023-02-05 13:02:50 -04:00
e2cf417144
fix: initialize lua api before handling signals (fixes #236) 2023-02-01 19:56:27 -04:00
f97a04179d
chore: update license 2023-01-20 19:35:33 -04:00
2f6ab5fd92
feat: add sink for commanders to write output/read input (#232)
to write output, you would usually just use the print builtin
since commanders are just lua custom commands but this does not
consider the fact of pipes or other shell operators being used
to redirect or whatever.

this adds readable/writable "sinks" which is a type for input
or output and is currently only used for commanders but can be
used for other hilbish things in the future
2023-01-20 19:07:42 -04:00
088e326bd1
fix(commands/doc): properly block out index doc 2023-01-20 18:43:46 -04:00
TorchedSammy
c87fbe2b99 docs: [ci] generate new docs 2023-01-18 10:59:10 +00:00
5bb6ba4aee
docs: mark job.stop function as member 2023-01-18 06:58:47 -04:00
8d20ad9eed
fix: make hilbish.which work properly with aliases 2023-01-18 06:52:22 -04:00
71d23a4727
chore: remove hugo lock 2023-01-18 06:40:58 -04:00
6530d48b00
docs: document types properly (#227) 2023-01-18 06:39:26 -04:00
d99e056a76
feat: add function to get current runner name 2023-01-17 22:04:54 -04:00
109b5785af
chore: bump version to 2.1 2023-01-07 14:59:55 -04:00
a6bcfdfca9
feat(commands/doc): return 1 exit code when doc not found 2023-01-07 14:02:21 -04:00
4e023703b6
feat(commands/doc): use local docs directory if hilbish branch is found 2023-01-07 14:01:57 -04:00
5814462f5d
chore: merge from upstream 2023-01-07 13:56:02 -04:00
354f257c03
feat(commands/doc): make it easier to get interface docs 2023-01-07 13:54:08 -04:00
TorchedSammy
a2f0ff3e09 docs: [ci] generate new docs 2023-01-07 15:52:49 +00:00
07a7a75b46
docs: fix return type for hilbish.aliases.list 2023-01-07 11:52:05 -04:00
887260cd8a
fix: print error on event error and dont release hook (closes #226) 2023-01-07 07:39:36 -04:00
ef5363cb1f
website: dont set install as draft 2022-12-31 20:01:10 -04:00
246fc4d7ee
website: add blog 2022-12-28 22:27:05 -04:00
91ec0cf4a4
docs: remove api index (there is already _index) 2022-12-28 22:26:20 -04:00
2a80795331
chore: update version 2022-12-28 22:23:47 -04:00
72d6b0a4a0
chore: add 2.0.1 tag to changelog 2022-12-28 20:53:38 -04:00
4eea793e69
chore: upload gallery image 2022-12-28 20:24:59 -04:00
b3410e85bc
docs: reorder screenshots, add showcase of history search menu 2022-12-28 20:21:11 -04:00
c12cb82fb5
docs: clean up install section on readme 2022-12-28 20:18:30 -04:00
TorchedSammy
68a37d8c79 docs: [ci] generate new docs 2022-12-28 23:33:44 +00:00
f107d1df71
docs: put all code in codeblock for timers example 2022-12-28 19:33:20 -04:00
61f6337f5f
docs: improve docs for timers interface 2022-12-28 19:32:52 -04:00
0f33f72de7
docs: fix docs for outdated hook 2022-12-28 19:28:16 -04:00
c2db9e65fa
fix(commands/cd): set oldpwd when cd-ing with no args (fixes #225) 2022-12-28 19:18:04 -04:00
97188e73a5
ci: revert using task and set ldflags 2022-12-20 22:14:04 -04:00
3cedff273a
ci: fix build command for release action 2022-12-20 22:05:24 -04:00
TorchedSammy
a1ce4389e8 docs: [ci] generate new docs 2022-12-21 01:03:09 +00:00
35e2a54172
docs: add emmy lua annotation for id in jobs.disown 2022-12-20 21:02:36 -04:00
TorchedSammy
7234111d6d docs: [ci] generate new docs 2022-12-21 01:00:31 +00:00
a105b8e38d
docs: improve emmy lua annotations 2022-12-20 20:59:55 -04:00
5dc3b7d337
feat: add constants to hilbish.timers for timeout and interval times types 2022-12-20 20:55:56 -04:00
d5dffabcb2
website(docs/intoduction): change text of introduction 2022-12-20 19:42:44 -04:00
5ea23d58d1
docs: change api index doc 2022-12-20 10:09:08 -04:00
1a2d29aee7
fix: list subdocs for hilbish module 2022-12-20 01:42:58 -04:00
b46bd0059e
fix: fixes for doc command
- get docs properly for hilbish module and its interfaces
- deal with negative numbers causing yaml metadata parsing to fail
- change from index to _index to match hugo
2022-12-20 01:38:19 -04:00
78c95de784
refactor: remove doc prop related code
should very very slightly improve startup. it's dead, obsolete,
and unused code now anyways with the docs refactor
2022-12-20 00:54:05 -04:00
e4d87afab3
website(faq): correct entry about api docs 2022-12-20 00:41:48 -04:00
70594f4db2
website: remove auto collapse from doc navigation 2022-12-20 00:39:34 -04:00
f661db158b
chore: add missing entries to changelog 2022-12-20 00:27:47 -04:00
787d6c082f
chore: prepare for v2.0 2022-12-19 23:46:45 -04:00
ad94be925c
chore: add rpm spec file (package for copr/fedora) (#220) 2022-12-19 23:19:48 -04:00
fc82d4f5eb
website: add doc navigation to navbar for collapsing 2022-12-19 00:03:13 -04:00
e5eefb1d2d
refactor!: rework docs and doc command (#218)
changes the actual file format of docs to markup since that's basically what we have been
using in the first place.

the docgen command has been modified to write markdown headings with the function name and
yaml metadata for easy consumption by hugo for the website.

all other docs have been moved to markdown as well this is the main reason this is a "breaking" change
users will have to reinstall hilbish (task uninstall and task install) to remove the old plaintext docs
2022-12-15 00:00:54 -04:00
6525fa774e
ci: fix indents 2022-12-14 21:32:21 -04:00
514cbe25c7
ci: set fetch-depth to 0 and checkout action to v3 2022-12-14 21:31:11 -04:00
84dd939bbf
ci: replace website build branch with docs-refactor for website 2022-12-14 21:30:47 -04:00
f94b8ae59b
chore: update golua for popen (#172)
* chore: update golua to popen branch

* chore: fix go sum

* chore: update golua with popen branch
2022-12-13 15:37:01 -04:00
7b3dc951c9
docs: add website (#176) 2022-12-13 15:14:48 -04:00
0a49e1a4ef
feat: print command errors via hook
this allows users to remove the handlers and print
a custom message to their liking
2022-12-13 12:57:27 -04:00
TorchedSammy
6ca36847f1
docs: add bolded notes/changes for building and installing hilbish 2.0 2022-12-12 21:04:04 -04:00
TorchedSammy
5ca728ba06
docs: change task link and notice 2022-12-12 21:03:36 -04:00
813354b662
build!: set datadir of hilbish and change default prefix to /usr/local (#221)
BREAKING (ish) CHANGE: Hilbish will by default install to `/usr/local`. To revert this, set `PREFIX="/usr/"`
2022-12-12 21:01:44 -04:00
TorchedSammy
8d40179a73
fix(readline): dont do anything if length of input rune slice is 0
this fixes an issue when readline splits multiline input.
sometimes, the multiple lines just end up being "stray?"
inputs of enter plus a newline. this can happen if a user attempts
to prefire the enter key while a command is running, for example
2022-12-10 17:27:42 -04:00
TorchedSammy
f7e725b5b9
docs: make note on task 2022-12-09 21:49:58 -04:00
4ee160fb66
fix: provide correct command when navigating history (#214)
fixes an issue of going up and down in history results in the incorrect order of commands being inserted (nothing happens to the order in the history itself, just when navigating via arrow keys)

* fix: provide correct command when navigating history

previously, the order while navigating history
with the arrow keys would be incorrect
meaning the command you expect if you go u
then go back down would not be there

* chore: update changelog
2022-12-09 21:45:52 -04:00
TorchedSammy
1024f93446
chore: update changelog 2022-12-06 12:54:56 -04:00
TorchedSammy
9c8d7692bc
chore: revert "build: apply hilbish datadir to allow changing install path"
This reverts commit 9131c7250128fb8c74316cf8e3f95e30132cf711.
temporary revert, will have to apply datadir eventually
2022-12-06 10:29:47 -04:00
TorchedSammy
9131c72501
build: apply hilbish datadir to allow changing install path 2022-12-05 23:38:52 -04:00
TorchedSammy
26ff6c9a46
fix(nature/completions): get command name properly for custom completions 2022-12-05 23:15:35 -04:00
TorchedSammy
604dedb36d
chore: update lunacolors 2022-12-05 14:16:43 -04:00
TorchedSammy
395f3c0742
ci: remove extra indent in release action 2022-12-02 09:42:06 -04:00
TorchedSammy
0c44531a7f
chore: merge from upstream 2022-12-02 09:39:48 -04:00
TorchedSammy
4e850bb322
ci: set build version to 1.18, use task for release builds 2022-12-02 09:39:22 -04:00
TorchedSammy
09d04a7850 docs: [ci] generate new docs 2022-12-02 00:05:24 +00:00
TorchedSammy
4df37b4341
chore: merge from upstream 2022-12-01 20:04:55 -04:00
TorchedSammy
5e2b3367de
docs(bait): add annotation strings for release and hooks functions 2022-12-01 20:04:24 -04:00
Daniel de Sá
b6aecb12f6
chore: add .editorconfig file (#217) 2022-12-01 09:29:27 -04:00
TorchedSammy
3f9b230381
chore: update changelog 2022-11-30 14:29:46 -04:00
TorchedSammy
b395b70ecd
fix: escape completion prefix if completions are escaped
fixes an issue with duplicated characters when
completing escaped paths
2022-11-30 14:26:43 -04:00
TorchedSammy
06102ebdae
perf: preallocate history slice 2022-11-30 13:20:00 -04:00
TorchedSammy
bd4e0df7b3
feat: select 1st item on history find menu (closes #148)
cancels on escape unless the user moves to another item
2022-11-25 20:14:29 -04:00
TorchedSammy
ebec585690
fix: binary completion with spaces (closes #210) 2022-11-25 19:35:26 -04:00
TorchedSammy
ff4609e432
feat: add hilbish.cancel hook (closes #213) 2022-11-25 19:21:36 -04:00
TorchedSammy
ef3e7d92bc
chore: update changelog 2022-11-25 19:13:32 -04:00
TorchedSammy
d6338fc021
fix(readline): make completion search menu display 2022-11-25 19:08:38 -04:00
TorchedSammy
3eaeb6a5da
fix(readline): grip completion menu fixes
- dont print item left justified if the max number
of cells is 1 (this fixes issues in cjk as an example)
- trim items that are longer than the terminal width
2022-11-25 18:39:18 -04:00
TorchedSammy
8b547f2af0
feat: make tab completion work with spaces and escaped characters 2022-11-25 16:56:35 -04:00
TorchedSammy
1febe66f84
fix(readline): use uniseg to calculate width of virtual tab entry (closes #209) 2022-11-17 19:18:57 -04:00
TorchedSammy
6ffcc498ac
docs: update changelog for rc 2022-10-14 19:25:18 -04:00
TorchedSammy
fe47c6c7a1
chore: change version to rc1 2022-10-14 19:16:24 -04:00
sammy
0d32a10ca3
feat: add builtins clear, exec and cat (#208)
* feat: add clear and exec command

* docs: add builtins to changelog

* feat: add cat command
2022-10-14 19:15:40 -04:00
TorchedSammy
cc6e5d01dd docs: [ci] generate new docs 2022-10-11 21:43:22 +00:00
TorchedSammy
068a5b5149
feat(bait): add error hook and hooks function (closes #205)
an `error` hook is now thrown when an event in lua
throws an error (errors from go side should not happen)
it includes the event name, handler, and error message

a hooks function has also been added. it returns a table
of handlers for a specific event.
2022-10-11 17:41:13 -04:00
TorchedSammy
117a4580b4
chore: merge from upstream master 2022-10-10 18:55:28 -04:00
TorchedSammy
0db7f96fd7
build: disable cgo in builds 2022-10-10 18:55:03 -04:00
TorchedSammy
300248de54 docs: [ci] generate new docs 2022-10-10 22:41:10 +00:00
TorchedSammy
3ee2b03330
feat: make prompt optional in hilbish.read 2022-10-10 18:40:29 -04:00
TorchedSammy
3bec2c91a8
fix: create an empty line reader instance for hilbish.read (closes #190) 2022-10-10 18:26:54 -04:00
TorchedSammy
b4ca5bfda3
fix(readline): put cursor at end of text when exiting editor 2022-10-10 18:19:24 -04:00
TorchedSammy
308e257872
fix(readline): take into account newlines when calculating amount of lines taken up by input
this does not really fix the issue of multiline input
being broken completely, but prevents the prompt
being reprinted on input
2022-10-10 18:17:58 -04:00
TorchedSammy
7db2a2c826
fix: check if there is cmd input before attempting to add to history (closes #206) 2022-10-10 18:11:09 -04:00
TorchedSammy
22f6ea8a3e
docs: remove getting started from readme toc 2022-10-10 17:34:08 -04:00
TorchedSammy
91596fa81c
docs: document drop in windows support 2022-10-10 17:33:36 -04:00
TorchedSammy
e5c8e5eaff
fix!: pass non expanded input to builtin runners
fixes an issue with expanded aliases being added
to history with a recent commit (6th time now with
this issue?) and makes behavior with other runners
consistent

this can technically be a breaking change to people
overriding the sh runner function
2022-09-17 21:00:28 -04:00
TorchedSammy
8647dc57a1
fix: set cmdString after prompting for continue input
makes sure that the old + new input is actually used for
builtin runners
2022-09-17 20:31:19 -04:00
TorchedSammy
8f41005da7
chore: update changelog 2022-09-17 20:24:31 -04:00
TorchedSammy
7108523a4c
fix: remove logging of autostart modules 2022-09-17 14:08:15 -04:00
TorchedSammy
ee34ccdbc3
fix: check if key in _G is string before trying to getenv 2022-09-17 10:48:34 -04:00
TorchedSammy
959030f70d
refactor: automatically load all nature commands 2022-09-02 23:01:39 -04:00
TorchedSammy
59cec0ffa5
fix: call hinter for hint text handler 2022-09-02 22:19:30 -04:00
TorchedSammy
1eed4cc7ee
fix: add back empty string in command line split
this fixes file completion in normal usage without
using quotes. it basically cut out the space at the
end which prevented normal usage without adding an
additional space or using quotes for file
completion
2022-08-30 23:38:46 -04:00
TorchedSammy
c13889592f
fix: pass alias expanded string to sh runner (fixes #201)
i have no idea why it didnt before, it *shouldnt*
introduce any problems and fixes this one.
2022-08-30 23:10:47 -04:00
TorchedSammy
2e192be2e1
refactor: setup autocd opt in a better way
with the previous commit allowing users to override
hilbish.runner.sh and it being ran by hilbish, the
code for the autocd opt can just override that
function and do the autocd functionality instead
of reimplementing a hybrid runner.

this means that if any other custom runner wants
autocd functionality they can have it with the sh runner
2022-08-30 23:08:22 -04:00
TorchedSammy
c96605e79c
feat: allow hilbish.runner.sh to be overridden 2022-08-30 23:07:24 -04:00
TorchedSammy
a1ce2ecba6
fix(readline): correct function to count len of prompt to accomodate east asian characters 2022-08-30 22:37:21 -04:00
TorchedSammy
a1410ae7ad
fix: set prompt to normal after ctrl d exit
this prevents the prompt being stuck at the multiline
prompt instead of normal prompt after exiting
via the ctrl d bind
2022-08-30 21:52:07 -04:00
TorchedSammy
20870b9004
fix: only print motd when interactive 2022-08-17 18:05:20 -04:00
TorchedSammy
3dcd99563a docs: [ci] generate new docs 2022-08-17 22:01:55 +00:00
sammy
2337f9ab60
refactor: use custom event emitter (#193)
* refactor: use custom event emitter

* fix: sigint hook emit on windows

* fix: restore correct hilbish conf file

* fix: call recoverer for go listeners

* refactor(golibs/bait): use 1 map for listeners

* feat: add once listeners, ability to remove listeners and remove listener on error

* perf: reslice listener slice instead of trying to do ordered move with append

* feat(bait): add release function to remove event listener

* perf: remove listener directly from once emit instead of using off function

* refactor: use bait event emitter on commander

* docs(golibs/bait): add doc strings for functions

* docs: set changelog

* docs(golibs/bait): add docs for lua release function
2022-08-17 18:01:32 -04:00
TorchedSammy
6ce4fb3973
fix: add dot to sample config path on windows 2022-08-16 12:30:39 -04:00
TorchedSammy
387d7d2243
fix: percentages in completion entries causing a problem in the completion menus 2022-07-26 19:24:02 -04:00
TorchedSammy
7de835fab4
chore: update lunacolors (adds blackBg format arg) 2022-07-26 10:41:12 -04:00
TorchedSammy
3e0a2d630b
feat(hilbish.editor): add getLine function to get contents of line 2022-07-19 17:55:03 -04:00
TorchedSammy
09a8b41063
chore!: remove guide command (closes #188) 2022-07-13 16:04:57 -04:00
sammy
349380ae6b
feat: lua backed history (#187)
* refactor: put file history handler in line reader instance instead of global

* feat: add lua history handler in go

* feat: use lua to retrieve readline history

* refactor: handle history in lua

this also introduces a new opt: history
if it is false, command history won't get added

* fix: remove nature.history require

* docs: add changes in changelog

* fix: add comma after history opt
2022-07-13 16:02:09 -04:00
TorchedSammy
f7806f5479 docs: [ci] generate new docs 2022-07-13 19:46:40 +00:00
TorchedSammy
c8c30e9861
docs: update changelog 2022-07-13 15:46:18 -04:00
TorchedSammy
083c266438
feat(golibs/fs): add join function to join path elements 2022-07-13 15:38:07 -04:00
TorchedSammy
dd9bdca5e0
fix(readline): only call raw input callback if not nil 2022-07-13 15:35:33 -04:00
TorchedSammy
9902560061
fix: set vt in on stdin 2022-07-13 15:11:06 -04:00
TorchedSammy
dd9aa4b6ea
fix: enable vt input for windows 2022-07-13 15:04:18 -04:00
TorchedSammy
be8bdef9c8
style: use single line import instead of list syntax 2022-07-13 14:18:23 -04:00
TorchedSammy
e185a32685
fix: expand tilde in dataDir on windows 2022-07-13 14:10:29 -04:00
TorchedSammy
2b480e50e6
feat: print tracebacks for errors 2022-07-13 10:08:23 -04:00
TorchedSammy
b65acca903
fix: initialize line reader before lua init 2022-07-10 22:07:01 -04:00
TorchedSammy
08e2951513
feat: add raw input hook (closes #180) 2022-07-10 20:34:00 -04:00
TorchedSammy
83a2ce38ea
docs: remove getting started section on readme 2022-07-09 18:39:21 -04:00
TorchedSammy
60dd5f598a
docs: replace make with task on readme 2022-07-09 18:38:57 -04:00
TorchedSammy
6eea5bce47
feat: add motd (closes #185) 2022-07-09 17:54:21 -04:00
TorchedSammy
a106f4aea0
refactor!: move hilbish.greeting to an opt (closes #184) 2022-07-09 17:15:13 -04:00
TorchedSammy
90ed12d551
feat: add hilbish.init hook (closes #186) 2022-07-09 17:04:50 -04:00
sammy
e0694c8862
build!: replace make with task (#171)
* build!: replace make with task

allows easy windows building (besides literally go build)
down the line because getting make on windows is dumb
and even if you do it probably wouldnt work as intended
on there

(i also find task more intuitive for simple things)

* ci: use task in build workflow instead of make

* style: remove whitespace errors in task file

* docs: add task in changelog

* docs: fix link to task

* docs: change message for task notice
2022-07-09 11:44:53 -04:00
TorchedSammy
d27ce26be0
feat: complete files plainly if tab query begins with quotes (workaround #183) 2022-07-09 10:45:42 -04:00
TorchedSammy
587d08773f
chore: merge from remote 2022-06-20 17:16:59 -04:00
TorchedSammy
362bb14d7e
feat: auto start lua modules (closes #167) 2022-06-20 17:07:15 -04:00
TorchedSammy
153a89b188 docs: [ci] generate new docs 2022-06-20 20:47:56 +00:00
TorchedSammy
453ba9f8ad
feat(fs): add some functions and properties (closes #168) 2022-06-20 16:47:16 -04:00
TorchedSammy
3e807f5235
fix: handle lua eval errors and normal runner errors separately 2022-06-20 15:47:19 -04:00
TorchedSammy
7e57b3de7d
fix: check if input is 0 on multiline splitting (closes #170) 2022-06-20 15:35:25 -04:00
sammyette
226605a996
feat: allow runners to specify if they want more input (#162)
* refactor!: make runners require returning a table

allows for more options for runners in the future,
and makes it so that you can avoid passing
certain args more easily.

* feat: allow runners to specify continue in return to prompt for more input

* docs: update changelog

* refactor: reorder returns of handleSh function

* refactor: move out reprompting and runner handling to functions

makes codefactor happy hopefully. this commit includes
a fix to check if after reprompt the user hits ctrl d
and just exits cleanly
2022-06-02 22:33:30 -04:00
TorchedSammy
1b4b41846f
chore: merge from remote branch 2022-05-31 15:17:50 -04:00
TorchedSammy
3196f0dcb9
fix: don't refetch tab completion on refresh if its already open (closes #163) 2022-05-31 15:16:32 -04:00
TorchedSammy
3f745e7e4d
docs: update contributing info to include writing changes to changelog 2022-05-30 18:16:36 -04:00
TorchedSammy
f9a2a981b4
fix: revert "fix: multiline cursor redraw"
This reverts commit 1339dc4a2f2e1ecfca4289f799631ab2cd337769.
this caused a few issues, including
history search messing up previous lines
what this commit was trying to fix is unimportant anyway
2022-05-29 19:02:20 -04:00
TorchedSammy
1339dc4a2f
fix: multiline cursor redraw 2022-05-28 21:05:03 -04:00
TorchedSammy
b4a5746093
ci: use make to build for artifacts 2022-05-28 20:21:57 -04:00
TorchedSammy
2faaf4e045
fix: print err don't panic and in the case of regex compile failing on menu find 2022-05-28 20:19:49 -04:00
sammyette
3990d370fa
feat: extend hilbish.runner interface to allow multiple runners (#159) 2022-05-28 19:06:18 -04:00
sammyette
b28a2c24c1
refactor!: use userdata where appropriate (#157)
any interface which has lua side objects that are from go side for its api (namely jobs) they will use userdata instead of always creating a table to represent the object. this might or might not bring lower ram usage since there is now only 1 single reference to an object instead of always creating a table to expose on lua

breaking change since methods need to be called with a colon instead of dot
2022-05-28 19:03:44 -04:00
TorchedSammy
e3c25586e4
fix: broken ansi escape codes on windows cmd 2022-05-28 09:07:28 -04:00
TorchedSammy
9d385efbfc
docs: add new methods for job objects 2022-05-24 19:32:03 -04:00
TorchedSammy
d99c24842f
docs: update changelog 2022-05-24 19:31:51 -04:00
TorchedSammy
61271dc70c
fix: load bg command on init 2022-05-24 19:26:35 -04:00
sammyette
8697344f98
feat: implement job foregrounding/backgrounding (#155) 2022-05-24 19:15:02 -04:00
TorchedSammy
d65b574cb2
docs: fix typo in job hook docs 2022-05-22 07:29:01 -04:00
TorchedSammy
d808534da6
perf: use waitgroup instead of loop to wait on timers 2022-05-21 21:58:58 -04:00
TorchedSammy
a4b358fd9c
perf: use struct{} for done channel in timer instead of bool 2022-05-21 21:39:14 -04:00
TorchedSammy
8f6f27e647
docs: add docs for lunacolors (closes #144) 2022-05-21 21:28:06 -04:00
TorchedSammy
f888aabc80
chore!: update lunacolors 2022-05-21 21:26:34 -04:00
TorchedSammy
2572d0ea9e
docs: update changelog with latest changes 2022-05-21 21:11:59 -04:00
sammyette
d2f16dfbbf
feat: job enhancements (#153)
* feat: add hilbish.job.add function

this is mainly to accomodate for the employer
handler (#152)

* feat!: add start function to jobs

the commit itself adds a few things but the
main purpose is to facilitate a lua side start
function that can restart the job

there is a breaking change in the hilbish.job.add
function; it is now required to provide an extra
table for arguments, since the first cmd
table isnt really what's actually ran

* fix: reuse standard files for jobs

* fix: deadlock in lua job add function and not taking proper amount of args

* fix: assign binary path to job

* feat: emit job.add hook when job is added

* chore: update modules

* fix: use setpgid on cmd procattr for background jobs

* fix: use right procattr on correct os

* fix: set bg proc attr in build tagged file

* feat: add disown function

* fix: stop jobs on exit

* feat: add disown command

* feat: add jobs.last function to get last job

* feat: make disown command get last job if id isnt suppied as arg

* chore: remove unused code

* feat: add job output

* chore: fix comments

* fix!: make exec path in job add explicit in lua side

* docs: add docs and changelogs relating to jobs
2022-05-21 20:53:36 -04:00
TorchedSammy
392cb66382
fix: handle sigterm and remove obsolete code 2022-05-21 20:53:02 -04:00
TorchedSammy
0b07b93de2
docs: move nature docs into a folder 2022-05-19 21:56:03 -04:00
TorchedSammy
8b6506b36c
refactor: move out home abbreviating code to a util function 2022-05-17 21:37:42 -04:00
TorchedSammy
ab8b9c8376
feat: add hilbish.version interface 2022-05-17 06:39:30 -04:00
TorchedSammy
5dd2af7250
fix: add release name to version 2022-05-17 06:39:05 -04:00
TorchedSammy
ac21109307
fix: change how version is retrieved 2022-05-16 19:36:34 -04:00
TorchedSammy
cb88db8cfc
feat: add hilbish.vim interface (closes #114) 2022-05-13 20:52:48 -04:00
TorchedSammy
960909b81d
fix: typo in editor interface 2022-05-13 20:52:30 -04:00
TorchedSammy
dc933934eb
feat: add hilbish.editor interface
this is going to be a middle level interface
which brings functions for interacting
with the line editor used in hilbish

adds the following functions:
setVimRegister(reg, text) - sets text in a vim register
getVimRegister(reg) - gets text from a vim register
insert(text) - inserts text into the line
accessible via hilbish.editor
2022-05-13 20:43:40 -04:00
TorchedSammy
827c25fb57
feat: add hilbish.job.add function
this is mainly to accomodate for the employer
handler (#152)
2022-05-13 17:08:15 -04:00
TorchedSammy
3374dfd28f
fix: always start job in exec handler
makes sure that if any errors occur the job
will still throw the start hook
2022-05-13 16:59:16 -04:00
TorchedSammy
9a87d76969
fix: finish job on lua job stop function
makesdoc  sure that a job is finalized by throwing
the job.done hook and setting its running status
to false
2022-05-12 22:29:07 -04:00
TorchedSammy
200fe1054f
fix: pass user input to runner function instead of expanded alias 2022-05-11 21:13:29 -04:00
TorchedSammy
52a58b14c3
docs: update nature doc to have new correct info 2022-05-08 16:03:44 -04:00
TorchedSammy
15035c02cb
fix(doc): check if modmt exists before trying to get module prop docs 2022-05-08 16:02:24 -04:00
Renzix
dd678a4a75
fix: Not loading nature module on some systems (#150) 2022-05-08 16:01:06 -04:00
TorchedSammy
0a01ed862c
feat: print error if nature is missing 2022-05-06 19:21:32 -04:00
TorchedSammy
200babf831
chore: merge 2022-05-06 19:06:57 -04:00
TorchedSammy
d6bc8b51de
ci: fix missing files on either oses 2022-05-06 19:06:06 -04:00
sammyette
86700c0a7b
ci: add codeql code scanning 2022-05-06 12:20:41 -04:00
TorchedSammy
30b07bc98b
fix: check if path has tilde prefix when trying to expand home 2022-05-01 07:20:40 -04:00
TorchedSammy
db437905e0
fix: implicitly expand tilde on args to all fs functions 2022-05-01 00:49:59 -04:00
TorchedSammy
c890b86e08
feat: add hilbish.opts and autocd opt
this adds `hilbish.opts`, a table to set
simple options akin to shopt or setopt on
other shells. this commit specifically also
includes the autocd opt, which functions the
way you expect it to

to set opts, simply do `hilbish.opts.name = val`,
where `name` is the opt you want to set and `val`
being the opt setting.

ie: `hilbish.opts.autocd = true` to turn on autocd
2022-04-30 21:22:37 -04:00
TorchedSammy
a8406657f9
fix: remove nature hook handles
since it was only for command exec errors,
and theyre handled runner side now, we dont
have to handle it via hooks anymore
2022-04-30 21:05:21 -04:00
TorchedSammy
4178b78341
fix: return other errors from sh runner
makes it so that the sh runner function will return
command not found and not executable errors,
which makes them able to be handled via lua properly
2022-04-30 21:02:36 -04:00
TorchedSammy
c4eb3ad368
chore: change lua init errors to make more sense 2022-04-30 20:31:37 -04:00
TorchedSammy
0642ddda36
fix: push home dir to recent dirs with correct function 2022-04-30 20:28:47 -04:00
TorchedSammy
b210378380
ci: remove .exe from windows artifact names 2022-04-30 12:08:54 -04:00
TorchedSammy
03cb9c06f3
ci: fix release builds; make them include lua libs and nature lib 2022-04-30 12:08:39 -04:00
TorchedSammy
c929c7602f
ci: checkout submodules 2022-04-30 12:00:41 -04:00
TorchedSammy
e678ef66d8
docS: update changelogs for master
800th commit!
2022-04-30 12:00:01 -04:00
TorchedSammy
d053b58204
ci: indent list of files 2022-04-30 10:50:06 -04:00
TorchedSammy
eb3123405a
ci: fix list of files for artifact build 2022-04-30 10:48:32 -04:00
TorchedSammy
f12f88ed00
ci: include all required files in build artifacts 2022-04-30 10:45:55 -04:00
TorchedSammy
3bad452f95
fix: load completions by default 2022-04-24 09:00:06 -04:00
TorchedSammy
2790982ad1
fix: no command completions if query/line is an alias
basically, i have a `c` alias which is `git commit`,
this would resolve to `git commit` literally to try
and complete `commit`, which wouldnt match.
this fixes that, and instead itll suggest commands
that start with `c`. if there is a space after and
completion is requested, itll use the alias properly
2022-04-24 00:06:19 -04:00
TorchedSammy
4e5f8b5c80
docs: add docs for nature module 2022-04-24 00:00:18 -04:00
TorchedSammy
4a4c4d8c74
refactor: rewrite completion handler in lua 2022-04-23 23:59:03 -04:00
TorchedSammy
bcf02a6b0e
fix: make custom hist dir match default by adding hilbish to the path 2022-04-23 23:55:04 -04:00
TorchedSammy
984b8a4308
feat: add hilbish.aliases.resolve to resolve an alias 2022-04-23 12:28:28 -04:00
TorchedSammy
3db6334445
docs: [ci] generate new docs 2022-04-23 00:03:50 -04:00
TorchedSammy
9e596dc271
refactor: (re)organize and change prelude path and structure
prelude is no longer. it is now nature.
organized the single file prelude into multiple
source files and renamed it to nature. this is coming
after thought that it can turn into a general hilbish
lua core, with user facing modules as well.

this introduces the `nature.dirs` module, to interact
and get recently changed to directories and last/old
cwd.
2022-04-23 00:03:50 -04:00
TorchedSammy
f003249632
docs: update doc reference for vim mode actions 2022-04-23 00:03:49 -04:00
TorchedSammy
1714aeac36
feat: add fs.abs 2022-04-23 00:03:49 -04:00
TorchedSammy
bca89197ad
fix: add io flush after doc help message 2022-04-23 00:03:49 -04:00
TorchedSammy
27ac60b856
fix: remove unused var 2022-04-23 00:03:48 -04:00
TorchedSammy
dbb27f7739
docs: [ci] generate new docs 2022-04-23 00:03:48 -04:00
TorchedSammy
03a57fce5b
docs: add more documentation for completions 2022-04-23 00:03:48 -04:00
TorchedSammy
abfbeb5f84
feat: allow overwrite of completion handler (closes #122)
this also makes the completion functions `bins`
and `files` also return the prefix to pass
to the completion handler.

this is an overhaul to the completion system,
which gets the completion handler from lua
instead of being made to only have lua provided
*command* completions.

it does not have any performance deficit, even
though it calls in to golua for completions.
2022-04-23 00:03:47 -04:00
TorchedSammy
3194add3dc
fix: restore doc related metafields on hilbish table 2022-04-23 00:03:47 -04:00
TorchedSammy
1ba88fea88
fix: correct custom runner mode handling with recent changes 2022-04-23 00:03:47 -04:00
TorchedSammy
1274811739
docs: [ci] generate new docs 2022-04-23 00:03:46 -04:00
TorchedSammy
0af36db6ff
fix!: change the way highlighter and hinter are set
with the change of blocking changes to the
hilbish table, i took an opportunity
to make the highlighter and hinter callbacks
set in a more natural way. instead of being
a function which takes a callback, you set
the function itself.
2022-04-23 00:03:38 -04:00
TorchedSammy
1a4008fcfb docs: [ci] generate new docs 2022-04-22 02:17:00 +00:00
TorchedSammy
57d7527356
fix: make hilbish.which work with aliases and commanders 2022-04-21 22:16:04 -04:00
TorchedSammy
3d525aa7da
fix: dont allow overrides on hilbish table 2022-04-21 20:39:38 -04:00
TorchedSammy
37e1b12b81
feat: add hilbish.completion.call to call a completer 2022-04-21 20:39:06 -04:00
TorchedSammy
abfd4e5196
fix(util): SetField on a table with a metatable causing panic 2022-04-21 20:33:32 -04:00
TorchedSammy
bd35e3b871
refactor: use foreach function to loop over lua tables 2022-04-21 14:01:59 -04:00
TorchedSammy
86aa40af64 docs: [ci] generate new docs 2022-04-21 16:19:31 +00:00
TorchedSammy
a89d3e59d6
docs: fix typo in hilbish.inputMode doc (closes #147) 2022-04-21 12:19:11 -04:00
TorchedSammy
1458ecdcab
fix: file completions changes
changed the way file completions are handed
completely, which fixes #130 and makes the
full name appear in the completion menu instead
of it being cut off
2022-04-20 13:06:46 -04:00
ym555
6ccb9ebeff
fix(readline): take into account character width (#145)
first step towards unicode support yay
2022-04-20 08:18:34 -04:00
Will Eccles
e34ab5314a
fix: make macOS config path match Linux (#143)
Also moves some variables around in vars_*.go to accommodate the fix.
2022-04-19 22:12:05 -04:00
TorchedSammy
0ae31123b9
fix: make expand home actually expand and not do the opposite 2022-04-19 22:05:48 -04:00
TorchedSammy
7a17d7931f
fix: use load from source in DoFile function instead of load chunk 2022-04-19 21:25:52 -04:00
TorchedSammy
d4084a82ba
fix: expandHome function using hist dir instead of passed arg 2022-04-19 21:23:48 -04:00
TorchedSammy
9d69b63a0f
chore: update golua (closes #142) 2022-04-19 14:37:57 -04:00
TorchedSammy
b83c09a2b3
fix(readline): check stdin error properly 2022-04-19 10:30:04 -04:00
TorchedSammy
bee8d6e9e6
fix(readline): input going to next line if its longer than terminal width 2022-04-18 22:42:27 -04:00
TorchedSammy
48cb62282d
fix(readline): input getting cut off on enter 2022-04-18 22:36:54 -04:00
TorchedSammy
1e48a3e03d
fix(readline): home and end buttons not putting the cursor in the right place 2022-04-18 16:04:56 -04:00
TorchedSammy
4e8aa7ed1d
fix(readline): use invert for completion highlight instead of hardcoded colors 2022-04-17 23:39:53 -04:00
TorchedSammy
919a52a630
fix: handle syntax error in aliased command
if an alias is something which isn't valid syntax,
specifically if hilbish cant split up the input
properly to execute, it will report the error to
the user. the previous behaviour was a panic since
on error the args slice will be of length 0

this is basically an edge case and fixes a bug
which shouldnt happen normally
2022-04-17 22:58:29 -04:00
TorchedSammy
b0c950a96a
fix: make sure user input is saved to history without alias expansion (4th same regression woo) 2022-04-17 22:57:31 -04:00
TorchedSammy
c4438579f6
build: remove all from install target 2022-04-14 10:11:20 -04:00
buffet
59e81d3996
build: improve makefile 2022-04-14 10:05:35 -04:00
Renzix
7f161e6683
feat: added forward/backward word keybinds (#139)
Added emacsForwardWord and emacsBackwardWord which is used by M-f and
M-b directly. Also added M-d to ctrl delete and removed the bad old
funcion in favor of the fancy new one. Lastly I added alt delete which
deletes with emacsBackwardWord. Works identically to gnu readline

Co-authored-by: Renzix <DanielDeBruno@renzix.com>
2022-04-14 07:42:46 -04:00
TorchedSammy
ded0be275f
chore: bump version to v2.0.0 2022-04-13 20:50:29 -04:00
TorchedSammy
e3fdf84f5c
fix!: make path to script the 0th arg instead of 1st
makes more sense, brings some lua parity
this means that user passed args start from 1
instead of 2
2022-04-13 20:19:28 -04:00
TorchedSammy
194e4e01b7
fix: don't insert any unhandled control keys 2022-04-13 19:36:18 -04:00
TorchedSammy
e5c9b85008
feat: add ctrl _ to undo 2022-04-13 16:58:36 -04:00
TorchedSammy
e044aeb5ed docs: [ci] generate new docs 2022-04-13 14:14:06 +00:00
sammyette
0a2046e985
feat: add right prompt (#140)
* feat: add right prompt (closes #111)

* chore: add comment for set right prompt function

* fix: add 1 space at the end of right prompt to fix character cut off

* docs: update doc for prompt function
2022-04-13 10:13:46 -04:00
TorchedSammy
626b036b4b
fix!: add complete input to history, including continued input
this introduces a breaking change to runner functions.
they are now required to return 3 values, the first
being the user's input, and the 2 others that it was
before. the `hilbish.runner` functions respectively
have been updated, so if you just return from those
there will be no difference
2022-04-13 10:12:17 -04:00
sammyette
ce625aca0c
feat: add ctrl delete to forward delete word (#138)
* feat: add ctrl delete to forward delete word (closes #124)

* fix: make delete word function accurately

* fix: make ctrl delete work on st
2022-04-12 23:08:44 -04:00
TorchedSammy
1715a1f626
feat: make ctrl d delete char below cursor if line isnt empty 2022-04-12 21:02:01 -04:00
TorchedSammy
f002eca258
fix: dont prompt for continued input on incomplete input when not interactive (closes #137) 2022-04-12 19:43:12 -04:00
TorchedSammy
2814f44163
fix: typo in timer create function 2022-04-12 19:41:50 -04:00
TorchedSammy
ea7517be05 docs: [ci] generate new docs 2022-04-12 23:37:39 +00:00
TorchedSammy
508fd5f8a2
docs: update docs for timer related functions 2022-04-12 19:37:15 -04:00
TorchedSammy
c95ff42dee
feat: add timer pool and api (closes #135)
adds a map (but lets call it a pool) of all
running timers. this makes us able to keep
track of all running intervals and timeouts.
it also means hilbish can wait for them to
be done before exiting (it only waits when
non interactive).

this introduces the `hilbish.timers` interface,
documented by `doc timers`. the `hilbish.interval`
and `hilbish.timeout` functions return a timer
object now.
2022-04-12 19:31:48 -04:00
TorchedSammy
c342f4f6f5
fix: handle when stdin is in nonblocking mode (closes #136) 2022-04-08 10:46:25 -04:00
TorchedSammy
393fe3962f
chore: update golua 2022-04-05 22:50:14 -04:00
TorchedSammy
8ae22127c0
fix: remove virt g handling at command exit 2022-04-05 07:41:11 -04:00
TorchedSammy
8f942f6f60 docs: [ci] generate new docs 2022-04-05 01:35:10 +00:00
TorchedSammy
b712efd278
fix(docgen): make functions that take varargs have the signature 2022-04-04 21:34:46 -04:00
TorchedSammy
ee4d97ff9a
fix: put input in history instead of resolved input ran by hilbish
ive fixed this like 3 times and regressed it
2022-04-04 21:21:46 -04:00
TorchedSammy
9ce861b080
refactor: set runner options in a better way and move out exec handler 2022-04-04 21:20:02 -04:00
TorchedSammy
69d38d7048 docs: [ci] generate new docs 2022-04-04 10:40:25 +00:00
sammyette
0fc5f457ad
refactor!: support lua 5.4 (#129)
major rewrite which changes the library hilbish uses for it's lua vm
this one implements lua 5.4, and since that's a major version bump,
it's a breaking change. introduced here also is a fix for `hilbish.login`
not being the right value

* refactor: start work on lua 5.4

lots of commented out code

ive found a go lua library which implements lua 5.4
and found an opportunity to start working on it.
this commit basically removes everything and just leaves
enough for the shell to be "usable" and able to start.
there are no builtins or libraries (besides the `hilbish` global)

* fix: call cont next in prompt function

this continues execution of lua, very obvious
fixes an issue with code stopping at the prompt function

* fix: handle errors in user config

* fix: handle panic in lua input if it is incorrect

* feat: implement bait

* refactor: use util funcs to run lua where possible

* refactor: move arg handle function to util

* feat: implement commander

* feat: implement fs

* feat: add hilbish module functions used by prelude

* chore: use custom fork of golua

* fix: make sure args to setenv are strings in prelude

* feat: implement completions

* chore: remove comment

* feat: implement terminal

* feat: implement hilbish.interval

* chore: update lunacolors

* chore: update golua

* feat: implement aliases

* feat: add input mode

* feat: implement runner mode

* style: use comma separated cases instead of fallthrough

* feat: implement syntax highlight and hints

* chore: add comments to document util functions

* chore: fix dofile comment doc

* refactor: make loader functions for go modules unexported

* feat: implement job management

* feat: add hilbish properties

* feat: implement all hilbish module functions

* feat: implement history interface

* feat: add completion interface

* feat: add module description docs

* feat: implement os interface

* refactor: use hlalias for add function in hilbish.alias interface

* feat: make it so hilbish.run can return command output

* fix: set hilbish.exitCode to last command exit code

* fix(ansikit): flush on io.write

* fix: deregister commander if return isnt number

* feat: run script when provided path

* fix: read file manually in DoFile to avoid shebang

* chore: add comment for reason of unreading byte

* fix: remove prelude error printing

* fix: add names at chunk load for context in errors

* fix: add newline at the beginning of file buffer when there is shebang

this makes the line count in error messages line up properly

* fix: remove extra newline after error
2022-04-04 06:40:02 -04:00
TorchedSammy
64bf7024d2
docs: fix hilbish typo 2022-04-03 21:43:13 -04:00
Renzix
0ebd8d9035
feat: added alt backspace keybinding (#132)
Co-authored-by: Renzix <DanielDeBruno@renzix.com>
2022-03-29 22:15:23 -04:00
Renzix
52caedc1f1
feat: delete key on st and fix: delete key crash on xterm (#131)
* fix: delete key on st

* fix: delete key crash on xterm

Co-authored-by: Renzix <DanielDeBruno@renzix.com>
2022-03-29 20:35:51 -04:00
TorchedSammy
34ae8ade7b
chore: tidy go modules 2022-03-29 15:28:39 -04:00
TorchedSammy
9ff6e5879f
chore: bump go version to 1.17 2022-03-29 13:31:16 -04:00
TorchedSammy
20fae8a870
fix: prompt refresh (closes #116) 2022-03-29 13:07:27 -04:00
TorchedSammy
eff942433d
fix!: remove complete global (was supposed to be gone in 1.0) 2022-03-27 21:10:13 -04:00
Renzix
61c9e12a4a
feat: control k to delete the rest of the line (#128)
Co-authored-by: Renzix <DanielDeBruno@renzix.com>
2022-03-26 23:43:30 -04:00
TorchedSammy
0aba60b5de docs: [ci] generate new docs 2022-03-26 22:28:27 +00:00
TorchedSammy
62a6cc56b9
docs: document hilbish.highlighter 2022-03-26 18:28:01 -04:00
TorchedSammy
e5d841a0a7 docs: [ci] generate new docs 2022-03-26 22:26:10 +00:00
TorchedSammy
3e50e608c1
chore: merge from remote 2022-03-26 18:25:35 -04:00
TorchedSammy
76f100ca77
feat: expose syntax highlighting (closes #125) 2022-03-26 18:25:19 -04:00
TorchedSammy
0cad0e7e66
fix: only try to run hinter function if it isnt nil 2022-03-26 18:24:49 -04:00
TorchedSammy
2fb481c4cb docs: [ci] generate new docs 2022-03-26 21:34:42 +00:00
TorchedSammy
6ea25a22b3
feat: add inline hint text and change what were hints previously to info (closes #126) 2022-03-26 17:34:09 -04:00
TorchedSammy
577f00dfef
fix(readline): make forward delete work properly 2022-03-23 21:11:24 -04:00
TorchedSammy
722bd1cd80
fix(readline): insert text in replace mode if cursor is at end of text 2022-03-23 21:10:04 -04:00
TorchedSammy
1ba314d961
chore: prepare for v1.2.0 release 2022-03-22 22:11:46 -04:00
sammyette
84dce8c537
docs: change short description back to block quote 2022-03-22 22:04:33 -04:00
TorchedSammy
3345c51064
docs: add newline after short description 2022-03-22 22:01:22 -04:00
TorchedSammy
a7e450904c
docs: add more info to readme 2022-03-22 21:59:34 -04:00
TorchedSammy
23efc8e54d
docs: update image for readme gallery 2022-03-22 21:19:36 -04:00
TorchedSammy
1d4c8a7645
feat: make history clear function work again 2022-03-22 19:01:29 -04:00
TorchedSammy
7272e035d9
ci: remove fetch-depth 0 setting for checkout 2022-03-22 18:41:26 -04:00
TorchedSammy
8a215ad742
docs: rename vimMode to vim-mode 2022-03-22 18:39:22 -04:00
TorchedSammy
6e69ee20f6
chore: merge 2022-03-22 18:38:26 -04:00
TorchedSammy
bc15da2f1a
docs: add more docs for runner mode interface 2022-03-22 18:38:13 -04:00
TorchedSammy
dd9e827735 docs: [ci] generate new docs 2022-03-22 22:33:52 +00:00
TorchedSammy
3636efe7f8
docs: add doc for mode param of runnerMode function 2022-03-22 18:33:11 -04:00
TorchedSammy
053914ec45
docs: fix dates for changelog versions 2022-03-22 17:19:23 -04:00
TorchedSammy
1e884e7c89
fix: handle job being nil (first sh exec case) 2022-03-21 21:25:43 -04:00
TorchedSammy
f27d60f827
fix: move cursor to end of line on history search (closes #121) 2022-03-21 06:47:14 -04:00
TorchedSammy
754a63c74b
chore: merge 2022-03-20 19:10:41 -04:00
TorchedSammy
2fe888e186
feat: add hilbish.jobs interface and add stop function to job in hooks (closes #109) 2022-03-20 19:10:12 -04:00
TorchedSammy
0d4143582f docs: [ci] generate new docs 2022-03-20 21:54:55 +00:00
TorchedSammy
654ca4b527
docs: fix hilbish.alias doc 2022-03-20 17:54:02 -04:00
TorchedSammy
802f444ba6 docs: [ci] generate new docs 2022-03-20 19:16:13 +00:00
TorchedSammy
86a15e6363
feat: add configurable runner mode (closes #110) 2022-03-20 15:15:44 -04:00
TorchedSammy
96c1487bfa
fix: make sure complete input is added to history 2022-03-19 18:48:03 -04:00
TorchedSammy
1e899bf18e
chore: set name of history in menu to History instead of file 2022-03-19 13:24:12 -04:00
TorchedSammy
f03f8c0da1
docs: add exitCode to job docs 2022-03-19 13:14:12 -04:00
TorchedSammy
1378a74e87
feat: add job hooks (part of #109) 2022-03-19 13:10:50 -04:00
TorchedSammy
63bc398f1c
fix: use unexported alias handler init function 2022-03-19 12:44:26 -04:00
TorchedSammy
579a0cd0ce
refactor: rename hilbishAliases to aliasHandler for clarity 2022-03-19 12:43:48 -04:00
TorchedSammy
f433ab8a6f
docs(guide): mention that users can copy the default dir from dataDir 2022-03-19 09:50:51 -04:00
TorchedSammy
eb0a81f7a2
chore: prepare for v1.1.0 release 2022-03-17 20:56:19 -04:00
TorchedSammy
24b88a0483
docs: add docs for vim mode 2022-03-17 20:25:38 -04:00
TorchedSammy
f73c6d4aa8
fix: completions of executables and running absolute paths on windows 2022-03-17 20:22:30 -04:00
TorchedSammy
925ded6cea
fix(readline): remove duplicate code 2022-03-17 19:57:57 -04:00
TorchedSammy
92d0e195ab
fix: change prompt back to user's prompt on contine prompt exit 2022-03-17 19:49:33 -04:00
TorchedSammy
4da82e872c
fix: completions on files/folders starting with a dot not having it 2022-03-17 19:41:37 -04:00
TorchedSammy
b0ece71de3
fix: use not-executable in prelude instead of no-perm 2022-03-17 19:29:27 -04:00
TorchedSammy
8b5dc69950
feat: add command.not-executable hook (closes #119) 2022-03-16 19:45:55 -04:00
sammyette
20a4cdb505
fix: handle path binaries properly on windows (closes #117, #118) (#120)
* fix: handle path binaries properly on windows (closes #117, #118)

* refactor: dont return exec name since it isnt needed

* fix: return correct error in find exec function and stat always

* fix: remove filepath import for exec file check on unix
2022-03-16 19:44:32 -04:00
TorchedSammy
01d937afd8
fix: correct username in greeting on windows 2022-03-16 18:42:38 -04:00
sammyette
32b421d402
docs: remove support notice 2022-03-15 22:20:23 -04:00
TorchedSammy
0ee47cc6f0
fix(readline): clear history filter on Readline, fixes filtering after ctrl-c 2022-03-15 16:27:12 -04:00
TorchedSammy
b8e0874ab0
fix: catch and ignore sigquit signal (closes #112) 2022-03-14 20:55:00 -04:00
TorchedSammy
ae449b89eb
fix(readline): dont show completions menu if there is only 1 entry (closes #107) 2022-03-14 20:17:45 -04:00
TorchedSammy
91222f9d74
fix(readline): dont reduce pos if its at 0 2022-03-13 20:00:11 -04:00
TorchedSammy
feb2ea18fb
docs: document hilbish.vimAction hook 2022-03-13 17:44:54 -04:00
TorchedSammy
726d265cca
feat: add hilbish.vimAction hook (closes #108) 2022-03-13 16:44:11 -04:00
TorchedSammy
7d9c7ddf18
fix: empty multiline prompt if entire prompt is single line 2022-03-13 16:42:14 -04:00
TorchedSammy
5e505d0a8d
fix: increate pos by 1 at paste instead of 2 2022-03-13 16:40:58 -04:00
TorchedSammy
e5b6a2586b
chore: update lunacolors 2022-03-13 16:37:33 -04:00
TorchedSammy
c5dd05bb1e
refactor: remove mode from prompt func in default conf and dont refresh in vim mode 2022-03-13 16:12:34 -04:00
TorchedSammy
0113a4e0b4
fix(readline): make esc escape any vim mode 2022-03-13 14:26:44 -04:00
TorchedSammy
5a2e3e4700
chore: bring readline in repo for easier maintenance 2022-03-13 13:48:49 -04:00
TorchedSammy
b05cb30ed7
fix: check if interactive *and* input starts with space to determine if to add to history 2022-03-13 12:51:27 -04:00
TorchedSammy
dc53eef829
ci: add checkout for create release 2022-03-12 22:32:32 -04:00
TorchedSammy
2f728de6a1
ci: fix checkout 2022-03-12 22:30:16 -04:00
TorchedSammy
4dc5ff60fd
ci: fix submodule clone 2022-03-12 22:22:15 -04:00
TorchedSammy
a414c87e06
chore: bump version to v1.0.4 2022-03-12 22:15:31 -04:00
TorchedSammy
b3db55708a
ci: clone submodules 2022-03-12 22:14:49 -04:00
TorchedSammy
7d7ccb5c9b
chore: prepare changelog for v1.0.4 2022-03-12 21:59:45 -04:00
TorchedSammy
ece5f92307
fix: create history dir if it doesnt exist (fixes #113) 2022-03-12 21:50:57 -04:00
TorchedSammy
0e4f552be2
refactor: panic in history.go for more context 2022-03-12 21:43:02 -04:00
TorchedSammy
23902ea25c
chore: prepare for v1.0.3 release 2022-03-12 20:10:39 -04:00
TorchedSammy
a7f0457dab
ci: include lua libs in release 2022-03-12 19:42:42 -04:00
TorchedSammy
4a4cb3409f
fix: set running to true before throwing exit hook on no input
this fixes an issue with the prompt being kind of a mess when
enter alone is pressed (and hilbish doesn't try to run anything)
2022-03-07 21:01:21 -04:00
TorchedSammy
853dfa369f
fix: add user input to history instead of hilbish expanded (closes #103) 2022-03-07 19:10:21 -04:00
TorchedSammy
738939e4c9
fix: remove duplicate binary suggestions (fixes #105) 2022-03-07 18:56:22 -04:00
TorchedSammy
3babf36c43
fix: remove newline from prompt 2022-03-06 22:23:38 -04:00
TorchedSammy
b7478c3c1a
chore: prepare for v1.0.2 release 2022-03-06 21:48:24 -04:00
TorchedSammy
605574f262
fix: create directory for hist dir if it doesnt exist 2022-03-06 21:44:46 -04:00
TorchedSammy
9165e0bdf9
chore: prepare for 1.0.1 release 2022-03-06 17:23:44 -04:00
TorchedSammy
ec886e17fa
fix: dont refresh prompt at startup 2022-03-06 17:20:41 -04:00
TorchedSammy
ba67278fad
fix: dont print types of args in appendPath 2022-03-06 17:19:47 -04:00
TorchedSammy
539cf402ca
fix: dont double set prompt 2022-03-06 17:08:53 -04:00
TorchedSammy
8eb5a6710d
build: update makefile 2022-03-06 15:12:10 -04:00
TorchedSammy
03795e5727
ci: update version of go-release-action 2022-03-06 15:04:45 -04:00
TorchedSammy
7959a8b572
docs: mention latest changes in changelog 2022-03-06 15:00:43 -04:00
TorchedSammy
5c4335ec6a
docs: include guide command in greeting message 2022-03-06 14:56:04 -04:00
TorchedSammy
99c9e95eeb
refactor!: change preload.lua to prelude/init.lua, add guide command
this commit has 2 changes:
- preload.lua is now init.lua in the prelude folder. the reason
for the name change of preload to prelude is to make update/
overwrite not hell

- the guide command has been added which is a simple step through
getting started type of thing for new users
2022-03-06 14:45:06 -04:00
TorchedSammy
46ef8ad122
ci: add name for release action 2022-03-06 14:44:28 -04:00
TorchedSammy
cec6287e07
ci: add action to make release 2022-03-06 14:40:02 -04:00
TorchedSammy
4364031b16
fix!: change config path when custom config dir is used to be init.lua instead of .hilbishrc.lua 2022-03-06 14:39:23 -04:00
TorchedSammy
4ef6c7d5c0
fix: hilbish.read overriding history 2022-03-06 14:38:27 -04:00
TorchedSammy
764e2372a2
feat(ansikit): add screenMain and screenAlt functions to switch terminal screen 2022-03-06 14:26:28 -04:00
TorchedSammy
fb3cedb161
fix: set prompt in hilbish.read 2022-03-06 14:23:41 -04:00
TorchedSammy
ef6bf24cda
fix: finish command properly when sh error occurs 2022-03-06 13:32:39 -04:00
TorchedSammy
639bd09d0e
fix: import util 2022-03-06 13:31:50 -04:00
TorchedSammy
4b57dc2ed8
feat: add hilbish.exitCode property (closes #101) 2022-03-06 12:09:10 -04:00
TorchedSammy
928b829388
fix: set hilbish.vimMode property before throwing hook 2022-03-06 12:08:00 -04:00
TorchedSammy
7b693908df
docs: document hilbish scope hooks (closes #100 - 100th issue!!*) 2022-03-06 12:06:39 -04:00
TorchedSammy
8d8b298053
docs: clarify what hooks are from 2022-03-06 12:04:28 -04:00
TorchedSammy
281c443b7b
docs: add spacing between signal hooks 2022-03-06 12:04:01 -04:00
TorchedSammy
3805f13369
feat: throw hilbish.exit hook (closes #99) 2022-03-06 10:23:32 -04:00
TorchedSammy
0b1b5bff2d
feat: change cursor shape based on vim mode 2022-03-06 10:08:42 -04:00
TorchedSammy
f8f8cd0b59
chore: update dependencies 2022-03-06 10:07:28 -04:00
TorchedSammy
4bb65572e4
fix(ansikit): define cursor consts 2022-03-06 09:42:35 -04:00
TorchedSammy
29c1e29bb7
docs: change date of 1.0 2022-03-05 21:41:33 -04:00
TorchedSammy
105552ac74
docs: fix 1.0 link in changelog 2022-03-05 21:40:48 -04:00
TorchedSammy
f28fd7e6c0
docs: fix indent size and type 2022-03-05 21:39:52 -04:00
TorchedSammy
f3f49fc398
docs: make changelog up to date 2022-03-05 21:34:59 -04:00
TorchedSammy
893d72a236
chore: prepare for 1.0 release 2022-03-05 21:29:38 -04:00
TorchedSammy
0637f2763b
fix: dont write history automatically with rl library 2022-03-05 21:29:13 -04:00
TorchedSammy
1cb536b1ac
fix: write to bottom of history file instead of at top 2022-03-05 21:26:03 -04:00
TorchedSammy
6740e012a5
fix: finish properly when command exit is successful after contine prompt 2022-03-05 21:25:32 -04:00
TorchedSammy
b1ad90443e docs: [ci] generate new docs 2022-03-05 20:13:15 +00:00
TorchedSammy
76c94bfcce
docs: fix docs for hilbish.complete 2022-03-05 16:12:46 -04:00
TorchedSammy
0ed365170c
refactor!: completion api, add hilbish.completion interface
this is a pretty big commit which mainly contains a refactor
and breaking change to how command completions are done.

before that, a hilbish.completion interface has been added
which for now just has 2 functions (`files` and `bins`)
for completions of normal files and executables.

hilbish.complete is now expected to return a table of
"completions groups," which are as the name suggests a group
for a completion. a completion group is a table which has
the fields `type`, which can be either `list` or `grid`,
and `items`, being an array (or string keyed table) of items

if an item is string keyed the item itself is the key name
and the value is a table with the first value in it being the
description for the item. this description is only applied
with the list type.

this is probably the longest commit message ive written
2022-03-05 15:59:00 -04:00
TorchedSammy
70724ec015
feat: make hilbish.history functional for go readline 2022-03-05 15:57:46 -04:00
TorchedSammy
f1dfd59c4c
fix: add back prompt global var
fixes an issue with multiline prompt overriding user's prompt
permanently
2022-03-05 15:46:38 -04:00
TorchedSammy
a0dff5babf
fix: remove print in history handler 2022-03-05 15:23:17 -04:00
TorchedSammy
058d6ac456
chore: update readline 2022-03-05 14:40:38 -04:00
TorchedSammy
9f206ebed0
fix: export hilbish.complete 2022-03-05 11:38:33 -04:00
TorchedSammy
59963add14
fix: dont complete binaries in path if complete req starts with file prefix 2022-03-05 08:58:12 -04:00
TorchedSammy
88fd6f01b9
fix: dont add last empty line of history, make sure first isnt missing in search 2022-03-05 08:28:34 -04:00
TorchedSammy
5175367b35
fix: handle errors in goro and timeout callbacks 2022-03-04 22:21:34 -04:00
TorchedSammy
83ca8066e6
chore: remove unused prompt var 2022-03-04 22:21:14 -04:00
TorchedSammy
92f279e5cf
fix: prevent writing empty line to history 2022-03-04 22:04:44 -04:00
TorchedSammy
f26ef935dd
feat: add file history (closes #97) 2022-03-04 21:55:37 -04:00
TorchedSammy
6b9bbb615d
fix: handle prompt properly and remove global 2022-03-04 21:54:47 -04:00
TorchedSammy
237bc19f68
fix: prompt handling 2022-03-04 21:16:45 -04:00
TorchedSammy
63e33af34d
chore: update readline 2022-03-04 20:48:22 -04:00
TorchedSammy
d7f10b0247 docs: [ci] generate new docs 2022-03-04 18:41:22 +00:00
TorchedSammy
99461e42d0
fix: export hilbish.goro (closes #98) 2022-03-04 14:40:54 -04:00
TorchedSammy
b0e4cf6ed1
chore: remove shell.nix 2022-03-03 21:01:56 -04:00
TorchedSammy
fca15886aa
docs: add more detail to changelog and make it up to date 2022-03-03 20:07:06 -04:00
TorchedSammy
e7ac7ce843
feat: add hilbish.os interface (closes #94) 2022-03-02 19:11:57 -04:00
TorchedSammy
c9f9ce07e8
docs: remove readline requirement, use nightly links 2022-03-02 06:58:55 -04:00
TorchedSammy
e7a31c5394
ci: add .exe to windows artifacts 2022-03-02 06:44:46 -04:00
TorchedSammy
b61a36d675
ci: fix artifact upload for windows 2022-03-02 06:42:48 -04:00
TorchedSammy
284248fc08 docs: [ci] generate new docs 2022-03-02 02:16:12 +00:00
TorchedSammy
7bde025c8e
chore: merge 2022-03-01 22:15:35 -04:00
TorchedSammy
e8d0ea12cc
fix: add substitute for exec syscall on windows 2022-03-01 22:14:55 -04:00
TorchedSammy
c175bb4d8a
docs: add emmylua doc comments for hilbish module functions 2022-03-01 22:12:48 -04:00
TorchedSammy
b3981b5a4e docs: [ci] generate new docs 2022-03-02 02:01:22 +00:00
TorchedSammy
065d752b82
feat: accessible vim input mode (closes #95) 2022-03-01 22:00:46 -04:00
TorchedSammy
062f40e9e5
fix: push hilbish.which return value properly 2022-03-01 19:34:07 -04:00
TorchedSammy
44e2a458f5 docs: [ci] generate new docs 2022-03-01 23:00:20 +00:00
TorchedSammy
3b6284bc7c
feat: add hilbish.which (closes #93) 2022-03-01 18:59:44 -04:00
TorchedSammy
52379dbdd7
feat: support macos 2022-02-28 18:53:58 -04:00
TorchedSammy
36cd4d4123
fix: custom handle ctrl c from readline 2022-02-28 18:32:57 -04:00
TorchedSammy
d355d02b93
fix: only notify ctrl c signal on windows 2022-02-28 16:15:08 -04:00
TorchedSammy
a3abd4bc91
ci: dont build for macos for now 2022-02-27 23:23:04 -04:00
TorchedSammy
ad6d3193ff
chore: update readline lib 2022-02-27 23:22:37 -04:00
TorchedSammy
1040872169
docs: mention that hilbish now requires go 1.17+ 2022-02-27 22:33:57 -04:00
TorchedSammy
7516956aac
ci: properly build for other oses 2022-02-27 21:00:37 -04:00
TorchedSammy
babb870383
ci: build with 1.17 2022-02-27 19:38:59 -04:00
TorchedSammy
8dcd57309f
ci: use newest 1.16 release of go 2022-02-27 19:32:16 -04:00
TorchedSammy
f292245c23
chore: remove unneeded comments 2022-02-27 19:29:05 -04:00
TorchedSammy
aaeecceabf
chore: remove unneded build directive 2022-02-27 19:28:12 -04:00
TorchedSammy
3cdd21a4fa
refactor: remove gnu readline 2022-02-27 19:27:18 -04:00
TorchedSammy
496bf616c6
chore: remove go:build directive 2022-02-27 19:24:50 -04:00
TorchedSammy
df6a2bb0c7
fix: add missing comma 2022-02-27 19:24:02 -04:00
TorchedSammy
3165552c21
refactor: make go readline lib default, remove hilbiline 2022-02-27 19:21:34 -04:00
TorchedSammy
f26931d4cb
fix: add missing comma in escape list for file completions and add more cases 2022-02-27 19:19:17 -04:00
TorchedSammy
994daba078
feat: add separate custom file complete function 2022-02-27 19:18:01 -04:00
TorchedSammy
311d7d56bd
feat: add full tab completion to alternate readline lib 2022-02-27 19:13:41 -04:00
TorchedSammy
d9d2152e04
fix: add full command after complete prompt to history 2022-02-27 19:12:58 -04:00
TorchedSammy
b221921ab7
docs: detail removal of .hprofile.lua 2022-02-26 12:15:03 -04:00
TorchedSammy
0b5bbcc73c
refactor!: remove .hprofile.lua
same reason as not using ~/.hilbishrc.lua, and also
the fact that users can now just check if
`hilbish.login` is true in their config which is
more organized
2022-02-26 12:14:26 -04:00
TorchedSammy
21b093559a docs: [ci] generate new docs 2022-02-26 15:37:02 +00:00
TorchedSammy
e5566f672a
chore: merge from upstream 2022-02-26 11:36:34 -04:00
TorchedSammy
715a67b882
docs: add emmylua annotations for hilbish module functions 2022-02-26 11:36:04 -04:00
TorchedSammy
18abb66ad4 docs: [ci] generate new docs 2022-02-26 15:32:36 +00:00
TorchedSammy
9d390c87cf
docs: put breaking changes under a separate heading 2022-02-26 11:32:10 -04:00
TorchedSammy
e3a0195eb3
refactor!: remove hilbish.flag
not really that useful
2022-02-26 11:29:20 -04:00
TorchedSammy
06221e06cd
chore: fix hilbiline version 2022-02-26 11:25:28 -04:00
TorchedSammy
fd513b6ae3
fix: correct require paths on windows 2022-02-25 21:34:30 -04:00
TorchedSammy
1b0ae5b1e3
chore: update go sum 2022-02-25 20:44:07 -04:00
TorchedSammy
15caa6e449
chore: replace gopher-lua import with github link 2022-02-25 20:42:50 -04:00
TorchedSammy
d448ef07e0
chore: update manifests 2022-02-25 20:37:11 -04:00
TorchedSammy
d7e78514de
docs: add changelog for master 2022-02-25 19:04:52 -04:00
TorchedSammy
186d620311
docs: bring contributing guide up to date 2022-02-25 18:22:59 -04:00
TorchedSammy
15cf5bb6f3 docs: [ci] generate new docs 2022-02-25 22:17:22 +00:00
TorchedSammy
a74c9a4200
docs(fs): change bool to boolean 2022-02-25 18:17:04 -04:00
TorchedSammy
0bf4072355 docs: [ci] generate new docs 2022-02-25 22:15:49 +00:00
TorchedSammy
a77b997942
refactor: add emmylua docs for all functions appropriate 2022-02-25 18:15:25 -04:00
TorchedSammy
dc608436c1
fix(commander): omit the 'in the shell' part for the description 2022-02-25 18:08:49 -04:00
TorchedSammy
18c115325a
ci: change regen to just gen 2022-02-25 18:04:34 -04:00
TorchedSammy
bd3628332e docs: [ci] regenerate new docs 2022-02-25 22:00:39 +00:00
TorchedSammy
e75c60ff49
feat(docgen): support outputting emmylua sources (closes #91) 2022-02-25 18:00:18 -04:00
TorchedSammy
165cedf328
ci: rename job to regen 2022-02-25 17:59:32 -04:00
TorchedSammy
4c371d8095
ci: fix setup for go 2022-02-25 17:58:09 -04:00
TorchedSammy
c5f5a83990
ci: add action to gen and push docs 2022-02-25 17:55:35 -04:00
TorchedSammy
d1b7515722
fix(docgen): remove trailing spaces in docs 2022-02-24 20:42:54 -04:00
TorchedSammy
b468727a32
refactor(docgen): remove global doc 2022-02-24 20:37:13 -04:00
TorchedSammy
62d8725d99
refactor: remove global module from doc command (closes #90) 2022-02-24 18:19:54 -04:00
TorchedSammy
2a0cd1464a
fix: dont copy default conf to user dir
doing this prevents problems in later releases with breaking
changes (though this shouldnt be the case anymore)
2022-02-23 22:20:11 -04:00
TorchedSammy
f05ab921d7
refactor!: use better default paths
~/.hilbishrc.lua has been removed and will no longer be loaded.
instead, $XDG_CONFIG_HOME/hilbish/init.lua is to be used

the history path has been changed to a more suited one.
on linux, it is in $XDG_DATA_HOME/hilbish/.hilbish-history,
or otherwise ~/.local/share/hilbish/.hilbish-history
2022-02-23 22:19:54 -04:00
TorchedSammy
cb3d0a2e8e
fix: use os agnostic function to get config dir 2022-02-23 22:01:35 -04:00
TorchedSammy
209abfac77
fix: change default hist path to use hist name instead of config name 2022-02-23 21:29:37 -04:00
TorchedSammy
5e9ea9fead
fix: dont add recent dir if its same as last previous (fixes #92) 2022-02-23 21:16:16 -04:00
TorchedSammy
11f193b394
fix: make default config work with breaking changes 2022-02-23 21:14:49 -04:00
TorchedSammy
4cc49d45c7
chore: update license 2022-02-12 16:46:41 -04:00
TorchedSammy
afe579f5be
fix: use correct signature for rl lua loader 2022-01-31 17:46:24 -04:00
TorchedSammy
5d3c129e80
fix: import gopher-lua in other rl impls 2022-01-31 17:45:21 -04:00
TorchedSammy
2bc75c8130
style: tiny style changes/fixes 2022-01-31 17:43:12 -04:00
TorchedSammy
22d8a61544
feat: add hilbish.history interface (closes #85) 2022-01-27 17:02:21 -04:00
TorchedSammy
3f9aad64b5
fix: use right function to set prompt in minimal config 2022-01-27 17:01:27 -04:00
TorchedSammy
8c802a6e6b
feat: dont put input in history if it starts with a space 2022-01-27 16:28:29 -04:00
TorchedSammy
f2a2ac44d6
refactor!: move global functions to the hilbish module
its more organized this way and the `hilbish` lua module
is now what global was before anyway

a feature in this commit also is that `goro` now allows
passing any amount of args to the calling function
2022-01-26 15:51:52 -04:00
TorchedSammy
ea9c3eac30
docs: document new signal hooks 2022-01-26 15:20:48 -04:00
TorchedSammy
9cf03e37c4
fix: change hooks from signals to signal
drop the s, dont remember when i added it
it makes more sense and its what the docs have anyway
2022-01-26 15:18:54 -04:00
TorchedSammy
e0b84aaff7
feat: emit sigusr1 and 2 signal hooks 2022-01-26 15:18:09 -04:00
TorchedSammy
8821171ff5
chore: clean up and update modules 2022-01-02 19:21:34 -04:00
TorchedSammy
c03671f47d
chore: rename files to avoid collision (hilbish bin and shell.nix) 2021-12-31 20:00:39 -04:00
TorchedSammy
5787582c2e
fix: expansion on quotes in alias expansion
to show what this fixes:
`git commit -m "a commit message"` would report that it didnt find
pathspecs for commit or message, because the commit message is only passed as `a`

also fixes it to make it work in commands in other sh syntax
2021-12-31 14:11:11 -04:00
TorchedSammy
9d685ab785
feat: add hilbish.greeting 2021-12-31 13:25:53 -04:00
TorchedSammy
bcbd4be7f9
feat: allow appendPath to take table of paths (closes #88) 2021-12-31 13:22:26 -04:00
TorchedSammy
54689b7dd1
docs: add newline after aur badge 2021-12-19 22:41:04 -04:00
TorchedSammy
740adf27f3
docs: change sizes of some headers and link to aur package 2021-12-19 22:40:25 -04:00
TorchedSammy
40578d9d5f
fix: use a rwmutex for aliases map 2021-12-19 22:37:44 -04:00
TorchedSammy
f81babe973
docs: remove extra newline after short description 2021-12-19 22:19:36 -04:00
TorchedSammy
f6ff6bb274
fix(hilbish.aliases): push list of aliases in all() function 2021-12-19 12:54:15 -04:00
TorchedSammy
bcc249a4bd
feat: add aliases interface (closes #87 and #86)
500th commit!
adds the `hilbish.aliases` interface
it allows you to add, delete and get all aliases

there was also a slight refactor with alias resolving in this commit,
there is a single resolve function instead of duplicate code.
with consideration this could be exported to lua side,
but i see no reason for it
2021-12-14 20:54:23 -04:00
TorchedSammy
afa40dd1a1
docs: update readme with new description 2021-12-14 10:19:11 -04:00
TorchedSammy
fe8372379c
fix: make user dataDir on non linux the config dir 2021-12-14 09:41:47 -04:00
TorchedSammy
2e4bea8292
refactor!: replace hilbish.xdg with hilbish.userDir
"xdg" is basically a linux specific thing and it acted linux specific also.
so replace that with a more portable and general "userDir" table

config is for the user's config directory and also defaults to xdg vars on linux.
data is a directory to store data, mostly for scripts.
on other oses beside linux, it is just the config directory for now
2021-12-13 20:13:17 -04:00
TorchedSammy
b920f7d7b1
docs: change the description for the hilbish module 2021-12-13 17:32:55 -04:00
TorchedSammy
bcfbb20685
fix: dont export lua init 2021-12-08 23:31:48 -04:00
TorchedSammy
4dadfb0874
docs(contributing): fix sentence in making pr section 2021-12-08 23:04:30 -04:00
TorchedSammy
970fe43413
chore: remove newline between replace directives in module file 2021-12-07 18:01:39 -04:00
TorchedSammy
11aaa0cd36
feat: accept a function in complete
the `complete` function will now also accept a nested function in the table
for you to have more fine control over what is suggested and easily
filter specific things
2021-12-07 17:58:56 -04:00
TorchedSammy
6bff669abe
docs(bait): document catchOnce 2021-12-07 17:41:41 -04:00
TorchedSammy
c6edbc20af
style: dont explicitly set exitcode to 0 since its the default value 2021-12-07 17:27:07 -04:00
TorchedSammy
82b4fa5e7c
fix(docgen): revert "fix(docgen): trim trailing space from doc comments"
This reverts commit 3f1f6985119d73a00e9150d244fc108914e49de5.
removes the newlines, dont do this for now
2021-12-07 17:08:25 -04:00
TorchedSammy
3f1f698511
fix(docgen): trim trailing space from doc comments 2021-12-07 16:57:53 -04:00
TorchedSammy
3421f286f2
fix: remove index subdoc (resolves #84) 2021-12-07 16:24:55 -04:00
TorchedSammy
bfc141f655
fix: add home to recent dirs when visited (cd with no args) 2021-12-07 16:13:05 -04:00
TorchedSammy
2f809e398c
fix: use fork of go readline 2021-12-06 20:56:04 -04:00
TorchedSammy
2ede1a195f
chore: remove test completion code 2021-12-06 20:52:49 -04:00
TorchedSammy
6653fa2e03
feat: add new readline lib
this is an almost 100% working readline implementation
in go, will add tab completion in another commit
2021-12-06 20:48:16 -04:00
TorchedSammy
5c6310b1ca
refactor: dont export functions and types 2021-12-06 17:21:31 -04:00
TorchedSammy
369ddcc100
chore: use correct version of hilbiline 2021-12-06 17:19:22 -04:00
TorchedSammy
eaaf17a792
fix: make table for args instead of using luar 2021-12-06 16:32:42 -04:00
TorchedSammy
f60f61e616
style: remove new line 2021-12-06 16:26:51 -04:00
TorchedSammy
28fcdb3122
fix: take care of readline segfault, update deps 2021-12-06 16:24:25 -04:00
TorchedSammy
4e2e8ddf94
fix: revert "fix: resize if terminal has been resized during running command and fix readline segfault"
This reverts commit d270e8f66b929163102998b0d0eaeeb811ca23c3.
causes breakage
2021-12-06 16:07:23 -04:00
TorchedSammy
d270e8f66b
fix: resize if terminal has been resized during running command and fix readline segfault 2021-12-06 15:53:51 -04:00
TorchedSammy
6ac4aa50b3
fix: check if interactive when handling signals 2021-12-06 15:45:35 -04:00
TorchedSammy
2a71fb0075
fix!: change xdg config file to init.lua 2021-12-06 15:42:04 -04:00
TorchedSammy
51b1219003
feat(bait): add catchOnce function 2021-12-04 17:59:19 -04:00
TorchedSammy
dd45766bae
style: dont redeclare function param, just assign 2021-12-04 17:56:45 -04:00
TorchedSammy
144e158473
chore: remove unused function param 2021-12-04 17:56:11 -04:00
TorchedSammy
dedb8cbf76
chore: make typ a local 2021-12-04 17:54:04 -04:00
TorchedSammy
284d4e01a3
chore: rename f to fname in subdoc map (doesnt redefine f) 2021-12-04 17:53:34 -04:00
TorchedSammy
3d36786cc7
chore: remove redundant returns 2021-12-04 17:53:10 -04:00
TorchedSammy
074c5f6766
fix: require lunacolors in preload 2021-12-04 17:50:04 -04:00
TorchedSammy
2e21af4d6b
refactor: use curuser to get homedir everywhere 2021-12-01 18:31:04 -04:00
TorchedSammy
effd028658
fix: substitution of home dir to ~ when names in path match it
fixes edge cases like `/mnt/home/user`
2021-12-01 18:30:03 -04:00
TorchedSammy
4a517bde5e
fix: remove handler when error in hook occurs 2021-12-01 17:35:12 -04:00
TorchedSammy
6a526dbbe4
fix: dont panic when error in bait hook occurs 2021-12-01 17:30:06 -04:00
TorchedSammy
3568b62219
style: use decl and assign operator instead of var and = 2021-12-01 17:29:14 -04:00
TorchedSammy
34778a4bdf
fix!: default SHLVL to 0 instead of 1 2021-11-28 23:19:14 -04:00
TorchedSammy
ce0b2ab955
fix: dont print extra new line on ctrl+d in continue prompt 2021-11-28 10:44:02 -05:00
TorchedSammy
9261253b63
fix: stop interval if error occurs 2021-11-28 09:29:17 -05:00
TorchedSammy
f6aaf85cca
fix: make minimal config actually minimal and not require lunacolors 2021-11-27 22:51:32 -05:00
TorchedSammy
12910ba724
fix: add docs for hilbish.xdg 2021-11-25 22:24:35 -05:00
TorchedSammy
e8a69d36bb
fix: executable tab completion 2021-11-23 19:09:07 -05:00
TorchedSammy
c329d21e7d
chore: make changelogs and bump for 0.7.1 2021-11-22 22:54:20 -05:00
TorchedSammy
4aafddfdb1
fix: tab complete absolute path binaries properly 2021-11-22 22:52:14 -05:00
TorchedSammy
80dcfc362b
fix: allow non absolute paths to be executed
this is a regression introduced in 06272778f85dad04e0e7abffc78a5b9b0cebd067
2021-11-22 22:49:23 -05:00
TorchedSammy
4127396892
docs: add docs for new functions 2021-11-22 22:04:30 -05:00
TorchedSammy
7ab81a61df
fix: dont trim trailing space for completion field 2021-11-22 21:52:58 -05:00
TorchedSammy
65435572d4
docs: clarify what a scope is 2021-11-22 19:40:00 -05:00
TorchedSammy
c0abeee648
docs: fixed heading size for bugfixes in 0.7 2021-11-22 19:38:55 -05:00
TorchedSammy
a38625d821
docs: changelog for 0.7 2021-11-22 19:38:06 -05:00
TorchedSammy
4e244e141f
fix: remove variables heading if there is none, account for global in new module doc format 2021-11-22 19:20:57 -05:00
TorchedSammy
f741c2709c
fix: check and print module isnt found instead of failing 2021-11-22 19:20:31 -05:00
TorchedSammy
179947cd98
fix: only add __docProp metatable from SetField function 2021-11-22 19:19:36 -05:00
TorchedSammy
43ddab699f
feat: add in shell documentation for module properties 2021-11-22 18:59:28 -05:00
TorchedSammy
538ba3547f
chore: reorder code 2021-11-22 18:58:30 -05:00
TorchedSammy
e67c549714
fix: get function docs for normal modules (regression from 52a6eb21252537fcdab32c99f2474b84c3e41f03) 2021-11-22 18:29:26 -05:00
TorchedSammy
812de48558
fix: completions not working with aliases commands (resolves #82) 2021-11-22 18:01:59 -05:00
TorchedSammy
52a6eb2125
docs: document available bait hooks 2021-11-22 16:36:32 -05:00
TorchedSammy
c61b428d67
fix: panic when error occurs in commander
check if commander has an error before trying to get a return code
2021-11-22 15:40:56 -05:00
TorchedSammy
af4c3885ae
feat: add signal hooks for sigint and sigwinch (#80) 2021-11-22 15:13:05 -05:00
TorchedSammy
94a8b4ad47
feat: add prependPath function (resolves #81) 2021-11-22 12:46:39 -05:00
TorchedSammy
72cf776882
fix: use golang path list separator to not be unix specific 2021-11-22 12:45:45 -05:00
TorchedSammy
123f8992b1
feat: add tab completion api
tab complete is better than it was before!
there is a new `complete` function which allows adding custom arguments
to complete specific functions.
hilbish will now also complete executables if it's the first input
argument (this also works with ./)
if no completion is added for a command, hilbish will just complete
files
2021-11-22 11:24:31 -05:00
TorchedSammy
77cc7fe24a
fix: only resize term if not running command 2021-11-22 10:41:27 -05:00
TorchedSammy
5a258ce68e
chore: bump version 2021-11-22 10:39:50 -05:00
TorchedSammy
35e648b7bc
style: remove extra whitespace 2021-11-21 18:50:35 -05:00
TorchedSammy
06272778f8
fix: say if no perms for executable instead of printing not found 2021-11-21 18:45:44 -05:00
sammyette
2f816c33cd
fix: revert "chore: update deps"
This reverts commit e06765abc386689817f9ec10b25be36830329d35.
broke builds
2021-10-30 23:08:29 -04:00
sammyette
9b66547803
docs: change urls to use new org name 2021-10-30 20:03:59 -04:00
sammyette
e06765abc3
chore: update deps 2021-10-30 20:01:07 -04:00
sammyette
2073752e7e
chore: merge from dev 2021-10-30 19:57:50 -04:00
sammyette
84ec3d085d
feat: add hilbish.read function
`hilbish.read` will read input from the user, using
hilbish's line editor library (hilbiline or readline)
2021-10-30 19:53:42 -04:00
sammyette
97a6e4baf2
feat: add hilbish.interactive and hilbish.login vars
these are to check from lua if hilbish is running an interactive or
login session
2021-10-30 19:44:40 -04:00
sammyette
174d67c9e1
chore: bump version 2021-10-21 22:54:23 -04:00
sammyette
c360ac7126
docs: add changelog for 0.6.1 2021-10-21 22:54:04 -04:00
sammyette
f46d4c7024
docs: just remove the vertical split 2021-10-21 22:41:48 -04:00
sammyette
d3c50aa227
docs: add newline before short description 2021-10-21 22:40:51 -04:00
sammyette
1ee8827c9c
docs: put short description above vertical split
this is the 420th commit! blaze it <o/
2021-10-21 22:38:20 -04:00
sammyette
54d88f9f6c
fix: use forked version of sh interp 2021-10-21 21:52:40 -04:00
sammyette
80acd0857d
fix(cd): use correct var 2021-10-21 20:55:54 -04:00
sammyette
c12fd1a8b4
fix: let sh interp handle registered commanders 2021-10-21 20:49:28 -04:00
sammyette
1a7dccb757
feat(cd): show path in error messages 2021-10-21 20:49:00 -04:00
sammyette
b008d48c60
fix: handle ctrl c properly when not interactive 2021-10-18 12:12:54 -04:00
sammyette
2cf979401b
feat: use dataDir in requirePaths 2021-10-17 23:14:18 -04:00
sammyette
87fcdd3c10
fix: remove / at the end of xdg data path 2021-10-17 23:13:53 -04:00
sammyette
9f523ba3c0
chore: fix merge conflict 2021-10-17 23:10:20 -04:00
sammyette
e08e3b9b94
fix: require paths 2021-10-17 23:09:48 -04:00
sammyette
00f41a95bc
fix: use dataDir var in requirePaths 2021-10-17 23:00:38 -04:00
sammyette
b1f4efd9ac
docs: remove links section 2021-10-17 22:43:58 -04:00
sammyette
212a52fd04
docs: fix link to nixos install info 2021-10-17 22:36:42 -04:00
legendofmiracles
0c7fadbaad
docs: add nix installation instructions (#78) 2021-10-17 22:34:43 -04:00
sammyette
a8ecd44efb
docs: add changelog for 0.6.0 2021-10-17 19:43:28 -04:00
sammyette
ce4ba48da0
feat: pass command string to command.exit, fix aliases with sh interp 2021-10-17 19:37:37 -04:00
sammyette
7a4cbbddff
fix(ansikit)!: return hyperlink ascii code instead of printing it 2021-10-17 19:19:43 -04:00
sammyette
72194898ba
fix: add back inspect 2021-10-17 18:51:44 -04:00
sammyette
3bd71828fa
fix: temporarily remove inspect 2021-10-17 18:51:25 -04:00
sammyette
7615e56ffd
feat: add cdr command
the cdr command will change to <index> directory from a list of 10
most recently moved to directories. this only works for the interactive
cd command, and not the fs.cd function.
you can find the list of recent directories with `cdr list`.
usage: `cdr <index>`
the `cdr help` command also gives this bit of info
2021-10-17 18:42:36 -04:00
sammyette
d51ae7d310
chore: update succulent 2021-10-17 18:39:14 -04:00
sammyette
3042fce50e
fix: cleanup since returned tables from functions aren't userdata anymore 2021-10-17 18:10:06 -04:00
sammyette
9b6ca1faf4
style: make modules underlined and colored 2021-10-17 18:09:42 -04:00
sammyette
b97e1efa8d
fix(cd): correctly report error 2021-10-17 17:55:41 -04:00
sammyette
86013e6576
fix: use RaiseError function from gopher-lua instead of Error 2021-10-17 17:55:21 -04:00
sammyette
51a68e24cf
chore: update succulent to fixed ver 2021-10-17 17:54:52 -04:00
sammyette
c95fb05fbf
fix: dont use luar to pass command args to commander 2021-10-17 17:46:26 -04:00
sammyette
006f0f986e
fix(fs): stop using luar, make readdir return a proper table 2021-10-17 17:26:29 -04:00
sammyette
7769d68859
style: use green instead of blue in doc command 2021-10-17 17:23:35 -04:00
sammyette
586566c595
chore: make changelog.md in uppercase 2021-10-17 17:17:53 -04:00
sammyette
1e76b1501f
fix: add back dataDir field to hilbish module 2021-10-17 17:16:49 -04:00
sammyette
7d9d3e4d72
style: make highlighted parts of docs underlined blue in doc command 2021-10-17 17:16:27 -04:00
sammyette
37610ad8b0
fix: remove extra newline on exit 2021-10-17 16:47:04 -04:00
sammyette
6271a7fc18
fix: use succulent in preload, remove string split from preload 2021-10-17 16:32:04 -04:00
sammyette
ad698b1a03
chore: bump version 2021-10-17 16:31:43 -04:00
sammyette
1b79abdab7
feat: add succulent lib 2021-10-17 16:31:31 -04:00
sammyette
7a3d9022e9
fix: add commonRequirePaths and linuxUserPaths to avoid repetition with custom require paths 2021-10-17 16:27:14 -04:00
sammyette
3d53e85fc9
feat: add terminal package
a simple, smaller but lower level terminal library, mainly used to set
raw mode. functions:
size, save and restore current state, set raw mode. documentation is in
docs/terminal.txt or `doc terminal` in hilbish
2021-10-17 16:10:57 -04:00
sammyette
85b347d5f3
feat(ansikit): add link function 2021-10-17 13:23:58 -04:00
sammyette
6b065dc035
fix(fs): make stat better
return a table with 4 values: name, size, mode and isDir
name -> name of path
size -> size (obviously)
mode -> permissions mode in a string as octal format
isDir -> whether path is a directory
2021-10-17 12:56:45 -04:00
sammyette
df70082a81
feat: add doc command (closes #76)
the `doc` command is a way to see hilbish documentation from
in the shell. for usage, just run the command
2021-10-16 15:42:55 -04:00
sammyette
4dd6db54fe
fix: stop using setField wrapper 2021-10-16 15:40:16 -04:00
sammyette
afd999a7b0
docs: add docs for functions 2021-10-16 15:38:49 -04:00
sammyette
54635072f6
fix(docgen): use better perm mask for output files and folder 2021-10-16 15:38:17 -04:00
sammyette
bd3e9fdca6
docs: make linebreaks to descriptions for better alignment 2021-10-16 15:36:30 -04:00
sammyette
784e611272
chore: remove unused setField func 2021-10-16 15:33:57 -04:00
sammyette
77b3dac1b1
build: add docs folder to makefile 2021-10-16 15:33:22 -04:00
sammyette
3b97b22f10
feat: add hilbish.dataDir var 2021-10-16 13:51:09 -04:00
sammyette
20acfad2c2
fix(fs)!: handle mkdir error, change error return for cd
breaking change: cd now returns a message instead of a code to indicate the error.
any error in mkdir is now handled
2021-10-16 13:49:01 -04:00
sammyette
539a39f83a
feat: add fs.readdir function
it takes 1 argument: the directory to read.
2021-10-16 13:47:39 -04:00
sammyette
452335d84a
fix: change luaErr to return string instead of code 2021-10-16 13:47:09 -04:00
sammyette
3cafbe8c4f
docs: document hilbish module functions, xdg vars, and add descriptions for modules 2021-10-16 12:41:10 -04:00
sammyette
a2f54b627b
feat: output docs to a docs folder, allow multiline docs 2021-10-16 12:38:46 -04:00
sammyette
71b72bbdd4
chore: move comments below package declaration 2021-10-16 11:31:01 -04:00
sammyette
1689d80721
feat: add docgen program, document almost all hilbish functions 2021-10-16 10:21:05 -04:00
sammyette
ecbcf9a968
feat: add docgen program 2021-10-15 23:58:56 -04:00
sammyette
f9133584d4
chore: add dataDir var 2021-10-14 19:46:25 -04:00
sammyette
e4833bdba9
feat: add command.preexec hook
it provides 2 arguments: what the user typed, and the command hilbish
will execute.
2021-10-14 08:51:29 -04:00
sammyette
63061e3a52
fix(bait): allow more than 1 argment for catch callback 2021-10-13 23:41:20 -04:00
sammyette
4596159b8f
feat: add command.precmd hook 2021-10-13 22:53:09 -04:00
sammyette
9eabe5323d
fix: throw command.exit with 0 code if input is nothing 2021-10-13 22:51:38 -04:00
sammyette
38233ccda4
feat: include inspect in hilbish libs
this provides the `inspect()` function for human readable tables
2021-10-13 19:29:10 -04:00
sammyette
7ac0e27739
fix: lib paths for ~/.config 2021-10-13 11:27:37 -04:00
sammyette
d2c720c863
fix: make lib paths in ~/.config/hilbish on linux 2021-10-13 10:50:38 -04:00
sammyette
0977110e79
feat: add default history dir to xdg dir, or fallback to home 2021-10-13 10:42:35 -04:00
sammyette
b387b18923
fix: properly default config dir to xdg dir 2021-10-13 10:41:55 -04:00
sammyette
d58617b173
docs: slight refactor of the readme 2021-10-12 16:01:17 -04:00
Gabriel Rato
c29b6c6fd4
fix: break for loop after finding the aliased command (#73) 2021-10-11 21:45:52 -04:00
sammyette
4808662893
chore: merge from dev 2021-10-09 11:39:02 -04:00
Angelo-F
22f33324e0
docs: add changelog.md (#72)
* docs: add changelog.md

* fix: Fix formatting in a section

* fix: changelog.md - remove stray line (l143) and bullet point (l34)
2021-10-09 11:15:25 -04:00
sammyette
cff7827ace
fix: trim extra whitespace from cd args
this fixed an issue with `cd -` not working
2021-10-08 09:49:57 -04:00
L3af
400dd2944d
feat: respect xdg directories (#71)
* feat: respect xdg directories

* fix: move xdg vars to table

Co-authored-by: L3af <ohhaon@icloud.com>
2021-10-07 20:58:07 -04:00
sammyette
144c082d3e
fix: change order of require paths
prevents using old outdated version of lunacolors if it isnt deleted
2021-09-30 00:15:35 -04:00
sammyette
2c10be0102
fix: add new require path 2021-09-30 00:01:03 -04:00
sammyette
37bc018a13
chore: update lunacolors 2021-09-29 23:56:16 -04:00
sammyette
630c0b0356
fix: dont trim spaces on cd dir args 2021-09-29 22:32:37 -04:00
sammyette
afcc6fe63a
fix: handle error case of target in fs.cd not being a dir (closes #66) 2021-09-28 22:55:08 -04:00
sammyette
a6a3962044
fix: correct url to github repo and add newline after error 2021-09-28 22:54:04 -04:00
sammyette
bc4e0f835f
fix: revert "fix: reuse sh runner"
This reverts commit 822b2876e9168e6ab53b67999e45291469c4258b.
this broke a few things with the shell so probably shouldnt do this yet
2021-09-25 22:46:06 -04:00
sammyette
c95b0b55be
fix: runtime errors on linux
this fixes out of bounds error since we tried to split the username
for '\' which is only valid on windows, so i added it for windows only
2021-09-25 21:39:06 -04:00
sammyette
7c815022a9
chore: merge from dev 2021-09-18 22:49:33 -04:00
sammyette
2ef2998279
fix: make timeout() blocking
may or may not be temporary
2021-09-18 22:48:28 -04:00
sammyette
196526cc6a fix: rename unix vars to linux 2021-07-08 17:55:19 -07:00
sammyette
5d78a0c574 feat: add compile vars for windows 2021-07-08 17:49:51 -07:00
sammyette
a3cc8160d3 fix: trim off hostname in %u verb for windows 2021-07-08 03:44:57 -07:00
sammyette
4caeb7ec91 feat: replace ~ in preloadPath and sampleConfPath with homedir 2021-07-08 03:44:11 -07:00
sammyette
822b2876e9
fix: reuse sh runner
this makes it so env variables persist, and some other stuff
builtin cd actually works now :]
2021-06-20 21:48:07 -04:00
245 changed files with 22462 additions and 1046 deletions

6
.editorconfig Normal file
View File

@ -0,0 +1,6 @@
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = tab

View File

@ -1,5 +1,5 @@
---
- [ ] I have reviewed CONTRIBUTING.md.
- [ ] My commits and title use the [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/) format.
- [ ] I have documented any breaking changes according to [SemVer](https://semver.org/).
- [ ] I have documented changes and additions in the CHANGELOG.md.
---

View File

@ -1,31 +1,64 @@
name: Build
on:
- push
- pull_request
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
name: ${{ matrix.build }}
runs-on: ${{ matrix.os }}
name: ${{ matrix.goos }}-${{ matrix.goarch }}
runs-on: ubuntu-latest
strategy:
matrix:
include:
- build: linux-amd64
os: ubuntu-latest
goos: [linux, windows, darwin]
goarch: ["386", amd64, arm64]
exclude:
- goarch: "386"
goos: darwin
- goarch: arm64
goos: windows
steps:
- name: Checkout sources
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Setup Go
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: '1.16.2'
go-version: '1.22.2'
- name: Download Task
run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d'
- name: Build
run: make hilbiline
- uses: actions/upload-artifact@v2
run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} ./bin/task
- uses: actions/upload-artifact@v4
if: matrix.goos == 'windows'
with:
name: hilbish-${{ matrix.build }}
path: hilbish
name: hilbish-${{ matrix.goos }}-${{ matrix.goarch }}
path: |
hilbish.exe
LICENSE
README.md
CHANGELOG.md
.hilbishrc.lua
nature
libs
docs
emmyLuaDocs
- uses: actions/upload-artifact@v4
if: matrix.goos != 'windows'
with:
name: hilbish-${{ matrix.goos }}-${{ matrix.goarch }}
path: |
hilbish
LICENSE
README.md
CHANGELOG.md
.hilbishrc.lua
nature
libs
docs
emmyLuaDocs

60
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,60 @@
name: CodeQL
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '38 2 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

29
.github/workflows/docs.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Generate docs
on:
push:
branches:
- master
jobs:
gen:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- uses: actions/setup-go@v5
- name: Download Task
run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d'
- name: Build
run: ./bin/task
- name: Run docgen (go-written)
run: go run cmd/docgen/docgen.go
- name: Run docgen (lua-written)
run: ./hilbish cmd/docgen/docgen.lua
- name: Commit new docs
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "docs: [ci] generate new docs"
file_pattern: docs/ emmyLuaDocs/

46
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,46 @@
name: Release
on:
push:
tags:
- v[0-9]+.*
jobs:
create-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: taiki-e/create-gh-release-action@v1
with:
title: Hilbish $tag
changelog: CHANGELOG.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
releases-matrix:
name: Build Release Binary
runs-on: ubuntu-latest
strategy:
matrix:
goos: [linux, windows, darwin]
goarch: ["386", amd64, arm64]
exclude:
- goarch: "386"
goos: darwin
- goarch: arm64
goos: windows
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Download Task
run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d'
- uses: wangyoucao577/go-release-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
ldflags: '-s -w'
binary_name: hilbish
extra_files: LICENSE README.md CHANGELOG.md .hilbishrc.lua nature libs docs emmyLuaDocs

54
.github/workflows/website.yml vendored Normal file
View File

@ -0,0 +1,54 @@
name: Build website
on:
push:
branches:
- master
tags:
- v[0-9]+.*
pull_request:
branches:
- master
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: '0.111.3'
extended: true
- name: Set branch name
id: branch
run: echo "BRANCH_NAME=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/*/}}" >> "$GITHUB_ENV"
- name: Fix base URL
if: env.BRANCH_NAME != 'master' && github.repository_owner == 'Rosettea'
run: sed -i "s%baseURL = 'https://rosettea.github.io/Hilbish/'%baseURL = 'https://rosettea.github.io/Hilbish/versions/${{ env.BRANCH_NAME }}'%" website/config.toml
- name: Build
run: 'cd website && hugo --minify'
- name: Deploy
if: env.BRANCH_NAME == 'master' && github.repository_owner == 'Rosettea'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./website/public
keep_files: true
- name: Deploy
if: env.BRANCH_NAME != 'master' && github.repository_owner == 'Rosettea'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./website/public
destination_dir: versions/${{ env.BRANCH_NAME }}
keep_files: true

4
.gitignore vendored
View File

@ -1,5 +1,9 @@
*.exe
hilbish
!docs/api/hilbish
docgen
!cmd/docgen
.vim
petals/
.hugo_build.lock

8
.gitmodules vendored
View File

@ -1,3 +1,9 @@
[submodule "libs/lunacolors"]
path = libs/lunacolors
url = https://github.com/Hilbis/Lunacolors
url = https://github.com/Rosettea/Lunacolors
[submodule "libs/succulent"]
path = libs/succulent
url = https://github.com/Rosettea/Succulent
[submodule "libs/inspect"]
path = libs/inspect
url = https://github.com/kikito/inspect.lua

View File

@ -1,19 +1,49 @@
-- Default Hilbish config
lunacolors = require 'lunacolors'
bait = require 'bait'
local hilbish = require 'hilbish'
local lunacolors = require 'lunacolors'
local bait = require 'bait'
local ansikit = require 'ansikit'
function doPrompt(fail)
prompt(lunacolors.format(
local unreadCount = 0
local running = false
local function doPrompt(fail)
hilbish.prompt(lunacolors.format(
'{blue}%u {cyan}%d ' .. (fail and '{red}' or '{green}') .. ''
))
end
print(lunacolors.format('Welcome to {magenta}Hilbish{reset}, {cyan}' .. hilbish.user
.. '{reset}.\n' .. 'The nice lil shell for {blue}Lua{reset} fanatics!\n'))
local function doNotifyPrompt()
if running or unreadCount == hilbish.messages.unreadCount() then return end
local notifPrompt = string.format('• %s unread notification%s', hilbish.messages.unreadCount(), hilbish.messages.unreadCount() > 1 and 's' or '')
unreadCount = hilbish.messages.unreadCount()
hilbish.prompt(lunacolors.blue(notifPrompt), 'right')
hilbish.timeout(function()
hilbish.prompt('', 'right')
end, 3000)
end
doPrompt()
bait.catch('command.exit', function(code)
doPrompt(code ~= 0)
bait.catch('command.preexec', function()
running = true
end)
bait.catch('command.exit', function(code)
running = false
doPrompt(code ~= 0)
doNotifyPrompt()
end)
bait.catch('hilbish.vimMode', function(mode)
if mode ~= 'insert' then
ansikit.cursorStyle(ansikit.blockCursor)
else
ansikit.cursorStyle(ansikit.lineCursor)
end
end)
bait.catch('hilbish.notification', function(notif)
doNotifyPrompt()
end)

853
CHANGELOG.md Normal file
View File

@ -0,0 +1,853 @@
# 🎀 Changelog
## Unreleased
### Added
- Forward/Right arrow key will fill in hint text (#327)
- The readline library adds the ability to create custom instances of the Hilbish
line editor. Now, `hilbish.editor` has been changed to a readline instance, instead of just being a table of a few functions to access it.
This means the colon operator is now the *preferred* way of accessing its functions,
and the dot operator will cause errors in 3.0.
Example: `hilbish.editor.getLine()` should be changed to `hilbish.editor:getLine()`
before 3.0
- Added the `hilbish.editor:read` and `hilbish.editor:log(text)` functions.
- `yarn` threading library (See the docs)
### Changed
- Documentation for Lunacolors has been improved, with more information added.
- Values returned by bait hooks will be passed to the `throw` caller
- `display` property to completion groups entries to style completion entries when type is `list`.
example:
```lua
local cg = {
items = {
'list item 1',
['--command-flag-here'] = {'this does a thing', '--the-flag-alias'},
['--styled-command-flag-here'] = {'this does a thing', '--the-flag-alias', display = lunacolors.blue '--styled-command-flag-here'}
},
type = 'list'
}
```
## [2.3.4] - 2024-12-28
### Fixed
- Skip over file and prevent panic if info cannot be retrieved during file completion (due to permission error or anything else)
- Apply environment variables properly after 2.3 shell interpreter changes
- hilbish.sink.readAll() function now reads data that doesn't end in a newline
## [2.3.3] - 2024-11-04
### Fixed
- Heredocs having issues
### Added
- Adding `\` at the end of input will add a newline and prompt for more input.
## [2.3.2] - 2024-07-30
### Fixed
- Command path searching due to 2.3 changes to the shell interpreter
## [2.3.1] - 2024-07-27
[hehe when you see it release](https://youtu.be/AaAF51Gwbxo?si=rhj2iYuQRkqDa693&t=64)
### Added
- `hilbish.opts.tips` was added to display random tips on start up.
Displayed tips can be modified via the `hilbish.tips` table.
### Fixed
- Fix a minor regression related to the cd command not working with relative paths
- Updated the motd for 2.3
## [2.3.0] - 2024-07-20
### Added
- `commander.registry` function to get all registered commanders.
- `fs.pipe` function to get a pair of connected files (a pipe).
- Added an alternative 2nd parameter to `hilbish.run`, which is `streams`.
`streams` is a table of input and output streams to run the command with.
It uses these 3 keys:
- `input` as standard input for the command
- `out` as standard output
- `err` as standard error
Here is a minimal example of the new usage which allows users to now pipe commands
directly via Lua functions:
```lua
local fs = require 'fs'
local pr, pw = fs.pipe()
hilbish.run('ls -l', {
stdout = pw,
stderr = pw,
})
pw:close()
hilbish.run('wc -l', {
stdin = pr
})
```
### Changed
- The `-S` flag will be set to Hilbish's absolute path
- Hilbish now builds on any Unix (if any dependencies also work, which should.)
### Fixed
- Fix ansi attributes causing issues with text when cut off in greenhouse
- Fix greenhouse appearing on terminal resize
- Fix crashes when history goes out of bounds when using history navigation
- `exec` command should return if no arg presented
- Commanders can now be cancelled by Ctrl-C and wont hang the shell anymore.
See [issue 198](https://github.com/Rosettea/Hilbish/issues/198).
- Shell interpreter can now preserve its environment and set PWD properly.
## [2.2.3] - 2024-04-27
### Fixed
- Highligher and hinter work now, since it was regressed from the previous minor release.
- `cat` command no longer prints extra newline at end of each file
### Added
- `cat` command now reads files in chunks, allowing for reading large files
## [2.2.2] - 2024-04-16
### Fixed
- Line refresh fixes (less flicker)
- Do more checks for a TTY
- Panic if ENOTTY is thrown from readline
- use `x/term` function to check if a terminal
### Added
- Page Up/Down keybinds for Greenhouse will now scroll up and down the size of the region (a page)
### Changed
- Remove usage of `hilbish.goro` in Greenhouse.
- Values in `hilbish` table are no longer protected. This means
they can be overridden. (#287)
## [2.2.1] - 2023-12-26
### Fixed
- Removed a left over debug print
- Recover panic in `hilbish.goro`
## [2.2.0] - 2023-12-25
### Added
- [Native Modules](https://rosettea.github.io/Hilbish/docs/api/hilbish/hilbish.module/)
- Made a few additions to the sink type:
- `read()` method for retrieving input (so now the `in` sink of commanders is useful)
- `flush()` and `autoFlush()` related to flushing outputs
- `pipe` property to check if a sink with input is a pipe (like stdin)
- Add fuzzy search to history search (enable via `hilbish.opts.fuzzy = true`)
- Show indexes on cdr list and use ~ for home directory.
- Fix doc command not displaying correct subdocs when using shorthand api doc access (`doc api hilbish.jobs` as an example)
- `hilbish.messages` interface (details in [#219])
- `hilbish.notification` signal when a message/notification is sent
- `notifyJobFinish` opt to send a notification when background jobs are
- `hilbish.goVersion` for the version of Go used to compile Hilbish.
completed.
- Allow numbered arg substitutions in aliases.
- Example: `hilbish.alias('hello', 'echo %1 says hello')` allows the user to run `hello hilbish`
which will output `hilbish says hello`.
- Greenhouse
- Greenhouse is a pager library and program. Basic usage is `greenhouse <file>`
- Using this also brings enhancements to the `doc` command like easy
navigation of neighboring doc files.
Ctrl-N can be used for the table of contents, which views adjacent documentation.
### Changed
- Documentation for EVERYTHING has been improved, with more
information added, code example, parameter details, etc.
You can see the improvements!
- Documentation has gotten an uplift in the `doc` command.
This includes:
- Proper highlighting of code
- Paging (via Greenhouse)
- Highlighting more markdown things
### Fixed
- Fix panic when runner doesn't return a table
- Fix edge case of crash on empty alias resolve
- File completion on Windows
- Job management commands work now
- Fix infinite loop when navigating history without any history. [#252](https://github.com/Rosettea/Hilbish/issues/252)
- Return the prefix when calling `hilbish.completions.call`. [#219](https://github.com/Rosettea/Hilbish/issues/219)
- Replaced `sed` in-place editing with `grep` and `mv` for compatibility with BSD utils
## [2.1.2] - 2022-04-10
### Removed
- Bad april fools code ;(
## [2.1.1] - 2022-04-01
### Added
- Validation checks for command input
- Improved runtime performance
- Validate Lua code
## [2.1.0] - 2022-02-10
### Added
- Documented custom userdata types (Job and Timer Objects)
- Coming with this fix is also adding the return types for some functions that were missing it
- Added a dedicated input and dedicated outputs for commanders (sinks - info at `doc api commander`).
- Local docs is used if one of Hilbish's branches is found
- Return 1 exit code on doc not found
- `hilbish.runner.getCurrent()` to get the current runner
- Initialize Hilbish Lua API before handling signals
### Fixed
- `index` or `_index` subdocs should not show up anymore
- `hilbish.which` not working correctly with aliases
- Commanders not being able to pipe with commands or any related operator.
- Resolve symlinks in completions
- Updated `runner-mode` docs
- Fix `hilbish.completion` functions panicking when empty input is provided
## [2.0.1] - 2022-12-28
### Fixed
- Corrected documentation for hooks, removing outdated `command.no-perm`
- Fixed an issue where `cd` with no args would not update the old pwd
- Tiny documentation enhancements for the `hilbish.timer` interface
## [2.0.0] - 2022-12-20
**NOTES FOR USERS/PACKAGERS UPDATING:**
- Hilbish now uses [Task] insead of Make for builds.
- The doc format has been changed from plain text to markdown.
**YOU MUST reinstall Hilbish to remove the duplicate, old docs.**
- Hilbish will by default install to **`/usr/local`** instead of just `/usr/`
when building via Task. This is mainly to avoid conflict of distro packages
and local installs, and is the correct place when building from git either way.
To keep Hilbish in `/usr`, you must have `PREFIX="/usr/"` when running `task build` or `task install`
- Windows is no longer supported. It will build and run, but **will** have problems.
If you want to help fix the situation, start a discussion or open an issue and contribute.
[Task]: https://taskfile.dev/#/
### Added
- Inline hints, akin to fish and the others.
To make a handler for hint text, you can set the `hilbish.hinter` function.
For more info, look at its docs with the `doc hilbish` command.
- Syntax highlighting function. To make a handler for it, set
`hilbish.highlighter`. Same thing as the hinter, check `doc hilbish` for
more info/docs.
- Ctrl+K deletes from the cursor to the end of the line. ([#128](https://github.com/Rosettea/Hilbish/pull/128))
- Alt+Backspace as an alternative of Ctrl+W to delete a word. ([#132](https://github.com/Rosettea/Hilbish/pull/132))
- Enhanced timer API (`doc timers`)
- Don't exit until intervals are stopped/finished when running a non interactive script.
- Ctrl+D deletes character below cursor if line isn't empty instead of exiting.
- Ctrl+Delete to forward delete a word.
- Right prompt ([#140](https://github.com/Rosettea/Hilbish/pull/140))
- Ctrl+_ to undo in Emacs input mode.
- Emacs style forward/backward word keybinds ([#139](https://github.com/Rosettea/Hilbish/pull/139))
- `hilbish.completion.call` to call a completion handler (`doc completions`)
- `hilbish.completion.handler` to set a custom handler for completions. This
is for everything/anything as opposed to just adding a single command completion.
[#122](https://github.com/Rosettea/Hilbish/issues/122)
- `fs.abs(path)` to get absolute path.
- Nature module (`doc nature`)
- `hilbish.jobs.add(cmdstr, args, execPath)` to add a job to the job table.
`cmdstr` would be user input, `args` is the args for the command (includes arg0)
and `execPath` is absolute path to command executable
- `job.add` hook is thrown when a job is added. acts as a unique hook for
jobs
- `hilbish.jobs.disown(id)` and `disown` builtin to disown a job. `disown`
without arguments will disown the last job.
- `hilbish.jobs.last()` returns the last added job.
- Job output (stdout/stderr) can now be obtained via the `stdout` and `stderr`
fields on a job object.
- Documentation for jobs is now available via `doc jobs`.
- `hilbish.alias.resolve(cmdstr)` to resolve a command alias.
- `hilbish.opts` for shell options.
- `hilbish.editor` interface for interacting with the line editor that
Hilbish uses.
- `hilbish.vim` interface to dynamically get/set vim registers.
Example usage: `hilbish.vim.registers['a'] = 'hello'`. You can also
get the mode with it via `hilbish.vim.mode`
- `hilbish.version` interface for more info about Hilbish's version. This
includes git commit, branch, and (new!!) release name.
- Added `fg` and `bg` builtins
- `job.foreground()` and `job.background()`, when `job` is a job object,
foreground and backgrounds a job respectively.
- Friendlier functions to the `hilbish.runner` interface, which also allow
having and using multiple runners.
- A few new functions to the `fs` module:
- `fs.basename(path)` gets the basename of path
- `fs.dir(path)` gets the directory part of path
- `fs.glob(pattern)` globs files and directories based on patterns
- `fs.join(dirs...)` joins directories by OS dir separator
- .. and 2 properties
- `fs.pathSep` is the separator for filesystem paths and directories
- `fs.pathListSep` is the separator for $PATH env entries
- Lua modules located in `hilbish.userDir.data .. '/hilbish/start'` (like `~/.local/share/hilbish/start/foo/init.lua`)
will be ran on startup
- `hilbish.init` hook, thrown after Hilbish has initialized Lua side
- Message of the day on startup (`hilbish.motd`), mainly intended as quick
small news pieces for releases. It is printed by default. To disable it,
set `hilbish.opts.motd` to false.
- `history` opt has been added and is true by default. Setting it to false
disables commands being added to history.
- `hilbish.rawInput` hook for input from the readline library
- Completion of files in quotes
- A new and "safer" event emitter has been added. This causes a performance deficit, but avoids a lot of
random errors introduced with the new Lua runtime (see [#197])
- `bait.release(name, catcher)` removes `handler` for the named `event`
- `exec`, `clear` and `cat` builtin commands
- `hilbish.cancel` hook thrown when user cancels input with Ctrl-C
- 1st item on history is now inserted when history search menu is opened ([#148])
- Documentation has been improved vastly!
[#148]: https://github.com/Rosettea/Hilbish/issues/148
[#197]: https://github.com/Rosettea/Hilbish/issues/197
### Changed
- **Breaking Change:** Upgraded to Lua 5.4.
This is probably one of (if not the) biggest things in this release.
To recap quickly on what matters (mostly):
- `os.execute` returns 3 values instead of 1 (but you should be using `hilbish.run`)
- I/O operations must be flushed (`io.flush()`)
- **Breaking Change:** MacOS config paths now match Linux.
- Overrides on the `hilbish` table are no longer permitted.
- **Breaking Change:** Runner functions are now required to return a table.
It can (at the moment) have 4 variables:
- `input` (user input)
- `exitCode` (exit code)
- `error` (error message)
- `continue` (whether to prompt for more input)
User input has been added to the return to account for runners wanting to
prompt for continued input, and to add it properly to history. `continue`
got added so that it would be easier for runners to get continued input
without having to actually handle it at all.
- **Breaking Change:** Job objects and timers are now Lua userdata instead
of a table, so their functions require you to call them with a colon instead
of a dot. (ie. `job.stop()` -> `job:stop()`)
- All `fs` module functions which take paths now implicitly expand ~ to home.
- **Breaking Change:** `hilbish.greeting` has been moved to an opt (`hilbish.opts.greeting`) and is
always printed by default. To disable it, set the opt to false.
- **Breaking Change:** `command.no-perm` hook has been replaced with `command.not-executable`
- History is now fetched from Lua, which means users can override `hilbish.history`
methods to make it act how they want.
- `guide` has been removed. See the [website](https://rosettea.github.io/Hilbish/)
for general tips and documentation
### Fixed
- If in Vim replace mode, input at the end of the line inserts instead of
replacing the last character.
- Make forward delete work how its supposed to.
- Prompt refresh not working properly.
- Crashing on input in xterm. ([#131](https://github.com/Rosettea/Hilbish/pull/131))
- Make delete key work on st ([#131](https://github.com/Rosettea/Hilbish/pull/131))
- `hilbish.login` being the wrong value.
- Put full input in history if prompted for continued input
- Don't put alias expanded command in history (sound familiar?)
- Handle cases of stdin being nonblocking (in the case of [#136](https://github.com/Rosettea/Hilbish/issues/136))
- Don't prompt for continued input if non interactive
- Don't insert unhandled control keys.
- Handle sh syntax error in alias
- Use invert for completion menu selection highlight instead of specific
colors. Brings an improvement on light themes, or themes that don't follow
certain color rules.
- Home/End keys now go to the actual start/end of the input.
- Input getting cut off on enter in certain cases.
- Go to the next line properly if input reaches end of terminal width.
- Cursor position with CJK characters has been corrected ([#145](https://github.com/Rosettea/Hilbish/pull/145))
- Files with same name as parent folder in completions getting cut off [#130](https://github.com/Rosettea/Hilbish/issues/130))
- `hilbish.which` now works with commanders and aliases.
- Background jobs no longer take stdin so they do not interfere with shell
input.
- Full name of completion entry is used instead of being cut off
- Completions are fixed in cases where the query/line is an alias alone
where it can also resolve to the beginning of command names.
(reference [this commit](https://github.com/Rosettea/Hilbish/commit/2790982ad123115c6ddbc5764677fdca27668cea))
for explanation.
- Jobs now throw `job.done` and set running to false when stopped via
Lua `job.stop` function.
- Jobs are always started in sh exec handler now instead of only successful start.
- SIGTERM is handled properly now, which means stopping jobs and timers.
- Fix panic on trailing newline on pasted multiline text.
- Completions will no longer be refreshed if the prompt refreshes while the
menu is open.
- Print error on search fail instead of panicking
- Windows related fixes:
- `hilbish.dataDir` now has tilde (`~`) expanded.
- Arrow keys now work on Windows terminals.
- Escape codes now work.
- Escape percentage symbols in completion entries, so you will no longer see
an error of missing format variable
- Fix an error with sh syntax in aliases
- Prompt now works with east asian characters (CJK)
- Set back the prompt to normal after exiting the continue prompt with ctrl-d
- Take into account newline in input when calculating input width. Prevents
extra reprinting of the prompt, but input with newlines inserted is still a problem
- Put cursor at the end of input when exiting $EDITOR with Vim mode bind
- Calculate width of virtual input properly (completion candidates)
- Users can now tab complete files with spaces while quoted or with escaped spaces.
This means a query of `Files\ to\ ` with file names of `Files to tab complete` and `Files to complete`
will result in the files being completed.
- Fixed grid menu display if cell width ends up being the width of the terminal
- Cut off item names in grid menu if its longer than cell width
- Fix completion search menu disappearing
- Make binary completion work with bins that have spaces in the name
- Completion paths having duplicated characters if it's escaped
- Get custom completion command properly to call from Lua
- Put proper command on the line when using up and down arrow keys to go through command history
- Don't do anything if length of input rune slice is 0 ([commit for explanation](https://github.com/Rosettea/Hilbish/commit/8d40179a73fe5942707cd43f9c0463dee53eedd8))
## [2.0.0-rc1] - 2022-09-14
This is a pre-release version of Hilbish for testing. To see the changelog,
refer to the `Unreleased` section of the [full changelog](CHANGELOG.md)
(version 2.0.0 for future reference).
## [1.2.0] - 2022-03-17
### Added
- Job Management additions
- `job.start` and `job.done` hooks (`doc hooks job`)
- `hilbish.jobs` interface (`get(id)` function gets a job object via `id`, `all()` gets all)
- Customizable runner/exec mode
- However Hilbish runs interactive user input can now be changed Lua side (`doc runner-mode`)
### Changed
- `vimMode` doc is now `vim-mode`
### Fixed
- Make sure input which is supposed to go in history goes there
- Cursor is right at the end of input on history search
## [1.1.0] - 2022-03-17
### Added
- `hilbish.vimAction` hook (`doc vimMode actions`)
- `command.not-executable` hook (will replace `command.no-perm` in a future release)
### Fixed
- Check if interactive before adding to history
- Escape in vim mode exits all modes and not only insert
- Make 2nd line in prompt empty if entire prompt is 1 line
- Completion menu doesnt appear if there is only 1 result
- Ignore SIGQUIT, which caused a panic unhandled
- Remove hostname in greeting on Windows
- Handle PATH binaries properly on Windows
- Fix removal of dot in the beginning of folders/files that have them for file complete
- Fix prompt being set to the continue prompt even when exited
## [1.0.4] - 2022-03-12
### Fixed
- Panic when history directory doesn't exist
## [1.0.3] - 2022-03-12
### Fixed
- Removed duplicate executable suggestions
- User input is added to history now instead of what's ran by Hilbish
- Formatting issue with prompt on no input
## [1.0.2] - 2022-03-06
### Fixed
- Cases where Hilbish's history directory doesn't exist will no longer cause a panic
## [1.0.1] - 2022-03-06
### Fixed
- Using `hilbish.appendPath` will no longer result in string spam (debugging thing left being)
- Prompt gets set properly on startup
## [1.0.0] - 2022-03-06
### Added
- MacOS is now officialy supported, default compile time vars have been added
for it
- Windows is properly supported as well
- `catchOnce()` to bait - catches a hook once
- `hilbish.aliases` interface - allows you to add, delete and list all aliases
with Lua
- `hilbish.appendPath()` can now take a table of arguments for ease of use
- `hilbish.which(binName)` acts as the which builtin for other shells,
it finds the path to `binName` in $PATH
- Signal hooks `sigusr1` and `sigusr2` (unavailable on Windows)
- Commands starting with a space won't be added to history
- Vim input mode
- Hilbish's input mode for text can now be changed to either Emacs
(like it always was) or Vim via `hilbish.inputMode()`
- Changing Vim mode throws a `hilbish.vimMode` hook
- The current Vim mode is also accessible with the `hilbish.vimMode` property
- Print errors in `hilbish.timeout()` and `hilbish.goro()` callbacks
- `hilbish.exit` hook is thrown when Hilbish is going to exit
- `hilbish.exitCode` property to get the exit code of the last executed command
- `screenMain` and `screenAlt` functions have been added to Ansikit to switch
to the terminal's main and alt buffer respectively
### Fixed
- Tab completion for executables
- Stop interval (`hilbish.interval()`) when an error occurs
- Errors in bait hooks no longer cause a panic, and remove the handler for the hook as well
- Formatting of home dir to ~
- Check if Hilbish is in interactive before trying to use its handlers for signals
- Global `args` table when running as script is no longer userdata
- Home dir is now added to recent dirs (the case of cd with no arg)
- `index` subdoc will no longer appear
- Alias expansion with quotes
- Add full command to history in the case of incomplete input
- `hilbish.exec()` now has a windows substitute
- Fixed case of successful command after prompted for more input not writing to history
- `command.exit` is thrown when sh input is incorrect and when command executed after continue
prompt exits successfully
### Changed
- The minimal config is truly minimal now
- Default config is no longer copied to user's config and is instead ran its location
#### Breaking Changes
(there were a lot...)
- Change default SHLVL to 0 instead of 1
- ~/.hilbishrc.lua will no longer be run by default, it now
only uses the paths mentioned below.
- Changed Hilbish's config path to something more suited
according to the OS (`$XDG_CONFIG_HOME/hilbish/init.lua` on Linux,
`~/Library/Application Support/hilbish/init.lua` on MacOS and
(`%APPDATA%/hilbish/init.lua` on Windows). Previously on Unix-like it was
`$XDG_CONFIG_HOME/hilbish/hilbishrc.lua`
- The history path has been changed to a better suited path.
On Linux, it is `$XDG_DATA_HOME/hilbish/.hilbish-history` and for others it is
the config path.
- `hilbish.xdg` no longer exists, use `hilbish.userDir` instead,
as it functions the same but is OS agnostic
- `hilbish.flag()` has been removed
- `~/.hprofile.lua` has been removed, instead check in your config if `hilbish.login`
is true
- `hilbish.complete()` has had a slight refactor to fit with the new readline library.
It now expects a table of "completion groups" which are just tables with the
`type` and `items` keys. Here is a (more or less) complete example of how it works now:
```lua
hilbish.complete('command.git', function()
return {
{
items = {
'add',
'clone'
},
type = 'grid'
},
{
items = {
['--git-dir'] = {'Description of flag'},
'-c'
},
type = 'list'
}
}
end)
```
Completer functions are now also expected to handle subcommands/subcompletions
## [0.7.1] - 2021-11-22
### Fixed
- Tab complete absolute paths to binaries properly
- Allow execution of absolute paths to binaries (https://github.com/Rosettea/Hilbish/commit/06272778f85dad04e0e7abffc78a5b9b0cebd067 regression)
## [0.7.0] - 2021-11-22
### Added
- `hilbish.interactive` and `hilbish.login` properties to figure out if Hilbish is interactive or a login shell, respectively.
- `hilbish.read` function to take input more elegantly than Lua's `io.read`
- Tab Completion Enhancements
- A new tab complete API has been added. It is the single `complete` function which takes a "scope" (example: `command.<cmdname>`) and a callback which is
expected to return a table. Users can now add custom completions for specific commands.
An example is:
```lua
complete('command.git', function()
return {
'add',
'version',
commit = {
'--message',
'--verbose',
'<file>'
}
}
end)
```
For `git`, Hilbish will complete commands add, version and commit. For the commit subcommand, it will complete the flags and/or files which `<file>` is used to represent.
- Hilbish will now complete binaries in $PATH, or any executable to a path (like `./` or `../`)
- Files with spaces will be automatically put in quotes and completions will work for them now.
- `prependPath` function (#81)
- Signal hooks (#80)
- This allows scripts to add their own way of handling terminal resizes (if you'd need that) or Ctrl-C
- Module properties (like `hilbish.ver`) are documented with the `doc` command.
- Document bait hooks
### Fixed
- The prompt won't come up on terminal resize anymore.
- `appendPath` should work properly on Windows.
- A panic when a commander has an error has been fixed.
## [0.6.1] - 2021-10-21
### Fixed
- Require paths now use the `dataDir` variable so there is no need to change it anymore unless you want to add more paths
- Remove double slash in XDG data require paths
- Ctrl+C is handled properly when not interactive and won't result in a panic anymore
- Commanders are handled by the sh interpreter library only now, so they work with sh syntax
### Changed
- Error messages from `fs` functions now include the path provided
## [0.6.0] - 2021-10-17
### Added
- Hilbish will expand `~` in the preloadPath and samplePathConf variables. These are for compile time.
- On Windows, the hostname in `%u` has been removed.
- Made it easier to compile on Windows by adding Windows-tailored vars and paths.
- Add require paths `./libs/?/?.lua`
- Hilbish will now respect $XDG_CONFIG_HOME and will load its config and history there first and use Lua libraries in there and $XDG_DATA_HOME if they are set. (#71)
- If not, Hilbish will still default to `~`
- Added some new hooks
- `command.precmd` is thrown right before Hilbish prompts for input
- `command.preexec` is thrown right before Hilbish executes a command. It passes 2 arguments: the command as the user typed, and what Hilbish will actually execute (resolved alias)
- `hilbish.dataDir` is now available to know the directory of Hilbish data files (default config, docs, preload, etc)
- A `docgen` program has been added to `cmd/docgen` in the GitHub repository, As the name suggests, it will output docs in a `docs` folder for functions implemented in Go
- All hilbish modules/libraries now have a `__doc` metatable entry which is simply a short description of the module.
- `fs.readdir(dir)` has been added. It will return a table of files in `dir`
- Errors in the `fs.mkdir` function are now handled.
- **Breaking Change:** `fs.cd` no longer returns a numeric code to indicate error. Instead, it returns an error message.
- The `doc` command has been added to document functions of Hilbish libraries. Run the command for more details.
- `link(url, text)` has been added to `ansikit`. It returns a string which can be printed to produce a hyperlink in a terminal. Note that not all terminals support this feature.
- The [Succulent](https://github.com/Rosettea/Succulent) library has been added. This includes more utility functions and expansions to the Lua standard library itself.
- The command string is now passed to the `command.exit` hook
### Changed
- Hilbish won't print an extra newline at exit with ctrl + d
- `command.exit` with 0 exit code will now be thrown if input is nothing
- **Breaking Change:** `fs.stat` has been made better. It returns a proper table instead of userdata, and has fields instead of functions
- It includes `name`, `mode` as a octal representation in a string, `isDir`, and `size`
### Fixed
- `timeout()` is now blocking
- Directories with spaces in them can now be `cd`'d to
- An alias with the same name as the command will now not cause a freeze (#73)
- Userdata is no longer returned in the following cases:
- Commander arguments
- `fs` functions
## [0.5.1] - 2021-06-16
### Added
- Add `~/.config/hilbish` as a require path
### Changed
- `cd` hook is only thrown after directory has actually changed
### Fixed
- Handle error in commander properly, preventing a panic from Lua
## [0.5.0] - 2021-06-12
An absolutely massive release. Probably the biggest yet, includes a bunch of fixes and new features and convenient additions to the Lua API.
### Added
- `-n` flag, which checks Lua for syntax errors without running it
- `exec(command)` function, acts like the `exec` builtin in sh
- Example: `exec 'awesome'` in an .xinitrc file with Hilbish as shebang
- Commands from commander can now `return` an exit code
```lua
commander.register('false', function()
return 1
end)
```
When `false` is run, it will have the exit code of `1`, this is shorter/easier than throwing the command.exit hook and can work if the functionality of that changes
- Added `-c` description
- `args` variable, set when Hilbish runs a Lua script. It is an array that includes the execute path as the first argument
- Lua code can be aliased
- Recursive aliases
- At the moment this only works for the first argument
- Hilbish can now be used with Hilbiline if compiled to do so (currently only for testing purposes)
- `goro(func)` runs a `func`tion in a goroutine. With channels that gopher-lua also provides, one can do parallelism and concurrency in Lua (but go style).
- `coroutine` no those dont exist they dont matter `goro` is easier
- `cd -` will change to the previous directory
- `hilbish.cwd()` gets the current working directory
- `timeout(func, time)` works exactly like the `setTimeout` function in JavaScript. It will run `func` after a period of `time` in milliseconds.
- `interval(func, time)` works exactly like the `setInterval` function in JavaScripit. It will run `func` every `time` milliseconds
- `hilbish.home` is a crossplatform Lua alternative to get the home directory easily.
- `commander.deregister(cmdName)` de-registers any command defined with commander.
### Changed
- **Breaking Change**: Move `_user` and `_ver` to a global `hilbish` table
- Accessing username and Hilbish version is now done with `hilbish.user` and `hilbish.ver`
- `hilbish.run(cmd)` runs cmd with Hilbish's sh interpreter. Using this function instead of `os.execute` ensures that sh syntax works everywhere Hilbish does.
- `hilbish.flag(flag)` checks if flag has been passed to Hilbish.
- Aliases now work with every command and not only the first one
- Therefore `alias1; alias2` works now
- `command.not-found` hook
- `$SHLVL` is now incremented in Hilbish. If not a valid number, it will be changed to 1
- `fs.mkdir` can now make directories recursively if the 2nd argument is set to `true`
- `fs.mkdir('path/to/dir', true)`
- Hilbish runs a `preload.lua` file in the current directory first, then falls back to the global preload. Before the order was reversed.
- Check if aliased command is defined in Lua, so registered `commander`s can be aliased
- Add input to history before alias expansion. Basically, this adds the actual alias to history instead of the aliased command.
- Global preload path, require paths, default config directory and sample config directory can now be changed at compile time to help support other systems.
### Fixed
- `cd` now exits with code `1` instead of the error code if it occurs
- Don't append directory to $PATH with `appendPath` if its already there
- Continued input is no longer joined with a space unless explicitly wanted
- Hilbish won't try to go interactive if it isn't launched in a TTY (terminal)
- Ctrl+D on a continue prompt with no input no longer causes a panic
- Actually handle the `-h`/`--help` option
## [0.4.0] - 2021-05-01
### Added
- Ctrl C in the prompt now cancels/clear input (I've needed this for so long also)
- Made Hilbish act like a login shell on login
- If Hilbish is the login shell, or the `-l`/`--login` flags are used, Hilbish will use an additional `~/.hprofile.lua` file, you can use this to set environment variables once on login
- `-c` has been added to run a single command (this works exactly like being in the prompt would, so Lua works as well)
- `-i` (also `--interactive`) has been added to force Hilbish to be an interactive shell in cases where it usually wont be (like with `-c`)
- Use readline in continue prompt
- Added a `mulitline` hook that's thrown when in the continue/multiline prompt
- Added `appendPath` function to append a directory to `$PATH`
- `~` will be expanded to `$HOME` as well
- A utility `string.split` function is now added
- `string.split(str, delimiter)`
- Added a `_user` variable to easily get current user's name
### Changed
- **BREAKING Change**: [Lunacolors](https://github.com/Hilbis/Lunacolors) has replaced ansikit for formatting colors, which means the format function has been removed from ansikit and moved to Lunacolors.
- Users must replace ansikit with `lunacolors` in their config files
- A getopt-like library is now used for command line flag parsing
- `cd` builtin now supports using environment variables
- This means you can now `cd $NVM_DIR` as an example
- Function arguments are now more strictly typed (`prompt(nil)` wouldnt work now)
- Other general code/style changes
## Fixed
- Fix makefile adding Hilbish to `/etc/shells` on every `make install`
Since Lunacolors is a submodule, you may just want to completely reclone Hilbish recursively and then update (rerun `make install`)
Or instead of recloning, run `git submodule update --init --recursive` in Hilbish's git directory
## [0.3.2] - 2021-04-10
### Added
- Add more functions to `ansikit` module
- Add functions `stat` and `mkdir` to `fs` module
- `-C` flag to define path to config
- Add require path `~/.local/share/hilbish/libs`
### Changed
- Continue to new line if output doesnt end with it
Observed:
![Observed](https://camo.githubusercontent.com/5be15fed950a2926e6f14dfe4427b84b7c0c448d5d937f9df15959ca934a50ce/68747470733a2f2f6d6f646575732e69732d696e736964652e6d652f70633335416133492e706e67)
## [0.3.1] - 2021-04-06
### Fixed
- Fix `%u` in prompt format being full name and instead make it actually username
## [0.3.0] - 2021-04-05
### Added
- Added a `multiprompt` function to change the prompt of the multiline/continuation/newline prompt
- `_ver` variable to get Hilbish's version from Lua
### Changed
- **BREAKING Change**: Removed Bait hooks `command.success` and `command.fail`, there is now the single hook `command.exit`, with a single argument passed which the exit code of the command. Use this to determine if a command has failed or not (failure is code != 0)
- **BREAKING Change**: The Ansikit function `text` has been renamed to `format`.
- `fs.cd` now throws an exception instead of silently failing, which you should handle with `pcall`
- Enhancements to the `cd` command:
- With no arguments will move to $HOME
- Now throws a cd hook, with a single hook arg being the arguments to the command
- Now works for directories with spaces
- Lua input now throws a success hook if it succeeded
- Command history is now saved to `~/.hilbish-history`
- Globals defined in Lua that are strings will be defined as an env variable ([#16](https://github.com/Rosettea/Hilbish/pull/16))
- Input ending with `\` will now go to a newline
- `exit` command is now written in Lua
### Fixed
- Input is now trimmed
- Internals are slightly cleaned up and codebase split up
- Hilbish will now fall back to a builtin minimal config if the user's config has syntax errors on loading
- Commands defined in Lua now report the error to the user cleanly instead of panicking if it has occured
## [0.2.0] - 2021-03-31
### Added
- Hooks (events) are the new and main thing in v0.2, you can now listen for hooks or cast out (emit) custom ones, via the [bait](https://github.com/Hilbis/Hilbish/wiki/Bait) package
- `^^` to refer to the previous command. It's for the lazy hands like me, so I can do something like `ENV=VAR ^^`
- Way more (more like any) comments in the core code.
### Changed
- Prompt has been changed to have printf-like verbs to format. This makes it easier on the user's side to configure, and doesn't require hooks to change it for things like current directory.
- Default prompt's changed and the triangle changes color based on if command failed or not.
## [0.1.2] - 2021-03-24
### Added
- Add Lua input to history
## [0.1.1] - 2021-03-24
### Added
- Go to new line if sh input is incomplete
```bash
> for i in {1..5}
```
This input for example will prompt for more input to complete:
![input](https://camo.githubusercontent.com/b757e474da5880d57be135087f59f45ab214b8f39f182b299d861cac7b6d84ff/68747470733a2f2f6d6f646575732e69732d696e736964652e6d652f30624456547461352e706e67)
## [0.1.0] - 2021-03-24
### Added
- Tab complete files
- Makefile installation
- sh support
## [0.0.12] - 2021-03-21
First "stable" release of Hilbish.
[2.3.4]: https://github.com/Rosettea/Hilbish/compare/v2.3.3...v2.3.4
[2.3.3]: https://github.com/Rosettea/Hilbish/compare/v2.3.2...v2.3.3
[2.3.2]: https://github.com/Rosettea/Hilbish/compare/v2.3.1...v2.3.2
[2.3.1]: https://github.com/Rosettea/Hilbish/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/Rosettea/Hilbish/compare/v2.2.3...v2.3.0
[2.2.3]: https://github.com/Rosettea/Hilbish/compare/v2.2.2...v2.2.3
[2.2.2]: https://github.com/Rosettea/Hilbish/compare/v2.2.1...v2.2.2
[2.2.1]: https://github.com/Rosettea/Hilbish/compare/v2.2.0...v2.2.1
[2.2.0]: https://github.com/Rosettea/Hilbish/compare/v2.1.0...v2.2.0
[2.1.2]: https://github.com/Rosettea/Hilbish/compare/v2.1.1...v2.1.2
[2.1.1]: https://github.com/Rosettea/Hilbish/compare/v2.1.0...v2.1.1
[2.1.0]: https://github.com/Rosettea/Hilbish/compare/v2.0.1...v2.1.0
[2.0.1]: https://github.com/Rosettea/Hilbish/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Rosettea/Hilbish/compare/v1.2.0...v2.0.0
[2.0.0-rc1]: https://github.com/Rosettea/Hilbish/compare/v1.2.0...v2.0.0-rc1
[1.2.0]: https://github.com/Rosettea/Hilbish/compare/v1.1.4...v1.2.0
[1.1.0]: https://github.com/Rosettea/Hilbish/compare/v1.0.4...v1.1.0
[1.0.4]: https://github.com/Rosettea/Hilbish/compare/v1.0.3...v1.0.4
[1.0.3]: https://github.com/Rosettea/Hilbish/compare/v1.0.2...v1.0.3
[1.0.2]: https://github.com/Rosettea/Hilbish/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/Rosettea/Hilbish/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/Rosettea/Hilbish/compare/v0.7.1...v1.0.0
[0.7.1]: https://github.com/Rosettea/Hilbish/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/Rosettea/Hilbish/compare/v0.6.1...v0.7.0
[0.6.1]: https://github.com/Rosettea/Hilbish/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/Rosettea/Hilbish/compare/v0.5.1...v0.6.0
[0.5.1]: https://github.com/Rosettea/Hilbish/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/Rosettea/Hilbish/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/Rosettea/Hilbish/compare/v0.3.2...v0.4.0
[0.3.2]: https://github.com/Rosettea/Hilbish/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/Rosettea/Hilbish/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/Rosettea/Hilbish/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/Rosettea/Hilbish/compare/v0.1.2...v0.2.0
[0.1.2]: https://github.com/Rosettea/Hilbish/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/Rosettea/Hilbish/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/Rosettea/Hilbish/compare/v0.0.12...v0.1.0
[0.0.12]: https://github.com/Rosettea/Hilbish/releases/tag/v0.0.12

View File

@ -10,38 +10,40 @@ a contribution. Be sure to read through it.
Use GitHub Issues to report any bugs or to request any features
that may be useful to *anyone* else.
Check [currently open issues](https://github.com/Hilbis/Hilbish/issues)
and [closed ones](https://github.com/Hilbis/Hilbish/issues?q=is%3Aissue+is%3Aclosed) to make sure someone else hasn't already made the issue.
Check [currently open issues](https://github.com/Rosettea/Hilbish/issues)
and [closed ones](https://github.com/Rosettea/Hilbish/issues?q=is%3Aissue+is%3Aclosed)
to make sure someone else hasn't already made the issue.
For bug reports, be sure to include:
- Hilbish Version (`hilbish -v`)
- Ways to reproduce
## Code
For any code contributions (Lua and/or Go), you should follow these
rules:
For any code contributions (Lua and/or Go), you should follow these rules:
- Tab size 4 indentation
- In Lua prefer no braces `()` if the function takes 1 argument
- Use camelCase for function names
- 80 line column limit, unless it breaks code or anything like that
- In Lua prefer no braces `()` if the function takes 1 string argument
- Use camelCase
### Making the Pull Request
1. Ensure that any new install or build dependencies are documented in
the README.md and PR request.
the README.md and pull request.
2. Say in the pull request details the changes to the shell,
this includes useful file locations and breaking changes.
2. Mention any and all changes, feature additons, removals, etc. This includes
useful file locations and breaking changes. Document them in the [changelog](CHANGELOG.md)
in the pull request.
3. The versioning scheme we use is [SemVer](http://semver.org/) and the
commit scheme we use is
[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
Please document any backwards incompatible changes and be sure to name
your commits correctly.
3. We use [Semver](http://semver.org/) for versioning and
[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
for commit messages. Please document any breaking changes and be sure to
write proper commits, or your pull request will not be considered.
4. Finally, make the pull request to the **dev** branch.
4. Finally, make the pull request.
## Finding Issues to Contribute to
You can check out the [help wanted](https://github.com/Hilbis/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+)
You can check out the [help wanted](https://github.com/Rosettea/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+)
labels to figure out what we need your help working on.
The [up for grabs](https://github.com/Hilbis/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22up+for+grabs%22+) labeled issues are low hanging fruit that should be
easy for anyone. You can use this to get started on contributing!
The [up for grabs](https://github.com/Rosettea/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22up+for+grabs%22+)
labeled issues are low hanging fruit that should be easy for anyone. You can
use this to get started on contributing!

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 Hilbis Development
Copyright (c) 2021-2023 Rosettea
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,34 +0,0 @@
PREFIX ?= /usr
DESTDIR ?=
BINDIR ?= $(PREFIX)/bin
LIBDIR ?= $(PREFIX)/share/hilbish
build:
@go build -ldflags "-s -w"
dev:
@go build -ldflags "-s -w -X main.version=$(shell git describe --tags)"
hilbiline:
@go build -ldflags "-s -w -X main.version=$(shell git describe --tags)+hilbiline" -tags hilbiline
install:
@install -v -d "$(DESTDIR)$(BINDIR)/" && install -m 0755 -v hilbish "$(DESTDIR)$(BINDIR)/hilbish"
@mkdir -p "$(DESTDIR)$(LIBDIR)"
@cp libs preload.lua .hilbishrc.lua "$(DESTDIR)$(LIBDIR)" -r
@grep "$(DESTDIR)$(BINDIR)/hilbish" -qxF /etc/shells || echo "$(DESTDIR)$(BINDIR)/hilbish" >> /etc/shells
@echo "Hilbish Installed"
uninstall:
@rm -vrf \
"$(DESTDIR)$(BINDIR)/hilbish" \
"$(DESTDIR)$(LIBDIR)"
@sed -i '/hilbish/d' /etc/shells
@echo "Hilbish Uninstalled"
clean:
@go clean
all: build install
.PHONY: install uninstall build dev hilbiline clean

160
README.md
View File

@ -1,126 +1,84 @@
<div align="center">
<h1>Hilbish</h1>
<blockquote>
🎀 a nice lil shell for lua people made with go and lua
</blockquote><p align="center">
<a href="https://github.com/Hilbis/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22"><img src="https://img.shields.io/github/issues/Hilbis/Hilbish/help%20wanted?color=green" alt="help wanted"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
</p>
</div>
> [!TIP]
> Check out [Hilbish: Midnight Edition](https://github.com/Rosettea/Hilbish/tree/midnight-edition) if you want to use C Lua, LuaJIT or anything related!
Hilbish is an interactive Unix-like shell written in Go, with the config
and other code written in Lua.
It is sort of in a stable state currently, usable as a daily shell,
but there may still be breaking changes in Lua modules.
<img src="./assets/hilbish-logo-and-text.png" width=512><br>
<blockquote>
🌓 The Moon-powered shell! A comfy and extensible shell for Lua fans! 🌺 ✨
</blockquote>
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/Rosettea/Hilbish?style=flat-square"><img alt="GitHub commits since latest release (by date)" src="https://img.shields.io/github/commits-since/Rosettea/Hilbish/latest?style=flat-square"><img alt="GitHub contributors" src="https://img.shields.io/github/contributors/Rosettea/Hilbish?style=flat-square"><br>
<a href="https://github.com/Rosettea/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22"><img src="https://img.shields.io/github/issues/Hilbis/Hilbish/help%20wanted?style=flat-square&color=green" alt="help wanted"></a>
<a href="https://github.com/Rosettea/Hilbish/blob/master/LICENSE"><img alt="GitHub license" src="https://img.shields.io/github/license/Rosettea/Hilbish?style=flat-square"></a>
<a href="https://discord.gg/3PDdcQz"><img alt="Discord" src="https://img.shields.io/discord/732357621503229962?color=blue&style=flat-square"></a>
<br>
Hilbish is an extensible shell designed to be highly customizable.
It is configured in Lua, and provides a good range of features.
It aims to be easy to use for anyone, and powerful enough for
those who need more.
The motivation for choosing Lua was that its simpler and better to use
than old shell scripts. It's fine for basic interactive shell uses,
and supports [both Lua and Sh interactively](https://rosettea.github.io/Hilbish/docs/features/runner-mode/).
That's the only place Hilbish can use traditional shell syntax though;
everything else is Lua and aims to be infinitely configurable.
If something isn't, open an issue!
# Screenshots
<div align="center">
<img src="gallery/default.png"><br><br>
<img src="gallery/terminal.png"><br><br>
<img src="gallery/pillprompt.png">
<img src="gallery/tab.png">
</div>
# Links
- **[Documentation](https://github.com/Hilbis/Hilbish/wiki)**
- **[Gallery](https://github.com/Hilbis/Hilbish/discussions/36)** - See
more screenshots of Hilbish in action
# Getting Hilbish
**NOTE:** Hilbish is not guaranteed to work properly on Windows, starting
from the 2.0 version. It will still be able to compile, but functionality
may be lacking. If you want to contribute to make the situation better,
comment on the Windows discussion.
# Installation
**NOTE:** Hilbish is currently only officially supported and tested on Linux
You can check the [install page](https://rosettea.github.io/Hilbish/install/)
on the website for distributed binaries from GitHub or other package repositories.
Otherwise, continue reading for steps on compiling.
### Prebuilt binaries
Binaries are provided for the latest commit.
## Prerequisites
- [Go 1.22+](https://go.dev)
- [Task](https://taskfile.dev/installation/) (**Go on the hyperlink here to see Task's install method for your OS.**)
**Note that these use Hilbiline, not readline, and may be missing functionality
(moving the cursor, proper unicode support and backspace working properly)**
Click on the checkmark (or x) near the commit hash, then details for your platform
<br><img src="https://modeus.is-inside.me/dyr8UGGq.png"><br>
Then click on the artifacts drop down, and download artifact for your platform,
like what is highlighted in the screenshot.
<br><img src="https://modeus.is-inside.me/KJ0Puceb.png"><br>
### AUR
Arch Linux users can install Hilbish from the AUR.
## Build
First, clone Hilbish. The recursive is required, as some Lua libraries
are submodules.
```sh
yay -S hilbish
```
If you want the latest and greatest, you can install and compile from the latest git commit
```sh
yay -S hilbish-git
```
### Manual Build
#### Prerequisites
- [Go 1.16](https://go.dev)
- GNU Readline
On Fedora, readline can be installed with:
```
sudo dnf install readline-devel
git clone --recursive https://github.com/Rosettea/Hilbish
cd Hilbish
go get -d ./...
```
On Debian/Ubuntu and distros based on them, it can be installed with:
```
sudo apt install libreadline-dev
To build, run:
```
task
```
On OpenSUSE, it can be installed with:
Or, if you want a stable branch, run these commands:
```
sudo zypper install readline-devel
```
On Arch Linux, it can be installed with:
```
sudo pacman -S readline
```
#### Build
First, clone Hilbish:
```sh
git clone --recursive https://github.com/Hilbis/Hilbish
cd Hilbish
# If you want the latest stable release, run this following command
git checkout $(git describe --tags `git rev-list --tags --max-count=1`)
```
task build
```
And get dependencies and build:
```sh
go get -d all
make dev
```
If you `git checkout`'d the latest stable release, run
`make build` instead of `make dev`.
or want to experiment Hilbiline, instead run
`make hilbiline`
#### Install
`sudo make install`
### Uninstall
```sh
sudo make uninstall
```
After you did all that, run `sudo task install` to install Hilbish globally.
# Contributing
Any kind of contributions to Hilbish are welcome!
Make sure to read [CONTRIBUTING.md](CONTRIBUTING.md) before getting started.
Any kind of contributions are welcome! Hilbish is very easy to contribute to.
Read [CONTRIBUTING.md](CONTRIBUTING.md) as a guideline to doing so.
### Special Thanks To
Everyone here who has contributed:
<a href="https://github.com/Hilbis/Hilbish/graphs/contributors">
<img src="https://contrib.rocks/image?repo=Hilbis/Hilbish" />
**Thanks to everyone below who's contributed!**
<a href="https://github.com/Rosettea/Hilbish/graphs/contributors">
<img src="https://contrib.rocks/image?repo=Rosettea/Hilbish" />
</a>
*Made with [contributors-img](https://contrib.rocks).*
### Credits
- [This blog post](https://www.vidarholen.net/contents/blog/?p=878) which
is how Hilbish now inserts a newline even if output doesn't have one.
# License
Hilbish is licensed under the MIT license.
[Read here](LICENSE) for more info.
Hilbish is licensed under the [MIT license](LICENSE).
[Images and assets](assets/) are licensed under CC-BY-SA 4.0

47
Taskfile.yaml Normal file
View File

@ -0,0 +1,47 @@
# https://taskfile.dev
version: '3'
vars:
PREFIX: '{{default "/usr/local" .PREFIX}}'
bindir__: '{{.PREFIX}}/bin'
BINDIR: '{{default .bindir__ .BINDIR}}'
libdir__: ''
LIBDIR: '{{default .libdir__ .LIBDIR}}'
goflags__: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}}"'
GOFLAGS: '{{default .goflags__ .GOFLAGS}}'
tasks:
default:
cmds:
- go build {{.GOFLAGS}}
vars:
GOFLAGS: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}} -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"'
default-nocgo:
cmds:
- CGO_ENABLED=0 go build {{.GOFLAGS}}
vars:
GOFLAGS: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}} -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"'
build:
cmds:
- go build {{.GOFLAGS}}
build-nocgo:
cmds:
- CGO_ENABLED=0 go build {{.GOFLAGS}}
install:
cmds:
- install -v -d "{{.DESTDIR}}{{.BINDIR}}/" && install -m 0755 -v hilbish "{{.DESTDIR}}{{.BINDIR}}/hilbish"
- mkdir -p "{{.DESTDIR}}{{.LIBDIR}}"
- cp -r libs docs emmyLuaDocs nature .hilbishrc.lua {{.DESTDIR}}{{.LIBDIR}}
- grep -qxF "{{.DESTDIR}}{{.BINDIR}}/hilbish" /etc/shells || echo "{{.DESTDIR}}{{.BINDIR}}/hilbish" >> /etc/shells
uninstall:
cmds:
- rm -vrf
"{{.DESTDIR}}{{.BINDIR}}/hilbish"
"{{.DESTDIR}}{{.LIBDIR}}"
- grep -v 'hilbish' /etc/shells > /tmp/shells.hilbish_uninstall && mv /tmp/shells.hilbish_uninstall /etc/shells

173
aliases.go Normal file
View File

@ -0,0 +1,173 @@
package main
import (
"regexp"
"strconv"
"strings"
"sync"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
)
var aliases *aliasModule
type aliasModule struct {
aliases map[string]string
mu *sync.RWMutex
}
// initialize aliases map
func newAliases() *aliasModule {
return &aliasModule{
aliases: make(map[string]string),
mu: &sync.RWMutex{},
}
}
func (a *aliasModule) Add(alias, cmd string) {
a.mu.Lock()
defer a.mu.Unlock()
a.aliases[alias] = cmd
}
func (a *aliasModule) All() map[string]string {
return a.aliases
}
func (a *aliasModule) Delete(alias string) {
a.mu.Lock()
defer a.mu.Unlock()
delete(a.aliases, alias)
}
func (a *aliasModule) Resolve(cmdstr string) string {
a.mu.RLock()
defer a.mu.RUnlock()
arg, _ := regexp.Compile(`[\\]?%\d+`)
args, _ := splitInput(cmdstr)
if len(args) == 0 {
// this shouldnt reach but...????
return cmdstr
}
for a.aliases[args[0]] != "" {
alias := a.aliases[args[0]]
alias = arg.ReplaceAllStringFunc(alias, func(a string) string {
idx, _ := strconv.Atoi(a[1:])
if strings.HasPrefix(a, "\\") || idx == 0 {
return strings.TrimPrefix(a, "\\")
}
if idx + 1 > len(args) {
return a
}
val := args[idx]
args = cut(args, idx)
cmdstr = strings.Join(args, " ")
return val
})
cmdstr = alias + strings.TrimPrefix(cmdstr, args[0])
cmdArgs, _ := splitInput(cmdstr)
args = cmdArgs
if a.aliases[args[0]] == alias {
break
}
if a.aliases[args[0]] != "" {
continue
}
}
return cmdstr
}
// lua section
// #interface aliases
// command aliasing
// The alias interface deals with all command aliases in Hilbish.
func (a *aliasModule) Loader(rtm *rt.Runtime) *rt.Table {
// create a lua module with our functions
hshaliasesLua := map[string]util.LuaExport{
"add": util.LuaExport{hlalias, 2, false},
"list": util.LuaExport{a.luaList, 0, false},
"del": util.LuaExport{a.luaDelete, 1, false},
"resolve": util.LuaExport{a.luaResolve, 1, false},
}
mod := rt.NewTable()
util.SetExports(rtm, mod, hshaliasesLua)
return mod
}
// #interface aliases
// add(alias, cmd)
// This is an alias (ha) for the [hilbish.alias](../#alias) function.
// --- @param alias string
// --- @param cmd string
func _hlalias() {}
// #interface aliases
// list() -> table[string, string]
// Get a table of all aliases, with string keys as the alias and the value as the command.
// #returns table[string, string]
/*
#example
hilbish.aliases.add('hi', 'echo hi')
local aliases = hilbish.aliases.list()
-- -> {hi = 'echo hi'}
#example
*/
func (a *aliasModule) luaList(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
aliasesList := rt.NewTable()
for k, v := range a.All() {
aliasesList.Set(rt.StringValue(k), rt.StringValue(v))
}
return c.PushingNext1(t.Runtime, rt.TableValue(aliasesList)), nil
}
// #interface aliases
// delete(name)
// Removes an alias.
// #param name string
func (a *aliasModule) luaDelete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
alias, err := c.StringArg(0)
if err != nil {
return nil, err
}
a.Delete(alias)
return c.Next(), nil
}
// #interface aliases
// resolve(alias) -> string?
// Resolves an alias to its original command. Will thrown an error if the alias doesn't exist.
// #param alias string
// #returns string
func (a *aliasModule) luaResolve(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
alias, err := c.StringArg(0)
if err != nil {
return nil, err
}
resolved := a.Resolve(alias)
return c.PushingNext1(t.Runtime, rt.StringValue(resolved)), nil
}

687
api.go Normal file
View File

@ -0,0 +1,687 @@
// the core Hilbish API
// The Hilbish module includes the core API, containing
// interfaces and functions which directly relate to shell functionality.
// #field ver The version of Hilbish
// #field goVersion The version of Go that Hilbish was compiled with
// #field user Username of the user
// #field host Hostname of the machine
// #field dataDir Directory for Hilbish data files, including the docs and default modules
// #field interactive Is Hilbish in an interactive shell?
// #field login Is Hilbish the login shell?
// #field vimMode Current Vim input mode of Hilbish (will be nil if not in Vim input mode)
// #field exitCode Exit code of the last executed command
package main
import (
//"bytes"
"errors"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
"syscall"
"time"
"hilbish/util"
"github.com/arnodel/golua/lib/packagelib"
rt "github.com/arnodel/golua/runtime"
//"github.com/arnodel/golua/lib/iolib"
"github.com/maxlandon/readline"
//"mvdan.cc/sh/v3/interp"
)
var exports = map[string]util.LuaExport{
"alias": {hlalias, 2, false},
"appendPath": {hlappendPath, 1, false},
"complete": {hlcomplete, 2, false},
"cwd": {hlcwd, 0, false},
"exec": {hlexec, 1, false},
"goro": {hlgoro, 1, true},
"highlighter": {hlhighlighter, 1, false},
"hinter": {hlhinter, 1, false},
"multiprompt": {hlmultiprompt, 1, false},
"prependPath": {hlprependPath, 1, false},
"prompt": {hlprompt, 1, true},
"inputMode": {hlinputMode, 1, false},
"interval": {hlinterval, 2, false},
"read": {hlread, 1, false},
"timeout": {hltimeout, 2, false},
"which": {hlwhich, 1, false},
}
var hshMod *rt.Table
var hilbishLoader = packagelib.Loader{
Load: hilbishLoad,
Name: "hilbish",
}
func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
if hshMod == nil {
hshMod = mod
}
host, _ := os.Hostname()
username := curuser.Username
if runtime.GOOS == "windows" {
username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows
}
util.SetField(rtm, mod, "ver", rt.StringValue(getVersion()))
util.SetField(rtm, mod, "goVersion", rt.StringValue(runtime.Version()))
util.SetField(rtm, mod, "user", rt.StringValue(username))
util.SetField(rtm, mod, "host", rt.StringValue(host))
util.SetField(rtm, mod, "home", rt.StringValue(curuser.HomeDir))
util.SetField(rtm, mod, "dataDir", rt.StringValue(dataDir))
util.SetField(rtm, mod, "interactive", rt.BoolValue(interactive))
util.SetField(rtm, mod, "login", rt.BoolValue(login))
util.SetField(rtm, mod, "vimMode", rt.NilValue)
util.SetField(rtm, mod, "exitCode", rt.IntValue(0))
// hilbish.userDir table
hshuser := userDirLoader(rtm)
mod.Set(rt.StringValue("userDir"), rt.TableValue(hshuser))
// hilbish.os table
hshos := hshosLoader(rtm)
mod.Set(rt.StringValue("os"), rt.TableValue(hshos))
// hilbish.aliases table
aliases = newAliases()
aliasesModule := aliases.Loader(rtm)
mod.Set(rt.StringValue("aliases"), rt.TableValue(aliasesModule))
// hilbish.history table
historyModule := lr.Loader(rtm)
mod.Set(rt.StringValue("history"), rt.TableValue(historyModule))
// hilbish.completion table
hshcomp := completionLoader(rtm)
// TODO: REMOVE "completion" AND ONLY USE "completions" WITH AN S
mod.Set(rt.StringValue("completions"), rt.TableValue(hshcomp))
// hilbish.runner table
runnerModule := runnerModeLoader(rtm)
mod.Set(rt.StringValue("runner"), rt.TableValue(runnerModule))
// hilbish.jobs table
jobs = newJobHandler()
jobModule := jobs.loader(rtm)
mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule))
// hilbish.timers table
timers = newTimersModule()
timersModule := timers.loader(rtm)
mod.Set(rt.StringValue("timers"), rt.TableValue(timersModule))
versionModule := rt.NewTable()
util.SetField(rtm, versionModule, "branch", rt.StringValue(gitBranch))
util.SetField(rtm, versionModule, "full", rt.StringValue(getVersion()))
util.SetField(rtm, versionModule, "commit", rt.StringValue(gitCommit))
util.SetField(rtm, versionModule, "release", rt.StringValue(releaseName))
mod.Set(rt.StringValue("version"), rt.TableValue(versionModule))
pluginModule := moduleLoader(rtm)
mod.Set(rt.StringValue("module"), rt.TableValue(pluginModule))
sinkModule := util.SinkLoader(rtm)
mod.Set(rt.StringValue("sink"), rt.TableValue(sinkModule))
return rt.TableValue(mod), nil
}
func getenv(key, fallback string) string {
value := os.Getenv(key)
if len(value) == 0 {
return fallback
}
return value
}
func setVimMode(mode string) {
util.SetField(l, hshMod, "vimMode", rt.StringValue(mode))
hooks.Emit("hilbish.vimMode", mode)
}
func unsetVimMode() {
util.SetField(l, hshMod, "vimMode", rt.NilValue)
}
/*
func handleStream(v rt.Value, strms *streams, errStream bool) error {
ud, ok := v.TryUserData()
if !ok {
return errors.New("expected metatable argument")
}
val := ud.Value()
var varstrm io.Writer
if f, ok := val.(*iolib.File); ok {
varstrm = f.Handle()
}
if f, ok := val.(*sink); ok {
varstrm = f.writer
}
if varstrm == nil {
return errors.New("expected either a sink or file")
}
if errStream {
strms.stderr = varstrm
} else {
strms.stdout = varstrm
}
return nil
}
*/
// cwd() -> string
// Returns the current directory of the shell.
// #returns string
func hlcwd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
cwd, _ := os.Getwd()
return c.PushingNext1(t.Runtime, rt.StringValue(cwd)), nil
}
// read(prompt) -> input (string)
// Read input from the user, using Hilbish's line editor/input reader.
// This is a separate instance from the one Hilbish actually uses.
// Returns `input`, will be nil if Ctrl-D is pressed, or an error occurs.
// #param prompt? string Text to print before input, can be empty.
// #returns string|nil
func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
luaprompt := c.Arg(0)
if typ := luaprompt.Type(); typ != rt.StringType && typ != rt.NilType {
return nil, errors.New("expected #1 to be a string")
}
prompt, ok := luaprompt.TryString()
if !ok {
// if we are here and `luaprompt` is not a string, it's nil
// substitute with an empty string
prompt = ""
}
lualr := &lineReader{
rl: readline.NewInstance(),
}
lualr.SetPrompt(prompt)
input, err := lualr.Read()
if err != nil {
return c.Next(), nil
}
return c.PushingNext1(t.Runtime, rt.StringValue(input)), nil
}
/*
prompt(str, typ)
Changes the shell prompt to the provided string.
There are a few verbs that can be used in the prompt text.
These will be formatted and replaced with the appropriate values.
`%d` - Current working directory
`%u` - Name of current user
`%h` - Hostname of device
#param str string
#param typ? string Type of prompt, being left or right. Left by default.
#example
-- the default hilbish prompt without color
hilbish.prompt '%u %d '
-- or something of old:
hilbish.prompt '%u@%h :%d $'
-- prompt: user@hostname: ~/directory $
#example
*/
func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
err := c.Check1Arg()
if err != nil {
return nil, err
}
p, err := c.StringArg(0)
if err != nil {
return nil, err
}
typ := "left"
// optional 2nd arg
if len(c.Etc()) != 0 {
ltyp := c.Etc()[0]
var ok bool
typ, ok = ltyp.TryString()
if !ok {
return nil, errors.New("bad argument to run (expected string, got " + ltyp.TypeName() + ")")
}
}
switch typ {
case "left":
prompt = p
lr.SetPrompt(fmtPrompt(prompt))
case "right":
lr.SetRightPrompt(fmtPrompt(p))
default:
return nil, errors.New("expected prompt type to be right or left, got " + typ)
}
return c.Next(), nil
}
// multiprompt(str)
// Changes the text prompt when Hilbish asks for more input.
// This will show up when text is incomplete, like a missing quote
// #param str string
/*
#example
--[[
imagine this is your text input:
user ~ echo "hey
but there's a missing quote! hilbish will now prompt you so the terminal
will look like:
user ~ echo "hey
--> ...!"
so then you get
user ~ echo "hey
--> ...!"
hey ...!
]]--
hilbish.multiprompt '-->'
#example
*/
func hlmultiprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return c.PushingNext1(t.Runtime, rt.StringValue(multilinePrompt)), nil
}
prompt, err := c.StringArg(0)
if err != nil {
return nil, err
}
multilinePrompt = prompt
return c.Next(), nil
}
// alias(cmd, orig)
// Sets an alias, with a name of `cmd` to another command.
// #param cmd string Name of the alias
// #param orig string Command that will be aliased
/*
#example
-- With this, "ga file" will turn into "git add file"
hilbish.alias('ga', 'git add')
-- Numbered substitutions are supported here!
hilbish.alias('dircount', 'ls %1 | wc -l')
-- "dircount ~" would count how many files are in ~ (home directory).
#example
*/
func hlalias(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(2); err != nil {
return nil, err
}
cmd, err := c.StringArg(0)
if err != nil {
return nil, err
}
orig, err := c.StringArg(1)
if err != nil {
return nil, err
}
aliases.Add(cmd, orig)
return c.Next(), nil
}
// appendPath(dir)
// Appends the provided dir to the command path (`$PATH`)
// #param dir string|table Directory (or directories) to append to path
/*
#example
hilbish.appendPath '~/go/bin'
-- Will add ~/go/bin to the command path.
-- Or do multiple:
hilbish.appendPath {
'~/go/bin',
'~/.local/bin'
}
#example
*/
func hlappendPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
arg := c.Arg(0)
// check if dir is a table or a string
if arg.Type() == rt.TableType {
util.ForEach(arg.AsTable(), func(k rt.Value, v rt.Value) {
if v.Type() == rt.StringType {
appendPath(v.AsString())
}
})
} else if arg.Type() == rt.StringType {
appendPath(arg.AsString())
} else {
return nil, errors.New("bad argument to appendPath (expected string or table, got " + arg.TypeName() + ")")
}
return c.Next(), nil
}
func appendPath(dir string) {
dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
pathenv := os.Getenv("PATH")
// if dir isnt already in $PATH, add it
if !strings.Contains(pathenv, dir) {
os.Setenv("PATH", pathenv+string(os.PathListSeparator)+dir)
}
}
// exec(cmd)
// Replaces the currently running Hilbish instance with the supplied command.
// This can be used to do an in-place restart.
// #param cmd string
func hlexec(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
cmd, err := c.StringArg(0)
if err != nil {
return nil, err
}
cmdArgs, _ := splitInput(cmd)
if runtime.GOOS != "windows" {
cmdPath, err := util.LookPath(cmdArgs[0])
if err != nil {
fmt.Println(err)
// if we get here, cmdPath will be nothing
// therefore nothing will run
}
// syscall.Exec requires an absolute path to a binary
// path, args, string slice of environments
syscall.Exec(cmdPath, cmdArgs, os.Environ())
} else {
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Run()
os.Exit(0)
}
return c.Next(), nil
}
// goro(fn)
// Puts `fn` in a Goroutine.
// This can be used to run any function in another thread at the same time as other Lua code.
// **NOTE: THIS FUNCTION MAY CRASH HILBISH IF OUTSIDE VARIABLES ARE ACCESSED.**
// **This is a limitation of the Lua runtime.**
// #param fn function
func hlgoro(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
fn, err := c.ClosureArg(0)
if err != nil {
return nil, err
}
// call fn
go func() {
defer func() {
if r := recover(); r != nil {
// do something here?
}
}()
_, err := rt.Call1(l.MainThread(), rt.FunctionValue(fn), c.Etc()...)
if err != nil {
fmt.Fprintln(os.Stderr, "Error in goro function:\n\n", err)
}
}()
return c.Next(), nil
}
// timeout(cb, time) -> @Timer
// Executed the `cb` function after a period of `time`.
// This creates a Timer that starts ticking immediately.
// #param cb function
// #param time number Time to run in milliseconds.
// #returns Timer
func hltimeout(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(2); err != nil {
return nil, err
}
cb, err := c.ClosureArg(0)
if err != nil {
return nil, err
}
ms, err := c.IntArg(1)
if err != nil {
return nil, err
}
interval := time.Duration(ms) * time.Millisecond
timer := timers.create(timerTimeout, interval, cb)
timer.start()
return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil
}
// interval(cb, time) -> @Timer
// Runs the `cb` function every specified amount of `time`.
// This creates a timer that ticking immediately.
// #param cb function
// #param time number Time in milliseconds.
// #return Timer
func hlinterval(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(2); err != nil {
return nil, err
}
cb, err := c.ClosureArg(0)
if err != nil {
return nil, err
}
ms, err := c.IntArg(1)
if err != nil {
return nil, err
}
interval := time.Duration(ms) * time.Millisecond
timer := timers.create(timerInterval, interval, cb)
timer.start()
return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil
}
// complete(scope, cb)
// Registers a completion handler for the specified scope.
// A `scope` is expected to be `command.<cmd>`,
// replacing <cmd> with the name of the command (for example `command.git`).
// The documentation for completions, under Features/Completions or `doc completions`
// provides more details.
// #param scope string
// #param cb function
/*
#example
-- This is a very simple example. Read the full doc for completions for details.
hilbish.complete('command.sudo', function(query, ctx, fields)
if #fields == 0 then
-- complete for commands
local comps, pfx = hilbish.completion.bins(query, ctx, fields)
local compGroup = {
items = comps, -- our list of items to complete
type = 'grid' -- what our completions will look like.
}
return {compGroup}, pfx
end
-- otherwise just be boring and return files
local comps, pfx = hilbish.completion.files(query, ctx, fields)
local compGroup = {
items = comps,
type = 'grid'
}
return {compGroup}, pfx
end)
#example
*/
func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
scope, cb, err := util.HandleStrCallback(t, c)
if err != nil {
return nil, err
}
luaCompletions[scope] = cb
return c.Next(), nil
}
// prependPath(dir)
// Prepends `dir` to $PATH.
// #param dir string
func hlprependPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
dir, err := c.StringArg(0)
if err != nil {
return nil, err
}
dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
pathenv := os.Getenv("PATH")
// if dir isnt already in $PATH, add in
if !strings.Contains(pathenv, dir) {
os.Setenv("PATH", dir+string(os.PathListSeparator)+pathenv)
}
return c.Next(), nil
}
// which(name) -> string
// Checks if `name` is a valid command.
// Will return the path of the binary, or a basename if it's a commander.
// #param name string
// #returns string
func hlwhich(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
name, err := c.StringArg(0)
if err != nil {
return nil, err
}
// itll return either the original command or what was passed
// if name isnt empty its not an issue
alias := aliases.Resolve(name)
cmd := strings.Split(alias, " ")[0]
// check for commander
if cmds.Commands[cmd] != nil {
// they dont resolve to a path, so just send the cmd
return c.PushingNext1(t.Runtime, rt.StringValue(cmd)), nil
}
path, err := util.LookPath(cmd)
if err != nil {
return c.Next(), nil
}
return c.PushingNext1(t.Runtime, rt.StringValue(path)), nil
}
// inputMode(mode)
// Sets the input mode for Hilbish's line reader.
// `emacs` is the default. Setting it to `vim` changes behavior of input to be
// Vim-like with modes and Vim keybinds.
// #param mode string Can be set to either `emacs` or `vim`
func hlinputMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
mode, err := c.StringArg(0)
if err != nil {
return nil, err
}
switch mode {
case "emacs":
unsetVimMode()
lr.rl.InputMode = readline.Emacs
case "vim":
setVimMode("insert")
lr.rl.InputMode = readline.Vim
default:
return nil, errors.New("inputMode: expected vim or emacs, received " + mode)
}
return c.Next(), nil
}
// hinter(line, pos)
// The command line hint handler. It gets called on every key insert to
// determine what text to use as an inline hint. It is passed the current
// line and cursor position. It is expected to return a string which is used
// as the text for the hint. This is by default a shim. To set hints,
// override this function with your custom handler.
// #param line string
// #param pos number Position of cursor in line. Usually equals string.len(line)
/*
#example
-- this will display "hi" after the cursor in a dimmed color.
function hilbish.hinter(line, pos)
return 'hi'
end
#example
*/
func hlhinter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
// highlighter(line)
// Line highlighter handler.
// This is mainly for syntax highlighting, but in reality could set the input
// of the prompt to *display* anything. The callback is passed the current line
// and is expected to return a line that will be used as the input display.
// Note that to set a highlighter, one has to override this function.
// #example
// --This code will highlight all double quoted strings in green.
// function hilbish.highlighter(line)
//
// return line:gsub('"%w+"', function(c) return lunacolors.green(c) end)
//
// end
// #example
// #param line string
func hlhighlighter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
line, err := c.StringArg(0)
if err != nil {
return nil, err
}
return c.PushingNext1(t.Runtime, rt.StringValue(line)), nil
}

BIN
assets/hilbish-flower.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

714
cmd/docgen/docgen.go Normal file
View File

@ -0,0 +1,714 @@
package main
import (
"fmt"
"go/ast"
"go/doc"
"go/parser"
"go/token"
"os"
"path/filepath"
"regexp"
"strings"
"sync"
md "github.com/atsushinee/go-markdown-generator/doc"
)
var header = `---
title: %s %s
description: %s
layout: doc
menu:
docs:
parent: "API"
---
`
type emmyPiece struct {
DocPiece *docPiece
Annotations []string
Params []string // we only need to know param name to put in function
FuncName string
}
type module struct {
Types []docPiece
Docs []docPiece
Fields []docPiece
Properties []docPiece
ShortDescription string
Description string
ParentModule string
HasInterfaces bool
HasTypes bool
}
type param struct {
Name string
Type string
Doc []string
}
type docPiece struct {
Doc []string
FuncSig string
FuncName string
Interfacing string
ParentModule string
GoFuncName string
IsInterface bool
IsMember bool
IsType bool
Fields []docPiece
Properties []docPiece
Params []param
Tags map[string][]tag
}
type tag struct {
id string
fields []string
startIdx int
}
var docs = make(map[string]module)
var interfaceDocs = make(map[string]module)
var emmyDocs = make(map[string][]emmyPiece)
var typeTable = make(map[string][]string) // [0] = parentMod, [1] = interfaces
var prefix = map[string]string{
"main": "hl",
"hilbish": "hl",
"fs": "f",
"commander": "c",
"bait": "b",
"terminal": "term",
"snail": "snail",
"readline": "rl",
"yarn": "yarn",
}
func getTagsAndDocs(docs string) (map[string][]tag, []string) {
pts := strings.Split(docs, "\n")
parts := []string{}
tags := make(map[string][]tag)
for idx, part := range pts {
if strings.HasPrefix(part, "#") {
tagParts := strings.Split(strings.TrimPrefix(part, "#"), " ")
if tags[tagParts[0]] == nil {
var id string
if len(tagParts) > 1 {
id = tagParts[1]
}
tags[tagParts[0]] = []tag{
{id: id, startIdx: idx},
}
if len(tagParts) >= 2 {
tags[tagParts[0]][0].fields = tagParts[2:]
}
} else {
if tagParts[0] == "example" {
exampleIdx := tags["example"][0].startIdx
exampleCode := pts[exampleIdx+1 : idx]
tags["example"][0].fields = exampleCode
parts = strings.Split(strings.Replace(strings.Join(parts, "\n"), strings.TrimPrefix(strings.Join(exampleCode, "\n"), "#example\n"), "", -1), "\n")
continue
}
fleds := []string{}
if len(tagParts) >= 2 {
fleds = tagParts[2:]
}
tags[tagParts[0]] = append(tags[tagParts[0]], tag{
id: tagParts[1],
fields: fleds,
})
}
} else {
parts = append(parts, part)
}
}
return tags, parts
}
func docPieceTag(tagName string, tags map[string][]tag) []docPiece {
dps := []docPiece{}
for _, tag := range tags[tagName] {
dps = append(dps, docPiece{
FuncName: tag.id,
Doc: tag.fields,
})
}
return dps
}
func setupDocType(mod string, typ *doc.Type) *docPiece {
docs := strings.TrimSpace(typ.Doc)
tags, doc := getTagsAndDocs(docs)
if tags["type"] == nil {
return nil
}
inInterface := tags["interface"] != nil
var interfaces string
typeName := strings.ToUpper(string(typ.Name[0])) + typ.Name[1:]
typeDoc := []string{}
if inInterface {
interfaces = tags["interface"][0].id
}
fields := docPieceTag("field", tags)
properties := docPieceTag("property", tags)
for _, d := range doc {
if strings.HasPrefix(d, "---") {
// TODO: document types in lua
/*
emmyLine := strings.TrimSpace(strings.TrimPrefix(d, "---"))
emmyLinePieces := strings.Split(emmyLine, " ")
emmyType := emmyLinePieces[0]
if emmyType == "@param" {
em.Params = append(em.Params, emmyLinePieces[1])
}
if emmyType == "@vararg" {
em.Params = append(em.Params, "...") // add vararg
}
em.Annotations = append(em.Annotations, d)
*/
} else {
typeDoc = append(typeDoc, d)
}
}
var isMember bool
if tags["member"] != nil {
isMember = true
}
parentMod := mod
dps := &docPiece{
Doc: typeDoc,
FuncName: typeName,
Interfacing: interfaces,
IsInterface: inInterface,
IsMember: isMember,
IsType: true,
ParentModule: parentMod,
Fields: fields,
Properties: properties,
Tags: tags,
}
typeTable[strings.ToLower(typeName)] = []string{parentMod, interfaces}
return dps
}
func setupDoc(mod string, fun *doc.Func) *docPiece {
if fun.Doc == "" {
return nil
}
docs := strings.TrimSpace(fun.Doc)
tags, parts := getTagsAndDocs(docs)
// i couldnt fit this into the condition below for some reason so here's a goto!
if tags["member"] != nil {
goto start
}
if prefix[mod] == "" {
return nil
}
if (!strings.HasPrefix(fun.Name, prefix[mod]) && tags["interface"] == nil) || (strings.ToLower(fun.Name) == "loader" && tags["interface"] == nil) {
return nil
}
start:
inInterface := tags["interface"] != nil
var interfaces string
funcsig := parts[0]
doc := parts[1:]
funcName := strings.TrimPrefix(fun.Name, prefix[mod])
funcdoc := []string{}
if inInterface {
interfaces = tags["interface"][0].id
funcName = interfaces + "." + strings.Split(funcsig, "(")[0]
}
em := emmyPiece{FuncName: funcName}
fields := docPieceTag("field", tags)
properties := docPieceTag("property", tags)
var params []param
if paramsRaw := tags["param"]; paramsRaw != nil {
params = make([]param, len(paramsRaw))
for i, p := range paramsRaw {
params[i] = param{
Name: p.id,
Type: p.fields[0],
Doc: p.fields[1:],
}
}
}
for _, d := range doc {
if strings.HasPrefix(d, "---") {
emmyLine := strings.TrimSpace(strings.TrimPrefix(d, "---"))
emmyLinePieces := strings.Split(emmyLine, " ")
emmyType := emmyLinePieces[0]
if emmyType == "@param" {
em.Params = append(em.Params, emmyLinePieces[1])
}
if emmyType == "@vararg" {
em.Params = append(em.Params, "...") // add vararg
}
em.Annotations = append(em.Annotations, d)
} else {
funcdoc = append(funcdoc, d)
}
}
var isMember bool
if tags["member"] != nil {
isMember = true
}
var parentMod string
if inInterface {
parentMod = mod
}
dps := &docPiece{
Doc: funcdoc,
FuncSig: funcsig,
FuncName: funcName,
Interfacing: interfaces,
GoFuncName: strings.ToLower(fun.Name),
IsInterface: inInterface,
IsMember: isMember,
ParentModule: parentMod,
Fields: fields,
Properties: properties,
Params: params,
Tags: tags,
}
if strings.HasSuffix(dps.GoFuncName, strings.ToLower("loader")) {
dps.Doc = parts
}
em.DocPiece = dps
emmyDocs[mod] = append(emmyDocs[mod], em)
return dps
}
func main() {
fset := token.NewFileSet()
os.Mkdir("docs", 0777)
os.RemoveAll("docs/api")
os.Mkdir("docs/api", 0777)
f, err := os.Create("docs/api/_index.md")
if err != nil {
panic(err)
}
f.WriteString(`---
title: API
layout: doc
weight: -100
menu: docs
---
Welcome to the API documentation for Hilbish. This documents Lua functions
provided by Hilbish.
`)
f.Close()
os.Mkdir("emmyLuaDocs", 0777)
dirs := []string{"./", "./util"}
filepath.Walk("golibs/", func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
return nil
}
dirs = append(dirs, "./"+path)
return nil
})
pkgs := make(map[string]*ast.Package)
for _, path := range dirs {
d, err := parser.ParseDir(fset, path, nil, parser.ParseComments)
if err != nil {
fmt.Println(err)
return
}
for k, v := range d {
pkgs[k] = v
}
}
interfaceModules := make(map[string]*module)
for l, f := range pkgs {
p := doc.New(f, "./", doc.AllDecls)
pieces := []docPiece{}
typePieces := []docPiece{}
mod := l
if mod == "main" || mod == "util" {
mod = "hilbish"
}
var hasInterfaces bool
for _, t := range p.Funcs {
piece := setupDoc(mod, t)
if piece == nil {
continue
}
pieces = append(pieces, *piece)
if piece.IsInterface {
hasInterfaces = true
}
}
for _, t := range p.Types {
typePiece := setupDocType(mod, t)
if typePiece != nil {
typePieces = append(typePieces, *typePiece)
if typePiece.IsInterface {
hasInterfaces = true
}
}
for _, m := range t.Methods {
piece := setupDoc(mod, m)
if piece == nil {
continue
}
pieces = append(pieces, *piece)
if piece.IsInterface {
hasInterfaces = true
}
}
}
tags, descParts := getTagsAndDocs(strings.TrimSpace(p.Doc))
shortDesc := descParts[0]
desc := descParts[1:]
filteredPieces := []docPiece{}
filteredTypePieces := []docPiece{}
for _, piece := range pieces {
if !piece.IsInterface {
filteredPieces = append(filteredPieces, piece)
continue
}
modname := piece.ParentModule + "." + piece.Interfacing
if interfaceModules[modname] == nil {
interfaceModules[modname] = &module{
ParentModule: piece.ParentModule,
}
}
if strings.HasSuffix(piece.GoFuncName, strings.ToLower("loader")) {
shortDesc := piece.Doc[0]
desc := piece.Doc[1:]
interfaceModules[modname].ShortDescription = shortDesc
interfaceModules[modname].Description = strings.Join(desc, "\n")
interfaceModules[modname].Fields = piece.Fields
interfaceModules[modname].Properties = piece.Properties
continue
}
interfaceModules[modname].Docs = append(interfaceModules[modname].Docs, piece)
}
for _, piece := range typePieces {
if !piece.IsInterface {
filteredTypePieces = append(filteredTypePieces, piece)
continue
}
modname := piece.ParentModule + "." + piece.Interfacing
if interfaceModules[modname] == nil {
interfaceModules[modname] = &module{
ParentModule: piece.ParentModule,
}
}
interfaceModules[modname].Types = append(interfaceModules[modname].Types, piece)
}
fmt.Println(filteredTypePieces)
if newDoc, ok := docs[mod]; ok {
oldMod := docs[mod]
newDoc.Types = append(filteredTypePieces, oldMod.Types...)
newDoc.Docs = append(filteredPieces, oldMod.Docs...)
docs[mod] = newDoc
} else {
docs[mod] = module{
Types: filteredTypePieces,
Docs: filteredPieces,
ShortDescription: shortDesc,
Description: strings.Join(desc, "\n"),
HasInterfaces: hasInterfaces,
Properties: docPieceTag("property", tags),
Fields: docPieceTag("field", tags),
}
}
}
for key, mod := range interfaceModules {
docs[key] = *mod
}
var wg sync.WaitGroup
wg.Add(len(docs) * 2)
for mod, v := range docs {
docPath := "docs/api/" + mod + ".md"
if v.HasInterfaces {
os.Mkdir("docs/api/"+mod, 0777)
os.Remove(docPath) // remove old doc path if it exists
docPath = "docs/api/" + mod + "/_index.md"
}
if v.ParentModule != "" {
docPath = "docs/api/" + v.ParentModule + "/" + mod + ".md"
}
go func(modname, docPath string, modu module) {
defer wg.Done()
modOrIface := "Module"
if modu.ParentModule != "" {
modOrIface = "Module"
}
lastHeader := ""
f, _ := os.Create(docPath)
f.WriteString(fmt.Sprintf(header, modOrIface, modname, modu.ShortDescription))
typeTag, _ := regexp.Compile(`\B@\w+`)
modDescription := typeTag.ReplaceAllStringFunc(strings.Replace(strings.Replace(modu.Description, "<", `\<`, -1), "{{\\<", "{{<", -1), func(typ string) string {
typName := typ[1:]
typLookup := typeTable[strings.ToLower(typName)]
ifaces := typLookup[0] + "." + typLookup[1] + "/"
if typLookup[1] == "" {
ifaces = ""
}
linkedTyp := fmt.Sprintf("/Hilbish/docs/api/%s/%s#%s", typLookup[0], ifaces, strings.ToLower(typName))
return fmt.Sprintf(`<a href="%s" style="text-decoration: none;">%s</a>`, linkedTyp, typName)
})
f.WriteString(fmt.Sprintf("## Introduction\n%s\n\n", modDescription))
if len(modu.Docs) != 0 {
funcCount := 0
for _, dps := range modu.Docs {
if dps.IsMember {
continue
}
funcCount++
}
f.WriteString("## Functions\n")
lastHeader = "functions"
mdTable := md.NewTable(funcCount, 2)
mdTable.SetTitle(0, "")
mdTable.SetTitle(1, "")
diff := 0
for i, dps := range modu.Docs {
if dps.IsMember {
diff++
continue
}
mdTable.SetContent(i-diff, 0, fmt.Sprintf(`<a href="#%s">%s</a>`, dps.FuncName, dps.FuncSig))
if len(dps.Doc) == 0 {
fmt.Printf("WARNING! Function %s on module %s has no documentation!\n", dps.FuncName, modname)
} else {
mdTable.SetContent(i-diff, 1, dps.Doc[0])
}
}
f.WriteString(mdTable.String())
f.WriteString("\n")
}
if len(modu.Fields) != 0 {
f.WriteString("## Static module fields\n")
mdTable := md.NewTable(len(modu.Fields), 2)
mdTable.SetTitle(0, "")
mdTable.SetTitle(1, "")
for i, dps := range modu.Fields {
mdTable.SetContent(i, 0, dps.FuncName)
mdTable.SetContent(i, 1, strings.Join(dps.Doc, " "))
}
f.WriteString(mdTable.String())
f.WriteString("\n")
}
if len(modu.Properties) != 0 {
f.WriteString("## Object properties\n")
mdTable := md.NewTable(len(modu.Fields), 2)
mdTable.SetTitle(0, "")
mdTable.SetTitle(1, "")
for i, dps := range modu.Properties {
mdTable.SetContent(i, 0, dps.FuncName)
mdTable.SetContent(i, 1, strings.Join(dps.Doc, " "))
}
f.WriteString(mdTable.String())
f.WriteString("\n")
}
if len(modu.Docs) != 0 {
if lastHeader != "functions" {
f.WriteString("## Functions\n")
}
for _, dps := range modu.Docs {
if dps.IsMember {
continue
}
f.WriteString(fmt.Sprintf("<hr>\n<div id='%s'>", dps.FuncName))
htmlSig := typeTag.ReplaceAllStringFunc(strings.Replace(modname+"."+dps.FuncSig, "<", `\<`, -1), func(typ string) string {
typName := typ[1:]
typLookup := typeTable[strings.ToLower(typName)]
ifaces := typLookup[0] + "." + typLookup[1] + "/"
if typLookup[1] == "" {
ifaces = ""
}
linkedTyp := fmt.Sprintf("/Hilbish/docs/api/%s/%s#%s", typLookup[0], ifaces, strings.ToLower(typName))
return fmt.Sprintf(`<a href="%s" style="text-decoration: none;" id="lol">%s</a>`, linkedTyp, typName)
})
f.WriteString(fmt.Sprintf(`
<h4 class='heading'>
%s
<a href="#%s" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
`, htmlSig, dps.FuncName))
for _, doc := range dps.Doc {
if !strings.HasPrefix(doc, "---") && doc != "" {
f.WriteString(doc + " \n")
}
}
f.WriteString("\n#### Parameters\n")
if len(dps.Params) == 0 {
f.WriteString("This function has no parameters. \n")
}
for _, p := range dps.Params {
isVariadic := false
typ := p.Type
if strings.HasPrefix(p.Type, "...") {
isVariadic = true
typ = p.Type[3:]
}
f.WriteString(fmt.Sprintf("`%s` **`%s`**", typ, p.Name))
if isVariadic {
f.WriteString(" (This type is variadic. You can pass an infinite amount of parameters with this type.)")
}
f.WriteString(" \n")
f.WriteString(strings.Join(p.Doc, " "))
f.WriteString("\n\n")
}
if codeExample := dps.Tags["example"]; codeExample != nil {
f.WriteString("#### Example\n")
f.WriteString(fmt.Sprintf("```lua\n%s\n```\n", strings.Join(codeExample[0].fields, "\n")))
}
f.WriteString("</div>")
f.WriteString("\n\n")
}
}
if len(modu.Types) != 0 {
f.WriteString("## Types\n")
for _, dps := range modu.Types {
f.WriteString("<hr>\n\n")
f.WriteString(fmt.Sprintf("## %s\n", dps.FuncName))
for _, doc := range dps.Doc {
if !strings.HasPrefix(doc, "---") {
f.WriteString(doc + "\n")
}
}
if len(dps.Properties) != 0 {
f.WriteString("## Object properties\n")
mdTable := md.NewTable(len(dps.Properties), 2)
mdTable.SetTitle(0, "")
mdTable.SetTitle(1, "")
for i, d := range dps.Properties {
mdTable.SetContent(i, 0, d.FuncName)
mdTable.SetContent(i, 1, strings.Join(d.Doc, " "))
}
f.WriteString(mdTable.String())
f.WriteString("\n")
}
f.WriteString("\n")
f.WriteString("### Methods\n")
for _, dps := range modu.Docs {
if !dps.IsMember {
continue
}
htmlSig := typeTag.ReplaceAllStringFunc(strings.Replace(dps.FuncSig, "<", `\<`, -1), func(typ string) string {
typName := regexp.MustCompile(`\w+`).FindString(typ[1:])
typLookup := typeTable[strings.ToLower(typName)]
fmt.Printf("%+q, \n", typLookup)
linkedTyp := fmt.Sprintf("/Hilbish/docs/api/%s/%s/#%s", typLookup[0], typLookup[0]+"."+typLookup[1], strings.ToLower(typName))
return fmt.Sprintf(`<a href="#%s" style="text-decoration: none;">%s</a>`, linkedTyp, typName)
})
f.WriteString(fmt.Sprintf("#### %s\n", htmlSig))
for _, doc := range dps.Doc {
if !strings.HasPrefix(doc, "---") {
f.WriteString(doc + "\n")
}
}
f.WriteString("\n")
}
}
}
}(mod, docPath, v)
go func(md, modname string, modu module) {
defer wg.Done()
if modu.ParentModule != "" {
return
}
ff, _ := os.Create("emmyLuaDocs/" + modname + ".lua")
ff.WriteString("--- @meta\n\nlocal " + modname + " = {}\n\n")
for _, em := range emmyDocs[modname] {
if strings.HasSuffix(em.DocPiece.GoFuncName, strings.ToLower("loader")) {
continue
}
dps := em.DocPiece
funcdocs := dps.Doc
ff.WriteString("--- " + strings.Join(funcdocs, "\n--- ") + "\n")
if len(em.Annotations) != 0 {
ff.WriteString(strings.Join(em.Annotations, "\n") + "\n")
}
accessor := "."
if dps.IsMember {
accessor = ":"
}
signature := strings.Split(dps.FuncSig, " ->")[0]
var intrface string
if dps.IsInterface {
intrface = "." + dps.Interfacing
}
ff.WriteString("function " + modname + intrface + accessor + signature + " end\n\n")
}
ff.WriteString("return " + modname + "\n")
}(mod, mod, v)
}
wg.Wait()
}

227
cmd/docgen/docgen.lua Normal file
View File

@ -0,0 +1,227 @@
local fs = require 'fs'
local emmyPattern = '^%-%-%- (.+)'
local emmyPattern2 = '^%-%- (.+)'
local modpattern = '^%-+ @module (.+)'
local pieces = {}
local descriptions = {}
local files = fs.readdir 'nature'
for _, fname in ipairs(files) do
local isScript = fname:match'%.lua$'
if not isScript then goto continue end
local f = io.open(string.format('nature/%s', fname))
local header = f:read '*l'
local mod = header:match(modpattern)
if not mod then goto continue end
pieces[mod] = {}
descriptions[mod] = {}
local docPiece = {}
local lines = {}
local lineno = 0
local doingDescription = true
for line in f:lines() do
lineno = lineno + 1
lines[lineno] = line
if line == header then goto continue2 end
if line:match(emmyPattern) or line:match(emmyPattern2) then
if doingDescription then
table.insert(descriptions[mod], line:match(emmyPattern) or line:match(emmyPattern2))
end
else
doingDescription = false
if line:match '^function' then
local pattern = (string.format('^function %s%%.', mod) .. '(%w+)')
local funcName = line:match(pattern)
if not funcName then goto continue2 end
local dps = {
description = {},
example = {},
params = {}
}
local offset = 1
local doingExample = false
while true do
local prev = lines[lineno - offset]
local docline = prev:match '^%-+ (.+)'
if docline then
local emmy = docline:match '@(%w+)'
local cut = 0
if emmy then cut = emmy:len() + 3 end
local emmythings = string.split(docline:sub(cut), ' ')
if emmy then
if emmy == 'param' then
table.insert(dps.params, 1, {
name = emmythings[1],
type = emmythings[2],
-- the +1 accounts for space.
description = table.concat(emmythings, ' '):sub(emmythings[1]:len() + 1 + emmythings[2]:len() + 1)
})
end
else
if docline:match '#example' then
doingExample = not doingExample
end
if not docline:match '#example' then
if doingExample then
table.insert(dps.example, 1, docline)
else
table.insert(dps.description, 1, docline)
end
end
end
offset = offset + 1
else
break
end
end
table.insert(pieces[mod], {funcName, dps})
end
docPiece = {}
goto continue2
end
table.insert(docPiece, line)
::continue2::
end
::continue::
end
local header = [[---
title: %s %s
description: %s
layout: doc
menu:
docs:
parent: "%s"
---
]]
for iface, dps in pairs(pieces) do
local mod = iface:match '(%w+)%.' or 'nature'
local docParent = 'Nature'
path = string.format('docs/%s/%s.md', mod, iface)
if mod ~= 'nature' then
docParent = "API"
path = string.format('docs/api/%s/%s.md', mod, iface)
end
if iface == 'hilbish' then
docParent = "API"
path = string.format('docs/api/hilbish/_index.md', mod, iface)
end
fs.mkdir(fs.dir(path), true)
local exists = pcall(fs.stat, path)
local newOrNotNature = (exists and mod ~= 'nature') or iface == 'hilbish'
local f <close> = io.open(path, newOrNotNature and 'r+' or 'w+')
local tocPos
if not newOrNotNature then
f:write(string.format(header, 'Module', iface, (descriptions[iface] and #descriptions[iface] > 0) and descriptions[iface][1] or 'No description.', docParent))
if descriptions[iface] and #descriptions[iface] > 0 then
table.remove(descriptions[iface], 1)
f:write(string.format('\n## Introduction\n%s\n\n', table.concat(descriptions[iface], '\n')))
f:write('## Functions\n')
f:write([[|||
|----|----|
]])
tocPos = f:seek()
end
end
local tocSearch = false
for line in f:lines() do
if line:match '^## Functions' then
tocSearch = true
end
if tocSearch and line == '' then
tocSearch = false
tocPos = f:seek() - 1
end
end
table.sort(dps, function(a, b) return a[1] < b[1] end)
for _, piece in pairs(dps) do
local func = piece[1]
local docs = piece[2]
local sig = string.format('%s.%s(', iface, func)
local params = ''
for idx, param in ipairs(docs.params) do
sig = sig .. param.name:gsub('%?$', '')
params = params .. param.name:gsub('%?$', '')
if idx ~= #docs.params then
sig = sig .. ', '
params = params .. ', '
end
end
sig = sig .. ')'
if tocPos then
f:seek('set', tocPos)
local contents = f:read '*a'
f:seek('set', tocPos)
local tocLine = string.format('|<a href="#%s">%s</a>|%s|\n', func, string.format('%s(%s)', func, params), docs.description[1])
f:write(tocLine .. contents)
f:seek 'end'
end
f:write(string.format('<hr>\n<div id=\'%s\'>\n', func))
f:write(string.format([[
<h4 class='heading'>
%s
<a href="#%s" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
]], sig, func))
f:write(table.concat(docs.description, '\n') .. '\n')
f:write '#### Parameters\n'
if #docs.params == 0 then
f:write 'This function has no parameters. \n'
end
for _, param in ipairs(docs.params) do
f:write(string.format('`%s` **`%s`** \n', param.name:gsub('%?$', ''), param.type))
f:write(string.format('%s\n\n', param.description))
end
if #docs.example ~= 0 then
f:write '#### Example\n'
f:write(string.format('```lua\n%s\n```\n', table.concat(docs.example, '\n')))
end
--[[
local params = table.filter(docs, function(t)
return t:match '^%-%-%- @param'
end)
for i, str in ipairs(params) do
if i ~= 1 then
f:write ', '
end
f:write(str:match '^%-%-%- @param ([%w]+) ')
end
f:write(')\n')
for _, str in ipairs(docs) do
if not str:match '^%-%-%- @' then
f:write(str:match '^%-%-%- (.+)' .. '\n')
end
end
]]--
f:write('</div>')
f:write('\n\n')
end
end

376
complete.go Normal file
View File

@ -0,0 +1,376 @@
package main
import (
"errors"
"path/filepath"
"strings"
"os"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
)
var charEscapeMap = []string{
"\"", "\\\"",
"'", "\\'",
"`", "\\`",
" ", "\\ ",
"(", "\\(",
")", "\\)",
"[", "\\[",
"]", "\\]",
"$", "\\$",
"&", "\\&",
"*", "\\*",
">", "\\>",
"<", "\\<",
"|", "\\|",
}
var charEscapeMapInvert = invert(charEscapeMap)
var escapeReplaer = strings.NewReplacer(charEscapeMap...)
var escapeInvertReplaer = strings.NewReplacer(charEscapeMapInvert...)
func invert(m []string) []string {
newM := make([]string, len(charEscapeMap))
for i := range m {
if (i + 1) % 2 == 0 {
newM[i] = m[i - 1]
newM[i - 1] = m[i]
}
}
return newM
}
func splitForFile(str string) []string {
split := []string{}
sb := &strings.Builder{}
quoted := false
for i, r := range str {
if r == '"' {
quoted = !quoted
sb.WriteRune(r)
} else if r == ' ' && str[i - 1] == '\\' {
sb.WriteRune(r)
} else if !quoted && r == ' ' {
split = append(split, sb.String())
sb.Reset()
} else {
sb.WriteRune(r)
}
}
if strings.HasSuffix(str, " ") {
split = append(split, "")
}
if sb.Len() > 0 {
split = append(split, sb.String())
}
return split
}
func fileComplete(query, ctx string, fields []string) ([]string, string) {
q := splitForFile(ctx)
path := ""
if len(q) != 0 {
path = q[len(q) - 1]
}
return matchPath(path)
}
func binaryComplete(query, ctx string, fields []string) ([]string, string) {
q := splitForFile(ctx)
query = ""
if len(q) != 0 {
query = q[len(q) - 1]
}
var completions []string
prefixes := []string{"./", "../", "/", "~/"}
for _, prefix := range prefixes {
if strings.HasPrefix(query, prefix) {
fileCompletions, filePref := matchPath(query)
if len(fileCompletions) != 0 {
for _, f := range fileCompletions {
fullPath, _ := filepath.Abs(util.ExpandHome(query + strings.TrimPrefix(f, filePref)))
if err := util.FindExecutable(escapeInvertReplaer.Replace(fullPath), false, true); err != nil {
continue
}
completions = append(completions, f)
}
}
return completions, filePref
}
}
// filter out executables, but in path
for _, dir := range filepath.SplitList(os.Getenv("PATH")) {
// search for an executable which matches our query string
if matches, err := filepath.Glob(filepath.Join(dir, query + "*")); err == nil {
// get basename from matches
for _, match := range matches {
// check if we have execute permissions for our match
err := util.FindExecutable(match, true, false)
if err != nil {
continue
}
// get basename from match
name := filepath.Base(match)
// add basename to completions
completions = append(completions, name)
}
}
}
// add lua registered commands to completions
for cmdName := range cmds.Commands {
if strings.HasPrefix(cmdName, query) {
completions = append(completions, cmdName)
}
}
completions = removeDupes(completions)
return completions, query
}
func matchPath(query string) ([]string, string) {
oldQuery := query
query = strings.TrimPrefix(query, "\"")
var entries []string
var baseName string
query = escapeInvertReplaer.Replace(query)
path, _ := filepath.Abs(util.ExpandHome(filepath.Dir(query)))
if string(query) == "" {
// filepath base below would give us "."
// which would cause a match of only dotfiles
path, _ = filepath.Abs(".")
} else if !strings.HasSuffix(query, string(os.PathSeparator)) {
baseName = filepath.Base(query)
}
files, _ := os.ReadDir(path)
for _, entry := range files {
file, err := entry.Info()
if err != nil {
continue
}
if file.Mode() & os.ModeSymlink != 0 {
path, err := filepath.EvalSymlinks(filepath.Join(path, file.Name()))
if err == nil {
file, err = os.Lstat(path)
}
}
if strings.HasPrefix(file.Name(), baseName) {
entry := file.Name()
if file.IsDir() {
entry = entry + string(os.PathSeparator)
}
if !strings.HasPrefix(oldQuery, "\"") {
entry = escapeFilename(entry)
}
entries = append(entries, entry)
}
}
if !strings.HasPrefix(oldQuery, "\"") {
baseName = escapeFilename(baseName)
}
return entries, baseName
}
func escapeFilename(fname string) string {
return escapeReplaer.Replace(fname)
}
// #interface completion
// tab completions
// The completions interface deals with tab completions.
func completionLoader(rtm *rt.Runtime) *rt.Table {
exports := map[string]util.LuaExport{
"bins": {hcmpBins, 3, false},
"call": {hcmpCall, 4, false},
"files": {hcmpFiles, 3, false},
"handler": {hcmpHandler, 2, false},
}
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
return mod
}
// #interface completion
// bins(query, ctx, fields) -> entries (table), prefix (string)
// Return binaries/executables based on the provided parameters.
// This function is meant to be used as a helper in a command completion handler.
// #param query string
// #param ctx string
// #param fields table
/*
#example
-- an extremely simple completer for sudo.
hilbish.complete('command.sudo', function(query, ctx, fields)
table.remove(fields, 1)
if #fields[1] then
-- return commands because sudo runs a command as root..!
local entries, pfx = hilbish.completion.bins(query, ctx, fields)
return {
type = 'grid',
items = entries
}, pfx
end
-- ... else suggest files or anything else ..
end)
#example
*/
func hcmpBins(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
query, ctx, fds, err := getCompleteParams(t, c)
if err != nil {
return nil, err
}
completions, pfx := binaryComplete(query, ctx, fds)
luaComps := rt.NewTable()
for i, comp := range completions {
luaComps.Set(rt.IntValue(int64(i + 1)), rt.StringValue(comp))
}
return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil
}
// #interface completion
// call(name, query, ctx, fields) -> completionGroups (table), prefix (string)
// Calls a completer function. This is mainly used to call a command completer, which will have a `name`
// in the form of `command.name`, example: `command.git`.
// You can check the Completions doc or `doc completions` for info on the `completionGroups` return value.
// #param name string
// #param query string
// #param ctx string
// #param fields table
func hcmpCall(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(4); err != nil {
return nil, err
}
completer, err := c.StringArg(0)
if err != nil {
return nil, err
}
query, err := c.StringArg(1)
if err != nil {
return nil, err
}
ctx, err := c.StringArg(2)
if err != nil {
return nil, err
}
fields, err := c.TableArg(3)
if err != nil {
return nil, err
}
var completecb *rt.Closure
var ok bool
if completecb, ok = luaCompletions[completer]; !ok {
return nil, errors.New("completer " + completer + " does not exist")
}
// we must keep the holy 80 cols
cont := c.Next()
err = rt.Call(l.MainThread(), rt.FunctionValue(completecb),
[]rt.Value{rt.StringValue(query), rt.StringValue(ctx), rt.TableValue(fields)},
cont)
if err != nil {
return nil, err
}
return cont, nil
}
// #interface completion
// files(query, ctx, fields) -> entries (table), prefix (string)
// Returns file matches based on the provided parameters.
// This function is meant to be used as a helper in a command completion handler.
// #param query string
// #param ctx string
// #param fields table
func hcmpFiles(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
query, ctx, fds, err := getCompleteParams(t, c)
if err != nil {
return nil, err
}
completions, pfx := fileComplete(query, ctx, fds)
luaComps := rt.NewTable()
for i, comp := range completions {
luaComps.Set(rt.IntValue(int64(i + 1)), rt.StringValue(comp))
}
return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil
}
// #interface completion
// handler(line, pos)
// This function contains the general completion handler for Hilbish. This function handles
// completion of everything, which includes calling other command handlers, binaries, and files.
// This function can be overriden to supply a custom handler. Note that alias resolution is required to be done in this function.
// #param line string The current Hilbish command line
// #param pos number Numerical position of the cursor
/*
#example
-- stripped down version of the default implementation
function hilbish.completion.handler(line, pos)
local query = fields[#fields]
if #fields == 1 then
-- call bins handler here
else
-- call command completer or files completer here
end
end
#example
*/
func hcmpHandler(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, error) {
if err := c.CheckNArgs(3); err != nil {
return "", "", []string{}, err
}
query, err := c.StringArg(0)
if err != nil {
return "", "", []string{}, err
}
ctx, err := c.StringArg(1)
if err != nil {
return "", "", []string{}, err
}
fields, err := c.TableArg(2)
if err != nil {
return "", "", []string{}, err
}
var fds []string
util.ForEach(fields, func(k rt.Value, v rt.Value) {
if v.Type() == rt.StringType {
fds = append(fds, v.AsString())
}
})
return query, ctx, fds, err
}

13
docs/_index.md Normal file
View File

@ -0,0 +1,13 @@
---
title: Introduction
layout: doc
weight: -1
menu: docs
---
Hilbish is a hyper-extensible shell mainly intended for interactive use.
To enhance the interactive experience, Hilbish comes with a wide range
of features and sane defaults, including a nice looking prompt,
advanced completion menus and history search.
Here documents some of the features of Hilbish and the Lua API.

9
docs/api/_index.md Normal file
View File

@ -0,0 +1,9 @@
---
title: API
layout: doc
weight: -100
menu: docs
---
Welcome to the API documentation for Hilbish. This documents Lua functions
provided by Hilbish.

167
docs/api/bait.md Normal file
View File

@ -0,0 +1,167 @@
---
title: Module bait
description: the event emitter
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
Bait is the event emitter for Hilbish. Much like Node.js and
its `events` system, many actions in Hilbish emit events.
Unlike Node.js, Hilbish events are global. So make sure to
pick a unique name!
Usage of the Bait module consists of userstanding
event-driven architecture, but it's pretty simple:
If you want to act on a certain event, you can `catch` it.
You can act on events via callback functions.
Examples of this are in the Hilbish default config!
Consider this part of it:
```lua
bait.catch('command.exit', function(code)
running = false
doPrompt(code ~= 0)
doNotifyPrompt()
end)
```
What this does is, whenever the `command.exit` event is thrown,
this function will set the user prompt.
## Functions
|||
|----|----|
|<a href="#catch">catch(name, cb)</a>|Catches an event. This function can be used to act on events.|
|<a href="#catchOnce">catchOnce(name, cb)</a>|Catches an event, but only once. This will remove the hook immediately after it runs for the first time.|
|<a href="#hooks">hooks(name) -> table</a>|Returns a table of functions that are hooked on an event with the corresponding `name`.|
|<a href="#release">release(name, catcher)</a>|Removes the `catcher` for the event with `name`.|
|<a href="#throw">throw(name, ...args)</a>|Throws a hook with `name` with the provided `args`.|
<hr>
<div id='catch'>
<h4 class='heading'>
bait.catch(name, cb)
<a href="#catch" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Catches an event. This function can be used to act on events.
#### Parameters
`string` **`name`**
The name of the hook.
`function` **`cb`**
The function that will be called when the hook is thrown.
#### Example
```lua
bait.catch('hilbish.exit', function()
print 'Goodbye Hilbish!'
end)
```
</div>
<hr>
<div id='catchOnce'>
<h4 class='heading'>
bait.catchOnce(name, cb)
<a href="#catchOnce" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Catches an event, but only once. This will remove the hook immediately after it runs for the first time.
#### Parameters
`string` **`name`**
The name of the event
`function` **`cb`**
The function that will be called when the event is thrown.
</div>
<hr>
<div id='hooks'>
<h4 class='heading'>
bait.hooks(name) -> table
<a href="#hooks" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns a table of functions that are hooked on an event with the corresponding `name`.
#### Parameters
`string` **`name`**
The name of the hook
</div>
<hr>
<div id='release'>
<h4 class='heading'>
bait.release(name, catcher)
<a href="#release" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Removes the `catcher` for the event with `name`.
For this to work, `catcher` has to be the same function used to catch
an event, like one saved to a variable.
#### Parameters
`string` **`name`**
Name of the event the hook is on
`function` **`catcher`**
Hook function to remove
#### Example
```lua
local hookCallback = function() print 'hi' end
bait.catch('event', hookCallback)
-- a little while later....
bait.release('event', hookCallback)
-- and now hookCallback will no longer be ran for the event.
```
</div>
<hr>
<div id='throw'>
<h4 class='heading'>
bait.throw(name, ...args)
<a href="#throw" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Throws a hook with `name` with the provided `args`.
#### Parameters
`string` **`name`**
The name of the hook.
`any` **`args`** (This type is variadic. You can pass an infinite amount of parameters with this type.)
The arguments to pass to the hook.
#### Example
```lua
bait.throw('greeting', 'world')
-- This can then be listened to via
bait.catch('gretting', function(greetTo)
print('Hello ' .. greetTo)
end)
```
</div>

113
docs/api/commander.md Normal file
View File

@ -0,0 +1,113 @@
---
title: Module commander
description: library for custom commands
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
Commander is the library which handles Hilbish commands. This makes
the user able to add Lua-written commands to their shell without making
a separate script in a bin folder. Instead, you may simply use the Commander
library in your Hilbish config.
```lua
local commander = require 'commander'
commander.register('hello', function(args, sinks)
sinks.out:writeln 'Hello world!'
end)
```
In this example, a command with the name of `hello` is created
that will print `Hello world!` to output. One question you may
have is: What is the `sinks` parameter?
The `sinks` parameter is a table with 3 keys: `input`, `out`, and `err`.
There is an `in` alias to `input`, but it requires using the string accessor syntax (`sinks['in']`)
as `in` is also a Lua keyword, so `input` is preferred for use.
All of them are a <a href="/Hilbish/docs/api/hilbish/#sink" style="text-decoration: none;">Sink</a>.
In the future, `sinks.in` will be removed.
- `in` is the standard input.
You may use the read functions on this sink to get input from the user.
- `out` is standard output.
This is usually where command output should go.
- `err` is standard error.
This sink is for writing errors, as the name would suggest.
## Functions
|||
|----|----|
|<a href="#deregister">deregister(name)</a>|Removes the named command. Note that this will only remove Commander-registered commands.|
|<a href="#register">register(name, cb)</a>|Adds a new command with the given `name`. When Hilbish has to run a command with a name,|
|<a href="#registry">registry() -> table</a>|Returns all registered commanders. Returns a list of tables with the following keys:|
<hr>
<div id='deregister'>
<h4 class='heading'>
commander.deregister(name)
<a href="#deregister" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Removes the named command. Note that this will only remove Commander-registered commands.
#### Parameters
`string` **`name`**
Name of the command to remove.
</div>
<hr>
<div id='register'>
<h4 class='heading'>
commander.register(name, cb)
<a href="#register" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Adds a new command with the given `name`. When Hilbish has to run a command with a name,
it will run the function providing the arguments and sinks.
#### Parameters
`string` **`name`**
Name of the command
`function` **`cb`**
Callback to handle command invocation
#### Example
```lua
-- When you run the command `hello` in the shell, it will print `Hello world`.
-- If you run it with, for example, `hello Hilbish`, it will print 'Hello Hilbish'
commander.register('hello', function(args, sinks)
local name = 'world'
if #args > 0 then name = args[1] end
sinks.out:writeln('Hello ' .. name)
end)
```
</div>
<hr>
<div id='registry'>
<h4 class='heading'>
commander.registry() -> table
<a href="#registry" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns all registered commanders. Returns a list of tables with the following keys:
- `exec`: The function used to run the commander. Commanders require args and sinks to be passed.
#### Parameters
This function has no parameters.
</div>

257
docs/api/fs.md Normal file
View File

@ -0,0 +1,257 @@
---
title: Module fs
description: filesystem interaction and functionality library
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The fs module provides filesystem functions to Hilbish. While Lua's standard
library has some I/O functions, they're missing a lot of the basics. The `fs`
library offers more functions and will work on any operating system Hilbish does.
## Functions
|||
|----|----|
|<a href="#abs">abs(path) -> string</a>|Returns an absolute version of the `path`.|
|<a href="#basename">basename(path) -> string</a>|Returns the "basename," or the last part of the provided `path`. If path is empty,|
|<a href="#cd">cd(dir)</a>|Changes Hilbish's directory to `dir`.|
|<a href="#dir">dir(path) -> string</a>|Returns the directory part of `path`. If a file path like|
|<a href="#glob">glob(pattern) -> matches (table)</a>|Match all files based on the provided `pattern`.|
|<a href="#join">join(...path) -> string</a>|Takes any list of paths and joins them based on the operating system's path separator.|
|<a href="#mkdir">mkdir(name, recursive)</a>|Creates a new directory with the provided `name`.|
|<a href="#pipe">fpipe() -> File, File</a>|Returns a pair of connected files, also known as a pipe.|
|<a href="#readdir">readdir(path) -> table[string]</a>|Returns a list of all files and directories in the provided path.|
|<a href="#stat">stat(path) -> {}</a>|Returns the information about a given `path`.|
## Static module fields
|||
|----|----|
|pathSep|The operating system's path separator.|
<hr>
<div id='abs'>
<h4 class='heading'>
fs.abs(path) -> string
<a href="#abs" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns an absolute version of the `path`.
This can be used to resolve short paths like `..` to `/home/user`.
#### Parameters
`string` **`path`**
</div>
<hr>
<div id='basename'>
<h4 class='heading'>
fs.basename(path) -> string
<a href="#basename" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the "basename," or the last part of the provided `path`. If path is empty,
`.` will be returned.
#### Parameters
`string` **`path`**
Path to get the base name of.
</div>
<hr>
<div id='cd'>
<h4 class='heading'>
fs.cd(dir)
<a href="#cd" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Changes Hilbish's directory to `dir`.
#### Parameters
`string` **`dir`**
Path to change directory to.
</div>
<hr>
<div id='dir'>
<h4 class='heading'>
fs.dir(path) -> string
<a href="#dir" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the directory part of `path`. If a file path like
`~/Documents/doc.txt` then this function will return `~/Documents`.
#### Parameters
`string` **`path`**
Path to get the directory for.
</div>
<hr>
<div id='glob'>
<h4 class='heading'>
fs.glob(pattern) -> matches (table)
<a href="#glob" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Match all files based on the provided `pattern`.
For the syntax' refer to Go's filepath.Match function: https://pkg.go.dev/path/filepath#Match
#### Parameters
`string` **`pattern`**
Pattern to compare files with.
#### Example
```lua
--[[
Within a folder that contains the following files:
a.txt
init.lua
code.lua
doc.pdf
]]--
local matches = fs.glob './*.lua'
print(matches)
-- -> {'init.lua', 'code.lua'}
```
</div>
<hr>
<div id='join'>
<h4 class='heading'>
fs.join(...path) -> string
<a href="#join" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Takes any list of paths and joins them based on the operating system's path separator.
#### Parameters
`string` **`path`** (This type is variadic. You can pass an infinite amount of parameters with this type.)
Paths to join together
#### Example
```lua
-- This prints the directory for Hilbish's config!
print(fs.join(hilbish.userDir.config, 'hilbish'))
-- -> '/home/user/.config/hilbish' on Linux
```
</div>
<hr>
<div id='mkdir'>
<h4 class='heading'>
fs.mkdir(name, recursive)
<a href="#mkdir" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Creates a new directory with the provided `name`.
With `recursive`, mkdir will create parent directories.
#### Parameters
`string` **`name`**
Name of the directory
`boolean` **`recursive`**
Whether to create parent directories for the provided name
#### Example
```lua
-- This will create the directory foo, then create the directory bar in the
-- foo directory. If recursive is false in this case, it will fail.
fs.mkdir('./foo/bar', true)
```
</div>
<hr>
<div id='pipe'>
<h4 class='heading'>
fs.fpipe() -> File, File
<a href="#pipe" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns a pair of connected files, also known as a pipe.
The type returned is a Lua file, same as returned from `io` functions.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='readdir'>
<h4 class='heading'>
fs.readdir(path) -> table[string]
<a href="#readdir" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns a list of all files and directories in the provided path.
#### Parameters
`string` **`dir`**
</div>
<hr>
<div id='stat'>
<h4 class='heading'>
fs.stat(path) -> {}
<a href="#stat" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the information about a given `path`.
The returned table contains the following values:
name (string) - Name of the path
size (number) - Size of the path in bytes
mode (string) - Unix permission mode in an octal format string (with leading 0)
isDir (boolean) - If the path is a directory
#### Parameters
`string` **`path`**
#### Example
```lua
local inspect = require 'inspect'
local stat = fs.stat '~'
print(inspect(stat))
--[[
Would print the following:
{
isDir = true,
mode = "0755",
name = "username",
size = 12288
}
]]--
```
</div>

541
docs/api/hilbish/_index.md Normal file
View File

@ -0,0 +1,541 @@
---
title: Module hilbish
description: the core Hilbish API
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The Hilbish module includes the core API, containing
interfaces and functions which directly relate to shell functionality.
## Functions
|||
|----|----|
|<a href="#alias">alias(cmd, orig)</a>|Sets an alias, with a name of `cmd` to another command.|
|<a href="#appendPath">appendPath(dir)</a>|Appends the provided dir to the command path (`$PATH`)|
|<a href="#complete">complete(scope, cb)</a>|Registers a completion handler for the specified scope.|
|<a href="#cwd">cwd() -> string</a>|Returns the current directory of the shell.|
|<a href="#exec">exec(cmd)</a>|Replaces the currently running Hilbish instance with the supplied command.|
|<a href="#goro">goro(fn)</a>|Puts `fn` in a Goroutine.|
|<a href="#highlighter">highlighter(line)</a>|Line highlighter handler.|
|<a href="#hinter">hinter(line, pos)</a>|The command line hint handler. It gets called on every key insert to|
|<a href="#inputMode">inputMode(mode)</a>|Sets the input mode for Hilbish's line reader.|
|<a href="#interval">interval(cb, time) -> @Timer</a>|Runs the `cb` function every specified amount of `time`.|
|<a href="#multiprompt">multiprompt(str)</a>|Changes the text prompt when Hilbish asks for more input.|
|<a href="#prependPath">prependPath(dir)</a>|Prepends `dir` to $PATH.|
|<a href="#prompt">prompt(str, typ)</a>|Changes the shell prompt to the provided string.|
|<a href="#read">read(prompt) -> input (string)</a>|Read input from the user, using Hilbish's line editor/input reader.|
|<a href="#timeout">timeout(cb, time) -> @Timer</a>|Executed the `cb` function after a period of `time`.|
|<a href="#which">which(name) -> string</a>|Checks if `name` is a valid command.|
|<a href="#runnerMode">runnerMode(mode)</a>|Sets the execution/runner mode for interactive Hilbish.|
|<a href="#run">run(cmd, streams)</a>|Runs `cmd` in Hilbish's shell script interpreter.|
## Static module fields
|||
|----|----|
|ver|The version of Hilbish|
|goVersion|The version of Go that Hilbish was compiled with|
|user|Username of the user|
|host|Hostname of the machine|
|dataDir|Directory for Hilbish data files, including the docs and default modules|
|interactive|Is Hilbish in an interactive shell?|
|login|Is Hilbish the login shell?|
|vimMode|Current Vim input mode of Hilbish (will be nil if not in Vim input mode)|
|exitCode|Exit code of the last executed command|
<hr>
<div id='alias'>
<h4 class='heading'>
hilbish.alias(cmd, orig)
<a href="#alias" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets an alias, with a name of `cmd` to another command.
#### Parameters
`string` **`cmd`**
Name of the alias
`string` **`orig`**
Command that will be aliased
#### Example
```lua
-- With this, "ga file" will turn into "git add file"
hilbish.alias('ga', 'git add')
-- Numbered substitutions are supported here!
hilbish.alias('dircount', 'ls %1 | wc -l')
-- "dircount ~" would count how many files are in ~ (home directory).
```
</div>
<hr>
<div id='appendPath'>
<h4 class='heading'>
hilbish.appendPath(dir)
<a href="#appendPath" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Appends the provided dir to the command path (`$PATH`)
#### Parameters
`string|table` **`dir`**
Directory (or directories) to append to path
#### Example
```lua
hilbish.appendPath '~/go/bin'
-- Will add ~/go/bin to the command path.
-- Or do multiple:
hilbish.appendPath {
'~/go/bin',
'~/.local/bin'
}
```
</div>
<hr>
<div id='complete'>
<h4 class='heading'>
hilbish.complete(scope, cb)
<a href="#complete" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Registers a completion handler for the specified scope.
A `scope` is expected to be `command.<cmd>`,
replacing <cmd> with the name of the command (for example `command.git`).
The documentation for completions, under Features/Completions or `doc completions`
provides more details.
#### Parameters
`string` **`scope`**
`function` **`cb`**
#### Example
```lua
-- This is a very simple example. Read the full doc for completions for details.
hilbish.complete('command.sudo', function(query, ctx, fields)
if #fields == 0 then
-- complete for commands
local comps, pfx = hilbish.completion.bins(query, ctx, fields)
local compGroup = {
items = comps, -- our list of items to complete
type = 'grid' -- what our completions will look like.
}
return {compGroup}, pfx
end
-- otherwise just be boring and return files
local comps, pfx = hilbish.completion.files(query, ctx, fields)
local compGroup = {
items = comps,
type = 'grid'
}
return {compGroup}, pfx
end)
```
</div>
<hr>
<div id='cwd'>
<h4 class='heading'>
hilbish.cwd() -> string
<a href="#cwd" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the current directory of the shell.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='exec'>
<h4 class='heading'>
hilbish.exec(cmd)
<a href="#exec" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Replaces the currently running Hilbish instance with the supplied command.
This can be used to do an in-place restart.
#### Parameters
`string` **`cmd`**
</div>
<hr>
<div id='goro'>
<h4 class='heading'>
hilbish.goro(fn)
<a href="#goro" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Puts `fn` in a Goroutine.
This can be used to run any function in another thread at the same time as other Lua code.
**NOTE: THIS FUNCTION MAY CRASH HILBISH IF OUTSIDE VARIABLES ARE ACCESSED.**
**This is a limitation of the Lua runtime.**
#### Parameters
`function` **`fn`**
</div>
<hr>
<div id='highlighter'>
<h4 class='heading'>
hilbish.highlighter(line)
<a href="#highlighter" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Line highlighter handler.
This is mainly for syntax highlighting, but in reality could set the input
of the prompt to *display* anything. The callback is passed the current line
and is expected to return a line that will be used as the input display.
Note that to set a highlighter, one has to override this function.
#### Parameters
`string` **`line`**
#### Example
```lua
--This code will highlight all double quoted strings in green.
function hilbish.highlighter(line)
return line:gsub('"%w+"', function(c) return lunacolors.green(c) end)
end
```
</div>
<hr>
<div id='hinter'>
<h4 class='heading'>
hilbish.hinter(line, pos)
<a href="#hinter" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
The command line hint handler. It gets called on every key insert to
determine what text to use as an inline hint. It is passed the current
line and cursor position. It is expected to return a string which is used
as the text for the hint. This is by default a shim. To set hints,
override this function with your custom handler.
#### Parameters
`string` **`line`**
`number` **`pos`**
Position of cursor in line. Usually equals string.len(line)
#### Example
```lua
-- this will display "hi" after the cursor in a dimmed color.
function hilbish.hinter(line, pos)
return 'hi'
end
```
</div>
<hr>
<div id='inputMode'>
<h4 class='heading'>
hilbish.inputMode(mode)
<a href="#inputMode" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets the input mode for Hilbish's line reader.
`emacs` is the default. Setting it to `vim` changes behavior of input to be
Vim-like with modes and Vim keybinds.
#### Parameters
`string` **`mode`**
Can be set to either `emacs` or `vim`
</div>
<hr>
<div id='interval'>
<h4 class='heading'>
hilbish.interval(cb, time) -> <a href="/Hilbish/docs/api/hilbish/hilbish.timers/#timer" style="text-decoration: none;" id="lol">Timer</a>
<a href="#interval" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Runs the `cb` function every specified amount of `time`.
This creates a timer that ticking immediately.
#### Parameters
`function` **`cb`**
`number` **`time`**
Time in milliseconds.
</div>
<hr>
<div id='multiprompt'>
<h4 class='heading'>
hilbish.multiprompt(str)
<a href="#multiprompt" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Changes the text prompt when Hilbish asks for more input.
This will show up when text is incomplete, like a missing quote
#### Parameters
`string` **`str`**
#### Example
```lua
--[[
imagine this is your text input:
user ~ ∆ echo "hey
but there's a missing quote! hilbish will now prompt you so the terminal
will look like:
user ~ ∆ echo "hey
--> ...!"
so then you get
user ~ ∆ echo "hey
--> ...!"
hey ...!
]]--
hilbish.multiprompt '-->'
```
</div>
<hr>
<div id='prependPath'>
<h4 class='heading'>
hilbish.prependPath(dir)
<a href="#prependPath" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Prepends `dir` to $PATH.
#### Parameters
`string` **`dir`**
</div>
<hr>
<div id='prompt'>
<h4 class='heading'>
hilbish.prompt(str, typ)
<a href="#prompt" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Changes the shell prompt to the provided string.
There are a few verbs that can be used in the prompt text.
These will be formatted and replaced with the appropriate values.
`%d` - Current working directory
`%u` - Name of current user
`%h` - Hostname of device
#### Parameters
`string` **`str`**
`string` **`typ?`**
Type of prompt, being left or right. Left by default.
#### Example
```lua
-- the default hilbish prompt without color
hilbish.prompt '%u %d ∆'
-- or something of old:
hilbish.prompt '%u@%h :%d $'
-- prompt: user@hostname: ~/directory $
```
</div>
<hr>
<div id='read'>
<h4 class='heading'>
hilbish.read(prompt) -> input (string)
<a href="#read" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Read input from the user, using Hilbish's line editor/input reader.
This is a separate instance from the one Hilbish actually uses.
Returns `input`, will be nil if Ctrl-D is pressed, or an error occurs.
#### Parameters
`string` **`prompt?`**
Text to print before input, can be empty.
</div>
<hr>
<div id='timeout'>
<h4 class='heading'>
hilbish.timeout(cb, time) -> <a href="/Hilbish/docs/api/hilbish/hilbish.timers/#timer" style="text-decoration: none;" id="lol">Timer</a>
<a href="#timeout" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Executed the `cb` function after a period of `time`.
This creates a Timer that starts ticking immediately.
#### Parameters
`function` **`cb`**
`number` **`time`**
Time to run in milliseconds.
</div>
<hr>
<div id='which'>
<h4 class='heading'>
hilbish.which(name) -> string
<a href="#which" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Checks if `name` is a valid command.
Will return the path of the binary, or a basename if it's a commander.
#### Parameters
`string` **`name`**
</div>
## Types
<hr>
## Sink
A sink is a structure that has input and/or output to/from a desination.
### Methods
#### autoFlush(auto)
Sets/toggles the option of automatically flushing output.
A call with no argument will toggle the value.
#### flush()
Flush writes all buffered input to the sink.
#### read() -> string
Reads a liine of input from the sink.
#### readAll() -> string
Reads all input from the sink.
#### write(str)
Writes data to a sink.
#### writeln(str)
Writes data to a sink with a newline at the end.
<hr>
<div id='run'>
<h4 class='heading'>
hilbish.run(cmd, streams)
<a href="#run" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Runs `cmd` in Hilbish's shell script interpreter.
The `streams` parameter specifies the output and input streams the command should use.
For example, to write command output to a sink.
As a table, the caller can directly specify the standard output, error, and input
streams of the command with the table keys `out`, `err`, and `input` respectively.
As a boolean, it specifies whether the command should use standard output or return its output streams.
#### Parameters
`cmd` **`string`**
`streams` **`table|boolean`**
#### Example
```lua
-- This code is the same as `ls -l | wc -l`
local fs = require 'fs'
local pr, pw = fs.pipe()
hilbish.run('ls -l', {
stdout = pw,
stderr = pw,
})
pw:close()
hilbish.run('wc -l', {
stdin = pr
})
```
</div>
<hr>
<div id='runnerMode'>
<h4 class='heading'>
hilbish.runnerMode(mode)
<a href="#runnerMode" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets the execution/runner mode for interactive Hilbish.
**NOTE: This function is deprecated and will be removed in 3.0**
Use `hilbish.runner.setCurrent` instead.
This determines whether Hilbish wll try to run input as Lua
and/or sh or only do one of either.
Accepted values for mode are hybrid (the default), hybridRev (sh first then Lua),
sh, and lua. It also accepts a function, to which if it is passed one
will call it to execute user input instead.
Read [about runner mode](../features/runner-mode) for more information.
#### Parameters
`mode` **`string|function`**
</div>

View File

@ -0,0 +1,67 @@
---
title: Module hilbish.abbr
description: command line abbreviations
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The abbr module manages Hilbish abbreviations. These are words that can be replaced
with longer command line strings when entered.
As an example, `git push` can be abbreviated to `gp`. When the user types
`gp` into the command line, after hitting space or enter, it will expand to `git push`.
Abbreviations can be used as an alternative to aliases. They are saved entirely in the history
Instead of the aliased form of the same command.
## Functions
|||
|----|----|
|<a href="#remove">remove(abbr)</a>|Removes the named `abbr`.|
|<a href="#add">add(abbr, expanded|function, opts)</a>|Adds an abbreviation. The `abbr` is the abbreviation itself,|
<hr>
<div id='add'>
<h4 class='heading'>
hilbish.abbr.add(abbr, expanded|function, opts)
<a href="#add" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Adds an abbreviation. The `abbr` is the abbreviation itself,
while `expanded` is what the abbreviation should expand to.
It can be either a function or a string. If it is a function, it will expand to what
the function returns.
`opts` is a table that accepts 1 key: `anywhere`.
`opts.anywhere` defines whether the abbr expands anywhere in the command line or not,
whereas the default behavior is only at the beginning of the line
#### Parameters
`abbr` **`string`**
`expanded|function` **`string`**
`opts` **`table`**
</div>
<hr>
<div id='remove'>
<h4 class='heading'>
hilbish.abbr.remove(abbr)
<a href="#remove" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Removes the named `abbr`.
#### Parameters
`abbr` **`string`**
</div>

View File

@ -0,0 +1,91 @@
---
title: Module hilbish.aliases
description: command aliasing
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The alias interface deals with all command aliases in Hilbish.
## Functions
|||
|----|----|
|<a href="#aliases.add">add(alias, cmd)</a>|This is an alias (ha) for the [hilbish.alias](../#alias) function.|
|<a href="#aliases.delete">delete(name)</a>|Removes an alias.|
|<a href="#aliases.list">list() -> table[string, string]</a>|Get a table of all aliases, with string keys as the alias and the value as the command.|
|<a href="#aliases.resolve">resolve(alias) -> string?</a>|Resolves an alias to its original command. Will thrown an error if the alias doesn't exist.|
<hr>
<div id='aliases.add'>
<h4 class='heading'>
hilbish.aliases.add(alias, cmd)
<a href="#aliases.add" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
This is an alias (ha) for the [hilbish.alias](../#alias) function.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='aliases.delete'>
<h4 class='heading'>
hilbish.aliases.delete(name)
<a href="#aliases.delete" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Removes an alias.
#### Parameters
`string` **`name`**
</div>
<hr>
<div id='aliases.list'>
<h4 class='heading'>
hilbish.aliases.list() -> table[string, string]
<a href="#aliases.list" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Get a table of all aliases, with string keys as the alias and the value as the command.
#### Parameters
This function has no parameters.
#### Example
```lua
hilbish.aliases.add('hi', 'echo hi')
local aliases = hilbish.aliases.list()
-- -> {hi = 'echo hi'}
```
</div>
<hr>
<div id='aliases.resolve'>
<h4 class='heading'>
hilbish.aliases.resolve(alias) -> string?
<a href="#aliases.resolve" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Resolves an alias to its original command. Will thrown an error if the alias doesn't exist.
#### Parameters
`string` **`alias`**
</div>

View File

@ -0,0 +1,149 @@
---
title: Module hilbish.completion
description: tab completions
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The completions interface deals with tab completions.
## Functions
|||
|----|----|
|<a href="#completion.bins">bins(query, ctx, fields) -> entries (table), prefix (string)</a>|Return binaries/executables based on the provided parameters.|
|<a href="#completion.call">call(name, query, ctx, fields) -> completionGroups (table), prefix (string)</a>|Calls a completer function. This is mainly used to call a command completer, which will have a `name`|
|<a href="#completion.files">files(query, ctx, fields) -> entries (table), prefix (string)</a>|Returns file matches based on the provided parameters.|
|<a href="#completion.handler">handler(line, pos)</a>|This function contains the general completion handler for Hilbish. This function handles|
<hr>
<div id='completion.bins'>
<h4 class='heading'>
hilbish.completion.bins(query, ctx, fields) -> entries (table), prefix (string)
<a href="#completion.bins" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Return binaries/executables based on the provided parameters.
This function is meant to be used as a helper in a command completion handler.
#### Parameters
`string` **`query`**
`string` **`ctx`**
`table` **`fields`**
#### Example
```lua
-- an extremely simple completer for sudo.
hilbish.complete('command.sudo', function(query, ctx, fields)
table.remove(fields, 1)
if #fields[1] then
-- return commands because sudo runs a command as root..!
local entries, pfx = hilbish.completion.bins(query, ctx, fields)
return {
type = 'grid',
items = entries
}, pfx
end
-- ... else suggest files or anything else ..
end)
```
</div>
<hr>
<div id='completion.call'>
<h4 class='heading'>
hilbish.completion.call(name, query, ctx, fields) -> completionGroups (table), prefix (string)
<a href="#completion.call" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Calls a completer function. This is mainly used to call a command completer, which will have a `name`
in the form of `command.name`, example: `command.git`.
You can check the Completions doc or `doc completions` for info on the `completionGroups` return value.
#### Parameters
`string` **`name`**
`string` **`query`**
`string` **`ctx`**
`table` **`fields`**
</div>
<hr>
<div id='completion.files'>
<h4 class='heading'>
hilbish.completion.files(query, ctx, fields) -> entries (table), prefix (string)
<a href="#completion.files" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns file matches based on the provided parameters.
This function is meant to be used as a helper in a command completion handler.
#### Parameters
`string` **`query`**
`string` **`ctx`**
`table` **`fields`**
</div>
<hr>
<div id='completion.handler'>
<h4 class='heading'>
hilbish.completion.handler(line, pos)
<a href="#completion.handler" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
This function contains the general completion handler for Hilbish. This function handles
completion of everything, which includes calling other command handlers, binaries, and files.
This function can be overriden to supply a custom handler. Note that alias resolution is required to be done in this function.
#### Parameters
`string` **`line`**
The current Hilbish command line
`number` **`pos`**
Numerical position of the cursor
#### Example
```lua
-- stripped down version of the default implementation
function hilbish.completion.handler(line, pos)
local query = fields[#fields]
if #fields == 1 then
-- call bins handler here
else
-- call command completer or files completer here
end
end
```
</div>

View File

@ -0,0 +1,102 @@
---
title: Module hilbish.history
description: command history
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The history interface deals with command history.
This includes the ability to override functions to change the main
method of saving history.
## Functions
|||
|----|----|
|<a href="#history.add">add(cmd)</a>|Adds a command to the history.|
|<a href="#history.all">all() -> table</a>|Retrieves all history as a table.|
|<a href="#history.clear">clear()</a>|Deletes all commands from the history.|
|<a href="#history.get">get(index)</a>|Retrieves a command from the history based on the `index`.|
|<a href="#history.size">size() -> number</a>|Returns the amount of commands in the history.|
<hr>
<div id='history.add'>
<h4 class='heading'>
hilbish.history.add(cmd)
<a href="#history.add" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Adds a command to the history.
#### Parameters
`string` **`cmd`**
</div>
<hr>
<div id='history.all'>
<h4 class='heading'>
hilbish.history.all() -> table
<a href="#history.all" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Retrieves all history as a table.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='history.clear'>
<h4 class='heading'>
hilbish.history.clear()
<a href="#history.clear" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Deletes all commands from the history.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='history.get'>
<h4 class='heading'>
hilbish.history.get(index)
<a href="#history.get" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Retrieves a command from the history based on the `index`.
#### Parameters
`number` **`index`**
</div>
<hr>
<div id='history.size'>
<h4 class='heading'>
hilbish.history.size() -> number
<a href="#history.size" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the amount of commands in the history.
#### Parameters
This function has no parameters.
</div>

View File

@ -0,0 +1,146 @@
---
title: Module hilbish.jobs
description: background job management
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
Manage interactive jobs in Hilbish via Lua.
Jobs are the name of background tasks/commands. A job can be started via
interactive usage or with the functions defined below for use in external runners.
## Functions
|||
|----|----|
|<a href="#jobs.add">add(cmdstr, args, execPath)</a>|Creates a new job. This function does not run the job. This function is intended to be|
|<a href="#jobs.all">all() -> table[@Job]</a>|Returns a table of all job objects.|
|<a href="#jobs.disown">disown(id)</a>|Disowns a job. This simply deletes it from the list of jobs without stopping it.|
|<a href="#jobs.get">get(id) -> @Job</a>|Get a job object via its ID.|
|<a href="#jobs.last">last() -> @Job</a>|Returns the last added job to the table.|
<hr>
<div id='jobs.add'>
<h4 class='heading'>
hilbish.jobs.add(cmdstr, args, execPath)
<a href="#jobs.add" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Creates a new job. This function does not run the job. This function is intended to be
used by runners, but can also be used to create jobs via Lua. Commanders cannot be ran as jobs.
#### Parameters
`string` **`cmdstr`**
String that a user would write for the job
`table` **`args`**
Arguments for the commands. Has to include the name of the command.
`string` **`execPath`**
Binary to use to run the command. Needs to be an absolute path.
#### Example
```lua
hilbish.jobs.add('go build', {'go', 'build'}, '/usr/bin/go')
```
</div>
<hr>
<div id='jobs.all'>
<h4 class='heading'>
hilbish.jobs.all() -> table[<a href="/Hilbish/docs/api/hilbish/hilbish.jobs/#job" style="text-decoration: none;" id="lol">Job</a>]
<a href="#jobs.all" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns a table of all job objects.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='jobs.disown'>
<h4 class='heading'>
hilbish.jobs.disown(id)
<a href="#jobs.disown" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Disowns a job. This simply deletes it from the list of jobs without stopping it.
#### Parameters
`number` **`id`**
</div>
<hr>
<div id='jobs.get'>
<h4 class='heading'>
hilbish.jobs.get(id) -> <a href="/Hilbish/docs/api/hilbish/hilbish.jobs/#job" style="text-decoration: none;" id="lol">Job</a>
<a href="#jobs.get" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Get a job object via its ID.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='jobs.last'>
<h4 class='heading'>
hilbish.jobs.last() -> <a href="/Hilbish/docs/api/hilbish/hilbish.jobs/#job" style="text-decoration: none;" id="lol">Job</a>
<a href="#jobs.last" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the last added job to the table.
#### Parameters
This function has no parameters.
</div>
## Types
<hr>
## Job
The Job type describes a Hilbish job.
## Object properties
|||
|----|----|
|cmd|The user entered command string for the job.|
|running|Whether the job is running or not.|
|id|The ID of the job in the job table|
|pid|The Process ID|
|exitCode|The last exit code of the job.|
|stdout|The standard output of the job. This just means the normal logs of the process.|
|stderr|The standard error stream of the process. This (usually) includes error messages of the job.|
### Methods
#### background()
Puts a job in the background. This acts the same as initially running a job.
#### foreground()
Puts a job in the foreground. This will cause it to run like it was
executed normally and wait for it to complete.
#### start()
Starts running the job.
#### stop()
Stops the job from running.

View File

@ -0,0 +1,135 @@
---
title: Module hilbish.messages
description: simplistic message passing
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The messages interface defines a way for Hilbish-integrated commands,
user config and other tasks to send notifications to alert the user.z
The `hilbish.message` type is a table with the following keys:
`title` (string): A title for the message notification.
`text` (string): The contents of the message.
`channel` (string): States the origin of the message, `hilbish.*` is reserved for Hilbish tasks.
`summary` (string): A short summary of the `text`.
`icon` (string): Unicode (preferably standard emoji) icon for the message notification
`read` (boolean): Whether the full message has been read or not.
## Functions
|||
|----|----|
|<a href="#unreadCount">unreadCount()</a>|Returns the amount of unread messages.|
|<a href="#send">send(message)</a>|Sends a message.|
|<a href="#readAll">readAll()</a>|Marks all messages as read.|
|<a href="#read">read(idx)</a>|Marks a message at `idx` as read.|
|<a href="#delete">delete(idx)</a>|Deletes the message at `idx`.|
|<a href="#clear">clear()</a>|Deletes all messages.|
|<a href="#all">all()</a>|Returns all messages.|
<hr>
<div id='all'>
<h4 class='heading'>
hilbish.messages.all()
<a href="#all" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns all messages.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='clear'>
<h4 class='heading'>
hilbish.messages.clear()
<a href="#clear" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Deletes all messages.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='delete'>
<h4 class='heading'>
hilbish.messages.delete(idx)
<a href="#delete" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Deletes the message at `idx`.
#### Parameters
`idx` **`number`**
</div>
<hr>
<div id='read'>
<h4 class='heading'>
hilbish.messages.read(idx)
<a href="#read" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Marks a message at `idx` as read.
#### Parameters
`idx` **`number`**
</div>
<hr>
<div id='readAll'>
<h4 class='heading'>
hilbish.messages.readAll()
<a href="#readAll" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Marks all messages as read.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='send'>
<h4 class='heading'>
hilbish.messages.send(message)
<a href="#send" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sends a message.
#### Parameters
`message` **`hilbish.message`**
</div>
<hr>
<div id='unreadCount'>
<h4 class='heading'>
hilbish.messages.unreadCount()
<a href="#unreadCount" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the amount of unread messages.
#### Parameters
This function has no parameters.
</div>

View File

@ -0,0 +1,73 @@
---
title: Module hilbish.module
description: native module loading
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The hilbish.module interface provides a function to load
Hilbish plugins/modules. Hilbish modules are Go-written
plugins (see https://pkg.go.dev/plugin) that are used to add functionality
to Hilbish that cannot be written in Lua for any reason.
Note that you don't ever need to use the load function that is here as
modules can be loaded with a `require` call like Lua C modules, and the
search paths can be changed with the `paths` property here.
To make a valid native module, the Go plugin has to export a Loader function
with a signature like so: `func(*rt.Runtime) rt.Value`.
`rt` in this case refers to the Runtime type at
https://pkg.go.dev/github.com/arnodel/golua@master/runtime#Runtime
Hilbish uses this package as its Lua runtime. You will need to read
it to use it for a native plugin.
Here is some code for an example plugin:
```go
package main
import (
rt "github.com/arnodel/golua/runtime"
)
func Loader(rtm *rt.Runtime) rt.Value {
return rt.StringValue("hello world!")
}
```
This can be compiled with `go build -buildmode=plugin plugin.go`.
If you attempt to require and print the result (`print(require 'plugin')`), it will show "hello world!"
## Functions
|||
|----|----|
|<a href="#module.load">load(path)</a>|Loads a module at the designated `path`.|
## Static module fields
|||
|----|----|
|paths|A list of paths to search when loading native modules. This is in the style of Lua search paths and will be used when requiring native modules. Example: `?.so;?/?.so`|
<hr>
<div id='module.load'>
<h4 class='heading'>
hilbish.module.load(path)
<a href="#module.load" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Loads a module at the designated `path`.
It will throw if any error occurs.
#### Parameters
`string` **`path`**
</div>

View File

@ -0,0 +1,20 @@
---
title: Module hilbish.os
description: operating system info
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
Provides simple text information properties about the current operating system.
This mainly includes the name and version.
## Static module fields
|||
|----|----|
|family|Family name of the current OS|
|name|Pretty name of the current OS|
|version|Version of the current OS|

View File

@ -0,0 +1,39 @@
---
title: Module hilbish.processors
description: No description.
layout: doc
menu:
docs:
parent: "API"
---
<hr>
<div id='add'>
<h4 class='heading'>
hilbish.processors.add()
<a href="#add" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='execute'>
<h4 class='heading'>
hilbish.processors.execute()
<a href="#execute" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Run all command processors, in order by priority.
It returns the processed command (which may be the same as the passed command)
and a boolean which states whether to proceed with command execution.
#### Parameters
This function has no parameters.
</div>

View File

@ -0,0 +1,247 @@
---
title: Module hilbish.runner
description: interactive command runner customization
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The runner interface contains functions that allow the user to change
how Hilbish interprets interactive input.
Users can add and change the default runner for interactive input to any
language or script of their choosing. A good example is using it to
write command in Fennel.
Runners are functions that evaluate user input. The default runners in
Hilbish can run shell script and Lua code.
A runner is passed the input and has to return a table with these values.
All are not required, only the useful ones the runner needs to return.
(So if there isn't an error, just omit `err`.)
- `exitCode` (number): Exit code of the command
- `input` (string): The text input of the user. This is used by Hilbish to append extra input, in case
more is requested.
- `err` (string): A string that represents an error from the runner.
This should only be set when, for example, there is a syntax error.
It can be set to a few special values for Hilbish to throw the right
hooks and have a better looking message.
- `\<command>: not-found` will throw a `command.not-found` hook
based on what `\<command>` is.
- `\<command>: not-executable` will throw a `command.not-executable` hook.
- `continue` (boolean): Whether Hilbish should prompt the user for no input
- `newline` (boolean): Whether a newline should be added at the end of `input`.
Here is a simple example of a fennel runner. It falls back to
shell script if fennel eval has an error.
```lua
local fennel = require 'fennel'
hilbish.runnerMode(function(input)
local ok = pcall(fennel.eval, input)
if ok then
return {
input = input
}
end
return hilbish.runner.sh(input)
end)
```
## Functions
|||
|----|----|
|<a href="#runner.lua">lua(cmd)</a>|Evaluates `cmd` as Lua input. This is the same as using `dofile`|
|<a href="#sh">sh()</a>|nil|
|<a href="#setMode">setMode(mode)</a>|**NOTE: This function is deprecated and will be removed in 3.0**|
|<a href="#setCurrent">setCurrent(name)</a>|Sets Hilbish's runner mode by name.|
|<a href="#set">set(name, runner)</a>|*Sets* a runner by name. The difference between this function and|
|<a href="#run">run(input, priv)</a>|Runs `input` with the currently set Hilbish runner.|
|<a href="#getCurrent">getCurrent()</a>|Returns the current runner by name.|
|<a href="#get">get(name)</a>|Get a runner by name.|
|<a href="#exec">exec(cmd, runnerName)</a>|Executes `cmd` with a runner.|
|<a href="#add">add(name, runner)</a>|Adds a runner to the table of available runners.|
<hr>
<div id='runner.lua'>
<h4 class='heading'>
hilbish.runner.lua(cmd)
<a href="#runner.lua" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Evaluates `cmd` as Lua input. This is the same as using `dofile`
or `load`, but is appropriated for the runner interface.
#### Parameters
`string` **`cmd`**
</div>
<hr>
<div id='add'>
<h4 class='heading'>
hilbish.runner.add(name, runner)
<a href="#add" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Adds a runner to the table of available runners.
If runner is a table, it must have the run function in it.
#### Parameters
`name` **`string`**
Name of the runner
`runner` **`function|table`**
</div>
<hr>
<div id='exec'>
<h4 class='heading'>
hilbish.runner.exec(cmd, runnerName)
<a href="#exec" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Executes `cmd` with a runner.
If `runnerName` is not specified, it uses the default Hilbish runner.
#### Parameters
`cmd` **`string`**
`runnerName` **`string?`**
</div>
<hr>
<div id='get'>
<h4 class='heading'>
hilbish.runner.get(name)
<a href="#get" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Get a runner by name.
#### Parameters
`name` **`string`**
Name of the runner to retrieve.
</div>
<hr>
<div id='getCurrent'>
<h4 class='heading'>
hilbish.runner.getCurrent()
<a href="#getCurrent" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the current runner by name.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='run'>
<h4 class='heading'>
hilbish.runner.run(input, priv)
<a href="#run" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Runs `input` with the currently set Hilbish runner.
This method is how Hilbish executes commands.
`priv` is an optional boolean used to state if the input should be saved to history.
#### Parameters
`input` **`string`**
`priv` **`bool`**
</div>
<hr>
<div id='set'>
<h4 class='heading'>
hilbish.runner.set(name, runner)
<a href="#set" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
*Sets* a runner by name. The difference between this function and
add, is set will *not* check if the named runner exists.
The runner table must have the run function in it.
#### Parameters
`name` **`string`**
`runner` **`table`**
</div>
<hr>
<div id='setCurrent'>
<h4 class='heading'>
hilbish.runner.setCurrent(name)
<a href="#setCurrent" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets Hilbish's runner mode by name.
#### Parameters
`name` **`string`**
</div>
<hr>
<div id='setMode'>
<h4 class='heading'>
hilbish.runner.setMode(mode)
<a href="#setMode" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
**NOTE: This function is deprecated and will be removed in 3.0**
Use `hilbish.runner.setCurrent` instead.
This is the same as the `hilbish.runnerMode` function.
It takes a callback, which will be used to execute all interactive input.
Or a string which names the runner mode to use.
#### Parameters
`mode` **`string|function`**
</div>
<hr>
<div id='sh'>
<h4 class='heading'>
hilbish.runner.sh()
<a href="#sh" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
#### Parameters
This function has no parameters.
</div>

View File

@ -0,0 +1,100 @@
---
title: Module hilbish.timers
description: timeout and interval API
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
If you ever want to run a piece of code on a timed interval, or want to wait
a few seconds, you don't have to rely on timing tricks, as Hilbish has a
timer API to set intervals and timeouts.
These are the simple functions `hilbish.interval` and `hilbish.timeout` (doc
accessible with `doc hilbish`, or `Module hilbish` on the Website).
An example of usage:
```lua
local t = hilbish.timers.create(hilbish.timers.TIMEOUT, 5000, function()
print 'hello!'
end)
t:start()
print(t.running) // true
```
## Functions
|||
|----|----|
|<a href="#timers.create">create(type, time, callback) -> @Timer</a>|Creates a timer that runs based on the specified `time`.|
|<a href="#timers.get">get(id) -> @Timer</a>|Retrieves a timer via its ID.|
## Static module fields
|||
|----|----|
|INTERVAL|Constant for an interval timer type|
|TIMEOUT|Constant for a timeout timer type|
<hr>
<div id='timers.create'>
<h4 class='heading'>
hilbish.timers.create(type, time, callback) -> <a href="/Hilbish/docs/api/hilbish/hilbish.timers/#timer" style="text-decoration: none;" id="lol">Timer</a>
<a href="#timers.create" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Creates a timer that runs based on the specified `time`.
#### Parameters
`number` **`type`**
What kind of timer to create, can either be `hilbish.timers.INTERVAL` or `hilbish.timers.TIMEOUT`
`number` **`time`**
The amount of time the function should run in milliseconds.
`function` **`callback`**
The function to run for the timer.
</div>
<hr>
<div id='timers.get'>
<h4 class='heading'>
hilbish.timers.get(id) -> <a href="/Hilbish/docs/api/hilbish/hilbish.timers/#timer" style="text-decoration: none;" id="lol">Timer</a>
<a href="#timers.get" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Retrieves a timer via its ID.
#### Parameters
`number` **`id`**
</div>
## Types
<hr>
## Timer
The Job type describes a Hilbish timer.
## Object properties
|||
|----|----|
|type|What type of timer it is|
|running|If the timer is running|
|duration|The duration in milliseconds that the timer will run|
### Methods
#### start()
Starts a timer.
#### stop()
Stops a timer.

View File

@ -0,0 +1,20 @@
---
title: Module hilbish.userDir
description: user-related directories
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
This interface just contains properties to know about certain user directories.
It is equivalent to XDG on Linux and gets the user's preferred directories
for configs and data.
## Static module fields
|||
|----|----|
|config|The user's config directory|
|data|The user's directory for program data|

66
docs/api/readline.md Normal file
View File

@ -0,0 +1,66 @@
---
title: Module readline
description: line reader library
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The readline module is responsible for reading input from the user.
The readline module is what Hilbish uses to read input from the user,
including all the interactive features of Hilbish like history search,
syntax highlighting, everything. The global Hilbish readline instance
is usable at `hilbish.editor`.
## Functions
|||
|----|----|
|<a href="#New">new() -> @Readline</a>|Creates a new readline instance.|
<hr>
<div id='New'>
<h4 class='heading'>
readline.new() -> <a href="/Hilbish/docs/api/readline/#readline" style="text-decoration: none;" id="lol">Readline</a>
<a href="#New" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Creates a new readline instance.
#### Parameters
This function has no parameters.
</div>
## Types
<hr>
## Readline
### Methods
#### deleteByAmount(amount)
Deletes characters in the line by the given amount.
#### getLine() -> string
Returns the current input line.
#### getVimRegister(register) -> string
Returns the text that is at the register.
#### insert(text)
Inserts text into the Hilbish command line.
#### log(text)
Prints a message *before* the prompt without it being interrupted by user input.
#### read() -> string
Reads input from the user.
#### getChar() -> string
Reads a keystroke from the user. This is in a format of something like Ctrl-L.
#### setVimRegister(register, text)
Sets the vim register at `register` to hold the passed text.

50
docs/api/snail.md Normal file
View File

@ -0,0 +1,50 @@
---
title: Module snail
description: shell script interpreter library
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The snail library houses Hilbish's Lua wrapper of its shell script interpreter.
It's not very useful other than running shell scripts, which can be done with other
Hilbish functions.
## Functions
|||
|----|----|
|<a href="#new">new() -> @Snail</a>|Creates a new Snail instance.|
<hr>
<div id='new'>
<h4 class='heading'>
snail.new() -> <a href="/Hilbish/docs/api/snail/#snail" style="text-decoration: none;" id="lol">Snail</a>
<a href="#new" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Creates a new Snail instance.
#### Parameters
This function has no parameters.
</div>
## Types
<hr>
## Snail
A Snail is a shell script interpreter instance.
### Methods
#### dir(path)
Changes the directory of the snail instance.
The interpreter keeps its set directory even when the Hilbish process changes
directory, so this should be called on the `hilbish.cd` hook.
#### run(command, streams)
Runs a shell command. Works the same as `hilbish.run`, but only accepts a table of streams.

81
docs/api/terminal.md Normal file
View File

@ -0,0 +1,81 @@
---
title: Module terminal
description: low level terminal library
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The terminal library is a simple and lower level library for certain terminal interactions.
## Functions
|||
|----|----|
|<a href="#restoreState">restoreState()</a>|Restores the last saved state of the terminal|
|<a href="#saveState">saveState()</a>|Saves the current state of the terminal.|
|<a href="#setRaw">setRaw()</a>|Puts the terminal into raw mode.|
|<a href="#size">size()</a>|Gets the dimensions of the terminal. Returns a table with `width` and `height`|
<hr>
<div id='restoreState'>
<h4 class='heading'>
terminal.restoreState()
<a href="#restoreState" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Restores the last saved state of the terminal
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='saveState'>
<h4 class='heading'>
terminal.saveState()
<a href="#saveState" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Saves the current state of the terminal.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='setRaw'>
<h4 class='heading'>
terminal.setRaw()
<a href="#setRaw" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Puts the terminal into raw mode.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='size'>
<h4 class='heading'>
terminal.size()
<a href="#size" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Gets the dimensions of the terminal. Returns a table with `width` and `height`
NOTE: The size refers to the amount of columns and rows of text that can fit in the terminal.
#### Parameters
This function has no parameters.
</div>

51
docs/api/yarn.md Normal file
View File

@ -0,0 +1,51 @@
---
title: Module yarn
description: multi threading library
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
Yarn is a simple multithreading library. Threads are individual Lua states,
so they do NOT share the same environment as the code that runs the thread.
Bait and Commanders are shared though, so you *can* throw hooks from 1 thread to another.
Example:
```lua
local yarn = require 'yarn'
-- calling t will run the yarn thread.
local t = yarn.thread(print)
t 'printing from another lua state!'
```
## Functions
|||
|----|----|
|<a href="#thread">thread(fun) -> @Thread</a>|Creates a new, fresh Yarn thread.|
<hr>
<div id='thread'>
<h4 class='heading'>
yarn.thread(fun) -> <a href="/Hilbish/docs/api/yarn/#thread" style="text-decoration: none;" id="lol">Thread</a>
<a href="#thread" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Creates a new, fresh Yarn thread.
`fun` is the function that will run in the thread.
#### Parameters
This function has no parameters.
</div>
## Types
<hr>
## Thread
### Methods

122
docs/completions.md Normal file
View File

@ -0,0 +1,122 @@
---
title: Completions
description: Tab completion for commands.
layout: doc
menu:
docs:
parent: "Features"
---
Completions for commands can be created with the [`hilbish.complete`](../api/hilbish#complete)
function. See the link for how to use it.
To create completions for a command is simple.
The callback will be passed 3 parameters:
- `query` (string): The text that the user is currently trying to complete.
This should be used to match entries.
- `ctx` (string): Contains the entire line. Use this if
more text is needed to be parsed for context.
- `fields` (string): The `ctx` split up by spaces.
In most cases, the completer just uses `fields` to check the amount
and `query` on what to match entries on.
In order to return your results, it has to go within a "completion group."
Then you return a table of completion groups and a prefix. The prefix will
usually just be the `query`.
Hilbish allows one to mix completion menus of different types, so
a grid menu and a list menu can be used and complete and display at the same time.
A completion group is a table with these keys:
- `type` (string): type of completion menu, either `grid` or `list`.
- `items` (table): a list of items.
The requirements of the `items` table is different based on the
`type`. If it is a `grid`, it can simply be a table of strings.
Otherwise if it is a `list` then each entry can
either be a string or a table.
Example:
```lua
local cg = {
items = {
'list item 1',
['--command-flag-here'] = {'this does a thing', '--the-flag-alias'}
},
type = 'list'
}
local cg2 = {
items = {'just', 'a bunch', 'of items', 'here', 'hehe'},
type = 'grid'
}
return {cg, cg2}, prefix
```
Which looks like this:
{{< video src="https://safe.saya.moe/t4CiLK6dgPbD.mp4" >}}
# Completion Group Types
### grid
Grid is the simplest completion group type. All items are strings and when
completion is done is displayed in a grid based on size.
Example:
```lua
{
items = {'just', 'a bunch', 'of items', 'here', 'hehe'},
type = 'grid'
}
```
### list
The list completion group type displays in a list. A list item can either be a string, or a table for additional display options.
A completion alias can be specified either as the `2nd` entry in the options table
or te `alias` key.
A description can optionally be displayed for a list item, which is either the `1st`
entry or the `description` key.
Lastly, list entries can be styled. This is done with the `display` key. If this is present, this
overrides what the completion item *looks* like.
Example:
```lua
{
items = {
['--flag'] = {
description = 'this flag nukes the bri ish',
alias = '--bye-bri-ish',
display = lunacolors.format('--{blue}fl{red}ag')
},
['--flag2'] = {
'make pizza', -- description
'--pizzuh', -- alias
display = lunacolors.yellow '--pizzuh'
},
'--flag3'
},
type = 'list'
}
```
# Completion Handler
Like most parts of Hilbish, it's made to be extensible and
customizable. The default handler for completions in general can
be overwritten to provide more advanced completions if needed.
This usually doesn't need to be done though, unless you know
what you're doing.
The default completion handler provides 3 things:
binaries (with a plain name requested to complete, those in
$PATH), files, or command completions. It will try to run a handler
for the command or fallback to file completions.
To overwrite it, just assign a function to `hilbish.completion.handler` like so:
```lua
-- line is the entire line as a string
-- pos is the position of the cursor.
function hilbish.completion.handler(line, pos)
-- do things
end
```

26
docs/faq.md Normal file
View File

@ -0,0 +1,26 @@
---
title: Frequently Asked Questions
layout: doc
weight: -20
menu: docs
---
# Is Hilbish POSIX compliant?
No, it is not. POSIX compliance is a non-goal. Perhaps in the future,
someone would be able to write a native plugin to support shell scripting
(which would be against it's main goal, but ....)
# Windows Support?
It compiles for Windows (CI ensures it does), but otherwise it is not
directly supported. If you'd like to improve this situation,
checkout [the discussion](https://github.com/Rosettea/Hilbish/discussions/165).
# Why?
Hilbish emerged from the desire of a Lua configured shell.
It was the initial reason that it was created, but now it's more:
to be hyper extensible, simpler and more user friendly.
# Does it have "autocompletion" or "tab completion"
Of course! This is a modern shell. Hilbish provides a way for users
to write tab completion for any command and/or the whole shell.
Inline hinting and syntax highlighting are also available.

11
docs/features/_index.md Normal file
View File

@ -0,0 +1,11 @@
---
title: Features
layout: doc
weight: -40
menu: docs
---
Hilbish has a wide range of features to enhance the user's experience
new ones are always being added. If there is something missing here or
something you would like to see, please [start a discussion](https://github.com/Rosettea/Hilbish/discussions)
or comment on any existing ones which match your request.

View File

@ -0,0 +1,39 @@
---
title: Notification
description: Get notified of shell actions.
layout: doc
menu:
docs:
parent: "Features"
---
Hilbish features a simple notification system which can be
used by other plugins and parts of the shell to notify the user
of various actions. This is used via the `hilbish.message` interface.
A `message` is defined as a table with the following properties:
- `icon`: A unicode/emoji icon for the notification.
- `title`: The title of the message
- `text`: Message text/body
- `channel`: The source of the message. This should be a
unique and easily readable text identifier.
- `summary`: A short summary of the notification and message.
If this is not present and you are using this to display messages,
you should take part of the `text` instead.
The `hilbish.message` interface provides the following functions:
- `send(message)`: Sends a message and emits the `hilbish.notification`
signal. DO NOT emit the `hilbish.notification` signal directly, or
the message will not be stored by the message handler.
- `read(idx)`: Marks message at `idx` as read.
- `delete(idx)`: Removes message at `idx`.
- `readAll()`: Marks all messages as read.
- `clear()`: Deletes all messages.
There are a few simple use cases of this notification/messaging system.
It could also be used as some "inter-shell" messaging system (???) but
is intended to display to users.
An example is notifying users of completed jobs/commands ran in the background.
Any Hilbish-native command (think the upcoming Greenhouse pager) can display
it.

83
docs/features/opts.md Normal file
View File

@ -0,0 +1,83 @@
---
title: Options
description: Simple customizable options.
layout: doc
menu:
docs:
parent: "Features"
---
Opts are simple toggle or value options a user can set in Hilbish.
As toggles, there are things like `autocd` or history saving. As values,
there is the `motd` which the user can either change to a custom string or disable.
Opts are accessed from the `hilbish.opts` table. Here they can either
be read or modified
### `autocd`
#### Value: `boolean`
#### Default: `false`
The autocd opt makes it so that lone directories attempted to be executed are
instead set as the shell's directory.
Example:
```
~/Directory
∆ ~
~
∆ Downloads
~/Downloads
∆ ../Documents
~/Documents
```
<hr>
### `history`
#### Value: `boolean`
#### Default: `true`
Sets whether command history will be saved or not.
<hr>
### `greeting`
#### Value: `boolean` or `string`
The greeting is the message that Hilbish shows on startup
(the one which says Welcome to Hilbish).
This can be set to either true/false to enable/disable or a custom greeting string.
<hr>
### `motd`
#### Value: `boolean`
#### Default: `true`
The message of the day shows the current major.minor version and
includes a small range of things added in the current release.
This can be set to `false` to disable the message.
<hr>
### `fuzzy`
#### Value: `boolean`
#### Default: `false`
Toggles the functionality of fuzzy history searching, usable
via the menu in Ctrl-R. Fuzzy searching is an approximate searching
method, which means results that match *closest* will be shown instead
of an exact match.
<hr>
### `notifyJobFinish`
#### Value: `boolean`
#### Default: `true`
If this is enabled, when a background job is finished,
a [notification](../notifications) will be sent.
### `processorSkipList`
#### Value: `table`
#### Default: `{}`
A table listing the names of command processors to skip.

View File

@ -0,0 +1,53 @@
---
title: Runner Mode
description: Customize the interactive script/command runner.
layout: doc
menu:
docs:
parent: "Features"
---
Hilbish allows you to change how interactive text can be interpreted.
This is mainly due to the fact that the default method Hilbish uses
is that it runs Lua first and then falls back to shell script.
In some cases, someone might want to switch to just shell script to avoid
it while interactive but still have a Lua config, or go full Lua to use
Hilbish as a REPL. This also allows users to add alternative languages like
Fennel as the interactive script runner.
Runner mode can also be used to handle specific kinds of input before
evaluating like normal, which is how [Link.hsh](https://github.com/TorchedSammy/Link.hsh)
handles links.
The "runner mode" of Hilbish is customizable via `hilbish.runnerMode`,
which determines how Hilbish will run user input. By default, this is
set to `hybrid` which is the previously mentioned behaviour of running Lua
first then going to shell script. If you want the reverse order, you can
set it to `hybridRev` and for isolated modes there is `sh` and `lua`
respectively.
You can also set it to a function, which will be called everytime Hilbish
needs to run interactive input. For more detail, see the [API documentation](../../api/hilbish/hilbish.runner)
The `hilbish.runner` interface is an alternative to using `hilbish.runnerMode`
and also provides the shell script and Lua runner functions that Hilbish itself uses.
## Functions
These are the "low level" functions for the `hilbish.runner` interface.
+ setMode(mode) > The same as `hilbish.runnerMode`
+ sh(input) -> table > Runs `input` in Hilbish's sh interpreter
+ lua(input) -> table > Evals `input` as Lua code
These functions should be preferred over the previous ones.
+ setCurrent(mode) > The same as `setMode`, but works with runners managed
via the functions below.
+ add(name, runner) > Adds a runner to a table of available runners. The `runner`
argument is either a function or a table with a run callback.
+ set(name, runner) > The same as `add` but requires passing a table and
overwrites if the `name`d runner already exists.
+ get(name) > runner > Gets a runner by name. It is a table with at least a
run function, to run input.
+ exec(cmd, runnerName) > Runs `cmd` with a runner. If `runnerName` isn't passed,
the current runner mode is used.

91
docs/getting-started.md Normal file
View File

@ -0,0 +1,91 @@
---
title: Getting Started
layout: doc
weight: -10
menu: docs
---
To start Hilbish, open a terminal. If Hilbish has been installed and is not the
default shell, you can simply run `hilbish` to start it. This will launch
a normal interactive session.
To exit, you can either run the `exit` command or hit Ctrl+D.
# Setting as Default
## Login shell
There are a few ways to make Hilbish your default shell. A simple way is
to make it your user/login shell.
{{< warning `It is not recommended to set Hilbish as your login shell. That
is expected to be a POSIX compliant shell, which Hilbish is not. Though if
you still decide to do it, there will just be a few variables missing in
your environment` >}}
To do that, simply run `chsh -s /usr/bin/hilbish`.
Some distros (namely Fedora) might have `lchsh` instead, which is used like `lchsh <user>`.
When prompted, you can put the path for Hilbish.
## Default with terminal
The simpler way is to set the default shell for your terminal. The way of
doing this depends on how your terminal settings are configured.
## Run after login shell
Some shells (like zsh) have an rc file, like `.zlogin`, which is ran when the shell session
is a login shell. In that file, you can run Hilbish. Example:
```
exec hilbish -S -l
```
This will replace the shell with Hilbish, set $SHELL to Hilbish and launch it as a login shell.
# Configuration
Once installation and setup has been done, you can then configure Hilbish.
It is configured and scripted via Lua, so the config file is a Lua file.
You can use any pure Lua library to do whatever you want.
Hilbish's sample configuration is usually located in `hilbish.dataDir .. '/.hilbishrc.lua'`.
You can print that path via Lua to see what it is: `print(hilbish.dataDir .. '/.hilbishrc.lua')`.
As an example, it will usually will result in `/usr/share/hilbish/.hilbishrc.lua` on Linux.
To edit your user configuration, you can copy that file to `hilbish.userDir.config .. '/hilbish/init.lua'`,
which follows XDG on Linux and MacOS, and is located in %APPDATA% on Windows.
As the directory is usually `~/.config` on Linux, you can run this command to copy it:
`cp /usr/share/hilbish/.hilbishrc.lua ~/.config/hilbish/init.lua`
Now we can get to customization!
If we closely examine a small snippet of the default config:
```lua
-- Default Hilbish config
-- .. with some omitted code .. --
local function doPrompt(fail)
hilbish.prompt(lunacolors.format(
'{blue}%u {cyan}%d ' .. (fail and '{red}' or '{green}') .. '∆ '
))
end
doPrompt()
bait.catch('command.exit', function(code)
doPrompt(code ~= 0)
end)
```
We see a whopping **three** Hilbish libraries being used in this part of code.
First is of course, named after the shell itself, [`hilbish`](../api/hilbish). This is kind of a
"catch-all" namespace for functions that directly related to shell functionality/settings.
And as we can see, the [hilbish.prompt](../api/hilbish/#prompt) function is used
to change our prompt. Change our prompt to what, exactly?
The doc for the function states that the verbs `%u` and `%d`are used for username and current directory
of the shell, respectively.
We wrap this in the [`lunacolors.format`](../lunacolors) function, to give
our prompt some nice color.
But you might have also noticed that this is in the `doPrompt` function, which is called once,
and then used again in a [bait](../api/bait) hook. Specifically, the `command.exit` hook,
which is called after a command exits, so when it finishes running.

11
docs/hooks/_index.md Normal file
View File

@ -0,0 +1,11 @@
---
title: Signals
description:
layout: doc
weight: -50
menu:
docs
---
Signals are global events emitted with the [Bait](../api/bait) module.
For more detail on how to use these signals, you may check the Bait page.

67
docs/hooks/command.md Normal file
View File

@ -0,0 +1,67 @@
---
title: Command
description:
layout: doc
menu:
docs:
parent: "Signals"
---
## command.preexec
Thrown right before a command is executed.
#### Variables
`string` **`input`**
The raw string that the user typed. This will include the text
without changes applied to it (argument substitution, alias expansion,
etc.)
`string` **`cmdStr`**
The command that will be directly executed by the current runner.
<hr>
## command.exit
Thrown after the user's ran command is finished.
#### Variables
`number` **`code`**
The exit code of what was executed.
`string` **`cmdStr`**
The command or code that was executed
<hr>
## command.not-found
Thrown if the command attempted to execute was not found.
This can be used to customize the text printed when a command is not found.
Example:
```lua
local bait = require 'bait'
-- Remove any present handlers on `command.not-found`
local notFoundHooks = bait.hooks 'command.not-found'
for _, hook in ipairs(notFoundHooks) do
bait.release('command.not-found', hook)
end
-- then assign custom
bait.catch('command.not-found', function(cmd)
print(string.format('The command "%s" was not found.', cmd))
end)
```
#### Variables
`string` **`cmdStr`**
The name of the command.
<hr>
## command.not-executable
Thrown when the user attempts to run a file that is not executable
(like a text file, or Unix binary without +x permission).
#### Variables
`string` **`cmdStr`**
The name of the command.

71
docs/hooks/hilbish.md Normal file
View File

@ -0,0 +1,71 @@
---
title: Hilbish
description:
layout: doc
menu:
docs:
parent: "Signals"
---
## hilbish.exit
Sent when Hilbish is going to exit.
#### Variables
This signal returns no variables.
<hr>
## hilbish.vimMode
Sent when the Vim mode of Hilbish is changed (like from insert to normal mode).
This can be used to change the prompt and notify based on Vim mode.
#### Variables
`string` **`modeName`**
The mode that has been set.
Can be these values: `insert`, `normal`, `delete` or `replace`
<hr>
## hilbish.cancel
Sent when the user cancels their command input with Ctrl-C
#### Variables
This signal returns no variables.
<hr>
## hilbish.notification
Thrown when a [notification](../../features/notifications) is sent.
#### Variables
`table` **`notification`**
The notification. The properties are defined in the link above.
<hr>
## hilbish.cd
Sent when the current directory of the shell is changed (via interactive means.)
If you are implementing a custom command that changes the directory of the shell,
you must throw this hook manually for correctness.
#### Variables
`string` **`path`**
Absolute path of the directory that was changed to.
`string` **`oldPath`**
Absolute path of the directory Hilbish *was* in.
<hr>
## hilbish.vimAction
Sent when the user does a "vim action," being something like yanking or pasting text.
See `doc vim-mode actions` for more info.
#### Variables
`string` **`actionName`**
Absolute path of the directory that was changed to.
`table` **`args`**
Table of args relating to the Vim action.
<hr>

7
docs/hooks/job.md Normal file
View File

@ -0,0 +1,7 @@
Note: `job` refers to a job object. You can check `doc jobs` for more
detail.
+ `job.start` -> job > Thrown when a new background job starts.
+ `job.done` -> job > Thrown when a background jobs exits.

40
docs/hooks/signal.md Normal file
View File

@ -0,0 +1,40 @@
---
title: Signal
description:
layout: doc
menu:
docs:
parent: "Signals"
---
## signal.sigint
Thrown when Hilbish receive the SIGINT signal,
aka when Ctrl-C is pressed.
#### Variables
This signal returns no variables.
<hr>
## signal.resize
Thrown when the terminal is resized.
#### Variables
This signal returns no variables.
<hr>
## signal.sigusr1
Thrown when SIGUSR1 is sent to Hilbish.
#### Variables
This signal returns no variables.
<hr>
## signal.sigusr2
Thrown when SIGUSR2 is sent to Hilbish.
#### Variables
This signal returns no variables.

48
docs/jobs.md Normal file
View File

@ -0,0 +1,48 @@
(This has mainly been replaced by [hilbish.jobs](../api/hilbish.jobs)).
Hilbish has pretty standard job control. It's missing one or two things,
but works well. One thing which is different from other shells
(besides Hilbish) itself is the API for jobs, and of course it's in Lua.
You can add jobs, stop and delete (disown) them and even get output.
# Job Interface
The job interface refers to `hilbish.jobs`.
## Functions
(Note that in the list here, they're called from `hilbish.jobs`, so
a listing of `foo` would mean `hilbish.jobs.foo`)
- `all()` -> {jobs}: Returns a table of all jobs.
- `last()` -> job: Returns the last added job.
- `get(id)` -> job: Get a job by its ID.
- `add(cmdstr, args, execPath)` -> job: Adds a new job to the job table.
Note that this does not run the command; You have to start it manually.
`cmdstr` is the user's input for the job, `args` is a table of arguments
for the command. It includes arg0 (don't set it as entry 0 in the table)
and `execPath` is an absolute path for the command executable.
- `disown(id)`: Removes a job by ID from the job table.
# Job Object
A job object is a piece of `userdata`. All the functions of a job require
you to call them with a colon, since they are *methods* for the job object.
Example: hilbish.jobs.last():foreground()
Which will foreground the last job.
You can still have a job object for a disowned job,
it just won't be *working* anywhere. :^)
## Properties
- `cmd`: command string
- `running`: boolean whether the job is running
- `id`: unique id for the job
- `pid`: process id for the job
- `exitCode`: exit code of the job
In ordinary cases you'd prefer to use the `id` instead of `pid`.
The `id` is unique to Hilbish and is how you get jobs with the
`hilbish.jobs` interface. It may also not describe the job entirely.
## Functions
- `stop()`: Stops the job.
- `start()`: Starts the job.
- `foreground()`: Set the job as the current running foreground process, or
run it in the foreground after it has been suspended.
- `background()`: Run the job in the background after it has been suspended.

44
docs/lunacolors.md Normal file
View File

@ -0,0 +1,44 @@
---
title: Lunacolors
layout: doc
weight: -60
menu: docs
---
Lunacolors is an ANSI color/styling library for Lua. It is included
by default in standard Hilbish distributions to provide easy styling
for things like prompts and text.
For simple usage, a single color or style is enough. For example,
you can just use `lunacolors.blue 'Hello world'` and that'll return
blue text which you can print. This includes styles like bold,
underline, etc.
In other usage, you may want to use a format string instead of having
multiple nested functions for different styles. This is where the format
function comes in. You can used named keywords to style a section of text.
The list of arguments are:
Colors:
- black
- red
- green
- yellow
- blue
- magenta
- cyan
- white
Styles:
- reset
- bold
- dim
- italic
- underline
- invert
For the colors, there are background and bright variants. Background color
variants have a `Bg` suffix, while bright variants use the `bright` prefix.
These can also be combined. Note that appropriate camel casing must be applied.
For example, bright blue would be written as `brightBlue`, a cyan background as
`cyanBg`, and combining them would result in `brightBlueBg`.

19
docs/nature/_index.md Normal file
View File

@ -0,0 +1,19 @@
---
title: Nature
layout: doc
weight: -90
menu: docs
---
A bit after creation, we have the outside nature. Little plants, seeds,
growing to their final phase: a full plant. A lot of Hilbish itself is
written in Go, but there are parts made in Lua, being most builtins
(`doc`, `cd`, cdr), completions, and other things.
Hilbish's Lua core module is called `nature`.
It runs after Hilbish's Go core does.
# Nature Modules
Currently, `nature` provides 1 intended public module: `nature.dirs`.
It is a simple API for managing recent directories and old
current working directory.

103
docs/nature/dirs.md Normal file
View File

@ -0,0 +1,103 @@
---
title: Module dirs
description: internal directory management
layout: doc
menu:
docs:
parent: "Nature"
---
## Introduction
The dirs module defines a small set of functions to store and manage
directories.
## Functions
|||
|----|----|
|<a href="#setOld">setOld(d)</a>|Sets the old directory string.|
|<a href="#recent">recent(idx)</a>|Get entry from recent directories list based on index.|
|<a href="#push">push(dir)</a>|Add `dir` to the recent directories list.|
|<a href="#pop">pop(num)</a>|Remove the specified amount of dirs from the recent directories list.|
|<a href="#peak">peak(num)</a>|Look at `num` amount of recent directories, starting from the latest.|
<hr>
<div id='peak'>
<h4 class='heading'>
dirs.peak(num)
<a href="#peak" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Look at `num` amount of recent directories, starting from the latest.
This returns a table of recent directories, up to the `num` amount.
#### Parameters
`num` **`number`**
</div>
<hr>
<div id='pop'>
<h4 class='heading'>
dirs.pop(num)
<a href="#pop" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Remove the specified amount of dirs from the recent directories list.
#### Parameters
`num` **`number`**
</div>
<hr>
<div id='push'>
<h4 class='heading'>
dirs.push(dir)
<a href="#push" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Add `dir` to the recent directories list.
#### Parameters
`dir` **`string`**
</div>
<hr>
<div id='recent'>
<h4 class='heading'>
dirs.recent(idx)
<a href="#recent" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Get entry from recent directories list based on index.
#### Parameters
`idx` **`number`**
</div>
<hr>
<div id='setOld'>
<h4 class='heading'>
dirs.setOld(d)
<a href="#setOld" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets the old directory string.
#### Parameters
`d` **`string`**
</div>

76
docs/nature/doc.md Normal file
View File

@ -0,0 +1,76 @@
---
title: Module doc
description: command-line doc rendering
layout: doc
menu:
docs:
parent: "Nature"
---
## Introduction
The doc module contains a small set of functions
used by the Greenhouse pager to render parts of the documentation pages.
This is only documented for the sake of it. It's only intended use
is by the Greenhouse pager.
## Functions
|||
|----|----|
|<a href="#renderInfoBlock">renderInfoBlock(type, text)</a>|Renders an info block. An info block is a block of text with|
|<a href="#renderCodeBlock">renderCodeBlock(text)</a>|Assembles and renders a code block. This returns|
|<a href="#highlight">highlight(text)</a>|Performs basic Lua code highlighting.|
<hr>
<div id='highlight'>
<h4 class='heading'>
doc.highlight(text)
<a href="#highlight" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Performs basic Lua code highlighting.
#### Parameters
`text` **`string`**
Code/text to do highlighting on.
</div>
<hr>
<div id='renderCodeBlock'>
<h4 class='heading'>
doc.renderCodeBlock(text)
<a href="#renderCodeBlock" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Assembles and renders a code block. This returns
the supplied text based on the number of command line columns,
and styles it to resemble a code block.
#### Parameters
`text` **`string`**
</div>
<hr>
<div id='renderInfoBlock'>
<h4 class='heading'>
doc.renderInfoBlock(type, text)
<a href="#renderInfoBlock" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Renders an info block. An info block is a block of text with
an icon and styled text block.
#### Parameters
`type` **`string`**
Type of info block. The only one specially styled is the `warning`.
`text` **`string`**
</div>

1
docs/timers.md Normal file
View File

@ -0,0 +1 @@
This has been moved to the `hilbish.timers` API doc (accessible by `doc api hilbish.timers`)

11
docs/vim-mode/_index.md Normal file
View File

@ -0,0 +1,11 @@
---
title: Vim Mode
layout: doc
weight: -90
menu: docs
---
Hilbish has a Vim binding input mode accessible for use.
It can be enabled with the `hilbish.inputMode` function (check `doc hilbish`).
This is documentation for everything relating to it.

25
docs/vim-mode/actions.md Normal file
View File

@ -0,0 +1,25 @@
---
title: Actions
layout: doc
weight: -80
menu:
docs:
parent: "Vim Mode"
---
Vim actions are essentially just when a user uses a Vim keybind.
Things like yanking and pasting are Vim actions.
This is not an "offical Vim thing," just a Hilbish thing.
The `hilbish.vimAction` hook is thrown whenever a Vim action occurs.
It passes 2 arguments: the action name, and an array (table) of args
relating to it.
Here is documentation for what the table of args will hold for an
appropriate Vim action.
- `yank`: register, yankedText
The first argument for the yank action is the register yankedText goes to.
- `paste`: register, pastedText
The first argument for the paste action is the register pastedText is taken from.

28
emmyLuaDocs/bait.lua Normal file
View File

@ -0,0 +1,28 @@
--- @meta
local bait = {}
--- Catches an event. This function can be used to act on events.
---
---
function bait.catch(name, cb) end
--- Catches an event, but only once. This will remove the hook immediately after it runs for the first time.
function bait.catchOnce(name, cb) end
--- Returns a table of functions that are hooked on an event with the corresponding `name`.
function bait.hooks(name) end
--- Removes the `catcher` for the event with `name`.
--- For this to work, `catcher` has to be the same function used to catch
--- an event, like one saved to a variable.
---
---
function bait.release(name, catcher) end
--- Throws a hook with `name` with the provided `args`.
---
---
function bait.throw(name, ...args) end
return bait

18
emmyLuaDocs/commander.lua Normal file
View File

@ -0,0 +1,18 @@
--- @meta
local commander = {}
--- Removes the named command. Note that this will only remove Commander-registered commands.
function commander.deregister(name) end
--- Adds a new command with the given `name`. When Hilbish has to run a command with a name,
--- it will run the function providing the arguments and sinks.
---
---
function commander.register(name, cb) end
--- Returns all registered commanders. Returns a list of tables with the following keys:
--- - `exec`: The function used to run the commander. Commanders require args and sinks to be passed.
function commander.registry() end
return commander

54
emmyLuaDocs/fs.lua Normal file
View File

@ -0,0 +1,54 @@
--- @meta
local fs = {}
--- Returns an absolute version of the `path`.
--- This can be used to resolve short paths like `..` to `/home/user`.
function fs.abs(path) end
--- Returns the "basename," or the last part of the provided `path`. If path is empty,
--- `.` will be returned.
function fs.basename(path) end
--- Changes Hilbish's directory to `dir`.
function fs.cd(dir) end
--- Returns the directory part of `path`. If a file path like
--- `~/Documents/doc.txt` then this function will return `~/Documents`.
function fs.dir(path) end
--- Match all files based on the provided `pattern`.
--- For the syntax' refer to Go's filepath.Match function: https://pkg.go.dev/path/filepath#Match
---
---
function fs.glob(pattern) end
--- Takes any list of paths and joins them based on the operating system's path separator.
---
---
function fs.join(...path) end
--- Creates a new directory with the provided `name`.
--- With `recursive`, mkdir will create parent directories.
---
---
function fs.mkdir(name, recursive) end
--- Returns a pair of connected files, also known as a pipe.
--- The type returned is a Lua file, same as returned from `io` functions.
function fs.fpipe() end
--- Returns a list of all files and directories in the provided path.
function fs.readdir(path) end
--- Returns the information about a given `path`.
--- The returned table contains the following values:
--- name (string) - Name of the path
--- size (number) - Size of the path in bytes
--- mode (string) - Unix permission mode in an octal format string (with leading 0)
--- isDir (boolean) - If the path is a directory
---
---
function fs.stat(path) end
return fs

222
emmyLuaDocs/hilbish.lua Normal file
View File

@ -0,0 +1,222 @@
--- @meta
local hilbish = {}
--- This is an alias (ha) for the [hilbish.alias](../#alias) function.
--- @param alias string
--- @param cmd string
function hilbish.aliases.add(alias, cmd) end
--- Return binaries/executables based on the provided parameters.
--- This function is meant to be used as a helper in a command completion handler.
---
---
function hilbish.completion.bins(query, ctx, fields) end
--- Calls a completer function. This is mainly used to call a command completer, which will have a `name`
--- in the form of `command.name`, example: `command.git`.
--- You can check the Completions doc or `doc completions` for info on the `completionGroups` return value.
function hilbish.completion.call(name, query, ctx, fields) end
--- Returns file matches based on the provided parameters.
--- This function is meant to be used as a helper in a command completion handler.
function hilbish.completion.files(query, ctx, fields) end
--- This function contains the general completion handler for Hilbish. This function handles
--- completion of everything, which includes calling other command handlers, binaries, and files.
--- This function can be overriden to supply a custom handler. Note that alias resolution is required to be done in this function.
---
---
function hilbish.completion.handler(line, pos) end
--- Sets an alias, with a name of `cmd` to another command.
---
---
function hilbish.alias(cmd, orig) end
--- Appends the provided dir to the command path (`$PATH`)
---
---
function hilbish.appendPath(dir) end
--- Registers a completion handler for the specified scope.
--- A `scope` is expected to be `command.<cmd>`,
--- replacing <cmd> with the name of the command (for example `command.git`).
--- The documentation for completions, under Features/Completions or `doc completions`
--- provides more details.
---
---
function hilbish.complete(scope, cb) end
--- Returns the current directory of the shell.
function hilbish.cwd() end
--- Replaces the currently running Hilbish instance with the supplied command.
--- This can be used to do an in-place restart.
function hilbish.exec(cmd) end
--- Puts `fn` in a Goroutine.
--- This can be used to run any function in another thread at the same time as other Lua code.
--- **NOTE: THIS FUNCTION MAY CRASH HILBISH IF OUTSIDE VARIABLES ARE ACCESSED.**
--- **This is a limitation of the Lua runtime.**
function hilbish.goro(fn) end
--- Line highlighter handler.
--- This is mainly for syntax highlighting, but in reality could set the input
--- of the prompt to *display* anything. The callback is passed the current line
--- and is expected to return a line that will be used as the input display.
--- Note that to set a highlighter, one has to override this function.
---
function hilbish.highlighter(line) end
--- The command line hint handler. It gets called on every key insert to
--- determine what text to use as an inline hint. It is passed the current
--- line and cursor position. It is expected to return a string which is used
--- as the text for the hint. This is by default a shim. To set hints,
--- override this function with your custom handler.
---
---
function hilbish.hinter(line, pos) end
--- Sets the input mode for Hilbish's line reader.
--- `emacs` is the default. Setting it to `vim` changes behavior of input to be
--- Vim-like with modes and Vim keybinds.
function hilbish.inputMode(mode) end
--- Runs the `cb` function every specified amount of `time`.
--- This creates a timer that ticking immediately.
function hilbish.interval(cb, time) end
--- Changes the text prompt when Hilbish asks for more input.
--- This will show up when text is incomplete, like a missing quote
---
---
function hilbish.multiprompt(str) end
--- Prepends `dir` to $PATH.
function hilbish.prependPath(dir) end
--- Changes the shell prompt to the provided string.
--- There are a few verbs that can be used in the prompt text.
--- These will be formatted and replaced with the appropriate values.
--- `%d` - Current working directory
--- `%u` - Name of current user
--- `%h` - Hostname of device
---
function hilbish.prompt(str, typ) end
--- Read input from the user, using Hilbish's line editor/input reader.
--- This is a separate instance from the one Hilbish actually uses.
--- Returns `input`, will be nil if Ctrl-D is pressed, or an error occurs.
function hilbish.read(prompt) end
--- Executed the `cb` function after a period of `time`.
--- This creates a Timer that starts ticking immediately.
function hilbish.timeout(cb, time) end
--- Checks if `name` is a valid command.
--- Will return the path of the binary, or a basename if it's a commander.
function hilbish.which(name) end
--- Puts a job in the background. This acts the same as initially running a job.
function hilbish.jobs:background() end
--- Puts a job in the foreground. This will cause it to run like it was
--- executed normally and wait for it to complete.
function hilbish.jobs:foreground() end
--- Evaluates `cmd` as Lua input. This is the same as using `dofile`
--- or `load`, but is appropriated for the runner interface.
function hilbish.runner.lua(cmd) end
--- Starts running the job.
function hilbish.jobs:start() end
--- Stops the job from running.
function hilbish.jobs:stop() end
--- Loads a module at the designated `path`.
--- It will throw if any error occurs.
function hilbish.module.load(path) end
--- Starts a timer.
function hilbish.timers:start() end
--- Stops a timer.
function hilbish.timers:stop() end
--- Removes an alias.
function hilbish.aliases.delete(name) end
--- Get a table of all aliases, with string keys as the alias and the value as the command.
---
---
function hilbish.aliases.list() end
--- Resolves an alias to its original command. Will thrown an error if the alias doesn't exist.
function hilbish.aliases.resolve(alias) end
--- Creates a new job. This function does not run the job. This function is intended to be
--- used by runners, but can also be used to create jobs via Lua. Commanders cannot be ran as jobs.
---
---
function hilbish.jobs.add(cmdstr, args, execPath) end
--- Returns a table of all job objects.
function hilbish.jobs.all() end
--- Disowns a job. This simply deletes it from the list of jobs without stopping it.
function hilbish.jobs.disown(id) end
--- Get a job object via its ID.
--- @param id number
--- @returns Job
function hilbish.jobs.get(id) end
--- Returns the last added job to the table.
function hilbish.jobs.last() end
--- Adds a command to the history.
function hilbish.history.add(cmd) end
--- Retrieves all history as a table.
function hilbish.history.all() end
--- Deletes all commands from the history.
function hilbish.history.clear() end
--- Retrieves a command from the history based on the `index`.
function hilbish.history.get(index) end
--- Returns the amount of commands in the history.
function hilbish.history.size() end
--- Creates a timer that runs based on the specified `time`.
function hilbish.timers.create(type, time, callback) end
--- Retrieves a timer via its ID.
function hilbish.timers.get(id) end
--- Sets/toggles the option of automatically flushing output.
--- A call with no argument will toggle the value.
--- @param auto boolean|nil
function hilbish:autoFlush(auto) end
--- Flush writes all buffered input to the sink.
function hilbish:flush() end
--- Reads a liine of input from the sink.
--- @returns string
function hilbish:read() end
--- Reads all input from the sink.
--- @returns string
function hilbish:readAll() end
--- Writes data to a sink.
function hilbish:write(str) end
--- Writes data to a sink with a newline at the end.
function hilbish:writeln(str) end
return hilbish

32
emmyLuaDocs/readline.lua Normal file
View File

@ -0,0 +1,32 @@
--- @meta
local readline = {}
--- Deletes characters in the line by the given amount.
function readline:deleteByAmount(amount) end
--- Returns the current input line.
function readline:getLine() end
--- Returns the text that is at the register.
function readline:getVimRegister(register) end
--- Inserts text into the Hilbish command line.
function readline:insert(text) end
--- Prints a message *before* the prompt without it being interrupted by user input.
function readline:log(text) end
--- Creates a new readline instance.
function readline.new() end
--- Reads input from the user.
function readline:read() end
--- Reads a keystroke from the user. This is in a format of something like Ctrl-L.
function readline:getChar() end
--- Sets the vim register at `register` to hold the passed text.
function readline:setVimRegister(register, text) end
return readline

16
emmyLuaDocs/snail.lua Normal file
View File

@ -0,0 +1,16 @@
--- @meta
local snail = {}
--- Changes the directory of the snail instance.
--- The interpreter keeps its set directory even when the Hilbish process changes
--- directory, so this should be called on the `hilbish.cd` hook.
function snail:dir(path) end
--- Creates a new Snail instance.
function snail.new() end
--- Runs a shell command. Works the same as `hilbish.run`, but only accepts a table of streams.
function snail:run(command, streams) end
return snail

18
emmyLuaDocs/terminal.lua Normal file
View File

@ -0,0 +1,18 @@
--- @meta
local terminal = {}
--- Restores the last saved state of the terminal
function terminal.restoreState() end
--- Saves the current state of the terminal.
function terminal.saveState() end
--- Puts the terminal into raw mode.
function terminal.setRaw() end
--- Gets the dimensions of the terminal. Returns a table with `width` and `height`
--- NOTE: The size refers to the amount of columns and rows of text that can fit in the terminal.
function terminal.size() end
return terminal

83
emmyLuaDocs/util.lua Normal file
View File

@ -0,0 +1,83 @@
--- @meta
local util = {}
---
function util.AbbrevHome changes the user's home directory in the path string to ~ (tilde) end
---
function util. end
---
function util.DoFile runs the contents of the file in the Lua runtime. end
---
function util.DoString runs the code string in the Lua runtime. end
--- directory.
function util.ExpandHome expands ~ (tilde) in the path, changing it to the user home end
---
function util. end
---
function util.ForEach loops through a Lua table. end
---
function util. end
--- a string and a closure.
function util.HandleStrCallback handles function parameters for Go functions which take end
---
function util. end
---
function util. end
---
function util.SetExports puts the Lua function exports in the table. end
--- It is accessible via the __docProp metatable. It is a table of the names of the fields.
function util.SetField sets a field in a table, adding docs for it. end
--- is one which has a metatable proxy to ensure no overrides happen to it.
--- It sets the field in the table and sets the __docProp metatable on the
--- user facing table.
function util.SetFieldProtected sets a field in a protected table. A protected table end
--- Sets/toggles the option of automatically flushing output.
--- A call with no argument will toggle the value.
--- @param auto boolean|nil
function util:autoFlush(auto) end
--- Flush writes all buffered input to the sink.
function util:flush() end
---
function util. end
--- Reads a liine of input from the sink.
--- @returns string
function util:read() end
--- Reads all input from the sink.
--- @returns string
function util:readAll() end
--- Writes data to a sink.
function util:write(str) end
--- Writes data to a sink with a newline at the end.
function util:writeln(str) end
---
function util. end
---
function util. end
---
function util. end
return util

9
emmyLuaDocs/yarn.lua Normal file
View File

@ -0,0 +1,9 @@
--- @meta
local yarn = {}
--- Creates a new, fresh Yarn thread.
--- `fun` is the function that will run in the thread.
function yarn.thread(fun) end
return yarn

85
exec.go Normal file
View File

@ -0,0 +1,85 @@
package main
import (
"errors"
"fmt"
"os"
"strings"
rt "github.com/arnodel/golua/runtime"
//"github.com/yuin/gopher-lua/parse"
)
var errNotExec = errors.New("not executable")
var errNotFound = errors.New("not found")
var runnerMode rt.Value = rt.NilValue
func runInput(input string, priv bool) {
running = true
runnerRun := hshMod.Get(rt.StringValue("runner")).AsTable().Get(rt.StringValue("run"))
_, err := rt.Call1(l.MainThread(), runnerRun, rt.StringValue(input), rt.BoolValue(priv))
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
}
func handleLua(input string) (string, uint8, error) {
cmdString := aliases.Resolve(input)
// First try to load input, essentially compiling to bytecode
chunk, err := l.CompileAndLoadLuaChunk("", []byte(cmdString), rt.TableValue(l.GlobalEnv()))
if err != nil && noexecute {
fmt.Println(err)
/* if lerr, ok := err.(*lua.ApiError); ok {
if perr, ok := lerr.Cause.(*parse.Error); ok {
print(perr.Pos.Line == parse.EOF)
}
}
*/
return cmdString, 125, err
}
// And if there's no syntax errors and -n isnt provided, run
if !noexecute {
if chunk != nil {
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
}
}
if err == nil {
return cmdString, 0, nil
}
return cmdString, 125, err
}
func splitInput(input string) ([]string, string) {
// end my suffering
// TODO: refactor this garbage
quoted := false
cmdArgs := []string{}
sb := &strings.Builder{}
cmdstr := &strings.Builder{}
for _, r := range input {
if r == '"' {
// start quoted input
// this determines if other runes are replaced
quoted = !quoted
// dont add back quotes
//sb.WriteRune(r)
} else if !quoted && r == '~' {
// if not in quotes and ~ is found then make it $HOME
sb.WriteString(os.Getenv("HOME"))
} else if !quoted && r == ' ' {
// if not quoted and there's a space then add to cmdargs
cmdArgs = append(cmdArgs, sb.String())
sb.Reset()
} else {
sb.WriteRune(r)
}
cmdstr.WriteRune(r)
}
if sb.Len() > 0 {
cmdArgs = append(cmdArgs, sb.String())
}
return cmdArgs, cmdstr.String()
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 58 KiB

BIN
gallery/tab.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 99 KiB

43
go.mod
View File

@ -1,18 +1,37 @@
module hilbish
go 1.16
go 1.21
toolchain go1.22.2
require (
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650 // indirect
github.com/bobappleyard/readline v0.0.0-20150707195538-7e300e02d38e
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/arnodel/golua v0.0.0-20230215163904-e0b5347eaaa1
github.com/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504
github.com/blackfireio/osinfo v1.0.5
github.com/maxlandon/readline v1.0.14
github.com/pborman/getopt v1.1.0
github.com/rivo/uniseg v0.2.0 // indirect
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
layeh.com/gopher-luar v1.0.8
mvdan.cc/sh/v3 v3.3.0
github.com/sahilm/fuzzy v0.1.1
golang.org/x/sys v0.22.0
golang.org/x/term v0.22.0
mvdan.cc/sh/v3 v3.8.0
)
require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/arnodel/strftime v0.1.6 // indirect
github.com/evilsocket/islazy v1.11.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
replace mvdan.cc/sh/v3 => github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20240815163633-562273e09b73
replace github.com/maxlandon/readline => ./golibs/readline
replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10
replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20241104031959-5551ea280f23

92
go.sum
View File

@ -1,52 +1,46 @@
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650 h1:nzFJUdJU8UJ1DA8mSQp4eoBtQyOJyecekVWusjfQsqE=
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650/go.mod h1:/FFZ4cgR6TXXYaskRUxyLIYdfG0PS4BPtWjWRQms754=
github.com/bobappleyard/readline v0.0.0-20150707195538-7e300e02d38e h1:4G8AYOOwZdDWOiJR6D6JXaFmj5BDS7c5D5PyqsG/+Hg=
github.com/bobappleyard/readline v0.0.0-20150707195538-7e300e02d38e/go.mod h1:fmqtV+Wqx0uFYLN1F4VhjZdtT56Dr8c3yA7nALFsw/Q=
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9 h1:xz6Nv3zcwO2Lila35hcb0QloCQsc38Al13RNEzWRpX4=
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9/go.mod h1:2wSM9zJkl1UQEFZgSd68NfCgRz1VL1jzy/RjCg+ULrs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/google/renameio v1.0.1-0.20210406141108-81588dbe0453/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/Rosettea/golua v0.0.0-20241104031959-5551ea280f23 h1:mUZnT0gmDEmTkqXsbnDbuJ3CNil7DCOMiCQYgjbKIdI=
github.com/Rosettea/golua v0.0.0-20241104031959-5551ea280f23/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20240815163633-562273e09b73 h1:zTTUJqNnrF2qf4LgygN8Oae5Uxn6ewH0hA8jyTCHfXw=
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20240815163633-562273e09b73/go.mod h1:YZalN5H7WNQw3DGij6IvHsEhn5YMW7M2FCwG6gnfKy4=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/arnodel/strftime v0.1.6 h1:0hc0pUvk8KhEMXE+htyaOUV42zNcf/csIbjzEFCJqsw=
github.com/arnodel/strftime v0.1.6/go.mod h1:5NbK5XqYK8QpRZpqKNt4OlxLtIB8cotkLk4KTKzJfWs=
github.com/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504 h1:R1/AOzdMbopSliUTTEHvHbyNmnZ3YxY5GvdhTkpPsSY=
github.com/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504/go.mod h1:kHBCvAXJIatTX1pw6tLiOspjGc3MhUDRlog9yrCUS+k=
github.com/blackfireio/osinfo v1.0.5 h1:6hlaWzfcpb87gRmznVf7wSdhysGqLRz9V/xuSdCEXrA=
github.com/blackfireio/osinfo v1.0.5/go.mod h1:Pd987poVNmd5Wsx6PRPw4+w7kLlf9iJxoRKPtPAjOrA=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/evilsocket/islazy v1.11.0 h1:B5w6uuS6ki6iDG+aH/RFeoMb8ijQh/pGabewqp2UeJ0=
github.com/evilsocket/islazy v1.11.0/go.mod h1:muYH4x5MB5YRdkxnrOtrXLIBX6LySj1uFIqys94LKdo=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 h1:LiZB1h0GIcudcDci2bxbqI6DXV8bF8POAnArqvRrIyw=
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0/go.mod h1:F/7q8/HZz+TXjlsoZQQKVYvXTZaFH4QRa3y+j1p7MS0=
github.com/pborman/getopt v1.1.0 h1:eJ3aFZroQqq0bWmraivjQNt6Dmm5M0h2JcDW38/Azb0=
github.com/pborman/getopt v1.1.0/go.mod h1:FxXoW1Re00sQG/+KIkuSqRL/LwQgSkv7uyac+STFsbk=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.7.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw=
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210414055047-fe65e336abe0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210521203332-0cec03c779c1 h1:lCnv+lfrU9FRPGf8NeRuWAAPjNnema5WtBinMgs1fD8=
golang.org/x/sys v0.0.0-20210521203332-0cec03c779c1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210406210042-72f3dc4e9b72/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
layeh.com/gopher-luar v1.0.8 h1:Uqws1Z6T0vK6pZ7ehNNurLLSFcz7+E0EOHVM4FNiMQs=
layeh.com/gopher-luar v1.0.8/go.mod h1:TPnIVCZ2RJBndm7ohXyaqfhzjlZ+OA2SZR/YwL8tECk=
mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0=
mvdan.cc/sh/v3 v3.3.0 h1:ujzElMnry63f4I5sjPFxzo6xia+gwsHZM0yyauuyZ6k=
mvdan.cc/sh/v3 v3.3.0/go.mod h1:dh3avhLDhJJ/MJKzbak6FYn+DJKUWk7Fb6Dh5mGdv6Y=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=

View File

@ -1,35 +1,365 @@
// the event emitter
/*
Bait is the event emitter for Hilbish. Much like Node.js and
its `events` system, many actions in Hilbish emit events.
Unlike Node.js, Hilbish events are global. So make sure to
pick a unique name!
Usage of the Bait module consists of userstanding
event-driven architecture, but it's pretty simple:
If you want to act on a certain event, you can `catch` it.
You can act on events via callback functions.
Examples of this are in the Hilbish default config!
Consider this part of it:
```lua
bait.catch('command.exit', function(code)
running = false
doPrompt(code ~= 0)
doNotifyPrompt()
end)
```
What this does is, whenever the `command.exit` event is thrown,
this function will set the user prompt.
*/
package bait
import (
"github.com/chuckpreslar/emission"
"github.com/yuin/gopher-lua"
"layeh.com/gopher-luar"
"errors"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
)
type Bait struct{
Em *emission.Emitter
type listenerType int
const (
goListener listenerType = iota
luaListener
)
// Recoverer is a function which is called when a panic occurs in an event.
type Recoverer func(event string, handler *Listener, err interface{})
// Listener is a struct that holds the handler for an event.
type Listener struct{
typ listenerType
once bool
caller func(...interface{}) rt.Value
luaCaller *rt.Closure
}
func New() Bait {
return Bait{
Em: emission.NewEmitter(),
type Bait struct{
Loader packagelib.Loader
recoverer Recoverer
handlers map[string][]*Listener
rtm *rt.Runtime
}
// New creates a new Bait instance.
func New(rtm *rt.Runtime) *Bait {
b := &Bait{
handlers: make(map[string][]*Listener),
rtm: rtm,
}
b.Loader = packagelib.Loader{
Load: b.loaderFunc,
Name: "bait",
}
return b
}
// Emit throws an event.
func (b *Bait) Emit(event string, args ...interface{}) []rt.Value {
var returns []rt.Value
handles := b.handlers[event]
if handles == nil {
return nil
}
for idx, handle := range handles {
defer func() {
if err := recover(); err != nil {
b.callRecoverer(event, handle, err)
}
}()
if handle.typ == luaListener {
funcVal := rt.FunctionValue(handle.luaCaller)
var luaArgs []rt.Value
for _, arg := range args {
var luarg rt.Value
switch arg.(type) {
case rt.Value: luarg = arg.(rt.Value)
default: luarg = rt.AsValue(arg)
}
luaArgs = append(luaArgs, luarg)
}
luaRet, err := rt.Call1(b.rtm.MainThread(), funcVal, luaArgs...)
if err != nil {
if event != "error" {
b.Emit("error", event, handle.luaCaller, err.Error())
return nil
}
// if there is an error in an error event handler, panic instead
// (calls the go recoverer function)
panic(err)
}
if luaRet != rt.NilValue {
returns = append(returns, luaRet)
}
} else {
ret := handle.caller(args...)
if ret != rt.NilValue {
returns = append(returns, ret)
}
}
if handle.once {
b.removeListener(event, idx)
}
}
return returns
}
// On adds a Go function handler for an event.
func (b *Bait) On(event string, handler func(...interface{}) rt.Value) *Listener {
listener := &Listener{
typ: goListener,
caller: handler,
}
b.addListener(event, listener)
return listener
}
// OnLua adds a Lua function handler for an event.
func (b *Bait) OnLua(event string, handler *rt.Closure) *Listener {
listener := &Listener{
typ: luaListener,
luaCaller: handler,
}
b.addListener(event, listener)
return listener
}
// Off removes a Go function handler for an event.
func (b *Bait) Off(event string, listener *Listener) {
handles := b.handlers[event]
for i, handle := range handles {
if handle == listener {
b.removeListener(event, i)
}
}
}
func (b *Bait) Loader(L *lua.LState) int {
mod := L.SetFuncs(L.NewTable(), map[string]lua.LGFunction{})
L.SetField(mod, "throw", luar.New(L, b.throw))
L.SetField(mod, "catch", luar.New(L, b.catch))
// OffLua removes a Lua function handler for an event.
func (b *Bait) OffLua(event string, handler *rt.Closure) {
handles := b.handlers[event]
L.Push(mod)
return 1
for i, handle := range handles {
if handle.luaCaller == handler {
b.removeListener(event, i)
}
}
}
func (b *Bait) throw(name string, args ...interface{}) {
b.Em.Emit(name, args...)
// Once adds a Go function listener for an event that only runs once.
func (b *Bait) Once(event string, handler func(...interface{}) rt.Value) *Listener {
listener := &Listener{
typ: goListener,
once: true,
caller: handler,
}
b.addListener(event, listener)
return listener
}
func (b *Bait) catch(name string, catcher func(interface{})) {
b.Em.On(name, catcher)
// OnceLua adds a Lua function listener for an event that only runs once.
func (b *Bait) OnceLua(event string, handler *rt.Closure) *Listener {
listener := &Listener{
typ: luaListener,
once: true,
luaCaller: handler,
}
b.addListener(event, listener)
return listener
}
// SetRecoverer sets the function to be executed when a panic occurs in an event.
func (b *Bait) SetRecoverer(recoverer Recoverer) {
b.recoverer = recoverer
}
func (b *Bait) addListener(event string, listener *Listener) {
if b.handlers[event] == nil {
b.handlers[event] = []*Listener{}
}
b.handlers[event] = append(b.handlers[event], listener)
}
func (b *Bait) removeListener(event string, idx int) {
b.handlers[event][idx] = b.handlers[event][len(b.handlers[event]) - 1]
b.handlers[event] = b.handlers[event][:len(b.handlers[event]) - 1]
}
func (b *Bait) callRecoverer(event string, handler *Listener, err interface{}) {
if b.recoverer == nil {
panic(err)
}
b.recoverer(event, handler, err)
}
func (b *Bait) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
exports := map[string]util.LuaExport{
"catch": util.LuaExport{b.bcatch, 2, false},
"catchOnce": util.LuaExport{b.bcatchOnce, 2, false},
"throw": util.LuaExport{b.bthrow, 1, true},
"release": util.LuaExport{b.brelease, 2, false},
"hooks": util.LuaExport{b.bhooks, 1, false},
}
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
return rt.TableValue(mod), nil
}
// catch(name, cb)
// Catches an event. This function can be used to act on events.
// #param name string The name of the hook.
// #param cb function The function that will be called when the hook is thrown.
/*
#example
bait.catch('hilbish.exit', function()
print 'Goodbye Hilbish!'
end)
#example
*/
func (b *Bait) bcatch(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
name, catcher, err := util.HandleStrCallback(t, c)
if err != nil {
return nil, err
}
b.OnLua(name, catcher)
return c.Next(), nil
}
// catchOnce(name, cb)
// Catches an event, but only once. This will remove the hook immediately after it runs for the first time.
// #param name string The name of the event
// #param cb function The function that will be called when the event is thrown.
func (b *Bait) bcatchOnce(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
name, catcher, err := util.HandleStrCallback(t, c)
if err != nil {
return nil, err
}
b.OnceLua(name, catcher)
return c.Next(), nil
}
// hooks(name) -> table
// Returns a table of functions that are hooked on an event with the corresponding `name`.
// #param name string The name of the hook
// #returns table<function>
func (b *Bait) bhooks(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
evName, err := c.StringArg(0)
if err != nil {
return nil, err
}
noHooks := errors.New("no hooks for event " + evName)
handlers := b.handlers[evName]
if handlers == nil {
return nil, noHooks
}
luaHandlers := rt.NewTable()
for _, handler := range handlers {
if handler.typ != luaListener { continue }
luaHandlers.Set(rt.IntValue(luaHandlers.Len() + 1), rt.FunctionValue(handler.luaCaller))
}
if luaHandlers.Len() == 0 {
return nil, noHooks
}
return c.PushingNext1(t.Runtime, rt.TableValue(luaHandlers)), nil
}
// release(name, catcher)
// Removes the `catcher` for the event with `name`.
// For this to work, `catcher` has to be the same function used to catch
// an event, like one saved to a variable.
// #param name string Name of the event the hook is on
// #param catcher function Hook function to remove
/*
#example
local hookCallback = function() print 'hi' end
bait.catch('event', hookCallback)
-- a little while later....
bait.release('event', hookCallback)
-- and now hookCallback will no longer be ran for the event.
#example
*/
func (b *Bait) brelease(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
name, catcher, err := util.HandleStrCallback(t, c)
if err != nil {
return nil, err
}
b.OffLua(name, catcher)
return c.Next(), nil
}
// throw(name, ...args)
// #param name string The name of the hook.
// #param args ...any The arguments to pass to the hook.
// Throws a hook with `name` with the provided `args`.
/*
#example
bait.throw('greeting', 'world')
-- This can then be listened to via
bait.catch('gretting', function(greetTo)
print('Hello ' .. greetTo)
end)
#example
*/
func (b *Bait) bthrow(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
name, err := c.StringArg(0)
if err != nil {
return nil, err
}
ifaceSlice := make([]interface{}, len(c.Etc()))
for i, v := range c.Etc() {
ifaceSlice[i] = v
}
ret := b.Emit(name, ifaceSlice...)
return c.PushingNext(t.Runtime, ret...), nil
}

View File

@ -1,45 +1,133 @@
// library for custom commands
/*
Commander is the library which handles Hilbish commands. This makes
the user able to add Lua-written commands to their shell without making
a separate script in a bin folder. Instead, you may simply use the Commander
library in your Hilbish config.
```lua
local commander = require 'commander'
commander.register('hello', function(args, sinks)
sinks.out:writeln 'Hello world!'
end)
```
In this example, a command with the name of `hello` is created
that will print `Hello world!` to output. One question you may
have is: What is the `sinks` parameter?
The `sinks` parameter is a table with 3 keys: `input`, `out`, and `err`.
There is an `in` alias to `input`, but it requires using the string accessor syntax (`sinks['in']`)
as `in` is also a Lua keyword, so `input` is preferred for use.
All of them are a @Sink.
In the future, `sinks.in` will be removed.
- `in` is the standard input.
You may use the read functions on this sink to get input from the user.
- `out` is standard output.
This is usually where command output should go.
- `err` is standard error.
This sink is for writing errors, as the name would suggest.
*/
package commander
import (
"github.com/chuckpreslar/emission"
"github.com/yuin/gopher-lua"
"hilbish/util"
"hilbish/golibs/bait"
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
)
type Commander struct{
Events *emission.Emitter
Events *bait.Bait
Loader packagelib.Loader
Commands map[string]*rt.Closure
}
func New() Commander {
return Commander{
Events: emission.NewEmitter(),
func New(rtm *rt.Runtime) *Commander {
c := &Commander{
Events: bait.New(rtm),
Commands: make(map[string]*rt.Closure),
}
}
func (c *Commander) Loader(L *lua.LState) int {
var exports = map[string]lua.LGFunction{
"register": c.register,
"deregister": c.deregister,
c.Loader = packagelib.Loader{
Load: c.loaderFunc,
Name: "commander",
}
mod := L.SetFuncs(L.NewTable(), exports)
L.Push(mod)
return 1
return c
}
func (c *Commander) register(L *lua.LState) int {
cmdName := L.CheckString(1)
cmd := L.CheckFunction(2)
func (c *Commander) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
exports := map[string]util.LuaExport{
"register": util.LuaExport{c.cregister, 2, false},
"deregister": util.LuaExport{c.cderegister, 1, false},
"registry": util.LuaExport{c.cregistry, 0, false},
}
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
c.Events.Emit("commandRegister", cmdName, cmd)
return 0
return rt.TableValue(mod), nil
}
func (c *Commander) deregister(L *lua.LState) int {
cmdName := L.CheckString(1)
// register(name, cb)
// Adds a new command with the given `name`. When Hilbish has to run a command with a name,
// it will run the function providing the arguments and sinks.
// #param name string Name of the command
// #param cb function Callback to handle command invocation
/*
#example
-- When you run the command `hello` in the shell, it will print `Hello world`.
-- If you run it with, for example, `hello Hilbish`, it will print 'Hello Hilbish'
commander.register('hello', function(args, sinks)
local name = 'world'
if #args > 0 then name = args[1] end
c.Events.Emit("commandDeregister", cmdName)
sinks.out:writeln('Hello ' .. name)
end)
#example
*/
func (c *Commander) cregister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
cmdName, cmd, err := util.HandleStrCallback(t, ct)
if err != nil {
return nil, err
}
return 0
c.Commands[cmdName] = cmd
return ct.Next(), err
}
// deregister(name)
// Removes the named command. Note that this will only remove Commander-registered commands.
// #param name string Name of the command to remove.
func (c *Commander) cderegister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
if err := ct.Check1Arg(); err != nil {
return nil, err
}
cmdName, err := ct.StringArg(0)
if err != nil {
return nil, err
}
delete(c.Commands, cmdName)
return ct.Next(), err
}
// registry() -> table
// Returns all registered commanders. Returns a list of tables with the following keys:
// - `exec`: The function used to run the commander. Commanders require args and sinks to be passed.
// #returns table
func (c *Commander) cregistry(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
registryLua := rt.NewTable()
for cmdName, cmd := range c.Commands {
cmdTbl := rt.NewTable()
cmdTbl.Set(rt.StringValue("exec"), rt.FunctionValue(cmd))
registryLua.Set(rt.StringValue(cmdName), rt.TableValue(cmdTbl))
}
return ct.PushingNext1(t.Runtime, rt.TableValue(registryLua)), nil
}

View File

@ -1,71 +1,332 @@
// filesystem interaction and functionality library
/*
The fs module provides filesystem functions to Hilbish. While Lua's standard
library has some I/O functions, they're missing a lot of the basics. The `fs`
library offers more functions and will work on any operating system Hilbish does.
#field pathSep The operating system's path separator.
*/
package fs
import (
"fmt"
"path/filepath"
"strconv"
"os"
"strings"
"github.com/yuin/gopher-lua"
"layeh.com/gopher-luar"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
"github.com/arnodel/golua/lib/iolib"
)
func Loader(L *lua.LState) int {
mod := L.SetFuncs(L.NewTable(), exports)
L.Push(mod)
return 1
var Loader = packagelib.Loader{
Load: loaderFunc,
Name: "fs",
}
func LuaErr(L *lua.LState, code int) {
// TODO: Error with a table, with path and error code
L.Error(lua.LNumber(code), 2)
func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
exports := map[string]util.LuaExport{
"cd": util.LuaExport{fcd, 1, false},
"mkdir": util.LuaExport{fmkdir, 2, false},
"stat": util.LuaExport{fstat, 1, false},
"readdir": util.LuaExport{freaddir, 1, false},
"abs": util.LuaExport{fabs, 1, false},
"basename": util.LuaExport{fbasename, 1, false},
"dir": util.LuaExport{fdir, 1, false},
"glob": util.LuaExport{fglob, 1, false},
"join": util.LuaExport{fjoin, 0, true},
"pipe": util.LuaExport{fpipe, 0, false},
}
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
mod.Set(rt.StringValue("pathSep"), rt.StringValue(string(os.PathSeparator)))
mod.Set(rt.StringValue("pathListSep"), rt.StringValue(string(os.PathListSeparator)))
return rt.TableValue(mod), nil
}
var exports = map[string]lua.LGFunction{
"cd": cd,
"mkdir": mkdir,
"stat": stat,
}
func cd(L *lua.LState) int {
path := L.CheckString(1)
err := os.Chdir(strings.TrimSpace(path))
// abs(path) -> string
// Returns an absolute version of the `path`.
// This can be used to resolve short paths like `..` to `/home/user`.
// #param path string
// #returns string
func fabs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
path, err := c.StringArg(0)
if err != nil {
switch e := err.(*os.PathError).Err.Error(); e {
case "no such file or directory":
LuaErr(L, 1)
default:
fmt.Printf("Found unhandled error case: %s", e)
fmt.Printf("Report this at https://github.com/Hilbis/Hilbish/issues with the title being: \"fs: unahndled error case %s\", and show what caused it.\n", e)
LuaErr(L, 213)
return nil, err
}
path = util.ExpandHome(path)
abspath, err := filepath.Abs(path)
if err != nil {
return nil, err
}
return c.PushingNext1(t.Runtime, rt.StringValue(abspath)), nil
}
// basename(path) -> string
// Returns the "basename," or the last part of the provided `path`. If path is empty,
// `.` will be returned.
// #param path string Path to get the base name of.
// #returns string
func fbasename(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
path, err := c.StringArg(0)
if err != nil {
return nil, err
}
return c.PushingNext(t.Runtime, rt.StringValue(filepath.Base(path))), nil
}
// cd(dir)
// Changes Hilbish's directory to `dir`.
// #param dir string Path to change directory to.
func fcd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
path, err := c.StringArg(0)
if err != nil {
return nil, err
}
path = util.ExpandHome(strings.TrimSpace(path))
oldWd, _ := os.Getwd()
abspath, err := filepath.Abs(path)
if err != nil {
return nil, err
}
err = os.Chdir(path)
if err != nil {
return nil, err
}
util.DoString(t.Runtime, fmt.Sprintf(`
local bait = require 'bait'
bait.throw('hilbish.cd', '%s', '%s')
`, abspath, oldWd))
return c.Next(), err
}
// dir(path) -> string
// Returns the directory part of `path`. If a file path like
// `~/Documents/doc.txt` then this function will return `~/Documents`.
// #param path string Path to get the directory for.
// #returns string
func fdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
path, err := c.StringArg(0)
if err != nil {
return nil, err
}
return c.PushingNext(t.Runtime, rt.StringValue(filepath.Dir(path))), nil
}
// glob(pattern) -> matches (table)
// Match all files based on the provided `pattern`.
// For the syntax' refer to Go's filepath.Match function: https://pkg.go.dev/path/filepath#Match
// #param pattern string Pattern to compare files with.
// #returns table A list of file names/paths that match.
/*
#example
--[[
Within a folder that contains the following files:
a.txt
init.lua
code.lua
doc.pdf
]]--
local matches = fs.glob './*.lua'
print(matches)
-- -> {'init.lua', 'code.lua'}
#example
*/
func fglob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
pattern, err := c.StringArg(0)
if err != nil {
return nil, err
}
matches, err := filepath.Glob(pattern)
if err != nil {
return nil, err
}
luaMatches := rt.NewTable()
for i, match := range matches {
luaMatches.Set(rt.IntValue(int64(i + 1)), rt.StringValue(match))
}
return c.PushingNext(t.Runtime, rt.TableValue(luaMatches)), nil
}
// join(...path) -> string
// Takes any list of paths and joins them based on the operating system's path separator.
// #param path ...string Paths to join together
// #returns string The joined path.
/*
#example
-- This prints the directory for Hilbish's config!
print(fs.join(hilbish.userDir.config, 'hilbish'))
-- -> '/home/user/.config/hilbish' on Linux
#example
*/
func fjoin(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
strs := make([]string, len(c.Etc()))
for i, v := range c.Etc() {
if v.Type() != rt.StringType {
// +2; go indexes of 0 and first arg from above
return nil, fmt.Errorf("bad argument #%d to run (expected string, got %s)", i + 1, v.TypeName())
}
strs[i] = v.AsString()
}
return 0
res := filepath.Join(strs...)
return c.PushingNext(t.Runtime, rt.StringValue(res)), nil
}
func mkdir(L *lua.LState) int {
dirname := L.CheckString(1)
recursive := L.ToBool(2)
path := strings.TrimSpace(dirname)
// mkdir(name, recursive)
// Creates a new directory with the provided `name`.
// With `recursive`, mkdir will create parent directories.
// #param name string Name of the directory
// #param recursive boolean Whether to create parent directories for the provided name
/*
#example
-- This will create the directory foo, then create the directory bar in the
-- foo directory. If recursive is false in this case, it will fail.
fs.mkdir('./foo/bar', true)
#example
*/
func fmkdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(2); err != nil {
return nil, err
}
path, err := c.StringArg(0)
if err != nil {
return nil, err
}
recursive, err := c.BoolArg(1)
if err != nil {
return nil, err
}
path = util.ExpandHome(strings.TrimSpace(path))
// TODO: handle error here
if recursive {
os.MkdirAll(path, 0744)
err = os.MkdirAll(path, 0744)
} else {
os.Mkdir(path, 0744)
err = os.Mkdir(path, 0744)
}
if err != nil {
return nil, err
}
return 0
return c.Next(), err
}
func stat(L *lua.LState) int {
path := L.CheckString(1)
// fpipe() -> File, File
// Returns a pair of connected files, also known as a pipe.
// The type returned is a Lua file, same as returned from `io` functions.
// #returns File
// #returns File
func fpipe(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
rf, wf, err := os.Pipe()
if err != nil {
return nil, err
}
// TODO: handle error here
pathinfo, _ := os.Stat(path)
L.Push(luar.New(L, pathinfo))
rfLua := iolib.NewFile(rf, 0)
wfLua := iolib.NewFile(wf, 0)
return 1
return c.PushingNext(t.Runtime, rfLua.Value(t.Runtime), wfLua.Value(t.Runtime)), nil
}
// readdir(path) -> table[string]
// Returns a list of all files and directories in the provided path.
// #param dir string
// #returns table
func freaddir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
dir, err := c.StringArg(0)
if err != nil {
return nil, err
}
dir = util.ExpandHome(dir)
names := rt.NewTable()
dirEntries, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
for i, entry := range dirEntries {
names.Set(rt.IntValue(int64(i + 1)), rt.StringValue(entry.Name()))
}
return c.PushingNext1(t.Runtime, rt.TableValue(names)), nil
}
// stat(path) -> {}
// Returns the information about a given `path`.
// The returned table contains the following values:
// name (string) - Name of the path
// size (number) - Size of the path in bytes
// mode (string) - Unix permission mode in an octal format string (with leading 0)
// isDir (boolean) - If the path is a directory
// #param path string
// #returns table
/*
#example
local inspect = require 'inspect'
local stat = fs.stat '~'
print(inspect(stat))
--[[
Would print the following:
{
isDir = true,
mode = "0755",
name = "username",
size = 12288
}
]]--
#example
*/
func fstat(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
path, err := c.StringArg(0)
if err != nil {
return nil, err
}
path = util.ExpandHome(path)
pathinfo, err := os.Stat(path)
if err != nil {
return nil, err
}
statTbl := rt.NewTable()
statTbl.Set(rt.StringValue("name"), rt.StringValue(pathinfo.Name()))
statTbl.Set(rt.StringValue("size"), rt.IntValue(pathinfo.Size()))
statTbl.Set(rt.StringValue("mode"), rt.StringValue("0" + strconv.FormatInt(int64(pathinfo.Mode().Perm()), 8)))
statTbl.Set(rt.StringValue("isDir"), rt.BoolValue(pathinfo.IsDir()))
return c.PushingNext1(t.Runtime, rt.TableValue(statTbl)), nil
}

122
golibs/readline/CHANGES.md Normal file
View File

@ -0,0 +1,122 @@
## Changes
### 4.1.0
---------
Many new features and improvements in this version:
- New keybindings (working on Emacs, and in `Vim Insert Mode`):
* `CtrlW` to cut the previous word at the cursor
* `CtrlA` to go back to the beginning of the line
* `CtrlY` to paste the laste copy/paste buffer (see Registers)
* `CtrlU` to cut the whole line.
- More precise Vim iterations:
* Iterations can now be applied to some Vim actions (`y4w`, `d3b`)
- Implemented Vim registers:
* Yank/paste operations of any sort can occur and be assigned to registers.
* The default `""` register
* 10 numbered registers, to which bufffers are automatically added
* 26 lettered registers (lowercase), to which you can append with `"D` (D being the uppercase of the `"d` register)
* Triggered in Insert Mode with `Alt"` (buggy sometimes: goes back to Normal mode selecting a register, will have to fix this)
- Unified iterations and registers:
* To copy to the `d` register the next 4 words: `"d y4w`
* To append to this `d` register the cuttend end of line: `"D d$"`
* In this example, the `d` register buffer is also the buffer in the default register `""`
* You could either:
- Paste 3 times this buffer while in Normal mode: `3p`
- Paste the buffer once in Insert mode: `CtrlY`
- History completions:
* The binding for the alternative history changed to `AltR` (the normal remains `CtrlR`)
* By defaul the history filters only against the search pattern.
* If there are matches for this patten, the first occurence is insert (virtually)
* This is refreshed as the pattern changes
* `CtrlG` to exit the comps, while leaving the current candidate
* `CtrlC` to exit and delete the current candidate
- Completions:
* When a candidate is inserted virtually, `CtrlC` to abort both completions and the candidate
* Implemented global printing size: If the overall number of completions is biffer, will roll over them.
**Notes:**
* The `rl.Readline()` function dispatch has some big cases, maybe a bit of refactoring would be nice
* The way the buffer storing bytes from key strokes sometimes gives weird results (like `Alt"` for showing Vim registers)
* Some defer/cancel calls related to DelayedTabContext that should have been merged from lmorg/readline are still missing.
### 4.0.0-beta
---------
This version is the merge of [maxlandon/readline](https://github.com/maxlandon/readline)
and [lmorg/readline](https://github.com/lmorg/readline). Therefore it both integrates parts
from both libraries, but also adds a few features, with some API breaking changes (ex: completions),
thus the new 4.0.0 version. Remains a beta because maxlandon/readline code has not been thoroughly
test neither in nor of itself, and no more against `lmorg/murex`, it's main consumer until now.
#### Code
- Enhance delete/copy buffer in Vim mode
- DelayedTabContext now works with completion groups
#### Packages
- Added a `completers` package, with a default tab/hint/syntax completer working with
the [go-flags](https://github.com/jessevdk/go-flags) library.
- The `examples` package has been enhanced with a more complete -base- application code. See the wiki
#### Documentation
- Merged relevant parts of both READMEs
- Use documentation from maxlandon/readline
#### New features / bindings
- CtrlL now clears the screen and reprints the prompt
- Added evilsocket's tui colors/effects, for ease of use & integration with shell. Has not yet replaced the current `seqColor` variables everywhere though
#### Changes I'm not sure of
- is the function leftMost() in cursor.go useful ?
- is the function getCursorPos() in cursor.go useful ?
### 3.0.0
---------
- Added test (input line, prompt, correct refresh, etc)
- Added multiline support
- Added `DelayedTabContext` and `DelayedSyntaxWorker`
### 2.1.0
---------
Error returns from `readline` have been created as error a variable, which is
more idiomatic to Go than the err constants that existed previously. Currently
both are still available to use however I will be deprecating the the constants
in a latter release.
**Deprecated constants:**
```go
const (
// ErrCtrlC is returned when ctrl+c is pressed
ErrCtrlC = "Ctrl+C"
// ErrEOF is returned when ctrl+d is pressed
ErrEOF = "EOF"
)
```
**New error variables:**
```go
var (
// CtrlC is returned when ctrl+c is pressed
CtrlC = errors.New("Ctrl+C")
// EOF is returned when ctrl+d is pressed
// (this is actually the same value as io.EOF)
EOF = errors.New("EOF")
)
```
## Version Information
`readline`'s version numbers are based on Semantic Versioning. More details can
be found in the [README.md](README.md#version-information).

201
golibs/readline/LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

165
golibs/readline/README.md Normal file
View File

@ -0,0 +1,165 @@
# Readline - Console library in Go
![Demo](../assets/readline-demo.gif)
*This demo GIF has been made with a Sliver project client.*
## Introduction
**This project is actually the merging of an original project (github.com/lmorg/readline) and one of its
forks (github.com/maxlandon/readline): both introductions are thus here given, in chronological order.**
#### lmorg
This project began a few years prior to this git commit history as an API for
_[murex](https://github.com/lmorg/murex)_, an alternative UNIX shell, because
I wasn't satisfied with the state of existing Go packages for readline (at that
time they were either bugger and/or poorly maintained, or lacked features I
desired). The state of things for readline in Go may have changed since then
however own package had also matured and grown to include many more features
that has arisen during the development of _murex_. So it seemed only fair to
give back to the community considering it was other peoples readline libraries
that allowed me rapidly prototype _murex_ during it's early stages of
development.
#### maxlandon
This project started out of the wish to make an enhanced console for a security tool (Sliver, see below).
There are already several readline libraries available in Go ([github.com/chzyer/readline](https://github.com/chzyer/readline),
and [github.com/lmorg/readline](https://github.com/lmorg/readline)), but being stricter readline implementations, their completion
## Features Summary
This project is not an integrated REPL/command-line application, which means it does not automatically understand nor executes any commands.
However, having been developed in a project using the CLI [github.com/jessevdk/go-flags](https://github.com/jessevdk/go-flags) library,
it also includes some default utilities (completers) that are made to work with this library, which I humbly but highly recommend.
Please see the [Wiki](https://github.com/maxlandon/readline/wiki) (or the `examples/` directory) for information on how to use these utilities.
A summarized list of features supported by this library is the following:
### Input & Editing
- Vim / Emacs input and editing modes.
- Optional, live-refresh Vim status.
- Vim modes (Insert, Normal, Replace, Delete) with visual prompt Vim status indicator
- line editing using `$EDITOR` (`vi` in the example - enabled by pressing `[ESC]` followed by `[v]`)
- Vim registers (one default, 10 numbered, and 26 lettered)
- Vim iterations
- Most default keybindings you might find in Emacs-like readline. Some are still missing though
### Completion engine
- 3 types of completion categories (`Grid`, `List` and `Map`)
- Stackable, combinable completions (completion groups of any type & size can be proposed simultaneously).
- Controlable completion group sizes (if size is greater than completions, the completions will roll automatically)
- Virtual insertion of the current candidate, like in Z-shell.
- In `List` completion groups, ability to have alternative candidates (used for displaying `--long` and `-s` (short) options, with descriptions)
- Completions working anywhere in the input line (your cursor can be anywhere)
- Completions are searchable with *Ctrl-F*, like in lmorg's library.
### Prompt system & Colors
- 1-line and 2-line prompts, both being customizable.
- Functions for refreshing the prompt, with optional behavior settings.
- Optional colors (can be disabled).
### Hints & Syntax highlighting
- A hint line can be printed below the input line, with any type of information. See utilities for a default one.
- The Hint system is now refreshed depending on the cursor position as well, like completions.
- A syntax highlighting system. A default one is also available.
### Command history
- Ability to have 2 different history sources (I used this for clients connected to a server, used by a single user).
- History is searchable like completions.
- Default history is an in-memory list.
- Quick history navigation with *Up*/*Down* arrow keys in Emacs mode, and *j*/*k* keys in Vim mode.
### Utilities
- Default Tab completer, Hint formatter and Syntax highlighter provided, using [github.com/jessevdk/go-flags](https://github.com/jessevdk/go-flags)
command parser to build themselves. These are in the `completers/` directory. Please look at the [Wiki page](https://github.com/maxlandon/readline/wiki)
for how to use them. Also feel free to use them as an inspiration source to make your owns.
- Colors mercilessly copied from [github.com/evilsocket/islazy/](https://github.com/evilsocket/islazy) `tui/` package.
- Also in the `completers` directory, completion functions for environment variables (using Go's std lib for getting them), and dir/file path completions.
## Installation & Usage
As usual with Go, installation:
```
go get github.com/maxlandon/readline
```
Please see either the `examples` directory, or the Wiki for detailed instructions on how to use this library.
## Documentation
The complete documentation for this library can be found in the repo's [Wiki](https://github.com/maxlandon/readline/wiki). Below is the Table of Contents:
**Getting started**
* [ Embedding readline in a project ](https://github.com/maxlandon/readline/wiki/Embedding-Readline-In-A-Project)
* [ Input Modes ](https://github.com/maxlandon/readline/wiki/Input-Modes)
**Prompt system**
* [ Setting the Prompts](https://github.com/maxlandon/readline/wiki/Prompt-Setup)
* [ Prompt Refresh ](https://github.com/maxlandon/readline/wiki/Prompt-Refresh)
**Completion Engine**
* [ Completion Groups ](https://github.com/maxlandon/readline/wiki/Completion-Groups)
* [ Completion Search ](https://github.com/maxlandon/readline/wiki/Completion-Search)
**Hint Formatter & Syntax Highlighter**
* [ Live Refresh Demonstration ](https://github.com/maxlandon/readline/wiki/Live-Refresh-Demonstration)
**Command History**
* [ Main & Alternative Sources ](https://github.com/maxlandon/readline/wiki/Main-&-Alternative-Sources)
* [ Navigation & Search ](https://github.com/maxlandon/readline/wiki/Navigation-&-Search)
#### Command & Completion utilities
* [ Interfacing with the go-flags library](https://github.com/maxlandon/readline/wiki/Interfacing-With-Go-Flags)
* [ Declaring go-flags commands](https://github.com/maxlandon/readline/wiki/Declaring-Commands)
* [ Colors/Effects Usage ](https://github.com/maxlandon/readline/wiki/Colors-&-Effects-Usage)
## Project Status & Support
Being alone working on this project and having only one lifetime (anyone able to solve this please call me), I can engage myself over the following:
- Support for any issue opened.
- Answering any questions related.
- Being available for any blame you'd like to make for my humble but passioned work. I don't mind, I need to go up.
## Version Information
* The version string will be based on Semantic Versioning. ie version numbers
will be formatted `(major).(minor).(patch)` - for example `2.0.1`
* `major` releases _will_ have breaking changes. Be sure to read CHANGES.md for
upgrade instructions
* `minor` releases will contain new APIs or introduce new user facing features
which may affect useability from an end user perspective. However `minor`
releases will not break backwards compatibility at the source code level and
nor will it break existing expected user-facing behavior. These changes will
be documented in CHANGES.md too
* `patch` releases will be bug fixes and such like. Where the code has changed
but both API endpoints and user experience will remain the same (except where
expected user experience was broken due to a bug, then that would be bumped
to either a `minor` or `major` depending on the significance of the bug and
the significance of the change to the user experience)
* Any updates to documentation, comments within code or the example code will
not result in a version bump because they will not affect the output of the
go compiler. However if this concerns you then I recommend pinning your
project to the git commit hash rather than a `patch` release
## License Information
The `readline` library is distributed under the Apache License (Version 2.0, January 2004) (http://www.apache.org/licenses/).
All the example code and documentation in `/examples`, `/completers` is public domain.
## Warmest Thanks
- The [Sliver](https://github.com/BishopFox/sliver) implant framework project, which I used as a basis to make, test and refine this library. as well as all the GIFs and documentation pictures !
- [evilsocket](https://github.com/evilsocket) for his TUI library !

237
golibs/readline/codes.go Normal file
View File

@ -0,0 +1,237 @@
package readline
import "os"
// Character codes
const (
charCtrlA = iota + 1
charCtrlB
charCtrlC
charEOF
charCtrlE
charCtrlF
charCtrlG
charBackspace // ISO 646
charTab
charCtrlJ
charCtrlK
charCtrlL
charCtrlM
charCtrlN
charCtrlO
charCtrlP
charCtrlQ
charCtrlR
charCtrlS
charCtrlT
charCtrlU
charCtrlV
charCtrlW
charCtrlX
charCtrlY
charCtrlZ
charEscape
charCtrlSlash // ^\
charCtrlCloseSquare // ^]
charCtrlHat // ^^
charCtrlUnderscore // ^_
charBackspace2 = 127 // ASCII 1963
)
// Escape sequences
var (
seqUp = string([]byte{27, 91, 65})
seqDown = string([]byte{27, 91, 66})
seqForwards = string([]byte{27, 91, 67})
seqBackwards = string([]byte{27, 91, 68})
seqHome = string([]byte{27, 91, 72})
seqHomeSc = string([]byte{27, 91, 49, 126})
seqEnd = string([]byte{27, 91, 70})
seqEndSc = string([]byte{27, 91, 52, 126})
seqDelete = string([]byte{27, 91, 51, 126})
seqDelete2 = string([]byte{27, 91, 80})
seqCtrlDelete = string([]byte{27, 91, 51, 59, 53, 126})
seqCtrlDelete2 = string([]byte{27, 91, 77})
seqAltDelete = string([]byte{27, 91, 51, 59, 51, 126})
seqShiftTab = string([]byte{27, 91, 90})
seqAltQuote = string([]byte{27, 34}) // Added for showing registers ^["
seqAltB = string([]byte{27, 98})
seqAltD = string([]byte{27, 100})
seqAltF = string([]byte{27, 102})
seqAltR = string([]byte{27, 114}) // Used for alternative history
seqAltBackspace = string([]byte{27, 127})
seqPageUp = string([]byte{27, 91, 53, 126})
seqPageDown = string([]byte{27, 91, 54, 126})
)
const (
seqPosSave = "\x1b[s"
seqPosRestore = "\x1b[u"
seqClearLineAfer = "\x1b[0K"
seqClearLineBefore = "\x1b[1K"
seqClearLine = "\x1b[2K"
seqClearScreenBelow = "\x1b[0J"
seqClearScreen = "\x1b[2J" // Clears screen fully
seqCursorTopLeft = "\x1b[H" // Clears screen and places cursor on top-left
seqGetCursorPos = "\x1b6n" // response: "\x1b{Line};{Column}R"
seqHideCursor = "\x1b[?25l"
seqUnhideCursor = "\x1b[?25h"
seqCtrlLeftArrow = "\x1b[1;5D"
seqCtrlRightArrow = "\x1b[1;5C"
// seqAltQuote = "\x1b\"" // trigger registers list
)
// Text effects
const (
seqReset = "\x1b[0m"
seqBold = "\x1b[1m"
seqUnderscore = "\x1b[4m"
seqBlink = "\x1b[5m"
seqInvert = "\x1b[7m"
)
// Text colours
const (
seqFgBlack = "\x1b[30m"
seqFgRed = "\x1b[31m"
seqFgGreen = "\x1b[32m"
seqFgYellow = "\x1b[33m"
seqFgBlue = "\x1b[34m"
seqFgMagenta = "\x1b[35m"
seqFgCyan = "\x1b[36m"
seqFgWhite = "\x1b[37m"
seqFgBlackBright = "\x1b[1;30m"
seqFgRedBright = "\x1b[1;31m"
seqFgGreenBright = "\x1b[1;32m"
seqFgYellowBright = "\x1b[1;33m"
seqFgBlueBright = "\x1b[1;34m"
seqFgMagentaBright = "\x1b[1;35m"
seqFgCyanBright = "\x1b[1;36m"
seqFgWhiteBright = "\x1b[1;37m"
)
// Background colours
const (
seqBgBlack = "\x1b[40m"
seqBgRed = "\x1b[41m"
seqBgGreen = "\x1b[42m"
seqBgYellow = "\x1b[43m"
seqBgBlue = "\x1b[44m"
seqBgMagenta = "\x1b[45m"
seqBgCyan = "\x1b[46m"
seqBgWhite = "\x1b[47m"
seqBgBlackBright = "\x1b[1;40m"
seqBgRedBright = "\x1b[1;41m"
seqBgGreenBright = "\x1b[1;42m"
seqBgYellowBright = "\x1b[1;43m"
seqBgBlueBright = "\x1b[1;44m"
seqBgMagentaBright = "\x1b[1;45m"
seqBgCyanBright = "\x1b[1;46m"
seqBgWhiteBright = "\x1b[1;47m"
)
// Xterm 256 colors
const (
seqCtermFg255 = "\033[48;5;255m"
)
// TODO: return whether its actually a sequence or not
// remedies the edge case of someone literally typing Ctrl-A for example.
func (rl *Readline) ReadChar() string {
b := make([]byte, 1024)
i, _ := os.Stdin.Read(b)
r := []rune(string(b))
s := string(r[:i])
switch b[0] {
case charCtrlA:
return "Ctrl-A"
case charCtrlB:
return "Ctrl-B"
case charCtrlC:
return "Ctrl-C"
case charEOF:
return "Ctrl-D"
case charCtrlE:
return "Ctrl-E"
case charCtrlF:
return "Ctrl-F"
case charCtrlG:
return "Ctrl-G"
case charBackspace, charBackspace2:
return "Backspace"
case charTab:
return "Tab"
case charCtrlK:
return "Ctrl-K"
case charCtrlL:
return "Ctrl-L"
case charCtrlN:
return "Ctrl-N"
case charCtrlO:
return "Ctrl-O"
case charCtrlP:
return "Ctrl-P"
case charCtrlQ:
return "Ctrl-Q"
case charCtrlR:
return "Ctrl-R"
case charCtrlS:
return "Ctrl-S"
case charCtrlT:
return "Ctrl-T"
case charCtrlU:
return "Ctrl-U"
case charCtrlV:
return "Ctrl-V"
case charCtrlW:
return "Ctrl-W"
case charCtrlX:
return "Ctrl-X"
case charCtrlY:
return "Ctrl-Y"
case charCtrlZ:
return "Ctrl-Z"
case '\r':
fallthrough
case '\n':
return "Enter"
case charEscape:
switch s {
case string(charEscape):
return "Escape"
case seqUp:
return "Up"
case seqDown:
return "Down"
case seqBackwards:
return "Left"
case seqForwards:
return "Right"
case seqCtrlLeftArrow:
return "Ctrl-Left"
case seqCtrlRightArrow:
return "Ctrl-Right"
case seqCtrlDelete, seqCtrlDelete2:
return "Ctrl-Delete"
case seqHome, seqHomeSc:
return "Home"
case seqEnd, seqEndSc:
return "End"
case seqDelete, seqDelete2:
return "Delete"
case seqPageUp:
return "Page-Up"
case seqPageDown:
return "Page-Down"
}
}
return s
}

View File

@ -0,0 +1,154 @@
package readline
import (
"fmt"
"strconv"
"strings"
"github.com/rivo/uniseg"
)
// initGrid - Grid display details. Called each time we want to be sure to have
// a working completion group either immediately, or later on. Generally defered.
func (g *CompletionGroup) initGrid(rl *Readline) {
// Compute size of each completion item box
tcMaxLength := 1
for i := range g.Suggestions {
if uniseg.GraphemeClusterCount(g.Suggestions[i]) > tcMaxLength {
tcMaxLength = uniseg.GraphemeClusterCount(g.Suggestions[i])
}
}
g.tcPosX = 0
g.tcPosY = 1
g.tcOffset = 0
// Max number of columns
g.tcMaxX = GetTermWidth() / (tcMaxLength + 2)
if g.tcMaxX < 1 {
g.tcMaxX = 1 // avoid a divide by zero error
}
// Maximum number of lines
maxY := len(g.Suggestions) / g.tcMaxX
rest := len(g.Suggestions) % g.tcMaxX
if rest != 0 {
// if rest != 0 && maxY != 1 {
maxY++
}
if maxY > g.MaxLength {
g.tcMaxY = g.MaxLength
} else {
g.tcMaxY = maxY
}
}
// moveTabGridHighlight - Moves the highlighting for currently selected completion item (grid display)
func (g *CompletionGroup) moveTabGridHighlight(rl *Readline, x, y int) (done bool, next bool) {
g.tcPosX += x
g.tcPosY += y
// Columns
if g.tcPosX < 1 {
if g.tcPosY == 1 && rl.tabCompletionReverse {
g.tcPosX = 1
g.tcPosY = 0
} else {
// This is when multiple ligns, not yet on first one.
g.tcPosX = g.tcMaxX
g.tcPosY--
}
}
if g.tcPosY > g.tcMaxY {
g.tcPosY = 1
return true, true
}
// If we must move to next line in same group
if g.tcPosX > g.tcMaxX {
g.tcPosX = 1
g.tcPosY++
}
// Real max number of suggestions.
max := g.tcMaxX * g.tcMaxY
if max > len(g.Suggestions) {
max = len(g.Suggestions)
}
// We arrived at the end of suggestions. This condition can never be triggered
// while going in the reverse order, only forward, so no further checks in it.
if (g.tcMaxX*(g.tcPosY-1))+g.tcPosX > max {
return true, true
}
// In case we are reverse cycling and currently selecting the first item,
// we adjust the coordinates to point to the last item and return
// We set g.tcPosY because the printer needs to get the a candidate nonetheless.
if rl.tabCompletionReverse && g.tcPosX == 1 && g.tcPosY == 0 {
g.tcPosY = 1
return true, false
}
// By default, come back to this group for next item.
return false, false
}
// writeGrid - A grid completion string
func (g *CompletionGroup) writeGrid(rl *Readline) (comp string) {
// If group title, print it and adjust offset.
if g.Name != "" {
comp += fmt.Sprintf("%s%s%s %s\n", BOLD, YELLOW, fmtEscape(g.Name), RESET)
rl.tcUsedY++
}
cellWidth := strconv.Itoa((GetTermWidth() / g.tcMaxX) - 4)
x := 0
y := 1
for i := range g.Suggestions {
x++
if x > g.tcMaxX {
x = 1
y++
if y > g.tcMaxY {
y--
break
} else {
comp += "\r\n"
}
}
if (x == g.tcPosX && y == g.tcPosY) && (g.isCurrent) {
comp += seqInvert
}
sugg := g.Suggestions[i]
if len(sugg) > GetTermWidth() {
sugg = sugg[:GetTermWidth()-4] + "..."
}
formatStr := "%-" + cellWidth + "s%s "
if g.tcMaxX == 1 {
formatStr = "%s%s"
}
comp += fmt.Sprintf(formatStr, fmtEscape(sugg), seqReset)
}
// Always add a newline to the group if the end if not punctuated with one
if !strings.HasSuffix(comp, "\n") {
comp += "\n"
}
// Add the equivalent of this group's size to final screen clearing.
// This is either the max allowed print size for this group, or its actual size if inferior.
if g.MaxLength < y {
rl.tcUsedY += g.MaxLength
} else {
rl.tcUsedY += y
}
return
}

View File

@ -0,0 +1,293 @@
package readline
import "strings"
// CompletionGroup - A group/category of items offered to completion, with its own
// name, descriptions and completion display format/type.
// The output, if there are multiple groups available for a given completion input,
// will look like ZSH's completion system.
type CompletionGroup struct {
Name string // If not nil, printed on top of the group's completions
Description string
// Candidates & related
Suggestions []string
Aliases map[string]string // A candidate has an alternative name (ex: --long, -l option flags)
Descriptions map[string]string // Items descriptions
ItemDisplays map[string]string // What to display the item as (can be used for styling items)
DisplayType TabDisplayType // Map, list or normal
MaxLength int // Each group can be limited in the number of comps offered
// When this is true, the completion is inserted really (not virtually) without
// the trailing slash, if any. This is used when we want to complete paths.
TrimSlash bool
// PathSeparator - If you intend to write path completions, you can specify the path separator to use, depending on which OS you want completion for. By default, this will be set to the GOOS of the binary. This is also used internally for many things.
PathSeparator rune
// When this is true, we don't add a space after entering the candidate.
// Can be used for multi-stage completions, like URLS (scheme:// + host)
NoSpace bool
// For each group, we can define the min and max tab item length
MinTabItemLength int
MaxTabItemLength int
// Values used by the shell
tcPosX int
tcPosY int
tcMaxX int
tcMaxY int
tcOffset int
tcMaxLength int // Used when display is map/list, for determining message width
tcMaxLengthAlt int // Same as tcMaxLength but for SuggestionsAlt.
// true if we want to cycle through suggestions because they overflow MaxLength
allowCycle bool
// This is to say we are currently cycling through this group, for highlighting choice
isCurrent bool
}
// init - The completion group computes and sets all its values, and is then ready to work.
func (g *CompletionGroup) init(rl *Readline) {
// Details common to all displays
g.checkCycle(rl) // Based on the number of groups given to the shell, allows cycling or not
g.checkMaxLength(rl)
// Details specific to tab display modes
switch g.DisplayType {
case TabDisplayGrid:
g.initGrid(rl)
case TabDisplayMap:
g.initMap(rl)
case TabDisplayList:
g.initList(rl)
}
}
// updateTabFind - When searching through all completion groups (whether it be command history or not),
// we ask each of them to filter its own items and return the results to the shell for aggregating them.
// The rx parameter is passed, as the shell already checked that the search pattern is valid.
func (g *CompletionGroup) updateTabFind(rl *Readline) {
suggs := rl.Searcher(rl.search, g.Suggestions)
// We perform filter right here, so we create a new completion group, and populate it with our results.
/*for i := range g.Suggestions {
if rl.regexSearch == nil { continue }
if rl.regexSearch.MatchString(g.Suggestions[i]) {
suggs = append(suggs, g.Suggestions[i])
} else if g.DisplayType == TabDisplayList && rl.regexSearch.MatchString(g.Descriptions[g.Suggestions[i]]) {
// this is a list so lets also check the descriptions
suggs = append(suggs, g.Suggestions[i])
}
}*/
// We overwrite the group's items, (will be refreshed as soon as something is typed in the search)
g.Suggestions = suggs
// Finally, the group computes its new printing settings
g.init(rl)
// If we are in history completion, we directly pass to the first candidate
if rl.modeAutoFind && rl.searchMode == HistoryFind && len(g.Suggestions) > 0 {
g.tcPosY = 1
}
}
// checkCycle - Based on the number of groups given to the shell, allows cycling or not
func (g *CompletionGroup) checkCycle(rl *Readline) {
if len(rl.tcGroups) == 1 {
g.allowCycle = true
}
if len(rl.tcGroups) >= 10 {
g.allowCycle = false
}
}
// checkMaxLength - Based on the number of groups given to the shell, check/set MaxLength defaults
func (g *CompletionGroup) checkMaxLength(rl *Readline) {
// This means the user forgot to set it
if g.MaxLength == 0 {
if len(rl.tcGroups) < 5 {
g.MaxLength = 20
}
if len(rl.tcGroups) >= 5 {
g.MaxLength = 20
}
// Lists that have a alternative completions are not allowed to have
// MaxLength set, because rolling does not work yet.
if g.DisplayType == TabDisplayList {
g.MaxLength = 1000 // Should be enough not to trigger anything related.
}
}
}
// checkNilItems - For each completion group we avoid nil maps and possibly other items
func checkNilItems(groups []*CompletionGroup) (checked []*CompletionGroup) {
for _, grp := range groups {
if grp.Descriptions == nil || len(grp.Descriptions) == 0 {
grp.Descriptions = make(map[string]string)
}
if grp.Aliases == nil || len(grp.Aliases) == 0 {
grp.Aliases = make(map[string]string)
}
checked = append(checked, grp)
}
return
}
// writeCompletion - This function produces a formatted string containing all appropriate items
// and according to display settings. This string is then appended to the main completion string.
func (g *CompletionGroup) writeCompletion(rl *Readline) (comp string) {
// Avoids empty groups in suggestions
if len(g.Suggestions) == 0 {
return
}
// Depending on display type we produce the approriate string
switch g.DisplayType {
case TabDisplayGrid:
comp += g.writeGrid(rl)
case TabDisplayMap:
comp += g.writeMap(rl)
case TabDisplayList:
comp += g.writeList(rl)
}
return
}
// getCurrentCell - The completion groups computes the current cell value,
// depending on its display type and its different parameters
func (g *CompletionGroup) getCurrentCell(rl *Readline) string {
switch g.DisplayType {
case TabDisplayGrid:
// x & y coodinates + safety check
cell := (g.tcMaxX * (g.tcPosY - 1)) + g.tcOffset + g.tcPosX - 1
if cell < 0 {
cell = 0
}
if cell < len(g.Suggestions) {
return g.Suggestions[cell]
}
return ""
case TabDisplayMap:
// x & y coodinates + safety check
cell := g.tcOffset + g.tcPosY - 1
if cell < 0 {
cell = 0
}
sugg := g.Suggestions[cell]
return sugg
case TabDisplayList:
// x & y coodinates + safety check
cell := g.tcOffset + g.tcPosY - 1
if cell < 0 {
cell = 0
}
sugg := g.Suggestions[cell]
// If we are in the alt suggestions column, check key and return
if g.tcPosX == 1 {
if alt, ok := g.Aliases[sugg]; ok {
return alt
}
return sugg
}
return sugg
}
// We should never get here
return ""
}
func (g *CompletionGroup) goFirstCell() {
switch g.DisplayType {
case TabDisplayGrid:
g.tcPosX = 1
g.tcPosY = 1
case TabDisplayList:
g.tcPosX = 0
g.tcPosY = 1
g.tcOffset = 0
case TabDisplayMap:
g.tcPosX = 0
g.tcPosY = 1
g.tcOffset = 0
}
}
func (g *CompletionGroup) goLastCell() {
switch g.DisplayType {
case TabDisplayGrid:
g.tcPosY = g.tcMaxY
restX := len(g.Suggestions) % g.tcMaxX
if restX != 0 {
g.tcPosX = restX
} else {
g.tcPosX = g.tcMaxX
}
// We need to adjust the X position depending
// on the interpretation of the remainder with
// respect to the group's MaxLength.
restY := len(g.Suggestions) % g.tcMaxY
maxY := len(g.Suggestions) / g.tcMaxX
if restY == 0 && maxY > g.MaxLength {
g.tcPosX = g.tcMaxX
}
if restY != 0 && maxY > g.MaxLength-1 {
g.tcPosX = g.tcMaxX
}
case TabDisplayList:
// By default, the last item is at maxY
g.tcPosY = g.tcMaxY
// If the max length is smaller than the number
// of suggestions, we need to adjust the offset.
if len(g.Suggestions) > g.MaxLength {
g.tcOffset = len(g.Suggestions) - g.tcMaxY
}
// We do not take into account the alternative suggestions
g.tcPosX = 0
case TabDisplayMap:
// By default, the last item is at maxY
g.tcPosY = g.tcMaxY
// If the max length is smaller than the number
// of suggestions, we need to adjust the offset.
if len(g.Suggestions) > g.MaxLength {
g.tcOffset = len(g.Suggestions) - g.tcMaxY
}
// We do not take into account the alternative suggestions
g.tcPosX = 0
}
}
func fmtEscape(s string) string {
return strings.Replace(s, "%", "%%", -1)
}

View File

@ -0,0 +1,264 @@
package readline
import (
"fmt"
"strconv"
"strings"
)
// initList - List display details. Because of the way alternative completions
// are handled, MaxLength cannot be set when there are alternative completions.
func (g *CompletionGroup) initList(rl *Readline) {
// We may only ever have two different
// columns: (suggestions, and alternatives)
g.tcMaxX = 2
// We make the list anyway, especially if we need to use it later
if g.Descriptions == nil {
g.Descriptions = make(map[string]string)
}
if g.Aliases == nil {
g.Aliases = make(map[string]string)
}
// Compute size of each completion item box. Group independent
g.tcMaxLength = rl.getListPad()
// Same for suggestions alt
g.tcMaxLengthAlt = 0
for i := range g.Suggestions {
if len(g.Suggestions[i]) > g.tcMaxLength {
g.tcMaxLength = len([]rune(g.Suggestions[i]))
}
}
// Max values depend on if we have alternative suggestions
if len(g.Aliases) == 0 {
g.tcMaxX = 1
} else {
g.tcMaxX = 2
}
if len(g.Suggestions) > g.MaxLength {
g.tcMaxY = g.MaxLength
} else {
g.tcMaxY = len(g.Suggestions)
}
g.tcPosX = 0
g.tcPosY = 0
g.tcOffset = 0
}
// moveTabListHighlight - Moves the highlighting for currently selected completion item (list display)
// We don't care about the x, because only can have 2 columns of selectable choices (--long and -s)
func (g *CompletionGroup) moveTabListHighlight(rl *Readline, x, y int) (done bool, next bool) {
// We dont' pass to x, because not managed by callers
g.tcPosY += x
g.tcPosY += y
// Lines
if g.tcPosY < 1 {
if rl.tabCompletionReverse {
if g.tcOffset > 0 {
g.tcPosY = 1
g.tcOffset--
} else {
return true, false
}
}
}
if g.tcPosY > g.tcMaxY {
g.tcPosY--
g.tcOffset++
}
// Once we get to the end of choices: check which column we were selecting.
if g.tcOffset+g.tcPosY > len(g.Suggestions) {
// If we have alternative options and that we are not yet
// completing them, start on top of their column
if g.tcPosX == 0 && len(g.Aliases) > 0 {
g.tcPosX++
g.tcPosY = 1
g.tcOffset = 0
return false, false
}
// Else no alternatives, return for next group.
// Reset all values, in case we pass on them again.
g.tcPosX = 0 // First column
g.tcPosY = 1 // first row
g.tcOffset = 0
return true, true
}
// Here we must check, in x == 1, that the current choice
// is not empty. Handle for both reverse and forward movements.
sugg := g.Suggestions[g.tcPosY-1]
_, ok := g.Aliases[sugg]
if !ok && g.tcPosX == 1 {
if rl.tabCompletionReverse {
for i := len(g.Suggestions[:g.tcPosY-1]); i > 0; i-- {
su := g.Suggestions[i]
if _, ok := g.Aliases[su]; ok {
g.tcPosY -= (len(g.Suggestions[:g.tcPosY-1])) - i
return false, false
}
}
g.tcPosX = 0
g.tcPosY = g.tcMaxY
} else {
for i, su := range g.Suggestions[g.tcPosY-1:] {
if _, ok := g.Aliases[su]; ok {
g.tcPosY += i
return false, false
}
}
}
}
// Setup offset if needs to be.
// TODO: should be rewrited to conditionally process rolling menus with alternatives
if g.tcOffset+g.tcPosY < 1 && len(g.Suggestions) > 0 {
g.tcPosY = g.tcMaxY
g.tcOffset = len(g.Suggestions) - g.tcMaxY
}
if g.tcOffset < 0 {
g.tcOffset = 0
}
// MIGHT BE NEEDED IF PROBLEMS WIHT ROLLING COMPLETIONS
// ------------------------------------------------------------------------------
// Once we get to the end of choices: check which column we were selecting.
// We use +1 because we may have a single suggestion, and we just want "a ratio"
// if g.tcOffset+g.tcPosY > len(g.Suggestions) {
//
// // If we have alternative options and that we are not yet
// // completing them, start on top of their column
// if g.tcPosX == 1 && len(g.SuggestionsAlt) > 0 {
// g.tcPosX++
// g.tcPosY = 1
// g.tcOffset = 0
// return false
// }
//
// // Else no alternatives, return for next group.
// g.tcPosY = 1
// return true
// }
return false, false
}
// writeList - A list completion string
func (g *CompletionGroup) writeList(rl *Readline) (comp string) {
// Print group title and adjust offset if there is one.
if g.Name != "" {
comp += fmt.Sprintf("%s%s%s %s\n", BOLD, YELLOW, g.Name, RESET)
rl.tcUsedY++
}
termWidth := GetTermWidth()
if termWidth < 20 {
// terminal too small. Probably better we do nothing instead of crash
// We are more conservative than lmorg, and push it to 20 instead of 10
return
}
// Suggestion cells dimensions
maxLength := g.tcMaxLength
if maxLength > termWidth-9 {
maxLength = termWidth - 9
}
cellWidth := strconv.Itoa(maxLength)
// Alternative suggestion cells dimensions
maxLengthAlt := g.tcMaxLengthAlt + 2
if maxLengthAlt > termWidth-9 {
maxLengthAlt = termWidth - 9
}
cellWidthAlt := strconv.Itoa(maxLengthAlt)
// Descriptions cells dimensions
maxDescWidth := termWidth - maxLength - maxLengthAlt - 4
// function highlights the cell depending on current selector place.
highlight := func(y int, x int) string {
if y == g.tcPosY && x == g.tcPosX && g.isCurrent {
return seqInvert
}
return ""
}
// For each line in completions
y := 0
for i := g.tcOffset; i < len(g.Suggestions); i++ {
y++ // Consider next item
if y > g.tcMaxY {
break
}
// Main suggestion
item := g.Suggestions[i]
if len(item) > maxLength {
item = item[:maxLength-3] + "..."
}
sugg := fmt.Sprintf("\r%s%-"+cellWidth+"s", highlight(y, 0), fmtEscape(item))
// Alt suggestion
alt, ok := g.Aliases[item]
if ok {
alt = fmt.Sprintf(" %s%"+cellWidthAlt+"s", highlight(y, 1), fmtEscape(alt))
} else {
// Else, make an empty cell
alt = strings.Repeat(" ", maxLengthAlt+1) // + 2 to keep account of spaces
}
styledSugg, ok := g.ItemDisplays[item]
if ok {
sugg = fmt.Sprintf("\r%s%-"+cellWidth+"s", highlight(y, 0), fmtEscape(styledSugg))
}
// Description
description := g.Descriptions[g.Suggestions[i]]
if len(description) > maxDescWidth {
description = description[:maxDescWidth-3] + "..." + RESET + "\n"
} else {
description += "\n"
}
// Total completion line
comp += sugg + seqReset + alt + " " + seqReset + description
}
// Add the equivalent of this group's size to final screen clearing
// Can be set and used only if no alterative completions have been given.
if len(g.Aliases) == 0 {
if len(g.Suggestions) > g.MaxLength {
rl.tcUsedY += g.MaxLength
} else {
rl.tcUsedY += len(g.Suggestions)
}
} else {
rl.tcUsedY += len(g.Suggestions)
}
return
}
func (rl *Readline) getListPad() (pad int) {
for _, group := range rl.tcGroups {
if group.DisplayType == TabDisplayList {
for i := range group.Suggestions {
if len(group.Suggestions[i]) > pad {
pad = len([]rune(group.Suggestions[i]))
}
}
}
}
return
}

140
golibs/readline/comp-map.go Normal file
View File

@ -0,0 +1,140 @@
package readline
import (
"fmt"
"strconv"
)
// initMap - Map display details. Called each time we want to be sure to have
// a working completion group either immediately, or later on. Generally defered.
func (g *CompletionGroup) initMap(rl *Readline) {
// We make the map anyway, especially if we need to use it later
if g.Descriptions == nil {
g.Descriptions = make(map[string]string)
}
// Compute size of each completion item box. Group independent
g.tcMaxLength = 1
for i := range g.Suggestions {
if len(g.Descriptions[g.Suggestions[i]]) > g.tcMaxLength {
g.tcMaxLength = len(g.Descriptions[g.Suggestions[i]])
}
}
g.tcPosX = 0
g.tcPosY = 0
g.tcOffset = 0
// Number of lines allowed to be printed for group
if len(g.Suggestions) > g.MaxLength {
g.tcMaxY = g.MaxLength
} else {
g.tcMaxY = len(g.Suggestions)
}
}
// moveTabMapHighlight - Moves the highlighting for currently selected completion item (map display)
func (g *CompletionGroup) moveTabMapHighlight(rl *Readline, x, y int) (done bool, next bool) {
g.tcPosY += x
g.tcPosY += y
// Lines
if g.tcPosY < 1 {
if rl.tabCompletionReverse {
if g.tcOffset > 0 {
g.tcPosY = 1
g.tcOffset--
} else {
return true, false
}
}
}
if g.tcPosY > g.tcMaxY {
g.tcPosY--
g.tcOffset++
}
if g.tcOffset+g.tcPosY < 1 && len(g.Suggestions) > 0 {
g.tcPosY = g.tcMaxY
g.tcOffset = len(g.Suggestions) - g.tcMaxY
}
if g.tcOffset < 0 {
g.tcOffset = 0
}
if g.tcOffset+g.tcPosY > len(g.Suggestions) {
g.tcOffset--
return true, true
}
return false, false
}
// writeMap - A map or list completion string
func (g *CompletionGroup) writeMap(rl *Readline) (comp string) {
if g.Name != "" {
// Print group title (changes with line returns depending on type)
comp += fmt.Sprintf("%s%s%s %s\n", BOLD, YELLOW, fmtEscape(g.Name), RESET)
rl.tcUsedY++
}
termWidth := GetTermWidth()
if termWidth < 20 {
// terminal too small. Probably better we do nothing instead of crash
// We are more conservative than lmorg, and push it to 20 instead of 10
return
}
// Set all necessary dimensions
maxLength := g.tcMaxLength
if maxLength > termWidth-9 {
maxLength = termWidth - 9
}
maxDescWidth := termWidth - maxLength - 4
cellWidth := strconv.Itoa(maxLength)
itemWidth := strconv.Itoa(maxDescWidth)
y := 0
// Highlighting function
highlight := func(y int) string {
if y == g.tcPosY && g.isCurrent {
return seqInvert
}
return ""
}
// String formating
var item, description string
for i := g.tcOffset; i < len(g.Suggestions); i++ {
y++ // Consider new item
if y > g.tcMaxY {
break
}
item = g.Suggestions[i]
if len(item) > maxDescWidth {
item = item[:maxDescWidth-3] + "..."
}
description = g.Descriptions[g.Suggestions[i]]
if len(description) > maxLength {
description = description[:maxLength-3] + "..."
}
comp += fmt.Sprintf("\r%-"+cellWidth+"s %s %-"+itemWidth+"s %s\n",
description, highlight(y), fmtEscape(item), seqReset)
}
// Add the equivalent of this group's size to final screen clearing
if len(g.Suggestions) > g.MaxLength {
rl.tcUsedY += g.MaxLength
} else {
rl.tcUsedY += len(g.Suggestions)
}
return
}

180
golibs/readline/cursor.go Normal file
View File

@ -0,0 +1,180 @@
package readline
import (
// "fmt"
"os"
"regexp"
"strconv"
)
// Lmorg code
// -------------------------------------------------------------------------------
func leftMost() []byte {
fd := int(os.Stdout.Fd())
w, _, err := GetSize(fd)
if err != nil {
return []byte{'\r', '\n'}
}
b := make([]byte, w+1)
for i := 0; i < w; i++ {
b[i] = ' '
}
b[w] = '\r'
return b
}
var rxRcvCursorPos = regexp.MustCompile("^\x1b([0-9]+);([0-9]+)R$")
func (rl *Readline) getCursorPos() (x int, y int) {
if !rl.EnableGetCursorPos {
return -1, -1
}
disable := func() (int, int) {
os.Stderr.WriteString("\r\ngetCursorPos() not supported by terminal emulator, disabling....\r\n")
rl.EnableGetCursorPos = false
return -1, -1
}
print(seqGetCursorPos)
b := make([]byte, 64)
i, err := os.Stdin.Read(b)
if err != nil {
return disable()
}
if !rxRcvCursorPos.Match(b[:i]) {
return disable()
}
match := rxRcvCursorPos.FindAllStringSubmatch(string(b[:i]), 1)
y, err = strconv.Atoi(match[0][1])
if err != nil {
return disable()
}
x, err = strconv.Atoi(match[0][2])
if err != nil {
return disable()
}
return x, y
}
// DISPLAY ------------------------------------------------------------
// All cursorMoveFunctions move the cursor as it is seen by the user.
// This means that they are not used to keep any reference point when
// when we internally move around clearning and printing things
/*
func moveCursorUpBuffered(i int) {
if i < 1 {
return
}
fmt.Fprintf(rl.bufferedOut, "\x1b[%dA", i)
}
func moveCursorDownBuffered(i int) {
if i < 1 {
return
}
fmt.Fprintf(rl.bufferedOut, "\x1b[%dB", i)
}
func moveCursorForwardsBuffered(i int) {
if i < 1 {
return
}
fmt.Fprintf(rl.bufferedOut, "\x1b[%dC", i)
}
func moveCursorUpBuffered(i int) {
if i < 1 {
return
}
fmt.Fprintf(rl.bufferedOut, "\x1b[%dD", i)
}
*/
func moveCursorUp(i int) {
if i < 1 {
return
}
printf("\x1b[%dA", i)
}
func moveCursorDown(i int) {
if i < 1 {
return
}
printf("\x1b[%dB", i)
}
func moveCursorForwards(i int) {
if i < 1 {
return
}
printf("\x1b[%dC", i)
}
func moveCursorBackwards(i int) {
if i < 1 {
return
}
printf("\x1b[%dD", i)
}
func hideCursor() {
print(seqHideCursor)
}
func unhideCursor() {
print(seqUnhideCursor)
}
func (rl *Readline) backspace(forward bool) {
if len(rl.line) == 0 || rl.pos == 0 {
return
}
rl.deleteBackspace(forward)
}
func (rl *Readline) moveCursorByAdjust(adjust int) {
switch {
case adjust > 0:
rl.pos += adjust
case adjust < 0:
rl.pos += adjust
}
// The position can never be negative
if rl.pos < 0 {
rl.pos = 0
}
// The cursor can never be longer than the line
if rl.pos > len(rl.line) {
rl.pos = len(rl.line)
}
// If we are at the end of line, and not in Insert mode, move back one.
if rl.modeViMode != VimInsert && (rl.pos == len(rl.line)) && len(rl.line) > 0 {
if rl.modeViMode != VimInsert {
rl.pos--
} else if rl.modeViMode == VimInsert && rl.searchMode == HistoryFind && rl.modeAutoFind {
rl.pos--
}
}
}

79
golibs/readline/editor.go Normal file
View File

@ -0,0 +1,79 @@
//go:build !windows
// +build !windows
package readline
import (
"crypto/md5"
"encoding/hex"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"time"
)
// writeTempFile - This function optionally accepts a filename (generally specified with an extension).
func (rl *Readline) writeTempFile(content []byte, filename string) (string, error) {
// The final path to the buffer on disk
var path string
// If the user has not provided any filename (including an extension)
// we generate a random filename with no extension.
if filename == "" {
fileID := strconv.Itoa(time.Now().Nanosecond()) + ":" + string(rl.line)
h := md5.New()
_, err := h.Write([]byte(fileID))
if err != nil {
return "", err
}
name := "readline-" + hex.EncodeToString(h.Sum(nil)) + "-" + strconv.Itoa(os.Getpid())
path = filepath.Join(rl.TempDirectory, name)
} else {
// Else, still use the temp/ dir, but with the provided filename
path = filepath.Join(rl.TempDirectory, filename)
}
file, err := os.Create(path)
if err != nil {
return "", err
}
defer file.Close()
_, err = file.Write(content)
return path, err
}
func readTempFile(name string) ([]byte, error) {
file, err := os.Open(name)
if err != nil {
return nil, err
}
b, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
if len(b) > 0 && b[len(b)-1] == '\n' {
b = b[:len(b)-1]
}
if len(b) > 0 && b[len(b)-1] == '\r' {
b = b[:len(b)-1]
}
if len(b) > 0 && b[len(b)-1] == '\n' {
b = b[:len(b)-1]
}
if len(b) > 0 && b[len(b)-1] == '\r' {
b = b[:len(b)-1]
}
err = os.Remove(name)
return b, err
}

View File

@ -0,0 +1,10 @@
//go:build plan9
// +build plan9
package readline
import "errors"
func (rl *Readline) launchEditor(multiline []rune) ([]rune, error) {
return rl.line, errors.New("Not currently supported on Plan 9")
}

View File

@ -0,0 +1,46 @@
//go:build !windows && !plan9
package readline
import (
"os"
"os/exec"
)
const defaultEditor = "vi"
// StartEditorWithBuffer - Enables a consumer of this console application to
// open an arbitrary buffer into the system editor. Currently only implemnted
// on *Nix systems. The modified buffer is returned when the editor quits, and
// depending on the actions taken by the user within it (eg: x or q! in Vim)
// The filename parameter can be used to pass a specific filename.ext pattern,
// which might be useful if the editor has builtin filetype plugin functionality.
func (rl *Readline) StartEditorWithBuffer(multiline []rune, filename string) ([]rune, error) {
name, err := rl.writeTempFile([]byte(string(multiline)), filename)
if err != nil {
return multiline, err
}
editor := os.Getenv("EDITOR")
// default editor if $EDITOR not set
if editor == "" {
editor = defaultEditor
}
cmd := exec.Command(editor, name)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
return multiline, err
}
if err := cmd.Wait(); err != nil {
return multiline, err
}
b, err := readTempFile(name)
return []rune(string(b)), err
}

View File

@ -0,0 +1,10 @@
//go:build windows
package readline
import "errors"
// StartEditorWithBuffer - Not implemented on Windows platforms.
func (rl *Readline) StartEditorWithBuffer(multiline []rune, filename string) ([]rune, error) {
return rl.line, errors.New("Not currently supported on Windows")
}

24
golibs/readline/errors.go Normal file
View File

@ -0,0 +1,24 @@
package readline
import (
"errors"
)
const (
// ErrCtrlC is returned when ctrl+c is pressed.
// WARNING: this is being deprecated! Please use CtrlC (type error) instead
ErrCtrlC = "Ctrl+C"
// ErrEOF is returned when ctrl+d is pressed.
// WARNING: this is being deprecated! Please use EOF (type error) instead
ErrEOF = "EOF"
)
var (
// CtrlC is returned when ctrl+c is pressed
CtrlC = errors.New("Ctrl+C")
// EOF is returned when ctrl+d is pressed.
// (this is actually the same value as io.EOF)
EOF = errors.New("EOF")
)

23
golibs/readline/events.go Normal file
View File

@ -0,0 +1,23 @@
package readline
// EventReturn is a structure returned by the callback event function.
// This is used by readline to determine what state the API should
// return to after the readline event.
type EventReturn struct {
ForwardKey bool
ClearHelpers bool
CloseReadline bool
InfoText []rune
NewLine []rune
NewPos int
}
// AddEvent registers a new keypress handler
func (rl *Readline) AddEvent(keyPress string, callback func(string, []rune, int) *EventReturn) {
rl.evtKeyPress[keyPress] = callback
}
// DelEvent deregisters an existing keypress handler
func (rl *Readline) DelEvent(keyPress string) {
delete(rl.evtKeyPress, keyPress)
}

12
golibs/readline/go.mod Normal file
View File

@ -0,0 +1,12 @@
module github.com/maxlandon/readline
go 1.18
require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/evilsocket/islazy v1.10.6
github.com/jessevdk/go-flags v1.5.0
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0
github.com/rivo/uniseg v0.2.0
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4
)

12
golibs/readline/go.sum Normal file
View File

@ -0,0 +1,12 @@
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/evilsocket/islazy v1.10.6 h1:MFq000a1ByoumoJWlytqg0qon0KlBeUfPsDjY0hK0bo=
github.com/evilsocket/islazy v1.10.6/go.mod h1:OrwQGYg3DuZvXUfmH+KIZDjwTCbrjy48T24TUpGqVVw=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 h1:LiZB1h0GIcudcDci2bxbqI6DXV8bF8POAnArqvRrIyw=
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0/go.mod h1:F/7q8/HZz+TXjlsoZQQKVYvXTZaFH4QRa3y+j1p7MS0=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

Some files were not shown because too many files have changed in this diff Show More