implemented markdown support

This commit is contained in:
Stefan Friese 2023-07-15 23:53:43 +02:00
parent b790e8fd8e
commit a484b5a82a
21 changed files with 571 additions and 597 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ __pycache__/
templates/blog/* templates/blog/*
flask_run.sh flask_run.sh
poetry.lock poetry.lock
build

View File

@ -1,110 +0,0 @@
<!doctype html>
{% extends "template.html" %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
{{ _date.date() }}
<p><h1>Keep It Simple</h1>
While studying architecture not only had I so little money that I ate spaghetti and pesto every day, I learned a thing or two about design principles as well. These principles hold true for every product or piece of engineering you plan out. It is the KISS principle. Keep it simple stupid, or to quote a guy Jony Ive is clearly a fan of <a href="#references" style="text-decoration:none">[1]</a>:
<blockquote>&ldquo;Good design is as little design as possible.&rdquo;<br>&mdash; Dieter Rams &mdash;</br></blockquote>
</p>
<p>
Let&rsquo;s expand on it so far that it should be as simple as possible without being outright stupid. To expand even further, a compelling and useful design is not only measurable by the things you can do with it, but even more important are the things you don&rsquo;t have to do when you use it.
</p>
<p>
As you craft something, you will inevitably communicate with everybody using your product. In proxy, any room, place or inanimate object created by a human speaks to the user. Even on an emotional level. Psychologists or product designers like computer and car designers are no strangers to this. Donald Norman wrote multiple books about it <a rhef="#references" style="text-decoration:none">[2]</a>, <a href="#references" style="text-decoration:none">[3]</a>. Some good reads. Schulz von Thun defined the <a href="http://temp.chpfeiffer.de/Four-sides_model.pdf">four-ears model</a> in which a sender&rsquo;s message is received on four different levels. These are Factual information, Appeal, Self-revelation and Relationship. This means it is helpful to think about the essence of the aspect you want to craft to communicate clearly and get the message across.
<img style="float: right", alt="A functional lighter.", src="{{ url_for('static', filename='images/218px-White_BIC_lighter.png') }}">
</p>
<p>
<h2>Pesto Principles</h2>
<hr/>
What about this website's design principles? First and foremost, how you spent your time is important. Do you really need to wait for more than a few seconds to load a website? Then there should be a plausible reason for that. Should you wait more than 5 seconds to be able to read something a guy is rambling about on his blog? I highly doubt it. The layout should respect you and your time. Network traffic should be minimal.
</p>
Second, I don&rsquo;t want your data. No cookies, no statistics about you, no ad tracking of your surfing behavior. That is what you and I won&rsquo;t have to put up with. You may read my blog, or you don&rsquo;t. Take it or leave it. But I hope you will learn something by doing it or have a good time at least.
<p>
There are some points to make this website work and make it accessible. To write entries, I will use plain HTML. For now, it is sufficient. HTML is a nice markup language. Use a <code>&lt;lang&gt;</code> tag and you got translation accessibility. Another one is the following line, making the layout respond dynamically to different screen sizes. More examples on <a href="https://perfectmotherfuckingwebsite.com">this beautiful website</a>.
<pre>
<code>
&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
</code>
</pre>
This will be a blog about computers, for the most part, there will be code examples. Further, I want to keep the stylesheet small and maintainable. Monospaced fonts are not only a dead giveaway about this fact, a solid layout is created via the following line of CSS.
<pre>
<code>
.content{text-align:justify;}
</code>
</pre>
</p>
<p>
To keep things in perspective, the date of publication will be the first line in each article. If the content may be of interest to you, knowing the date it was created is beneficial in evaluating its potential usefulness over time.
</p>
<p>
There is no harm in growing something like a website incrementally. You will never miss a feature you never had in the first place. You could aspire to get it if it is conceptually meaningful and makes some sense in the overall picture. But a feature that does not exist needs no maintenance, does not produce any bugs and needs no documentation.
<blockquote>&ldquo;The things you own end up owning you.&rdquo;<br>&mdash; Chuck Palahniuk &mdash;</br></blockquote>
<h2>Cordial Code</h2>
<hr/>
The website was created on a Saturday afternoon in Python and Flask framework. Six months down the line, I do not want to put much energy into grasping what I had done this weekend regarding to code structure. I want to put the least amount of time possible into extending and maintaining the framework of the site. It consists of a Python file, a stylesheet, a jinja template and an empty favicon file. The last one exists because I want to avoid any error possible displayed in the network console of the browser. Everything else is content.
You can find the site as a repository on <a href="https://git.stefan.works">my git</a>.
<p>
A directory named <code>blog</code> contains all entries released as well as the ones I am working on. Metadata about subdirectories and the corresponding content is gathered inside a &lt;key&gt;:&lt;value&gt; structure. An entry is seen as valid and stored in the dictionary as soon as an index.html file is found. Who knows what might be added in the future. It will be added to a list of values. For now, metadata is solely the date of the blog articles. It is added to the RSS site automatically as well. The code snippet contains the dictionary.
</p>
<pre>
<code>
meta_data = {root[len("./templates/blog/"):] :
datetime.fromtimestamp(os.path.getmtime(os.path.join(root,"index.html")))
for root, dirs, files in os.walk("./templates/blog") if "index.html" in files}
</code>
</pre>
Routes are set by the use of decorators. The landing page is declared in the following snippet. After the dictionary is sorted by date, <a href="https://flask.palletsprojects.com/en/2.0.x/api/#flask.render_template"><code>render_template()</code></a> returns a string. The result will be interpreted by the browser in HTML/CSS format.
<pre>
<code>
@app.route('/')
def index(_paths=meta_data):
sorted_meta_data = dict(sorted(meta_data.items(), reverse=True, key=lambda item : item[1]))
return render_template("index.html", _paths=sorted_meta_data)
</code>
</pre>
The main page, like every other page, extends the general jinja template. It contains a list of all articles found.
<pre>
<code>
&#x7b;% extends "template.html" %&#x7d;
&#x7b;% block head %&#x7d;
&#x7b;&#x7b; super() &#x7d;&#x7d;
&#x7b;% endblock %&#x7d;
&#x7b;% block content %&#x7d;
&lt;p&gt;Welcome to my website&lt;/p&gt;
&lt;span class="index"&gt;
&#x7b;% for name,_date in _paths.items() %&#x7d;
&lt;p&gt;&lt;a href="&#x7b;&#x7b; url_for('blog', blog_item=name) &#x7d;&#x7d;"&gt;&#x7b;&#x7b; _date.date() &#x7d;&#x7d;&emsp;&emsp;&#x7b;&#x7b; name &#x7d;&#x7d;&lt;/a&gt;&lt;/p&gt;
&#x7b;% endfor %&#x7d;
&lt;/span&gt;
&#x7b;% endblock %&#x7d;
</code>
</pre>
URLs originate from the meta_data dictionary keys. These are the blog entries&rsquo; directory names. Flask&rsquo;s <a href="https://flask.palletsprojects.com/en/2.0.x/api/#flask.url_for" ><code>url_for()</code></a> returns the articles if you want to visit the site. It handles URL encoding as well. This is pretty neat since there are spaces in the names.
<pre>
<code>
@app.route('/blog/&lt;blog_item&gt;/index.html')
def blog(blog_item, _date=meta_data):
return render_template(f"blog/{blog_item}/index.html", _date=meta_data[blog_item])
</code>
</pre>
<h2>Digestif</h2>
<hr/>
Incidentally, this turned out to be not only an opener for my blog but code documentation for myself as well. Maybe, I&rsquo;ll need to pick it up in six months, who knows&#8230;.
As a closure, at least from my experience, the most feature-rich application seldom reaches its set goals. The one with a clear and precise target, fulfilling its minimal scope, most likely will.
<p>
<a href="https://www.bonappetit.com/recipe/best-pesto">This is how you make pesto, by the way.</a> Bon Appetit!
</p>
<p id="references" class="references">
<h2>References</h2>
<a href="https://www.bookfinder.com/?isbn=9783899555844">[1] Less and More: The Design Ethos of Dieter Rams, 2015, ISBN:9783899555844</a><br>
<a href="https://www.bookfinder.com/?isbn=9780465051366">[2] Emotional Design: Why We Love (or Hate) Everyday Things, 2005, ISBN:9780465051366</a>
<a href="https://www.bookfinder.com/?isbn=9780465067107">[3] The Design of Everyday Things, 2002, ISBN, 9780465067107</a>
</p>
{% endblock %}

View File

@ -7,7 +7,7 @@ spaghetti and pesto every day, I learned a thing or two about design
principles as well. These principles hold true for every product or principles as well. These principles hold true for every product or
piece of engineering you plan out. It is the KISS principle. Keep it piece of engineering you plan out. It is the KISS principle. Keep it
simple stupid, or to quote a guy Jony Ive is clearly a fan of simple stupid, or to quote a guy Jony Ive is clearly a fan of
[[1]](#references){style="text-decoration:none"}: [[1]](#references):
> "Good design is as little design as possible." > "Good design is as little design as possible."
> --- Dieter Rams --- > --- Dieter Rams ---
@ -29,9 +29,9 @@ model](http://temp.chpfeiffer.de/Four-sides_model.pdf) in which a
sender's message is received on four different levels. These are Factual sender's message is received on four different levels. These are Factual
information, Appeal, Self-revelation and Relationship. This means it is information, Appeal, Self-revelation and Relationship. This means it is
helpful to think about the essence of the aspect you want to craft to helpful to think about the essence of the aspect you want to craft to
communicate clearly and get the message across. ![A functional lighter. >](../../static/images/218px-White_BIC_lighter.png)<style="float: right",=""/> communicate clearly and get the message across. ![A functional lighter. >](../../static/images/218px-White_BIC_lighter.png)
## [Pesto Principles](#Pesto Principles) ## [Pesto Principles](#pesto-principles)
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -83,7 +83,7 @@ maintenance, does not produce any bugs and needs no documentation.
> "The things you own end up owning you." > "The things you own end up owning you."
> --- Chuck Palahniuk --- > --- Chuck Palahniuk ---
## Cordial Code ## [Cordial Code](#cordial-code)
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -156,7 +156,7 @@ names.
return render_template(f"blog/{blog_item}/index.html", _date=meta_data[blog_item]) return render_template(f"blog/{blog_item}/index.html", _date=meta_data[blog_item])
``` ```
## Digestif ## [Digestif](#digestif)
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -170,7 +170,7 @@ will.
[This is how you make pesto, by the [This is how you make pesto, by the
way.](https://www.bonappetit.com/recipe/best-pesto) Bon Appetit! way.](https://www.bonappetit.com/recipe/best-pesto) Bon Appetit!
## References ## [References](#references)
[[1] Less and More: The Design Ethos of Dieter Rams, 2015, [[1] Less and More: The Design Ethos of Dieter Rams, 2015,
ISBN:9783899555844](https://www.bookfinder.com/?isbn=9783899555844) ISBN:9783899555844](https://www.bookfinder.com/?isbn=9783899555844)

View File

@ -1,85 +0,0 @@
<!doctype html>
{% extends "template.html" %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
{{ _date.date() }}
<p><h1>The Joy of One-Liners</h1>
There is an engineering idiom which withstands time like no other. As old as the hills but never forgotten. In informational technology relations, one could say it is ancient. Its dawn proclaimed from the shores of Seattle, defeated by an apocalyptic horseman with the melodious name <i>NT</i>. Shot! Point blank into the chest. Buried under the hills of an IT dark age which we call the nineties, dead. But is it? Well, not exactly. There is still life in the old dog. Like Beatrix Kiddo, it one-inch punches itself back to daylight. Coal black as a miner. Topsoil sticks to its beige 1978&rsquo;s leather jacket, it trickles to the ground with every step taken to the nearest diner. The door opens again. &ldquo;May I have a glass of water, please?&rdquo;
</p>
<p>
An art passed down from the ancestors. Its most visible interface: <i>The Shell</i>. Its name: <i>The Unix Philosophy</i>.
<p>
Coined by Doug McIlroy in the <a href="https://archive.org/details/bstj57-6-1899/mode/2up">Bell System Technical Journal</a> as a foreword to the UNIX Time-Sharing System. There is an even more concise version<a href=#references" style="text-decoration:none">[1]</a> and according to <a href="http://www.catb.org/~esr/writings/taoup/html/ch01s06.html">Eric Steven Raymond</a> this is <a href="#references" style="text-decoration:none">[2]</a>:
<blockquote>&ldquo;This is the Unix philosophy: Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.&rdquo;<br>&mdash; Doug McIlroy &mdash;</br></blockquote>
</p>
<p>
In some way, this is similar to the concept of the on vogue philosophy of microservices everywhere. Services are written to do one thing and do it well. They work together. Also, text is the connecting link between programs, services, and humans. The possibility to read a program&rsquo;s output as text seems benign, as long as everything is working well. The advantage is interactivity at any time, testability of every component, and debuggability at every step of the process in an on the fly manner. Impromptu, out of reflex like a punch.
</p>
<h2>Pipe Dreams</h2>
<hr/>
Mc Ilroy made another very important contribution, which is the Unix pipe. It is the practical implementation of connecting the programs inside the shell. He saw the programs as tools, plugged together via pipes building a <a href="http://www.princeton.edu/~hos/Mahoney/expotape.htm">toolbox</a>. Program A&rsquo;s <code>stdout</code> is put into the <code>stdin</code> of program B. This leaves us with a single line of chained, well-defined programs to solve a problem that would otherwise be an extensive, multi-line program in any programming language of your choice.
</p>
Let&rsquo;s say we&rsquo;ve got two programs. The first is one is <i>fortune</i>, the fortune cookie program from BSD games, which outputs random quotes as text. The second one is <i>cowsay</i>, which displays various kinds of animals as ASCII art. In order to work in a coherent manner a <code>|</code> is used. The pipe connects the first one to the second one.
<p>
<pre>
<code>
fortune | cowsay
_________________________________________
/ Gil-galad was an Elven-king. Of him the \
| harpers sadly sing: the last whose |
| realm was fair and free between the |
| Mountains and the Sea. |
| |
| His sword was long, his lance was keen, |
| his shining helm afar was seen; the |
| countless stars of heaven's field were |
| mirrored in his silver shield. |
| |
| But long ago he rode away, and where he |
| dwelleth none can say; for into |
| darkness fell his star in Mordor where |
| the shadows are. |
| |
\ -- J. R. R. Tolkien /
-----------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
</code>
</pre>
<p>
To mix in some colors pipe everything through lolcat. Try it out!
</p>
<pre>
<code>
fortune | cowsay | lolcat
</code>
</pre>
<p>
So far so good, let us gain some real-world practice.
</p>
<h2>Punching Lines &mdash; Retire Your Password Generator</h2>
<hr/>
Have you ever questioned the integrity of your one-click, GUI, proprietary password generator? Is its randomness really as unpredictable as it proclaims? Are you the only one which ends up knowing your generated password? There is a one-liner that ups your opsec instantly. Right from the source of randomness:
<pre>
<code>
head -n 42 /dev/urandom | tr -cd '[:alnum:]' | cut -c-12
</code>
</pre>
So, what is going on here? Everything is a file, that is the way *nix systems see it, even the device which puts out random data. To read the upper part of a file we use <code>head</code>. It will be sent to <code>stdout</code> and displayed via the shell. Parameter <code>-n</code> reads exactly 42 lines of the file given to gather enough randomness. The output of <code>head</code> will be sent to <code>tr</code>. In order to select only alphanumeric characters for our password, we use <code>'[:alnum:]'</code>. Parameters <code>-c</code> selects the complement of alphanumeric characters and <code>-d</code> deletes them. <code>cut</code> does exactly what it says, <code>-c-12</code> cuts after 12 characters with leaves us with a random password of length 12. Every time you execute this one-liner a freshly made random password is returned.
<p>
To extend the pool of possible symbols the manual of <code>tr</code> lists various sets of filtered symbols. In the case of a password generator, further sensible filters are <code>'[:alpha:]'</code> or <code>'[:digit:]'</code>. While <code>'[:graph:]'</code> is also viable in this case it returns one of the greater sets of symbols. Use it with caution, especially if you create passwords for database users. These might be terminated prematurely through <code>`</code> or <code>'</code> inside the returned string.
</p>
<h2>Sunday Punch</h2>
<hr/>
This blog entrance can be seen as a prelude to a series of one-liners I use time and time again. The are multiple in the pipeline. One-liners should save you the time you otherwise would spend coding a complex solution. There is little better than solving a challenging problem in a single line.
<p id="references" class="references">
<h2>References</h2>
<a href="https://www.bookfinder.com/?isbn=9780201547771">[1] A Quarter Century of Unix, 1994, Peter Salus, ISBN:9780201547771</a><br>
<a href="https://www.bookfinder.com/?isbn=9780131429017">[2] The Art of UNIX Programming, 2003, Eric Raymond, ISBN:9780131429017</a><br>
</p>
{% endblock %}

View File

@ -20,10 +20,10 @@ Shell*. Its name: *The Unix Philosophy*.
Coined by Doug McIlroy in the [Bell System Technical Coined by Doug McIlroy in the [Bell System Technical
Journal](https://archive.org/details/bstj57-6-1899/mode/2up) as a Journal](https://archive.org/details/bstj57-6-1899/mode/2up) as a
foreword to the UNIX Time-Sharing System. There is an even more concise foreword to the UNIX Time-Sharing System. There is an even more concise
version[[1]](#references){style="text-decoration:none"} and version[[1]](#references) and
according to [Eric Steven according to [Eric Steven
Raymond](http://www.catb.org/~esr/writings/taoup/html/ch01s06.html) this Raymond](http://www.catb.org/~esr/writings/taoup/html/ch01s06.html) this
is [[2]](#references){style="text-decoration:none"}: is [[2]](#references):
> "This is the Unix philosophy: Write programs that do one thing and do > "This is the Unix philosophy: Write programs that do one thing and do
> it well. Write programs to work together. Write programs to handle > it well. Write programs to work together. Write programs to handle
@ -39,7 +39,7 @@ advantage is interactivity at any time, testability of every component,
and debuggability at every step of the process in an on the fly manner. and debuggability at every step of the process in an on the fly manner.
Impromptu, out of reflex like a punch. Impromptu, out of reflex like a punch.
## Pipe Dreams ## [Pipe Dreams](#pipe-dreams)
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -93,7 +93,7 @@ fortune | cowsay | lolcat
``` ```
So far so good, let us gain some real-world practice. So far so good, let us gain some real-world practice.
## Punching Lines --- Retire Your Password Generator ## [Punching Lines and Retire Your Password Generator](#punching-lines-and-retire-your-password-generator)
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -127,7 +127,7 @@ symbols. Use it with caution, especially if you create passwords for
database users. These might be terminated prematurely through `` ` `` or database users. These might be terminated prematurely through `` ` `` or
`'` inside the returned string. `'` inside the returned string.
## Sunday Punch ## [Sunday Punch](#sunday-punch)
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -137,7 +137,7 @@ should save you the time you otherwise would spend coding a complex
solution. There is little better than solving a challenging problem in a solution. There is little better than solving a challenging problem in a
single line. single line.
## References ## [References](#references)
[[1] A Quarter Century of Unix, 1994, Peter Salus, [[1] A Quarter Century of Unix, 1994, Peter Salus,
ISBN:9780201547771](https://www.bookfinder.com/?isbn=9780201547771) ISBN:9780201547771](https://www.bookfinder.com/?isbn=9780201547771)

View File

@ -11,6 +11,19 @@
<div class="menu"> <div class="menu">
<a href="/" style="text-decoration:none">Stefan Friese's Website</a> <a href="/" style="text-decoration:none">Stefan Friese's Website</a>
</div> </div>
<style>
/* Stylesheet 1 */
body { background: #2f333d; color: #979fad; }
hr{ color: #979fad; border-color: #979fad; }
pre { background: #282c34; color: #979fad; border: 1px solid #282c34; }
code { background: #282c34; color: #979fad; }
a:hover { color: #be5046; }
details > summary { background: #282c34; }
details > summary:hover { background: #2f333d; color: #979fad; }
::selection { background: #668799; }
::-moz-selection { background: #668799; }
</style>
<hr style="width: 36ch;"/> <hr style="width: 36ch;"/>
<div class="menu"> <div class="menu">
<a href="/about.html" style="text-decoration:none">about&emsp;</a> <a href="/about.html" style="text-decoration:none">about&emsp;</a>

View File

@ -1,5 +1,4 @@
<!doctype html> <!doctype html>
<!doctype html>
<html lang="en"> <html lang="en">
<center> <center>
<head> <head>
@ -12,6 +11,19 @@
<div class="menu"> <div class="menu">
<a href="/" style="text-decoration:none">Stefan Friese's Website</a> <a href="/" style="text-decoration:none">Stefan Friese's Website</a>
</div> </div>
<style>
/* Stylesheet 1 */
body { background: #2f333d; color: #979fad; }
hr{ color: #979fad; border-color: #979fad; }
pre { background: #282c34; color: #979fad; border: 1px solid #282c34; }
code { background: #282c34; color: #979fad; }
a:hover { color: #be5046; }
details > summary { background: #282c34; }
details > summary:hover { background: #2f333d; color: #979fad; }
::selection { background: #668799; }
::-moz-selection { background: #668799; }
</style>
<hr style="width: 36ch;"/> <hr style="width: 36ch;"/>
<div class="menu"> <div class="menu">
<a href="/about.html" style="text-decoration:none">about&emsp;</a> <a href="/about.html" style="text-decoration:none">about&emsp;</a>
@ -28,110 +40,244 @@
</head> </head>
<body> <body>
<div lang="en" class="content"> <div lang="en" class="content">
2021-06-01 <span class="body">
<p><h1>Keep It Simple</h1> <!-- 2021-06-01 -->
While studying architecture not only had I so little money that I ate spaghetti and pesto every day, I learned a thing or two about design principles as well. These principles hold true for every product or piece of engineering you plan out. It is the KISS principle. Keep it simple stupid, or to quote a guy Jony Ive is clearly a fan of <a href="#references" style="text-decoration:none">[1]</a>: <style>pre { line-height: 125%; }
<blockquote>&ldquo;Good design is as little design as possible.&rdquo;<br>&mdash; Dieter Rams &mdash;</br></blockquote> td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
</p> span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
<p> td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
Let&rsquo;s expand on it so far that it should be as simple as possible without being outright stupid. To expand even further, a compelling and useful design is not only measurable by the things you can do with it, but even more important are the things you don&rsquo;t have to do when you use it. span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
</p> .codehilite .hll { background-color: #ffffcc }
<p> .codehilite .c { color: #7F848E } /* Comment */
As you craft something, you will inevitably communicate with everybody using your product. In proxy, any room, place or inanimate object created by a human speaks to the user. Even on an emotional level. Psychologists or product designers like computer and car designers are no strangers to this. Donald Norman wrote multiple books about it <a rhef="#references" style="text-decoration:none">[2]</a>, <a href="#references" style="text-decoration:none">[3]</a>. Some good reads. Schulz von Thun defined the <a href="http://temp.chpfeiffer.de/Four-sides_model.pdf">four-ears model</a> in which a sender&rsquo;s message is received on four different levels. These are Factual information, Appeal, Self-revelation and Relationship. This means it is helpful to think about the essence of the aspect you want to craft to communicate clearly and get the message across. .codehilite .err { color: #ABB2BF } /* Error */
.codehilite .esc { color: #ABB2BF } /* Escape */
.codehilite .g { color: #ABB2BF } /* Generic */
.codehilite .k { color: #C678DD } /* Keyword */
.codehilite .l { color: #ABB2BF } /* Literal */
.codehilite .n { color: #E06C75 } /* Name */
.codehilite .o { color: #56B6C2 } /* Operator */
.codehilite .x { color: #ABB2BF } /* Other */
.codehilite .p { color: #ABB2BF } /* Punctuation */
.codehilite .ch { color: #7F848E } /* Comment.Hashbang */
.codehilite .cm { color: #7F848E } /* Comment.Multiline */
.codehilite .cp { color: #7F848E } /* Comment.Preproc */
.codehilite .cpf { color: #7F848E } /* Comment.PreprocFile */
.codehilite .c1 { color: #7F848E } /* Comment.Single */
.codehilite .cs { color: #7F848E } /* Comment.Special */
.codehilite .gd { color: #ABB2BF } /* Generic.Deleted */
.codehilite .ge { color: #ABB2BF } /* Generic.Emph */
.codehilite .gr { color: #ABB2BF } /* Generic.Error */
.codehilite .gh { color: #ABB2BF } /* Generic.Heading */
.codehilite .gi { color: #ABB2BF } /* Generic.Inserted */
.codehilite .go { color: #ABB2BF } /* Generic.Output */
.codehilite .gp { color: #ABB2BF } /* Generic.Prompt */
.codehilite .gs { color: #ABB2BF } /* Generic.Strong */
.codehilite .gu { color: #ABB2BF } /* Generic.Subheading */
.codehilite .gt { color: #ABB2BF } /* Generic.Traceback */
.codehilite .kc { color: #E5C07B } /* Keyword.Constant */
.codehilite .kd { color: #C678DD } /* Keyword.Declaration */
.codehilite .kn { color: #C678DD } /* Keyword.Namespace */
.codehilite .kp { color: #C678DD } /* Keyword.Pseudo */
.codehilite .kr { color: #C678DD } /* Keyword.Reserved */
.codehilite .kt { color: #E5C07B } /* Keyword.Type */
.codehilite .ld { color: #ABB2BF } /* Literal.Date */
.codehilite .m { color: #D19A66 } /* Literal.Number */
.codehilite .s { color: #98C379 } /* Literal.String */
.codehilite .na { color: #E06C75 } /* Name.Attribute */
.codehilite .nb { color: #E5C07B } /* Name.Builtin */
.codehilite .nc { color: #E5C07B } /* Name.Class */
.codehilite .no { color: #E06C75 } /* Name.Constant */
.codehilite .nd { color: #61AFEF } /* Name.Decorator */
.codehilite .ni { color: #E06C75 } /* Name.Entity */
.codehilite .ne { color: #E06C75 } /* Name.Exception */
.codehilite .nf { color: #61AFEF; font-weight: bold } /* Name.Function */
.codehilite .nl { color: #E06C75 } /* Name.Label */
.codehilite .nn { color: #E06C75 } /* Name.Namespace */
.codehilite .nx { color: #E06C75 } /* Name.Other */
.codehilite .py { color: #E06C75 } /* Name.Property */
.codehilite .nt { color: #E06C75 } /* Name.Tag */
.codehilite .nv { color: #E06C75 } /* Name.Variable */
.codehilite .ow { color: #56B6C2 } /* Operator.Word */
.codehilite .pm { color: #ABB2BF } /* Punctuation.Marker */
.codehilite .w { color: #ABB2BF } /* Text.Whitespace */
.codehilite .mb { color: #D19A66 } /* Literal.Number.Bin */
.codehilite .mf { color: #D19A66 } /* Literal.Number.Float */
.codehilite .mh { color: #D19A66 } /* Literal.Number.Hex */
.codehilite .mi { color: #D19A66 } /* Literal.Number.Integer */
.codehilite .mo { color: #D19A66 } /* Literal.Number.Oct */
.codehilite .sa { color: #98C379 } /* Literal.String.Affix */
.codehilite .sb { color: #98C379 } /* Literal.String.Backtick */
.codehilite .sc { color: #98C379 } /* Literal.String.Char */
.codehilite .dl { color: #98C379 } /* Literal.String.Delimiter */
.codehilite .sd { color: #98C379 } /* Literal.String.Doc */
.codehilite .s2 { color: #98C379 } /* Literal.String.Double */
.codehilite .se { color: #98C379 } /* Literal.String.Escape */
.codehilite .sh { color: #98C379 } /* Literal.String.Heredoc */
.codehilite .si { color: #98C379 } /* Literal.String.Interpol */
.codehilite .sx { color: #98C379 } /* Literal.String.Other */
.codehilite .sr { color: #98C379 } /* Literal.String.Regex */
.codehilite .s1 { color: #98C379 } /* Literal.String.Single */
.codehilite .ss { color: #98C379 } /* Literal.String.Symbol */
.codehilite .bp { color: #E5C07B } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #56B6C2; font-weight: bold } /* Name.Function.Magic */
.codehilite .vc { color: #E06C75 } /* Name.Variable.Class */
.codehilite .vg { color: #E06C75 } /* Name.Variable.Global */
.codehilite .vi { color: #E06C75 } /* Name.Variable.Instance */
.codehilite .vm { color: #E06C75 } /* Name.Variable.Magic */
.codehilite .il { color: #D19A66 } /* Literal.Number.Integer.Long */</style>
<p>2021-06-01</p>
<h1 id="keep-it-simple">Keep It Simple</h1>
<p>While studying architecture not only had I so little money that I ate
spaghetti and pesto every day, I learned a thing or two about design
principles as well. These principles hold true for every product or
piece of engineering you plan out. It is the KISS principle. Keep it
simple stupid, or to quote a guy Jony Ive is clearly a fan of
<a href="#references">[1]</a>:</p>
<blockquote>
<p>"Good design is as little design as possible."<br />
--- Dieter Rams ---</p>
</blockquote>
<p>Let's expand on it so far that it should be as simple as possible
without being outright stupid. To expand even further, a compelling and
useful design is not only measurable by the things you can do with it,
but even more important are the things you don't have to do when you use
it.</p>
<p>As you craft something, you will inevitably communicate with everybody
using your product. In proxy, any room, place or inanimate object
created by a human speaks to the user. Even on an emotional level.
Psychologists or product designers like computer and car designers are
no strangers to this. Donald Norman wrote multiple books about it
<a href="#references">[2]</a>, <a href="#references">[3]</a>.
Schulz von Thun defined the <a href="http://temp.chpfeiffer.de/Four-sides_model.pdf">four-ears
model</a> in which a
sender's message is received on four different levels. These are Factual
information, Appeal, Self-revelation and Relationship. This means it is
helpful to think about the essence of the aspect you want to craft to
communicate clearly and get the message across. <img alt="A functional lighter. &gt;" src="../../static/images/218px-White_BIC_lighter.png" /></p>
<h2 id="pesto-principles"><a href="#pesto-principles">Pesto Principles</a></h2>
<hr />
<p>What about this website's design principles? First and foremost, how
you spent your time is important. Do you really need to wait for more
than a few seconds to load a website? Then there should be a plausible
reason for that. Should you wait more than 5 seconds to be able to read
something a guy is rambling about on his blog? I highly doubt it. The
layout should respect you and your time. Network traffic should be
minimal.</p>
<p>Second, I don't want your data. No cookies, no statistics about you, no
ad tracking of your surfing behavior. That is what you and I won't have
to put up with. You may read my blog, or you don't. Take it or leave it.
But I hope you will learn something by doing it or have a good time at
least.</p>
<p>There are some points to make this website work and make it accessible.
To write entries, I will use plain HTML. For now, it is sufficient. HTML
is a nice markup language. Use a <code>&lt;lang&gt;</code> tag and you got translation
accessibility. Another one is the following line, making the layout
respond dynamically to different screen sizes. More examples on <a href="https://perfectmotherfuckingwebsite.com">this
beautiful website</a>.</p>
<div class="codehilite"><pre><span></span><code><span class="p">&lt;</span><span class="nt">meta</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;viewport&quot;</span> <span class="na">content</span><span class="o">=</span><span class="s">&quot;width=device-width, initial-scale=1&quot;</span><span class="p">&gt;</span>
</code></pre></div>
<img style="float: right", alt="A functional lighter.", src="/static/images/218px-White_BIC_lighter.png"> <p>This will be a blog about computers, for the most part, there will be
</p> code examples. Further, I want to keep the stylesheet small and
<p> maintainable. Monospaced fonts are not only a dead giveaway about this
<h2>Pesto Principles</h2> fact, a solid layout is created via the following line of CSS.</p>
<hr/> <div class="codehilite"><pre><span></span><code><span class="p">.</span><span class="nc">content</span><span class="p">{</span><span class="k">text-align</span><span class="p">:</span><span class="kc">justify</span><span class="p">;}</span>
What about this website's design principles? First and foremost, how you spent your time is important. Do you really need to wait for more than a few seconds to load a website? Then there should be a plausible reason for that. Should you wait more than 5 seconds to be able to read something a guy is rambling about on his blog? I highly doubt it. The layout should respect you and your time. Network traffic should be minimal. </code></pre></div>
</p>
Second, I don&rsquo;t want your data. No cookies, no statistics about you, no ad tracking of your surfing behavior. That is what you and I won&rsquo;t have to put up with. You may read my blog, or you don&rsquo;t. Take it or leave it. But I hope you will learn something by doing it or have a good time at least.
<p>
There are some points to make this website work and make it accessible. To write entries, I will use plain HTML. For now, it is sufficient. HTML is a nice markup language. Use a <code>&lt;lang&gt;</code> tag and you got translation accessibility. Another one is the following line, making the layout respond dynamically to different screen sizes. More examples on <a href="https://perfectmotherfuckingwebsite.com">this beautiful website</a>.
<pre>
<code>
&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
</code>
</pre>
This will be a blog about computers, for the most part, there will be code examples. Further, I want to keep the stylesheet small and maintainable. Monospaced fonts are not only a dead giveaway about this fact, a solid layout is created via the following line of CSS.
<pre>
<code>
.content{text-align:justify;}
</code>
</pre>
</p>
<p>
To keep things in perspective, the date of publication will be the first line in each article. If the content may be of interest to you, knowing the date it was created is beneficial in evaluating its potential usefulness over time.
</p>
<p>
There is no harm in growing something like a website incrementally. You will never miss a feature you never had in the first place. You could aspire to get it if it is conceptually meaningful and makes some sense in the overall picture. But a feature that does not exist needs no maintenance, does not produce any bugs and needs no documentation.
<blockquote>&ldquo;The things you own end up owning you.&rdquo;<br>&mdash; Chuck Palahniuk &mdash;</br></blockquote>
<h2>Cordial Code</h2>
<hr/>
The website was created on a Saturday afternoon in Python and Flask framework. Six months down the line, I do not want to put much energy into grasping what I had done this weekend regarding to code structure. I want to put the least amount of time possible into extending and maintaining the framework of the site. It consists of a Python file, a stylesheet, a jinja template and an empty favicon file. The last one exists because I want to avoid any error possible displayed in the network console of the browser. Everything else is content.
You can find the site as a repository on <a href="https://git.stefan.works">my git</a>. <p>To keep things in perspective, the date of publication will be the first
<p> line in each article. If the content may be of interest to you, knowing
A directory named <code>blog</code> contains all entries released as well as the ones I am working on. Metadata about subdirectories and the corresponding content is gathered inside a &lt;key&gt;:&lt;value&gt; structure. An entry is seen as valid and stored in the dictionary as soon as an index.html file is found. Who knows what might be added in the future. It will be added to a list of values. For now, metadata is solely the date of the blog articles. It is added to the RSS site automatically as well. The code snippet contains the dictionary. the date it was created is beneficial in evaluating its potential
</p> usefulness over time.</p>
<p>There is no harm in growing something like a website incrementally. You
will never miss a feature you never had in the first place. You could
aspire to get it if it is conceptually meaningful and makes some sense
in the overall picture. But a feature that does not exist needs no
maintenance, does not produce any bugs and needs no documentation.</p>
<blockquote>
<p>"The things you own end up owning you."<br />
--- Chuck Palahniuk ---</p>
</blockquote>
<h2 id="cordial-code"><a href="#cordial-code">Cordial Code</a></h2>
<hr />
<p>The website was created on a Saturday afternoon in Python and Flask
framework. Six months down the line, I do not want to put much energy
into grasping what I had done this weekend regarding to code structure.
I want to put the least amount of time possible into extending and
maintaining the framework of the site. It consists of a Python file, a
stylesheet, a jinja template and an empty favicon file. The last one
exists because I want to avoid any error possible displayed in the
network console of the browser. Everything else is content. You can find
the site as a repository on <a href="https://git.stefan.works">my git</a>.</p>
<p>A directory named <code>blog</code> contains all entries released as well as the
ones I am working on. Metadata about subdirectories and the
corresponding content is gathered inside a \&lt;key&gt;:\&lt;value&gt; structure.
An entry is seen as valid and stored in the dictionary as soon as an
index.html file is found. Who knows what might be added in the future.
It will be added to a list of values. For now, metadata is solely the
date of the blog articles. It is added to the RSS site automatically as
well. The code snippet contains the dictionary.</p>
<div class="codehilite"><pre><span></span><code> <span class="n">meta_data</span> <span class="o">=</span> <span class="p">{</span><span class="n">root</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="s2">&quot;./templates/blog/&quot;</span><span class="p">):]</span> <span class="p">:</span>
<span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getmtime</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">root</span><span class="p">,</span><span class="s2">&quot;index.html&quot;</span><span class="p">)))</span>
<span class="k">for</span> <span class="n">root</span><span class="p">,</span> <span class="n">dirs</span><span class="p">,</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="s2">&quot;./templates/blog&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="s2">&quot;index.html&quot;</span> <span class="ow">in</span> <span class="n">files</span><span class="p">}</span>
</code></pre></div>
<pre> <p>Routes are set by the use of decorators. The landing page is declared in
<code> the following snippet. After the dictionary is sorted by date,
meta_data = {root[len("./templates/blog/"):] : <a href="https://flask.palletsprojects.com/en/2.0.x/api/#flask.render_template"><code>render_template()</code></a>
datetime.fromtimestamp(os.path.getmtime(os.path.join(root,"index.html"))) returns a string. The result will be interpreted by the browser in
for root, dirs, files in os.walk("./templates/blog") if "index.html" in files} HTML/CSS format.</p>
</code> <div class="codehilite"><pre><span></span><code> <span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
</pre> <span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">_paths</span><span class="o">=</span><span class="n">meta_data</span><span class="p">):</span>
Routes are set by the use of decorators. The landing page is declared in the following snippet. After the dictionary is sorted by date, <a href="https://flask.palletsprojects.com/en/2.0.x/api/#flask.render_template"><code>render_template()</code></a> returns a string. The result will be interpreted by the browser in HTML/CSS format. <span class="n">sorted_meta_data</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">meta_data</span><span class="o">.</span><span class="n">items</span><span class="p">(),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">item</span> <span class="p">:</span> <span class="n">item</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
<pre> <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">&quot;index.html&quot;</span><span class="p">,</span> <span class="n">_paths</span><span class="o">=</span><span class="n">sorted_meta_data</span><span class="p">)</span>
<code> </code></pre></div>
@app.route('/')
def index(_paths=meta_data):
sorted_meta_data = dict(sorted(meta_data.items(), reverse=True, key=lambda item : item[1]))
return render_template("index.html", _paths=sorted_meta_data)
</code>
</pre>
The main page, like every other page, extends the general jinja template. It contains a list of all articles found.
<pre>
<code>
&#x7b;% extends "template.html" %&#x7d;
&#x7b;% block head %&#x7d;
&#x7b;&#x7b; super() &#x7d;&#x7d;
&#x7b;% endblock %&#x7d;
&#x7b;% block content %&#x7d;
&lt;p&gt;Welcome to my website&lt;/p&gt;
&lt;span class="index"&gt;
&#x7b;% for name,_date in _paths.items() %&#x7d;
&lt;p&gt;&lt;a href="&#x7b;&#x7b; url_for('blog', blog_item=name) &#x7d;&#x7d;"&gt;&#x7b;&#x7b; _date.date() &#x7d;&#x7d;&emsp;&emsp;&#x7b;&#x7b; name &#x7d;&#x7d;&lt;/a&gt;&lt;/p&gt;
&#x7b;% endfor %&#x7d;
&lt;/span&gt;
&#x7b;% endblock %&#x7d;
</code>
</pre>
URLs originate from the meta_data dictionary keys. These are the blog entries&rsquo; directory names. Flask&rsquo;s <a href="https://flask.palletsprojects.com/en/2.0.x/api/#flask.url_for" ><code>url_for()</code></a> returns the articles if you want to visit the site. It handles URL encoding as well. This is pretty neat since there are spaces in the names.
<pre>
<code>
@app.route('/blog/&lt;blog_item&gt;/index.html')
def blog(blog_item, _date=meta_data):
return render_template(f"blog/{blog_item}/index.html", _date=meta_data[blog_item])
</code>
</pre>
<h2>Digestif</h2>
<hr/>
Incidentally, this turned out to be not only an opener for my blog but code documentation for myself as well. Maybe, I&rsquo;ll need to pick it up in six months, who knows&#8230;.
As a closure, at least from my experience, the most feature-rich application seldom reaches its set goals. The one with a clear and precise target, fulfilling its minimal scope, most likely will.
<p>
<a href="https://www.bonappetit.com/recipe/best-pesto">This is how you make pesto, by the way.</a> Bon Appetit!
</p>
<p id="references" class="references">
<h2>References</h2>
<a href="https://www.bookfinder.com/?isbn=9783899555844">[1] Less and More: The Design Ethos of Dieter Rams, 2015, ISBN:9783899555844</a><br>
<a href="https://www.bookfinder.com/?isbn=9780465051366">[2] Emotional Design: Why We Love (or Hate) Everyday Things, 2005, ISBN:9780465051366</a>
<a href="https://www.bookfinder.com/?isbn=9780465067107">[3] The Design of Everyday Things, 2002, ISBN, 9780465067107</a>
</p>
<p>The main page, like every other page, extends the general jinja
template. It contains a list of all articles found.</p>
<div class="codehilite"><pre><span></span><code><span class="w"> </span><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&quot;template.html&quot;</span> <span class="cp">%}</span>
<span class="w"> </span><span class="cp">{%</span> <span class="k">block</span> <span class="nv">head</span> <span class="cp">%}</span>
<span class="w"> </span><span class="cp">{{</span> <span class="nb">super</span><span class="o">()</span> <span class="cp">}}</span>
<span class="w"> </span><span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
<span class="w"> </span><span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span><span class="w"> </span>
<span class="w"> </span><span class="nt">&lt;p&gt;</span>Welcome<span class="w"> </span>to<span class="w"> </span>my<span class="w"> </span>website<span class="nt">&lt;/p&gt;</span>
<span class="w"> </span><span class="nt">&lt;span</span><span class="w"> </span><span class="na">class=</span><span class="s">&quot;index&quot;</span><span class="nt">&gt;</span>
<span class="w"> </span><span class="cp">{%</span> <span class="k">for</span> <span class="nv">name</span><span class="o">,</span><span class="nv">_date</span> <span class="k">in</span> <span class="nv">_paths.items</span><span class="o">()</span> <span class="cp">%}</span>
<span class="w"> </span><span class="nt">&lt;p&gt;&lt;a</span><span class="w"> </span><span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;blog&#39;</span><span class="o">,</span> <span class="nv">blog_item</span><span class="o">=</span><span class="nv">name</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">_date.date</span><span class="o">()</span> <span class="cp">}}</span><span class="w"></span><span class="cp">{{</span> <span class="nv">name</span> <span class="cp">}}</span><span class="nt">&lt;/a&gt;&lt;/p&gt;</span>
<span class="w"> </span><span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="w"> </span><span class="nt">&lt;/span&gt;</span>
<span class="w"> </span><span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</code></pre></div>
<p>URLs originate from the meta_data dictionary keys. These are the blog
entries' directory names. Flask's
<a href="https://flask.palletsprojects.com/en/2.0.x/api/#flask.url_for"><code>url_for()</code></a>
returns the articles if you want to visit the site. It handles URL
encoding as well. This is pretty neat since there are spaces in the
names.</p>
<div class="codehilite"><pre><span></span><code> <span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/blog/&lt;blog_item&gt;/index.html&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">blog</span><span class="p">(</span><span class="n">blog_item</span><span class="p">,</span> <span class="n">_date</span><span class="o">=</span><span class="n">meta_data</span><span class="p">):</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;blog/</span><span class="si">{</span><span class="n">blog_item</span><span class="si">}</span><span class="s2">/index.html&quot;</span><span class="p">,</span> <span class="n">_date</span><span class="o">=</span><span class="n">meta_data</span><span class="p">[</span><span class="n">blog_item</span><span class="p">])</span>
</code></pre></div>
<h2 id="digestif"><a href="#digestif">Digestif</a></h2>
<hr />
<p>Incidentally, this turned out to be not only an opener for my blog but
code documentation for myself as well. Maybe, I'll need to pick it up in
six months, who knows.... As a closure, at least from my experience, the
most feature-rich application seldom reaches its set goals. The one with
a clear and precise target, fulfilling its minimal scope, most likely
will.</p>
<p><a href="https://www.bonappetit.com/recipe/best-pesto">This is how you make pesto, by the
way.</a> Bon Appetit!</p>
<h2 id="references"><a href="#references">References</a></h2>
<p><a href="https://www.bookfinder.com/?isbn=9783899555844">[1] Less and More: The Design Ethos of Dieter Rams, 2015,
ISBN:9783899555844</a><br />
<a href="https://www.bookfinder.com/?isbn=9780465051366">[2] Emotional Design: Why We Love (or Hate) Everyday Things, 2005,
ISBN:9780465051366</a><br />
<a href="https://www.bookfinder.com/?isbn=9780465067107">[3] The Design of Everyday Things, 2002, ISBN,
9780465067107</a></p>
</span>
</div> </div>
<div id="footer"> <div id="footer">

View File

@ -1,5 +1,4 @@
<!doctype html> <!doctype html>
<!doctype html>
<html lang="en"> <html lang="en">
<center> <center>
<head> <head>
@ -12,6 +11,19 @@
<div class="menu"> <div class="menu">
<a href="/" style="text-decoration:none">Stefan Friese's Website</a> <a href="/" style="text-decoration:none">Stefan Friese's Website</a>
</div> </div>
<style>
/* Stylesheet 1 */
body { background: #2f333d; color: #979fad; }
hr{ color: #979fad; border-color: #979fad; }
pre { background: #282c34; color: #979fad; border: 1px solid #282c34; }
code { background: #282c34; color: #979fad; }
a:hover { color: #be5046; }
details > summary { background: #282c34; }
details > summary:hover { background: #2f333d; color: #979fad; }
::selection { background: #668799; }
::-moz-selection { background: #668799; }
</style>
<hr style="width: 36ch;"/> <hr style="width: 36ch;"/>
<div class="menu"> <div class="menu">
<a href="/about.html" style="text-decoration:none">about&emsp;</a> <a href="/about.html" style="text-decoration:none">about&emsp;</a>
@ -28,85 +40,216 @@
</head> </head>
<body> <body>
<div lang="en" class="content"> <div lang="en" class="content">
2022-05-29 <span class="body">
<p><h1>The Joy of One-Liners</h1> <!-- 2022-05-29 -->
There is an engineering idiom which withstands time like no other. As old as the hills but never forgotten. In informational technology relations, one could say it is ancient. Its dawn proclaimed from the shores of Seattle, defeated by an apocalyptic horseman with the melodious name <i>NT</i>. Shot! Point blank into the chest. Buried under the hills of an IT dark age which we call the nineties, dead. But is it? Well, not exactly. There is still life in the old dog. Like Beatrix Kiddo, it one-inch punches itself back to daylight. Coal black as a miner. Topsoil sticks to its beige 1978&rsquo;s leather jacket, it trickles to the ground with every step taken to the nearest diner. The door opens again. &ldquo;May I have a glass of water, please?&rdquo; <style>pre { line-height: 125%; }
</p> td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
<p> span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
An art passed down from the ancestors. Its most visible interface: <i>The Shell</i>. Its name: <i>The Unix Philosophy</i>. td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
<p> span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
Coined by Doug McIlroy in the <a href="https://archive.org/details/bstj57-6-1899/mode/2up">Bell System Technical Journal</a> as a foreword to the UNIX Time-Sharing System. There is an even more concise version<a href=#references" style="text-decoration:none">[1]</a> and according to <a href="http://www.catb.org/~esr/writings/taoup/html/ch01s06.html">Eric Steven Raymond</a> this is <a href="#references" style="text-decoration:none">[2]</a>: .codehilite .hll { background-color: #ffffcc }
<blockquote>&ldquo;This is the Unix philosophy: Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.&rdquo;<br>&mdash; Doug McIlroy &mdash;</br></blockquote> .codehilite .c { color: #7F848E } /* Comment */
</p> .codehilite .err { color: #ABB2BF } /* Error */
<p> .codehilite .esc { color: #ABB2BF } /* Escape */
In some way, this is similar to the concept of the on vogue philosophy of microservices everywhere. Services are written to do one thing and do it well. They work together. Also, text is the connecting link between programs, services, and humans. The possibility to read a program&rsquo;s output as text seems benign, as long as everything is working well. The advantage is interactivity at any time, testability of every component, and debuggability at every step of the process in an on the fly manner. Impromptu, out of reflex like a punch. .codehilite .g { color: #ABB2BF } /* Generic */
</p> .codehilite .k { color: #C678DD } /* Keyword */
<h2>Pipe Dreams</h2> .codehilite .l { color: #ABB2BF } /* Literal */
<hr/> .codehilite .n { color: #E06C75 } /* Name */
Mc Ilroy made another very important contribution, which is the Unix pipe. It is the practical implementation of connecting the programs inside the shell. He saw the programs as tools, plugged together via pipes building a <a href="http://www.princeton.edu/~hos/Mahoney/expotape.htm">toolbox</a>. Program A&rsquo;s <code>stdout</code> is put into the <code>stdin</code> of program B. This leaves us with a single line of chained, well-defined programs to solve a problem that would otherwise be an extensive, multi-line program in any programming language of your choice. .codehilite .o { color: #56B6C2 } /* Operator */
</p> .codehilite .x { color: #ABB2BF } /* Other */
Let&rsquo;s say we&rsquo;ve got two programs. The first is one is <i>fortune</i>, the fortune cookie program from BSD games, which outputs random quotes as text. The second one is <i>cowsay</i>, which displays various kinds of animals as ASCII art. In order to work in a coherent manner a <code>|</code> is used. The pipe connects the first one to the second one. .codehilite .p { color: #ABB2BF } /* Punctuation */
<p> .codehilite .ch { color: #7F848E } /* Comment.Hashbang */
<pre> .codehilite .cm { color: #7F848E } /* Comment.Multiline */
<code> .codehilite .cp { color: #7F848E } /* Comment.Preproc */
fortune | cowsay .codehilite .cpf { color: #7F848E } /* Comment.PreprocFile */
_________________________________________ .codehilite .c1 { color: #7F848E } /* Comment.Single */
/ Gil-galad was an Elven-king. Of him the \ .codehilite .cs { color: #7F848E } /* Comment.Special */
| harpers sadly sing: the last whose | .codehilite .gd { color: #ABB2BF } /* Generic.Deleted */
| realm was fair and free between the | .codehilite .ge { color: #ABB2BF } /* Generic.Emph */
| Mountains and the Sea. | .codehilite .gr { color: #ABB2BF } /* Generic.Error */
| | .codehilite .gh { color: #ABB2BF } /* Generic.Heading */
| His sword was long, his lance was keen, | .codehilite .gi { color: #ABB2BF } /* Generic.Inserted */
| his shining helm afar was seen; the | .codehilite .go { color: #ABB2BF } /* Generic.Output */
| countless stars of heaven's field were | .codehilite .gp { color: #ABB2BF } /* Generic.Prompt */
| mirrored in his silver shield. | .codehilite .gs { color: #ABB2BF } /* Generic.Strong */
| | .codehilite .gu { color: #ABB2BF } /* Generic.Subheading */
| But long ago he rode away, and where he | .codehilite .gt { color: #ABB2BF } /* Generic.Traceback */
| dwelleth none can say; for into | .codehilite .kc { color: #E5C07B } /* Keyword.Constant */
| darkness fell his star in Mordor where | .codehilite .kd { color: #C678DD } /* Keyword.Declaration */
| the shadows are. | .codehilite .kn { color: #C678DD } /* Keyword.Namespace */
| | .codehilite .kp { color: #C678DD } /* Keyword.Pseudo */
\ -- J. R. R. Tolkien / .codehilite .kr { color: #C678DD } /* Keyword.Reserved */
----------------------------------------- .codehilite .kt { color: #E5C07B } /* Keyword.Type */
\ ^__^ .codehilite .ld { color: #ABB2BF } /* Literal.Date */
\ (oo)\_______ .codehilite .m { color: #D19A66 } /* Literal.Number */
(__)\ )\/\ .codehilite .s { color: #98C379 } /* Literal.String */
||----w | .codehilite .na { color: #E06C75 } /* Name.Attribute */
|| || .codehilite .nb { color: #E5C07B } /* Name.Builtin */
</code> .codehilite .nc { color: #E5C07B } /* Name.Class */
</pre> .codehilite .no { color: #E06C75 } /* Name.Constant */
<p> .codehilite .nd { color: #61AFEF } /* Name.Decorator */
To mix in some colors pipe everything through lolcat. Try it out! .codehilite .ni { color: #E06C75 } /* Name.Entity */
</p> .codehilite .ne { color: #E06C75 } /* Name.Exception */
<pre> .codehilite .nf { color: #61AFEF; font-weight: bold } /* Name.Function */
<code> .codehilite .nl { color: #E06C75 } /* Name.Label */
fortune | cowsay | lolcat .codehilite .nn { color: #E06C75 } /* Name.Namespace */
</code> .codehilite .nx { color: #E06C75 } /* Name.Other */
</pre> .codehilite .py { color: #E06C75 } /* Name.Property */
<p> .codehilite .nt { color: #E06C75 } /* Name.Tag */
So far so good, let us gain some real-world practice. .codehilite .nv { color: #E06C75 } /* Name.Variable */
</p> .codehilite .ow { color: #56B6C2 } /* Operator.Word */
<h2>Punching Lines &mdash; Retire Your Password Generator</h2> .codehilite .pm { color: #ABB2BF } /* Punctuation.Marker */
<hr/> .codehilite .w { color: #ABB2BF } /* Text.Whitespace */
Have you ever questioned the integrity of your one-click, GUI, proprietary password generator? Is its randomness really as unpredictable as it proclaims? Are you the only one which ends up knowing your generated password? There is a one-liner that ups your opsec instantly. Right from the source of randomness: .codehilite .mb { color: #D19A66 } /* Literal.Number.Bin */
<pre> .codehilite .mf { color: #D19A66 } /* Literal.Number.Float */
<code> .codehilite .mh { color: #D19A66 } /* Literal.Number.Hex */
head -n 42 /dev/urandom | tr -cd '[:alnum:]' | cut -c-12 .codehilite .mi { color: #D19A66 } /* Literal.Number.Integer */
</code> .codehilite .mo { color: #D19A66 } /* Literal.Number.Oct */
</pre> .codehilite .sa { color: #98C379 } /* Literal.String.Affix */
So, what is going on here? Everything is a file, that is the way *nix systems see it, even the device which puts out random data. To read the upper part of a file we use <code>head</code>. It will be sent to <code>stdout</code> and displayed via the shell. Parameter <code>-n</code> reads exactly 42 lines of the file given to gather enough randomness. The output of <code>head</code> will be sent to <code>tr</code>. In order to select only alphanumeric characters for our password, we use <code>'[:alnum:]'</code>. Parameters <code>-c</code> selects the complement of alphanumeric characters and <code>-d</code> deletes them. <code>cut</code> does exactly what it says, <code>-c-12</code> cuts after 12 characters with leaves us with a random password of length 12. Every time you execute this one-liner a freshly made random password is returned. .codehilite .sb { color: #98C379 } /* Literal.String.Backtick */
<p> .codehilite .sc { color: #98C379 } /* Literal.String.Char */
To extend the pool of possible symbols the manual of <code>tr</code> lists various sets of filtered symbols. In the case of a password generator, further sensible filters are <code>'[:alpha:]'</code> or <code>'[:digit:]'</code>. While <code>'[:graph:]'</code> is also viable in this case it returns one of the greater sets of symbols. Use it with caution, especially if you create passwords for database users. These might be terminated prematurely through <code>`</code> or <code>'</code> inside the returned string. .codehilite .dl { color: #98C379 } /* Literal.String.Delimiter */
</p> .codehilite .sd { color: #98C379 } /* Literal.String.Doc */
<h2>Sunday Punch</h2> .codehilite .s2 { color: #98C379 } /* Literal.String.Double */
<hr/> .codehilite .se { color: #98C379 } /* Literal.String.Escape */
This blog entrance can be seen as a prelude to a series of one-liners I use time and time again. The are multiple in the pipeline. One-liners should save you the time you otherwise would spend coding a complex solution. There is little better than solving a challenging problem in a single line. .codehilite .sh { color: #98C379 } /* Literal.String.Heredoc */
<p id="references" class="references"> .codehilite .si { color: #98C379 } /* Literal.String.Interpol */
<h2>References</h2> .codehilite .sx { color: #98C379 } /* Literal.String.Other */
<a href="https://www.bookfinder.com/?isbn=9780201547771">[1] A Quarter Century of Unix, 1994, Peter Salus, ISBN:9780201547771</a><br> .codehilite .sr { color: #98C379 } /* Literal.String.Regex */
<a href="https://www.bookfinder.com/?isbn=9780131429017">[2] The Art of UNIX Programming, 2003, Eric Raymond, ISBN:9780131429017</a><br> .codehilite .s1 { color: #98C379 } /* Literal.String.Single */
</p> .codehilite .ss { color: #98C379 } /* Literal.String.Symbol */
.codehilite .bp { color: #E5C07B } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #56B6C2; font-weight: bold } /* Name.Function.Magic */
.codehilite .vc { color: #E06C75 } /* Name.Variable.Class */
.codehilite .vg { color: #E06C75 } /* Name.Variable.Global */
.codehilite .vi { color: #E06C75 } /* Name.Variable.Instance */
.codehilite .vm { color: #E06C75 } /* Name.Variable.Magic */
.codehilite .il { color: #D19A66 } /* Literal.Number.Integer.Long */</style>
<p>2022-05-29</p>
<h1 id="the-joy-of-one-liners">The Joy of One-Liners</h1>
<p>There is an engineering idiom which withstands time like no other. As
old as the hills but never forgotten. In informational technology
relations, one could say it is ancient. Its dawn proclaimed from the
shores of Seattle, defeated by an apocalyptic horseman with the
melodious name <em>NT</em>. Shot! Point blank into the chest. Buried under the
hills of an IT dark age which we call the nineties, dead. But is it?
Well, not exactly. There is still life in the old dog. Like Beatrix
Kiddo, it one-inch punches itself back to daylight. Coal black as a
miner. Topsoil sticks to its beige 1978's leather jacket, it trickles to
the ground with every step taken to the nearest diner. The door opens
again. "May I have a glass of water, please?"</p>
<p>An art passed down from the ancestors. Its most visible interface: <em>The
Shell</em>. Its name: <em>The Unix Philosophy</em>.</p>
<p>Coined by Doug McIlroy in the <a href="https://archive.org/details/bstj57-6-1899/mode/2up">Bell System Technical
Journal</a> as a
foreword to the UNIX Time-Sharing System. There is an even more concise
version<a href="#references">[1]</a> and
according to <a href="http://www.catb.org/~esr/writings/taoup/html/ch01s06.html">Eric Steven
Raymond</a> this
is <a href="#references">[2]</a>:</p>
<blockquote>
<p>"This is the Unix philosophy: Write programs that do one thing and do
it well. Write programs to work together. Write programs to handle
text streams, because that is a universal interface."<br />
--- Doug McIlroy ---</p>
</blockquote>
<p>In some way, this is similar to the concept of the on vogue philosophy
of microservices everywhere. Services are written to do one thing and do
it well. They work together. Also, text is the connecting link between
programs, services, and humans. The possibility to read a program's
output as text seems benign, as long as everything is working well. The
advantage is interactivity at any time, testability of every component,
and debuggability at every step of the process in an on the fly manner.
Impromptu, out of reflex like a punch.</p>
<h2 id="pipe-dreams"><a href="#pipe-dreams">Pipe Dreams</a></h2>
<hr />
<p>Mc Ilroy made another very important contribution, which is the Unix
pipe. It is the practical implementation of connecting the programs
inside the shell. He saw the programs as tools, plugged together via
pipes building a
<a href="http://www.princeton.edu/~hos/Mahoney/expotape.htm">toolbox</a>. Program
A's <code>stdout</code> is put into the <code>stdin</code> of program B. This leaves us with a
single line of chained, well-defined programs to solve a problem that
would otherwise be an extensive, multi-line program in any programming
language of your choice.</p>
<p>Let's say we've got two programs. The first is one is <em>fortune</em>, the
fortune cookie program from BSD games, which outputs random quotes as
text. The second one is <em>cowsay</em>, which displays various kinds of
animals as ASCII art. In order to work in a coherent manner a <code>|</code> is
used. The pipe connects the first one to the second one.</p>
<div class="codehilite"><pre><span></span><code>fortune<span class="w"> </span><span class="p">|</span><span class="w"> </span>cowsay
<span class="w"> </span>_________________________________________
<span class="w"> </span>/<span class="w"> </span>Gil-galad<span class="w"> </span>was<span class="w"> </span>an<span class="w"> </span>Elven-king.<span class="w"> </span>Of<span class="w"> </span>him<span class="w"> </span>the<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>harpers<span class="w"> </span>sadly<span class="w"> </span>sing:<span class="w"> </span>the<span class="w"> </span>last<span class="w"> </span>whose<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>realm<span class="w"> </span>was<span class="w"> </span>fair<span class="w"> </span>and<span class="w"> </span>free<span class="w"> </span>between<span class="w"> </span>the<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>Mountains<span class="w"> </span>and<span class="w"> </span>the<span class="w"> </span>Sea.<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>His<span class="w"> </span>sword<span class="w"> </span>was<span class="w"> </span>long,<span class="w"> </span>his<span class="w"> </span>lance<span class="w"> </span>was<span class="w"> </span>keen,<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>his<span class="w"> </span>shining<span class="w"> </span>helm<span class="w"> </span>afar<span class="w"> </span>was<span class="w"> </span>seen<span class="p">;</span><span class="w"> </span>the<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>countless<span class="w"> </span>stars<span class="w"> </span>of<span class="w"> </span>heaven<span class="err">&#39;</span>s<span class="w"> </span>field<span class="w"> </span>were<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>mirrored<span class="w"> </span><span class="k">in</span><span class="w"> </span>his<span class="w"> </span>silver<span class="w"> </span>shield.<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>But<span class="w"> </span>long<span class="w"> </span>ago<span class="w"> </span>he<span class="w"> </span>rode<span class="w"> </span>away,<span class="w"> </span>and<span class="w"> </span>where<span class="w"> </span>he<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>dwelleth<span class="w"> </span>none<span class="w"> </span>can<span class="w"> </span>say<span class="p">;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span>into<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>darkness<span class="w"> </span>fell<span class="w"> </span>his<span class="w"> </span>star<span class="w"> </span><span class="k">in</span><span class="w"> </span>Mordor<span class="w"> </span>where<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>the<span class="w"> </span>shadows<span class="w"> </span>are.<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="se">\ </span>--<span class="w"> </span>J.<span class="w"> </span>R.<span class="w"> </span>R.<span class="w"> </span>Tolkien<span class="w"> </span>/
<span class="w"> </span>-----------------------------------------
<span class="w"> </span><span class="se">\ </span><span class="w"> </span>^__^
<span class="w"> </span><span class="se">\ </span><span class="w"> </span><span class="o">(</span>oo<span class="o">)</span><span class="se">\_</span>______
<span class="w"> </span><span class="o">(</span>__<span class="o">)</span><span class="se">\ </span><span class="w"> </span><span class="o">)</span><span class="se">\/\</span>
<span class="w"> </span><span class="o">||</span>----w<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">||</span>
</code></pre></div>
<p>To mix in some colors pipe everything through lolcat. Try it out!</p>
<div class="codehilite"><pre><span></span><code>fortune<span class="w"> </span><span class="p">|</span><span class="w"> </span>cowsay<span class="w"> </span><span class="p">|</span><span class="w"> </span>lolcat
</code></pre></div>
<p>So far so good, let us gain some real-world practice.</p>
<h2 id="punching-lines-and-retire-your-password-generator"><a href="#punching-lines-and-retire-your-password-generator">Punching Lines and Retire Your Password Generator</a></h2>
<hr />
<p>Have you ever questioned the integrity of your one-click, GUI,
proprietary password generator? Is its randomness really as
unpredictable as it proclaims? Are you the only one which ends up
knowing your generated password? There is a one-liner that ups your
opsec instantly. Right from the source of randomness:</p>
<div class="codehilite"><pre><span></span><code>head<span class="w"> </span>-n<span class="w"> </span><span class="m">42</span><span class="w"> </span>/dev/urandom<span class="w"> </span><span class="p">|</span><span class="w"> </span>tr<span class="w"> </span>-cd<span class="w"> </span><span class="s1">&#39;[:alnum:]&#39;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>cut<span class="w"> </span>-c-12
</code></pre></div>
<p>So, what is going on here? Everything is a file, that is the way *nix
systems see it, even the device which puts out random data. To read the
upper part of a file we use <code>head</code>. It will be sent to <code>stdout</code> and
displayed via the shell. Parameter <code>-n</code> reads exactly 42 lines of the
file given to gather enough randomness. The output of <code>head</code> will be
sent to <code>tr</code>. In order to select only alphanumeric characters for our
password, we use <code>'[:alnum:]'</code>. Parameters <code>-c</code> selects the complement
of alphanumeric characters and <code>-d</code> deletes them. <code>cut</code> does exactly
what it says, <code>-c-12</code> cuts after 12 characters with leaves us with a
random password of length 12. Every time you execute this one-liner a
freshly made random password is returned.</p>
<p>To extend the pool of possible symbols the manual of <code>tr</code> lists various
sets of filtered symbols. In the case of a password generator, further
sensible filters are <code>'[:alpha:]'</code> or <code>'[:digit:]'</code>. While <code>'[:graph:]'</code>
is also viable in this case it returns one of the greater sets of
symbols. Use it with caution, especially if you create passwords for
database users. These might be terminated prematurely through <code>`</code> or
<code>'</code> inside the returned string.</p>
<h2 id="sunday-punch"><a href="#sunday-punch">Sunday Punch</a></h2>
<hr />
<p>This blog entrance can be seen as a prelude to a series of one-liners I
use time and time again. The are multiple in the pipeline. One-liners
should save you the time you otherwise would spend coding a complex
solution. There is little better than solving a challenging problem in a
single line.</p>
<h2 id="references"><a href="#references">References</a></h2>
<p><a href="https://www.bookfinder.com/?isbn=9780201547771">[1] A Quarter Century of Unix, 1994, Peter Salus,
ISBN:9780201547771</a><br />
<a href="https://www.bookfinder.com/?isbn=9780131429017">[2] The Art of UNIX Programming, 2003, Eric Raymond,
ISBN:9780131429017</a></p>
</span>
</div> </div>
<div id="footer"> <div id="footer">

View File

@ -11,6 +11,19 @@
<div class="menu"> <div class="menu">
<a href="/" style="text-decoration:none">Stefan Friese's Website</a> <a href="/" style="text-decoration:none">Stefan Friese's Website</a>
</div> </div>
<style>
/* Stylesheet 1 */
body { background: #2f333d; color: #979fad; }
hr{ color: #979fad; border-color: #979fad; }
pre { background: #282c34; color: #979fad; border: 1px solid #282c34; }
code { background: #282c34; color: #979fad; }
a:hover { color: #be5046; }
details > summary { background: #282c34; }
details > summary:hover { background: #2f333d; color: #979fad; }
::selection { background: #668799; }
::-moz-selection { background: #668799; }
</style>
<hr style="width: 36ch;"/> <hr style="width: 36ch;"/>
<div class="menu"> <div class="menu">
<a href="/about.html" style="text-decoration:none">about&emsp;</a> <a href="/about.html" style="text-decoration:none">about&emsp;</a>

View File

@ -11,6 +11,19 @@
<div class="menu"> <div class="menu">
<a href="/" style="text-decoration:none">Stefan Friese's Website</a> <a href="/" style="text-decoration:none">Stefan Friese's Website</a>
</div> </div>
<style>
/* Stylesheet 1 */
body { background: #2f333d; color: #979fad; }
hr{ color: #979fad; border-color: #979fad; }
pre { background: #282c34; color: #979fad; border: 1px solid #282c34; }
code { background: #282c34; color: #979fad; }
a:hover { color: #be5046; }
details > summary { background: #282c34; }
details > summary:hover { background: #2f333d; color: #979fad; }
::selection { background: #668799; }
::-moz-selection { background: #668799; }
</style>
<hr style="width: 36ch;"/> <hr style="width: 36ch;"/>
<div class="menu"> <div class="menu">
<a href="/about.html" style="text-decoration:none">about&emsp;</a> <a href="/about.html" style="text-decoration:none">about&emsp;</a>

View File

@ -1,2 +1,2 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Website of Stefan Friese</title><link>https://stefan.works</link><description>test</description><atom:link href="https://stefan.works" rel="self"/><docs>http://www.rssboard.org/rss-specification</docs><generator>python-feedgen</generator><language>en-us</language><lastBuildDate>Tue, 20 Jun 2023 19:21:25 +0000</lastBuildDate><item><title>The Joy of One-Liners</title><link>https://stefan.works/blog/The Joy of One-Liners/index.html</link><guid isPermaLink="false">https://stefan.works/blog/The Joy of One-Liners/index.html</guid><pubDate>Sun, 29 May 2022 22:27:49 +0200</pubDate></item><item><title>Keep It Simple</title><link>https://stefan.works/blog/Keep It Simple/index.html</link><guid isPermaLink="false">https://stefan.works/blog/Keep It Simple/index.html</guid><pubDate>Tue, 01 Jun 2021 18:57:19 +0200</pubDate></item></channel></rss> <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Website of Stefan Friese</title><link>https://stefan.works</link><description>test</description><atom:link href="https://stefan.works" rel="self"/><docs>http://www.rssboard.org/rss-specification</docs><generator>python-feedgen</generator><language>en-us</language><lastBuildDate>Sat, 15 Jul 2023 21:28:59 +0000</lastBuildDate><item><title>The Joy of One-Liners</title><link>https://stefan.works/blog/The Joy of One-Liners/index.html</link><guid isPermaLink="false">https://stefan.works/blog/The Joy of One-Liners/index.html</guid><pubDate>Sun, 29 May 2022 00:00:00 +0200</pubDate></item><item><title>Keep It Simple</title><link>https://stefan.works/blog/Keep It Simple/index.html</link><guid isPermaLink="false">https://stefan.works/blog/Keep It Simple/index.html</guid><pubDate>Tue, 01 Jun 2021 00:00:00 +0200</pubDate></item></channel></rss>

View File

@ -1,2 +1,2 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Website of Stefan Friese</title><link>https://stefan.works</link><description>test</description><atom:link href="https://stefan.works" rel="self"/><docs>http://www.rssboard.org/rss-specification</docs><generator>python-feedgen</generator><language>en-us</language><lastBuildDate>Tue, 20 Jun 2023 19:11:26 +0000</lastBuildDate><item><title>The Joy of One-Liners</title><link>https://stefan.works/blog/The Joy of One-Liners/index.html</link><guid isPermaLink="false">https://stefan.works/blog/The Joy of One-Liners/index.html</guid><pubDate>Sun, 07 Aug 2022 22:27:46 +0200</pubDate></item><item><title>Keep It Simple</title><link>https://stefan.works/blog/Keep It Simple/index.html</link><guid isPermaLink="false">https://stefan.works/blog/Keep It Simple/index.html</guid><pubDate>Sun, 30 Jan 2022 17:57:19 +0100</pubDate></item></channel></rss> <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Website of Stefan Friese</title><link>https://stefan.works</link><description>test</description><atom:link href="https://stefan.works" rel="self"/><docs>http://www.rssboard.org/rss-specification</docs><generator>python-feedgen</generator><language>en-us</language><lastBuildDate>Tue, 11 Jul 2023 21:32:56 +0000</lastBuildDate><item><title>The Joy of One-Liners</title><link>https://stefan.works/blog/The Joy of One-Liners/index.html</link><guid isPermaLink="false">https://stefan.works/blog/The Joy of One-Liners/index.html</guid><pubDate>Sun, 29 May 2022 00:00:00 +0200</pubDate></item><item><title>Keep It Simple</title><link>https://stefan.works/blog/Keep It Simple/index.html</link><guid isPermaLink="false">https://stefan.works/blog/Keep It Simple/index.html</guid><pubDate>Tue, 01 Jun 2021 00:00:00 +0200</pubDate></item></channel></rss>

View File

@ -1,20 +1,39 @@
html *{ font-family: Dejavu Sans Mono, MesloGS NF, Menlo, Consolas, Monospace !important; color: #222;} /* html *{ font-family: Dejavu Sans Mono, MesloGS NF, Menlo, Consolas, Monospace !important; color: #222;} */
/* body {text-align: justify; max-width: 86ch; margin:40px auto; padding: 0 10px; text-decoration: none;} */
/* h1 { font-size: 28px; } */
/* h2 { font-size: 22px; margin-bottom: 2px; } */
/* h3 { font-size: 14px; } */
/* p { font-size: 16px; } */
/* blockquote { text-align: center; font-size: 16px; font-style: normal; line-height: 30px;} */
/* pre { background-color: #eee;color: #2f3337;border: 1px solid #ddd; font-size: 14px; padding-left: 2ch; line-height: 18px; overflow: auto; } */
/* code { background-color: #eee;color: #2f3337; } */
/* hr { height: 1px; background: #333; border: 0px;} */
/* a {color: inherit; text-decoration: solid underline;} */
/* a:hover {color: red;} */
/* img { max-width: 100%; } */
/* .menu { line-height: 1em; font-size: 24px; line-height: 1em; text-decoration: none; } */
/* .index { color: inherit; text-decoration: solid underline; } */
/* .references { text-decoration: solid underline; text-underline-position: under; } */
/* .contact{text-align: center;} */
html *{ font-family: Dejavu Sans Mono, MesloGS NF, Menlo, Consolas, Monospace !important;}
body {text-align: justify; max-width: 86ch; margin:40px auto; padding: 0 10px; text-decoration: none;} body {text-align: justify; max-width: 86ch; margin:40px auto; padding: 0 10px; text-decoration: none;}
h1 { font-size: 28px; } h1 { font-size: 28px; }
h2 { font-size: 22px; margin-bottom: 2px; } h2 { font-size: 22px; margin-bottom: 2px; }
h2 a:link{ text-decoration: none; }
h3 { font-size: 14px; } h3 { font-size: 14px; }
p { font-size: 16px; } p { font-size: 16px; }
blockquote { text-align: center; font-size: 16px; font-style: normal; line-height: 30px;} blockquote { text-align: center; font-size: 16px; font-style: normal; line-height: 30px;}
pre { background-color: #eee;color: #2f3337;border: 1px solid #ddd; font-size: 14px; padding-left: 2ch; line-height: 18px; overflow: auto; } pre { border: 1px solid #ddd; font-size: 14px; padding: 1ch; line-height: 18px; overflow: auto; }
code { background-color: #eee;color: #2f3337; } /* code { background-color: #282C34; color: #979FAD; } */
hr { height: 1px; background: #333; border: 0px;} code {padding-left: 0.5ch; padding-right: 0.5ch;}
/* hr { height: 1px; border: 0px;} */
a {color: inherit; text-decoration: solid underline;} a {color: inherit; text-decoration: solid underline;}
a:hover {color: red;} img { max-width: 100%; display: block; margin-left: auto; margin-right: auto; margin-top: 2ch; margin-bottom: 2ch; padding: 1ch;}
img { max-width: 100%; }
.menu { line-height: 1em; font-size: 24px; line-height: 1em; text-decoration: none; } .menu { line-height: 1em; font-size: 24px; line-height: 1em; text-decoration: none; }
.index { color: inherit; text-decoration: solid underline; } .index { color: inherit; text-decoration: solid underline; }
.references { text-decoration: solid underline; text-underline-position: under; } .references { text-decoration: solid underline; text-underline-position: under; }
.contact{text-align: center;} .contact{text-align: center;}

0
freezer.py Normal file → Executable file
View File

View File

View File

@ -1,2 +1,2 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Website of Stefan Friese</title><link>https://stefan.works</link><description>test</description><atom:link href="https://stefan.works" rel="self"/><docs>http://www.rssboard.org/rss-specification</docs><generator>python-feedgen</generator><language>en-us</language><lastBuildDate>Tue, 11 Jul 2023 21:32:56 +0000</lastBuildDate><item><title>The Joy of One-Liners</title><link>https://stefan.works/blog/The Joy of One-Liners/index.html</link><guid isPermaLink="false">https://stefan.works/blog/The Joy of One-Liners/index.html</guid><pubDate>Sun, 29 May 2022 00:00:00 +0200</pubDate></item><item><title>Keep It Simple</title><link>https://stefan.works/blog/Keep It Simple/index.html</link><guid isPermaLink="false">https://stefan.works/blog/Keep It Simple/index.html</guid><pubDate>Tue, 01 Jun 2021 00:00:00 +0200</pubDate></item></channel></rss> <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Website of Stefan Friese</title><link>https://stefan.works</link><description>test</description><atom:link href="https://stefan.works" rel="self"/><docs>http://www.rssboard.org/rss-specification</docs><generator>python-feedgen</generator><language>en-us</language><lastBuildDate>Sat, 15 Jul 2023 21:28:59 +0000</lastBuildDate><item><title>The Joy of One-Liners</title><link>https://stefan.works/blog/The Joy of One-Liners/index.html</link><guid isPermaLink="false">https://stefan.works/blog/The Joy of One-Liners/index.html</guid><pubDate>Sun, 29 May 2022 00:00:00 +0200</pubDate></item><item><title>Keep It Simple</title><link>https://stefan.works/blog/Keep It Simple/index.html</link><guid isPermaLink="false">https://stefan.works/blog/Keep It Simple/index.html</guid><pubDate>Tue, 01 Jun 2021 00:00:00 +0200</pubDate></item></channel></rss>

View File

@ -21,7 +21,8 @@
html *{ font-family: Dejavu Sans Mono, MesloGS NF, Menlo, Consolas, Monospace !important;} html *{ font-family: Dejavu Sans Mono, MesloGS NF, Menlo, Consolas, Monospace !important;}
body {text-align: justify; max-width: 86ch; margin:40px auto; padding: 0 10px; text-decoration: none;} body {text-align: justify; max-width: 86ch; margin:40px auto; padding: 0 10px; text-decoration: none;}
h1 { font-size: 28px; } h1 { font-size: 28px; }
h2 { font-size: 22px; margin-bottom: 2px; } h2 { font-size: 22px; margin-bottom: 2px; }
h2 a:link{ text-decoration: none; }
h3 { font-size: 14px; } h3 { font-size: 14px; }
p { font-size: 16px; } p { font-size: 16px; }
blockquote { text-align: center; font-size: 16px; font-style: normal; line-height: 30px;} blockquote { text-align: center; font-size: 16px; font-style: normal; line-height: 30px;}
@ -30,7 +31,7 @@ pre { border: 1px solid #ddd; font-size: 14px; padding: 1ch; line-height: 18px;
code {padding-left: 0.5ch; padding-right: 0.5ch;} code {padding-left: 0.5ch; padding-right: 0.5ch;}
/* hr { height: 1px; border: 0px;} */ /* hr { height: 1px; border: 0px;} */
a {color: inherit; text-decoration: solid underline;} a {color: inherit; text-decoration: solid underline;}
img { max-width: 100%; display: block; margin-left: auto; margin-right: auto; } img { max-width: 100%; display: block; margin-left: auto; margin-right: auto; margin-top: 2ch; margin-bottom: 2ch; padding: 1ch;}
.menu { line-height: 1em; font-size: 24px; line-height: 1em; text-decoration: none; } .menu { line-height: 1em; font-size: 24px; line-height: 1em; text-decoration: none; }
.index { color: inherit; text-decoration: solid underline; } .index { color: inherit; text-decoration: solid underline; }
.references { text-decoration: solid underline; text-underline-position: under; } .references { text-decoration: solid underline; text-underline-position: under; }

View File

@ -1,6 +1,8 @@
[github-dark] [github-dark]
body_background ="#161b22" body_background ="#161b22"
body = "#ecf2f8" body = "#ecf2f8"
hr = "#ecf2f8"
hr_border = "#ecf2f8"
pre_background = "#0d1117" pre_background = "#0d1117"
pre = "#ecf2f8" pre = "#ecf2f8"
#pre_border = "#89929b" #pre_border = "#89929b"
@ -33,6 +35,8 @@ autocomplete_suggestion_hover = "#ecf2f8"
[nord] [nord]
body_background ="#616e87" body_background ="#616e87"
body = "#d8dee9" body = "#d8dee9"
hr = "#d8dee9"
hr_border = "#d8dee9"
pre_background = "#2e3440" pre_background = "#2e3440"
pre = "#d8dee9" pre = "#d8dee9"
#pre_border = "#89929b" #pre_border = "#89929b"
@ -65,6 +69,8 @@ autocomplete_suggestion_hover = "#d8dee9"
[one-dark] [one-dark]
body_background ="#2f333d" body_background ="#2f333d"
body = "#979fad" body = "#979fad"
hr = "#979fad"
hr_border = "#979fad"
pre_background = "#282c34" pre_background = "#282c34"
pre = "#979fad" pre = "#979fad"
pre_border = "#282c34" pre_border = "#282c34"
@ -97,6 +103,8 @@ autocomplete_suggestion_hover = "#3a3f4b"
[solarized-dark] [solarized-dark]
body_background ="#073642" body_background ="#073642"
body = "#93a1a1" body = "#93a1a1"
hr = "#93a1a1"
hr_border = "#93a1a1"
pre_background = "#002b36" pre_background = "#002b36"
pre = "#839496" pre = "#839496"
pre_border = "none" pre_border = "none"
@ -128,6 +136,8 @@ autocomplete_suggestion_hover = "#93a1a1"
[solarized-light] [solarized-light]
body_background ="#fdf6e3" body_background ="#fdf6e3"
body = "#657b83" body = "#657b83"
hr = "#657b83"
hr_border = "#657b83"
pre_background = "#eee8d5" pre_background = "#eee8d5"
pre = "#657b83" pre = "#657b83"
pre_border = "none" pre_border = "none"
@ -159,6 +169,8 @@ autocomplete_suggestion_hover = "#93a1a1"
[monokai] [monokai]
body_background ="#3e3d32" body_background ="#3e3d32"
body = "#f8f8f2" body = "#f8f8f2"
hr = "#f8f8f2"
hr_border = "#f8f8f2"
pre_background = "#272822" pre_background = "#272822"
pre = "#cfcfc2" pre = "#cfcfc2"
pre_border = "none" pre_border = "none"
@ -190,6 +202,8 @@ autocomplete_suggestion_hover = "#cfcfc2"
[xcode] [xcode]
body_background ="#fff" body_background ="#fff"
body = "#262626" body = "#262626"
hr = "#262626"
hr_border = "#262626"
pre_background = "#ecf5ff" pre_background = "#ecf5ff"
pre = "#262626" pre = "#262626"
pre_border = "none" pre_border = "none"

View File

@ -1,110 +0,0 @@
<!doctype html>
{% extends "template.html" %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
{{ _date.date() }}
<p><h1>Keep It Simple</h1>
While studying architecture not only had I so little money that I ate spaghetti and pesto every day, I learned a thing or two about design principles as well. These principles hold true for every product or piece of engineering you plan out. It is the KISS principle. Keep it simple stupid, or to quote a guy Jony Ive is clearly a fan of <a href="#references" style="text-decoration:none">[1]</a>:
<blockquote>&ldquo;Good design is as little design as possible.&rdquo;<br>&mdash; Dieter Rams &mdash;</br></blockquote>
</p>
<p>
Let&rsquo;s expand on it so far that it should be as simple as possible without being outright stupid. To expand even further, a compelling and useful design is not only measurable by the things you can do with it, but even more important are the things you don&rsquo;t have to do when you use it.
</p>
<p>
As you craft something, you will inevitably communicate with everybody using your product. In proxy, any room, place or inanimate object created by a human speaks to the user. Even on an emotional level. Psychologists or product designers like computer and car designers are no strangers to this. Donald Norman wrote multiple books about it <a rhef="#references" style="text-decoration:none">[2]</a>, <a href="#references" style="text-decoration:none">[3]</a>. Some good reads. Schulz von Thun defined the <a href="http://temp.chpfeiffer.de/Four-sides_model.pdf">four-ears model</a> in which a sender&rsquo;s message is received on four different levels. These are Factual information, Appeal, Self-revelation and Relationship. This means it is helpful to think about the essence of the aspect you want to craft to communicate clearly and get the message across.
<img style="float: right", alt="A functional lighter.", src="{{ url_for('static', filename='images/218px-White_BIC_lighter.png') }}">
</p>
<p>
<h2>Pesto Principles</h2>
<hr/>
What about this website's design principles? First and foremost, how you spent your time is important. Do you really need to wait for more than a few seconds to load a website? Then there should be a plausible reason for that. Should you wait more than 5 seconds to be able to read something a guy is rambling about on his blog? I highly doubt it. The layout should respect you and your time. Network traffic should be minimal.
</p>
Second, I don&rsquo;t want your data. No cookies, no statistics about you, no ad tracking of your surfing behavior. That is what you and I won&rsquo;t have to put up with. You may read my blog, or you don&rsquo;t. Take it or leave it. But I hope you will learn something by doing it or have a good time at least.
<p>
There are some points to make this website work and make it accessible. To write entries, I will use plain HTML. For now, it is sufficient. HTML is a nice markup language. Use a <code>&lt;lang&gt;</code> tag and you got translation accessibility. Another one is the following line, making the layout respond dynamically to different screen sizes. More examples on <a href="https://perfectmotherfuckingwebsite.com">this beautiful website</a>.
<pre>
<code>
&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
</code>
</pre>
This will be a blog about computers, for the most part, there will be code examples. Further, I want to keep the stylesheet small and maintainable. Monospaced fonts are not only a dead giveaway about this fact, a solid layout is created via the following line of CSS.
<pre>
<code>
.content{text-align:justify;}
</code>
</pre>
</p>
<p>
To keep things in perspective, the date of publication will be the first line in each article. If the content may be of interest to you, knowing the date it was created is beneficial in evaluating its potential usefulness over time.
</p>
<p>
There is no harm in growing something like a website incrementally. You will never miss a feature you never had in the first place. You could aspire to get it if it is conceptually meaningful and makes some sense in the overall picture. But a feature that does not exist needs no maintenance, does not produce any bugs and needs no documentation.
<blockquote>&ldquo;The things you own end up owning you.&rdquo;<br>&mdash; Chuck Palahniuk &mdash;</br></blockquote>
<h2>Cordial Code</h2>
<hr/>
The website was created on a Saturday afternoon in Python and Flask framework. Six months down the line, I do not want to put much energy into grasping what I had done this weekend regarding to code structure. I want to put the least amount of time possible into extending and maintaining the framework of the site. It consists of a Python file, a stylesheet, a jinja template and an empty favicon file. The last one exists because I want to avoid any error possible displayed in the network console of the browser. Everything else is content.
You can find the site as a repository on <a href="https://git.stefan.works">my git</a>.
<p>
A directory named <code>blog</code> contains all entries released as well as the ones I am working on. Metadata about subdirectories and the corresponding content is gathered inside a &lt;key&gt;:&lt;value&gt; structure. An entry is seen as valid and stored in the dictionary as soon as an index.html file is found. Who knows what might be added in the future. It will be added to a list of values. For now, metadata is solely the date of the blog articles. It is added to the RSS site automatically as well. The code snippet contains the dictionary.
</p>
<pre>
<code>
meta_data = {root[len("./templates/blog/"):] :
datetime.fromtimestamp(os.path.getmtime(os.path.join(root,"index.html")))
for root, dirs, files in os.walk("./templates/blog") if "index.html" in files}
</code>
</pre>
Routes are set by the use of decorators. The landing page is declared in the following snippet. After the dictionary is sorted by date, <a href="https://flask.palletsprojects.com/en/2.0.x/api/#flask.render_template"><code>render_template()</code></a> returns a string. The result will be interpreted by the browser in HTML/CSS format.
<pre>
<code>
@app.route('/')
def index(_paths=meta_data):
sorted_meta_data = dict(sorted(meta_data.items(), reverse=True, key=lambda item : item[1]))
return render_template("index.html", _paths=sorted_meta_data)
</code>
</pre>
The main page, like every other page, extends the general jinja template. It contains a list of all articles found.
<pre>
<code>
&#x7b;% extends "template.html" %&#x7d;
&#x7b;% block head %&#x7d;
&#x7b;&#x7b; super() &#x7d;&#x7d;
&#x7b;% endblock %&#x7d;
&#x7b;% block content %&#x7d;
&lt;p&gt;Welcome to my website&lt;/p&gt;
&lt;span class="index"&gt;
&#x7b;% for name,_date in _paths.items() %&#x7d;
&lt;p&gt;&lt;a href="&#x7b;&#x7b; url_for('blog', blog_item=name) &#x7d;&#x7d;"&gt;&#x7b;&#x7b; _date.date() &#x7d;&#x7d;&emsp;&emsp;&#x7b;&#x7b; name &#x7d;&#x7d;&lt;/a&gt;&lt;/p&gt;
&#x7b;% endfor %&#x7d;
&lt;/span&gt;
&#x7b;% endblock %&#x7d;
</code>
</pre>
URLs originate from the meta_data dictionary keys. These are the blog entries&rsquo; directory names. Flask&rsquo;s <a href="https://flask.palletsprojects.com/en/2.0.x/api/#flask.url_for" ><code>url_for()</code></a> returns the articles if you want to visit the site. It handles URL encoding as well. This is pretty neat since there are spaces in the names.
<pre>
<code>
@app.route('/blog/&lt;blog_item&gt;/index.html')
def blog(blog_item, _date=meta_data):
return render_template(f"blog/{blog_item}/index.html", _date=meta_data[blog_item])
</code>
</pre>
<h2>Digestif</h2>
<hr/>
Incidentally, this turned out to be not only an opener for my blog but code documentation for myself as well. Maybe, I&rsquo;ll need to pick it up in six months, who knows&#8230;.
As a closure, at least from my experience, the most feature-rich application seldom reaches its set goals. The one with a clear and precise target, fulfilling its minimal scope, most likely will.
<p>
<a href="https://www.bonappetit.com/recipe/best-pesto">This is how you make pesto, by the way.</a> Bon Appetit!
</p>
<p id="references" class="references">
<h2>References</h2>
<a href="https://www.bookfinder.com/?isbn=9783899555844">[1] Less and More: The Design Ethos of Dieter Rams, 2015, ISBN:9783899555844</a><br>
<a href="https://www.bookfinder.com/?isbn=9780465051366">[2] Emotional Design: Why We Love (or Hate) Everyday Things, 2005, ISBN:9780465051366</a>
<a href="https://www.bookfinder.com/?isbn=9780465067107">[3] The Design of Everyday Things, 2002, ISBN, 9780465067107</a>
</p>
{% endblock %}

View File

@ -1,85 +0,0 @@
<!doctype html>
{% extends "template.html" %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
{{ _date.date() }}
<p><h1>The Joy of One-Liners</h1>
There is an engineering idiom which withstands time like no other. As old as the hills but never forgotten. In informational technology relations, one could say it is ancient. Its dawn proclaimed from the shores of Seattle, defeated by an apocalyptic horseman with the melodious name <i>NT</i>. Shot! Point blank into the chest. Buried under the hills of an IT dark age which we call the nineties, dead. But is it? Well, not exactly. There is still life in the old dog. Like Beatrix Kiddo, it one-inch punches itself back to daylight. Coal black as a miner. Topsoil sticks to its beige 1978&rsquo;s leather jacket, it trickles to the ground with every step taken to the nearest diner. The door opens again. &ldquo;May I have a glass of water, please?&rdquo;
</p>
<p>
An art passed down from the ancestors. Its most visible interface: <i>The Shell</i>. Its name: <i>The Unix Philosophy</i>.
<p>
Coined by Doug McIlroy in the <a href="https://archive.org/details/bstj57-6-1899/mode/2up">Bell System Technical Journal</a> as a foreword to the UNIX Time-Sharing System. There is an even more concise version<a href=#references" style="text-decoration:none">[1]</a> and according to <a href="http://www.catb.org/~esr/writings/taoup/html/ch01s06.html">Eric Steven Raymond</a> this is <a href="#references" style="text-decoration:none">[2]</a>:
<blockquote>&ldquo;This is the Unix philosophy: Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.&rdquo;<br>&mdash; Doug McIlroy &mdash;</br></blockquote>
</p>
<p>
In some way, this is similar to the concept of the on vogue philosophy of microservices everywhere. Services are written to do one thing and do it well. They work together. Also, text is the connecting link between programs, services, and humans. The possibility to read a program&rsquo;s output as text seems benign, as long as everything is working well. The advantage is interactivity at any time, testability of every component, and debuggability at every step of the process in an on the fly manner. Impromptu, out of reflex like a punch.
</p>
<h2>Pipe Dreams</h2>
<hr/>
Mc Ilroy made another very important contribution, which is the Unix pipe. It is the practical implementation of connecting the programs inside the shell. He saw the programs as tools, plugged together via pipes building a <a href="http://www.princeton.edu/~hos/Mahoney/expotape.htm">toolbox</a>. Program A&rsquo;s <code>stdout</code> is put into the <code>stdin</code> of program B. This leaves us with a single line of chained, well-defined programs to solve a problem that would otherwise be an extensive, multi-line program in any programming language of your choice.
</p>
Let&rsquo;s say we&rsquo;ve got two programs. The first is one is <i>fortune</i>, the fortune cookie program from BSD games, which outputs random quotes as text. The second one is <i>cowsay</i>, which displays various kinds of animals as ASCII art. In order to work in a coherent manner a <code>|</code> is used. The pipe connects the first one to the second one.
<p>
<pre>
<code>
fortune | cowsay
_________________________________________
/ Gil-galad was an Elven-king. Of him the \
| harpers sadly sing: the last whose |
| realm was fair and free between the |
| Mountains and the Sea. |
| |
| His sword was long, his lance was keen, |
| his shining helm afar was seen; the |
| countless stars of heaven's field were |
| mirrored in his silver shield. |
| |
| But long ago he rode away, and where he |
| dwelleth none can say; for into |
| darkness fell his star in Mordor where |
| the shadows are. |
| |
\ -- J. R. R. Tolkien /
-----------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
</code>
</pre>
<p>
To mix in some colors pipe everything through lolcat. Try it out!
</p>
<pre>
<code>
fortune | cowsay | lolcat
</code>
</pre>
<p>
So far so good, let us gain some real-world practice.
</p>
<h2>Punching Lines &mdash; Retire Your Password Generator</h2>
<hr/>
Have you ever questioned the integrity of your one-click, GUI, proprietary password generator? Is its randomness really as unpredictable as it proclaims? Are you the only one which ends up knowing your generated password? There is a one-liner that ups your opsec instantly. Right from the source of randomness:
<pre>
<code>
head -n 42 /dev/urandom | tr -cd '[:alnum:]' | cut -c-12
</code>
</pre>
So, what is going on here? Everything is a file, that is the way *nix systems see it, even the device which puts out random data. To read the upper part of a file we use <code>head</code>. It will be sent to <code>stdout</code> and displayed via the shell. Parameter <code>-n</code> reads exactly 42 lines of the file given to gather enough randomness. The output of <code>head</code> will be sent to <code>tr</code>. In order to select only alphanumeric characters for our password, we use <code>'[:alnum:]'</code>. Parameters <code>-c</code> selects the complement of alphanumeric characters and <code>-d</code> deletes them. <code>cut</code> does exactly what it says, <code>-c-12</code> cuts after 12 characters with leaves us with a random password of length 12. Every time you execute this one-liner a freshly made random password is returned.
<p>
To extend the pool of possible symbols the manual of <code>tr</code> lists various sets of filtered symbols. In the case of a password generator, further sensible filters are <code>'[:alpha:]'</code> or <code>'[:digit:]'</code>. While <code>'[:graph:]'</code> is also viable in this case it returns one of the greater sets of symbols. Use it with caution, especially if you create passwords for database users. These might be terminated prematurely through <code>`</code> or <code>'</code> inside the returned string.
</p>
<h2>Sunday Punch</h2>
<hr/>
This blog entrance can be seen as a prelude to a series of one-liners I use time and time again. The are multiple in the pipeline. One-liners should save you the time you otherwise would spend coding a complex solution. There is little better than solving a challenging problem in a single line.
<p id="references" class="references">
<h2>References</h2>
<a href="https://www.bookfinder.com/?isbn=9780201547771">[1] A Quarter Century of Unix, 1994, Peter Salus, ISBN:9780201547771</a><br>
<a href="https://www.bookfinder.com/?isbn=9780131429017">[2] The Art of UNIX Programming, 2003, Eric Raymond, ISBN:9780131429017</a><br>
</p>
{% endblock %}

View File

@ -13,6 +13,7 @@
<style> <style>
/* Stylesheet 1 */ /* Stylesheet 1 */
body { background: {{ colors.body_background }}; color: {{ colors.body }}; } body { background: {{ colors.body_background }}; color: {{ colors.body }}; }
hr{ color: {{ colors.hr }}; border-color: {{ colors.hr_border }}; }
pre { background: {{ colors.pre_background }}; color: {{ colors.pre }}; border: 1px solid {{ colors.pre_border }}; } pre { background: {{ colors.pre_background }}; color: {{ colors.pre }}; border: 1px solid {{ colors.pre_border }}; }
code { background: {{ colors.code_background }}; color: {{ colors.code }}; } code { background: {{ colors.code_background }}; color: {{ colors.code }}; }
a:hover { color: {{ colors.a }}; } a:hover { color: {{ colors.a }}; }