diff --git a/gawa/blog/data/articles/en-bash-arrays.md b/gawa/blog/data/articles/en-bash-arrays.md new file mode 100644 index 0000000..c2556f0 --- /dev/null +++ b/gawa/blog/data/articles/en-bash-arrays.md @@ -0,0 +1,102 @@ +--- +Title: Bash Arrays +Subtitle: sub +Desc: Brief intro to Bash Arrays +Date: 2023-09-29 +Keywords: bash + technology +Category: Test +Featured: True +Public: True +--- + +**NOTE** + +This is a stolen article from [opensource.com](https://opensource.com/article/18/5/you-dont-know-bash-intro-bash-arrays) +about bash scripting. It's a good article and I've decided to use it to test my +markdown rendering. + +# Bash scripting + +[TOC] + + +## Wait, but why? + +Writing about Bash is challenging because it's remarkably easy for an article +to devolve into a manual that focuses on syntax oddities. Rest assured, +however, the intent of this article is to avoid having you RTFM. + +## A real (actually useful) example + +To that end, let's consider a real-world scenario and how Bash can help: +You are leading a new effort at your company to evaluate and optimize the +runtime of your internal data pipeline. As a first step, you want to do a +parameter sweep to evaluate how well the pipeline makes use of threads. For +the sake of simplicity, we'll treat the pipeline as a compiled C++ black box +where the only parameter we can tweak is the number of threads reserved for +data processing: `./pipeline --threads 4.` + +## The basics + +The first thing we'll do is define an array containing the values of the +`--threads` parameter that we want to test: + +```bash +allThreads=(1 2 4 8 16 32 64 128) +``` + +In this example, all the elements are numbers, but it need not be the +case—arrays in Bash can contain both numbers and strings, e.g., `myArray=(1 +2 "three" 4 "five")` is a valid expression. And just as with any other Bash +variable, make sure to leave no spaces around the equal sign. Otherwise, +Bash will treat the variable name as a program to execute, and the `=` as its +first parameter! + +Now that we've initialized the array, let's retrieve a few of its +elements. You'll notice that simply doing `echo $allThreads` will output only +the first element. + +To understand why that is, let's take a step back and revisit how we usually +output variables in Bash. Consider the following scenario: + +```bash +type="article" echo "Found 42 $type" +``` + +Say the variable $type is given to us as a singular noun and we want to add +an `s` at the end of our sentence. We can't simply add an s to `$type` since +that would turn it into a different variable, `$types`. And although we could +utilize code contortions such as `echo "Found 42 "$type"s"`, the best way +to solve this problem is to use curly braces: `echo "Found 42 ${type}s"`, +which allows us to tell Bash where the name of a variable starts and ends +(interestingly, this is the same syntax used in JavaScript/ES6 to inject +variables and expressions in template literals). + +So as it turns out, although Bash variables don't generally require curly +brackets, they are required for arrays. In turn, this allows us to specify +the index to access, e.g., `echo ${allThreads[1]}` returns the second element +of the array. Not including brackets, e.g.,`echo $allThreads[1]`, leads Bash +to treat `[1]` as a string and output it as such. + +Yes, Bash arrays have odd syntax, but at least they are zero-indexed, unlike +some other languages (I'm looking at you, R).[^1] + +## Looping through arrays + +Although in the examples above we used integer indices in our arrays, let's +consider two occasions when that won't be the case: First, if we wanted the +$i-th element of the array, where $i is a variable containing the index of +interest, we can retrieve that element using: echo ${allThreads[$i]}. Second, +to output all the elements of an array, we replace the numeric index with +the @ symbol (you can think of @ as standing for all): + +```bash +type="article" +echo "Found 42 $type" +``` + +*[RTFM]: Read the Fucking Manual +*[HTML]: Hyper Text Markup Language + +[^1]: Example Footnote diff --git a/gawa/blog/data/articles/en-test.md b/gawa/blog/data/articles/en-test.md index daaacfc..c2556f0 100644 --- a/gawa/blog/data/articles/en-test.md +++ b/gawa/blog/data/articles/en-test.md @@ -1,86 +1,102 @@ --- -Title: test +Title: Bash Arrays Subtitle: sub -Desc: brief desc -Date: 2023-09-27 -Keywords: main - foo - bar - qux +Desc: Brief intro to Bash Arrays +Date: 2023-09-29 +Keywords: bash + technology Category: Test Featured: True Public: True --- -# Test article ----------------------------------------- -This is a crazy testy +**NOTE** + +This is a stolen article from [opensource.com](https://opensource.com/article/18/5/you-dont-know-bash-intro-bash-arrays) +about bash scripting. It's a good article and I've decided to use it to test my +markdown rendering. + +# Bash scripting -### toc? [TOC] -## foo -HTML +## Wait, but why? -lipsum[^1] +Writing about Bash is challenging because it's remarkably easy for an article +to devolve into a manual that focuses on syntax oddities. Rest assured, +however, the intent of this article is to avoid having you RTFM. -
INLINE DIVbold
+## A real (actually useful) example -### bar bar +To that end, let's consider a real-world scenario and how Bash can help: +You are leading a new effort at your company to evaluate and optimize the +runtime of your internal data pipeline. As a first step, you want to do a +parameter sweep to evaluate how well the pipeline makes use of threads. For +the sake of simplicity, we'll treat the pipeline as a compiled C++ black box +where the only parameter we can tweak is the number of threads reserved for +data processing: `./pipeline --threads 4.` -| important | table | -|-----------|-------| -| value | 2 | -| 3 | 4 | -| 5 | 2 | +## The basics -## foo +The first thing we'll do is define an array containing the values of the +`--threads` parameter that we want to test: -#### big code - -```py -from django.db import models -from django.utils.translation import gettext as _ -from start.models import Searchable - -import logging -logger = logging.getLogger(__name__) - -import markdown -ARTICLE_DIR = "/app/blog/data/articles" -EXTENSIONS = [ - "extra", - "admonition", - "codehilite", - "toc" -] - -class Category(models.Model): - """ - A category of blog posts - - Name not translated because it would make i18n in urls and Searchables specifically a pain. - Maybe some day it would be cool if these were Searchable - """ - name= models.CharField(max_length=50) - slug = models.SlugField() - - class Meta: - verbose_name = _("Category") - verbose_name_plural = _("Categories") - - def __str__(self): - return f"{{<{self.__class__.__name__}>\"{self.name}\"}}" +```bash +allThreads=(1 2 4 8 16 32 64 128) ``` -### a -bar -#### a -qux -###### a -baau +In this example, all the elements are numbers, but it need not be the +case—arrays in Bash can contain both numbers and strings, e.g., `myArray=(1 +2 "three" 4 "five")` is a valid expression. And just as with any other Bash +variable, make sure to leave no spaces around the equal sign. Otherwise, +Bash will treat the variable name as a program to execute, and the `=` as its +first parameter! +Now that we've initialized the array, let's retrieve a few of its +elements. You'll notice that simply doing `echo $allThreads` will output only +the first element. + +To understand why that is, let's take a step back and revisit how we usually +output variables in Bash. Consider the following scenario: + +```bash +type="article" echo "Found 42 $type" +``` + +Say the variable $type is given to us as a singular noun and we want to add +an `s` at the end of our sentence. We can't simply add an s to `$type` since +that would turn it into a different variable, `$types`. And although we could +utilize code contortions such as `echo "Found 42 "$type"s"`, the best way +to solve this problem is to use curly braces: `echo "Found 42 ${type}s"`, +which allows us to tell Bash where the name of a variable starts and ends +(interestingly, this is the same syntax used in JavaScript/ES6 to inject +variables and expressions in template literals). + +So as it turns out, although Bash variables don't generally require curly +brackets, they are required for arrays. In turn, this allows us to specify +the index to access, e.g., `echo ${allThreads[1]}` returns the second element +of the array. Not including brackets, e.g.,`echo $allThreads[1]`, leads Bash +to treat `[1]` as a string and output it as such. + +Yes, Bash arrays have odd syntax, but at least they are zero-indexed, unlike +some other languages (I'm looking at you, R).[^1] + +## Looping through arrays + +Although in the examples above we used integer indices in our arrays, let's +consider two occasions when that won't be the case: First, if we wanted the +$i-th element of the array, where $i is a variable containing the index of +interest, we can retrieve that element using: echo ${allThreads[$i]}. Second, +to output all the elements of an array, we replace the numeric index with +the @ symbol (you can think of @ as standing for all): + +```bash +type="article" +echo "Found 42 $type" +``` + +*[RTFM]: Read the Fucking Manual *[HTML]: Hyper Text Markup Language -[^1]: foooootnote +[^1]: Example Footnote diff --git a/gawa/blog/models.py b/gawa/blog/models.py index 660e918..130eb51 100644 --- a/gawa/blog/models.py +++ b/gawa/blog/models.py @@ -74,56 +74,58 @@ class BlogPost(Searchable): """ logger.info(f"regenerating article from markdown for: {self}") try: - f_en = open(f"{ARTICLE_DIR}/en-{self.slug}.md") + with open(f"{ARTICLE_DIR}/en-{self.slug}.md") as f_en: - body_en: str = f_en.read() + body_en: str = f_en.read() - html_en: str = MD.convert(body_en) - try: - meta_en = MD.Meta - self.title_en = meta_en["title"][0] - self.subtitle_en = meta_en["subtitle"][0] - self.desc_en = meta_en["desc"][0] - # TODO: parse date from markdown - self.featured = meta_en["featured"][0] == "True" - self.public = meta_en["public"][0] == "True" - # TODO: parse keywords from markdown - # TODO: parse category from markdown + html_en: str = MD.convert(body_en) + try: + meta_en = MD.Meta + self.title_en = meta_en["title"][0] + self.subtitle_en = meta_en["subtitle"][0] + self.desc_en = meta_en["desc"][0] + # TODO: parse date from markdown + self.featured = meta_en["featured"][0] == "True" + self.public = meta_en["public"][0] == "True" + # TODO: parse keywords from markdown + # TODO: parse category from markdown - # if keyword or category do not exist, create them - # I suppose - except Exception as e: - logger.warning(f"could not generate metadata {self.slug} from markdown: {e}") + # if keyword or category do not exist, create them + # I suppose + except Exception as e: + logger.warning(f"could not generate metadata {self.slug} from markdown: {e}") - self.body_en = html_en + self.body_en = "" + self.body_en = html_en except FileNotFoundError as e: # TODO: mark as untranslated pass except Exception as e: logger.warning(f"could not generate article {self.slug} from markdown: {e}") try: - f_de = open(f"{ARTICLE_DIR}/de-{self.slug}.md") + with open(f"{ARTICLE_DIR}/de-{self.slug}.md") as f_de: - body_de: str = f_de.read() + body_de: str = f_de.read() - html_de: str = MD.convert(body_de) - try: - meta_de = MD.Meta - self.title_de = meta_de["title"][0] - self.subtitle_de = meta_de["subtitle"][0] - self.desc_de = meta_de["desc"][0] - # TODO: parse date from markdown - self.featured = meta_de["featured"][0] == "True" - self.public = meta_de["public"][0] == "True" - # TODO: parse keywords from markdown - # TODO: parse category from markdown + html_de: str = MD.convert(body_de) + try: + meta_de = MD.Meta + self.title_de = meta_de["title"][0] + self.subtitle_de = meta_de["subtitle"][0] + self.desc_de = meta_de["desc"][0] + # TODO: parse date from markdown + self.featured = meta_de["featured"][0] == "True" + self.public = meta_de["public"][0] == "True" + # TODO: parse keywords from markdown + # TODO: parse category from markdown - # if keyword or category do not exist, create them - # I suppose - except Exception as e: - logger.warning(f"could not generate metadata {self.slug} from markdown: {e}") + # if keyword or category do not exist, create them + # I suppose + except Exception as e: + logger.warning(f"could not generate metadata {self.slug} from markdown: {e}") - self.body_de = html_de + self.body_de = "" + self.body_de = html_de except FileNotFoundError as e: # TODO: mark as untranslated pass