From b657968a1d70dce9ec19976cc62fcc6bddd90a83 Mon Sep 17 00:00:00 2001 From: Daniel-at-github Date: Thu, 27 Feb 2025 18:52:18 +0100 Subject: [PATCH] Add Xonsh + Anki talk --- .../README.md" | 7 + .../charla.md" | 358 ++++++++ .../site/index.html" | 776 ++++++++++++++++++ .../site/media/anki.jpg" | Bin 0 -> 29329 bytes README.rst | 4 + docs/index.rst | 4 + 6 files changed, 1149 insertions(+) create mode 100644 "2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/README.md" create mode 100644 "2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/charla.md" create mode 100644 "2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/site/index.html" create mode 100644 "2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/site/media/anki.jpg" diff --git "a/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/README.md" "b/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/README.md" new file mode 100644 index 0000000..821c19a --- /dev/null +++ "b/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/README.md" @@ -0,0 +1,7 @@ +# Descripción + +Cómo utilizar repetición espaciada con Anki para aprender Xonsh, el lenguaje de shell basado en Python. + +# Presentación + +https://daniel-at-github.github.io/charla_xonsh/site/ diff --git "a/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/charla.md" "b/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/charla.md" new file mode 100644 index 0000000..b802166 --- /dev/null +++ "b/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/charla.md" @@ -0,0 +1,358 @@ +% Aprendiendo un shell pythonico, xonsh, con anki +% Daniel Sánchez +% 16 de Noviembre, 2023 + +# ¿Quién soy yo? + +- 🧔🏻 Daniel Sánchez +- Integrante de Python Vigo +- Administrador de sistemas +- pyvideo.org, pycon-es 2024 + +# Introducción + +- **Anki**: Aplicación de estudio basada en tarjetas + - [https://apps.ankiweb.net/](https://apps.ankiweb.net/) +- **Xonsh**: Lenguaje de shell basado en Python + - [https://xon.sh](https://xon.sh) + +## Causa de la charla + +- Buscar herramientas (libres) de estudio para mi hija (tablet/chromebook) +- Anki como aplicación para estudiar +- Tomar de mi propia medicina con algo que quería aprender: Xonsh + +## Porqué en Python Vigo + +- Xonsh: Python en el shell +- Anki: Somos "knowledge workers" + +# Anki + +- Tarjetas con pregunta/respuesta +- Repetición espaciada: [https://ncase.me/remember](https://ncase.me/remember) + +## Repetición espaciada + +- Se basa en la `curva del olvido` propuesta por `Hermann Ebbinghaus`(1885). +- Consiste en repasar en intervalos espaciados para maximizar $memorización/esfuerzo$. +- Intervalos cada vez más largos para reducir tiempo de estudio y aumentar retención a largo plazo. +- La tarjeta que olvidas vuelve al intervalo más corto. + +## Anki - Aplicación + +- Multiplataforma +- Las tarjetas se agrupan en mazos (grupos, subgrupos, ...) +- Puedes exportarlos a fichero o a la web de Anki + +## Creación de tarjetas - Fichero + +`~/ejemplo.md` +``` sh +# IT::Xonsh + +## Crear una variable de entorno en xonsh + +`$X = 1` +``` + +## Creación de tarjetas - *.apkg + +``` sh +pip install markdown-anki-decks +mkdir input/ output/ +cp ~/ejemplo.md input/ejemplo.md +mdankideck input/ output/ # Crea output/ejemplo.apkg +``` + +`ejemplo.apkg` es el mazo de tarjetas (deck) a cargar en anki + +## Muestra de tarjeta + +![Imagen de tarjeta de Anki](media/anki.jpg) + +## markdown-anki-decks + +- Pros + - Sencillo y efectivo + - Soporta imagen y sonido (importante para estudiar idiomas) +- Contras + - Modificar equivale a crear una pregunta distinta + - El mantenedor creó una startup y ya no responde + +## Consejos para crear tarjetas + +- Tu yo futuro no ha de decir: 🚽🪠💩💥🤬 + - ¿Que me pregunta? + - Se cosas de la pregunta ¿Porqué no me dice en concreto lo que quiere? + - No me dice ni cuantas ni cuales. Pense tres apartados, pero eran 4. +- La pregunta ha de guiar a una respuesta concreta + +## Nunca apetece estudiar + +- Adaptarlo a tu propia experienecia (Iterar) + - Preparar las preguntas ya es aprender + - Ver cuantas preguntas al día + - Podar o reescribir lo que no convenza o ya no haga falta + - Compartimentar en submódulos + +# Xonsh + +- Shell script mezcla de python y bash +- No poner como default shell del usuario, sino del terminal. + +## Pros + +- Python +- Prompt: Historial, Syntax highlighting, Tab completion +- Globs: Clásico, python (\*\*), regexp (\`\`) +- Cross-platform, ... + +## Contras + +- Utiliza más recursos que bash (180M vs 5M) +- No es posix compliant +- Añade sintaxis que no es ni bash ni python + +## Instalación + +``` sh +python3 -m ensurepip --upgrade +python3 -m pip install --upgrade pip pipx +pipx install "xonsh[full]" +# Si solo quieres probar: +podman run -it --rm docker.io/xonsh/interactive +``` + +xfce4-terminal → (Menú) Editar → Preferencias + → General → Orden personalizada + +## Modo subproceso + +``` sh +ls -l +``` +``` +foo bar baz +``` + +``` sh +ls /proc/ | grep b | tr '\n' ' ' +``` +``` +bootconfig buddyinfo bus dynamic_debug fb slabinfo +``` + +## Modo python + +``` py +2**12345 +``` + +``` +16417101068825821635602074166390650141012723553073588127211610308792509417139014 +42801590345364394577348704191271404016671955103310856571853327210892364011930444 +93457116299768844344303479235489462436380672117015123283299131391904179287678259 +17330853673876198113995865488085223490844833881728901416677416986925133937982859 +97484929187754378647390322177780513338829900741162462812693649337248923421345047 +02491040016637557429810893780765197418589477584716543480995722533317862352141459 +21778131626621118648615701926208041407767026464273601842699811352344573268085614 +43298769722733007033925849977292071979710839457003454940924001471869973070120694 +54068489589035676979448169848060836924945824197706493306108258511936030341393221 +58642352326445244940378199335242188509466405227079552763272189612142481317352247 +46743958861550922034040367307484747817107157454461354680981398318240832596479191 +75273503681561172684624283384438504776503000432241604550454374116320822227191911 +32212348408506392635060634219714640784117802807114719253394251727055351398814292 +59760907696954562211596990525835330113316520793470930981730869754835392744640233 +57456484465482927479569437320368592222760278170306076733438801098370797675711274 +67105497071144215893056168434313577411874159450670283314739675882501585004298334 +36903451859959562351438257716205435460306645626478546564313026445741198738202155 +95718618624485232422006575550007068883734241454686368856734496265385908809403972 +49468513774112286689671967805393728581840975167032014050184303922404073587009688 +95962734191063891036620953189379906259801367119882374219623152666868560895059814 +38440850638067589321141759499017023839596858455548192000140085142294166987063499 +02479268133484315979093632135191985975866956920054150761209978090970519890217602 +62198722017154220960903436862729843514415945695067780410626632667993427938563138 +01540959815845788584759033248828248561586450271172777240971795656082001848115815 +26093052166316748017388606401911857277828151673515777955588816778706443255859541 +08439874464978816662884232331700604130259246299504773033421801493989260736185827 +15358742250388958231281694757980523791263699450732952325727664209947786063982561 +77532763850451691857010131939169841238860760374248441474826838966912911802687896 +97357822868411168426564105746476075244189007203280453779933862798087689903762894 +24757351052369393977137871998119168898493037938756635621557623138404459266598837 +78422932579983878202606048149686556175703183900225709180287694924839274417566911 +22420884398832483363105970012573859807769615293511988777471935310549568818083321 +77946751404038228718567911769630971553915410012677600002457982207465176670752102 +11700277398054808969653097247643969459988128181297321726585388472790653547974585 +40853388511051445854819941562064974367458999448777325314125412790143003245948906 +23941145509856940982863769834430048120562966797907114102689879364945689860493474 +95453842236771950788251316605100735299406831925145066667664836820056432938299875 +88757604142596540049772613099882673198063548560517845539909366106347333759841590 +28722378614984450255386315585631994503350002142910493190254825610707400589976364 +98574846795513107797164188267289585457123636828281133622076917478472011333126908 +47465242041242634750541128416309335861661950361156964696860756004804205635575676 +16835633252622327172811002146392754445051182169805284630259703542633955126179520 +11305962991422983368853592572967677802840689731610610103846911909098456715259196 +23654150396463945915038307976263392469860570777586114136649141687453752667862981 +41171496573941614387744125843685677063619782918759823106021054037757857761587472 +24083504058044736054402906493041256994316972923810216231221868793020306805540027 +5795180972382856696655279408212344832 +``` + +## Modo python + +``` py +import sys +sys.version +``` +``` +'3.12.0 (main, Oct 2 2023, 00:00:00) [GCC 13.2.1 20230918 (Red Hat 13.2.1-3)]' +``` + +## Modo python + +(En Xonsh) Python siempre gana :) + +``` py +ls, l = 68,26 +ls -l +``` + +``` +42 +``` + +``` py +del ls, l +``` + +## Variables de entorno (modo subproceso) + +``` sh +$HOME +# Específico de Xonsh +expresion_python = "HOME" +${expresion_python} +${...} +``` + +## Truco. Pedir clave y que solo sea accesible en un bloque with + +``` sh +import getpass +with ${...}.swap(PASS=getpass.getpass()): + echo $PASS +``` + +## Usando shell dentro de python + +``` sh +$(comando) ; !(comando) # Capturando stdout +$[comando] ; ![comando] # Sin capturar stdout +``` + +## Usando python dentro de shell + +``` sh +${expresion_python} # Stdout como nombre de variable +@(expresion_python) # La salida se usa como un token o una lista de tokens +``` + +## Usando shell dentro de shell, pasando por python + +``` sh +@$(comando) # La salida del comando da otro comando, que es ejecutado +``` + +## Ejemplo + +``` py +for x in list(set($(man bash).split()))[:300]: + if x.isalnum(): + touch @(x) +``` + +## Anidando subprocesos + +``` sh +echo @("file." + $(date -I).strip() + ".bak") +``` + +## Strings avanzados + +| Nativo | Icono | Transformación | +| ------ | ------- | --------------------------------- | +| 🐍 | \\ | Backslash escapes | +| 🐍 | 🔄 {} | Sustituye expresiones entre {} | +| 🐚 | 🔄 $VAR | Sustituye $VAR en modo subproceso | +| 🐚 | / | Devuelve un pathlib.Path | + +## Strings avanzados + +| String | Tipo | +| -------- | ----------------------- | +| ` ""` | 🐍regular string | +| ` r""` | 🐍raw string | +| ` f""` | 🐍formatted string | +| `fr""` | 🐚raw formatted string | +| ` p""` | 🐚path string | +| `pr""` | 🐚raw Path string | +| `pf""` | 🐚formatted Path string | + +## Strings avanzados + +| String | \ | 🔄 $VAR | 🔄 {} | /path | +| -------- | ---- | ------- | ----- | ----- | +| ` ""` | ✅ | ✅ | ❌ | ❌ | +| ` r""` | ❌Ⓡ | ❌Ⓡ | ❌ | ❌ | +| ` f""` | ✅ | ✅ | ✅Ⓕ | ❌ | +| `fr""` | ❌Ⓡ | ❌Ⓡ | ✅Ⓕ | ❌ | +| ` p""` | ✅ | ✅Ⓟ | ❌ | ✅Ⓟ | +| `pr""` | ❌Ⓡ | ✅Ⓟ | ❌ | ✅Ⓟ | +| `pf""` | ✅ | ✅Ⓟ | ✅Ⓕ | ✅Ⓟ | + +## Globs + +| Representación | Tipo de glob | +| -------------- | --------------------- | +| `*` | Shell glob | +| `**` | Python glob | + +## Globs + +| Representación | Tipo de glob | +| ------------------------ | --------------------- | +| ``` `` ``` | Regexp glob | +| ``` f`` ``` | Formatted regexp glob | +| ``` p`` ``` | Path regexp glob | +| ``` g`` ``` | Shell glob | +| ``` fg`` ``` | Formatted shell glob | +| ``` pg`` ``` | Path shell glob | +| ``` @`test` ``` | Custom glob | + +## Help → ? + +Ayuda de objetos y métodos de python +``` sh +"".join ? # Muestra help(join) +aliases['showcmd'] ?? # Muestra ayuda y fuente +``` + +## aliases + +```py +aliases['piu'] = 'pip install -U @($args)' +``` + +# Bill of materials + +- Pandoc: +``` sh +pandoc --standalone --mathjax --slide-level 2 --write=revealjs \ + charla.md --output=charla.html +``` +- Reveal.js +- Xonsh +- Anki +- markdown-anki-decks +- fedora kinoite diff --git "a/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/site/index.html" "b/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/site/index.html" new file mode 100644 index 0000000..ec13d66 --- /dev/null +++ "b/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/site/index.html" @@ -0,0 +1,776 @@ + + + + + + + Aprendiendo un shell pythonico, xonsh, con anki + + + + + + + + + +
+
+ +
+

Aprendiendo un shell pythonico, xonsh, con anki

+

Daniel Sánchez

+

16 de Noviembre, 2023

+
+ +
+

¿Quién soy yo?

+
    +
  • 🧔🏻 Daniel Sánchez
  • +
  • Integrante de Python Vigo
  • +
  • Administrador de sistemas
  • +
  • pyvideo.org, pycon-es 2024
  • +
+
+ +
+
+

Introducción

+ +
+
+

Causa de la charla

+
    +
  • Buscar herramientas (libres) de estudio para mi hija (tablet/chromebook)
  • +
  • Anki como aplicación para estudiar
  • +
  • Tomar de mi propia medicina con algo que quería aprender: Xonsh
  • +
+
+
+

Porqué en Python Vigo

+
    +
  • Xonsh: Python en el shell
  • +
  • Anki: Somos “knowledge workers”
  • +
+
+
+
+

Anki

+ +
+
+

Repetición espaciada

+
    +
  • Se basa en la curva del olvido propuesta por Hermann Ebbinghaus(1885).
  • +
  • Consiste en repasar en intervalos espaciados para maximizar \(memorización/esfuerzo\).
  • +
  • Intervalos cada vez más largos para reducir tiempo de estudio y aumentar retención a largo plazo.
  • +
  • La tarjeta que olvidas vuelve al intervalo más corto.
  • +
+
+
+

Anki - Aplicación

+
    +
  • Multiplataforma
  • +
  • Las tarjetas se agrupan en mazos (grupos, subgrupos, …)
  • +
  • Puedes exportarlos a fichero o a la web de Anki
  • +
+
+
+

Creación de tarjetas - Fichero

+

~/ejemplo.md

+
# IT::Xonsh
+
+## Crear una variable de entorno en xonsh
+
+`$X = 1`
+
+
+

Creación de tarjetas - *.apkg

+
pip install markdown-anki-decks
+mkdir input/ output/
+cp ~/ejemplo.md input/ejemplo.md
+mdankideck input/ output/ # Crea output/ejemplo.apkg
+

ejemplo.apkg es el mazo de tarjetas (deck) a cargar en anki

+
+
+

Muestra de tarjeta

+
+Imagen de tarjeta de Anki +
+
+
+

markdown-anki-decks

+
    +
  • Pros +
      +
    • Sencillo y efectivo
    • +
    • Soporta imagen y sonido (importante para estudiar idiomas)
    • +
  • +
  • Contras +
      +
    • Modificar equivale a crear una pregunta distinta
    • +
    • El mantenedor creó una startup y ya no responde
    • +
  • +
+
+
+

Consejos para crear tarjetas

+
    +
  • Tu yo futuro no ha de decir: 🚽🪠💩💥🤬 +
      +
    • ¿Que me pregunta?
    • +
    • Se cosas de la pregunta ¿Porqué no me dice en concreto lo que quiere?
    • +
    • No me dice ni cuantas ni cuales. Pense tres apartados, pero eran 4.
    • +
  • +
  • La pregunta ha de guiar a una respuesta concreta
  • +
+
+
+

Nunca apetece estudiar

+
    +
  • Adaptarlo a tu propia experienecia (Iterar) +
      +
    • Preparar las preguntas ya es aprender
    • +
    • Ver cuantas preguntas al día
    • +
    • Podar o reescribir lo que no convenza o ya no haga falta
    • +
    • Compartimentar en submódulos
    • +
  • +
+
+
+
+

Xonsh

+
    +
  • Shell script mezcla de python y bash
  • +
  • No poner como default shell del usuario, sino del terminal.
  • +
+
+
+

Pros

+
    +
  • Python
  • +
  • Prompt: Historial, Syntax highlighting, Tab completion
  • +
  • Globs: Clásico, python (**), regexp (``)
  • +
  • Cross-platform, …
  • +
+
+
+

Contras

+
    +
  • Utiliza más recursos que bash (180M vs 5M)
  • +
  • No es posix compliant
  • +
  • Añade sintaxis que no es ni bash ni python
  • +
+
+
+

Instalación

+
python3 -m ensurepip --upgrade
+python3 -m pip install --upgrade pip pipx
+pipx install "xonsh[full]"
+# Si solo quieres probar:
+podman run -it --rm docker.io/xonsh/interactive
+

xfce4-terminal → (Menú) Editar → Preferencias → General → Orden personalizada

+
+
+

Modo subproceso

+
ls -l
+
foo bar baz
+
ls /proc/ | grep b | tr '\n' ' '
+
bootconfig buddyinfo bus dynamic_debug fb slabinfo
+
+
+

Modo python

+
2**12345
+
16417101068825821635602074166390650141012723553073588127211610308792509417139014
+42801590345364394577348704191271404016671955103310856571853327210892364011930444
+93457116299768844344303479235489462436380672117015123283299131391904179287678259
+17330853673876198113995865488085223490844833881728901416677416986925133937982859
+97484929187754378647390322177780513338829900741162462812693649337248923421345047
+02491040016637557429810893780765197418589477584716543480995722533317862352141459
+21778131626621118648615701926208041407767026464273601842699811352344573268085614
+43298769722733007033925849977292071979710839457003454940924001471869973070120694
+54068489589035676979448169848060836924945824197706493306108258511936030341393221
+58642352326445244940378199335242188509466405227079552763272189612142481317352247
+46743958861550922034040367307484747817107157454461354680981398318240832596479191
+75273503681561172684624283384438504776503000432241604550454374116320822227191911
+32212348408506392635060634219714640784117802807114719253394251727055351398814292
+59760907696954562211596990525835330113316520793470930981730869754835392744640233
+57456484465482927479569437320368592222760278170306076733438801098370797675711274
+67105497071144215893056168434313577411874159450670283314739675882501585004298334
+36903451859959562351438257716205435460306645626478546564313026445741198738202155
+95718618624485232422006575550007068883734241454686368856734496265385908809403972
+49468513774112286689671967805393728581840975167032014050184303922404073587009688
+95962734191063891036620953189379906259801367119882374219623152666868560895059814
+38440850638067589321141759499017023839596858455548192000140085142294166987063499
+02479268133484315979093632135191985975866956920054150761209978090970519890217602
+62198722017154220960903436862729843514415945695067780410626632667993427938563138
+01540959815845788584759033248828248561586450271172777240971795656082001848115815
+26093052166316748017388606401911857277828151673515777955588816778706443255859541
+08439874464978816662884232331700604130259246299504773033421801493989260736185827
+15358742250388958231281694757980523791263699450732952325727664209947786063982561
+77532763850451691857010131939169841238860760374248441474826838966912911802687896
+97357822868411168426564105746476075244189007203280453779933862798087689903762894
+24757351052369393977137871998119168898493037938756635621557623138404459266598837
+78422932579983878202606048149686556175703183900225709180287694924839274417566911
+22420884398832483363105970012573859807769615293511988777471935310549568818083321
+77946751404038228718567911769630971553915410012677600002457982207465176670752102
+11700277398054808969653097247643969459988128181297321726585388472790653547974585
+40853388511051445854819941562064974367458999448777325314125412790143003245948906
+23941145509856940982863769834430048120562966797907114102689879364945689860493474
+95453842236771950788251316605100735299406831925145066667664836820056432938299875
+88757604142596540049772613099882673198063548560517845539909366106347333759841590
+28722378614984450255386315585631994503350002142910493190254825610707400589976364
+98574846795513107797164188267289585457123636828281133622076917478472011333126908
+47465242041242634750541128416309335861661950361156964696860756004804205635575676
+16835633252622327172811002146392754445051182169805284630259703542633955126179520
+11305962991422983368853592572967677802840689731610610103846911909098456715259196
+23654150396463945915038307976263392469860570777586114136649141687453752667862981
+41171496573941614387744125843685677063619782918759823106021054037757857761587472
+24083504058044736054402906493041256994316972923810216231221868793020306805540027
+5795180972382856696655279408212344832
+
+
+

Modo python

+
import sys
+sys.version
+
'3.12.0 (main, Oct  2 2023, 00:00:00) [GCC 13.2.1 20230918 (Red Hat 13.2.1-3)]'
+
+
+

Modo python

+

(En Xonsh) Python siempre gana :)

+
ls, l = 68,26
+ls -l
+
42
+
del ls, l
+
+
+

Variables de entorno (modo subproceso)

+
$HOME
+# Específico de Xonsh
+expresion_python = "HOME"
+${expresion_python}
+${...}
+
+
+

Truco. Pedir clave y que solo sea accesible en un bloque with

+
import getpass
+with ${...}.swap(PASS=getpass.getpass()):
+  echo $PASS
+
+
+

Usando shell dentro de python

+
$(comando) ; !(comando) # Capturando stdout
+$[comando] ; ![comando] # Sin capturar stdout
+
+
+

Usando python dentro de shell

+
${expresion_python} # Stdout como nombre de variable
+@(expresion_python) # La salida se usa como un token o una lista de tokens
+
+
+

Usando shell dentro de shell, pasando por python

+
@$(comando) # La salida del comando da otro comando, que es ejecutado
+
+
+

Ejemplo

+
for x in list(set($(man bash).split()))[:300]:
+    if x.isalnum():
+        touch @(x)
+
+
+

Anidando subprocesos

+
echo @("file." + $(date -I).strip() + ".bak")
+
+
+

Strings avanzados

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NativoIconoTransformación
🐍\Backslash escapes
🐍🔄 {}Sustituye expresiones entre {}
🐚🔄 $VARSustituye $VAR en modo subproceso
🐚/Devuelve un pathlib.Path
+
+
+

Strings avanzados

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StringTipo
""🐍regular string
r""🐍raw string
f""🐍formatted string
fr""🐚raw formatted string
p""🐚path string
pr""🐚raw Path string
pf""🐚formatted Path string
+
+
+

Strings avanzados

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
String\🔄 $VAR🔄 {}/path
""
r""❌Ⓡ❌Ⓡ
f""✅Ⓕ
fr""❌Ⓡ❌Ⓡ✅Ⓕ
p""✅Ⓟ✅Ⓟ
pr""❌Ⓡ✅Ⓟ✅Ⓟ
pf""✅Ⓟ✅Ⓕ✅Ⓟ
+
+
+

Globs

+ + + + + + + + + + + + + + + + + +
RepresentaciónTipo de glob
*Shell glob
**Python glob
+
+
+

Globs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RepresentaciónTipo de glob
``Regexp glob
f``Formatted regexp glob
p``Path regexp glob
g``Shell glob
fg``Formatted shell glob
pg``Path shell glob
@<func_name>`test`Custom glob
+
+
+

Help → ?

+

Ayuda de objetos y métodos de python

+
"".join ? # Muestra help(join)
+aliases['showcmd'] ?? # Muestra ayuda y fuente
+
+
+

aliases

+
aliases['piu'] = 'pip install -U @($args)'
+
+
+

Bill of materials

+
    +
  • Pandoc:
  • +
+
pandoc --standalone --mathjax --slide-level 2 --write=revealjs \
+  charla.md --output=charla.html
+
    +
  • Reveal.js
  • +
  • Xonsh
  • +
  • Anki
  • +
  • markdown-anki-decks
  • +
  • fedora kinoite
  • +
+
+
+
+ + + + + + + + + + + + diff --git "a/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/site/media/anki.jpg" "b/2023-11-16 - Aprendiendo un shell pythonico, xonsh, con anki [charla] - Daniel S\303\241nchez/site/media/anki.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..8e5ed0d1e754392d57196f8b8e092f8a2ebd912f GIT binary patch literal 29329 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