• OK, it's on.
  • Please note that many, many Email Addresses used for spam, are not accepted at registration. Select a respectable Free email.
  • Done now. Domine miserere nobis.

World's (imo) best text editor

BurnedOut

Your friendly neighborhood asshole
Local time
Tomorrow 5:13 AM
Joined
Apr 19, 2016
Messages
1,444
---
Location
A fucking black hole
This thread will attempt to document my musings on Emacs - one of the pieces of technology that had a profound impact on my programming skills and computer usage in general. I want you to think about the power of text editing and hopefully use emacs at least once in your life.

Emacs is one of the best of kind of I have ever used. It has a relatively esoteric (for most coders) language that is LISP. That's the selling point. In my decade-old experience of coding, having lisp changes everything. It's homoiconic - code is data and data is code in lisp. Remember this, this will be very important in the future posts.

Homoiconicity changes a lot about how software is made. Combine that lisp's dynamic nature. It basically means code can be changed on the fly and lazily executed in the context specified. However dynamic homoiconicity changes how you code. Any language that is not truly lisp will ALWAYS use functions. This is OK but results into verbose configurations. Compare a lisp version of config vs Lua version of that same config

Emacs lisp python config:
(mode-config!
 :id python-mode
 :builtin-terminal t
 :formatter "black -"

 :compile
 (buffer "python3 %path")
 (cwd "cd %path && python3 %buffer")

 :repl
 (buffer "python3")
 (workspace "python3")
 (cwd "python3")

 :hooks
 (eglot-ensure))

Lua python config:
local python = {}

python.formatter = {
  buffer = "cat {path} | black -q -",
  workspace = "black -q .",
  dir = "black -q .",
  stdin = true,
}

python.test = "pytest {path}"

python.repl = {
  buffer = "ipython3",
  workspace = "ipython3",
  dir = "python3",
}
  
python.server = "jedi_language_server"

python.compile = "python3 {path}"

python.buf_opts = {
  shiftwidth = 4,
  tabstop = 4,
  expandtab = true,
}

return python
 

Cognisant

cackling in the trenches
Local time
Today 12:43 PM
Joined
Dec 12, 2009
Messages
11,113
---
That's the selling point. In my decade-old experience of coding, having lisp changes everything. It's homoiconic - code is data and data is code in lisp.
Are you saying I can rewrite a program as it runs? That seems useful if I want to make a virus that can evade scans, otherwise I don't really see the point.
 

dr froyd

__________________________________________________
Local time
Today 11:43 PM
Joined
Jan 26, 2015
Messages
1,445
---
nice to see a fellow emacs comrade

i've fiddled around quite a lot of with the config but tbh i still have no clue how emacs lisp works. It's some voodoo shiet
 

BurnedOut

Your friendly neighborhood asshole
Local time
Tomorrow 5:13 AM
Joined
Apr 19, 2016
Messages
1,444
---
Location
A fucking black hole
Are you saying I can rewrite a program as it runs?
Yes milord, you can construct code as you go. It's usually a lot more difficult to literally create code and store it as data. The only other language I have used does this is R. So you can basically construct code fragments, store them in a file, etc
 

BurnedOut

Your friendly neighborhood asshole
Local time
Tomorrow 5:13 AM
Joined
Apr 19, 2016
Messages
1,444
---
Location
A fucking black hole
So the parenthesis is what puts people off. It's annoying at first simply solves a lot of issues that stem from the compiling process. You can invent your own syntax as you go unlike other languages who happen to be burdened with their syntax choices. Basically insane syntax can be emulated by using in-line code expansion using macros. I regularly use them to do stuff that would take a lot of time to do in other language. As a result my lua configurations for neovim are twice or thrice as long SOMETIMES
 

EndogenousRebel

Even a mean person is trying their best, right?
Local time
Today 5:43 PM
Joined
Jun 13, 2019
Messages
2,226
---
Location
Narnia
It's not so bad seeing as you can debug and test primitive features REALLY fucking fast.

Only issue is it's(elisp) not receiving well funded updates. Ie it's still single threaded language.

Ive looked into guile scheme, which is what the GNU project (people who invented emacs) use to create their OS (Guix) these days.

Iirc scheme can be used in emacs interchangeably.

They are a small org and only have so many resources to develop upon.

There is another "language programming language" called Racket that peaked my interest, looks well maintained, but I didn't want to run away from elisp.
 

fluffy

Pony Influencer
Local time
Today 4:43 PM
Joined
Sep 21, 2024
Messages
446
---
I heard that prolog was the first self evolvable programming language. It is good to use if you have data that needs to self organize. The one guy I know whom made me aware of it used it to make global predictions based on world Internet data traffic.
 

BurnedOut

Your friendly neighborhood asshole
Local time
Tomorrow 5:13 AM
Joined
Apr 19, 2016
Messages
1,444
---
Location
A fucking black hole
Macros creating new function as if they were written manually:
(defmacro repl--dispatch-mapping-function (type name live? body)
  (declare (indent 3))
  (let* ((fn-name (concat "repl-mapping-" (symbol-name type) "-" (symbol-name name)))
         (fn-name (intern fn-name))
         (dispatcher (if live? 'repl-live-dispatch 'repl-dispatch))
         (final-form nil))
    `(progn
       (setq final-form
             (list 'defun ',fn-name '()
                   '(interactive)
                   (list ',dispatcher '(current-buffer) ',type ',body)))
       (eval final-form))))

(defmacro repl--create-mapping-functions ()
  (setq fn-name (gensym))
  (setq form (gensym))
  (setq fn-names '(split split-right stop hide))
  (setq live? (gensym))
  (setq send-string? (gensym))
  `(progn
     (cl-loop for x in '(buffer workspace cwd)
              do (progn
                   (eval (append@ '(repl--dispatch-mapping-function)
                                  x 'start nil
                                  '(repl-start it)))
                   (cl-loop for y in '(send-line send-region send-buffer)
                            do (eval (append@ '(repl--dispatch-send-string-mapping-function) x y)))
                   (cl-loop for y in ',fn-names
                            do (let* ((,fn-name (symbol-name y))
                                      (,fn-name (concat "repl-" (symbol-name y)))
                                      (,fn-name (intern ,fn-name))
                                      (,form '(repl--dispatch-mapping-function))
                                      (,form (append@ ,form x y t))
                                      (,form (append@ ,form (list ,fn-name 'it))))
                                 (eval ,form)))))))

This is one of the serious macros I have written that does code expansion on the fly. The other alternative was tonnes and tonnes of copy-pasting.
 
Top Bottom