Created
November 11, 2020 13:17
-
-
Save progapandist/97f7ccc8169b792e2d0b4a6aab6faf9b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"github.com/gdamore/tcell" | |
"github.com/rivo/tview" | |
) | |
var ( | |
app *tview.Application // The tview application. | |
pages *tview.Pages | |
textView *tview.TextView | |
menu *tview.List | |
) | |
const about = `[::bu]Hi, I'm Andy[::-] π | |
Coming from the international news broadcasting background, I performed a drastic career change at the age of 30 to become a full-stack web developer, thanks to Le Wagon bootcamp in Paris and Vrije Universiteit Amsterdam (CS department). | |
Now based in Berlin and employed full-time by Le Wagon, I help shape the education process in the bootcamp and work as a back-end and DevOps engineer on our learning platforms. I use (and teach) Ruby on Rails, Docker, and Kubernetes every day. | |
I have never severed my ties to journalism, so I also hold the position of Lead Writer at Evil Martians, the extraterrestrial product development consultancy. | |
[::bu]Le Wagon Berlin[::-] https://www.lewagon.com/berlin | |
[::bu]Evil Martians[::-] https://www.evilmartians.com | |
[::bu]Martian Chronicles[::-] https://www.evilmartians.com/blog | |
[::bu]Twitter[::-] https://twitter.com/progapandist | |
[::bu]Github[::-] https://github.com/progapandist | |
This is my personal website with a "frontend" built entirely in Go. | |
` | |
const cv = `[::bu]My career in a gist[::-] π¨βπΌ | |
* I got my first proper [::b]job in tech[::-] in the year 2000, at the very early age of 15, as a technical editor at [::b]Yandex[::-]. | |
* In 2003, I switched to [::b]broadcast journalism[::-], and worked as an editor, reporter, foreign correspondent, and chief of European bureau for [::b]13 years[::-], covering events from car expos to local conflicts. While working, I graduated from the [::b]Moscow State University[::-], Department of Journalism (5-year degree). | |
* In 2015, I started [::b]teaching myself programming[::-], covering Python, C, Objective-C, and Swift. I went through Full-Stack Development Bootcamp at Le Wagon in Paris where I fell in love with [::b]Ruby on Rails[::-]. After my graduation, I moved to Amsterdam where I attended first two years of a Bachelor Degree in Computer Science at VU, spending time with C++ and Java. | |
* Since then, I've been working on various Rails applications for companies and private clients. | |
* I currently live and work in [::b]Berlin[::-], shaping the educational process at [::b]Le Wagon[::-] and writing Ruby, JavaScript, and Go code that allows our students to learn better. I am also managing [::b]Kubernetes[::-] deploys and set up local environments with [::b]Docker[::-]. | |
` | |
const how = `[::bu]How it's built[::-] π·ββοΈ | |
* A Svelte front-end app uses Xterm.js to emulate terminal | |
* A Golang server establishes a Websocket connection to front-end | |
* An Alpine container starts in the backend | |
* A Golang binary in the container renders TUI | |
* Stdin and stdout of a container are piped back and forth through Websocket | |
The app is open-source, feel free to use it for your own inspiration: https://github.com/progapandist/progapanda.org | |
` | |
const why = `[::bu]But... Why?[::-] π€ | |
I am obsessed with terminals and TUI programming, that's why! | |
To be serious though, this is a part of my research project for creating a highly scalable interactive learning environment for programming students. | |
This application is deployed on a single Digital Ocean VPS that is turned into a Kuberenetes cluster with k3s. | |
` | |
func main() { | |
app = tview.NewApplication() | |
textView = tview.NewTextView(). | |
SetDynamicColors(true) | |
textView.SetBorder(true) | |
textView.SetBorderPadding(1, 1, 2, 1) | |
textView.SetWrap(true).SetWordWrap(true) | |
textView.SetBackgroundColor(tcell.Color19) | |
textView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { | |
if event.Key() == tcell.KeyESC { | |
app.SetFocus(menu) | |
} | |
return event | |
}) | |
menu = tview.NewList().ShowSecondaryText(false) | |
menu.SetBorder(true).SetTitle("Menu") | |
menu.SetWrapAround(true).SetHighlightFullLine(true) | |
menu.SetBorderPadding(1, 1, 2, 1) | |
menu.SetSelectedBackgroundColor(tcell.ColorWhite) | |
menu.SetBackgroundColor(tcell.Color19) | |
menu. | |
AddItem(" [::b]Hello", "", 0, func() { | |
app.SetFocus(textView) | |
}). | |
AddItem(" [::b]CV", "", 0, func() { | |
app.SetFocus(textView) | |
}). | |
AddItem(" [::b]How", "", 0, func() { | |
app.SetFocus(textView) | |
}). | |
AddItem(" [::b]Why", "", 0, func() { | |
app.SetFocus(textView) | |
}). | |
AddItem(" [::b]Quit", "", 0, func() { | |
app.Stop() | |
}) | |
menu.SetChangedFunc(func(i int, mt, st string, sc rune) { | |
switch i { | |
case 0: | |
printAbout() | |
case 1: | |
printCv() | |
case 2: | |
printHow() | |
case 3: | |
printWhy() | |
} | |
}) | |
printAbout() | |
flex := tview.NewFlex(). | |
AddItem(menu, 0, 1, true). | |
AddItem(textView, 0, 5, false) | |
flexFrame := tview.NewFrame(flex). | |
AddText( | |
" [::b](c) 2020, Andy B.[::-] [::b]Up/Down[::-]: Navigate, [::b]Enter[::-]: Open item, [::b]Esc[::-]: Back to Menu", | |
false, | |
tview.AlignLeft, | |
tcell.ColorWhite). | |
SetBorders(0, 1, 0, 0, 0, 0) | |
pages = tview.NewPages(). | |
AddPage("layout", flexFrame, true, true) | |
app.SetRoot(pages, true).SetFocus(menu).EnableMouse(true).Run() | |
} | |
func printAbout() { | |
textView.Clear() | |
fmt.Fprintf(textView, "%s ", about) | |
textView.ScrollToBeginning() | |
textView.SetTitle("Hello") | |
} | |
func printCv() { | |
textView.Clear() | |
fmt.Fprintf(textView, "%s ", cv) | |
textView.SetTitle("CV") | |
} | |
func printHow() { | |
textView.Clear() | |
fmt.Fprintf(textView, "%s ", how) | |
textView.SetTitle("How") | |
} | |
func printWhy() { | |
textView.Clear() | |
fmt.Fprintf(textView, "%s ", why) | |
textView.SetTitle("Why") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment