Browse Source

some stuff in general_purpose/

pull/1/head
Brennen Bearnes 7 years ago
parent
commit
5378897d7e
5 changed files with 123 additions and 51 deletions
  1. +77
    -9
      general_purpose/index.md
  2. +34
    -24
      index.html
  3. +4
    -8
      script/addprop
  4. +3
    -1
      script/index.md
  5. +5
    -9
      script/markpoem

+ 77
- 9
general_purpose/index.md View File

@ -8,13 +8,13 @@ Let me begin this chapter with a confession: I kind of hate shell scripts, and
I think it's ok if you hate them too.
That doesn't mean you shouldn't _know_ about them, or that you shouldn't
_write_ them. I write little tiny ones all the time, and the ability to puzzle
_write_ them. I write little ones all the time, and the ability to puzzle
through other people's scripts comes in handy. Oftentimes, the best, most
tasteful way to automate something is to build a script out of the commonly
available commands. The standard tools are already there on millions of
machines. Many of them have been pretty well understood for a generation, and
most will probably be around for a generation or three to come. They do neat
stuff. Scripts let you build on things you've already figured out, and give
stuff. Scripts let you build on ideas you've already worked out, and give
repeatable operations a memorable, user-friendly name. They encourage reuse of
existing programs, and help express your ideas to people who'll come after you.
@ -23,17 +23,85 @@ extends to its users some of the same power that its authors used in creating
it. Scriptable software is to some extent _living_ software. It's a book that
you, the reader, get to help write.
In all these ways, shell scripts are wonderful, and a little bit magical, and
actually, quietly indispensable to the machinery of modern civilization.
In all these ways, shell scripts are wonderful, a little bit magical, and
quietly indispensable to the machinery of modern civilization.
Unfortunately, in all the ways that a shell like Bash is weird, finicky, and
covered in 40 years of incidental cruft, long-form Bash scripts are even worse.
Bash is a useful glue language, particularly if you're already comfortable
wiring commands together. Syntactic and conceptual innovations like pipes are
beautiful and necessary. What Bash is _not_, despite its power, is a very good
general purpose programming language. It turns out those are really nice to
have at your disposal.
general purpose programming language. It's just not especially good for things
like math, or complex data structures, or not looking like a punctuation-heavy
variety of alphabet soup.
Maybe you already know a general-purpose programming language. A lot of the
people I imagine reading this are already comfortable in C, PHP, Python, Ruby,
or JavaScript.
It turns out that there's a threshold of complexity beyond which life is easier
if you switch from shell scripting to a more robust language. Just where this
threshold is located varies a lot between users and problems, but I often start
thinking about switching languages before a script gets bigger than I can view
on my screen all at once. Last chapter's `addprop` is a good example:
<!-- exec -->
$ wc -l ../script/addprop
41 ../script/addprop
<!-- end -->
41 lines is a touch over what fits on one screen in the editor I usually use.
If I were going to add much in the way of features, I'd think pretty hard about
porting it to another language first.
warm fuzzies
------------
What's really beautiful about programming in the context of the shell is that,
as long as you follow certain conventions, it doesn't matter _too_ much what
language you favor. If your code works with text files and/or standard input,
there's a good chance it can fit nicely into the rest of the ecosystem.
Here's the help text for a utility I wrote a little while ago:
<!-- exec -->
$ words -h
Usage: words [-ucaih] [-s n] [-b n] [-d pattern] [file]
Split input into individual words, crudely understood.
-u: print each unique word only once
-c: print a count of words and exit
-uc: print a count for each unique word
-a: strip non-alphanumeric characters for current locale
-i: coerce all to lowercase, ignore case when considering duplicates
-h: print this help and exit
-s n, -b n: (s)hortest and (b)iggest words to pass through
-d pattern: word delimiter (a Perl regexp)
If no file is given, standard input will be read instead.
Examples:
# list all unique words, ignoring case, in foo:
words -ui ./foo
# find ten most used words longer than 6 letters in foo:
words -uci -s6 foo | sort -nr | head -10
<!-- end -->
I wrote `words` because I wanted a simple command to split input up by word.
In the simplest terms, it does this:
<!-- exec -->
$ echo "Fuck it, Dude. Let's go bowling." | words -ia
Fuck
it,
Dude.
Let's
go
bowling.
<!-- end -->

+ 34
- 24
index.html View File

@ -1626,8 +1626,7 @@ exit 0
POEM=$1
# Complain and exit if we weren't given a path:
if [ ! $POEM ]
then
if [ ! $POEM ]; then
echo 'usage: markpoem &lt;path&gt;'
# Confusingly, an exit status of 0 means to the shell that everything went
@ -1635,20 +1634,18 @@ then
exit 64
fi
if [ ! -e $POEM ]
then
if [ ! -e $POEM ]; then
echo "$POEM not found"
exit 66
fi
echo "marking $1 an ok poem"
echo "marking $POEM an ok poem"
POEM_BASENAME=$(basename $POEM)
# If the target is a plain file instead of a directory, make it into
# a directory and move the content into $POEM/index:
if [ -f $POEM ]
then
if [ -f $POEM ]; then
echo "making $POEM into a directory, moving content to"
echo " $POEM/index"
TEMPFILE="/tmp/$POEM_BASENAME.$(date +%s.%N)"
@ -1657,8 +1654,7 @@ then
mv $TEMPFILE $POEM/index
fi
if [ -d $POEM ]
then
if [ -d $POEM ]; then
# touch(1) will either create the file or update its timestamp:
touch $POEM/meta-ok-poem
else
@ -1726,14 +1722,12 @@ ENTRY=$1
PROPERTY=$2
# Complain and exit if we weren't given a path and a property:
if [[ ! $ENTRY || ! $PROPERTY ]]
then
if [[ ! $ENTRY || ! $PROPERTY ]]; then
echo "usage: addprop &lt;path&gt; &lt;property&gt;"
exit 64
fi
if [ ! -e $ENTRY ]
then
if [ ! -e $ENTRY ]; then
echo "$ENTRY not found"
exit 66
fi
@ -1742,8 +1736,7 @@ echo "marking $ENTRY with $PROPERTY"
# If the target is a plain file instead of a directory, make it into
# a directory and move the content into $ENTRY/index:
if [ -f $ENTRY ]
then
if [ -f $ENTRY ]; then
echo "making $ENTRY into a directory, moving content to"
echo " $ENTRY/index"
@ -1755,8 +1748,7 @@ then
mv $TEMPFILE $ENTRY/index
fi
if [ -d $ENTRY ]
then
if [ -d $ENTRY ]; then
touch $ENTRY/$PROPERTY
else
echo "something broke - why isn't $ENTRY a directory?"
@ -1795,6 +1787,10 @@ exit 0
<!-- end -->
<p>These scripts aren&rsquo;t much more complicated than their more specific
counterparts, but now they can be used to solve problems I haven&rsquo;t even thought
of yet, and included in other scripts that need their functionality.</p>
<hr />
<h1><a name=general-purpose-programmering href=#general-purpose-programmering>#</a> 5. general purpose programmering</h1>
@ -1820,20 +1816,34 @@ extends to its users some of the same power that its authors used in creating
it. Scriptable software is to some extent <em>living</em> software. It&rsquo;s a book that
you, the reader, get to help write.</p>
<p>In all these ways, shell scripts are wonderful, and a little bit magical, and
actually, quietly indispensable to the machinery of modern civilization.</p>
<p>In all these ways, shell scripts are wonderful, a little bit magical, and
quietly indispensable to the machinery of modern civilization.</p>
<p>Unfortunately, in all the ways that a shell like Bash is weird, finicky, and
covered in 40 years of incidental cruft, long-form Bash scripts are even worse.
Bash is a useful glue language, particularly if you&rsquo;re already comfortable
wiring commands together. Syntactic and conceptual innovations like pipes are
beautiful and necessary. What Bash is <em>not</em>, despite its power, is a very good
general purpose programming language. It turns out those are really nice to
have at your disposal.</p>
general purpose programming language.</p>
<p>It turns out that there&rsquo;s a threshold of complexity beyond which life is easier
if you switch from shell scripting to a more robust language. Just where this
threshold is located varies a lot between users and problems, but I often start
thinking about switching languages before a shell script gets bigger than I can
view on my screen all at once. How long is last chapter&rsquo;s <code>addprop</code>?</p>
<!-- exec -->
<pre><code>$ wc -l ../script/addprop
41 ../script/addprop
</code></pre>
<!-- end -->
<p>Maybe you already know a general-purpose programming language. A lot of the
people I imagine reading this are already comfortable in C, PHP, Python, Ruby,
or JavaScript.</p>
<p>If I were going to add much in the way of features, I&rsquo;d think pretty hard about
porting it to another language.</p>
<hr />


+ 4
- 8
script/addprop View File

@ -4,14 +4,12 @@ ENTRY=$1
PROPERTY=$2
# Complain and exit if we weren't given a path and a property:
if [[ ! $ENTRY || ! $PROPERTY ]]
then
if [[ ! $ENTRY || ! $PROPERTY ]]; then
echo "usage: addprop <path> <property>"
exit 64
fi
if [ ! -e $ENTRY ]
then
if [ ! -e $ENTRY ]; then
echo "$ENTRY not found"
exit 66
fi
@ -20,8 +18,7 @@ echo "marking $ENTRY with $PROPERTY"
# If the target is a plain file instead of a directory, make it into
# a directory and move the content into $ENTRY/index:
if [ -f $ENTRY ]
then
if [ -f $ENTRY ]; then
echo "making $ENTRY into a directory, moving content to"
echo " $ENTRY/index"
@ -33,8 +30,7 @@ then
mv $TEMPFILE $ENTRY/index
fi
if [ -d $ENTRY ]
then
if [ -d $ENTRY ]; then
touch $ENTRY/$PROPERTY
else
echo "something broke - why isn't $ENTRY a directory?"


+ 3
- 1
script/index.md View File

@ -268,4 +268,6 @@ property to find:
<!-- end -->
These scripts aren't much more complicated than their poem-specific
counterparts, but now they can be used to solve problems I haven't even thought
of yet, and included in other scripts that need their functionality.

+ 5
- 9
script/markpoem View File

@ -4,8 +4,7 @@
POEM=$1
# Complain and exit if we weren't given a path:
if [ ! $POEM ]
then
if [ ! $POEM ]; then
echo 'usage: markpoem <path>'
# Confusingly, an exit status of 0 means to the shell that everything went
@ -13,20 +12,18 @@ then
exit 64
fi
if [ ! -e $POEM ]
then
if [ ! -e $POEM ]; then
echo "$POEM not found"
exit 66
fi
echo "marking $1 an ok poem"
echo "marking $POEM an ok poem"
POEM_BASENAME=$(basename $POEM)
# If the target is a plain file instead of a directory, make it into
# a directory and move the content into $POEM/index:
if [ -f $POEM ]
then
if [ -f $POEM ]; then
echo "making $POEM into a directory, moving content to"
echo " $POEM/index"
TEMPFILE="/tmp/$POEM_BASENAME.$(date +%s.%N)"
@ -35,8 +32,7 @@ then
mv $TEMPFILE $POEM/index
fi
if [ -d $POEM ]
then
if [ -d $POEM ]; then
# touch(1) will either create the file or update its timestamp:
touch $POEM/meta-ok-poem
else


Loading…
Cancel
Save