diff --git a/config/_default/config.toml b/config/_default/config.toml
index 071b65c..60800f8 100644
--- a/config/_default/config.toml
+++ b/config/_default/config.toml
@@ -16,7 +16,7 @@ baseurl = "https://rocketnine.space/"
copyright = ""
# Enable analytics by entering your Google Analytics tracking ID
-googleAnalytics = "UA-71983-61"
+googleAnalytics = ""
############################
## Advanced options below ##
diff --git a/config/_default/menus.toml b/config/_default/menus.toml
index 28917c4..298a094 100644
--- a/config/_default/menus.toml
+++ b/config/_default/menus.toml
@@ -8,10 +8,10 @@
url = "#about"
weight = 10
-#[[main]]
-# name = "Posts"
-# url = "#posts"
-# weight = 20
+[[main]]
+ name = "Posts"
+ url = "#posts"
+ weight = 20
[[main]]
name = "Projects"
@@ -34,3 +34,6 @@
# name = "CV"
# url = "files/cv.pdf"
# weight = 70
+
+[[post]]
+
diff --git a/config/_default/params.toml b/config/_default/params.toml
index 3573741..ce45446 100644
--- a/config/_default/params.toml
+++ b/config/_default/params.toml
@@ -36,7 +36,7 @@ logo = ""
# Enable source code highlighting? true/false
# Documentation: https://sourcethemes.com/academic/docs/writing-markdown-latex/#highlighting-options
highlight = true
-highlight_languages = ["r"] # Add support for highlighting additional languages
+highlight_languages = ["r", "go", "golang"] # Add support for highlighting additional languages
# highlight_style = "github" # For supported styles, see https://cdnjs.com/libraries/highlight.js/
# Enable LaTeX math rendering? true/false
diff --git a/content/authors/admin/_index.md b/content/authors/admin/_index.md
index b53ada4..2226c49 100644
--- a/content/authors/admin/_index.md
+++ b/content/authors/admin/_index.md
@@ -18,7 +18,7 @@ role: Developer &
System Administrator
# url: ""
# Short bio (displayed in user profile at end of posts)
-bio: Install Gentoo
+bio:
#interests:
#- Open source software
@@ -72,7 +72,6 @@ email: "trevor@rocketnine.space"
I use [Linux](https://en.wikipedia.org/wiki/Linux) to write [open-source software](https://en.wikipedia.org/wiki/Open-source_software).
-My projects are available on [sourcehut](https://sr.ht) and [GitLab](https://gitlab.com/users/tslocum/projects).
-
-Be sure to check out [stick](https://git.sr.ht/~tslocum/stick) and [gophast](https://git.sr.ht/~tslocum/gophast).
+My projects are available on [sourcehut](https://git.sr.ht/~tslocum) and [GitLab](https://gitlab.com/users/tslocum/projects).
+Be sure to check out [stick](https://git.sr.ht/~tslocum/stick) and [netris](https://git.sr.ht/~tslocum/netris).
diff --git a/content/home/posts.md b/content/home/posts.md
index 4afc303..12b3b6f 100644
--- a/content/home/posts.md
+++ b/content/home/posts.md
@@ -4,7 +4,7 @@
widget = "pages" # See https://sourcethemes.com/academic/docs/page-builder/
headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
+active = true # Activate this widget? true/false
weight = 60 # Order that this section will appear.
title = "Recent Posts"
diff --git a/content/post/gotcha-slice-append-backing-array-overwrite.md b/content/post/gotcha-slice-append-backing-array-overwrite.md
index cefd81e..cc4ddaa 100644
--- a/content/post/gotcha-slice-append-backing-array-overwrite.md
+++ b/content/post/gotcha-slice-append-backing-array-overwrite.md
@@ -1,7 +1,31 @@
---
-title: "Gotcha - Overiting a shared backing array when calling append"
+title: "Gotcha - Up-ending a backing array"
date: 2019-09-26T21:42:18-07:00
categories: [gotcha]
+draft: true
---
-Test
+To give better context to the problem being presented in this article, we must go over how slices work.
+
+A slice value consists of three parts: a pointer to a backing array, a length and a capacity.
+
+Excerpt of **runtime/slice.go** from the standard library:
+
+```go
+
+type slice struct {
+ array unsafe.Pointer
+ len int
+ cap int
+}
+```
+
+When calling append on a slice whose length is the same as its capacity, a new backing array of greater size is created. The previous backing array's contents are copied.
+
+A range of elements from a slice may be selected like so:
+
+```go
+bar := foo[4:7]
+```
+
+When calling append on such a slice,
diff --git a/content/post/tview-and-you.md b/content/post/tview-and-you.md
new file mode 100644
index 0000000..1461bb0
--- /dev/null
+++ b/content/post/tview-and-you.md
@@ -0,0 +1,321 @@
+---
+title: "tview and you - Creating Rich Terminal User Interfaces"
+date: 2019-11-08T01:42:18-07:00
+categories: [tutorial]
+---
+
+
+
+This is an introduction to using [tview](https://github.com/rivo/tview) to create rich terminal-based user interfaces with Go.
+
+## Contents
+
+* [Primitives](#primitives)
+* [Widgets](#widgets)
+ * [Elements](#widget-elements)
+ * [Containers](#widget-containers)
+* [Thread Safety](#thread-safety)
+* [Example Application](#example-application)
+
+# Primitives
+
+The [Primitive](https://godoc.org/github.com/rivo/tview#Primitive) interface is as follows:
+
+```go
+type Primitive interface {
+ Draw(screen tcell.Screen)
+ GetRect() (int, int, int, int)
+ SetRect(x, y, width, height int)
+ InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive))
+ Focus(delegate func(p Primitive))
+ Blur()
+ GetFocusable() Focusable
+}
+```
+
+[Box](https://godoc.org/github.com/rivo/tview#Box) is the only primitive implemented.
+It has a size, padding amount, optional border, optional title and background color.
+
+# Widgets
+
+Widgets are structs which embed a [Box](https://godoc.org/github.com/rivo/tview#Box) and build upon it.
+
+From the [TextView](https://godoc.org/github.com/rivo/tview#TextView) declaration:
+
+```go
+type TextView struct {
+ *Box
+
+ // The text buffer.
+ buffer []string
+
+ // The text alignment, one of AlignLeft, AlignCenter, or AlignRight.
+ align int
+
+ // ...
+}
+```
+
+Some widgets allow nesting other widgets within them, such as [Grid](https://godoc.org/github.com/rivo/tview#Grid).
+
+Most widget commands may be chained together:
+
+```go
+nameLabel := tview.NewTextView().
+ SetTextAlign(tview.AlignRight).
+ SetDynamicColors(true).
+ SetWrap(true).
+ SetWordWrap(true).
+ SetText("Please enter your name:")
+```
+
+New widgets may be defined, as documented in the [Primitive demo](https://github.com/rivo/tview/tree/master/demos/primitive).
+
+## Widget Elements
+
+---
+
+[**Button**](https://godoc.org/github.com/rivo/tview#Button) is a labeled box that triggers an action when selected.
+
+```go
+button := tview.NewButton("OK").SetSelectedFunc(func() {
+ pressedOK()
+})
+```
+
+---
+
+[**Checkbox**](https://godoc.org/github.com/rivo/tview#Checkbox) holds a label and boolean value which may be checked and unchecked.
+
+```go
+checkbox := tview.NewCheckbox().SetLabel("Toggle value with Enter: ")
+```
+
+---
+
+[**DropDown**](https://godoc.org/github.com/rivo/tview#DropDown) holds one or more options which may be selected as a dropdown list.
+
+```go
+dropdown := tview.NewDropDown().
+ SetLabel("Select an option with Enter: ").
+ SetOptions([]string{"Foo", "Bar", "Baz"}, nil)
+```
+
+---
+
+[**InputField**](https://godoc.org/github.com/rivo/tview#InputField) is a box where text may be entered.
+
+```go
+inputField := tview.NewInputField().
+ SetLabel("Name: ").
+ SetPlaceholder("John Smith").
+ SetFieldWidth(14).
+ SetDoneFunc(func(key tcell.Key) {
+ processName()
+ })
+```
+
+---
+
+[**Modal**](https://godoc.org/github.com/rivo/tview#Modal) is a centered message window which may have one or more buttons.
+
+```go
+modal := tview.NewModal().
+ SetText("Are you sure you want to exit?").
+ AddButtons([]string{"Cancel", "Quit"}).
+ SetDoneFunc(func(buttonIndex int, buttonLabel string) {
+ if buttonIndex == 1 {
+ app.Stop()
+ }
+ })
+```
+
+---
+
+[**TextView**](https://godoc.org/github.com/rivo/tview#TextView) is a box containing text.
+[Colored text](https://godoc.org/github.com/rivo/tview#hdr-Colors) is supported when enabled.
+
+```go
+textView := tview.NewTextView().
+ SetWrap(true).
+ SetWordWrap(true).
+ SetText("Hello, World!")
+```
+
+---
+
+## Widget Containers
+
+---
+
+[**Flex**](https://godoc.org/github.com/rivo/tview#Flex) is a [flexbox layout](https://en.wikipedia.org/wiki/CSS_Flexible_Box_Layout) container.
+
+See the [Flex demo](https://github.com/rivo/tview/tree/master/demos/flex) for example usage.
+
+---
+
+[**Grid**](https://godoc.org/github.com/rivo/tview#Grid) is a [grid layout](https://en.wikipedia.org/wiki/CSS_grid_layout) container.
+
+See the [Grid demo](https://github.com/rivo/tview/tree/master/demos/grid) for example usage.
+
+---
+
+[**Form**](https://godoc.org/github.com/rivo/tview#Form) displays one or more form elements in a vertical or horizontal layout.
+
+See the [Form demo](https://github.com/rivo/tview/tree/master/demos/form) for example usage.
+
+---
+
+[**List**](https://godoc.org/github.com/rivo/tview#List) displays one or more widgets as a selectable list.
+
+See the [List demo](https://github.com/rivo/tview/tree/master/demos/list) for example usage.
+
+---
+
+[**Pages**](https://godoc.org/github.com/rivo/tview#Pages) displays one or more widgets at a time.
+
+See the [Pages demo](https://github.com/rivo/tview/tree/master/demos/pages) for example usage.
+
+---
+
+[**Table**](https://godoc.org/github.com/rivo/tview#Table) displays one or more widgets in rows and columns.
+
+See the [Table demo](https://github.com/rivo/tview/tree/master/demos/table) for example usage.
+
+---
+
+[**TreeView**](https://godoc.org/github.com/rivo/tview#TreeView) displays one or more widgets in a tree.
+
+See the [TreeView demo](https://github.com/rivo/tview/tree/master/demos/treeview) for example usage.
+
+---
+
+# Thread Safety
+
+**Most tview functions cannot safely be called from any thread except the main one**.
+
+Using either of the following functions, we can queue a function to be executed in the main thread.
+
+* [Application.QueueUpdate](https://godoc.org/github.com/rivo/tview#Application.QueueUpdate)
+* [Application.QueueUpdateDraw](https://godoc.org/github.com/rivo/tview#Application.QueueUpdateDraw)
+
+The only difference between the two is that QueueUpdateDraw calls [Application.Draw](https://godoc.org/github.com/rivo/tview#Application.Draw) after the queued function returns.
+
+One exception is [TextView.Write](https://godoc.org/github.com/rivo/tview#TextView.Write), which may safely be called from multiple goroutines.
+
+Below is an example of setting a new root primitive from another goroutine.
+
+```go
+app.QueueUpdateDraw(func() {
+ app.SetRoot(appGrid, true)
+})
+```
+
+# Example Application
+
+A tview application is constructed of a running [Application](https://godoc.org/github.com/rivo/tview#Application) with at least one root widget.
+
+To display a primitive (and its contents), we call [Application.SetRoot](https://godoc.org/github.com/rivo/tview#Application.SetRoot).
+
+This function has two arguments, a primitive which will become the root of the screen, and a boolean which controls whether the primitive will be resized to fit the screen.
+
+In this example, the root is a Grid containing a label, an input and a submit button. For a more complex example, see [netris](https://git.sr.ht/~tslocum/netris).
+
+Install tview if you haven't already:
+
+```command
+go get -u github.com/rivo/tview
+```
+
+Then create a file named greet.go:
+
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "strings"
+
+ "github.com/gdamore/tcell"
+ "github.com/rivo/tview"
+)
+
+func main() {
+ // Initialize application
+ app := tview.NewApplication()
+
+ // Create label
+ label := tview.NewTextView().SetText("Please enter your name:")
+
+ // Create input field
+ input := tview.NewInputField()
+
+ // Create submit button
+ btn := tview.NewButton("Submit")
+
+ // Create empty Box to pad each side of appGrid
+ bx := tview.NewBox()
+
+ // Create Grid containing the application's widgets
+ appGrid := tview.NewGrid().
+ SetColumns(-1, 24, 16, -1).
+ SetRows(-1, 2, 3, -1).
+ AddItem(bx, 0, 0, 3, 1, 0, 0, false). // Left - 3 rows
+ AddItem(bx, 0, 1, 1, 1, 0, 0, false). // Top - 1 row
+ AddItem(bx, 0, 3, 3, 1, 0, 0, false). // Right - 3 rows
+ AddItem(bx, 3, 1, 1, 1, 0, 0, false). // Bottom - 1 row
+ AddItem(label, 1, 1, 1, 1, 0, 0, false).
+ AddItem(input, 1, 2, 1, 1, 0, 0, false).
+ AddItem(btn, 2, 1, 1, 2, 0, 0, false)
+
+ // submittedName is toggled each time Enter is pressed
+ var submittedName bool
+
+ // Capture user input
+ app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
+ // Anything handled here will be executed on the main thread
+ switch event.Key() {
+ case tcell.KeyEnter:
+ submittedName = !submittedName
+
+ if submittedName {
+ name := input.GetText()
+ if strings.TrimSpace(name) == "" {
+ name = "Anonymous"
+ }
+
+ // Create a modal dialog
+ m := tview.NewModal().
+ SetText(fmt.Sprintf("Greetings, %s!", name)).
+ AddButtons([]string{"Hello"})
+
+ // Display and focus the dialog
+ app.SetRoot(m, true).SetFocus(m)
+ } else {
+ // Clear the input field
+ input.SetText("")
+
+ // Display appGrid and focus the input field
+ app.SetRoot(appGrid, true).SetFocus(input)
+ }
+ return nil
+ case tcell.KeyEsc:
+ // Exit the application
+ app.Stop()
+ return nil
+ }
+
+ return event
+ })
+
+ // Set the grid as the application root and focus the input field
+ app.SetRoot(appGrid, true).SetFocus(input)
+
+ // Run the application
+ err := app.Run()
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+```
diff --git a/content/project/netris.md b/content/project/netris.md
new file mode 100644
index 0000000..d194f0a
--- /dev/null
+++ b/content/project/netris.md
@@ -0,0 +1,8 @@
+---
+title: netris
+summary: Multiplayer Tetris clone
+tags:
+- Go
+
+external_link: "https://git.sr.ht/~tslocum/netris"
+---