18 KiB
- PERFORMANCE
- LIMPEZA VISUAL
- DEFAULTS & COMPORTAMENTO BASE
- NÚMEROS DE LINHA
- GESTOR DE PACOTES
- INTERFACE MODERNA & ATALHOS WHICH-KEY
- AÇÕES DE CONTEXTO (EMBARK)
- ESTÉTICA
- BARRA DE ESTADO (MODE-LINE)
- AUTOMATIZAÇÃO (ORG-AUTO-TANGLE)
- ORG-MODE & LITERATE PROGRAMMING
- INSERÇÃO DE IMAGENS E RECORTES (ORG-DOWNLOAD)
- VERIFICAÇÃO DE SINTAXE (FLYCHECK)
- TREE-SITTER (SINTAXE ESTRUTURAL)
- LANGUAGE SERVER PROTOCOL (EGLOT + CLANGD)
- ZETTELKASTEN (ORG-ROAM)
- GIT (MAGIT)
- ORG-ROAM-UI (GRAFO VISUAL)
- LEITURA DE PDFS (PDF-TOOLS)
- ANOTAÇÕES SINCRONIZADAS (ORG-NOTER)
- BIBLIOGRAFIA (CITAR)
- LATEX (AUCTEX)
- GESTÃO DE PROJETOS (PROJECTILE)
- AI ASSISTANT (GPTEL - LOCAL LLAMA.CPP)
- PESQUISA INTELIGENTE (KHOJ)
- O MEU PRIMEIRO AGENTE (RAG)
- LEITOR DE NOTÍCIAS (ELFEED + FRESHRSS)
PERFORMANCE
Configuração do Garbage Collector para acelerar o arranque.
(setq gc-cons-threshold (* 50 1024 1024))
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold (* 50 1024 1024))))
LIMPEZA VISUAL
Remover barras desnecessárias e ecrã de boas-vindas.
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(setq inhibit-startup-screen t)
DEFAULTS & COMPORTAMENTO BASE
;; Define os caminhos de forma dinâmica com base na localização real da configuração
(defvar my-backup-dir (expand-file-name "backups/" user-emacs-directory))
(defvar my-autosave-dir (expand-file-name "auto-save-list/" user-emacs-directory))
;; Força a criação das pastas no sistema de ficheiros caso não existam
(unless (file-exists-p my-backup-dir) (make-directory my-backup-dir t))
(unless (file-exists-p my-autosave-dir) (make-directory my-autosave-dir t))
;; Aplica as regras (o acento grave ` permite a injeção da variável com a vírgula)
(setq backup-directory-alist `(("." . ,my-backup-dir)))
(setq auto-save-file-name-transforms `((".*" ,my-autosave-dir t)))
(setq create-lockfiles nil)
(setq-default fill-column 80)
;; Desativa completamente o som de erro (não faz som nem pisca)
(setq ring-bell-function 'ignore)
(electric-pair-mode 1)
NÚMEROS DE LINHA
Ativa os números de linha relativos para facilitar a navegação, exceto em modos de leitura.
;; Define o estilo como relativo
(setq display-line-numbers-type t)
;; Ativa globalmente
(global-display-line-numbers-mode 1)
;; Desativa em modos onde não fazem sentido (Org, PDFs, Terminais)
(dolist (mode '(org-mode-hook
pdf-view-mode-hook
term-mode-hook
eshell-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode -1))))
GESTOR DE PACOTES
Configurar o use-package para instalar tudo automaticamente.
(require 'package)
;; Adiciona o repositório da comunidade (MELPA)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; Garante que a lista de pacotes está atualizada no primeiro arranque
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(setq package-install-upgrade-built-in t)
(require 'use-package)
(setq use-package-always-ensure t)
INTERFACE MODERNA & ATALHOS WHICH-KEY
Configuração do Vertico, Orderless e Marginalia para pesquisa rápida.
O which-key é configurado aqui para dar nomes amigáveis aos nossos atalhos C-c.
(use-package vertico
:init (vertico-mode 1))
(use-package orderless
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion)))))
(use-package marginalia
:init (marginalia-mode 1))
(use-package consult
:bind (("C-s" . consult-line)
("C-x b" . consult-buffer)
;; Os nossos atalhos de pesquisa personalizados
("C-c s s" . consult-line)
("C-c s r" . consult-ripgrep)))
(use-package which-key
:ensure nil ; Built-in no Emacs 30
:init (which-key-mode 1)
:config
;; Dá nomes bonitos aos menus do C-c
(which-key-add-key-based-replacements
"C-c s" "Pesquisa"
"C-c c" "Código/Estrutura"
"C-c a" "Ações/Contexto"
"C-c n" "Notas/Org"
"C-c n d" "Dailies"
"C-c g" "Git"
"C-c l" "Leitura/RSS"
"C-c p" "Projetos"))
AÇÕES DE CONTEXTO (EMBARK)
Funciona como um "botão direito do rato" para o teclado.
(use-package embark
:bind
(("C-." . embark-act)
("M-." . embark-dwim)
("C-h B" . embark-bindings)
;; Atalhos organizados no menu "Ações"
("C-c a a" . embark-act)
("C-c a d" . embark-dwim)
("C-c a e" . embark-export)
("C-c a b" . embark-bindings))
:init
(setq prefix-help-command #'embark-prefix-help-command)
:config
(setq embark-indicators
'(embark-minimal-indicator
embark-highlight-indicator
embark-isearch-highlight-indicator)))
(use-package embark-consult
:ensure t
:after (embark consult)
:hook
(embark-collect-mode . consult-preview-at-point-mode))
ESTÉTICA
Tema e embelezamento do Org-mode.
(use-package doom-themes
:config
(load-theme 'doom-dracula t))
(use-package org-modern
:hook (org-mode . org-modern-mode))
ÍCONES (NERD-ICONS)
(use-package nerd-icons)
(use-package nerd-icons-completion
:after (marginalia vertico)
:init
(nerd-icons-completion-mode)
:hook
(marginalia-mode . nerd-icons-completion-marginalia-setup))
RAINBOW DELIMITERS
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
BARRA DE ESTADO (MODE-LINE)
Uma barra de estado moderna, limpa e altamente informativa.
(use-package doom-modeline
:init (doom-modeline-mode 1)
:custom
(doom-modeline-height 30)
(doom-modeline-bar-width 4)
(doom-modeline-icon t)
(doom-modeline-major-mode-icon t)
(doom-modeline-workspace-name t)
(doom-modeline-time t))
AUTOMATIZAÇÃO (ORG-AUTO-TANGLE)
Gera o config.el automaticamente.
(use-package org-auto-tangle
:defer t
:hook (org-mode . org-auto-tangle-mode)
:config
(setq org-auto-tangle-default t))
ORG-MODE & LITERATE PROGRAMMING
Configurações essenciais para escrita e blocos de código.
(use-package org
:bind (("C-c n a" . org-agenda))
:hook (org-mode . visual-line-mode)
:custom
(org-directory "~/org/")
(org-agenda-files '("~/org/agenda/" "~/org/roam/daily/"))
(org-todo-keywords
'((sequence "TODO(t)" "DOING(i)" "WAIT(w)" "|" "DONE(d)" "CANCEL(c)")))
(org-todo-keyword-faces
'(("DOING" . (:foreground "#ffb86c" :weight bold))
("WAIT" . (:foreground "#8be9fd" :weight bold))
("CANCEL". (:foreground "#6272a4" :weight bold))))
(org-hide-emphasis-markers t)
(org-startup-indented t)
(org-src-fontify-natively t)
(org-src-preserve-indentation nil)
(org-edit-src-content-indentation 0)
(org-src-tab-acts-natively t)
(org-startup-with-inline-images t)
(org-image-actual-width nil)
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(shell . t)
(python . t)
(C . t)))
(require 'org-tempo)
(setq org-confirm-babel-evaluate
(lambda (lang body)
(not (member lang '("C" "shell" "emacs-lisp" "python"))))))
INSERÇÃO DE IMAGENS E RECORTES (ORG-DOWNLOAD)
(use-package org-download
:after org
:defer t
:bind ("C-c n v" . org-download-clipboard)
:config
(org-download-enable)
(setq-default org-download-image-dir "./images")
(setq org-download-clipboard-command "wl-paste -t image/png > %s"))
VERIFICAÇÃO DE SINTAXE (FLYCHECK)
(use-package flycheck
:init
(global-flycheck-mode))
TREE-SITTER (SINTAXE ESTRUTURAL)
Motor de parsing moderno. C e C++ mantidos propositadamente no modo clássico (regex).
(use-package treesit
:ensure nil
:bind (("C-c c m" . treesit-explore-mode)
("C-c c f" . treesit-beginning-of-defun)
("C-c c e" . treesit-end-of-defun)))
;; 1. Dizer ao Emacs a localização exata das gramáticas testadas
(setq treesit-language-source-alist
'((bash "https://github.com/tree-sitter/tree-sitter-bash")
(c "https://github.com/tree-sitter/tree-sitter-c")
(cpp "https://github.com/tree-sitter/tree-sitter-cpp")
(python "https://github.com/tree-sitter/tree-sitter-python")
(json "https://github.com/tree-sitter/tree-sitter-json")
(yaml "https://github.com/ikatyang/tree-sitter-yaml")
(dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile")))
;; 2. Instalar automaticamente as gramáticas
(dolist (lang '(bash c cpp python json yaml dockerfile))
(unless (treesit-language-available-p lang)
(treesit-install-language-grammar lang)))
;; 3. Configurar o treesit-auto
(use-package treesit-auto
:custom
(treesit-auto-install nil)
:config
(setq treesit-auto-langs '(c cpp python bash json yaml dockerfile))
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
LANGUAGE SERVER PROTOCOL (EGLOT + CLANGD)
Obrigatório para desenvolvimento bare-metal em C.
(use-package eglot
:ensure nil ; Built-in
:hook ((c-mode c-ts-mode c++-mode c++-ts-mode) . eglot-ensure)
:config
;; Desativa logs pesados que atrasam o Emacs
(fset #'jsonrpc--log-event #'ignore)
;; Formatação automática antes de guardar (apenas para buffers geridos pelo LSP)
(add-hook 'eglot-managed-mode-hook
(lambda ()
(when (derived-mode-p 'c-mode 'c-ts-mode 'c++-mode 'c++-ts-mode)
(add-hook 'before-save-hook #'eglot-format-buffer -10 t))))
;; Configura o clangd para projetos embebidos
(add-to-list 'eglot-server-programs
'((c-mode c-ts-mode c++-mode c++-ts-mode)
. ("clangd"
"--background-index"
"--header-insertion=never" ; Evita #includes de bibliotecas standard do SO
"--completion-style=detailed"))))
ZETTELKASTEN (ORG-ROAM)
O núcleo do sistema de notas.
(use-package org-roam
:ensure t
:demand t
:bind (("C-c n f" . org-roam-node-find)
("C-c n i" . org-roam-node-insert)
("C-c n t" . org-roam-tag-add)
("C-c n d d" . org-roam-dailies-goto-today)
("C-c n d y" . org-roam-dailies-goto-yesterday)
("C-c n d m" . org-roam-dailies-goto-tomorrow))
:custom
(org-roam-directory (file-truename "~/org/roam"))
(org-roam-dailies-directory "daily/")
(org-roam-dailies-capture-templates
'(("d" "default" entry
"* Sessão de Trabalho: %?w"
:target (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y-%m-%d>\n#+filetags: :diario:sessao:\n\n* [/] Tarefas da Sessão\n** TODO Rever pendentes da sessão anterior\n** TODO %?\n\n* Notas de Engenharia & Logs\n"))))
:config
(unless (file-exists-p org-roam-directory)
(make-directory org-roam-directory t))
(require 'org-id)
(setq org-id-track-globally t)
(org-roam-db-autosync-mode))
GIT (MAGIT)
(use-package magit
:bind ("C-c g s" . magit-status)
:commands magit-status)
ORG-ROAM-UI (GRAFO VISUAL)
(use-package org-roam-ui
:after org-roam
:bind ("C-c n u" . org-roam-ui-mode)
:config
(setq org-roam-ui-sync-theme t
org-roam-ui-follow t
org-roam-ui-update-on-save t
org-roam-ui-open-on-start t))
LEITURA DE PDFS (PDF-TOOLS)
(use-package pdf-tools
:defer t
:mode ("\\.pdf\\'" . pdf-view-mode)
:bind ("C-c s p" . pdf-occur)
:config
(pdf-tools-install :no-query)
(setq-default pdf-view-display-size 'fit-page)
(setq pdf-annot-activate-created-annotations t))
ANOTAÇÕES SINCRONIZADAS (ORG-NOTER)
(use-package org-noter
:defer t
:config
(setq org-noter-always-create-frame nil)
(setq org-noter-kill-frame-at-session-end nil)
(setq org-noter-doc-split-fraction '(0.5 . 0.5))
(setq org-noter-notes-search-path '("~/org/roam")))
BIBLIOGRAFIA (CITAR)
(use-package citar
:bind ("C-c n x" . citar-insert-citation)
:custom
(citar-bibliography '("~/org/roam/referencias.bib"))
(citar-library-paths '("~/org/refs/"))
:hook
(org-mode . citar-capf-setup))
(use-package citar-org-roam
:after (citar org-roam)
:config
(citar-org-roam-mode))
LATEX (AUCTEX)
(use-package tex
:ensure auctex
:custom
(TeX-auto-save t)
(TeX-parse-self t)
(TeX-master nil)
(TeX-view-program-selection '((output-pdf "PDF Tools")))
(TeX-view-program-list '(("PDF Tools" TeX-pdf-tools-sync-view)))
(TeX-source-correlate-start-server t)
:hook
(LaTeX-mode . TeX-source-correlate-mode)
(TeX-after-compilation-finished . TeX-revert-document-buffer))
GESTÃO DE PROJETOS (PROJECTILE)
(use-package projectile
:init
(projectile-mode +1)
:custom
(projectile-project-search-path '("~/dev/"))
:bind-keymap
("C-c p" . projectile-command-map))
(use-package dired
:ensure nil
:custom
(dired-listing-switches "-agho --group-directories-first")
(dired-dwim-target t))
AI ASSISTANT (GPTEL - LOCAL LLAMA.CPP)
Integração offline com o servidor local do llama.cpp via Vulkan.
(use-package gptel
:ensure t
:bind (("C-c q" . gptel-menu) ; Abre o menu interativo (O que você quer)
("C-c RET" . gptel-send)) ; Envia instantaneamente (Para chat rápido)
:config
;; O llama-server imita a API da OpenAI perfeitamente
(setq gptel-backend
(gptel-make-openai "llama.cpp"
:protocol "http"
:host "localhost:8080"
:stream t
:key "no-key"
:models '("Llama-3.2-3B")))
(setq gptel-model 'Llama-3.2-3B)
(setq gptel-directives
'((default . "You are a Senior Staff Embedded Software Engineer.
Your primary domains are bare-metal C, ARM Cortex-M (STM32), ESP32, and Linux terminal tooling.
STRICT RULES OF INTERACTION:
1. Tone: Zero fluff. No greetings, no sycophancy, no apologies. Deliver dense, direct, and highly technical answers.
2. Architecture First: Ground your explanations in physical hardware reality. Explain memory mapping, register states, clock cycles, and bitwise operations.
3. Code Standard: Favour direct register manipulation (bare-metal) over HAL abstractions. Write robust, deterministic C code.
4. Environment: Assume the user operates strictly in Linux, compiling with CMake/GCC, debugging with GDB/OpenOCD, and editing in Emacs.")
(elisp . "You are an Emacs Lisp architect.
Your task is to debug, optimize, or write Emacs Lisp code for a highly customized Emacs 30 environment.
RULES:
1. Use modern conventions (lexical-binding, use-package, cl-lib).
2. Prioritize performance and non-blocking execution (asynchronous processes where applicable).
3. Provide the raw code and a dense technical explanation of the evaluation model or API used. No basic tutorials.")
(rag . "You are a data-extraction and synthesis engine.
You will receive JSON or plain text data extracted from an org-roam Zettelkasten via a RAG pipeline.
RULES:
1. Base your answer EXCLUSIVELY on the provided data.
2. DO NOT hallucinate external knowledge. If the answer is not in the text, state exactly that.
3. Output the response in clean Org-mode syntax (using headings, lists, and code blocks) for easy integration into the user's notes.")
(refactor . "You are a strict code reviewer and refactoring engine.
Analyze the provided C/Zig/Rust code.
1. Identify memory leaks, race conditions, blocking operations, or inefficient bitwise logic.
2. Provide the refactored code block.
3. List the structural changes made in bullet points, focusing on space/time complexity and hardware safety."))))
PESQUISA INTELIGENTE (KHOJ)
Integração com o servidor Khoj para busca semântica nas notas.
(use-package khoj
:ensure t
:bind ("C-c n s" . khoj) ; Atalho: "Notes Search"
:config
;; Aponta o Emacs para o servidor
(setq khoj-server-url "http://127.0.0.1:5000")
;; Opcional: Define a pasta padrão caso use a interface local do pacote
(setq khoj-index-directories '("~/org/roam/")))
O MEU PRIMEIRO AGENTE (RAG)
Integração direta entre a pesquisa semântica (Khoj) e a geração de texto (Llama).
(defun gabi/agente-notas (pesquisa pergunta)
"Agente RAG de 2 Fases: Pesquisa Cirúrgica + Resposta Estrita."
(interactive
(list (read-string "1. Palavras-chave para o Khoj (ex: gentoo instalação): ")
(read-string "2. O que queres perguntar ao Llama sobre isto?: ")))
(require 'gptel)
(message "Fase 1: A extrair as notas sobre '%s' do Khoj..." pesquisa)
(let* ((url (format "http://127.0.0.1:5000/api/search?q=%s&n=5" (url-hexify-string pesquisa)))
(comando (format "curl -s '%s'" url))
(resultados-khoj (shell-command-to-string comando))
(buffer-resposta (get-buffer-create "*Síntese do Agente*"))
;; PROMPT DE FERRO: Proibido inventar.
(prompt-sistema (concat "És um assistente técnico de extração de informação. "
"Vais receber dados JSON retirados das notas do utilizador.\n\n"
"REGRAS ABSOLUTAS:\n"
"1. Baseia a resposta EXCLUSIVAMENTE nos dados abaixo.\n"
"2. NÃO inventes conhecimento externo. Se não está nos dados, não escrevas.\n"
"3. Ignora o código JSON e foca-te apenas no texto org-mode que está lá dentro.\n\n"
"DADOS EXTRAÍDOS:\n"
resultados-khoj)))
(pop-to-buffer buffer-resposta)
(erase-buffer)
(org-mode)
(insert (format "#+TITLE: %s\n" pergunta))
(insert (format "#+SUBTITLE: Baseado na pesquisa por: %s\n" pesquisa))
(insert (format "#+DATE: %s\n\n" (format-time-string "%Y-%m-%d")))
(message "Fase 2: A analisar notas e a gerar resposta...")
(gptel-request pergunta
:system prompt-sistema
:stream t)))
LEITOR DE NOTÍCIAS (ELFEED + FRESHRSS)
(use-package elfeed
:ensure t
:bind (("C-c l e" . elfeed)
("C-c l u" . elfeed-update)
:map elfeed-show-mode-map
("b" . my/elfeed-abrir-no-eww))
:preface
(defun my/elfeed-abrir-no-eww ()
"Abre o artigo atual no EWW (browser interno) em vez do browser externo."
(interactive)
(let ((link (elfeed-entry-link elfeed-show-entry)))
(when link
(message "A descarregar o artigo completo...")
(eww link))))
:config
(setq elfeed-use-curl t)
;; Atualiza o Elfeed a cada 30 minutos em background
(run-at-time nil (* 30 60) #'elfeed-update))
(use-package elfeed-protocol
:ensure t
:after elfeed
:config
(setq elfeed-feeds
'(("fever+https://gabi@vm-magasirala-rss.duckdns.org"
:api-url "https://vm-magasirala-rss.duckdns.org/api/fever.php"
:use-authinfo t
:autotags ("freshrss"))))
(elfeed-protocol-enable))