Compare commits

...

No commits in common. "main" and "master" have entirely different histories.
main ... master

25 changed files with 1229 additions and 18232 deletions

1
.#emacs.org Symbolic link
View File

@ -0,0 +1 @@
logan@mars.114927:1618938609

BIN
.DS_Store vendored Normal file

Binary file not shown.

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
log/*
!log/.gitkeep

944
emacs.html Normal file
View File

@ -0,0 +1,944 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2021-10-13 Wed 22:01 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Emacs - "Editor MACroS"</title>
<meta name="author" content="Simponic" />
<meta name="description" content="An emacs presentation" />
<meta name="generator" content="Org Mode" />
<style>
#content { max-width: 60em; margin: auto; }
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #f2f2f2;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: auto;
}
pre.src:before {
display: none;
position: absolute;
top: -8px;
right: 12px;
padding: 3px;
color: #555;
background-color: #f2f2f299;
}
pre.src:hover:before { display: inline; margin-top: 14px;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-authinfo::before { content: 'Authinfo'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'Javascript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { width: 90%; }
</style>
</head>
<body>
<div id="content" class="content">
<h1 class="title">Emacs - &ldquo;Editor MACroS&rdquo;</h1>
<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org48122a1">1. XKCD</a></li>
<li><a href="#orgd143ec1">2. What is Emacs?</a></li>
<li><a href="#org1cba9c8">3. From GNU.org:</a>
<ul>
<li><a href="#org9a21c74">3.1. Emacs history</a>
<ul>
<li><a href="#org4e0128f">3.1.1. From the EmacsWiki:</a></li>
</ul>
</li>
<li><a href="#org0a31c89">3.2. Emacs is a super extensible &ldquo;editor&rdquo; that is written in Elisp</a>
<ul>
<li><a href="#org54488ba">3.2.1. &ldquo;Editor&rdquo;</a></li>
<li><a href="#org770e2ee">3.2.2. Emacs Glossary</a></li>
</ul>
</li>
<li><a href="#orgd138802">3.3. First look at Elisp</a>
<ul>
<li><a href="#orgfdb2559">3.3.1. Lisp&rsquo;s simple syntax</a></li>
<li><a href="#orgd990cd9">3.3.2. Writing a simple function in Elisp</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#orgc62f346">4. Why is Emacs better than Vim?</a>
<ul>
<li><a href="#org9cb415d">4.1. Org mode</a>
<ul>
<li><a href="#orgfd1cfa9">4.1.1. &ldquo;Your life, in plain text&rdquo;</a></li>
<li><a href="#org5703388">4.1.2. Programming in org mode</a></li>
<li><a href="#org9ceb068">4.1.3. Math homework in org mode</a></li>
<li><a href="#org5f332b5">4.1.4. Export to literally any format</a></li>
</ul>
</li>
<li><a href="#orgeae2586">4.2. Amazing package support and community</a>
<ul>
<li><a href="#org384b002">4.2.1. MELPA</a></li>
<li><a href="#org2cec309">4.2.2. SLIME</a></li>
<li><a href="#org8692c74">4.2.3. Magit</a></li>
<li><a href="#org4b39e5d">4.2.4. Company-mode</a></li>
<li><a href="#org167ed70">4.2.5. Undo-tree</a></li>
<li><a href="#org9b1f6b7">4.2.6. LSP-mode</a></li>
</ul>
</li>
<li><a href="#org966691d">4.3. It&rsquo;s written in Lisp</a></li>
</ul>
</li>
<li><a href="#org86d0202">5. First steps in going forward with Emacs</a>
<ul>
<li><a href="#org8dbd14d">5.1. Want to learn ELisp?</a></li>
<li><a href="#org7b98e1f">5.2. Want to get started with Emacs?</a></li>
</ul>
</li>
<li><a href="#orga0006b1">6. The compromise</a>
<ul>
<li><a href="#org4832571">6.1. Can&rsquo;t decide which is better (it&rsquo;s emacs)? Good news! You don&rsquo;t have to!</a></li>
<li><a href="#org1231631">6.2. More on Doom</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-org48122a1" class="outline-2">
<h2 id="org48122a1"><span class="section-number-2">1.</span> XKCD</h2>
<div class="outline-text-2" id="text-1">
<div id="orgda3dd78" class="figure">
<p><img src="./images/real_programmers.png" alt="real_programmers.png" />
</p>
</div>
</div>
</div>
<div id="outline-container-orgd143ec1" class="outline-2">
<h2 id="orgd143ec1"><span class="section-number-2">2.</span> What is Emacs?</h2>
</div>
<div id="outline-container-org1cba9c8" class="outline-2">
<h2 id="org1cba9c8"><span class="section-number-2">3.</span> From <a href="https://www.gnu.org/software/emacs/">GNU.org</a>:</h2>
<div class="outline-text-2" id="text-3">
<p>
Emacs is &ldquo;an extensible, customizable, free/libre text editor — and more. At its core is an interpreter for Emacs Lisp, a dialect of the Lisp programming language with extensions to support text editing.&rdquo;
</p>
</div>
<div id="outline-container-org9a21c74" class="outline-3">
<h3 id="org9a21c74"><span class="section-number-3">3.1.</span> Emacs history</h3>
<div class="outline-text-3" id="text-3-1">
</div>
<div id="outline-container-org4e0128f" class="outline-4">
<h4 id="org4e0128f"><span class="section-number-4">3.1.1.</span> From the <a href="https://www.emacswiki.org/emacs/EmacsHistory">EmacsWiki</a>:</h4>
<div class="outline-text-4" id="text-3-1-1">
<p>
Emacs began at the Artificial Intelligence Laboratory at MIT. Beginning in 1972, staff hacker CarlMikkelsen added display-editing capability to TECO, the text editor on the AI Labs IncompatibleTimeSharingSystem (ITS) “Display-editing” meant that the screen display was updated as the user entered new commands; compare the behavior of &ldquo;ed&rdquo;. In 1974, Richard Stallman added macro features to the TECO editor.
</p>
<p>
In 1976, Stallman wrote the first Emacs (“Editor MACroS”), which organized these macros into a single command set and added facilities for SelfDocumentation and to be extensible.
</p>
<p>
<a href="https://www.jwz.org/doc/emacs-timeline.html">A Map Of Emacs History Until 2007</a>
</p>
</div>
</div>
</div>
<div id="outline-container-org0a31c89" class="outline-3">
<h3 id="org0a31c89"><span class="section-number-3">3.2.</span> Emacs is a super extensible &ldquo;editor&rdquo; that is written in Elisp</h3>
<div class="outline-text-3" id="text-3-2">
</div>
<div id="outline-container-org54488ba" class="outline-4">
<h4 id="org54488ba"><span class="section-number-4">3.2.1.</span> &ldquo;Editor&rdquo;</h4>
<div class="outline-text-4" id="text-3-2-1">
</div>
<ol class="org-ol">
<li><a id="orge87755b"></a>Emacs does much more than edit text<br />
<div class="outline-text-5" id="text-3-2-1-1">
<ul class="org-ul">
<li><p>
To show itself off, Emacs by default comes with a full game of tetris!
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #c678dd;">tetris</span><span style="color: #51afef;">)</span>
</pre>
</div>
<ul class="org-ul">
<li>Besides being a great tool to play tetris when you&rsquo;re bored and your boss is looking away, Emacs can also:
<ol class="org-ol">
<li>Write emails with the `mu4e` package</li>
<li>Write documents with Org Mode (more on this later)</li>
<li>Be your window manager with the exwm package
<ul class="org-ul">
<li>I&rsquo;ve given this a try, but I&rsquo;m gonna stick with dwm</li>
</ul></li>
<li><p>
Browse the internet with eww!
</p>
<ul class="org-ul">
<li>Eww in action</li>
</ul>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #c678dd;">eww</span> <span style="color: #98be65;">"https://gnu.org"</span><span style="color: #51afef;">)</span>
</pre>
</div></li>
</ol></li>
</ul></li>
</ul>
</div>
</li>
</ol>
</div>
<div id="outline-container-org770e2ee" class="outline-4">
<h4 id="org770e2ee"><span class="section-number-4">3.2.2.</span> Emacs Glossary</h4>
<div class="outline-text-4" id="text-3-2-2">
</div>
<ol class="org-ol">
<li><a id="orgff89100"></a>Weird key-binding notation?<br />
<div class="outline-text-5" id="text-3-2-2-1">
<ul class="org-ul">
<li>&ldquo;C&rdquo; is control</li>
<li>&ldquo;M&rdquo; is alt/meta</li>
<li>&ldquo;S&rdquo; is shift</li>
</ul>
<p>
When there is a &ldquo;-&rdquo; between two keys that means press them together.
</p>
<p>
&ldquo;C-x C-f&rdquo;: Control and x and then control and f (you can also hold down control)
</p>
</div>
</li>
<li><a id="org8bead97"></a>What is a &ldquo;buffer&rdquo;?<br />
<div class="outline-text-5" id="text-3-2-2-2">
<p>
Buffers hold a file&rsquo;s text. In the example before with Tetris, `(tetris)` creates a Tetris buffer.
</p>
<p>
You can think of buffers as &ldquo;tabs&rdquo; in a browser or GUI text editor
</p>
</div>
</li>
<li><a id="org00851d7"></a>What is a &ldquo;window&rdquo;?<br />
<div class="outline-text-5" id="text-3-2-2-3">
<p>
A window hosts a buffer. When you make a split, each side is a &ldquo;window&rdquo;
</p>
<p>
Cycle between windows with &ldquo;C-x C-o&rdquo;
</p>
<p>
Close a window with &ldquo;C-x 0&rdquo;
</p>
</div>
</li>
<li><a id="org89ad707"></a>What is a &ldquo;frame&rdquo;?<br />
<div class="outline-text-5" id="text-3-2-2-4">
<p>
A frame hosts a complete instance Emacs. They are equivalent to &ldquo;windows&rdquo; in a window manager. It&rsquo;s common to only really ever use one.
</p>
</div>
</li>
<li><a id="orga9691c6"></a>Good-to-know keybindings<br />
<div class="outline-text-5" id="text-3-2-2-5">
<ol class="org-ol">
<li>Quit emacs with &ldquo;C-x C-c&rdquo;</li>
<li>Open a file with &ldquo;C-x C-f&rdquo;</li>
<li>Save a file with &ldquo;C-x C-s&rdquo;</li>
<li>Accidentally pressed a different command and you have no idea what you&rsquo;re looking at? &ldquo;C-g&rdquo; will probably get you out of it.</li>
<li>&ldquo;C-x u&rdquo; to undo</li>
<li>&ldquo;C-space&rdquo; to select a region and &ldquo;C-g&rdquo; to stop selecting it</li>
<li>With a region selected, cut it with &ldquo;C-w&rdquo; (this is also known as &ldquo;killing&rdquo;)</li>
<li>Paste with &ldquo;C-y&rdquo; (this is also known as &ldquo;yanking&rdquo;)</li>
<li>Window/buffer keybindings:
<ul class="org-ul">
<li>&ldquo;C-x C-b&rdquo; changes the buffer in the current window</li>
<li>&ldquo;C-x 2&rdquo; splits a buffer vertically</li>
<li>&ldquo;C-x 3&rdquo; splits a buffer horizontally</li>
<li>&ldquo;C-x o&rdquo; changes the current window</li>
<li>&ldquo;C-x 0&rdquo; kills the current window</li>
<li>&ldquo;C-x k&rdquo; kills the current buffer</li>
</ul></li>
<li>Movement keys
<ul class="org-ul">
<li>&ldquo;C-n&rdquo; goes to the next line
<ul class="org-ul">
<li>Vim: &ldquo;j&rdquo;</li>
</ul></li>
<li>&ldquo;C-p&rdquo; goes to the previous line
<ul class="org-ul">
<li>Vim: &ldquo;k&rdquo;</li>
</ul></li>
<li>&ldquo;C-f&rdquo; goes to the next character
<ul class="org-ul">
<li>Vim: &ldquo;l&rdquo;</li>
</ul></li>
<li>&ldquo;C-b&rdquo; goes to the previous character
<ul class="org-ul">
<li>Vim: &ldquo;h&rdquo;</li>
</ul></li>
<li>&ldquo;M-f&rdquo; and &ldquo;M-b&rdquo; goes forward/back a word
<ul class="org-ul">
<li>Vim: &ldquo;f&rdquo; and &ldquo;b&rdquo;</li>
</ul></li>
<li>&ldquo;C-a&rdquo; goes to beginning of a line
<ul class="org-ul">
<li>Vim: &ldquo;0&rdquo;</li>
</ul></li>
<li>&ldquo;C-e&rdquo; goes to the end of a line
<ul class="org-ul">
<li>Vim: &ldquo;$&rdquo;</li>
</ul></li>
</ul></li>
<li>Documentation
<ul class="org-ul">
<li>&ldquo;C-h a&rdquo; to find the keybindings for a command, or to search for a command</li>
<li>&ldquo;C-h k&rdquo; to find the name of a function tied to a keybinding</li>
</ul></li>
</ol>
</div>
</li>
</ol>
</div>
</div>
<div id="outline-container-orgd138802" class="outline-3">
<h3 id="orgd138802"><span class="section-number-3">3.3.</span> First look at Elisp</h3>
<div class="outline-text-3" id="text-3-3">
<p>
Elisp is a dialect of Lisp specifically written for Emacs. Everything in Elisp is a function. Drawing the buffer, splitting windows, moving the text cursor, are all functions you can call in Elisp. It makes it super easy to configure Emacs if you know just a little bit of Lisp.
</p>
<p>
In fact, let&rsquo;s take a look at Elisp and how we can start to customize our own environment programatically.
</p>
</div>
<div id="outline-container-orgfdb2559" class="outline-4">
<h4 id="orgfdb2559"><span class="section-number-4">3.3.1.</span> Lisp&rsquo;s simple syntax</h4>
<div class="outline-text-4" id="text-3-3-1">
<p>
In Lisps, the syntax is super simple. Everything is essentially a linked list, both in data and in source code. Lists are written like `(a . (b . (c . NIL)))`. This would be equivalent to the linked list `a -&gt; b -&gt; c -&gt; null` (nil = null = false in lisp).
</p>
<p>
However, writing a dot and a period becomes cumbersome when you have even a medium sized list. This is where s-expressions are useful.
</p>
<p>
S-expressions are written with parentheses around them, like so: `(a b c)`. This is shorthand for the above `(a . (b . (c . NIL)))`.
</p>
<p>
By convention, Lisp code is written with the function as the first element in the linked list, and arguments of the function afterwards.
</p>
</div>
<ol class="org-ol">
<li><a id="orgb9cf56d"></a>Sum of numbers<br />
<ol class="org-ol">
<li><a id="org236624d"></a>The list way<br />
<div class="outline-text-6" id="text-3-3-1-1-1">
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #a9a1e1;">+</span> . <span style="color: #c678dd;">(</span><span style="color: #da8548; font-weight: bold;">2</span> . <span style="color: #98be65;">(</span><span style="color: #da8548; font-weight: bold;">2</span> . nil<span style="color: #98be65;">)</span><span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">2 + 2</span>
</pre>
</div>
</div>
</li>
<li><a id="org330d3c2"></a>The S-expression way<br />
<div class="outline-text-6" id="text-3-3-1-1-2">
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #a9a1e1;">+</span> <span style="color: #da8548; font-weight: bold;">2</span> <span style="color: #da8548; font-weight: bold;">2</span><span style="color: #51afef;">)</span>
</pre>
</div>
</div>
</li>
</ol>
</li>
<li><a id="org4aa0d6d"></a>Difference of numbers<br />
<div class="outline-text-5" id="text-3-3-1-2">
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #a9a1e1;">-</span> <span style="color: #da8548; font-weight: bold;">3</span> <span style="color: #da8548; font-weight: bold;">2</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">3 - 2</span>
</pre>
</div>
</div>
</li>
<li><a id="org2a94823"></a>Printing values<br />
<div class="outline-text-5" id="text-3-3-1-3">
<p>
`princ` will take the value of a lisp object at print it:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #a9a1e1;">princ</span> <span style="color: #98be65;">"Hello, world!"</span><span style="color: #51afef;">)</span>
</pre>
</div>
</div>
</li>
<li><a id="org7955f20"></a>Multiplication<br />
<div class="outline-text-5" id="text-3-3-1-4">
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #a9a1e1;">*</span> <span style="color: #da8548; font-weight: bold;">3</span> <span style="color: #da8548; font-weight: bold;">5</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">3 * 5</span>
</pre>
</div>
</div>
</li>
<li><a id="orgd4ff441"></a>Division<br />
<div class="outline-text-5" id="text-3-3-1-5">
<p>
(Integer math)
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #a9a1e1;">princ</span> <span style="color: #c678dd;">(</span><span style="color: #a9a1e1;">/</span> <span style="color: #da8548; font-weight: bold;">3</span> <span style="color: #da8548; font-weight: bold;">5</span><span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">3 / 5</span>
</pre>
</div>
<p>
(Floating-point math)
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #a9a1e1;">princ</span> <span style="color: #c678dd;">(</span><span style="color: #a9a1e1;">/</span> <span style="color: #da8548; font-weight: bold;">3.0</span> <span style="color: #da8548; font-weight: bold;">5</span><span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">3 / 5</span>
</pre>
</div>
</div>
</li>
<li><a id="org663413f"></a>Order of operations<br />
<div class="outline-text-5" id="text-3-3-1-6">
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #51afef;">setq</span> a <span style="color: #c678dd;">(</span><span style="color: #a9a1e1;">/</span> <span style="color: #98be65;">(</span><span style="color: #a9a1e1;">*</span> <span style="color: #da8548; font-weight: bold;">2</span> <span style="color: #da8548; font-weight: bold;">3</span><span style="color: #98be65;">)</span> <span style="color: #98be65;">(</span><span style="color: #a9a1e1;">-</span> <span style="color: #da8548; font-weight: bold;">6</span> <span style="color: #da8548; font-weight: bold;">1</span><span style="color: #98be65;">)</span><span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">variable a = (2 * 3) / (6 - 1) = 1</span>
<span style="color: #51afef;">(</span><span style="color: #51afef;">setq</span> b <span style="color: #c678dd;">(</span><span style="color: #a9a1e1;">-</span> <span style="color: #98be65;">(</span><span style="color: #a9a1e1;">*</span> <span style="color: #da8548; font-weight: bold;">2</span> <span style="color: #a9a1e1;">(</span><span style="color: #a9a1e1;">/</span> <span style="color: #da8548; font-weight: bold;">3.0</span> <span style="color: #da8548; font-weight: bold;">6.0</span><span style="color: #a9a1e1;">)</span><span style="color: #98be65;">)</span> <span style="color: #da8548; font-weight: bold;">1</span><span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">variable b = (2 * (3 / 6)) - 1 = 0</span>
<span style="color: #51afef;">(</span><span style="color: #a9a1e1;">princ</span> <span style="color: #c678dd;">(</span><span style="color: #a9a1e1;">list</span> a b<span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">Print a linked list a -&gt; b -&gt; nil</span>
</pre>
</div>
</div>
</li>
</ol>
</div>
<div id="outline-container-orgd990cd9" class="outline-4">
<h4 id="orgd990cd9"><span class="section-number-4">3.3.2.</span> Writing a simple function in Elisp</h4>
<div class="outline-text-4" id="text-3-3-2">
<p>
Here I will split this window into three sections with Elisp:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #c678dd;">split-window-right</span><span style="color: #51afef;">)</span>
<span style="color: #51afef;">(</span><span style="color: #c678dd;">split-window-below</span><span style="color: #51afef;">)</span>
</pre>
</div>
<p>
To cycle forward through these windows, I press &ldquo;C-x C-o&rdquo;.
</p>
<p>
However, what if I want to go back a window?
</p>
<p>
Emacs doesn&rsquo;t provide a keybinding for this by default (to my knowledge), so let&rsquo;s make it in Elisp ourselves!
</p>
</div>
<ol class="org-ol">
<li><a id="org2121b3d"></a>Definining a function to go back a window<br />
<div class="outline-text-5" id="text-3-3-2-1">
<p>
Functions in Elisp are made with the `defun` macro (macros are for a different presentation) and the syntax is:
</p>
<p>
`(defun function-name (list-of-args) function-body)`
</p>
<p>
The last element in the function body is what is returned
</p>
<p>
For example, to make a function to find the hypotenuse of a right triangle with lengths a,b:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #51afef;">defun</span> <span style="color: #c678dd;">pythagoras</span> <span style="color: #c678dd;">(</span>a b<span style="color: #c678dd;">)</span>
<span style="color: #c678dd;">(</span><span style="color: #51afef;">setq</span> a-squared <span style="color: #98be65;">(</span><span style="color: #a9a1e1;">*</span> a a<span style="color: #98be65;">)</span><span style="color: #c678dd;">)</span>
<span style="color: #c678dd;">(</span><span style="color: #51afef;">setq</span> b-squared <span style="color: #98be65;">(</span><span style="color: #a9a1e1;">*</span> b b<span style="color: #98be65;">)</span><span style="color: #c678dd;">)</span>
<span style="color: #c678dd;">(</span><span style="color: #a9a1e1;">sqrt</span> <span style="color: #98be65;">(</span><span style="color: #a9a1e1;">+</span> a-squared b-squared<span style="color: #98be65;">)</span><span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span>
<span style="color: #51afef;">(</span><span style="color: #a9a1e1;">princ</span> <span style="color: #c678dd;">(</span><span style="color: #c678dd;">pythagoras</span> <span style="color: #da8548; font-weight: bold;">5</span> <span style="color: #da8548; font-weight: bold;">12</span><span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span>
</pre>
</div>
<p>
Defining the function
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #51afef;">defun</span> <span style="color: #c678dd;">go-back-window</span> <span style="color: #c678dd;">()</span>
<span style="color: #c678dd;">(</span><span style="color: #51afef;">interactive</span><span style="color: #c678dd;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">makes a function an interactively-callable command (e.g. allowing call by a keybinding)</span>
<span style="color: #c678dd;">(</span><span style="color: #c678dd;">other-window</span> <span style="color: #da8548; font-weight: bold;">-1</span><span style="color: #c678dd;">)</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">(other-window n) goes n windows forward in the window stack</span>
</pre>
</div>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #c678dd;">go-back-window</span><span style="color: #51afef;">)</span>
</pre>
</div>
<p>
Let&rsquo;s add a key binding for this!
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #c678dd;">global-set-key</span> <span style="color: #c678dd;">(</span><span style="color: #c678dd;">kbd</span> <span style="color: #98be65;">"C-c u"</span><span style="color: #c678dd;">)</span> <span style="color: #51afef;">'</span><span style="color: #ECBE7B;">go-back-window</span><span style="color: #51afef;">)</span> <span style="color: #5B6268;">;; </span><span style="color: #5B6268;">We specify the name of the function by turning it into a "symbol"</span>
</pre>
</div>
</div>
</li>
</ol>
</div>
</div>
</div>
<div id="outline-container-orgc62f346" class="outline-2">
<h2 id="orgc62f346"><span class="section-number-2">4.</span> Why is Emacs better than Vim?</h2>
<div class="outline-text-2" id="text-4">
</div>
<div id="outline-container-org9cb415d" class="outline-3">
<h3 id="org9cb415d"><span class="section-number-3">4.1.</span> Org mode</h3>
<div class="outline-text-3" id="text-4-1">
</div>
<div id="outline-container-orgfd1cfa9" class="outline-4">
<h4 id="orgfd1cfa9"><span class="section-number-4">4.1.1.</span> &ldquo;Your life, in plain text&rdquo;</h4>
<div class="outline-text-4" id="text-4-1-1">
<p>
Every single org file is represented in Plain Text. Similar to markdown, it&rsquo;s a way to format this plain text so that it&rsquo;s readable and understandable by humans, but still parsable and extensible for programmers. This presentation itself is in org mode!
</p>
</div>
</div>
<div id="outline-container-org5703388" class="outline-4">
<h4 id="org5703388"><span class="section-number-4">4.1.2.</span> Programming in org mode</h4>
<div class="outline-text-4" id="text-4-1-2">
<p>
You may have noticed these things here in my presentations:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #a9a1e1;">princ</span> <span style="color: #98be65;">"I run in a source block!"</span><span style="color: #51afef;">)</span>
</pre>
</div>
<p>
These blocks, called &ldquo;source blocks&rdquo;, are blocks of code you can run interactively in an org mode document. It&rsquo;s incredibly common for emacs users to define their init.el (the file emacs will run first when it starts up) in an org mode document, whose source-blocks are cut out and placed automatically.
</p>
<p>
They are also great for presentations, and taking notes in a CS class
</p>
<p>
These blocks are run with &ldquo;C-c C-c&rdquo;
</p>
</div>
</div>
<div id="outline-container-org9ceb068" class="outline-4">
<h4 id="org9ceb068"><span class="section-number-4">4.1.3.</span> Math homework in org mode</h4>
<div class="outline-text-4" id="text-4-1-3">
<p>
Org mode also has amazing LaTeX support. It&rsquo;s really easy to add mathematical symbols in an org mode document.
</p>
</div>
<ol class="org-ol">
<li><a id="org0e3a524"></a>Inline org mode math<br />
<ol class="org-ol">
<li><a id="org203efc0"></a>A function f<br />
<div class="outline-text-7" id="text-4-1-3-0-1-1">
<p>
S = {students at USU}
M = {members of FSLC}
B = {cool, uncool}
</p>
<p>
f : S &rarr; B &ni; f(x) = {
cool (x &isin; M),
uncool
}
</p>
</div>
</li>
<li><a id="org87287e7"></a>Definition of a proper subset<br />
<div class="outline-text-7" id="text-4-1-3-0-1-2">
<p>
Let A,B be sets:
A &sub; B &hArr; &forall; x (x &isin; A &rArr; x &isin; B) &and; A &ne; B
</p>
</div>
</li>
<li><a id="org452addb"></a>Let&rsquo;s make it pretty!<br />
<div class="outline-text-7" id="text-4-1-3-0-1-3">
<p>
Right now, it doesn&rsquo;t look pretty, but watch this:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #51afef;">(</span><span style="color: #c678dd;">org-toggle-pretty-entities</span><span style="color: #51afef;">)</span>
</pre>
</div>
</div>
</li>
</ol>
</li>
<li><a id="org669a24d"></a>Exporting to LaTeX<br />
<div class="outline-text-6" id="text-4-1-3-0-2">
<p>
There&rsquo;s still a lot more flexibility in completely exporting an org mode document to a LaTeX pdf. You can define equations, include diagrams, captions, etc. It&rsquo;s super simple too! Just use the command `C-c C-e l o` (you need latex packages installed)
</p>
</div>
</li>
</ol>
</div>
<div id="outline-container-org5f332b5" class="outline-4">
<h4 id="org5f332b5"><span class="section-number-4">4.1.4.</span> Export to literally any format</h4>
<div class="outline-text-4" id="text-4-1-4">
<p>
With the export menu, you can easily export to Open Office documents, HTML pages, Markdown, iCalendar (you can make agendas in Emacs), really anything!
</p>
</div>
</div>
</div>
<div id="outline-container-orgeae2586" class="outline-3">
<h3 id="orgeae2586"><span class="section-number-3">4.2.</span> Amazing package support and community</h3>
<div class="outline-text-3" id="text-4-2">
<p>
Yeah yeah, vim has packages too&#x2026; but they&rsquo;re not as cool or easy to install as Emacs :)
</p>
<p>
The emacs community has made an insane amount of useful packages that are super easy to install. Here are a few:
</p>
</div>
<div id="outline-container-org384b002" class="outline-4">
<h4 id="org384b002"><span class="section-number-4">4.2.1.</span> MELPA</h4>
<div class="outline-text-4" id="text-4-2-1">
<p>
Essentially a repository of user-made extensions for Emacs. Think of this as the AUR.
</p>
</div>
</div>
<div id="outline-container-org2cec309" class="outline-4">
<h4 id="org2cec309"><span class="section-number-4">4.2.2.</span> SLIME</h4>
<div class="outline-text-4" id="text-4-2-2">
<p>
Get into a great Lisp interactive session!
</p>
</div>
</div>
<div id="outline-container-org8692c74" class="outline-4">
<h4 id="org8692c74"><span class="section-number-4">4.2.3.</span> Magit</h4>
<div class="outline-text-4" id="text-4-2-3">
<p>
Great for git interaction!
</p>
</div>
</div>
<div id="outline-container-org4b39e5d" class="outline-4">
<h4 id="org4b39e5d"><span class="section-number-4">4.2.4.</span> Company-mode</h4>
<div class="outline-text-4" id="text-4-2-4">
<p>
For completion
</p>
</div>
</div>
<div id="outline-container-org167ed70" class="outline-4">
<h4 id="org167ed70"><span class="section-number-4">4.2.5.</span> Undo-tree</h4>
<div class="outline-text-4" id="text-4-2-5">
<p>
For undoing your work in a neater fashion
</p>
</div>
</div>
<div id="outline-container-org9b1f6b7" class="outline-4">
<h4 id="org9b1f6b7"><span class="section-number-4">4.2.6.</span> LSP-mode</h4>
<div class="outline-text-4" id="text-4-2-6">
<p>
For running language servers
</p>
</div>
</div>
</div>
<div id="outline-container-org966691d" class="outline-3">
<h3 id="org966691d"><span class="section-number-3">4.3.</span> It&rsquo;s written in Lisp</h3>
<div class="outline-text-3" id="text-4-3">
<p>
We&rsquo;ve already taken a look at Elisp, but Lisp goes far more in depth than our simple breach of the surface. It&rsquo;s by far my favorite language, and it has influenced language since its creation in the 60&rsquo;s (10 years before C).
</p>
<p>
Lisp is wholly functional, which is great in comparison to ugly Object-Oriented languages like Java.
(Really, OOP is fine where necessary but it gets really bloated really really fast)
</p>
</div>
</div>
</div>
<div id="outline-container-org86d0202" class="outline-2">
<h2 id="org86d0202"><span class="section-number-2">5.</span> First steps in going forward with Emacs</h2>
<div class="outline-text-2" id="text-5">
</div>
<div id="outline-container-org8dbd14d" class="outline-3">
<h3 id="org8dbd14d"><span class="section-number-3">5.1.</span> Want to learn ELisp?</h3>
<div class="outline-text-3" id="text-5-1">
<p>
I recommend reading &ldquo;Writing GNU Emacs Extensions&rdquo;. It goes into detail with Lisp, Emacs functions, and how everything works under the hood. It&rsquo;s an O&rsquo;Reilly book, so you get it free through USU.
</p>
</div>
</div>
<div id="outline-container-org7b98e1f" class="outline-3">
<h3 id="org7b98e1f"><span class="section-number-3">5.2.</span> Want to get started with Emacs?</h3>
<div class="outline-text-3" id="text-5-2">
<p>
Dive right into emacs by installing it with whatever package manager you use.
</p>
<p>
Read the guide that is accessible on the default emacs start page! It will teach you the basics of movement and usage of the software. From there, just search around the internet for resources. There are plenty.
</p>
<p>
If you need help or a recommendation, you can start <a href="https://www.emacswiki.org/emacs/EmacsNewbie">at the emacs wiki.</a> Or ask on the FSLC Discord in the `emacs-lisp` channel.
</p>
</div>
</div>
</div>
<div id="outline-container-orga0006b1" class="outline-2">
<h2 id="orga0006b1"><span class="section-number-2">6.</span> The compromise</h2>
<div class="outline-text-2" id="text-6">
</div>
<div id="outline-container-org4832571" class="outline-3">
<h3 id="org4832571"><span class="section-number-3">6.1.</span> Can&rsquo;t decide which is better (it&rsquo;s emacs)? Good news! You don&rsquo;t have to!</h3>
<div class="outline-text-3" id="text-6-1">
<p>
Let&rsquo;s take a look at the &ldquo;evil-mode&rdquo; package. This project aims to have 100% vim emulation within emacs. Whatever Vim can do, Evil Mode can do it too.
</p>
<p>
A great pre-built bundle for Emacs, called <a href="https://github.com/hlissner/doom-emacs">Doom Emacs</a>, is great for new users who have familiarity with vim keybindings.
</p>
</div>
</div>
<div id="outline-container-org1231631" class="outline-3">
<h3 id="org1231631"><span class="section-number-3">6.2.</span> More on Doom</h3>
<div class="outline-text-3" id="text-6-2">
<p>
Personally, I used to use my own Emacs configuration that I wrote my own extensions in Lisp for, but Doom has much saner defaults so I switched. Default Emacs looks ugly as hell:
</p>
<div id="orgcaf8af1" class="figure">
<p><img src="./images/emacs_default.png" alt="emacs_default.png" />
</p>
</div>
</div>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: Simponic</p>
<p class="date">Created: 2021-10-13 Wed 22:01</p>
</div>
</body>
</html>

655
emacs.org
View File

@ -1,418 +1,331 @@
#+TITLE: EMACS - the Extensible Machine Aggregating Creative S-Expressions.
#+AUTHOR: simponic
#+STARTUP: inlineimages fold
#+TITLE: Emacs - "Editor MACroS"
#+AUTHOR: Simponic
#+DESCRIPTION: An emacs presentation
#+STARTUP: fold inlineimages
[[./img/xkcd.png]]
* XKCD
[[./images/real_programmers.png]]
* what is emacs?
well... whatever it is, it's better than valve's Steam!
* What is Emacs?
* From [[https://www.gnu.org/software/emacs/][GNU.org]]:
Emacs is "an extensible, customizable, free/libre text editor — and more. At its core is an interpreter for Emacs Lisp, a dialect of the Lisp programming language with extensions to support text editing."
* what?
* yes, emacs is a gaming platform
** some tetris?
** Emacs history
*** From the [[https://www.emacswiki.org/emacs/EmacsHistory][EmacsWiki]]:
Emacs began at the Artificial Intelligence Laboratory at MIT. Beginning in 1972, staff hacker CarlMikkelsen added display-editing capability to TECO, the text editor on the AI Labs IncompatibleTimeSharingSystem (ITS) “Display-editing” meant that the screen display was updated as the user entered new commands; compare the behavior of "ed". In 1974, Richard Stallman added macro features to the TECO editor.
comes with emacs.
In 1976, Stallman wrote the first Emacs (“Editor MACroS”), which organized these macros into a single command set and added facilities for SelfDocumentation and to be extensible.
#+BEGIN_SRC emacs-lisp
(tetris)
[[https://www.jwz.org/doc/emacs-timeline.html][A Map Of Emacs History Until 2007]]
** Emacs is a super extensible "editor" that is written in Elisp
*** "Editor"
**** Emacs does much more than edit text
- To show itself off, Emacs by default comes with a full game of tetris!
#+BEGIN_SRC emacs-lisp :results silent
(tetris)
#+END_SRC
- Besides being a great tool to play tetris when you're bored and your boss is looking away, Emacs can also:
1. Write emails with the `mu4e` package
2. Write documents with Org Mode (more on this later)
3. Be your window manager with the exwm package
+ I've given this a try, but I'm gonna stick with dwm
4. Browse the internet with eww!
+ Eww in action
#+BEGIN_SRC emacs-lisp :results silent
(eww "https://gnu.org")
#+END_SRC
*** Emacs Glossary
**** Weird key-binding notation?
+ "C" is control
+ "M" is alt/meta
+ "S" is shift
When there is a "-" between two keys that means press them together.
"C-x C-f": Control and x and then control and f (you can also hold down control)
**** What is a "buffer"?
Buffers hold a file's text. In the example before with Tetris, `(tetris)` creates a Tetris buffer.
You can think of buffers as "tabs" in a browser or GUI text editor
**** What is a "window"?
A window hosts a buffer. When you make a split, each side is a "window"
Cycle between windows with "C-x C-o"
Close a window with "C-x 0"
**** What is a "frame"?
A frame hosts a complete instance Emacs. They are equivalent to "windows" in a window manager. It's common to only really ever use one.
**** Good-to-know keybindings
1. Quit emacs with "C-x C-c"
2. Open a file with "C-x C-f"
3. Save a file with "C-x C-s"
4. Accidentally pressed a different command and you have no idea what you're looking at? "C-g" will probably get you out of it.
5. "C-x u" to undo
6. "C-space" to select a region and "C-g" to stop selecting it
7. With a region selected, cut it with "C-w" (this is also known as "killing")
8. Paste with "C-y" (this is also known as "yanking")
9. Window/buffer keybindings:
+ "C-x C-b" changes the buffer in the current window
+ "C-x 2" splits a buffer vertically
+ "C-x 3" splits a buffer horizontally
+ "C-x o" changes the current window
+ "C-x 0" kills the current window
+ "C-x k" kills the current buffer
10. Movement keys
+ "C-n" goes to the next line
- Vim: "j"
+ "C-p" goes to the previous line
- Vim: "k"
+ "C-f" goes to the next character
- Vim: "l"
+ "C-b" goes to the previous character
- Vim: "h"
+ "M-f" and "M-b" goes forward/back a word
- Vim: "f" and "b"
+ "C-a" goes to beginning of a line
- Vim: "0"
+ "C-e" goes to the end of a line
- Vim: "$"
11. Documentation
+ "C-h a" to find the keybindings for a command, or to search for a command
+ "C-h k" to find the name of a function tied to a keybinding
** First look at Elisp
Elisp is a dialect of Lisp specifically written for Emacs. Everything in Elisp is a function. Drawing the buffer, splitting windows, moving the text cursor, are all functions you can call in Elisp. It makes it super easy to configure Emacs if you know just a little bit of Lisp.
In fact, let's take a look at Elisp and how we can start to customize our own environment programatically.
*** Lisp's simple syntax
In Lisps, the syntax is super simple. Everything is essentially a linked list, both in data and in source code. Lists are written like `(a . (b . (c . NIL)))`. This would be equivalent to the linked list `a -> b -> c -> null` (nil = null = false in lisp).
However, writing a dot and a period becomes cumbersome when you have even a medium sized list. This is where s-expressions are useful.
S-expressions are written with parentheses around them, like so: `(a b c)`. This is shorthand for the above `(a . (b . (c . NIL)))`.
By convention, Lisp code is written with the function as the first element in the linked list, and arguments of the function afterwards.
**** Sum of numbers
***** The list way
#+BEGIN_SRC emacs-lisp :result output
(+ . (2 . (2 . nil))) ;; 2 + 2
#+END_SRC
** or bubbles?
comes with emacs.
#+BEGIN_SRC emacs-lisp
(bubbles)
#+RESULTS:
: 4
***** The S-expression way
#+BEGIN_SRC emacs-lisp :result output
(+ 2 2)
#+END_SRC
** or the game of life?
#+RESULTS:
: 4
believe it or not, comes with emacs.
#+BEGIN_SRC emacs-lisp
(life)
**** Difference of numbers
#+BEGIN_SRC emacs-lisp :result output
(- 3 2) ;; 3 - 2
#+END_SRC
* why have a web browser when you can have emacs?
#+RESULTS:
: 1
**** Printing values
`princ` will take the value of a lisp object at print it:
#+BEGIN_SRC emacs-lisp
(eww "https://print.linux.usu.edu")
#+BEGIN_SRC emacs-lisp :result output
(princ "Hello, world!")
#+END_SRC
* or an init system when you can have emacs?
[[https://github.com/a-schaefers/systemE]]
* or a window manager when you can have emacs?
[[https://github.com/ch11ng/exwm]]
* or a therapist when you can have emacs?
emacs can help you solve all your life's issues. literally.
#+BEGIN_SRC emacs-lisp
(doctor)
#+RESULTS:
: Hello, world!
**** Multiplication
#+BEGIN_SRC emacs-lisp :result output
(* 3 5) ;; 3 * 5
#+END_SRC
* or a trongleposting server... in anything but emacs?
that's right. a RESTful API, websocket server, and static file HTTP server. in ELisp. in Emacs.
does this not blow your mind??
#+BEGIN_SRC emacs-lisp
(use-package web-server
:ensure t
:straight '(web-server
:type git
:host github
:repo "eschulte/emacs-web-server"))
(defvar *trongle-chats* (make-ring 100)) ;; "db"
(defvar *static* "/home/lizzy/git/usufslc/emacs/trongleposting-client/build/") ;; npm run build
(defvar *chatlog* "/home/lizzy/git/usufslc/emacs/log/emacs-presie.txt")
(defvar *index* (concat *static* "index.html"))
(defvar *port* 9000)
(defvar *safe-chars* "^[ A-Za-z0-9._~()'!*:@,;+?-]+$")
(defvar *clients* '())
(defun current-iso-time ()
(format-time-string "%FT%T%:z"))
(defun safe-string-p (s &optional regex)
(unless regex (setq regex *safe-chars*))
(if (null s)
nil
(not (null (string-match regex s)))))
(defun validate-chat (chat)
(seq-every-p
'safe-string-p
(mapcar (lambda (field)
(cdr (assoc field chat)))
'(author message))))
(defun deflate-chat (chat)
(let ((parsed-j (json-parse-string chat)))
`((author . ,(gethash "author" parsed-j))
(message . ,(gethash "message" parsed-j)))))
(defun inflate-chat (chat)
(json-serialize chat))
(defun inflate-chat-list (chats)
(json-serialize
(vconcat [] chats)))
(defun remove-client (process event)
(setq *clients* (seq-filter
(lambda (proc)
(not (equal process proc)))
,*clients*)))
(defun handle-ws (proc input)
(setq *clients* (cons proc *clients*))
(set-process-sentinel proc 'remove-client)
(process-send-string proc (ws-web-socket-frame "pong")))
(defun new-post (request)
(with-slots (process headers) request
(let* ((body (ws-body request))
(chat (deflate-chat body)))
(if (validate-chat chat)
(let* ((chat (cons `(date . ,(current-iso-time)) chat))
(chat-json (inflate-chat chat)))
;; store and log
(ring-insert *trongle-chats* chat)
(append-to-file (concat chat-json "\n") nil *chatlog*)
;; propogate to open clients
(mapcar (lambda (client)
(process-send-string
client
(ws-web-socket-frame (inflate-chat chat))))
,*clients*)
(ws-response-header process 200 '("Content-Type" . "application/json"))
(process-send-string process (json-serialize '((success . t)))))
(ws-response-header process 400 '("Content-Type" . "application/json"))
(process-send-string process (json-serialize
'((error . "invalid chat")
(success . :false))))))))
(defun list-posts (request)
(with-slots (process headers) request
(ws-response-header process 200 '("Content-Type" . "application/json"))
(process-send-string process
(inflate-chat-list
(reverse (ring-elements *trongle-chats*))))))
(defun retrieve-static-file (request)
(with-slots (process headers) request
(let* ((path (replace-regexp-in-string "^/" "" (cdr (assoc :GET headers)))))
(if (equal path "")
(ws-send-file process *index*)
(if (ws-in-directory-p *static* path)
(if (file-directory-p path)
(ws-send-404 process)
(ws-send-file process
(expand-file-name path *static*)))
(ws-send-404 process))))))
(ws-start
`(((:POST . "/posts") . new-post)
((:GET . "/posts") . list-posts)
((:GET . ".*") .
(lambda (request)
(if (ws-web-socket-connect request 'handle-ws)
:keep-alive
(retrieve-static-file request)))))
,*port*)
#+RESULTS:
: 15
**** Division
(Integer math)
#+BEGIN_SRC emacs-lisp :result output
(princ (/ 3 5)) ;; 3 / 5
#+END_SRC
* EEE-macs
i've come up with "Three E's" that kind of cover emacs' design tenets and goals:
** 1. be Extensible
this is the first and foremost goal of emacs, and one that should certainly be demonstrated by
the above demos.
the only limit is your creativity. and with a fully bytecode JIT compilable LISP, that
creativity is (don't quote me) _Easy to Express_.
** 2. be Evolving
like many other softwares, emacs is a living and breathing creature that is continuously
growing.
the emacs community aims to make emacs the provider of an experience at the bleeding edge
of writing software. major releases often bring about huge features that "evolve" emacs:
1. native lsp support (~tree-sitter~, ~eglot~ in 29 - 2023)
2. elisp JIT compiler to emacs bytecode (28.1 - 2022)
3. pixel precise scrolling (long awaited)
(there's a joke here about emacs still being single threaded somewhere...)
** 3. be Easy as possible
while emacs may not adhere to the unix philosophy, it is easy to grok by anyone that
has used a text editor before.
even with no experience, today _you_ could simply drop into ~emacs test.c~ and begin
writing text. there's no weird "action modes" that require a barrier of entry to write
code - besides knowing the key combination to save and quit, and how to press arrow keys.
there's no necessary ~emacstutor~.
people even create specific "distributions" of emacs like linux itself to provide a simple
interface for beginners to even further lower the **mean delta time to become dangerous**.
at the same time, emacs is more rich in features than any other software due to its
extensibility. the further you go, the easier it gets. emacs is self documenting in itself
(i.e. ~describe-*~) and has great online docs too.
* so what does the FSF say?
#+BEGIN_QUOTE
"
Emacs is "an extensible, customizable, free/libre text editor — and more.
At its core is an interpreter for Emacs Lisp, a dialect of the Lisp programming
language with extensions to support text editing.
"
- https://www.gnu.org/software/emacs
#+END_QUOTE
_hopefully_ this is starting to make sense...
* final answer
so to answer the question, "what is emacs?"...
0. it's a text editor
1. it's a window manager
2. it's a rich email client
3. it's a native IDE for ELISP, with optional support for all other languages
4. it's a web browser
5. it's a gaming console
6. it's an interpreter
7. it's a document editor (more on this later)
8. it's the love of my life (... what)
9. ~<insert your thing here>~
...maybe it's best to ask, "what is it not?".
and the answer to that, dear reader, is that emacs is not a good text editor :)
* ORG mode
you may've noticed i have these little guys here in my presentation:
#+BEGIN_SRC emacs-lisp :results output
(princ "I run in a source block!")
#+RESULTS:
: 0
(Floating-point math)
#+BEGIN_SRC emacs-lisp :result output
(princ (/ 3.0 5)) ;; 3 / 5
#+END_SRC
these are source blocks! blocks of code that can be run interactively in an "org" file; like a jupyter
notebook.
#+RESULTS:
: 0.6
org is by far my most used environment in emacs, outside of editing code. but what's an "org" file?
**** Order of operations
#+BEGIN_SRC emacs-lisp :result output
(setq a (/ (* 2 3) (- 6 1))) ;; variable a = (2 * 3) / (6 - 1) = 1
(setq b (- (* 2 (/ 3.0 6.0)) 1)) ;; variable b = (2 * (3 / 6)) - 1 = 0
(princ (list a b)) ;; Print a linked list a -> b -> nil
#+END_SRC
well, like the question "what is emacs?" itself, it's another very complicated answer.
"org" is a...
0. presentation software (what you see here)
1. calendar
2. latex editor
3. markdown editor
4. html editor
5. obsidian alternative
6. open office editor
7. programming notebook
8. ...
* "your life, in plain text"
every single org file is simply plain text. that's the **elegancy**. thus, any way there is to
structure code, can also be applied to org files.
as such, it's common for emacs users to define their ~init.el~ (the bootstrap config script run when
emacs starts) in an org mode document, whose source-blocks are "compiled" into an ~init.el~ file.
then one can add notes to one's code, organizing it into separate "trees" of concerns.
and certainly org is "your life" - ~org-roam~ is a whole second **extensible** [[https://systemcrafters.net/build-a-second-brain-in-emacs/getting-started-with-org-roam/][brain]].
* students, this is for you
emacs is godly for math and cs students. between this "interactive notebook" and latex editor,
you can write stuff without the overhead of ~LaTeX~.
introducing a function f:
S = { students at USU }
M = { members of FSLC }
B = { cool, uncool }
f : S \rightarrow B \ni f(x) = {
cool (x \in M),
uncool
}
definition of a proper subset:
A \subset B \Leftrightarrow \forall x (x \in A \Rightarrow x \in B) \wedge A \neq B
right now, it doesn't look pretty, but watch this:
#+RESULTS:
| 1 | 0.0 |
*** Writing a simple function in Elisp
Here I will split this window into three sections with Elisp:
#+BEGIN_SRC emacs-lisp :results silent
(org-toggle-pretty-entities)
(split-window-right)
(split-window-below)
#+END_SRC
with the built-in emacs pdf viewer it's also easy to completely export a document to latex and view
its compilation. perfect for assignments!
To cycle forward through these windows, I press "C-x C-o".
* buffers, windows, frames, oh my
However, what if I want to go back a window?
to get you in the world of emacs, i should at least introduce the very basics.
Emacs doesn't provide a keybinding for this by default (to my knowledge), so let's make it in Elisp ourselves!
+ frames are the "top level instance" of emacs. they're the actual "window" controlled by
your window manager or terminal emulator in the instance of a tui; you can drag it around
and such.
**** Definining a function to go back a window
Functions in Elisp are made with the `defun` macro (macros are for a different presentation) and the syntax is:
+ buffers are interfaces between your emacs client and a file (or process). it's what controls
the individual text on the screen.
`(defun function-name (list-of-args) function-body)`
+ windows simply hold buffers; think of a "glass window" into a buffer.
i.e. i can create a new window split in my frame
The last element in the function body is what is returned
#+BEGIN_SRC emacs-lisp
(split-window-below)
For example, to make a function to find the hypotenuse of a right triangle with lengths a,b:
#+BEGIN_SRC emacs-lisp :results output
(defun pythagoras (a b)
(setq a-squared (* a a))
(setq b-squared (* b b))
(sqrt (+ a-squared b-squared)))
(princ (pythagoras 5 12))
#+END_SRC
i now have two windows, "viewing" the buffer representing the org file of this presentation.
#+RESULTS:
: 13.0
* modes
#+BEGIN_QUOTE
"
A mode is a set of definitions that customize Emacs behavior in useful ways.
There are two varieties of modes: minor modes, which provide features that users can turn on
and off while editing; and major modes, which are used for editing or interacting with a particular
kind of text.
" - https://www.gnu.org/software/emacs/manual/html_node/elisp/Modes.html
#+END_QUOTE
by example, "ORG MODE", a major mode, tells emacs how to format the buffer to a window and draw
all the neat little symbols and indentation.
by contrast ~format-all-mode~ is a minor mode that might look at the major mode (maybe LISP mode, or
C mode) and determines a formatter to auto-format a buffer's file on save.
* key bindings
there's a reason it's called "emacs pinky"
[[./img/emacs_user_fingers.png]]
anyways, you should absolutely know:
+ "C-x C-s" (ctrl-x ctrl-s) to save a file
+ "C-x C-c" (ctrl-x ctrl-c) to quit an emacs frame
+ "C-g" (ctrl-g) to cancel something (in most cases) if you fuck up
+ "C-x u" (ctrl-x u) to undo
+ "M-x butterfly" (meta / alt - x) "butterfly"
* getting started
you don't really every need to get good in ELISP to use emacs, despite what you may've been lead to
believe in this presentation.
all you need is the help screen. when you open emacs without a file specified, this is what
you're greeted with.
* so is emacs better than vim?
** let's see what trongle has to say
#+BEGIN_SRC
____________________________________________________
/ \
| i'm gonna start using emacs to write my rust |
----------------------------------------------------
\\ :::.
\\ .::::::
\\ :::::::::
\\ .:::::::;od8888bo.
::::::::OP?'::`*YO?
.:::::::::::::::::.
,od8888bo;::::::d88b::
*":d88b:"*::::::Y88D:::
.:::Y88D::::::::::YP:::::.
::::::YP::::::::::::::::::::
::::::::::::::::::::::::::::::. .oo.
.:::::::::::::::::::::oOOb:::::::. ,oOOOD
::::::::::::d8b:::::::::*OOO::::::;oOOOOP"
::::::::::::::`*Y88888P:::OOOb:::;dOOOP"
.::::::::::::::::::::::::::;OOOD:/dOOOOo::
.::::::::::::::::::::::::::;OOOOOOOOOOOOO*::
.:::::::::::::::::::::::::::oOOOOOOOOOOOOOOD::.
`:::::::::::::::::::::::::::OOOOOOOOOOOOOOOB::'
*OOOOOOOOOOOOOOD
`*OOOOOOOOOOP"
`"OOOP*"
Defining the function
#+BEGIN_SRC emacs-lisp :results silent
(defun go-back-window ()
(interactive) ;; makes a function an interactively-callable command (e.g. allowing call by a keybinding)
(other-window -1)) ;; (other-window n) goes n windows forward in the window stack
#+END_SRC
thank you trongle! very insightful.
#+BEGIN_SRC emacs-lisp :results silent
(go-back-window)
#+END_SRC
** in all seriousness
Let's add a key binding for this!
... well the answer is **it doesn't matter**. none is greater than the other.
#+BEGIN_SRC emacs-lisp :results silent
(global-set-key (kbd "C-c u") 'go-back-window) ;; We specify the name of the function by turning it into a "symbol"
#+END_SRC
hahahah!! just kidding! yes, of _course_ emacs is better than vim.
** can't decide? be EVIL
* Why is Emacs better than Vim?
** Org mode
*** "Your life, in plain text"
Every single org file is represented in Plain Text. Similar to markdown, it's a way to format this plain text so that it's readable and understandable by humans, but still parsable and extensible for programmers. This presentation itself is in org mode!
[[./img/yay_evil.png]]
*** Programming in org mode
You may have noticed these things here in my presentations:
if you want to be EVIL and "emulate" vim in emacs, there's EVIL mode.
#+BEGIN_SRC emacs-lisp :results output
(princ "I run in a source block!")
#+END_SRC
EVIL mode aims to be near 100% compatible with all things vim. Doom Emacs
and Spacemacs are somewhat sane distributions of Emacs meant for recent
converts to the Church of Emacs that may know a thing or two about ViM
bindings.
#+RESULTS:
: I run in a source block!
and... a recent convert to being EVIL... take it away, Ethan!
These blocks, called "source blocks", are blocks of code you can run interactively in an org mode document. It's incredibly common for emacs users to define their init.el (the file emacs will run first when it starts up) in an org mode document, whose source-blocks are cut out and placed automatically.
They are also great for presentations, and taking notes in a CS class
These blocks are run with "C-c C-c"
*** Math homework in org mode
Org mode also has amazing LaTeX support. It's really easy to add mathematical symbols in an org mode document.
***** Inline org mode math
****** A function f
S = {students at USU}
M = {members of FSLC}
B = {cool, uncool}
f : S \rightarrow B \ni f(x) = {
cool (x \in M),
uncool
}
****** Definition of a proper subset
Let A,B be sets:
A \subset B \Leftrightarrow \forall x (x \in A \Rightarrow x \in B) \wedge A \neq B
****** Let's make it pretty!
Right now, it doesn't look pretty, but watch this:
#+BEGIN_SRC emacs-lisp :results silent
(org-toggle-pretty-entities)
#+END_SRC
***** Exporting to LaTeX
There's still a lot more flexibility in completely exporting an org mode document to a LaTeX pdf. You can define equations, include diagrams, captions, etc. It's super simple too! Just use the command `C-c C-e l o` (you need latex packages installed)
*** Export to literally any format
With the export menu, you can easily export to Open Office documents, HTML pages, Markdown, iCalendar (you can make agendas in Emacs), really anything!
** Amazing package support and community
Yeah yeah, vim has packages too... but they're not as cool or easy to install as Emacs :)
The emacs community has made an insane amount of useful packages that are super easy to install. Here are a few:
*** MELPA
Essentially a repository of user-made extensions for Emacs. Think of this as the AUR.
*** SLIME
Get into a great Lisp interactive session!
*** Magit
Great for git interaction!
*** Company-mode
For completion
*** Undo-tree
For undoing your work in a neater fashion
*** LSP-mode
For running language servers
** It's written in Lisp
We've already taken a look at Elisp, but Lisp goes far more in depth than our simple breach of the surface. It's by far my favorite language, and it has influenced language since its creation in the 60's (10 years before C).
Lisp is wholly functional, which is great in comparison to ugly Object-Oriented languages like Java.
(Really, OOP is fine where necessary but it gets really bloated really really fast)
* First steps in going forward with Emacs
** Want to learn ELisp?
I recommend reading "Writing GNU Emacs Extensions". It goes into detail with Lisp, Emacs functions, and how everything works under the hood. It's an O'Reilly book, so you get it free through USU.
** Want to get started with Emacs?
Dive right into emacs by installing it with whatever package manager you use.
Read the guide that is accessible on the default emacs start page! It will teach you the basics of movement and usage of the software. From there, just search around the internet for resources. There are plenty.
If you need help or a recommendation, you can start [[https://www.emacswiki.org/emacs/EmacsNewbie][at the emacs wiki.]] Or ask on the FSLC Discord in the `emacs-lisp` channel.
* The compromise
** Can't decide which is better (it's emacs)? Good news! You don't have to!
Let's take a look at the "evil-mode" package. This project aims to have 100% vim emulation within emacs. Whatever Vim can do, Evil Mode can do it too.
A great pre-built bundle for Emacs, called [[https://github.com/hlissner/doom-emacs][Doom Emacs]], is great for new users who have familiarity with vim keybindings.
** More on Doom
Personally, I used to use my own Emacs configuration that I wrote my own extensions in Lisp for, but Doom has much saner defaults so I switched. Default Emacs looks ugly as hell:
[[./images/emacs_default.png]]

BIN
images/emacs_default.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
images/real_programmers.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

View File

View File

@ -1,2 +0,0 @@
.env*
node_modules/*

View File

@ -1,23 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@ -1,70 +0,0 @@
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"crypto-js": "^4.1.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"socket.io-client": "^4.4.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,45 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="TronglePosting in our god language ELisp"
/>
<link rel="icon" type="image/x-icon" sizes="512x512" href="/favicon.ico" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>TrongELISPosting</title>
</head>
<body>
<noscript
>TronglePosting requires our unholy language JavaScript (no relation to
java).</noscript
>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -1,8 +0,0 @@
{
"short_name": "Dockerposting",
"name": "Dockerposting docker docker docker docker",
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -1,78 +0,0 @@
body {
font-family: Consolas, monaco, monospace;
color: #fbf1c7;
margin: 0;
background-color: #3c3836;
}
.container {
max-width: 900px;
width: 80%;
border: 1px solid #b16286;
border-radius: 8px;
margin: 0;
padding: 24px;
position: absolute;
top: 50%;
left: 50%;
-moz-transform: translateX(-50%) translateY(-50%);
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
background-color: #282828;
box-shadow: rgb( 0, 0, 0, 0.6) 6px 45px 45px -12px;
}
.chat {
border-bottom: 1px solid #d65d0e;
height: 200px;
overflow-y: scroll;
padding-bottom: 12px;
}
* {
scrollbar-width: thin;
scrollbar-color: #d5c4a1 rgba(0,0,0,0);
}
*::-webkit-scrollbar {
width: 4px;
}
*::-webkit-scrollbar-track {
background: rgba(0,0,0,0);
}
*::-webkit-scrollbar-thumb {
background-color: #d5c4a1;
border-radius: 12px;
}
.input {
font-size: 16px;
font-size: max(16px, 1em);
font-family: inherit;
padding: 0.25em 0.5em;
background-color: rgba(0,0,0,0);
border: none;
border-bottom: 1px solid #83a598;
color: #d5c4a1;
margin-top: 12px;
margin-bottom: 12px;
display: block;
}
.input:focus {
outline: none;
}
.button {
padding: 12px;
cursor: pointer;
border: 1px solid #8ec07c;
color: #8ec07c;
border-radius: 8px;
display: inline-block;
}

View File

@ -1,126 +0,0 @@
import { useRef, useState, useEffect } from "react";
import { generateGruvboxFromString } from "./utils/generate_gruvbox";
import "./App.css";
function App() {
const [socket, setSocket] = useState(null);
const [posts, setPosts] = useState([]);
const postsRef = useRef([]);
const [content, setContent] = useState("");
const [username, setUsername] = useState("");
const [error, setError] = useState("");
const [color, setColor] = useState("");
const scrollToBottomOfChat = () => {
const objDiv = document.getElementById("chat");
objDiv.scrollTop = objDiv.scrollHeight;
};
useEffect(() => {
const protocol = document.location.protocol === "https:" ? "wss:" : "ws:";
let socket;
fetch("/posts")
.then((r) => r.json())
.then((msgs) => {
postsRef.current = msgs;
setPosts(postsRef.current);
scrollToBottomOfChat();
})
.then(() => {
socket = new WebSocket(`${protocol}//${document.location.host}/`);
socket.addEventListener("open", () => {
socket.send("ping");
});
socket.addEventListener("message", (msg) => {
const { data } = msg;
if (data === "pong") return;
const chat = JSON.parse(msg.data);
if (chat.author) {
postsRef.current = [...postsRef.current, chat];
setPosts(postsRef.current);
scrollToBottomOfChat();
}
});
setSocket(socket);
});
return () => {
socket.close();
};
}, []);
useEffect(() => {
setColor(generateGruvboxFromString(username));
}, [username]);
const addPost = () => {
setError("");
if (socket) {
fetch("/posts", {
method: "POST",
headers: { Content: "application/json" },
body: JSON.stringify({ author: username, message: content }),
}).then(() => setContent(""));
}
};
return (
<div className="container" style={{ border: `1px solid ${color}` }}>
<div style={{ textAlign: "center" }}>
<h2>TrongELISPosting</h2>
</div>
<div id="chat" className="chat">
<p>Welcome!</p>
{posts.map((post) => (
<div
key={post.id}
style={{
lineBreak: "normal",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
<div>
<span style={{ color: generateGruvboxFromString(post.author) }}>
{post.author}:{" "}
</span>
<span>{post.message}</span>
</div>
<div style={{ fontSize: "x-small" }}>
[{new Date(post.date).toLocaleString()}]
</div>
</div>
))}
</div>
<div>
<input
placeholder={"Username"}
className="input"
style={{ color }}
onChange={(e) => {
setUsername(e.target.value);
}}
value={username}
></input>
<textarea
placeholder={"Message"}
className="input"
onChange={(e) => setContent(e.target.value)}
value={content}
rows={1}
cols={40}
></textarea>
<div className="button" onClick={addPost}>
Post
</div>
{error ? <p style={{ color: "red" }}>{error}</p> : null}
</div>
</div>
);
}
export default App;

View File

@ -1,10 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

View File

@ -1,14 +0,0 @@
const gruvboxColors = [
"#b8bb26",
"#fabd2f",
"#83a598",
"#d3869b",
"#8ec07c",
"#458588",
"#cc241d",
"#d65d0e",
"#bdae93",
];
export const generateGruvboxFromString = (string) =>
gruvboxColors[Array.from(string).map((x) => x.charCodeAt(0)).reduce((a, x) => a+x, 0) % gruvboxColors.length];