mirror of
https://github.com/foo-dogsquared/wiki.git
synced 2025-01-31 10:58:28 +00:00
549f476c4c
The topics I've covered so far for Linux, package managers, archiving, and learning. I also updated some formatting for other notes especially with the command line references.
282 lines
8.9 KiB
Org Mode
282 lines
8.9 KiB
Org Mode
:PROPERTIES:
|
|
:ID: ba829d63-02a9-48df-9148-a82aaa51cee9
|
|
:END:
|
|
#+title: Oil shell language
|
|
#+date: "2021-05-09 16:40:50 +08:00"
|
|
#+date_modified: "2021-07-28 10:52:44 +08:00"
|
|
#+language: en
|
|
#+property: header-args:oil :eval no
|
|
|
|
|
|
For future references, this note mainly notes Oil v0.8.11 and later versions.
|
|
Also, we'll be comparing to Bash shell (src_bash[:eval yes :results output]{bash --version | head -n 1} {{{results(=GNU bash\, version 4.4.23(1)-release (x86_64-unknown-linux-gnu)=)}}}) as it is the most popular shell on the Unix world.
|
|
|
|
|
|
|
|
* What is Oil shell?
|
|
|
|
Ripping off from the [[https://www.oilshell.org/blog/2020/01/simplest-explanation.html][explanation page]]:
|
|
|
|
#+begin_quote
|
|
Oil is also aimed at people who know say Python or JavaScript, but purposely avoid shell.
|
|
#+end_quote
|
|
|
|
A modern shell attempting the replace Bash slowly.
|
|
The project has an ambitious goal with a wide scope.
|
|
It is known for its [[https://oilshell.org/blog][shell-oriented blog]] and the developer is very responsive and active with shell-related posts.
|
|
|
|
While there are multiple components in this project, we're focusing on two: *OSH and Oil shell*.
|
|
|
|
- *OSH is the bridge between Bash and Oil.*
|
|
It aims to be the most Bash-compatible shell that you can run most Bash scripts just fine.
|
|
The point of this component is improving what's under the hood, imposing sensible defaults on them, and getting a wide reach since Bash is the most popular shell.
|
|
While it may not run every Bash script in existence, the other point is to require minimal rewrites to run it with OSH or eventually rewrite it in Oil.
|
|
|
|
- *Oil shell is the modern replacement of Bash* from its syntax and behavior.
|
|
It aims to be the shell for people familiar to Python, Ruby, JavaScript, and the like.
|
|
This is the other side of the bridge that OSH aims to reach.
|
|
|
|
Both OSH and Oil are referring to the same interpreter but configured differently.
|
|
|
|
|
|
|
|
|
|
* Overview of the Oil language
|
|
|
|
Oil is an entirely new programming language built from scratch.
|
|
It adds a hint of familiarity with Bash and takes a big queue of Python.
|
|
|
|
The following block should be sufficient for jogging your memory and a quick glance of what Oil is all about.
|
|
|
|
#+begin_src oil
|
|
var title = "Catenbury's Tale"
|
|
setvar title = "MS Fnd in a Lbry"
|
|
|
|
var keywords = %("metadata" "information overload" "information retrieval")
|
|
append :keywords "information organization"
|
|
|
|
var metadata = {}
|
|
setvar metadata['author'] = "Hal Draper"
|
|
setvar metadata['year'] = 1961
|
|
|
|
# Practically, it's a function.
|
|
# Not necessarily a function since it doesn't return an output.
|
|
proc kebab_case(word) {
|
|
write -- $word | sed -E -e 's/./\L&/g' -e 's/s+/-/g' -e 's/[^.a-z0-9-]//g' -e 's/-+/-/g'
|
|
}
|
|
|
|
var title_slug = $(kebab_case $title)
|
|
|
|
{
|
|
var keywords = %("alternate universes" "aliens" "spaceships")
|
|
for i in @keywords { echo "keyword: $i" }
|
|
}
|
|
for i in @keywords { echo "keyword: $i" }
|
|
#+end_src
|
|
|
|
|
|
** Strings
|
|
|
|
While strings are similar to Bash strings[fn:: Really more like Python strings.], there are subtle differences.
|
|
Most notably, Bash splits the string when trying to do something.
|
|
|
|
#+begin_src bash
|
|
d='echo 3'
|
|
e='echo "The quick brown fox jumps over the lazy dog."'
|
|
|
|
parallel -- $d $e
|
|
#+end_src
|
|
|
|
It should throw an error because =parallel= interprets it as if it has 4 arguments due to the splitting — i.e., ~parallel -- echo 3 echo "The quick brown fox jumps over the lazy dog."~.
|
|
The solution here is to quote the variables in evaluation (e.g., ~parallel -- "$d" "$e"~).
|
|
|
|
Compare that to Oil...
|
|
|
|
#+begin_src oil
|
|
var d = 'echo 3'
|
|
var e = 'echo "The quick brown fox jumps over the lazy dog."'
|
|
|
|
parallel -- $d $e
|
|
#+end_src
|
|
|
|
If you want splitting, you could use =split= Oil function — e.g., ~@split(array_var)~.
|
|
|
|
|
|
** Arrays
|
|
|
|
Arrays are mostly similar to Bash arrays except you have more options.
|
|
|
|
- You can create a heterogenous list containing different types of data — e.g., ~var a = ['Dogs', 24, true ]~.
|
|
Useful for JSON compatability.
|
|
|
|
- A homogenous array is useful for data consistency.
|
|
It can accept a list of data of the same type — e.g., ~var b = %("foo" "bar" "baz")~.
|
|
|
|
You can iterate through an array with a loop.
|
|
|
|
#+begin_src oil
|
|
for i in @a { echo "word: $i" }
|
|
#+end_src
|
|
|
|
You can also add an item to the array with =append= keyword.
|
|
|
|
#+begin_src oil
|
|
append :a "biz"
|
|
|
|
# The expression mode equivalent
|
|
# You can also append associative arrays due to the expressiveness of the mode
|
|
_ a.append("biz")
|
|
#+end_src
|
|
|
|
|
|
** Conditions
|
|
|
|
Conditions in Oil look like this...
|
|
Note that the parenthesis is a part of it.
|
|
|
|
#+begin_src oil
|
|
if (4 == 5) {
|
|
echo "Alright, this is true."
|
|
} elif (1 > 5) {
|
|
echo "Another condition?"
|
|
} else {
|
|
echo "It seems you got me."
|
|
}
|
|
#+end_src
|
|
|
|
You can also make ternary conditionals.
|
|
|
|
#+begin_src oil
|
|
echo $['dogs' if dogs == 'cute' else 'cats']
|
|
#+end_src
|
|
|
|
While Oil expressions are usually used for conditions, you can also use command mode lines (see [[Expression and command mode]]).
|
|
Similar to Bash conditions, it will pass when the exit code is zero.
|
|
|
|
#+begin_src oil
|
|
if test -d /usr/home {
|
|
echo "OK, you have an unusual home."
|
|
} elif test -d /home {
|
|
echo "Alrighty, home does exist."
|
|
} else {
|
|
echo "Homeless."
|
|
}
|
|
#+end_src
|
|
|
|
|
|
** Associative arrays
|
|
|
|
- similar to Bash associative arrays or Python dictionaries (practically like Python dictionaries)
|
|
- when interacting with Oil, an associative array is exactly that, an array
|
|
|
|
#+begin_src oil
|
|
const conditions = {}
|
|
setvar conditions['sunny'] = 80
|
|
setvar conditions['cloudy'] = 30
|
|
setvar conditions['rainy'] = -20
|
|
|
|
for key in @conditions {
|
|
write -- $key $[conditions[key]]
|
|
}
|
|
#+end_src
|
|
|
|
You can check for a member in an associative with =in= keyword.
|
|
|
|
#+begin_src oil
|
|
if ('rainy' in conditions) {
|
|
write -- "We have rainy days over here."
|
|
}
|
|
#+end_src
|
|
|
|
|
|
|
|
|
|
* Expression and command mode
|
|
|
|
- There are different ways [[https://www.oilshell.org/release/latest/doc/syntactic-concepts.html][how Oil can create an expressive language with the shell]].
|
|
It can parse different sublanguages with different lexer modes.
|
|
But there are dominantly two modes to keep in mind: expression and command mode.
|
|
|
|
- simply put: + *command mode is similar to Bash expressions*
|
|
+ *expression mode is akin to Python expressions*
|
|
|
|
- Expression mode even has Python familiarisms — e.g., ~if ("item" in array)~, ~if ("key" in object)~.
|
|
|
|
- The addition of a Python-like expressiveness is how Oil can make a rich scripting exprience.
|
|
|
|
- command mode is what you see most of the time
|
|
- expression mode is activated when: + right-hand side of === — e.g., ~var a = 234~
|
|
+ the =_= keyword where output will be ignored — e.g., ~_ a.append(b)~ + the === command where it will print the results — e.g., ~= 53~
|
|
+ you can interpolate expression mode expressions with =$[]= — e.g., ~echo $[4 + 43 + a]~, ~echo $[len(ARGV)]~
|
|
+ in =if= statements — e.g., ~if (true) { echo "WHOA" }~
|
|
|
|
|
|
|
|
|
|
* Quoted string notation (QSN)
|
|
|
|
- a data format that can represent any byte sequence
|
|
- adapted from Rust's string syntax
|
|
- Oil can print non-ASCII stuff through [[https://www.oilshell.org/release/latest/doc/qsn.html][QSN]]
|
|
|
|
#+begin_src oil
|
|
write -- $'\u044f\u043c\u0443' $'\u3bc'
|
|
#+end_src
|
|
|
|
|
|
|
|
|
|
* Structured data
|
|
|
|
While Bash have support for structured data such as arrays and associative arrays, it does not go any further such as not letting you assign arrays in an item.
|
|
As of v0.8.9, Oil also comes with the same problem but it seems [[https://github.com/oilshell/oil/issues/741][the developer is also interested in solving that]].
|
|
|
|
Though, you can still declare and assign variables with nested data structures.
|
|
|
|
#+begin_src oil
|
|
const author = {
|
|
"name": "John Doe",
|
|
"birthdate": "1992-04-04",
|
|
"portfolio": [
|
|
{ "title": "Philistine: A Jon Doe story", "isbn": "392-423-2113-123" },
|
|
{ "title": "Whoa there!", "isbn": "241-123-35241-123" }
|
|
]
|
|
"has_criminal_record": false
|
|
}
|
|
|
|
write -- $[author['name']] $[author['portfolio'][0]['title']]
|
|
#+end_src
|
|
|
|
Oil has a built-in JSON support with the =json= keyword.
|
|
|
|
#+begin_src oil :shebang "#!/usr/bin/env oil"
|
|
const author = {
|
|
"name": "John Doe",
|
|
"birthdate": "1992-04-04",
|
|
"portfolio": [
|
|
{ "title": "Philistine: A Jon Doe story", "isbn": "392-423-2113-123" },
|
|
{ "title": "Whoa there!", "isbn": "241-123-35241-123" }
|
|
]
|
|
"has_criminal_record": false
|
|
}
|
|
|
|
json write :author
|
|
#+end_src
|
|
|
|
This is handy as most tools has an option to print JSON data — e.g., =systemctl=, Ripgrep, =buku=, [[id:8135ece9-0dc0-4799-ac63-a24f9486ddd2][BorgBackup]].
|
|
|
|
|
|
|
|
|
|
* Tips and tricks
|
|
|
|
- Oil seems to evaluate in normal order, evaluating only when the conditions passed — e.g., ~echo $['' + null if null else 'EEEEHHH']~ should print =EEEEHHH=. + Just like most modern mainstream languages... nice.
|
|
- Two operands of different types are considered unequal — e.g., ~'4' == 4~.
|
|
+ You can use Python-like type conversions like =Int=, =Bool=, and =Str= — e.g., ~Int('4') == 4~.
|
|
- By default, errexit is disabled (e.g., the script will not exit on error).
|
|
You can have fine control over it with =run=.
|