Table of Contents
- Welcome to the
bakery
! May I wrap your program?- Program options can be directly set without baking them in first (heresy, I know!)
- The general command string will end up like this
- While I'm not sure how different the following behavious is, you can iterate over the
bakery
object itself to get its output - You can use specific shells to run commands as well
- Want to get the command you're about to run?
- Want to see the command you're about to run?
- Want some more details?
- Here's how to use
sudo
- If you want visible prompts, set
:m/capture
torun
, or:m/run
toTrue
- Freeze
bakery
objects, allowing otherbakery
objects to act on them - Piping and Redirection is implemented through the use of frozen
bakery
objects and strings… - Use a
bakery
object with a context manager - Ignore Stderr
- Pipe Stderr to Stdout
Welcome to the bakery
! May I wrap your program?
bakery
is a hylang module heavily inspired by sh,
written by Andrew Moffat / amoffat;
I loved the concept of baking
a command so much that I created an entire module based on it.
While amoffat's sh
runs only Unix-based systems at the moment, bakery
is able to run on DOS-based systems as well, such as Microsoft Windows
.
Here are a few more differences (note that in python, m/option
becomes _option
):
Program options can be directly set without baking them in first (heresy, I know!)
Python:
import hy
from bakery import git
# git -C "..." status
git(C = "...").status()
Hy:
(import bakery [git])
;; git -C "..." status
(.status (git :C "..."))
Note:
Because git
and yadm
are in a list called m/gitea.list
, they can be imported with the ability to set program options;
setting program.m/gitea.bool
to True
, or adding to the list, will trigger this as well,
while setting program.m/gitea.off
to False
will override both of the former.
The general command string will end up like this
f"{m/shell} -c {m/program}
{m/starter-kwargs}
{m/subcommand}
{m/starter-args}
{m/regular-kwargs}
{m/regular-args}"
Python:
import hy
from bakery import ls, find
# ls -l -a ~
ls("~", l = True, a = True)
# find . -empty -type d -delete
find(
empty = True,
delete = True,
type = "d",
_one_dash = True,
_starter_args = "."
)
Hy:
(import bakery [ls find])
;; ls -l -a ~
(ls "~" :l True :a True)
;; find . -empty -type d -delete
(find :empty True :delete True :type "d" :m/one-dash True :m/starter-args ".")
Note:
To use single dashes for options, set m/one-dash
to True
.
While I'm not sure how different the following behavious is, you can iterate over the bakery
object itself to get its output
Python:
import hy
from bakery import ls
# And no, I didn't miss the brackets.
# ls
for item in ls:
print(item)
Hy:
(import bakery [ls])
;; And no, I didn't miss the brackets.
;; ls
(for [item ls] (print item))
You can use specific shells to run commands as well
Python:
import hy
from bakery import ls
# bash -c 'ls'
ls(_shell = "bash")
Hy:
(import bakery [ls])
# bash -c 'ls'
ls(:m/shell "bash")
Want to get the command you're about to run?
Python:
import hy
from bakery import ls
# bash -c 'ls'
ls(_shell = "bash", _return_command = True)
Hy:
(import bakery [ls])
;; bash -c 'ls'
ls(:m/shell "bash" :m/return-command True)
Want to see the command you're about to run?
Python:
import hy
from bakery import ls
# bash -c 'ls'
ls(_shell = "bash", _print_command = True)
Hy:
(import bakery [ls])
;; bash -c 'ls'
ls(:m/shell "bash" :m/print-command True)
Want some more details?
Python:
import hy
from bakery import ls
ls(_debug = True)
# OR
ls.inspect_()
Hy:
(import bakery [ls])
(ls :m/debug True)
;; OR
(.inspect- ls)
Here's how to use sudo
Python:
import hy
from bakery import ls
# sudo ls /
ls("/", _sudo = True)
# sudo -i -u root ls /
ls("/", _sudo = "i")
# sudo -s -u root ls /
ls("/", _sudo = "s")
# sudo -i -u user ls /
ls("/", _sudo = dict(i = "user"))
# sudo -s -u user ls /
ls("/", _sudo = dict(s = "user"))
Hy:
(import bakery [ls])
;; sudo -i -u user ls /
(ls "/" :m/sudo { "i" "user" })
;; sudo -s -u user ls /
(ls "/" :m/sudo { "s" "user" })
If you want visible prompts, set :m/capture
to run
, or :m/run
to True
Otherwise, prompts will be captured in the output, while the process still halts for input.
Python:
import hy
from bakery import zfs
# Will show input prompt
# zfs load-key pool
zfs.load_key(pool, _capture = "run")
# Will NOT show input prompt
# zfs load-key pool
zfs.load_key(pool)
Hy:
(import bakery [zfs])
;; Will show input prompt
;; zfs load-key pool
(.load-key zfs pool :m/capture "run")
;; Will NOT show input prompt
;; zfs load-key pool
(.load-key zfs pool)
Note:
This does not happen with the use of sudo
, or the m/sudo
keyword argument;
the password prompt will still be shown, input will still be passed to sudo
, and output will still be returned.
Freeze bakery
objects, allowing other bakery
objects to act on them
Freeze using anything but tea objects, strings, integers, or the milcery
class in this module;
frozen objects are simply deepcopies
of the instance they were called from, after all settings and program arguments and options are set, but not reset.
Python:
import hy
from bakery import ls
# ls
ls([])
# Some Alternatives
ls(None)
ls(False)
ls(bool(0))
ls(bool(""))
# Freeze using the keyword (but it's longer; why would you want to do that? :P)
ls(_frozen = True)
# Freeze using... Nothing! :D
ls
Hy:
(import bakery [ls])
;; ls
(ls [])
;; Some Alternatives
(ls None)
(ls False)
(ls bool(0))
(ls bool(""))
;; Freeze using the keyword (but it's longer; why would you want to do that? :P)
(ls :m/frozen True)
;; Freeze using... Nothing! :D
ls
Note:
In the last example, assume all bakery objects are frozen by default, with default settings.
Piping and Redirection is implemented through the use of frozen bakery
objects and strings…
… or tea or frosting objects.
Mind that, while freezing the bakery
objects, the settings on the right-hand side will override those on the right-hand side,
if the same setting is set while freezing both objects.
Python:
import hy
from os import devnull
from bakery import ls, tail
# Piping using frozen objects
# ls | tail
tails = ls | tail
tails = "ls" | tail
tails = ls | "tail"
tails = ls([]) | tail([])
tails = "ls" | tail([])
tails = ls([]) | "tail"
tails()
# Piping to tee
# ls | tee /dev/null
teels = ls & devnull
teels()
# ls | tee -a /dev/null
teels = ls + devnull
teels()
# Redirection using frozen objects
# ls > /dev/null
nulls = ls > devnull
nulls()
# ls >> /dev/null
nulls = ls >> devnull
nulls()
# ls < /dev/null
nulls = ls < devnull
nulls()
# ls << /dev/null
nulls = ls << devnull
nulls()
# Any of the above pipes or redirections with a tuple
# ls 2>&1 /dev/null
nulls = ls | (devnull, "2>&1")
nulls()
# ls &> /dev/null
nulls = ls > (devnull, "&>")
nulls()
Hy:
(import os [devnull])
(import bakery [ls tail])
;; Piping using frozen objects
;; ls | tail
(setv tails (| ls tail))
(setv tails (| "ls" tail))
(setv tails (| ls "tail"))
(setv tails (| (ls []) (tail [])))
(setv tails (| (ls []) "tail"))
(setv tails (| "ls" (tail [])))
(tails)
;; Piping to tee
;; ls | tee /dev/null
(setv teels (& ls devnull))
(teels)
;; ls | tee -a /dev/null
(setv teels (+ ls devnull))
(teels)
;; Redirection using frozen objects
;; ls > /dev/null
(setv nulls (> ls devnull))
(nulls)
;; ls >> /dev/null
(setv nulls (>> ls devnull))
(nulls)
;; ls < /dev/null
(setv nulls (< ls devnull))
(nulls)
;; ls << /dev/null
(setv nulls (<< ls devnull))
(nulls)
;; Any of the above pipes or redirections with a tuple
;; ls 2>&1 /dev/null
(setv nulls (| ls (, devnull "2>&1")))
(nulls)
;; ls &> /dev/null
(setv nulls (> ls (, devnull "&>")))
(nulls)
Use a bakery
object with a context manager
Python:
import hy
from bakery import ls
# ls -l -a
with ls(_c = True, l = True) as lsl:
lsl(a = True)
# ls -l -a | tail
with ls([], l = True, a = True) | tail as tails:
tails()
Hy:
(import bakery [ls tail])
;; ls -l -a
(with [lsl (ls :m/c True :l True)]
(lsl :a True))
;; ls -l -a | tail
(with [tails (| (ls [] :l True :a True) tail)]
(tails))
Ignore Stderr
Python:
ls(j = True)
# Without `_ignore_stderr = True':
# SystemError: In trying to run `ls -j':
# ls: invalid option -- 'j'
# Try 'ls --help' for more information.
ls(j = True, _ignore_stderr = True)
# With `_ignore_stderr = True':
# ...
Hy:
(ls :j True)
;; Without `:m/ignore-stderr True':
;; SystemError: In trying to run `ls -j':
;; ls: invalid option -- 'j'
;; Try 'ls --help' for more information.
(ls :j True :m/ignore-stderr True)
;; With `:m/ignore-stderr True':
;; ...
Pipe Stderr to Stdout
Python:
ls(j = True)
# Without `_stdout_stderr = True':
# SystemError: In trying to run `ls -j':
# ls: invalid option -- 'j'
# Try 'ls --help' for more information.
ls(j = True, _stdout_stderr = True)
# With `_stdout_stderr = True':
# ls: invalid option -- 'j'
# Try 'ls --help' for more information.
Hy:
(ls :j True)
# Without `:m/stdout-stderr True':
# SystemError: In trying to run `ls -j':
# ls: invalid option -- 'j'
# Try 'ls --help' for more information.
(ls :j True :m/stdout-stderr True)
# With `:m/stdout-stderr True':
# ls: invalid option -- 'j'
# Try 'ls --help' for more information.