We Are Syvlorg.

About Me About This Website About Syvlorg Résumé Index

Table of Contents

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.

Author: Jeet Ray

Created: 2023-09-05 Tue 02:09

Validate