FG42/docs/videos.org

11 KiB

How to build an editor with Emacs Lisp

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

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 family

    • C-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:

    1. Everything in Lisp is an expression and evaluation of an expression means replacing it with its value
    2. Almost everything in Lisp evaluates to themselves except:

      • Lists
      • Symbols
      • Quotes
    3. 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:

  1. Lisp is made of Expressions and they evaluate to a value.
  2. All the expression types evaluates to themselves with some exceptions.
  3. 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

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"]
    }
}

/tmp/cons.svg

  (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
    }
}

/tmp/list.svg

  (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 same
  • equal 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 or lax-plist-get
  (plist-get x :a)
  (plist-get x "b")
  (lax-plist-get x "b")
  • plist-put or lax-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 the CDR 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 the CONDITION 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 with element set to the CAR of list on each iteration
  • At the ends evaluates result and return the evaluation result (if result 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 iterates number 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))))

Episode 8 - More Loops

Recursion

Functional style loops