Add files

This commit is contained in:
ge
2022-08-07 14:03:38 +03:00
parent 77499a5bd8
commit 82c56a247d
25 changed files with 3814 additions and 4 deletions

49
content/bash_prompt.rst Normal file
View File

@ -0,0 +1,49 @@
:title: Функциональный и простой Bash prompt
:date: 10 Jul 2022
====================================
Функциональный и простой Bash prompt
====================================
О промптинге в Bash написано очень много, в этой заметке я просто покажу
лаконичный и функциональный вариант приглашения командной строки.
Вот фрагмент из моего **~/.bashrc**:
.. code-block:: shell
# Command line prompt
# Print a non-zero exit code
__exit_code_ps1() {
if [ "$1" -ne 0 ]; then
echo "$1 "
fi
}
PS1='\[\033[0;92m\]\w \[\033[0;31m\]$(__exit_code_ps1 $?)\[\033[0;15m\]\$ '
# Git prompt
# See /usr/share/git/completion/git-prompt.sh or download from:
# https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh
if [ -f /usr/share/git/completion/git-prompt.sh ]; then
. /usr/share/git/completion/git-prompt.sh
GIT_PS1_SHOWDIRTYSTATE=1
PS1='\[\033[0;96m\]$(__git_ps1 "(%s) ")\[\033[0;92m\]\w \[\033[0;31m\]$(__exit_code_ps1 $?)\[\033[0;15m\]\$ '
fi
На GitHub можно найти много всяких скриптов или даже целых "фремворков" типа `этого`_
или `отдельные скрипты`_ для Git. А вы знали, что скрипт для PS1 и так `поставляется`_
в пакете Git? Не вижу смысла не использовать его, если только вам не надо
как-то иначе работать с PS1.
.. _этого: https://github.com/ohmybash/oh-my-bash
.. _отдельные скрипты: https://github.com/magicmonty/bash-git-prompt
.. _поставляется: https://github.com/git/git/tree/master/contrib/completion>
Помимо **git-prompt.sh** я использую функцию ``__exit_code_ps1()``, которая просто
печатает число, если оно не равно нулю. Это очень удобно — всегда видишь код выхода
предыдущей запущенной команды, порой очень помогает при отладке скриптов.
В итоге всё это дело у меня выглядит вот так:
.. image:: https://i.nxhs.cloud/ovD.png

54
content/python_oop.rst Normal file
View File

@ -0,0 +1,54 @@
:title: Питонячье ООП на уточках
:date: 24 Jul 2021
========================
Питонячье ООП на уточках
========================
Это весьма скупая на информацию напоминалка о работе с классами. Более подробно написали на `proglib.io`_ и в `документации`_.
.. _proglib.io: https://proglib.io/p/python-oop/
.. окументации: https://docs.python.org/3/reference/compound_stmts.html#class-definitions
Создал файл ``duck.py``:
.. code-block:: python
# Объявляем класс "птица". От него в последствии будет унаследован
# класс "уточка". Здесь задаются общие характеристики для всех птиц
# и метод "летать". Аргумент `self` это ссылка на объект, в контексте
# которого вызывается метод. Она обязательна для методов классов.
class Bird(object):
can_fly = True
wings = 2
def fly(self):
print('I\'m flying!')
# Уточка это уже конкретный биологический вид (опускам породы и
# виды уточек).
# У неё есть имя и цвет (хотя цвет мог быть и у абстрактной птицы).
# Также уточка обладает уникальным методом "сказать кря".
class Duck(Bird):
name = 'Duck'
color = 'Yellow'
def say_quack(self):
print('quack!')
Как этим пользоваться:
.. code-block:: text
>>> import duck
>>> bird = duck.Bird()
>>> duck = duck.Duck()
>>> bird.fly()
I'm flying!
>>> duck.fly()
I'm flying!
>>> duck.say_quack()
quack!
>>> duck.name = 'Cool Duck'
>>> duck.name
'Cool Duck'

192
content/rst.rst Normal file
View File

@ -0,0 +1,192 @@
:title: Превью reStructuredText
:date: 5 Aug 2022
:not_a_post:
===================================
Превью *re*\ **Structured**\ *Text*
===================================
This document is the theme preview.
Sphinx provides several different types of admonitions.
.. topic:: This is a topic.
This is what admonitions are a special case of, according to the docutils
documentation.
.. admonition:: The one with the custom titles
It's got a certain charm to it.
.. attention::
Climate change is real.
.. caution::
Cliff ahead: Don't drive off it.
.. danger::
Mad scientist at work!
.. error::
Does not compute.
.. hint::
Insulators insulate, until they are subject to ______ voltage.
.. important::
Tech is not neutral, nor is it apolitical.
.. note::
This is a note.
.. tip::
25% if the service is good.
.. warning::
Reader discretion is strongly advised.
Subheading
==========
.. Press :kbd:`Ctrl+Alt+Del`.
Subsubheading
-------------
Subsububheading
```````````````
Subsubsubsubheading
'''''''''''''''''''
Subsubsubsubsubheading
~~~~~~~~~~~~~~~~~~~~~~
`Python Docs`_.
.. _Python Docs: https://docs.python.org/
The area of a circle is :math:`A_\text{c} = (\pi/4) d^2`.
.. math::
\frac{ \sum_{t=0}^{N}f(t,k) }{N}
Python code block:
.. code:: python
@app.get('/api/hello/{name}')
async def get_user_info(name: str) -> str:
return 'Hello, {}!'.format(name)
There is an ``inline literal`` and `interpreted text`
``code-block`` properties supported by Sphinx:
::
:linenos: Show line numbers
:emphasize-lines: 3,5 Highlight specific lines
------------
Bullet lists:
- This is item 1
- Sub item
- 3rd level sub item
- 4nd level
- This is item 2
- Bullets are "-", "*" or "+".
Continuing text must be aligned
after the bullet and whitespace.
Note that a blank line is required
before the first item and after the
last, but is optional between items.
Enumerated lists:
3. This is the first item
4. This is the second item
5. Enumerators are arabic numbers,
single letters, or roman numerals
6. List items should be sequentially
numbered, but need not start at 1
(although not all formatters will
honour the first index).
#. This item is auto-enumerated
Definition lists:
what
Definition lists associate a term with
a definition.
how
The term is a one-line phrase, and the
definition is one or more paragraphs or
body elements, indented relative to the
term. Blank lines are not allowed
between term and definition.
Field Lists:
:Authors:
Tony J. (Tibs) Ibbs,
David Goodger
(and sundry other good-natured folks)
:Version: 1.0 of 2001/08/08
:Dedication: To my father.
Block quotes are just:
Indented paragraphs,
and they may nest.
Grid table:
+------------+------------+-----------+
| Header 1 | Header 2 | Header 3 |
+============+============+===========+
| body row 1 | column 2 | column 3 |
+------------+------------+-----------+
| body row 2 | Cells may span columns.|
+------------+------------+-----------+
| body row 3 | Cells may | - Cells |
+------------+ span rows. | - contain |
| body row 4 | | - blocks. |
+------------+------------+-----------+
Simple table:
===== ===== ======
Inputs Output
------------ ------
A B A or B
===== ===== ======
False False False
True False True
False True True
True True True
===== ===== ======

335
content/this_blog.rst Normal file
View File

@ -0,0 +1,335 @@
:title: Как я написал этот блог
:date: 5 Aug 2022
=======================
Как я написал этот блог
=======================
Предыстория
===========
Я очень давно планировал написать блог. Именно что написать CMS для ведения
блога. Если погуглить, то CMS для этих целей сотни на разных языках с разным
позиционированием и фичами. Но мне хотелось своего.
Первые попытки создать сайт были на `Flask`_, особым успехом не увенчались,
но это была хорошая практика и я немного прокачал свой уровень программирования.
Для блога я не хотел использовать базу данных. Вместо этого я хранил статьи в
исходном Markdown, а метаданные по каждой статье писал в отдельный JSON, который
заменял мне БД. С тем же успехом я мог бы использовать SQLite, но мне нужно было
хранить контент в text/plain.
Блог даже работал, но мне хотелось сделать админку, чтобы можно было писать
прямо в браузере. На этой части разработка заглохла и я окончательно запутался в
импортах в Python)
Прошло ещё много времени, я вернулся к идее, но решил сделать ставку на простоту
и начал писать на `Bottle`_. Здесь разработка остановилась не дойдя даже до
варианта хоть как-то работающей системы. Причины скорее всего надо искать в
лени.
Устав я взял `CMS Bludit`_ и стал вести свои редкие заметки в нём. Решение не
самое плохое, но и не супер отличное. Для простой кастомизации футера пришлось
городить костыли.
.. _Flask: https://flask.palletsprojects.com/
.. _Bottle: https://bottlepy.org/
.. _CMS Bludit: https://www.bludit.com/ru/
Статика VS динамика
===================
Преимуществ у статических сайтов много. Об этом уже много написано. Мне больше
всего в статических сайтах нравится то, что:
* роутингом запросов не управляет какой-либо скрипт, я могу свободно
распоряжаться тем, что у меня есть в DocumentRoot;
* не нужно настраивать application-сервер и реверс-прокси на него.
С редактированием сайта чуть сложнее, так как сперва надо внести изменения
локально, а затем заменить изменившиеся файлы на сервере. Но и тут есть
какие-то решения.
Я рассматривал уже готовые генераторы статических сайтов, но у них всех были
фатальные недостатки:
* они сложные и требуют изучения документации чтобы начать писать;
* написать собственную тему задача весьма непростая;
* они написаны не мной.
Здесь и рождается мой велосипед, которому я не придумал названия. Буду называть
его `генератором`.
*re*\ **Structured**\ *Text*
============================
Я очень долго писал на Markdown, но в один момент понял, что возможностей языка
стало нехватать. Тут пришёлся очень кстати `Python-Markdown`_ к которому можно
было прикручивать `расширения`_. Одно даже сам `написал`_.
Постепенно я пришёл к `reStructuredText`_. Все приколюхи, которые в нём есть
существуют не за счёт расширения синтаксиса плагинами, а заложены в спецификации.
Функциональности из коробки хватает чтобы писать даже `формулы`_.
Такие вещи делаются через `роли` и `директивы`. Некоторые готовые директивы есть
в системе документации `Sphinx`_. Их я собираюсь потихоньку скопировать к себе.
Ещё одно большое преимущество перед Markdown состоит в том, что reStructuredText
поддерживает атрибуты. Вот как это выглядит:
.. code-block:: rst
:title: Как я написал этот блог
:date: 5 Aug 2022
Это нативная фича, которую можно использовать в статьях для добавления метаданных.
По сути это место, где можно сделать настройки, касающиеся отдельно взятой статьи.
Большинство генераторов статических сайтов колхозят нечно подобное в Markdown, делая
исходник статьи непригодным для парсинга другими инструментами. Это причина по
которой в старой реализации блога мне пришлось использовать JSON для метаданных.
.. _Sphinx: https://www.sphinx-doc.org/en/master/index.html
.. _Python-Markdown: https://python-markdown.github.io/
.. _расширения: https://python-markdown.github.io/extensions/
.. аписал: https://pypi.org/project/markdown-alerts/
.. _rST: https://docutils.sourceforge.io/rst.html
.. ормулы: https://docutils.sourceforge.io/docs/ref/rst/mathematics.html
Обзор
=====
Сайт состоит из следующих частей.
rst_blg.py
Непосредственно код генератора. Сейчас там всего около 200 строк без учёта
комментариев.
requirements.txt
Список зависимостей. Стараюсь держать минимум. Пока что там: `docutils`,
`jinja2`, `toml` и `pygments`.
settings.toml
Файл с настройками. Здесь можно переопределить практически всё.
Makefile
Через него запускаются команды для сборки сайта и некоторые другие. Не
является обязательным, но с ним удобнее.
layouts
Директория для шаблонов Jinja2.
assets
Директория для хранения статических файлов, будь то CSS, JS или изображения.
Всё что нужно для визуального оформления страниц. Внутренняя структура
каталога может быть произвольной.
content
Директория с исходниками статей в reStructuredText. Сюда можно также
положить любые файлы и директории.
build
В эту директорию копируются ассеты, файлы и сгенерированный HTML.
Статьи, шаблоны и ассеты могут быть оформлены абсолютно любым образом. Скрипту
безразлично что собирать. Пути и имена всех директорий можно переопределить в
settings.toml.
Написание постов
================
Тут всё предельно просто. Пишем файл и кладём в директорию `content`. В файле
должны быть указаны обязательные атрибуты ``:title:`` и ``:date:``.
Блог пока не умеет работать с вложенной структурой статей. Поэтому всё будет
свалено в кучу в корневую директорию сайта.
Все статьи добавляются в список постов и отображаются на главной странице.
Для того, чтобы сделать "отдельную" страницу, надо добавить атрибут
``:not_a_post:``.
================= ======= =========== ====================================
Атрибут Тип Умолчание Описание
================= ======= =========== ====================================
``:title:`` Строка Заголовок статьи
``:date:`` Дата Дата публикации, формат задаётся в
settings.toml
``:not_a_post:`` Флаг для одиночных страниц
================= ======= =========== ====================================
Темы оформления
===============
Никаких готовых тем. Пишем CSS вручную. Генератору сайтов всё равно что там
будет. От уровеня представления он никак не зависит. Так что можно писать любые
шаблоны и стили для них.
Отдельно можно задать тему для блоков кода. Список тем для Pygments с превью
есть на странице https://pygments.org/styles/
Чтобы поменять тему, например, на `default` надо выполнить команду:
.. code-block:: shell
make css default
# или
pygmentize -f html -S default -a .highlight > assets/css/pygments/default.css
Затем поменять значение ``theme`` в секции ``pygments`` settings.toml.
.. code-block:: toml
[pygments]
theme = 'default'
Шаблоны
========
Шаблоны можно писать какие угодно. Для этогой сайта я написал три файла.
Приведу их без лишних строк.
**base.j2**
.. code-block:: html+jinja
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="icon" href="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=">
<link rel="stylesheet" href="assets/css/pygments/{{ pygments_theme }}.css">
<link rel="stylesheet" href="assets/css/custom.css">
<title>{{ page_title }} | {{ site_title }}</title>
</head>
<body>
<header>
<p>
{% if posts %}
{{ site_title }}
{% else %}
<a href="/">{{ site_title }}</a> / {{ page_title }}</p>
{% endif %}
</p>
</header>
{% block content %}{% endblock %}
<footer>
<!-- Footer content -->
</footer>
</body>
</html>
**post.j2**
.. code-block:: html+jinja
{% extends "base.j2" %}
{% block content %}
<article>
{{ post | safe }}
<article>
{% endblock %}
**index.j2**
.. code-block:: html+jinja
{% extends "base.j2" %}
{% block content %}
<section>
<ul id="posts">
{% for post in posts %}
<li>
<a href="/{{ post['path'] }}">{{ post['title'] }}</a>
<span class="meta"> — {{ post['date'] }}</span>
</li>
{% endfor %}
</ul>
</section>
{% endblock %}
settings.toml
=============
Сначала я хотел использовать обычный INI, но мне нужно было получать из конфига
словарь. Немного подумал и выбрал TOML. Он отлично сериализируется в словарь,
визуально повторяет INI.
**settings.toml** разделён на несколько секций.
site
Данные касающиеся непосредственно сайта.
title
Название сайта
index_page_title
Заголовок главной страницы. Для всех остальных страниц заголовок
берётся из атрибута.
datatime_format
Формат даты для атрибута ``:date:``.
build
Параметры, используетмые при сборке.
build_dir
Директория, куда будет сохранён собранный сайт.
content_dir
Директория с исходниками статей.
templates_dir
Директория с шаблонами Jinja2.
assets_dir
Директория с ассетами.
pygments
Параметры подсветки синтаксиса в блоках кода.
theme
Стиль Pygments.
docutils
Конфигурация для docutils. Здесь можно указать любые параметры, которые
есть здесь: https://docutils.sourceforge.io/docs/user/config.html
Мне достаточно:
.. code-block:: toml
[docutils]
initial_header_level = 2
section_self_link = true
syntax_highlight = 'short'
Что ещё хочется сделать
=======================
В перспективе я планирую добавить следующие фичи.
- RSS
- OpenGraph
- Webmention
- Расширить возможности rST до уровня Sphinx
- Улучшить CSS
- Комментарии
- Кастомный лейаут для отдельных статей
- Поддержка вложенной структуры статей
.. * https://jinja.palletsprojects.com/en/3.0.x/templates/
* https://docutils.sourceforge.io/docs/user/config.html

View File

@ -0,0 +1,43 @@
:title: Менеджер задач в текстовом файле
:date: 2 Sep 2021
================================
Менеджер задач в текстовом файле
================================
Кажется, я нашёл почти идеальную формулу для ведения списка задач. По сути я
придумал новый формат разметки текста, специализированный для списков задач.
Придумать для него название оказалось тяжело. Приложение Todo это второе по
популярности приложение после Hello World и все хорошие названия уже давно
заняты. Поэтому пусть будет просто **.todo**.
Синтаксис выглядит таким образом
.. code-block:: text
- Uncompleted task (light blue)
+ Completed task (green)
x Rejected task (red)
# Comment
\Marked text (yellow background)\
`Code (magenta)`
Plain text
.. image:: https://i.nxhs.cloud/MQ9.png
Да, это все элементы синтаксиса. Предельно просто.
Какие есть возможности (сравниваю с тем, что предлагают обычные
todo-приложения):
- Не нужно устанавливать никакого дополнительного ПО или каждый раз открывать
громоздкий веб-интерфейс. Всё что надо это текстовый редактор. В моём случае
идеально подошёл **vim**. Написал для него `скрипт для подсветки синтаксиса`_.
При желании можно написать подсветку для других редакторов.
- Текстовая заметка и задача это одна сущность — один файл.
- Всё управление полностью с клавиатуры.
- Полная свобода включать в файл что угодно. Разумеется, текст, это не
специальный формат для встраивания изображений или других файлов, но можно
использовать элементы Markdown.
.. _скрипт для подсветки синтаксиса: https://git.nxhs.cloud/ge/todolist-syntax