Manual do EEditor

Referência completa para o aplicativo EEditor e a linguagem EELisp. Abrange todos os recursos, todas as funções embutidas e todos os atalhos de teclado.

Sumário

I. Guia do Editor

  1. Primeiros Passos
  2. O Editor
  3. Barra Lateral e Árvore de Arquivos
  4. Abas e Arquivos Fixados
  5. Busca e Abertura Rápida
  6. Visualização e Exportação PDF
  7. Notas Diárias e Planejador Semanal
  8. Visualização de Calendário
  9. Barra Lateral de Agenda
  10. Barra Lateral do REPL
  11. Blocos de Código EELisp
  12. Atalhos de Teclado

II. O REPL

  1. Usando o REPL
  2. Comandos do REPL

III. Linguagem EELisp

  1. Aritmética e Matemática
  2. Comparação e Lógica
  3. Variáveis e Funções
  4. Fluxo de Controle
  5. Strings
  6. Listas
  7. Dicionários
  8. Tipos e Conversão
  9. E/S e Datas
  10. Funções do Prelude
  11. HTTP e JSON
  12. Sistema de Arquivos
  13. Integração com o Editor
  14. Área de Transferência

IV. Banco de Dados

  1. Definindo Tabelas
  2. Registros e Consultas
  3. Visualizações Interativas
  4. Gerenciamento de Banco de Dados

V. Sistema de Agenda

  1. Itens
  2. Categorias
  3. Regras de Auto-Categorização
  4. Visualizações
  5. Consultas de Calendário
  6. Entrada Inteligente
  7. Itens Recorrentes e Modelos
  8. Múltiplas Agendas

VI. Integração

  1. Integração GUI e EELisp
Parte I — Guia do Editor

1. Primeiros Passos

Ao iniciar o EEditor pela primeira vez, você vê um editor vazio com uma barra lateral. Três passos para começar:

  1. Abrir uma pasta — pressione ⌘O ou toque no ícone de pasta. O EEditor escaneia o diretório e exibe todos os arquivos na árvore da barra lateral.
  2. Selecionar um arquivo — clique em qualquer arquivo na barra lateral para abri-lo em uma nova aba.
  3. Comece a escrever — as edições são salvas automaticamente após 1 segundo de inatividade. Pressione ⌘S para salvar imediatamente.
Dica: O EEditor lembra da última pasta aberta por meio de bookmarks com escopo de segurança. Ela é restaurada automaticamente ao reiniciar.

Abrindo arquivos individuais

Use ⌘⇧O para abrir um único arquivo de qualquer lugar no disco. O diretório pai do arquivo se torna a pasta ativa.

2. O Editor

O EEditor oferece um ambiente de escrita sem distrações com destaque de sintaxe em tempo real para Markdown e mais de 24 linguagens de programação.

3. Barra Lateral e Árvore de Arquivos

A barra lateral mostra uma visualização hierárquica da sua pasta. Diretórios aparecem primeiro, depois arquivos em ordem alfabética.

A barra lateral possui três modos através do controle segmentado: Arquivos, Calendário e Agenda.

4. Abas e Arquivos Fixados

Cada arquivo abre como uma aba no topo do editor.

AçãoAtalhoObservações
Próxima aba⌘⌥→Volta ao início
Aba anterior⌘⌥←Volta ao início
Fechar aba⌘WSalva automaticamente se houver alterações
Fechar todas as não fixadas⌘⌥W
Fixar / Desfixar⌘⇧KAbas fixadas persistem entre sessões

Abas fixadas exibem um ícone de pino, aparecem primeiro (ordenadas alfabeticamente) e não podem ser fechadas até serem desfixadas. Elas são restauradas automaticamente ao reiniciar.

5. Busca e Abertura Rápida

Busca em texto completo (⌘⇧F)

Abertura Rápida (⌘P)

Wiki-links (⌘O)

Posicione o cursor em um link [[nome-do-arquivo]] e pressione ⌘O para abrir o arquivo diretamente.

6. Visualização e Exportação PDF

Visualização Markdown (⌘⇧P)

Exportação PDF (⌘⇧E)

7. Notas Diárias e Planejador Semanal

Nota diária (⌘D)

Planejador semanal (⌘⇧W)

8. Visualização de Calendário

Alterne a barra lateral para o modo Calendário usando o controle segmentado.

9. Barra Lateral de Agenda

Alterne para o modo Agenda pelo ícone de prancheta. O painel mostra sua programação em três seções:

Cada item mostra um ponto de prioridade (vermelho = urgente, laranja = alta, amarelo = média, cinza = normal), texto, categorias e data formatada. Toque em atualizar para recarregar após adicionar itens no REPL.

Barra Lateral do REPL

O REPL é um painel na barra lateral direita que coexiste com o editor. Alterne-o com ⌘⇧L ou o ícone de terminal na barra de ferramentas.

Blocos de Código EELisp em Markdown

Incorpore código EELisp executável diretamente nos seus arquivos Markdown usando blocos de código delimitados:

```eelisp
(+ 1 2 3)
```

Executando um bloco de código

  1. Posicione o cursor em qualquer lugar dentro de um bloco ```eelisp.
  2. Pressione ⌘⇧Return (ou use o menu: Visualizar → Executar Bloco EELisp).
  3. O resultado aparece como um bloco ```result logo abaixo.
```eelisp
(+ 1 2 3)
```
```result
6
```

Reexecutar substitui o resultado existente. O resultado é inserido como texto simples (não em um bloco de código) e é selecionado automaticamente para que você possa imediatamente ⌘C para copiar ou ⌘X para recortar.

Formulários e tabelas no editor

Quando um bloco EELisp retorna um formulário (edit, defform) ou tabela (browse), ele abre como um painel lateral interativo ao lado do editor em vez de inserir texto simples. Você pode interagir com o formulário — navegar registros, editar campos, salvar — mantendo seu documento visível. Uma linha de resumo ainda é inserida no documento.

Casos de uso incluem cálculos inline, adição de itens de agenda a partir de entradas de diário, consulta de dados e operações com arquivos:

```eelisp
(add-item (smart-parse "tomorrow review quarterly report !!"))
```

```eelisp
(write-file "todo.txt" "Buy groceries\nCall dentist")
```

10. Atalhos de Teclado

Pressione ⌘? no aplicativo para ver a folha completa de atalhos. Aqui está a referência completa:

Arquivos

AçãoAtalho
Novo arquivo⌘N
Abrir pasta⌘O
Abrir arquivo⌘⇧O
Salvar⌘S
Atualizar árvore⌘⇧R
Nota diária⌘D
Planejador semanal⌘⇧W

Navegação

AçãoAtalho
Abertura Rápida⌘P
Buscar nos arquivos⌘⇧F
Buscar e Substituir⌘F
Focar no editor⌘\
Abrir wiki-link⌘O

Abas

AçãoAtalho
Próxima aba⌘⌥→
Aba anterior⌘⌥←
Fechar aba⌘W
Fechar todas as não fixadas⌘⌥W
Fixar / Desfixar aba⌘⇧K

Edição

AçãoAtalho
Inserir data/hora⌘I
Desfazer⌘Z
Refazer⌘⇧Z

Visualização e Exportação

AçãoAtalho
Visualizar⌘⇧P
Exportar PDF⌘⇧E
Alternar Barra Lateral do REPL⌘⇧L
Enviar para o REPL⌘R
Executar Bloco EELisp⌘⇧Return
Inserir Bloco EELisp⌘⇧C
Executar (no REPL)⌘Return
Ajuda de atalhos⌘?
Parte II — O REPL

11. Usando o REPL

O EEditor inclui um interpretador Lisp embutido chamado EELisp — projetado para gerenciamento de dados pessoais, cálculos e scripts.

Abrindo o REPL

Avaliando expressões

Enviar para o REPL (⌘R ou ⌘⇧L)

Selecione texto no editor e pressione ⌘R ou ⌘⇧L. A barra lateral do REPL abre com sua seleção pré-preenchida no campo de entrada, pronta para você pressionar ⌘Return para avaliar.

Comandos de banco de dados

O EELisp inclui funções embutidas e comandos do REPL para gerenciamento de bancos de dados:

ComandoDescrição
(tables)Listar todas as tabelas no banco de dados atual
(describe tablename)Mostrar o esquema de uma tabela
(drop-table tablename)Excluir uma tabela
:dbMostrar o caminho do banco de dados atual
:db <path>Alternar para um arquivo de banco de dados diferente
:db new <name>Criar um novo arquivo de banco de dados na pasta atual
:db memoryAlternar para um banco de dados em memória

Carregando arquivos

Use :load path/to/file.el para carregar e avaliar um script EELisp. No iOS, toque no botão Carregar na barra de ferramentas ou clique com botão direito em um arquivo .el na barra lateral.

Barra de ferramentas do iOS

No iOS/iPadOS, uma barra de ferramentas aparece com: navegação de histórico (↑/↓), snippets rápidos (query, deftable, defn), Carregar Arquivo e Limpar.

12. Comandos do REPL

Comandos prefixados com dois-pontos controlam o próprio REPL (não são expressões EELisp):

ComandoAliasDescrição
:help:hMostrar referência de comandos e exemplos rápidos
:load <file>:lCarregar e avaliar um arquivo .el / .lisp
:dbMostrar caminho do banco de dados atual (:memory: ou caminho do arquivo)
:db <path>Alternar para um arquivo de banco de dados diferente
:db new <name>Criar um novo banco de dados na pasta atual
:db memoryAlternar para um banco de dados em memória
:env:eListar todos os símbolos definidos no ambiente
:clear:cLimpar histórico de saída do REPL
:reset:rReiniciar interpretador (ambiente limpo, mesmo banco de dados)
Conexão automática ao banco de dados: Quando você abre uma pasta contendo um arquivo eelisp.db, o REPL conecta-se automaticamente a ele para armazenamento persistente. Dados criados com deftable e insert são salvos em disco.
Parte III — Referência da Linguagem EELisp

13. Aritmética e Matemática

Todos os operadores aritméticos são variádicos (aceitam múltiplos argumentos) e funcionam com inteiros e números de ponto flutuante.

FunçãoAssinaturaDescrição
+(+ num ...)Adição. (+ 1 2 3)6
-(- num ...)Subtração ou negação. (- 10 3)7, (- 5)-5
*(* num ...)Multiplicação. (* 2 3 4)24
/(/ num num ...)Divisão. (/ 100 3)33.333...
mod(mod a b)Módulo. (mod 10 3)1
abs(abs num)Valor absoluto. (abs -42)42
min(min num ...)Mínimo. (min 3 1 4)1
max(max num ...)Máximo. (max 3 1 4)4
floor(floor num)Arredondar para baixo. (floor 3.7)3
ceil(ceil num)Arredondar para cima. (ceil 3.2)4
pow(pow base exp)Exponenciação. (pow 2 10)1024
round(round num [places])Arredondar. (round 3.14159 2)3.14
;; Exemplos de aritmética
(+ 1 2 3 4)            ; → 10
(* 6 7)                ; → 42
(/ 100 3)              ; → 33.333...
(pow 2 10)             ; → 1024
(round 3.14159 2)     ; → 3.14

;; Aninhamento
(+ (* 3 4) (- 10 5))    ; → 17

14. Comparação e Lógica

FunçãoAssinaturaDescrição
=(= a b)Igualdade. Funciona com números, strings, booleanos
!=(!= a b)Desigualdade
<(< a b)Menor que
>(> a b)Maior que
<=(<= a b)Menor ou igual
>=(>= a b)Maior ou igual

Operadores lógicos

Estes são formas especiais (avaliação em curto-circuito):

(and true false)        ; → false
(or  false true)        ; → true
(not true)              ; → false

;; Curto-circuito: (or) retorna o primeiro valor verdadeiro
(or nil false 42 99)    ; → 42

15. Variáveis e Funções

Definindo variáveis

(def x 42)
(def greeting "Hello, world!")
(def pi 3.14159)

Definindo funções

(defn square (x)
  (* x x))

(square 5)  ; → 25

;; Corpo com múltiplas expressões (último valor é retornado)
(defn greet (name)
  (def msg (str "Hello, " name "!"))
  (println msg)
  msg)

Funções anônimas

(map (fn (x) (* x x)) '(1 2 3))  ; → (1 4 9)

Parâmetros rest

(defn sum (first . rest)
  (reduce + first rest))

(sum 1 2 3 4 5)  ; → 15

Ligações locais

(let ((x 1) (y 2))
  (+ x y))  ; → 3

16. Fluxo de Controle

if

(if (> x 0) "positive" "non-positive")

cond

(cond
  (< x 0)  "negative"
  (= x 0)  "zero"
  else     "positive")

when

;; Executa o corpo somente se a condição for verdadeira
(when (> x 0)
  (println "positive!")
  x)

loop / recur

;; Soma de 0 a 10
(loop ((i 0) (acc 0))
  (> i 10)
  (recur (+ i 1) (+ acc i)))  ; → 55

begin

;; Avalia múltiplas expressões, retorna a última
(begin
  (def a 10)
  (def b 20)
  (+ a b))  ; → 30

17. Strings

FunçãoAssinaturaExemplo → Resultado
str(str val ...)(str "a" "b" "c")"abc"
str-len(str-len s)(str-len "hello")5
str-upper(str-upper s)(str-upper "hello")"HELLO"
str-lower(str-lower s)(str-lower "HELLO")"hello"
str-contains(str-contains s sub)(str-contains "hello" "ell")true
str-starts-with(str-starts-with s prefix)(str-starts-with "hello" "he")true
str-ends-with(str-ends-with s suffix)(str-ends-with "hello" "lo")true
str-split(str-split s sep)(str-split "a,b,c" ",")("a" "b" "c")
str-join(str-join sep list)(str-join "-" '("a" "b"))"a-b"
str-trim(str-trim s)(str-trim " hi ")"hi"
str-replace(str-replace s target repl)(str-replace "hello" "l" "r")"herro"
str-matches(str-matches s regex)Retorna lista de grupos de captura ou nil
substr(substr s start [end])(substr "hello" 1 3)"el"

18. Listas

FunçãoAssinaturaExemplo → Resultado
list(list val ...)(list 1 2 3)(1 2 3)
cons(cons val list)(cons 0 '(1 2))(0 1 2)
car / head(car list)(car '(1 2 3))1
cdr / tail(cdr list)(cdr '(1 2 3))(2 3)
nth(nth list n)(nth '(a b c) 1)b
length(length seq)(length '(1 2 3))3
append(append list ...)(append '(1) '(2 3))(1 2 3)
reverse(reverse list)(reverse '(1 2 3))(3 2 1)
map(map fn list)(map inc '(1 2 3))(2 3 4)
filter(filter fn list)(filter even? '(1 2 3 4))(2 4)
reduce(reduce fn init list)(reduce + 0 '(1 2 3))6
range(range [start] end [step])(range 1 6)(1 2 3 4 5)
flatten(flatten list)(flatten '(1 (2 3) (4)))(1 2 3 4)
sort-by(sort-by fn list)(sort-by id '(3 1 2))(1 2 3)
zip(zip list list)(zip '(1 2) '(a b))((1 a) (2 b))
empty?(empty? val)(empty? '())true
;; Encadeando operações de lista
(def nums (range 1 11))
(filter even? nums)            ; → (2 4 6 8 10)
(map (fn (x) (* x x))
     (filter even? nums))       ; → (4 16 36 64 100)
(reduce + 0 (range 1 101))   ; → 5050

19. Dicionários

Dicionários usam chaves de palavra-chave (:name) e são imutáveis — operações retornam novos dicionários.

FunçãoAssinaturaExemplo → Resultado
dict(dict :key val ...)(dict :a 1 :b 2){:a 1 :b 2}
dict-get(dict-get d key [default])(dict-get d :name) → valor ou nil
dict-set(dict-set d key val)Retorna novo dicionário com a chave definida
dict-keys(dict-keys d)(dict-keys {:a 1 :b 2})(:a :b)
dict-values(dict-values d)(dict-values {:a 1 :b 2})(1 2)
dict-has(dict-has d key)(dict-has {:a 1} :a)true
dict-merge(dict-merge d ...)Mescla dicionários; chaves posteriores sobrescrevem
(def person {:name "Alice" :age 30})
(dict-get person :name)          ; → "Alice"
(dict-set person :age 31)        ; → {:name "Alice" :age 31}
(dict-merge person {:city "NYC"}) ; → {:name "Alice" :age 30 :city "NYC"}

20. Tipos e Conversão

Predicados de tipo

FunçãoRetorna verdadeiro quando
string?O valor é uma string
number?O valor é um número
bool?O valor é um booleano
list?O valor é uma lista
nil?O valor é nil/null
symbol?O valor é um símbolo
keyword?O valor é uma palavra-chave
fn?O valor é uma função
dict?O valor é um dicionário
date?O valor é uma data
record?O valor é um registro de banco de dados
item?O valor é um item de agenda

Inspeção de tipo

(type 42)          ; → "number"
(type "hello")     ; → "string"
(type '(1 2))      ; → "list"

Funções de conversão

FunçãoDescrição
->stringConverter qualquer valor para sua representação em string
->numberConverter string para número, booleano para 0/1
->boolVeracidade: nil, false, 0, "" → false; todo o resto → true

21. I/O & Datas

Saída

FunçãoDescrição
(print val ...)Imprime valores sem nova linha final
(println val ...)Imprime valores com nova linha final

Funções de data

FunçãoAssinaturaDescrição
now(now)Objeto de data/hora atual
today(today)Hoje como string ISO "YYYY-MM-DD"
date-format(date-format date [fmt])Formata uma data. Padrão: "yyyy-MM-dd HH:mm"
date-add(date-add date n :unit)Adiciona dias/semanas/meses. Unidades: :days, :weeks, :months
date-diff(date-diff d1 d2)Diferença em dias entre duas strings de data ISO
(today)                              ; → "2026-02-23"
(date-add (today) 7 :days)          ; → "2026-03-02"
(date-add "2026-01-31" 1 :months)   ; → "2026-02-28"
(date-diff "2026-01-01" "2026-12-31") ; → 364

22. Funções do Prelude

Essas funções são definidas no próprio EELisp e carregadas automaticamente na inicialização:

FunçãoDescriçãoExemplo
incIncrementa por 1(inc 5)6
decDecrementa por 1(dec 5)4
even?Verdadeiro se par(even? 4)true
odd?Verdadeiro se ímpar(odd? 3)true
zero?Verdadeiro se zero(zero? 0)true
pos?Verdadeiro se positivo(pos? 5)true
neg?Verdadeiro se negativo(neg? -3)true
firstPrimeiro elemento(first '(a b c))a
secondSegundo elemento(second '(a b c))b
thirdTerceiro elemento(third '(a b c))c
lastÚltimo elemento(last '(a b c))c
takePega os primeiros n(take 2 '(a b c))(a b)
dropDescarta os primeiros n(drop 1 '(a b c))(b c)
some?Algum corresponde?(some? even? '(1 2 3))true
every?Todos correspondem?(every? pos? '(1 2 3))true
pipeEncadeamento(pipe 5 inc inc square)49
composeCompõe funções((compose inc square) 5)26
partialAplicação parcial((partial + 10) 5)15
idFunção identidade(id 42)42

23. HTTP & JSON

FunçãoAssinaturaDescrição
http-get(http-get url)Requisição GET. Retorna {:status N :body "..."}
http-post(http-post url body [:content-type "..."])Requisição POST com corpo
json-parse(json-parse string)Analisa JSON para dict/lista EELisp
json-stringify(json-stringify value)Converte valor EELisp para string JSON
;; Buscar dados de uma API
(def resp (http-get "https://api.example.com/data"))
(def data (json-parse (dict-get resp :body)))

;; Enviar JSON via POST
(http-post "https://api.example.com/items"
  (json-stringify {:name "test"})
  :content-type "application/json")

Avaliação

FunçãoDescrição
(eval expr)Avalia uma expressão não avaliada
(parse string)Analisa uma string como código EELisp

Sistema de Arquivos

O EELisp pode ler e escrever arquivos na sua pasta aberta. Todos os caminhos são relativos ao diretório do workspace atual.

FunçãoDescrição
(read-file path)Lê o conteúdo do arquivo como uma string
(write-file path content)Escreve conteúdo em um arquivo (cria ou sobrescreve)
(append-file path content)Adiciona conteúdo ao final de um arquivo existente
(file-exists? path)Verifica se um arquivo existe
(list-files [path])Lista nomes de arquivos em um diretório (padrão: raiz do workspace)
(current-dir)Obtém o caminho raiz do workspace
;; Ler um arquivo
(def content (read-file "notes.md"))

;; Escrever resultados em um arquivo
(write-file "output.txt" (str "Report: " (today)))

;; Adicionar a um log
(append-file "log.txt" (str (today) " - Done\n"))

;; Listar arquivos do workspace
(list-files)       ; → ("README.md" "notes.md" ...)
(list-files "src") ; → ("main.el" "utils.el" ...)

Integração com o Editor

Esses builtins permitem que o código EELisp interaja com o buffer ativo do editor.

FunçãoDescrição
(cursor-pos)Obtém a posição atual do cursor (offset de caractere)
(set-cursor-pos pos)Move o cursor para uma posição
(insert-at pos text)Insere texto em uma posição
(replace-range start end text)Substitui texto entre início e fim
(selection)Obtém o texto selecionado atualmente (ou nil)
(current-file)Obtém o caminho do arquivo ativo
(buffer-text)Obtém o texto completo do editor ativo
;; Inserir texto na posição do cursor
(insert-at (cursor-pos) (str "Updated: " (today)))

;; Obter o que está selecionado
(def sel (selection))

;; Ler o buffer inteiro
(def text (buffer-text))
(println (str "Length: " (str-len text)))

Área de Transferência

FunçãoDescrição
(clipboard-get)Lê texto da área de transferência
(clipboard-set text)Copia texto para a área de transferência
;; Copiar um resultado para a área de transferência
(clipboard-set (str "Total: $" (reduce + 0 '(10 20 30))))

;; Colar e processar conteúdo da área de transferência
(str-upper (clipboard-get))
Parte IV — Referência de Banco de Dados

24. Definindo Tabelas

O EELisp inclui um mecanismo de banco de dados SQLite integrado. As tabelas são definidas com esquemas tipados.

Sintaxe básica

(deftable contacts (name:string email:string age:number))

Tipos de campo

TipoDescriçãoValores de exemplo
stringDados de texto"Alice", "hello@example.com"
numberInteiro ou float42, 3.14
boolBooleanotrue, false
dateString de data ISO"2026-02-23"
memoTexto longoConteúdo multilinha
choiceSeletor dropdownLista de opções predefinidas

Gerenciamento de tabelas

FunçãoDescrição
(tables)Lista todos os nomes de tabelas
(describe table)Mostra o esquema da tabela
(drop-table table)Exclui uma tabela e todos os seus dados
(pack table)Remove permanentemente registros excluídos por soft-delete
;; Exemplo completo
(deftable tasks (title:string priority:number done:bool due:date))
(tables)       ; → (tasks)
(describe tasks) ; → detalhes do esquema

25. Registros & Consultas

Inserindo registros

(insert tasks {:title "Write docs" :priority 1 :done false})
(insert tasks {:title "Fix bug" :priority 2 :done false :due "2026-03-01"})

Consultando

;; Todos os registros
(query tasks)

;; Com cláusula WHERE
(query tasks :where "priority <= ?" :params (list 2))

;; Ordenado e limitado
(query tasks :order "priority" :limit 5)

;; Selecionar colunas específicas
(query tasks :select "title, done")

;; Ordem decrescente
(query tasks :order "priority" :asc false)

Atualizando & excluindo

;; Atualizar por ID
(update tasks 1 {:done true})

;; Soft-delete (estilo dBASE, pode ser recuperado)
(delete tasks 1)

;; Remover permanentemente registros com soft-delete
(pack tasks)

;; Contar registros
(count-records tasks)
(count-records tasks :where "done = ?" :params (list false))

Acesso a registros

FunçãoDescrição
(field-get record :field)Obtém o valor de um campo de um registro
(field-set record :field val)Retorna novo registro com campo atualizado
(record-id record)Obtém o ID numérico do registro
(records result-set)Extrai lista de registros de um resultado de consulta
;; Trabalhando com resultados de consulta programaticamente
(def results (query tasks :where "done = ?" :params (list false)))
(def recs (records results))
(map (fn (r) (field-get r :title)) recs)  ; → ("Write docs" "Fix bug")

26. Visualizações Interativas

O EELisp pode renderizar componentes de UI interativos diretamente na saída do REPL.

Browse (visualização em tabela)

;; Navegar por todos os registros em uma grade rolável
(browse tasks)

;; Com filtros e ordenação
(browse tasks :where "done = ?" :params (list false) :order "priority")

Edit (formulário CRUD)

;; Abrir um formulário interativo para criar/ler/atualizar/excluir
(edit tasks)

;; Com filtros
(edit tasks :where "priority = ?" :params (list 1))

O formulário mostra um registro por vez com navegação Anterior/Próximo, edição inline, e botões Salvar, Novo e Excluir.

Formulários computados (defform)

;; Formulário de calculadora independente com campos computados
(defform loan-calc
  (principal:number rate:number years:number)
  :computed (
    (monthly-payment
      (let ((r (/ rate 1200))
            (n (* years 12)))
        (round (/ (* principal r (pow (+ 1 r) n))
                  (- (pow (+ 1 r) n) 1)) 2)))
    (total-paid
      (round (* monthly-payment (* years 12)) 2))))

Campos computados são atualizados automaticamente quando os campos de entrada mudam.

Campos de escolha (dropdown)

Use a sintaxe (name:choice "opt1" "opt2" ...) para criar um seletor dropdown:

(defform new-task
  (title:string
   (priority:choice "low" "medium" "high" "urgent")
   (status:choice "todo" "in-progress" "done")
   notes:memo))

Campos de escolha são renderizados como um menu dropdown na interface do formulário.

Formulários vinculados a tabelas (:source)

Vincule um formulário a uma tabela de banco de dados existente com :source para habilitar CRUD completo:

;; Criar uma tabela primeiro
(deftable projects (name:string status:string budget:number))
(insert projects {:name "Alpha" :status "active" :budget 50000})

;; Formulário vinculado à tabela com dropdown para status
(defform project-editor
  (name:string
   (status:choice "planning" "active" "completed")
   budget:number)
  :source projects)

O formulário carrega registros da tabela de origem com navegação Anterior/Próximo, e botões Salvar, Novo e Excluir — como (edit table) mas com tipos de campo personalizados.

27. Gerenciamento de Banco de Dados

Conexão automática

Comandos de banco de dados do REPL

ComandoDescrição
:dbMostra o caminho do banco de dados atual
:db <path>Alterna para um arquivo de banco de dados diferente (relativo à pasta)
:db new <name>Cria um novo banco de dados na pasta atual
:db memoryAlterna para um banco de dados em memória
Dica: Os caminhos do banco de dados são relativos à pasta aberta atualmente. Use :db mydata.db em vez de digitar o caminho completo.
Parte V — Sistema de Agenda

28. Itens

O sistema de agenda é um gerenciador de informações pessoais inspirado no Lotus Agenda. Itens são entradas de texto livre com metadados opcionais.

Adicionando itens

(add-item "Finish quarterly report")

;; Com metadados
(add-item "Call dentist" :when "2026-03-01" :priority 2)
(add-item "Buy groceries" :category "personal" :notes "milk, eggs")

;; Adicionar com a data de hoje
(add-item-today "Review pull requests" :priority 1)

Consultando itens

(items)                          ; todos os itens (visualização em tabela)
(items :category "work")        ; filtrar por categoria
(items :search "quarterly")     ; busca por texto
(items :priority 1)             ; filtrar por prioridade
(items :when-before "2026-03-01") ; vencimento antes da data

Gerenciando itens

FunçãoDescrição
(item-get id)Busca um único item por ID
(item-edit id)Abre item na visualização de formulário para edição
(item-set id :field val ...)Atualiza campos do item
(item-done id)Marca item como concluído (soft-delete)
(item-count)Conta todos os itens
(item-count :category "work")Conta itens em uma categoria

29. Categorias

As categorias são hierárquicas (use separadores /) e opcionalmente exclusivas (o item pode estar em apenas um filho).

;; Categorias hierárquicas
(defcategory work)
(defcategory work/projects)
(defcategory work/meetings)
(defcategory personal)
(defcategory personal/errands)

;; Exclusiva: item pode estar em apenas um filho
(defcategory priority :exclusive true
  :children (high medium low))

;; Atribuir / desatribuir
(assign 1 "work/projects")
(assign 1 "priority/high")
(unassign 1 "personal")

;; Ver árvore de categorias
(categories)
Dica: Quando um pai é :exclusive true, atribuir um filho (ex.: priority/low) remove automaticamente os irmãos (ex.: priority/high). Perfeito para status, prioridade ou qualquer agrupamento de escolha única.

30. Regras de Auto-Categorização

Regras categorizam automaticamente itens com base em seu conteúdo — o recurso principal do Lotus Agenda.

;; Regras de correspondência de texto
(defrule urgent-flag
  :when (str-contains text "URGENT")
  :assign "priority/high")

(defrule meeting-detect
  :when (or (str-contains text "meeting")
            (str-contains text "call with"))
  :assign "work/meetings")

;; Regex com extração de data
(defrule date-extract
  :when (str-matches text "\\b(\\d{4}-\\d{2}-\\d{2})\\b")
  :action (item-set id :when (match 1)))

;; Aplicar regras
(apply-rules)      ; aplicar em lote a todos os itens
(apply-rules 42)   ; aplicar ao item #42

;; Auto-aplicar em cada add-item
(auto-categorize true)

Gerenciamento de regras

FunçãoDescrição
(rules)Lista todas as regras definidas
(drop-rule name)Exclui uma regra
(auto-categorize bool)Alterna auto-aplicação na inserção
Contexto da regra: As condições têm acesso a text, notes, categories, todas as propriedades do item, além de auxiliares como has-category e overdue?. Combine com and/or/not.

31. Visualizações

Visualizações são consultas salvas que filtram, ordenam e agrupam itens dinamicamente.

(defview work-board
  :source items
  :filter (has-category "work")
  :group-by category
  :sort-by when)

(defview urgent
  :source items
  :filter (= priority "1")
  :sort-by when)

(defview inbox
  :source items
  :filter (= (length categories) 0))

;; Mostrar uma visualização
(show work-board)
(show urgent)
FunçãoDescrição
(views)Lista todas as visualizações definidas
(drop-view name)Exclui uma visualização

32. Consultas de Calendário

;; Itens para uma data específica
(items-on "2026-02-24")

;; Itens em um intervalo de datas
(items-between "2026-02-24" "2026-02-28")

;; Usando auxiliares de data
(items-on (today))
(items-between (today) (date-add (today) 7 :days))
Dica: A barra lateral do Calendário e a barra lateral da Agenda na interface gráfica usam essas mesmas funções internamente. Adicione itens no REPL e depois alterne para o modo Calendário ou Agenda para vê-los visualmente.

33. Entrada Inteligente

O comando add analisa linguagem natural para extrair datas, prioridades e pessoas automaticamente.

(add "Meet Alice tomorrow for coffee !!")
; → :when = tomorrow, :priority 2, :who "Alice"

(add "Call Bob next Monday about the project")
; → :when = next Monday, :who "Bob"

(add "URGENT fix server crash")
; → :priority 1

;; Visualizar sem criar
(smart-parse "email Sarah March 15 about renewal !!")
; → {:text "email Sarah about renewal" :when "2026-03-15" :priority 2 :who ("Sarah")}

Padrões reconhecidos

34. Itens Recorrentes & Modelos

Recorrência

;; Intervalos integrados
(add-item "Team standup" :when (today) :recur :daily)
(add-item "Weekly review" :when (today) :recur :weekly)
(add-item "Monthly report" :when (today) :recur :monthly)

;; Intervalo personalizado
(add-item "Check filters" :when (today) :recur (every 3 :months))

;; Quando você marca como concluído, a próxima ocorrência é criada automaticamente
(item-done 1)  ; cria a próxima recorrência automaticamente

Modelos

;; Definir um modelo reutilizável de item
(deftemplate weekly-review
  :text "Weekly review"
  :category "work"
  :priority 2
  :recur :weekly)

;; Criar a partir do modelo com substituições
(from-template weekly-review :when "2026-03-01")

;; Gerenciar modelos
(templates)           ; listar todos
(drop-template weekly-review)  ; excluir

35. Múltiplas Agendas

Abra, alterne entre e gerencie múltiplos bancos de dados de agenda. Útil para separar agendas de trabalho e pessoais.

;; Abrir uma nova agenda
(open-agenda "work.db")
(open-agenda "personal.db")

;; Alternar entre agendas
(use-agenda "work")

;; Listar todas as agendas abertas
(agendas)  ; mostra marcador ativo (*)

;; Fechar uma agenda
(close-agenda "personal")

Exportar & Importar

;; Exportar para backup ou migração
(export-agenda "work" :format :json :path "work-backup.json")

;; Importar de uma exportação anterior
(import-agenda "work-backup.json")
Parte VI — Integração

36. Integração GUI & EELisp

A interface gráfica do EEditor se integra com o EELisp através do método eval() do interpretador. Todos os dados fluem através de expressões EELisp — a GUI nunca acessa o SQLite diretamente.

Arquitetura

┌─────────────────────────┐
│  SwiftUI Views          │
│  (Sidebar, Calendar,    │
│   Agenda, REPL)         │
├─────────────────────────┤
│  ViewModels             │
│  (call interpreter.eval)│
├─────────────────────────┤
│  EELisp Interpreter     │
│  (builtins, prelude)    │
├─────────────────────────┤
│  SQLite Database        │
│  (eelisp.db)            │
└─────────────────────────┘

Como funciona

Exemplo de fluxo de dados

;; 1. Usuário adiciona itens no REPL
(add-item "Review PRs" :when (today) :priority 1)

;; 2. Alterna para a barra lateral da Agenda → GUI chama:
;;    interpreter.eval("(items-between startKey endKey)")
;;    Analisa resultados em structs AgendaDisplayItem

;; 3. Alterna para o Calendário → GUI chama:
;;    interpreter.eval("(items-on \"2026-02-23\")")
;;    Conta itens por dia para indicadores de ponto
Princípio fundamental: A GUI é uma camada fina de apresentação. Toda a lógica de negócios — esquemas de tabelas, consultas, regras de agenda, visualizações — vive no EELisp. Isso significa que você pode criar scripts e automatizar tudo a partir do REPL.

Dicas para iOS & iPadOS