|
| 1 | +% Aprendiendo un shell pythonico, xonsh, con anki |
| 2 | +% Daniel Sánchez |
| 3 | +% 16 de Noviembre, 2023 |
| 4 | + |
| 5 | +# ¿Quién soy yo? |
| 6 | + |
| 7 | +- 🧔🏻 Daniel Sánchez |
| 8 | +- Integrante de Python Vigo |
| 9 | +- Administrador de sistemas |
| 10 | +- pyvideo.org, pycon-es 2024 |
| 11 | + |
| 12 | +# Introducción |
| 13 | + |
| 14 | +- **Anki**: Aplicación de estudio basada en tarjetas |
| 15 | + - [https://apps.ankiweb.net/](https://apps.ankiweb.net/) |
| 16 | +- **Xonsh**: Lenguaje de shell basado en Python |
| 17 | + - [https://xon.sh](https://xon.sh) |
| 18 | + |
| 19 | +## Causa de la charla |
| 20 | + |
| 21 | +- Buscar herramientas (libres) de estudio para mi hija (tablet/chromebook) |
| 22 | +- Anki como aplicación para estudiar |
| 23 | +- Tomar de mi propia medicina con algo que quería aprender: Xonsh |
| 24 | + |
| 25 | +## Porqué en Python Vigo |
| 26 | + |
| 27 | +- Xonsh: Python en el shell |
| 28 | +- Anki: Somos "knowledge workers" |
| 29 | + |
| 30 | +# Anki |
| 31 | + |
| 32 | +- Tarjetas con pregunta/respuesta |
| 33 | +- Repetición espaciada: [https://ncase.me/remember](https://ncase.me/remember) |
| 34 | + |
| 35 | +## Repetición espaciada |
| 36 | + |
| 37 | +- Se basa en la `curva del olvido` propuesta por `Hermann Ebbinghaus`(1885). |
| 38 | +- Consiste en repasar en intervalos espaciados para maximizar $memorización/esfuerzo$. |
| 39 | +- Intervalos cada vez más largos para reducir tiempo de estudio y aumentar retención a largo plazo. |
| 40 | +- La tarjeta que olvidas vuelve al intervalo más corto. |
| 41 | + |
| 42 | +## Anki - Aplicación |
| 43 | + |
| 44 | +- Multiplataforma |
| 45 | +- Las tarjetas se agrupan en mazos (grupos, subgrupos, ...) |
| 46 | +- Puedes exportarlos a fichero o a la web de Anki |
| 47 | + |
| 48 | +## Creación de tarjetas - Fichero |
| 49 | + |
| 50 | +`~/ejemplo.md` |
| 51 | +``` sh |
| 52 | +# IT::Xonsh |
| 53 | + |
| 54 | +## Crear una variable de entorno en xonsh |
| 55 | + |
| 56 | +`$X = 1` |
| 57 | +``` |
| 58 | + |
| 59 | +## Creación de tarjetas - *.apkg |
| 60 | + |
| 61 | +``` sh |
| 62 | +pip install markdown-anki-decks |
| 63 | +mkdir input/ output/ |
| 64 | +cp ~/ejemplo.md input/ejemplo.md |
| 65 | +mdankideck input/ output/ # Crea output/ejemplo.apkg |
| 66 | +``` |
| 67 | + |
| 68 | +`ejemplo.apkg` es el mazo de tarjetas (deck) a cargar en anki |
| 69 | + |
| 70 | +## Muestra de tarjeta |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | +## markdown-anki-decks |
| 75 | + |
| 76 | +- Pros |
| 77 | + - Sencillo y efectivo |
| 78 | + - Soporta imagen y sonido (importante para estudiar idiomas) |
| 79 | +- Contras |
| 80 | + - Modificar equivale a crear una pregunta distinta |
| 81 | + - El mantenedor creó una startup y ya no responde |
| 82 | + |
| 83 | +## Consejos para crear tarjetas |
| 84 | + |
| 85 | +- Tu yo futuro no ha de decir: 🚽🪠💩💥🤬 |
| 86 | + - ¿Que me pregunta? |
| 87 | + - Se cosas de la pregunta ¿Porqué no me dice en concreto lo que quiere? |
| 88 | + - No me dice ni cuantas ni cuales. Pense tres apartados, pero eran 4. |
| 89 | +- La pregunta ha de guiar a una respuesta concreta |
| 90 | + |
| 91 | +## Nunca apetece estudiar |
| 92 | + |
| 93 | +- Adaptarlo a tu propia experienecia (Iterar) |
| 94 | + - Preparar las preguntas ya es aprender |
| 95 | + - Ver cuantas preguntas al día |
| 96 | + - Podar o reescribir lo que no convenza o ya no haga falta |
| 97 | + - Compartimentar en submódulos |
| 98 | + |
| 99 | +# Xonsh |
| 100 | + |
| 101 | +- Shell script mezcla de python y bash |
| 102 | +- No poner como default shell del usuario, sino del terminal. |
| 103 | + |
| 104 | +## Pros |
| 105 | + |
| 106 | +- Python |
| 107 | +- Prompt: Historial, Syntax highlighting, Tab completion |
| 108 | +- Globs: Clásico, python (\*\*), regexp (\`\`) |
| 109 | +- Cross-platform, ... |
| 110 | + |
| 111 | +## Contras |
| 112 | + |
| 113 | +- Utiliza más recursos que bash (180M vs 5M) |
| 114 | +- No es posix compliant |
| 115 | +- Añade sintaxis que no es ni bash ni python |
| 116 | + |
| 117 | +## Instalación |
| 118 | + |
| 119 | +``` sh |
| 120 | +python3 -m ensurepip --upgrade |
| 121 | +python3 -m pip install --upgrade pip pipx |
| 122 | +pipx install "xonsh[full]" |
| 123 | +# Si solo quieres probar: |
| 124 | +podman run -it --rm docker.io/xonsh/interactive |
| 125 | +``` |
| 126 | + |
| 127 | +xfce4-terminal → (Menú) Editar → Preferencias |
| 128 | + → General → Orden personalizada |
| 129 | + |
| 130 | +## Modo subproceso |
| 131 | + |
| 132 | +``` sh |
| 133 | +ls -l |
| 134 | +``` |
| 135 | +``` |
| 136 | +foo bar baz |
| 137 | +``` |
| 138 | + |
| 139 | +``` sh |
| 140 | +ls /proc/ | grep b | tr '\n' ' ' |
| 141 | +``` |
| 142 | +``` |
| 143 | +bootconfig buddyinfo bus dynamic_debug fb slabinfo |
| 144 | +``` |
| 145 | + |
| 146 | +## Modo python |
| 147 | + |
| 148 | +``` py |
| 149 | +2**12345 |
| 150 | +``` |
| 151 | + |
| 152 | +``` |
| 153 | +16417101068825821635602074166390650141012723553073588127211610308792509417139014 |
| 154 | +42801590345364394577348704191271404016671955103310856571853327210892364011930444 |
| 155 | +93457116299768844344303479235489462436380672117015123283299131391904179287678259 |
| 156 | +17330853673876198113995865488085223490844833881728901416677416986925133937982859 |
| 157 | +97484929187754378647390322177780513338829900741162462812693649337248923421345047 |
| 158 | +02491040016637557429810893780765197418589477584716543480995722533317862352141459 |
| 159 | +21778131626621118648615701926208041407767026464273601842699811352344573268085614 |
| 160 | +43298769722733007033925849977292071979710839457003454940924001471869973070120694 |
| 161 | +54068489589035676979448169848060836924945824197706493306108258511936030341393221 |
| 162 | +58642352326445244940378199335242188509466405227079552763272189612142481317352247 |
| 163 | +46743958861550922034040367307484747817107157454461354680981398318240832596479191 |
| 164 | +75273503681561172684624283384438504776503000432241604550454374116320822227191911 |
| 165 | +32212348408506392635060634219714640784117802807114719253394251727055351398814292 |
| 166 | +59760907696954562211596990525835330113316520793470930981730869754835392744640233 |
| 167 | +57456484465482927479569437320368592222760278170306076733438801098370797675711274 |
| 168 | +67105497071144215893056168434313577411874159450670283314739675882501585004298334 |
| 169 | +36903451859959562351438257716205435460306645626478546564313026445741198738202155 |
| 170 | +95718618624485232422006575550007068883734241454686368856734496265385908809403972 |
| 171 | +49468513774112286689671967805393728581840975167032014050184303922404073587009688 |
| 172 | +95962734191063891036620953189379906259801367119882374219623152666868560895059814 |
| 173 | +38440850638067589321141759499017023839596858455548192000140085142294166987063499 |
| 174 | +02479268133484315979093632135191985975866956920054150761209978090970519890217602 |
| 175 | +62198722017154220960903436862729843514415945695067780410626632667993427938563138 |
| 176 | +01540959815845788584759033248828248561586450271172777240971795656082001848115815 |
| 177 | +26093052166316748017388606401911857277828151673515777955588816778706443255859541 |
| 178 | +08439874464978816662884232331700604130259246299504773033421801493989260736185827 |
| 179 | +15358742250388958231281694757980523791263699450732952325727664209947786063982561 |
| 180 | +77532763850451691857010131939169841238860760374248441474826838966912911802687896 |
| 181 | +97357822868411168426564105746476075244189007203280453779933862798087689903762894 |
| 182 | +24757351052369393977137871998119168898493037938756635621557623138404459266598837 |
| 183 | +78422932579983878202606048149686556175703183900225709180287694924839274417566911 |
| 184 | +22420884398832483363105970012573859807769615293511988777471935310549568818083321 |
| 185 | +77946751404038228718567911769630971553915410012677600002457982207465176670752102 |
| 186 | +11700277398054808969653097247643969459988128181297321726585388472790653547974585 |
| 187 | +40853388511051445854819941562064974367458999448777325314125412790143003245948906 |
| 188 | +23941145509856940982863769834430048120562966797907114102689879364945689860493474 |
| 189 | +95453842236771950788251316605100735299406831925145066667664836820056432938299875 |
| 190 | +88757604142596540049772613099882673198063548560517845539909366106347333759841590 |
| 191 | +28722378614984450255386315585631994503350002142910493190254825610707400589976364 |
| 192 | +98574846795513107797164188267289585457123636828281133622076917478472011333126908 |
| 193 | +47465242041242634750541128416309335861661950361156964696860756004804205635575676 |
| 194 | +16835633252622327172811002146392754445051182169805284630259703542633955126179520 |
| 195 | +11305962991422983368853592572967677802840689731610610103846911909098456715259196 |
| 196 | +23654150396463945915038307976263392469860570777586114136649141687453752667862981 |
| 197 | +41171496573941614387744125843685677063619782918759823106021054037757857761587472 |
| 198 | +24083504058044736054402906493041256994316972923810216231221868793020306805540027 |
| 199 | +5795180972382856696655279408212344832 |
| 200 | +``` |
| 201 | + |
| 202 | +## Modo python |
| 203 | + |
| 204 | +``` py |
| 205 | +import sys |
| 206 | +sys.version |
| 207 | +``` |
| 208 | +``` |
| 209 | +'3.12.0 (main, Oct 2 2023, 00:00:00) [GCC 13.2.1 20230918 (Red Hat 13.2.1-3)]' |
| 210 | +``` |
| 211 | + |
| 212 | +## Modo python |
| 213 | + |
| 214 | +(En Xonsh) Python siempre gana :) |
| 215 | + |
| 216 | +``` py |
| 217 | +ls, l = 68,26 |
| 218 | +ls -l |
| 219 | +``` |
| 220 | + |
| 221 | +``` |
| 222 | +42 |
| 223 | +``` |
| 224 | + |
| 225 | +``` py |
| 226 | +del ls, l |
| 227 | +``` |
| 228 | + |
| 229 | +## Variables de entorno (modo subproceso) |
| 230 | + |
| 231 | +``` sh |
| 232 | +$HOME |
| 233 | +# Específico de Xonsh |
| 234 | +expresion_python = "HOME" |
| 235 | +${expresion_python} |
| 236 | +${...} |
| 237 | +``` |
| 238 | + |
| 239 | +## Truco. Pedir clave y que solo sea accesible en un bloque with |
| 240 | + |
| 241 | +``` sh |
| 242 | +import getpass |
| 243 | +with ${...}.swap(PASS=getpass.getpass()): |
| 244 | + echo $PASS |
| 245 | +``` |
| 246 | + |
| 247 | +## Usando shell dentro de python |
| 248 | + |
| 249 | +``` sh |
| 250 | +$(comando) ; !(comando) # Capturando stdout |
| 251 | +$[comando] ; ![comando] # Sin capturar stdout |
| 252 | +``` |
| 253 | + |
| 254 | +## Usando python dentro de shell |
| 255 | + |
| 256 | +``` sh |
| 257 | +${expresion_python} # Stdout como nombre de variable |
| 258 | +@(expresion_python) # La salida se usa como un token o una lista de tokens |
| 259 | +``` |
| 260 | + |
| 261 | +## Usando shell dentro de shell, pasando por python |
| 262 | + |
| 263 | +``` sh |
| 264 | +@$(comando) # La salida del comando da otro comando, que es ejecutado |
| 265 | +``` |
| 266 | + |
| 267 | +## Ejemplo |
| 268 | + |
| 269 | +``` py |
| 270 | +for x in list(set($(man bash).split()))[:300]: |
| 271 | + if x.isalnum(): |
| 272 | + touch @(x) |
| 273 | +``` |
| 274 | + |
| 275 | +## Anidando subprocesos |
| 276 | + |
| 277 | +``` sh |
| 278 | +echo @("file." + $(date -I).strip() + ".bak") |
| 279 | +``` |
| 280 | +
|
| 281 | +## Strings avanzados |
| 282 | +
|
| 283 | +| Nativo | Icono | Transformación | |
| 284 | +| ------ | ------- | --------------------------------- | |
| 285 | +| 🐍 | \\ | Backslash escapes | |
| 286 | +| 🐍 | 🔄 {} | Sustituye expresiones entre {} | |
| 287 | +| 🐚 | 🔄 $VAR | Sustituye $VAR en modo subproceso | |
| 288 | +| 🐚 | / | Devuelve un pathlib.Path | |
| 289 | +
|
| 290 | +## Strings avanzados |
| 291 | +
|
| 292 | +| String | Tipo | |
| 293 | +| -------- | ----------------------- | |
| 294 | +| ` ""` | 🐍regular string | |
| 295 | +| ` r""` | 🐍raw string | |
| 296 | +| ` f""` | 🐍formatted string | |
| 297 | +| `fr""` | 🐚raw formatted string | |
| 298 | +| ` p""` | 🐚path string | |
| 299 | +| `pr""` | 🐚raw Path string | |
| 300 | +| `pf""` | 🐚formatted Path string | |
| 301 | +
|
| 302 | +## Strings avanzados |
| 303 | +
|
| 304 | +| String | \ | 🔄 $VAR | 🔄 {} | /path | |
| 305 | +| -------- | ---- | ------- | ----- | ----- | |
| 306 | +| ` ""` | ✅ | ✅ | ❌ | ❌ | |
| 307 | +| ` r""` | ❌Ⓡ | ❌Ⓡ | ❌ | ❌ | |
| 308 | +| ` f""` | ✅ | ✅ | ✅Ⓕ | ❌ | |
| 309 | +| `fr""` | ❌Ⓡ | ❌Ⓡ | ✅Ⓕ | ❌ | |
| 310 | +| ` p""` | ✅ | ✅Ⓟ | ❌ | ✅Ⓟ | |
| 311 | +| `pr""` | ❌Ⓡ | ✅Ⓟ | ❌ | ✅Ⓟ | |
| 312 | +| `pf""` | ✅ | ✅Ⓟ | ✅Ⓕ | ✅Ⓟ | |
| 313 | +
|
| 314 | +## Globs |
| 315 | +
|
| 316 | +| Representación | Tipo de glob | |
| 317 | +| -------------- | --------------------- | |
| 318 | +| `*` | Shell glob | |
| 319 | +| `**` | Python glob | |
| 320 | +
|
| 321 | +## Globs |
| 322 | +
|
| 323 | +| Representación | Tipo de glob | |
| 324 | +| ------------------------ | --------------------- | |
| 325 | +| ``` `` ``` | Regexp glob | |
| 326 | +| ``` f`` ``` | Formatted regexp glob | |
| 327 | +| ``` p`` ``` | Path regexp glob | |
| 328 | +| ``` g`` ``` | Shell glob | |
| 329 | +| ``` fg`` ``` | Formatted shell glob | |
| 330 | +| ``` pg`` ``` | Path shell glob | |
| 331 | +| ``` @<func_name>`test` ``` | Custom glob | |
| 332 | +
|
| 333 | +## Help → ? |
| 334 | +
|
| 335 | +Ayuda de objetos y métodos de python |
| 336 | +``` sh |
| 337 | +"".join ? # Muestra help(join) |
| 338 | +aliases['showcmd'] ?? # Muestra ayuda y fuente |
| 339 | +``` |
| 340 | +
|
| 341 | +## aliases |
| 342 | +
|
| 343 | +```py |
| 344 | +aliases['piu'] = 'pip install -U @($args)' |
| 345 | +``` |
| 346 | +
|
| 347 | +# Bill of materials |
| 348 | +
|
| 349 | +- Pandoc: |
| 350 | +``` sh |
| 351 | +pandoc --standalone --mathjax --slide-level 2 --write=revealjs \ |
| 352 | + charla.md --output=charla.html |
| 353 | +``` |
| 354 | +- Reveal.js |
| 355 | +- Xonsh |
| 356 | +- Anki |
| 357 | +- markdown-anki-decks |
| 358 | +- fedora kinoite |
0 commit comments