summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Wilkie <antigravityd@gmail.com>2023-09-18 08:33:40 -0500
committerDuncan Wilkie <antigravityd@gmail.com>2023-09-18 08:33:40 -0500
commit84b6d6c6a7e55a606373607c054906f95d0f4ad3 (patch)
treeb32b45cf0dcd7f69c234ec9ecefd337bdae25a2d
parent339574faed9da546db432cc94b66e0ad9d10d4c2 (diff)
Emacs Lisp -> Scheme transpiler, implementing forms.el logic.
-rw-r--r--assets/css/style.css20
-rwxr-xr-xbuild-n-publish.sh10
-rw-r--r--dnw/forms.scm207
-rw-r--r--dnw/static-pages.scm18
-rw-r--r--dnw/theme.scm2
-rw-r--r--org/anarchofoss/anarchofoss.org48
6 files changed, 268 insertions, 37 deletions
diff --git a/assets/css/style.css b/assets/css/style.css
index 3f0accd..413d3ff 100644
--- a/assets/css/style.css
+++ b/assets/css/style.css
@@ -113,3 +113,23 @@ a:active {
text-align: center;
border-bottom: 5px double #292b2b;
}
+
+
+.forms-carousel {
+ margin: auto;
+ overflow: hidden;
+ position: relative;
+}
+
+.forms-carousel li {
+ white-space: pre-line;
+ border-bottom: 2px solid #292b2b;
+}
+
+.forms-carousel ul {
+ list-style: none;
+}
+
+.form-entry p {
+ font-family: Iosevka;
+}
diff --git a/build-n-publish.sh b/build-n-publish.sh
index 9ee2df9..bcd0cdb 100755
--- a/build-n-publish.sh
+++ b/build-n-publish.sh
@@ -1,8 +1,14 @@
#!/bin/sh
+# Make sure the library assets are synchronized:
+cd assets/library
+git fetch --all && git reset --hard origin/master
+cd ../..
+
# Build and publish the HTML site:
haunt build && haunt publish
+# Now convert to Gemini
# Uses https://github.com/LukeEmmet/html2gmi
# Converts the site into text/gemini; outputs to ./gemini.
# There is a publisher which copies that to /home/gemini/gemini/content on the remote.
@@ -34,9 +40,13 @@ for pic in $root/site/assets/image/*; do
cp $pic $root/gemini/assets/image/
done
+# Copy over relevant site assets to Gemland
cp $root/site/assets/cv.pdf $root/gemini/assets/
cp $root/site/assets/pubkey.txt $root/gemini/assets/
cp $root/site/feed.xml $root/gemini/
+# Refresh the Gemini site on the server.
rsync -r gemini/* root@$remotename:$remotedir
ssh root@functorial.xyz "systemctl restart agate"
+
+# TODO: see if committing and pushing interactively here makes sense.
diff --git a/dnw/forms.scm b/dnw/forms.scm
new file mode 100644
index 0000000..c163267
--- /dev/null
+++ b/dnw/forms.scm
@@ -0,0 +1,207 @@
+(define-module (dnw forms)
+ #:use-module (ice-9 peg)
+ #:use-module (ice-9 textual-ports)
+ #:use-module (ice-9 match)
+ #:use-module (ice-9 string-fun)
+ #:use-module (srfi srfi-1)
+ #:export (forms.el->sxml))
+
+
+
+;; Idea: function that takes in a git repository link pointing to something containing a forms file pair,
+;; and reads it in along with a mapping between whatever Elisp functions you use in forms-format-list
+;; and equivalent Scheme implementations (bc I can't figure out how to programmatically use Guile's Elisp support).
+;; It parses the .el file, creating a Scheme translation of your code, and then reimplements the forms.el logic,
+;; but outputs an SHTML interface instead.
+;; The necessary forms.el logic is basically:
+;; - read in data from forms-file as lists based on field-separator value,
+;; - filter out the list elements according to forms-read-file-filter,
+;; - replace the multi-line character with newlines,
+;; - iterate over the list elements, setting up a proper execution environment (defining forms-fields/forms-enumerate),
+;; - map over forms-format-list, replacing numbers with the corresponding field in the list element and evaluating code blocks,
+;; - put resulting string inside a corresponding display.
+
+
+
+(define-peg-string-patterns ;; An elisp "parser" that extracts relevant variables from the control file.
+ "form-control-file <- (setq/other-sexp/whitespace)+
+comment < ';' (!'\n' .)* '\n'?
+whitespace < (comment/[\r\n\t ])*
+
+setq <- OPEN-PAREN whitespace SETQ (whitespace name-value-pair/other-pair)* whitespace CLOSE-PAREN
+other-sexp < elisp-value
+
+name-value-pair <- whitespace name whitespace elisp-value
+other-pair < whitespace symbol whitespace elisp-value
+
+name <-- 'forms-file'/'forms-format-list'/'forms-number-of-fields'/'forms-field-sep'\
+/'forms-read-only'/'forms-multi-line'/'forms-read-file-filter'/'forms-write-file-filter'\
+/'forms-new-record-filter'/'forms-insert-after'/'forms-check-number-of-fields'
+
+elisp-value <- literal/function-access/quoted/quasiquoted/sexp
+sexp <-- OPEN-PAREN (whitespace elisp-value)* whitespace CLOSE-PAREN
+
+literal <- integer/float/character/string/symbol/vector
+FUNCTION-ACCESS-PREFIX < '#' [']
+function-access <- FUNCTION-ACCESS-PREFIX symbol
+quoted <-- QUOTE elisp-value
+quasiquoted <-- BACKTICK OPEN-PAREN (whitespace elisp-value/whitespace unquoted)* whitespace CLOSE-PAREN
+unquoted <-- COMMA whitespace elisp-value
+
+integer <-- decimal/binary/octal/hex
+sign <- ('+'/'-')
+digit <- [0-9]
+decimal <- sign? digit+ [.]?
+binary <- '#b' [01]+
+octdigit <- [0-7]
+octal <- '#o' octdigit+
+hexdigit <- [0-9a-fA-F]
+hex <- '#x' hexdigit+
+
+float <-- sign? digit* [.]? digit* [eE] ((sign? digit+)/'+INF'/'+NaN') / sign? digit* [.] digit+
+
+character <- control-character/named-character/hex-character/oct-character/self-character
+SELF-START < '?' '\\'?
+self-character <-- SELF-START .
+NAME-START < '?\\N{'
+NAME-END < '}'
+named-character <-- NAME-START (!'}' .)+ NAME-END
+HEX-START < '?\\x'
+hex-character <-- HEX-START hexdigit+
+OCT-START < '?\\'
+oct-character <-- OCT-START octdigit octdigit? octdigit?
+CONTROL-START < '?\\^'
+control-character <-- CONTROL-START alph
+
+string <- regular-string/propertized-string
+
+regular-string <-- '\"' ( '\\' '\"' / !'\"' .)* '\"'
+PROPERTIZED-START < '#('
+propertized-string <-- PROPERTIZED-START whitespace regular-string (whitespace elisp-value)* whitespace CLOSE-PAREN
+
+
+vector <-- OPEN-BRACKET (whitespace elisp-value)* whitespace CLOSE-BRACKET
+
+symbol <-- ((!digit symbol-char) symbol-char*)
+symbol-char <- '-'/[0-9a-zA-Z+=*/_~!@$%^&:<>{}?.]/('\\' .)
+
+alph <- [a-zA-Z]
+
+OPEN-PAREN < '('
+CLOSE-PAREN < ')'
+OPEN-BRACKET < '['
+CLOSE-BRACKET < ']'
+QUOTE < [']
+BACKTICK < '`'
+COMMA < ','
+QUESTION < '?'
+SETQ < 'setq'")
+
+(define (walk tree symbol-remapping)
+ (define (recurse tree2) (walk tree2 symbol-remapping))
+ (define (string1->character c) (car (string->list c)))
+ (define (read-string s) (call-with-input-string s read))
+
+ (match tree
+ (('sexp contents ...) (recurse contents))
+ (('quoted contents ...) (apply list (cons 'quote (recurse contents))))
+ (('quasiquoted contents ...) (apply list (cons 'quasiquote (recurse contents))))
+ (('unquoted contents ...) (apply list (cons 'unquote (recurse contents))))
+ (('vector contents ...) (list->vector (recurse contents)))
+ (('integer literal) (read-string literal))
+ (('float literal) (cond
+ ((string=? literal "1.0e+INF") +inf.0)
+ ((string=? literal "-1.0e+INF") -inf.0)
+ ((string=? literal "0.0e+NaN") +nan.0)
+ ((string=? literal "0.0e-NaN") +nan.0)
+ (else (read-string literal))))
+ (('self-character literal) (string1->character literal))
+ (((or 'named-character 'oct-character) literal) (read-string (string-append "#\\" literal)))
+ (('hex-character literal) (read-string (string-append "#\\x" literal)))
+ (('control-character literal) (integer->char
+ (- (char->integer (char-upcase (string1->character literal)))
+ 64)))
+ (('regular-string literal) (read-string literal))
+ (('propertized-string ('regular-string literal) (properties ...)) (read-string literal)) ;; Discard properties.
+ (('symbol literal) (let* ((symbol (string->symbol literal))
+ (lookup (assq-ref symbol-remapping symbol)))
+ (if lookup
+ lookup
+ symbol)))
+ (('name literal) (string->symbol literal))
+ ((other ...) (map recurse other))
+ (other other)))
+
+
+(define (forms.el->sxml control-file-contents data-file-contents extra-remapping)
+ (let* ((symbol-remapping (append extra-remapping
+ '((nil . ''())
+ (consp . pair?)
+ (atom . (lambda (x) (not (pair? x))))
+ (listp . list?)
+ (null . null?)
+ (nth . (lambda (x y) (list-ref y x)))
+ (stringp . string?)
+ (concat . string-append)
+ (split-string . string-split)
+ (string= . string=?)
+ (string-equal . string=?)
+ (t . #t))))
+ (parse-alist (map (lambda (pair) (cons (car pair) (cadr pair)))
+ (walk (peg:tree (match-pattern form-control-file control-file-contents)) symbol-remapping)))
+ (forms-file (assq-ref parse-alist 'forms-file))
+ (forms-format-list (cadr (assq-ref parse-alist 'forms-format-list)))
+ (forms-field-symbols (match (assq-ref parse-alist 'forms-number-of-fields)
+ (('forms-enumerate ('quote symbols)) (map (lambda (x y) (cons x y))
+ symbols
+ (iota (length symbols))))
+ (other '())))
+ (forms-field-sep (if (assq-ref parse-alist 'forms-field-sep)
+ (car (string->list (assq-ref parse-alist 'forms-field-sep)))
+ #\tab))
+ (forms-multi-line (if (assq-ref parse-alist 'forms-multi-line)
+ (assq-ref parse-alist 'forms-multi-line)
+ "\v"))
+ (split-data (filter (lambda (x)
+ (not (string-null? (apply string-append x))))
+ (map (lambda (record)
+ (string-split (string-replace-substring record forms-multi-line " ") forms-field-sep))
+ (string-split data-file-contents #\newline))))
+ (textualized-data
+ (map (lambda (record)
+ (if (not (null? record))
+ (fold-right (lambda (x y)
+ (if (integer? x)
+ (string-append (number->string x) y)
+ (string-append x y)))
+ ""
+ (map (lambda (format-entry)
+ (cond ((string? format-entry) format-entry)
+ ((integer? format-entry) (list-ref record
+ (- format-entry 1)))
+ ((symbol? format-entry) (list-ref record
+ (assq-ref forms-field-symbols format-entry)))
+ ((list? format-entry)
+ (module-define! (current-module) 'forms-fields record)
+ (for-each (lambda (x)
+ (module-define! (current-module)
+ (car x)
+ (cdr x)))
+ forms-field-symbols)
+ (eval format-entry (current-module)))))
+ forms-format-list))
+ ""))
+ split-data)))
+ `(div (@ (class "forms-carousel"))
+ (ul
+ ,@(map (lambda (entry)
+ `(li (div (@ (class "form-entry"))
+ (p ,entry))))
+ textualized-data)))))
+
+;; TODO: explain that no modified characters can be parsed within the non-thrown-away variable settings.
+;; TODO: explain that octal string escape characters will be parsed improperly/naively.
+;; TODO: explain circular lists not supported because Scheme doesn't have read syntax for it.
+;; TODO: consider how to convert propertized string literals to HTML.
+;; TODO: explain that check-number-of-fields must be set and each field the correct size.
+;; TODO: add option for newline replacement character re-substitution.
diff --git a/dnw/static-pages.scm b/dnw/static-pages.scm
index ab51b02..eab7e46 100644
--- a/dnw/static-pages.scm
+++ b/dnw/static-pages.scm
@@ -4,9 +4,11 @@
#:use-module (ice-9 match)
#:use-module (ice-9 rdelim)
#:use-module (ice-9 popen)
+ #:use-module (ice-9 textual-ports)
#:use-module (dnw utils)
#:use-module (dnw theme)
#:use-module (dnw tags)
+ #:use-module (dnw forms)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-19)
#:use-module (sxml simple)
@@ -28,7 +30,7 @@
(p "My name is Duncan. I live below the Mason-Dixon.")
(p "I write down thoughts I think are interesting here; the content is mirrored to " ,(hyperlink "http://dnw.i2p" "I2P") " and "
,(hyperlink "gemini://functorial.xyz" "Gemini")
- " . I couldn't make heads or tails of Tor onion services; email me if you know how to marry a torrc with an nginx.conf."))))
+ ". I couldn't make heads or tails of Tor onion services; email me if you know how to marry a torrc with an nginx.conf."))))
(define (recents site posts)
`(section (@ (id "recent"))
@@ -59,7 +61,7 @@
(ul (p "Github: " ,(hyperlink "https://github.com/Antigravityd" "Antigravityd")))) ;; TODO: consider moving to Sourcehut.
(section (@ (id "prose"))
(h1 "About Me")
- (p "My name is Duncan. I am 20, and have lived most of my life in rural Arkansas. I graduated in 2023 from LSU, cum laude, "
+ (p "My name is Duncan. I am 21, and have lived most of my life in rural Arkansas. I graduated in 2023 from LSU, cum laude, "
"with dual degrees in math and physics, and have at various times been employed as a dishwasher, maintainence guy, tutor, "
"data science intern, embedded developer, and research scientist. I am currently unemployed.")
(p "Had I my druthers, I would like to be able to make a career out of decentralized science, "
@@ -169,11 +171,19 @@
(define influences
`((h1 "Influences")
(p "Any and every third-party I can think of that's affected how I think. ")
- (h2 "Blogs")
- (h2 "Books and Monographs")
+ (h2 "My Library")
+ (p "The books I physically own, or want to own. I haven't quite digitized everything yet (just one moving box of like 4).")
+ ,(forms.el->sxml (get-string-all (open-input-file "assets/library/library.el"))
+ (get-string-all (open-input-file "assets/library/library.tsv"))
+ '())
+ (h2 "Blogs and Podcasts")
+ (ul
+ (li "Not Related"))
+
(h2 "Scholarly Articles")
(h2 "Videos and Talks")))
+
(define (influences-page site posts)
(make-page "/pages/influences.html"
(base-template site influences #:title "Influences")
diff --git a/dnw/theme.scm b/dnw/theme.scm
index fd17cb0..7544e23 100644
--- a/dnw/theme.scm
+++ b/dnw/theme.scm
@@ -19,7 +19,7 @@
(define nav-bar-tabs '(("Me" "/pages/me.html")
("Friends" "/pages/friends.html")
("Influences" "/pages/influences.html")
- ("Projects" "https://git.functorial.xyz/dnw")))
+ ("Projects" "https://git.functorial.xyz")))
(define dnw-title "Through the Heart of Every Man")
diff --git a/org/anarchofoss/anarchofoss.org b/org/anarchofoss/anarchofoss.org
index 9b05eae..447b760 100644
--- a/org/anarchofoss/anarchofoss.org
+++ b/org/anarchofoss/anarchofoss.org
@@ -1,17 +1,17 @@
-#+TITLE: Free Software: A Shining Example of Nongovernmental Externality Control
+#+TITLE: Free Software as Nongovernmental Externality Control
#+DATE: <2023-07-30 Sun>
#+TAGS: Praxeology, Economics, Free Software, Libertarianism
-One of the most common arguments against anarcho-capitalism alleges the absolute necessity of coercion in provisioning public goods, or preventing tragedy of the commons. There are obvious theoretical rebuttals from an Austrian perspective (how does the /state/ know what is a "public good?"), but for the sound rhetorical strategy of engaging your opposition on his own terms counterexamples are required—ideally, ones more concrete than medieval Iceland. The absolute /dominance/ of the Free Software movement, with 77% of web servers, 71% of smartphone/tablets, 100% of top supercomputers, and 38% of embedded devices using operating systems in approximate compliance with its principles [fn:1], means it should live near the top of the Austro-libertarian rhetorical toolkit.
+One of the most common arguments against anarcho-capitalism alleges the absolute necessity of coercion in provisioning public goods, or preventing tragedy of the commons. There are obvious theoretical rebuttals from an Austrian perspective (how does the /state/ know about the "public good?"), but for the sound rhetorical strategy of engaging your opposition on his own terms counterexamples are required—ideally, ones more concrete than medieval Iceland. The Free Software movement's indisputable success in handling market failure means it should live near the top of the Austro-libertarian rhetorical toolkit.
* The Economic Problem
-Charging for a program almost necessarily entails concealing its source code and legally restricting how the software may be used, modified, and shared. For if the user pays for the source, and copyright or contract does not restrict what he may do with it in-hand, the demand for that product and the fact that copying is nearly cost-free together mean he has an incentive to distribute what he has acquired at a much lower price, as he need not recoup the capital its creator invested up front.
+Charging for a program almost necessarily entails concealing its source code and legally restricting how the software may be used, modified, and shared. For if the user pays for the source, and copyright or contract does not restrict what he may do with it in-hand, the demand for that product and the fact that copying is nearly cost-free together mean he has an incentive to distribute what he has acquired at a much lower price (possibly zero), as he does not need to recoup the capital its creator invested up front.
-The non-technical minarchist might wonder what the problem is. But there are two:
+The non-technical minarchist might wonder what the problem with charging for software is. But there are two:
- the means of legally restricting user behavior amount to intellectual property law, and so are incompatible with a Rothbardian theory of property rights and contract law;
- technical users prefer having a program to having the experience of running a program.
-The first should need no explanation. However, exactly what a technically-competent user means by "having a program" probably does. The Free Software Foundation ties all this up in its eponymous term, "Free Software," defined thus:
+The first should need no elaboration. However, exactly what a technically-competent user means by "having a program" probably does. The Free Software Foundation ties all this up in its eponymous term, defined thus:
#+begin_quote
@@ -27,49 +27,33 @@ copies, you always have the freedom to copy and change the software, even to sel
We campaign for these freedoms because everyone deserves them. With these freedoms, the users (both individually and collectively) control
the program and what it does for them. When users don't control the program, we call it a “nonfree” or “proprietary” program. The nonfree
program controls the users, and the developer controls the program; this makes the program an instrument of unjust power.
-
-...
-
-A program is free software if the program's users have the four essential freedoms: [1]
-
-- The freedom to run the program as you wish, for any purpose (freedom 0).
-- The freedom to study how the program works, and change it so it does your computing as you wish (freedom 1). Access to the source code is a precondition for this.
-- The freedom to redistribute copies so you can help others (freedom 2).
-- The freedom to distribute copies of your modified versions to others (freedom 3). By doing this you can give the whole community a chance to benefit from your changes. Access to the source code is a precondition for this.
-
-A program is free software if it gives users adequately all of these freedoms. Otherwise, it is nonfree. While we can distinguish various nonfree
-distribution schemes in terms of how far they fall short of being free, we consider them all equally unethical.
...
#+end_quote
-While not excluding the operation of the market process, this nevertheless presents a "market failure:" users who share these values of the Free Software Foundation desire software with the described liberties more than software without, but providing said liberties makes it difficult for the market to price it "correctly." A price makes it less valuable. This appears, on every level, to be a case where the neoclassical economist would identify a dead-weight loss, and perscribe some tailor-made state intervention.
+While not excluding the operation of the market process, this nevertheless presents a "market failure:" users who share these values of the Free Software Foundation desire software with the described liberties more than software without, but providing said liberties makes it difficult for the market to price it "correctly." A price makes it less valuable. This appears, on every level, to be a case where the neoclassical economist would identify a dead-weight loss, and prescribe some tailor-made state intervention.
-But, possibly due to government's eternal and absolute technical incompetence, this intervention never materialized. And free software outcompetes commercial software in every domain, save markets that are both older than widespread free software and whose users desire only the experience of running programs (to name it: the desktop/laptop space).
+But, possibly due to government's eternal and absolute technical incompetence, this intervention never materialized. And free software out-competes commercial software in every domain, save the desktop/laptop space, which is both older than the free software movement and has users generally desiring only the experience of running programs.
How?
* The GNU Solution
-The FSF's founder, Richard Stallman, ran into the problems of commercial software at the MIT Artificial Intelligence Lab in the 70s. He characterizes its initial state as a "software-sharing community," where "[w]henever people from another
+The FSF's founder, Richard Stallman, ran into problems with commercial software at the MIT Artificial Intelligence Lab in the 70s. He characterizes its initial state as a "software-sharing community," where "[w]henever people from another
university or a company wanted to port and use a program, we gladly let them. If you saw someone using an unfamiliar and interesting
-program, you could always ask to see the source code, so that you could read it, change it, or cannibalize parts of it to make a new program."[fn:2] Commercializing interests, exploiting extensively intellectual property priveleges, brought about the demise of this perceived utopia, tearing apart the society of the AI lab. Stallman responded by "building his own," from the ground up: an operating system and then a philosophical, social, and political movement, with the end of promoting the kind of environment surrounding software that was lost at MIT.
+program, you could always ask to see the source code, so that you could read it, change it, or cannibalize parts of it to make a new program."[fn:1] Commercializing interests, exploiting extensively intellectual property privileges, brought about the demise of this perceived utopia, tearing apart the society of the AI lab. Stallman responded by "building his own," from the ground up: an operating system and then a philosophical, social, and political movement, with the end of promoting the kind of environment surrounding software that was lost at MIT.
-It is this GNU operating system, based exclusively on freely-licensed software, written by Stallman, the wider GNU project, and others entirely, whose derivatives dominate all serious computing in the current day. Not only did the non-state, entrepreneurial solution to the externality work, it /outcompeted/ its commercial alternative in a market that, if anything, had state actors hampering it (governments funding nonfree software startups, buying and using nonfree software, etc). The software, rather than being written to be sold later, is funded /ex ante/ or /ex post facto/, via crowdfunding or donations either to individual maintainers/projects or to foundations that organize such development. These donations come from individual users, politically-motivated idealists, or corporations whose bottom line depends to some extent on such projects. Lots of development is uncompensated, and are projects that a person develops primarily for personal use or interest and simply chooses to share for the benefit of others, at no cost to himself (indeed, often at a net benefit to himself: having users helps test the software, baazar-style development means that development responsibilities may be delegated, and prominent open-source maintainership is an excellent recommendation to prospective employers).
+It is this GNU operating system, based exclusively on freely-licensed software, written by Stallman, the wider GNU project, and others entirely, whose derivatives dominate all serious computing in the current day. Not only did the non-state, entrepreneurial solution to the externality work, it /out-competed/ its commercial alternative in a market that, if anything, had state actors hampering it (governments funding nonfree software startups, buying and using nonfree software, etc.). An estimated 54% of all computer devices shipped in 2015 running operating systems in approximate compliance with its principles (Android/Linux)[fn:2]. The software, rather than being written to be sold later, is funded /ex ante/ or /ex post facto/, via crowdfunding and donations to individual maintainers/projects or to foundations that organize such development. These donations come from individual users, politically-motivated idealists, or corporations whose bottom line depends to some extent on the software in question. Lots of development is uncompensated, and are projects that a person develops primarily for personal use or interest and simply chooses to share for the benefit of others, at no cost to himself (indeed, often at a non-pecuniary benefit to himself: having users helps test the software, bazaar-style development means that development responsibilities may be delegated, and prominent open-source maintainership is an excellent recommendation to prospective employers).
-A hard example for interventionists to chew on, indeed!
+A hard example for interventionists to chew on, indeed! It illustrates a common fallacy of those who would advocate state control: belief that entrepreneurs are somehow less capable of identifying and acting to correct externalities than the state.
* A Pragmatic Lesson: Copyleft
-Free sofware contains an additional lesson for libertarians: that of pragmatism. Stallman sought to establish a particular end in a legally-hostile system; ordinarily, there would be nothing preventing someone from copying, modifying, and redistributing the fruits of the project's labor under nonfree licenses, frustrating that end.
-
-So, he chose to exploit the legally-hostile system to prevent this practical harm to freedom, restricting users' freedom to make others less free. Most of the GNU code proper is licensed under the GNU Public License, which contains so-called "copyleft" provisions, mandate that derivative works be licensed under the same terms. Copyleft uses copyright to destroy copyright, so to speak.
+Free software contains an additional lesson for libertarians: one in pragmatism. Stallman sought to establish a particular end in a legally-hostile system; ordinarily, there would be nothing preventing someone from copying, modifying, and redistributing the fruits of the project's labor under nonfree licenses, frustrating that end. So, he chose to exploit the legally-hostile system to prevent this practical harm to freedom, restricting users' freedom to make other users less free. Most of the GNU code proper is licensed under the GNU Public License, which contains so-called "copyleft" provisions, mandating that derivative works be licensed under the same terms. Copyleft uses copyright to destroy copyright, so to speak.
-Often, libertarians fall into myopic fixations on the ideal free society, to the neglect of the reality that the fastest realistic path to it almost certainly will involve some stopgap policies that, in isolation, would be unacceptable on libertarian terms [fn:3]. Taking a page out of copyleft's book, adopting instead additudes and policy perscriptions that celebrate and optimize for any increase in freedom, even if strictly incompatible with ideals, would go a long way towards securing libertarian ends.
+Often, libertarians fall into myopic fixations on the ideal free society, to the neglect of the reality that the fastest realistic path to it almost certainly will involve some liberty-maximizing stopgaps which, in isolation, would be unacceptable on libertarian terms[fn:3]. Taking a page out of copyleft's book, adopting instead attitudes and policy prescriptions that celebrate and optimize for any increase in freedom, even if strictly incompatible with ideals, would go a long way towards securing libertarian ends.
* Footnotes
-[fn:3] Dave Smith calls this "being too autistic."
-
-[fn:2] [[http://www.gnu.org/gnu/thegnuproject.html][About the GNU Project - GNU Project - Free Software Foundation]]
-
-[fn:1] TODO: insert relevant sources of the Wikipeda page "Usage share of operating systems".
+[fn:3] Comic Dave Smith calls this "being too autistic." Extreme care must be taken in identifying these, with due awareness of history's myriad "temporary" and "emergency" government policies.
+[fn:2] [[https://www.computerworld.com/article/3050931/windows-comes-up-third-in-os-clash-two-years-early.html][Gartner report]]
+[fn:1] [[http://www.gnu.org/gnu/thegnuproject.html][About the GNU Project - GNU Project - Free Software Foundation]]