commit 772fedb8f9952e6fec050d1fdd8c6889318f0ff0 parent a8ada830162dd940a56d7f17979d1e596f701c5c Author: Yuval Langer <yuval.langer@gmail.com> Date: Fri, 19 Jan 2024 07:43:54 +0200 Merge the Commonly Forgotten repository into kaka.farm. Diffstat:
41 files changed, 1053 insertions(+), 0 deletions(-)
diff --git a/commonly-forgotten/.gitignore b/commonly-forgotten/.gitignore @@ -0,0 +1,9 @@ +secret-config.mk +public/ +/site/ +*.swp +output/ +pelican_base_configuration.pyc +__pycache__ +*~ +/_site/ diff --git a/commonly-forgotten/.gitlab-ci.yml b/commonly-forgotten/.gitlab-ci.yml @@ -0,0 +1,16 @@ +image: ubuntu:latest + +pages: + stage: deploy + script: + - apt-get update + - apt-get install -y wget make + - wget https://github.com/cobalt-org/cobalt.rs/releases/download/v0.15.4/cobalt-v0.15.4-x86_64-unknown-linux-gnu.tar.gz + - tar xvf cobalt-v0.15.4-x86_64-unknown-linux-gnu.tar.gz + - make gitlab-ci + artifacts: + paths: + - public/ + only: + - master + - dev diff --git a/commonly-forgotten/Makefile b/commonly-forgotten/Makefile @@ -0,0 +1,86 @@ +PY?=python3 +PELICAN?=pelican +PELICANOPTS=--theme-path themes/fixed-simple + +BASEDIR=$(CURDIR) +INPUTDIR=$(BASEDIR)/content +OUTPUTDIR=$(BASEDIR)/output +CONFFILE=$(BASEDIR)/pelicanconf.py +PUBLISHCONF=$(BASEDIR)/publishconf.py + +SSH_HOST=kaka.farm +SSH_PORT=22 +SSH_USER=commonly-forgotten +SSH_TARGET_DIR=/home/commonly-forgotten/public_html + + +DEBUG ?= 0 +ifeq ($(DEBUG), 1) + PELICANOPTS += -D +endif + +RELATIVE ?= 0 +ifeq ($(RELATIVE), 1) + PELICANOPTS += --relative-urls +endif + +help: + @echo 'Makefile for a pelican Web site ' + @echo ' ' + @echo 'Usage: ' + @echo ' make html (re)generate the web site ' + @echo ' make clean remove the generated files ' + @echo ' make regenerate regenerate files upon modification ' + @echo ' make publish generate using production settings ' + @echo ' make serve [PORT=8000] serve site at http://localhost:8000' + @echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 ' + @echo ' make devserver [PORT=8000] serve and regenerate together ' + @echo ' make ssh_upload upload the web site via SSH ' + @echo ' make rsync_upload upload the web site via rsync+ssh ' + @echo ' ' + @echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html ' + @echo 'Set the RELATIVE variable to 1 to enable relative urls ' + @echo ' ' + +html: + $(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) + +clean: + [ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR) + +regenerate: + $(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) + +serve: +ifdef PORT + $(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) +else + $(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) +endif + +serve-global: +ifdef SERVER + $(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) -b $(SERVER) +else + $(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) -b 0.0.0.0 +endif + + +devserver: +ifdef PORT + $(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) +else + $(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) +endif + +publish: + $(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS) + +ssh_upload: publish + scp -P $(SSH_PORT) -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) + +rsync_upload: publish + rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --cvs-exclude --delete $(OUTPUTDIR)/ $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) + + +.PHONY: html help clean regenerate serve serve-global devserver stopserver publish ssh_upload rsync_upload diff --git a/commonly-forgotten/README.md b/commonly-forgotten/README.md @@ -0,0 +1,14 @@ +title: About. + +commonly-forgotten +================== + +I forget, so I write. + +Main repository: + +<https://codeberg.org/yuvallangerontheroad/commonly-forgotten> + +Mirror repositories: + +<https://gitlab.com/yuvallangerontheroad/commonly-forgotten> diff --git a/commonly-forgotten/_cobalt.yml b/commonly-forgotten/_cobalt.yml @@ -0,0 +1,7 @@ + +site: + title: cobalt blog + description: Blog Posts Go Here + base_url: http://kaka.farm +posts: + rss: rss.xml diff --git a/commonly-forgotten/_defaults/pages.md b/commonly-forgotten/_defaults/pages.md @@ -0,0 +1,10 @@ +--- +layout: default.liquid +--- +## Blog! + +{% for post in collections.posts.pages %} +#### {{post.title}} + +[{{ post.title }}]({{ post.permalink }}) +{% endfor %} diff --git a/commonly-forgotten/_defaults/posts.md b/commonly-forgotten/_defaults/posts.md @@ -0,0 +1,10 @@ +--- +layout: default.liquid + +title: First Post +is_draft: true +--- + +# This is our first Post! + +Welcome to the first post ever on cobalt.rs! diff --git a/commonly-forgotten/_layouts/default.liquid b/commonly-forgotten/_layouts/default.liquid @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>{{ page.title }}</title> + </head> + <body> + <!-- A web hipster told me to centralize with the following top div style --> + <div style="max-width: 920px; margin: auto; padding: 20px;"> + <h2>{{ page.title }}</h2> + {{ page.content }} + </div> + </body> +</html> diff --git a/commonly-forgotten/_posts/test.md b/commonly-forgotten/_posts/test.md @@ -0,0 +1,22 @@ +--- +title: "Test Page" +published: false +layout: post +category: test +tags: +- yolk +- exoskeleton +- test +--- + +# Test # + +Lorem ipsum... + +### Stuff + +More stuff + +### Yolk + +Exoskeleton... diff --git a/commonly-forgotten/content/2019-06-12-making-quicksilver-and-friends-play-nice-with-wasm32.md b/commonly-forgotten/content/2019-06-12-making-quicksilver-and-friends-play-nice-with-wasm32.md @@ -0,0 +1,189 @@ +--- +title: Making Quicksilver and friends play nice with wasm32. +published_date: "2019-06-12 20:23:48 +0000" +layout: default.liquid +is_draft: false +--- +## Disclaimer: + +This technology is indistinguishable from magic. I am merely recalling which + spells and incantations worked for me. If you have anything to add, you can + reach me on <https://gitgud.io/yuvallanger/kaka.farm/> or + <https://gitlab.com/yuvallanger/kaka.farm/>. + +Several months ago, writing a Flappy Bird clone called [Rectangly +Rect](https://gitgud.io/yuvallanger/rectangly-rect/), I have done a bunch of +asking around and found exactly which parts don't work and how to replace them. +Yesterday, trying to adapt YasamSim to the web, I have re-discovered those +workarounds, and decided to write this down. + +## `println!`! + +First thing, drop all of your `println!`s. For some esoteric reason, this +function throws a wrench into the web's machinery. Same goes for +`std::time::Instance::now()`. For now I just dropped all calls to `now()`, +maybe I could ask the browser manually with whatever function Javascript has, +or maybe there is a more standardized `std` alternative for the web - I don't +know. + +In order to replace `println!`, I had to add to `Cargo.toml` a general +dependency for the crate `log`, an entry for every target that is not wasm32 +for the crate `env_logger`, and an entry for the crate `web_logger` for the +wasm32 target: + +```Cargo.toml +[dependencies] +log = "0.4" + +[target.'cfg(not(wasm32))'.dependencies] +env_logger = "0.6" + +[target.'cfg(wasm32)'.dependencies] +web_logger = "0.1" +``` + +In `src/logging.rs`, conditionally compile a different `init_logger()` function +for each platform, wasm32 and not-wasm32: + +```src/logging.rs +#[cfg(target_arch = "wasm32")] +pub fn init_logger() { + ::web_logger::init(); +} + +#[cfg(not(target_arch = "wasm32"))] +pub fn init_logger() { + ::env_logger::init(); +} +``` + +In `src/main.rs`, call the `init_logger()` defined in the `logging.rs` +sub-module at the head of your `main()` function: + +```src/main.rs +mod logging; + +fn main() { + logging::init_logger(); + … +} +``` + +Now you can call `info!()`, `error!()`, `warn!()`, etc., as described in <https://docs.rs/log/0.4/log/>. + +If you also debug it in your native target, you can also provide the `RUST_LOG` +environment variable, as per <https://docs.rs/env_logger/0.6/env_logger/>'s +documentation, in your command line incantations: + +``` +$ RUST_LOG=DEBUG cargo run +``` + +## Sequentialize SPECS. + +For some more esoteric reasons, probably something to do with threads, I had to +rewrite how I run my `specs::System`s , and +how `specs::System`s written. + +### Dispatching `specs::Dispatcher`. + +One normally builds a dependency graph of `specs::System`s using something +like: + +```src/main.rs +fn make_specs_dispatcher() -> specs::Dispatcher<'static, 'static> { + specs::DispatcherBuilder::new() + .with( + SystemFoo, + "system_foo", + &[], + ) + .with( + SystemBar, + "system_bar", + &["system_foo"], + ) + .build() +} + +struct OurGameState { + specs_world: specs::World, + specs_dispatcher: specs::Dispatcher, +} + + +impl State for OurGameState { + fn new() -> Result<World> { + let specs_world = make_specs_world_and_register_components(); // Implemented elsewhere… + let specs_dispatcher = make_specs_dispatcher(); + + Ok( + OurGameState { + specs_world, + specs_dispatcher, + } + ) + } + + fn update(&mut self, window: &mut Window) -> Result<()> { + let system_foo = SystemFoo; + let system_bar = SystemBar; + + system_foo.run_now(&selfworld.res); + system_bar.run_now(&world.res); + + world.maintain(); + + Ok(()) + } + + [imagine the rest of the quicksilver::lifecycle::State methods implemented here…] +} +``` + +In this example `SystemBar` depends on the state of the `specs::World` left by +`SystemFoo` after it does its thing. + +Instead of using this `Dispatcher` as described in +<https://slide-rs.github.io/specs/03_dispatcher.html>, you do this in your +`quicksilver::lifecycle::State::update()` + +``` +struct OurGameState { + specs_world: specs::World, +} + +impl State for OurGameState { + fn new() -> Result<World> { + let specs_world = make_specs_world_and_register_components(); // Implemented elsewhere… + + Ok( + OurGameState { + specs_world, + } + ) + } + + fn update(&mut self, window: &mut Window) -> Result<()> { + let system_foo = SystemFoo; + let system_bar = SystemBar; + + system_foo.run_now(&selfworld.res); + system_bar.run_now(&world.res); + + world.maintain(); + + Ok(()) + } + + [imagine the rest of the quicksilver::lifecycle::State methods implemented here…] +} +``` + +But in order to sequentialize how you deal with `specs`, you'd need to change one more thing: + +### Lay off `specs::LazyUpdater`. + +If you do anything with `specs::LazyUpdate`, you would have to convert it into +another form, interacting with your `Component` `Storage`s directly with +`WriteStorage` or whatever. diff --git a/commonly-forgotten/content/2022-01-27-opencv-and-gtk.md b/commonly-forgotten/content/2022-01-27-opencv-and-gtk.md @@ -0,0 +1,45 @@ +title: Finding mouse location in Python + GTK + OpenCV. +date: 2022-01-27 + +Expanding on the tutorial: + +<https://nofurtherquestions.wordpress.com/2017/03/03/python-3-5-gtk-3-glade-and-opencv/> + +it originally had shown the following structure: + +``` +- window1 (GtkWindow) + - box1 (GtkBox) + - grayscaleButton (GtkToggleButton) + - image (GtkImage) +``` + +According to <https://stackoverflow.com/a/24388310/189995> `GtkImage` does not +generate events, so if you want to find the mouse location, put your +`GtkImage` inside a `GtkEventBox`: + +``` +- window1 (GtkWindow) + - box1 (GtkBox) + - grayscaleButton (GtkToggleButton) + - eventbox (GtkEventBox) + - image (GtkImage) +``` + +and in `eventbox` set the `Common -> Events -> Pointer Motion` so you can add +a handler to the `motion-notify-event` event. + +Now you can write your handler: + +```python +class Handler: + … + … + … + def onMotionNotifyEvent(*args): + global current_mouse_location + + event = args[1] + + current_mouse_location = event.x, event.y +``` diff --git a/commonly-forgotten/content/2022-01-29-python-gtk-scale-value-changed-event-handler.md b/commonly-forgotten/content/2022-01-29-python-gtk-scale-value-changed-event-handler.md @@ -0,0 +1,35 @@ +title: Handling Python/GTK's GtkScale value-changed event. +date: 2022-01-29 + +It took me way too long, but now I know how to handle the value-changed event of GtkScale. + +In Glade: + +1. Create a GtkScale widget. We will ID it `foo_scale`. +2. In the `Signals -> GtkRange -> value-changed` line change the `Handler` + field to something sensible like `on_foo_scale_value_changed`. That will + be the name of the handler. +3. Make a new Adjustment in: + + ``` + General -> + Adjustment -> + (little pen button in the field) -> + Choose a [sic] Adjustment in this project -> + New + ``` + +4. Rename the adjustment to something sensible like `foo_adjustment` and set + the `Value`, `Minimum Value`, `Maximum Value`, etc. Those are kind of self + explanatory… +5. In Python, your handler will be called with a single argument - the signal + emitting object, which is the GtkScale object itself. It has a method, + `get_value()`, used to get its current value: + + ```python + def on_foo_scale_value_changed(emitter): + scale_value = emitter.get_value() + do_stuff_with_scale_value(scale_value) + ``` + +Fin. diff --git a/commonly-forgotten/content/pages/Commands.md b/commonly-forgotten/content/pages/Commands.md @@ -0,0 +1,3 @@ +title: Commands I infrequently need. + +Dump streams, vlecs (personal use, of course), videos - mplayer -dumpfile [file] -dumpstream [url] diff --git a/commonly-forgotten/content/pages/Python-versus-c.md b/commonly-forgotten/content/pages/Python-versus-c.md @@ -0,0 +1,5 @@ +title: Python versus C. + +## Modulus + +[C/Python different behaviour of the modulo operation](http://stackoverflow.com/questions/1907565/c-python-different-behaviour-of-the-modulo-operation) diff --git a/commonly-forgotten/content/pages/Python.md b/commonly-forgotten/content/pages/Python.md @@ -0,0 +1,14 @@ +title: Python. + +# Python + +## Getting a dictionary of the attribute name and attribute value pairs + +```python +class a: + b = 'b' + def __init__(self, c): + self.c = c + def who(self): + return(scipy.who(vars(self))) +``` diff --git a/commonly-forgotten/content/pages/README.md b/commonly-forgotten/content/pages/README.md @@ -0,0 +1 @@ +../../README.md +\ No newline at end of file diff --git a/commonly-forgotten/content/pages/Vim.md b/commonly-forgotten/content/pages/Vim.md @@ -0,0 +1,7 @@ +title: Vim. + +How many lines / Count marked lines + +"In visual mode, press g C-g." + +http://stackoverflow.com/questions/7262536/vim-count-lines-in-selected-range diff --git a/commonly-forgotten/content/pages/Words.md b/commonly-forgotten/content/pages/Words.md @@ -0,0 +1,7 @@ +title: Words on the tip of my tongue. + +# Words on the tip of my tongue # + +* Rhetoric +* Demagogue +* Corruption diff --git a/commonly-forgotten/content/pages/irc-operator.md b/commonly-forgotten/content/pages/irc-operator.md @@ -0,0 +1,14 @@ +title: IRC tasks. + +## Forward to another channel. + +Let's say you have an existing channel named `#channel` and you want to move to `#newchannel`. + +Use these commands on the libera.chat IRC network (may also work on other networks. I do not know) to forward users who join `#channel` to `#newchannel`: + +``` +/msg chanserv set #yourchannel mlock +if #yourotherchannel +/msg chanserv set #yourchannel guard on +``` + +NOTICE: You must not set any akick, or the kicked users would not be forwarded to your new channel. diff --git a/commonly-forgotten/content/pages/pixel-manipulations-in-godot.md b/commonly-forgotten/content/pages/pixel-manipulations-in-godot.md @@ -0,0 +1,7 @@ +title: pixel manipulation in Godot-engine. + +# Per pixel manipulation in Godotengine. + +* [Image class](https://docs.godotengine.org/en/stable/classes/class_image.html) +* [Can I create an image and draw to it in Godot?](https://godotengine.org/qa/78068/can-i-create-an-image-and-draw-to-it-in-godot?show=78068#q78068) + * [this is the minimal code that you need to draw pixels to screen using an image](https://gist.github.com/kasthor/da23d1ed802a1eab7ac354305608f40f) diff --git a/commonly-forgotten/content/pages/terminal-programming.markdown b/commonly-forgotten/content/pages/terminal-programming.markdown @@ -0,0 +1,27 @@ +title: Notes on terminal programming. + +# Notes on terminal programming. + +If you want get keys pressed immediately, not only after pressing enter, amongst other nice terminal programs features, you have to talk with the "termios driver", according to this talk, at 09:06. + +- `stty -onlcr` - will disable the "translate newline to carriage return newline" (from man's STTY(1)), so its negation is just move cursor one row down, without changing column. +- `stty -echo` - disable STTY(1) "echo input characters" or the "Where did my keyboard go?!" mode. +- `stty -icanon` - disable the "line editor" (Brandon Rhodes). + STTY(1): "enable special characters: erase, kill, werase, rprnt" +- `stty raw` - too? + +`Animations In The TERMINAL [Animating With ASCII]`: <https://youtu.be/K_6peGEsq0U?t=9m6s> + +You can read stty state with `stty -g` at the start of the program and then use that as the argument of stty to return to the previous state. +While using it to read the state within a program, stty complained about something like "not a typewriter". Need to figure that one out. Right now there is no other way but to use something like termion, the "gay space communism" (sheesh...) project ([I wish I were kidding...](https://gitlab.redox-os.org/redox-os/termion/-/blob/master/examples/commie.rs)). + +Oops! According to `#rust:matrix.org` I can do this: + +``` +std::process::Command::new("stty") + .arg("-g") + .stdin(std::process::Stdio::inherit()) + .output() +``` + +What exactly is inherited stdin? the same stdin as the father process? diff --git a/commonly-forgotten/content/pages/weave.md b/commonly-forgotten/content/pages/weave.md @@ -0,0 +1,46 @@ +title: Weave stuff. (insanely obsolete) + + +# Accessing an array and its metadata through C/C++ in *scipy.weave.inline()* + +* Accessing an array *foo* with *foo.ndim == 3*: + - The array itself will be accessable through the *FOO3(i, j, k)* function. + - Array assignments will be the same. *FOO3(i, j, k) = bar;* + - *foo.shape* will be accessable through the *Nfoo[]* array. + + +## The inline code: + +~~~ { .cpp } + +long dim1, dim2, dim3; + +dim1 = Nfoo[0]; // dimension access. +dim2 = Nfoo[1]; +dim3 = Nfoo[2]; + +FOO3(0,0,0) = 1; // array assignment +return_val = FOO3(0,0,0); // array access. + +~~~ + +## The Python code: + +~~~ { .python } +import scipy +import scipy.weave +inline_code = r""" +put C/C++ code in here +""" +foo = scipy.arange(3**3).reshape((3,3,3)) +scipy.weave.inline(inline_code, foo) +~~~ + +# Using Python functions in weave.inline + +Call *foo.call(py:tuple arg)*. + +# Links + +* At Weave and Numpy array arguments: [Scipy's Weave page](http://www.scipy.org/Weave) +* [Calling Python functions from inline C with scipy.weave (stackoverflow)](http://stackoverflow.com/questions/5929600/calling-python-functions-from-inline-c-with-scipy-weave) diff --git a/commonly-forgotten/index.md b/commonly-forgotten/index.md @@ -0,0 +1,10 @@ +--- +layout: default.liquid +--- +## Blog! + +{% for post in collections.posts.pages %} +#### {{post.title}} + +[{{ post.title }}]({{ post.permalink }}) +{% endfor %} diff --git a/commonly-forgotten/pelicanconf.py b/commonly-forgotten/pelicanconf.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- # +from __future__ import unicode_literals + +AUTHOR = 'Yuval Langer' +SITENAME = 'Commonly Forgotten' +SITEURL = '' + +PATH = 'content' + +TIMEZONE = 'Asia/Jerusalem' + +DEFAULT_LANG = 'en' + +# Feed generation is usually not desired when developing +FEED_ALL_ATOM = None +CATEGORY_FEED_ATOM = None +TRANSLATION_FEED_ATOM = None +AUTHOR_FEED_ATOM = None +AUTHOR_FEED_RSS = None + +# Blogroll +LINKS = (('Pelican', 'http://getpelican.com/'), + ('Python.org', 'http://python.org/'), + ('Jinja2', 'http://jinja.pocoo.org/'), + ('You can modify those links in your config file', '#'),) + +# Social widget +SOCIAL = (('You can add links in your config file', '#'), + ('Another social link', '#'),) + +DEFAULT_PAGINATION = 10 + +# Uncomment following line if you want document-relative URLs when developing +#RELATIVE_URLS = True +\ No newline at end of file diff --git a/commonly-forgotten/publishconf.py b/commonly-forgotten/publishconf.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- # +from __future__ import unicode_literals + +# This file is only used if you use `make publish` or +# explicitly specify it as your config file. + +import os +import sys +sys.path.append(os.curdir) +from pelicanconf import * + +# If your site is available via HTTPS, make sure SITEURL begins with https:// +SITEURL = 'https://kaka.farm/~commonly-forgotten' +RELATIVE_URLS = False + +FEED_ALL_ATOM = 'feeds/all.atom.xml' +CATEGORY_FEED_ATOM = 'feeds/{slug}.atom.xml' + +DELETE_OUTPUT_DIRECTORY = True + +# Following items are often useful when publishing + +#DISQUS_SITENAME = "" +#GOOGLE_ANALYTICS = "" +\ No newline at end of file diff --git a/commonly-forgotten/tasks.py b/commonly-forgotten/tasks.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +import os +import shutil +import sys +import datetime + +from invoke import task +from invoke.util import cd +from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer + +CONFIG = { + # Local path configuration (can be absolute or relative to tasks.py) + 'deploy_path': 'output', + # Remote server configuration + 'production': 'commonly-forgotten@kaka.farm:22', + 'dest_path': '/home/commonly-forgotten/public_html', + # Port for `serve` + 'port': 8000, +} + +@task +def clean(c): + """Remove generated files""" + if os.path.isdir(CONFIG['deploy_path']): + shutil.rmtree(CONFIG['deploy_path']) + os.makedirs(CONFIG['deploy_path']) + +@task +def build(c): + """Build local version of site""" + c.run('pelican -s pelicanconf.py') + +@task +def rebuild(c): + """`build` with the delete switch""" + c.run('pelican -d -s pelicanconf.py') + +@task +def regenerate(c): + """Automatically regenerate site upon file modification""" + c.run('pelican -r -s pelicanconf.py') + +@task +def serve(c): + """Serve site at http://localhost:8000/""" + + class AddressReuseTCPServer(RootedHTTPServer): + allow_reuse_address = True + + server = AddressReuseTCPServer( + CONFIG['deploy_path'], + ('', CONFIG['port']), + ComplexHTTPRequestHandler) + + sys.stderr.write('Serving on port {port} ...\n'.format(**CONFIG)) + server.serve_forever() + +@task +def reserve(c): + """`build`, then `serve`""" + build(c) + serve(c) + +@task +def preview(c): + """Build production version of site""" + c.run('pelican -s publishconf.py') + + +@task +def publish(c): + """Publish to production via rsync""" + c.run('pelican -s publishconf.py') + c.run( + 'rsync --delete --exclude ".DS_Store" -pthrvz -c ' + '{} {production}:{dest_path}'.format( + CONFIG['deploy_path'].rstrip('/') + '/', + **CONFIG)) + diff --git a/commonly-forgotten/themes/fixed-simple/templates/archives.html b/commonly-forgotten/themes/fixed-simple/templates/archives.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} + +{% block title %}{{ SITENAME }} - Archives{% endblock %} + +{% block content %} +<h1>Archives for {{ SITENAME }}</h1> + +<dl> +{% for article in dates %} + <dt>{{ article.locale_date }}</dt> + <dd><a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a></dd> +{% endfor %} +</dl> +{% endblock %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/article.html b/commonly-forgotten/themes/fixed-simple/templates/article.html @@ -0,0 +1,67 @@ +{% extends "base.html" %} +{% block html_lang %}{{ article.lang }}{% endblock %} + +{% block title %}{{ SITENAME }} - {{ article.title }}{% endblock %} + +{% block head %} + {{ super() }} + + {% import 'translations.html' as translations with context %} + {% if translations.entry_hreflang(article) %} + {{ translations.entry_hreflang(article) }} + {% endif %} + + {% if article.description %} + <meta name="description" content="{{article.description}}" /> + {% endif %} + + {% for tag in article.tags %} + <meta name="tags" content="{{tag}}" /> + {% endfor %} + +{% endblock %} + +{% block content %} +<section id="content" class="body"> + <header> + <h2 class="entry-title"> + <a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark" + title="Permalink to {{ article.title|striptags }}">{{ article.title }}</a></h2> + {% import 'translations.html' as translations with context %} + {{ translations.translations_for(article) }} + </header> + <footer class="post-info"> + <time class="published" datetime="{{ article.date.isoformat() }}"> + {{ article.locale_date }} + </time> + {% if article.modified %} + <time class="modified" datetime="{{ article.modified.isoformat() }}"> + {{ article.locale_modified }} + </time> + {% endif %} + {% if article.authors %} + <address class="vcard author"> + By {% for author in article.authors %} + <a class="url fn" href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a> + {% endfor %} + </address> + {% endif %} + {% if article.category %} + <div class="category"> + Category: <a href="{{ SITEURL }}/{{ article.category.url }}">{{ article.category }}</a> + </div> + {% endif %} + {% if article.tags %} + <div class="tags"> + Tags: + {% for tag in article.tags %} + <a href="{{ SITEURL }}/{{ tag.url }}">{{ tag }}</a> + {% endfor %} + </div> + {% endif %} + </footer><!-- /.post-info --> + <div class="entry-content"> + {{ article.content }} + </div><!-- /.entry-content --> +</section> +{% endblock %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/author.html b/commonly-forgotten/themes/fixed-simple/templates/author.html @@ -0,0 +1,8 @@ +{% extends "index.html" %} + +{% block title %}{{ SITENAME }} - Articles by {{ author }}{% endblock %} + +{% block content_title %} +<h2>Articles by {{ author }}</h2> +{% endblock %} + diff --git a/commonly-forgotten/themes/fixed-simple/templates/authors.html b/commonly-forgotten/themes/fixed-simple/templates/authors.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block title %}{{ SITENAME }} - Authors{% endblock %} + +{% block content %} + <h1>Authors on {{ SITENAME }}</h1> + <ul> + {% for author, articles in authors|sort %} + <li><a href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a> ({{ articles|count }})</li> + {% endfor %} + </ul> +{% endblock %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/base.html b/commonly-forgotten/themes/fixed-simple/templates/base.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<html lang="{% block html_lang %}{{ DEFAULT_LANG }}{% endblock html_lang %}"> +<head> + {% block head %} + <title>{% block title %}{{ SITENAME }}{% endblock title %}</title> + <meta charset="utf-8" /> + {% if FEED_ALL_ATOM %} + <link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_ATOM_URL %}{{ FEED_ALL_ATOM_URL }}{% else %}{{ FEED_ALL_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Full Atom Feed" /> + {% endif %} + {% if FEED_ALL_RSS %} + <link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_RSS_URL %}{{ FEED_ALL_RSS_URL }}{% else %}{{ FEED_ALL_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Full RSS Feed" /> + {% endif %} + {% if FEED_ATOM %} + <link href="{{ FEED_DOMAIN }}/{%if FEED_ATOM_URL %}{{ FEED_ATOM_URL }}{% else %}{{ FEED_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Atom Feed" /> + {% endif %} + {% if FEED_RSS %} + <link href="{{ FEED_DOMAIN }}/{% if FEED_RSS_URL %}{{ FEED_RSS_URL }}{% else %}{{ FEED_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} RSS Feed" /> + {% endif %} + {% if CATEGORY_FEED_ATOM and category %} + <link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_ATOM_URL %}{{ CATEGORY_FEED_ATOM_URL.format(slug="category.slug") }}{% else %}{{ CATEGORY_FEED_ATOM.format(slug="category.slug") }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Categories Atom Feed" /> + {% endif %} + {% if CATEGORY_FEED_RSS and category %} + <link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_RSS_URL %}{{ CATEGORY_FEED_RSS_URL.format(slug="category.slug") }}{% else %}{{ CATEGORY_FEED_RSS.format(slug="category.slug") }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Categories RSS Feed" /> + {% endif %} + {% if TAG_FEED_ATOM and tag %} + <link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_ATOM_URL %}{{ TAG_FEED_ATOM_URL.format(slug="tag.slug") }}{% else %}{{ TAG_FEED_ATOM.format(slug="tag.slug") }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Tags Atom Feed" /> + {% endif %} + {% if TAG_FEED_RSS and tag %} + <link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_RSS_URL %}{{ TAG_FEED_RSS_URL.format(slug="tag.slug") }}{% else %}{{ TAG_FEED_RSS.format(slug="tag.slug") }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Tags RSS Feed" /> + {% endif %} + {% endblock head %} +</head> + +<body id="index" class="home"> + <header id="banner" class="body"> + <h1><a href="{{ SITEURL }}/">{{ SITENAME }} <strong>{{ SITESUBTITLE }}</strong></a></h1> + </header><!-- /#banner --> + <nav id="menu"><ul> + {% for title, link in MENUITEMS %} + <li><a href="{{ link }}">{{ title }}</a></li> + {% endfor %} + {% if DISPLAY_PAGES_ON_MENU %} + {% for p in pages %} + <li{% if p == page %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li> + {% endfor %} + {% endif %} + {% if DISPLAY_CATEGORIES_ON_MENU %} + {% for cat, null in categories %} + <li{% if cat == category %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ cat.url }}">{{ cat }}</a></li> + {% endfor %} + {% endif %} + </ul></nav><!-- /#menu --> + {% block content %} + {% endblock %} + <footer id="contentinfo" class="body"> + <address id="about" class="vcard body"> + Proudly powered by <a href="http://getpelican.com/">Pelican</a>, + which takes great advantage of <a href="http://python.org">Python</a>. + </address><!-- /#about --> + </footer><!-- /#contentinfo --> +</body> +</html> diff --git a/commonly-forgotten/themes/fixed-simple/templates/categories.html b/commonly-forgotten/themes/fixed-simple/templates/categories.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block title %}{{ SITENAME }} - Categories{% endblock %} + +{% block content %} + <h1>Categories on {{ SITENAME }}</h1> + <ul> + {% for category, articles in categories|sort %} + <li><a href="{{ SITEURL }}/{{ category.url }}">{{ category }}</a> ({{ articles|count }})</li> + {% endfor %} + </ul> +{% endblock %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/category.html b/commonly-forgotten/themes/fixed-simple/templates/category.html @@ -0,0 +1,8 @@ +{% extends "index.html" %} + +{% block title %}{{ SITENAME }} - {{ category }} category{% endblock %} + +{% block content_title %} +<h2>Articles in the {{ category }} category</h2> +{% endblock %} + diff --git a/commonly-forgotten/themes/fixed-simple/templates/gosquared.html b/commonly-forgotten/themes/fixed-simple/templates/gosquared.html @@ -0,0 +1,14 @@ +{% if GOSQUARED_SITENAME %} +<script type="text/javascript"> + var GoSquared={}; + GoSquared.acct = "{{ GOSQUARED_SITENAME }}"; + (function(w){ + function gs(){ + w._gstc_lt=+(new Date); var d=document; + var g = d.createElement("script"); g.type = "text/javascript"; g.async = true; g.src = "https://d1l6p2sc9645hc.cloudfront.net/tracker.js"; + var s = d.getElementsByTagName("script")[0]; s.parentNode.insertBefore(g, s); + } + w.addEventListener?w.addEventListener("load",gs,false):w.attachEvent("onload",gs); + })(window); +</script> +{% endif %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/index.html b/commonly-forgotten/themes/fixed-simple/templates/index.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} +{% block content %} +<section id="content"> +{% block content_title %} +<h2>All articles</h2> +{% endblock %} + +<ol id="post-list"> +{% for article in articles_page.object_list %} + <li><article class="hentry"> + <header> <h2 class="entry-title"><a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark" title="Permalink to {{ article.title|striptags }}">{{ article.title }}</a></h2> </header> + <footer class="post-info"> + <time class="published" datetime="{{ article.date.isoformat() }}"> {{ article.locale_date }} </time> + <address class="vcard author">By + {% for author in article.authors %} + <a class="url fn" href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a> + {% endfor %} + </address> + </footer><!-- /.post-info --> + <div class="entry-content"> {{ article.summary }} </div><!-- /.entry-content --> + </article></li> +{% endfor %} +</ol><!-- /#posts-list --> +{% if articles_page.has_other_pages() %} + {% include 'pagination.html' %} +{% endif %} +</section><!-- /#content --> +{% endblock content %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/page.html b/commonly-forgotten/themes/fixed-simple/templates/page.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} +{% block html_lang %}{{ page.lang }}{% endblock %} + +{% block title %}{{ SITENAME }} - {{ page.title }}{%endblock%} + +{% block head %} + {{ super() }} + + {% import 'translations.html' as translations with context %} + {% if translations.entry_hreflang(page) %} + {{ translations.entry_hreflang(page) }} + {% endif %} +{% endblock %} + +{% block content %} + <h1>{{ page.title }}</h1> + {% import 'translations.html' as translations with context %} + {{ translations.translations_for(page) }} + + {{ page.content }} + + {% if page.modified %} + <p> + Last updated: {{ page.locale_modified }} + </p> + {% endif %} +{% endblock %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/pagination.html b/commonly-forgotten/themes/fixed-simple/templates/pagination.html @@ -0,0 +1,11 @@ +{% if DEFAULT_PAGINATION %} +<p class="paginator"> + {% if articles_page.has_previous() %} + <a href="{{ SITEURL }}/{{ articles_previous_page.url }}">«</a> + {% endif %} + Page {{ articles_page.number }} / {{ articles_paginator.num_pages }} + {% if articles_page.has_next() %} + <a href="{{ SITEURL }}/{{ articles_next_page.url }}">»</a> + {% endif %} +</p> +{% endif %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/period_archives.html b/commonly-forgotten/themes/fixed-simple/templates/period_archives.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} + +{% block title %}{{ SITENAME }} - {{ period | reverse | join(' ') }} archives{% endblock %} + +{% block content %} +<h1>Archives for {{ period | reverse | join(' ') }}</h1> + +<dl> +{% for article in dates %} + <dt>{{ article.locale_date }}</dt> + <dd><a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a></dd> +{% endfor %} +</dl> +{% endblock %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/tag.html b/commonly-forgotten/themes/fixed-simple/templates/tag.html @@ -0,0 +1,7 @@ +{% extends "index.html" %} + +{% block title %}{{ SITENAME }} - {{ tag }} tag{% endblock %} + +{% block content_title %} +<h2>Articles tagged with {{ tag }}</h2> +{% endblock %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/tags.html b/commonly-forgotten/themes/fixed-simple/templates/tags.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block title %}{{ SITENAME }} - Tags{% endblock %} + +{% block content %} + <h1>Tags for {{ SITENAME }}</h1> + <ul> + {% for tag, articles in tags|sort %} + <li><a href="{{ SITEURL }}/{{ tag.url }}">{{ tag }}</a> ({{ articles|count }})</li> + {% endfor %} + </ul> +{% endblock %} diff --git a/commonly-forgotten/themes/fixed-simple/templates/translations.html b/commonly-forgotten/themes/fixed-simple/templates/translations.html @@ -0,0 +1,16 @@ +{% macro translations_for(article) %} +{% if article.translations %} +Translations: +{% for translation in article.translations %} +<a href="{{ SITEURL }}/{{ translation.url }}" hreflang="{{ translation.lang }}">{{ translation.lang }}</a> +{% endfor %} +{% endif %} +{% endmacro %} + +{% macro entry_hreflang(entry) %} +{% if entry.translations %} + {% for translation in entry.translations %} + <link rel="alternate" hreflang="{{ translation.lang }}" href="{{ SITEURL }}/{{ translation.url }}"> + {% endfor %} +{% endif %} +{% endmacro %}