Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
ef6529b9e6 | |||
865c60ceec | |||
611fb33c9d | |||
23b1ea0749 | |||
89c71daeca | |||
9aa77fcca3 | |||
0d215d0b32 | |||
65ebe2e1e3 | |||
ce94958cd5 | |||
ad91f76ff3 |
12 changed files with 1034 additions and 260 deletions
95
.drone.yml
95
.drone.yml
|
@ -17,7 +17,7 @@ steps:
|
|||
when:
|
||||
event: push
|
||||
branch:
|
||||
- develop
|
||||
- master
|
||||
- testing
|
||||
|
||||
- name: "Test: Build docker image"
|
||||
|
@ -34,96 +34,5 @@ steps:
|
|||
when:
|
||||
event: push
|
||||
branch:
|
||||
- develop
|
||||
- master
|
||||
- testing
|
||||
|
||||
- name: "Test: Deploy docker image"
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: daemons.it
|
||||
username: drone
|
||||
port: 6699
|
||||
key:
|
||||
from_secret: ssh_key
|
||||
script:
|
||||
- sudo docker pull registry.daemons.it/baddaemons:testing
|
||||
- sudo systemctl restart docker-hugo-test
|
||||
script_stop: true
|
||||
when:
|
||||
event: push
|
||||
branch:
|
||||
- develop
|
||||
- testing
|
||||
|
||||
- name: "Test: Test page"
|
||||
image: wjdp/htmltest
|
||||
commands:
|
||||
- htmltest -c .htmltest.yml
|
||||
when:
|
||||
event: push
|
||||
branch:
|
||||
- develop
|
||||
- testing
|
||||
|
||||
- name: "Main: Clean"
|
||||
image: alpine
|
||||
commands:
|
||||
- rm -r public
|
||||
when:
|
||||
event: push
|
||||
branch: develop
|
||||
|
||||
- name: "Main: Build web"
|
||||
image: plugins/hugo
|
||||
settings:
|
||||
hugo_version: 0.74.3
|
||||
url: https://daemons.it
|
||||
validate: true
|
||||
when:
|
||||
event: push
|
||||
branch: develop
|
||||
|
||||
- name: "Main: Build docker image"
|
||||
image: banzaicloud/drone-kaniko
|
||||
settings:
|
||||
username:
|
||||
from_secret: docker_user
|
||||
password:
|
||||
from_secret: docker_password
|
||||
repo: baddaemons
|
||||
registry:
|
||||
from_secret: docker_registry
|
||||
tags: latest
|
||||
when:
|
||||
event: push
|
||||
branch: develop
|
||||
|
||||
- name: "Main: Deploy docker image"
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: daemons.it
|
||||
username: drone
|
||||
port: 6699
|
||||
key:
|
||||
from_secret: ssh_key
|
||||
script:
|
||||
- sudo docker pull registry.daemons.it/baddaemons:latest
|
||||
- sudo systemctl restart docker-hugo
|
||||
script_stop: true
|
||||
when:
|
||||
event: push
|
||||
branch: develop
|
||||
|
||||
- name: Notify
|
||||
image: registry.daemons.it/drone-xmpp
|
||||
environment:
|
||||
XMPP_USER:
|
||||
from_secret: xmpp_user
|
||||
XMPP_PASSWORD:
|
||||
from_secret: xmpp_password
|
||||
XMPP_ROOM:
|
||||
from_secret: xmpp_room
|
||||
PLUGIN_MESSAGE: "Beep, boop, I'm a bot. The CI job finished: {build_status}\n- Job url: {build_link}"
|
||||
when:
|
||||
status: [success, failure]
|
||||
event: push
|
||||
|
|
|
@ -6,8 +6,6 @@ theme:
|
|||
- "after-dark"
|
||||
|
||||
pygmentsUseClasses: true
|
||||
pygmentsCodeFences: true
|
||||
pygmentsStyle: "monokai"
|
||||
|
||||
postNavigation: true
|
||||
permalinks:
|
||||
|
|
|
@ -6827,3 +6827,84 @@ if err != nil {
|
|||
Se lo enseñe a [[https://gnusocial.net/ameba][Ameba]] y como cualquier persona con ojos, se sintió muy ofendida por el "diseño". Por ello, hizo una primera implementación de [[https://bulma.io/][bulma]], un framework CSS como lo es bootstrap. Viendo que se habia tomado la molestia, por sentido de la vergüenza y por que en realidad soy consciente de que la UX es importante, decidí terminar de implementarlo (con mucha ayuda) y aprender bastante de conceptos básicos de html, css y js, que siempre voy muy pez. Y ha quedado algo más cuqui, como se puede ver en la primera imagen.
|
||||
|
||||
Poco más que añadir. Go me parece un lenguaje interesante y probablemente siga aprendiendo porque hace ya tiempo que quiero tener algún otro lenguaje a parte de python. Es improbable que Gomic reciba muchas más actualizaciones más allá de añadir más orígenes, pero cualquier sugerencia siempre será bienvenida.
|
||||
|
||||
|
||||
* DONE Estandarizar commits en Magit con commitizen :magit:emacs:git:
|
||||
:PROPERTIES:
|
||||
:EXPORT_FILE_NAME: estandarizar-commits-en-magit-con-commitizen
|
||||
:ARCHIVE_TIME: 2020-08-27 Thu 20:50
|
||||
:ARCHIVE_FILE: ~/.syncthing/Casa/Proyectos/BadDaemons/content-org/articulos.org
|
||||
:ARCHIVE_CATEGORY: articulos
|
||||
:END:
|
||||
Quién trabaje o contribuya a proyectos de software con otras personas sabrá que a veces el tiempo se va discutiendo chorradas. Un ejemplo típico son las convenciones del código.
|
||||
|
||||
Por ejemplo, en python lineas más largas de 79 carácteres (como el pep8 define) o más (ya que no estamos en los 90 y tenemos pantallas de más de 8 pulgadas)? Una lista debería estar en una sola línea o en varias?
|
||||
|
||||
Para la mayor parte de los casos no hay respuesta correcta, por que es cuestión de gustos. Por ello, ya hace un tiempo que decidí que paso de dedicar mi tiempo a esto y que otra persona decida por mi. En el caso de los ejemplos anteriores he decidido que sea [[https://github.com/psf/black][black]] quien decida como hacer las cosas. Pero yendo al articulo, he decidido que quién se encargue del formato de mis commits sea [[https://commitizen-tools.github.io/commitizen/][commitizen]].
|
||||
|
||||
Alredor del formato de los commits hay mucha historia. Lo idóneo es poner el tipo de cambio, el alcance de este, un título que resuma el cambio, un cuerpo con una explicación más profunda si hace falta y un ticket del gestor de tareas que uses. De esta forma es más fácil ver como evoluciona el código y la lógica que hay detrás. Tiene un añadido y es que si los commits tienen el mismo formato, se pueden generar changelogs de forma automática.
|
||||
|
||||
Meter toda esta información no es fácil. Para ello está [[https://commitizen-tools.github.io/commitizen/][commitizen]]. Esta herramienta da lo siguiente:
|
||||
- [[https://www.conventionalcommits.org/en/v1.0.0/][Implementar una convencion de commits]]
|
||||
- [[https://semver.org/][Gestión de versiones semántica]]
|
||||
- [[https://keepachangelog.com/en/1.0.0/][Crear un changelog]]
|
||||
|
||||
=cz= es un plugin de git. En vez de usar `git commit` lo que hay que hacer es usar =git cz= y te hace una serie de preguntas que ayudarán a generar el mensaje. Se puede ver un ejemplo en esta imagen:
|
||||
|
||||
[[/img/commitizen.gif]]
|
||||
|
||||
Pero esta es una herramienta para la terminal, y teniendo emacs, la terminal está obsoleta. Así que veamos como usar esto en Magit. Lo idóneo sería llamar a =git cz= directamente, ya que aunque =cz= define las convenciones, estas se pueden cambiar por proyecto, por lo que generar una plantilla para el commit sin más puede no cubrir todos los casos. Estuve investigando cómo hacerlo pero tendría que haberme metido mucho más en la madriguera del conejo de lo que ya he hecho, por lo que decidí ir a por una solución de compromiso.
|
||||
|
||||
Por un lado, hice una plantilla para magit. Esto me servirá para la mayoría de los casos. Pero para cuando no, tengo una función que me deja hacer el commit desde emacs. No usa magit, lo cual es una pena, pero para el caso valdrá. Veamos ambas opciones.
|
||||
|
||||
He creado una función que usa [[https://github.com/joaotavora/yasnippet][yasnippet]], un sistema de plantillas. Luego se añade esa función al hook del git-commit y de esta forma cada vez que se haga un commit, se llama a la función:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(defun daemons/commitizen-template()
|
||||
"Expand a commitizen template."
|
||||
(yas-expand-snippet "${1:Select the type of change you are committing: $$(yas-choose-value '(\"fix\" \"feat\" \"docs\" \"style\" \"refactor\" \"perf\" \"test\" \"build\" \"ci\"))}(${2:Scope. Could be anything specifying place of the commit change (users, db, poll): )}): ${3:Subject. Concise description of the changes. Imperative, lower case and no final dot}
|
||||
|
||||
${4:Body. Motivation for the change and contrast this with previous behavior}
|
||||
|
||||
${5:Footer. Information about Breaking Changes and reference issues that this commit closes}"))
|
||||
|
||||
(add-hook 'git-commit-setup-hook #'daemons/commitizen-template)
|
||||
#+END_SRC
|
||||
|
||||
Para llamar a =cz= directamente he usado una función bonica que encontré en reddit (la fuente está en la función) que en resumen usa [[https://github.com/akermu/emacs-libvterm][vterm]] para lanzar una orden arbitrária. Creé la función chorra que llama a esa función con =cz= y ya está.
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(defun phalp/run-in-vterm (command)
|
||||
"Execute string COMMAND in a new vterm.
|
||||
|
||||
From: https://www.reddit.com/r/emacs/comments/ft84xy/run_shell_command_in_new_vterm/
|
||||
|
||||
Interactively, prompt for COMMAND with the current buffer's file
|
||||
name supplied. When called from Dired, supply the name of the
|
||||
file at point.
|
||||
|
||||
Like `async-shell-command`, but run in a vterm for full terminal features.
|
||||
|
||||
The new vterm buffer is named in the form `*foo bar.baz*`, the
|
||||
command and its arguments in earmuffs.
|
||||
|
||||
When the command terminates, the shell remains open, but when the
|
||||
shell exits, the buffer is killed."
|
||||
(interactive
|
||||
(list
|
||||
(let* ((f (cond (buffer-file-name)
|
||||
((eq major-mode 'dired-mode)
|
||||
(dired-get-filename nil t))))
|
||||
(filename (concat " " (shell-quote-argument (and f (file-relative-name f))))))
|
||||
(read-shell-command "Terminal command: "
|
||||
(cons filename 0)
|
||||
(cons 'shell-command-history 1)
|
||||
(list filename)))))
|
||||
(with-current-buffer (vterm (concat "*" command "*"))
|
||||
(vterm-send-string command)
|
||||
(vterm-send-return)))
|
||||
|
||||
(defun daemons/commitizen-gz() (interactive) (phalp/run-in-vterm "git cz commit; exit"))
|
||||
#+END_SRC
|
||||
|
||||
Tiene pinta de que no integraré nunca magit con =cz= dada su dificultad, por lo que probablemente vaya creando plantillas para los commits según el proyecto y buscaré alguna forma de que use una plantilla u otra según el directorio en el que esté. Aún así molaria ver =cz= integrado.
|
||||
|
|
|
@ -4,6 +4,87 @@ author = ["drymer"]
|
|||
draft = false
|
||||
+++
|
||||
|
||||
<div class="ox-hugo-toc toc">
|
||||
<div></div>
|
||||
|
||||
<div class="heading">Índice</div>
|
||||
|
||||
- [Tabla de contenido](#tabla-de-contenido):TOC_5_org:
|
||||
- [Acerca de este documento](#acerca-de-este-documento)
|
||||
- [Configurar el init.el](#configurar-el-init-dot-el)
|
||||
- [Configurar el bind léxico](#configurar-el-bind-léxico)
|
||||
- [Hacer más usable ivy](#hacer-más-usable-ivy)
|
||||
- [Hacer más usable evil](#hacer-más-usable-evil)
|
||||
- [Configuración principal de doom](#configuración-principal-de-doom)
|
||||
- [Configuración Genérica](#configuración-genérica)
|
||||
- [Seguridad de las conexiones](#seguridad-de-las-conexiones)
|
||||
- [Moverse por el buffer](#moverse-por-el-buffer)
|
||||
- [Establecer nombre y correo](#establecer-nombre-y-correo)
|
||||
- [Lenguaje por defecto en emacs y org-mode](#lenguaje-por-defecto-en-emacs-y-org-mode)
|
||||
- [No seguir enlaces simbólicos](#no-seguir-enlaces-simbólicos)
|
||||
- [Terminal](#terminal)
|
||||
- [kill-this-buffer en vez de kill-buffer](#kill-this-buffer-en-vez-de-kill-buffer)
|
||||
- [Ispell](#ispell)
|
||||
- [Tipo de fuente](#tipo-de-fuente)
|
||||
- [Tema](#tema)
|
||||
- [Kill-ring-max](#kill-ring-max)
|
||||
- [url accionables](#url-accionables)
|
||||
- [Expander el PATH](#expander-el-path)
|
||||
- [org-mode](#org-mode)
|
||||
- [Agenda](#agenda)
|
||||
- [Definir archivos de la agenda](#definir-archivos-de-la-agenda)
|
||||
- [Comandos de Agenda](#comandos-de-agenda)
|
||||
- [Capturas de notas](#capturas-de-notas)
|
||||
- [Estados de los objetos de las listas](#estados-de-los-objetos-de-las-listas)
|
||||
- [Refile](#refile)
|
||||
- [Configuración del calendario](#configuración-del-calendario)
|
||||
- [Tareas repetitivas](#tareas-repetitivas)
|
||||
- [Quitar tags de la agenda](#quitar-tags-de-la-agenda)
|
||||
- [Alargar el historial del reloj](#alargar-el-historial-del-reloj)
|
||||
- [Mostrar los clockin en la agenda](#mostrar-los-clockin-en-la-agenda)
|
||||
- [Añadir timestamp al terminar tarea](#añadir-timestamp-al-terminar-tarea)
|
||||
- [Archivado](#archivado)
|
||||
- [org-super-agenda](#org-super-agenda)
|
||||
- [punch-in y punch-out](#punch-in-y-punch-out)
|
||||
- [Desactivar festivos](#desactivar-festivos)
|
||||
- [org-clock-convenience](#org-clock-convenience)
|
||||
- [Edición, diseño y varios](#edición-diseño-y-varios)
|
||||
- [Mostrar horas en vez dias](#mostrar-horas-en-vez-dias)
|
||||
- [org-mru-clock](#org-mru-clock)
|
||||
- [Mapear org-cycle](#mapear-org-cycle)
|
||||
- [Mostrar solo las cabeceras](#mostrar-solo-las-cabeceras)
|
||||
- [org-superstar](#org-superstar)
|
||||
- [Asignar keybinds](#asignar-keybinds)
|
||||
- [Misc](#misc)
|
||||
- [Flycheck](#flycheck)
|
||||
- [elisp](#elisp)
|
||||
- [package-lint](#package-lint)
|
||||
- [python](#python)
|
||||
- [Javascript](#javascript)
|
||||
- [compile-mode](#compile-mode)
|
||||
- [ivy-mode / counsel-mode / swipper-mode](#ivy-mode-counsel-mode-swipper-mode)
|
||||
- [undo-tree](#undo-tree)
|
||||
- [go-mode](#go-mode)
|
||||
- [hl-todo](#hl-todo)
|
||||
- [magit-mode](#magit-mode)
|
||||
- [Plantilla en magit](#plantilla-en-magit)
|
||||
- [Abrir cz en una terminal](#abrir-cz-en-una-terminal)
|
||||
- [vterm-mode](#vterm-mode)
|
||||
- [evil-hardcore-mode](#evil-hardcore-mode)
|
||||
- [Cambiar atajos de doom](#cambiar-atajos-de-doom)
|
||||
- [Deshabilitar numeros en los laterales](#deshabilitar-numeros-en-los-laterales)
|
||||
- [Insertar fechas](#insertar-fechas)
|
||||
- [Documentación](#documentación)
|
||||
- [Popups](#popups)
|
||||
- [En progreso / Pendiente](#en-progreso-pendiente)
|
||||
- [molecule](#molecule)
|
||||
- [Autenticación para terraform](#autenticación-para-terraform)
|
||||
|
||||
</div>
|
||||
<!--endtoc-->
|
||||
|
||||
|
||||
|
||||
## Tabla de contenido {#tabla-de-contenido}
|
||||
|
||||
- [Acerca de este documento](#acerca-de-este-documento)
|
||||
|
@ -25,6 +106,7 @@ draft = false
|
|||
- [Tema](#tema)
|
||||
- [Kill-ring-max](#kill-ring-max)
|
||||
- [url accionables](#url-accionables)
|
||||
- [Expander el PATH](#expander-el-path)
|
||||
- [org-mode](#org-mode)
|
||||
- [Agenda](#agenda)
|
||||
- [Definir archivos de la agenda](#definir-archivos-de-la-agenda)
|
||||
|
@ -45,35 +127,37 @@ draft = false
|
|||
- [org-clock-convenience](#org-clock-convenience)
|
||||
- [Edición, diseño y varios](#edición-diseño-y-varios)
|
||||
- [Mostrar horas en vez dias](#mostrar-horas-en-vez-dias)
|
||||
- [Mostrar popups de org-mode más grandes](#mostrar-popups-de-org-mode-más-grandes)
|
||||
- [org-mru-clock](#org-mru-clock)
|
||||
- [Mapear org-cycle](#mapear-org-cycle)
|
||||
- [Mostrar solo las cabeceras](#mostrar-solo-las-cabeceras)
|
||||
- [org-superstar](#org-superstar)
|
||||
- [Asignar keybinds](#asignar-keybinds)
|
||||
- [Misc](#misc)
|
||||
- [Flycheck](#flycheck)
|
||||
- [elisp](#elisp)
|
||||
- [package-lint](#package-lint)
|
||||
- [python-mode](#python-mode)
|
||||
- [python](#python)
|
||||
- [Javascript](#javascript)
|
||||
- [compile-mode](#compile-mode)
|
||||
- [ivy-mode / counsel-mode / swipper-mode](#ivy-mode-counsel-mode-swipper-mode)
|
||||
- [counsel-rg](#counsel-rg)
|
||||
- [undo-tree](#undo-tree)
|
||||
- [docker](#docker)
|
||||
- [go-mode](#go-mode)
|
||||
- [hl-todo](#hl-todo)
|
||||
- [vue-mode](#vue-mode)
|
||||
- [magit-mode](#magit-mode)
|
||||
- [Plantilla en magit](#plantilla-en-magit)
|
||||
- [Abrir cz en una terminal](#abrir-cz-en-una-terminal)
|
||||
- [vterm-mode](#vterm-mode)
|
||||
- [evil-hardcore-mode](#evil-hardcore-mode)
|
||||
- [Cambiar atajos de doom](#cambiar-atajos-de-doom)
|
||||
- [Hacer gifs con camcorder.el](#hacer-gifs-con-camcorder-dot-el)
|
||||
- [Deshabilitar numeros en los laterales](#deshabilitar-numeros-en-los-laterales)
|
||||
- [Insertar fechas](#insertar-fechas)
|
||||
- [Documentación](#documentación)
|
||||
- [Popups](#popups)
|
||||
- [En progreso / Pendiente](#en-progreso-pendiente)
|
||||
- [molecule](#molecule)
|
||||
- [Autenticación para terraform](#autenticación-para-terraform)
|
||||
|
||||
|
||||
## Acerca de este documento {#acerca-de-este-documento}
|
||||
|
||||
Este documento está hecho en org-mode y es tanto mi configuración de emacs como la explicación de esta.
|
||||
|
@ -84,8 +168,10 @@ Uso [doom](https://github.com/hlissner/doom-emacs/), que es una configuración "
|
|||
|
||||
Para usar esta configuración tal cual sólo hay que clonar el repositorio en `~/.doom.d/config.org` y seguir las instrucciones habituales de `doom`.
|
||||
|
||||
|
||||
## Configurar el init.el {#configurar-el-init-dot-el}
|
||||
|
||||
|
||||
### Configurar el bind léxico {#configurar-el-bind-léxico}
|
||||
|
||||
La verdad es que no termino de entender que es ni por que es bueno usarlo. En la [wiki de emacs](https://www.emacswiki.org/emacs/DynamicBindingVsLexicalBinding) lo explican muy bien, pero doy para lo que doy.
|
||||
|
@ -94,6 +180,7 @@ La verdad es que no termino de entender que es ni por que es bueno usarlo. En la
|
|||
;;; init.el -*- lexical-binding: t; -*-
|
||||
```
|
||||
|
||||
|
||||
### Hacer más usable ivy {#hacer-más-usable-ivy}
|
||||
|
||||
FLX ordena los resultados de `M-x` de acorde al último usado.
|
||||
|
@ -111,6 +198,7 @@ FLX ordena los resultados de `M-x` de acorde al último usado.
|
|||
ivy-initial-inputs-alist nil))
|
||||
```
|
||||
|
||||
|
||||
### Hacer más usable evil {#hacer-más-usable-evil}
|
||||
|
||||
```elisp
|
||||
|
@ -121,27 +209,25 @@ FLX ordena los resultados de `M-x` de acorde al último usado.
|
|||
(setq evil-want-fine-undo t))
|
||||
```
|
||||
|
||||
|
||||
### Configuración principal de doom {#configuración-principal-de-doom}
|
||||
|
||||
Aquí es donde se define toda la configuración que **no** se modificará en este documento. Se puede ver información de estos módulos en la [documentación de doom](https://github.com/hlissner/doom-emacs/blob/develop/docs/modules.org).
|
||||
|
||||
```elisp
|
||||
(doom! :completion
|
||||
(company +childframe )
|
||||
(company +childframe)
|
||||
(ivy +fuzzy +icons)
|
||||
|
||||
:tools
|
||||
(magit +forge)
|
||||
pass
|
||||
pdf
|
||||
make
|
||||
ansible
|
||||
(docker +lsp)
|
||||
(terraform +lsp)
|
||||
terraform
|
||||
(lsp +peek)
|
||||
eval
|
||||
debugger
|
||||
(lookup +docsets +dictionary)
|
||||
(lookup +docsets +dictionary +offline)
|
||||
(eval +overlay)
|
||||
|
||||
:checkers
|
||||
|
@ -161,7 +247,7 @@ Aquí es donde se define toda la configuración que **no** se modificará en est
|
|||
:lang
|
||||
data
|
||||
emacs-lisp
|
||||
java
|
||||
(java +lsp)
|
||||
markdown
|
||||
php
|
||||
ruby
|
||||
|
@ -170,20 +256,20 @@ Aquí es donde se define toda la configuración que **no** se modificará en est
|
|||
(sh +lsp)
|
||||
(go +lsp)
|
||||
(python +lsp)
|
||||
(org +brain +pretty +hugo)
|
||||
(org +brain +hugo +roam +dragndrop)
|
||||
(java +lsp)
|
||||
(json +lsp)
|
||||
(yaml +lsp)
|
||||
(yaml)
|
||||
|
||||
:app
|
||||
calendar
|
||||
everywhere
|
||||
|
||||
:editor
|
||||
(evil +everywhere)
|
||||
multiple-cursors
|
||||
snippets
|
||||
file-templates
|
||||
(format +onsave)
|
||||
format
|
||||
fold
|
||||
word-wrap
|
||||
|
||||
|
@ -192,11 +278,12 @@ Aquí es donde se define toda la configuración que **no** se modificará en est
|
|||
(default +bindings +smartparens)
|
||||
|
||||
:ui
|
||||
treemacs
|
||||
doom
|
||||
doom-dashboard
|
||||
modeline
|
||||
doom-quit
|
||||
(popup +all +defaults +hacks)
|
||||
(popup +all +defaults)
|
||||
hl-todo
|
||||
nav-flash
|
||||
unicode
|
||||
|
@ -204,18 +291,21 @@ Aquí es donde se define toda la configuración que **no** se modificará en est
|
|||
vc-gutter
|
||||
workspaces
|
||||
ophints
|
||||
fill-column
|
||||
)
|
||||
(emoji +ascii +github +unicode)
|
||||
hydra)
|
||||
```
|
||||
|
||||
|
||||
## Configuración Genérica {#configuración-genérica}
|
||||
|
||||
|
||||
### Seguridad de las conexiones {#seguridad-de-las-conexiones}
|
||||
|
||||
```elisp
|
||||
(setq network-security-level 'high)
|
||||
```
|
||||
|
||||
|
||||
### Moverse por el buffer {#moverse-por-el-buffer}
|
||||
|
||||
Subir y bajar párrafos:
|
||||
|
@ -225,6 +315,7 @@ Subir y bajar párrafos:
|
|||
:ne "M-n" 'forward-paragraph)
|
||||
```
|
||||
|
||||
|
||||
### Establecer nombre y correo {#establecer-nombre-y-correo}
|
||||
|
||||
Al exportar en org-mode, por ejemplo, coge estos valores.
|
||||
|
@ -234,6 +325,7 @@ Al exportar en org-mode, por ejemplo, coge estos valores.
|
|||
user-mail-address "drymer [ EN ] autistici.org")
|
||||
```
|
||||
|
||||
|
||||
### Lenguaje por defecto en emacs y org-mode {#lenguaje-por-defecto-en-emacs-y-org-mode}
|
||||
|
||||
```elisp
|
||||
|
@ -241,12 +333,14 @@ Al exportar en org-mode, por ejemplo, coge estos valores.
|
|||
(setq org-export-default-language "es")
|
||||
```
|
||||
|
||||
|
||||
### No seguir enlaces simbólicos {#no-seguir-enlaces-simbólicos}
|
||||
|
||||
```elisp
|
||||
(setq vc-follow-symlinks nil)
|
||||
```
|
||||
|
||||
|
||||
### Terminal {#terminal}
|
||||
|
||||
Establecer zsh como shell por defecto, aunque no lo uso demasiado.
|
||||
|
@ -258,6 +352,7 @@ Establecer zsh como shell por defecto, aunque no lo uso demasiado.
|
|||
(add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m)
|
||||
```
|
||||
|
||||
|
||||
### kill-this-buffer en vez de kill-buffer {#kill-this-buffer-en-vez-de-kill-buffer}
|
||||
|
||||
No quiero que me pregunte si de verdad quiero matar un buffer, quiero que lo mate y punto.
|
||||
|
@ -268,6 +363,7 @@ No quiero que me pregunte si de verdad quiero matar un buffer, quiero que lo mat
|
|||
|
||||
Fuente: <http://pragmaticemacs.com/emacs/dont-kill-buffer-kill-this-buffer-instead/>
|
||||
|
||||
|
||||
### Ispell {#ispell}
|
||||
|
||||
Instalamos el diccionario de [esta dirección](https://www.cs.hmc.edu/~geoff/ispell-dictionaries.html#Spanish-dicts) y configuramos emacs para que lo use:
|
||||
|
@ -276,18 +372,21 @@ Instalamos el diccionario de [esta dirección](https://www.cs.hmc.edu/~geoff/isp
|
|||
(setq ispell-dictionary "espanol")
|
||||
```
|
||||
|
||||
|
||||
### Tipo de fuente {#tipo-de-fuente}
|
||||
|
||||
```elisp
|
||||
(setq doom-font (font-spec :family "DejaVu Sans Mono" :height 107))
|
||||
```
|
||||
|
||||
|
||||
### Tema {#tema}
|
||||
|
||||
```elisp
|
||||
(setq doom-theme 'doom-molokai)
|
||||
```
|
||||
|
||||
|
||||
### Kill-ring-max {#kill-ring-max}
|
||||
|
||||
```elisp
|
||||
|
@ -296,6 +395,7 @@ Instalamos el diccionario de [esta dirección](https://www.cs.hmc.edu/~geoff/isp
|
|||
|
||||
Fuente: <http://puntoblogspot.blogspot.com/2018/10/kill-ring-max-is-thing.html?m=1>
|
||||
|
||||
|
||||
### url accionables {#url-accionables}
|
||||
|
||||
```elisp
|
||||
|
@ -311,22 +411,34 @@ Fuente: <http://puntoblogspot.blogspot.com/2018/10/kill-ring-max-is-thing.html?m
|
|||
goto-address-mode))
|
||||
```
|
||||
|
||||
|
||||
### Expander el PATH {#expander-el-path}
|
||||
|
||||
```elisp
|
||||
(add-to-list 'exec-path (concat (getenv "HOME") "/.bin/"))
|
||||
(add-to-list 'exec-path "/opt/go/bin")
|
||||
(add-to-list 'exec-path "/opt/brew/bin")
|
||||
```
|
||||
|
||||
|
||||
## org-mode {#org-mode}
|
||||
|
||||
org-mode merece tener la configuración a parte. Ahí va.
|
||||
|
||||
|
||||
### Agenda {#agenda}
|
||||
|
||||
|
||||
#### Definir archivos de la agenda {#definir-archivos-de-la-agenda}
|
||||
|
||||
```elisp
|
||||
(setq org-agenda-files '("~/Documentos/org/inbox.org" "~/Documentos/org/trabajo.org" "~/Documentos/org/index.org" "~/Documentos/org/casa.org"))
|
||||
```
|
||||
|
||||
|
||||
#### Comandos de Agenda {#comandos-de-agenda}
|
||||
|
||||
<a id="code-snippet--custom-commands"></a>
|
||||
|
||||
```elisp
|
||||
(after! org-super-agenda
|
||||
(setq org-agenda-custom-commands
|
||||
|
@ -514,10 +626,12 @@ Referencias:
|
|||
|
||||
- <http://orgmode.org/worg/org-tutorials/advanced-searching.html>
|
||||
|
||||
|
||||
#### Capturas de notas {#capturas-de-notas}
|
||||
|
||||
```elisp
|
||||
(setq org-capture-templates
|
||||
(after! org
|
||||
(setq org-capture-templates
|
||||
'(
|
||||
("r" "Reuniones" entry (file "~/Documentos/org/inbox.org")
|
||||
(file "~/.doom.d/org-capture-templates/reuniones.org")
|
||||
|
@ -554,11 +668,22 @@ Referencias:
|
|||
("m" "Captura desde correo" entry (file "~/Documentos/org/inbox.org") "* %? %^G\n%U\n%a\n" :clock-in t :clock-resume t)
|
||||
("log" "Log" entry (file+olp+datetree "~/Documentos/org/log.org" "Log")
|
||||
(file "~/.doom.d/org-capture-templates/log.org") :time-prompt t)
|
||||
("L" "Protocol Link" entry (file+headline ,(concat org-directory "notes.org") "Inbox")
|
||||
"* %? [[%:link][%:description]] \nCaptured On: %U") ("p" "Protocol" entry (file+headline "~/Documentos/org/inbox.org" "Links")
|
||||
"* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?")
|
||||
|
||||
// La funcion falla
|
||||
("roam" "roam" entry (file ,(concat "~/org/roam/" (daemons/insert-current-date-and-time) "-%:description.org"))
|
||||
|
||||
"#+TITLE: %^{Title}\n#+roam_tags:\n- contexto ::\n- referencias ::\n\n%?"
|
||||
)
|
||||
|
||||
("b" "Articulo" entry (file "~/Proyectos/BadDaemons/content-org/articulos.org")
|
||||
"* TODO %(read-string \"Insert title: \")\n:PROPERTIES:\n:EXPORT_FILE_NAME: %(org-hugo-slug (nth 4 (org-heading-components)))\n:END:")))
|
||||
|
||||
(setq org-roam-ref-capture-templates '(("d" "default" plain (function org-roam--capture-get-point)
|
||||
"#+TITLE: ${title}\n#+roam_tags:\n- contexto ::\n- referencias ::\n\n%?"
|
||||
:file-name "%<%Y%m%d%H%M%S>-${slug}"
|
||||
:unnarrowed t)))
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Referencias:
|
||||
|
@ -572,6 +697,7 @@ Capturar interrupciones rapidamente:
|
|||
(map! :ne "<f12>" (lambda () (interactive) (org-capture nil "a")))
|
||||
```
|
||||
|
||||
|
||||
#### Estados de los objetos de las listas {#estados-de-los-objetos-de-las-listas}
|
||||
|
||||
Todas las secuencias anteriores al símbolo `|` son tareas que no se consideran terminadas, al contrario de las que estan después de este.
|
||||
|
@ -583,12 +709,14 @@ Los estados que tienen el símbolo `@` son los que, al escogerlos, abren un buff
|
|||
'((sequence "TODO(t)" "NEXT(n)" "INPROGRESS(p@/!)" "WAITING(w@/!)" "|" "DONE(d!)" "CANCELED(c@)")))
|
||||
```
|
||||
|
||||
|
||||
#### Refile {#refile}
|
||||
|
||||
Mover un arbol debajo de otro del mismo fichero o de los archivos de las agendas.
|
||||
|
||||
```elisp
|
||||
(setq org-refile-targets '((nil :maxlevel . 10) (org-agenda-files . (:maxlevel . 10))))
|
||||
(after! org
|
||||
(setq org-refile-targets '((nil :maxlevel . 10) (org-agenda-files . (:maxlevel . 10)))))
|
||||
```
|
||||
|
||||
Crear nodo si no existe:
|
||||
|
@ -600,12 +728,14 @@ Crear nodo si no existe:
|
|||
(setq org-refile-allow-creating-parent-nodes t)
|
||||
```
|
||||
|
||||
|
||||
#### Configuración del calendario {#configuración-del-calendario}
|
||||
|
||||
```elisp
|
||||
(setq org-icalendar-timezone "Europe/Madrid")
|
||||
```
|
||||
|
||||
|
||||
#### Tareas repetitivas {#tareas-repetitivas}
|
||||
|
||||
Las tareas marcadas para repetirse, al marcarlas cómo DONE vuelven al estado TODO y añade un timestamp del dia y la hora.
|
||||
|
@ -614,36 +744,42 @@ Las tareas marcadas para repetirse, al marcarlas cómo DONE vuelven al estado TO
|
|||
(setq org-log-repeat "time")
|
||||
```
|
||||
|
||||
|
||||
#### Quitar tags de la agenda {#quitar-tags-de-la-agenda}
|
||||
|
||||
```elisp
|
||||
(setq org-agenda-remove-tags t)
|
||||
```
|
||||
|
||||
|
||||
#### Alargar el historial del reloj {#alargar-el-historial-del-reloj}
|
||||
|
||||
```elisp
|
||||
(setq org-clock-history-length 60)
|
||||
```
|
||||
|
||||
|
||||
#### Mostrar los clockin en la agenda {#mostrar-los-clockin-en-la-agenda}
|
||||
|
||||
```elisp
|
||||
(setq org-agenda-clock-consistency-checks t)
|
||||
```
|
||||
|
||||
|
||||
#### Añadir timestamp al terminar tarea {#añadir-timestamp-al-terminar-tarea}
|
||||
|
||||
```elisp
|
||||
(setq org-log-done 'time)
|
||||
```
|
||||
|
||||
|
||||
#### Archivado {#archivado}
|
||||
|
||||
```elisp
|
||||
(setq org-archive-mark-done t)
|
||||
```
|
||||
|
||||
|
||||
#### org-super-agenda {#org-super-agenda}
|
||||
|
||||
```elisp
|
||||
|
@ -654,6 +790,7 @@ Las tareas marcadas para repetirse, al marcarlas cómo DONE vuelven al estado TO
|
|||
(use-package! org-super-agenda :config (org-super-agenda-mode))
|
||||
```
|
||||
|
||||
|
||||
#### punch-in y punch-out {#punch-in-y-punch-out}
|
||||
|
||||
Estas funciones tan útiles las he cogido de eof. Las funciones principales son `eos/punch-in` y `eos/punch-out`. La primera va a una tarea genérica que tengo en el fichero principal del trabajo y empieza el reloj. Después de hacer eso, cuando quiera, podré arrancar el reloj en la tarea que considere. Cuando acabe esta y pare el reloj, gracias a la función de punch-in, en vez de quedarme sin contabilizar el tiempo, el reloj se encenderá en la tarea genérica. Cuando termino, le doy a punch-out y se para el reloj definitivamente.
|
||||
|
@ -813,12 +950,14 @@ subprojects from INPROGRESS back to TODO"
|
|||
(and is-a-task has-subtask))))
|
||||
```
|
||||
|
||||
|
||||
#### Desactivar festivos {#desactivar-festivos}
|
||||
|
||||
```elisp
|
||||
(setq calendar-holidays nil)
|
||||
```
|
||||
|
||||
|
||||
#### org-clock-convenience {#org-clock-convenience}
|
||||
|
||||
```elisp
|
||||
|
@ -842,19 +981,16 @@ subprojects from INPROGRESS back to TODO"
|
|||
(add-hook 'org-agenda-mode-hook #'dfeich/org-agenda-mode-fn))
|
||||
```
|
||||
|
||||
|
||||
### Edición, diseño y varios {#edición-diseño-y-varios}
|
||||
|
||||
|
||||
#### Mostrar horas en vez dias {#mostrar-horas-en-vez-dias}
|
||||
|
||||
```elisp
|
||||
(setq org-duration-format 'h:mm)
|
||||
```
|
||||
|
||||
#### Mostrar popups de org-mode más grandes {#mostrar-popups-de-org-mode-más-grandes}
|
||||
|
||||
```elisp
|
||||
(set-popup-rule! "agenda" :size 0.50 :select t)
|
||||
```
|
||||
|
||||
#### org-mru-clock {#org-mru-clock}
|
||||
|
||||
|
@ -882,6 +1018,7 @@ subprojects from INPROGRESS back to TODO"
|
|||
:desc "Clock select recent" :nv "j" #'org-mru-clock-select-recent-task))))
|
||||
```
|
||||
|
||||
|
||||
#### Mapear org-cycle {#mapear-org-cycle}
|
||||
|
||||
```elisp
|
||||
|
@ -889,18 +1026,32 @@ subprojects from INPROGRESS back to TODO"
|
|||
(remove-hook 'org-tab-first-hook #'+org-cycle-only-current-subtree-h))
|
||||
```
|
||||
|
||||
|
||||
#### Mostrar solo las cabeceras {#mostrar-solo-las-cabeceras}
|
||||
|
||||
```elisp
|
||||
(setq org-startup-folded t)
|
||||
```
|
||||
|
||||
|
||||
#### org-superstar {#org-superstar}
|
||||
|
||||
```elisp
|
||||
(package! org-superstar)
|
||||
```
|
||||
|
||||
```elisp
|
||||
(use-package! org-superstar :config (add-hook 'org-mode-hook (lambda () (org-superstar-mode 1))))
|
||||
```
|
||||
|
||||
|
||||
### Asignar keybinds {#asignar-keybinds}
|
||||
|
||||
```elisp
|
||||
(after! org
|
||||
(map! [remap outline-toggle-children] #'org-cycle)
|
||||
(map! (:leader
|
||||
:desc "Org Capture" "X" #'counsel-org-capture
|
||||
(:desc "brain stuff"
|
||||
:prefix "k"
|
||||
:desc "Brain refile" :n "r" #'org-brain-refile
|
||||
|
@ -937,10 +1088,34 @@ subprojects from INPROGRESS back to TODO"
|
|||
:desc "Ctrl-Ctrl" :nv "C" #'org-ctrl-c-ctrl-c)))
|
||||
```
|
||||
|
||||
|
||||
## Misc {#misc}
|
||||
|
||||
|
||||
### Flycheck {#flycheck}
|
||||
|
||||
```elisp
|
||||
;; (defvar-local my/flycheck-local-cache nil)
|
||||
|
||||
;; (defun my/flycheck-checker-get (fn checker property)
|
||||
;; (or (alist-get property (alist-get checker my/flycheck-local-cache))
|
||||
;; (funcall fn checker property)))
|
||||
|
||||
;; (advice-add 'flycheck-checker-get :around 'my/flycheck-checker-get)
|
||||
|
||||
;; (add-hook 'lsp-managed-mode-hook
|
||||
;; (lambda ()
|
||||
;; (when (derived-mode-p 'sh-mode)
|
||||
;; (setq my/flycheck-local-cache '((lsp . ((next-checkers . (sh-posix-bash)))))))
|
||||
;; (when (derived-mode-p 'web-mode)
|
||||
;; (setq my/flycheck-local-cache '((lsp . ((next-checkers . (javascript-eslint)))))))
|
||||
;; ))
|
||||
```
|
||||
|
||||
|
||||
### elisp {#elisp}
|
||||
|
||||
|
||||
#### package-lint {#package-lint}
|
||||
|
||||
Linter de problemas habituales de paquetes de melpa:
|
||||
|
@ -954,7 +1129,8 @@ Linter de problemas habituales de paquetes de melpa:
|
|||
(use-package! package-lint :defer t))
|
||||
```
|
||||
|
||||
### python-mode {#python-mode}
|
||||
|
||||
### python {#python}
|
||||
|
||||
```elisp
|
||||
(defun daemons/docker-tox ()
|
||||
|
@ -978,6 +1154,43 @@ docker run -ti -v `pwd`:/tox/files/ registry.daemons.it/tox:latest tox "$@"
|
|||
|
||||
De esta forma, ejecuto `tox-current-class` una vez y el del tiempo ejecuto `recompile`.
|
||||
|
||||
|
||||
### Javascript {#javascript}
|
||||
|
||||
Linter:
|
||||
|
||||
```elisp
|
||||
(setq lsp-javascript-implicit-project-config-check-js t)
|
||||
(setq lsp-typescript-implementations-code-lens-enabled t)
|
||||
(setq lsp-typescript-references-code-lens-enabled t)
|
||||
(setq lsp-typescript-references-code-lens-enabled t)
|
||||
|
||||
(add-hook! 'lsp-after-initialize-hook
|
||||
(run-hooks (intern (format "%s-lsp-hook" major-mode))))
|
||||
(defun daemons/eslint-flycheck-setup ()
|
||||
(flycheck-add-next-checker 'lsp 'javascript-eslint))
|
||||
(add-hook 'web-mode-lsp-hook
|
||||
#'daemons/eslint-flycheck-setup)
|
||||
(add-hook 'javascript-mode-lsp-hook
|
||||
#'daemons/eslint-flycheck-setup)
|
||||
(add-hook 'typescript-mode-lsp-hook
|
||||
#'daemons/eslint-flycheck-setup)
|
||||
```
|
||||
|
||||
Formatter:
|
||||
|
||||
```elisp
|
||||
(setq lsp-vetur-format-enable nil)
|
||||
(setq-hook! 'web-mode-hook +format-with-lsp nil)
|
||||
(setq-hook! 'javascript-mode-hook +format-with-lsp nil)
|
||||
(setq-hook! 'typescript-mode-hook +format-with-lsp nil)
|
||||
(set-formatter! 'prettier-eslint "prettier-eslint --write" :ok-statuses '(0 1))
|
||||
(setq-hook! 'web-mode-hook +format-with 'prettier-eslint)
|
||||
(setq-hook! 'javascript-mode-hook +format-with 'prettier-eslint)
|
||||
(setq-hook! 'typescript-mode-hook +format-with 'prettier-eslint)
|
||||
```
|
||||
|
||||
|
||||
### compile-mode {#compile-mode}
|
||||
|
||||
Varias herramientas usan el modo compile, como `molecule.el`:
|
||||
|
@ -989,7 +1202,6 @@ Varias herramientas usan el modo compile, como `molecule.el`:
|
|||
:config
|
||||
(setq compilation-skip-threshold 2)
|
||||
(setq compilation-scroll-output 'next-error)
|
||||
(set-popup-rule! "*compilation*" :size 0.40 :quit nil)
|
||||
(defun colorize-compilation-buffer ()
|
||||
(let ((inhibit-read-only t))
|
||||
(ansi-color-apply-on-region (point-min) (point-max))))
|
||||
|
@ -997,6 +1209,7 @@ Varias herramientas usan el modo compile, como `molecule.el`:
|
|||
(setq compilation-scroll-output 'first-error))
|
||||
```
|
||||
|
||||
|
||||
### ivy-mode / counsel-mode / swipper-mode {#ivy-mode-counsel-mode-swipper-mode}
|
||||
|
||||
Cambiar un poco el formato de ivy.
|
||||
|
@ -1008,13 +1221,6 @@ Cambiar un poco el formato de ivy.
|
|||
(setq counsel-find-file-at-point t))
|
||||
```
|
||||
|
||||
### counsel-rg {#counsel-rg}
|
||||
|
||||
Seguir enlaces simbólicos:
|
||||
|
||||
```elisp
|
||||
(setq counsel-rg-base-command "rg -L -S --no-heading --line-number --color never %s .")
|
||||
```
|
||||
|
||||
### undo-tree {#undo-tree}
|
||||
|
||||
|
@ -1028,13 +1234,6 @@ Personalizaciones para hacer que sea más chuli y que guarde la historia de cada
|
|||
(setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo-tree"))))
|
||||
```
|
||||
|
||||
### docker {#docker}
|
||||
|
||||
Uso la configuración por defecto de doom, pero me gusta que no muera el buffer de compilación:
|
||||
|
||||
```elisp
|
||||
(set-popup-rule! "docker-build-output" :size 0.30 :select t)
|
||||
```
|
||||
|
||||
### go-mode {#go-mode}
|
||||
|
||||
|
@ -1056,6 +1255,7 @@ Además quiero que se formatee al guardar y que use `goimports` en vez de `gofmt
|
|||
(setq gofmt-command "goimports")
|
||||
```
|
||||
|
||||
|
||||
### hl-todo {#hl-todo}
|
||||
|
||||
Añadir un nuevo `TODO` para las cosas feas.
|
||||
|
@ -1065,16 +1265,12 @@ Añadir un nuevo `TODO` para las cosas feas.
|
|||
'("HACK" . "DarkRed"))
|
||||
```
|
||||
|
||||
### vue-mode {#vue-mode}
|
||||
|
||||
```elisp
|
||||
(package! vue-mode)
|
||||
```
|
||||
|
||||
### magit-mode {#magit-mode}
|
||||
|
||||
Quiero usar [commitizen](https://commitizen-tools.github.io/commitizen/) en vez del commit pelado. Para ello tengo dos opciones, abrir una terminal que ejecute `cz` o usar una plantilla para los commits. La primera opción tiene la ventaja de que puede usar la configuración de `commitizen` del repositorio, que es lo bonico. Lo malo es que no he encontrado una forma de integralo bonito con magit. Por ello, de momento tiraré con la segunda opción, ya que no trabajo con más gente que use este plugin de git. En el caso de encontrarmelo, igual decidiré si creo varias plantillas o si intento mejorar la integración de magit con `commitizen`.
|
||||
|
||||
|
||||
#### Plantilla en magit {#plantilla-en-magit}
|
||||
|
||||
```elisp
|
||||
|
@ -1089,6 +1285,7 @@ ${5:Footer. Information about Breaking Changes and reference issues that this co
|
|||
(add-hook 'git-commit-setup-hook #'daemons/commitizen-template)
|
||||
```
|
||||
|
||||
|
||||
#### Abrir cz en una terminal {#abrir-cz-en-una-terminal}
|
||||
|
||||
```elisp
|
||||
|
@ -1125,6 +1322,7 @@ shell exits, the buffer is killed."
|
|||
(defun daemons/commitizen-gz() (interactive) (phalp/run-in-vterm "git cz commit; exit"))
|
||||
```
|
||||
|
||||
|
||||
### vterm-mode {#vterm-mode}
|
||||
|
||||
Hacer que entre en insert mode al lanzar una terminal:
|
||||
|
@ -1134,6 +1332,7 @@ Hacer que entre en insert mode al lanzar una terminal:
|
|||
(add-hook 'vterm-mode-hook #'evil-insert-state))
|
||||
```
|
||||
|
||||
|
||||
### evil-hardcore-mode {#evil-hardcore-mode}
|
||||
|
||||
Hardcodear atajos de teclado:
|
||||
|
@ -1162,6 +1361,7 @@ Hardcodear atajos de teclado:
|
|||
(global-evil-hardcore-mode))
|
||||
```
|
||||
|
||||
|
||||
### Cambiar atajos de doom {#cambiar-atajos-de-doom}
|
||||
|
||||
Cambiar los atajos por unos que me gustan más.
|
||||
|
@ -1175,18 +1375,6 @@ Cambiar los atajos por unos que me gustan más.
|
|||
)
|
||||
```
|
||||
|
||||
### Hacer gifs con camcorder.el {#hacer-gifs-con-camcorder-dot-el}
|
||||
|
||||
```elisp
|
||||
(package! camcorder)
|
||||
```
|
||||
|
||||
```elisp
|
||||
(use-package camcorder
|
||||
:ensure t
|
||||
:config
|
||||
(setq camcorder-recording-command '("recordmydesktop" " --fps 100 --no-sound --windowid " window-id " -o " file)))
|
||||
```
|
||||
|
||||
### Deshabilitar numeros en los laterales {#deshabilitar-numeros-en-los-laterales}
|
||||
|
||||
|
@ -1195,10 +1383,85 @@ Cambiar los atajos por unos que me gustan más.
|
|||
(setq display-line-numbers-type nil)
|
||||
```
|
||||
|
||||
|
||||
### Insertar fechas {#insertar-fechas}
|
||||
|
||||
Esta la he cogido de emacswiki:
|
||||
|
||||
```emacs-lisp
|
||||
(defun emacswiki/insert-current-date ()
|
||||
(interactive)
|
||||
(shell-command-to-string "echo -n $(date +%Y-%m-%d)"))
|
||||
```
|
||||
|
||||
Siguiendo la misma tonica:
|
||||
|
||||
```emacs-lisp
|
||||
(defun daemons/insert-current-month-number ()
|
||||
(interactive)
|
||||
(shell-command-to-string "echo -n $(date +%m)"))
|
||||
```
|
||||
|
||||
Siguiendo la misma tonica:
|
||||
|
||||
```emacs-lisp
|
||||
(defun daemons/insert-current-year-number ()
|
||||
(interactive)
|
||||
(shell-command-to-string "echo -n $(date +%Y)"))
|
||||
```
|
||||
|
||||
Siguiendo la misma tonica:
|
||||
|
||||
```emacs-lisp
|
||||
(defun daemons/insert-current-week-number ()
|
||||
(interactive)
|
||||
(shell-command-to-string "echo -n $(date +%V)"))
|
||||
```
|
||||
|
||||
Fecha de la semana que viene:
|
||||
|
||||
```emacs-lisp
|
||||
(defun daemons/insert-next-week()
|
||||
(interactive)
|
||||
(shell-command-to-string "echo -n $(date -d 'next week' '+%m %d %Y')"))
|
||||
```
|
||||
|
||||
Fecha y hora actual:
|
||||
|
||||
```emacs-lisp
|
||||
(defun daemons/insert-current-date-and-time ()
|
||||
(interactive)
|
||||
(shell-command-to-string "echo -n $(date +%Y%m%d%H%M%S)"))
|
||||
```
|
||||
|
||||
|
||||
### Documentación {#documentación}
|
||||
|
||||
```emacs-lisp
|
||||
(setq +lookup-open-url-fn #'eww)
|
||||
```
|
||||
|
||||
|
||||
### Popups {#popups}
|
||||
|
||||
```elisp
|
||||
|
||||
(set-popup-rule! "agenda" :size 0.50 :select t :quit nil)
|
||||
(set-popup-rule! "^CAPTURE" :size 0.50 :select t :quit nil)
|
||||
(set-popup-rule! "*compilation*" :size 0.40 :select nil :quit nil)
|
||||
(set-popup-rule! "^ivy-occur*" :size 0.40 :select nil :quit nil)
|
||||
(set-popup-rule! "*grep*" :size 0.40 :select nil :quit nil)
|
||||
(set-popup-rule! "docker-build-output" :size 0.40 :select t)
|
||||
(set-popup-rule! "^\\*helpful*" :size 0.40 :select nil :quit nil)
|
||||
|
||||
```
|
||||
|
||||
|
||||
## En progreso / Pendiente {#en-progreso-pendiente}
|
||||
|
||||
En esta sección van las cosas que no tengo muy provadas o tengo a medio configurar.
|
||||
|
||||
|
||||
### molecule {#molecule}
|
||||
|
||||
No se activa automaticamente.
|
||||
|
@ -1212,6 +1475,7 @@ No se activa automaticamente.
|
|||
;; :config (add-hook 'yaml-mode-hook 'molecule-mode))
|
||||
```
|
||||
|
||||
|
||||
### Autenticación para terraform {#autenticación-para-terraform}
|
||||
|
||||
Uso el modo de terraform que da doom, pero le he añadido una función cutre
|
||||
|
|
138
content/posts/antisocial-analizar-datos-del-fediverso.md
Normal file
138
content/posts/antisocial-analizar-datos-del-fediverso.md
Normal file
|
@ -0,0 +1,138 @@
|
|||
+++
|
||||
title = "Antisocial - Analizar datos del fediverso"
|
||||
author = ["drymer"]
|
||||
lastmod = 2021-08-09T00:20:15+02:00
|
||||
tags = ["antisocial", "fediverso"]
|
||||
draft = false
|
||||
+++
|
||||
|
||||
**Disclaimer**: Este artículo se ha escrito del tirón con cosas que tengo en mente desde hace mucho. Es posible que no sea del todo riguroso en algunos aspectos y que en alguno exagere. Intento simplificar cosas que son complejas de explicar, por lo que seguro que hay cosas que no son exactas.
|
||||
|
||||
|
||||
## Tabla de contenido {#tabla-de-contenido}
|
||||
|
||||
- [Prólogo](#prólogo)
|
||||
- [De quién nos protegemos?](#de-quién-nos-protegemos)
|
||||
- [Definiciones de seguridad y anónimato](#definiciones-de-seguridad-y-anónimato)
|
||||
- [Matriz para decidir como protegerte](#matriz-para-decidir-como-protegerte)
|
||||
- [Antisocial: Qué datos se pueden sacar de las redes sociales libres?](#antisocial-qué-datos-se-pueden-sacar-de-las-redes-sociales-libres)
|
||||
|
||||
|
||||
## Prólogo {#prólogo}
|
||||
|
||||
Qué diferencia una red social privativa de una red social libre? Se podría decir que la principal diferencia es que detrás de las redes privativas hay una o varias empresas con ánimo de lucro. Normalmente esto se traduce en que quieren recopilar cuantos más datos de sus usuarias. Pero que datos tienen realmente las empresas de nosotras?
|
||||
|
||||
Para simplificar la pregunta, vamos a reducir solamente al uso de la propia red social, sin entrar en [movidas de cookies](https://anytech365.com/es/stop-facebook-spying-on-you-outside-of-facebook/) de terceros ni nada parecido.
|
||||
|
||||
Qué datos puede ver facebook o twitter cuando usamos sus páginas?:
|
||||
|
||||
- El contenido de lo que públicamos, ya sea público o privado
|
||||
- Interacciones (favoritos, compartir)
|
||||
- Dónde ponemos el ratón y durante cuanto tiempo
|
||||
- Que páginas miramos (perfiles privados, grupos, ...)
|
||||
- Cuanto tiempo pasamos en cada página
|
||||
- Anuncios que vemos
|
||||
- Información física (IP desde la que te conectas)
|
||||
|
||||
Cuando lo comparamos con los datos que se pueden sacar del fediverso, vemos que en realidad de esa lista de seis, solo se cumplen dos. Contenido e interacciones. Desde luego es una mejora, motivo suficiente para no usar redes privativas. Está bien que no cojan tus datos y los usen para alimentar AIs malignas o venderlas a terceros.
|
||||
|
||||
|
||||
## De quién nos protegemos? {#de-quién-nos-protegemos}
|
||||
|
||||
Pero que pasa con los datos que se comparten en las redes libres? Que daño podrían causar? Creo que para responder a esta pregunta correctamente, hay que hablar de algunos temas que a veces se mezclan:
|
||||
|
||||
- Enemigos o actores malignos
|
||||
- Seguridad de la información
|
||||
- Anonimato
|
||||
|
||||
Qué actores malignos podrian existir en general?
|
||||
|
||||
- **Un gobierno**: no son pocos los gobiernos que espian de forma masiva a sus ciudadanos con el fin de "protegerlos". Sobre este tema hay [información para aburrir](https://es.wikipedia.org/wiki/Revelaciones%5Fsobre%5Fla%5Fred%5Fde%5Fvigilancia%5Fmundial%5F(2013-2015)).
|
||||
- **Una empresa**: las empresas de las redes sociales privativas recogen los datos para sí pero además los venden a otros. [Ejemplo reciente](https://time.com/6083323/bishop-pillar-grindr-data/), un cura denunciado por ser gay y ir a bares gays. La fuente de los datos? Datos disponibles a la venta por parte de Grindr.
|
||||
- **Un particular**: normalmente esta persona no tiene interés en la recopilación de datos masiva, sinó en la recopilación de datos personales. Puede estar relacionado con ataques personales y doxxing. Un ejemplo, [Gamergate](http://www.mtv.com/news/2245633/gamer-gate-one-year-later/).
|
||||
|
||||
|
||||
## Definiciones de seguridad y anónimato {#definiciones-de-seguridad-y-anónimato}
|
||||
|
||||
**Disclaimer**: Es un tochazo.
|
||||
|
||||
Una vez definidos los actores malignos, definamos las otras dos palabras, ya que a veces las mezclamos.
|
||||
|
||||
|
||||
### Seguridad {#seguridad}
|
||||
|
||||
La [seguridad de la información](https://es.wikipedia.org/wiki/Seguridad%5Fde%5Fla%5Finformaci%C3%B3n), en el contexto del fediverso, está compuesta de las siguientes claves:
|
||||
|
||||
- **Confidencialidad**: Que la información llegue a quien tenga que llegar. La información pública la tenemos clara, la publicamos y la ve cualquiera. Luego hay otras formas de limitar quien puede ver que. Esta funcionalidad la tienen varias implementaciones, como Mastodon o Pleroma, y está cogida con pinzas. El problema es que en la federación, si mi servidor dice que algo es privado y se lo manda a otro servidor, este otro servidor tiene que respetarlo. Ejemplo, el usuario a del nodo manda un mensaje privado al usuario b del nodo b. El nodo b podría decidir hacer público este mensaje.
|
||||
- **Integridad**: Que nadie pueda modificar nuestra información. El problema es similar al anterior, dentro de tu servidor controlas lo que quieras, pero cuando lo lanzas fuera hay que confiar. Ejemplo, el usuario a del nodo a lanza un mensaje al mundo y el nodo b modifica el mensaje para decir que odia las aceitunas.
|
||||
- **Disponibilidad**: Que la información se pueda consultar cuando se requiera. Hay diferentes acercamientos en el fediverso, algunas implementaciones copian los datos (con la consecuencia sobrecarga) y aunque el origen falle, pueden mostrarlo. Otras simplemente referencian al origen.
|
||||
- **Autenticación**: Que se pueda identificar a la persona que ha escrito la información. Esta parte es especialmente importante y se relaciona con el siguiente palabro, **anonimato**.
|
||||
|
||||
|
||||
### Anonimato {#anonimato}
|
||||
|
||||
Qué significa **anonimato**? Incluso dentro del contexto de las redes libres, puede tener distintas connotaciones. Una parte del problema es que usamos la palabra **anónimo** cuando en realidad queremos decir **pseudoanónimo**. Una persona anónima es una persona que es de nombre desconocido o que se oculta, según la RAE. Pero entonces, como podemos garantizar la seguridad de la información? Una de las claves es la integridad y la autenticación. Como podemos saber que el mensaje es de quien dice ser, si no sabemos quien es?
|
||||
|
||||
Una primera diferenciación que tenemos que hacer es la de personas e identidades. Yo como persona soy lo que pone en mi DNI, pero tengo más identidades. Una es drymer, alguien que lleva en comunidades de software libre varios años y que tiene interéses y actividades x.
|
||||
|
||||
Pero no es la única identidad que tengo, tengo otros nicks y otras actividades. Estas identidades pueden ser o no **pseudoanonimas**. Digo pseudoanonimas por que necesitan un identificador. Por ejemplo, el identificador más viejo y fiable de drymer es mi correo eléctronico.
|
||||
|
||||
Más ejemplos de identidades pseudoanonimas. Un foro en la red de tor. Si yo me logue como paquito, yo ahí tendré la identidad de paquito. **Sabran** quien es mi identidad. Pero desde un punto de vista técnico, no sabran quien soy yo como persona, ya que Tor se asegura de ello.
|
||||
|
||||
Llevando la definición a las redes libres, seremos **anónimas** si usamos herramientas para tal fin (tor, vpns, 7 proxies, etc...). Pero tendremos una identidad identificable, valga la redundancia, que será la que usaremos para iniciar sesión en uno de los nodos del fediverso. Por ejemplo, mi identidad será drymer@barcelona.social.
|
||||
|
||||
|
||||
## Matriz para decidir como protegerte {#matriz-para-decidir-como-protegerte}
|
||||
|
||||
Después de todo ese desvarío, que creo era necesario, vamos a ver como facilitarnos un poco la vida. He aquí una matriz para escoger que cosas podemos hacer según de quien nos queremos proteger:
|
||||
|
||||
- RSP: Red social privativa.
|
||||
- RSL: Red social libre.
|
||||
- PH: Protección por herramientas, como tor, proxies, vpns,...
|
||||
- PC: Protección por contenido, no decir direcciones físicas, nombres, gustos personales, etc.
|
||||
- IC: Irse a vivir a una cueva, plantar zanahorias y tomates.
|
||||
|
||||
| De quien me protejo? | RSP + PH | RSP + PC | RSP + PH + PC | RSL + PH | RSL + PC | RSL + PH + PC | Irse a vivir a una cueva |
|
||||
|----------------------------|----------|----------|---------------|----------|----------|---------------|--------------------------|
|
||||
| De un gobierno | | | X | | | X | X |
|
||||
| De las empresas | X | X | X | | X | | X |
|
||||
| De una persona / colectivo | | X | | | X | | X |
|
||||
| Del mundo | | | | | | | X |
|
||||
|
||||
Hay bastante a desgranar:
|
||||
|
||||
- **Gobierno**: Tenemos que usar herramientas de ocultación tanto física como mediante el contenido. Esta última parte suele ser en la que se falla. Si coges y pones en tu red social favorita del fediverso que te vas a tomar un helado a la plaza del Sol, ya puedes usar tor que te van a poder encontrar igual. Por ello, ambos métodos de ocultación son absolutamente necesarios para usar tanto redes socialas privativas como libres. Si una de los dos métodos de ocultación falla, estarás expuesta.
|
||||
- **Empresas**: En general, como individuos somos irrelevantes (salvo excepciones, como la del cura de grindr). No les interesa Paco Perez, les interesa su edad, sexo, género y gustos. Y todo ello se puede conseguir tanto en redes sociales como privadas (aunque en mayor medida en las privativas). Si compartes una foto de la compra en la tienda del barrio para hacerles promoción, les estás diciendo tus gustos. Aunque sea una red social libre, son datos accesibles públicos. Por ello, uses la red que uses, si quieres protegerte de una empresa debes enmascarar tus datos. Usar protección de herramientas puede ser útil, pero no es la parte gorda de la que sacan tu información.
|
||||
- **Persona / colectivo**: En este caso da igual si usas redes privadas o libres, por que no tienen acceso a los servidores (a menos que hablemos de juankers malosos), a diferencia de los dos anteriores. De lo que se alimentan estos actores es del contenido de tus publicaciones. Por ello, en este caso, es irrelevante si usas una red social privada o pública. Lo importante es qué publicas en ellas y si pueden llegar a encontrar tus otras identidades, ya sea la física u otras identidades virtuales. Por lo tanto, la principal protección es la de protección por contenido.
|
||||
- **Mundo**: Papel de aluminio en la cabeza y al monte, poco más hay que hacer.
|
||||
|
||||
Si lo pensamos, los actores se diferencian solamente en el grado de recursos y de cosas ilegales que están dispuestos a hacer. Un gobierno siempre tendrá más recursos que una persona. Aunque una persona o un grupo de personas con la suficiente motivación pueden tocar las narices igual.
|
||||
|
||||
PD: algo que se puede ver en la matriz es que la solución a todos los problemas es irse a vivir a una cueva...
|
||||
|
||||
|
||||
## Antisocial: Qué datos se pueden sacar de las redes sociales libres? {#antisocial-qué-datos-se-pueden-sacar-de-las-redes-sociales-libres}
|
||||
|
||||
Todo este tocho y yo en verdad venia a hablar de mi libro. Hace tiempo que me preocupa que nos pensemos que las redes sociales libres son seguras y anónimas, por que no lo son.
|
||||
|
||||
Estan sujetas a leyes, por lo que en el mejor de los casos tenemos que confiar en que los colectivos que las mantienen **rompan** la ley si tienen algún requerimiento legal. Algo que es mucho más fácil de decir que hacer. Por no hablar del peor de los males, que somos nosotras mismas. Somos nosotras quienes damos más información en nuestras publicaciones. Es este tema en concreto en el que yo quiero profundizar.
|
||||
|
||||
Como prueba de concepto, he pedido a unas buenas gentes del fediverso que me dejen descargar sus datos públicos y meterlos en una aplicación que he desarrollado que los trata. Hace dos cosas, mostrar una nube de palabras con sus palabras más usadas y muestra un gráfico de relaciones. En este gráfico de relaciones se ve con quien han interactuado, ya sea con reposts, favoritos o menciones.
|
||||
|
||||
Quiero agradecer a todas las personas que han ofrecido sus datos. Al final he cogido solo algunas pocas, tanto por facilidad como por problemas técnicos. Estas son:
|
||||
|
||||
- <https://pleroma.libretux.com/@anoncf>
|
||||
- <https://mastodon.lol/@dark>
|
||||
- <https://todon.nl/@talogeta>
|
||||
- <https://mastodon.madrid/@notxor>
|
||||
- <https://pleroma.libretux.com/@izaro>
|
||||
- <https://qoto.org/@qapaq>
|
||||
|
||||
Quiero recalcar la parte en la que esta buena gente me ha permitido descargar sus datos. Me han dicho que si, pero no han tenido que hacer nada, por que yo podria haberlos descargados sin más. Si fuese un actor maligno, no se habrian enterado.
|
||||
|
||||
Para cerrar, hay dos temas de los cuales me parece interesante hablar, por lo que crearé dos hilos en el fediverso para ello:
|
||||
|
||||
- Las redes sociales (libres o privativas), tiene ventajas y desventajas. Cúal es el balance? Los peligros en los que nos ponen sobrepasan las ventajas? El hilo es [este](https://barcelona.social/notice/AA82X5uJC1p9pKkk0O).
|
||||
- Que opinais de que se publique una herramienta que permita descargar y tratar los datos del fediverso? Concretamente hablo de **antisocial**, que es la herramienta que he desarrollado. El hilo es [este](https://barcelona.social/notice/AA82aSoAVK63ioUHx2).
|
||||
|
||||
Sin más dilación, sacad vuestras conclusiones. Los datos y parte de se puede consultar [aquí](https://antisocial.daemons.it).
|
15
content/posts/como-diseñar-un-rol-de-ansible-1.md
Normal file
15
content/posts/como-diseñar-un-rol-de-ansible-1.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
+++
|
||||
title = "Cómo diseñar un rol de ansible - 1"
|
||||
author = ["drymer"]
|
||||
lastmod = 2021-11-28T18:24:41+01:00
|
||||
tags = ["ansible", "desarrollo"]
|
||||
draft = false
|
||||
+++
|
||||
|
||||
He empezado una serie de videos en Peertube en los que explicaré como diseñar un rol de ansible.
|
||||
|
||||
El fin no es tanto cómo hacer un rol, ya que hay mucha documentación sobre el tema, sinó intentar mostrar el hilo del pensamiento cuando te encuentras con la necesidad de automatizar algo que tal vez no conozcas mucho y diseñar como será la interfaz para el usuario.
|
||||
|
||||
Peertube es compatible con cualquier implementación del fediverso, por lo que se puede [suscribir al canal](https://fediverse.tv/c/bad%5Fdaemons/videos) desde el botón de "Subscribe".
|
||||
|
||||
<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts allow-popups" title="Cómo diseñar un rol de ansible - 1" src="<https://fediverse.tv/videos/embed/0dc56409-bc6a-4b0f-838f-57ac2913d80e>" frameborder="0" allowfullscreen></iframe>
|
|
@ -0,0 +1,81 @@
|
|||
+++
|
||||
title = "Estandarizar commits en Magit con commitizen"
|
||||
author = ["drymer"]
|
||||
lastmod = 2020-08-27T20:47:43+02:00
|
||||
tags = ["magit", "emacs", "git"]
|
||||
draft = false
|
||||
+++
|
||||
|
||||
Quién trabaje o contribuya a proyectos de software con otras personas sabrá que a veces el tiempo se va discutiendo chorradas. Un ejemplo típico son las convenciones del código.
|
||||
|
||||
Por ejemplo, en python lineas más largas de 79 carácteres (como el pep8 define) o más (ya que no estamos en los 90 y tenemos pantallas de más de 8 pulgadas)? Una lista debería estar en una sola línea o en varias?
|
||||
|
||||
Para la mayor parte de los casos no hay respuesta correcta, por que es cuestión de gustos. Por ello, ya hace un tiempo que decidí que paso de dedicar mi tiempo a esto y que otra persona decida por mi. En el caso de los ejemplos anteriores he decidido que sea [black](https://github.com/psf/black) quien decida como hacer las cosas. Pero yendo al articulo, he decidido que quién se encargue del formato de mis commits sea [commitizen](https://commitizen-tools.github.io/commitizen/).
|
||||
|
||||
Alredor del formato de los commits hay mucha historia. Lo idóneo es poner el tipo de cambio, el alcance de este, un título que resuma el cambio, un cuerpo con una explicación más profunda si hace falta y un ticket del gestor de tareas que uses. De esta forma es más fácil ver como evoluciona el código y la lógica que hay detrás. Tiene un añadido y es que si los commits tienen el mismo formato, se pueden generar changelogs de forma automática.
|
||||
|
||||
Meter toda esta información no es fácil. Para ello está [commitizen](https://commitizen-tools.github.io/commitizen/). Esta herramienta da lo siguiente:
|
||||
|
||||
- [Implementar una convencion de commits](https://www.conventionalcommits.org/en/v1.0.0/)
|
||||
- [Gestión de versiones semántica](https://semver.org/)
|
||||
- [Crear un changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
|
||||
`cz` es un plugin de git. En vez de usar \`git commit\` lo que hay que hacer es usar `git cz` y te hace una serie de preguntas que ayudarán a generar el mensaje. Se puede ver un ejemplo en esta imagen:
|
||||
|
||||
{{< figure src="/img/commitizen.gif" >}}
|
||||
|
||||
Pero esta es una herramienta para la terminal, y teniendo emacs, la terminal está obsoleta. Así que veamos como usar esto en Magit. Lo idóneo sería llamar a `git cz` directamente, ya que aunque `cz` define las convenciones, estas se pueden cambiar por proyecto, por lo que generar una plantilla para el commit sin más puede no cubrir todos los casos. Estuve investigando cómo hacerlo pero tendría que haberme metido mucho más en la madriguera del conejo de lo que ya he hecho, por lo que decidí ir a por una solución de compromiso.
|
||||
|
||||
Por un lado, hice una plantilla para magit. Esto me servirá para la mayoría de los casos. Pero para cuando no, tengo una función que me deja hacer el commit desde emacs. No usa magit, lo cual es una pena, pero para el caso valdrá. Veamos ambas opciones.
|
||||
|
||||
He creado una función que usa [yasnippet](https://github.com/joaotavora/yasnippet), un sistema de plantillas. Luego se añade esa función al hook del git-commit y de esta forma cada vez que se haga un commit, se llama a la función:
|
||||
|
||||
```emacs-lisp
|
||||
(defun daemons/commitizen-template()
|
||||
"Expand a commitizen template."
|
||||
(yas-expand-snippet "${1:Select the type of change you are committing: $$(yas-choose-value '(\"fix\" \"feat\" \"docs\" \"style\" \"refactor\" \"perf\" \"test\" \"build\" \"ci\"))}(${2:Scope. Could be anything specifying place of the commit change (users, db, poll): )}): ${3:Subject. Concise description of the changes. Imperative, lower case and no final dot}
|
||||
|
||||
${4:Body. Motivation for the change and contrast this with previous behavior}
|
||||
|
||||
${5:Footer. Information about Breaking Changes and reference issues that this commit closes}"))
|
||||
|
||||
(add-hook 'git-commit-setup-hook #'daemons/commitizen-template)
|
||||
```
|
||||
|
||||
Para llamar a `cz` directamente he usado una función bonica que encontré en reddit (la fuente está en la función) que en resumen usa [vterm](https://github.com/akermu/emacs-libvterm) para lanzar una orden arbitrária. Creé la función chorra que llama a esa función con `cz` y ya está.
|
||||
|
||||
```emacs-lisp
|
||||
(defun phalp/run-in-vterm (command)
|
||||
"Execute string COMMAND in a new vterm.
|
||||
|
||||
From: https://www.reddit.com/r/emacs/comments/ft84xy/run_shell_command_in_new_vterm/
|
||||
|
||||
Interactively, prompt for COMMAND with the current buffer's file
|
||||
name supplied. When called from Dired, supply the name of the
|
||||
file at point.
|
||||
|
||||
Like `async-shell-command`, but run in a vterm for full terminal features.
|
||||
|
||||
The new vterm buffer is named in the form `*foo bar.baz*`, the
|
||||
command and its arguments in earmuffs.
|
||||
|
||||
When the command terminates, the shell remains open, but when the
|
||||
shell exits, the buffer is killed."
|
||||
(interactive
|
||||
(list
|
||||
(let* ((f (cond (buffer-file-name)
|
||||
((eq major-mode 'dired-mode)
|
||||
(dired-get-filename nil t))))
|
||||
(filename (concat " " (shell-quote-argument (and f (file-relative-name f))))))
|
||||
(read-shell-command "Terminal command: "
|
||||
(cons filename 0)
|
||||
(cons 'shell-command-history 1)
|
||||
(list filename)))))
|
||||
(with-current-buffer (vterm (concat "*" command "*"))
|
||||
(vterm-send-string command)
|
||||
(vterm-send-return)))
|
||||
|
||||
(defun daemons/commitizen-gz() (interactive) (phalp/run-in-vterm "git cz commit; exit"))
|
||||
```
|
||||
|
||||
Tiene pinta de que no integraré nunca magit con `cz` dada su dificultad, por lo que probablemente vaya creando plantillas para los commits según el proyecto y buscaré alguna forma de que use una plantilla u otra según el directorio en el que esté. Aún así molaria ver `cz` integrado.
|
208
content/posts/gestion-declarativa-de-paquetes-en-arch.md
Normal file
208
content/posts/gestion-declarativa-de-paquetes-en-arch.md
Normal file
|
@ -0,0 +1,208 @@
|
|||
+++
|
||||
title = "Gestión de paquetes y dotfiles en arch"
|
||||
author = ["drymer"]
|
||||
lastmod = 2021-08-25T00:17:38+02:00
|
||||
tags = ["arch"]
|
||||
draft = false
|
||||
+++
|
||||
|
||||
<div class="ox-hugo-toc toc">
|
||||
<div></div>
|
||||
|
||||
<div class="heading">Índice</div>
|
||||
|
||||
- [TL;DR](#tl-dr)
|
||||
- [Prólogo](#prólogo)
|
||||
- [Diferencia entre herramientas imperativas y herramientas declarativas](#diferencia-entre-herramientas-imperativas-y-herramientas-declarativas)
|
||||
- [Aconfmgr y brew](#aconfmgr-y-brew)
|
||||
- [Dotfiles](#dotfiles)
|
||||
- [Empaquetado](#empaquetado)
|
||||
|
||||
</div>
|
||||
<!--endtoc-->
|
||||
|
||||
|
||||
## TL;DR {#tl-dr}
|
||||
|
||||
Antes usaba ansible para gestionar los paquetes de mi SO y mis dotfiles y no me gustaba. Cambié de ansible a `aconfmgr`, `brew` y `stow`. Aquí se puede ver lo [viejo](https://git.disroot.org/drymer/dotfiles/src/commit/37ef0175848c3d4ea6e5ae63e2a4883b68afdd2f) y aquí lo [nuevo](https://git.disroot.org/drymer/dotfiles).
|
||||
|
||||
|
||||
## Prólogo {#prólogo}
|
||||
|
||||
Hace tiempo me di cuenta de que me le dedicaba mucho tiempo a personalizar mi ordenador. Configuraciones varias, scripts, alias, programas, etc. Muchos de los programas no estaban en los repositorios comunes, ya que por aquel entonces aún usaba debian. Y mi solución fue hacer bastantes roles de ansible y un playbook de ansible que me gestionase todo. Tanto la instalación de todos los paquetes (algunos compilados, descargados de no se donde, etc) como de las configuraciones. Hice [este articulo](https://daemons.it/posts/como-gestionar-las-configuraciones-y-programas-de-tu-ordenador-con-ansible/), de hecho. El repositorio git ya no está en la misma dirección, pero el código se puede ver [aquí](https://git.disroot.org/drymer/dotfiles/src/commit/37ef0175848c3d4ea6e5ae63e2a4883b68afdd2f).
|
||||
|
||||
En ese momento me venia muy bien, por que necesitaba aprender [ansible](https://www.ansible.com/) y como cualquier tonto con un martillo, todo lo que veia eran clavos. Pero la realidad es que ansible no es la mejor herramienta para este tipo de cosas, sobretodo si hablamos de ordenadores personales.
|
||||
|
||||
Entre eso y que debian es leeeeeento a la hora de actualizar paquetes, hay pocos repositorios no oficiales (o menos), decidí pasarme a Arch.
|
||||
|
||||
Arch tiene el gestor de paquetes oficial, `pacman`. Y además, como Slackware, tiene un repositorio de paquetes hechos por la comunidad, llamado [Aur](https://aur.archlinux.org/). Tienen menos calidad que cualquier paquete de oficial de Arch o de Debian, pero ahí están. No es raro que algún paquete se te rompa al actualizar y tengas que hacer algún apaño o abrir un issue. Hay varias opciones para instalar paquetes de Aur, ir a pelo y clonar el repositorio git y ejecutar las órdenes o usar un gestor de paquetes. Han habido muchos a lo largo de los años, como pacaur o yaourt.
|
||||
|
||||
Pero hace un tiempo está [yay](https://github.com/Jguer/yay). Las ventajas de yay es que tiene los mismos parámetros que `pacman`, por lo que es fácil de usar. Y lo mejor, se sincroniza con `pacman`. Osea que cuando haces la típica actualización de sistema de `sudo pacman -Syu`, también te actualiza los paquetes de Aur. Muy útil.
|
||||
|
||||
Pero aún así se me quedaba corto, aún con lo grande que es Aur, le siguen faltando paquetes. Y por ello el resto los complemento con [Homebrew](https://brew.sh/). Homebrew nació como el gestor de paquetes que MacOS no tenia y necesitaba, pero con el tiempo se hizo compatible con GNU/Linux. No es mi preferido, ya que usa dependencias estáticas. Esto significa que si instalas el paquete `yamllint` de `brew`, como tiene de dependencia Python, te descargará python para que puedas usar `yamllint`, aunque tu distribución ya tenga python. Hay formas de evitar que lo haga, pero es incómodo y depende de la fórmula igual no puedes hacerlo. Por lo tanto, es la peor de las 3 opciones, aunque sigue siendo una opción, ya que no necesita root, es rápido y no da problemas.
|
||||
|
||||
Aún así, seguía con el problema de como reproducir los programas que tengo instalado. Decidí que en vez de una herramienta imperativa como es Ansible, lo que necesitaba era una herramienta declarativa. Tras luchar mucho para no saltar a [Guix](https://guix.gnu.org/), que gestiona todo el sistema operativo de forma declarativa, con rollback incluido, busque otras herramientas en Arch. Y encontré lo que buscaba, [aconfmgr](https://github.com/CyberShadow/aconfmgr) y vi que brew tiene esa misma funcionalidad metida, llamada [bundle](https://github.com/Homebrew/homebrew-bundle).
|
||||
|
||||
|
||||
## Diferencia entre herramientas imperativas y herramientas declarativas {#diferencia-entre-herramientas-imperativas-y-herramientas-declarativas}
|
||||
|
||||
Antes de entrar en las herramientas, hablemos de las diferencias entre una herramienta imperativa y otra declarativa. Una herramienta imperativa "ordena" que hagas cosas. Si tu borras una orden, esta no se deshace la próxima vez que la ejecutes, sinó que simplemente no se ejecuta. Por ejemplo, si yo tengo un script así:
|
||||
|
||||
```bash
|
||||
mkdir -p ejemplo/loQueSea
|
||||
echo "holi" > ejemplo/loQueSea
|
||||
```
|
||||
|
||||
Ejecuto el script y decido que no me gusta esa ruta y que quiero cambiarla:
|
||||
|
||||
```bash
|
||||
mkdir -p ejemplo/estoMolaMas
|
||||
echo "holi" > ejemplo/estoMolaMas
|
||||
```
|
||||
|
||||
Al ejecutar el siguiente script, no deshacemos el primero. Es decir, sigue existiendo `ejemplo/loQueSea` con el contenido `holi`.
|
||||
|
||||
En cambio, una herramienta declarativa habria borrado el fichero `ejemplo/loQueSea`. De una forma mágica y transparente para nosotras, al ejecutar el primer script habria hecho algo como:
|
||||
|
||||
```bash
|
||||
cambioAHacer=ejemplo/loQueSea
|
||||
mkdir -p $camgioAHacer
|
||||
echo "holi" > $cambioAHacer
|
||||
```
|
||||
|
||||
Y al ejecutarlo por segunda vez, de forma mágica y transparente habria hecho:
|
||||
|
||||
```bash
|
||||
rm $cambioAHacer
|
||||
cambioAHacer=ejemplo/estoMolaMas
|
||||
mkdir -p $camgioAHacer
|
||||
echo "holi" > $cambioAHacer
|
||||
```
|
||||
|
||||
Sé que es un ejemplo cogido con pinzas, pero espero que quede clara la diferencia.
|
||||
|
||||
De una forma más practica, si yo con ansible tenia una lista de paquetes tales como:
|
||||
|
||||
- git
|
||||
- curl
|
||||
- zsh
|
||||
|
||||
Y lo ejecutaba, me los instalaba. Pero si luego cambiaba la lista a:
|
||||
|
||||
- git
|
||||
- curl
|
||||
|
||||
No me desinstalaba zsh.
|
||||
|
||||
En cambio, con herramientas declarativas como `aconfmgr` si lo hace.
|
||||
|
||||
|
||||
## Aconfmgr y brew {#aconfmgr-y-brew}
|
||||
|
||||
Después de este intento de explicar las diferencias entre herramientas imperativas y declarativas, vamos al turrón. Con `aconfmgr`, tengo un ficherito tal que así:
|
||||
|
||||
```text
|
||||
AddPackage base # Minimal package set to define a basic Arch Linux installation
|
||||
AddPackage acpi # Client for battery, power, and thermal readings
|
||||
AddPackage alacritty # A cross-platform, GPU-accelerated terminal emulator
|
||||
AddPackage alsa-utils # Advanced Linux Sound Architecture - Utilities
|
||||
IgnorePackage amd-ucode # Microcode update image for AMD CPUs
|
||||
AddPackage arandr # Provide a simple visual front end for XRandR 1.2.
|
||||
AddPackage archlinux-themes-slim # Arch Linux branded themes for the SLiM login manager
|
||||
```
|
||||
|
||||
Es gigante y aburrido. Hacer la lista manualmente es una locura, por lo que el primer paso es hacer un dump de todo lo que tengas con `aconfmgr save`. Esto te creará un fichero llamado `99-unsorted.sh`. La idea es que en tu directorio de `aconfmgr` cojas los chorrocientos paquetes de ese fichero y los partas en varios, dividiendo de alguna forma razonable. Uno de mis ficheros es [este](https://git.disroot.org/drymer/dotfiles/src/branch/master/packages/arch/70-development.sh), y he estructurado así el directorio:
|
||||
|
||||
```text
|
||||
arch
|
||||
├── 1-ignore.sh
|
||||
├── 10-base.sh
|
||||
├── 15-utils.sh
|
||||
├── 30-gui.sh
|
||||
├── 50-media.sh
|
||||
├── 70-development.sh
|
||||
└── 90-misc.sh
|
||||
```
|
||||
|
||||
`aconfmgr` también te gestiona los ficheros de configuración, pero yo he decidido no usar esa funcionalidad, por eso en el fichero `1-ignore.sh` ignoro todos los ficheros.
|
||||
|
||||
Una vez organizaditos, sólo queda aplicar los paquetes. Esto se hace con `aconfmgr apply`. Cuidado al hacer esto por primera vez, sobretodo si habéis hecho limpieza al hacer dump. Puede que intente reinstalar paquetes. A mi me la lió la primera vez y tuve que reinstalar el kernel.
|
||||
|
||||
Y con esto, ya tendriamos gestionados los paquetes de Arch. Ahora van los de `brew`. El concepto es el mismo, se hace un dump, se limpia y se aplica. Se vuelcan los paquetes instalados con `brew bundle dump`. Esto crea un fichero llamado `Brewfile`. Lo modificamos como querramos y para aplicarlo se ejecuta `brew bundle install`. Si se quiere borrar cualquier paquete que no esté declarado ahí, se puede ejecutar `brew bundle cleanup`.
|
||||
|
||||
|
||||
## Dotfiles {#dotfiles}
|
||||
|
||||
Hasta ahora hemos hablado solo de los paquetes del SO, nada de dotfiles. Esto era lo que peor llevaba ansible, por que al final solo se trataba de hacer enlaces simbólicos y se le daban regular los cambios.
|
||||
|
||||
Ahora uso GNU Stow, que es más viejo que cagar sentado, que dicen en mi tierra. Pero hace lo que tiene que hacer, pone los ficheritos que tu quieres en su ruta. Está en todos los repositorios, por lo que se puede instalar con `pacman`.
|
||||
|
||||
La idea es crear una estructura de directorios en los que separas según alguna lógica. Yo me he decidido por esta estructura:
|
||||
|
||||
```bash
|
||||
dotfiles
|
||||
├── git
|
||||
│ ├── .compartido
|
||||
│ │ ├── Proyectos
|
||||
│ │ │ ├── alias
|
||||
│ │ │ │ └── .gitconfig
|
||||
│ │ │ └── real
|
||||
│ │ │ └── .gitconfig
|
||||
│ │ └── Trabajo
|
||||
│ │ └── .gitconfig
|
||||
│ └── .gitconfig
|
||||
├── i3
|
||||
│ ├── .compton.conf
|
||||
│ ├── .config
|
||||
│ │ ├── dunst
|
||||
│ │ │ └── dunstrc
|
||||
│ │ ├── i3status.conf
|
||||
│ │ └── rofi
|
||||
│ │ └── config
|
||||
│ ├── .i3
|
||||
│ │ ├── config
|
||||
│ │ └── scripts
|
||||
│ │ ├── autolock.sh
|
||||
│ │ ├── battery
|
||||
│ │ ├── date
|
||||
│ │ ├── lock
|
||||
│ │ ├── sensors
|
||||
│ │ └── volume-pulseaudio
|
||||
│ └── .i3blocks.conf
|
||||
└── shells
|
||||
├── .alacritty.yml
|
||||
├── .aliases
|
||||
├── .bashrc
|
||||
├── .config
|
||||
│ └── starship.toml
|
||||
├── .functions
|
||||
├── .Xmodmap
|
||||
└── .zshrc
|
||||
```
|
||||
|
||||
La idea es fácil, tres directorios principales: git, i3 y shells. En estos, se reproduce la estructura del directorio en el que querrás colocar las configuraciones. Por ejemplo, todas mis configuraciones van bajo el $HOME. Entonces, si yo quiero tener en mi $HOME el fichero `.alacritty.yml`, en el directorio shells lo pongo tal cual, en `.alacritty.yml`.
|
||||
|
||||
Cuando tienes la estructura hecha, solo queda ejecutar stow. En mi caso:
|
||||
|
||||
```bash
|
||||
stow -t ~ git
|
||||
stow -t ~ i3
|
||||
stow -t ~ shells
|
||||
```
|
||||
|
||||
Y ale, los dotfiles instalados.
|
||||
|
||||
PD: La parte de git no la veréis completa en mi repositorio, ya que ahí salen mi nombre real que uso tanto para el trabajo como para proyectos personales que hago bajo mi nombre. Pero el resto es tal cual.
|
||||
|
||||
|
||||
## Empaquetado {#empaquetado}
|
||||
|
||||
La idea es que todo esto sea fácil tanto de mantener como de instalar en un ordenador nuevo, por lo que habrá que usar algo de pegamento para unirlo. Por ello, he hecho un script que se puede consultar [aquí](https://git.disroot.org/drymer/dotfiles/src/branch/master/manage.sh). Nada como usar bash como buen pegamento.
|
||||
|
||||
Este script acepta los siguientes parámetros a día de hoy:
|
||||
|
||||
- ****install-packages****: Instalar todas las herramientas necesarias (aconfmgr, brew, yay y oh-my-zsh por que si).
|
||||
- ****diff-bundle****: Mostrar las diferencias en los paquetes instalados y los declarados.
|
||||
- ****apply-bundle****: Aplicar los paquetes declarados.
|
||||
- ****update-bundle****: Actualizar el sistema operativo.
|
||||
- ****dotfiles****: Instalar los dotfiles.
|
|
@ -4,7 +4,7 @@ author = ["drymer"]
|
|||
date = 2015-04-30T19:15:00+02:00
|
||||
draft = false
|
||||
tags = ["sysadmin", "elbinario"]
|
||||
url = "/posts/cosillas-de-emacs-escapar-simbolos-al-usar-usar-marcado-en-org-mode/"
|
||||
url = "/posts/spigot:-publicando-feeds-en-pump-io/"
|
||||
+++
|
||||
Andaba pensando en hacer algo similar a [gnusrss](https://elbinario.net/2015/02/11/gnusrss-publicando-feeds-en-gnu-social/) pero para [Pump.io](https://elbinario.net/?s%3Dpump), pero pude ahorrarmelo al preguntar en [la sala de redeslibres](https://www.mijabber.es/jappix/?r%3Dredeslibres@salas.mijabber.es) y saber de la existencia de [Spigot](https://pypi.python.org/pypi/spigot). Este programa hace lo que promete, publicar los feeds en Pump.io pero además con una particularidad, se encarga de hacerlo sin floodear la cuenta, por si el RSS en cuestión tiene muchas actualizaciones.
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<div itemprop="articleBody">
|
||||
{{ .Content }}
|
||||
|
||||
<div>Cualquier duda, se puede preguntar aquí o en los canales descritos en la <a href="/">página principal</a></div>
|
||||
<div>Cualquier duda o comentario, me puedes contactar en los canales descritos en la <a href="/">página principal</a></div>
|
||||
</div>
|
||||
<footer>
|
||||
<hr>
|
||||
|
|
|
@ -1,2 +1,82 @@
|
|||
img {width:100%;height: auto} .highlight,pre.highlight{background:#283c34;color:#abb2bf}.highlight pre{background:#282c34}.highlight .ge{font-style:italic}.highlight .gs{font-weight:700}.highlight .ow{font-weight:700}.highlight .n,.highlight .nf,.highlight .nn,.highlight .o,.highlight .p{color:#abb2bf}.highlight .c,.highlight .c1,.highlight .cm,.highlight .cp,.highlight .cs{color:#5c6370;font-style:italic}.highlight .sr,.highlight .ss{color:#56b6c2}.highlight .k,.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:#c678dd}.highlight .l,.highlight .ld,.highlight .s,.highlight .s1,.highlight .s2,.highlight .sb,.highlight .sc,.highlight .sd,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#98c379}.highlight .nt,.highlight .nx,.highlight .vi{color:#e06c75}.highlight .il,.highlight .m,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo,.highlight .na{color:#d19a66}.highlight .bp,.highlight .nb,.highlight .nc,.highlight .nd,.highlight .ne,.highlight .ni,.highlight .nl,.highlight .no,.highlight .nv,.highlight .py,.highlight .vc,.highlight .vg{color:#e5c07b}.highlight .err{color:#fff;background-color:#e05252}.highlight .gd{color:#e05252}.highlight .gi{color:#43d08a}.highlight .w{color:#f8f8f2}.highlight .cpf{color:navy}.highlight .gu{color:#75715e}.highlight .lineno{color:#636d83;user-select:none}.highlight .ln{color:#636d83;user-select:none}.highlight .ln:after{content:" "}.highlight .hll{color:#abb2bf;background-color:#3a3f4b}.highlight .hl{color:#abb2bf;background-color:#3a3f4b}.highlight .language-json .w+.s2{color:#e06c75}.highlight .language-json .kc{color:#56b6c2}
|
||||
|
||||
/* Background */ .chroma { color: #ffffff; background-color: #111111 }
|
||||
/* Other */ .chroma .x { }
|
||||
/* Error */ .chroma .err { }
|
||||
/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
|
||||
/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; }
|
||||
/* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc }
|
||||
/* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
|
||||
/* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
|
||||
/* Keyword */ .chroma .k { color: #fb660a; font-weight: bold }
|
||||
/* KeywordConstant */ .chroma .kc { color: #fb660a; font-weight: bold }
|
||||
/* KeywordDeclaration */ .chroma .kd { color: #fb660a; font-weight: bold }
|
||||
/* KeywordNamespace */ .chroma .kn { color: #fb660a; font-weight: bold }
|
||||
/* KeywordPseudo */ .chroma .kp { color: #fb660a }
|
||||
/* KeywordReserved */ .chroma .kr { color: #fb660a; font-weight: bold }
|
||||
/* KeywordType */ .chroma .kt { color: #cdcaa9; font-weight: bold }
|
||||
/* Name */ .chroma .n { }
|
||||
/* NameAttribute */ .chroma .na { color: #ff0086; font-weight: bold }
|
||||
/* NameBuiltin */ .chroma .nb { }
|
||||
/* NameBuiltinPseudo */ .chroma .bp { }
|
||||
/* NameClass */ .chroma .nc { }
|
||||
/* NameConstant */ .chroma .no { color: #0086d2 }
|
||||
/* NameDecorator */ .chroma .nd { }
|
||||
/* NameEntity */ .chroma .ni { }
|
||||
/* NameException */ .chroma .ne { }
|
||||
/* NameFunction */ .chroma .nf { color: #ff0086; font-weight: bold }
|
||||
/* NameFunctionMagic */ .chroma .fm { }
|
||||
/* NameLabel */ .chroma .nl { }
|
||||
/* NameNamespace */ .chroma .nn { }
|
||||
/* NameOther */ .chroma .nx { }
|
||||
/* NameProperty */ .chroma .py { }
|
||||
/* NameTag */ .chroma .nt { color: #fb660a; font-weight: bold }
|
||||
/* NameVariable */ .chroma .nv { color: #fb660a }
|
||||
/* NameVariableClass */ .chroma .vc { }
|
||||
/* NameVariableGlobal */ .chroma .vg { }
|
||||
/* NameVariableInstance */ .chroma .vi { }
|
||||
/* NameVariableMagic */ .chroma .vm { }
|
||||
/* Literal */ .chroma .l { }
|
||||
/* LiteralDate */ .chroma .ld { }
|
||||
/* LiteralString */ .chroma .s { color: #0086d2 }
|
||||
/* LiteralStringAffix */ .chroma .sa { color: #0086d2 }
|
||||
/* LiteralStringBacktick */ .chroma .sb { color: #0086d2 }
|
||||
/* LiteralStringChar */ .chroma .sc { color: #0086d2 }
|
||||
/* LiteralStringDelimiter */ .chroma .dl { color: #0086d2 }
|
||||
/* LiteralStringDoc */ .chroma .sd { color: #0086d2 }
|
||||
/* LiteralStringDouble */ .chroma .s2 { color: #0086d2 }
|
||||
/* LiteralStringEscape */ .chroma .se { color: #0086d2 }
|
||||
/* LiteralStringHeredoc */ .chroma .sh { color: #0086d2 }
|
||||
/* LiteralStringInterpol */ .chroma .si { color: #0086d2 }
|
||||
/* LiteralStringOther */ .chroma .sx { color: #0086d2 }
|
||||
/* LiteralStringRegex */ .chroma .sr { color: #0086d2 }
|
||||
/* LiteralStringSingle */ .chroma .s1 { color: #0086d2 }
|
||||
/* LiteralStringSymbol */ .chroma .ss { color: #0086d2 }
|
||||
/* LiteralNumber */ .chroma .m { color: #0086f7; font-weight: bold }
|
||||
/* LiteralNumberBin */ .chroma .mb { color: #0086f7; font-weight: bold }
|
||||
/* LiteralNumberFloat */ .chroma .mf { color: #0086f7; font-weight: bold }
|
||||
/* LiteralNumberHex */ .chroma .mh { color: #0086f7; font-weight: bold }
|
||||
/* LiteralNumberInteger */ .chroma .mi { color: #0086f7; font-weight: bold }
|
||||
/* LiteralNumberIntegerLong */ .chroma .il { color: #0086f7; font-weight: bold }
|
||||
/* LiteralNumberOct */ .chroma .mo { color: #0086f7; font-weight: bold }
|
||||
/* Operator */ .chroma .o { }
|
||||
/* OperatorWord */ .chroma .ow { }
|
||||
/* Punctuation */ .chroma .p { }
|
||||
/* Comment */ .chroma .c { color: #008800; background-color: #0f140f; font-style: italic }
|
||||
/* CommentHashbang */ .chroma .ch { color: #008800; background-color: #0f140f; font-style: italic }
|
||||
/* CommentMultiline */ .chroma .cm { color: #008800; background-color: #0f140f; font-style: italic }
|
||||
/* CommentSingle */ .chroma .c1 { color: #008800; background-color: #0f140f; font-style: italic }
|
||||
/* CommentSpecial */ .chroma .cs { color: #008800; background-color: #0f140f; font-style: italic }
|
||||
/* CommentPreproc */ .chroma .cp { color: #ff0007; background-color: #0f140f; font-weight: bold; font-style: italic }
|
||||
/* CommentPreprocFile */ .chroma .cpf { color: #ff0007; background-color: #0f140f; font-weight: bold; font-style: italic }
|
||||
/* Generic */ .chroma .g { }
|
||||
/* GenericDeleted */ .chroma .gd { }
|
||||
/* GenericEmph */ .chroma .ge { }
|
||||
/* GenericError */ .chroma .gr { }
|
||||
/* GenericHeading */ .chroma .gh { font-weight: bold }
|
||||
/* GenericInserted */ .chroma .gi { }
|
||||
/* GenericOutput */ .chroma .go { color: #444444; background-color: #222222 }
|
||||
/* GenericPrompt */ .chroma .gp { }
|
||||
/* GenericStrong */ .chroma .gs { }
|
||||
/* GenericSubheading */ .chroma .gu { font-weight: bold }
|
||||
/* GenericTraceback */ .chroma .gt { }
|
||||
/* GenericUnderline */ .chroma .gl { }
|
||||
/* TextWhitespace */ .chroma .w { color: #888888 }
|
||||
|
|
BIN
static/img/commitizen.gif
Normal file
BIN
static/img/commitizen.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 684 KiB |
Loading…
Reference in a new issue