/etc/udev/rules.d/50-bluetooth.rules
ACTION=="add", SUBSYSTEM=="input", ATTRS{uniq}=="<keyboard-mac-address>", RUN+="/home/cleber/bin/on-bt-keyboard-connected.sh"
Preste atenção ao <keyboard-mac-address>
. Você pode vê-lo usando o comando bluetoothctl
:
$ bluetoothctl
[prompt] devices
Device F4:73:xx:xx:xx:xx Keyboard K380
Device 2E:D6:xx:xx:xx:xx Philips TAT1215
bin/on-bt-keyboard-connected.sh
#!/bin/bash
export DISPLAY=:0.0
(
sleep 2.5
su -c 'xmodmap /home/cleber/.Xmodmap' cleber
# su -c 'command' user
) &
O sleep
é necessário (pelo que entendi) porque o Xorg demora um pouco para “carregar” o teclado depois que o mesmo é detectado pelo udev
.
~/.Xmodmap
No meu caso, eu mapeio o CTRL para a tecla Caps Lock, enquanto o Caps Lock mesmo vai parar na right-CTRL.
$ cat ~/.Xmodmap
remove Lock = Caps_Lock
keysym Caps_Lock = Control_L
add Control = Control_L
remove Control = Control_R
add Lock = Control_R
Ou seria “golang”?
golang golang golang golang golang golang golang golang golang golang golang golang golang golang
Pronto. Talvez assim esse artigo seja encontrado quando alguém buscar algo sobre “Go” no Google.
Briguinhas
Durante uma década inteira ficamos contentes com nossas pequenas brigas entre diversos feudos. Python (ou, “os programadores que usavam linguagem Python”) fazia graça com Java e sua sintaxe ridícula, Java gabava-se de ser “Enterprise” enquanto temia a vinda da .Net que, por sua vez, tentava ser um pouco de tudo, mas focava mesmo em C#, que por sua vez era desprezada pelo C++ por ser “muito pesada” ou “pouco portável” enquanto o velho C assistia a tudo, sentindo-se superior, e dava risada enquanto seus usuários dançavam num salão recém-encerado carregando navalhas.
Read more...
Pode parecer um erro idiota (e talvez seja mesmo), mas acredito ser bem comum, especialmente quando você está começando com Erlang: chamar self/0 logo depois do spawn, pensando que está referindo-se ao processo pai.
Exemplo:
funcao_pai() -ᐳ faz_algo(),
spawn(
fun() -ᐳ
funcao_filha(self())
end
).
É fácil de você se confundir e começar a pensar no processo novo a partir da execução de funcao_filha/1, isto é, a partir da entrada em seu escopo. Engano! O escopo do novo processo é a fun/0 que foi chamada pela spawn/1.
Consequentemente, aquela chamada a self/0 não retorna o PID do processo pai (execução em funcao_pai/0), mas o PID do processo filho (execução já na fun/0).
Quando você está no meio de um “ímpeto programadorístico”, essa coisa óbvia pode passar desapercebida. Fica a dica. :)
Este artigo foi escrito originalmente em 14/12/2014.
A ideia do kerl é facilitar o building e a instalação de instâncias de Erlang/OTP ([https://github.com/yrashk/kerl]). Ele permite que você instale, por exemplo, várias versões da VM e até facilita que você tenha várias instâncias da mesma versão, mas compiladas com opções diferentes (habilitar o HiPE apenas em uma, por exemplo).
E o melhor é que trata-se apenas de um pequeno script shell. Vamos começar a usá-lo?
Read more...
Chegou a hora de vermos uma das features mais alardeadas pelo povo do Erlang: concorrência.
Primeiramente, vamos definir o que é concorrência e o que é paralelismo.
Na visão dos criadores de Erlang, concorrência é, meramente, você ter mais de um processo trabalhando na mesma máquina. Eles não precisam ser executados ao mesmo tempo. Se você tem uma CPU com um núcleo só e um sistema operacional multi-tasking, você deve ter vários programas sendo executados em condição de concorrência nesse exato momento. Mas cada um tem seu próprio “espacinho” na fila da CPU.
Read more...
É, pois é. A gente costuma começar com o “Hello World” e eu simplesmente esqueci. Se bem que não faz diferença, mesmo, já que há anos eu não faço “Hello Worlds” para começar a aprender linguagens de programação…
O que vamos ver hoje são os caracteres de formatação de io:format/2.
~n
Imprime o caracter de “nova linha”.
Read more...
Eu não gastei muito tempo explicando recursão por causa daquilo que disse no começo deste curso: eu considero que quem o está seguindo são programadores experientes. Eu sei que o conceito de recursão pode ser difícil para iniciantes, mas não é aqui o lugar para entrar no b+a=ba da coisa.
O que programadores experientes podem achar estranho é o uso de recursão para quase tudo. “É que recursão consome pilha” você deve estar pensando. E está até certo. Nas linguagens procedurais e nas orientadas a calças, fazer uma recursão muito profunda pode se tornar uma grande dor de cabeça.
Python, por exemplo, tem um limite de recursão interno. Depois de umas milhares de chamadas, o interpretador sobe uma exceção (“RuntimeError: maximum recursion depth exceeded”). Em C, se você estourar a pilha, teu programa morre.
Read more...
Eu cá estava pensando em pegar leve e mostrar comparações entre valores, shifts, aritmética, etc. Depois iria ver estruturas de dados. Mas, seria muito, muito chato. É melhor já entrarmos nas funções para que você possa se animar com a linguagem. :)
Mas, primeiro…
Átomos
Pois é, antes de entrarmos no reino das funções, precisamos entender o que é um átomo.
Ao contrário de Python, por exemplo, em que as coisas são, basicamente, valores ou keywords (10, “x”, while), Erlang, sendo um bom filho de Prolog, tem também átomos.
Read more...
Conforme prometido, vamos ver uma implementação alternativa da função ler_arquivo/1. Para isso, vamos criar o módulo funcoes2 (“funcoes2.erl”).
-module(funcoes2).-export([ler_arquivo/1]).
ler_arquivo(Filename) -ᐳ
{ok, Fd} = file:open(Filename, [read]),
interpretar_linha(Fd).
interpretar_linha(Fd) -ᐳ
Leitura = file:read_line(Fd),
case Leitura of
{ok, Linha} -ᐳ
[PrimeiroChar|Resto] = Linha,
case PrimeiroChar of
$# -ᐳ pulando;
_ -ᐳ io:format("~s", [Linha])
end,
interpretar_linha(Fd);
eof -ᐳ file:close(Fd)
end.
Aqui a recursão permanece (vide linha 17), formando nosso “loop”, mas o tratamento dos tipos de linha é feito dentro da própria função. Para isso, usamos um case.
Read more...
Vamos implementar a nossa função das aulas anteriores em Python?
Vamos!
#!/usr/bin/python
# -*- coding: utf-8 -*-
def interpretar_linhas(filename):
with open(filename) as arquivo:
for linha in arquivo:
if not linha.startswith('#'):
print linha,
if __name__ == '__main__':
import sys
interpretar_linhas(sys.argv[1])
Sim, eu sei que tem menos linhas e sei que o código aparenta ser mais claro. É quase desonesto comparar esse tipo de requisito (jogar na tela um arquivo texto com todas as linhas que não comecem com “#”) implementado em Python com qualquer outra linguagem.
(Mas, claro, um Perl monk conseguiria fazer isso tudo em uma linha só (eu acho).)
Read more...