<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ferramentas-De-Desenvolvimento | AkitaOnRails.com</title><link>https://akitaonrails.github.io/tags/ferramentas-de-desenvolvimento/</link><description>Blog do Fabio Akita do Canal do YouTube 'Akitando' falando sobre tecnologia, carreira e coisas geek.</description><generator>Hugo -- gohugo.io</generator><language>pt-BR</language><lastBuildDate>Mon, 19 Oct 2026 23:20:48 +0000</lastBuildDate><atom:link href="https://akitaonrails.github.io/tags/ferramentas-de-desenvolvimento/index.xml" rel="self" type="application/rss+xml"/><item><title>Brincando de TUI com LLMs - Ratatui+Bubbletea</title><link>https://akitaonrails.github.io/2026/06/08/brincando-tui-llms-ratatui-bubbletea/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/06/08/brincando-tui-llms-ratatui-bubbletea/</guid><pubDate>Mon, 08 Jun 2026 16:00:00 -0300</pubDate><description>&lt;p&gt;Antes de falar do brinquedo novo, um lembrete rápido: &lt;a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener"&gt;ai-jail&lt;/a&gt; e &lt;a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener"&gt;ai-memory&lt;/a&gt; continuam recebendo bastante atenção. Issues, pull requests, pequenas correções, melhorias de empacotamento, bugs de ambiente, ajustes de documentação. Aquelas coisas que ninguém vê num post de lançamento, mas que transformam experimento em ferramenta que dá pra usar todo dia.&lt;/p&gt;
&lt;p&gt;Eu gosto dessa fase. O projeto deixa de ser &amp;ldquo;o que eu imaginei no meu setup&amp;rdquo; e vira &amp;ldquo;o que quebra na máquina de outra pessoa&amp;rdquo;. Aí aparece Windows, macOS, Arch, AUR, path esquisito, token salvo em lugar diferente, shell diferente, terminal diferente. Chato? Sim. Necessário? Também.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Antes de falar do brinquedo novo, um lembrete rápido: <a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a> e <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a> continuam recebendo bastante atenção. Issues, pull requests, pequenas correções, melhorias de empacotamento, bugs de ambiente, ajustes de documentação. Aquelas coisas que ninguém vê num post de lançamento, mas que transformam experimento em ferramenta que dá pra usar todo dia.</p>
<p>Eu gosto dessa fase. O projeto deixa de ser &ldquo;o que eu imaginei no meu setup&rdquo; e vira &ldquo;o que quebra na máquina de outra pessoa&rdquo;. Aí aparece Windows, macOS, Arch, AUR, path esquisito, token salvo em lugar diferente, shell diferente, terminal diferente. Chato? Sim. Necessário? Também.</p>
<p>Mas o prato principal de hoje não é ai-jail nem ai-memory. É TUI. Mais especificamente, é minha mania recente de escrever pequenas ferramentas de terminal em Rust com <a href="https://ratatui.rs/"target="_blank" rel="noopener">Ratatui</a>, mas querendo que elas fiquem com cara de <a href="https://github.com/charmbracelet/bubbletea"target="_blank" rel="noopener">Bubble Tea</a>.</p>
<h2>O app que não vou abrir<span class="hx:absolute hx:-mt-20" id="o-app-que-não-vou-abrir"></span>
    <a href="#o-app-que-n%c3%a3o-vou-abrir" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Nas últimas semanas também mexi num projeto privado que não pretendo abrir. É uma TUI pra acompanhar minha conta nos EUA, investimentos, assets, posições, covered calls, open calls, essas coisas chatas de adulto. Não vou publicar o código porque é o tipo de ferramenta que nasceu colada no meu fluxo financeiro, nas minhas planilhas, nos meus extratos e nas minhas gambiarras internas. Abrir isso seria transformar uma ferramenta minha em suporte gratuito pra bug de banco dos outros. Tô fora.</p>
<p>Mas dá pra mostrar a cara geral. Censurei o que precisava censurar:</p>
<p><strong>Observação óbvia, mas vou deixar explícito: todos os valores, tickers, posições e datas mostrados no screenshot são dados falsos de demonstração. Não é dado real da minha conta, nem portfolio real, nem recomendação de investimento.</strong></p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/08/ratatui-bubbletea/private-portfolio-censored.png" alt="TUI privada de portfolio em terminal, com abas de dashboard e tabela de holdings. O nome do banco foi censurado."  loading="lazy" /></p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/08/ratatui-bubbletea/private-allocation-censored.png" alt="TUI privada mostrando uma visão de alocação por classe de asset, com nomes sensíveis censurados."  loading="lazy" /></p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/08/ratatui-bubbletea/private-open-calls-censored.png" alt="TUI privada mostrando uma aba de open calls com dados falsos de demonstração e nomes sensíveis censurados."  loading="lazy" /></p>
<p>Toda vez que faço uma TUI pequena, a mesma dúvida aparece: que stack usar?</p>
<p>Se eu fosse escrever tudo na unha, provavelmente escolheria Python ou Go. São linguagens mais confortáveis pra esse tipo de utilitário pequeno. Python porque é direto, cheio de biblioteca, ótimo pra script que conversa com API e parseia JSON. Go porque gera binário simples, cruza plataforma bem, e tem ergonomia boa pra CLI.</p>
<p>Só que hoje eu raramente escrevo esse código todo na unha. Eu orquestro Claude, Codex, OpenCode, mando revisar, mando refatorar, mando testar. Nesse cenário, a falta de ergonomia do Rust pesa menos, porque quem briga com borrow checker, trait bound e lifetime chato é o LLM. Eu fico mais no papel de revisor e usuário final. E aí Rust começa a ficar muito atraente.</p>
<p>Ferramental bom. <code>cargo</code> é ótimo. Testes são fáceis de rodar. Cross compile é administrável. O binário final é limpo. Erro de memória idiota praticamente some. Não estou dizendo que Rust é magicamente melhor que Go ou Python pra toda TUI. Não é. Mas com LLM escrevendo a maior parte, o custo que normalmente me faria evitar Rust cai bastante. E os modelos atuais estão surpreendentemente competentes em Rust, desde que você mande rodar teste, consertar warning e não aceite a primeira versão como se fosse revelação divina.</p>
<h2>Ratatui é bom, mas eu queria a cara do Charm<span class="hx:absolute hx:-mt-20" id="ratatui-é-bom-mas-eu-queria-a-cara-do-charm"></span>
    <a href="#ratatui-%c3%a9-bom-mas-eu-queria-a-cara-do-charm" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O <a href="https://ratatui.rs/"target="_blank" rel="noopener">Ratatui</a> é uma biblioteca Rust pra construir interfaces ricas no terminal: dashboards, apps interativos, tabelas, listas, gauges, layouts, tudo aquilo que antigamente a gente chamava de &ldquo;ncurses moderno&rdquo;. Ele é o sucessor espiritual do <code>tui-rs</code>, e hoje é provavelmente o caminho mais óbvio se você quer fazer TUI séria em Rust.</p>
<p>Ratatui funciona bem. O problema é gosto pessoal: por padrão, não acho bonito. Não é feio no sentido &ldquo;isso parece programa de DOS de 1993&rdquo;. Dá pra fazer coisa boa. Mas muita TUI em Ratatui cai naquela estética quadrada, cinza, funcional, meio admin panel de datacenter.</p>
<p>Eu gosto mais da pegada da <a href="https://charm.sh/"target="_blank" rel="noopener">Charmbracelet</a>. O <code>gum</code>, por exemplo, é uma coleção de comandos pra deixar shell script interativo sem virar festival de <code>read -p</code> e <code>case</code>. Prompt, select, filter, spinner, tabela, pager, estilo. Você monta um script bash com cara de app decente em minutos.</p>
<p>E tem o <a href="https://github.com/charmbracelet/bubbletea"target="_blank" rel="noopener">Bubble Tea</a>, em Go, inspirado na arquitetura Elm. Você tem um model, recebe mensagens, atualiza estado, renderiza uma view. É uma ideia simples e muito boa pra terminal: estado entra, evento entra, view sai. A Charm também tem um gosto visual que eu curto: cores boas, espaçamento decente, componentes leves, nada com cara de formulário WinForms jogado no terminal.</p>
<p>Então eu queria o seguinte: continuar em Rust com Ratatui, mas roubar a sensação de Bubble Tea. Não o runtime inteiro. Não um clone perfeito. Só a direção visual e alguns componentes.</p>
<p>Daí nasceu o <a href="https://github.com/akitaonrails/ratatui-bubbletea"target="_blank" rel="noopener">ratatui-bubbletea</a>.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/08/ratatui-bubbletea/ratatui-bubbletea-example.png" alt="Showcase do ratatui-bubbletea rodando em terminal, com SelectList, Spinner, Theme, ThemedTable, TextInput, Progress e Viewport no estilo Charm."  loading="lazy" /></p>
<p>O projeto não substitui o Ratatui. Ele fica por cima. A ideia é oferecer uma camada de tema e componentes com inspiração em Bubble Tea/Bubbles, mas ainda renderizando com Ratatui.</p>
<p>Hoje ele é dividido em crates:</p>
<ul>
<li><code>ratatui-bubbletea-theme</code>, com paleta, helpers e estilos compartilhados.</li>
<li><code>ratatui-bubbletea-components</code>, com componentes prontos como select list, spinner, progress, table, text input, viewport e help.</li>
<li><code>ratatui-tea</code>, opcional, pra quem quer uma ergonomia mais perto de <code>Model</code>, <code>Msg</code> e <code>Cmd</code>, sem fingir que Rust virou Go.</li>
</ul>
<p>O README tem os exemplos completos e a documentação do que já existe. Por enquanto, eu trato como toolkit pequeno. Serve pra meus apps, e se servir pra mais alguém, ótimo. Se não servir, também não tem drama. O objetivo era parar de reimplementar o mesmo tema e os mesmos widgets toda vez que eu começava uma TUI nova.</p>
<h2>ai-usagebar como exemplo público<span class="hx:absolute hx:-mt-20" id="ai-usagebar-como-exemplo-público"></span>
    <a href="#ai-usagebar-como-exemplo-p%c3%bablico" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Como não vou abrir o app financeiro, precisava de um exemplo público usando essa estética. Então atualizei meu <a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">ai-usagebar</a>.</p>
<p>Pra quem não lembra, expliquei o projeto no post <a href="/2026/05/24/criei-widget-waybar-omarchy-monitorar-uso-llms-ai-usagebar/">&ldquo;Criei um Widget de Waybar pra Omarchy pra Monitorar Uso de Planos de LLM: ai-usagebar&rdquo;</a>. Ele nasceu como widget de Waybar pra mostrar uso de planos de LLM: Claude, OpenAI Codex/ChatGPT, Z.AI, OpenRouter. Bateu o olho na barra, sabe se está perto do limite e qual vendor usar agora.</p>
<p>Depois virou também TUI standalone. E graças a contribuições, hoje suporta Windows também. Isso é engraçado porque a origem dele é totalmente Linux/Omarchy/Waybar. Mas é open source: alguém usa em outro ambiente, encontra atrito, manda PR, e pronto, o projeto fica menos provinciano.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/08/ratatui-bubbletea/ai-usagebar.png" alt="ai-usagebar em modo TUI mostrando dashboard de uso de OpenAI, abas de vendors, gauges de limite e atalhos no rodapé."  loading="lazy" /></p>
<p>No ai-usagebar a diferença visual não muda a vida de ninguém. É uma tela simples. Abas, gauges, texto, atalhos. Mas é um bom exemplo porque é pequeno, real, testado, empacotado, e não depende do meu app privado. Dá pra olhar o código e ver como apliquei a camada de tema.</p>
<h2>Os apps de coceira própria<span class="hx:absolute hx:-mt-20" id="os-apps-de-coceira-própria"></span>
    <a href="#os-apps-de-coceira-pr%c3%b3pria" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Esses projetos todos seguem a mesma lógica: eu tenho uma coceira, faço uma ferramenta pequena, uso, ajusto, empacoto. Nada de roadmap de startup. Nada de manifesto. Só ferramenta que resolve um incômodo meu.</p>
<p>Um exemplo recente é o <a href="https://github.com/akitaonrails/clock-tui"target="_blank" rel="noopener">clock-tui</a>. Ele não nasceu comigo. Era um projeto Rust antigo, <code>tclock</code>, que parecia abandonado. Eu queria um relógio grande no meu segundo monitor vertical. Aquele monitor fica do lado, e eu gosto de ter um &ldquo;desk clock&rdquo; enorme ocupando parte da tela. Usei o clock-tui original por um tempo.</p>
<p>Só que uma tela vertical inteira só pra mostrar hora é desperdício. Eu já tinha o <a href="https://github.com/akitaonrails/ghpending"target="_blank" rel="noopener">ghpending</a>, que lista issues e PRs abertos em todos os meus projetos. Ele é meu &ldquo;tem alguém esperando resposta?&rdquo; em formato de CLI. Também queria ver minha agenda.</p>
<p>Então fiz outro app pequeno: <a href="https://github.com/akitaonrails/google-calendar-tui"target="_blank" rel="noopener">google-calendar-tui</a>. Ele usa as contas Gmail já registradas no GNOME Online Accounts e resume meus próximos compromissos no terminal. Read-only. Sem ritual de OAuth novo. Sem mais um config secreto espalhado em lugar esquisito.</p>
<p>Com essas duas peças, modernizei o clock-tui e adicionei layout de widgets auto-refresh. Agora o relógio ocupa a tela como eu queria, mas em volta dele aparecem pendências do GitHub e agenda do Google Calendar.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/08/ratatui-bubbletea/tclock.png" alt="tclock em monitor vertical, com relógio grande, widget de pendências do GitHub à esquerda e agenda do Google Calendar à direita."  loading="lazy" /></p>
<p>Isso é exatamente o tipo de coisa que eu nunca faria se custasse um fim de semana inteiro. Mas com LLM, vira uma sequência de tarefas pequenas: lê o projeto antigo, moderniza dependências, roda teste, adiciona módulo de widget, chama ghpending, chama google-calendar-tui, organiza layout, corrige bug, empacota. Ainda dá trabalho. Mas é trabalho de supervisão e refinamento, não de ficar brigando com boilerplate.</p>
<h2>Ajustando Geary sem fork<span class="hx:absolute hx:-mt-20" id="ajustando-geary-sem-fork"></span>
    <a href="#ajustando-geary-sem-fork" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Outra coceira veio do GNOME.</p>
<p>Como eu queria centralizar minhas contas no GNOME Online Accounts, comecei a usar <a href="https://wiki.gnome.org/Apps/Geary"target="_blank" rel="noopener">Geary</a> e o calendário do GNOME no segundo monitor também. Gosto da ideia: contas configuradas uma vez, apps do desktop reaproveitando a mesma infraestrutura, nada de cada programinha inventar seu próprio login.</p>
<p>O problema é que o Geary tem um layout fixo de três colunas. Numa tela normal, tudo bem. Num monitor vertical, fica apertado. A coluna de pastas, a lista de mensagens e o corpo do e-mail brigam por espaço. Eu não queria manter um fork do Geary só pra esconder uma sidebar. Fork de app GTK grande é dívida. Você pisca e passa o resto da vida resolvendo conflito de merge.</p>
<p>Então fiz um módulo GTK: <a href="https://github.com/akitaonrails/geary-hide-sidebar-module"target="_blank" rel="noopener">geary-hide-sidebar-module</a>. Ele injeta um comportamento no Geary em runtime e permite recolher/expandir a sidebar, com atalho e auto-collapse em janela estreita. Sem recompilar Geary. Sem manter fork. Só um módulo pequeno com uma responsabilidade bem específica.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/08/ratatui-bubbletea/geary-sidebar-hidden.png" alt="Geary com sidebar recolhida, mostrando lista de e-mails e corpo da mensagem em layout mais confortável para tela vertical."  loading="lazy" /></p>
<p>Essa é uma lição boa: às vezes você não precisa forkar a aplicação inteira. Dá pra ajustar por fora. GTK_MODULES existe. Wrapper existe. Config existe. CSS existe. Script existe. Nem toda personalização precisa virar uma manutenção eterna de código dos outros.</p>
<h2>Código pequeno ficou barato<span class="hx:absolute hx:-mt-20" id="código-pequeno-ficou-barato"></span>
    <a href="#c%c3%b3digo-pequeno-ficou-barato" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>É por isso que estou insistindo tanto nessa ideia de apps pequenos. Com LLMs atuais, ficou muito fácil implementar uma ideia específica pra deixar seu ambiente do jeito que você quer. Sem esperar alguém ter exatamente a mesma dor. Sem ficar procurando no GitHub por três horas uma ferramenta que faz 80% do que você quer e 40% do que você não quer.</p>
<p>Você descreve a coceira, cria um repo, pede um protótipo, testa, manda refatorar, manda escrever teste, manda empacotar. Se ficar ruim, joga fora. Se ficar bom, instala e usa.</p>
<p>Eu não deixo isso virar gambiarra jogada no <code>~/bin</code> sem dono. Meus apps têm testes. Têm builds automatizados. Muitos têm release no GitHub, pacote no AUR, instalação normal com <code>yay</code> no Arch. Usam paths XDG, então config vai pra <code>~/.config</code>, cache vai pra <code>~/.cache</code>, dados vão pra <code>~/.local/share</code>. Fica organizado. Dá pra atualizar. Dá pra remover. Dá pra outra pessoa clonar e contribuir.</p>
<p>Pra fechar, os links todos num lugar só:</p>
<ul>
<li><a href="https://github.com/akitaonrails/ratatui-bubbletea"target="_blank" rel="noopener">ratatui-bubbletea</a></li>
<li><a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">ai-usagebar</a></li>
<li><a href="https://github.com/akitaonrails/clock-tui"target="_blank" rel="noopener">clock-tui</a></li>
<li><a href="https://github.com/akitaonrails/ghpending"target="_blank" rel="noopener">ghpending</a></li>
<li><a href="https://github.com/akitaonrails/google-calendar-tui"target="_blank" rel="noopener">google-calendar-tui</a></li>
<li><a href="https://github.com/akitaonrails/geary-hide-sidebar-module"target="_blank" rel="noopener">geary-hide-sidebar-module</a></li>
<li><a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a></li>
<li><a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a></li>
</ul>
<p>Se você usar algum deles e quebrar no seu setup, abre issue. Se souber corrigir, manda PR. Eu uso essas ferramentas de verdade, então bug report útil tende a virar correção rápido.</p>
<p>Minha regra prática é essa: personalize seu ambiente sem transformar tudo em gambiarra. Faça ferramenta pequena. Teste. Empacote. Documente. Deixe o LLM carregar o peso chato e use seu cérebro pra decidir o que presta.</p>
<p>Essa é a parte divertida de programar que tinha sumido um pouco. Agora voltou.</p>
]]></content:encoded><category>ai-usagebar</category><category>ferramentas-de-desenvolvimento</category><category>rust</category><category>open-source</category></item><item><title>Criei um Widget de Waybar pra Omarchy pra Monitorar Uso de Planos de LLM: ai-usagebar</title><link>https://akitaonrails.github.io/2026/05/24/criei-widget-waybar-omarchy-monitorar-uso-llms-ai-usagebar/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/05/24/criei-widget-waybar-omarchy-monitorar-uso-llms-ai-usagebar/</guid><pubDate>Sun, 24 May 2026 00:01:00 -0300</pubDate><description>&lt;p&gt;Quem acompanha o blog já sabe que eu uso um monte de vendor de LLM diferente. Os principais são Claude e GPT, via Claude Code e Codex. Eu uso o harness de cada um porque estou preso aos planos de assinatura deles (Pro, Plus, Max), que saem muito mais baratos do que pagar crédito por token tipo OpenRouter. Mesmo assim, também uso OpenRouter pra acessar outros modelos pra teste, e tenho até uma assinatura Z.AI GLM pra coisas pequenas.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Quem acompanha o blog já sabe que eu uso um monte de vendor de LLM diferente. Os principais são Claude e GPT, via Claude Code e Codex. Eu uso o harness de cada um porque estou preso aos planos de assinatura deles (Pro, Plus, Max), que saem muito mais baratos do que pagar crédito por token tipo OpenRouter. Mesmo assim, também uso OpenRouter pra acessar outros modelos pra teste, e tenho até uma assinatura Z.AI GLM pra coisas pequenas.</p>
<p>O problema de ter vários planos é acompanhar quanto já gastei de cada um. Eu vinha usando o <a href="https://github.com/mryll/claudebar"target="_blank" rel="noopener">claudebar</a>, um widget de Waybar que mostra o uso do plano da Anthropic. Gosto dele, mas queria ver todos os meus vendors num lugar só, pra bater o olho e saber onde estou. E não queria encher minha Waybar de widget separado pra cada vendor. Então resolvi fazer o meu: o <strong><a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">ai-usagebar</a></strong>.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/24/ai-usagebar/ai-usagebar-waybar.png" alt="Widget na Waybar mostrando “cld 29% · 1h 12m” no canto superior direito, com tooltip aberto exibindo o plano Claude Max 20x: Session 29%, Weekly 47%, Sonnet only 0%, Extra usage $0.00 sobre limite de $1100, e horário da última atualização."  loading="lazy" /></p>
<p>É um port em Rust do claudebar, drop-in compatível, estendido pra quatro vendors: Anthropic Claude, OpenAI Codex/ChatGPT, Z.AI (GLM) e OpenRouter. Mantém os mesmos parâmetros (<code>--icon</code>, <code>--format</code>, <code>--tooltip-format</code>, etc.), o mesmo tooltip minimalista com borda Pango, e a mesma auto-detecção do tema do Omarchy. A diferença é que agora os quatro vendors aparecem no mesmo lugar, em vez de 865 linhas de bash cuidando de um só.</p>
<h2>Como ele autentica em cada vendor<span class="hx:absolute hx:-mt-20" id="como-ele-autentica-em-cada-vendor"></span>
    <a href="#como-ele-autentica-em-cada-vendor" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Essa é a parte que vale explicar, porque cada vendor faz diferente. Claude e Codex usam OAuth: os CLIs oficiais (<code>claude</code> e <code>codex</code>) já escreveram as credenciais no disco quando você logou, e o ai-usagebar lê esses mesmos arquivos. Não precisa de variável de ambiente nenhuma, o token até se renova sozinho.</p>
<p>Z.AI e OpenRouter usam API key, então pra esses você precisa setar uma chave (via env var ou inline no config).</p>
<table>
  <thead>
      <tr>
          <th>Vendor</th>
          <th>Método</th>
          <th>O que você precisa fazer</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Anthropic</td>
          <td>OAuth, lê de <code>~/.claude/.credentials.json</code></td>
          <td>Roda <code>claude</code> uma vez pra logar. Token renova sozinho.</td>
      </tr>
      <tr>
          <td>OpenAI</td>
          <td>OAuth, lê de <code>~/.codex/auth.json</code></td>
          <td>Roda <code>codex login</code> uma vez. Token renova sozinho.</td>
      </tr>
      <tr>
          <td>Z.AI</td>
          <td>API key (<code>ZAI_API_KEY</code> ou <code>[zai] api_key</code> no config)</td>
          <td>Seta uma das duas.</td>
      </tr>
      <tr>
          <td>OpenRouter</td>
          <td>API key (<code>OPENROUTER_API_KEY</code> ou <code>[openrouter] api_key</code>)</td>
          <td>Seta uma das duas.</td>
      </tr>
  </tbody>
</table>
<h2>A interface além da Waybar<span class="hx:absolute hx:-mt-20" id="a-interface-além-da-waybar"></span>
    <a href="#a-interface-al%c3%a9m-da-waybar" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Além do widget na barra, tem uma TUI com abas (<code>ai-usagebar-tui</code>) pra ver tudo de uma vez. Navega com Tab / h / l entre os vendors, atualiza a cada 60s. Dá pra abrir clicando no widget da Waybar, ou rodar direto no terminal (mais sobre isso na próxima seção).</p>
<p>A aba do OpenRouter mostra saldo de crédito, gasto de hoje / semana / mês e o tier:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/24/ai-usagebar/ai-usagebar-tui-openrouter.png" alt="ai-usagebar-tui na aba OpenRouter: gauge de saldo de crédito em 98% em vermelho ($13.67 restante de $900), bloco de uso por período (hoje/semana/mês), tier pago."  loading="lazy" /></p>
<p>E tem um overlay de settings pra escolher o vendor primário e colar as API keys sem editar o config na mão:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/24/ai-usagebar/ai-usagebar-tui-settings.png" alt="Overlay de settings flutuando sobre a TUI: radio de vendor primário (Anthropic selecionado), API key da Z.AI mascarada (•••), API key do OpenRouter mascarada (•••), botão Save, atalhos no rodapé."  loading="lazy" /></p>
<h2>Não usa Omarchy nem Hyprland? Roda como TUI standalone<span class="hx:absolute hx:-mt-20" id="não-usa-omarchy-nem-hyprland-roda-como-tui-standalone"></span>
    <a href="#n%c3%a3o-usa-omarchy-nem-hyprland-roda-como-tui-standalone" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O widget de Waybar é opcional. Os dois binários são independentes, então se você não usa Omarchy, nem Hyprland, nem Waybar (ou simplesmente prefere checar o uso de vez em quando em vez de ter na barra o tempo todo), o <code>ai-usagebar-tui</code> funciona como app de terminal totalmente standalone:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-usagebar-tui    <span class="c1"># abre no seu terminal atual</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Roda em qualquer emulador de terminal (Kitty, Alacritty, Foot, Ghostty, etc.), funciona até numa sessão SSH pura, e não depende de compositor nem de feature de window manager. Todos os controles e o overlay de settings funcionam igual. Os mesmos quatro vendors, as mesmas abas:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/24/ai-usagebar/ai-usagebar-tui-openai.png" alt="ai-usagebar-tui na aba OpenAI rodando num terminal: gauges de Codex 5h e semanal, bloco de Credits com faixas de contagem de mensagens, abas Claude / OpenAI / GLM (Z.AI) / OpenRouter no topo, atalhos de tecla no rodapé."  loading="lazy" /></p>
<p>Uso típico fora do Omarchy: uma checada rápida antes de começar uma sessão longa (&ldquo;será que tô perto do limite semanal do Claude?&rdquo;), um monitor num painel de tmux enquanto você programa, ou uma ferramenta só de shell em máquina remota (instala o binário e pronto, sem dependência de Waybar ou Hyprland). A TUI é a forma canônica de ver os quatro vendors de uma vez, independente de você configurar o widget ou não.</p>
<h2>Instalação<span class="hx:absolute hx:-mt-20" id="instalação"></span>
    <a href="#instala%c3%a7%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>No Arch tem pacote no AUR, dois sabores:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">yay -S ai-usagebar-bin    <span class="c1"># binário pré-compilado do GitHub Releases (~5s)</span>
</span></span><span class="line"><span class="cl">yay -S ai-usagebar        <span class="c1"># compila do fonte (~30-60s)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Ou do fonte direto:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cargo build --release
</span></span><span class="line"><span class="cl">sudo make install                  <span class="c1"># → /usr/local/bin</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ou</span>
</span></span><span class="line"><span class="cl">make install <span class="nv">PREFIX</span><span class="o">=</span><span class="nv">$HOME</span>/.local   <span class="c1"># → ~/.local/bin</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>A config de Waybar recomendada é um único módulo com scroll pra ciclar entre os vendors, e clique pra abrir a TUI:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-jsonc" data-lang="jsonc"><span class="line"><span class="cl"><span class="s2">&#34;custom/aibar&#34;</span><span class="err">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exec&#34;</span><span class="p">:</span> <span class="s2">&#34;ai-usagebar --format &#39;{vendor_short} {session_pct}% · {session_reset}&#39;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;return-type&#34;</span><span class="p">:</span> <span class="s2">&#34;json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;interval&#34;</span><span class="p">:</span> <span class="mi">300</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;signal&#34;</span><span class="p">:</span> <span class="mi">13</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;tooltip&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;on-click&#34;</span><span class="p">:</span> <span class="s2">&#34;ai-usagebar-tui&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;on-scroll-up&#34;</span><span class="p">:</span>   <span class="s2">&#34;ai-usagebar --cycle-next&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;on-scroll-down&#34;</span><span class="p">:</span> <span class="s2">&#34;ai-usagebar --cycle-prev&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Se preferir ver os quatro vendors ao mesmo tempo, dá pra usar um módulo por vendor. O <a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">README</a> tem o detalhe completo de config, placeholders de formato, e as variações.</p>
<h2>Por que fiz<span class="hx:absolute hx:-mt-20" id="por-que-fiz"></span>
    <a href="#por-que-fiz" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Esse parecia um projetinho de sábado à noite, então resolvi só fazer. E foi: portar o claudebar pra Rust e adicionar os vendors extras que eu queria foi tranquilo. Saí de uma noite com um widget que faz exatamente o que eu precisava e ainda é mais confiável (testado, modular) do que o shell script original.</p>
<p>Se você usa outros vendors que eu não cobri, ou achar bug, manda issue ou pull request: <a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">github.com/akitaonrails/ai-usagebar</a>. É MIT.</p>
]]></content:encoded><category>ai-usagebar</category><category>omarchy</category><category>ferramentas-de-desenvolvimento</category><category>llms</category></item><item><title>Criei um CLI pra Checar Pendências no Meu GitHub: ghpending</title><link>https://akitaonrails.github.io/2026/05/23/criei-cli-pra-checar-pendencias-github-ghpending/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/05/23/criei-cli-pra-checar-pendencias-github-ghpending/</guid><pubDate>Sat, 23 May 2026 22:00:00 -0300</pubDate><description>&lt;p&gt;Depois da minha &lt;a href="https://akitaonrails.github.io/2026/05/14/terminando-maratona-ia-sucesso-ou-fracasso/"&gt;maratona de IA&lt;/a&gt;, fiquei com dezenas de repositórios públicos no GitHub pra cuidar. Vários deles têm contribuidores postando issues e mandando pull requests. O problema é que abrir o navegador, entrar em cada repo, ver se tem alguma coisa nova esperando, vira um ritual cansativo que eu acabo evitando. E quando evito, fico semanas sem responder os colaboradores.&lt;/p&gt;
&lt;p&gt;Sei que tem várias ferramentas que resolvem isso. Mas eu queria algo bem simples e rápido pra rodar no terminal e ver pendências de todos os meus projetos de uma vez só. Então fiz: o &lt;strong&gt;&lt;a href="https://github.com/akitaonrails/ghpending"target="_blank" rel="noopener"&gt;ghpending&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Depois da minha <a href="/2026/05/14/terminando-maratona-ia-sucesso-ou-fracasso/">maratona de IA</a>, fiquei com dezenas de repositórios públicos no GitHub pra cuidar. Vários deles têm contribuidores postando issues e mandando pull requests. O problema é que abrir o navegador, entrar em cada repo, ver se tem alguma coisa nova esperando, vira um ritual cansativo que eu acabo evitando. E quando evito, fico semanas sem responder os colaboradores.</p>
<p>Sei que tem várias ferramentas que resolvem isso. Mas eu queria algo bem simples e rápido pra rodar no terminal e ver pendências de todos os meus projetos de uma vez só. Então fiz: o <strong><a href="https://github.com/akitaonrails/ghpending"target="_blank" rel="noopener">ghpending</a></strong>.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/23/ghpending/ghpending-screenshot.png" alt="Saída do ghpending no terminal: tabela compacta listando cada repo monitorado com contagem de issues e pull requests abertos, autor da última atividade e há quanto tempo."  loading="lazy" /></p>
<p>Roda em Linux e macOS. Eu testei em Linux (Arch + Omarchy) mas ainda não rodei no macOS. Se você for testar lá e topar com algum bug, abre uma issue lá: <a href="https://github.com/akitaonrails/ghpending/issues"target="_blank" rel="noopener">github.com/akitaonrails/ghpending/issues</a>.</p>
<h2>Instalação<span class="hx:absolute hx:-mt-20" id="instalação"></span>
    <a href="#instala%c3%a7%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Três caminhos, escolhe o que mais combina com seu setup.</p>
<p>Via Homebrew (macOS ou Linux):</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">brew tap akitaonrails/tap <span class="o">&amp;&amp;</span> brew install ghpending</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Via Cargo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">cargo install ghpending</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Via mise:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">mise use -g github:akitaonrails/ghpending</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h2>Atualizando<span class="hx:absolute hx:-mt-20" id="atualizando"></span>
    <a href="#atualizando" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="c1"># Homebrew</span>
</span></span><span class="line"><span class="cl">brew upgrade ghpending
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Cargo</span>
</span></span><span class="line"><span class="cl">cargo install ghpending --force
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># mise</span>
</span></span><span class="line"><span class="cl">mise upgrade ghpending
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># From source</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> ghpending <span class="o">&amp;&amp;</span> git pull <span class="o">&amp;&amp;</span> cargo install --path .</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h2>Uso<span class="hx:absolute hx:-mt-20" id="uso"></span>
    <a href="#uso" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Quatro comandos. O fluxo normal é rodar <code>ghpending add</code> uma vez pra configurar quais repos você quer monitorar, depois é só <code>ghpending</code> quando quiser ver o digest.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">ghpending add    <span class="c1"># pick os repos de um usuário ou org pra monitorar</span>
</span></span><span class="line"><span class="cl">ghpending        <span class="c1"># imprime o digest de issues e PRs abertos</span>
</span></span><span class="line"><span class="cl">ghpending list   <span class="c1"># mostra os repos monitorados</span>
</span></span><span class="line"><span class="cl">ghpending rm     <span class="c1"># tira repos do monitoramento via menu interativo</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>O <code>add</code> pergunta o usuário ou organização, lista os repos públicos, e deixa você marcar os que quer acompanhar. O username fica salvo, então rodar <code>add</code> de novo já pula essa pergunta.</p>
<p>O comando principal (<code>ghpending</code> sem argumentos) busca todos os repos monitorados em paralelo e mostra a tabela com issues e PRs abertos.</p>
<h2>Token do GitHub (opcional)<span class="hx:absolute hx:-mt-20" id="token-do-github-opcional"></span>
    <a href="#token-do-github-opcional" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Sem autenticação funciona, mas o GitHub limita em 60 requisições por hora pra anônimo. Pra subir esse teto pra 5.000 req/h, exporta um token:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="nv">GITHUB_TOKEN</span><span class="o">=</span><span class="k">$(</span>gh auth token<span class="k">)</span> ghpending</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Ele é lido silenciosamente na inicialização, não precisa configurar nada.</p>
<h2>Onde fica o config<span class="hx:absolute hx:-mt-20" id="onde-fica-o-config"></span>
    <a href="#onde-fica-o-config" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><ul>
<li>Linux: <code>~/.config/ghpending/config.toml</code></li>
<li>macOS: <code>~/Library/Application Support/ghpending/config.toml</code></li>
</ul>
<p>Você pode editar direto se quiser reordenar ou trocar o <code>user</code>. Estrutura:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">user</span> <span class="p">=</span> <span class="s2">&#34;akitaonrails&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">repos</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;akitaonrails/ai-memory&#34;</span><span class="p">,</span> <span class="s2">&#34;akitaonrails/ai-jail&#34;</span><span class="p">]</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h2>Por que esse CLI existe<span class="hx:absolute hx:-mt-20" id="por-que-esse-cli-existe"></span>
    <a href="#por-que-esse-cli-existe" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A real é simples: ferramenta que eu fizesse pra mim mesmo, eu uso. Ferramenta de outro autor, sempre tem fricção (login web, opinião arquitetural diferente, feature que faltou ou sobrou). Como o objetivo era reduzir o atrito de checar 30 repos por semana, melhor 200 linhas de Rust escritas num sábado à tarde do que aprender um stack novo.</p>
<p>Agora espero conseguir responder as pendências dos colaboradores mais rápido. Se você achar útil, é MIT, PRs são bem-vindos.</p>
]]></content:encoded><category>ghpending</category><category>automacao</category><category>ferramentas-de-desenvolvimento</category><category>controle-de-versao</category></item><item><title>AI Agents: Instalando LSPs pro Crush</title><link>https://akitaonrails.github.io/2026/01/21/ai-agents-instalando-lsps-pro-crush/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/01/21/ai-agents-instalando-lsps-pro-crush/</guid><pubDate>Wed, 21 Jan 2026 13:14:07 -0300</pubDate><description>&lt;p&gt;Este post é mais pra eu documentar e não esquecer. Como falei nos últimos posts, tenho usado &lt;a href="https://github.com/charmbracelet/crush"target="_blank" rel="noopener"&gt;Charm&amp;rsquo;s Crush&lt;/a&gt; como meu agente favorito de IA pra programação. Repetindo: tanto faz se você usa Claude Code ou OpenCode, todos eles são igualmente bons. Minha preferência pessoal ainda é Crush porque acho mais bonito, só isso.&lt;/p&gt;
&lt;p&gt;Ainda não entendi o quanto faz diferença ou não, mas tanto OpenCode quanto Crush tem suporte a Language Servers (LSPs) então achei legal deixar configurado. Eis meu &lt;code&gt;~/.config/crush/crush.json&lt;/code&gt;:&lt;/p&gt;</description><content:encoded><![CDATA[<p>Este post é mais pra eu documentar e não esquecer. Como falei nos últimos posts, tenho usado <a href="https://github.com/charmbracelet/crush"target="_blank" rel="noopener">Charm&rsquo;s Crush</a> como meu agente favorito de IA pra programação. Repetindo: tanto faz se você usa Claude Code ou OpenCode, todos eles são igualmente bons. Minha preferência pessoal ainda é Crush porque acho mais bonito, só isso.</p>
<p>Ainda não entendi o quanto faz diferença ou não, mas tanto OpenCode quanto Crush tem suporte a Language Servers (LSPs) então achei legal deixar configurado. Eis meu <code>~/.config/crush/crush.json</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;$schema&#34;</span><span class="p">:</span> <span class="s2">&#34;https://charm.land/crush.json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;default_provider&#34;</span><span class="p">:</span> <span class="s2">&#34;openrouter&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;providers&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;openrouter&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;api_key&#34;</span><span class="p">:</span> <span class="s2">&#34;sk-...&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;lmstudio&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;LM Studio&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;base_url&#34;</span><span class="p">:</span> <span class="s2">&#34;http://localhost:1234/v1/&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;openai&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;models&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;gpt-oss-120b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;gpt-oss:120b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">100000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;gpt-oss-20b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;gpt-oss:20b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">130000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;zai-org/glm-4.6v-flash&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;glm-4.6v-flash&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">130000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;deepseek-coder-v2-lite-instruct&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;deepseek-coder-v2-lite-instruct&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">64000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen/qwen3-coder-30b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen3-coder-30b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">120000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;ollama&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;openai-compat&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;base_url&#34;</span><span class="p">:</span> <span class="s2">&#34;http://127.0.0.1:11434/v1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;api_key&#34;</span><span class="p">:</span> <span class="s2">&#34;ollama&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;models&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;glm-4.7-flash&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;glm-4.7-flash&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">65536</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;gpt-oss-20b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;gpt-oss:20b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">64000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen3-nuclear&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen3-nuclear&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">120000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen3-coder:30b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen3-coder:30b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">120000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen2.5-coder:32b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;qwen2.5-coder:32b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">32768</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;deepseek-coder-v2:16b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;deepseek-coder-v2:16b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">128000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;glm-4.7:cloud&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;glm-4.7:cloud&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;context_window&#34;</span><span class="p">:</span> <span class="mi">128000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;default_max_tokens&#34;</span><span class="p">:</span> <span class="mi">-1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;supports_tools&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;lsp&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;gopls&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;gopls&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;rust-analyzer&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;rust-analyzer&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;ruby-lsp&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;ruby-lsp&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;solargraph&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;solargraph&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;pylsp&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;pylsp&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;pyright&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;pyright-langserver&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;--stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;elixir-ls&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;elixir-ls&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;docker-langserver&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;docker-langserver&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;--stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;languages&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;dockerfile&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;bash-language-server&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;bash-language-server&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;start&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;marksman&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;marksman&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;server&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;typescript-language-server&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;typescript-language-server&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;--stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;vscode-html-language-server&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;vscode-html-language-server&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;--stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;vscode-css-language-server&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;vscode-css-language-server&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;--stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;vscode-json-language-server&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;vscode-json-language-server&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;--stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;yaml-language-server&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;yaml-language-server&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;--stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;taplo&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;taplo&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;lsp&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;stdio&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;mcp&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;blender&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;stdio&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;uvx&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;blender-mcp&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Notem que eu uso primariamente Claude Opus 4.5 via OpenRouter e tenho LM Studio e Ollama configurados como providers pra testar outros modelos open source.</p>
<p>Também uso <a href="/2025/09/07/omarchy-2-0-mise-pra-organizar-ambientes-de-desenvolvimento/">Mise</a> pra organizar as linguagens de programação que uso.</p>
<p>Porém, agora precisa instalar os LSPs de cada linguagem. Eu não conheço um jeito melhor de gerenciar isso da mesma forma como com um Mason no Neovim. Então fiz um script pra instalar tudo pra mim (no meu Arch Linux). Pra isso criei este script <code>~/.local/bin/install-lsps.sh</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash
</span></span></span><span class="line"><span class="cl"><span class="nb">set</span> -euo pipefail
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># LSP Installer for Arch Linux with Mise</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Installs major LSPs using native package managers or yay</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Only installs LSPs for languages that are already installed</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">GREEN</span><span class="o">=</span><span class="s1">&#39;\033[0;32m&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nv">BLUE</span><span class="o">=</span><span class="s1">&#39;\033[0;34m&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nv">YELLOW</span><span class="o">=</span><span class="s1">&#39;\033[1;33m&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nv">RED</span><span class="o">=</span><span class="s1">&#39;\033[0;31m&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nv">NC</span><span class="o">=</span><span class="s1">&#39;\033[0m&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">info<span class="o">()</span> <span class="o">{</span> <span class="nb">echo</span> -e <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BLUE</span><span class="si">}</span><span class="s2">[INFO]</span><span class="si">${</span><span class="nv">NC</span><span class="si">}</span><span class="s2"> </span><span class="nv">$1</span><span class="s2">&#34;</span><span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">success<span class="o">()</span> <span class="o">{</span> <span class="nb">echo</span> -e <span class="s2">&#34;</span><span class="si">${</span><span class="nv">GREEN</span><span class="si">}</span><span class="s2">[OK]</span><span class="si">${</span><span class="nv">NC</span><span class="si">}</span><span class="s2"> </span><span class="nv">$1</span><span class="s2">&#34;</span><span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">warn<span class="o">()</span> <span class="o">{</span> <span class="nb">echo</span> -e <span class="s2">&#34;</span><span class="si">${</span><span class="nv">YELLOW</span><span class="si">}</span><span class="s2">[SKIP]</span><span class="si">${</span><span class="nv">NC</span><span class="si">}</span><span class="s2"> </span><span class="nv">$1</span><span class="s2">&#34;</span><span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">skip_lang<span class="o">()</span> <span class="o">{</span> <span class="nb">echo</span> -e <span class="s2">&#34;</span><span class="si">${</span><span class="nv">RED</span><span class="si">}</span><span class="s2">[LANG]</span><span class="si">${</span><span class="nv">NC</span><span class="si">}</span><span class="s2"> </span><span class="nv">$1</span><span class="s2"> not installed, skipping LSPs&#34;</span><span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">command_exists<span class="o">()</span> <span class="o">{</span> <span class="nb">command</span> -v <span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span> <span class="p">&amp;</span>&gt;/dev/null<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Language detection helpers</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">has_c<span class="o">()</span>       <span class="o">{</span> command_exists gcc <span class="o">||</span> command_exists clang<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_rust<span class="o">()</span>    <span class="o">{</span> command_exists rustc <span class="o">||</span> command_exists cargo<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_go<span class="o">()</span>      <span class="o">{</span> command_exists go<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_python<span class="o">()</span>  <span class="o">{</span> command_exists python <span class="o">||</span> command_exists python3<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_node<span class="o">()</span>    <span class="o">{</span> command_exists node <span class="o">||</span> command_exists npm<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_java<span class="o">()</span>    <span class="o">{</span> command_exists java <span class="o">||</span> command_exists javac<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_kotlin<span class="o">()</span>  <span class="o">{</span> command_exists kotlin <span class="o">||</span> command_exists kotlinc<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_ruby<span class="o">()</span>    <span class="o">{</span> command_exists ruby<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_php<span class="o">()</span>     <span class="o">{</span> command_exists php<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_lua<span class="o">()</span>     <span class="o">{</span> command_exists lua <span class="o">||</span> command_exists luajit<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_zig<span class="o">()</span>     <span class="o">{</span> command_exists zig<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_haskell<span class="o">()</span> <span class="o">{</span> command_exists ghc <span class="o">||</span> command_exists stack <span class="o">||</span> command_exists cabal<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_elixir<span class="o">()</span>  <span class="o">{</span> command_exists elixir <span class="o">||</span> command_exists iex<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_scala<span class="o">()</span>   <span class="o">{</span> command_exists scala <span class="o">||</span> command_exists sbt<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_dotnet<span class="o">()</span>  <span class="o">{</span> command_exists dotnet<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_ocaml<span class="o">()</span>   <span class="o">{</span> command_exists ocaml <span class="o">||</span> command_exists opam<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_clojure<span class="o">()</span> <span class="o">{</span> command_exists clojure <span class="o">||</span> command_exists clj <span class="o">||</span> command_exists lein<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_nix<span class="o">()</span>     <span class="o">{</span> command_exists nix<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_terraform<span class="o">()</span> <span class="o">{</span> command_exists terraform <span class="o">||</span> command_exists tofu<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_latex<span class="o">()</span>   <span class="o">{</span> command_exists latex <span class="o">||</span> command_exists pdflatex <span class="o">||</span> command_exists xelatex<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_docker<span class="o">()</span>  <span class="o">{</span> command_exists docker <span class="o">||</span> command_exists podman<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_ansible<span class="o">()</span> <span class="o">{</span> command_exists ansible<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_sql<span class="o">()</span>     <span class="o">{</span> command_exists psql <span class="o">||</span> command_exists mysql <span class="o">||</span> command_exists sqlite3<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">has_bash<span class="o">()</span>    <span class="o">{</span> command_exists bash<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Package installation helpers</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_pacman<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">pkg</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> pacman -Qi <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="p">&amp;</span>&gt;/dev/null<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2"> already installed&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        sudo pacman -S --noconfirm --needed <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> success <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">||</span> warn <span class="s2">&#34;Failed: </span><span class="nv">$pkg</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">install_yay<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">pkg</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! command_exists yay<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;yay not found, skipping </span><span class="nv">$pkg</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> yay -Qi <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="p">&amp;</span>&gt;/dev/null<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2"> already installed&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        yay -S --noconfirm --needed <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> success <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">||</span> warn <span class="s2">&#34;Failed: </span><span class="nv">$pkg</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">install_npm<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">pkg</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> npm list -g <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="p">&amp;</span>&gt;/dev/null 2&gt;<span class="p">&amp;</span>1<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2"> already installed&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        npm install -g <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> success <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">||</span> warn <span class="s2">&#34;Failed: </span><span class="nv">$pkg</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">install_pipx<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">pkg</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! command_exists pipx<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        pip install --user pipx 2&gt;/dev/null <span class="o">||</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            pip install --user <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> success <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">||</span> warn <span class="s2">&#34;Failed: </span><span class="nv">$pkg</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> pipx list 2&gt;/dev/null <span class="p">|</span> grep -q <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2"> already installed&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        pipx install <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> success <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">||</span> warn <span class="s2">&#34;Failed: </span><span class="nv">$pkg</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">install_go<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">pkg</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">name</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">pkg</span><span class="p">##*/</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nv">name</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">name</span><span class="p">%%@*</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># Check if binary already exists in GOPATH/bin</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">gobin</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">GOBIN</span><span class="k">:-</span><span class="si">${</span><span class="nv">GOPATH</span><span class="k">:-</span><span class="nv">$HOME</span><span class="p">/go</span><span class="si">}</span><span class="p">/bin</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="o">[[</span> -x <span class="s2">&#34;</span><span class="nv">$gobin</span><span class="s2">/</span><span class="nv">$name</span><span class="s2">&#34;</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;</span><span class="nv">$name</span><span class="s2"> already installed&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    go install <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> success <span class="s2">&#34;</span><span class="nv">$name</span><span class="s2">&#34;</span> <span class="o">||</span> warn <span class="s2">&#34;Failed: </span><span class="nv">$name</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">install_gem<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">pkg</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> gem list -i <span class="s2">&#34;^</span><span class="si">${</span><span class="nv">pkg</span><span class="si">}</span>$<span class="s2">&#34;</span> <span class="p">&amp;</span>&gt;/dev/null<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2"> already installed&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        gem install <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> success <span class="s2">&#34;</span><span class="nv">$pkg</span><span class="s2">&#34;</span> <span class="o">||</span> warn <span class="s2">&#34;Failed: </span><span class="nv">$pkg</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># C/C++ LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_c_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_c<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;C/C++ (gcc/clang)&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing C/C++ LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman clang  <span class="c1"># includes clangd</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Rust LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_rust_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_rust<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Rust&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Rust LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span> command_exists rustup<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        rustup component add rust-analyzer 2&gt;/dev/null <span class="o">&amp;&amp;</span> success <span class="s2">&#34;rust-analyzer (rustup)&#34;</span> <span class="o">||</span> install_pacman rust-analyzer
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        install_pacman rust-analyzer
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Go LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_go_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_go<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Go&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Go LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    install_go golang.org/x/tools/gopls@latest
</span></span><span class="line"><span class="cl">    install_go github.com/go-delve/delve/cmd/dlv@latest
</span></span><span class="line"><span class="cl">    install_go github.com/nametake/golangci-lint-langserver@latest
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Python LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_python_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_python<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Python&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Python LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># Prefer npm pyright (faster updates) if node available</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> has_node<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        install_npm pyright
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        install_pipx pyright
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    install_pipx python-lsp-server
</span></span><span class="line"><span class="cl">    install_pipx ruff-lsp
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Node.js/TypeScript LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_node_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_node<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Node.js&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Node.js/TypeScript LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    install_npm typescript
</span></span><span class="line"><span class="cl">    install_npm typescript-language-server
</span></span><span class="line"><span class="cl">    install_npm vscode-langservers-extracted  <span class="c1"># HTML, CSS, JSON, ESLint</span>
</span></span><span class="line"><span class="cl">    install_npm <span class="s2">&#34;@tailwindcss/language-server&#34;</span>
</span></span><span class="line"><span class="cl">    install_npm <span class="s2">&#34;@vue/language-server&#34;</span>
</span></span><span class="line"><span class="cl">    install_npm svelte-language-server
</span></span><span class="line"><span class="cl">    install_npm graphql-language-service-cli
</span></span><span class="line"><span class="cl">    install_npm <span class="s2">&#34;@prisma/language-server&#34;</span>
</span></span><span class="line"><span class="cl">    install_npm emmet-ls
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Java LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_java_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_java<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Java&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Java LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_yay jdtls
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Kotlin LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_kotlin_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_kotlin<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Kotlin&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Kotlin LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_yay kotlin-language-server
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Ruby LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_ruby_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_ruby<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Ruby&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Ruby LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_gem solargraph
</span></span><span class="line"><span class="cl">    install_gem ruby-lsp
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># PHP LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_php_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_php<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;PHP&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_node<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;PHP LSP (intelephense) requires npm, skipping&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing PHP LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_npm intelephense
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Lua LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_lua_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_lua<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Lua&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Lua LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman lua-language-server
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Zig LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_zig_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_zig<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Zig&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Zig LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman zls
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Haskell LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_haskell_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_haskell<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Haskell&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Haskell LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_yay haskell-language-server
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Elixir LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_elixir_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_elixir<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Elixir&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Elixir LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_yay elixir-ls
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Scala LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_scala_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_scala<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Scala&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Scala LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_yay metals
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># C# / F# (.NET) LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_dotnet_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_dotnet<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;.NET (C#/F#)&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing .NET LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_yay omnisharp-roslyn
</span></span><span class="line"><span class="cl">    install_yay fsautocomplete
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># OCaml LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_ocaml_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_ocaml<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;OCaml&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing OCaml LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> command_exists opam<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        opam install ocaml-lsp-server -y <span class="o">&amp;&amp;</span> success <span class="s2">&#34;ocaml-lsp-server&#34;</span> <span class="o">||</span> warn <span class="s2">&#34;Failed&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        install_yay ocaml-lsp-server
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Clojure LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_clojure_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_clojure<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Clojure&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Clojure LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_yay clojure-lsp-bin
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Nix LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_nix_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_nix<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Nix&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Nix LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman nil
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Bash LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_bash_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_bash<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Bash&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Bash LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman bash-language-server
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Terraform LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_terraform_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_terraform<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Terraform&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Terraform LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman terraform-ls
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># LaTeX LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_latex_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_latex<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;LaTeX&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing LaTeX LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman texlab
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Docker LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_docker_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_docker<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Docker&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Docker LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_yay dockerfile-language-server
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Ansible LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_ansible_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_ansible<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;Ansible&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_node<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        warn <span class="s2">&#34;Ansible LSP requires npm, skipping&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing Ansible LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_npm <span class="s2">&#34;@ansible/ansible-language-server&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># SQL LSPs</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_sql_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! has_sql<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        skip_lang <span class="s2">&#34;SQL (psql/mysql/sqlite)&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing SQL LSPs...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman sqls
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Generic config file LSPs (always install)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">install_generic_lsps<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    info <span class="s2">&#34;Installing generic config LSPs (YAML, TOML, JSON, Markdown, XML)...&#34;</span>
</span></span><span class="line"><span class="cl">    install_pacman yaml-language-server
</span></span><span class="line"><span class="cl">    install_pacman taplo               <span class="c1"># TOML</span>
</span></span><span class="line"><span class="cl">    install_pacman marksman            <span class="c1"># Markdown</span>
</span></span><span class="line"><span class="cl">    install_yay lemminx                <span class="c1"># XML</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Main</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ─────────────────────────────────────────────────────────────</span>
</span></span><span class="line"><span class="cl">main<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;═══════════════════════════════════════════════════════════&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;         LSP Installer for Arch Linux + Mise&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;    (Only installs LSPs for detected languages)&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;═══════════════════════════════════════════════════════════&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># Language-specific LSPs</span>
</span></span><span class="line"><span class="cl">    install_c_lsps
</span></span><span class="line"><span class="cl">    install_rust_lsps
</span></span><span class="line"><span class="cl">    install_go_lsps
</span></span><span class="line"><span class="cl">    install_python_lsps
</span></span><span class="line"><span class="cl">    install_node_lsps
</span></span><span class="line"><span class="cl">    install_java_lsps
</span></span><span class="line"><span class="cl">    install_kotlin_lsps
</span></span><span class="line"><span class="cl">    install_ruby_lsps
</span></span><span class="line"><span class="cl">    install_php_lsps
</span></span><span class="line"><span class="cl">    install_lua_lsps
</span></span><span class="line"><span class="cl">    install_zig_lsps
</span></span><span class="line"><span class="cl">    install_haskell_lsps
</span></span><span class="line"><span class="cl">    install_elixir_lsps
</span></span><span class="line"><span class="cl">    install_scala_lsps
</span></span><span class="line"><span class="cl">    install_dotnet_lsps
</span></span><span class="line"><span class="cl">    install_ocaml_lsps
</span></span><span class="line"><span class="cl">    install_clojure_lsps
</span></span><span class="line"><span class="cl">    install_nix_lsps
</span></span><span class="line"><span class="cl">    install_bash_lsps
</span></span><span class="line"><span class="cl">    install_terraform_lsps
</span></span><span class="line"><span class="cl">    install_latex_lsps
</span></span><span class="line"><span class="cl">    install_docker_lsps
</span></span><span class="line"><span class="cl">    install_ansible_lsps
</span></span><span class="line"><span class="cl">    install_sql_lsps
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Always-useful LSPs for config files</span>
</span></span><span class="line"><span class="cl">    install_generic_lsps
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;═══════════════════════════════════════════════════════════&#34;</span>
</span></span><span class="line"><span class="cl">    success <span class="s2">&#34;LSP installation complete!&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;═══════════════════════════════════════════════════════════&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">main <span class="s2">&#34;</span><span class="nv">$@</span><span class="s2">&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Teoricamente é só isso. Se alguém conhecer um jeito melhor, mande nos comentários abaixo.</p>
]]></content:encoded><category>agentes-de-codigo</category><category>automacao</category><category>ferramentas-de-desenvolvimento</category></item><item><title>Omarchy 2.0 - Básico de LazyVim</title><link>https://akitaonrails.github.io/2025/09/12/omarchy-2-0-basico-de-lazyvim/</link><guid isPermaLink="true">https://akitaonrails.github.io/2025/09/12/omarchy-2-0-basico-de-lazyvim/</guid><pubDate>Fri, 12 Sep 2025 15:00:00 -0300</pubDate><description>&lt;p&gt;Droga, eu falei que o post anterior seria o último da série de &lt;a href="https://akitaonrails.github.io/tags/omarchy/"&gt;Omarchy&lt;/a&gt;, mas achei que a oportunidade é boa pra evangelizar um pouco de Vim também. Já deixei a recomendação pra seguir o canal do &lt;a href="https://www.youtube.com/@EustaquioRangel"target="_blank" rel="noopener"&gt;@Taq&lt;/a&gt;, onde ele explica muito mais a fundo como o NeoVim funciona. Também existe o &lt;a href="https://github.com/ThePrimeagen/vim-be-good"target="_blank" rel="noopener"&gt;tutorial &amp;ldquo;vim-be-good&amp;rdquo; do Primeagen&lt;/a&gt;. Esse segundo, em particular, é um tutorial interativo dentro do próprio NeoVim, pra praticar a navegação - que muitos podem achar difícil no começo.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Droga, eu falei que o post anterior seria o último da série de <a href="/tags/omarchy/">Omarchy</a>, mas achei que a oportunidade é boa pra evangelizar um pouco de Vim também. Já deixei a recomendação pra seguir o canal do <a href="https://www.youtube.com/@EustaquioRangel"target="_blank" rel="noopener">@Taq</a>, onde ele explica muito mais a fundo como o NeoVim funciona. Também existe o <a href="https://github.com/ThePrimeagen/vim-be-good"target="_blank" rel="noopener">tutorial &ldquo;vim-be-good&rdquo; do Primeagen</a>. Esse segundo, em particular, é um tutorial interativo dentro do próprio NeoVim, pra praticar a navegação - que muitos podem achar difícil no começo.</p>
<p>Vou fazer somente este um artigo sobre isso e não pretendo cobrir mais do que a ponta do Iceberg. A idéia é servir pra quem está vindo de outros editores como Sublime Text ou VS Code e não consegue começar a navegar ou até mesmo quitar do Vim kkk 🤣.</p>
<h3>Comandos Iniciais<span class="hx:absolute hx:-mt-20" id="comandos-iniciais"></span>
    <a href="#comandos-iniciais" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Como falei no <a href="https://akitaonrails.com/2025/09/07/omarchy-2-0-lazyvim-lazyextras/"target="_blank" rel="noopener">post anterior sobre LazyVim</a>, vou assumir que já entendeu pelo menos como instalar suporte à sua linguagem com <strong>LazyExtras</strong> e já aprendeu a versionar usando <a href="https://akitaonrails.com/2025/09/07/omarchy-2-0-mise-pra-organizar-ambientes-de-desenvolvimento/"target="_blank" rel="noopener"><strong>Mise</strong></a>.</p>
<p>Sem nem entrar no LazyVim, a primeira coisa a saber é que ele instala todas as configurações relevantes no diretório <code>~/.config/nvim</code>. Normalmente não precisa mexer nada lá. Deixa arquivos como <code>lazyvim.json</code> sem mexer. Notem que ele faz a mesma coisa quem um NPM da vida: tem um arquivo <code>lazy-lock.json</code> que declara a versão/commit de cada plugin instalado. O Lazyvim faz algo parecido com um <code>npm install</code> da vida. Só curiosidade pra você saber como ele se organiza.</p>
<p>Se precisar customizar algo, normalmente vai ser no diretório <code>~/.config/nvim/lua/config</code>. Foi lá onde eu adicionei suporte a Mise, por exemplo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">~/.config/nvim
</span></span><span class="line"><span class="cl">❯ cat lua/config/mise.lua
</span></span><span class="line"><span class="cl">-- Prepend mise shims to PATH
</span></span><span class="line"><span class="cl">vim.env.PATH <span class="o">=</span> vim.env.HOME .. <span class="s2">&#34;/.local/share/mise/shims:&#34;</span> .. vim.env.PATH</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Vão ser sempre scripts escritos em Lua. E nem precisa saber Lua a fundo. De bater o olho é uma linguagem muito simples, não muito diferente de um Python ou Javascript e qualquer programador deve ser capaz de ler qualquer trecho sem nenhum problema. Além disso, na maioria dos casos você vai copiar configurações que tirou da documentação, wiki ou chatgpt mesmo, então é só saber que as coisas vão nesse local.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912110425_screenshot-2025-09-12_11-04-07.png" alt="primeiros passos"  loading="lazy" /></p>
<p>Entenda que NeoVim tem o conceito de tecla &ldquo;<strong>Leader</strong>&rdquo;, é uma tecla que precede hotkeys pra outros comandos (também tem <strong>localleader</strong> que é barra invertida <strong>\</strong>). Isso é configurável mas no LazyVim o Leader é a tecla <strong>&ldquo;Espaço/Space&rdquo;</strong>. Em muita documentação vamos ver falando <em>&ldquo;apertem Leader-w&rdquo;</em>, que significa <strong>Espaço+w</strong> e agora você sabe o que isso significa.</p>
<p>Pra abrir um arquivo tem pelo menos 3 formas diferentes, 2 delas mostradas na foto acima:</p>
<blockquote>
  <p><strong>Space+E</strong> abre o <strong>NeoTree</strong> que é esse sidebar na esquerda que se parece com o Windows Explorer. Dá pra navegar com teclado ou com mouse mesmo. Ache seu arquivo e pressione &ldquo;Enter&rdquo; pra abrir, daí &ldquo;Space+E&rdquo; de novo pra esconder o sidebar. Se quiser saber como criar um novo arquivo, um novo sub-diretório, renomear e tals, digite <strong>?</strong> (tecla de interrogação) pra ver esta ajuda:</p>

</blockquote>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912142438_neotree.gif" alt="NeoTree"  loading="lazy" /></p>
<p>A terceira forma é manualmente com o comando <strong>:e</strong> seguida do nome do arquivo no diretório local. Tem auto-complete também, esse é o jeito mais rápido, se souber o que está procurando.</p>
<p>Sempre que quiser cancelar qualquer coisa ou fechar &ldquo;floating windows&rdquo; (pop-ups, dialog boxes). Só apertar &ldquo;Esc&rdquo;. Esc é fundamental no NeoVim.</p>
<p>Aberto um arquivo, ele fica no <strong>Buffer</strong>. Pense em Buffer como &ldquo;Abas Abertas&rdquo; no seu VS Code. Pra navegar por Buffer (tipo alt+tab entre seus arquivos já abertos) é simples:</p>
<ul>
<li><strong>]+b</strong> pra próxima &ldquo;aba&rdquo; (próximo Buffer)</li>
<li><strong>[+b</strong> Buffer anterior</li>
<li><strong>Space+bd</strong> pra &ldquo;fechar a aba&rdquo; (fechar o Buffer)</li>
<li><strong>Space+bo</strong> pra ficar onde está e fechar os outros buffers</li>
</ul>
<p>Abra quantos arquivos quiser. Se um deles for um daqueles logs enormes que abriu por acidente, <code>Space+bd</code> pra fechar e pronto.</p>
<p>Falando em fechar, <strong>como que sai do NeoVim?</strong> Tem vários jeitos:</p>
<ul>
<li><strong>Space+q</strong></li>
<li><strong>:q</strong></li>
<li><strong>:q!</strong></li>
</ul>
<p>A diferença: o primeiro é o jeito customizado no LazyVim. O Segundo é o jeito padrão usando o recurso de &ldquo;comandos&rdquo; que começa sempre com &ldquo;dois pontos&rdquo;. E o terceiro é se você modificou algo no arquivo mas cancelar, sair sem salvar nada, por isso a exclamação.</p>
<p>Normalmente eu uso <strong>:wq</strong> que significa &ldquo;write&rdquo; e &ldquo;quit&rdquo;. Então ele primeiro salva as mudanças no arquivo e depois já quita do programa. É útil quando estou só editando um arquivo de configuração rápido.</p>
<h3>Navegação Básica<span class="hx:absolute hx:-mt-20" id="navegação-básica"></span>
    <a href="#navega%c3%a7%c3%a3o-b%c3%a1sica" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Agora tenho um arquivo aberto. Como navegar por ele? Primeiro, como ir até o fim do arquivo e depois voltar pro começo do arquivo? É uma coisa que uso bastante, só digitar <strong>Shift+g</strong> pra ir pro fim do arquivo e depois <strong>gg</strong> pra voltar pro começo. Simples assim.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912143147_home-end.gif" alt="home-end"  loading="lazy" /></p>
<p>Agora vamos aprender vários comandos de uma só vez:</p>
<ul>
<li>Digite <strong>v</strong>. Isso inicia o <strong>&ldquo;modo de visualização&rdquo;</strong> que, na prática, significa começar a selecionar a partir de onde se encontra seu cursor.</li>
<li>Digite <strong>j</strong>. Que é o equivalente à &ldquo;seta pra baixo&rdquo; pra ir pra linha de baixo. Já deve ter ouvido falar que em Vim se navega com &ldquo;hjkl&rdquo; que são, respectivamente, pra esquerda, pra baixo, pra cima, pra direita.</li>
<li>Digite <strong>x</strong>. Que é o equivalente a &ldquo;cortar&rdquo; e colocar o conteúdo no clipboard. Feito isso, digitando <strong>p</strong> você dá &ldquo;paste&rdquo;, que é colar.</li>
<li>Digite <strong>u</strong>. Que é o comando que mais se usa: o de <strong>Undo</strong> ou desfazer a última modificação.</li>
</ul>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912143741_marcar-apagar.gif" alt="marcar-apagar"  loading="lazy" /></p>
<p>Isso tudo funciona no chamado <strong>&ldquo;modo de comando&rdquo;</strong>, que é o modo padrão que o Vim abre todo arquivo. Nesse modo não dá pra digitar nenhum texto. Como podem ver, cada letra sozinha é um comando, como &ldquo;x&rdquo; pra cut ou &ldquo;p&rdquo; pra paste.</p>
<p>Pra digitar, primeiro precisa digitar <strong>i</strong> (só a letra &ldquo;i&rdquo; em minúsculo), que daí muda do modo de comando pro <strong>&ldquo;modo de edição&rdquo;</strong>. Agora é só digitar seu texto normalmente, como em qualquer editor. Quando quiser algum comando, basta digitar <strong>ESC</strong> pra voltar pro modo de comando. Vamos fazer isso o tempo todo, por isso muita gente re-mapeia a tecla &ldquo;caps lock&rdquo; do teclado pra ser a ESC e ficar fácil só tocar com o mindinho esquerdo.</p>
<h3>Combinando Comandos<span class="hx:absolute hx:-mt-20" id="combinando-comandos"></span>
    <a href="#combinando-comandos" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><blockquote>
  <p>Ainda no modo de comando, como navegamos pelo arquivo mais fácil?</p>

</blockquote>
<p>Além das teclas &ldquo;hjkl&rdquo;, podemos navegar mais fácil usando <strong>b</strong> pra &ldquo;palavra anterior&rdquo; ou <strong>w</strong> pra palavra (<em>word</em>) posterior:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912144226_words.gif" alt="words"  loading="lazy" /></p>
<p>O modo de comando permite combinar comandos, portanto podemos fazer:</p>
<ul>
<li><strong>dw</strong> pra apagar a próxima palavra</li>
<li><strong>db</strong> pra apagar a palavra anterior</li>
<li><strong>d4w</strong> pra apagar (delete) as 4 palavras (words) seguintes</li>
<li><strong>d4j</strong> pra apagar as 4 linhas pra baixo</li>
</ul>
<p>O <a href="https://github.com/ThePrimeagen/vim-be-good"target="_blank" rel="noopener">tutorial do Primeagen</a> tem vários exercícios pra esse tipo de navegação, recomendo se exercitar. Num VS Code todo mundo está acostumado a primeiro pegar o mouse, marcar o bloco que quer apagar visualmente, depois apertar delete ou backspace. No Vim, olhamos onde está o cursor, apertamos ESC pra estar no modo de comando, e digitamos a operação e a localização. Teste todas as combinações que conseguir imaginar.</p>
<p>Esta é a <strong>mudança de paradigma</strong> que incomoda os preguiçosos. Mas uma vez aprendido isso, você vai achar incômodo um editor que te obrigado a usar mouse pra coisas básicas.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912144801_change.gif" alt="change in place"  loading="lazy" /></p>
<p>Agora fica mais interessante: <em>e se em vez de apagar uma palavra, eu queira substituir a palavra onde meu cursor está pra outra palavra?</em></p>
<p>Num editor normal, você marcaria com o mouse (ou usando alguma combinação como &ldquo;ctrl+shift+seta&rdquo;), e digitaria por cima ou apagaria a palavra.</p>
<p>No LazyVim tem plugins configurados pra coisas mais interessantes. No video acima veja como estou substituindo palavras <em>&ldquo;in-place&rdquo;</em>. Isso se faz com o comando <strong>ciw</strong>.</p>
<ul>
<li><strong>ciw</strong> apaga a palavra inteira embaixo do cursor e abre o modo de edição pra você digitar a substituição</li>
<li><strong>ce</strong> apaga a partir do cursor até o fim da palavra (preserva o começo da palavra) e também abre pra você digitar no lugar</li>
<li><strong>Shift-c</strong> (C maiúsculo) apaga tudo a partir do seu cursor até o fim da linha inteira e abre pra você digitar.</li>
</ul>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912145439_bloco.gif" alt="Mudar Bloco Vertical"  loading="lazy" /></p>
<p>Mas isso ainda não parece tãaaaao legal. E se quiser mudar só a primeira letra de várias linhas ao mesmo tempo, por exemplo, no texto do video acima, quero mudar só o hífen (&quot;-&quot;) de cada linha de tags?</p>
<p>Falei antes que apertando <strong>v</strong> no modo de comando ele começa o modo de visualização e dá pra selecionar a partir dali. Mas existe <strong>Ctrl+v</strong> que abre o modo de marcação de blocos verticais.</p>
<p>Nesse modo usamos as teclas &ldquo;hjkl&rdquo; normalmente, como <strong>j</strong> pra ir pra baixo, mas em vez de marcar a próxima linha inteira, ele marca só o caracter logo abaixo do seu cursor. Agora posso apagar com <strong>d</strong> e digitar <strong>Shift-i</strong> (&ldquo;I&rdquo; maiúsculo) pra entrar em modo de edição no começo do bloco e substituir pelo que quiser.</p>
<p>LazyVim tem plugins pra comentários, mas essa é outra alternativa se quiser adicionar &ldquo;//&rdquo; ou &ldquo;#&rdquo; no começo de várias linhas pra comentar, por exemplo. No caso, leia sobre o plugin <a href="https://github.com/folke/ts-comments.nvim"target="_blank" rel="noopener"><strong>ts-comments</strong></a> pra opções melhores pra comentário. Pra iniciar um novo bloco de comentário, digite <strong>gco</strong> pra adicionar um comentário abaixo.</p>
<p><em>&ldquo;Modo de bloco&rdquo;</em> como mostrei acima, é uma das coisas que eu mais uso em código.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912150112_search-replace.gif" alt="Search and Replace"  loading="lazy" /></p>
<p>Mas só isso é muito pouco. E se quiser substituir <strong>TODAS AS PALAVRAS</strong> iguais do texto de uma só vez. No video de exemplo acima, quero substituir &ldquo;domínio&rdquo; por &ldquo;DOMAIN&rdquo; e &ldquo;Cloudflare&rdquo; por &ldquo;AWS Amazon&rdquo;, como faço? Isso é &ldquo;Search and Replace&rdquo; que tem em todo editor e em Vim é muito fácil:</p>
<p>Digitamos <strong>:%s/domínio/DOMAIN/</strong>.</p>
<p>Se você é programador já deve ter visto essa sintaxe antes. É a sintaxe de <strong>REGEX MATCH</strong>. Sim, tem que saber Regex (e não, não é nem PCRE e nem Unicode, é um dialeto de Regex do próprio NeoVim, mas é parecido).</p>
<p>Como falei antes, &ldquo;dois pontos&rdquo; abre o box de digitar comandos, <strong>&quot;%s&quot;</strong> inicia &ldquo;search com regex&rdquo; e entre as barras &ldquo;//&rdquo; primeiro vai o que procura e depois com o que quer substituir.</p>
<p>Mas esse é o jeito no NeoVim puro, no LazyVim, tem o plugin <a href=""><strong>grug-far</strong></a> e se ativa com o comando <strong>SPACE+sr</strong>:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912150648_screenshot-2025-09-12_15-06-32.png" alt="grug-far"  loading="lazy" /></p>
<p>Agora sim, mais parecido com do VS Code, né? Use o que achar mais fácil.</p>
<h3>Conclusão<span class="hx:absolute hx:-mt-20" id="conclusão"></span>
    <a href="#conclus%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Como falei, isto é somente a ponta da ponta do iceberg, o mínimo do mínimo suficiente pra pelo menos começar editando arquivos simples de configuração sem abrir Nano ou VS Code só pra isso.</p>
<p>Leia a documentação do LazyVim. Veja os <a href="https://www.lazyvim.org/keymaps"target="_blank" rel="noopener">keymaps</a> pra descobrir outros comandos. Preste atenção em cada letra que aperta no modo de comando, o LazyVim mostra as opções disponíveis. Por exemplo, digamos que eu apertei <strong>g</strong> (goto), ele vai mostrar uma ajuda no canto inferior direito:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20250912151849_screenshot-2025-09-12_15-18-38.png" alt="ajuda"  loading="lazy" /></p>
<p>Assim você sempre pode descobrir novos comandos ou relembrar comandos que usa pouco. Por isso recomendo o LazyVim, que já vem bem configurado pra te ajudar. Quem faz essa funcionalidade é o plugin <a href="https://github.com/folke/which-key.nvim"target="_blank" rel="noopener"><strong>which-key</strong></a>, caso queira a mesma coisa num NeoVim que você configurou do zero.</p>
<p>Existem diversos <a href="https://vim.rtorr.com/"target="_blank" rel="noopener"><strong>Cheatsheets</strong></a> por aí com tabelas de combinações de comandos importantes. Vale explorar.</p>
<p>Mas não é só isso, LazyVim vem com dezenas de <a href="https://www.lazyvim.org/plugins"target="_blank" rel="noopener">plugins</a> pra formatação, linting, LSP integrado, GIT integrado, e muito mais. Não tem como eu documentar um a um aqui. Cada um deles tem sua própria documentação na página de plugins do LazyVim.org.</p>
<p>Novamente, não esqueça de chamar o <strong>:LazyExtras</strong> e instalar os plugins opcionais das suas linguagens.</p>
]]></content:encoded><category>omarchy</category><category>ferramentas-de-desenvolvimento</category><category>tutoriais</category></item><item><title>Omarchy 2.0 - TUIs (Terminal User Interface Apps)</title><link>https://akitaonrails.github.io/2025/09/09/omarchy-2-0-tuis/</link><guid isPermaLink="true">https://akitaonrails.github.io/2025/09/09/omarchy-2-0-tuis/</guid><pubDate>Tue, 09 Sep 2025 01:00:00 -0300</pubDate><description>&lt;p&gt;Uma das coisas mais frustrantes pra um usuário de Linux é que existem muito poucos Apps gráficos bem feitos. Veja um Gimp ou LibreOffice. São feios, antiquados, muito parecidos com a primeira vez que usei eles mais de 20 anos atrás.&lt;/p&gt;
&lt;p&gt;Os apps mais &amp;ldquo;modernos&amp;rdquo; são basicamente front-ends web enlatados dentro de um wrapper Electron. O problema? São &lt;strong&gt;PESADOS&lt;/strong&gt; consomem RAM como se não houvesse amanhã. Comece a abrir Discord, Spotify, e vários desses e veja se seu notebook velho de 8GB de RAM vai aguentar.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Uma das coisas mais frustrantes pra um usuário de Linux é que existem muito poucos Apps gráficos bem feitos. Veja um Gimp ou LibreOffice. São feios, antiquados, muito parecidos com a primeira vez que usei eles mais de 20 anos atrás.</p>
<p>Os apps mais &ldquo;modernos&rdquo; são basicamente front-ends web enlatados dentro de um wrapper Electron. O problema? São <strong>PESADOS</strong> consomem RAM como se não houvesse amanhã. Comece a abrir Discord, Spotify, e vários desses e veja se seu notebook velho de 8GB de RAM vai aguentar.</p>
<p>Mas, especialmente se você é um programador, deveria dar mais atenção pra TUIs. Num primeiro momento alguns devem virar o nariz: <em>&ldquo;apps de terminal são feios, preto e branco, quadrados, blerg&rdquo;</em></p>
<p>Se fosse 20 anos atrás, estariam certos. Mas é 2025 e hoje em dia terminais suportam 256 cores (mais que suficiente), suportam várias resoluções e, mais importante, suportam fontes, em particular <a href="https://www.nerdfonts.com/"target="_blank" rel="noopener">Nerd Fonts</a>, fontes que tem ícones dentro. É assim que funciona uma ferramenta como <a href="https://github.com/eza-community/eza"target="_blank" rel="noopener">eza</a>, que eu uso todo dia com alias pra <code>ls</code> e fica assim:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-08-29_16-50-25.png" alt="eza"  loading="lazy" /></p>
<p>Não é só isso, existem bibliotecas modernas, pra diversas linguagens, como <a href="https://github.com/charmbracelet/bubbletea"target="_blank" rel="noopener"><strong>BubbleTea</strong></a>, que é um framework pra construir TUIs. Chequem o GitHub deles mas tem as ferramentas pra fazer interfaces assim:</p>
<p><img src="https://camo.githubusercontent.com/e2b13cfb4ea64e98028ab21e0dca97a6af46d8eeb78ef092c5cd4669ea7b7bef/68747470733a2f2f73747566662e636861726d2e73682f627562626c657465612f627562626c657465612d6578616d706c652e676966" alt="BubbleTea"  loading="lazy" /></p>
<p>E se quiser só um widget simples pra complementar um script Bash que está fazendo, eles tem o <a href="https://github.com/charmbracelet/gum"target="_blank" rel="noopener"><strong>Gum</strong></a>, que permite interfaces assim:</p>
<p><img src="https://camo.githubusercontent.com/cea695e2df946b14838196a5cfb7d6608f03387ba42c7a7fb5afa6432371635c/68747470733a2f2f7668732e636861726d2e73682f7668732d31715935375272516c584375796473456744703638472e676966" alt="Gum"  loading="lazy" /></p>
<p>E pra usar é só instalar o binário e no seu script fazer linhas assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># exemplos de Gum</span>
</span></span><span class="line"><span class="cl">gum choose <span class="s2">&#34;fix&#34;</span> <span class="s2">&#34;feat&#34;</span> <span class="s2">&#34;docs&#34;</span> <span class="s2">&#34;style&#34;</span> <span class="s2">&#34;refactor&#34;</span> <span class="s2">&#34;test&#34;</span> <span class="s2">&#34;chore&#34;</span> <span class="s2">&#34;revert&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">gum input --placeholder <span class="s2">&#34;scope&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">gum confirm <span class="s2">&#34;Commit changes?&#34;</span> <span class="o">&amp;&amp;</span> git commit -m <span class="s2">&#34;</span><span class="nv">$SUMMARY</span><span class="s2">&#34;</span> -m <span class="s2">&#34;</span><span class="nv">$DESCRIPTION</span><span class="s2">&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E se usa <a href="https://akitaonrails.com/tags/omarchy/"target="_blank" rel="noopener"><strong>Omarchy</strong></a> eles ainda trazem uma funcionalidade extra pra TUIs. Basta clicar &ldquo;SUPER+ALT+SPACE&rdquo; pra trazer o menu principal, depois escolher &ldquo;INSTALL&rdquo; e &ldquo;TUI&rdquo;. Ou simplesmente abrir o terminal e executar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>$OMARCHY_PATH/bin/omarchy-tui-install</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-08_23-22-50.png" alt="omarchy-tui-install"  loading="lazy" /></p>
<p>Ele vai pedir um nome pro App e a linha de comando pra executar. Dá pra escolher icones também no <a href="https://dashboardicons.com/"target="_blank" rel="noopener">Dashboard Icons</a>. Registrando dessa forma, quando chamar o launcher Rofi com &ldquo;SUPER+SPACE&rdquo; e digitar &ldquo;lazy&rdquo; vai aparecer o LazyDocker como se fosse um app normal:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/hdmi-a-3.png" alt="Rofi LazyDocker"  loading="lazy" /></p>
<p>E como em Hyprland não tem barra de título nem nada, apps TUI ou webapps (tem <code>omarchy-webapp-install</code> também) abrem como se fossem apps &ldquo;nativos&rdquo;:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-09_00-49-28.png" alt="tiles windows"  loading="lazy" /></p>
<p>Leiam as seções de <a href="https://learn.omacom.io/2/the-omarchy-manual/59/tuis"target="_blank" rel="noopener">TUIs</a> e <a href="https://learn.omacom.io/2/the-omarchy-manual/63/web-apps"target="_blank" rel="noopener">Web-Apps</a> no manual do Omarchy.</p>
<p>Obviamente, isso é só se você é daqueles que prefere a sensação de estar executando &ldquo;Apps&rdquo;, mas é a mesma coisa se abrir um Terminal e simplesmente digitar o <code>lazydocker</code> na linha de comando - que é minha preferência. O que esses scripts do Omarchy fazem é criar um arquivo <code>.desktop</code> em <code>~/.local/share/applications</code>. O exemplo do <code>LazyDocker.desktop</code> gera isto:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>❯ cat ~/.local/share/applications/LazyDocker.desktop
[Desktop Entry]
Version=1.0
Name=LazyDocker
Comment=LazyDocker
Exec=alacritty --class TUI.tile -e lazydocker
Terminal=false
Type=Application
Icon=/home/akitaonrails/.local/share/applications/icons/LazyDocker.png
StartupNotify=true</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Se não quiser mais este launcher é só apagar o arquivo ou chamar o script <code>$OMARCHY_PATH/bin/omarchy-tui-remove</code>.</p>
<p>Esse recurso é particularmente interessante no Hyprland porque diferente de GNOME ou KDE, a janela não tem barra superior de título, então não entrega que você está só abrindo um terminal ou navegador web. É assim que ele já vem pré-configurado com coisas como ChatGPT ou Grok parecendo que são apps &ldquo;nativos&rdquo;, mas na verdade são só janelas de Chromium abrindo direto as URLs de cada um:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-09_00-54-52.png" alt="WebApps Omarchy"  loading="lazy" /></p>
<h2>Alguns TUIs que eu gosto<span class="hx:absolute hx:-mt-20" id="alguns-tuis-que-eu-gosto"></span>
    <a href="#alguns-tuis-que-eu-gosto" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Na minha opinião, já que não tem Apps com GUIs bonitas pra Linux, é melhor mesmo usar os respectivos web-apps como Canva ou ChatGPT dessa forma, mas mais interessante é ter TUIs mesmo. Como falei, hoje em dia não é difícil fazer TUIs bonitas. Pra um programador, a vantagem é não tem que lidar, primeiro com frameworks de front-end, segundo, ter que fazer deploy em algum lugar na internet.</p>
<p>TUIs são leves, usam poucos recursos na máquina, são fáceis pra qualquer programador fazer, e você pode ter um home server ou um servidor num cloud qualquer, acessar via SSH e acessar a TUI, sem ter que lidar com X11 ou RDP ou qualquer coisa mais pesada só pra ter um GUI.</p>
<p>Alguns TUIs são óbvios, no <a href="https://akitaonrails.com/2025/09/07/omarchy-2-0-lazyvim-lazyextras/"target="_blank" rel="noopener">post anterior</a> já falei de <a href="https://www.lazyvim.org/"target="_blank" rel="noopener"><strong>LazyVim</strong></a> e como ele é um editor de textos tão competente e completo quando um VS Code, usando só uma fração dos recursos da máquina. Todo mundo deve conhecer ferramentas como HTOP ou BTOP. Além dos <a href="https://github.com/jesseduffield/lazygit"target="_blank" rel="noopener">LazyGit</a> ou <a href="https://github.com/jesseduffield/lazydocker"target="_blank" rel="noopener">LazyDocker</a> também. Esses todos já vem no Omarchy.</p>
<p>Mas tem muito mais, por exemplo, <a href="https://github.com/danvergara/dblab"target="_blank" rel="noopener"><strong>dblab</strong></a> que é um TUI cliente de banco de dados como MySQL ou Postgres:</p>
<p><img src="https://github.com/danvergara/dblab/raw/main/screenshots/dblab-cover.png" alt="dblab"  loading="lazy" /></p>
<p>Outro similar é <a href="https://github.com/jorgerojas26/lazysql"target="_blank" rel="noopener">LazySQL</a>, feito em Go:</p>
<p><img src="https://github.com/jorgerojas26/lazysql/raw/main/images/lazysql.png" alt="LazySQL"  loading="lazy" /></p>
<p>Ou se você prefere ferramentas feitas em Rust, tem o <a href="https://github.com/achristmascarl/rainfrog"target="_blank" rel="noopener"><strong>rainfrog</strong></a>:</p>
<p><img src="https://github.com/achristmascarl/rainfrog/raw/main/vhs/demo.gif" alt="rainfrog"  loading="lazy" /></p>
<p>Pra quem não consegue usar CURL na linha de comando e prefere usar Postman pra chamar e explorar APIs, tem o TUI <a href="https://github.com/darrenburns/posting"target="_blank" rel="noopener"><strong>Posting</strong></a> que faz a mesma coisa:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/422760155-78359ab0-5e0c-4c0b-a60b-dce06b11bbf5.png" alt="Posting"  loading="lazy" /></p>
<p>Pra nós que rodamos muitos containers Docker, já falei do LazyDocker, mas tem também o <a href="https://github.com/mrjackwills/oxker"target="_blank" rel="noopener"><strong>oxker</strong></a>:</p>
<p><img src="https://github.com/mrjackwills/oxker/raw/main/.github/demo_01.webp" alt="oxker"  loading="lazy" /></p>
<p>Se usar Discord, tem o <a href="https://github.com/ayn2op/discordo"target="_blank" rel="noopener"><strong>discordo</strong></a>:</p>
<p><img src="https://github.com/ayn2op/discordo/raw/main/.github/preview.png" alt="Discordo"  loading="lazy" /></p>
<p>Quem faz muito ricing de Linux já teve que gravar ISOs em Pen Drives dezenas de vezes, pra isso tem o <code>dd</code> na linha de comando, mas tem um TUI mais legal que é o <a href="https://github.com/ifd3f/caligula"target="_blank" rel="noopener"><strong>Caligula</strong></a>:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2025/09/09/omarchy-2-0-tuis/caligula-burning.png" alt="Caligula gravando uma imagem de disco no terminal: barra “Burning… 251.7 MB” no topo, um gráfico de velocidade de escrita oscilando até 32 MB/s ao longo de ~12 segundos, e um painel de Stats mostrando entrada my_cool.img.lz4, saída /dev/sdb, média de escrita de 20.2 MB/s e ETA de 24 segundos."  loading="lazy" /></p>
<p>Se seu SSD está ficando cheio e você não sabe onde diabos que tá ocupando tanto espaço, tem várias ferramentas pra analisar e te mostrar, um deles é o <a href="https://github.com/dundee/gdu"target="_blank" rel="noopener"><strong>gdu</strong></a>:</p>
<p><img src="https://camo.githubusercontent.com/d8fa7d2f7bdd10dce45a81c2accf26d597b300b82e01b97a1288ff2f1fe06c57/68747470733a2f2f61736369696e656d612e6f72672f612f3338323733382e737667" alt="gdu"  loading="lazy" /></p>
<p>E o último que achei legal pela nostalgia é o <a href="https://github.com/andmarti1424/sc-im"target="_blank" rel="noopener"><strong>sc-im</strong></a>, pense em Excel como TUI ou - pra nós que viemos dos anos 80 - pense Lotus 1-2-3 mas com key bindings de Vim:</p>
<p><img src="https://github.com/andmarti1424/sc-im/raw/main/screenshots/scim-plot-graph.gif?raw=true" alt="sc-im"  loading="lazy" /></p>
<p>Pra que abrir Google Spreadsheets só pra fazer um Todo list se dá pra fazer no Terminal?? TUIs são excepcionais!</p>
<p>Se quiser conhecer mais TUIs olhe o <a href="https://github.com/rothgar/awesome-tuis/?tab=readme-ov-file"target="_blank" rel="noopener"><strong>awesome-tuis</strong></a> no GitHub:</p>
<p><a href="https://github.com/rothgar/awesome-tuis/?tab=readme-ov-file"target="_blank" rel="noopener"><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2025/09/09/omarchy-2-0-tuis/awesome-tuis-banner.png" alt="awesome tuis"  loading="lazy" /></a>
De novo: zero necessidade de front-ends web pesadas pra coisas simples. Nada supera a simplicidade de uma linha de comando. E com bibliotecas como BubbleTea ou Gum, está muito fácil pra qualquer um fazer um app bonito. E com Hyprland e Omarchy, fica tudo integrado lado-a-lado de qualquer outro app com GUI.</p>
<p>Filosofando um pouco, a história das GUIs começa com interfaces gráficas <em>skeumorphic</em> que tentam imitar objetos do nosso dia a dia, em particular parecendo pseudo-3D, como era um Windows 95. Chegou nos anos 2000 e começaram a migrar pra interfaces <em>flat</em> ou <em>minimalistas</em>, tirando completamente o skeumorphismo, deixando tudo plano. Foi a partir do Metro do Windows 8, principalmente. E eu acho que isso converge pra estilo mais de TUI, dando uma volta completa, voltando a como era nos terminais dos anos 70. Eu particularmente acho isso fascinante.</p>
]]></content:encoded><category>omarchy</category><category>ferramentas-de-desenvolvimento</category><category>linux</category></item><item><title>Omarchy 2.0 - Mise pra organizar ambientes de desenvolvimento</title><link>https://akitaonrails.github.io/2025/09/07/omarchy-2-0-mise-pra-organizar-ambientes-de-desenvolvimento/</link><guid isPermaLink="true">https://akitaonrails.github.io/2025/09/07/omarchy-2-0-mise-pra-organizar-ambientes-de-desenvolvimento/</guid><pubDate>Sun, 07 Sep 2025 16:40:00 -0300</pubDate><description>&lt;p&gt;Continuando meus posts sobre &lt;a href="https://www.akitaonrails.com/tags/omarchy"target="_blank" rel="noopener"&gt;Omarchy&lt;/a&gt; mais um post introdutório, mas agora sobre &lt;a href="https://mise.jdx.dev/getting-started.html"target="_blank" rel="noopener"&gt;Mise-en-place&lt;/a&gt; que já vem pré-instalado. No Omarchy, se digitar &amp;ldquo;Super+Alt+Espaço&amp;rdquo; vai abrir o menu principal. Escolha &amp;ldquo;Install&amp;rdquo; e depois &amp;ldquo;Development&amp;rdquo; e vai aparecer várias linguagens/frameworks que pode instalar, como Ruby on Rails ou Go.&lt;/p&gt;
&lt;p&gt;Mas não precisa usar estes menus. Vamos entender.&lt;/p&gt;
&lt;p&gt;Num Arch Linux ou Ubuntu da vida, um amador instalaria ruby ou python fazendo algo assim:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;# arch
yay -S ruby python3
# ubuntu
apt install ruby python3&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copy code"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Este é o jeito ERRADO.&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>Continuando meus posts sobre <a href="https://www.akitaonrails.com/tags/omarchy"target="_blank" rel="noopener">Omarchy</a> mais um post introdutório, mas agora sobre <a href="https://mise.jdx.dev/getting-started.html"target="_blank" rel="noopener">Mise-en-place</a> que já vem pré-instalado. No Omarchy, se digitar &ldquo;Super+Alt+Espaço&rdquo; vai abrir o menu principal. Escolha &ldquo;Install&rdquo; e depois &ldquo;Development&rdquo; e vai aparecer várias linguagens/frameworks que pode instalar, como Ruby on Rails ou Go.</p>
<p>Mas não precisa usar estes menus. Vamos entender.</p>
<p>Num Arch Linux ou Ubuntu da vida, um amador instalaria ruby ou python fazendo algo assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code># arch
yay -S ruby python3
# ubuntu
apt install ruby python3</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p><strong>Este é o jeito ERRADO.</strong></p>
<p>Esses comandos vão instalar a versão mais nova de cada linguagens e toda vez que atualizar o sistema com <code>yay -Syu</code> ou <code>apt upgrade</code>, vai puxar as versões mais novas ainda.</p>
<p>Só que se você desenvolve projetos de verdade, <strong>não quer que as versões mudem</strong>.</p>
<p>A versão do deploy no servidor no cloud e a versão na sua máquina local <strong>TEM QUE SER AS MESMAS</strong>.</p>
<p>Se está usando Ruby v3.0.7 e Node.js 22.19.0, não pode ficar refém que quando atualizar seu sistema, do nada vai aparecer Ruby 3.4.5 e Node 24.7.0. Tudo vai começar a quebrar e você vai ficar super confuso sem saber porque. Esse é o erro mais primário que um júnior comete.</p>
<p>Pra evitar isso, cada projeto que está trabalhando PRECISA ESTAR TRAVADO EM VERSÕES FIXAS.</p>
<p>O jeito mais fácil de fazer isso em 2025 é usando <strong>MISE</strong>. Como falei, ele já vem instalado e ativado no Omarchy, mas se estiver usando outra distro basta instalar Mise manualmente:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>yay -S mise

# .bashrc
eval $(mise activate bash)</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Adapte isso pra ZSH, Fish ou outro shell que estiver usando, leia a <a href="https://mise.jdx.dev/installing-mise.html"target="_blank" rel="noopener">documentação</a></p>
<p>Agora navegue pro diretório do seu projeto, por exemplo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>cd ~/Projects/AkitaOnRails.com</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E trave as versões:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>mise use ruby@3.2.3
mise use node@14.21.3</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Isso vai criar o arquivo <code>.tool-versions</code> que você deve adicionar no git do seu repositório:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>❯ cat .tool-versions
ruby 3.2.3
nodejs 14.21.3

❯ git add .tool-versions</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E pronto, toda vez que fizer <code>cd</code> pro diretório, o Mise vai ativar exatamente a versão correta pra esse projeto. Veja:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>AkitaOnRails.com [ master][$!?⇡][ v24.7.0][💎 v3.2.3]
❯ ruby -v
ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [x86_64-linux]

AkitaOnRails.com [ master][$!?⇡][ v24.7.0][💎 v3.2.3]
❯ which ruby
/home/akitaonrails/.local/share/mise/installs/ruby/3.2.3/bin/ruby</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Note que, se estiver usando o prompt <a href="https://akitaonrails.com/2025/09/07/omarchy-2-0-zsh-configs/"target="_blank" rel="noopener">Starship</a> como expliquei no post anterior, com um preset como Pure Prompt, ele mostra no prompt as versões de cada linguagem pra que fique fácil de ver se estiver numa versão errada.</p>
<p>No caso, se leu com atenção, já deve ter notado que <strong>SIM, ESTOU NA VERSÃO ERRADA</strong> do Node.js. Olhem como no prompt ele fala que estou usando Node 24.7.0 mas no arquivo <code>.tool-versions</code> ele pede 14.21.3.</p>
<p>O motivo de estar &ldquo;missing&rdquo; é porque esta máquina é recém-instalada, mas o projeto é velho.</p>
<p>Então vamos checar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>AkitaOnRails.com [ master][$!?⇡][ v24.7.0][💎 v3.2.3]
❯ mise list
Tool    Version            Source                                              Requested
go      1.25.0             ~/.config/mise/config.toml                          latest
node    14.21.3 (missing)  /mnt/data/Projects/AkitaOnRails.com/.tool-versions  14.21.3
node    22.18.0
python  3.13.7
ruby    3.2.3              /mnt/data/Projects/AkitaOnRails.com/.tool-versions  3.2.3
ruby    3.4.5</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Veja como na listagem de <code>mise list</code> ele fala que 14.21.3 está &ldquo;missing&rdquo;. Então vamos instalar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>AkitaOnRails.com [ master][$!?⇡][ v24.7.0][💎 v3.2.3]
❯ mise use node@14.21.3
mise /mnt/data/Projects/AkitaOnRails.com/.tool-versions tools: node@14.21.3

AkitaOnRails.com [ master][$!?⇡][ v14.21.3][💎 v3.2.3]
❯</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Com o comando <code>mise use</code> podemos pedir pra instalar e usar uma versão em particular. Se já não estiver instalado, ele vai instalar. Note como depois disso o prompt do Starship mudou pra refletir que agora estamos usando 14.21.3. Esse é o jeito certo.</p>
<p>Se não estiver necessariamente num diretório de projeto com versões travadas, ainda assim é possível rodar comandos usando uma versão específica, assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>mise exec ruby@3.2.1 -- ruby ...</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Digamos que queira gerar um projeto de Rails numa versão específica de Ruby:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>mise exec ruby@3.2.3 -- rails new todo-exercise</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Mesma coisa vale pra generators em Node, como Next.js ou qualquer outro framework.</p>
<p>Não chequei se o LazyVim no Omarchy já vem configurado assim, mas caso não venha, pro NeoVim suportar Mise precisa adicionar isso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="c1">-- Prepend mise shims to PATH</span>
</span></span><span class="line"><span class="cl"><span class="n">vim.env</span><span class="p">.</span><span class="n">PATH</span> <span class="o">=</span> <span class="n">vim.env</span><span class="p">.</span><span class="n">HOME</span> <span class="o">..</span> <span class="s2">&#34;/.local/share/mise/shims:&#34;</span> <span class="o">..</span> <span class="n">vim.env</span><span class="p">.</span><span class="n">PATH</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Basta colocar isso em <code>~/.config/nvim/lua/config/mise.lua</code> que ele deve carregar o path correto. Pra integrar com outros editores, cheque <a href="https://mise.jdx.dev/ide-integration.html"target="_blank" rel="noopener">esta documentação</a>. Tem um MONTE de opções avançadas que é bom ler a respeito na <a href="https://mise.jdx.dev/dev-tools/"target="_blank" rel="noopener">seção de Dev-Tools</a> mas o básico é o que listei aqui.</p>
<h2>E bancos de dados??<span class="hx:absolute hx:-mt-20" id="e-bancos-de-dados"></span>
    <a href="#e-bancos-de-dados" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O mesmo vale pra bancos de dados. Cada projeto deve estar travado numa versão específica idêntica à que está rodando no servidor de produção e nunca deve depender dos pacotes do sistema operacional. Dá pra usar mise pra isso mas o mais recomendado é usar Docker. Cada projeto <strong>DEVE</strong> ter um <code>docker-compose.yml</code> pra subir somente os bancos de dados. Não precisa subir containers pra linguagens, pra isso é melhor usar Mise.</p>
<p>Se não entende Docker, eu fiz videos ensinando:</p>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/85k8se4Zo70"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

</br>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/-yGHG3pnHLg"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>Somando Mise + Docker Compose + LazyVim, é tudo que se precisa pra ser um desenvolvedor web produtivo, além de usar os recursos da sua máquina de maneira eficiente. Todo desenvolvedor PRECISA aprender este combo de opções. Omarchy já trás tudo pré-instalado, por isso tem sido minha recomendação pra todo iniciante.</p>
<p>Não precisa se preocupar: Arch Linux (com archinstall), é tão fácil de instalar quanto um Ubuntu ou Linux Mint e o Hyprland do Omarchy é muito mais bonito e fluido que um MacOS. O melhor dos mundos. Aprenda hoje!</p>
]]></content:encoded><category>omarchy</category><category>ferramentas-de-desenvolvimento</category><category>containers</category></item><item><title>Omarchy 2.0 - LazyVim - LazyExtras</title><link>https://akitaonrails.github.io/2025/09/07/omarchy-2-0-lazyvim-lazyextras/</link><guid isPermaLink="true">https://akitaonrails.github.io/2025/09/07/omarchy-2-0-lazyvim-lazyextras/</guid><pubDate>Sun, 07 Sep 2025 16:00:00 -0300</pubDate><description>&lt;p&gt;Continuando meus posts de dicas sobre &lt;a href="https://akitaonrails.com/tags/omarchy/"target="_blank" rel="noopener"&gt;Omarchy&lt;/a&gt; resolvi postar sobre &lt;a href="https://www.lazyvim.org/"target="_blank" rel="noopener"&gt;LazyVim&lt;/a&gt; que já vem pré-instalado.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://user-images.githubusercontent.com/292349/213447056-92290767-ea16-430c-8727-ce994c93e9cc.png" alt="LazyVim" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;Mesmo se não usa Omarchy, recomendo &lt;a href="https://www.lazyvim.org/installation"target="_blank" rel="noopener"&gt;instalar&lt;/a&gt; LazyVim, só fazer isso:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;# required
mv ~/.config/nvim{,.bak}
# optional but recommended
mv ~/.local/share/nvim{,.bak}
mv ~/.local/state/nvim{,.bak}
mv ~/.cache/nvim{,.bak}
git clone https://github.com/LazyVim/starter ~/.config/nvim
rm -rf ~/.config/nvim/.git
nvim&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copy code"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Pronto, é só isso. NeoVim, pra quem não sabe, é um fork mais moderno do antigo Vim (por isso o comando é &lt;code&gt;nvim&lt;/code&gt;, reservando &lt;code&gt;vim&lt;/code&gt; pro antigo). Ele troca o antigo VimScripts por scripts em Lua e tem várias otimizações e funcionalidades de qualidade de vida melhores. Hoje em dia, não tem porque usar o Vim antigo mais.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Continuando meus posts de dicas sobre <a href="https://akitaonrails.com/tags/omarchy/"target="_blank" rel="noopener">Omarchy</a> resolvi postar sobre <a href="https://www.lazyvim.org/"target="_blank" rel="noopener">LazyVim</a> que já vem pré-instalado.</p>
<p><img src="https://user-images.githubusercontent.com/292349/213447056-92290767-ea16-430c-8727-ce994c93e9cc.png" alt="LazyVim"  loading="lazy" /></p>
<p>Mesmo se não usa Omarchy, recomendo <a href="https://www.lazyvim.org/installation"target="_blank" rel="noopener">instalar</a> LazyVim, só fazer isso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code># required
mv ~/.config/nvim{,.bak}

# optional but recommended
mv ~/.local/share/nvim{,.bak}
mv ~/.local/state/nvim{,.bak}
mv ~/.cache/nvim{,.bak}

git clone https://github.com/LazyVim/starter ~/.config/nvim

rm -rf ~/.config/nvim/.git

nvim</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pronto, é só isso. NeoVim, pra quem não sabe, é um fork mais moderno do antigo Vim (por isso o comando é <code>nvim</code>, reservando <code>vim</code> pro antigo). Ele troca o antigo VimScripts por scripts em Lua e tem várias otimizações e funcionalidades de qualidade de vida melhores. Hoje em dia, não tem porque usar o Vim antigo mais.</p>
<p>Usando Lua dá pra configurar o Nvim como quiser. Mas dá muito trabalho configurar tudo do zero. É um bom exercício, mas sendo prático, não compensa pro dia a dia. É melhor instalar um setup pré-configurado como os antigos <a href="https://www.lunarvim.org/"target="_blank" rel="noopener">LunarVim</a> que eu usava antes e até recomendei em alguns videos de Linux do meu canal, ou o <a href="https://astronvim.com/"target="_blank" rel="noopener">AstroNvim</a> ou o <strong>LazyVim</strong> que atualmente é meu favorito. Qualquer um deles é um bom começo e vai ser preferência pessoal qual vai escolher.</p>
<p>Cada plugin que eles instalam tem diversas funcionalidades e combinações de teclas (hotkeys) próprias que precisa ler na documentação pra saber o que faz o que. Recomendo ir na seção <a href="https://www.lazyvim.org/plugins"target="_blank" rel="noopener">plugins</a> do site oficial e ler um por um. Tem muita coisa que você nem espera e todos são muito úteis.</p>
<p>LazyVim sozinho já ajuda bastante porque ele abre pop-ups documentando algumas das hotkeys. Por exemplo, o que se chama de comando <strong>Leader</strong> em LazyVim é a &ldquo;barra de espaço&rdquo;. Quando apertar, vai aparecer esse menu de contexto:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-44-17.png" alt="Leader context menu"  loading="lazy" /></p>
<p>A partir daqui, se digitar, digamos &ldquo;b&rdquo;, vai aparece outro menu de contexto:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-46-48.png" alt="Buffer context menu"  loading="lazy" /></p>
<p>E se digitar &ldquo;b&rdquo; de novo, ele vai trocar pro próximo arquivo já aberto no Buffer. <strong>Buffer</strong> é o nome em Vim onde ficam os arquivos já abertos. Deletar do Buffer é o equivalente a &ldquo;fechar o arquivo&rdquo;.</p>
<p>Da próxima vez, não precisa olhar os menus, só digitar rápido de uma só vez: &ldquo;Espaço+b+b&rdquo;. E é assim que você vai decorando os comandos que mais usa.</p>
<p>Alguns comandos que vale a pena já saber são: <strong>Espaço+Espaço&quot;</strong> (duas vezes), e vai abrir o menu que abre arquivos. digite algumas letras do nome do arquivo e vai filtrando dinamicamente:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-49-35.png" alt="find files"  loading="lazy" /></p>
<p>Ou então &ldquo;Espaço+e&rdquo; pra abrir o Explorer NeoTree. Digite &ldquo;?&rdquo; pra abrir um popup com os comandos que pode usar pra criar novos sub-diretórios ou arquivos no subdiretório:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-51-08.png" alt="NeoTree"  loading="lazy" /></p>
<p>Quando aprender os demais comandos e plugins, vai notar que nem precisa abrir NeoTree, ele é mais pra quando quiser explorar visualmente mesmo. Mas pro dia a dia comando como &ldquo;:e&rdquo; devem ser suficiente. Aliás, &ldquo;:&rdquo; (dois pontos) é o comando pra executar funções do NeoVim. Por exemplo &ldquo;:q&rdquo; é quit, ou &ldquo;:w&rdquo; é write e &ldquo;:wq&rdquo; é write e quit ao mesmo tempo.</p>
<p>Se quiser aprender mais a fundo sobre NeoVim, recomendo o canal do YouTube do camarada <a href="https://www.youtube.com/@EustaquioRangel"target="_blank" rel="noopener">Eustáquio Rangel</a> que é veterano de Linux, Rails e Vim e ele ensina NeoVim do zero (sem LazyVim).</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_16-09-53.png" alt="TaQ"  loading="lazy" /></p>
<p>Agora, digamos que já aprendeu o básico de NeoVim e LazyVim, e agora quer começar a mexer nos seus projetos de PHP, Java, C#, Ruby, Python ou o que for. Vai notar que o LazyVim não tem nenhuma funcionalidade pra nenhuma delas.</p>
<p>O que fazer agora? Instalar VS Code?? <strong>NÃO!!</strong></p>
<p>Isso porque você não executou <a href="https://www.lazyvim.org/extras"target="_blank" rel="noopener">:LazyExtras</a>.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-35-36.png" alt="LazyExtras command"  loading="lazy" /></p>
<p>Digite exatamente assim e veja isto:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-36-01.png" alt="Enabled Plugins"  loading="lazy" /></p>
<p>Essa janela parece complicada mas é só uma lista de plugins dividida em seções. No começo aparecem os plugins já instalados e habilitados. Caso não queira algum deles, basta usar as setas pra descer o cursor até uma delas e apertar &ldquo;x&rdquo; pra desmarcar. Mas deixe essa seção como está. Vamos descer até a seção de &ldquo;Languages&rdquo;:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-36-43.png" alt="Languages section"  loading="lazy" /></p>
<p>É nesta seção que estão todas as linguagens que você pode habilitar o suporte. Basta descer com as setas e ir marcando com &ldquo;x&rdquo; quais quer instalar. E tem de tudo, desde Angular, Vue, Erlang, Elixir, Rust, Zig, Haskell e muito mais.</p>
<p>Ao lado de cada linguagem tem o grupo de plugins individuais que ele vai instalar. Pra saber o que cada uma faz, digite o nome delas no Google e ache a página com a documentação, onde vai ter hotkeys e configurações extras que pode fazer.</p>
<p>Com isso vai ganhar coisas como Linters, syntax highlighting, LSP, snippets e muito mais.</p>
<p>E se quiser instalar plugins a mais que não tem listado, dá pra adicionar manualmente. Leia a seção de <a href="https://www.lazyvim.org/configuration/plugins#-adding-plugins"target="_blank" rel="noopener">Adding Plugins</a> na documentação.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_16-05-15.png" alt="Linter"  loading="lazy" /></p>
<p>LazyVim + LazyExtras é 90% de tudo que precisa pro seu dia a dia de desenvolvimento de software. É mais leve e mais rápido que um VS Code, usando muito menos memória e vai ser muito melhor especialmente em máquinas mais antigas. Não tenha preguiça de aprender Vim, um programador de verdade não deveria ficar num VS Code só porque tem preguiça de aprender hotkeys extras.</p>
]]></content:encoded><category>omarchy</category><category>ferramentas-de-desenvolvimento</category><category>tutoriais</category></item><item><title>Omarchy 2.0 - ZSH Configs</title><link>https://akitaonrails.github.io/2025/09/07/omarchy-2-0-zsh-configs/</link><guid isPermaLink="true">https://akitaonrails.github.io/2025/09/07/omarchy-2-0-zsh-configs/</guid><pubDate>Sun, 07 Sep 2025 15:00:00 -0300</pubDate><description>&lt;p&gt;Estou gostando bastante de usar &lt;a href="https://omarchy.org/"target="_blank" rel="noopener"&gt;Omarchy&lt;/a&gt; como meu desktop manager. Leia &lt;a href="https://akitaonrails.com/2025/08/29/new-omarchy-2-0-install/"target="_blank" rel="noopener"&gt;meu post anterior&lt;/a&gt; pra ver como eu instalei e fiz modificações pra servir o meu setup. Seguindo nessa linha, o Omarchy vem por padrão com shell Bash. Mas eu prefiro ZSH. Bash é perfeitamente usável, é só preferência pessoal mesmo. Tem gente que prefere Fish ou outros. Mas o Omarchy vem só com Bash por enquanto, então resolvi modificar o setup pra suportar meu ZSH.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Estou gostando bastante de usar <a href="https://omarchy.org/"target="_blank" rel="noopener">Omarchy</a> como meu desktop manager. Leia <a href="https://akitaonrails.com/2025/08/29/new-omarchy-2-0-install/"target="_blank" rel="noopener">meu post anterior</a> pra ver como eu instalei e fiz modificações pra servir o meu setup. Seguindo nessa linha, o Omarchy vem por padrão com shell Bash. Mas eu prefiro ZSH. Bash é perfeitamente usável, é só preferência pessoal mesmo. Tem gente que prefere Fish ou outros. Mas o Omarchy vem só com Bash por enquanto, então resolvi modificar o setup pra suportar meu ZSH.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-16-57.png" alt="Meu ZSH"  loading="lazy" /></p>
<p>Se quiser mudar pra ZSH, é fácil, só fazer isso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">yay -S zsh zoxide
</span></span><span class="line"><span class="cl">chsh -s <span class="k">$(</span>which zsh<span class="k">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Logout, login e pronto. Mas agora seu shell vai estar vazio. Pra baixar minha config faça isso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/akitaonrails/omarchy-zsh.git ~/.config/zsh
</span></span><span class="line"><span class="cl">ln -s ~/.config/zsh/.zshrc ~/.zshrc </span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Tem duas coisas que precisa modificar. Em <code>.zshrc</code> remova esta linha:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>source ~/.config/zsh/mounts</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Isso é só pra eu checar meus mounts de NFS pro meu NAS. Pra você não serve pra nada então pode tirar.</p>
<p>A segunda coisa é criar um novo arquivo para segredos:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>touch ~/.config/zsh/secrets
chmod 600 ~/.config/zsh/secrets</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>É nele que vai colocar coisas como suas chaves de OpenAI ou Google Cloud ou qualquer coisa assim. Por exemplo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code># ~/.config/zsh/secrets
export OPENAI_API_KEY=&#34;sk-xx-v1-xxx...xxxxx&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Assim seus segredos ficam separados das suas configurações e podemos dar <code>git push</code> pra um repositório sem se preocupar que algo possa vazar no futuro. Sempre mantenha segredos, senhas, chaves, separados localmente. Isso já está no <code>.gitignore</code> então está seguro.</p>
<p>De bônus, no <code>~/.config/init</code> adicionei suporte ao <a href="https://atuin.sh/"target="_blank" rel="noopener">Atuin</a> que é uma ferramenta que serve pra sincronizar todo histórico de comandos que fez no seu shell pra um repositório no &ldquo;cloud&rdquo; (leia a documentação, você pode criar seu próprio server local também). O repositório é encriptado, então não é inseguro, mesmo se seu histórico contenha chaves secretas nos comandos.</p>
<p>Instale assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>yay -S atuin
atuin register -u &lt;seu username&gt; -e &lt;seu email&gt;
atuin import auto
atuin sync</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Logo que registrar o Atuin vai gerar uma chave de encriptação aleatório. Garanta que guardou essa chave num lugar seguro como 1password, Bitwarden ou outro cofre seguro!! Sem ela não vai conseguir decriptar numa nova instalação. Se esquecer, ainda dá pra ver antes de reinstalar, por exemplo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>atuin key</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Se reinstalar sua máquina ou instalar uma nova máquina e quiser seus históricos de volta, basta instalar o Atuin e fazer:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>atuin login -u &lt;seu username&gt;
atuin sync</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Ele vai pedir sua senha e chave de encriptação e trazer todo seu histórico de volta.</p>
<p>Segundo minha config, basta digitar <code>Ctrl+R</code> pra chamar a procura do histórico (que a partir de agora vai estar num sqlite na sua máquina). Leia a <a href="https://docs.atuin.sh/"target="_blank" rel="noopener">documentação</a> pra mais funcionalidades.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/screenshot-2025-09-07_15-17-20.png" alt="Ctrl&#43;R"  loading="lazy" /></p>
<p>O DHH configurou o prompt do <strong>Starship</strong> usando o jeito antigo de variável <code>PS1</code>. Mas o Starship já tem vários prompt bem bonitos fáceis de usar como &ldquo;presets&rdquo;. Eu escolhi o Pure Prompt, que eu gosto, mas tem vários outros. Se gostar de algo mais chamativo e colorido, tem este <a href="https://starship.rs/presets/pastel-powerline"target="_blank" rel="noopener">Pastel Powerline</a>:</p>
<p><img src="https://starship.rs/presets/img/pastel-powerline.png" alt="Pastel Powerline"  loading="lazy" />
Escolha o de sua preferência na <a href="https://starship.rs/presets/"target="_blank" rel="noopener">página de Presets</a> e mude em <code>~/.config/zsh/prompt</code> no lugar desta linha:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>starship preset bracketed-segments -o ~/.config/starship.toml</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Por fim, eu deixei alguns ENVs em <code>~/.config/zsh/envs</code> que funcionam pros meus testes de Ollama e coisas assim, mas é bom você saber que estão lá pra não achar estranho se seu Ollama estiver se comportando estranho, edite o arquivo <code>~/.config/zsh/envs</code> pra ter os envs de sua preferência:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code># envs
export OPENAI_API_BASE=&#34;https://openrouter.ai/api/v1&#34;
export DEFAULT_MODEL=&#34;o1-mini&#34;;
export OLLAMA_API_BASE=http://127.0.0.1:11434
export OLLAMA_HOME=http://127.0.0.1:11434
export OLLAMA_MODELS=/mnt/gigachad/ollama/models</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Também modifique o arquivo <code>~/.config/zsh/aliases</code> pra ter alias que você prefira:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code># aliases
alias monhd=&#34;sudo ddcutil -d 1 setvcp 60 0x12&#34;
alias mondp=&#34;sudo ddcutil -d 1 setvcp 60 0x0F&#34;

alias sgpt=&#39;docker run --rm -e OPENAI_API_BASE=${OPENAI_API_BASE} -e OPENAI_API_KEY=${OPENROUTER_API_KEY} ghcr.io/tbckr/sgpt:latest txt &#39;

alias git=&#39;nocorrect git&#39;
git config --global alias.a &#39;add&#39;
git config --global alias.ps &#39;push&#39;
git config --global alias.pl &#39;pull&#39;
git config --global alias.l &#39;log&#39;
git config --global alias.c &#39;commit -m&#39;
git config --global alias.s &#39;status&#39;
git config --global alias.co &#39;checkout&#39;
git config --global alias.b &#39;branch&#39;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Os primeiros dois aliases são pro meu setup de 2 monitores onde um dos monitores recebe sinal tanto da entrada HDMI quanto da entrada DisplayPort (tenho 2 GPUs). Se não sabia, dá pra controlar isso usando o shell. Leia <a href="https://jeancharles.quillet.org/posts/2021-08-20-How-to-use-ddcutil-to-switch-input-of-a-Dell-screen.html"target="_blank" rel="noopener">este post sobre ddcutil</a></p>
<p>Em seguida você ganha o comando <code>sgpt</code>. Omarchy já trás Docker instalado. Agora no shell você pode perguntar ao ChatGPT sem precisar ficar abrindo um navegador web pra isso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sgpt &#34;qual é a sintaxe de rsync pra sincronizar dois diretórios?&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Leia <a href="https://github.com/tbckr/sgpt"target="_blank" rel="noopener">documentação do SGPT</a> pra saber outras funcionalidades ou quais LLMs você pode escolher.</p>
<p>No final temos aliases pra Git. O Omarchy já tem alias pra fazer &ldquo;g&rdquo; ser &ldquo;git&rdquo; e com este que eu adicionei você pode fazer:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>git add . # antigo
g a . # novo

git commit -m &#34;initial commit&#34; # antigo
g c &#34;initial commit&#34; # novo

git commit --amend -m &#34;initial commit&#34;
g ca &#34;initial commit&#34;

git push origin master
g ps origin master

git pull origin master
g pl origin master

git log
g l

# e assim por diante</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Mais prático e menos verbose. Adicione mais aliases conforme seu workflow em <code>~/.config/aliases</code>.</p>
<p>E acho que é isso, agora sim, meu Omarchy está organizado do jeito que eu gosto. Faça suas próprias configurações pra tudo ficar do seu jeito também!</p>
]]></content:encoded><category>omarchy</category><category>ferramentas-de-desenvolvimento</category><category>automacao</category></item><item><title>Omakub pra Manjaro e ArchWSL</title><link>https://akitaonrails.github.io/2024/10/30/omakub-pra-manjaro-e-archwsl/</link><guid isPermaLink="true">https://akitaonrails.github.io/2024/10/30/omakub-pra-manjaro-e-archwsl/</guid><pubDate>Wed, 30 Oct 2024 12:41:00 -0300</pubDate><description>&lt;p&gt;Algum tempo atrás o DHH lançou uma ferramenta open source chamada &lt;a href="https://omakub.org"target="_blank" rel="noopener"&gt;Omakub&lt;/a&gt; que instala diversas ferramentas e configura um ambiente de desenvolvimento moderno em Ubuntu. Ele vai além de coisas só de terminal e também configura vários aspectos do ambiente GNOME. Vale a pena experimentar, nem que seja numa Virtual Machine, pra ver como fica.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/1ddbjucxzkah963tou557907bkmr" alt="Omakub - demo" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;Eu gostei bastante das escolhas do DHH, ele sempre foi um cara de Mac, eu também. Mas eu migrei de volta pra Linux quase 10 anos atrás. O motivo foi porque eu evangelizava tech pra desenvolvedores júniors e no Brasil ficou inviável incentivar Macs. E não queria que parecesse que sem usar Macs você estaria automaticamente em grande desvantagem. Então passei a usar exclusivamente Linux e no blog fiz vários posts explicando sobre isso, como estes:&lt;/p&gt;</description><content:encoded><![CDATA[<p>Algum tempo atrás o DHH lançou uma ferramenta open source chamada <a href="https://omakub.org"target="_blank" rel="noopener">Omakub</a> que instala diversas ferramentas e configura um ambiente de desenvolvimento moderno em Ubuntu. Ele vai além de coisas só de terminal e também configura vários aspectos do ambiente GNOME. Vale a pena experimentar, nem que seja numa Virtual Machine, pra ver como fica.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/1ddbjucxzkah963tou557907bkmr" alt="Omakub - demo"  loading="lazy" /></p>
<p>Eu gostei bastante das escolhas do DHH, ele sempre foi um cara de Mac, eu também. Mas eu migrei de volta pra Linux quase 10 anos atrás. O motivo foi porque eu evangelizava tech pra desenvolvedores júniors e no Brasil ficou inviável incentivar Macs. E não queria que parecesse que sem usar Macs você estaria automaticamente em grande desvantagem. Então passei a usar exclusivamente Linux e no blog fiz vários posts explicando sobre isso, como estes:</p>
<ul>
<li><a href="https://www.akitaonrails.com/2015/11/10/situacao-brasil-no-macs-for-the-rest-of-us"target="_blank" rel="noopener">2015 - Situação Brasil: No Macs for the Rest of Us</a></li>
<li><a href="https://www.akitaonrails.com/2016/04/12/o-ano-do-linux-no-desktop-pela-microsoft"target="_blank" rel="noopener">2016 - The Year of Linux on the Desktop, by Microsoft ??</a></li>
<li><a href="https://www.akitaonrails.com/2017/01/12/off-topic-por-que-estamos-todos-migrando-para-longe-da-apple"target="_blank" rel="noopener">2017 - Off-Topic - Why are we all moving away from Apple?</a></li>
</ul>
<p>Sem contar os diversos videos com setups que fiz no meu canal, como estes:</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=epiyExCyb2s"target="_blank" rel="noopener">O Guia Definitivo de Ubuntu pra Devs Iniciantes</a></li>
<li><a href="https://www.youtube.com/watch?v=sjrW74Hx5Po"target="_blank" rel="noopener">O Melhor Setup Dev com Arch e WSL2</a></li>
</ul>
<p>Em 2024, com exceção se precisa desenvolver apps pra iOS ou coisas específicas de .NET, usar distros Linux é superior a usar Windows ou MacOS. Antigamente eu diria um &ldquo;mas&rdquo; se quiser jogar, aí seria obrigado a fazer dual-boot com Windows. Mas até isso Linux já superou Macs graças aos esforços da Valve e as comunidades open source em torno de projetos como Proton. Hoje, uma quantidade absurda de jogos novos de PC rodam liso em Linux, basta instalar Steam e já era.</p>
<p>Não é o tema do artigo, mas já que toquei no assunto, estava justamente  assistindo um review do <a href="https://bazzite.gg/"target="_blank" rel="noopener">BazziteOS</a> rodando no <strong>Asus ROG Ally</strong> (meu favorito), criando um Steam Deck ainda mais potente. É Fedora rodando num handheld, com uma interface tão boa que ninguém sabe que é Linux por baixo, rodando jogos com mesma performance que em Windows. É impressionante mesmo. Quem ficou totalmente pra trás em games foi a Apple.</p>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/OwWRCrGoXV0"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>Isso tudo dito, o DHH mudou pra um hardware muito bacana de uma empresa pequena e nova chamada <a href="https://frame.work/"target="_blank" rel="noopener">Framework</a>, que faz notebooks modulares. A idéia é não precisar jogar tudo fora quando quiser fazer upgrades de hardware. Só trocar o módulo pra um mais novo. E não só coisas simples como trocar uma porta USB-A por uma USB-C, mas até trocar GPU, trocar placa-mãe, monitor.</p>
<p>É um conceito muito bacana que eu gostaria que mais fabricantes se comprometessem a fazer. Evita lixo eletrônico desnecessário, pra começar, muito mais fácil de reparar partes, sem ter que jogar tudo fora, como acontece com um Macbook. Vi isso pela primeira vez no canal do Linus Tech Tips porque o Linus Sebastian se tornou um dos primeiros investidores anjo deles.</p>
<p><img src="https://images.prismic.io/frameworkmarketplace/Zv77LrVsGrYSwWcu_3A-marketplace-parts-2x.png?auto=format,compress" alt="Framework"  loading="lazy" /></p>
<p>A maioria dos fabricantes que suportam Linux, costumam oferecer algum tipo de suporte a Ubuntu. Ele acabou meio que se tornando o &ldquo;padrão&rdquo; de Linux pra usuários comuns. Na dúvida, instale Ubuntu. E não é uma má escolha. Se escolher Ubuntu, use o projeto <a href="https://github.com/basecamp/omakub"target="_blank" rel="noopener">Omakub</a> oficial do DHH, que vai configurar tudo bonitinho pra você.</p>
<p>Eu não gosto de Ubuntu, é uma escolha pessoal (e cada um de Linux vai ter sua própria opção. Já sei que o primeiro comentário vai ser alguém falando de porque todo mundo não usa NixOS de uma vez &hellip;). Não precisa ficar preocupado nem se sentir mal por usar Ubuntu, não tem absolutamente nada de errado com ele. Escolher distros é que nem escolher marca de carro.  Qual a diferença de Ferrari, Lambo, Porsche, McLaren? Você vai achar ruim se prefere Lambo e eu prefiro McLaren?</p>
<p>Além disso, puristas vão dizer que é pra ficar no Arch Linux puro, mas faz anos que prefiro <a href="https://manjaro.org/products/download/x86"target="_blank" rel="noopener"><strong>Manjaro GNOME</strong></a> no meu PC desktop e em notebook prefiro ficar com Windows 11 mesmo e WSL2 rodando <a href="https://github.com/yuk7/ArchWSL"target="_blank" rel="noopener"><strong>ArchWSL</strong></a>. Ainda recomendo brincar com Arch puro pra aprender. Mas depois de tantos anos, como é meu caso, prefiro um instalador que faz igual Ubuntu: vai do zero ao desktop em poucos cliques.</p>
<p>Então não teve jeito, fui obrigado a fazer um fork e ajustar o Omakub num novo projeto, o <a href="https://github.com/akitaonrails/omakub-mj"target="_blank" rel="noopener"><strong>OMAKUB-MJ</strong></a> (o nome não tá muito correto, deveria ser algo como OMAKAMJ ou algo assim que seria Omakase com Manjaro, mas fica feio, mandem sugestões nos comentários). Migrei todos os comandos de Apt pra Yay, além de diversos outros ajustes. Rodei no meu PC principal (depois de ter testado bastante numa VM, claro) e agora ficou bonitão assim:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/8sq62mkbc4kxuzqk5opej275xpuc" alt="Omakub-MJ"  loading="lazy" /></p>
<p>Igual à versão de Ubuntu, ele ativa o tema Tokyo Night, mas dá pra mudar pra vários outros temas. Depois de instalado, vai ter um comando <code>omakub</code> no terminal que abre um menu com várias opções, incluindo mudar tamanho das fontes ou trocar temas:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/7qvbv50ipzifo3cv5bhe3lb64kq8" alt="Omakub trocar tema"  loading="lazy" />
Tem <strong>MUITAS</strong> coisas legais pré-instaladas, por isso repito pra ler <a href="https://manual.omakub.org/"target="_blank" rel="noopener">o manual</a> que é muito bonito, bem escrito, e eu não mudei nenhuma das configurações principais (só o zellij, já explico), então tudo que vale pra versão Ubuntu também vale pra Manjaro. E eu sei que a maioria de vocês tem preguiça de abrir o manual, mas uma coisa que o DHH sabe fazer é uma documentação atraente:</p>
<p><a href="https://manual.omakub.org/1/read#leaf_29"target="_blank" rel="noopener"><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/xdsu6gghf5ncic9rh852hv1c7bcz" alt="Manual Omakub"  loading="lazy" /></a></p>
<h3>Migrando pra Manjaro<span class="hx:absolute hx:-mt-20" id="migrando-pra-manjaro"></span>
    <a href="#migrando-pra-manjaro" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Enfim, pra migrar de Ubuntu pra Manjaro, a primeira coisa que fiz foi trocar comandos apt por yay, coisa simples assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl"><span class="gd">- sudo apt install -y alacritty
</span></span></span><span class="line"><span class="cl"><span class="gi">+ yay -S alacritty --noconfirm
</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Mas rapidamente encontramos as partes de porque eu prefiro o <strong>YAY</strong> do que <strong>APT</strong> como gerenciador de pacotes:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl"><span class="gd">-  sudo curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg
</span></span></span><span class="line"><span class="cl"><span class="gd">-  echo &#34;deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main&#34; \| sudo tee /etc/apt/sources.list.d/brave-browser-release.list
</span></span></span><span class="line"><span class="cl"><span class="gd">-  sudo apt update -y
</span></span></span><span class="line"><span class="cl"><span class="gd">-  sudo apt install -y brave-browser
</span></span></span><span class="line"><span class="cl"><span class="gi">+  yay -S brave-browser --noconfirm
</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Em Ubuntu, tudo que a própria Canonical não controla, fica em repositórios de terceiros, então precisamos explicitamente adicionar esses repositórios antes de conseguir instalar seus pacotes.</p>
<p>Em Arch é a mesma coisa, com o Pacman só conseguimos instalar os pacotes oficiais que o grupo do Arch controla e testa. Mas existe um repositório de terceiros chamado AUR, o Arch User Repository. Daí instalamos ferramentas como Pamac (que vem instalado em muitas distros) ou o Yay (que eu gosto mais). Por baixo eles rodam Pacman, mas oferecem um único comando que serve pros dois: instalar pacotes oficiais e instalar pacotes do AUR, com os mesmos comandos. Então não tem que ficar manualmente gerenciando trocentos repositórios externos.</p>
<p>Foi bem fácil converter porque no AUR tem tudo que precisamos. É muito raro precisar de um software e não achar no AUR. Além disso fiz outra modificação: eu prefiro manter aplicativos gráficos como Spotify ou Discord instalados via <strong>Flatpak</strong>.</p>
<p>Não é nem por razões de segurança. Prefiro que aplicativos de terceiros mexam no sistema operacional abaixo o menos possível. E muitos deles precisam de várias dependências. Quando preciso fazer um upgrade geral, demora mais porque vem um monte de pacotes de dependência junto que eu nem precisava. Pelo menos com Flatpak, as dependências ficam isoladas em imagens de containers.</p>
<p>Enfim, quando preciso atualizar o sistema só faço <code>yay -Syyuu</code> e quando quero atualizar aplicativos, basta fazer <code>flatpak update -y</code>, assim posso rodar separadamente. As únicas exceções são editores de texto como Visual Studio Code, nesse caso prefiro que ele tenha acesso ao sistema de arquivos todo mesmo, e não ter que lidar com permissões de acesso em containers de Flatpak, por isso instalo via Yay.</p>
<h3>GNOME<span class="hx:absolute hx:-mt-20" id="gnome"></span>
    <a href="#gnome" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Adicionei dois aplicativos opcionais, o Bitwarden (o DHH prefere o 1password, ambos são bons) e o Discord. Aplicativos de Flatpak são fáceis de instalar, nem precisa estar num instalador como esse, mas coloquei só mais esses por conveniência pra mim mesmo. Obviamente você pode instalar depois o que quiser. Basta procurar com <code>flatpak search</code> e instalar com <code>flatpak install</code>.</p>
<p>No lado Gnome, o DHH escolheu apps como <a href="https://flameshot.org/"target="_blank" rel="noopener">Flameshot</a> pra substituir o app de screenshot do Gnome. Uma das vantagens é que depois de tirar a foto de tela, dá pra imediatamente editar a imagem antes de salvar. Pra ter preview rápido de imagens no gerenciador de arquivos Nautilus, ele escolheu o <a href="https://gitlab.gnome.org/GNOME/sushi"target="_blank" rel="noopener">Gnome Sushi</a>. Todas essas opções são muito boas e você pode ver tudo que é instalado no desktop no diretório <a href="https://github.com/akitaonrails/omakub-mj/tree/master/install/desktop"target="_blank" rel="noopener">install/desktop</a>. Cada app é um script separado.</p>
<p>De todos, o único que realmente não conhecia é o <a href="https://play.google.com/store/apps/details?id=org.localsend.localsend_app&amp;hl=en"target="_blank" rel="noopener"><strong>Localsend</strong></a>. Mas agora já instalei no meu Linux, Windows, smartphone e tudo mais. É o jeito mais fácil de transferir arquivos entre máquinas na mesma rede. Igual o Airdrop de iPhone. Vale a pena ter instalado em tudo.</p>
<p><a href="https://localsend.org/pt-BR"target="_blank" rel="noopener"><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/fnpyyqis498wth9do5qodt7xli0x" alt="Localsend"  loading="lazy" /></a></p>
<p>Outro app que eu não conhecia é o <a href="https://ulauncher.io/"target="_blank" rel="noopener">Ulauncher</a> que é um executador de aplicações, igual a barra de Spotlight de Mac. Basta apertar <code>Super/Tecla de Windows + Espaço</code> e ele abre uma barra onde podemos digitar o nome do app que queremos abrir:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/ttbw39v9y0r17rw16x4s99p45epe" alt="Ulauncher"  loading="lazy" /></p>
<p>Se fosse só isso, não é muito útil porque em Gnome, só de apertar <code>Super</code> já dá pra digitar o nome de apps. Mas o interessante é que ele faz mais que executar apps. Depois fuce a <a href="https://ext.ulauncher.io/"target="_blank" rel="noopener">Página de Extensions</a> pro Ulauncher. Tem coisas como calculadoras, controlador de Spotify, pesquisador de arquivos, facilitador pra editores com Obsidian ou Notion, pesquisador de snippets de código pra VS Code, tradutores, integradores pra serviços de GPT e um dos meus favoritos, facilitador de Emojis:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/dsjsfzdr6rddfrqqtlcmj3uu9891" alt="Ulauncher Emojis"  loading="lazy" /></p>
<p>O Omakub ajusta bastante coisa do Gnome. Em particular adiciona várias extensions que mudam o comportamento do ambiente gráfico:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/ocm6xifnbygf4cagdb5icjusz1t6" alt="Gnome Extensions"  loading="lazy" /></p>
<p>Depois vale fuçar as configurações de um por um. Por exemplo, ele instala e já configura a extension <a href="https://extensions.gnome.org/extension/4548/tactile/"target="_blank" rel="noopener"><strong>Tactile</strong></a> que é provavelmente a melhor pra organizar as janelas em &ldquo;tiles&rdquo; ou &ldquo;azulejos&rdquo;, ou seja, pra facilitar alinhar uma janela em cima ou do lado da outra de forma proporcional. Ele faz isso pré-dividindo a tela em áreas e atribuindo letras a cada área, assim fica fácil de fazer uma janela se encaixar numa dessas áreas.</p>
<p>Por exemplo, com o comando <code>Super + T</code> aparece esse grid. Se digitar &ldquo;w&rdquo; duas vezes, minha janela de Alacritty se encaixa no topo, no meio, na área marcada com &ldquo;W&rdquo;:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/ofqh86tf3l3p6eviesq1dhosbio2" alt="Tactile W"  loading="lazy" /></p>
<p>Normalmente, eu gosto de ter a janela aberta no meio do monitor, maximizado na vertical, sem esticar pros lados, especialmente pra ler ou digitar textos. Então posso fazer <code>Super + T</code> e logo depois <code>W e S</code> pra marcar duas áreas:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/ijvlxzdvykxn12nbkvcwy73s5i6p" alt="Tactile W S"  loading="lazy" /></p>
<p>Mas também continuo podendo teclar <code>F11</code> ou <code>Super + seta pra cima</code> pra maximizar a janela na tela inteira. Ou usar as combinações clássicas de Windows como <code>Super + seta esquerda</code> ou <code>Super + seta direita</code> pra fazer a janela usar metade vertical da tela, desta forma:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/jjznbiwblc0zdlfydrmdqqxuxwkk" alt="Tactile lado a lado"  loading="lazy" /></p>
<p>Vale fuçar a documentação e as configurações da extension Tactile pra dividir as áreas do jeito que mais gosta. Isso vai variar bastante caso use monitor secundário na vertical, ou use monitor Ultra Wide. E nesse caso é onde esse tipo de extensão vai fazer mais diferença pra manter suas janelas organizadas.</p>
<h3>Neovim e LazyVim<span class="hx:absolute hx:-mt-20" id="neovim-e-lazyvim"></span>
    <a href="#neovim-e-lazyvim" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Eu mencionei Visual Studio Code, e ele está aqui pra quem gosta, mas quem acompanha meus videos e artigos, sabe que sou usuário de Vim de longa data. E a comunidade Vim não pára quieta. Hoje em dia tem um fork mais moderno, o <strong>NEOVIM</strong>, que se tornou o mais usado.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/k00pryy0c676m4ryssrt7d48aqqr" alt="LazyVim"  loading="lazy" /></p>
<p>Em cima do NeoVim podemos instalar plugins manualmente e ficar ajustando configuração pela eternidade, ou usar configs já prontas. Até poucos meses atrás eu usava o LunarVim, mas ele meio que caiu em desuso. Depois passei a usar o <a href="https://astronvim.com/"target="_blank" rel="noopener">AstroNVIM</a>, que resolve muito bem, mas parece que a maioria das pessoas passou a convergir pro <a href="https://www.lazyvim.org/"target="_blank" rel="noopener"><strong>LazyVim</strong></a>. Confesso que fico em dúvida entre qual é o melhor, AstroNvim ou LazyVim, mas vou ficar com o LazyVim por enquanto.</p>
<p>No fundo vão usar muitos dos mesmos plugins, análise de código vai ter plugins pra LSP, navegação vai ter o mesmo neo-tree, o mesmo telescope e assim por diante. Por isso vai ser muito subjetivo mesmo. Acho que nenhum dos dois tem como errar.</p>
<p>Muita gente acha que esses pacotes são contra a filosofia de &ldquo;aprenda a configurar você mesmo&rdquo;. E de fato, se puder, recomendo mesmo que monte sua configuração do zero. Mas faça isso só uma vez, desfaça e use um desses pacotes. Na realidade, essa noção começa a falhar porque esses plugins, sejam eles escritos no antigo VimScript ou na mais moderna linguagem Lua, são programas completos. Pegue plugins como Neo-Tree ou Telescope. Você não fez nem nunca vai fazer nenhum deles do zero, isso é pra poucos.</p>
<p>Na prática, o NeoVim já poderia vir pré-instalado com eles, pra você não faria diferença, porque são modernos, bem escritos, customizáveis, e não ficam no seu caminho. Não vem porque a idéia toda de um Vim é ser hiper-leve, pra podermos usar rapidamente dentro de um container, ou conectando num outro servidor via SSH, sem GUI, sem dependências, se bugs de interface nem nada disso. Só no nosso desktop, em ambiente controlado, gostaríamos dele tão pesado e funcional quanto um VS Code.</p>
<p>Depois tente dar uma olhada na configuração de um LazyVim, é muito mais coisa do que uma única pessoa deveria se preocupar. E saem plugins novos todos os dias, plugins antigos deixam de ser usados, não tem como você ficar de olho em tudo isso. Melhor ser um esforço dividido pela comunidade e a gente ter a oportunidade de usar o que tem de melhor só dando um update.</p>
<p>Sinceramente, seja Astronvim ou LazyVim, eu não tenho nem vontade e nem disposição de tentar montar do zero uma config como essa. E o que eles me oferecem &ldquo;out-of-the-box&rdquo; está perfeito já, eu não preciso ficar mudando. Basta usar. Você tem que ser muito chato pra achar que pode fazer melhor. Se achar isso, faça um pull request pra esses projetos então. Será tempo melhor gasto.</p>
<h3>ZelliJ<span class="hx:absolute hx:-mt-20" id="zellij"></span>
    <a href="#zellij" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Eu sou usuário de Tmux de longa data. E meus amigos usavam o antigo Screen, antes disso ainda. Eu lembro quando falávamos do Tmux como o software mais moderno. Agora ele é o legado e o mais moderno é o ZelliJ.</p>
<p>Todos eles são gerenciadores de sessão. Pense quando você se conecta num servidor remoto via SSH e fica trabalhando nele. Daí temos uma pane na internet ou cai a luz. O que acontece? Não só a conexão fecha, mas seja lá o que você estava rodando remotamente vai crashear porque o app está atrelado - é um filho - da sua shell (bash, zsh). E sua shell estava atrelada à sessão SSH. Quando a conexão cai, o SSH mata o shell que mata sua app. Você perde o que estava fazendo ou, pior, se o programa estava no meio, ele vai crashear no meio e pode corromper alguma coisa.</p>
<p>Em vez de correr esse risco, quando logar via SSH, imediatamente abra uma sessão de Screen, Tmux ou Zellij. Agora o shell vai abrir atrelado ao Zellij. Se a conexão cair e o SSH fechar, o ZelliJ vai continuar rodando, ele fica atrelado a um daemon na máquina remota. Seu shell e seu app ficam atrelados ao ZelliJ e não à sua sessão SSH.</p>
<p>Quando a luz voltar ou a internet voltar, basta conectar via SSH de novo e rodar o comando <code>zellij attach</code> ou <code>tmux attach</code>  e ele vai &ldquo;re-anexar&rdquo; à última sessão de apps, e você vai voltar ao seu shell, como se nunca tivesse saido de lá. Quaisquer apps que estivessem rodando e processando, ia continuar até acabar, normalmente, como qualquer app em background. Essa é a vantagem principal de um gerenciador como ZelliJ ou Tmux.</p>
<p>Mesmo se não estiver trabalhando numa máquina remota via SSH. Mesmo no seu desktop. Digamos que esteja brincando de editar configurações, instalar extensions e coisas assim. E do nada seu GNOME ou seu X resolvam dar pau, crashear e reiniciar. Todos os apps gráficos vão crashear junto, incluindo seu app de terminal, como Alacritty e junto com ele, qualquer shell e programa em linha de comando que estivesse rodando, como seu NeoVim, podendo perder código que estava editando e não salvou.</p>
<p>Não mais. Quando o X reiniciar, basta reabrir seu Alacritty e, mesma coisa, fazer um <code>zellij attach</code> pra voltar exatamente onde estava. Inclusive, se dentro do zellij você estava remotamente conectado a um servidor, monitorando com htop ou algo assim, nada vai fechar, vai continuar tudo conectado. Isso é mais uma camada de estabilidade pra você.</p>
<p>Veja este exemplo abaixo:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/wmxxa8a061mg6ius1chgukb4k86m" alt="ZelliJ"  loading="lazy" /></p>
<p>O Omakub já configura o ícone do Alacritty pra abrir uma janela de ZelliJ. Se seguir a configuração padrão, teclando <code>Ctrl P D</code>, sendo &ldquo;P&rdquo; pra Painel e &ldquo;D&rdquo; pra &ldquo;D&quot;ividir a janela horizontalmente, dá pra abrir dois programas um em cima do outro.</p>
<p><strong>ATENÇÃO:</strong> este é o único app do Omakub que fui obrigado a mudar os shortcuts, por isso o que tem na documentação oficial não vai bater.</p>
<p>O problema é o seguinte: vários apps de terminal, como NeoVim, tem vários shortcuts de navegação. Se digitar &ldquo;Espaço + E&rdquo; vai abrir o painel de exploração do Neo-Tree na esquerda. Dá pra navegar por diretórios usando &ldquo;J&rdquo; ou &ldquo;K&rdquo; pra ir pra cima ou pra baixo e &ldquo;Enter&rdquo; pra abrir os diretórios ou abrir arquivos.</p>
<p>Quando o arquivo abre, ele abre num painel na direita. Mas como você navega entre os painéis? Basta digitar <code>Ctrl + H</code> ou <code>Ctrl + L</code> (lembrando que em Vim as &ldquo;setas&rdquo; são as telas da home row da mão direita <code>H J K L</code>). Só que se você estiver dentro do ZelliJ, isso não vai funcionar. Isso porque o ZelliJ em si usa o modificador <code>Ctrl</code> pra ele. Então ele engole o comando e não passa pro NeoVim.</p>
<p>Uma das soluções é que o ZelliJ, assim como NeoVim, tem &ldquo;modes&rdquo;. Vim tem modo normal, modo de edição e modo visual. ZelliJ tem vários modos, como modo normal, modo de scroll, modo de painel e cada modo tem seu sub-conjunto de shortcuts/combinações de teclas. Um desses modos é &ldquo;Locked&rdquo;. Podemos travar o zellij, daí usar o programa dentro do painel isoladamente, e lembrar de ficar &ldquo;desbloqueando&rdquo; o zellij. É meio chatinho de ficar fazendo isso.</p>
<p>Outra solução é o que eu fiz no Omakub-MJ. Eu adicionei as configurações do usuários de GitHub &ldquo;shoukoo&rdquo; que fez um artigo um tempo atrás chamado <a href="https://shoukoo.github.io/blog/zellij-love-neovim/"target="_blank" rel="noopener">ZelliJ 💓 NeoVim</a>. A configuração completa dele está <a href="https://github.com/shoukoo/dotfiles/blob/master/zellij.kdl"target="_blank" rel="noopener">neste arquivo</a>. Mas em resumo, ele cria um modo especial que batizou de &ldquo;modo tmux&rdquo;.</p>
<p>Pra entrar nesse modo, precisa digitar primeiro <code>Ctrl f</code> e na barra inferior, dá pra ver mudando de modo Normal pra Tmux:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/ecr3jpesab4l2ilalp24vf7f9n4c" alt="zellij tmux"  loading="lazy" /></p>
<p>E agora sim, podemos digitar comandos como <code>P D</code> pra dividir painel. E fazendo isso, enquanto estiver no modo Normal mesmo, dentro do Neovim, combinações como <code>Ctrl H</code> ou <code>Ctrl L</code> vão funcionar normalmente. Win-win!</p>
<p>Só lembrar que, se na documentação oficial do zellij/omakub ele mandar digitar <code>Ctrl P W</code> pra abrir um painel flutuante, agora vai ser <code>Ctrl + F</code> e depois <code>P W</code>. E ele chama de &ldquo;modo tmux&rdquo; porque em Tmux, todo comando é depois de digitar <code>Ctrl + B</code> antes. No caso ele escolheu <code>Ctrl + F</code> pro ZelliJ, mas é arbitrário, poderia ser qualquer combinação inicial.</p>
<p>O resto continua funcionando igual. Pra navegar entre os painéis de ZelliJ, só digitar <code>Alt + H</code> ou <code>Alt + K</code> como no NeoVim, mas usando Alt em vez de Ctrl. Pra salvar a sessão atual e sair do ZelliJ, só fazer <code>Ctrl + F, O D</code> e quando voltar, só digitar <code>Ctrl + F, O W</code> pra listar as sessões salvas (sim, dá pra ter várias), e restaurar a que quiser com Enter.</p>
<p>Como o manual do Omakub recomenda, vale <a href="https://zellij.dev/documentation/"target="_blank" rel="noopener">estudar a documentação oficial do ZelliJ</a>.</p>
<h3>ASDF pra MISE<span class="hx:absolute hx:-mt-20" id="asdf-pra-mise"></span>
    <a href="#asdf-pra-mise" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Finalmente, uma das ferramentas que eu usei por mais anos foi o ASDF. Quem já programa em Node, Ruby, Python, etc já teve que usar algo como NVM, RVM ou RBenv, VENV ou Conda e assim por diante.</p>
<p>O mundo ideal é que todo mundo sempre usasse a versão mais nova de tudo, toda linguagem, toda biblioteca, tudo. Mas isso é inviável. Um bom programador vai acumular vários projetos na sua máquina, cada um vai estar numa versão diferente.</p>
<p>Ano retrasado ele trabalhou num projeto em Node na versão 16. Hoje está trabalhando num projeto novo na versão 22. Mas do nada, teve a necessidade de rodar esse projeto antigo. E agora? Ele atualizou tudo e só tem o node 22. Se desinstalar e instalar o 16 pra rodar o antigo, como fica o projeto novo? E as bibliotecas, como fica seu diretório de NPM? Uma zona completa.</p>
<p>Pra conseguir ter várias versões de node instaladas em paralelo na mesma máquina, recomenda-se usar NVM, que é o Node Version Manager.</p>
<p>Mas você é um programador poliglota. Trabalha em projetos em várias diferentes linguagens. Vai ter que aprender os comandos individuais de gerenciar versão pra cada linguagem? NVM pra Node. VENV pra Python. RVM pra Ruby, o que usa pra Java? Fodeu.</p>
<p>Pra isso criaram projetos como o antigo ASDF. Com ele era muito simples, bastava fazer <code>asdf install nodejs 14.21.3</code> pra instalar uma versão antiga de node e depois <code>asdf local nodejs 14.21.3</code> dentro do diretório do projeto antigo. Ele cria uma arquivo <code>.tool-versions</code> declarando a versão de nodejs pra esse diretório e quando entramos nele, o asdf detecta e já muda o que precisa pra poder usar a versão certa. Super conveniente.</p>
<p>Mais conveniente ainda porque podemos usar o mesmo conjunto de comandos pra qualquer linguagem. Basta instalar o plugin da linguagem com <code>asdf plugin add java</code> por exemplo. E ele suporta dezenas de linguagens, até as mais exóticas que você nunca ouviu falar. É o verdadeiro canivete suíço de gerenciamento de linguagens.</p>
<p>E esse seria o fim da história. Hoje mesmo, se você já usa ASDF, pode continuar usando, não tem nenhum problema com ele. Mas você conhece o povo de Rust: eles querem reescrever tudo em Rust. O Omakub mesmo instala vários substitutos como o &ldquo;exa&rdquo; que substitui &ldquo;ls&rdquo; e é feito em Rust. Tem vários assim.</p>
<p>No caso, existe o novo <a href="https://mise.jdx.dev/dev-tools/"target="_blank" rel="noopener"><strong>Mise</strong></a> de &ldquo;mise-en-place&rdquo;, pra quem já assistiu Masterchef. É exatamente a mesma coisa que ASDF só que feito em Rust. Inclusive ele é compatível com o mesmo arquivo <code>.tool-versions</code> que mencionei antes. Se não tiver, ele gera arquivo com nome próprio <code>.mise.local.toml</code> porque, claro, YAML ou JSON são antigos, o negócio é usar TOML &hellip;</p>
<p>Ele simplifica os comandos, mas não necessariamente acho que ficaram mais intuitivos. Mas é bem simples. Digamos que eu precise do tal Nodejs antigo, basta fazer <code>mise install node@14.21.3</code> ou direto <code>mise use node@14.21.3</code> pra instalar e já escolher pra usar.</p>
<p>Dá pra configurar versões locais pra cada diretório de projeto com <code>mise use --env local node@14.21.3</code>. E essa sintaxe de &ldquo;@&rdquo; é pra permitir instalar mais de uma versão num único comando, por exemplo <code>mise install ruby@3.1 nodejs@22.3.0</code>.</p>
<p>Mesma coisa como asdf, também podemos configurar a versão global padrão, caso não tenha arquivos como <code>.tool-versions</code> no diretório, fazendo <code>mise use --global nodejs@22.3.0</code>. Pra listar o que tem instalado, só fazer <code>mise ls</code>.</p>
<p>Enfim, vale <a href="https://mise.jdx.dev/getting-started.html"target="_blank" rel="noopener">estudar a documentação oficial</a>. No geral é uma ótima ferramenta e um bom substituto pra ASDF. Mas ele é tão parecido com ASDF que, se já estiver acostumado, não tem necessidade de mudar. Não tem nada a mais que ele faça que eu fosse sentir falta se não tivesse. Povo de Rust tem que parar de ficar substituindo as coisas pra fazer exatamente a mesma coisa. Era melhor gastar esse tempo ajustando e mandando patches pro próprio ASDF. Só dividiu os esforços da comunidade em duas ferramentas que fazem a mesma coisa.</p>
<h3>Últimas Considerações - Atuin<span class="hx:absolute hx:-mt-20" id="últimas-considerações---atuin"></span>
    <a href="#%c3%baltimas-considera%c3%a7%c3%b5es---atuin" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Uma última coisa, é que eu adicionei a ferramenta <a href="https://atuin.sh/"target="_blank" rel="noopener"><strong>Atuin</strong></a> &ldquo;Magical Shell History&rdquo;. Ele substitui o histórico do seu shell (sabe, aquele que você pode digitar &ldquo;Ctrl + R&rdquo; e procurar a linha de comando?) que normalmente é gravado em arquivo texto e manda pra um banco de dados SQLite3.</p>
<p>Só isso já seria legal, pra tirar as limitações de arquivo texto e evitar corromper e perder histórico. Mas além disso ele tem um serviço que permite sincronizar seu histórico entre diferentes máquinas. Digamos, seu PC desktop de casa, seu notebook de trabalho, seu servidor remoto. Hoje em dia todos tem históricos isolados e diferentes. E se desse pra sincronizar todos?</p>
<p>Aquele dia que você esquece seu notebook no trabalho, está no PC de casa e fica <em>&ldquo;puts, quais eram mesmo aqueles comandos de docker que eu fiz no trabalho??&rdquo;</em> Agora tem com, basta fazer <code>atuin sync</code> e pronto, seus históricos sincronizam!</p>
<p>Pra isso, no script de instalação eu rodo o <code>atuin register</code> que pede um username, email e uma senha (que, se não me engano, vai servir pra encriptar seus dados). E pronto, já vai sozinho se virar pra ficar sincronizando. Se já tinha conta, numa máquina nova basta rodar <code>atuin login</code> e logar. Só isso.</p>
<p>Ele substitui o <code>Ctrl + R</code> pra pesquisar no sqlite3 e agora seu histórico será muito mais robusto. Eu imagino que isso é mais importante ainda pro povo de devops. Eu lembro que rodava trocentos comandos de pods e containers e usava <strong>MUITO</strong> o histórico pra lembrar das coisas e repetir comandos. Fucem a documentação, tem como montar seu próprio servidor de Atuin pra onde sincronizar. Mesmo estando encriptado, talvez você queira 100% de controle. Tem como.</p>
<p>E por hoje é isso. Eu gostei bastante de brincar com o Omakub-MJ e meu PC pessoal com Manjaro GNOME e meu notebook com Windows 11 + ArchWSL já estão usando tudo exatamente como expliquei aqui. Novamente, leiam o <a href="https://manual.omakub.org/1/read#leaf_29"target="_blank" rel="noopener">Manual do Omakub</a> escrito pelo DHH, usem o Omakub dele caso estejam em Ubuntu, usem o <a href="https://github.com/akitaonrails/omakub-mj"target="_blank" rel="noopener">meu fork</a> pra Manjaro e Arch e não deixem de mandar Pull Requests ou Issues lá.</p>
]]></content:encoded><category>linux</category><category>ferramentas-de-desenvolvimento</category><category>open-source</category></item><item><title>[Akitando] #114 - O Melhor Setup Dev com Arch e WSL2</title><link>https://akitaonrails.github.io/2022/02/15/akitando-114-o-melhor-setup-dev-com-arch-e-wsl2/</link><guid isPermaLink="true">https://akitaonrails.github.io/2022/02/15/akitando-114-o-melhor-setup-dev-com-arch-e-wsl2/</guid><pubDate>Tue, 15 Feb 2022 12:52:00 -0300</pubDate><description>&lt;div class="embed-container"&gt;
&lt;iframe
src="https://www.youtube.com/embed/sjrW74Hx5Po"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2&gt;DESCRIPTION&lt;span class="hx:absolute hx:-mt-20" id="description"&gt;&lt;/span&gt;
&lt;a href="#description" class="subheading-anchor" aria-label="Permalink for this section"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Vale a pena usar WSL2? Por que Arch Linux?&lt;/p&gt;
&lt;p&gt;Se quiser conhecer a fascinante de como Linux veio parar dentro do Windows, assistam meu video original sobre WSL2 onde eu conto todos os detalhes da história do Windows que você nunca conheceu: &lt;a href="https://www.youtube.com/watch?v=28jHuWBi72w"target="_blank" rel="noopener"&gt;https://www.youtube.com/watch?v=28jHuWBi72w&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Porém, a parte sobre a configuraçâo do Linux no WSL2 estão defasadas e pra corrigir isso fiz o video de hoje.&lt;/p&gt;</description><content:encoded><![CDATA[

<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/sjrW74Hx5Po"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<h2>DESCRIPTION<span class="hx:absolute hx:-mt-20" id="description"></span>
    <a href="#description" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Vale a pena usar WSL2? Por que Arch Linux?</p>
<p>Se quiser conhecer a fascinante de como Linux veio parar dentro do Windows, assistam meu video original sobre WSL2 onde eu conto todos os detalhes da história do Windows que você nunca conheceu: <a href="https://www.youtube.com/watch?v=28jHuWBi72w"target="_blank" rel="noopener">https://www.youtube.com/watch?v=28jHuWBi72w</a></p>
<p>Porém, a parte sobre a configuraçâo do Linux no WSL2 estão defasadas e pra corrigir isso fiz o video de hoje.</p>
<p>O Guia Definitivo de Ubuntu é um dos videos que vocês mais gostaram e continua válido, assistam se ainda não viram. O de hoje vai complementar aquele video com um novo setup mais moderno pra quem usa Windows e tem máquina suficiente pra instalar Linux em cima com WSL2. E não qualquer Linux, mas o venerado Arch Linux. Vamos ver um setup para desenvolvedores web que é enxuto e poderoso!</p>
<p>E pra quem conhece WSL2 já, vá até o fim pra uma dica de como organizar seu arquivo de projetos entre diferentes máquinas virtuais ao mesmo tempo com performance máxima!</p>
<p>== Conteúdo</p>
<ul>
<li>00:00:00 - intro</li>
<li>00:01:03 - motivação: cuidado com Insider</li>
<li>00:02:46 - recapitulando WSL2</li>
<li>00:03:13 - máquina recomendada</li>
<li>00:06:01 - instalando WSL2</li>
<li>00:07:16 - qual distribuição Linux?</li>
<li>00:10:26 - meu problema com APT</li>
<li>00:12:52 - instalando ArchWSL</li>
<li>00:17:08 - temas do Windows Terminal</li>
<li>00:18:59 - Vim antigo e Vim moderno</li>
<li>00:22:56 - instalando NeoVim e LunarVim</li>
<li>00:26:38 - apresentando LunarVim</li>
<li>00:30:48 - porque não oh-my-zsh? starship?</li>
<li>00:32:02 - instalando YAY</li>
<li>00:33:08 - instalando ZSH, Nerd Fonts e Powerlevel10k</li>
<li>00:38:28 - instalando plugins (zsh-autosuggestions)</li>
<li>00:40:05 - instalando alternativas em Rust</li>
<li>00:42:17 - instalando e mostrando ASDF de novo</li>
<li>00:46:47 - instalando e mostrando Docker</li>
<li>00:49:48 - apps gráficas de Linux funcionam bem?</li>
<li>00:53:02 - WSL, mounts P9 e HDs virtuais</li>
<li>00:56:43 - usando HDs externos do jeito certo</li>
<li>01:00:04 - criando HDs virtuais</li>
<li>01:01:32 - habilitando Hyper-V (parte avançada)</li>
<li>01:02:15 - montando e formatando HDs virtuais</li>
<li>01:03:49 - montando HDs virtuais automaticamente</li>
<li>01:08:37 - bônus: não esqueça das chaves ssh</li>
<li>01:09:16 - repetindo: o que você deve fazer?</li>
</ul>
<p>== Links</p>
<ul>
<li>Windows Insider (<a href="https://insider.windows.com/en-us/about-windows-insider-program"target="_blank" rel="noopener">https://insider.windows.com/en-us/about-windows-insider-program</a>)</li>
<li>WSL Config (<a href="https://github.com/MicrosoftDocs/WSL/blob/main/WSL/wsl-config.md"target="_blank" rel="noopener">https://github.com/MicrosoftDocs/WSL/blob/main/WSL/wsl-config.md</a>)</li>
<li>Win10 Smart Debloat (<a href="https://github.com/LeDragoX/Win10SmartDebloat"target="_blank" rel="noopener">https://github.com/LeDragoX/Win10SmartDebloat</a>)</li>
<li>Get Windows Terminal (<a href="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701"target="_blank" rel="noopener">https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701</a>)</li>
<li>Windows Terminal Themes (<a href="https://windowsterminalthemes.dev/"target="_blank" rel="noopener">https://windowsterminalthemes.dev/</a>)</li>
<li>Arch Wiki (<a href="https://wiki.archlinux.org/"target="_blank" rel="noopener">https://wiki.archlinux.org/</a>)</li>
<li>ArchWSL (<a href="https://github.com/yuk7/ArchWSL"target="_blank" rel="noopener">https://github.com/yuk7/ArchWSL</a>)</li>
<li>VSCodium (<a href="https://vscodium.com/"target="_blank" rel="noopener">https://vscodium.com/</a>)</li>
<li>Chris@Machine (<a href="https://www.chrisatmachine.com/"target="_blank" rel="noopener">https://www.chrisatmachine.com/</a>)</li>
<li>LunarVim (<a href="https://www.lunarvim.org/#opinionated"target="_blank" rel="noopener">https://www.lunarvim.org/#opinionated</a>)</li>
<li>Powerlevel10k (<a href="https://github.com/romkatv/powerlevel10k"target="_blank" rel="noopener">https://github.com/romkatv/powerlevel10k</a>)</li>
<li>zsh-autosuggestions (<a href="https://github.com/zsh-users/zsh-autosuggestions"target="_blank" rel="noopener">https://github.com/zsh-users/zsh-autosuggestions</a>)</li>
<li>oh-my-zsh (<a href="https://ohmyz.sh/"target="_blank" rel="noopener">https://ohmyz.sh/</a>)</li>
<li>How to install Yay (<a href="https://www.tecmint.com/install-yay-aur-helper-in-arch-linux-and-manjaro/"target="_blank" rel="noopener">https://www.tecmint.com/install-yay-aur-helper-in-arch-linux-and-manjaro/</a>)</li>
<li>ASDF (<a href="https://asdf-vm.com/guide/getting-started.html#_1-install-dependencies"target="_blank" rel="noopener">https://asdf-vm.com/guide/getting-started.html#_1-install-dependencies</a>)</li>
<li>Nerd Fonts (<a href="https://github.com/ryanoasis/nerd-fonts"target="_blank" rel="noopener">https://github.com/ryanoasis/nerd-fonts</a>)</li>
<li>Rewritten in Rust: Modern Alternatives of Command-Line Tools (<a href="https://zaiste.net/posts/shell-commands-rust/"target="_blank" rel="noopener">https://zaiste.net/posts/shell-commands-rust/</a>)</li>
<li>Docker Desktop (<a href="https://docs.docker.com/desktop/windows/wsl/"target="_blank" rel="noopener">https://docs.docker.com/desktop/windows/wsl/</a>)</li>
<li>Mount a Linux disk in WSL 2 (<a href="https://docs.microsoft.com/en-us/windows/wsl/wsl2-mount-disk"target="_blank" rel="noopener">https://docs.microsoft.com/en-us/windows/wsl/wsl2-mount-disk</a>)</li>
<li>How to create advanced tasks with the Task Scheduler (<a href="https://www.digitalcitizen.life/advanced-users-task-creation-task-scheduler/"target="_blank" rel="noopener">https://www.digitalcitizen.life/advanced-users-task-creation-task-scheduler/</a>)</li>
<li>How to Shrink a WSL2 Virtual Disk (<a href="https://stephenreescarter.net/how-to-shrink-a-wsl2-virtual-disk/"target="_blank" rel="noopener">https://stephenreescarter.net/how-to-shrink-a-wsl2-virtual-disk/</a>)</li>
</ul>
<h2>SCRIPT<span class="hx:absolute hx:-mt-20" id="script"></span>
    <a href="#script" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Olá pessoal, Fabio Akita</p>
<p>Um dos videos que vocês mais gostaram foi o meu Guia Definitivo de Ubuntu. A palavra &ldquo;definitivo&rdquo; nunca é definitivo de verdade, especialmente no mundo Linux onde as coisas mudam rápido. Faz muito tempo que fiz aquele video então hoje vou dar uma atualizada. Se você é iniciante em Linux, assista o video de Ubuntu porque tem coisas básicas que ensino lá que não vou repetir mais aqui.</p>
<p>Quero aproveitar e falar rapidinho de WSL 2, o Windows Subsystem for Linux, que também já fiz video algum tempo atrás. Então o de hoje vai ser configurar um bom ambiente de desenvolvimento web de Linux, que independe se está no WSL ou num Linux nativo, mas vou focar um pouco mais em WSL. Se quiser pular pra configuração específica de Linux, vá direto pra este tempo aqui embaixo e se já usa WSL2 ainda assim eu ainda tenho uma dica avançada no final. Consulte os capítulos do video e os links que complementam o conteúdo na descrição abaixo.</p>
<p>(&hellip;)</p>
<p>A motivação desse video é que recentemente eu reinstalei meu notebook do zero. O que aconteceu foi o seguinte: antes do Windows 11 ser lançado obviamente eu fiquei coçando pra experimentar. A Microsoft tem um programa chamado Insider. Se você se registra nele, vai habilitar o Windows Update pra baixar versões não-oficiais do Windows, versões beta ou mais instáveis ainda, em desenvolvimento. Eu fortemente recomendo contra fazer isso numa máquina de trabalho porque a chance de dar ruim é muito alta.</p>
<p>E justamente deu ruim comigo. As últimas versões Insider Preview quebram alguma coisa no suporte a Docker que ele sequer consegue inicializar o serviço. Dá um erro de timeout e crasheia. E não tá errado porque o povo do Docker ainda não teve tempo de corrigir seja lá o que a Microsoft mudou no Windows na versão em desenvolvimento. Não é culpa de ninguém. Esse é o propósito do programa Insider. O desenvolvedor do Docker pode ver o que o povo dentro da Microsoft tá mexendo e ir atualizando o Docker antes da próxima atualização oficial do Windows ser lançado, que pode ser daqui algumas semanas, pode ser daqui alguns meses. Eu que tava adiantado demais. É o mesmo motivo de porque em Linux recomenda-se sempre usar uma distribuição LTS, que é Long Term Support.</p>
<p>O problema é que a versão Insider Preview de desenvolvimento não tem como dar rollback pra versão estável anterior. Precisa fazer um clean install, instalar tudo do zero. Como o Windows 11 já foi oficialmente lançado, não tem porque eu ficar tendo dor de cabeça na versão Insider mais, então fiz o de sempre. Baixei o ISO da versão estável do Windows, queimei um pendrive, bootei e reinstalei tudo do zero. Agora estou com um Windows 11 limpo. Já que ia ter que instalar o WSL tudo de novo, aproveitei pra registrar tudo e mostrar pra vocês.</p>
<p>Vamos recapitular esse tal de WSL2. É uma camada de suporte pra facilitar e integrar uma máquina virtual Linux rodando sobre o hypervisor da própria Microsoft chamado Hyper-V. Máquinas virtuais e containers como Docker são coisas diferentes, por isso eu já tinha feito videos antes explicando a diferença entre os dois e recomendo que assista caso não saiba a diferença. Na prática é uma máquina virtual, só mais conveniente do que rodar dentro de um Virtual Box ou Virt Manager.</p>
<p>Por ser virtualização, significa que na mesma máquina estamos bootando um Windows e em cima dele bootando um Linux. Os recursos da sua máquina como disco, memória RAM, núcleos da CPU e GPU vão ser compartilhados entre os dois sistemas operacionais e por isso é mais pesado do que rodar só um dos dois sozinho. Não é recomendado rodar um WSL ou qualquer máquina virtual se tiver menos que 4 núcleos de CPU e menos de 8Gb de RAM.</p>
<p>Vai rodar se tiver menos? Vai, mas vai ser mais lento porque se faltar CPU vai ficar bem lento, se faltar RAM vai fazer swap em disco e isso vai deixar bem lento. O ideal é pelo menos, pelo menos, 8 núcleos de CPU e pelo menos 16Gb de RAM. Isso dito, não fiquem mandando nos comentários &ldquo;ah, e minha máquina com 4Gb?&rdquo;, faça a conta, 4 é menos que 8 que eu acabei de falar, vai ser lento. Se você não for fizer nada pesado, não tem problema, mas pra trabalhar vai ser super sofrido.</p>
<p>Se tiver máquina mais fraca, recomendo não usar WSL nem nenhum tipo de máquina virtual e sim instalar uma distribuição Linux mais leve como Puppy Linux ou Lubuntu. Não vai ser uma experiência bonita porque a intenção dessas distros é ser leve. Mas mesmo com uma distro que faça boot usando poucos recursos, se abrir um monte de abas no Chrome ou se começar a tentar subir muitos containers de Docker, super rápido vai faltar RAM e CPU e, de novo, vai ser uma experiência bem lenta.</p>
<p>Então pro resto do video vou assumir que você tem uma máquina com pelo menos um Intel Core i5 de 9a geração pra cima ou um Ryzen 5 de 3a geração pra cima e pelo menos 16 Gb de RAM com pelo menos SSD como armazenamento. Aliás, se tem uma máquina fraca e não tem dinheiro pra atualizar tudo, no mínimo do mínimo tente trocar seu HD mecânico por um SSD, é o que mais vai fazer diferença na performance geral. Em segundo lugar é aumentar RAM.</p>
<p>Meu notebook de trabalho que uso pra viajar é um Asus ROG Zephyrus G14. Ele tem um Ryzen 9 5900 HS com 8 núcleos e 16 threads, mais 40Gb de memória DDR4 e um NVME de 4 terabytes, portanto tem recursos mais que sobrando pra rodar um WSL2. Como falei antes, tá com Windows 11 recém instalado. E a primeira coisa que recomendo toda vez que se acaba de instalar Windows é rodar algum script de debloating, ou seja, um script que desabilita inutilidades como a telemetria que fica mandando dados pros servidores da Microsoft sem você saber. Também desabilita Cortana que ninguém usa e coisas assim que ficam roubando recursos da sua máquina.</p>
<p>Um dos scripts mais conhecidos é do LeDragoX. Não vou mostrar como rodar aqui porque tá explicado na página do projeto no GitHub. Se não conseguir seguir essas instruções, também não vai conseguir entender quase nada do video então sugiro que gaste 1 minuto pra tentar abrir a interface gráfica da ferramenta dele. Precisa saber o que é PowerShell, coisa que explico no meu video original sobre WSL2. Assiste lá depois.</p>
<p>Uma vez que desabilitamos o grosso de coisas que um Windows sobe automaticamente, mesmo assim ainda vai consumir quase 5Gb logo depois do boot. Por isso falei que com menos de 8Gb, no Windows, as coisas vão ficar lentas. Vamos começar instalando o tal WSL e se estiver nas versões mais recentes de Windows pode só abrir uma janela de PowerShell com permissões de administrador e digitar <code>wsl --install</code>. Agora vai tomar um café até baixar tudo e instalar os pacotes que precisa.</p>
<p>Não esqueça de instalar o Windows Terminal da loja da Microsoft ou usando algum instalador como o Chocolatey. Se você não é de Linux talvez não entenda ainda a importância de um bom emulador de terminal. No Mac temos o iTerm2, em distros Linux temos o Alacritty que é o melhor ultimamente, mas o Windows Terminal devo dizer que tá muito bem feito e na mesma categoria dos que acabei de falar. Obviamente use o WSL nesse terminal. Depois disso precisamos reiniciar o Windows, como sempre.</p>
<p>A instalação padrão de WSL já vai instalar o Ubuntu mais novo automaticamente e quando reiniciar vai pedir pra criar um usuário Linux. Esse passo é opcional, mas como não custa nada, vamos criar. Colocamos uma senha forte e pronto, estamos dentro de um Ubuntu, dentro do Windows. Se é sua primeira vez instalando WSL, essa visão deve ser bizarra.</p>
<p>Qualquer outro tutorial ia continuar configurando o Ubuntu, mas como sou eu, vou ignorar totalmente porque pessoalmente prefiro distros baseadas em ArchLinux. Sem me alongar demais, hoje em dia você tem 3 grandes famílias de distribuições Linux. Primeiro as baseadas em Debian, com pacotes formato DEB e o gerenciador APT como o Ubuntu, Elementary, Mint, Deepin, Pop OS.</p>
<p>Em segundo tem as baseadas no antigo RedHat, como o Fedora, CentOS, SuSe, com pacotes formato RPM e o gerenciador DNF. O mundo mais enterprise comercial tende a suportar o ecossistema RedHat, então a gente vê marcas como Oracle rodando seus sistemas num CentOS.</p>
<p>O Ubuntu meio que dominou os derivados de Debian. Debian era considerado uma das distribuições mais estáveis, mas pra isso ela sempre vinha com programas em versões um pouco mais defasadas. Lembra o que eu falei sobre o programa Insider do Windows? O Debian é como se fosse o Windows 10 quando já temos o Windows 11. Ele prefere estar mais atrasado pra não comprometer estabilidade.</p>
<p>Pra gerenciar isso o mundo Ubuntu tem o conceito de LTS. Por exemplo, no momento que estou gravando este episódio a versão mais nova do Ubuntu é a 21.10, mas a versão que eles recomendam como mais estável, e que vão dar suporte por alguns anos é a 20.04 que foi lançada 1 ano atrás. A esta altura a maioria dos principais software de Linux tem suporte ao Ubuntu 20.04 mas nem todos suportam a 21.10 ainda.</p>
<p>Ainda existem diversas outras famílias de distribuições que não são nem baseadas em Debian e nem em RedHat, como Slackware ou Gentoo. Mas essas são pra usuários mais avançados. Não recomendo pra iniciantes que ainda não tem costume de fuçar muito documentação e fóruns. Pra mim o melhor meio do caminho entre facilidade e coisas novas é a família Arch Linux que incluem distribuições como Manjaro, Endeavor, Garuda e outras.</p>
<p>Na dúvida eu sempre falo: escolha o Manjaro e seja feliz. O padrão no Manjaro é instalar com GNOME que é meio pesado, mas tem versão com KDE ou XFCE que são gerenciadores de janela mais leves e customizáveis. E você sempre pode instalar outras interfaces gráficas como o Cinnamon ou LXQT. Enfim, tem bastante coisa pra se divertir.</p>
<p>Uma das grandes vantagens do Arch é o gerenciador de pacotes Pacman e o AUR que é o Arch User Repository. Aqui vale uma explicação. Todo tutorial de Ubuntu por aí vai fazer você digitar um comando como <code>apt install</code> pra instalar algum pacote. Esse comando mantém um banco de dados com nomes e versões de pacotes que é atualizado sempre que se faz <code>apt update</code>. Ele faz isso se conectando nos diversos servidores oficiais da Canonical, que faz o Ubuntu, e atualiza os bancos de dados. Daí quando fazemos <code>apt install</code> vai em algum servidor e baixa o pacote do programa que quer instalar. Tudo costuma ser muito simples.</p>
<p>Mas isso implica que todo software do mundo precisaria estar registrado nesses servidores da Canonical, incluindo a versão mais nova e todas as antigas. É muita coisa pra uma empresa só conseguir catalogar e manter atualizado. Por isso é possível outras empresas terem repositórios próprios só com o arquivo de pacotes dos seus software em particular. Por exemplo, se quiser instalar o Docker, os pacotes não estão nos servidores da Canonical. Vamos abrir o tutorial de instalação oficial do Docker.</p>
<p>Tá vendo? Não é só um simples <code>apt install docker</code>, tem vários passos. Em resumo, primeiro precisa instalar alguns pacotes de infraestrutura do Ubuntu no passo 1. No passo 2 precisamos baixar a chave pública em formato GPG do Docker. Se não sabe o que é assinatura e chaves assimétricas, assista meus videos explicando o básico sobre criptografia. Mas em resumo, todo gerenciador de pacotes que se preza vai tentar garantir que você não instale malware de servidores falsos de hackers tentando se passar pelo Docker ou outra empresa.</p>
<p>Pra fazer isso eles assinam os pacotes e os dados transmitidos dos seus servidores usando chaves assimétricas. Eles assinam os pacotes com uma chave privada que ninguém nunca vai ter acesso. Daí instalamos essa chave GPG que é a chave pública. Tudo que a chave privada assina, só a chave pública consegue acessar e vice-versa. Um hacker não tem acesso à chave privada, então não vai conseguir assinar malwares.</p>
<p>No passo 3 precisamos indicar pra ferramenta APT onde está a listagem de pacotes nas mais diversas versões. Nessa lista tem coisas como versão mas também quais pacotes tem pra quais arquiteturas como x64 da Intel, ARM de Mac e assim por diante. Essa linha estranha é um comando pra adicionar um arquivo no diretório de sources do apt, que lista de onde que é pra baixar.</p>
<p>Finalmente no passo 4 fazemos primeiro um <code>apt update</code> pra baixar a listagem desse novo source e atualizar o banco de dados local e só agora podemos fazer o <code>apt install</code>. Quando fizer isso várias vezes, vai ficar meio automático, mas viu quantos passos precisamos fazer pra instalar um pacote que a Canonical não controla?</p>
<p>Como é instalar o mesmo Docker num Arch? Pra começar, a documentação existe no próprio wiki do Arch. E temos dois pacotes, ou o <code>docker</code> ou o <code>docker-git</code> que provavelmente é uma versão mais nova e potencialmente mais instável. Mas por padrão podemos fazer só <code>pacman install docker</code>. Pronto, só isso.</p>
<p>Pacman, assim como Apt ou DNF é um gerenciador e instalador de pacotes. E os repositórios do Arch costumam ter mais pacotes do que os equivalente de Ubuntu ou Fedora. E o que não tem, não precisamos fazer toda a burocracia de procurar um repositório de terceiros, instalar chaves e bla bla como fizemos no caso do Docker. A comunidade mantém um repositório de usuários que é o Arch User Repository ou AUR. A gente pode baixar um script de lá, que serve pra construir um pacote do zero e usamos pacman pra instalar. Mas tem um jeito ainda mais fácil que já vou mostrar.</p>
<p>Isso tudo dito, a Microsoft ainda não tem suporte oficial pra distros Arch no WSL, mas existe um projeto no GitHub chamado ArchWSL. Eu uso acho que desde 2018 e nunca tive problemas. É um Arch mínimo, mais leve que um Manjaro, mais leve que um Ubuntu. E a instalação é bem trivial. Pra isso vamos na página de GitHub do projeto baixar um zip que tem tudo que precisamos. Descompacte onde quiser mas eu costumo deixar na raíz do C: mesmo.</p>
<p>Agora abra um command prompt ou powershell no Windows Terminal, dê <code>cd</code> pro diretório onde descompactou o Arch e execute. Em dois segundos ele vai se registrar no WSL. Como o Windows Terminal já tava aberto ele ainda não detecta o novo Arch, mas basta reiniciar e voilá, já apareceu. O que eu gosto de fazer primeiro é configurar o Terminal pra sempre abrir o Arch primeiro.</p>
<p>Da primeira vez que entramos nele, estamos logados como usuário <code>root</code> que, como já expliquei no guia de Ubuntu, não se deve fazer. Lembra quando o Ubuntu oficial que o WSL instalou nos forçou a criar um usuário não-root? No caso do Arch vamos fazer isso manualmente. Uma das coisas que afasta muitos iniciantes do Arch é que ele nos obriga um pouco a saber o que estamos fazendo e não faz tanta coisa automaticamente. Por isso que é bom pra aprender.</p>
<p>No próprio GitHub do ArchWSL tem um link pra documentação. Vamos seguir e olha só. Daqui você não precisa de talento tampouco habilidade. Basta saber fazer copy e paste e saber ler. Vamos copiar esta primeira linha e colar no terminal com o Arch aberto. Isso vai configurar o arquivo sudoers pra permitir que comandos com <code>sudo</code> possam ser executados pra elevar privilégio a partir de qualquer usuário. O ideal não é abrir tudo pra <code>ALL</code> como fala aqui, mas como é máquina de desenvolvedor, não tem tanto problema. Depois estude sobre sudoers se não conhecia.</p>
<p>Em seguida são comandos básicos de <code>useradd</code> pra criar um novo usuário. Faça copy e paste mas obviamente digite um usuário com seu nome, né. Daí usamos o comando <code>passwd</code> passando o usuário que acabamos de criar pra configurar uma senha segura. Abrimos outra aba com um command prompt, e podemos fechar a que estava com o Arch aberto, porque precisamos configurar o WSL pra quando abrir o Arch de novo use o usuário que acabamos de criar em vez de `root. Então mais um copy e paste.</p>
<p>Pronto, se abrir o Arch no terminal de novo e dermos o comando <code>whoami</code> diz que é o novo usuário. A partir daqui, se precisarmos fazer alguma coisa que exija permissão de root é só começar o comando com <code>sudo</code>. E a primeira coisa que se deve fazer logo que se instala uma distro linux é atualizar todos os pacotes. No caso deste Arch, precisa fazer algumas coisas antes. De novo, a documentação já diz tudo. Só copiar e colar esses comandos de <code>pacman</code> que vai inicializar e popular as chaves que o Arch usa pra checar os pacotes.</p>
<p>O pacman é um pouco chatinho pra quem nunca viu porque não tem comandos fáceis como <code>install</code>, em vez disso o equivalente é <code>-S</code> maiúsculo que significa &ldquo;sync&rdquo;. Daí adicionamos a opção <code>y</code> que se não me engano é pra atualizar o banco de dados com as listagens do servidor oficial do arch. E a opção <code>u</code> é pra atualizar os pacotes. E eu faço <code>yyuu</code> duplicado pra forçar mesmo se já estiver tudo atualizado. O normal é fazer só <code>-Syu</code> sem duplicar, mas quando alguma coisa dá problema ou agora, que é primeira vez, acabo fazendo assim.</p>
<p>E esqueci de fazer uma coisa, então vamos dar <code>control-C</code> pra cancelar e abrir o arquivo <code>/etc/pacman.conf</code> com o editor <code>nano</code>. Procurar a palavra <code>Verbose</code> e adicionar uma nova linha embaixo dizendo <code>ParallelDownloads = 5</code>. Por padrão o pacman baixa um arquivo de cada vez e isso é bem demorado. Se você tem uma boa internet banda larga, pode testar, mas por volta de 5 downloads simultâneos ou até mais, aguenta. Agora sim, vamos repetir o comando do pacman pra atualizar tudo, e agora vai ser mais rápido.</p>
<p>Ele vai checar tudo que precisa ser atualizado, mostrar a lista de pacotes que vai baixar e pedir pra ir confirmando. Olha só como mostra 5 pacotes sendo baixados simultaneamente. Bem mais rápido, mas aí temos esse problema aqui. Um erro de chaves que ele não reconheceu. E isso porque eu fui burro e a documentação do ArchWSL tá incompleta. Faltou fazer <code>pacman -S archlinux-keyring</code> que instala as chaves mais novas que precisa pra instalar os pacotes. Então vamos instalar e repetir o comando de atualizar tudo.</p>
<p>Agora sim, foi até o fim. E é isso. Temos um Arch Linux rodando no WSL 2. Fim do video! Brincadeira. Antes de continuar, vamos deixar nosso terminal um pouco menos feio. Tá tudo com fundo preto. Pra mudar isso podemos ir no site windows terminal themes .dev. Dêem uma fuçada. Eu pessoalmente gosto do &ldquo;Moonlight II&rdquo; ou variações de &ldquo;Monokai&rdquo;. Clique em &ldquo;Get Theme&rdquo; e ele vai copiar pro clipboard.</p>
<p>No Windows Terminal faça &ldquo;ctrl-virgula&rdquo; ou na setinha na barra de título escolha &ldquo;Settings&rdquo;. Lá embaixo tem a opção de abrir o arquivo de configurações que é em formato JSON. Abre no Notepad mesmo por enquanto e vai lá pro fim. Logo embaixo do último tema, garante que tem uma vírgula e cole o novo tema. Cuidado pra não quebrar o JSON. Não precisa reiniciar, só salvar o arquivo. Agora seleciono o &ldquo;Arch&rdquo; no menu e vamos pra &ldquo;Appearance&rdquo;. Pronto, posso selecionar o &ldquo;Moonlight II&rdquo; e embaixo posso aumentar a fonte pra 16 só pra ficar mais fácil de ver aqui no video.</p>
<p>Falando em editor, o próximo passo é instalar um bom editor de textos. Na prática, basta instalar o Visual Studio Code que ele se integra plug and play com o WSL. Vamos ver? Vai na loja do Windows mesmo, procura por Visual Studio, seleciona e instala. Pra ter a integração com o terminal precisa fechar e abrir de novo. Pronto, basta ir pra algum diretório e digitar <code>code .</code> e olha só como abre o Visual Studio listando os arquivos de Linux.</p>
<p>O VSCode funciona super bem e se você prefere uma versão mais light e com mais privacidade, procure pela alternativa chamada VSCodium, que é a mesma proposta do Chromium em relação ao Chrome. VSCode e Chrome tem a péssima mania de se comunicar com servidores da Microsoft ou do Google, respectivamente, e ficar comunicando coisas que não sabemos. O VSCodium e Chromium desligam essas comunicações desnecessárias. Se você é do tipo mais paranóico com privacidade, instale essas alternativas.</p>
<p>Mas de vez em quando ainda prefiro ficar só no terminal mesmo. E hoje em dia ainda não tem nada melhor do que Vim na minha humilde opinião. Esse nosso ArchWSL já vem com vim pré-instalado. O básico que você tem que saber é que ele tem um modo de edição e um modo de navegação. Dá pra ficar horas falando de vim e no video de Ubuntu já mostrei o básico. Se nunca tentou, recomendo que dê uma chance de verdade. Acho importante conhecer o básico de Vim pra mudar a perspectiva do que um editor de textos realmente deveria fazer.</p>
<p>O Vim foi criado numa época onde se usava terminais remotos em redes super lentas. Por isso não existia o conceito de IDEs como um Visual Studio. Seria pesado demais. Quando conversei com o Uncle Bob a gente falou disso, recomendo que assistam nossa live que está gravada no canal. Mas por isso o Vim padrão parece tão espartano, com comandos super curtos, pra minimizar ao máximo os comandos enviados ao servidor a partir do terminal remoto.</p>
<p>Aliás, é por isso que este programa que estamos usando, esta janela do Windows Terminal se chama terminal ou, mais corretamente, emulador de terminal. É um terminal remoto que se conecta com o servidor de terminal rodando por baixo dos panos, localmente. O &ldquo;Linux&rdquo; em si não roda &ldquo;dentro&rdquo; desse programa, por isso podemos fechar o Terminal mas o Linux em si continua rodando por baixo. E quando abrimos um novo Windows Terminal, ele conecta de novo no servidor por baixo. Pense no Linux como se fosse um servidor web e o terminal como se fosse um navegador web, é o mesmo conceito.</p>
<p>Enfim, o Vim na verdade é a evolução do editor original que se chamava só &ldquo;Vi&rdquo;, do Bill Joy, que era da Sun Microsystems. Já o Vim é um fork do Brian Moolenar. Depois do Vim versão 8 surgiu um fork dele chamado de NeoVim que tem a proposta de modernizar o Vim, em particular modernizar o código-fonte, que tem coisa de décadas atrás que nem precisamos mais e funcionalidades que hoje são possíveis. Uma das coisas que adicionaram faz poucos meses foi suporte à linguagem Lua.</p>
<p>O Vim sempre teve plugins escritos numa linguagem própria chamada VimScript, que é uma linguagem bem feia e chata de trabalhar, meio como scripts em Bash. É super antiquado, super fácil de criar bugs acidentais. Por isso pouca gente tem paciência pra escrever plugins nessa linguagem. Já Lua é uma linguagem mais moderna e madura, muito mais difundida, especialmente pra quem programa games. Além de ser uma linguagem super leve e fácil de embutir em qualquer programa.</p>
<p>Tem um canal no YouTube que recomendo que assinem, do Chris at Machine. Ele veio acompanhando essa nova integração e criou um projeto no GitHub chamado LunarVim, que é uma coleção de plugins escritos em Vim e uma configuração super completa que transforma o NeoVim praticamente num Visual Studio Code, só que mais leve e mais produtivo. E &ldquo;praticamente&rdquo; porque uma das características mais importantes do VSCode são seus servidores de linguagens.</p>
<p>Explicando bem curto e porcamente, o VSCode foi inteligente em fazer um editor que por si só é leve e não tem suporte a nenhuma linguagem. É um editor neutro se não configurar nada. Mas quando instala um plugin pra linguagem Ruby, por baixo ele instala um SolarGraph como servidor. Daí o VSCode passa a ser um cliente desse servidor que vai analizar o código Ruby que estamos digitando e dar suporte a coisas como autocomplete, debug, e mais. E cada servidor de linguagens diferentes vai implementar o Language Server Protocol ou LSP que é a API que o VSCode entende.</p>
<p>Agora, se eu pegar outro editor e fazer ele entender o protocolo LSP, dá pra usar os mesmos servidores. Por isso consigo trocar o cliente VSCode e substituir por NeoVim. LSP é como se fosse HTML, o VSCode é como se fosse o navegador Chrome ou Edge e o NeoVim poderia ser como o Firefox, sacaram? E o tal LunarVim que o Chris fez já pré-instala todos os plugins necessários pra integrar com LSP. Então vamos instalar pra ver.</p>
<p>Primeiro, precisamos do NeoVim. E hoje a versão que tem no repositório oficial já serve. Meses atrás precisava compilar o NeoVim manualmente porque não estava disponível esse suporte na versão oficial, só na beta. Pra instalar no Arch é fácil, só fazer <code>sudo pacman -S neovim</code> e veja como lista pacotes de Lua. Sabemos que é a versão que precisamos.</p>
<p>Quando terminar de instalar, vamos pra página no GitHub do LunarVim e tem um script instalador pra facilitar nossa vida. Só copiar essa linha e colar no terminal. E de cara já começa reclamando que não temos Git instalado. Bora instalar <code>pacman -S git</code> como ele manda.</p>
<p>Esse script vai ajudar a instalar as dependências que precisamos. A primeira coisa são pacotes de javascript, daí reclama que não tem nodejs instalado então vamos fazer <code>sudo pacman -S yarn npm</code> pra instalar&hellip; Agora com a seta pra cima repetimos o instalador do LunarVim e damos yes e pronto, tá usando o <code>yarn</code> pra instalar o que precisa.</p>
<p>No próximo passo pede pra instalar dependências de Python e como já temos <code>pip</code> instalado, prossegue instalando o que precisa&hellip; Essa foi fácil, e no passo seguinte ele quer instalar dependências de Rust, mas não temos Rust então o instalador pára de novo. Vamos fazer <code>sudo pacman -S rust</code> pra poder usar o <code>cargo</code> pra instalar as ferramentas de Rust.</p>
<p>Assim como <code>yarn</code> é instalador de dependências de Javascript, <code>pip</code> é instalador de dependências de Python, o <code>cargo</code> é instalador de dependências de Rust. O Rust é uma linguagem compilada que gera binários nativos super otimizados e com segurança superior à de C puro. E no meio da instalação ele deu um erro. Parece que não conseguiu compilar o jemalloc-sys ou pam.</p>
<p>Eu já tinha ido no Google antes e o que aconteceu é que o Rust se integra com binários compilados em C também e nesse ponto ele precisou compilar alguma coisa de C só que não instalamos o ferramental pra isso ainda. Num Ubuntu isso seria o pacote <code>build-essential</code>, mas não existe no Arch. O equivalente é <code>sudo pacman -S base-devel</code>. Só ir dando <code>yes</code> no que tá perguntando, mas sempre leia antes, lógico.</p>
<p>Pronto. Seta pra cima, vamos repetir os mesmos passos tudo de novo. Ele sempre passa pelos passos de javascript e python mas agora é mais rápido porque já instalou esses passos. O Rust volta a compilar o que falta e agora &hellip;. vai até o fim. Mas atenção que fala que precisa colocar o diretório <code>$HOME/.cargo/bin</code> no PATH senão não vai achar as ferramentas que acabou de compilar. E no final o instalador também avisa que não vamos usar o comando <code>nvim</code> que inicia o NeoVim normalmente mas sim o <code>lvim</code> e pra isso precisamos adicionar o <code>$HOME/.local/bin</code> no PATH. Eu explico o que é PATH no episódio do guia de Ubuntu.</p>
<p>Só pra agora podermos ver o LunarVim, vamos exportar o PATH manualmente adicionando esses dois diretórios&hellip; Pronto. Agora podemos abrir <code>lvim</code> e olha só que diferença. No LunarVim apertamos &ldquo;espaço&rdquo; pra abrir esse menu e com a opção &ldquo;e&rdquo; de &ldquo;explorer&rdquo; temos um painel com o projeto organizado como árvore, todo configurado com ícones e bem bonito. Podemos navegar pra cima e pra baixo com as teclas &ldquo;j&rdquo; e &ldquo;k&rdquo; e com a tecla &ldquo;o&rdquo; podemos abrir o arquivo embaixo do cursor.</p>
<p>Vamos abrir o arquivo &ldquo;config.lua&rdquo; pra adicionar uma configuração pra corrigir um pequeno bugzinho que essa versão ainda tem com esse negócio de abrir menu com &ldquo;espaço&rdquo;. Ele é rápido demais e pode dar conflito com outras combinações de teclas então colocamos <code>vim.opt.timeoutlen = 500</code> milissegundos como gambiarra pra contornar e pronto.</p>
<p>O video de hoje não é sobre Vim então não quero me alongar demais nele, mas acho que vale a pena fazer uma pequena tangente pra mostrar um pouquinho de porque instalei o LunarVim. Então vou me adiantar um pouco e abrir um projetinho besta em Rails antigo meu só pra dar exemplo. Primeira coisa é que posso fazer ele ficar parecido com uma IDE apertando espaço, que abre esse menu principal, e com &ldquo;e&rdquo; eu abro o explorer do lado, que é o plugin NvimTree. A partir dele posso usar o mouse normalmente pra abrir arquivos.</p>
<p>Por acaso abri um arquivo de Ruby. Lá embaixo dá pra ver a mensagem de &ldquo;LSP inactive&rdquo;, ou seja, não tem nenhum servidor de linguagem analisando este arquivo. Mas se esperar alguns segundos, olha só, assim como o VSCode, o LunarVim achou um LSP de Ruby, no caso o Solargraph, e instalou sozinho e a partir daqui todo arquivo de Ruby que eu abrir ele vai analizar.</p>
<p>Pra abrir mais arquivos, posso voltar pro painel do explorer com o mouse, ou como eu prefiro, com o teclado fazendo ctrl+h pra ir pro painel da esquerda ou ctrl+l pro painel da direita, e os mesmos comandos de navegação como &ldquo;j&rdquo; pra ir uma linha pra baixo ou &ldquo;k&rdquo; pra uma linha pra cima funcionam igual. E com &ldquo;o&rdquo; posso abrir o arquivo embaixo do cursor.</p>
<p>Mas esse explorer usa muito espaço, então posso fechar ele. Em vez de usar o explorer posso abrir o menu principal com &ldquo;espaço&rdquo; e apertar &ldquo;f&rdquo;, que vai abrir o plugin Telescope que usa a ferramenta &ldquo;fd&rdquo; que é uma das que ele instalou de Rust no começo, lembram? E posso fazer um fuzzy find direto do nome de algum arquivo, como &ldquo;archives&rdquo; e abro o controller.</p>
<p>Notem que o editor parece meio poluído à primeira vista, mas isso é o solargraph que analizou o código e fica dando dicas e avisos de coisas que podem melhorar ou bugs óbvios que precisam ser corrigidos. Toda linguagem moderna hoje tem um LSP que faz essas coisas. Por exemplo, nesse trecho ele fala pra evitar usar chaves num bloco de múltiplas linhas, em Ruby é mais bonito usar &ldquo;do-end&rdquo; em vez disso, e pronto, o aviso sumiu.</p>
<p>Outro exemplo é a sintaxe de atoms em hash que mudou desde a versão 1.9 do Ruby, antes era usando um fat arrow, hoje é usando dois pontos que nem um JSON. E mesma coisa, substituir chaves por &ldquo;do-end&rdquo;. E aqui embaixo ele fala pra não fazer comparação com zero e sim usar o método &ldquo;empty?&rdquo; pra checar se a variável está vazia ou é zero.</p>
<p>Além disso, ele nos ajuda quando temos dúvida numa função. Aqui eu digito ponto e ele já me dá uma lista de métodos que a String aceita. E se eu sair navegando, ele até me dá a documentação da função caso eu não me lembre ou tenha dúvidas. E se for digitando, ele vai filtrando na lista até eu achar o método que eu estava precisando. Tudo coisa básica que se você já usou uma IDE moderna já tinha, mas agora disponível dentro do terminal no vim.</p>
<p>E só como último exemplo de coisas avançadas, alguns LSPs tem recursos de refactoring. Vamos procurar o arquivo do model chamado Post. E se eu quisesse renomear essa classe de Post pra Article e não ter que ir abrindo arquivo a arquivo de todo lugar que a classe Post é usado? Posso abrir o menu principal com espaço, apertar &ldquo;l&rdquo; pra abrir o sub-menu do LSP e olha que ele tem &ldquo;rename&rdquo;. Lá embaixo eu mudo de Post pra Article e deixo o LSP trabalhar.</p>
<p>Notem que lá em cima apareceu um monte de aba de arquivos que ele abriu. Ele ainda não salvou nada. Só abriu todo arquivo onde aparece a classe Post e substituiu por Article. Abrindo aquele mesmo arquivo do ArchivesController, olha como onde tava Post agora tem Article no lugar direitinho. Mesma coisa no PostsController e assim por diante. Eu devo ir checando e salvando um a um pra garantir que fez tudo certo e, lógico, no final eu teria testes automatizados pra garantir que nada quebrou. Mas é uma das coisas que uma IDE como o LunarVim consegue fazer. E isso foram só 2 minutos de demonstração, tem bem mais coisas por baixo pra facilitar nossa vida.</p>
<p>Se você se animar a dar uma chance pro jeito Vim de navegar, em breve vai conseguir programar sem precisar ficar tirando a mão pro mouse toda hora. É muito mais confortável e até mais ergonômico de trabalhar. Além disso ele renderiza tudo em modo texto dentro do Terminal, o que usa muito menos recursos do seu sistema do que o VSCode que, por baixo, é tão pesado quanto um navegador web, como programas feitos em Electron. O VSCode, recém instalado, logo que abre já consome de 250 a 300 mega de RAM. O LunarVim fica na faixa de menos de 150 mega. É quase metade de recursos. Mas claro, hoje em dia depende mais dos LSP que rodam por trás analisando seu código.</p>
<p>Voltando pra nossa instalação, precisamos configurar o PATH de forma permanente e pra isso é só adicionar o mesmo comando de export que fizemos no arquivo <code>.bashrc</code>. Mas eu pessoalmente prefiro o shell ZSH. Eu sei, tem alguns que vão comentar sobre o Fish, mas eu ainda gosto do ZSH mesmo. Pra quem não sabe, além de Bash existem outras linhas de comando ou shells e suporte a scripts diferentes. O Bash é meio antiquado pra hoje, mas não tem nenhum problema de ficar nele.</p>
<p>No video do guia de Ubuntu eu baixei um conjunto de dotfiles de um usuário chamado skwp pra customizar meu prompt, vim e tudo mais, mas ele é muito pouco suportado e hoje em dia existem opções muito melhores. Essa é a parte do video antigo que ficou desfasado. Mesmo na época já existia o Oh-my-zsh que eu testei por um tempo, mas nenhum dos plugins foi muito importante pra mim e acho um pouco pesado. Muita gente gosta de usar só o starship, que faz um prompt até que minimalista e bonitinho de ver.</p>
<p>Meu preferido e o que achei mais fácil de instalar e configurar é o Powerlevel10k. Antes precisamos instalar uma outra ferramenta de Arch Linux pra facilitar nossa vida. Lembra dos pacotes que a comunidade mantém no AUR que mencionei? Pra instalar direto de lá não dá pra usar Pacman. Tem vários gerenciadores de AUR mas o que mais gosto é o Yay. E muitos tutoriais mais novos já assumem que você tem yay. Dá pra saber que um artigo aleatório é mais antigo se em vez de yay ele manda usar yaourt, que é desafado. Então vamos lá.</p>
<p>Na página de GitHub do Yay vamos descer pras instruções. A primeira coisa é instalar os pacotes de git e base-devel, mas acabamos de instalar então pula. Próxima linha é fazer <code>git clone</code> do projeto. Eu prefiro dar <code>cd</code> pro diretório temporário do sistema porque não vamos usar esse clone pra mais nada depois de instalar. Feito o clone damos <code>cd</code> pra ele e &ldquo;make package&rdquo; com opção pra instalar logo depois de construir o pacote. Lembram o que eu expliquei? O AUR não tem os binários nos servidores, só a receita de como montar o pacote de determinado programa. Uma ferramenta com o Yay vai automatizar o que acabamos de fazer manualmente, que é dar clone do projeto, montar o pacote e instalar com pacman localmente.</p>
<p>Pronto, com o Yay instalado praticamente não precisamos usar mais o pacman porque ele serve pra instalar tanto pacotes oficiais dos repositórios do Arch quanto do AUR, usando a mesma sintaxe do pacman. De exemplo, vamos instalar o shell ZSH, que vamos usar no lugar no Bash. Basta fazer <code>yay -S zsh</code>, nem precisa de <code>sudo</code>, ele se vira.</p>
<p>Agora vamos pra página de GitHub do PowerLevel10K. Mesma coisa, pulamos pra seção de Instalação e veja como tem instruções pra várias distros. Queremos do Arch. Simples, duas linhas e ele já assume que temos o <code>yay</code> instalado, então copiamos a primeira linha e colamos no terminal&hellip; pronto. No final ele recomenda instalar algumas fontes. Acho que não faz diferença dentro do terminal, mas pode instalar como fiz aqui. Vai fazer diferença se usar aplicativos gráficos de Linux iniciados de dentro do WSL, como o VSCode de Linux. Mas falo disso depois.</p>
<p>Seguindo as instruções é só executar essa linha de comando que vai inserir a inicialização do powerlevel10k no script <code>.zshrc</code> que é o equivalente <code>.bashrc</code> só que pra zsh, obviamente. Podemos fechar essa aba, abrir outra e &hellip; nada acontece. Isso porque por padrão sempre inicia o Bash, precisamos usar o comando de Linux de &ldquo;change shell&rdquo; que é <code>chsh -s /usr/bin/zsh</code> pra da próxima vez executar direto o zsh em vez do bash&hellip;</p>
<p>Pronto, agora fechamos a aba, reabrimos e como é a primeira vez, o powerlevel10k abre esse wizard de configuração. E a primeira coisa que ele pede pra gente confirmar é se estamos vendo um ícone com formato de diamante. Mas em vez disso estamos vendo um quadradinho, que nem quando vemos fontes quebradas numa página.</p>
<p>Isso porque ele espera encontrar uma família de fontes que tenham gráficos além de só letras. Chamamos essas famílias de Nerd Fonts. Se você é web designer ou desenvolvedor front-end sabe disso. Acho que foi o GitHub que inventou isso de embutir gráficos como fonte. Isso porque sites como o próprio GitHub usam dezenas de pequenos ícones em todo lugar. Em vez de fazer dúzias de PNGs que além de ser um saco de gerenciar também prejudica a performance do download de assets da página, eles tiveram a idéia de embutir todos os ícones em uma família de fonte, que a gente baixa tudo de uma vez só, como a Font Awesome e fica muito mais fácil de usar em qualquer lugar, não só em sites, porque os emuladores de terminais modernos são capazes de renderizar essas fontes também.</p>
<p>Além disso foi a época que Emojis começaram a popularizar, que nada mais são que um padrão onde imagens são associadas com códigos Unicode dentro da família de fontes. Então o mesmo código sempre vai devolver o mesmo emoji independente da família de fontes que estamos usando. Mas a fonte que o Windows Terminal usa por padrão que é a Microsoft Consolas, não tem nenhum desses ícones, por isso devolve um quadradinho pra indicar que não encontrou. Existem várias fontes que você pode pesquisar depois que tem esses ícones com o Fira Code mas eu pessoalmente gosto do Meslo LGS.</p>
<p>Na própria página de instruções do Powerlevel10k tem links pra baixar os arquivos de fonte, então vamos lá baixar uma a uma&hellip; Pronto, agora vamos no explorer no diretório de downloads, selecionamos todos os arquivos que acabamos de baixar, e escolhemos pra instalar as fontes no sistema&hellip; E pronto, agora podemos ir no Windows Terminal, abrir de novo a aba de configurações, escolhemos o Arch, escolhemos a aba de aparência e finalmente podemos trocar o Consolas pelo Meslo LGS.</p>
<p>Agora sim, abrimos uma nova aba. Vai carregar o ZSH que, por sua vez, vai carregar o Powerlevel10k. Como não prosseguimos a configuração da última vez, vai pedir pra começar de novo e desta vez veja como aparece o ícone de diamante. Nos próximos passos ele pede pra confirmar que estamos vendo os outros ícones e daí podemos continuar o passo a passo. E aqui vai do gosto de cada um. Vou passar rapidinho o que eu costumo escolher, mas recomendo que vocês experimentem opções diferentes. No final vai gravar tudo que escolheu no arquivo de configuração <code>.p10k.zsh</code>.</p>
<p>Se não gostou do que escolheu basta digitar <code>p10k configure</code> na linha de comando pra chamar esse passo a passo tudo de novo ou editar manualmente o arquivo <code>.p10k.zsh</code>. Mas no final, olha só como ficou o meu prompt. Com ícones aqui na esquerda, mostrando o diretório onde estou. Se eu estiver num projeto de Git vai mostrar a branch também. Lá na direita mostrando a hora, mas quando entrar num projeto de código ele mostra outros ícones indicando a linguagem do projeto, a versão dessa linguagem e coisas assim.</p>
<p>Agora não podemos esquecer de configurar o PATH no arquivo <code>.zshrc</code>, assim podemos ter acesso ao LunarVim e qualquer nova ferramenta instalada pelo Cargo do Rust. Pode abrir com qualquer editor como o VSCode mas neste video sempre vou usar o NeoVim. Só adicionar o export no final do arquivo e não esquecer que a variável <code>$HOME</code> é um atalho pro diretório padrão do seu usuário e no final anexar o que já tinha no $PATH antes&hellip; Pronto, veja que neste instante se chamarmos <code>lvim</code> não vai achar. Mas agora abrimos outro terminal e boom, abriu o LunarVim como deveria.</p>
<p>O powerlevel10k é bem flexível pra customizar o visual como quiser, e eu gosto do passo a passo do que ter que ficar ajustando arquivo de configuração manualmente. Só tem que fazer isso uma vez e esquecer. Mas como eu disse dá pra customizar o zsh pra ficar bem mais complexo com um oh-my-zsh e colocar vários plugins. Depende de que tipo de trabalhos mais faz no terminal, então não deixe de fuçar que plugins existem. Mas tem um que eu acho útil e por isso vou instalar manualmente agora. Quem usa a shell Fish já tem isso automaticamente.</p>
<p>Vamos instalar que eu mostro pra que serve. No diretório do seu usuário, que você sempre volta fazendo <code>cd</code> sozinho, vamos criar um diretório chamado <code>.zsh</code> pra instalar o plugin. Agora vamos na página de GitHub dele. Tem link pra outra página com instruções de instalação. Olha como tem instrução pro Oh-my-zsh, mas queremos a forma manual. O primeiro passo é clonar o projeto pro diretório que criamos, então é só copiar essa linha de <code>git clone</code> e colar no terminal.</p>
<p>Queremos que toda vez que o zsh carregue, também carregue o plugin então temos que editar o arquivo <code>.zshrc</code> de novo. Copiamos a segunda linha das instruções e podemos colar no script. Salvamos e pronto. Mas pra carregar agora mesmo, é só executar a linha que copiamos que ele carrega o script do plugin. Pra que serve isso? Vamos fazer um comando idiota de <code>echo</code>. E se eu quiser repetir o mesmo comando?</p>
<p>Posso copiar o que acabei de digitar e colar ou, começo a digitar <code>e</code> e ele consulta no histórico e vai tentando auto completar. Olha como já apareceu aqui. Agora é só dar <code>tab</code> ou seta pra direita e vai completar tudo. Isso é super útil porque o tempo todo estamos repetindo os mesmos comandos e eles ficam no histórico da sessão. Isso é um bom exemplo de plugin útil.</p>
<p>Como o LunarVim já pediu pra instalar algumas ferramentas feitas em Rust e já colocamos no PATH onde o Cargo instala os binários, podemos aproveitar e instalar mais algumas ferramentas modernas. Se procurar no Google vai achar vários artigos a respeito mas vou usar este entitulado Rewritten in Rust junto com os outros links na descrição do video. Depois leiam com calma, ele lista diversas novas ferramentas feitas em Rust.</p>
<p>Por exemplo, logo de cara tem os que eu mais gosto, por exemplo o <code>bat</code>, que é um substituto do <code>cat</code> que usamos pra listar o conteúdo de arquivos texto. Ou o <code>exa</code> que é substituto pro <code>ls</code> que usamos toda hora pra listar arquivos de diretórios. Em seguida ele fala do <code>fd</code> que é uma alternativa mais performática pro <code>find</code> e que o LunarVim já instalou porque o plugin Telescope usa. Além do <code>fd</code> o LunarVim também instalou o <code>rg</code> ou RipGrep que é um grep mais performático.</p>
<p>Podemos instalar usando o pacman ou o yay mas vamos instalar usando o Cargo mesmo. Basta fazer <code>cargo install</code> e passar todas as ferramentas que queremos. Olha só o cargo baixando, compilando e instalando&hellip; e no final deu alguns problemas. Ele não conseguiu instalar o ytop, dust e delta. Pode ter algum bug nos repositórios mas não me incomodei pra procurar porque não são essenciais. Os principais que eu queria eram o bat e exa.</p>
<p>Vamos testar. Primeiro, olha como é a saída do <code>ls</code> normal de Linux. Uma listagem normal de arquivos e diretórios, nada demais. Agora vamos usar o <code>exa</code> com as mesmas opções de <code>-la</code>. Ele não aceita todas as opções iguais do <code>ls</code> só as mais comuns e veja só como ficou BEM mais bonito. E pra cereja no bolo tem a opção <code>--icons</code>, e olha só como ficou ainda MAIS bonito. Depois que a gente vê assim, não dá vontade de usar o <code>ls</code> padrão mais. Eu não testei, mas tudo tem trade-off, não sei se um diretório com milhares de arquivos vai ficar mais lento de listar. E também se quiser capturar a listagem num arquivo texto pra trabalhar depois, daí é melhor não usar o exa.</p>
<p>Mesma coisa com o cat. Vamos listar o conteúdo do script <code>.zshrc</code>. E como sempre, listado, nada demais. Mas e com o <code>bat</code>? Olha só como ficou BEM mais bonito. Mas mesma coisa: se precisar trabalhar com o conteúdo do arquivo num script é melhor usar o cat normal. O bat é só pra visualizar mais bonito.</p>
<p>Mas como eu uso <code>ls</code> e <code>cat</code> só pra visualizar no terminal mesmo, prefiro até substituir eles com aliases, e pra isso vamos abrir o <code>.zshrc</code>. Só quero adicionar <code>alias</code> pra dizer que quando eu digitar <code>ls</code> no terminal o zsh vai na verdade chamar o <code>exa</code> e mesma coisa pro <code>cat</code> sempre chamar o <code>bat</code>. Isso é opcional, mas só pra saber que dá pra fazer isso.</p>
<p>Agora que nosso terminal tá bonitão, hora de instalar o ASDF. Não vou me alongar nessa parte porque já expliquei em detalhes sobre isso no guia de ubuntu e vai ser exatamente a mesma coisa agora. Pra quem não lembra, no dia a dia de programador a gente nunca usa uma única versão de alguma linguagem ou framework em todos os projetos. Podemos estar programando um projeto em Node.js versão 16, mas aí alguém me reporta um bug num projeto mais antigo que tava no Node.js 14. Eu preciso ter os dois instalados na minha máquina.</p>
<p>Pra isso existem ferramentas como o NVM pra poder ficar trocando de versão de Node. Mas e se eu precisar mexer também num projeto de Python? Daí vou precisar instalar e configurar o VirtualEnv. Mas amanhã talvez eu tenha que ajudar no front-end de um projetinho em Rails, aí preciso instalar também o RVM ou Rbenv. E assim vai. Cada linguagem tem um gerenciador de versões diferente. Em vez de ter que lidar com essa zona toda, posso instalar o asdf, que tem plugins pra dezenas de linguagens e nunca mais usar outro.</p>
<p>No Arch é fácil, basta fazer <code>yay -S asdf-vm</code>&hellip; Ele vai instalar no diretório <code>/opt/asdf-vm</code> e pra ativar precisamos fazer <code>source /opt/asdf-vm/asdf.sh</code>. Pronto, tá ativado e precisamos colocar essa linha no <code>.zshrc</code> pra toda ver que abrirmos o terminal ter o asdf carregado. A partir daqui é como já mostrei no video de ubuntu. Com <code>asdf list</code> podemos ver todas as linguagens e versões instaladas. Como ainda não instalamos nenhuma, tá vazio. Então vamos instalar o plugin de node com <code>asdf plugin add nodejs</code>.</p>
<p>Pronto, agora podemos fazer <code>asdf list-all nodejs</code> e ver que a versão mais recente hoje é a 17.4.0 então vamos fazer <code>asdf install nodejs 17.4.0</code> e boom, instalado. Só pra fazer graça, podemos instalar uma versão mais antiga também, por exemplo com <code>asdf install nodejs 16.13.2</code>. E depois que instalar rodamos <code>asdf list</code> e ele mostra que temos as duas instaladas direitinho.</p>
<p>Pra escolher uma delas configuramos uma como versão global mas o certo é configurar por projeto. Pra dar exemplo, vamos pro diretório tmp criar um diretório falso de projeto chamado de <code>teste</code>. Dentro podemos fazer <code>asdf local nodejs 16.13.2</code>. Vamos listar o que tem no diretório e achamos o <code>.tool-versions</code> que acabou de ser criado. Dando um <code>cat</code> vemos que está declarada a versão que pedimos. Toda vez que entrarmos nesse diretório o asdf vai usar essa versão específica de Node.js independente do que for a versão global. E fazendo isso em todos os projetos, sempre vai mudar pra correta que cada projeto precisa.</p>
<p>Pra complementar, vamos adicionar Ruby agora. Só adicionar o plugin com <code>asdf plugin add ruby</code>. Mesma coisa de antes, vamos listar todas as versões disponíveis de Ruby e é uma lista gigante porque no meio tem versões não oficiais como o truffleruby, rubinius, jruby mas lá em cima vemos que tem a versão de desenvolvimento do 3.2.0 que ainda não é estável então vamos fazer <code>asdf install ruby 3.1.0</code>. Ruby costuma demorar um pouco mais pra instalar, acho que baixa o código fonte e compila. Boa hora pra ir pegar um café.</p>
<p>Agora que tá instalado, se der <code>asdf list</code> mostra o Ruby também. E assim você pode ir instalando plugins de diversas outras linguagens como Rust, Kotlin, Python, Clojure e tudo mais e instalar versões específicas de cada uma. E como disse antes posso dizer que quero que essa versão 3.1 seja o global com <code>asdf global ruby 3.1.0</code>. Agora todas as ferramentas de ruby que usarmos, a partir de qualquer diretório, vai estar apontando pra essa versão.</p>
<p>Por exemplo, vamos usar o comando <code>gem</code> que vem com todo Ruby e instalar o framework Ruby on Rails fazendo <code>gem install rails</code>. No final ele vai instalar o comando <code>rails</code>, então vamos de novo pro diretório temporário do sistema e executar <code>rails new teste_rails</code> pra criar um novo projeto. Vai demorar um pouquinho pra instalar todas as dependências, mas no final podemos dar <code>cd</code> pro novo diretório. Olha só, tudo funcionando e se quisermos perguntar a versão do ruby ativo, ainda é o 3.1.0.</p>
<p>Como eu não declarei o arquivo <code>.tool-versions</code> se amanhã eu atualizar o ruby global pra 3.2, esse projeto vai pegar 3.2. Se eu quiser travar pra versão específica o certo é rodar o <code>asdf local</code> pra criar o arquivo <code>.tool-versions</code>. Estou me alongando nisso porque é comum você atualizar o sistema, vem versão nova da sua linguagem, e de repente seu projeto começa a dar problema porque você não se tocou que tá rodando uma versão diferente. Por isso é boa prática ter declarada a versão correta em todo projeto mesmo se não usar asdf.</p>
<p>Bom, agora que temos o ASDF e acesso a instalar linguagens, o último grande passo é instalar Docker. Antigamente eu preferia instalar banco de dados como postgres ou redis nativamente no sistema operacional, mas era mais por hábito mesmo. O ideal é não instalar esse tipo de serviço localmente, mesmo porque o WSL não tem um systemd pra controlar boot de serviços. Melhor usar Docker e configurar Docker Compose em todo projeto pra subir versões específicas de tudo que precisa.</p>
<p>Assim como várias coisas podem quebrar quando você pula de Node 16 pra Node 17, um banco como Postgres tem funcionalidades diferentes por versão. A versão mais nova do Postgres no momento que estou fazendo este video é a 14, mas ainda tem muito projeto rodando na versão 9. Você não pode desenvolver na versão mais nova porque pode acabar dependendo de funcionalidades que não existem na 9, daí quando subir em produção, vai dar pau. Repetindo, declare a versão correta de cada coisa no manifesto de um Docker Compose.</p>
<p>Se fosse um Arch Linux nativo fora do WSL, a instalação não seria muito mais do que um <code>yay -S docker</code>, mas no caso do WSL tem um passo extra que é baixar e instalar o Docker Desktop antes. Então vamos no site oficial, baixar o instalador e instalar&hellip; Não precisa mudar nada na instalação, vai só prosseguindo &hellip; ele vai baixar os componentes, vai configurar o WSL pra ter os grupos e permissões direitinho e no final vai pedir pra deslogar e logar de novo. Então vamos fazer isso.</p>
<p>Toda vez que se logar no Windows, o Docker Desktop vai ficar carregado aqui embaixo na barra da tarefas. Certifique-se que ele tá carregado antes de usar. Mas da primeira vez vai abrir essa janela aqui pra aceitar os termos de serviço e só depois inicia. Não tem nenhuma configuração muito importante que precisa mudar, do jeito que veio já tá bom, com exceção de uma coisa que vou mostrar já já.</p>
<p>Agora podemos abrir o terminal e fazer o <code>yay -S docker</code> pra mandar comandos pro servidor que acabamos de instalar. Mas se tentarmos rodar <code>docker ps</code> vai dizer que não conseguiu se conectar. Vamos abrir o Docker Desktop de novo e ir nas configurações. Aqui no item de Resources e WSL Integration tá marcado pra dar suporte pra minha distro default de WSL que vai ser aquele Ubuntu que instalou automaticamente primeiro. Então precisamos habilitar aqui embaixo pro Arch. Pronto.</p>
<p>Se tentar rodar o mesmo comando, vai dar outro erro mas agora é de permissão. Isso porque quando mudamos aquela configuração, por baixo dos panos ele criou o grupo de docker e adicionou meu usuário nele, mas pra termos a permissão precisamos sair e entrar de novo. Então fazemos isso e veja só, o <code>docker ps</code> agora roda sem problemas e listou que não tem nenhum container rodando. Então vamos seguir o exemplo que o Docker Desktop sugere na primeira tela. Só copie essa linha e cole no terminal.</p>
<p>Demora alguns minutos mas ele vai baixar a imagem de um site que vai carregar na porta 80. Deixa baixar e executar. Agora podemos ir no navegador e digitar <code>localhost</code> pra conectar na porta 80 e voilá, ele baixou um site com documentação pra iniciantes. Se você ainda é novo no Docker, é um bom lugar pra começar a estudar. Leia tudo que tem aqui.</p>
<p>Por último, o novo WSL2 tem um novo recurso que vai facilitar muito sua vida quando for rodar testes automatizados com coisas como Selenium ou Cypress, que abrem um navegador de verdade com o Chromium pra testar sua aplicação. Antes já tinha como rodar aplicações gráficas manualmente instalando um cliente de X no Windows como o X410 mas agora o WSL2 já tem suporte nativo.</p>
<p>Só instalar a aplicação que quiser e executar que vai abrir de boa. Infelizmente ainda não tem suporte estável pra fazer pass thru pra GPU da sua máquina então tudo vai rodar 100% via CPU e isso certamente vai ser mais lento do que o navegador nativo no Windows. Mas como é pra cenários como de testes automatizados que falei, tá mais que bom.</p>
<p>Pra instalar é normal, só ir no terminal e fazer <code>yay -S chromium</code>, vai demorar porque o pacote é grandinho, mas é só isso. Vamo lá, vamo lá, acelerar um pouco aqui, e pronto. Agora é só digitar <code>chromium</code> no terminal e olha só, abre bonitinho como qualquer aplicação gráfica. Podemos carregar o YouTube e carrega rápido. Se abrir um video toca sem problemas no meu notebook inclusive com som. Tá sem som aqui porque eu tirei na edição mas pode acreditar que tem som.</p>
<p>Tem um site que costumam usar pra fazer benchmark de navegador, o Speedometer, mas do que já usei dele sei que é bem pouco confiável. Já rodei o teste múltiplas vezes no mesmo navegador e dava resultados bem diferentes, mas só por diversão vamos rodar nesse Chromium. Isso é o cenário que falei de testes automatizados. Ele vai circular por dezenas de aplicações de todo list feitos em diversos frameworks como Angular, React, Ember e outros. Acelerando um pouco o resultado final foi 172 pontos.</p>
<p>Agora vou abrir o Microsoft Edge aqui do lado e carregar o mesmo teste. Vamos ver. Vamos acelerar um pouco aqui com um pouco de mágica de edição e boom. Olha só que bizarro, o Chromium rodando virtualizado ganhou. Mas lógico, meu Edge tá cheio de extensions, cheio de abas abertas, e o Chromium tá recém instalado, totalmente vazio. De qualquer forma, na prática, a performance dentro do WSL tá muito boa. Daria até pra usar como segundo navegador.</p>
<p>Só pra mostrar onde o Chromium via WSL chora é se tentar rodar qualquer coisa 3D nele, por exemplo, um aplicativo em WebAssembly como o Google Earth. Olha só como fica lento, absurdamente lento, é literalmente inusável. E não tinha como ser diferente porque o WSL ainda não tem integração com aceleração 3D da máquina, é tudo renderizado pelo CPU. Mas se eu abrir o Edge que perdeu no Speedometer e carregar o mesmo Google Earth, olha a diferença. Roda liso, praticamente sem perder frames. Essa é a diferença de ter aceleração via GPU. Mas de novo, se você não estiver mexendo com games ou modelagem 3D, pra sites normais, não faz tanta diferença assim.</p>
<p>As novas versões do WSL tem suporte experimental a drivers de paravirtualização de GPU da Nvidia e Amd pra rodar projetos de machine learning em containers de Docker, como Tensorflow ou PyTorch. Eu mesmo não brinquei com isso ainda, não é estável nem garantido que vai funcionar, mas se alguém aí tiver inclinação pra escovar bit pra ver se funciona, vou deixar o link nas descrições também. Mas pra maioria de nós significa que se tiver aplicações gráficas de Linux que você precisa rodar no Windows, agora tem mais uma opção também, só não precisar de aceleração 3D.</p>
<p>E já que estou falando de coisas que foram adicionadas recentemente no WSL, tem uma que gostei muito. Pra mostrar, tem duas últimas coisas que eu faço sempre que reconfiguro um novo Linux. A primeira é copiar minhas chaves privadas que ficam no diretório <code>.ssh</code>, pra ter acesso às minhas contas de Heroku, AWS, GitHub, GitLab e tudo mais. Eu expliquei sobre chaves no episódio de Ubuntu e nos de criptografia. Você precisa tomar muito cuidado pra nunca ninguém pegar essas chaves. De qualquer forma, quando configuro máquina nova, eu zipo as chaves e copio.</p>
<p>A segunda coisa é copiar minha pasta de projetos. Normalmente você não precisa ter tudo, projetos que nem mexe mais. Com as chaves no lugar, é só dar <code>git clone</code> dos projetos que precisa pra agora e tá ótimo. Mas eu quero dar um exemplo do que é possível fazer com o novo WSL. Vamos dar contexto. Lembram lá no começo do video que instalei o Arch no diretório <code>C:\arch</code>? Pois é. Vamos abrir o explorer de novo e temos um arquivo chamado <code>ext4.vhdx</code>. Esse é o &ldquo;HD virtual&rdquo; do Arch Linux que instalamos e estamos usando agora. Olhem como o Arch é levinho, com tudo que instalamos tá ocupando menos de 7 giga.</p>
<p>Esse é o melhor jeito de lidar com HDs virtuais, eles são arquivões binários. E eis porque eu fiz uns 4 videos explicando tudo que um programador deveria saber sobre dispositivos de armazenamento, particionamento, formatação e tipos de filesystems diferentes, porque agora vou assumir você entende o que é um HD virtual. Caso não saiba definir o que é uma partição ou qual a diferença de um filesystem ntfs ou ext4, recomendo que assistam os videos. Mas vamos lá.</p>
<p>Voltando pro terminal, o WSL automaticamente monta seus HDs de verdade, como o seu C:, dentro do diretório <code>/mnt</code>. Então se navegarmos pra <code>cd /mnt/c</code> e dermos um ls, vai listar exatamente o que tem no seu C:. E aí você pode ficar com a idéia errada de deixar seus diretórios de projetos no Windows e trabalhar neles de dentro do WSL. E isso seria uma péssima idéia. Isso porque esse mount que ele fez é parecido com conectar com um servidor de arquivos via rede, mais especificamente usando o protocolo P9 em vez de CIFS. Toda operação de arquivos nesse mount vai ser lenta, porque tem um overhead a mais por cima.</p>
<p>O lado oposto também dá. Do Windows acessar os arquivos dentro do Linux. Só abrir o explorer e digitar &ldquo;\wsl$&rdquo; e pronto, podemos ficar copiando arquivos do Windows pro Linux e vice versa, tanto via terminal quanto via explorer. Mas como eu disse, é como se fosse uma pasta compartilhada na rede, mesmo sendo local, ainda vai ser uma ordem de grandeza mais lento. Especialmente projetos web que tem centenas de arquivos pequenos. O melhor sempre é transferir um zip grandão via rede do que centenas de arquivos pequenos.</p>
<p>A melhor performance é dentro do HD virtual montado diretamente, aquele arquivão VHDX. Lá dentro a velocidade é quase a mesma que nativa, tem muito pouco overhead. Tanto que ficamos aqui instalando pacotes, editando arquivos e tudo mais e a sensação era que estava rodando tudo nativo. Então o mais prático é fazer git clone dos seus projetos lá dentro mesmo e nunca jogar pra fora a partir no <code>/mnt/c</code>. Mesmo se conectar um HD externo que vai montar como <code>/mnt/d</code>, é a mesma coisa, vai ter overhead.</p>
<p>Em 90% dos casos você nunca vai ter nenhum problema se ficar dentro do hd virtual. Mas se for que nem eu que vira e mexe quer mudar de distribuição Linux, mover tudo pra outra máquina ou coisas assim, se tiver muitos arquivos pra ficar movendo, vai ser super lento e demorado, pode levar horas ou mais. O ideal seria alguma coisa tipo um HD externo montado direto. Mantém tudo fora, daí se quiser reinstalar a máquina não tem problema e não demora porque tudo que não era instalação de aplicativos já tava fora.</p>
<p>E se quiser usar um HD externo, o WSL agora suporta montar direto. Vamos ver esse cenário primeiro. Eu tenho um SSD com um adaptador pra USB. Quando conecta no notebook, o Windows detecta e monta como drive D:. Normal, todo mundo já viu isso quinhentas vezes. O que a maioria de vocês não sabe é como o Windows controla isso por baixo. Vamos abrir um Powershell com privilégios de administrador primeiro, alguns comandos que vamos usar a partir de agora vai precisar.</p>
<p>Desde a época do Windows 2000 existe a ferramenta <code>wmic</code> que é o Windows Management Instrumentation Command. É uma forma de instrumentar o Windows sem precisar usar aplicativos gráficos. Quando estamos vendo o drive D: isso é um mount point, um ponto de montagem como no Linux que monta dispositivos como diretórios como no <code>/mnt/c</code>. No Linux os dispositivos de verdade ficam declarados no diretório <code>/dev</code> e seu HD poderia ser um <code>/dev/sda</code> que montamos como a raíz <code>/</code>. Ficou confuso? Eu avisei, é porque você não assistiu meus videos sobre sistemas de arquivos.</p>
<p>Enfim, no Windows tem o mesmo conceito. Os dispositivos podem existir ligados sem ter um ponto de montagem como &ldquo;D:&rdquo; ou eu posso mudar o ponto de montagem pra outra letra se eu quiser, mas o dispositivo em si tem um identificador único que foi dado quando foi conectado. Pra ver isso, no Powershell que acabamos de abrir podemos digitar <code>wmic diskdrive list brief</code> e olha só, nesse notebook temos dois dispositivos de armazenamento, o NVME Sabrent Rocket de 4 terabytes que é o C: e o Kingston conectado via USB de 480 gigas. E os nomes dos dispositivos são esses <code>\\.\PHYSICALDRIVE0</code> e 1. São os equivalente no Linux a um <code>/dev/sda</code> e <code>sdb</code>.</p>
<p>O WSL2 mais novo ganhou a habilidade de montar um HD externo e acessar direto sem ter aquele overhead de rede do protocolo P9 que falei antes, ele monta direto o filesystem. Pra isso, aqui no Powershell mesmo é só fazer <code>wsl --mount \\.\PHYSICALDRIVE1</code>. Ele avisa que o disco foi anexado na máquina virtual mas falhou em criar um ponto de montagem. Notem que quando fiz isso, o Windows desmontou o drive D:, que era só um ponto de montagem. O ideal é não ter dois sistemas operacionais diferentes mexendo no mesmo HD ao mesmo tempo direto, obviamente.</p>
<p>De dentro do WSL, por padrão ele vai montar drives externos em <code>/mnt/wsl</code>, olha só, apareceu um novo diretório chamado &ldquo;PHYSICALDRIVE1&rdquo;, mas se entrarmos nele não tem nada. O comando de mount do WSL tinha avisado que falhou e se consultarmos o <code>dmesg</code> que registra o log global do sistema operacional, tem de fato um erro do VFS que é o subsistema de file system virtual que falhou em tentar montar com filesystem ext4. E ia falhar mesmo porque esse SSD está formatado com NTFS, que o Linux não entende por padrão. Mesmo assim o dispositivo foi registrado dentro do Linux como <code>/dev/sdg</code> e se eu quiser poderia formatar usando o comando <code>mkfs.ext4</code> como qualquer outro drive.</p>
<p>Isso é legal porque posso ter um drive externo com partição formatada em ext4 e toda vez que reiniciar meu note, é só eu dar o comando <code>wsl --mount</code> que vai aparecer dentro do WSL e ter excelente performance, basicamente performance de um drive nativo, sem overhead nenhum. E eu posso compartilhar esse drive com meu Linux em casa e com outro Linux no escritório por exemplo. Super conveniente.</p>
<p>Mas eu gosto de complicar um pouco mais. Eu não quero usar um drive externo, quero usar um outro HD virtual só pra projetos, pra ficar separado do HD virtual de sistema operacional. Assim, posso compartilhar esse drive virtual com mais de um WSL na mesma máquina, que nem agora que eu já tenho um Ubuntu e um Arch Linux instalados no WSL. Ambos poderiam acessar os mesmos projetos sem duplicar nada. Como fazemos isso?</p>
<p>Pra criar um HD virtual é simples. Basta abrir o Disk Management e criar um VHD. Vou criar um arquivo chamado <code>test.vhdx</code> de 150 giga, formato VHDX que é mais moderno e com tamanho dinâmico, ou seja, quando montarmos esse disco virtual, o sistema operacional vai achar que ocupa 150 giga mas na verdade vai ter o tamanho dos arquivos que colocarmos dentro dele, então não desperdiça espaço do seu HD de verdade. Olha no Explorer o arquivo que criamos e como não tá ocupando praticamente nada de espaço porque ainda tá vazio.</p>
<p>De volta ao mesmo Powershell, o que precisamos agora é que esse arquivo seja reconhecido como um disco de verdade e pra isso precisa aparecer como um PHYSICALDRIVE no Windows primeiro, que nem quando espetamos o SSD via USB. E pra fazer isso usamos o comando <code>Mount-VHD</code> passando o caminho completo pro arquivo de disco virtual e &hellip; deu pau. Isso porque esse comando só existe se você instalou as ferramentas do Hyper-V que é a plataforma de hypervisor da Microsoft. E isso só existe se estiver usando Windows 10 ou 11 versão Pro ou versão Server.</p>
<p>Tudo que fizemos até este ponto do video funciona na versão Home do Windows. Eu sei disso porque quando reinstalei o Windows 11 do zero ele instalou como Home sei lá porque. Mas é só ir na loja do Windows e fazer o upgrade pra versão Pro. Custa um pouco caro, mas se sua profissão é ser programador, é um custo necessário. O upgrade hoje em dia é super rápido, leva alguns minutos e um reboot e já era. Se não gosta da idéia de pagar pelo Windows, é pra isso que existe Linux.</p>
<p>Estando no Windows Pro, agora eu procuro a opção de Turn On Features que é o instalador de funcionalidades opcionais do Windows e boom, ta aí a opção de Hyper-V que só tem na versão Pro. Leva mais alguns poucos minutos pra instalar, mais um reboot e pronto. Agora temos suporte às ferramentas do Hyper-V. Então podemos abrir o Powershell com privilégios de administrador de novo e repetir o mesmo comando de antes de <code>Mount-VHD</code>.</p>
<p>Desta vez foi com sucesso. A partir deste ponto, pro sistema operacional, esse disco virtual se comporta igual a um SSD de verdade. Vamos rodar aquele mesmo comando <code>wmic diskdrive list brief</code> e olha só, entrou como Microsoft Virtual Disk e se registrou como <code>\\.\PHYSICALDRIVE1</code> igual meu SSD Kingston via USB antes. E finalmente, podemos repetir o mesmo comando <code>wsl --mount</code>. Isso vai anexar o disco no WSL mas vai falhar a montagem de novo porque acabamos de criar esse disco virtual e ele tá vazio e nunca foi formatado.</p>
<p>Abrindo o terminal e olhando os logs no <code>dmesg</code>, mesmo erro de antes, não achou uma partição formatada com ext4. Mas ele tá bonitinho anexado como <code>/dev/sdg</code>. Como é um drive zerado, podemos formatar fazendo <code>sudo mkfs.ext4</code> que é o comando de &lsquo;make filesystem&rsquo;. Pronto, agora que tá formatado, podemos dar <code>cd</code> pro ponto de montagem que é <code>/mnt/wsl/PHYSICALDRIVE1</code>. Mas note que ele tá com permissão pro usuário root então não vamos conseguir criar nada aqui.</p>
<p>Só falta dar um <code>sudo chown</code> pro meu usuário nesse Linux que é &ldquo;akitaonrails&rdquo; e pronto. Agora eu posso criar um arquivo aqui dentro com o comando <code>touch</code> e sucesso! Arquivo criado. Pro Linux isso é um SSD normal, montado diretamente sem nenhum tipo de gambiarra de rede, com velocidade máxima. Tem a mesma performance do disco virtual principal onde o sistema operacional tá instalado. Você pode criar quantos discos virtuais quiser e montar dessa forma.</p>
<p>Por acaso, eu tenho meu PC de casa que uso pra editar meus videos com WSL instalado e fiz um disco virtual com todos os projetos pessoais e da empresa. Virou um arquivão de mais de 20 gigas de coisas. Transferi pro notebook e agora coloquei no mesmo diretório C:\Arch. Tem que tomar cuidado se deixar em diretórios como Documents, caso Dropbox ou OneDrive estejam configurados pra fazer backup automático. Como é um arquivão gigante, toda vez pode tentar fazer upload de tudo, o que vai ser hiper lento. Faça backup mas tome cuidado de como vai fazer.</p>
<p>E pro último truque, eu queria que esse disco virtual de projetos fosse montado e anexado automaticamente no WSL toda vez que eu bootar a máquina pra não ter que toda vez abrir o Powershell e ficar fazendo <code>Mount-VHD</code> e <code>wsl --mount</code> todos os dias. Já vimos que se quisermos que algo rode toda vez que inicio o Terminal, no Linux foi fácil, foi só adicionar os comandos no nosso script <code>.zshrc</code>, aí ele inicia automaticamente o prompt powerlevel10k, o asdf. Mas no Windows não tem o equivalente fácil assim pra scripts.</p>
<p>Vamos ter que usar o bom e velho Task Scheduler que é o agendador de tarefas do Windows, que fica no aplicativo Computer Management e só tem opção gráfica. Então, botão direito menu de Start, selecionar Computer Management e na lista tem o Task Scheduler. Botão direito nele pra Criar Nova Tarefa. Colocamos um nome descritivo como &ldquo;Auto Mount VHD&rdquo; e configuramos pra rodar independente se eu estiver logado, marcamos pra não salvar senha e pra rodar com Privilégios de Administrador.</p>
<p>Na aba de Trigger criamos um novo que é &ldquo;At Startup&rdquo; que é pra rodar logo que o Windows carregar. Na aba seguinte de Actions é onde dizemos o que vai rodar no boot. O tipo de programa vai ser PowerShell e o argumento vai ser o comando de <code>Mount-VHD</code> só que agora o PATH vai ser pra &ldquo;C:\Arch\projects-disk.vhd&rdquo; que é meu disco virtual de projetos. Coloque o nome do disco que você criou. Pronto, e na última aba de condições é tirar a opção dele rodar de novo se o notebook entrar em modo de economia de energia e acordar. Não tem que rodar de novo.</p>
<p>Agora vamos fazer exatamente a mesma coisa só que pra outro comando. O nome vai ser Auto Mount VHD in WSL. Esses nomes são arbitrários, descreva como quiser. Mesma configuração. Depois o mesmo trigger at startup, mas diferente da última vez vamos colocar a opção de &ldquo;Delay&rdquo;, ou seja, eu quero um pequeno atraso. 1 minuto pra garantir. Isso porque queremos rodar este comando só depois que o anterior tiver já rodado. O Mount VHD tem que anexar o disco virtual e só depois podemos montar no WSL. Se não for nessa ordem, não vai funcionar.</p>
<p>Agora a action vai ser de novo tipo PowerShell e o argumento vai ser o comando <code>wsl --mount</code> e vai estar hardcoded aqui que é pra montar o PHYSICALDRIVE1. Lembrando que se eu bootar a máquina com um pendrive ou algo assim pré-conectado, quando montar o disco virtual provavelmente vai cair pra PHYSICALDRIVE2 e aí esse mount no WSL vai montar o disco errado. Mas normalmente vai ser sempre PHYSICALDRIVE1. E finalmente mesma coisa, não precisa rodar de novo se acordar de sleep.</p>
<p>Feito isso, podemos bootar a máquina e quando voltar, esperamos 1 minuto e quando abrimos o Terminal podemos checar com o comando <code>lsblk</code> que lista dispositivos de bloco e lá está nosso <code>/dev/sdg</code> devidamente montado em <code>/mnt/wsl/PHYSICALDRIVE1</code> como a gente queria. Se listarmos os arquivos lá podemos ver que tem todo meu material. Mas convenhamos que digitar esse PATH enorme toda vez é um saco, mas pra isso que todo Linux suporta links simbólicos.</p>
<p>Vamos voltar pro meu diretório de casa com <code>cd</code> e vamos usar o comando <code>ln -s</code> pra mapear o link simbólico &ldquo;Projects&rdquo; apontando pro <code>/mnt/wsl/PHYSICALDRIVE1</code>. Pronto, agora podemos fazer <code>cd Projects</code> e ele entra no lugar certo. E agora sim, posso continuar dando <code>git clone</code> e <code>git pull</code> dos meus projetos pra cá e tudo vai funcionar com velocidade máxima. E tudo separado do disco virtual do sistema operacional.</p>
<p>E mais do que isso. Lembra do Ubuntu que o WSL instalou lá no começo e eu não mexi mais? Vamos abrir uma aba pra ele e vamos pro diretório <code>/mnt/wsl</code> e olha só, aqui também tá montado. Tanto do Arch quanto do Ubuntu, o comando <code>wsl --mount</code> monta em todas as máquinas virtuais e eu posso acessar de qualquer uma a qualquer momento. Obviamente não recomendo abrir o mesmo arquivo dos dois lugares ao mesmo tempo, mas isso abre diversas possibilidades diferentes. Eu não preciso ficar copiando arquivos entre os dois, posso compartilhar o mesmo drive virtual. E isso só funciona porque o Arch e o Ubuntu compartilham o mesmo Kernel do Linux e esse kernel único tem acesso ao drive e por isso aparece no container dos dois sistemas operacionais diferentes. Eles não sabem que estão compartilhando a mesma kernel.</p>
<p>E por último, eu tinha falado que faltava transferir as chaves privadas de SSH e nesse disco virtual eu tinha copiado o arquivo <code>ssh.tgz</code>. Aqui vai depender de como você compactou mas eu preciso ir pra raíz do drive e fazer <code>tar xvfz /mnt/wsl/PHYSICALDRIVE1/ssh.tgz</code> e vai descompactar no lugar certo e já com as permissões corretas. Se tivesse copiado de um pendrive formatado em FAT por exemplo, as permissões não teriam sido mantidas então precisaria fazer <code>chmod -R 600 .ssh</code> que significa permissão 6 pro meu usuário que é leitura e escrita e permissão 0 pra todos os outros usuários, que é não conseguir nem ler e nem mesmo listar os arquivos desse diretório.</p>
<p>Com isso o WSL do meu notebook está configurado e pronto pra eu poder voltar a mexer em código. Tenho o <code>yay</code> pra poder instalar qualquer programa do repositório AUR, tenho o Cargo do Rust pra instalar programas feitos em Rust, tenho o ASDF pra conseguir instalar qualquer linguagem de programação em qualquer versão e tenho o Docker pra poder rodar qualquer projeto. Além disso tenho meu prompt bonitão com o Powerlevel10K e posso editar código tanto no VSCode quanto no meu LunarVim fodão. E isso é tudo que um programador web precisa. Se eu fosse lidar com devops precisaria instalar outras ferramentas como do google cloud, kubernetes e coisas assim, mas aí é de projeto a projeto e com o que tenho configurado aqui, é só instalar com o <code>yay</code>.</p>
<p>Eu mencionei muito rápido no começo, mas uma das grandes vantagens de usar o Arch é a documentação da comunidade. Como no exemplo de instalar Docker, pra Ubuntu, eu precisei achar no site do próprio Docker e não no site do Ubuntu. Mas no caso do Arch tem um Wiki de Docker feito pela comunidade com um monte de informação e dicas muito úteis, seja pra quem é iniciante ou quem é avançado tentando resolver problemas mais complexos. Em vez de sair fuçando em fóruns ou lugares como o site stackexchange, normalmente você acha o que precisa no Wiki do Arch. Gaste tempo estudando tudo que não conhecia que mostrei nesse video a partir desse Wiki. Tenho certeza que vai aprender muito.</p>
<p>Tenho certeza também que muitos vão ficar mandando nos comentários ou mensagens diretas pra mim perguntando qual distro usar. Se tem dúvida, instale Ubuntu. Por isso eu fiz o guia definitivo de Ubuntu pra iniciantes. É a resposta padrão. De novo, se você tem dúvidas e veio perguntar é porque não tá com muita disposição de pesquisar, então é Ubuntu. Quem se importa já instalou um VirtualBox ou Virt Manager e criou máquinas virtuais pra baixar os ISOs das distribuições que tem interesse pra ver com os próprios olhos.</p>
<p>Hoje em dia é muito fácil. As ISOs você baixa de graça no site de cada distro. Daí é só bootar numa máquina virtual e usar alguns dias pra ver se gosta. Se ficou confortável, daí reserva um fim de semana, faz backup de tudo, queima a ISO num pendrive e instala como sistema operacional nativo. Não gostou? Muda pra outro. É assim que se faz. Perguntar pros outros não faz nenhuma diferença porque cada um usa pra coisas diferentes.</p>
<p>Eu pessoalmente gosto de distros baseados em Arch como o Manjaro, mas acho o Manjaro meio feinho. Prefiro a cara de um Deepin, mas acho Deepin muito pesado e não confio muito nele. Kali Linux é seguro, mas não foi feito pra usar no dia a dia, só rodaria numa máquina virtual se precisasse fuçar coisas de segurança. E assim por diante.</p>
<p>A parte ruim é instalar em notebooks super novos. Meu Zephyrus G14 comprei acho que lá por julho do ano passado, tinha acabado de lançar. Significa que o suporte de Linux pra ele ainda era muito insipiente. Eu achei alguns scripts, alguns hacks pra tentar fazer tudo funcionar, mas coisas como bluetooth não ia de jeito nenhum, perfil de economia de energia ainda não tava adequado. No final das contas não tive muita confiança, daí voltei pra Windows com WSL que todos os periféricos iam funcionar direitinho.</p>
<p>Agora que já passou 1 ano, talvez já tenha mais gente que gastou tempo ajustando e talvez agora já funcione melhor, não sei. Mas no meu caso, realmente não vejo tanta vantagem. O Windows me atende bem, tenho zero problemas com coisas como Steam, e tudo que preciso pra programar roda no WSL. Como é uma máquina parruda, com CPU e RAM sobrando, mesmo numa máquina virtual como o WSL funciona tudo zero bala. Se fosse um notebook mais antigo e menos potente, daí já justifica deixar Linux nativo, porque quanto mais antigo for o hardware, maiores as chances de drivers e coisas assim já existirem e serem estáveis.</p>
<p>Por isso que a resposta é sempre, depende. E por isso que se você é programador ou quer ser, precisa saber ir atrás da documentação e todos os componentes da sua própria máquina, pra saber quais distros são mais compatíveis, que tipos de gambiarra vai precisar fazer ou não. Este video, não tem nada que eu inventei, tudo tem na web, só saber procurar. E de novo, expliquei coisas mais básicas no meu video de Ubuntu e assistam os videos sobre máquina virtual e containers, os videos sobre sistemas de arquivos e dispositivos de armazenamento e tudo mais.</p>
<p>Se importe um pouco mais com sua própria máquina e seu ambiente de desenvolvimento. Se ficaram com outras dúvidas, mandem nos comentários abaixo. Se curtiram o video deixem um joinha, não deixem de assinar o canal e compartilhar o video com seus amigos. A gente se vê, até mais.</p>
]]></content:encoded><category>linux</category><category>ferramentas-de-desenvolvimento</category><category>microsoft</category><category>akitando</category></item><item><title>[Akitando] #60 - Entendendo WSL 2 | E uma curta história sobre Windows NT</title><link>https://akitaonrails.github.io/2019/09/04/akitando-60-entendendo-wsl-2-e-uma-curta-historia-sobre-windows-nt/</link><guid isPermaLink="true">https://akitaonrails.github.io/2019/09/04/akitando-60-entendendo-wsl-2-e-uma-curta-historia-sobre-windows-nt/</guid><pubDate>Wed, 04 Sep 2019 11:00:00 -0300</pubDate><description>&lt;div class="embed-container"&gt;
&lt;iframe
src="https://www.youtube.com/embed/28jHuWBi72w"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;(obs: este script depende muito dos demos no video em si, pode ser difícil de ler só o texto)&lt;/p&gt;
&lt;h2&gt;DESCRIPTION&lt;span class="hx:absolute hx:-mt-20" id="description"&gt;&lt;/span&gt;
&lt;a href="#description" class="subheading-anchor" aria-label="Permalink for this section"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Eu vinha prometendo esse tema já faz algum tempo e finalmente resolvi explicar esse tal de WSL ou Windows Subsystem for Linux, a solução que permite rodar programas de Linux diretamente em cima do Windows.&lt;/p&gt;
&lt;p&gt;Mas desde que eu comecei a acompanhar esse projeto em 2016 muita coisa mudou. O WSL evoluiu do então chamado &amp;ldquo;Bash on Ubuntu&amp;rdquo; para &amp;ldquo;WSL 1&amp;rdquo; e agora migrando pra &amp;ldquo;WSL 2&amp;rdquo;.&lt;/p&gt;</description><content:encoded><![CDATA[

<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/28jHuWBi72w"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>(obs: este script depende muito dos demos no video em si, pode ser difícil de ler só o texto)</p>
<h2>DESCRIPTION<span class="hx:absolute hx:-mt-20" id="description"></span>
    <a href="#description" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Eu vinha prometendo esse tema já faz algum tempo e finalmente resolvi explicar esse tal de WSL ou Windows Subsystem for Linux, a solução que permite rodar programas de Linux diretamente em cima do Windows.</p>
<p>Mas desde que eu comecei a acompanhar esse projeto em 2016 muita coisa mudou. O WSL evoluiu do então chamado &ldquo;Bash on Ubuntu&rdquo; para &ldquo;WSL 1&rdquo; e agora migrando pra &ldquo;WSL 2&rdquo;.</p>
<p>Quais as diferenças? Como funciona? Como instalo e configuro na minha máquina?</p>
<p>Além de responder essas perguntas eu achei adequado aproveitar o gancho pra contar a história do UNIX/Linux sobre o Windows e como essa história remete até o anos 80! Então vamos entender a história de como a Microsoft sempre flertou e de fato dormiu na cama do UNIX muito antes do que você pensa!</p>
<p>Se já sabe de tudo isso e só quer saber sobre o WSL especificamente, pode pular direto pro tempo 32:12.</p>
<p>Errata:</p>
<p>Eu disse que o VHD é limitado em 256GB e não havia como redimensionar, mas na verdade tem sim. Este link tem mais informações: <a href="https://docs.microsoft.com/en-us/windows/wsl/wsl2-ux-changes"target="_blank" rel="noopener">https://docs.microsoft.com/en-us/windows/wsl/wsl2-ux-changes</a></p>
<p>Eu disse que 8086/8088 eram processadores de 8-bits, mas esses já eram 16-bits! Sempre confundi isso.</p>
<p>Pré-requisitos:</p>
<ul>
<li>Playlist: Começando aos 40 (<a href="https://www.youtube.com/playlist?list=PLdsnXVqbHDUc7htGFobbZoNen3r_wm3ki"target="_blank" rel="noopener">https://www.youtube.com/playlist?list=PLdsnXVqbHDUc7htGFobbZoNen3r_wm3ki</a>)</li>
<li>Concorrência e Paralelismo Parte 1 (<a href="https://www.youtube.com/watch?v=cx1ULv4wYxM"target="_blank" rel="noopener">https://www.youtube.com/watch?v=cx1ULv4wYxM</a>)</li>
<li>Concorrência e Paralelismo Parte 2 (<a href="https://www.youtube.com/watch?v=gYJSWs-gp1g"target="_blank" rel="noopener">https://www.youtube.com/watch?v=gYJSWs-gp1g</a>)</li>
<li>Gerenciamento de Memória Parte 1 (<a href="https://www.youtube.com/watch?v=9AK_1gqEfkQ"target="_blank" rel="noopener">https://www.youtube.com/watch?v=9AK_1gqEfkQ</a>)</li>
<li>Gerenciamento de Memória Parte 2 (<a href="https://www.youtube.com/watch?v=DGU1awKrNiA"target="_blank" rel="noopener">https://www.youtube.com/watch?v=DGU1awKrNiA</a>)</li>
<li>Virtualização Parte 1 (<a href="https://www.youtube.com/watch?v=bwO8EZf0gLI"target="_blank" rel="noopener">https://www.youtube.com/watch?v=bwO8EZf0gLI</a>)</li>
<li>Virtualização Parte 2 (<a href="https://www.youtube.com/watch?v=mcwnQVAn0pw"target="_blank" rel="noopener">https://www.youtube.com/watch?v=mcwnQVAn0pw</a>)</li>
<li>Apple, GPL e compiladores (<a href="https://www.youtube.com/watch?v=suSvMnNwV-8"target="_blank" rel="noopener">https://www.youtube.com/watch?v=suSvMnNwV-8</a>)</li>
</ul>
<p>Links:</p>
<ul>
<li>
<p>Announcing WSL 2 (<a href="https://devblogs.microsoft.com/commandline/announcing-wsl-2/"target="_blank" rel="noopener">https://devblogs.microsoft.com/commandline/announcing-wsl-2/</a>)</p>
</li>
<li>
<p>Awesome-WSL (<a href="https://github.com/sirredbeard/Awesome-WSL"target="_blank" rel="noopener">https://github.com/sirredbeard/Awesome-WSL</a>)</p>
</li>
<li>
<p>Xfce4 Desktop Environment and X Server for Ubuntu on WSL 2 (<a href="https://autoize.com/xfce4-desktop-environment-and-x-server-for-ubuntu-on-wsl-2/"target="_blank" rel="noopener">https://autoize.com/xfce4-desktop-environment-and-x-server-for-ubuntu-on-wsl-2/</a>)</p>
</li>
<li>
<p>HOWTO: Enable WSL2 and Convert Existing Pengwin Installations (<a href="https://www.pengwin.dev/blog/2019/6/12/enable-wsl2-and-convert-existing-pengwin-installations"target="_blank" rel="noopener">https://www.pengwin.dev/blog/2019/6/12/enable-wsl2-and-convert-existing-pengwin-installations</a>)</p>
</li>
<li>
<p>Plan 9 rides again; WSL file access (<a href="https://nelsonslog.wordpress.com/2019/02/16/plan-9-rides-again-wsl-file-access/"target="_blank" rel="noopener">https://nelsonslog.wordpress.com/2019/02/16/plan-9-rides-again-wsl-file-access/</a>)</p>
</li>
<li>
<p>WSL Distro Launcher Reference Implementation (<a href="https://github.com/Microsoft/WSL-DistroLauncher"target="_blank" rel="noopener">https://github.com/Microsoft/WSL-DistroLauncher</a>)</p>
</li>
<li>
<p>Shipping a Linux Kernel with Windows (<a href="https://devblogs.microsoft.com/commandline/shipping-a-linux-kernel-with-windows/"target="_blank" rel="noopener">https://devblogs.microsoft.com/commandline/shipping-a-linux-kernel-with-windows/</a>)</p>
</li>
<li>
<p>Awesome Powershell (<a href="https://github.com/janikvonrotz/awesome-powershell"target="_blank" rel="noopener">https://github.com/janikvonrotz/awesome-powershell</a>)</p>
</li>
<li>
<p>WSL2-Linux-Kernel (<a href="https://github.com/microsoft/WSL2-Linux-Kernel"target="_blank" rel="noopener">https://github.com/microsoft/WSL2-Linux-Kernel</a>)</p>
</li>
<li>
<p>ArchWSL (<a href="https://github.com/yuk7/ArchWSL"target="_blank" rel="noopener">https://github.com/yuk7/ArchWSL</a>)</p>
</li>
<li>
<p>XMing (<a href="https://sourceforge.net/projects/xming/"target="_blank" rel="noopener">https://sourceforge.net/projects/xming/</a>)</p>
</li>
<li>
<p>VcXSrv (<a href="https://sourceforge.net/projects/vcxsrv/"target="_blank" rel="noopener">https://sourceforge.net/projects/vcxsrv/</a>)</p>
</li>
<li>
<p>Project Drawbridge (<a href="https://www.microsoft.com/en-us/research/project/drawbridge/"target="_blank" rel="noopener">https://www.microsoft.com/en-us/research/project/drawbridge/</a>)</p>
</li>
<li>
<p>How to install Flat-Remix Theme on Any Linux Distribution? (<a href="https://www.osradar.com/install-flat-remix-theme-ubuntu/"target="_blank" rel="noopener">https://www.osradar.com/install-flat-remix-theme-ubuntu/</a>)</p>
</li>
<li>
<p>2016 - Bash on Ubuntu on Windows (<a href="https://devblogs.microsoft.com/commandline/bash-on-ubuntu-on-windows-download-now-3/"target="_blank" rel="noopener">https://devblogs.microsoft.com/commandline/bash-on-ubuntu-on-windows-download-now-3/</a>)</p>
</li>
<li>
<p>Installing PowerShell Core on Linux (<a href="https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-6"target="_blank" rel="noopener">https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-6</a>)</p>
</li>
<li>
<p>Install .NET Core SDK on Linux Ubuntu 18.04 (<a href="https://dotnet.microsoft.com/download/linux-package-manager/ubuntu18-04/sdk-current"target="_blank" rel="noopener">https://dotnet.microsoft.com/download/linux-package-manager/ubuntu18-04/sdk-current</a>)</p>
</li>
<li>
<p>coLinux (não-suportado mais) (<a href="http://www.colinux.org"target="_blank" rel="noopener">http://www.colinux.org</a>)</p>
</li>
<li>
<p>Cygwin (<a href="https://cygwin.com/install.html"target="_blank" rel="noopener">https://cygwin.com/install.html</a>)</p>
</li>
<li>
<p>AkitaOnRails: Windows Subsystem for Linux is good, but not enough yet (<a href="https://www.akitaonrails.com/2017/09/20/windows-subsystem-for-linux-e-bom-mas-ainda-nao-suficiente"target="_blank" rel="noopener">https://www.akitaonrails.com/2017/09/20/windows-subsystem-for-linux-e-bom-mas-ainda-nao-suficiente</a>)</p>
</li>
<li>
<p>AkitaOnRails: Running Arch Linux over Windows 10! (<a href="https://www.akitaonrails.com/2018/04/29/rodando-arch-linux-sobre-o-windows-10"target="_blank" rel="noopener">https://www.akitaonrails.com/2018/04/29/rodando-arch-linux-sobre-o-windows-10</a>)</p>
</li>
</ul>
<h2>SCRIPT<span class="hx:absolute hx:-mt-20" id="script"></span>
    <a href="#script" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Olá pessoal, Fabio Akita</p>
<p>O próximo grande upgrade de Windows 10 está próximo, não sei ainda se vai ser agora já em setembro ou outubro, mas quando vier ele vai trazer a funcionalidade que todo desenvolvedor estava precisando: conseguir rodar aplicações de Linux quase nativamente em Windows 10.</p>
<p>Acho que a esta altura quase todo mundo já ouviu falar do tal WSL ou Windows Subsystem for Linux. Porém muita gente ainda não entendeu direito o que é isso. Na real é super simples. E se você é iniciante e já assistiu meus vídeos da série Começando aos 40, muito do que eu expliquei na parte de virtualização e containers vai ser usado hoje então, se ainda não assistiu, recomendo assistir antes, especialmente os que explicam sobre virtualização e containers.</p>
<p>Rodar um ambiente Unix ou Linux em cima do Windows, com suporte oficial da Microsoft, é um elo perdido que muitos de nós viemos perseguindo nas últimas décadas, eu mesmo venho acompanhando isso faz algum tempo. E pra sua surpresa essa nem é a primeira vez que a Microsoft oferece algo assim. Se você está interessado só na parte prática do WSL pode pular direto pra este tempo aqui embaixo, mas como sempre eu vou fazer uma tangente pela história, então vamos lá.</p>
<p>Essa história se inicia nos primórdios dos anos 80. Se você não sabe disso a Microsoft cresceu graças à IBM que licenciou seu MS-DOS para ser instalado nos IBM PC, fruto da amizade da mãe de Bill, Mary Gates com o CEO da IBM na época, John Opel. Todo mundo relaciona Microsoft com MS-DOS e depois Windows. Todo mundo relaciona interface gráfica com o Macintosh original ou no máximo com o Apple Lisa e a Xerox Parc. Em termos de interfaces gráficas, existiram diversas tentativas como o GEM dos Atari ST, o famoso Amiga Workbench no AmigaOS, o DeskMate do TRS-80.</p>
<p>Mas em processadores de 8-bits que, com muito esforço, dava pra mapear 64 kilobytes de RAM, desperdiçar espaço com interfaces gráficas era demais. O AmigaOS, por exemplo, precisava do processador Motorola 68000 de 16 ou 32-bits. De qualquer forma pouca gente relaciona que a Microsoft teve outros sistemas operacionais e outras interfaces gráficas muito antes do Windows.</p>
<p>Por exemplo, vocês sabiam que a Microsoft já teve um UNIX de verdade? Sim, muito antes da Apple comprar a Next e transformar o NextStep no OS X. Aliás, vale relembrar: Linux não é um UNIX, ele é mais ou menos compatível, mas na prática é um sistema operacional totalmente diferente. O UNIX original vem da Bell Labs e sua herança hoje vive nos derivados de BSD como FreeBSD ou NetBSD e no Darwin do MacOS. A maioria dos UNIX de verdade vieram desaparecendo ou diminuindo consideravelmente com o tempo como o Solaris da Sun ou o Irix da Silicon Graphics que, de curiosidade, se você assistiu Jurassic Park, já viu o Irix funcionando.</p>
<p>Em 1980 a Microsoft se uniu à SCO ou Santa Cruz Operation e eles desenvolveram o Xenix que era outro UNIX de verdade, e estamos falando mais de uma década antes do surgimento do Linux. Segundo a Microsoft era um UNIX muito próximo do UNIX original versão 7 que rodava nos minicomputadores PDP-11. Aliás, de curiosidade também, antigamente a gente chamava os mainframes de computadores, coisas como o PDP são os minicomputadores, e os Commodore, TRS-80, Sinclair, MSX, e mesmo os IBM PC eram os microcomputadores. Por isso falamos em &ldquo;micros&rdquo;.</p>
<p>Enfim, uma das idéias era evoluir o MS-DOS 2 pra se aproximar do XENIX em single-user, que iria virar o XEDOS, mas foi mais um vaporware que nunca saiu do papel. Aliás, foi daí que o termo &ldquo;vaporware&rdquo; nasceu, em 1982 por causa do XENIX. A SCO seguiu sozinha com seu SCO UNIX depois e a Microsoft desistiu da idéia e se uniu à IBM pro projeto OS/2 em 1987.</p>
<p>Esse período foi especialmente conturbado porque estamos falando da transição dos processadores de 8-bits como os antigos Z80 ou Intel 8086 e 8088 e indo pra 16-bits com o 80286, que inclusive foi onde eu ganhei meu primeiro computador, um clone de IBM PC XT em 1989. Porém o 286 era um processador complicado, pra dizer o mínimo. Estávamos migrando do modo real de execução pro modo protegido, que hoje é o padrão. Nessa transição apareceu a necessidade de emular o 8086 no modo protegido. Mas o modo protegido e emulado do 8086 nos 286 era falho. Além disso existia o problema do endereçamento segmentado de memória, diferente do modelo flat que você está acostumado hoje, onde pode endereçar toda a memória de 32 ou 64-bits.</p>
<p>Pense que em 16-bits você só consegue endereçar 64kb de RAM, pra ter acesso a mais RAM você precisa apontar pra espaços secundários, ou segmentados, de RAM. Como um índice apontando pra uma página em outro livro. Em termos simples você tinha um índice de 24-bits com endereços de 16-bits em múltiplos segmentos. No frigir dos ovos, com os problemas de hardware não seria possível rodar múltiplos ambientes paralelos de MS-DOS como deveriam. E a Microsoft obviamente não gostou muito disso.</p>
<p>Na parceria da IBM com a Microsoft eles desenvolveram o OS/2. A primeira versão era só modo texto, e a primeira interface gráfica tinha a cara do Windows 2, que saiu mais ou menos na mesma época. Porém a IBM insistiu no suporte ao 286 e esse foi um dos motivos da quebra da parceria porque o MS-DOS e o Windows tinham problemas com o 286. A Microsoft queria ir direto pro 386 de 32-bits que era muito melhor. Aliás, no caso do 286, imagine um processador que tinha máximo de 16MB de RAM. Claro, estamos falando de 1988. Os 386, em comparação, sendo de 32-bits, tinha máximo teórico de infinitos 4GB de RAM. Mas mais importante, rodava DOS em modo protegido perfeitamente.</p>
<p>Por outro lado, a IBM queria privilegiar a sua linha de hardware, claro, e eles tinham se comprometido com os 286 e sua linha de PCs PS/2 (entenderam? PS/2, OS/2 &hellip;) e por isso insistiram no OS/2 ser especializado nesse processador. Então em 1992 a IBM e a Microsoft se separaram, a IBM se manteve com o OS/2 e a Microsoft estava muito bem, obrigado, com seu Windows 3, a interface gráfica de maior sucesso da época.</p>
<p>Em paralelo a isso a Microsoft começou a criar um sistema operacional portável pra múltiplas arquiteturas de computador como processadores RISC da MIPS, PowerPC, Itanium, Intel e contratou Dave Cutler que trabalhava na VMS, que fazia o VAX/VMS mas não estava interessado em muitas de suas idéias. Daí ele foi pra Microsoft e caiu no projeto NT onde ele pôde aplicar muitas dessas idéias. Aliás, o nome Windows NT tem alguma controvérsia no seu significado, muitos talvez ainda pensem em NT como sendo New Technology.</p>
<p>O Dave Cutler vai dizer que WNT seria uma brincadeira em cima do nome da VMS de onde ele veio. Assim como muita gente gosta de brincar que IBM é uma brincadeira em cima do nome HAL, a inteligência artificial do filme 2001 do Stanley Kubrick. Se você pegar HAL e dar shift de uma letra pra frente, o H vira i, o a vira b e o l vira m. Mesma coisa com VMS se você der shift uma letra pra frente o v vira w o M vira N e o S vira T e daí WNT ou Windows NT. Tem outras teorias mas eu pessoalmente gosto mais dessa. Hoje em dia na real não significa nada, só um nome mesmo.</p>
<p>Com o objetivo de ser portável o Windows NT implementa uma camada de abstração do hardware, chamado convenientemente de HAL também, ou Hardware Abstration Layer. Vocês veem que nós de programação não somos exatamente muito criativos com nomenclatura das coisas. Além disso o NT começou tentando implementar um micro-kernel, inspirado nas idéias da kernel Mach de Carnegie Mellon. Hoje em dia nós usamos kernels monolíticos ou kernels híbridos. A idéia de um microkernel é ser um kernel o mais minimalista, leve e estável possível rodando no modo de supervisão ou Ring-0 que é o anel de maior privilégio. Eu expliquei isso em outro vídeo. Daí todos os serviços que compõe o sistema rodam em user mode ou Ring-3. O problema disso é que você acaba com um overhead muito grande de IPC ou interprocess communication pois os programas rodando no anel de menor privilégio precisam ficar constantemente se comunicando com o kernel que roda no anel de maior privilégio.</p>
<p>Essa controvérsia de micro-kernels versus kernels monolíticos ou macro-kernels foi tema de grande discussão na comunidade Linux no começo, inclusive é um episódio histórico a discussão de Linus Torvalds defendendo o design monolítico da kernel do Linux contra a visão acadêmica de micro-kernels do professor Andrew Tanenbaum, autor de um dos livros sobre sistemas operacionais mais famosos e que você provavelmente teve que estudar se cursou ciências da computação. Na prática, apesar do design de micro-kernels ser o mais elegante, macro-kernels funcionam melhor como o sucesso do Linux já comprovou.</p>
<p>No caso do NT, por exemplo, subsistemas de drivers de I/O, como video ou mesmo impressão rodavam tudo em Ring-3, em user-mode, como deveriam. Mas no Windows NT 4 eles foram movidos pro Ring-0, dentro do espaço do kernel. Eu costumo dizer que o Windows NT mais estável e robusto era o Windows NT 3.5 justamente porque ele tinha o menor kernel, mas pro hardware da época acho que não tinha muita alternativa. No Windows 2000 ou XP se não me engano eles moveram uma parte do IIS na versão 6.0, pro Ring-0 na forma do driver HTTP.sys. Isso substituiu o Winsock que rodava em user-mode, e eu acho que isso foi um erro. Imagine parte do seu servidor web embutido na kernel incluindo coisas como cache e fila de requests. De qualquer forma isso garantiu melhor performance pro IIS se comparado ao Apache que rodava exclusivamente em user mode, mas ao custo de bugs na stack de HTTP potencialmente causarem problemas no nível do kernel, que poderia levar desde um crash do sistema até a buracos sérios de segurança.</p>
<p>A equipe do Windows NT era formada por muita gente da DEC ou Digital Equipment Corporation, liderada pelo Cutler, e uma das tais idéias que ele trouxe da VMS foi a noção de um sistema operacional orientado a objetos e por isso na arquitetura do NT você tem um Object Manager na camada privilegiada do Windows Executive, abstraindo todos os recursos do sistema na forma de objetos lógicos. Além deles alguns membros da equipe vieram do time do OS/2 que também queria integrar noções de orientação a objetos. Uma das coisas que eu achava fascinante na interface do OS/2, o Workplace Shell, é que tudo eram objetos. Infelizmente isso não foi implementado no Windows. Mas por exemplo, em vez de abrir um programa e clicar no menu em Novo Arquivo, você abria uma pasta de templates e arrastava o template pro desktop pra criar um novo arquivo, como uma instância de uma classe. A idéia de orientação a objetos foi embutido em todos os sistemas operacionais dos anos 90 e por isso coisas como a API de um NextStep sendo orientados a objetos, e você tem abstrações e encapsulamento de comportamento criando coisas como o Hardware Abstration Layer do NT.</p>
<p>Pra todos os efeitos e propósitos, do fim dos anos 80 pro início dos anos 90 eu diria que os sistemas operacionais desktop mais avançados eram o OS/2, o AmigaOS, o NextStep e o Solaris. Eles inspiraram diversos outros como o BeOS ou o Irix. Mas os mais populares eram sem dúvida o MS-DOS, o Windows 3.1 e o System 7. O Windows NT apareceu pela primeira vez em 1993 com o nome de Windows NT 3.1 pra ser paralelo ao nome Windows 3.1 que era completamente diferente e ainda rodava por cima do DOS. De comum eles tinham basicamente a mesma interface gráfica.</p>
<p>Daí em 1995 tudo mudou com o advento do Windows 95, trazendo a era de 32-bits pros desktops populares. Comparado com hoje em dia, eu lembro como a gente achava o Windows 95 pesado, precisando de 4MB de RAM sendo que o Windows 3.1 rodava tranquilamente com 2MB de RAM. No ano seguinte saiu o Windows NT 4.0 com a interface mais parecida com do Windows 95. Os NT, pela natureza da sua arquitetura mais robusta também precisava de mais recursos pra rodar, eu acho que com menos de 8MB ou 16MB de RAM não dava pra rodar decentemente, e por isso eles eram mais usados em servidores.</p>
<p>Nos anos 90 fomos evoluindo do Windows 95 pro 98 até o famigerado Windows ME ou Millenium Edition. E no lado do NT que era mais voltado a servidor fomos do NT 4 pro 2000. Passamos os anos 90 surfando na Lei de Moore e processadores mais rápidos iam saindo o tempo todo, do 486 pros Pentium pro Pentium II, Pentium III, no servidor tínhamos os Itanium. RAM foi ficando mais barato. A grande virada veio em 2001 com a unificação dos Windows no famigerado XP e finalmente nos livramos do legado do MS-DOS por baixo do Windows. Desde então sempre tivemos uma versão de NT pra desktop e outro pra servidor.</p>
<p>Então na era do XP tivemos o Windows Server 2003 e 2003 R2. Com o Windows Vista sucedendo o XP tivemos o Windows Server 2008. Depois o Windows 7 e o Windows 2008 R2. Depois disso o Windows 8 e o Windows Server 2012 e 2012 R2 e na geração do Windows 10 a partir de 2015, que teoricamente vai ter só upgrades sem mudar o nome, tivemos o Windows Server 2016 e Server 2019. O Windows 10 hoje está na oitava edição estável build 1903 de maio de 2019. Essas edições costumam sair entre abril e maio e depois outubro, por isso eu acho que a próxima edição importante vai sair em outubro de 2019.</p>
<p>Eu falei que o NT desde o começo veio com a mentalidade de ser portável, ele não rodava só em Intel. Mas aos poucos o suporte de hardware foi diminuindo à medida que essas arquiteturas foram caindo em desuso. Por exemplo, no Windows 2000 caiu o suporte a MIPS, Alpha e PowerPC. Mas além do lado hardware o NT implementou a idéia de &ldquo;personalidades&rdquo; ou subsistemas. Você tinha a Win32 que é o suporte a API moderna do Windows. Hoje em dia programas 32-bits rodam emulado sobre o WoW64 ou Windows 32 on Windows 64. Mas desde o começo ele foi lançado com suporte a subsistemas como OS/2 que permitia um grau de compatibilidade com a API do OS/2, já que a Microsoft tinha interesse no nicho que eles ajudaram a criar com a IBM.</p>
<p>Claro que eles precisavam manter compatibilidade com o MS-DOS e pra isso eles já embutiam uma virtual machine pra DOS. Sim, um tipo de máquina virtual. E pra conseguir atender contratos de governo que requeriam UNIX eles também tinham um subsistema compatível com POSIX, que como eu já expliquei em outro episódio, é a superfície de compatibilidade com os UNIX da época.</p>
<p>Ou seja, seria possível pegar o código fonte de aplicativos feitos pra UNIX e teoricamente compilar num Windows NT e rodar nativamente! Ele era compatível com o padrão POSIX.1 por isso não tinha um shell ou ambiente de uso e comandos de usuários, coisas como um mísero &rsquo;ls&rsquo;, que só passaria a existir como padrão no POSIX.2. Por isso pra usuários normais de Linux como nós, esse ambiente é basicamente inútil. Só serve se você tinha código fonte em C compatível com POSIX.1 e precisava de um compilador C compatível.</p>
<p>Com a evolução rápida das distros Linux nos anos 90 e igualmente rápido desuso dos UNIX, esse subsistema no Windows era meio inútil. Nesse vácuo, projetos open source como o Cygwin apareceram. Cygwin se chama assim porque foi criado pela empresa Cygnus Solutions que depois foi adquirida pela RedHat. Era um ambiente em user-mode compatível com POSIX e com Linux em particular. E diferente do subsistema POSIX original da Microsoft, eles portaram boa parte do toolchain do GNU no pacote, trazendo shells como bash e além das ferramentas pro compilador, também trouxe diversas outras coisas úteis como awk, sed, tar, ssh, servidores como Apache, Postgres, linguagens como Perl, Python, Ruby, Prolog e muito mais.</p>
<p>Era como uma distro baseada em Linux rodando sobre uma camada que tentava abstrair o NT por baixo na forma de DLLs. Muita gente ainda usa Cygwin até hoje e sempre foi a melhor ou mesmo a única forma de rodar muitas ferramentas de Linux de forma nativa no Windows. Mas Cygwin não se encaixa na categoria de distro de Linux porque ele tem uma semi compatibilidade em nível de código fonte, mas os binários de Linux não rodam no Cygwin nativamente, precisa recompilar sempre.</p>
<p>Com o passar dos anos o subsistema POSIX original foi removido no Windows XP e Windows Server 2003 sendo substituído por outro subsistema que foi originalmente desenvolvido por uma empresa chamada Interix, adquirida pela Microsoft, e sua solução foi renomeada como Windows Services for UNIX ou SFU e você podia instalar opcionalmente. O suporte ao SFU veio gradativamente diminuindo, tendo muitos de seus componentes removidos do instalador até o Windows 8 e Windows Server 2012. Mas pra todos os efeitos e propósitos ele é muito similar ao Cygwin só que o Cygwin é compatível com GNU/Linux e o SFU é compatível com UNIX. Novamente, se você tinha código fonte de UNIX podia compilar no SFU e rodar no Windows.</p>
<p>Em 2004 surgiu a primeira forma de rodar Linux sobre o Windows de verdade, sem virtualização. Foi o Cooperative Linux ou coLinux. Infelizmente a última versão estável dele é de 2011 então não espere que ele funcione hoje em dia. Mas em vez de ser um subsistema ou uma máquina virtual, ele era uma kernel linux modificada que era carregado no Ring-0 do lado do kernel do NT. E ele compartilhava os recursos da máquina com o kernel NT, por isso cooperativo. Isso era possível através de um driver, e drivers rodam em Ring-0 junto com ferramentas como um Windows Service pra dar acesso. Daí em user-land você podia rodar os binários originais de uma distro como Ubuntu ou Arch. Dava pra acessar o terminal via SSH ou mesmo a interface gráfica do X via um VNC. Pra todos os efeitos era quase como rodar um Virtualbox mas sem o overhead de virtualização. Eu imagino que manter suporte de algo assim deve ser bem complicado porque você meio que está lobotomizando o kernel do NT por um hack via um driver.</p>
<p>Como podem ver, rodar Linux ou UNIX sobre o Windows é uma coisa que muita gente já tentou fazer de diversas formas. Com hardware moderno, a opção mais estável é abrir um Virtualbox ou VMWare e rodar virtualizado. Graças à evolução do suporte de virtualização dos processadores, na minha experiência não só é viável mas serve muito bem como máquina principal de desenvolvimento. E quando eu digo hardware moderno estou falando no mínimo de um Core i5 de 4 cores com no mínimo 8GB de RAM, preferencialmente 16GB. O problema de virtualização normal é que normalmente você precisa pré-reservar quantos cores e quanto de RAM vai ser dedicado pra máquina virtual.</p>
<p>Vejam o problema. Com soluções como o subsistema POSIX, o Cygwin ou o SFU tudo roda nativo, não é virtualização. Mas pra funcionar você precisa ter o código fonte de tudo, talvez modificar alguma coisa, compilar e gerar um binário nativo de Windows NT. Se conseguir fazer isso o binário vai rodar como qualquer outro binário de Windows. Por outro lado, é muito difícil conseguir compatibilidade com tudo e muita coisa simplesmente não vai nem compilar sem modificações significativas. Pelo simples fato que as primitivas do kernel do NT são diferentes do kernel do Linux. Já expliquei em detalhes em outros vídeos como o Windows, o Mac e o Linux gerenciam coisas como estrutura de processos, scheduler de threads, memória, I/O de formas diferentes.</p>
<p>Por exemplo, num SFU não adianta eu compilar alguma coisa como o programa &lsquo;ip&rsquo; ou o antigo &lsquo;ifconfig&rsquo;, eles vão tentar mexer em coisas como o /etc/network/interfaces que o Windows NT não usa pra expor suas interfaces de rede. Isso sem contar que coisas como &lsquo;fork&rsquo; funcionam diferente no Windows, como já expliquei no vídeo de gerenciamento de memória. Não adianta eu compilar um programa que gerencia processos via o diretório /proc porque o Windows não expõe os metadados dos processos lá. O sistema de autenticação e permissão são completamente diferentes, então nenhum programa que gerencia usuários e permissões como &lsquo;useradd&rsquo; ou &lsquo;chown&rsquo; vai conseguir modificar nada no Windows. Essas diferenças tornam complicado rodar programas de UNIX ou Linux lado a lado de programas Windows porque existe uma dissociação semântica enorme.</p>
<p>Por outro lado, rodar dentro de uma virtual machine traz a vantagem de isolar completamente os comportamentos de Linux e Windows. De dentro da máquina virtual tudo funciona perfeitamente como se fosse uma máquina de verdade isolada. Daí você controla coisas do host Windows via ferramentas de Windows e coisas de Linux separadamente com coisas de Linux e cada um vive feliz separado.</p>
<p>Vamos ver o caso do macOS rapidamente. Como ele foi construído sobre uma fundação UNIX, todo o sistema operacional obedece às leis do UNIX. Todo programa de Mac é de fato um processo UNIX e pode ser controlado com coisas que todo mundo de Linux conhece. Se eu usar o comando <code>ps</code> no terminal, vai listar processos como o Chrome ou Final Cut. Se eu usar o comando <code>kill</code> no terminal, vai matar de fato os programas todos. Se eu usar comandos como <code>ip</code> eu de fato gerencio as interfaces de rede da máquina, e assim por diante. A API do Mac é construído sobre as APIs do UNIX por baixo. Então a integração é praticamente 100%. Um serviço de UNIX é um serviço de Mac e assim coisas como servidor de SSH ou Postgres rodam lado a lado de serviços do Mac. Usuário de Mac são usuários do UNIX. Permissões de arquivos feitos via o Finder ou feitos via Terminal com comandos como &lsquo;chown&rsquo; ou &lsquo;chmod&rsquo; são a mesma coisa. Por isso existe coerência semântica entre os aplicativos gráficos e os de linha de comando. E a Apple trouxe muito do toolchain GNU pra dentro, então o MacOS é como se fosse um FreeBSD mais bonito, na prática.</p>
<p>Por outro lado, assim como no subsistema POSIX, Cygwin ou SFU no Windows, o macOS tem compatibilidade de código-fonte mas não de binário. Binários formato ELF de Linux não são compatíveis com binários de BSD ou macOS ou Cygwin ou SFU. Por isso no Mac você precisa compilar programas de Linux especificamente pra rodar no Mac e por isso a gente não pode usar pacotes pré-compilados que já existem em distros como Ubuntu ou Arch. Por outro lado, ao contrário de Cygwin ou SFU, o comportamento do macOS, que é parecido com o comportamento do BSD e tem a mesma semântica do Linux, garante que quase todo o código-fonte seja compatível porque coisas como interfaces de I/O, gerenciamento de memória e de threads é significativamente parecido.</p>
<p>Então existe algum trabalho que precisa ser feito no código-fonte de alguns programas, mas no geral, basta recompilar no Mac e tudo magicamente funciona. O mesmo não pode ser dito em ambientes como o antigo subsistema POSIX ou SFU ou Cygwin. E mesmo quando compilam, eles não tem acesso ao resto do sistema Windows.</p>
<p>A grande reclamação do povo de Linux quanto a gerenciar os recursos de um Windows é que tudo precisa ser feito via ambiente gráfico. Por isso gerenciar um servidor remoto sempre exigiu coisas como um Remote Desktop ou VNC pra podermos ter a tela gráfica remotamente. É um puta pé no saco quando em servidores Linux podemos conectar via terminal com um cliente de SSH e gerenciar todos os recursos da máquina via linha de comando. Pra resolver parte disso a Microsoft criou o Powershell.</p>
<p>Em resumo, a história remete ao fim dos anos 90 de novo, quando a Microsoft iniciou o projeto .NET. Com o tempo boa parte, se não toda a API do Windows, foi mapeada em classes dos frameworks disponíveis no .NET, além de componentes COM e WMI. Porém o antigo programa de linha de comando do Windows, o Command, que herda as características do antigo MS-DOS, é um lixo. As linguagens de script que ele traz como o BATCH ou REXX, oriundo da antiga herança do OS/2, são muito fracos e quase nada do sistema operacional é exposto pra linha de comando, você é obrigado a programar coisas como scripts em visual basic pra acessar o WMI ou componentes COM que tem algum acesso a algumas coisas do sistema como gerenciar usuários. Esquece fazer scripts complicados como os que fazemos em Bash pra Linux.</p>
<p>Porém, uma idéia interessante é um console de linha de comando com acesso ao framework do .NET. E é basicamente isso que é o Powershell. Ele trás uma linguagem de script mais poderoso e com muitas coisas que encontramos num Bash. Ele tem inclusive um pipe! E eu argumentaria que um pipe superior ao do Linux. No Linux todo script ou comando aceita argumentos e um stream de bytes que chamamos de standard input e tem uma saída de bytes na forma do standard output, que eu também já expliquei nos vídeos sobre concorrência e paralelismo. E por isso você precisa de comandos como awk ou sed ou grep pra tratar o texto que os scripts devolvem. No caso do Powershell os comandos devolvem estruturas de .NET, ou seja, são dados estruturados.</p>
<p>O episódio nem é de Powershell mas obviamente agora eu empolguei. Eu também acho interessante que muita gente que usa Linux nunca viu Powershell. Pense num script de Bash pra selecionar processos que estão usando mais que 100MB de RAM, como você faria. Num bash provavelmente algo parecido com este script aqui:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>ps -eo rss=,pid=,user=,comm= k -rss |
  while read size pid user comm
  do
    if [ &#34;$size&#34; -gt 102400 ]
    then
      echo &#34;$pid $size $user $comm&#34;
    else
      break
    fi
  done</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Ou seja, precisamos ir linha a linha da saída do comando <code>ps</code> e checar o tamanho em kilobytes até achar o que queremos. Em Powershell podemos fazer assim:</p>
<p><code>Get-Process | Where-Object WorkingSet -gt 104857600</code></p>
<p>E como o Powershell suporta aliases e ele já vem com muitos aliases pré-programados, a mesma linha poderia ser escrita assim:</p>
<p><code>ps | ? WorkingSet -gt 104857600</code></p>
<p>Do ponto de vista de usabilidade pra novatos, a sintaxe do Powershell é muito mais fácil de ler. E pra veteranos de shell existem formas de simplificar pra comandos mais familiares. E veja como estamos usando o pipe pra passar os objetos do ps pro where-object fazer um filtro na propriedade do objeto. E isso é universal pra todos os comandos.</p>
<p>Tecnicamente eu diria que o Powershell pode ser considerado superior em muitos aspectos a Bash ou outros shells de Linux. Eu acho que não é 100% do Windows que pode ser controlado via Powershell mas uma parte considerável pode, e ele pode ser estendido via .NET, então seja via C# ou F# você pode expor o que quiser pra esse shell. E mesmo se você for de Linux pode usar Powershell, porque a Microsoft abriu não só o .NET na forma do .NET Core como open source como também o Powershell na forma do Powershell Core. Aqui o problema é o inverso, ainda não sei quanto do Powershell se integra aos recursos do Linux mas ele pode ser uma opção interessante pra fazer scripts de automação numa linguagem menos cheia de truques se comparado a um Bash, especialmente se estiver rodando coisas como SQL Server pra Linux e outros programas .NET. Ele é particularmente bom pra lidar com dados estruturados como JSON.</p>
<p>Essa tangente pro Powershell foi primeiro pra introduzir vocês ao tema, mas segundo pra dizer que apesar dele ser muito bem feito e eu pessoalmente achar elegante e um passo grande pra Microsoft, ele ainda não resolve o problema de quem quer usar o Bash de verdade e está acostumado com o ferramental GNU. Mesmo o Powershell sendo bacana, a gente ainda quer usar ferramentas antiquadas mas funcionais como awk, sed, grep e tudo mais. A única saída nesses casos é instalar Cygwin ou rodar num Virtualbox já que o subsistema POSIX já morreu, o SFU já morreu, e o coLinux não tem suporte desde 2011.</p>
<p>Até aqui eu expliquei como era possível rodar alguma coisa de UNIX ou Linux no Windows mas e o oposto? Ou seja, rodar programas de Windows no Linux? Se você já brincou de Linux por algum tempo já deve ter ouvido falar ou mesmo usado o projeto Wine ou Wine is not an Emulador que é um acrônimo recursivo, coisa de programador, como eu já disse a gente é ruim de nomenclatura. O Wine é um projeto capaz de carregar um binário feito pra Windows, sem precisar recompilar, e executar no Linux. Pra fazer isso ele mapeia as chamadas de API pra Kernel do NT em chamadas pra kernel do Linux e faz engenharia reversa de dezenas de DLLs que compõe o Windows e com isso ele consegue executar muitos aplicativos de Windows rodando com performance quase nativa em ambiente Linux. Claro, engenharia reversa significa que 100% de compatibilidade é extremamente difícil. Muitos aplicativos abrem e rodam bem, mas algumas partes deles podem precisar de APIs que não foram reimplementados ainda e crashear ou simplesmente não funcionar.</p>
<p>Lembram como no video sobre Ubuntu eu falo como não dava pra rodar todos os games do Windows no Linux? Muitos me lembraram depois que a Steam tem o projeto Proton que permite rodar muitos jogos, mas não todos. Você precisa consultar o site da comunidade, o ProtonDB pra ver se seu jogo roda. Na realidade o Proton usa Wine por baixo. Ele é mais um de uma família de aplicativos que usam Wine e tentam facilitar a instalação de dependências pra programas específicos, como o antigo CrossOver. Por isso o Proton consegue rodar jogos que originalmente foram feitos pra Windows, mas em Linux. O Wine é como se um fosse uma camada de Windows dentro do Linux.</p>
<p>O maior problema é que como os binários do Windows não são código aberto, é preciso fazer engenharia reversa dos binários e reimplementar do zero no Linux. É um processo black-box de desenvolvimento, ou mais corretamente, um grande cornojob de tentar executar o binário do Windows, ver ele crasheando, ver que chamada de sistema ele tentou fazer que ainda não existe e implementar essa função no Linux. Função a função. Wine existe já faz muitos anos e com o tempo ele evoluiu bastante, mas o Windows não parou no tempo também, então cada vez que sai uma versão nova, o Wine ganha mais trabalho pra suportar as coisas novas. É um trabalho insano que me deixa fascinado pelo fato de até hoje ainda existir.</p>
<p>Muito bem, vamos resumir agora. Vocês lembram o que eu já expliquei em outros vídeos. Um sistema operacional é composto de pelo menos duas partes principais, o kernel e drivers e outros subsistemas que rodam no Ring-0 de maior privilégio do sistema. E a outra parte são outros subsistemas e aplicativos que rodam em user-land ou Ring-3 de menor privilégio. Pra rodar os programas de outro sistema operacional você precisa ter as dependências, talvez fazer algumas modificações no código-fonte, recompilar o programa. É o processo que chamamos de &ldquo;portar&rdquo;. É pra isso que serviam ambientes como o subsistema POSIX, o SFU e o Cygwin. É como funciona no macOS hoje ou mesmo nos BSDs. Compatibilidade de nível de código-fonte. Quer rodar programas de Linux fora do Linux, precisa recompilar em todos esses ambientes: Windows, macOS ou outros UNIX.</p>
<p>Pra rodar um binário de outro sistema operacional, sem recompilar, você precisa ter o kernel e dependências rodando lado a lado do seu sistema principal e um mecanismo pra carregar os binários não modificados. O coLinux conseguiu executar a kernel do Linux cooperativamente, compartilhando os recursos da máquina, do lado da kernel do NT, ele conseguia montar um filesystem de Linux e executar os programas de Linux em user-land sem precisar recompilar nada. Você podia rodar os binários de um Ubuntu ou Arch por cima desse ambiente.</p>
<p>Fora isso você tem a opção de virtualização, seja com VirtualBox, VMWare ou Hyper-V, daí você roda tudo em user-land mas com as instruções da VT-X da Intel que permite o kernel virtualizado conseguir acessar o hardware por baixo com menor overhead possível. Você perde 20% ou mais de performance virtualizando, dependendo da configuração do seu hardware, mas no geral tudo funciona perfeitamente. Virtualização é uma opção quase plug-and-play hoje em dia.</p>
<p>Eis que do nada a Microsoft anunciou o projeto Windows Subsystem for Linux ou WSL 1 como podemos chamar hoje. Ele começou a aparecer no Fast Ring do Windows Insider lá pelo Anniversary Edition acho que pelo começo de 2016, e foi lançado de verdade no Creators Update uns 3 meses depois. Hoje em dia temos o WSL 2 que é completamente diferente e já vou explicar porque. Mas o WSL 1 do ponto de vista técnico é muito mais interessante, mas eu entendo porque eles desistiram dessa forma.</p>
<p>Antes de mais nada, a Microsoft faz muita pesquisa, e eventualmente muitos dos resultados dessas pesquisas realmente acabam no Windows de verdade. Um desses projetos foi o Drawbridge que estava pesquisando formas de rodar processos isolados, como em containers, sem precisar de virtualização. Um dos resultados foi permitir o kernel de criar processos com o mínimo ou zero de interferências. Lembram nos episódios de gerenciamento de memória que eu expliquei que dentro do espaço de endereços virtuais do processo o Windows mapeia suas DLLs de sistema e outras coisas pra compartilhar seus recursos com os processos e por isso um processo de 32-bits no Windows de 32-bits nunca tinha os 4GB totais disponíveis pra ele? O resultado desse projeto Drawbridge foi permitir o kernel NT de criar o que eles chamaram de Minimal Process e Pico Process que são processos sem interferência do OS, com o espaço de memória limpo. A diferença de um processo Minimal e Pico é que no caso do Pico existe um driver associado a ele que permite a comunicação desse processo pra fazer syscalls.</p>
<p>Isso existe desde 2013 e o time do WSL resolveu usar esse recurso pra carregar o binário não-modificado de um programa Linux que tem o formato ELF64 pra dentro de um Pico process. Agora pra executar, esse programa vai querer fazer coisas como syscalls pra kernel do Linux. E aí entra a parte do driver. Esse driver vai converter as chamadas pra kernel do Linux em chamadas pra kernel do NT. Então na prática não existe um kernel de Linux rodando. Quando o programa de Linux chamar um fork ele vai ser traduzido pro equivalente NtCreateProcess, ou se chamar fopen ele vai ser traduzido pro NtOpenFile e assim por diante. Na realidade a tradução acontece no nível do assembly, mas a idéia é a mesma.</p>
<p>Como já expliquei, o Windows trata todos os recursos do sistema como objetos, incluindo arquivos e o file system, tudo é roteado pelo Object Manager. E ele sempre teve essa idéia do HAL de abstrair o hardware. E de fato, por cima do NTFS temos o VFS ou Virtual File System. Se vocês já usaram Windows e Linux sabem que existem diferenças em como o filesystem NTFS do Windows e o EXT4 do Linux se comportam. Por exemplo, no Windows não tem como deletar um arquivo que está em uso por algum programa, no Linux podemos renomear ou deletar o arquivo mesmo que ele esteja em uso. São comportamentos diferentes e não defeitos na operação, prova disso é que o WSL 1 replica o comportamento de um EXT4 por cima do NTFS removendo algumas validações e checagens que no NTFS são ligadas por padrão. Inclusive o WSL consegue replicar o comportamento do ProcFS e SysFS pra expor partes do sistema operacional como arquivos, como no diretório /proc que lista processos do sistema como expliquei no episódio de Ubuntu.</p>
<p>Então esse novo subsistema que seria o herdeiro do antigo subsistema POSIX e do SFU emula o comportamento da kernel do Linux, sem de fato ter o kernel do Linux e sim traduzir tudo pro kernel NT, com a vantagem de carregar binários não modificados. Como eu já expliquei antes, tirando a kernel o que muda de uma distro pra outra são os binários de user-land. E como o WSL consegue carregar os programas de Linux diretamente nos processos Pico, sem precisar modificar ou recompilar esses binários, você pode literalmente pegar todos os binários de um Ubuntu ou Arch ou Fedora e rodar em cima desse subsistema.</p>
<p>Uma grande vantagem dessa forma é que ao abrir um Bash e usar comandos como ps ou kill podemos não só manipular programas Linux como programas Windows também. Muitos comandos que num Cygwin seriam inúteis como programas pra configurar interfaces de rede e muito mais passam a funcionar minimamente. Programas que manipulam arquivos podem manipular alguns arquivos do lado Windows também. Foi a primeira vez que programas Linux não modificados puderam rodar lado a lado de programas Windows. Era bizarro porque eu podia abrir o Task Manager do lado do Windows e ver cada programa de Linux individualmente listado. A integração era muito bem feita embora ainda incompleta.</p>
<p>Eu rodei esse ambiente por algum tempo, e apesar de não ser tudo que funcionava, era possível rodar tudo que eu precisava pra desenvolver projetos de Ruby on Rails ou Node.js incluindo bancos de dados como Postgres ou Redis e carregar servidores que corretamente faziam binds nas portas nativas do Windows, e conseguir testar do Chrome do Windows. Seria esse o ambiente perfeito?</p>
<p>Infelizmente havia ainda vários problemas. O maior ofensor eu diria que era a virtualização do file system. Essa virtualização em cima do VFS funciona, mas o VFS é interligado com o Windows Defender e outros antivírus e antimalware. Toda operação de disco no Windows dá trigger pro Defender avaliar se não tem perigo ler o arquivo. Obviamente isso adiciona um overhead gigantesco. Some a isso operações altamente custosas de I/O como um <code>npm install</code> em um projeto de Node e você pode ir tomar um café enquanto espera ele terminar. Isso poderia ser resolvido se a equipe do WSL mudasse a estratégia de tentar manter o file system aberto em cima do NTFS e simplesmente montasse um disco virtual dentro de um arquivão como no formato VHD que Virtualbox ou VMWare usam. Máquinas virtuais costumam montar o filesystem do sistema Guest na forma de arquivos esparsos, ou seja, digamos que você configure um HD de 1 TB dentro do Linux virtualizado mas seu HD de verdade só tem 500GB. Claro que não cabe, mas você não precisa pré-alocar esse espaço, pode só mentir pro sistema virtualizado e só alocar o que ele realmente for usar e ir adicionando novos blocos nesse disco virtual sob demanda.</p>
<p>Mas o problema principal não é esse. O conceito original é mapear syscalls do Linux pra syscalls do kernel NT. Eles esbarraram no mesmo problema que a equipe do Wine tem até hoje: toda vez que sai uma atualização pro Windows, alguma coisa vai quebrar no Wine porque as syscalls e outras dependências mudaram. Então manter essa camada de compatibilidade entre as duas kernels vai ser sempre instável. Toda vez que sai uma versão nova da kernel do Linux, alguém na equipe do WSL vai precisar ajustar essa camada de tradução. Então nunca vai ser possível ter um sistema totalmente estável porque essa é a natureza de wrappers e adapters, eles são alvos móveis.</p>
<p>Ficar fazendo isso desde 2016 demonstrou que como prova de conceito, de fato tudo funciona, mas muitas syscalls de Linux não tem equivalente em NT e davam trabalho de manter. E toda vez que a kernel atualizava tanto do lado Linux quanto do lado NT, precisava ajustar a camada de adaptação. É uma bola de neve sem fim. Por fim eles decidiram mudar a estratégia toda e recomeçar do zero.</p>
<p>É uma pena, porque como eu disse, eu gostava muito dessa estratégia porque uma das vantagens era ter os recursos do Windows como processos em execução, expostos numa camada Linux onde era possível usar as ferramentas de Linux pra mexer em partes do Windows. Se eles conseguissem abstrair coisas mais complicadas como o Registry em alguma forma que pudesse ser gerenciada pelo Bash, ia começar a ficar mais útil ainda, mas aí já era pedir demais mesmo. Pra isso existem coisas como o Powershell. Se a intenção é gerenciar os recursos do Windows pela linha de comando, ainda é muito melhor, mais estável e mais completo usar o Powershell.</p>
<p>Em vez de tentar fazer de tudo, melhor fazer menos mas fazer direito. Já que é muito difícil emular a kernel do Linux como um adaptador em cima da kernel do NT e se simplesmente rodássemos o kernel do Linux de verdade? Seria a estratégia do coLinux, mas em vez de um hack, podemos usar o Hyper-V que nesta altura evoluiu bastante e é muito bom. O problema com programas de virtualização, como expliquei antes é que você normalmente precisa reservar quantos cores e quanta RAM vai ficar travado pra máquina virtual.</p>
<p>Mas durante a evolução do Windows Server pra atender os requerimentos de serviços como o Azure, eles conseguiram evoluir o Hyper-V pra criar máquinas virtuais mais leves e mais flexíveis. Existe a opção de lightweight utility VMs onde ele consegue pedir mais recursos à medida que for precisando. Daí não precisamos desperdiçar 4GB do sistema deixando reservado pra máquina virtual se logo no boot ele só precisa de 500Mb, por exemplo. Além disso existe a opção de não exigir um cold boot, ou seja, um boot do zero. Ele dá a opção de você conseguir carregar o equivalente a um dump da RAM, como no processo de hibernate. Dessa forma você consegue boots quase instantâneos, que levam segundos em vez de minutos.</p>
<p>E como também expliquei no video de virtualização, existe a opção de paravirtualização. Numa virtualização completa o kernel dentro da máquina virtual não sabe que está numa máquina virtual, é um Inception. Numa paravirtualização você modifica o kernel de dentro pra ele estar ciente de estar num ambiente virtualizado e conseguir um comportamento melhor cooperando com o sistema operacional do lado de fora.</p>
<p>Um último componente um pouco inusitado foi a inclusão de uma parte do antigo projeto Plan9, no caso o protocolo 9P que era usado pra file system em rede. Pense assim, como a partir do Windows eu poderia acessar o filesystem do Linux e vice versa se agora o Linux vai rodar de dentro de uma máquina virtual? Existem várias opções como o próprio protocolo SMB e o serviço SAMBA ou mesmo SFTP que é FTP em cima de SSH. A própria Microsoft não se manifestou do porque dessa escolha oficialmente, mas algumas teorias dizem que talvez seja porque o protocolo 9P é mais simples e mais fácil de implementar do que os disponíveis hoje.</p>
<p>De curiosidade o Plan9 é outro projeto da antiga Bell Labs que inventou a linguagem C e o UNIX, na realidade parte das mesmas equipes criaram o Plan9 que era um sistema operacional distribuído em rede. Com o tempo o Plan9 caiu em desuso e a Bell Labs criou o projeto Inferno que tinha como objetivo virar concorrente do então novo Java da Sun, e nas pesquisas de sistemas distribuídos tanto a Sun quanto a Bell Labs chegaram à conclusão que precisariam de uma máquina virtual pra lidar com tantas configurações de rede diferentes disponíveis na época. Vocês podem ver que a história da virtualização vem de longa data, e só nesse episódio vocês viram que nos anos 70, 80, 90 até os 2000 tinha alguma coisa de virtualização em cada solução da época. Virtualização e containerização não são tecnologias novas, são décadas e décadas de pesquisas e experimentação.</p>
<p>De qualquer forma, somando os lightweight utility VM do Hyper-V com a capacidade de boot rápido, mais uma kernel de Linux de verdade customizada pela Microsoft, mais a implementação do protocolo 9P pra exposição do filesystem em rede, e agora temos o Windows Subsystem for Linux versão 2 ou WSL 2. Ela nunca vai ter as mesmas possibilidades de integração com o resto do Windows como o WSL 1 tinha, mas por outro lado ela oferece 100% de compatibilidade binária com Linux, coisa que o WSL 1 nunca ia ter. E como agora o filesystem se tornou virtualizado, ele parou de ter os problemas de performance por causa do Windows Defender também. Por outro lado o WSL2 não oferece ainda opções pra configurar o filesystem virtual, se não me engano ele tem um limite máximo pra 256GB, o que é suficiente pra maioria dos cenários, mas seria bom ter futuramente a opção de expandir esse drive.</p>
<p>Do ponto de vista de performance, sem rodar nenhum benchmark nem nada, eu diria que é a mesma performance que eu já sentia rodando num VMWare, porém reservando menos recursos da máquina no geral. Usando todos os dias tudo vem funcionando exatamente igual funcionaria num Linux em Virtualbox ou Vmware. É um linux virtualizado. E como bônus se de dentro do WSL2 você subir um servidor, digamos um servidor de Rails que se liga na porta 3000, você pode abrir o Chrome do Windows e acessar localhost:3000 e vai abrir normalmente, porque ele faz automaticamente o NAT interno de mapeamento de portas. Isso é ao mesmo tempo bom e ruim, porque se você tiver serviços no Linux com portas que conflitam com portas no lado do Windows, vai ter problemas que podem ser difíceis de diagnosticar.</p>
<p>Do ponto de vista de ecossistema é um passo gigantesco porque se você acompanhou pessoalmente a história que eu contei até agora, como foi o meu caso, se no ano 2000 alguém me dissesse que um dia a Microsoft embutiria o binário da kernel do Linux dentro do Windows, eu diria que a pessoa era louca e devia se tratar. Diferente de alguma coisa como Cygwin, sendo suportado pela própria Microsoft, mais e mais pessoas podem depender dessa opção como algo estável e que vai estar disponível mesmo em futuros upgrades do Windows.</p>
<p>A história foi longa, mas instalar o WSL 2 é super easy, barely an inconvenience&hellip; Quando sair a versão oficial no próximo upgrade do Windows 10 você pode pular o primeiro passo, mas se ainda for setembro de 2019, você vai precisar se cadastrar no programa Windows Insider. Ah sim, só funciona no Windows 10 Pro, o Windows 10 Home não tem suporte a Hyper-V se não me engano. Uma vez cadastrado, você vai precisar habilitar o Fast Ring que vai trazer os builds mais recentes do Windows mas também tem o risco de vir binários instáveis. Habilitar o Fast Ring é concordar que você está baixando versões alfa de muita coisa e instabilidades fazem parte do contrato. Eu venho usando o Fast Ring faz meses e tirando uma ou duas vezes que tive telas azuis, no geral tudo tem funcionado sem problemas graves.</p>
<p>No caso até a data onde estou gravando este episódio está na build 18970. Com o Fast Ring ativado é só deixar o Windows Update baixar as últimas versões. Vai demorar bastante pra baixar e instalar a última versão, vamos esperar um pouco &hellip; só mais um pouco &hellip;. só mais um pouco &hellip;. ah sim, em uma das vezes que fui instalar ele reclamou que eu tinha o VMWare instalado, precisei baixar a versão mais nova pra ele parar de reclamar, mas cuidado com isso: com o Hyper-V ativado, não dá pra usar Virtualbox nem VMWare até eles aderirem às APIs de virtualização da Microsoft. Enfim, uma vez atualizado daí é restartar. Agora você precisa abrir um Powershell como Administrador e digitar o seguinte comando:</p>
<p><code>Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform</code></p>
<p>Isso vai exigir um restart e pronto, agora você já tem WSL. Abra um command prompt ou powershell e garanta que está com o WSL 2 como padrão executando o comando</p>
<p><code>wsl --set-default-version 2</code></p>
<p>E pra instalar o Ubuntu você pode ir na Windows Store, procurar por Ubuntu e instalar. É gratuito. Daí você espera um pouco … configura seu usuário e senha  e &hellip;. Instalado. Primeira coisa que eu sempre faço quando instalo é rodar o apt update e upgrade pra atualizar todos os pacotes. Daqui você pode seguir meu video de Ubuntu e praticamente tudo deve funcionar.</p>
<p>Eu digo praticamente porque o WSL é feito primariamente pra aplicativos de linha de comando como o próprio Bash, coisas como ssh, git e tudo mais. Mas sempre existe a opção de instalar um cliente X no Windows e rotear o DISPLAY do X no Linux pra ser fora dele. Se você não sabia disso, o X é outro capítulo conturbado na história do UNIX e Linux. Nós tivemos o XFree86, depois o X.org e finalmente muitos estão migrando pro Wayland.</p>
<p>Em termos simples, o X é feito pra aplicativos gráficos. A intenção original é que um servidor UNIX com um servidor X poderia servir múltiplos terminais burros, incluindo terminais gráficos, que seriam clientes de X. Pense em servidor web e navegador web, é basicamente a mesma coisa só que em vez de trafegar um protocolo primitivo como o HTTP ele usa um protocolo próprio do X pra enviar comandos como &ldquo;desenhe um botão na tela&rdquo; e quando o botão é clicado essa ação trafega pro servidor X decidir o que fazer e devolver outro comando pra redesenhar alguma parte da tela. Isso até que funciona, o que o povo de desenvolvimento não gosta é da implementação, é um código difícil de dar manutenção.</p>
<p>E as coisas ficaram mais difíceis depois que a Apple mostrou o que era possível fazer com um sistema de composite e aceleração via hardware como o Quartz e a interface Aqua. Como você faz pros clientes X terem os mesmos recursos? Dificulta muito que o X era um monolito, que os drivers das principais GPUs como NVIDIA é proprietário e distribuído só como binário, e as versões open source tem qualidades variadas, e no final o que acaba acontecendo é que você raramente usa o X de forma distribuída e tanto o cliente quanto o servidor ficam na mesma máquina desktop de qualquer jeito. Por causa disso o X tem dois modos de renderização acelerada, a direta onde o próprio servidor X acessa a GPU e o indireto onde ele manda os comandos de OpenGL pro cliente rodar.</p>
<p>No caso do WSL, ele não tem acesso direto a algumas coisas incluindo o hardware de vídeo. Portanto ele depende de um rasterizador via software. Você não tem como rodar o cliente de X dentro do WSL porém você pode rodar o cliente de X de Windows e rotear os comandos de X do WSL via rede pra fora. E vai funcionar perfeitamente bem. Existem duas opções gratuitas e open source que são o VcXSrv e o XMing e uma versão paga que eu pessoalmente acho melhor que é o X410, que eu costumo usar, mas na prática tanto faz. Se eu não estou enganado todos devem suportar o modo de aceleração indireta, basta configurar dentro do WSL uma variável de ambiente dizendo isso, o libgl_always_indirect e adicionar num bashrc pra sempre ter a variável quando se logar.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>export LIBGL_ALWAYS_INDIRECT=1</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pra rotear os comandos o WSL precisa do endereço IP do host Windows. No WSL 1 ficava tudo em localhost porque pra todos os efeitos e propósitos o WSL 1 rodava lado a lado do Windows e não virtualizado. No WSL 2 como ele é uma máquina virtual, do lado de dentro ele tem também uma rede virtual e o Windows do lado de fora é mapeado pra um endereço local dentro, é um tipo de ponte de rede que traduz o roteamento de pacotes do lado de dentro pro lado de fora. Se fosse localhost bastava fazer a variável Display ser igual a dois pontos e zero. Porém toda vez que a máquina reinicia pode ser que esse endereço virtual mude. Precisamos configurar uma variável de ambiente que aponte pra esse endereço e pra isso podemos fazer o seguinte one-liner, adicionar no bashrc e agora configurar a variável display pra usar o valor</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>export WSL_HOST=$(tail -1 /etc/resolv.conf | cut -d &#39; &#39; -f2)
export DISPLAY=$WSL_HOST:0</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Colocando essas variáveis de ambiente no arquivo .bashrc, toda vez que o bash iniciar ele vai ter essas variáveis. E agora podemos instalar alguns programas gráficos que eles vão aparecer do lado de fora, no Windows mesmo. Vamos instalar o gvim que eu gosto, o terminal Tilix que é o mesmo que eu instalei no tutorial de Ubuntu e o pacote dbus-x11 que programas gnome precisam.</p>
<p>Agora, precisamos instalar o tal cliente X, que como eu disse antes tem opções gratuitas mas eu pessoalmente gosto do X410 que eu já tinha comprado então vamos instalar pela Windows Store. Quando terminar e ele carregar, não esquecer de habilitar pra poder receber conexões da rede pública, se for a primeira vez o Windows Firewall vai apitar pra liberar acesso, libere e pronto. De volta ao bash, como só editamos o script bashrc precisamos ou deslogar e logar de novo ou só recarregar o bashrc com o comando source. Agora podemos abrir o gvim e olha só, abriu fora da máquina virtual, como um programa normal de Windows. Mesma coisa o Tilix e nele podemos configurar a aparência, escolhemos o tema Material … melhor o Monokai Dark … pronto, e agora podemos configurar o tamanho das fontes.</p>
<p>Mas pra mudar o tema geral, das bordas e tudo mais não vamos poder usar o gnome-tweaks. Como não estamos carregando todos os serviços que o gnome precisa pra rodar, se gastar algum tempo em tentativa e erro uma hora o gnome tweaks deve funcionar, mas por agora podemos simplesmente editar manualmente o arquivo de configurações em .config, gtk-3 settings.ini. Dentro dele habilitamos o modo dark, depois declaramos o nome do tema que é o Flat Remix GTK Blue Darker e finalmente o nome do pacote de ícones que é o Flat Remix Blue Dark.</p>
<p>Agora precisamos de fato baixar esses temas e ícones e aqui é a mesma coisa que já fizemos no episódio de Ubuntu, vou seguir exatamente o mesmo tutorial de antes. E como é a mesma coisa, vamos acelerar isso aqui.</p>
<p>Pronto, agora podemos chamar o Tilix de novo boom, tá bem mais bonito não acham? O Gvim também ficou um pouco melhor mas ele ainda está mais cru porque não carreguei nenhum dotfiles que configura ele como o Yadr que mostrei no episódio de Ubuntu.</p>
<p>Até agora eu estava usando o programa Command que vem com todo Windows. A Microsoft veio modernizando o antigo Command pra aceitar comandos de VT100, ANSI e tudo mais e com isso ele hoje é capaz de renderizar corretamente, vocês podem ver que as cores ANSI funcionam perfeitamente. Ele ainda tem cheiro de coisa velha mas comparado a como era até as primeiras edições do Windows 10, foi uma evolução considerável. Mas terminais mais maduros como o Tilix que acabamos de instalar ou mesmo o terminal padrão de um MacOS ainda são melhores.</p>
<p>Em vez de mexer demais no código velho do antigo Command, eles resolveram codificar um novo e com isso existe o programa simplesmente chamado de Terminal que você pode instalar via o Windows Store. Ele ainda está em desenvolvimento e por isso se chama Preview, mas mesmo no estágio atual ele já é muito melhor que o Command, inclusive ele é acelerado via DirectX então coisas como scrolls longos renderiza muito rápido. Vamos abrir e veja como ele é mais moderno com suporte a tabs. A configuração ainda é toda em texto, o que eu não acho ruim. Por exemplo, podemos mudar o tamanho das fontes de todos os perfis. Vale a pena brincar nesse arquivo um pouco pra customizar como você quiser.</p>
<p>Você pode usar esse novo Terminal pro WSL 2 até pra rodar o antigo CMD se precisar de scripts de batch antigos ou também rodar Powershell em outra aba. Ele é totalmente configurável e customizável, suporta abas e pode ser uma boa opção. Eu particularmente prefiro carregar o próprio Tilix e usar um terminal de verdade que suporta split de tela. Tem gente que prefere usar o TMux pra splits mas pro meu workflow um simples split do próprio terminal é suficiente. Se quiser ver o Tmux em funcionamento, veja meu vídeo de Ubuntu onde eu mostro como instalar e usar.</p>
<p>Mas só instalar o Ubuntu é muito fácil. Agora é uma boa hora de mostrar algo diferente. Hoje a Microsoft suporta o Ubuntu, o Fedora e o OpenSuse além de uma distro paga feita especialmente pro WSL 2 que é Pengwin, que se não me engano é uma derivação de Debian. Mas eles tem receitas no GitHub de como você pode empacotar qualquer outra distro de Linux. Desde o WSL 1 havia uma versão de Arch que você podia instalar e eu testei e vi que eles deram suporte pro WSL 2 também, então porque não testar? Mas, aviso que essa demo é meio experimental, ele não tem suporte da Microsoft e muitas coisas não funcionam perfeitamente ainda. Se você for experiente em Linux talvez consiga achar os workarounds, mas se for iniciante, por agora é melhor ficar no Ubuntu mesmo.</p>
<p>Vamos no Google, pesquise por ArchWSL e o primeiro link deve ser a página de GitHub do projeto. Lá tem todas as instruções que você precisa. Baixe o zip, descompacte em algum lugar como no seu diretório de usuário do Windows. Dentro vai ter um executável de Arch, dê duplo clique ou abra o novo Terminal, navegue até o diretório, digite arch e execute. Esse instalador faz menos coisas que o de Ubuntu, o que é esperado pra filosofia Arch de fazer você configurar tudo. Ele vai te logar como root direto. A primeira coisa a fazer é colocar uma senha pro root. Agora vamos criar um novo usuário não-root, configurar a senha, e abrir o visudo pra dar permissão de sudoer pra esse novo usuário. Dessa forma você vai poder logar como esse usuário em vez de root e ter acesso a sudo. … Feito isso podemos sair da sessão do Arch de volta ao Command do Windows e configurar o arch pra carregar com esse novo usuário.</p>
<p>Feito isso precisamos inicializar o pacman que é o gerenciador de pacotes, isso só precisa ser feito uma vez. Uma vez inicializado, mesma coisa de antes, eu gosto de atualizar os pacotes todos e fazemos isso com o comando pacman traço Syu. No Ubuntu começamos instalando pacotes como o build-essential pra ter o toolchain de desenvolvimento. Com o pacman instalamos pacotes como o base, base-devel e vamos aproveitar pra instalar também o gvim, tilix e git.</p>
<p>Seguindo os mesmos passos, vamos exportar as mesmas variáveis de ambiente pra rotear o X….
Pronto, podemos carregar o Tilix. Porém aqui já vemos um problema dessa versão. Programas gnome precisam do dbus pra comunicação interprocessos, incluindo gerenciar configurações. Mas veja as mensagens de aviso dizendo que não encontra o dbus-launch. Um workaround pra isso é chamar o dbus-launch manualmente. De novo, eu não parei pra investigar a fundo quais dependências estão faltando ou serviços que não estão carregando. Se você souber como corrigir isso, não deixe de mandar nos comentários abaixo.</p>
<p>Aliás, uma coisa que notei é que tanto o Ubuntu como esse Arch de WSL não bootam com o systemd, ou qualquer outro init system então nenhum serviço carrega e comandos como systemctl pra iniciar ou parar serviços não vão funcionar. Você precisa carregar serviços manualmente se precisar.</p>
<p>De qualquer forma, só pra mostrar como as coisas são muito parecidas, vou acelerar de novo pela parte que eu baixo os temas Flat Remix, editar o arquivo settings.ini manualmente e … pronto, tilix carregado com o novo tema, igualzinho antes.</p>
<p>E com isso temos um Arch instalado, você pode seguir qualquer tutorial normal de como configurar seu Arch como ambiente de desenvolvimento ou seguir as mesmas instruções que eu mostrei pro Ubuntu.</p>
<p>Agora, vamos voltar pro Ubuntu. Pra demonstrar que tudo funciona, vamos seguir meu tutorial e instalar o bom e velho ASDF como já mostrei antes. …</p>
<p>Não esqueça de colocar os scripts de asdf no bashrc ou equivalente do seu shell pra iniciar sempre que se logar. …</p>
<p>Feito isso podemos instalar o plugin de ruby ….</p>
<p>Agora podemos listar as versões de Ruby disponíveis …</p>
<p>Vamos escolher a mais recente, a 2.6.4 e instalar ….</p>
<p>Oops faltou instalar mais dependências de desenvolvimento do sistema, então vamos começar pelo pacote build-essential.</p>
<p>Ainda temos mais dependências, então vamos instalar …
Oops ele não acha o libgdbm3 então vamos tentar libgdbm
Oops ele não acha libgdbm também, ok deixa ele pra lá, não vamos precisar disso agora mesmo</p>
<p>Pronto, pacotes instalador, então vamos instalar o Ruby 2.6.4. Demora um pouco mas uma hora ele termina.</p>
<p>Não esquecer de configurar essa versão pra ser a padrão do sistema
Ruby instalado, vamos instalar a gem do Bundler</p>
<p>E finalmente, vamos instalar as gems do ruby on rails</p>
<p>Como o Rails hoje usa muito javascript também, inclusive ele integra com o yarn e com webpack, melhor instalar o plugin de nodejs do asdf. …</p>
<p>Pronto, mesma coisa, vamos listar as versões disponíveis e &hellip;
escolher a mais recente, a 12.9.1</p>
<p>Oops faltou configurar as chaves gpg dos repositórios,
então vamos na página de github do plugin</p>
<p>Basta copiar esta linha e executar pra instalar as chaves
Pronto, chaves configuradas, agora podemos tentar instalar a última versão de novo</p>
<p>Quando terminar, não esquecer de configurar essa versão como a global do sistema
Esse passo nem precisa na real, mas eu tenho costume forçar a atualização do npm pra garantir que estou com a versão mais nova.</p>
<p>Vamos instalar o yarn também</p>
<p>Agora, vamos brincar um pouco e criar um novo projeto Rails do zero com seu gerador.</p>
<p>Oops falhou porque faltou instalar o sqlite3. Isso é opcional mas como eu não indiquei nada no gerador ele por padrão espera ter o sqlite3 então vamos instalar.</p>
<p>Como parou o gerador no meio, então vamos entrar no diretório do projeto e rodar manualmente o comando bundle install pra terminar de instalar as dependências.</p>
<p>Agora vamos carregar o rails server pra testar a página de Bem Vindo e oops, como o gerador tinha parado aquela hora ele não inicializou o webpack, então vamos fazer isso manualmente com a task webpacker dois pontos install.</p>
<p>Pronto, agora sim vamos carregar o rails server.</p>
<p>E com meu navegador Opera de Windows, podemos carregar o localhost porta 3000 e veja que funcionou! O WSL mapeou corretamente a porta 3000 de dentro da máquina virtual pra estar acessível do lado de fora no Windows.</p>
<p>Como última parte desse demo, vamos continuar o projeto gerando um controller de rails pra testar mais um pouco. Mas e agora, como vamos editar esses novos arquivos? A partir daqui eu abriria meu gVim devidamente configurado mas eu sei que muita gente migrou pra Visual Studio Code hoje, que eu também concordo que é um editor de textos e uma IDE excepcional. Altamente recomendado então vamos na página dele e baixar o instalador. E sim, vamos baixar o instalador de Windows e instalar do lado de fora no Windows.</p>
<p>Mas e agora? Como o VS Code de Windows vai editar os arquivos do meu projeto que está dentro do WSL? Aqui começa uma das vantagens do WSL ser desenvolvido pela Microsoft, o VS Code automaticamente detecta a existência do WSL, detecta que o Ubuntu é a distro padrão, instala os plugins adequados e agora podemos abrir uma nova janela do VS Code que vai estar conectado no WSL, olha a barra de status, no canto inferior esquerdo, e veja que ele está abrindo o WSL.</p>
<p>Com isso quando mandamos abrir uma pasta ele vai explorar o filesystem de dentro do WSL automaticamente apontando a partir do diretório do meu usuário e de lá podemos abrir o projeto Rails que acabamos de criar.</p>
<p>Então vamos procurar nosso arquivo de index html e editar alguma coisa.</p>
<p>Vamos também editar o arquivo de rotas pra colocar esse controller como raiz.</p>
<p>Agora vamos reiniciar o servidor e recarregar a página no navegador e boom, olha só, funciona de boas. Apesar do WSL 2 ainda não ser tão completo quanto rodar uma máquina virtual de verdade, ele é leve e simples o suficiente pra ser tipo um runtime que roda em background, você pode usar o Terminal no Windows e o VS Code no Windows mesmo e desenvolver quase como se estivesse num Linux de verdade. Pra muitos casos de uso isso pode ser exatamente o que as pessoas precisam.</p>
<p>A última questão que todo mundo tem é, mas e o Docker? Funciona? Vamos no google de novo procurar um tutorial de docker pra ubuntu, os da digital ocean costumam ser bons então vamos nele.</p>
<p>Vamos seguir passo a passo como ele manda, primeiro instalar a chave gpg dos repositórios oficiais do docker.</p>
<p>Adicionar os repositórios como fontes pro apt</p>
<p>Rodar o apt update pra atualizar</p>
<p>Garantir que vamos instalar dos repositórios do docker</p>
<p>Finalmente instalar o docker propriamente dito</p>
<p>E iniciar o serviço com o systemctl e oops</p>
<p>Como eu disse antes, o WSL não boota com o systemd então não existe suporte ao init system e o comando systemctl não vai funcionar.</p>
<p>Mas, podemos executar os daemons do Docker manualmente, e pronto, é meio chato ter que fazer isso toda vez que o WSL reiniciar, mas é melhor que nada.</p>
<p>Continuando o tutorial, vamos adicionar o grupo docker ao nosso usuário. Agora a gente ou desloga fechando o terminal ou só fazemos <code>su</code> pra abrir uma nova sessão direto.</p>
<p>Pronto, checando se tá tudo ok e agora podemos rodar o famoso hello world e ver que tudo funciona.</p>
<p>E pra garantir vamos um passo além e instalar o Postgres no Docker. E mesma coisa, primeiro vamos no Google procurar um tutorial qualquer.</p>
<p>Primeiro, puxamos a imagem do docker</p>
<p>Agora criamos diretórios pra guardar os bancos de dados</p>
<p>Finalmente podemos subir o Postgres dentro do Docker com esse comandão aqui, que vai configurar coisas como o mapeamento de portas.</p>
<p>Pra demonstrar que é o docker nativo de verdade rodando, se rodarmos o comando <code>ps aux</code> podemos ver todos os processos rodando dentro da máquina virtual e temos o postgres aparecendo como deveria. Se você assistiu meus episódios sobre virtualização e containers já entendeu que Docker não é virtualização. Na prática tudo que você roda via Docker roda normalmente como um processo no seu sistema, mas o Docker usa recursos da Kernel do Linux como cgroups pra fazer o sistema operacional mentir pro processo, fazendo esse processo acreditar que está rodando sozinho na máquina.</p>
<p>Como eu já tinha mostrado no episódio de Ubuntu, podemos navegar pro diretório /proc no subdiretório que é o pid do processo e oops, pid errado, vamos listar de novo e pegar o pid certo e navegar de novo</p>
<p>Pronto, agora podemos listar o conteúdo do meta arquivo cgroups e ver como ele está sendo mascarado pelo docker.</p>
<p>Pra todos os efeitos e propósitos, o processo do postgres acredita que está rodando sozinho na máquina, e pra gente do lado de “fora” é só mais um processo rodando como se tivesse sido instalado fora do Docker. Por isso containers de Docker são ordens de grandeza mais leves e performáticos do que uma máquina virtual, porque na prática não existe um hypervisor envolvido, é só uma casquinha muito leve do próprio kernel. O kernel precisa ter esse suporte e por isso não funcionava no WSL 1 porque é difícil recriar isso só com um wrapper em cima da kernel do NT e eles nem chegaram a tentar eu acho. Então o Docker de Windows, pra rodar containers de Linux precisava de fato executar um Linux no Hyper-V pra criar os containers dentro. Aqui é a mesma coisa já que o WSL 2 é uma máquina virtual rodando uma kernel de Linux de verdade, entenderam?</p>
<p>Agora podemos conectar nesse postgres dentro do container através da porta que o Docker mapeou pra fora. Vamos seguir o tutorial e oops ainda não temos o cliente de postgres instalado então vamos seguir o que ele manda instalar.</p>
<p>Oops, ainda falta mais um pacote, vamos seguir a instrução e instalar e agora sim, cliente instalado, vamos rodar o comando de novo.</p>
<p>Pronto! Estamos conectados no postgres, rodando dentro do container do Docker.</p>
<p>Podemos rodar docker ps pra ver quais containers estão sendo executados e podemos pegar o pid do container e com ele rodar comandos como o docker stop pra parar o container e assim derrubar esse postgres.</p>
<p>Eu até acho que nesse ambiente de WSL 2, onde ele não sobe o systemd no boot e por isso não sobe daemons automaticamente</p>
<p>E é isso, o WSL 2 é basicamente um Hyper-V customizado pra rodar um kernel de Linux modificado pela Microsoft. E como a licença GPL obriga qualquer empresa a abrir o código fonte se for modificado, a Microsoft mantém o fork com as modificações no GitHub, e eu vou deixar o link nas descrições abaixo também. Eles vão sempre manter a versão estável mais nova e não devem ficar dando suporte pra kernels antigas, então você sempre vai ter a opção de rodar as distros mais novas. Se precisar rodar Linux velhos, você mesmo vai ter que instalar e configurar tudo manualmente numa máquina virtual Hyper-V do jeito antigo. O WSL 2 é um facilitador pro Hyper-V com um Linux melhor integrado.</p>
<p>Na prática, o WSL 1 era algo parecido com o Wine só que ao inverso. O WSL 2 é mais parecido em conceito com o coLinux, mas na prática é um Linux rodando dentro de uma máquina virtual. Então se você já usava Linux em Virtualbox ou VMWare na prática não tem grandes vantagens, especialmente porque o WSL não expõe tantas opções de configuração como um VMware.  Por outro lado a grande vantagem é o suporte oficial da Microsoft, ou seja, pela primeira vez é uma opção padrão. Veja a integração do Visual Studio Code com o WSL por exemplo. Uma vez que o WSL é um componente oficial no Windows, outras soluções podem começar a se integrar e criar um ecossistema</p>
<p>Eu gostava bastante do conceito do WSL 1, que seria o único caminho pra ter uma camada Linux integrada de verdade na fundação do Windows, o mais próximo que já se chegou do que se tem um macOS sem precisar reescrever todo o sistema operacional. Mas, eu entendo que era bem pouco prático dar suporte. Então o WSL 2 é um bom meio do caminho. Muita gente precisa estar no Windows seja pra usar programas corporativos que só existem em Windows, ou rodar pacotes como os da Adobe que não existem pra Linux ou mesmo fazer desenvolvimento em .NET pra Windows. Agora existe uma opção oficial pra rodar ferramental Linux lado a lado, com uma boa integração. Ele é mais limitado, ainda existem alguns bugs, mas com o tempo isso deve melhorar.</p>
<p>Na prática, se você já usa Virtualbox ou Vmware pra desenvolver em ambiente Linux, não existe de fato muita vantagem em usar o WSL 2. Mas se você quer integrar desenvolvimento de projetos em Node ou Python dentro do Linux junto com outros projetos no Windows usando o mesmo Visual Studio Code, por exemplo, é uma ótima opção. Aliás, apesar de existir um certo suporte nativo a rodar coisas como Node, PHP e Python no próprio Windows, eu altamente não recomendo, o certo é rodar dentro do Linux e ter acesso a tudo que esses ecossistemas oferecem. Toda versão de uma ferramenta Linux no Windows tem limitações, e rodando no WSL 2 ou numa máquina virtual elimina essas restrições. Evite ao máximo rodar ferramentas de Linux compiladas pra Windows, você sempre vai estar usando menos do que as ferramentas oferecem. Nesses casos o WSL 2 interessante pra desmotivar a existência dessas alternativas e simplesmente rodar o original num Linux de verdade, agora suportado pela própria Microsoft.</p>
<p>O único cenário onde eu ainda recomendaria Linux instalado nativo é se você está brincando de machine learning com ferramentas que precisam de acesso direto à GPU. Isso nem o WSL 2 e nem muitas máquinas virtuais vai conseguir te dar. Você precisa de acesso direto ao hardware. O WSL 2 hoje não tem como expor a GPU pra dentro da máquina virtual. Esse é um dos casos que é melhor uma configuração de dual boot se você também precisa de Windows, e se manter num Linux instalado nativamente na sua máquina.</p>
<p>No caso de desenvolvimento Web normal, onde você quer ter um postgres, redis, nginx, nodejs, rails, elixir, o WSL 2 é uma opção excelente e com a integração do Visual Studio, eu acho que se torna um pacote bastante atraente. Eu estou usando os dois, numa máquina tenho um WSL 2 e em outra tenho o VMWare. Como meu dia a dia não é mais ocupado por programação na maior parte do tempo, então pra mim o impacto é muito menor. Se você já testou essas opções, compartilhe sua experiência com o pessoal nos comentários abaixo. Se curtiu o video deixe um joinha, assine o canal e não deixe de clicar no sininho pra não perder os próximos episódios. Por hoje é só, a gente se vê, até mais!</p>
]]></content:encoded><category>linux</category><category>microsoft</category><category>ferramentas-de-desenvolvimento</category><category>akitando</category></item><item><title>[Akitando] #54 - O Guia DEFINITIVO de UBUNTU para Devs Iniciantes</title><link>https://akitaonrails.github.io/2019/07/12/akitando-54-o-guia-definitivo-de-ubuntu-para-devs-iniciantes/</link><guid isPermaLink="true">https://akitaonrails.github.io/2019/07/12/akitando-54-o-guia-definitivo-de-ubuntu-para-devs-iniciantes/</guid><pubDate>Fri, 12 Jul 2019 17:00:00 -0300</pubDate><description>&lt;div class="embed-container"&gt;
&lt;iframe
src="https://www.youtube.com/embed/epiyExCyb2s"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;No primeiro episódio técnico da série Começando aos 40 (&lt;a href="https://www.youtube.com/watch?v=sx4hAHhO9CY"target="_blank" rel="noopener"&gt;https://www.youtube.com/watch?v=sx4hAHhO9CY&lt;/a&gt;) eu recomendei que todos estudassem Linux, e foi só isso. Hoje eu resolvi retomar o que eu disse e mostrar que em casa de ferreiro o espeto é de ferro!&lt;/p&gt;
&lt;p&gt;Vou pegar um Ubuntu recém-instalado, e do zero ir até um ambiente completo para desenvolvedores de software (em particular Web, claro), com Docker, Tmux, Vim, ASDF e durante o percurso explicar várias coisas sobre Linux em geral, várias dicas, e até mesmo como customizar os temas pra ficar &amp;ldquo;dahura&amp;rdquo;!&lt;/p&gt;</description><content:encoded><![CDATA[

<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/epiyExCyb2s"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>No primeiro episódio técnico da série Começando aos 40 (<a href="https://www.youtube.com/watch?v=sx4hAHhO9CY"target="_blank" rel="noopener">https://www.youtube.com/watch?v=sx4hAHhO9CY</a>) eu recomendei que todos estudassem Linux, e foi só isso. Hoje eu resolvi retomar o que eu disse e mostrar que em casa de ferreiro o espeto é de ferro!</p>
<p>Vou pegar um Ubuntu recém-instalado, e do zero ir até um ambiente completo para desenvolvedores de software (em particular Web, claro), com Docker, Tmux, Vim, ASDF e durante o percurso explicar várias coisas sobre Linux em geral, várias dicas, e até mesmo como customizar os temas pra ficar &ldquo;dahura&rdquo;!</p>
<p>As dicas estão espalhadas por todo o vídeo, então tente assistir o vídeo inteiro sem pular nada.</p>
<p>Até o momento esse deve ser o vídeo mais longo que eu já fiz, e eu fiz de propósito pra que seja facilmente compartilhável num link só! Compartilhe com o máximo de pessoas que puder!</p>
<p>E pra ninguém perder tempo, desta vez vou deixar listado aqui os tempos pra cada seção do vídeo pra que você possa pular direto pro que interessa caso já não seja mais tão iniciante ou se quiser relembrar alguma parte em particular:</p>
<p>== COMPLEMENTO</p>
<p>Esqueci de dizer que depois de instalar o dotfiles YADR os shortcuts de Tmux, Vim, Git mudam (vejam o código fonte!!). O Tmux em vez de Ctrl-B vira Ctrl-A por exemplo. No yadr-appearance.vim não use Solarized se quiser usar o Vim no Terminal (por alguma razão ele crasheia), troque por um &ldquo;gruvbox&rdquo; por exemplo. Pra abrir o NerdTree no terminal, use Ctrl+\</p>
<p>== ERRATA</p>
<p>Em 00:54:24 eu percebi que faltou um áudio, eu devo ter apagado por engano e só percebi agora que já subi. Era a introdução da seção de Docker e o texto era: &ldquo;Tem gente que prefere não instalar esses serviços diretamente, pelo mesmo motivo que usamos ASDF. E se você tem um projeto antigo que depende do PostgreSQL 7 e quebra se tentar conectar no Postgresql 10? Pra isso precisamos de algo parecido com um ASDF. E se não me engano acho até que o ASDF tem suporte pra Postgresql, vamos ver no google, e sim, tem mesmo. Mas se for esse o caso eu prefiro fazer diferente. Serviços como os que acabamos de instalar é o caso de uso perfeito pra usar Docker. Então é hora de instalar e configurar Docker. E a essa altura você já adivinhou: vamos pro GOOGLE.&rdquo;</p>
<p>Em 00:03:00 eu falo que o Steam roda poucos jogos em Linux mas eu realmente me esqueci do Proton que é habilitado dentro da própria interface do Steam e você pode rodar os jogos quase que normalmente em Linux também! Eu mesmo não uso porque uso Steam no Windows mas fica a dica pra quem tem insegurança de mudar pra Linux e ficar sem Steam.</p>
<p>== Seções:</p>
<p>00:03:50 - Manjaro/Arch?
00:04:19 - Que hardware/notebook devo comprar pra programar?
00:08:46 - Que máquina Akita tem? Por que não comprar um topo de linha?
00:13:27 - Ubuntu: aprendendo sobre Workspaces
00:15:40 - Ubuntu: Tema Flat-Remix
00:18:19 - Linux: Conceitos e comandos básicos
00:22:59 - Linux: Entendendo os principais diretórios do sistema
00:28:41 - Linux: Entendendo Processos e manipulando arquivos e diretórios
00:40:42 - ASDF: Instalando e gerenciando versão de TODAS as linguagens!!
00:49:30 - Bancos: Postgresql 10, Redis, Memcached e MongoDB
00:54:24 - Docker: instalando, usando Postgres em container e mais!
01:00:21 - Básico do básico de criptografia, chaves SSH
01:05:52 - Básico de TMux e Vim
01:12:28 - Dotfiles: meu preferido, o YADR
01:17:22 - Configurações finais de Desktop</p>
<p>== Links:</p>
<ul>
<li>
<p>Upgrade Your SSH Key to Ed25519 (<a href="https://medium.com/risan/upgrade-your-ssh-key-to-ed25519-c6e8d60d3c54"target="_blank" rel="noopener">https://medium.com/risan/upgrade-your-ssh-key-to-ed25519-c6e8d60d3c54</a>)</p>
</li>
<li>
<p>How to install Flat-Remix Theme on Any Linux Distribution? (<a href="https://www.osradar.com/install-flat-remix-theme-ubuntu/"target="_blank" rel="noopener">https://www.osradar.com/install-flat-remix-theme-ubuntu/</a>)</p>
</li>
<li>
<p>SWKP Dotfiles YADR (<a href="https://github.com/skwp/dotfiles"target="_blank" rel="noopener">https://github.com/skwp/dotfiles</a>)</p>
</li>
<li>
<p>VIM Cheat Sheet (<a href="https://vim.rtorr.com"target="_blank" rel="noopener">https://vim.rtorr.com</a>)</p>
</li>
<li>
<p>TMUX Cheat Sheet (<a href="https://tmuxcheatsheet.com"target="_blank" rel="noopener">https://tmuxcheatsheet.com</a>)</p>
</li>
<li>
<p>ASDF (<a href="https://github.com/asdf-vm/asdf"target="_blank" rel="noopener">https://github.com/asdf-vm/asdf</a>)</p>
</li>
<li>
<p>Understanding Shell Script&rsquo;s idiom: 2&lt;&amp;1 (<a href="https://www.brianstorti.com/understanding-shell-script-idiom-redirect/"target="_blank" rel="noopener">https://www.brianstorti.com/understanding-shell-script-idiom-redirect/</a>)</p>
</li>
<li>
<p>Upgrade Your SSH Key to Ed25519 (<a href="https://medium.com/risan/upgrade-your-ssh-key-to-ed25519-c6e8d60d3c54"target="_blank" rel="noopener">https://medium.com/risan/upgrade-your-ssh-key-to-ed25519-c6e8d60d3c54</a>)</p>
</li>
<li>
<p>Bash scripting cheatsheet (<a href="https://devhints.io/bash"target="_blank" rel="noopener">https://devhints.io/bash</a>)</p>
</li>
<li>
<p>Arguments against systemd (<a href="https://without-systemd.org/wiki/index.php/Arguments_against_systemd"target="_blank" rel="noopener">https://without-systemd.org/wiki/index.php/Arguments_against_systemd</a>)</p>
</li>
<li>
<p>Vim cheatsheet (<a href="https://devhints.io/vim"target="_blank" rel="noopener">https://devhints.io/vim</a>)</p>
</li>
<li>
<p>Tmux cheatsheet (<a href="https://devhints.io/tmux"target="_blank" rel="noopener">https://devhints.io/tmux</a>)</p>
</li>
<li>
<p>AkitaOnRails: Optimizing Linux for Slow Computers (<a href="https://www.akitaonrails.com/2017/01/17/otimizando-o-linux-para-computadores-lentos"target="_blank" rel="noopener">https://www.akitaonrails.com/2017/01/17/otimizando-o-linux-para-computadores-lentos</a>)</p>
</li>
</ul>
<p>Olá pessoal, Fabio Akita</p>
<p>Eu coloquei a série de vídeos Começando aos 40 numa playlist chamada Programação para Iniciantes, e que você pode assistir no link acima. Claro que não dá pra explicar “tudo”. Eu entro em mais detalhes em conceitos que eu sei que é muito mal explicado ou difícil de entender só lendo, como concorrência e paralelismo ou gerenciamento de memória, e meio que deixei implícito coisas que você facilmente encontra em meia hora de Google.</p>
<p>Eu imagino que pra quem está iniciando as coisas são bem menos óbvias do que pra quem já tem alguns anos na carreira. A primeira coisa que eu disse que você deveria tentar aprender é um pouco de Linux, em particular eu falei pra você tentar sofrer um pouco num Arch Linux por exemplo, e a recomendação continua valendo. Porém, e depois que você instalou o Arch ou mesmo qualquer outro Linux, como você continua e monta um ambiente de desenvolvimento suficiente pra começar a treinar programação?</p>
<p>Hoje vou seguir um pouco a tradição do meu blog, akitaonrails.com. Faz anos que mesmo quando eu estava no Mac eu não usava as coisas nativamente no ambiente UNIX do Mac, eu sempre preferi usar um Linux de verdade dentro de uma máquina virtual. Na época eu usava Vagrant que é um facilitador pra eu conseguir acessar essa máquina virtual localmente usando SSH. Apesar de parecer que todo desenvolvedor avançado usa Mac pra desenvolver, a menos que você seja um desenvolvedor de iOS pra iPhone ou iPad, você não precisa usar Macs.</p>
<p>Na verdade, o melhor ambiente de desenvolvimento sempre é um Linux. Especialmente se estamos falando de programação de aplicações Web. No final você sempre vai subir a aplicação num servidor da Amazon AWS ou Azure ou Google Cloud ou Heroku e sempre vai ser servidores Linux, por isso quanto mais perto do ambiente final de produção você puder estar, sempre vai ser melhor.</p>
<p>Mesmo num Windows, existem de fato versões de Python ou PHP e até Javascript pra Node.js que instalam e rodam nativamente em Windows. Mas não se engane, eles nunca vão funcionar 100%. Eu expliquei isso durante a série quando falei sobre como funciona compilação e dependências nativas. O comportamento é um pouco diferente e muitas bibliotecas que precisam de dependências nativas de Linux não tem similares em Windows. Na dúvida, evite as versões de Windows. Se for programar numa linguagem que se originou no mundo de código-aberto, use um sistema operacional baseado em Linux. No caso do Windows, em breve você vai poder desenvolver usando Linux usando o novo Windows Subsystems for Linux versão 2, mas mesmo ele vai precisar de uma máquina um pouco mais parruda porque vai rodar usando um hypervisor. Eu quero falar desse assunto em outro vídeo ainda.</p>
<p>Prefira instalar um Linux como sistema operacional primário e nativo na sua máquina. Na pior das hipóteses, faça um dual-boot com Windows 10 pra coisas como seus games de Steam. Sim, eu sei, Steam roda no Linux, mas a grande maioria dos principais jogos não rodam e os hacks que você precisa fazer com Wine e outras coisas pra conseguir rodar raramente compensa a menos que você seja geek de configuração como eu.</p>
<p>Isso tudo dito, o objetivo de hoje é partir de uma instalação de Ubuntu e chegar no final com um ambiente de desenvolvimento usável e demonstrar um pouco de como algumas coisas funcionam se você ainda é novato no mundo de Linux. Este episódio vai ser GIGANTE e tem múltiplas seções então pra você pode voltar depois pra seção específica que quer ver ou se quiser pular algumas partes, vou deixar os tempos de cada uma nas descrições abaixo.</p>
<p>(&hellip;)</p>
<p>Vamos lá. Eu pessoalmente prefiro usar a distro Manjaro que é uma versão de Arch mais simples de instalar. O que eu gosto em Arch é o gerenciador de pacotes Pacman e da filosofia de rolling updates, ou seja, que você não tem quebras entre versões major, tipo pular do Ubuntu 17 pro 18, ou do MacOS High Sierra pro MacOS Catalina. No caso das distros baseadas em Pacman, ele vai atualizando os pacotes continuamente, sem necessariamente dar grandes saltos que podem quebrar as coisas do nada.</p>
<p>A idéia de eu começar explicando pelo Ubuntu é porque a grande maioria das pessoas vai acabar chegando no Ubuntu primeiro e é um dos sistemas com mais suporte tanto de hardware quanto da maioria dos softwares então é o que possivelmente dê menos dor de cabeça para iniciantes. O Ubuntu 18 substitui o antigo gerenciador de janelas Unity pelo mais comum GNOME, que em termos de uso de memória é um dos mais pesados. Mas mesmo dizendo assim, hoje em dia, 300MB de RAM a mais ou a menos não é o que vai te fazer a diferença considerando que qualquer aba de Google Chrome vai consumir muito, mas muito mais que isso.</p>
<p>A atual geração de aplicativos desktop usando Javascript e navegadores deixou tudo mais pesado, principalmente em termos de RAM. O mínimo que você precisa hoje em dia é de 8GB de RAM, de preferência invista mais um pouco e consiga 16GB de memória DDR4. Um processador Core i3 é possível de usar pra desenvolver, mas você gostaria de ter um pouco mais de cores se possível e eu recomendaria tentar investir pelo menos num Core i5 acima da 6a geração Skylake.</p>
<p>Pra quem não sabe, os processadores da Intel são divididas em gerações, depois da Skylake tivemos a 7a com Kaby Lake, 8a e 9a com Coffee Lake. Todas tem processadores i3, i5 e i7 e na 9a geração temos também i9. A diferença é principalmente número de cores, os i3 são só dual-core, os i5 e i7 pode ser dual ou quad-core. Os i9 acho que tem uns 10 cores. Outra diferença, se não me engano, é o tamanho dos caches L1, L2 e L3. E também suporte a Hyperthreading. Então um Core i7 quad-core pode ter 8 threads.</p>
<p>Se você estiver com dinheiro sobrando, monte um PC torre com Core i9 9900K com 32GB de RAM e 512GB a 1TB de SSD nvme2 como um Samsung EVO. Mas pra começar você pode ir com um Core i3 9320, 8GB de RAM, 128GB de SSD normal pra instalar o sistema operacional e 512GB de HD mecânico de 5400 ou 7200 rpm se possível. Não existe a necessidade de começar com a melhor máquina, na verdade eu recomendaria começar com uma máquina fraca. Não tão fraca pra ser nível Positivo porque ali acho que nem dá pra desenvolver direito. Mas um notebook como o Dell Inspiron 15 3000 com o Core i5-8265U Skylake, 8GB de RAM, 256 GB de SSD seria um dos melhores custos benefícios no Brasil em Julho de 2019, ao custo de R$ 3.500 em até 10x. Este vídeo não é patrocinado pela Dell mas eu mesmo já usei um notebook desses e dá pra desenvolver num desses com muita sobra, pra maioria dos programadores, especialmente iniciantes. Existem opções mais baratas, mas você vai sacrificar em algum lugar.</p>
<p>Pro povo mais avançado eu sei que depois de falar tanto de Intel já já vai aparecer comentário de “mas e os AMD Ryzen”? Sim, nos anos recentes a AMD começou a voltar ao jogo das CPUs e as CPUs Ryzen são muito boas, particularmente pra multithreading porque ele vem com mais cores se comparado com equivalentes de preço da Intel. Então um AMD Ryzen 3 já vem com 4 cores comparado ao Intel Core i3 de 2 cores. O Ryzen 5 vai de 4 a 6 cores. O Ryzen 7 tem 8 cores. O Ryzen 9 tem até 16 cores e você ainda tem o Ryzen Threadripper que vai até 32 cores. Apesar de ter mais cores, a performance máxima de cada core ainda era menor se comparado aos da Intel, e em particular ele não superava a Intel em games, mas a nova geração deste ano está ultrapassando a Intel até em games!</p>
<p>Ou seja, por um preço menor você conseguiria comprar um Ryzen equivalente e seria mais barato e mais performático que a 9a geração da Intel. As CPUs da Intel tem o Turbo Boost que ativa quando você está fazendo algo particularmente intensivo de CPU, por exemplo compilando projetos gigantes em C e C++ que costuma exigir muito da CPU. Ou então em coisas como renderizar cenas 3D num Blender ou exportar vídeos no Adobe Premiere. O problema é que Turbo Boost costuma ser um pico de curta duração. Nos novos Ryzen eles tem o Precision Boost que aumenta o clock numa faixa menor que da Intel mas entrega essa velocidade maior por mais tempo e no geral pode te dar performance maior em períodos de grande carga. Ou seja, os Ryzen vieram atropelando a Intel nesses últimos 2 ou 3 anos. Se você encontrar boas configurações com Ryzen, especialmente pra nós de desenvolvimento de software, eu recomendo.</p>
<p>Muita gente que tá começando sonha com um Macbook Pro, ou um Surface Book ou algo caro assim. Eu pessoalmente tenho um Surface Book 2 e um Lenovo Extreme. Junto com o Macbook Pro são notebooks na faixa dos USD 3000 se comprar nos Estados Unidos, ou seja, máquinas que facilmente custam na faixa dos R$ 15 mil no Brasil se comprar no mercado negro. Vai por mim, você não precisa disso. Então, por que eu tenho? Sendo curto e grosso: porque eu posso. Mas faça as contas, eu tenho 42 anos, se a essa altura eu não pudesse, pelamor né.</p>
<p>Pra dar perspectiva, quando eu tinha uns 25 anos eu comprava meus notebooks via contrabandista de Miami mesmo, como todo mundo faz hoje também. Eram máquinas mais fracas, como os antigos Toshiba Sattelite em 2002. Acho que eram Pentiums com 512MB ou 1GB de RAM. Eu falei que estamos na 9a geraçao da Intel, mas a série de processadores Core da Intel só iria começar a sair a partir de 2006. SSD ainda não existia. E Java naquela época já era quase tão pesado quanto é hoje. Na verdade hoje eu sinto o Java super leve em comparação como que eu sofria em 2002.</p>
<p>Ao longo dos anos eu fui crescendo na carreira e trocando pra computadores mais potentes. Nunca se compare com alguém como eu que já tem quase 30 anos de carreira. Além disso ter um computador topo de linha não vai te beneficiar em muita coisa se você não sabe como tirar proveito de uma máquina dessas. Em janeiro de 2017 eu decidi usar um Dell Inspiron que comprei numa promoção da Magazine Luisa eu acho, um pouco melhor do que o que eu sugeri agora a pouco, mas não muito, e com HD mecânico. Eu queria ver o quanto eu conseguia otimizar o Linux pra performar nesse ambiente e escrevi um longo tutorial sobre o que é possível fazer e você pode ver nos links na descrição abaixo. E eu fiquei usando essa máquina como minha máquina primária por alguns meses sem grandes problemas.</p>
<p>Em toda profissão de prática eu acho que todo iniciante deveria começar num ambiente mais hostil. Não digo em ambientes impossíveis, mas longe do topo de linha. Um cara que consegue desenvolver bons software e ter produtividade em um Core i3, com 4GB de RAM, imagine o que ele vai conseguir fazer com um Core i9 e 32GB de RAM.</p>
<p>Por outro lado se um programador amador ruim com 32GB de RAM só vai entregar software vazando memória. Um programador que não tem interesse em otimizar e aprender mais sobre seu próprio ambiente de trabalho não faz sentido pra mim. Amanhã ou depois você vai ter um problema em produção e vai precisar tirar o máximo possível dos servidores e outros recursos que tem. Se você sequer sabe como otimizar seu próprio computador, como você espera conseguir otimizar qualquer outra coisa? Tudo faz parte do treino, todo conhecimento conta. Comece a se interessar em abrir o capô e mexer na mecânica do seu carro em vez de só dirigir e ficar de braços cruzados quando o carro não quer pegar. Nese caso você vai ser só um motorista, bons programadores dirigem e consertam o próprio carro.</p>
<p>Isso tudo dito, instalar um Ubuntu é simples, beira o trivial a menos que você tenha um hardware muito fora de padrão. Basicamente baixe a ISO do site, grave num pendrive USB usando ferramentas como o Rufus no Windows, boote pelo pendrive e siga as instruções. Primeira coisa que você precisa aprender a fazer: ler a porcaria das instruções e não só ficar apertando próximo, próximo, como minha avó faria. Metade dos erros que os programadores iniciantes travam são trivialmente resolvíveis só lendo o que aparece na tela. Leia as fucking mensagens de erro!!</p>
<p>Bom, essa parte você vai ter que seguir um tutorial como o que eu deixei linkado nas descrições abaixo. No meu caso eu estou usando Windows 10 como sistema operacional principal e por isso vou instalar o Ubuntu numa máquina virtual usando VMWare Workstation. Em outro vídeo explico porque eu uso Windows como máquina principal, mas deixando isso de lado, a instalação costuma ser muito simples. Em hardware não tão antigo (pelo menos de uns 5 anos pra cá) qualquer distro moderna de Linux deve ser capaz de identificar tudo e instalar e configurar os drivers corretos. Se por acaso você tem um hardware muito fora de padrão e não for detectado, minha sugestão é simples: ache um canto aí no seu quarto, deita em posição fetal e chora um pouco. .. chorou? Bom, agora você vai ter que ir no Google, ou direto em sites como o ArchWiki ou Stackeroverflow e sair procurando. Bom, pense que isso faz parte do aprendizado também. Eu não consigo ajudar porque não tem como eu mostrar aqui todas as variações diferentes de todos os tipos de hardware que existem.</p>
<p>(&hellip; PARTE B - SCREENCASTS)</p>
<p>Depois que terminar de instalar esta é a tela que você vai ver. O instalador já vai ter criado uma conta pro seu usuário e você pode optar por logar automaticamente nela. Você pode customizar o que quiser mas uma das mecânicas que eu recomendo que você se habitue é navegar por workspaces. Por muitos anos só desktop managers de UNIX e Linux como os antigos baseados em Motif ou os mais atuais como Cinnamon, XFCE, KDE e GNOME que é o que o Ubuntu usa hoje em dia possuem o recurso de workspaces, que é como se você tivesse mais de um monitor. Demorou algumas décadas mas finalmente hoje em dia nos MacOS e Windows você também tem isso. Mas no Ubuntu funciona assim. Vamos abrir alguns programas pra ter algumas janelas pra mostrar. Vamos abrir o Nautilus que é como o Finder no Mac ou Explorer no Windows, vamos abrir o Firefox que já vem pré-instalado, vamos abrir o Terminal apertando a tecla Super e digitando Terminal que é outro jeito de abrir programas.</p>
<p>Agora você tem a situação em que tem muitas janelas no mesmo monitor, ou no caso no mesmo workspace. Então vamos mover o Firefox pra outra workspace usando a combinação Super + Shift + Page Down e boom, agora o Firefox está na worspace de baixo. E eu posso voltar pra workspace de cima com Super + Page Up e Super + Page Down. E eu posso ficar movendo janelas entre os workspaces com Super + Shift e Page Up ou Page Down. Mais do que isso, já que estamos falando de janelas, agora que o Firefox está num workspace só dele, podemos maximizar a janela toda usando Super + seta pra cima. Ou voltando pra primeira workspace podemos maximizar na metade da esquerda usando Super pra esquerda ou Super pra direita, e assim podemos ter janelas lado a lado organizado. Treine bastante essa combinação de teclas porque costuma ser bem útil pra manter seus programas organizados. A idéia é ter conjuntos de programas relacionados no mesmo workspace. Por exemplo, você pode ter uma com Slack e Discord, outro de trabalho que tem Terminal e Sublime Text e assim por diante.</p>
<p>Mas você veio até o Linux não por causa do ambiente gráfico, senão ficaria no MacOS que ainda é o melhor ambiente gráfico que existe. Você veio por causa do que tem por baixo do capô e a porta de entrada pra isso é o Terminal. Se você nunca mexeu num Linux precisa aprender alguns conceitos muito básicos. De novo, a idéia não é ser um tutorial completo mas só mostrar o principal, isso dito, vamos abrir o Terminal de novo, maximizar e aumentar as fontes pra vocês conseguirem enxergar.</p>
<p>Aproveitando, eu sou um pouco exigente com meu ambiente e apesar de não achar o tema do Ubuntu particularmente feio, eu prefiro um tema mais elegante do que esse laranjão todo, e um dos mais usados parece ser o Flat Remix. Vou deixar o link nas descrições abaixo, mas na prática poderíamos instalar pelos pacotes de atp mas vou instalar o Git pra baixar do Github pra mostrar como instala manualmente. Então a primeira coisa vai ser <code>sudo apt install git gnome-tweak-tool fonts-hack-ttf</code> pra instalar não só o Git como o Tweak Tool do Gnome pra trocar o tema e minha fonte monospace preferida que é a Hack. Em seguida vamos criar um mkdir Projects e cd Projects pra onde podemos baixar nossos códigos.</p>
<p>Agora vamos clonar o repositório de icones do Gihub git clone <a href="https://github.com/daniruiz/flat-remix"target="_blank" rel="noopener">https://github.com/daniruiz/flat-remix</a> e em seguida vamos clonar o tema com git clone <a href="https://github.com/daniruiz/flat-remix-gtk"target="_blank" rel="noopener">https://github.com/daniruiz/flat-remix-gtk</a>. Agora vamos criar alguns diretórios com mkdir -p ~/.icons &amp;&amp; mkdir -p ~/.themes e copiar os arquivos que baixamos pra lá com cp -r flat-remix/Flat-Remix* ~/.icons/ &amp;&amp; cp -r flat-remix-gtk/Flat-Remix-GTK* ~/.themes/ Pronto, podemos abrir o Tweak Tool e mudar pro tema e os ícones para o que queremos, vamos aproveitar e trocar a fonte monospace pela Hack e mudar o wallpaper pra alguma coisa mais agradável. Viu só? Podemos trocar totalmente o look and feel e existem centenas de temas e coleções de ícones. Eu encorajo vocês a procurarem pelo visual com que mais se identificam e começar a tornar o sistema operacional mais próximo de você. Outra sugestão, se quiserem procurar é o conjunto de temas chamado Material, testem o Material Dark que também fica bacana.</p>
<p>Como eu disse antes, o instalador criou já um usuário pra você e cada novo usuário ganha um diretório próprio. Esse diretório fica em /home seguido do seu username. No caso o meu é akitaonrails e se você ficou com dúvidas de quem você é, você pode perguntar pro Linux com o comando <code>whoami</code>. A navegação por diretórios é usando o comando <code>cd</code>. Todo diretório tem 2 entradas padrão, o “.” que representa onde você está agora e o “..” que é o diretório anterior. Pra saber quais diretórios existe você usa o comando <code>ls</code> ou pra ter uma listagem mais completa faz um <code>ls -l</code> ou <code>ls -la</code> que vai te mostrar os diretórios e arquivos escondidos. O que determina o que é escondido ou não é só se o nome começa com ponto. Daí por padrão não vamos ver esses arquivos em programas como o Nautilus que falei antes.</p>
<ul>
<li></li>
</ul>
<p>Você pode criar arquivos de diversas formas, mas a mais simples pra criar um arquivo vazio é usar o comando <code>touch</code> que literalmente vai tocar o arquivo. Se já existir ele vai atualizar a data e hora de última modificação, se não existir, ele vai criar o arquivo. Aliás, pra todo comando do Linux, se você quiser rapidamente ver o que ele faz exatamente e quais opções o comando aceita, use o comando <code>man</code> que significa “manual” e não “homem”. Falando nisso, a maioria dos comandos e nomes legados de UNIX são acrônimos de poucas letras não porque a gente é masoquista, mas primeiro porque digitar comandos longos demora mais e segundo porque você precisa digitar esses comandos num terminal remoto dos anos 60. Era uma época onde você apertava uma tecla e tinha que esperar um pouquinho pra registrar no servidor e aparecer na tela, então era meio maçante ficar esperando. Se eu fosse simular seria mais ou menos assim (DELAY DIGITANDO)</p>
<ul>
<li></li>
</ul>
<p>Por isso os nomes são curtos. E pra piorar cada letra a mais que você escreve consome 1 byte (ou 2 hoje dia). Lembra quando eu contei sobre a história dos computadores eu mencionei que os grandes mainframes da época gravavam em fitas que tinham só algumas centenas ou milhares de Kbytes. Ou seja, cada letra contava. Hoje em dia não existe mais essa preocupação. De qualquer forma você precisa ir aprendendo o que significa cada comando. O comando <code>cd</code> pra mudar de diretório obviamente é change directory, o mkdir pra criar diretório é make directory, o comando <code>rm</code> pra apagar é remove, o comando <code>chown</code> é change ownership e assim por diante.</p>
<p>Você já sabe whoami pra saber “quem eu sou” no sistema, e pra saber onde estamos podemos usar o comando <code>pwd</code> que significa print working directory ou imprimir o diretório corrente. E vemos que estamos no /home/akitaonrails. Se navegarmos pra algum lugar aleatório no sistema como cd /usr/local e quisermos voltar pra nossa casa podemos fazer cd $HOME onde o cifrão denota uma variável do ambiente e você que é de Perl ou PHP deve estar mais familiarizado com essa notação. Mas cd $HOME é muito comprido, em vez disso podemos usar o atalho cd ~ til ou tilde que o shell vai expandir para o que estiver na variável $HOME e por isso chamamos isso de tilde expansion. Toda vez que você escreve ~/Documents o shell vai expandir pra /home/akitaonrails/Documents. Pra provar isso o comando echo do shell mostra a variavel, então echo $HOME mostra o diretório de casa e echo tilde também. Pra ir pro diretório de Downloads a partir de qualquer lugar basta fazer cd ~/Downloads. Se for só pra voltar pro diretório de casa nem precisa do tilde, só <code>cd</code> também funciona.</p>
<ul>
<li></li>
</ul>
<p>Quando falamos shell, na grande maioria dos casos estamos falando do famoso Bash, o Bourne Again Shell que eu mencionei no vídeo de Sua Linguagem não é Especial. Existem diversos outros shells como o tcshell e muitos desenvolvedores usam o Z shell que vou mostrar mais na frente. Mas quando executamos comandos no shell que é nossa linha de comando podemos estar executando binários do sistema, scripts com permissão de execução ou comandos diretos do Bash ou o shell que estivermos, isso pode confundir um pouco se você não souber qual dos 3 você está executando, comecem a prestar atenção nisso.</p>
<p>Voltando aos diretórios, se navegarmos pra raíz com cd / e listar o que tem lá podemos ver alguma coisas interessantes. Evita modificar qualquer coisa fora da sua home sem saber pra que serve. Bem na raíz temos só dois arquivos, esse vmlinuz e o initrd.img. Na verdade ambos são links simbólicos pra arquivos que estão no /boot. Um link simbólico é um atalho, o arquivo real mesmo está no diretório /boot como pode ver. O binário vmlinuz é o kernel do Linux propriamente dito, o primeiro binário que vai carregar logo que a máquina bootar e vai começar a carregar o sistema operacional e coisas como drivers. E o initrd.img é o segundo binário que vai carregar logo na sequência subindo um RAM disk. O vmlinuz tem só o mínimo necessário pra bootar e o resto dos módulos vem desse RAM disk carregado a partir do inird.img. É uma convenção de sistemas derivados de Debian como é o caso do Ubuntu. O motivo de ser um symbolic link ou symlink é que daí no diretório /boot podemos ter kernels de múltiplas versões e mudar de um pra outro só mudando o symlink se quisermos testar uma versão mais nova mas sem jogar fora a versão anterior.</p>
<p>Se listarmos o ls /dev podemos ver todos os dispositivos ligados nesta máquina. Alguns desses dispositivos serão coisas como drives USB, pendrives, cdroms ou até mesmo floppys. Pra gente poder gravar ou ler alguma coisa de um desses dispositivos precisamos primeiro “montar” eles com um sistema de arquivos como exFAT ou NTFS se for de Windows ou HFS+ se for de Mac ou ext4 se for de Linux e quando eles são montados normalmente criamos um subdiretório no /mnt ou /media. A maioria dos Linux modernos tem serviços pra montar automaticamente quando inserimos um USB e essas configurações ficam no arquivo /etc/fstab e podemos ver que ele tem a configuração pro caso de alguém inserir um disquete.</p>
<p>Vamos brincar um pouco. Se usarmos o comando df -h podemos listar os dispositivos que estão montados e quais são os pontos de montagem, veja o / por exemplo. Agora vamos plugar um pendrive e rodar o mesmo comando. Olha como o Ubuntu já automaticamente detectou e montou corretamente em /media/akitaonrailks/KINGSTON que era o nome do pendrive. O dispositivo de verdade está em /dev/sdb1 mas não adianta tentar executar comandos como cd ou ls nele porque não tem um sistema de arquivos ali, só no ponto de montagem. A menos que você esteja escrevendo um programa de mais baixo nível, você quase nunca vai mexer no que tem nesse /dev onde dev significa device ou dispositivo, e sim no que é montado em /media ou /mnt.</p>
<p>Seguindo, o /root é o equivalente home do usuário root que é o administrador da máquina, ainda temos o /opt onde alguns programas de fora podem ser instalados. No /sbin ficam muitos dos binários do sistema operacional. O programa shutdown fica lá. Programas pra gerenciar discos como fdisk pra reparticionar discos, o fsck pra checar o disco, o mkfs pra formatar, ifup e ifdown pra subir e derrubar placas de rede e coisas assim. No /bin fica outros programas do sistema como o próprio bash e outros shells, coisas simples como o cp pra copiar arquivos, chown e chmod pra mexer na permissão de arquivos, todos os programas pra navegar e criar diretórios como mkdir pra criar diretórios e rmdir pra remover diretórios, ou o próprio rm que apaga arquivos e vários outros são todos binários nesse diretório.</p>
<p>O diretório /usr é um dos maiores e onde fica a maior parte das aplicações que você instala. Ele significa Unix System Resources mas na prática você pode pensar nele como user ou programas dos usuários. Por exemplo, o X, os aplicativos do GNOME, o Firefox, todos esses binários ficam em /usr/bin, suas bibliotecas de dependência ficam em /usr/lib, se eles instalam código fonte junto deveria ficar em /usr/src, se você instala os pacotes -dev que trazem os arquivos de header em C ou C++ pra quando você precisa compilar dependências ficam em /usr/include e antigamente tinha o /usr/etc pra arquivos de configuração mas hoje em dia acaba ficando tudo em /etc ou em diretórios escondidos como .config no seu home pra configuração exclusiva do usuário.</p>
<p>Etc não tem um consenso de o que exatamente significa mas a maioria gosta de pensar que significa literalmente etcetera, bem coisa de programador mesmo. Finalmente temos o diretório /var contém dados variáveis, então antigamente a gente usava o /var/spool pra ser o a bobina de impressão quando a gente usava impressora, o /var/mail pra e-mails, o /var/log é onde vai todos os principais logs do sistema, o /var/run tem PIDs que são os IDs dos processos sendo executados, o /var/cache como o nome diz serve pra alguns caches do sistema.</p>
<p>Falando em processos, temos o /proc. Se você usar o comando ps consegue listar os processos dos aplicativos que estão em execução e eles tem um ID numérico. No diretório /proc esses processos são representados como diretórios e você pode fuçar ali. Por exemplo, vamos achar o PID do nosso shell Bash com <code>ps</code> e ir pro diretório dele com <code>cd /proc/aaaaaa</code> e se dermos ls podemos ver vários pseudo-arquivos que não são exatamente como um arquivo de texto que você cria mas do ponto de vista do sistema operacional, podemos operar neles como se fossem. Por exemplo, podemos usar o comando <code>less</code> pra fuçar esse arquivo chamado status ou esse arquivo chamado io pra ver um pouco das características desse processo em particular. Se você quiser entrar a fundo no mundo baixo nível, vai achar esse tipo de coisa particularmente interessante. Na prática, pra gente não tem muita coisa pra fazer aqui a não ser fuçar mesmo, mas se em algum momento você precisar fazer um programa que busca informações sobre os processos em execução, é por aqui que você vai começar. Em vez de ter alguma API complicada do sistema operacional, você pode fuçar tudo como fuçaria qualquer diretório e arquivos.</p>
<p>E falando nesses outros comandos, vamos aprender mais alguns comandos. Pra não sujar seu diretório vamos pro diretório /tmp na raíz do sistema. O /tmp é o diretório pra onde vai coisas temporárias que o sistema não garante que vão estar lá depois do próximo boot, por isso é bom pra gente jogar coisas que não nos importamos se perder. Então vamos fazer o seguinte exercício:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>cd /tmp
touch a.txt</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>serve pra tocar um arquivo como já expliquei, nesse caso vai criar um novo</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>echo &#34;hello world&#34; &gt; a.txt</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<pre><code>O echo serve pra escrever qualquer coisa no standard output, normalmente pro próprio shell mas aqui estamos conectando o standard output pra um arquivo com esse simbolo de maior. Então o hello world vai pra dentro do arquivo a.txt
</code></pre>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>cat a.txt
hello world</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<pre><code>O cat significa concatenate e serve pra concatenar arquivos mas vira e mexe usamos pra ver o conteúdo de arquivos pequenos. Evite usar cat pra arquivos grandes porque ele precisa ler tudo pra memória antes de mostrar
</code></pre>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>echo &#34;fabio akita&#34; &gt; a.txt
cat a.txt
fabio akita</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<pre><code>Se fizermos a mesma coisa com outro texto vamos ver que acabamos sobrescrevendo o que tinha antes. Então toda vez que você redireciona o standard out pra um arquivo desse jeito o conteúdo anterior morre. Mas podemos ir apendando ao fim do arquivo em vez de sobrescrever desse jeito:
</code></pre>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>echo &#34;hello world&#34; &gt;&gt; a.txt
cat a.txt
fabio akita
hello world</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<pre><code>Com o maior e maior agora podemos ir concatenando no fim do arquivo.
</code></pre>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>more a.txt
fabio akita
hello world</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<pre><code>O comando more aqui fez a mesma coisa que o cat. A diferença é quando você faz isso com arquivos maiores do que cabe na tela. Vamos dar um exemplo:
</code></pre>
<p><code>Ps aux</code>
Esse comando lista todos os processos rodando no sistema, incluindo os que não foi você que iniciou e sim o initd do sistema operacional e outros serviços. Você pode ver como ele não cabe na tela e você precisa scrolar no terminal pra ver o começo. Usando o comando more temos o seguinte:
<code>Ps aux | more</code>
Essa é uma das características marcantes dos UNIX e Linux: a capacidade de ligar o standard output de um comando ao standard in de outro comando usando o simbolo de pipe que é essa barra vertical. Eu expliquei sobre isso na minha série de Começando aos 40, por isso falei pra assistir. Mas veja como aqui ele começa a listar e pára na primeira tela e agora eu posso ir avançando aos poucos. O more é um comando antigo e primitivo, ele primeiro precisa carregar todo o conteúdo em memória pra depois ir mostrando tela a tela. Não é muito eficiente e não recomendo que faça isso com arquivos de log de gigabytes por exemplo. Na prática, você não precisa usar nem cat e nem more, existe uma versão mais moderna, o less:
<code>Ps aux | less</code>
O less faz a mesma coisa que o more, deixa você navegar por conteúdos longos que não cabem numa tela. Porém ele faz isso baseado em streams, como eu também expliquei na minha série. Em vez de carregar tudo na memória, ele vai puxando do stream só o que precisa pra preencher uma tela e navegar. Mais do que isso ele permite usar alguns dos mesmos comandos de navegação do editor de textos VI. Então você pode usar j k como cima, baixo,, você pode digitar “gg” minúsculo pra voltar pro topo do arquivo, pode digitar 10j pra descer 10 linhas ou 5k pra subir 5 linhas. E pode digitar barra com uma palavra que quer procurar e ir descendo usando n. E finalmente digitar q de quit pra parar.
<code>Ln -s a.txt b.txt</code>
Eu falei de links simbólicos ou symlinks antes e é assim que você cria: ln -s arquivo de origem e nome do symlink. Agora esse b.txt é só um atalho mas você pode usar ele como se fosse um arquivo, por exemplo se fizermos cat b.txt veremos o mesmo conteúdo de a.txt. Mas podemos fazer mais ainda.
<code>tail -f b.txt</code>
Tail é um comando pra ver o final do arquivo, você pode fazer tail -10 pra ler a 10 últimas linhas, ou pode fazer tail -f pra se pendurar no final do arquivo.
Pra demonstrar vamos abrir outro terminal e começar a apendar coisas no arquivo a.txt.
<code>echo “foo” &gt;&gt; a.txt</code>
Estão vendo como eu estou mandando coisas pro fim do arquivo a.txt mas o tail do symlink b.txt vai me mostrando o que está sendo gravado? São coisas assim que tornam o Linux um bicho diferente. Comandos como tail -f são super úteis quando você quer ficar monitorando um arquivo de log em produção por exemplo.
Eu mostrei rapidamente como podemos usar comandos como ps pra mostrar informações dos processos em execução, você pode pesquisar mais sobre os binários que estão nos diretórios /sbin ou /bin ou /usr/bin como falei antes. Mas com o conceito de pipes podemos ir mais longe e conectar o standard output de um comando ao standard input de outro comando. Por exemplo, vamos fazer
<code>Ps aux | grep bash</code>
E isso vai filtrar a saída do ps pra só mostrar as linhas que tem a palavra bash. O grep é um comando antigo que permite processar texto usando regular expressions similares de Perl 5. Hoje em dia usamos outros como o ag, que é o silversearcher. Ele aceita regex similares mas é muito mais rápido que grep. Se você não entendeu porque chama silversearcher é porque AG é o símbolo pra prata na tabela periódica. Mas digamos que estamos interessados em pegar os IDs de processo, os PIDs dos processos bash. Podemos ver que é a segunda coluna. Como filtramos por coluna? Uma das muitas opções é usar o AWK que é outra ferramenta super tradicional de UNIX e Linux e colocar outro pipe no fim desse comando:
<code>Ps aux | ag bash | awk ‘{ print $2 }’</code>
Olha o que aconteceu! Por padrão ele splita as linhas pelo separador padrão que é espaço, mas podemos configurar outros separadores incluindo regex também. O AWK é uma linguagem de programação interpretada, como um Perl, voltado a processar dados e textos.
Finalmente, digitamos vários comandos, e talvez você não se lembre de cor de tudo que digitou, ninguém lembra. Por isso shells como o Bash tem history, todos os comandos que você digitou até agora ficam gravados. Basta ir apertando a seta pra cima pra navegar pelos últimos comandos. Mas e se você quer lembrar dum comando que digitou sei lá, 2 semanas atrás? Se ficar apertando seta pra cima vai ficar fazendo isso até amanhã. Pra isso o Bash tem um atalho, digite Ctrl R e comece a digitar uma parte do comando. Agora vai apertando Ctrl R pra navegar pelo histórico filtrado pelo que acabou de digitar. Viu só?
De bônus deixa eu mostrar os últimos comandos que você precisa. Pra apagar um arquivo você faz: rm b.txt. Podemos criar um diretório com mkdir foo. Podemos mover um arquivo pra lá com mv a.txt foo. Se quisermos apagar um diretório só rm foo não funciona. Pra isso precisamos força com rm -f foo. E pronto, você já sabe o básico de como manipular diretórios, arquivos e comandos. Um comando que é complexo é o chmod e a regras de permissão mas por hoje entenda que todo binário ou script, pra ser executável precisa ter permissão de execução e a forma que você dá essa permissão é via o comando chmod +x seu_script.sh
A partir daqui é com você!</p>
<ul>
<li></li>
</ul>
<p>Veja e reveja essa demonstração que eu acabei de mostrar caso você seja um iniciante. Esses são os conceitos mais importantes que você precisa dominar pra seguir em frente. E dominar significa chegar num ponto em que você sequer pensa mais nisso. Se você usar o Nautilus que é que nem o Explorer, dá pra fazer tudo isso com o mouse. Arrastar, apertar F2 pra renomear ou DEL pra apagar um arquivo. Não tem problema. Mas quando você se conectar remotamente num servidor você não vai ter ambiente gráfico, só um shell. E por isso você precisa saber esses comandos. Mais do que isso, você precisa aprender a combinar os comandos como mostrei aqui com pipe pra fazer coisas como mover só arquivos com determinada nomenclatura pra outro diretório por exemplo, ou só arquivos que tenham determinado conteúdo.</p>
<ul>
<li></li>
</ul>
<p>E quando você precisa manipular muitos arquivos com critérios mais complicados assim, é onde programar scripts de Bash começa a fazer sentido. E sim, o Bash em si é um ambiente de programação que tem variáveis, comandos como if, e você pode executar um script que automatiza tudo pra você. E, claro, você pode combinar o Bash com outras linguagens como o AWK ou mesmo Perl, Python, Ruby ou outras linguagens e com alguns dos conceitos que mostrei pra vocês como saber que você tem seus dispositivos em /dev, seus processos representados em /proc, suas configurações em /etc e assim por diante, você pode fazer scripts que manipulam seu sistema inteiro. Aí você começa a se sentir realmente o dono da sua máquina. Tem bastante coisa pra estudar aqui.</p>
<ul>
<li></li>
</ul>
<p>Falando em outras linguagens de programação. Chegou a hora de avançarmos mais rápido e montarmos de uma vez esse ambiente. Como eu falei antes, até este ponto na instalação seu Linux está bom pra ser usado por usuários comuns. Mas pra virar sistema de desenvolvimento a primeira coisa que você precisa instalar são compiladores e todas as dependências de desenvolvimento do sistema. Pra isso vamos instalar os seguintes pacotes:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt install build-essential default-jdk libssl-dev exuberant-ctags ncurses-term ack-grep silversearcher-ag fontconfig imagemagick libmagickwand-dev software-properties-common git vim-gtk3 curl</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<ul>
<li></li>
</ul>
<p>O principal pacote é o build-essential que como o nome diz tem todo o essencial pra fazer builds. Aproveito também pra já instalar o JDK pra termos não só a JVM como o compilador do Java mais novo. Poderíamos instalar outras linguagens com o APT também como Ruby ou Python e outras, mas você precisa entender um problema desta atualidade de 2019. Linguagens mais antigas e mais estáveis como C, C++ e Java mudam com pouca frequência. De vez em quando sai patches de segurança mas não mudanças que quebram compatibilidade. Uma vez a cada X anos o C muda. Por isso é bom instalarmos via gerenciador de pacotes. Porém outras linguagens como Go ou Javascript mudam com muito mais frequência e os pacotes de distros Linux normalmente não acompanham tão de perto porque os objetivos são diferentes: as distros preferem manter versões estáveis, que já foram testadas em produção, que já receberam correções de bugs. Mas nós desenvolvedores preferimos ter acesso às versões mais instáveis justamente porque precisamos testar as coisas novas mesmo se não formos usar em produção.</p>
<ul>
<li></li>
</ul>
<p>Pior, nós trabalhamos em diversos projetos diferentes. Alguns projetos são novos e usam, por exemplo Ruby 2.6.3. Mas às vezes precisamos dar manutenção em projetos de 3 ou 4 anos atrás que podem estar ainda num Ruby 2.4.4 por exemplo. Significa que precisamos ter todas essas versões instaladas na nossa máquina ao mesmo tempo. O mesmo vale pra Javascript ou outras linguagens. Mas o gerenciador de pacotes de uma distro Linux só gerencia uma versão. Depois que ela atualiza, a versão antiga não existe mais. Então precisamos de um jeito por fora pra gerenciar isso. Ao longo dos anos cada linguagem veio construindo seu próprio gerenciador de versões como o RVM e RBENV no Ruby, ou o NVM do Javascript, ou o Virtualenv do Python. Mas também é um saco ter que ficar lembrando as sintaxes e configurações de tantas ferramentas diferentes. E pra nos salvar surgiu o gerenciador de versões Universal, o ASDF. Vamos instalar pra vocês verem.</p>
<p>(&hellip;)</p>
<p>Aliás, aprendam a usar o Google. Olhem como eu vou fazer. Eu falei ASDF, é um nominho que pode confundir o Google, coloquem github como termo se precisar. Vamos seguir o que diz na documentação pra instalar.</p>
<p>&ndash; instalar via Google</p>
<p>O truque do ASDF é usar variáveis de ambiente do shell. Quando você digitar ruby ou npm, ele não vai executar diretamente o binário chamado ruby. Na verdade ele vai procurar no PATH. Eu não falei de PATH então vamos dar echo no PATH. Tudo que você digita no shell, se não for uma instrução do próprio Bash ele entende como sendo um binário executável e vai procurar por ele nos diretórios listados nesse PATH. Você pode tentar saber de onde o Bash está executando determinado binário usando o comando <code>which</code> por exemplo o tal echo que acabamos de fazer se digitar <code>which echo</code> vemos o PATH completo dele, e aliás, o echo é um binário do sistema e não instrução de Bash.</p>
<p>Pra ficar mais fácil de gerenciar, o ASDF em si é um framework, ele não tem suporte a linguagem nenhuma. Em cima do ASDF precisamos instalar plugins. Então vamos instalar os diversos plugins pras linguagens. Leia as instruções. No caso de Javascript vemos que ele tem comandos pra instalar chaves públicas pra validar a instalação. No caso de Erlang vemos que ele manda instalar várias dependências do sistema, siga as instruções. linguagens, javascript, golang, erlang, elixir, kotlin, rust, crystal</p>
<p>Pronto, agora que instalamos os diversos plugins, podemos instalar as linguagens em si. Usamos o comando list-all do asdf pra listar quais versões estão disponívels pra instalar daí podemos fazer asdf install linguagem versão pra instalar a que queremos. Então vamos lá instalar o Ruby primeiro. Ao terminar, agora precisamos declarar que queremos usar essa versão e pra isso fazemos asdf global ruby 2.6.3 e se digitarmos ruby -v vemos que agora o Ruby está disponível. Dentro de um projeto antigo podemos usar asdf local ruby 2.4.4 depois de instalar a versão 2.4.4 pra só dentro daquele projeto ele escolher o Ruby mais antigo. E com isso resolvemos nosso problema de ter projetos que dependem de versões diferentes. Agora vamos fazer a mesma coisa pra todas as outras linguagens, javascript, golang, erlang, elixir, kotlin, rust, crystal</p>
<p>Digitem asdf help pra ver outros comandos mas os próprios plugins podem precisar de atualização e pra isso podemos fazer asdf plugins-update. E pra atualizar o asdf de vez em quando podemos fazer asdf update. Agora, se fizermos <code>which ruby</code> vemos que ele executa um script nesse diretório de reshims. Todo script executável que um ruby instalaria talvez num /usr/local/bin agora é instalado nesse reshim. Um NPM do javascript também ou outro pacote de Javascript como yarn que você instala com a flag de -g pra global. Se por acaso você instalar uma biblioteca que deveria ter um executável no PATH como webpack ou yarn mas ele não é encontrado quando você digita, pra garantir que está tudo bem, digite asdf reshim pra ele recriar esses shims, que são como proxies.</p>
<ul>
<li></li>
</ul>
<p>De qualquer forma, agora que instalamos e declaramos quais versões queremos que estejam ativas globalmente, temos acesso a todas as linguagens que quisermos. Em particular essas são as linguagens que mais me interessam hoje em dia. Mas existem dezenas de outros plugins pra tudo que é linguagem que você imaginar. Tem até coisas velhas como Prolog ou linguagens modernas como Julia. Procure e instale o plugin que você precisa e divirta-se.</p>
<p>(&hellip;)</p>
<ul>
<li></li>
</ul>
<p>Agora que instalamos todas as linguagens, vamos instalar alguns serviços que você provavelmente vai precisar. Eu sempre gosto de deixar instalado o Postgresql, o Redis e o Memcache. Um banco de dados relacional decente, um nosql que faz o mínimo que precisamos, e um cache pra quando não precisamos do Redis como banco. Tá, vou deixar instalado o Mongodb também, mas se você viu minha série de devops já sabe que eu não recomendo que você escolha Mongo como banco primário sem saber se realmente precisa. E normalmente não só você não precisa como você pode acabar usando o Mongo onde na verdade o mais adequado teria sido o Postgresql. Na dúvida, sempre escolha o Postgresql como padrão, nunca o Mongo, nem muito menos o Redis. Redis é um bom cache. E Mongo é bom pra dados que se você perder, não vai fazer muita falta, como dados de analytics ou logs.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt install postgresql-10 postgresql-contrib postgresql-server-dev-10 redis-server libhiredis-dev memcached libmemcached-dev</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pra instalar o Mongo precisamos seguir as instruções do site oficial. Nem vou deixar o link nas descrições, vocês precisam aprender a fazer um google por mongo install ubuntu 18.04 que vai aparecer o link certo. <a href="https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/"target="_blank" rel="noopener">https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/</a></p>
<p>Ao que parece, os pacotes do Mongo não estão nos repositórios oficiais do próprio Ubuntu e isso é comum com software de terceiros. Pra começar precisamos instalar as chaves públicas do MongoDB pra validar os pacotes que vamos instalar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Agora precisamos adicionar os repositórios do Mongo na lista de repositórios do gerenciador de pacotes APT e puxar a lista de pacotes:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>echo &#34;deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse&#34; | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list

sudo apt-get update</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Esse comando tee, é parecido com o que eu mostrei antes com o &raquo; pra apendar novas linhas no final de um arquivo. O que acabamos de fazer foi dizer pro APT procurar pacotes nesse endereço novo também.</p>
<p>Agora podemos instalar o mongo em si:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt-get install -y mongodb-org

sudo service mongod start</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Tanto Postgresql, Redis, Memcache e Mongo vem com daemons que podem carregar sozinhos depois do boot do sistema. Se você tem bastante memória sobrando pode deixar eles ativos que não vai fazer diferença. Se precisar derrubar ou restartar basta usar o comando service mongod stop ou restart. Porém, se você prefere que eles não carreguem automaticamente, você pode fazer service mongod disable e depois fazer service mongod start manualmente toda vez que precisar.</p>
<p>Esse comando service é importante de lembrar no Ubuntu. Ele executa esses comandos start ou stop que estão declarados no que chamamos de um init script. Esses scripts ficam em /etc/init.d por exemplo vamos ver o que tem no do redis fazendo
<code>cat /etc/init.d/redis-server</code></p>
<p>E podemos ver cada um dos comandos de start, stop, status e o que eles fazem quando são chamados. Podemos nem usar o comando service e ir direto no script também:
<code>sudo /etc/init.d/redis-server status</code></p>
<p>Mas o comando service é mais simples de lembrar. Em outros sistemas operacionais usando Systemd pra controlar daemons também existe o comando systemctl. A diferença é que com o comando service a gente faz service [nome do serviço] e [comando] tipo service mongod start. Mas o systemctl é o contrário e fazemos systemctl start mongod, eu sempre me confundo. Antigamente o Ubuntu usava o Upstart e hoje usar o Systemd. Existe uma grande controvérsia em torno desse systemd mas hoje não vou fazer essa tangente. Na prática pra você é importante só lembrar que existem serviços e daemons e é assim que você gerencia esses serviços.</p>
<p>De qualquer forma, memcache, redis e mongo, por padrão não precisam de senha pra conectar nos servidores, por isso por padrão você jamais deve expor esses servidores na internet. O Postgresql você precisa configurar usuários pra conectar no servidor e pra fazer isso você precisa se logar como o usuário postgres e de lá criar novos usuários. Se tentarmos usar o cliente de posgresql que é o psql ele vai dar erro. Então pra criar um novo usuário precisamos fazer:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo su postgres
createuser --interactive - aqui crie um usuário com o mesmo nome do usuário que você está usando pra logar no sistema, isso vai facilitar sua vida
createdb akitaonrails - e crie um banco de dados com o mesmo nome do seu usuário
Exit</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<ul>
<li></li>
</ul>
<p>Pronto agora se fizermos psql provavelmente vamos logar direto no shell do postgresql. Viu? Agora quando estiver desenvolvendo sua aplicação, seu framework favorito provavelmente vai conseguir conectar fácil sem precisar declarar senha nem nada. Obviamente isso é pra ambientes de desenvolvimento. Em produção você não vai conectar num usuário que é superuser. Mas está fora do escopo deste episódio fazer tutorial de Postgresql pra produção. Mas você já sabe o que fazer: GOOGLE.</p>
<ul>
<li></li>
</ul>
<p>Tem gente que prefere não instalar esses serviços diretamente, pelo mesmo motivo que usamos ASDF. E se você tem um projeto antigo que depende do PostgreSQL 7 e quebra se tentar conectar no Postgresql 10? Pra isso precisamos de algo parecido com um ASDF. E se não me engano acho até que o ASDF tem suporte pra Postgresql, vamos ver no google, e sim, tem mesmo. Mas se for esse o caso eu prefiro fazer diferente. Serviços como os que acabamos de instalar é o caso de uso perfeito pra usar Docker. Então é hora de instalar e configurar Docker. E a essa altura você já adivinhou: vamos pro GOOGLE.</p>
<p>Seguindo as instruções, primeiro ele recomenda apagar versões antigas, caso você tenha. Como esta demonstração começou do zero, não precisamos fazer isso. Então vamos pular esse passo e instalar direto o que precisamos:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common


curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Mesma coisa que fizemos com o Mongo, instalamos chaves públicas do povo do Docker pra validar os pacotes. Se você não entendeu, todo pacote que vem nos repositórios oficiais do Ubuntu são assinados digitalmente pela chave privada do povo da Canonical que faz o Ubuntu. Mas quando adicionamos repositórios externos, eles são assinados por outras chaves. Então primeiro instalamos a chave pra depois instalar os pacotes. Esse passo é importante porque caso você seja enganado a instalar manualmente pacotes que foram modificados por um hacker, ele não vai ter a chave privada da Canonical então teoricamente o APT vai recusar instalar esse pacote. Claro, se você for enganado a instalar a chave do hacker também, aí já era, então sempre preste atenção no que está fazendo. Veja como no caso do comando anterior estamos instalando a chave vinda do domínio docker.com e não de um domínio com cara de russo.</p>
<p>Agora que instalamos as chaves, assim como fizemos com o Mongo vamos adicionar novos repositórios pro APT. A diferença é que na instrução do Mongo usamos o comando tee pra adicionar o arquivo com o repositório manualmente e aqui estamos usando o comando add-apt-repository que vem no pacote software-properties-commons.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo add-apt-repository \
   &#34;deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>De bônus, como eu sei que o add-apt-repository vem no software-properties-commons? Porque eu posso checar com o comando dpkg -L software-properties-commons. Viu?</p>
<p>Enfim, agora precisamos puxar a lista de pacotes novos com apt update e instalar os pacotes do Docker propriamente ditos:</p>
<p><code>sudo apt-get install docker-ce docker-ce-cli containerd.io</code></p>
<p>Você devem ter notado que eu uso o comando apt e muitas instruções vem com apt-get. Na prática apt é o jeito novo, mas apt-get ainda funciona. De qualquer forma agora temos os pacotes todos instalados. Mas o Docker ainda tem um pequena configuração: ele cria um grupo de usuários chamado docker e o usuário que vai gerenciar o Docker precisa estar nesse grupo, então vamos fazer o seguinte:</p>
<p><code>sudo usermod -aG docker $USER</code></p>
<p>Você já sabe que existe a variável $HOME que o tilde expansion usa, e o whoami que eu mostrei lá no começo usa essa variável $USER que tem o nome do seu usuário. Se quiser ver todas as variáveis do ambiente, digite o comando <code>set | less</code> pra ver as dezenas de variáveis que estão disponíveis no seu ambiente. Mas enfim, agora que nosso usuário está no grupo, acho que precisamos deslogar e logar de novo. Vamos restartar pra garantir.</p>
<p>Pra testar, basta fazer docker run hello-world e se tudo deu certo ele vai baixar a imagem de Docker de uma aplicação que só imprime um Hello. Mas nós estávamos falando em baixar o Postgresql, então vamos fazer isso. Você já sabe a rotina: GOOGLE (hackernoon)</p>
<p><code>docker pull postgres</code></p>
<p>O comando docker pull baixa a imagem mais recente. Agora vamos criar um diretório externo pra onde o postgres vai gravar os bancos de dados e tudo mais:</p>
<p><code>mkdir -p $HOME/docker/volumes/postgres</code></p>
<p>Agora vamos nos certificar que o postgresql que instalamos nativamente no sistema agora a pouco está desligado com sudo service postgresql stop e sudo service postgresql status. Agora podemos iniciar o Postgresql via Docker que acabamos de instalar:</p>
<p><code>docker run --rm   --name pg-docker -e POSTGRES_PASSWORD=docker -d -p 5432:5432 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data  postgres</code></p>
<p>Teoricamente agora podemos usar o cliente nativo psql pra conectar nesse docker assim:</p>
<p><code>psql -h localhost -U postgres -p</code>
Senha postgres</p>
<p>Pronto!! Estamos no postgresql. E se seu projeto tiver configuração pra Docker Compose, você pode subir sua aplicação web num container, seu postgresql em outro container e tudo gerenciado pelo Docker. E aproveitando que falei de Docker. Vamos dar um ps aux na máquina e você vai ver que o postgresql está visível (!!). Pra você que ainda acha que Docker é uma máquina virtual, ele não é. O postgresql está subindo normalmente, nativamente, em cima do mesmo kernel que você está. Agora vamos pegar o PID do processo e dar um cat /proc/PID/cgroup. Lembram do meu episódio sobre containers e virtualização quando expliquei que o cgroup é um jeito do sistema operacional mentir pro processo? Compare com a configuração de cgroup do bash por exemplo (ps | grep bash; cat /proc/PID/cgroup). Essa é a configuração normal pra um processo que enxerga o sistema todo e em cima vemos como é o cgroup que o Docker configura pro processo não enxergar o sistema todo. É assim que o Docker funciona e é por isso que ele é tão leve: ele está rodando lado a lado com seus outros programas.</p>
<p>Eu recomendo que você pegue qualquer tutorial pra aprender os comandos básicos. Aqui acabamos de ver o docker run e docker pull, também tem o docker ps pra mostrar os containers rodando a partir de onde podemos pegar o nome do container e o docker stop [nome do container] pra parar o postgres que acabamos de subir. Tem comandos pra gerenciar os volumes de disco virtuais, pra baixar versões diferentes desse postgres, e assim por diante. E como eu já falei, aprenda a usar Docker Compose pra criar um mini cluster de containers que conseguem acessar uns aos outros.</p>
<p>(&hellip;)</p>
<ul>
<li></li>
</ul>
<p>Já que eu mencionei chaves, vou aproveitar pra fazer uma explicação super porca. No mundo de criptografia existem pelo menos 3 tipos de tecnologias que você precisa saber. Existem algoritmos de digest, que literalmente digere qualquer blob de bits e devolve uma impressão digital de tamanho fixo. Exemplos disso são os antigos MD5 ou SHA1  e coisas mais novas como SHA512 ou Bcrypt ou HMAC. Você pode passar pra eles uma palavra ou a Wikipedia inteira e eles vão sempre cuspir um string de tamanho fixo. Isso você usa pra garantir que a informação não foi adulterada porque se você mudar um bit nessa Wikipedia que eu falei, a impressão digital vai ser completamente diferente. A gente usa isso pra tudo hoje em dia, sempre que você ver strings com caracteres que parecem aleatórios, normalmente é um fingerprint, ou impressão digital.</p>
<p>A segunda categoria são os algoritmos de encriptação reversível. Aqui é o que a maioria das pessoas pensa quando pensa em criptografia: uma forma de bagunçar a mensagem e ter uma senha. E quando passar a senha a mensagem é descriptografada. De novo você tem coisas antigas como o Triple DES ou Blowfish e coisas mais recentes como o AES que é usado pra criptografar seu HD por exemplo. Quando você vê nos filmes alguém tentando quebrar uma encriptação em força bruta ou algo assim, normalmente é um algoritmo reversível ou mais corretamente chamada de criptografia simétrica.</p>
<p>Finalmente, temos criptografia assimétrica. Nessa categoria temos a geração de duas chaves que costumam ser dois números primos relacionados. Por convenção chamamos um desses números, tanto faz qual, de chave privada e ela nunca deve sair da máquina de onde foi criada. O outro número chamamos de chave pública e ela pode ser distribuída por aí, como as chaves que instalamos do povo do Mongo e Docker antes. Tudo que for criptogrado pela chave privada só pode ser aberta pela chave pública e vice-versa. O que é criptografado com uma chave não pode ser aberta com a mesma chave, necessariamente precisamos da outra. Esse é o conceito de chaves públicas e privadas.</p>
<p>Eu expliquei tudo isso porque na nossa instalação, se você ainda nao fez isso, precisa ter seu próprio par de chaves. Serviços como GitHub ou GitLab ou tudo da Amazon AWS ou Google Cloud ou Azure, exigem que você cadastre sua chave pública na sua conta, daí o que você criptografar com sua chave privada local pode ser checada com a pública que você cadastrou e assim podemos nos certificar que você é realmente você.</p>
<p>(&hellip;)</p>
<p>Pra criar uma chave é simples, no terminal fazemos:</p>
<p><code>ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id_ed25519 -C &quot;boss@akitaonrails.com&quot;</code></p>
<p>Normalmente a maioria dos tutoriais vai mandar você criar uma chave com algoritmo RSA mas hoje em dia  preferimos usar a ed25519 por ser mais segura. Ela vai pedir um passphrase, que de preferência como o nome diz é uma frase secreta grande que você não vai esquecer. Esse comando vai criar dois arquivos no diretório .ssh do seu home, o id_ed25519 e o id_ed25519.pub, que se você prestou atenção, representam a chave privada e a chave pública. Vamos ver o que tem dentro:</p>
<p><code>cat ~/.ssh/id_ed25519</code></p>
<p>Eu estou mostrando aqui a chave privada e não deveria obviamente, mas eu nunca vou usar essa chave de verdade, a minha está bem guardada. Mas só pra vocês verem como se parece uma chave privada. Faça backup do seu diretório .ssh que tem essas chaves. Se você perder a chave, não tem mais como recuperar só a partir da pública, obviamente. Toda vez que você precisar cadastrar sua chave, por exemplo num servidor SSH de alguém, vai precisar mandar o conteúdo do outro arquivo:</p>
<p><code>cat ~/.ssh/id_ed25519.pub</code></p>
<p>Isso é sua chave pública. Essa você pode mostrar pra qualquer pessoa. É essa chave que você cadastrar na Amazon ou no GitHub, por exemplo nessa página deles (mostra GITHUB).</p>
<p>Pra você não ter que ficar digitando a passphrase toda hora, na sua máquina precisa ter o serviço ssh-agent. Você checa se ele tá rodando assim:</p>
<p><code>eval &quot;$(ssh-agent -s)&quot;</code></p>
<p>Agora adicione sua nova chave no agente, daí ele só vai pedir sua passphrase uma vez e você pode ficar se logando nos servidores SSH que precisar sem toda hora ter que redigitar a passphrase:</p>
<p><code>ssh-add ~/.ssh/id_ed25519</code></p>
<p>Muito bem, agora você é um cidadão respeitável e criptograficamente identificável na nossa sociedade. NUNCA  mas NUNCA compartilhe sua chave privada. E faça backup num pendrive que você vai guardar num cofre ou algo assim. Enfim, cuide da sua chave, ela é sua identidade. Se por acaso perder, gere outra e substitua a chave pública em todos os servidores e serviços que tem acesso. Quem tiver sua chave privada tem acesso a tudo que você tinha acesso.</p>
<p>E já que falamos em Github, falta configurar o Git também. Existem milhares de bons tutoriais pra iniciantes no GOOGLE então aprenda de uma vez porque isso é obrigatório, mas a primeira coisa que você precisa fazer é configurar seu nome e seu email assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>git config --global user.name &#34;AkitaOnRails&#34;
git config --global user.email &#34;boss@akitaonrails.com&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<ul>
<li></li>
</ul>
<p>Isso é a configuração global padrão. Então todo commit que você fizer vai com essa identificação. E se você quiser usar nomes e e-mails diferentes pra projetos diferentes, você pode configurar no arquivo .git/config em cada projeto também, assim você pode ter e-mail pessoal nos projetos pessoais e e-mail da empresa em projetos de clientes se fizer muita questão. Eu uso sempre meu pessoal pra tudo.</p>
<ul>
<li></li>
</ul>
<p>Pronto, agora temos os principais pacotes de desenvolvimento instalados, temos todas as linguagens que vamos precisar, temos até bancos de dados e docker instalados. Agora vem uma parte que é muito particular só pra mim. Eu gosto muito de usar VIM como editor de textos. Hoje em dia você pode ser virar muito bem com Visual Studio Code que eu recomendo como uma das melhores opções modernas, seguindo do bom e velho Sublime Text 3. Tem o Atom do GitHub também mas eu acho que o Atom é muito pesado por ser totalmente em Electron e eu prefiro evitar Electron como eu evitaria uma praga. O VS Code tem partes em Javascript mas se não me engano ele usa uma toolkit híbrida com componentes nativos e isso torna ele mais responsivo. Porém tanto VS Code quanto Atom, por terem muito Javascript por baixo, é que nem uma aba de Google Chrome: come memória como se não houvesse amanhã. O Sublime Text 3 é totalmente nativo e extremamente leve. E o VIM obviamente é mais leve ainda. Eu gosto de editores de texto que eu chamo e abrem instantaneamente, em milissegundos pra ser mais exato, senão eu me entedio muito rápido.</p>
<ul>
<li></li>
</ul>
<p>Na realidade o GVIM já está instalado. O VIM é um editor que você abre na linha de comando, mas existe o VIM-GTK que é o mesmo VIM só que aberto dentro de uma janela gráfica de GNOME e com algum suporte básico a mouse também. Tanto faz qual dos dois você vai usar. Na verdade faz diferença. Aqui eu vou dividir o caso de uso pra usuários como eu que tiveram história usando tantos ambientes puramente de texto e também ambientes gráficos como Mac e aqueles que tem a oportunidade de começar sem vícios só no ambiente de texto do Linux. Agora eu vou mostrar a combinação que a maioria dos veteranos de Linux realmente gostam. Vamos instalar o TMUX, o sucessor do lendário GNU Screen que a gente usava antigamente.</p>
<p>(..)</p>
<p>Pra instalar é simples: <code>apt install tmux</code>.</p>
<p>O TMUX é um multiplexer de terminal. Esse palavrão significa que você ganha a capacidade de ter mútiplas sessões de terminal dentro de um único terminal. Lembram os workspaces gráficos do GNOME que seria como se fossem monitores virtuais? O TMUX são terminais virtuais. Você inicia com o comando tmux. Aqui ainda não tem nada demais, parece o mesmo terminal de sempre. Vamos abrir um VIM agora e editar alguma coisa. O básico de VIM é que ele tem dois modos, modo de comando e modo de edição. Ele sempre está no modo de comando, mas apertando comandos como i ou a de insert ou append, você entra no modo de edição. Agora você pode editar normalmente e quando terminar aperte ESC e volta pro modo de comando. Agora podemos gravar o arquivo com o comando :w /tmp/teste.rb por exemplo. Nesse modo também podemos navegar, por exemplo com as teclas hjkl que no teclado ficam um do lado do outro e servem como setas. Podemos fazer gg ou G pra ir pro começo ou fim do arquivo. Podemos combinar comandos como 10l pra andar 10 caracteres pra direita. E pra sair do VIM apertamos ESC pra garantir que estamos no modo de comando e fazemos :q pra dar quit. Isso é o mínimo do mínimo pra você navegar no VIM. Mas voltando ao TMUX.</p>
<p>Digamos que eu queira executar esse script idiota que eu acabei de fazer. Eu posso agora apertar a combinação Ctrl b % e boom temos um split do terminal. Com Ctrl b O eu posso navegar pelos painéis. Ctrl b “ faz split em outra direção. E Ctrl b w fecha o painel. Fala que isso não é bem foda. Tanto TMUX quanto VIM tem essa funcionalidade de split horizontal e split vertical que eu acho ultra útil e sei lá porque razão nenhum outro editor de textos tem exatamente a mesma funcionalidade. Terminais que fazem split tem vários hoje como o Tilix que vamos instalar já já, ou o iTerm2 em MacOS.</p>
<p>Mas o que torna o TMUX diferente é o seguinte: e se eu fechar o aplicativo do Terminal inteiro? Vamos fazer isso. Se fosse no Terminal normal ou num iTerm2 da vida, você acabou de perder tudo que estava fazendo e vai ter que abrir tudo. Mas não no TMUX eu posso fazer o comando tmux ls, pra listar as minhas sessões e olha só: tem uma sessão ativa. Agora posso fazer
tmux attach-session -t 0 que é o número da sessão e boom, tudo exatamente com eu tinha deixado. Isso era particularmente útil quando você só tinha terminais burros conectados remotamente num servidor via TELNET porque e se a conexão caísse bem quando você estava no meio de uma edição de código? Você perdia o que estava fazendo. Mas se estivesse usando o GNU Screen a sessão permanecia rodando no servidor, você podia esperar a conexão voltar, conectar de novo com seu terminal burro e recuperar a sessão que ainda estaria ativa.</p>
<p>Acho que isso deve convencer vocês a aprender tmux. Da próxima vez que precisar se conectar via SSH num servidor remoto pra fazer alguma coisa que vai demorar, abra um TMUX primeiro. Se por acaso der pau na sua máquina ou na sua conexão por alguma razão, você não vai perder nada que estava fazendo. Basta reconectar e dar attach na session que ainda vai estar ativa lá. E pra ser ainda mais versátil, você pode ver que já tem paineis demais aqui né? Vamos criar uma outra janela inteira com Ctrl b c e agora podemos navegar com Ctrl b n. Ou seja, você pode estar fazendo várias coisas em paralelo em múltiplas janelas de terminais splitadas em múltiplos painéis e você não vai perder nada caso feche essa janela. No final você pode fazer Ctrl b d pra desatachar manualmente. Se quiser mesmo fechar tudo que estava aberto na sessão você pode fazer tmux kill-session -t 0. Pra saber todos atalhos de teclas e comandos que o tmux aceita, o man tmux vai ajudar muito.</p>
<ul>
<li></li>
</ul>
<p>Pronto, com isso você tem o ambiente perfeito. Mas ainda falta mais uma coisa. O VIM puro é bem inútil na verdade, ele não é muito diferente de um NANO que você vê em muito tutorial. Eu particularmente fico irritado de ver o nano. O nano é derivado do antigo editor PICO que era o editor do cliente de e-mails antigo chamado PINE que eu inclusive usei muito na faculdade no meio dos anos 90. PICO era conterrâneo do editor JOE que por sua vez era inspirado no editor de MS-DOS, o Wordstar que eu usava no fim dos anos 80. São editores velhos, cansados, que eu não teria coragem de usar hoje em dia pra programar.</p>
<p>O VIM, assim como o Emacs são extremamente versáveis porque são scriptáveis. O Emacs em Emacs Lisp ou eLisp e o VIM em VimScript. Por causa disso podemos adicionar funcionalidades modernas como colorização de sintaxe pra cada linguagem, auto complete e muito mais. Infelizmente eu nunca tive muito saco pra aprender Emacs e o Vim sempre foi suficiente pra mim. Ele é leve e tem todas as funcionalidades que eu preciso. Mais do que isso: ele é perfeito pra editar coisas remotamente via SSH se precisar. Ele foi feito pra ter comandos e atalhos curtos, pra era onde conexões de rede eram lentas. E isso é perfeito porque mesmo hoje em dia ainda temos que lidar com conexões lentas ou instáveis de vez em quando.</p>
<p>E aqui vem a parte que é bem subjetivo ao mesmo próprio gosto. Por isso esta parte é opcional e você vai encontrar outras configurações diferentes. Até agora estávamos usando o Terminal que já vem no Ubuntu, eu prefiro usar o Tilix como já falei. Eu também prefiro usar o Z Shell em vez do Bash e eu tenho um conjunto de dotfiles que eu já me acostumei e gosto bastante.</p>
<p>Então vamos instalar:</p>
<p><code>sudo apt install tilix zsh</code></p>
<p>Feito isso agora é hora de instalar os dotfiles que eu gosto. Lembre dessa palavra dotfiles. Eu já expliquei que todo arquivo ou diretório que começa com ponto é escondido, e no seu diretório home vai começar a aparecer vários assim como o .config que o GNOME usa pra colocar configurações ou o .gcloud se você configurou as ferramentas do Google Cloud. Mas do que isso tem .vim pra configurações do VIM. Mas existem vários projetos no Github com dotfiles pré-prontos, um dos mais famosos pra ZSH é o Oh-my-ZSH que é bem customizável mas eu prefiro o do usuário SKWP que se instala assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sh -c &#34;`curl -fsSL https://raw.githubusercontent.com/skwp/dotfiles/master/install.sh `&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Ele precisa de Ruby, por isso já instalei via ASDF lá atrás. Vamos entrar no diretório .yadr e rodar rake update e deixar ele trabalhar.</p>
<p>Pronto, no final ele vai instalar temas como o Solarized Dark, vai configurar o prompt pra mostrar o branch de Git que você está e deixa tudo organizado no lado do ZSH e do VIM pra você customizar e adicionar novos plugins se precisar. Por exemplo, eu quero mudar a fonte do VIM pra ser a fonte Hack que instalamos antes. O VIM tem uma tecla especial chamada de Leader que dependendo do dotfiles pode estar assinalada pra qualquer coisa mas neste pacote é a vírgula. Com virgula T eu posso procurar por arquivos como o Ctrl P no Sublime ou VS Code. Vamos abrir o yadr-appearance. Olha como está tudo colorido corretamente. Vamos navegar e adicionar a fonte.</p>
<p>No Tilix também quero mudar o tema pra ser Dark e usar Solarized com fonte maior e bordas menores. E também mudar o atalho de splitar a tela que seria Ctrl Alt D para outra coisa como Ctrl Alt E e a razão disso é porque no Ubuntu esse atalho já é usado pra esconder a janela. E pronto. Veja porque eu disse que aqui é uma questão de que tipo de usuário você é. Você pode usar um terminal maximizado com TMUX e splitar pra ter o VIM de um lado e o terminal do outro pra você trabalhar, OU, no caso de alguém como eu que já se acostumou ao iTerm2 no Mac e MacVim, eu prefiro deixar um terminal aberto de um lado que eu posso facilmente splitar com Ctrl Alt E e Ctrl Alt R e navegar com ALT e numero do terminal e do outro lado o GVIM que eu também posso splitar usando ss ou vv e navegar com ctrl shit e as teclas de navegação hjkl.</p>
<p>Só pra exibir essa versão customizada de vim, veja como eu posso facilmente substituir uma palavra inteira com ciw ou usar o pacote de git pra dar um :Gblame ou :Gdiff, ou então abrir um explorador de arquivos inteiro que é o NerdTree com Alt Shift N e os comandos de navegação são os mesmos pra painéis splitados então ctrl alt l ou j. E :q fecha cada painel. :w grava. :e serve pra abrir outros arquivos. Posso usar :Ag que se integra com o silversearcher pra procurar rapidamente em todos os arquivos do projeto.</p>
<ul>
<li></li>
</ul>
<p>E agora sim, eu tenho tudo que eu preciso instalado. Se eu estiver no humor de usar 100% terminal, posso abrir o TMUX com o VIM de linha de comando, ou se eu quiser ficar no mundo híbrido gráfico posso usar os splits de Tilix com GVIM. Tanto faz, contanto que você tenha todos os atalhos e shortcuts pra ser produtivo. Na prática o jeito 100% é o melhor porque evita que você precisa ficar toda hora usando o mouse, e isso é uma das coisas que vai evitar que você tenha tendinite no futuro. Por isso quanto mais você aprender os shortcuts de TMUX e VIM, menos você vai precisar usar o mouse e isso sempre vai ser mais produtivo mesmo. Fora que as mesmas ferramentas que você usar na sua máquina de desenvolvimento, você também vai poder usar remotamente via SSH num servidor. E só de bônus, você pode compartilhar sessões de TMUX com outro usuário via SSH pra fazer pair programming remoto. Eu não vou mostrar aqui hoje mas você já sabe no GOOGLE você acha como.</p>
<p>Pra finalizar o vídeo de hoje, se você vai usar esse Linux que acabou de instalar como sua máquina primária, tem uma última coisa que você vai precisar fazer se quiser assistir vídeos online. Os codecs de H.264 ou mp3 e outros não são free software, então você precisa habilitar o que o Ubuntu chama de repositórios restritos. A forma de fazer isso é instalando o pacote ubuntu-restricted-extras pelo apt.</p>
<p>Esses repositórios são considerados restritos porque na instalação base vem tudo que é 100% código aberto. É parte da Filosofia do mundo de Software Livre que você deveria boicotar tudo que não tem código-aberto ou usa licenças que não são de software livre. E eles tem bons argumentos, porém, eu não sou ativista, eu prefiro ter o melhor dos dois mundos sempre. Minha produtividade nunca vai ser boa se eu tiver ideologias extremistas. Dou meus parabéns a quem vem lutando pra conseguir ter o máximo de código-aberto no mundo, mas no mundo real nem sempre isso é possível e eu prefiro não me restringir.</p>
<p>O Ubuntu vem por padrão com o Firefox e eu recomendo que você tente mesmo usar o Firefox como seu navegador primário, o mundo está sendo monopolizado pelo Google Chrome e mesmo navegadores como o novo Microsoft Edge, o Brave e o Opera usam a mesma engine do Chrome. Novamente, eu preferia que o mundo tivesse mais opções, mas na realidade se você é um programador web, vai precisar se certificar que sua aplicação tanto em Firefox quanto em Chrome, então você precisa instalar o próprio Chrome do Google ou a versão aberta que é o Chromium e pra instalar é via apt install chromium-browser.</p>
<p>Procure por Ubuntu 18 post-install e veja o que os outros fazem logo depois do primeiro boot. Você vai achar como instalar outros aplicativos úteis pra você como Spotify, Discord, Skype e muito mais.</p>
<p>E meu deus do céu, esse vídeo deu MUITO trabalho, mas eu precisava ter ele gravado pra poder referencias nos próximos vídeos, assim quando eu quiser mostrar a parte de programação de verdade ninguém vai poder dizer que não sabe o que é Docker, Postgres, ASDF, Vim e muito menos que não sabe como instalar, porque eu vou mandar sempre pra cá. Obviamente se você é iniciante deve ter ainda muitas dúvidas, então mandem nos comentários abaixo. Se tudo isso que eu falei você já sabia contribuem mandando mais dicas e ajudando a galera que tá começando agora nos comentários também. Se curtiram esse vídeo mandem um joinha, assinem o canal, e cliquem no sininho pra não perder os próximos episódios. Compartilhem o vídeo com seus amigos. A gente se vê semana que vem, até mais!</p>
]]></content:encoded><category>linux</category><category>ferramentas-de-desenvolvimento</category><category>tutoriais</category><category>akitando</category></item><item><title>Rodando Arch Linux sobre o Windows 10!</title><link>https://akitaonrails.github.io/2018/04/29/rodando-arch-linux-sobre-o-windows-10/</link><guid isPermaLink="true">https://akitaonrails.github.io/2018/04/29/rodando-arch-linux-sobre-o-windows-10/</guid><pubDate>Sun, 29 Apr 2018 22:06:00 -0300</pubDate><description>&lt;p&gt;Ok, quem acompanha meu blog há um ano ou dois sabe como eu &lt;a href="http://www.akitaonrails.com/archlinux"target="_blank" rel="noopener"&gt;curto o Arch Linux&lt;/a&gt; — em particular o Manjaro com GNOME.&lt;/p&gt;
&lt;p&gt;Também continuo bastante intrigado com a ideia do Windows Subsystem for Linux (WSL), que estreou de verdade na &lt;a href="http://www.akitaonrails.com/2016/07/26/o-ano-do-linux-no-desktop-esta-usavel"target="_blank" rel="noopener"&gt;Windows 10 Anniversary Edition&lt;/a&gt; em meados de 2016.&lt;/p&gt;
&lt;p&gt;Já faz quase 2 anos e a expectativa é de atualizações expressivas em compatibilidade e performance do WSL para a próxima &lt;a href="https://winaero.com/blog/command-line-wsl-improvements-windows-10-version-1803/"target="_blank" rel="noopener"&gt;Spring Creators Update&lt;/a&gt; (versão 1803), prevista para 30 de abril de 2018. Isso aproxima o WSL de algo realmente utilizável por programadores profissionais. Só para ter uma ideia: hoje em dia você consegue desempenho ordens de magnitude superior rodando sua distro favorita dentro do Virtualbox ou do VMWare Workstation.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Ok, quem acompanha meu blog há um ano ou dois sabe como eu <a href="http://www.akitaonrails.com/archlinux"target="_blank" rel="noopener">curto o Arch Linux</a> — em particular o Manjaro com GNOME.</p>
<p>Também continuo bastante intrigado com a ideia do Windows Subsystem for Linux (WSL), que estreou de verdade na <a href="http://www.akitaonrails.com/2016/07/26/o-ano-do-linux-no-desktop-esta-usavel"target="_blank" rel="noopener">Windows 10 Anniversary Edition</a> em meados de 2016.</p>
<p>Já faz quase 2 anos e a expectativa é de atualizações expressivas em compatibilidade e performance do WSL para a próxima <a href="https://winaero.com/blog/command-line-wsl-improvements-windows-10-version-1803/"target="_blank" rel="noopener">Spring Creators Update</a> (versão 1803), prevista para 30 de abril de 2018. Isso aproxima o WSL de algo realmente utilizável por programadores profissionais. Só para ter uma ideia: hoje em dia você consegue desempenho ordens de magnitude superior rodando sua distro favorita dentro do Virtualbox ou do VMWare Workstation.</p>
<p>Além disso, o &ldquo;Bash for Windows&rdquo; de fábrica suporta oficialmente apenas Ubuntu, Fedora e OpenSuse, acho. A maioria das pessoas instala o Ubuntu mesmo. E funciona, ok. Para brincar e impressionar nas demonstrações, funciona. Mas me irrita profundamente conseguir fazer tanta coisa e não poder usar isso no meu dia a dia de verdade. É como carregar o protótipo finalizado do próximo iPhone sem suporte a 4G. Um brinquedo, só isso.</p>
<p>Mas se você quiser apenas ver como está a performance comparada ao meu setup com VMWare, pule direto para o final do artigo.</p>
<p>Voltando ao assunto das distros: usuários sérios de Linux preferem alternativas melhores. Eis o repositório no GitHub:</p>
<p><a href="https://github.com/yuk7/ArchWSL"target="_blank" rel="noopener"><img src="http://web.archive.org/web/20221226012212/https://raw.githubusercontent.com/wiki/yuk7/WSL-DistroLauncher/img/Arch_Alpine_Ubuntu.png" alt="screenfetch of arch"  loading="lazy" /></a></p>
<p>Você baixa <a href="https://github.com/yuk7/ArchWSL/releases/latest"target="_blank" rel="noopener">esse arquivo zip</a>, descompacta e executa o <code>Arch.exe</code> incluso. Só isso!</p>
<p>Aí é só abrir o &ldquo;Bash&rdquo; na versão Windows e bootstrapar o restante da instalação por lá.</p>
<p>Precisamos do Pacman e de algum gerenciador de AUR. Para iniciar o Pacman:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>pacman-key --init
pacman-key --populate
pacman -Syu</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Que delícia, o Pacman rodando nativamente no Windows! Quem diria??</p>
<p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/674/big_IMG_20180429_174518.jpg" alt="pacman no windows"  loading="lazy" /></p>
<p>Isso vai atualizar tudo. Em seguida, criamos um usuário não-root:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>useradd -m your_user
passwd your_user
EDITOR=nano visudo</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Procure a linha que diz <code>root   ALL=(ALL) ALL</code> e adicione o seu usuário logo abaixo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>your_user   ALL=(ALL) ALL</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Por último, fazemos login como esse usuário:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>su your_user</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Agora vamos instalar o Yaourt para depois instalar o Pacaur (preferência pessoal minha — acho o Yaourt verboso demais com suas confirmações, por isso prefiro o Pacaur).</p>
<p>Comece editando o arquivo <code>/etc/pacman.conf</code> com seu editor favorito (vim ou nano).</p>
<p>Adicione a seguinte seção no final do arquivo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>[archlinuxfr]
SigLevel = Never
Server = http://repo.archlinux.fr/$arch</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Antes de prosseguir, temos um pequeno problema. O WSL ainda não tem suporte a SYSV IPC, que é necessário para o <a href="https://unix.stackexchange.com/questions/9714/what-is-the-need-for-fakeroot-command-in-linux"target="_blank" rel="noopener">fakeroot</a>, que por sua vez é exigido pelo <code>makepkg</code> (que não pode rodar como root).</p>
<p>Para contornar isso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>wget https://github.com/yuk7/arch-prebuilt/releases/download/17121600/fakeroot-tcp-1.22-1-x86_64.pkg.tar.xz
sudo pacman -U fakeroot-tcp-1.22-1-x86_64.pkg.tar.xz</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Por enquanto é isso! Até o WSL ter suporte nativo a SYSV IPC, usamos esse workaround. O próprio Yaourt provavelmente vai te pedir para instalar o <code>fakeroot-tcp</code> também — pode deixar.</p>
<p>Como disse, o Yaourt é bastante verboso nas confirmações. Regra geral: quando perguntar se quer editar algo, responda &ldquo;N&rdquo;. Quando perguntar se quer compilar ou instalar, responda &ldquo;Y&rdquo;. Se você quiser se livrar de mim nessa parte, faça logo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>yaourt -S pacaur</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>A partir de agora assumo que você tem o Pacaur instalado.</p>
<h3>Suporte a Interface Gráfica<span class="hx:absolute hx:-mt-20" id="suporte-a-interface-gráfica"></span>
    <a href="#suporte-a-interface-gr%c3%a1fica" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Vamos instalar o básico para um ambiente de desenvolvimento:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo pacman -S base base-devel gvim git</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Quando aparecer &ldquo;default: all&rdquo;, instale tudo. Espaço em disco não deveria ser preocupação em 2018.</p>
<p>Prefiro ter um ambiente GNOME 3 completo, então:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo pacman -S gnome</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>De novo, deixe instalar tudo que quiser. Cada um tem seu gosto em termos de GUI — uns preferem KDE5, outros XFCE4. Tem quem vá ainda mais longe e use o gerenciador de janelas tileado <a href="https://i3wm.org/"target="_blank" rel="noopener">i3</a>.</p>
<p>Isso exige uma adaptação séria. É para quem curte usar teclado tenkeyless sem legenda nas teclas e layouts alienígenas como DVORAK ou <a href="https://colemak.com/"target="_blank" rel="noopener">Colemak</a> (argh!). Gosto é gosto. E que tal se tornar digitador fluente no <a href="https://www.maltron.com/the-maltron-letter-layout-advantage.html"target="_blank" rel="noopener">Maltron</a>? Eu te desafio, e muito! :-D</p>
<p>Mas estou divagando. Adicione isso ao seu <code>/etc/.bashrc</code> ou ao <code>/etc/environment</code> global:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>echo &#34;export LIBGL_ALWAYS_INDIRECT=1&#34; &gt;&gt; /etc/.bashrc
echo &#34;export DISPLAY=:0&#34; &gt;&gt; /etc/.bashrc</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Exporte as variáveis no shell atual ou feche e reabra o Bash.</p>
<p>Para ter um ambiente gráfico completo, instale um servidor X local. São duas opções: Xming ou VcXSrv. Tenho tido problemas para redimensionar janelas no Xming, então recomendo o <a href="https://sourceforge.net/projects/vcxsrv/"target="_blank" rel="noopener">VcXSrv</a>. Baixe e instale como qualquer aplicativo Windows, depois inicie. Ele vai criar um atalho no Desktop chamado &ldquo;XLaunch&rdquo; — é só abrir.</p>
<p>E finalmente, instalamos um terminal <strong>DE VERDADE</strong> no lugar daquela tralha derivada do cmd.exe antigo que o WSL oferece por padrão:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>pacaur -S tilix-bin
tilix</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Quem usou Mac provavelmente conhece o iTerm2, possivelmente o melhor emulador de terminal que já usei. Nada chega perto. Nada, exceto talvez o <a href="https://gnunn1.github.io/tilix-web/"target="_blank" rel="noopener">Tilix</a> (antigamente chamado Terminix).</p>
<p>Só pelo &ldquo;Ctrl-Alt-D&rdquo; para dividir o terminal horizontalmente e &ldquo;Ctrl-Alt-R&rdquo; para dividir verticalmente, e &ldquo;Alt-1&rdquo;, &ldquo;Alt-2&rdquo; etc. para navegar entre os painéis, já vale a pena. Ainda vem com temas prontos excelentes como o clássico Solarized Dark ou meu favorito atual, Monokai Dark.</p>
<p>Não me xingue, eu sei. Alguns preferem o terminal padrão com TMUX. Também é gosto — faz mais sentido quando se trabalha em servidor remoto.</p>
<p>Adicione a fonte Hack monotype para um visual mais agradável:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo pacman -S ttf-hack</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>Linguagens de Programação<span class="hx:absolute hx:-mt-20" id="linguagens-de-programação"></span>
    <a href="#linguagens-de-programa%c3%a7%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Vamos ver se as linguagens mais importantes instalam corretamente. Como sempre digo, o ASDF resolve essa questão.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.4.3
echo -e &#39;\n. $HOME/.asdf/asdf.sh&#39; &gt;&gt; ~/.bashrc
echo -e &#39;\n. $HOME/.asdf/completions/asdf.bash&#39; &gt;&gt; ~/.bashrc</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Reinicie o terminal e continue:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf plugin-add nodejs
addf plugin-add ruby</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Para Node.js é preciso adicionar as chaves GPG corretas antes de instalar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>bash ~/.asdf/plugins/nodejs/bin/import-release-team-keyring
asdf install nodejs 10.0.0
asdf global nodejs 10.0.0</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Ruby se beneficia do jemalloc para alocar menos memória do sistema. Não sei se impacta no WSL, mas vamos fazer de qualquer forma:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo pacman -S jemalloc
RUBY_EXTRA_CONFIGURE_OPTIONS=&#34;--with-jemalloc&#34; asdf install ruby 2.5.1
asdf global ruby 2.5.1
gem install bundler</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/675/big_IMG_20180429_193432.jpg" alt="ruby compilando"  loading="lazy" /></p>
<p>Até aqui tudo bem. Se precisar instalar um Ruby antigo (&lt; 2.4) para projetos legados:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>pacaur -S openssl-1.0
PKG_CONFIG_PATH=/usr/lib/openssl-1.0/pkgconfig RUBY_EXTRA_CONFIGURE_OPTIONS=&#34;--with-openssl-dir=/usr/lib/openssl-1.0&#34; asdf install ruby 2.3.3</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Infelizmente precisa de uma versão de OpenSSL que não deveria mais ser usada por questões de segurança. Todo mundo migrou para a 1.1. Além disso, o Ruby 2.3.x chegou ao seu EOL (fim de vida). Use por sua conta e risco.</p>
<p>Mas até aqui tudo funcionando. E o Go? Vamos ver:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf plugin-add golang
asdf install golang 1.9.5
asdf global goland 1.9.5</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Poderíamos continuar, mas acho que você já pegou a ideia. Simplesmente funciona!</p>
<h3>Processos em Background<span class="hx:absolute hx:-mt-20" id="processos-em-background"></span>
    <a href="#processos-em-background" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Outra limitação atual do WSL (que esperamos ver resolvida na Spring Creators Update) é a capacidade de iniciar e manter processos em background (daemons).</p>
<p>Fazer <code>sudo systemctl enable postgresql</code> e reiniciar não vai iniciar o Postgresql automaticamente em background como deveria. O próprio Arch.exe que estamos usando nem tem systemd.</p>
<p>Felizmente, servidores como Postgresql ou Redis funcionam normalmente — podem ser iniciados como processos de usuário e se vinculam corretamente às suas portas TCP. Mas você vai ter que iniciá-los manualmente a cada sessão. Feche o terminal Bash e todos morrem.</p>
<p>Por exemplo, Postgresql:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>[your_user]# sudo pacman -S postgresql
[your_user]# sudo mkdir -p /run/postgresql
[your_user]# sudo chown -R postgres:postgres /run/postgresql

[your_user]# sudo -u postgres -i
[postgresql]# initdb --locale $LANG -E UTF8 -D &#39;/var/lib/postgres/data&#39;

[postgresql]# pg_ctl -D /var/lib/postgres/data start
waiting for server to start....2018-04-29 23:30:35.483 UTC [1064] LOG:  listening on IPv4 address &#34;127.0.0.1&#34;, port 5432
2018-04-29 23:30:35.505 UTC [1064] LOG:  listening on Unix socket &#34;/run/postgresql/.s.PGSQL.5432&#34;
2018-04-29 23:30:35.583 UTC [1065] LOG:  database system was shut down at 2018-04-29 23:23:48 UTC
2018-04-29 23:30:35.660 UTC [1064] LOG:  database system is ready to accept connections

[postgresql]# createuser --interactive
Enter name of role to add: your_user
Shall the new role be a superuser? (y/n) y

[postgresql]# exit
[your_user]#</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Viu o que fiz aqui? Tem um problema na instalação sob WSL em que o <code>/run/postgresql</code> não é criado com as permissões corretas. Corrigindo isso conseguimos iniciar o servidor. Podemos sair da sessão <code>su</code> e o PostgreSQL continua rodando. Mas quando fecharmos a primeira janela/sessão Bash, ele morre.</p>
<p>E tem mais uma coisa irritante: as correções de <code>mkdir</code> e <code>chown</code> acima? Preciso fazer toda vez que fecho o Bash for Windows e abro novamente!! Absurdamente chato!</p>
<p>Mas dá para conviver por enquanto. Esperançosamente isso vai estar resolvido amanhã (30 de abril) ou em uma atualização próxima.</p>
<p>Em um ambiente de desenvolvimento Rails, dá para usar o <a href="https://github.com/theforeman/foreman"target="_blank" rel="noopener">Foreman</a> para ajudar. Basta editar um arquivo <code>Procfile.dev</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>web: bundle exec puma -C config/puma.rb -p 3000
db: su postgres -c &#39;pg_ctl start -D /var/lib/postgres/data&#39;
redis: redis-server /usr/local/etc/redis.conf
mailcatcher: mailcatcher -f</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Aí é só: <code>foreman start -f Procfile.dev</code> e todos os serviços sobem de uma vez.</p>
<h3>Performance no Mundo Real<span class="hx:absolute hx:-mt-20" id="performance-no-mundo-real"></span>
    <a href="#performance-no-mundo-real" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Minha máquina do dia a dia é o Manjaro GNOME rodando no VMWare Workstation Pro no meu Surface Book 2. Dou a ele 6 dos 8 threads e generosos 12GB de RAM dos 16GB totais (Microsoft, precisamos de mais RAM! Os modernos implantam aplicativos estúpidos com camadas pesadas de JS/CSS que comem tudo que tem).</p>
<p>No projeto em que estou trabalhando, minha suite RSpec completa é um pouco lenta. Para essa comparação, estou pulando os feature specs porque não tenho paciência agora para configurar o chrome-driver no WSL (provavelmente funciona, mas fica para outra vez).</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>Finished in 12 minutes 8 seconds (files took 14.58 seconds to load)
1493 examples, 0 failures, 35 pending

531,34s user 127,56s system 88% cpu 12:24,99 total</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>No ambiente WSL comparável que acabei de instalar, rodando a mesma suite RSpec, obtive:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>Finished in 13 minutes 43 seconds (files took 3 minutes 16.8 seconds to load)
1474 examples, 0 failures, 35 pending


455.80s user 399.14s system 83% cpu 17:04.96 total</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Por algum motivo meu ambiente WSL está pulando alguns exemplos (parece mais um bug de contador do RSpec), mas acho que isso não muda muito o panorama geral. O WSL perde mesmo que o contador esteja correto e ele esteja rodando menos exemplos.</p>
<p>Quando começamos a exercitar o WSL de verdade, toda sorte de problemas aparece. Por exemplo, o PostgreSQL entra em colapso e fica imprimindo &ldquo;could not flush dirty data: Function not implemented&rdquo; no stdout, por causa de <a href="https://github.com/Microsoft/WSL/issues/645"target="_blank" rel="noopener">um problema documentado</a> do WSL! O que acaba acontecendo é que o runner do RSpec simplesmente pausa enquanto o PG tenta se resolver.</p>
<p>No VMWare os arquivos carregaram em menos de 15 segundos. No WSL levou mais de 3 minutos só em I/O de arquivos! Ordens de magnitude mais lento. Esse é o problema grave. Quando é só CPU contra CPU, os dois são bastante comparáveis.</p>
<p>No total, os tempos ficam próximos no papel. Em CPU o WSL até leva vantagem, o que explica como ele consegue recuperar o tempo total apesar do I/O claramente lento.</p>
<p>Na prática, numa situação normal de programação, você abre o Vim ou qualquer editor. Todo programador fica abrindo e alternando entre muitos arquivos o tempo todo. Com o I/O super lento, cada arquivo que você tenta abrir trava sua ação por uma fração de segundo. E isso vai acumulando.</p>
<p>Dentro do VMWare, o Vim responde na hora, abrir um arquivo é quase instantâneo.</p>
<p>O benchmark pode não capturar essa situação. Mas no dia a dia você vai acabar irritado. Além disso, rodar uma GUI sobre o X (VcXsrv no meu caso) também adiciona lentidão. Dentro do VMWare, o Xorg normal aproveita aceleração GPU, então todo o pipeline de rasterização é mais rápido.</p>
<p>Dá para usar o WSL como ambiente principal. Mas se consigo uma experiência mais fluida dentro do VMWare, é lá que vou ficar por enquanto.</p>
<h3>Conclusão<span class="hx:absolute hx:-mt-20" id="conclusão"></span>
    <a href="#conclus%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Vou segurar minhas conclusões até amanhã (30 de abril) ou mais para o final da semana, porque se a Spring Creators Update realmente corrigir os problemas de performance, aí posso me ver usando isso no lugar da minha instalação do Manjaro GNOME no VMWare Workstation.</p>
<p>Pode não vir nessa grande atualização, mas tenho informações de que estão trabalhando nos problemas pendentes de performance de I/O. Então está chegando.</p>
<p>Tudo que preciso simplesmente funciona: Tilix, Vim, Git, Zsh, Ruby, Node.js. Tudo instala como esperado pelo Pacman e AUR. Pura glória do Arch Linux! Que pena que a performance ruim estraga tudo.</p>
<p>Está perto, muito perto! Pela primeira vez em quase 15 anos, consigo quase me ver voltando 100% para o Windows (sem VMWare) e ainda sendo totalmente produtivo com ferramentas reais, profissionais e open source que &ldquo;simplesmente funcionam&rdquo;.</p>
<p>Fique de olho neste post para atualizações esta semana!</p>
]]></content:encoded><category>linux</category><category>microsoft</category><category>ferramentas-de-desenvolvimento</category></item><item><title>Substituindo rvm, rbenv, nvm e outros pelo asdf</title><link>https://akitaonrails.github.io/2017/10/24/substituindo-rvm-rbenv-nvm-e-outros-pelo-asdf/</link><guid isPermaLink="true">https://akitaonrails.github.io/2017/10/24/substituindo-rvm-rbenv-nvm-e-outros-pelo-asdf/</guid><pubDate>Tue, 24 Oct 2017 14:19:00 -0200</pubDate><description>&lt;p&gt;Muita gente está usando Docker como meio de ter diferentes versões de Ruby ou de qualquer outra linguagem. Ainda acho que o overhead adicional tanto em uso de recursos quanto em fricção de usabilidade simplesmente não compensa. Recomendo fortemente contra isso. Docker é ótimo como base para infraestruturas automatizadas, mas prefiro tê-lo apenas em servidores.&lt;/p&gt;
&lt;p&gt;Faz bastante tempo que uso o &lt;a href="https://github.com/asdf-vm/asdf"target="_blank" rel="noopener"&gt;asdf&lt;/a&gt; como meu gerenciador principal de versões de Ruby, e estou confiante de que posso recomendá-lo no lugar dos mais conhecidos RVM ou Rbenv.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Muita gente está usando Docker como meio de ter diferentes versões de Ruby ou de qualquer outra linguagem. Ainda acho que o overhead adicional tanto em uso de recursos quanto em fricção de usabilidade simplesmente não compensa. Recomendo fortemente contra isso. Docker é ótimo como base para infraestruturas automatizadas, mas prefiro tê-lo apenas em servidores.</p>
<p>Faz bastante tempo que uso o <a href="https://github.com/asdf-vm/asdf"target="_blank" rel="noopener">asdf</a> como meu gerenciador principal de versões de Ruby, e estou confiante de que posso recomendá-lo no lugar dos mais conhecidos RVM ou Rbenv.</p>
<p>Além disso, ele não gerencia só Ruby — ele gerencia praticamente todas as linguagens que você precisar, com um único conjunto de comandos. Então nem precisa mais de virtualenv para Python ou NVM para Node.js. É só usar o ASDF.</p>
<p>A instalação não poderia ser mais simples. Basta seguir o <a href="https://github.com/asdf-vm/asdf/blob/master/README.md"target="_blank" rel="noopener">README</a> na página do projeto.</p>
<p>Não esqueça de instalar as ferramentas base de desenvolvimento para o seu ambiente. Você pode seguir a <a href="https://github.com/rbenv/ruby-build/wiki"target="_blank" rel="noopener">wiki do ruby-build</a> como referência:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>## Para OS X
# opcional, mas recomendado:
brew install openssl libyaml libffi

# obrigatório para compilar Ruby &lt;= 1.9.3-p0:
brew tap homebrew/dupes &amp;&amp; brew install apple-gcc42

## Para Ubuntu
sudo apt-get install gcc-6 autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev

## Para Arch
sudo pacman -S --needed gcc5 base-devel libffi libyaml openssl zlib</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Depois instale o próprio ASDF:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.4.0</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Então adicione a configuração de ambiente para o PATH e o autocomplete:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code># Para Ubuntu ou outras distros Linux
echo -e &#39;\n. $HOME/.asdf/asdf.sh&#39; &gt;&gt; ~/.bashrc
echo -e &#39;\n. $HOME/.asdf/completions/asdf.bash&#39; &gt;&gt; ~/.bashrc

# OU para Mac OSX
echo -e &#39;\n. $HOME/.asdf/asdf.sh&#39; &gt;&gt; ~/.bash_profile
echo -e &#39;\n. $HOME/.asdf/completions/asdf.bash&#39; &gt;&gt; ~/.bash_profile</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Por fim, você precisa instalar um dos dezenas de <a href="https://github.com/asdf-vm/asdf-plugins"target="_blank" rel="noopener">plugins</a> disponíveis. No meu caso, tenho estes instalados:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf plugin-add clojure https://github.com/vic/asdf-clojure.git
asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git
asdf plugin-add erlang https://github.com/asdf-vm/asdf-erlang.git
asdf plugin-add golang https://github.com/kennyp/asdf-golang.git
asdf plugin-add python https://github.com/tuvistavie/asdf-python.git
asdf plugin-add ruby https://github.com/asdf-vm/asdf-ruby.git

# Importa as chaves OpenPGP do time de releases do Node.js para o keyring principal
bash ~/.asdf/plugins/nodejs/bin/import-release-team-keyring

asdf plugin-add nodejs https://github.com/asdf-vm/asdf-nodejs.git</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Para atualizar todos os plugins de uma vez, basta rodar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf plugin-update --all</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Para ver as versões disponíveis de uma linguagem específica:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf list-all ruby
asdf list-all clojure
asdf list-all python</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Para instalar qualquer versão que você precisar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf install ruby 2.4.2
asdf install nodejs 8.7.0
asdf install erlang 20.1</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Depois de instalar uma versão, costumo definir uma como padrão global do sistema:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf global ruby 2.4.2
asdf global elixir 1.5.2</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E dentro de um diretório de projeto específico, posso definir outra versão, válida só para aquele projeto:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf local ruby 2.3.4</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Esse comando grava um arquivo <code>.tool-versions</code> no diretório onde você está quando o executa. Ele contém a linguagem e a versão escolhidas, então sempre que você voltar para aquele diretório o ASDF vai configurar a versão correta automaticamente. O <code>asdf global &lt;linguagem&gt;</code> que mencionei antes faz a mesma coisa, só que grava o <code>.tool-versions</code> no seu diretório home. A configuração local sobrescreve a do home.</p>
<p>Outro ponto importante: sempre que você instalar bibliotecas que têm scripts executáveis que precisam estar no PATH, você deve fazer o <strong>reshim</strong> deles. Por exemplo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>npm install -g phantomjs # instala o phantomjs
asdf reshim nodejs # coloca o shim do executável phantomjs no PATH
phantomjs # executa corretamente</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Se você tentar instalar versões de Ruby anteriores à 2.4, vai encontrar <a href="https://github.com/asdf-vm/asdf-ruby/wiki/Ruby-Installation-Problems"target="_blank" rel="noopener">problemas de compilação</a>, pois elas dependem do gcc5 e do openssl-1.0. Nesse caso, use o seguinte comando (assumindo que você já instalou o openssl-1.0 e o gcc5 obsoletos):</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>CC=gcc-5 PKG_CONFIG_PATH=/usr/lib/openssl-1.0/pkgconfig \
RUBY_EXTRA_CONFIGURE_OPTIONS=&#34;--with-openssl-dir=/usr/lib/openssl-1.0&#34; \
asdf install ruby 2.3.4</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Às vezes, quando uma dependência está faltando e a instalação falha, você precisa remover manualmente a versão antes de tentar reinstalar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf remove &lt;linguagem&gt; &lt;versão&gt;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Por fim, se você costumava adicionar algo ao seu bash ou zsh para mostrar a versão atual da linguagem na linha de comando — provavelmente usando algo como <code>rvm-prompt</code> — no caso do ASDF você vai precisar de algo um pouco mais longo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>asdf current ruby | awk -F&#39; &#39; &#39;{print $1}&#39;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Isso extrai só a versão (o comando <code>asdf current</code> mostra também qual arquivo <code>.tool-versions</code> está sendo usado, por isso o resultado é mais longo).</p>
<p>Fora isso, está tudo pronto. Um gerenciador de versões para governar todos. Sem RVM, sem Virtualenv, sem NVM. Pode viver feliz para sempre!</p>
]]></content:encoded><category>ferramentas-de-desenvolvimento</category><category>automacao</category></item><item><title>Customizando o Fedora 25 para Desenvolvedores</title><link>https://akitaonrails.github.io/2017/01/06/customizando-o-fedora-25-para-desenvolvedores/</link><guid isPermaLink="true">https://akitaonrails.github.io/2017/01/06/customizando-o-fedora-25-para-desenvolvedores/</guid><pubDate>Fri, 06 Jan 2017 17:11:00 -0200</pubDate><description>&lt;p&gt;&lt;strong&gt;Atualização 18/01/2017:&lt;/strong&gt; Logo depois de experimentar o Fedora por alguns dias, resolvi &lt;a href="http://www.akitaonrails.com/2017/01/10/arch-linux-a-melhor-distro-de-todas"target="_blank" rel="noopener"&gt;testar o Arch Linux&lt;/a&gt; e não me arrependi nem um pouco. Recomendo que você também experimente, provavelmente vai te surpreender. Pode se interessar também pelo post sobre &lt;a href="http://www.akitaonrails.com/2017/01/17/otimizando-o-linux-para-computadores-lentos"target="_blank" rel="noopener"&gt;tuning avançado de Linux para melhor responsividade&lt;/a&gt; no desktop.&lt;/p&gt;
&lt;p&gt;Sou usuário de Ubuntu há muito tempo. Sempre que preciso configurar uma máquina Linux, vou direto para a última LTS. É memória muscular, não tem jeito.&lt;/p&gt;</description><content:encoded><![CDATA[<p><strong>Atualização 18/01/2017:</strong> Logo depois de experimentar o Fedora por alguns dias, resolvi <a href="http://www.akitaonrails.com/2017/01/10/arch-linux-a-melhor-distro-de-todas"target="_blank" rel="noopener">testar o Arch Linux</a> e não me arrependi nem um pouco. Recomendo que você também experimente, provavelmente vai te surpreender. Pode se interessar também pelo post sobre <a href="http://www.akitaonrails.com/2017/01/17/otimizando-o-linux-para-computadores-lentos"target="_blank" rel="noopener">tuning avançado de Linux para melhor responsividade</a> no desktop.</p>
<p>Sou usuário de Ubuntu há muito tempo. Sempre que preciso configurar uma máquina Linux, vou direto para a última LTS. É memória muscular, não tem jeito.</p>
<p>Mas para substituir o macOS, Unity é feio demais, sendo honesto. Tentei customizar o Cinnamon e quase gostei, e nem me fale de KDE ou XFCE.</p>
<p>O <a href="https://www.gnome.org/news/2016/09/gnome-3-22-released-the-future-is-now/"target="_blank" rel="noopener">GNOME 3.22</a>, por outro lado, é muito bem feito. Não preciso fuçar nada para deixar com boa aparência. O conjunto padrão de atalhos globais é exatamente o que um usuário antigo de macOS espera. Gosto de quase tudo nele.</p>
<p>Estava curioso com toda a movimentação em torno da transição do X.org para o Wayland e queria ver como estava.</p>
<p>A melhor distro que encontrei para isso é o bom e velho Fedora. RedHat (4) foi a segunda distro Linux que experimentei, logo depois do Slackware 1 lá em meados dos anos 90. Volto e saio de tempos em tempos. É uma boa hora de tentar de novo.</p>
<p>O resumo é que estou bem satisfeito com o <a href="https://getfedora.org/en/workstation/download/"target="_blank" rel="noopener">Fedora 25</a>. Ele faz praticamente tudo que preciso já de cara, sem configuração adicional.</p>
<p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/578/big_Screenshot_from_2017-01-06_16-58-17.png" alt="Fedora 25"  loading="lazy" /></p>
<p>Tirei da gaveta um desktop Lenovo ThinkCentre Edge 71z de 4 anos de idade e um notebook Lenovo IdeaPad G400s. São, respectivamente, um Core i5 SandyBridge de 2ª geração a 2,5GHz e um Core i3 a 2,4GHz, com 8GB de RAM no desktop e 4GB no notebook. Para a rotina de um desenvolvedor, são mais que suficientes. Um CPU mais potente não faria grande diferença.</p>
<p>Fiquei feliz ao ver que o desktop velho tem uma placa Intel antiga com saída DVI. Por sorte tinha um cabo DVI-to-HDMI por aí e consegui conectar ao meu monitor ultrawide LG 21:9 (2560x1080), que escalou tudo corretamente (o macOS Sierra tinha uma regressão que precisava de hack para funcionar!).</p>
<p>O que pesa mesmo são os HDs mecânicos super lentos (7200rpm e 5400rpm). Já pedi upgrade de RAM e 2 SSDs Crucial MX300 compatíveis. Quando chegarem, vou ter a agilidade que preciso.</p>
<p>Dito isso, o que fazer depois de uma instalação zerada do Fedora 25?</p>
<h3>Para usuários de Ubuntu<span class="hx:absolute hx:-mt-20" id="para-usuários-de-ubuntu"></span>
    <a href="#para-usu%c3%a1rios-de-ubuntu" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Lembre disso: em vez de <code>apt-get</code>, você usa <code>dnf</code>. O Fedora antes da versão 22 usava <code>yum</code>, mas o <code>dnf</code> o substitui com basicamente as mesmas opções de comando.</p>
<p>Não existe equivalente ao <code>apt-get update</code> porque ele atualiza automaticamente. O resto é bem parecido: <code>dnf install pacote</code> em vez de <code>apt-get install pacote</code>, <code>dnf search pacote</code> em vez de <code>apt-cache search pacote</code>, e assim por diante. Para um upgrade global, use <code>dnf upgrade</code> em vez de <code>apt-get update &amp;&amp; apt-get upgrade</code>.</p>
<p>Para serviços, em vez de <code>sudo service restart memcached</code>, use <code>sudo systemctl restart memcached</code>.</p>
<p>É basicamente isso. Leia essa <a href="https://fedoraproject.org/wiki/Differences_to_Ubuntu"target="_blank" rel="noopener">página da wiki</a> para mais diferenças de comandos.</p>
<h3>Suporte à linguagem Crystal<span class="hx:absolute hx:-mt-20" id="suporte-à-linguagem-crystal"></span>
    <a href="#suporte-%c3%a0-linguagem-crystal" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Digamos que você queira aprender essa linguagem nova chamada &ldquo;Crystal&rdquo;: sintaxe e bibliotecas padrão familiares ao Ruby, mas com geração de binários nativos como no Go, primitivas de concorrência rápidas e todos os benefícios de um binário otimizado pelo LLVM.</p>
<p>Siga a <a href="https://crystal-lang.org/docs/installation/on_redhat_and_centos.html"target="_blank" rel="noopener">wiki deles</a> e também essa <a href="https://github.com/crystal-lang/crystal/wiki/All-required-libraries#fedora"target="_blank" rel="noopener">página</a>, mas basicamente é isso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install \
  gmp-devel \
  libbsd-devel \
  libedit-devel \
  libevent-devel \
  libxml2-devel \
  libyaml-devel \
  llvm-static \
  openssl-devel \
  readline-devel

sudo dnf -y install fedora-repos-rawhide
sudo dnf -y install gc gc-devel # get all dependencies from Fedora 25
sudo dnf -y install gc gc-devel --enablerepo=rawhide --best --allowerasing

sudo dnf -y install crystal</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>É isso, muitas dependências, mas como ainda é pré-1.0 acredito que vão melhorar isso no futuro.</p>
<h3>Suporte a Ruby e Node.js<span class="hx:absolute hx:-mt-20" id="suporte-a-ruby-e-nodejs"></span>
    <a href="#suporte-a-ruby-e-nodejs" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Rubyistas têm várias opções de gerenciador de versões, mas eu prefiro RVM. Primeiro, precisamos instalar alguns <a href="http://www.socialquesting.com/blog/octopress-installation-fedora-25/"target="_blank" rel="noopener">pré-requisitos</a>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install patch autoconf gcc-c&#43;&#43; patch libffi-devel automake libtool bison sqlite-devel ImageMagick-devel nodejs git gitg
curl -sSL https://rvm.io/mpapis.asc | gpg2 --import
curl -L https://get.rvm.io | bash -s stable --ruby

sudo npm -g install brunch phantomjs</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pronto, você terá o Ruby estável mais recente, Node, Npm e ferramentas úteis como Brunch (necessário para projetos Elixir-Phoenix) e PhantomJS para testes de aceitação automatizados em várias linguagens.</p>
<p>Note que já estamos instalando o Git e o opcional <a href="https://git.gnome.org//browse/gitg"target="_blank" rel="noopener">GitG</a>, um companheiro fantástico para a sua rotina com Git.</p>
<p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/583/big_Screenshot_from_2017-01-06_16-59-05.png" alt="GitG"  loading="lazy" /></p>
<h3>Suporte a Postgresql, Redis, Memcached<span class="hx:absolute hx:-mt-20" id="suporte-a-postgresql-redis-memcached"></span>
    <a href="#suporte-a-postgresql-redis-memcached" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>O que é uma aplicação web sem banco de dados e serviços de cache? Vamos instalá-los:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install postgresql-server postgresql-contrib postgresql-devel memcached redis

sudo postgresql-setup --initdb
sudo sed -i.bak &#39;s/ident/trust/&#39; /var/lib/pgsql/data/pg_hba.conf # NUNCA faça isso em servidores de produção
sudo systemctl start postgresql

sudo su - postgres
createuser youruser -p
createdb youruser --owner=youruser</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Substitua <code>youruser</code> pelo nome do seu usuário atual, claro.</p>
<h3>Suporte a Java<span class="hx:absolute hx:-mt-20" id="suporte-a-java"></span>
    <a href="#suporte-a-java" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Fácil, basta instalar o <a href="http://www.2daygeek.com/install-java-openjdk-6-7-8-on-ubuntu-centos-debian-fedora-mint-rhel-opensuse-manjaro-archlinux/#"target="_blank" rel="noopener">OpenJDK 8</a> mais recente e os plugins para o navegador:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install java-1.8.0-openjdk icedtea-web</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>Suporte a Go<span class="hx:absolute hx:-mt-20" id="suporte-a-go"></span>
    <a href="#suporte-a-go" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Ainda mais simples:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install go</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Não esqueça de editar seu perfil, como <code>$HOME/.profile</code>, e adicionar as variáveis de ambiente necessárias:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>Suporte a Elixir<span class="hx:absolute hx:-mt-20" id="suporte-a-elixir"></span>
    <a href="#suporte-a-elixir" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Tem o jeito fácil e um mais complicado e demorado. Vamos começar com <a href="http://elixir-lang.org/install.html#unix-and-unix-like"target="_blank" rel="noopener">o fácil</a>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install erlang elixir
mix local.hex
mix local.rebar
mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>O problema é que os pacotes para distros como Fedora demoram para ser atualizados. Por exemplo, o Elixir 1.4 foi lançado há alguns dias, mas ainda não há atualização para o Fedora.</p>
<p>Outro problema, se você desenvolve Elixir profissionalmente, é que vai precisar de um gerenciador de versões, porque vai acabar pegando projetos de clientes em versões diferentes e precisa configurar o ambiente adequadamente. É aí que entra o <a href="https://github.com/asdf-vm/asdf"target="_blank" rel="noopener">asdf</a>. Você pode seguir <a href="https://gist.github.com/rubencaro/6a28138a40e629b06470"target="_blank" rel="noopener">este gist</a>, mas vou colar os pontos importantes aqui:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install make automake gcc gcc-c&#43;&#43; kernel-devel git wget openssl-devel ncurses-devel wxBase3 wxGTK3-devel m4

git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.2.1

# Para Ubuntu ou outras distros Linux
echo &#39;. $HOME/.asdf/asdf.sh&#39; &gt;&gt; ~/.bashrc
echo &#39;. $HOME/.asdf/completions/asdf.bash&#39; &gt;&gt; ~/.bashrc

# reinicie o terminal ou faça source do arquivo acima:
source ~/.bashrc

asdf plugin-add erlang https://github.com/asdf-vm/asdf-erlang.git
asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git

asdf install erlang 19.0
asdf install elixir 1.4.0

asdf global erlang 19.0
asdf global elixir 1.4.0</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Compilar o Erlang a partir do código-fonte demora uma eternidade, especialmente com CPUs velhos como os meus. Mas é assim que você tem acesso ao Elixir mais recente e, ao mesmo tempo, a capacidade de usar versões antigas para projetos de clientes.</p>
<p>Por sinal, você pode instalar plugins adicionais do asdf para gerenciar outras plataformas como Go, Rust, Node, Julia e muitas outras. Veja a <a href="https://github.com/asdf-vm/asdf"target="_blank" rel="noopener">página do projeto</a> para mais detalhes.</p>
<h3>Suporte a Docker<span class="hx:absolute hx:-mt-20" id="suporte-a-docker"></span>
    <a href="#suporte-a-docker" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Provavelmente você vai querer Docker também, então <a href="https://docs.docker.com/engine/installation/linux/fedora/"target="_blank" rel="noopener">vamos lá</a>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install docker docker-compose

# você pode testar se funcionou com o famoso hello world
sudo docker run --rm hello-world</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h2>Aplicativos de Desktop<span class="hx:absolute hx:-mt-20" id="aplicativos-de-desktop"></span>
    <a href="#aplicativos-de-desktop" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Com tudo instalado, vamos configurar os aspectos não-terminais para uma experiência melhor.</p>
<h3>Terminator (e Terminix)<span class="hx:absolute hx:-mt-20" id="terminator-e-terminix"></span>
    <a href="#terminator-e-terminix" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/579/Screenshot_from_2017-01-06_16-59-53.png" alt="Terminator"  loading="lazy" /></p>
<p>Falando em terminais, você vai querer instalar o <a href="https://gnometerminator.blogspot.com.br/p/introduction.html"target="_blank" rel="noopener">Terminator</a>. Não gosto de usar screen ou tmux na minha máquina local (não consigo me acostumar com os atalhos). Estou mais habituado ao iTerm2 do macOS, e o Terminator é praticamente a mesma coisa com atalhos similares. Você definitivamente precisa substituir o terminal padrão por ele.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install terminator</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Você também vai querer editar <code>~/.config/terminator/config</code> e adicionar o seguinte para melhorar a configuração:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>[global_config]
  title_transmit_bg_color = &#34;#d30102&#34;
  focus = system
[keybindings]
[layouts]
  [[default]]
    [[[child1]]]
      parent = window0
      type = Terminal
      profile = default
    [[[window0]]]
      parent = &#34;&#34;
      type = Window
[plugins]
[profiles]
  [[default]]
    use_system_font = false
    font = Hack 12
    scrollback_lines = 2000
    palette = &#34;#073642:#dc322f:#859900:#b58900:#268bd2:#d33682:#2aa198:#eee8d5:#586e75:#cb4b16:#586e75:#657b83:#839496:#6c71c4:#93a1a1:#fdf6e3&#34;
    foreground_color = &#34;#eee8d5&#34;
    background_color = &#34;#002b36&#34;
    cursor_color = &#34;#eee8d5&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Outra ótima opção que me recomendaram é o <a href="https://copr.fedorainfracloud.org/coprs/heikoada/terminix/"target="_blank" rel="noopener">Terminix</a>. Para instalar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf copr enable heikoada/terminix
sudo dnf -y install terminix</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>Fonte Hack<span class="hx:absolute hx:-mt-20" id="fonte-hack"></span>
    <a href="#fonte-hack" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Você vai querer uma fonte melhor, como <a href="https://github.com/chrissimpkins/Hack"target="_blank" rel="noopener">Hack</a>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>dnf -y install dnf-plugins-core
dnf copr enable heliocastro/hack-fonts
dnf -y install hack-fonts</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>Gnome Tweak Tool<span class="hx:absolute hx:-mt-20" id="gnome-tweak-tool"></span>
    <a href="#gnome-tweak-tool" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Instale o <strong>Gnome Tweak Tool</strong> para poder definir a Hack como fonte monoespaçada padrão:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install gnome-tweak-tool</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>Vim, Zsh, Yadr<span class="hx:absolute hx:-mt-20" id="vim-zsh-yadr"></span>
    <a href="#vim-zsh-yadr" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/582/big_Screenshot_from_2017-01-06_16-59-36.png" alt="Vim gruvbox"  loading="lazy" /></p>
<p>Gosto muito de usar Vim, então instale assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install vim-enhanced vim-X11</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E gosto de usar o <a href="https://github.com/Codeminer42/dotfiles"target="_blank" rel="noopener">YADR</a> para customizar todos os aspectos do meu ZSH e Vim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sh -c &#34;`curl -fsSL https://raw.githubusercontent.com/skwp/dotfiles/master/install.sh `&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Recomendo ter Zsh, Vim e Ruby instalados antes de rodar o script acima. Depois de concluir, tive que ajustar as configurações um pouco:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sed &#39;s/gtk2/gtk3&#39; ~/.vim/settings/yadr-appearance.vim</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Você vai querer ajustar esse arquivo também, para adicionar novas fontes como Hack. Atualmente estou mais no mood &ldquo;gruvbox&rdquo; do que &ldquo;solarized&rdquo; como tema do Vim.</p>
<h3>GIMP Photoshop<span class="hx:absolute hx:-mt-20" id="gimp-photoshop"></span>
    <a href="#gimp-photoshop" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/580/big_Screenshot_from_2017-01-06_17-07-14.png" alt="Gimp with Photoshop Theme"  loading="lazy" /></p>
<p>Se você é desenvolvedor web, vai precisar editar algumas imagens de vez em quando. E se for como eu, o Gimp é um pesadelo de usabilidade. Mas <a href="http://www.omgubuntu.co.uk/2016/08/make-gimp-look-like-photoshop-easy"target="_blank" rel="noopener">existem maneiras</a> de torná-lo um <a href="https://github.com/doctormo/GimpPs"target="_blank" rel="noopener">pouco mais palatável</a>.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo dnf -y install gimp
sh -c &#34;$(curl -fsSL https://raw.githubusercontent.com/doctormo/GimpPs/master/tools/install.sh)&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pronto, um tema parecido com Photoshop para o Gimp deixar menos feio.</p>
<h3>Spotify<span class="hx:absolute hx:-mt-20" id="spotify"></span>
    <a href="#spotify" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>O que seria de nós, desenvolvedores, sem música para concentrar?</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>dnf config-manager --add-repo=http://negativo17.org/repos/fedora-spotify.repo
dnf -y install spotify-client</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>CoreBird<span class="hx:absolute hx:-mt-20" id="corebird"></span>
    <a href="#corebird" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/581/big_Screenshot_from_2017-01-06_17-08-43.png" alt="CoreBird"  loading="lazy" /></p>
<p>Fico feliz que alguém construiu um cliente de Twitter muito competente e elegante para Linux. Instale o CoreBird:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>dnf -y install corebird</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Provavelmente é até melhor que a versão oficial para Mac.</p>
<h3>Ajustando a barra de título<span class="hx:absolute hx:-mt-20" id="ajustando-a-barra-de-título"></span>
    <a href="#ajustando-a-barra-de-t%c3%adtulo" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Encontrei <a href="http://blog.samalik.com/make-your-gnome-title-bars-smaller/"target="_blank" rel="noopener">esse hack</a> para deixar as barras de título do Gnome um pouco menos gordas, que é praticamente a única reclamação que tenho sobre o visual até agora:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>tee ~/.config/gtk-3.0/gtk.css &lt;&lt;-EOF
.header-bar.default-decoration {
 padding-top: 3px;
 padding-bottom: 3px;
 font-size: 0.8em;
}

.header-bar.default-decoration .button.titlebutton {
 padding: 0px;
}
EOF</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<h3>Conclusão<span class="hx:absolute hx:-mt-20" id="conclusão"></span>
    <a href="#conclus%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>A maioria das coisas que você precisa é web, então Gmail, Slack, tudo funciona bem. Abra o Chromium, Firefox ou instale o <a href="http://meetfranz.com/"target="_blank" rel="noopener">Franz</a> ou <a href="http://thomas101.github.io/wmail/"target="_blank" rel="noopener">WMail</a> se precisar. Infelizmente tudo que é web consome muita RAM, o que é um problema sério. Sinto falta dos bons e velhos aplicativos nativos, leves e rápidos. Aplicativos web são um porre.</p>
<p>Eles &ldquo;funcionam&rdquo;, mas prefiro um bom aplicativo nativo. Por outro lado, Dropbox e Skype têm clientes terríveis. São muito mal mantidos, cheios de bugs e com suporte péssimo. Prefiro não usá-los.</p>
<p>Estava tentando me acostumar com o Thunderbird no Ubuntu. O Geary ainda não é bom o suficiente. Mas fiquei surpreso ao tentar o Evolution de novo. Ele tem a única coisa que realmente quero de qualquer cliente de email: um atalho para mover emails para pastas: Ctrl-Shift-V (!!) Será que é tão difícil assim??</p>
<p>O Gnome 3 tem um repositório global de Contas Online nas Configurações onde você pode cadastrar redes sociais como Facebook e Google, mas o suporte ao Google está <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=820913"target="_blank" rel="noopener">bugado</a>. Expira toda hora, então não use o Evolution com ele. Adicione as informações de Imap/Smtp manualmente. Email e dados do Calendar sincronizam corretamente dessa forma.</p>
<p>Você já deve ter todas as suas senhas em uma conta LastPass. O Authy é uma extensão do Chrome, então sua autenticação de múltiplos fatores também deve funcionar.</p>
<p>Meu banco e corretoras, com seus feios applets Java, funcionam bem com Chromium e IcedTea, então estou ok por aí.</p>
<p>Só preciso descobrir a estratégia de backup mais fácil para ter tudo realmente seguro. Na instalação, não esqueça de escolher a opção de partição criptografada - e se fizer isso, faça backup dos dados regularmente, pois ouvi relatos de bugs em upgrades que tornaram as partições criptografadas inacessíveis. Seja seguro e cuidadoso.</p>
<p>Como sempre, do macOS as únicas 2 coisas que vou realmente sentir falta são o Apple Keynote (é incrível, ninguém conseguiu fazer uma ferramenta de apresentação tão elegante e rápida) e o iMovie para edição rápida de vídeo (embora o <a href="https://kdenlive.org/"target="_blank" rel="noopener">Kdenlive</a> seja uma alternativa bem boa).</p>
<p>Você ainda tem <a href="https://wiki.gnome.org/Gnome3CheatSheet"target="_blank" rel="noopener">atalhos</a> embutidos para capturar uma janela ou área e <a href="https://fedoramagazine.org/taking-screencast-fedora/"target="_blank" rel="noopener">gravar um screencast</a>!</p>
<p>Comparado à minha configuração no Ubuntu, esse Fedora 25 é realmente um prazer de usar. Uma boa alternativa ao macOS. Recomendo!</p>
<p>E como disse na atualização no início do post: dê uma olhada no <a href="http://www.akitaonrails.com/2017/01/10/arch-linux-a-melhor-distro-de-todas"target="_blank" rel="noopener">Arch Linux</a> e em como <a href="http://www.akitaonrails.com/2017/01/17/otimizando-o-linux-para-computadores-lentos"target="_blank" rel="noopener">otimizar sua distro para ser mais responsiva</a>, especialmente em hardware antigo.</p>
]]></content:encoded><category>linux</category><category>ferramentas-de-desenvolvimento</category></item><item><title>Ubuntu 16.04 LTS Xenial no Vagrant com Vmware Fusion</title><link>https://akitaonrails.github.io/2016/09/21/ubuntu-16-04-lts-xenial-no-vagrant-com-vmware-fusion/</link><guid isPermaLink="true">https://akitaonrails.github.io/2016/09/21/ubuntu-16-04-lts-xenial-no-vagrant-com-vmware-fusion/</guid><pubDate>Wed, 21 Sep 2016 18:08:00 -0300</pubDate><description>&lt;p&gt;Sou old school. Sei que a garotada descolada está toda brincando com Docker hoje em dia, mas gosto de ter um ambiente linux completo com todas as dependências num lugar só. Deixo as máquinas voláteis para a nuvem.&lt;/p&gt;
&lt;p&gt;Gosto de manter uma box Vagrant por perto, porque por mais bagunçado que um upgrade de sistema operacional possa ser (olhando pra você, macOS), sei que minha máquina de desenvolvimento vai simplesmente funcionar.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Sou old school. Sei que a garotada descolada está toda brincando com Docker hoje em dia, mas gosto de ter um ambiente linux completo com todas as dependências num lugar só. Deixo as máquinas voláteis para a nuvem.</p>
<p>Gosto de manter uma box Vagrant por perto, porque por mais bagunçado que um upgrade de sistema operacional possa ser (olhando pra você, macOS), sei que minha máquina de desenvolvimento vai simplesmente funcionar.</p>
<p>Mas mesmo com tudo virtualizado e isolado, coisas ainda podem dar errado. Atualmente estou usando <a href="https://www.vagrantup.com/downloads.html"target="_blank" rel="noopener">Vagrant 1.8.5</a>, com o <a href="https://www.vagrantup.com/vmware/"target="_blank" rel="noopener">plugin vagrant-vmware-fusion 4.0.11</a> e Vmware Fusion 8.5 no El Capitan (mesmo com o macOS Sierra tendo acabado de ser lançado, vou esperar pelo menos 1 mês antes de atualizar, nada ali vale o risco).</p>
<p>Se você está instalando uma box novinha pela primeira vez, essa é a configuração mínima do <code>Vagrantfile</code> que eu uso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="c1"># -*- mode: ruby -*-</span>
</span></span><span class="line"><span class="cl"><span class="c1"># vi: set ft=ruby :</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="no">Vagrant</span><span class="o">.</span><span class="n">configure</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">box</span> <span class="o">=</span> <span class="s2">&#34;bento/ubuntu-16.04&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:forwarded_port</span><span class="p">,</span> <span class="ss">guest</span><span class="p">:</span> <span class="mi">8080</span><span class="p">,</span> <span class="ss">host</span><span class="p">:</span> <span class="mi">8080</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:forwarded_port</span><span class="p">,</span> <span class="ss">guest</span><span class="p">:</span> <span class="mi">3000</span><span class="p">,</span> <span class="ss">host</span><span class="p">:</span> <span class="mi">3000</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:forwarded_port</span><span class="p">,</span> <span class="ss">guest</span><span class="p">:</span> <span class="mi">3001</span><span class="p">,</span> <span class="ss">host</span><span class="p">:</span> <span class="mi">3001</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:forwarded_port</span><span class="p">,</span> <span class="ss">guest</span><span class="p">:</span> <span class="mi">4000</span><span class="p">,</span> <span class="ss">host</span><span class="p">:</span> <span class="mi">4000</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:forwarded_port</span><span class="p">,</span> <span class="ss">guest</span><span class="p">:</span> <span class="mi">5555</span><span class="p">,</span> <span class="ss">host</span><span class="p">:</span> <span class="mi">5555</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:forwarded_port</span><span class="p">,</span> <span class="ss">guest</span><span class="p">:</span> <span class="mi">5556</span><span class="p">,</span> <span class="ss">host</span><span class="p">:</span> <span class="mi">5556</span>
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:forwarded_port</span><span class="p">,</span> <span class="ss">guest</span><span class="p">:</span> <span class="mi">3808</span><span class="p">,</span> <span class="ss">host</span><span class="p">:</span> <span class="mi">3808</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="s2">&#34;private_network&#34;</span><span class="p">,</span> <span class="ss">ip</span><span class="p">:</span> <span class="s2">&#34;192.168.0.100&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">synced_folder</span> <span class="s2">&#34;/Users/akitaonrails/Sites&#34;</span><span class="p">,</span> <span class="s2">&#34;/vagrant&#34;</span><span class="p">,</span> <span class="ss">nfs</span><span class="p">:</span> <span class="kp">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provider</span> <span class="ss">:vmware_fusion</span> <span class="k">do</span> <span class="o">|</span><span class="n">v</span><span class="o">|</span>
</span></span><span class="line"><span class="cl">    <span class="n">v</span><span class="o">.</span><span class="n">vmx</span><span class="o">[</span><span class="s2">&#34;memsize&#34;</span><span class="o">]</span> <span class="o">=</span> <span class="s2">&#34;2048&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Normalmente entro nas configurações do Vmware da máquina virtual e habilito um processador extra (já que meu Macbook tem 8 núcleos virtuais pra compartilhar) e habilito o hypervisor (suporte ao VT-x/EPT da Intel).</p>
<p>Como regra geral, a primeira coisa que sempre faço é configurar o locale para en_US.UTF-8:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo locale-gen &#34;en_US.UTF-8&#34;
sudo dpkg-reconfigure locales
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E, só pra garantir, adicione o seguinte ao <code>/etc/environment</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>LC_ALL=en_US.UTF-8
LANG=en_US.UTF-8</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Você precisa configurar o UTF-8 antes de instalar pacotes como o Postgresql.</p>
<p>Depois eu atualizo os pacotes e instalo o básico:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt-get update &amp;&amp; sudo apt-get upgrade
sudo apt-get install open-vm-tools build-essential libssl-dev exuberant-ctags ncurses-term ack-grep silversearcher-ag fontconfig imagemagick libmagickwand-dev python-software-properties redis-server libhiredis-dev memcached libmemcached-dev</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Isso vai instalar ferramentas importantes como Imagemagick, Memcached e Redis pra gente.</p>
<p>Agora, para <a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-16-04"target="_blank" rel="noopener">instalar o Postgresql</a>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt-get install postgresql-9.5 postgresql-contrib postgresql-server-dev-9.5</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Crie o superusuário para o vagrant:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo -i -u postgres
createuser --interactive

Enter name of role to add: vagrant
Shall the new role be a superuser? (y/n) y</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E <strong>apenas para o ambiente de desenvolvimento</strong> edite o <code>/etc/postgresql/9.5/main/pg_hba.conf</code> e altere o seguinte:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code># &#34;local&#34; is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Isso deixa sua vida mais fácil na hora de programar. Se você fez tudo certo até aqui, terá seu PG com encoding unicode adequado e sem incomodar com senha quando rodar <code>bin/rails db:create</code>. Se não configurou o locale direito antes, pode seguir <a href="https://gist.github.com/turboladen/6790847"target="_blank" rel="noopener">este gist</a> para setar o locale do PG manualmente para UTF-8.</p>
<p>Instalar <a href="https://rvm.io/rvm/install"target="_blank" rel="noopener">Ruby</a> ainda é melhor via RVM:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL https://get.rvm.io | bash
source $HOME/.rvm/scripts/rvm
rvm install 2.3.1
rvm use 2.3.1 --default</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E eu prefiro usar o <a href="https://github.com/skwp/dotfiles"target="_blank" rel="noopener">YADR</a> como meus dotfiles padrão, trocando o Bash pelo ZSH. Comparado com outros dotfiles, gosto desse porque normalmente não preciso mexer em nada, ponto. Nem vou configurar nada de RVM depois da instalação porque o YADR já cuida disso.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sh -c &#34;`curl -fsSL https://raw.githubusercontent.com/skwp/dotfiles/master/install.sh `&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Para atualizar (ou retomar caso quebre por algum motivo):</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>cd .yadr
rake update</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Os únicos 2 ajustes que tenho que fazer são mudar meu perfil do <a href="https://github.com/altercation/solarized/tree/master/iterm2-colors-solarized"target="_blank" rel="noopener">iTerm2</a> para usar <a href="http://ethanschoonover.com/solarized"target="_blank" rel="noopener">Solarized</a>, e adicionar as 2 linhas a seguir no topo do arquivo <code>.vimrc</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>scriptencoding utf-8
set encoding=utf-8</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Próximo passo, <a href="https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-16-04"target="_blank" rel="noopener">instalar o NodeJS</a>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install nodejs</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Próximo passo, <a href="https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-get-on-ubuntu-16-04"target="_blank" rel="noopener">instalar o Java</a>. Você pode escolher o instalador da Oracle, mas acredito que o openjdk deva ser suficiente:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt-get install default-jdk</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Vamos precisar do Java para o <a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-elasticsearch-on-ubuntu-16-04"target="_blank" rel="noopener">Elasticsearch</a> 2.4.0:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/deb/elasticsearch/2.4.0/elasticsearch-2.4.0.deb &amp;&amp; sudo dpkg -i elasticsearch-2.4.0.deb</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Agora você pode iniciá-lo manualmente com <code>sudo /etc/init.d/elasticsearch start</code>, e é melhor deixar assim porque ele consome bastante RAM, então só inicie quando realmente precisar.</p>
<p>Com o Java no lugar, também podemos instalar o <a href="http://leiningen.org/"target="_blank" rel="noopener">Leiningen</a> para ter o Clojure pronto.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>echo &#34;PATH=$PATH:~/bin&#34; &gt;&gt; ~/.zsh.after/bin.zsh
mkdir ~/bin &amp;&amp; cd ~/bin
wget https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
chmod a&#43;x lein
lein</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>O Leiningen vai instalar suas dependências e você pode seguir o <a href="https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md"target="_blank" rel="noopener">tutorial</a> dele para começar.</p>
<p>Instalar <a href="https://www.rust-lang.org/en-US/downloads.html"target="_blank" rel="noopener">Rust</a> é igualmente fácil:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>curl -sSf https://static.rust-lang.org/rustup.sh | sh</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Instalar <a href="https://crystal-lang.org/docs/installation/on_debian_and_ubuntu.html"target="_blank" rel="noopener">Crystal</a>, também fácil:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>curl https://dist.crystal-lang.org/apt/setup.sh | sudo bash
sudo apt-get install crystal</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Instalar <a href="https://www.digitalocean.com/community/tutorials/how-to-install-go-1-6-on-ubuntu-16-04"target="_blank" rel="noopener">Go</a> até dá, mas é mais manual:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>wget https://storage.googleapis.com/golang/go1.7.1.linux-amd64.tar.gz
tar xvfz go1.7.1.linux-amd64.tar.gz
chown -R root:root .go
sudo mv go /usr/local
touch ~/.zsh.after/go.zsh
echo &#34;export GOPATH=$HOME/go&#34; &gt;&gt; ~/.zsh.after/go.zsh
echo &#34;export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin&#34; &gt;&gt; ~/.zsh.after/go.zsh</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Assim que instalar o go e configurar o work path dele, podemos instalar algumas ferramentas úteis como o <a href="https://github.com/ddollar/forego"target="_blank" rel="noopener">forego</a> e o <a href="https://github.com/alco/goon#goon"target="_blank" rel="noopener">goon</a> (que o Hex do Elixir pode usar opcionalmente):</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>go get -u github.com/ddollar/forego
go get -u github.com/alco/goon</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E falando em <a href="http://elixir-lang.org/install.html"target="_blank" rel="noopener">Elixir</a>, deixamos o melhor pro final:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb &amp;&amp; sudo dpkg -i erlang-solutions_1.0_all.deb
sudo apt-get update
sudo apt-get install esl-erlang elixir</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E é isso, um tutorial bem direto para ter um ambiente de desenvolvimento moderno pronto pra usar. Essas são as ferramentas básicas de desenvolvimento de software que acredito que deveriam estar no cinto de utilidades de todo mundo nos próximos anos.</p>
<p>Honestamente, não mexo tanto com Clojure e Go quanto acho que deveria. E ainda não dei muito tempo pro .NET Core, mas vou explorar esses em mais detalhes no futuro.</p>
]]></content:encoded><category>linux</category><category>ferramentas-de-desenvolvimento</category></item><item><title>O Ano do Linux no Desktop - Está Usável!</title><link>https://akitaonrails.github.io/2016/07/26/o-ano-do-linux-no-desktop-esta-usavel/</link><guid isPermaLink="true">https://akitaonrails.github.io/2016/07/26/o-ano-do-linux-no-desktop-esta-usavel/</guid><pubDate>Tue, 26 Jul 2016 14:13:00 -0300</pubDate><description>&lt;p&gt;23/07/16: por coincidência, postei esse review um dia antes do release final :-) Então o build final é o 14393 e &lt;a href="http://arstechnica.com/information-technology/2016/07/windows-10-anniversary-update-is-ready-to-go-and-free-for-just-a-few-more-days/"target="_blank" rel="noopener"&gt;já está disponível&lt;/a&gt; de graça agora mesmo!&lt;/p&gt;
&lt;p&gt;Já fazem 3 meses desde que postei &lt;a href="http://www.akitaonrails.com/2016/04/12/o-ano-do-linux-no-desktop-pela-microsoft"target="_blank" rel="noopener"&gt;minhas impressões iniciais&lt;/a&gt; sobre a feature mais importante do Windows 10 Anniversary Edition: o Bash no Windows. Minha conclusão na época foi que ainda não estava pronto pra produção.&lt;/p&gt;
&lt;p&gt;Minha conclusão agora, em 26 de julho, é que finalmente está usável o suficiente pra desenvolvedores web, particularmente pra desenvolvedores Ruby que sempre sofreram com a falta de suporte no Windows.&lt;/p&gt;</description><content:encoded><![CDATA[<p>23/07/16: por coincidência, postei esse review um dia antes do release final :-) Então o build final é o 14393 e <a href="http://arstechnica.com/information-technology/2016/07/windows-10-anniversary-update-is-ready-to-go-and-free-for-just-a-few-more-days/"target="_blank" rel="noopener">já está disponível</a> de graça agora mesmo!</p>
<p>Já fazem 3 meses desde que postei <a href="http://www.akitaonrails.com/2016/04/12/o-ano-do-linux-no-desktop-pela-microsoft"target="_blank" rel="noopener">minhas impressões iniciais</a> sobre a feature mais importante do Windows 10 Anniversary Edition: o Bash no Windows. Minha conclusão na época foi que ainda não estava pronto pra produção.</p>
<p>Minha conclusão agora, em 26 de julho, é que finalmente está usável o suficiente pra desenvolvedores web, particularmente pra desenvolvedores Ruby que sempre sofreram com a falta de suporte no Windows.</p>
<p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/543/big_Screen_Shot_2016-07-26_at_13.28.48.png" alt="It’s alive!"  loading="lazy" /></p>
<p>O processo de instalação é o mesmo. Você precisa estar inscrito no programa <a href="http://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/"target="_blank" rel="noopener">Windows Insider</a>, esperar pelo menos um dia se for sua primeira vez. Habilite o <strong>Fast ring</strong> de updates, instale a edição Preview pelo Windows Update normal e então ligue a feature &ldquo;Windows Subsystem for Linux (Beta)&rdquo;.</p>
<blockquote>
  <p>Da última vez eu estava testando Windows 10 sobre Virtualbox sobre Ubuntu 14.04 num notebook Dell Inspiron (i7 com 8 cores e 16GB de RAM). Estava lentíssimo, não recomendo de jeito nenhum. Agora voltei pro meu confiável Macbook Pro 2013 com 16GB de RAM e SSD rodando VMWare Fusion, e o Windows 10 voa aqui. Super recomendado.</p>

</blockquote>
<p>Depois de fazer tudo isso, você pode iniciar o &ldquo;Bash on Ubuntu on Windows&rdquo; (que nome enorme). A primeira boa surpresa é que ele pede pra você registrar um novo nome de usuário em vez de cair direto no Root. Como falei no post anterior, é boa prática criar um novo usuário e adicionar ao grupo sudoers, e é isso que ele faz. Então você pode instalar pacotes usando &ldquo;sudo apt-get install&rdquo;.</p>
<p>Você deveria seguir meu <a href="http://www.akitaonrails.com/2016/04/12/o-ano-do-linux-no-desktop-pela-microsoft"target="_blank" rel="noopener">post anterior</a> pra ver todos os pacotes e configurações que eu normalmente faço numa máquina Linux de desenvolvimento.</p>
<p>RVM agora funciona! Consegui instalar Ruby 2.3.1 via RVM sem nenhum problema.</p>
<p>Consegui dar <code>git clone</code> num pequeno projeto Rails e rodar <code>bundle install</code> direitinho. Todas as gems foram baixadas, extensões nativas compilaram sem nenhuma falha.</p>
<p>Algumas coisas ainda não funcionam. Por exemplo, você não vai conseguir terminar a instalação do Postgresql 9.3. Ele vai baixar e instalar, mas o setup do cluster falha, como você pode acompanhar nessa <a href="https://github.com/microsoft/WSL/issues/61"target="_blank" rel="noopener">thread de issue</a>.</p>
<p>Mas você não precisa ter <strong>tudo</strong> instalado sob o Ubuntu, dá pra usar o <a href="https://www.postgresql.org/download/windows/"target="_blank" rel="noopener">Postgresql for Windows</a> nativo e editar seu <code>config/database.yml</code> apontando pro server <code>127.0.0.1</code> e porta <code>5432</code>. No lado do Ubuntu, basta instalar o <code>libpq-dev</code> pra que a gem <code>pg</code> consiga compilar suas extensões nativas e pronto.</p>
<p>Serviços menores como Memcached ou Redis instalam direitinho com <code>apt-get</code>, mas eles não vão dar auto-start via Upstart. Você pode iniciá-los manualmente e usar algo como <a href="https://github.com/ddollar/foreman"target="_blank" rel="noopener">Foreman</a> pra controlar os processos. Os dois sobem e funcionam bem o suficiente, então dá pra testar caching nos seus projetos Rails e também testar workers Sidekiq.</p>
<p>Eu sei que ainda é um Preview, então ainda vêm correções de bug e possivelmente algumas features novas até o release final de agosto. O que mais me incomoda é que todo comando que rodo com <code>sudo</code> demora alguns segundos pra começar. É irritante, mas funciona no final.</p>
<p>Node.js 6.3.1 instala e roda com sucesso. Consegui dar <code>npm i</code> e <code>node server.js</code> no <a href="https://github.com/openshift/nodejs-ex"target="_blank" rel="noopener">repositório de exemplo</a> Node do Openshift.</p>
<p>Crystal 0.18.7 instala com sucesso e compilou meu projeto <a href="https://github.com/akitaonrails/cr_manga_downloadr"target="_blank" rel="noopener">Manga Downloader</a> direitinho. Rodou meu teste de performance embutido em 15 minutos. A performance é modesta, mas executa corretamente até o fim. (E sim, Crystal agora também roda no Windows!).</p>
<p>Go 1.6 funciona. Só dei um <code>go get</code> pra instalar o Martini e rodei o simples server &ldquo;Hello World&rdquo;. Compila, inicia e executa rapidíssimo como esperado.</p>
<p>Infelizmente, Elixir 1.3.1 trava, ainda não sei por quê.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>$ iex
Crash dump is being written to: erl_crash.dump...done
erl_child_setup closed</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Na real, o próprio Erlang trava só de tentar rodar <code>erl</code>. Nenhuma das ferramentas Elixir funciona como consequência. Sem iex, sem mix. O engraçado é que estava funcionando no Preview inicial. Então ou é algo do novo Preview ou algo dos releases mais novos do Erlang. Existem <a href="https://github.com/microsoft/WSL/issues?utf8=%e2%9c%93&amp;q=is%3Aissue%20elixir"target="_blank" rel="noopener">issues abertas</a> sobre esse problema, então vamos torcer pra ser corrigido logo.</p>
<p><a name="best-windows-dev-env"></a></p>
<h3>&ldquo;O Melhor Ambiente para Rails no Windows&rdquo;<span class="hx:absolute hx:-mt-20" id="o-melhor-ambiente-para-rails-no-windows"></span>
    <a href="#o-melhor-ambiente-para-rails-no-windows" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Eu tenho <a href="https://web.archive.org/web/20160814041945/http://www.akitaonrails.com/2009/1/13/the-best-environment-for-rails-on-windows"target="_blank" rel="noopener">esse post bem antigo de 2009</a> pra guiar desenvolvedores presos no Windows que precisam implementar projetos Rails. O primeiro conselho é evitar Ruby for Windows. Eu realmente louvo os esforços de grandes desenvolvedores como o Luis Lavena, que investiu muito tempo pra fazer aquilo funcionar bem o suficiente. Mas, infelizmente, a realidade é que Ruby foi feito pra ambientes Linux, ele se conecta a extensões nativas em C que têm um monte de dependências difíceis de disponibilizar no Windows.</p>
<p>Então a melhor opção até agora era instalar Vagrant (via Virtualbox ou, melhor ainda, VMWare) como runtime e usar editores disponíveis no Windows como Sublime Text 3 ou Atom.</p>
<p>Agora você pode evitar a parte de Vagrant/virtualização e usar diretamente o &ldquo;Bash on Ubuntu on Windows&rdquo;. É tão completo que dá até pra usar ZSH e instalar dotfiles complexos como o YADR. Dá pra rodar Postgresql for Windows e conectar em localhost:5432 na sua aplicação Rails ou em qualquer aplicação web que precise de Postgresql, por exemplo.</p>
<p>Você pode instalar o ConEmu como um emulador de terminal melhor do que o cmd.exe padrão estupidamente ruim. Siga <a href="https://conemu.github.io/en/BashOnWindows.html"target="_blank" rel="noopener">esse artigo</a> pra acompanhar novidades sobre o suporte ao Bash no Windows. Por enquanto você tem que mudar o hotkey &ldquo;Ctrl-V&rdquo; pra outra coisa (&ldquo;Ctrl-Shift-V&rdquo;), as setas não funcionam direito no Vim, e dá pra adicionar uma Default Task pro Bash assim: <code>%windir%\system32\bash.exe ~ -cur_console:p</code></p>
<p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/544/big_Screen_Shot_2016-07-28_at_14.13.36.png" alt="Desenvolvendo Rails no Windows"  loading="lazy" /></p>
<h3>Conclusão<span class="hx:absolute hx:-mt-20" id="conclusão"></span>
    <a href="#conclus%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Então, sim, pelo menos a partir dessa versão que testei (instalada em 25 de julho), esse é um &ldquo;Bash on Ubuntu on Windows&rdquo; <strong>usável</strong> e desenvolvedores web de Ruby a Javascript a Crystal a Go podem começar a testar e tentar fazer do Windows 10 Anniversary sua plataforma primária pra desenvolvimento sério baseado em Linux.</p>
<p>Adicione Sublime Text ou Atom (ou Visual Studio, se for sua praia) e você está pronto. Espero que os próximos releases corrijam alguns dos bugs e problemas de performance, mas comparado ao que vimos em abril, é uma melhoria gigantesca.</p>
<p>Parabéns à Microsoft por isso!</p>
<p>E se você quer saber mais detalhes hardcore sobre como o Windows Subsystem for Linux é de fato implementado, eu recomendo essa série de posts no blog do próprio MSDN:</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/wsl/2016/04/22/windows-subsystem-for-linux-overview/"target="_blank" rel="noopener">Windows Subsystem for Linux Overview</a></li>
<li><a href="https://blogs.msdn.microsoft.com/wsl/2016/05/23/pico-process-overview/"target="_blank" rel="noopener">Pico Process Overview</a></li>
<li><a href="https://blogs.msdn.microsoft.com/wsl/2016/06/08/wsl-system-calls/"target="_blank" rel="noopener">WSL System Calls</a></li>
<li><a href="https://blogs.msdn.microsoft.com/wsl/2016/06/15/wsl-file-system-support/"target="_blank" rel="noopener">WSL File System Support</a></li>
</ul>
]]></content:encoded><category>microsoft</category><category>linux</category><category>ferramentas-de-desenvolvimento</category><category>off-topic</category></item><item><title>O Ano do Linux no Desktop, pela Microsoft??</title><link>https://akitaonrails.github.io/2016/04/12/o-ano-do-linux-no-desktop-pela-microsoft/</link><guid isPermaLink="true">https://akitaonrails.github.io/2016/04/12/o-ano-do-linux-no-desktop-pela-microsoft/</guid><pubDate>Tue, 12 Apr 2016 18:33:00 -0300</pubDate><description>&lt;p&gt;Pois é, finalmente chegou. Escrevi sobre o anúncio no evento Build alguns dias atrás &lt;a href="http://www.akitaonrails.com/2016/03/31/off-topic-uma-nova-era-para-a-microsoft"target="_blank" rel="noopener"&gt;aqui&lt;/a&gt;. Agora a Microsoft provoca mais um pouco e &lt;a href="http://thehackernews.com/2016/04/how-to-run-ubuntu-on-windows-10.html"target="_blank" rel="noopener"&gt;liberou o primeiro Insider Build Preview&lt;/a&gt;. O rótulo é &amp;ldquo;Build 14316.rs1_release.160402-2217&amp;rdquo;; confira se é exatamente esse antes de seguir.&lt;/p&gt;
&lt;p&gt;Para conseguir baixar, você precisa atender aos seguintes requisitos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ter um Windows 10 64 bits ativado&lt;/li&gt;
&lt;li&gt;Inscrever-se no programa &lt;a href="https://insider.windows.com/"target="_blank" rel="noopener"&gt;Windows Insider&lt;/a&gt;. Se for sua primeira vez, pode levar até 24 horas para ativar&lt;/li&gt;
&lt;li&gt;Nas configurações do Windows Update, em Opções Avançadas, escolha &amp;ldquo;Get Started&amp;rdquo; na opção Insider e também escolha o anel &amp;ldquo;Fast&amp;rdquo;. Agora, ao buscar atualizações, o Preview 14316 deve aparecer. Se não aparecer, espere até a Microsoft atualizar sua conta.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/538/windows_update_settings.jpg"target="_blank" rel="noopener"&gt;&lt;img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/538/big_windows_update_settings.jpg" alt="configurações do windows update" loading="lazy" /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>Pois é, finalmente chegou. Escrevi sobre o anúncio no evento Build alguns dias atrás <a href="http://www.akitaonrails.com/2016/03/31/off-topic-uma-nova-era-para-a-microsoft"target="_blank" rel="noopener">aqui</a>. Agora a Microsoft provoca mais um pouco e <a href="http://thehackernews.com/2016/04/how-to-run-ubuntu-on-windows-10.html"target="_blank" rel="noopener">liberou o primeiro Insider Build Preview</a>. O rótulo é &ldquo;Build 14316.rs1_release.160402-2217&rdquo;; confira se é exatamente esse antes de seguir.</p>
<p>Para conseguir baixar, você precisa atender aos seguintes requisitos:</p>
<ul>
<li>Ter um Windows 10 64 bits ativado</li>
<li>Inscrever-se no programa <a href="https://insider.windows.com/"target="_blank" rel="noopener">Windows Insider</a>. Se for sua primeira vez, pode levar até 24 horas para ativar</li>
<li>Nas configurações do Windows Update, em Opções Avançadas, escolha &ldquo;Get Started&rdquo; na opção Insider e também escolha o anel &ldquo;Fast&rdquo;. Agora, ao buscar atualizações, o Preview 14316 deve aparecer. Se não aparecer, espere até a Microsoft atualizar sua conta.</li>
</ul>
<p><a href="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/538/windows_update_settings.jpg"target="_blank" rel="noopener"><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/538/big_windows_update_settings.jpg" alt="configurações do windows update"  loading="lazy" /></a></p>
<p>Você precisa ter, no mínimo, 10GB de espaço livre na sua partição principal, então tenha isso em mente. Outra observação: se você é como eu e está testando no Virtualbox, lembre que para redimensionar um disco virtual é preciso deletar os snapshots, e o processo de merge pode demorar um tempo ridículo.</p>
<p>Depois de instalado, vá às opções de Desenvolvedor no Painel de Controle &ldquo;Update &amp; Security&rdquo; e mude seu perfil para &ldquo;Developer Mode&rdquo;. A feature &ldquo;Bash on Windows&rdquo; vai aparecer na lista de Windows Features. É voltada <strong>apenas para desenvolvedores</strong>, não deve ser usada em servidores de produção.</p>
<p>Com o Preview instalado, você deve conseguir abrir o velho cmd.exe (ou qualquer console melhor como o <a href="https://conemu.github.io/"target="_blank" rel="noopener">ConEmu</a>) e digitar &ldquo;bash&rdquo;. Ele vai pedir para instalar o userland do Ubuntu empacotado pela Canonical. Mais um tempinho. Aliás, o processo todo demora bastante, então reserve pelo menos meio dia. Não faça isso no trabalho :-)</p>
<p>Um problema que esbarrei logo de cara foi que a rede não estava funcionando direito. Alguém <a href="https://github.com/microsoft/WSL/issues/35"target="_blank" rel="noopener">identificou</a> que o DNS não estava sendo adicionado em <tt>/etc/resolv.conf</tt>, então é preciso adicionar manualmente. Basta colocar o DNS do Google (8.8.8.8 e 8.8.4.4) no arquivo resolv.conf e pronto.</p>
<p>Por fim, você cai dentro do bash como usuário root. Se você é um usuário Windows, saiba desde já que rodar como root é inseguro e uma péssima prática. Não faça isso.</p>
<p>A primeira coisa que você <strong>precisa</strong> fazer é criar manualmente um usuário Linux sem privilégios e adicioná-lo ao grupo sudo, como Andrew Malton <a href="https://web.archive.org/web/20160411063840/http://blog.greenarrow.me/elixir-with-ubuntu-for-windows/"target="_blank" rel="noopener">publicou</a> primeiro:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>useradd new_username -m -s /bin/bash 
passwd new_username
usermod -aG sudo new_username</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Aí você pode logar nesse shell de usuário com <tt>su - [seu usuário]</tt> sempre que quiser!</p>
<p>A partir daqui, podemos assumir que é um Ubuntu 14.04 comum e você deve conseguir seguir o <a href="http://www.akitaonrails.com/2015/01/28/ruby-e-rails-no-ubuntu-14-04-lts-trusty-tahr"target="_blank" rel="noopener">meu post bem antigo</a> sobre como configurar um ambiente Ubuntu para desenvolvedor, ou qualquer outro tutorial pelo Google. Os pacotes básicos de desenvolvimento que sempre instalo primeiro rodam normalmente:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo apt-get install curl build-essential openssl libcurl4-openssl-dev libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev libgmp-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion redis-server libhiredis-dev memcached libmemcached-dev imagemagick libmagickwand-dev exuberant-ctags ncurses-term ack-grep git git-svn gitk ssh libssh-dev

sudo dpkg-divert --local --divert /usr/bin/ack --rename --add /usr/bin/ack-grep</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Isso te dá toda a toolchain essencial de compilação além de algumas ferramentas de linha de comando bem conhecidas como o ack (muito melhor que o grep). Também adiciona Redis e Memcached. Todos rodam.</p>
<p>Como boa prática, adicione o seguinte ao arquivo de configuração <tt>/etc/bash.bashrc</tt>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E depois disso, configure também o locale para UTF-8:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>sudo locale-gen en_US.UTF-8
sudo dpkg-reconfigure locales</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Só para esquentar um pouco, podemos começar com uma das coisas que eram impossíveis no Windows: ter uma instalação estável de Ruby. Para isso, dizem que o RVM não funciona (assim como o ZSH também não funciona devido a problemas de /dev/pts e symlinks neste preview, veja mais abaixo). Mas o RBENV funciona! Você precisa <a href="https://github.com/rbenv/rbenv"target="_blank" rel="noopener">instalá-lo</a> primeiro e depois o plugin <a href="https://github.com/rbenv/ruby-build#readme"target="_blank" rel="noopener">ruby-build</a>:</p>
<p><a href="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/536/installing_ruby.png"target="_blank" rel="noopener"><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/536/big_installing_ruby.png" alt="instalando ruby pelo rbenv"  loading="lazy" /></a></p>
<p>Curiosamente, demora bastante para terminar e durante o processo o uso de CPU vai às alturas. Instalar Go é ainda mais demorado! Algo continua instável por baixo dos panos, porque a CPU não deveria ficar a 100% por tanto tempo.</p>
<p><img src="https://akitaonrails.s3.amazonaws.com/assets/image_asset/image/537/big_resources.jpg" alt="CPU nas alturas"  loading="lazy" /></p>
<p>Se eu checar quanta memória tenho no sistema fica mais claro:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>root@localhost:/mnt/c/Users/fabio# free -h
             total       used       free     shared    buffers     cached
Mem:          1.0G       342M       664M         0B         0B         0B
-/&#43; buffers/cache:       342M       664M
Swap:           0B         0B         0B</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Não tenho certeza se esse valor de memória é meio &ldquo;hard-coded&rdquo;, já que muita gente está reportando os mesmos &ldquo;664M&rdquo; livres independente do que esteja rodando. Mas tem algo incompleto aqui. Swap também é zero e você não consegue adicionar nenhum, pelo que pude testar. Swapon, fallocate, nada disso funciona ainda.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>root@localhost:/mnt/c/Users/fabio# swapon -s
swapon: /proc/swaps: open failed: No such file or directory

root@localhost:/mnt/c/Users/fabio# fallocate -l 4G swapfile
fallocate: swapfile: fallocate failed: Invalid argument</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Cheguei a tentar <a href="https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04"target="_blank" rel="noopener">criar um swap file</a> usando <tt>dd</tt> em vez de <tt>fallocate</tt> e adicionar ao <tt>/etc/fstab</tt>, mas não funcionou:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>root@localhost:/mnt/c/Users/fabio# free -m
             total       used       free     shared    buffers     cached
Mem:          1006        342        664          0          0          0
-/&#43; buffers/cache:        342        664
Swap:            0          0          0

root@localhost:/mnt/c/Users/fabio# cat /etc/fstab
LABEL=cloudimg-rootfs   /        ext4   defaults        0 0
/swapfile       none    swap    sw      0 0</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Então parece mesmo que a memória está &ldquo;hard-coded&rdquo;. Acompanhe <a href="https://github.com/microsoft/WSL/issues/92"target="_blank" rel="noopener">esta issue #92</a> se quiser ver como vai evoluir.</p>
<p>Mas pior que isso, a memória compartilhada tem limites muito baixos e comportamento estranho. O Postgresql instala mas não sobe de jeito nenhum:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>root@localhost:/mnt/c/Users/fabio# pg_createcluster 9.3 main --start
Creating new cluster 9.3/main ...
  config /etc/postgresql/9.3/main
  data   /var/lib/postgresql/9.3/main
  locale en_US.UTF-8
FATAL:  could not create shared memory segment: Invalid argument
DETAIL:  Failed system call was shmget(key=1, size=48, 03600).
HINT:  This error usually means that PostgreSQL&#39;s request for a shared memory segment exceeded your kernel&#39;s SHMMAX parameter, or possibly that it is less than your kernel&#39;s SHMMIN parameter.
        The PostgreSQL documentation contains more information about shared memory configuration.
child process exited with exit code 1
initdb: removing contents of data directory &#34;/var/lib/postgresql/9.3/main&#34;
Error: initdb failed</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E se tentamos expandir o limite SHMMAX, é isso que acontece:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>root@localhost:/mnt/c/Users/fabio# sysctl -w kernel.shmmax=134217728
sysctl: cannot stat /proc/sys/kernel/shmmax: No such file or directory

root@localhost:/mnt/c/Users/fabio# echo 134217728 &gt;/proc/sys/kernel/shmmax
bash: /proc/sys/kernel/shmmax: Operation not permitted</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Então, sem Postgresql por enquanto. Algumas pessoas que conseguiram completar a instalação do Go Lang (eu desisti depois de muito tempo esperando o apt-get terminar) reclamaram que o Go também quebrou nos requisitos de memória compartilhada. Acompanhe a <a href="https://github.com/microsoft/WSL/issues/32"target="_blank" rel="noopener">Issue #32</a> e a <a href="https://github.com/microsoft/WSL/issues/146"target="_blank" rel="noopener">Issue #146</a> para ver se alguém consegue fazer rodar.</p>
<p>Também tentei instalar o Node.js. Sem sorte com a instalação dos pacotes:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>curl -sL https://deb.nodesource.com/setup_5.x | sudo -E bash -
...
E: dpkg was interrupted, you must manually run &#39;sudo dpkg --configure -a&#39; to correct the problem.
Error executing command, exiting</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>O NVM instala, mais ou menos, com vários erros no git:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>...
error: unable to create file test/slow/nvm run/Running &#34;nvm run 0.x&#34; should work (No such file or directory)
error: unable to create file test/slow/nvm run/Running &#34;nvm run&#34; should pick up .nvmrc version (No such file or directory)
error: unable to create file test/slow/nvm use/Running &#34;nvm use iojs&#34; uses latest io.js version (No such file or directory)
error: unable to create file test/slow/nvm use/Running &#34;nvm use node&#34; uses latest stable node version (No such file or directory)
error: unable to create file test/slow/nvm use/Running &#34;nvm use v1.0.0&#34; uses iojs-v1.0.0 iojs version (No such file or directory)
error: unable to create file test/slow/nvm use/Running &#34;nvm use&#34; calls &#34;nvm_die_on_prefix&#34; (No such file or directory)</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E é isso que acontece se eu tento instalar a versão mais recente:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>akitaonrails@localhost:~/.nvm$ nvm install 5.10.1
Downloading https://nodejs.org/dist/v5.10.1/node-v5.10.1-linux-x64.tar.xz...
######################################################################## 100.0%
tar: bin/npm: Cannot create symlink to &#39;../lib/node_modules/npm/bin/npm-cli.js&#39;: Invalid argument
tar: Exiting with failure status due to previous errors
Binary download failed, trying source.
######################################################################## 100.0%
Checksums empty
tar: bin/npm: Cannot create symlink to &#39;../lib/node_modules/npm/bin/npm-cli.js&#39;: Invalid argument
tar: Exiting with failure status due to previous errors
Binary download failed, trying source.
Detected that you have 1 CPU thread(s)
Number of CPU thread(s) less or equal to 2 will have only one job a time for &#39;make&#39;
Installing node v1.0 and greater from source is not currently supported</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>A <a href="https://github.com/microsoft/WSL/issues/9"target="_blank" rel="noopener">Issue #9</a> aponta para a falta de suporte a symlinks.</p>
<p>Outra coisa muito chata é a falta de Pseudo-Terminais (/dev/pts), que é possivelmente uma das razões do ZSH não funcionar. Acompanhe a <a href="https://github.com/microsoft/WSL/issues/80"target="_blank" rel="noopener">Issue #80</a>.</p>
<p>Você também deve conseguir copiar suas chaves SSH privadas para &ldquo;.ssh&rdquo; e começar a clonar do Github ou dar git push para o Heroku rapidinho.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>akitaonrails@localhost:~$ ssh-keygen  -t rsa
Generating public/private rsa key pair.
Created directory &#39;/home/akitaonrails/.ssh&#39;.kitaonrails/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/akitaonrails/.ssh/id_rsa.
Your public key has been saved in /home/akitaonrails/.ssh/id_rsa.pub.
The key fingerprint is:
f8:16:b1:be:85:31:0c:71:f8:c2:d3:72:ab:48:42:9a akitaonrails@localhost
The key&#39;s randomart image is:
&#43;--[ RSA 2048]----&#43;
|      ...        |
|      .o         |
|     ..o.        |
|  .   =&#43;&#43;o       |
| &#43;    .=S.       |
|E . .  o.=       |
|   o . .= .      |
|    . .. o       |
|        .        |
&#43;-----------------&#43;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pelo menos o Elixir parece funcionar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>akitaonrails@localhost:~$ iex
Erlang/OTP 18 [erts-7.3] [source-d2a6d81] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.2.3) - press Ctrl&#43;C to exit (type h() ENTER for help)
iex(1)&gt; defmodule HelloWorld do; def say(name) do; IO.puts(&#34;Hello #{name}&#34;); end; end
iex:1: warning: redefining module HelloWorld
{:module, HelloWorld,
 &lt;&lt;70, 79, 82, 49, 0, 0, 5, 240, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 147, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;,
 {:say, 1}}
iex(2)&gt; HelloWorld.say(&#34;Fabio&#34;)
Hello Fabio
:ok</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Calma lá&hellip;</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>akitaonrails@localhost:~$ mix new ex_test
** (ErlangError) erlang error: :terminated
    (stdlib) :io.put_chars(#PID&lt;0.25.0&gt;, :unicode, [[[[[[[] | &#34;\e[32m&#34;], &#34;* creating &#34;] | &#34;\e[0m&#34;], &#34;.gitignore&#34;] | &#34;\e[0m&#34;], 10])
    (mix) lib/mix/generator.ex:26: Mix.Generator.create_file/3
    (mix) lib/mix/tasks/new.ex:76: Mix.Tasks.New.do_generate/4
    (elixir) lib/file.ex:1138: File.cd!/2
    (mix) lib/mix/cli.ex:58: Mix.CLI.run_task/2</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Você vai encontrar mais informações no pseudo-projeto que a Microsoft abriu no Github para acompanhar as <a href="https://github.com/microsoft/WSL/issues?q=is%3Aissue&#43;is%3Aclosed"target="_blank" rel="noopener">Issues</a> de testers como eu. Dá para acompanhar a lista de issues abertas e fechadas por lá. Você vai ver muita coisa que funciona, mas também muita outra que não vai funcionar até sair uma nova release que conserte tudo o que mencionei aqui.</p>
<h3>Conclusão<span class="hx:absolute hx:-mt-20" id="conclusão"></span>
    <a href="#conclus%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Então, o &ldquo;Bash on Windows&rdquo; é um bom ambiente de desenvolvimento para usuários Linux terem sobre o Windows?</p>
<p>No Preview 14316, ainda não. A palavra-chave aqui é &ldquo;ainda&rdquo;. Está tomando forma de um jeito legal e, se conseguirem realmente corrigir todas as issues abertas até agora, vai ficar muito utilizável muito rápido.</p>
<p>Ainda faltam controles de memória decentes, suporte bem implementado de pseudo-terminal, limites configuráveis de memória compartilhada e symlinks funcionando. Falta também o upstart do Ubuntu, para que serviços como Redis ou Memcached (que instalei e rodam) subam sozinhos quando eu inicio o ambiente. Hoje eles não voltam sozinhos depois que reinicio a máquina.</p>
<p><a href="http://www.neowin.net/news/bash-plus-windows-10-equals-linux-gui-apps-on-the-windows-desktop"target="_blank" rel="noopener">Algumas pessoas</a> chegaram a conseguir enganar o X11 e rodar apps GUI como Firefox e até XFCE sobre esse ambiente, então é realmente promissor. Essa ideia funciona.</p>
<p>Uma vez que essas issues sejam resolvidas, sim, acredito que estamos mais perto do que nunca de finalmente usar Windows como um ambiente de desenvolvimento viável e completo. Vamos ver se até o Anniversary Release do Windows 10 em junho vamos ter uma instalação estável de Ubuntu.</p>
<p>Uma coisa que acho que fizeram muito errado foi amarrar o Linux Subsystem à instalação do Windows 10. Devia ter sido um instalador separado, para que o time pudesse liberar atualizações de build sem ter que empacotar tudo junto com o sistema operacional inteiro.</p>
<p>Se você estava pretendendo migrar para Windows para seus desenvolvimentos baseados em Linux, ainda não. Segure os cavalos um pouco mais.</p>
]]></content:encoded><category>microsoft</category><category>linux</category><category>ferramentas-de-desenvolvimento</category><category>off-topic</category></item><item><title>[Off-Topic] Uma Nova Era para a Microsoft</title><link>https://akitaonrails.github.io/2016/03/31/off-topic-uma-nova-era-para-a-microsoft/</link><guid isPermaLink="true">https://akitaonrails.github.io/2016/03/31/off-topic-uma-nova-era-para-a-microsoft/</guid><pubDate>Thu, 31 Mar 2016 16:10:00 -0300</pubDate><description>&lt;p&gt;Atualização 07/04: &lt;a href="http://thehackernews.com/2016/04/how-to-run-ubuntu-on-windows-10.html"target="_blank" rel="noopener"&gt;o preview já saiu&lt;/a&gt; antecipando o lançamento em Junho. Se você for membro do programa Insider, baixe e teste já. Deixe suas impressões nos comentários.&lt;/p&gt;
&lt;p&gt;Ontem foi um dia histórico para a Microsoft. Na minha visão pessoal, pode ter sido um divisor de águas. Desde ontem venho tentando pensar em como deixar isso registrado para a posteridade.&lt;/p&gt;
&lt;h3&gt;Prólogo - 1995 a 2005, 1a Década&lt;span class="hx:absolute hx:-mt-20" id="prólogo---1995-a-2005-1a-década"&gt;&lt;/span&gt;
&lt;a href="#pr%c3%b3logo---1995-a-2005-1a-d%c3%a9cada" class="subheading-anchor" aria-label="Permalink for this section"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Digo isso para nós, desenvolvedores de software. Já conhecemos alguns divisores assim na história: o lançamento do Turbo Pascal em 1983, o do Visual Basic em 1991, o do Java em 1995, as primeiras distros de Linux como o Slackware a partir de 1993, o lançamento do OS X em 2000 e a transição de PowerPC para Intel em 2005.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Atualização 07/04: <a href="http://thehackernews.com/2016/04/how-to-run-ubuntu-on-windows-10.html"target="_blank" rel="noopener">o preview já saiu</a> antecipando o lançamento em Junho. Se você for membro do programa Insider, baixe e teste já. Deixe suas impressões nos comentários.</p>
<p>Ontem foi um dia histórico para a Microsoft. Na minha visão pessoal, pode ter sido um divisor de águas. Desde ontem venho tentando pensar em como deixar isso registrado para a posteridade.</p>
<h3>Prólogo - 1995 a 2005, 1a Década<span class="hx:absolute hx:-mt-20" id="prólogo---1995-a-2005-1a-década"></span>
    <a href="#pr%c3%b3logo---1995-a-2005-1a-d%c3%a9cada" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Digo isso para nós, desenvolvedores de software. Já conhecemos alguns divisores assim na história: o lançamento do Turbo Pascal em 1983, o do Visual Basic em 1991, o do Java em 1995, as primeiras distros de Linux como o Slackware a partir de 1993, o lançamento do OS X em 2000 e a transição de PowerPC para Intel em 2005.</p>
<p>Os anos 80 e 90 foram conturbados, uma época de crescimento acelerado em que tudo ficava obsoleto muito rápido. Numa década, de 1989 até 1999, passei de Basic para dBase, Clipper, Fox Pro, Visual Basic, Delphi, Java, multimídia (Flash, Director/Shockwave) e Internet (HTML, Javascript, ASP, PHP, Perl). Nunca vi uma década andar tão rápido. Fui de um XT de 4 MHz para um Pentium III de quase 1 GHz nesses dez anos.</p>
<p>Chegamos ao fim do século no ápice da Bolha da Internet, tivemos o 11 de Setembro em 2001 e o crash. Mas a Internet chegou para ficar, e os dispositivos começaram a despontar com os Palms e iPods. Em 2001 a Microsoft lançou o Windows XP e passaria a década seguinte carregando esse legado nas costas.</p>
<p>Um ano antes, a pequena Apple iniciava seu levante com os novos iMac, iBook e iPod, além do OS X baseado em BSD UNIX. Um passo de cada vez, ela montava um sistema pensado tanto para consumidores quanto para desenvolvedores, a promessa da NeXT ganhando forma uma década depois de sua concepção.</p>
<p>Então, em 2005, a Apple forjaria aliança com uma das mais antigas parceiras da Microsoft, a Intel, e finalmente os Macs rodariam no mesmo processador que o Windows, dando um salto estratosférico em adoção. E isso abria mais uma porta: como o OS X foi feito agnóstico de processador, era questão de tempo até rodar em chips ARM, menores e mais eficientes. Foi o que aconteceu em 2007 com o lançamento do iPhone. O resto é história.</p>
<h3>2005 a 2015 - 2a Década<span class="hx:absolute hx:-mt-20" id="2005-a-2015---2a-década"></span>
    <a href="#2005-a-2015---2a-d%c3%a9cada" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Enquanto isso, a Microsoft ficou para trás. Fracassou na promessa do Windows Vista, entregou um Windows 7 competente e emendou no controverso Windows 8. Só com o Windows 10, anunciado no fim de 2014, é que as coisas começaram a mudar. E os efeitos da morte de Steve Jobs, no fim de 2011, ficavam mais aparentes: a Apple parou.</p>
<p>De 2011 até hoje, só tivemos novas versões. Nada significativo, nada novo. O último grande iPhone foi o 5, de 2012. O último grande felino do OS X foi o Mountain Lion, de 2011. Enquanto isso, o Google passou à frente no mundo mobile quando o KitKat saiu em 2013, para mim a primeira versão do Android em pé de igualdade com o iOS.</p>
<p>De 1999 até 2005, no geral, o desenvolvedor de software enterprise tinha duas opções: Java e .NET. O PHP tinha boa adoção, mas na maioria como customização de Wordpress e Magento, longe da mesma categoria de Java ou .NET; o resto era nicho. A partir de 2006 surgiu uma nova geração de desenvolvedores para a chamada Web 2.0, o mundo pós-Google, com SEO, UX, iterações rápidas e Agilidade com &ldquo;A&rdquo; maiúsculo. Foi ali que Ruby, Python e depois Node aceleraram exponencialmente.</p>
<p>A partir de 2010, o mundo mobile acelerou, e em particular um tipo de desenvolvimento integrado: baseado em &ldquo;Cloud&rdquo;, em que uma &ldquo;app&rdquo; nativa fala com serviços em servidores remotos, sobretudo da Amazon AWS, que havia estreado não fazia muito tempo, em 2006.</p>
<p>A Microsoft ficou de fora desse movimento e gastou os dez anos seguintes correndo atrás, na ressaca do Vista. Manteve a liderança em mercados puramente enterprise, com licenças de SQL Server e Office, mas à margem do &ldquo;cutting-edge&rdquo; do desenvolvimento de software.</p>
<p>Na verdade, eu diria que o divisor de águas veio em 2013, com a <a href="http://web.archive.org/web/20160404073120/http://olhardigital.uol.com.br/pro/noticia/mercado-reage-bem-a-saida-de-ballmer-da-microsoft/36992"target="_blank" rel="noopener">saída de Ballmer</a> e o fim da &ldquo;Era Estendida de Gates&rdquo;, abrindo espaço para a <a href="http://www.businessinsider.com/microsoft-year-in-review-2015-12"target="_blank" rel="noopener">entrada de Satya Nadella</a>. A Microsoft é uma entidade gigante, muitos cérebros já pesquisavam isso fazia anos, e boa parte só apareceu agora. Mas falo em &ldquo;Eras&rdquo; num sentido simbólico: o fim da cultura Highlander da Microsoft, o &ldquo;there can only be one&rdquo;.</p>
<p>A <a href="http://1995blog.com/2015/05/24/the-internet-tidal-wave-20-years-on/"target="_blank" rel="noopener">profecia de 1995</a>, de que a Internet destruiria a hegemonia do Windows, se cumpriu. E chegamos ao mundo pós-Moore, em que a computação ficou acessível e ubíqua. Pense nisso: em 1995, ter um cluster de &ldquo;super&rdquo; computadores para computação distribuída de alto processamento era coisa de universidade ou grande corporação. Hoje, você cria um cluster de quantas dúzias de máquinas quiser no EC2 por um mês pelo preço de um videogame.</p>
<p>Fui usuário de DOS desde 1988, mudei para o Windows 95 assim que saiu e passei quase dez anos desenvolvendo primariamente em Windows, em ambiente corporativo. Fui de Visual Basic para ASP e para .NET ao mesmo tempo que mexia com Java e PHP. Mas eu queria poder usar Perl, PHP, Python e Ruby nativos de Linux, sem abrir mão de Office e Photoshop.</p>
<p>A resposta que já esperávamos era o OS X. Com o lançamento do Tiger, a coisa ficou séria. Eu mesmo experimentei com um Mac Mini G4 em 2004. Era excepcional ter uma usabilidade muito melhor que a do Windows XP e acesso a tudo de UNIX numa única máquina.</p>
<p>Quando a Intel lançou o Core Duo e depois o Core 2 Duo de 64 bits, e o Tiger passou a rodar em Intel em 2005, não havia o que pensar: era hora de migrar. Passaria a década seguinte num ambiente puramente OS X, desenvolvendo em outro tipo de plataforma, com outras ferramentas e outra cultura. Foi toda a minha história com Ruby e OS X nesses dez anos, que vocês conhecem bem se acompanham o blog.</p>
<h3>2015 em diante, Epílogo<span class="hx:absolute hx:-mt-20" id="2015-em-diante-epílogo"></span>
    <a href="#2015-em-diante-ep%c3%adlogo" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>2015 chegou, quatro anos depois da morte de Steve Jobs. Foi um intervalo importante, porque deu tempo para as plataformas não-Mac se equipararem e superarem o OS X em muitas áreas. Estamos definitivamente na Era do Software como Serviço. Não &ldquo;compramos&rdquo; mais nada, &ldquo;assinamos&rdquo; serviços.</p>
<p>Passamos da Era Pós-PC. Passamos da Era do Smartphone. Estamos na Era dos Serviços, em que tudo é um serviço. Nossa identidade é um perfil do Facebook, nossa voz é o Zap Zap, e tudo o que fazemos gera dados. Estamos na Era do Big Data, um monte de dados inúteis que nenhum SQL Server do mundo dá conta de manter.</p>
<p>Precisamos de coisas novas para lidar com esse paradigma: Cassandra, Riak, Hadoop, HBase, Spark, Elasticsearch, Go, Rust, Elixir. Todos eles &ldquo;rodam&rdquo; em Windows, mas alguém precisa gastar tempo fazendo ports, criando patches de compatibilidade e empacotando instaladores. E o principal: a maioria dos desenvolvedores dessas tecnologias está em Linux ou em OS X, quase ninguém desenvolve essa nova geração de ferramentas dentro do Windows. Todos usam Emacs, Vim ou Sublime Text, quase ninguém quer o Visual Studio.</p>
<p>E isso volta ao começo do post: é uma nova Era para a Microsoft. Ela passou os últimos dez anos correndo atrás e, pela primeira vez, parece ter chances reais de dar a volta por cima e voltar a ser relevante para o desenvolvedor não-.NET.</p>
<p>Para isso, duas coisas aconteceram ontem.</p>
<h3>2016 - O Ano do Linux no Desktop<span class="hx:absolute hx:-mt-20" id="2016---o-ano-do-linux-no-desktop"></span>
    <a href="#2016---o-ano-do-linux-no-desktop" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Primeiro, o anúncio de que o <a href="http://thehackernews.com/2016/03/ubuntu-on-windows-10.html"target="_blank" rel="noopener">&ldquo;Bash está chegando ao Windows&rdquo;</a>. Que na prática é muito mais do que o Bash: é uma parceria com a Canonical, que já vinha se desenhando desde o anúncio do <a href="http://web.archive.org/web/20160415160138/http://www.microsoft.com/en/server-cloud/sql-server-on-linux.aspx"target="_blank" rel="noopener">SQL Server rodando em Linux</a>. Na prática, é um <a href="http://blog.dustinkirkland.com/2016/03/ubuntu-on-windows.html"target="_blank" rel="noopener">subsistema Linux</a> rodando em paralelo à kernel do Windows, traduzindo chamadas de sistema Linux para Windows.</p>
<p>A ideia original veio do falecido Projeto Astoria, ou Windows Bridge for Android, que na época queria permitir apps Android rodando em Windows. Tecnicamente o Android é um tipo de Linux, então o salto para ontem foi curto.</p>
<p>Assim, será possível pegar um binário feito para Ubuntu e rodá-lo no Windows sem modificar nada.</p>
<p>Desde que começamos a desenvolver com Ruby, muita gente que usa Windows queria rodar Ruby nativamente. Existe uma <a href="http://rubyinstaller.org/"target="_blank" rel="noopener">distribuição</a>, mas não é boa, e a culpa não é dos mantenedores. O Ruby, assim como Python e PHP, foi feito para funcionar em Linux.</p>
<p>Para portar para Windows é preciso fazer &ldquo;wrappers&rdquo;, e ainda falta um ambiente com compiladores como o GCC para compilar pacotes de extensões. Tudo isso é trivial no Linux e uma dor de cabeça no Windows. Não valia o trabalho, então a única saída era rodar uma máquina virtual (como o VirtualBox) com algo como o Vagrant para facilitar e usar o Ruby de Linux de verdade.</p>
<p>Tudo de Linux que &ldquo;funciona&rdquo; em Windows, seja Python ou PHP, nunca funcionou 100%, e a gente simplesmente se acostumou com isso.</p>
<p>O que a Microsoft vai lançar no Anniversary Update é uma camada muito fina de tradução no nível mais baixo, e não uma máquina virtual ou um hypervisor: de uma kernel Linux &ldquo;virtual&rdquo; para a kernel do Windows. Tudo vai pensar que está rodando em Linux. É o que o projeto Wine tenta fazer para rodar aplicações Windows no Linux, só que ao contrário. Também é diferente do Cygwin, que exige recompilar tudo do Linux para ter um ambiente semi-Linux sobre o Windows.</p>
<p>Provavelmente não haverá ambiente gráfico secundário num primeiro momento, então nada de X, nada de GNOME ou KDE. E nem precisa: estamos num mundo Web, nosso ambiente gráfico agora é HTML e Javascript, e Chrome e Firefox já existem nativos no Windows. Para coisas como compilar gems com extensões nativas, até o GCC vai funcionar. É exatamente o mesmo binário, no mesmo ambiente, com tudo a que estamos acostumados no UNIX. Ter Bash e SSH no Windows é só a ponta do iceberg.</p>
<p>O segundo anúncio é o <a href="http://techcrunch.com/2016/03/31/thanks-to-microsoft-small-teams-can-now-get-xamarins-ide-and-core-tools-for-free"target="_blank" rel="noopener">lançamento das ferramentas Xamarin de graça e como open source</a>! A Microsoft adquiriu a Xamarin, de Miguel de Icaza, há pouco tempo. Eles desenvolveram o .NET open source por pura engenharia reversa, reimplementando tudo em código aberto, e agora a Microsoft fez a coisa inteligente: além de comprá-los, abriu as ferramentas. A última coisa que ainda prendia um desenvolvedor no Mac era precisar do Xcode, que já vem no OS X, para desenvolver para iOS. Agora dá para fazer isso no Windows de graça.</p>
<p>Portanto, a conta ficou bem mais simples. O Windows 10 é a primeira versão respeitável de Windows desde o breve intervalo do 7. Vamos esquecer que o 8 existiu, do mesmo jeito que já esquecemos do Vista. O XP finalmente morreu, levou mais de uma década, junto com os horrorosos Internet Explorer 6, 7 e 8. O Google nos fez o favor de tornar o Chrome ubíquo, e serviços como o Facebook forçaram os usuários a migrar mais rápido.</p>
<p>Com o <a href="http://arstechnica.com/information-technology/2016/03/windows-10-270-million-users-binbash-supporting-anniversary-update-coming-summer/"target="_blank" rel="noopener">Windows 10 Anniversary Update</a>, provavelmente vamos poder fazer:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>apt-get install build-essential
\curl -sSL https://get.rvm.io | bash
rvm install 2.3.0
bundle install</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E tudo deve funcionar.</p>
<p>No mesmo ambiente, ainda vamos poder usar o Xamarin Studio e, com um pouco de esforço para relembrar os músculos de C#, criar apps iOS e Android. Vamos poder usar o Office 365 nativo, todas as ferramentas mais recentes do Adobe CS6 e até jogar The Division, tudo na mesma máquina.</p>
<p>De uma só vez, o Windows 10 vira a escolha com o melhor custo-benefício: comodidade de uso, opções de desenvolvimento e hardware competente na forma de Surface Book, Lenovo Yoga 3 e Razer Blade Stealth, que finalmente alcançaram e passaram o lendário acabamento dos MacBook.</p>
<p>2016 é finalmente o famigerado Ano do Linux no Desktop, só que não do jeito que o pessoal de Free Software gostaria. Não dá para ter tudo.</p>
]]></content:encoded><category>microsoft</category><category>ferramentas-de-desenvolvimento</category><category>mercado-de-tecnologia</category><category>off-topic</category></item></channel></rss>