forked from FG42/FG42
11 KiB
11 KiB
How to build an editor with Emacs Lisp
- Episode 1 - Introduction
- Episode 2 - Survive on the first day
- Episode 3 - Lisp Basics
- Episode 4 - Conditionals
- Episode 5 - Lists
- Episode 6 - Property & Association Lists
- Episode 7 - Basic Loops
- Episode 8 - More Loops
DONE Episode 1 - Introduction
CLOSED: [2022-01-09 Sun 19:03]
What is it all about?
- Create an editor, development environment and Window Manager (yeah window manager) and …
- GNU/Emacs is amazing
- Spread the joy
- Guide for contributors
- A guide for people who wants to learn some Lisp
The Plan
- Parallel video series to How to build a compiler with LLVM and MLIR
- Git branches
- No live coding
- Start from Emacs and Jump to FG42
- Feel free to contribute
FG42 and a bit of history
-
It's my:
- Editor/IDE
- Email client
- Window Manager
- File Manager
- Terminal Emulator
- IRC client (at some point)
- TODO manager
- "Office suit" (air qoute)
- ….
- Started on 2010 in a train
- I'm working on the V3
-
Requirements
- Emacs >= 27.1
- Website: https://fg42.org/
- Repository: https://devheroes.codes/FG42
- Website: https://lxsameer.com
- Email: lxsameer@gnu.org or lxsameer@lxsameer.com
DONE Episode 2 - Survive on the first day
CLOSED: [2022-02-11 Fri 10:28]
Why bother?
Why GNU/Emacs?
People might say because of
- Org-mode
- LSP support
- Support for many many languages
- It's lightweight
- Tons of plugins
- …
I'd say
- Coz it's a lisp environment with an editor attached to it
-
Lisp is the difference
- It's super easy to extend/hack emacs
- In compare to other editors
- You can do pretty much whatever your like in ELisp
- It's like a framework for building an editor
FAQ
What is the difference between Doom, Spacemacs, FG42 and …?
Different editors based on Emacs
Which one should I use?
How to install Emacs packages?
UI Basics & Basic Concepts
- Window
- Frame
- Mode line
- Buffers
- Mini buffer/Echo area
- Point
- Major mode
- Minor mode
Basic Keybindings
How to read key bindings? Here is an example C-x M-e 4
, it means press x
key while
holding Control
and then press e
key while pressing down Alt
and finally press 4
.
- Emacs tutorial
C-h t
(or https://www.gnu.org/software/emacs/tour/) - Quit emacs
C-x C-c
- Abort
C-g
-
Get Help
C-h
familyC-h f
C-h v
C-h m
C-h k
C-h a
- Run a command (function)
M-x
- Visit a file
C-x C-f
- Search in Buffer
C-s
- Save buffer
C-x C-s
- Select region
C-SPC
- Copy
M-w
- Cut(killing)
C-w
- Paste(yanking)
C-y
- Kill buffer
C-x k
- Switch buffer
C-x b
- Undo
C-/
- Eval expression
C-x C-e
describe-mode
Lisp basics
- Expressions everywhere
- Code a data structure
-
Almost everything in Lisp evaluates to themselves except:
- lists
- Symbols
- …
-
Lisp laws:
- Everything in Lisp is an expression and evaluation of an expression means replacing it with its value
-
Almost everything in Lisp evaluates to themselves except:
- Lists
- Symbols
- Quotes
-
…
- List evaluation
DONE Episode 3 - Lisp Basics
CLOSED: [2022-03-12 Sat 18:38]
FAQ:
-
How to install Emacs?
- Just make sure to have Emacs >= 27.1
-
What's the routine to use Emacs ?
- Don't use Emacs like how you use other Editors.
- There is no limits(Almost).
-
How evaluate forms?
- C-x C-e at the end of any expression and anywhere
- ielm
- Batch mode
So Fare:
Lisp rules:
- Lisp is made of Expressions and they evaluate to a value.
- All the expression types evaluates to themselves with some exceptions.
- List evaluation
We will continue with Lisp basics for few episodes
Variables
- How to define variables and constants
- Set the value of a variable
- Global and local scope
-
Lexical bindings vs Dynamic bindings
-*- lexical-binding: t; -*-
Functions
- How to define functions
- vs macros
- vs special forms
DONE Episode 4 - Conditionals
CLOSED: [2022-04-09 Sat 11:24]
What we learned so far
what is true and what's not
Let & prog family
Conditional special forms
- if
- when
- unless
- cond
Useful forms and functions
- eq
- equal
- and
- not
- or
- …
Type Predicts
- numberp
- stringp
- listp
- boundp
- More at https://www.gnu.org/software/emacs/manual/html_node/elisp/Type-Predicates.html
type-of
DONE Episode 5 - Lists
CLOSED: [2022-05-18 Wed 12:40]
What is a list?
- Not a primitive type
- A linked list made out of cons cells
Cons Cells
- A container for pairs
- CAR
- CDR (could-er)
digraph {
graph [bgcolor=transparent]
fontcolor="gray80"
node [color=gray80 shape="box", fontcolor="gray80"]
edge [color=gray80]
rankdir = "LR"
subgraph cluster_0 {
label="Cell"
color="gray80"
graph [bgcolor=transparent, fontcolor="gray80"]
node [color=gray80 shape="box", fontcolor="gray80"]
a0[label="car: 'head"]
b0[label="cdr: 'tail"]
}
}
(setq x1 (cons 'head 'tail))
(car x1)
(cdr x1)
'(head . tail)
(cons 2 nil)
(cons 1 x1)
digraph {
graph [bgcolor=transparent]
fontcolor="gray80"
node [color=gray80 shape="box", fontcolor="gray80"]
edge [color=gray80]
rankdir = "LR"
subgraph cluster_0 {
label="Cell"
color="gray80"
graph [bgcolor=transparent, fontcolor="gray80"]
node [color=gray80 shape="box", fontcolor="gray80"]
a0[label="car: 1"]
b0[label="cdr: "]
}
subgraph cluster_1 {
label="Cell"
color="gray80"
node [color=gray80 shape="box"]
a1[label="car: 2"]
b1[label="cdr: "]
b0 -> a1
}
subgraph cluster_2 {
label="Cell"
color="gray80"
node [color=gray80 shape="box"]
a2[label="car: 3"]
b2[label="cdr: nil"]
b1 -> a2
}
}
(setq x2 (cons 1 (cons 2 (cons 3 nil))))
(setq x3 (list 1 2 3))
Some useful functions
- add-to-list
(setq x4 (list 1 2 3 4))
(add-to-list 'x4 3)
(add-to-list 'x4 6)
- push & pop
(setq x5 (list 1 2 3 4))
(push 1 x5)
(pop x5)
- member
(setq x6 (list 'a 'b 1 2))
(member 'z x6)
(member 1 x6)
- delete
(setq x7 (list 1 2 3 4 5))
(delete 3 x7)
x7
- remove
(setq x8 (list 1 2 3 4 5))
(remove 3 x8)
x8
- car
- cdr
(setq x9 (list 1 2 3 4))
(car x9)
(cdr x9)
DONE Episode 6 - Property & Association Lists
CLOSED: [2022-06-13 Mon 10:38]
I have an idea
- Develop FG42 on stream
-
I'll announce the date and time on:
- Twitter: @lxsameer
- Youtube Community (maybe)
eq vs equal
eq
checks whether two objects are the sameequal
checks whether two objects have similar structure and content.
Property List (plist)
- Is a list of paired elements
- Each of the pairs associates a property name with a property or value
- The order of the property names (keys) is not significant
- Keys must be unique
- Emacs uses plists to store text properties and symbol properties
Examples
(setq x '(:a 1 "b" 2 c 3 :d ("foo" "bar") :j nil))
x
Functions
plist-get
orlax-plist-get
(plist-get x :a)
(plist-get x "b")
(lax-plist-get x "b")
plist-put
orlax-plist-put
(plist-put x :z 325)
(plist-put x :z 10)
(lax-plist-put x "b" 20)
plist-member
(plist-get x :j)
(plist-get x :g)
(plist-member x :j)
(plist-member x :g)
An example use case of plist
(defun foo (&rest args)
(message "ARGS: %s" args)
(plist-get args :name))
(foo :age 20 :name 'bob "blah" '(12 34 4))
Association List (alist)
- It is a list of cons cells called associations
- Mapping some keys to some values
- The
CAR
of each cons cell is the key, and theCDR
is the associated value - The order of associations matters
Examples
(setq y '((:a . 1) ("b" . 2) (c . 3) (:d "foo" "bar")))
y
Functions
assoc
(assoc :a y)
(assoc "b" y)
rassoc
(rassoc 1 y)
(rassoc 3 y)
assq
(assq :a y)
(assq "b" y)
alist-get
(alist-get :a y)
(alist-get :z y "blah")
cons
(setq y1 (cons '(:z . 31) y))
(assoc :z y1)
Episode 7 - Basic Loops
About previous episode
- Duplicate keys in an association list
eval-defun
While
- Form:
(while CONDITION
...body...)
- Loops and evaluates
body
as long as theCONDITION
evaluates to true. - It always evaluats to the value of the
CONDITION
which will be false aaaaall the time. - We need to explicitly manage the condition.
- Example:
(let ((foo 1))
(while (< foo 10)
(message ">> %s" foo)
(setq foo (+ 1 foo))))
(let ((foo '(bar baz)))
(while foo
(message ">> %s" (car foo))
(setq foo (cdr foo))))
dolist
- It's a macro
- Form:
(dolist (element list [result])
...body...)
- Evaluates the
body
withelement
set to the CAR oflist
on each iteration - At the ends evaluates
result
and return the evaluation result (ifresult
is provided) - Example:
(let ((foo '(9 8 7 6 5 4)))
(dolist (x foo (+ 10 1))
(message ">> %s" x)))
(let ((foo '(9 8 7 6 5 4)))
(macroexpand-1
'(dolist (x foo 10)
(message ">> %s" x))))
dotimes
- It's a macro too
- Form:
(dotimes (var number)
...body...)
- It's similar to
dolist
but iteratesnumber
of times var
in will contains the number of current iteration- Example:
(let ((foo 10))
(dotimes (x foo)
(message ">> %s" x)))
(let ((foo 10))
(macroexpand-1
'(dotimes (x foo)
(message ">> %s" x))))