diff --git a/.opencode/AGENTS.md b/.opencode/AGENTS.md new file mode 100644 index 0000000..673ea95 --- /dev/null +++ b/.opencode/AGENTS.md @@ -0,0 +1,102 @@ +# OpenCortex Agent Mandate + +This file defines the operating policies and engineering guidelines that all autonomous agents MUST follow. + +## Vision + +- **Pure Lisp + Org-mode**: All intelligence implemented in Lisp, all documentation in Org-mode +- **No JSON, No YAML**: Thin harness, fat skills +- **Constraint**: No temporary scripts in opencortex repo - use `/home/user/memex/system/` instead + +## Current Goal + +- **v0.2.0**: Self-Improvement + Local LLMs + - org-skill-self-edit (self-modification) + - org-skill-emacs-edit (full org-mode manipulation) + - Local vector search (Ollama embeddings) + - Tool permission tiers (ask/allow/deny) + - Skill hot-reload ✅ DONE + - Engineering Standards skill ✅ DONE + - Literate Programming skill ✅ DONE + +## Wake-Up Protocol + +When this agent starts, it MUST: + +1. **Read this file** (`~/.opencode/AGENTS.md`) +2. **Query the skill catalog**: Before any analysis, check if a skill covers the problem domain + - `(list-skills)` to see all loaded skills + - `(find-skill :keyword)` to check for a specific domain + - Read the skill's org file if found +3. **Verify git status**: Working tree MUST be clean before modification +4. **Read `gtd.org`**: Load current task context from the roadmap +5. **Enter lifecycle**: Follow the Engineering Standards lifecycle (Phase 0 → A → B → C → D → E) + +Rationale: Raw LLM reasoning is a fallback, not a starting point. The skill layer encodes the system's accumulated wisdom. Ignoring skills creates drift. + +## Engineering Standards + +The Engineering Standards skill (`opencortex.skills.org-skill-engineering-standards`) defines the full lifecycle. The summaries below are reminders; the skill org file is authoritative. + +### Phase 0: Before You Think + +**Skill-First Query Rule**: Before analysis, debugging, or implementation, query the skill catalog. If a relevant skill exists, follow its mandates. Do not duplicate logic. + +### Phase A: Design (Test-First) + +1. **Define success criteria first** — Write the test or PROTOCOL that proves the feature works +2. **Break the design with chaos** — Three tiers of adversarial testing: + - *Deterministic chaos*: Scripted regression tests on every change + - *Probabilistic chaos*: Randomized fuzzing on every major release + - *Stress chaos*: Load and resource starvation during hardening sprints + +### Phase B: Commit (Recovery Point) + +3. **Commit Before Modify** — Commit and push (if network available) before any file changes + +### Phase C: Build (Implementation) + +4. **Literate Programming** — All logic in Org files; generated `.lisp` is derived, not authored +5. **Function-Block Granularity** — One function per `#+begin_src lisp` block +6. **Tangle Mandate** — Edit Org only; never touch generated `.lisp` +7. **Configuration Externalization** — No hardcoded values; use `.env.example` +8. **Org as Thinking Medium** — Document investigation before fixing + +### Phase D: Validate (Proof) + +9. **Test Verification** — Run the full suite. A change that breaks tests is damage, not a fix. + +### Phase E: Document (Audit Trail) + +10. **Decision Audit Trail** — Document root cause, options, tradeoffs, and rationale +11. **Stop-and-Wait** — For major changes, propose strategy, state "Waiting for user feedback," yield turn +12. **GTD Synchronization** — Update `gtd.org` with TODO headlines before marking complete + +## Literate Programming Rules + +The Literate Programming skill (`opencortex.skills.org-skill-literate-programming`) enforces Org discipline: + +1. **One Function, One Block** — No bundling multiple definitions +2. **Org-Mode Evaluation Gate** — `C-c C-c` after every block change +3. **Pre-Tangle Structural Check** — Verify paren balance before tangling +4. **No Direct `.lisp` Edits** — All changes flow through Org +5. **Code and Prose Together** — Every block preceded by explanatory text + +Violating these rules corrupts the skill loader and causes boot failure (as seen in the 2026-04-25 incident). + +## Agent Workflow + +- **Boot Sequence**: Read AGENTS.md → query skills → verify git → read gtd.org +- **Before Any Modification**: Commit first (Commit Before Modify rule) +- **Plan Mode**: Draft PROTOCOL.md before complex implementations +- **Testing**: Run FiveAM test suite + chaos tests before marking task complete +- **Completion**: Update gtd.org, commit, sync with user + +## References + +- opencortex repo: `/home/user/memex/projects/opencortex` +- Engineering Standards: `/home/user/memex/projects/opencortex/skills/org-skill-engineering-standards.org` +- Literate Programming: `/home/user/memex/projects/opencortex/skills/org-skill-literate-programming.org` +- Policy Skill: `/home/user/memex/projects/opencortex/skills/org-skill-policy.org` +- Roadmap: `/home/user/memex/gtd.org` +- README: `/home/user/memex/projects/opencortex/README.org` diff --git a/README.org b/README.org index 199e034..0dc7617 100644 --- a/README.org +++ b/README.org @@ -5,7 +5,7 @@ #+FILETAGS: :memex:psf:opencortex:lisp:sovereignty: * Overview -The *Master Memex* is a sovereign, neurosymbolic intelligence organization system. It is not merely a collection of notes, but a live, programmable environment—a **Personal Software Foundry (PSF)**—where a human (the Sovereign Executive) and agentic co-processes (the `opencortex` kernel and Gemini CLI) collaborate within a shared address space. +The *Master Memex* is a sovereign, neurosymbolic intelligence organization system. It is not merely a collection of notes, but a live, programmable environment—a **Personal Software Foundry (PSF)**—where a human (the Sovereign Executive) and agentic co-processes (the `opencortex` kernel and opencode) collaborate within a shared address space. This system synthesizes three core organizational methodologies into a unified "Lisp Machine" experience: - *Zettelkasten:* For atomic, evergreen, and interlinked knowledge. @@ -36,7 +36,7 @@ The Memex is inhabited by autonomous agents that operate as "Probabilistic" (pro ** [[file:projects/opencortex/README.org][opencortex (The Kernel)]] A Common Lisp microkernel that maintains a live, threaded Object-Store in RAM. It uses Org-mode as its native Abstract Syntax Tree (AST), allowing it to "perceive" and "act" on the Memex with structural precision. -** Gemini CLI +** opencode A strategic orchestrator that handles large-scale batch tasks, research, and planning. It operates according to the *PSF Consensus Loop* (Demand -> Blueprint -> Success -> Build -> Chaos -> Memory). * The Cognitive Architecture: A Session-less Mind diff --git a/boot-sequence-plan.md b/boot-sequence-plan.md deleted file mode 100644 index 3971534..0000000 --- a/boot-sequence-plan.md +++ /dev/null @@ -1,36 +0,0 @@ -# Implementation Plan: The Micro-Loader (Boot Sequence Refactor) - -## Objective -Consolidate and harden the kernel's skill-loading logic into a stateful "Micro-Loader." This improves boot reliability, provides clear error reporting for malformed skills, and centralizes all capability management within the `skills` module. - -## Key Files & Context -- **Target:** `projects/opencortex/literate/skills.org` (Consolidating logic here). -- **Target:** `projects/opencortex/literate/core.org` (Moving `load-all-skills` out of here). -- **Mandate:** Syntax Pre-flight and Dependency Assertion. - -## Implementation Steps - -### 1. Define the Skill Catalog -- Introduce `*skill-catalog*` in `skills.lisp` to track metadata and load status for every skill file found in `SKILLS_DIR`. -- Statuses: `:discovered`, `:loading`, `:ready`, `:failed`. - -### 2. Refactor `load-skill-from-org` (Harden) -- **Syntax Check:** Invoke `validate-lisp-syntax` before evaluation. -- **Dependency Check:** If `#+DEPENDS_ON` refers to a skill that failed or is missing, mark this skill as `:failed` immediately with a clear error. -- **Detailed Logging:** Record the specific reason for failure (syntax, timeout, runtime error) in the catalog. - -### 3. Implement `initialize-all-skills` (The Orchestrator) -- Move the directory scanning and loop logic from `core.lisp` into `skills.lisp`. -- This function will: - 1. Scan `SKILLS_DIR`. - 2. Populate the catalog. - 3. Run the topological sort. - 4. Execute the load loop with timeouts. - 5. Print a final "Boot Summary" report. - -### 4. Simplify Kernel Boot -- Update `start-daemon` in `core.lisp` to call `(initialize-all-skills)` instead of the old `load-all-skills`. - -## Phase E: Chaos (Verification) -- **Integrity Test:** Add a test that verifies `initialize-all-skills` correctly identifies a missing dependency and prevents the dependent skill from attempting to load. -- **Report Test:** Verify that the skill catalog correctly reflects the status of loaded vs. failed skills. diff --git a/fedora-43-repos.repo b/fedora-43-repos.repo new file mode 100644 index 0000000..56dc312 --- /dev/null +++ b/fedora-43-repos.repo @@ -0,0 +1,15 @@ +[fedora] +name=Fedora 43 - x86_64 +enabled=1 +metadata_expire=1h +baseurl=https://mirrors.fedoraproject.org/metalink?repo=fedora-43&arch=x86_64 +type=rpm-md +gpgcheck=0 + +[updates] +name=Fedora 43 - x86_64 - Updates +enabled=1 +metadata_expire=1h +baseurl=https://mirrors.fedoraproject.org/metalink?repo=fedora-43-updates&arch=x86_64 +type=rpm-md +gpgcheck=0 \ No newline at end of file diff --git a/inbox.org b/inbox.org index 728f8bb..bd464d8 100644 --- a/inbox.org +++ b/inbox.org @@ -157,3 +157,45 @@ This is the inbox. Everything goes in here when you capture it. :CREATED: [2026-04-17 Fri 14:52] :END: +* [[https://www.jori.com/en/products/pacific-jr-9700][Pacific Pure | Sofas | Product | Design furniture | JORI]] :furniture:years: +:PROPERTIES: +:TITLE: Pacific Pure | Sofas | Product | Design furniture | JORI +:URI: https://www.jori.com/en/products/pacific-jr-9700 +:CREATED: [2026-04-21 Tue 15:25] +:END: + +* [[https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6372438][AI Agent Traps by Matija Franklin, Nenad Tomašev, Julian Jacobs, Joel Z. Leibo, Simon Osindero :: SSRN]] +:PROPERTIES: +:TITLE: AI Agent Traps by Matija Franklin, Nenad Tomašev, Julian Jacobs, Joel Z. Leibo, Simon Osindero :: SSRN +:URI: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6372438 +:CREATED: [2026-04-21 Tue 15:26] +:END: + +* [[https://www.storagereview.com/review/comino-grando-rtx-pro-6000-review-768gb-of-vram-in-a-liquid-cooled-4u-chassis][Comino Grando RTX PRO 6000 Review: 768GB of VRAM in a Liquid-Cooled 4U Chassis - StorageReview.com]] +:PROPERTIES: +:TITLE: Comino Grando RTX PRO 6000 Review: 768GB of VRAM in a Liquid-Cooled 4U Chassis - StorageReview.com +:URI: https://www.storagereview.com/review/comino-grando-rtx-pro-6000-review-768gb-of-vram-in-a-liquid-cooled-4u-chassis +:CREATED: [2026-04-21 Tue 15:26] +:END: + +* [[https://x.com/elvissun/status/2044784140831301728/photo/1][Elvis on X: "some agentic engineering realization: stop reviewing code. start reviewing contracts. and here's what i mean. the highest leverage work right now is drawing the right boundaries in your system. i've been splitting the system into multiple sub-systems, each with clearly defined https://t.co/Hy0d9WHI1m" / X]] +:PROPERTIES: +:TITLE: Elvis on X: "some agentic engineering realization: stop reviewing code. start reviewing contracts. and here's what i mean. the highest leverage work right now is drawing the right boundaries in your system. i've been splitting the system into multiple sub-systems, each with clearly defined https://t.co/Hy0d9WHI1m" / X +:URI: https://x.com/elvissun/status/2044784140831301728/photo/1 +:CREATED: [2026-04-21 Tue 15:26] +:END: + +* [[https://x.com/i/status/2044307601463357791][EverMars on X: "Respect to the Man Chasing AI Immortality, Even Though He's Freeloading Off Our Platform" / X]] +:PROPERTIES: +:TITLE: EverMars on X: "Respect to the Man Chasing AI Immortality, Even Though He's Freeloading Off Our Platform" / X +:URI: https://x.com/i/status/2044307601463357791 +:CREATED: [2026-04-21 Tue 15:26] +:END: + +* [[https://x.com/i/status/2045289299269070978][Seth Howes on X: "I’ve wanted to do this for a decade. But I never did - I refuse to give any company my DNA. It is me. So this week I sequenced my genome entirely at home. Literally on my kitchen table. I never exposed my DNA sequence to the internet. Not at any point. I used a MinION to do https://t.co/qCzXIGxWsy" / X]] +:PROPERTIES: +:TITLE: Seth Howes on X: "I’ve wanted to do this for a decade. But I never did - I refuse to give any company my DNA. It is me. So this week I sequenced my genome entirely at home. Literally on my kitchen table. I never exposed my DNA sequence to the internet. Not at any point. I used a MinION to do https://t.co/qCzXIGxWsy" / X +:URI: https://x.com/i/status/2045289299269070978 +:CREATED: [2026-04-21 Tue 15:27] +:END: + diff --git a/inbox/2512.24601v2.pdf b/inbox/2512.24601v2.pdf new file mode 100644 index 0000000..037305e Binary files /dev/null and b/inbox/2512.24601v2.pdf differ diff --git a/peripheral-vision-plan.md b/peripheral-vision-plan.md deleted file mode 100644 index d49e5de..0000000 --- a/peripheral-vision-plan.md +++ /dev/null @@ -1,32 +0,0 @@ -# Implementation Plan: Component IV - Peripheral Vision Extraction - -## Objective -Implement a sophisticated "Foveal-Peripheral" context model. This ensures the agent has high-resolution focus on the current task (Foveal) while maintaining a low-resolution "skeletal" awareness of the broader Memex structure (Peripheral), optimized for token efficiency and reasoning accuracy. - -## Key Files & Context -- **Target:** `projects/opencortex/literate/context.org` (Source of `src/context.lisp`) -- **Core Concept:** Deep pruning of the Org AST based on semantic distance and structural hierarchy. - -## Implementation Steps - -### 1. Identify Foveal Focus -- Extend the `SIGNAL` structure processing to identify a `target-id` (the current headline being operated on). - -### 2. Implement Tree Pruning (`context-extract-peripheral-vision`) -- Create a recursive function that walks the Object Store starting from the root (or active projects). -- **Rule A (Foveal):** If the node matches `target-id`, include it and its immediate children in **Full Resolution** (Content + Attributes). -- **Rule B (Peripheral):** For ancestors and siblings of the target, include only **Title and ID**. -- **Rule C (Background):** For unrelated nodes, omit entirely or include only at Level 1. - -### 3. AST to Org Renderer (`context-render-to-org`) -- Implement a serializer that transforms our `org-object` structures back into valid Org-mode strings. -- This allows the LLM to "see" the Memex in its native habitat. - -### 4. Integrate with `context-assemble-global-awareness` -- Update this function to use the new extraction and rendering logic. -- Ensure it respects a maximum token/character budget to prevent context overflow. - -## Phase E: Chaos (Verification) -- **Structural Test:** Verify that ancestors are rendered as "skeletons" (no body text). -- **Foveal Test:** Verify that the target node is rendered with its full body text. -- **Budget Test:** Verify that the output string stays within defined limits even for large Memex structures. diff --git a/pipeline-refactor.md b/pipeline-refactor.md deleted file mode 100644 index df9924b..0000000 --- a/pipeline-refactor.md +++ /dev/null @@ -1,37 +0,0 @@ -# Implementation Plan: Reactive Signal Pipeline Refactor - -## Objective -Refactor the monolithic recursive `cognitive-cycle` into a functional, gate-based `reactive-signal-pipeline`. This flattens the execution stack, enables multi-backend consensus, and improves observability according to Component VII of the evolutionary roadmap. - -## Key Files & Context -- **Target:** `projects/opencortex/literate/core.org` (Source of `src/core.lisp`) -- **Architectural Reference:** `projects/opencortex/literate/evolution.org` - -## Implementation Steps - -### 1. Define the Signal Structure -Transition from raw plists to a structured `:SIGNAL` format that tracks state as it moves through the pipeline. -- Attributes: `:status`, `:payload`, `:context`, `:depth`, `:proposals`, `:reply-stream`. - -### 2. Implement the Pipeline Gates -Extract existing logic from `cognitive-cycle` into discrete functional gates: -- **`perceive-gate`**: Normalizes input, updates `*object-store*`. -- **`neuro-gate`**: Invokes Probabilistic Engine. Support for future parallel backend calls. -- **`consensus-gate`**: (New) Selects the best proposal from multiple backends (initially a pass-through for the single proposal). -- **`decide-gate`**: Invokes Deterministic Engine safety checks. -- **`dispatch-gate`**: Executes tools or physical actuators. - -### 3. Implement the Pipeline Orchestrator (`process-signal`) -Create a function that moves a signal through the sequence of gates. -- **Flattening Recursion:** If `dispatch-gate` results in a tool output or error, it MUST NOT call the pipeline recursively. Instead, it returns a new `:SIGNAL` with `depth + 1`, which the orchestrator then re-injects into the top of the pipe via a loop or queue. - -### 4. Refactor `inject-stimulus` -Update `inject-stimulus` to initialize a Signal and hand it to the `process-signal` pipeline instead of `cognitive-cycle`. - -### 5. Cleanup -Remove the obsolete `cognitive-cycle` function and update `literate/core.org` documentation/diagrams to reflect the new architecture. - -## Verification & Testing (Phase E: Chaos) -- **Unit Tests:** Verify each gate function in isolation. -- **Pipeline Test:** Simulate a complex multi-turn interaction (e.g., User Prompt -> Tool Call -> Tool Result -> LLM Final Answer) and ensure the stack depth remains flat. -- **Immune System Test:** Verify that the depth limit (Max depth 10) still correctly terminates runaway loops. diff --git a/projects/dotemacs/docs/README.org b/projects/dotemacs/docs/README.org deleted file mode 100644 index f77604c..0000000 --- a/projects/dotemacs/docs/README.org +++ /dev/null @@ -1,26 +0,0 @@ -#+title: Emacs Setup Improvement & Documentation Project -#+author: Amero Garcia -#+created: [2026-03-16 Mon 13:58] -#+begin_comment -This file outlines the project to collaboratively improve and document Amr's Emacs setup, aiming to make Emacs his primary computing tool. -#+end_comment - -* Emacs Setup Improvement & Documentation Project - -*Goal:** To collaboratively improve and comprehensively document Amr's Emacs configuration, transitioning Emacs into his primary computing environment. - -*Initial Scope:** -- Reviewing the existing Emacs Org-mode configuration file (tangled to set up Emacs). -- Identifying areas for optimization, new functionalities, and better integration with workflows. -- Documenting each significant setting, function, and package. - -*Information Needed from Amr:** -- Location of the current Emacs Org-mode configuration file. -- Key pain points or areas where Emacs currently falls short as a "main computing tool." -- Specific desired functionalities or integrations (e.g., mail, calendar, task management, coding environments, note-taking, web browsing within Emacs). -- Any existing documentation or design principles for the current setup. - -*Next Steps:** -1. Receive Emacs configuration file location from Amr. -2. Analyze current setup. -3. Propose documentation structure and initial improvements. \ No newline at end of file diff --git a/projects/dotemacs/docs/dotemacs.org b/projects/dotemacs/docs/dotemacs.org deleted file mode 100644 index 0d344b1..0000000 --- a/projects/dotemacs/docs/dotemacs.org +++ /dev/null @@ -1,27 +0,0 @@ -#+TITLE: Amr's Modular Emacs Configuration -#+PROPERTY: header-args :tangle no ; This file is for loading other modules, not for tangling itself. - -* Configuration Modules - -This file loads the modular Emacs configuration files. It should be the primary way Emacs is configured, replacing or integrating with the original `~/.emacs`, `~/.emacs.d/init.el`, `~/.emacs.d/early-init.el`, and `~/.emacs.d/config.el`. - -#+begin_src emacs-lisp :exports none -;; Load early-init.el first, if it exists and is separate (though it's now part of emacs-early-init.org) -;; (load-file (expand-file-name "emacs-early-init.org" (file-name-directory load-file-name))) - -;; Load the core settings, including package management and essential setup. -(org-babel-load-file (expand-file-name "emacs-core.org" (file-name-directory load-file-name))) - -;; Load early init settings (if separate and not fully covered by core) -(org-babel-load-file (expand-file-name "emacs-early-init.org" (file-name-directory load-file-name))) - -;; Load other modules in a logical order -(org-babel-load-file (expand-file-name "emacs-org.org" (file-name-directory load-file-name))) -(org-babel-load-file (expand-file-name "emacs-gtd.org" (file-name-directory load-file-name))) -(org-babel-load-file (expand-file-name "emacs-roam.org" (file-name-directory load-file-name))) -(org-babel-load-file (expand-file-name "emacs-writing.org" (file-name-directory load-file-name))) -(org-babel-load-file (expand-file-name "emacs-media.org" (file-name-directory load-file-name))) -(org-babel-load-file (expand-file-name "emacs-shell.org" (file-name-directory load-file-name))) -(org-babel-load-file (expand-file-name "emacs-ai.org" (file-name-directory load-file-name))) -(org-babel-load-file (expand-file-name "emacs-misc.org" (file-name-directory load-file-name))) -#+end_src \ No newline at end of file diff --git a/projects/dotemacs/docs/emacs-ai.org b/projects/dotemacs/docs/emacs-ai.org deleted file mode 100644 index e268adc..0000000 --- a/projects/dotemacs/docs/emacs-ai.org +++ /dev/null @@ -1,104 +0,0 @@ -#+TITLE: AI Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* AI Settings - -** Ellama - -#+begin_src elisp :tangle no - ;; YOU DON'T NEED NONE OF THIS CODE FOR SIMPLE INSTALL - ;; IT IS AN EXAMPLE OF CUSTOMIZATION. - (use-package ellama - :init - (require 'llm-openai) - ;; setup key bindings - (setq ellama-keymap-prefix "C-c e") - ) -#+end_src - -#+begin_src elisp ~/.emacs.d/custom.el :tangle no - (setopt ellama-providers - '( - ;; Ollama Provider (added here with a name) - ("ollama" . (make-llm-ollama - ;; Consider a dedicated embedding model if gemma isn't ideal for it. - :chat-model "gemma3:latest" - :embedding-model "gemma3:latest" ; Or e.g., "nomic-embed-text" - :default-chat-non-standard-params '(("num_ctx" . 8192)))) - - ("openai" . (make-llm-openai - :key (auth-source-pass-get "api-key" "www/openai.com/amr@gharbeia.net") - :chat-model "gpt-4o" - :embedding-model "text-embedding-3-large")) - - ("groq" . (make-llm-openai-compatible - :url "https://api.groq.com/openai/v1" - :key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net") - ;; Check Groq console for available models, these might change - :chat-model "llama3-70b-8192" ; Example, verify on Groq - :embedding-model "llama3-70b-8192")) ; Groq might not offer dedicated embedding models via this API - )) - - ;; --- Set Active Providers --- - ;; Choose your default provider from the list above by its name - (setopt ellama-provider "ollama") ; Or "ollama", "openai", "groq" - - ;; You can specify different providers for different tasks if needed - (setopt ellama-translation-provider "ollama") - (setopt ellama-naming-provider "ollama") - (setopt ellama-naming-scheme 'ellama-generate-name-by-llm) - - (setq llm-debug t) -#+end_src - -#+begin_src elisp - (use-package ellama - :ensure t - :bind ("C-c e" . ellama) - ;; send last message in chat buffer with C-c C-c - :hook (org-ctrl-c-ctrl-c-final . ellama-chat-send-last-message) - :init (setopt ellama-auto-scroll t) - :config - ;; show ellama context in header line in all buffers - (ellama-context-header-line-global-mode +1) - ;; show ellama session id in header line in all buffers - (ellama-session-header-line-global-mode +1)) -#+end_src - -** GPTel - -#+begin_src elisp :tangle no - (use-package gptel) -#+end_src - -#+begin_src elisp :tangle no - (setq gptel-api-key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net")) -#+end_src - -#+begin_src elisp :tangle no - (gptel-make-openai "Groq" ;Any name you want - :host "api.groq.com" - :endpoint "/openai/v1/chat/completions" - :stream t - :key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net") ;can be a function that returns the key - :models '(llama-3.1-70b-versatile - llama-3.1-8b-instant - llama3-70b-8192 - llama3-8b-8192 - mixtral-8x7b-32768 - gemma-7b-it)) -#+end_src - -** Elisa - -#+begin_src elisp :tangle no - (use-package elisa - :init - (setopt elisa-limit 5) - (require 'llm-ollama) - (setopt elisa-embeddings-provider (make-llm-ollama :embedding-model "nomic-embed-text")) - (setopt elisa-chat-provider (make-llm-ollama - :chat-model "sskostyaev/openchat:8k-rag" - :embedding-model "nomic-embed-text")) - ) -#+end_src \ No newline at end of file diff --git a/projects/dotemacs/docs/emacs-core.org b/projects/dotemacs/docs/emacs-core.org deleted file mode 100644 index b8b2011..0000000 --- a/projects/dotemacs/docs/emacs-core.org +++ /dev/null @@ -1,169 +0,0 @@ -#+TITLE: Core Emacs Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* Front matter - -#+begin_src elisp :tangle ~/.emacs - ;;; .emacs --- Global settings - ;;; Commentary: - ;;; Code: - - ;; -*- lexical-binding: t; -*- -#+end_src - -#+begin_src elisp - ;;; config.el --- Summary - ;;; Commentary: - ;;; Code: - - ;; -*- lexical-binding: t; -*- -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - ;;; custom.el --- Summary - ;;; Commentary: - ;;; Code: - - ;; -*- lexical-binding: t; -*- -#+end_src - -* Garbage collector - -Increase threshold to 500 MB to ease startup -#+begin_src elisp :tangle ~/.emacs - (setq gc-cons-threshold (* 500 1024 1024)) -#+end_src - -Decrease threshold to 5 MB after init -#+begin_src elisp :tangle ~/.emacs - (add-hook 'after-init-hook (lambda () (setq gc-cons-threshold (* 5 1024 1024)))) -#+end_src - -* Straight.el and use-package - -Bootstrap Straight.el and install use-package -#+begin_src elisp :tangle ~/.emacs - (setq straight-repository-branch "develop") ;; Using develop branch temporarily to fix the org-roam-dailies issue. - - (eval-and-compile - (defvar bootstrap-version) - (let ((bootstrap-file - (expand-file-name "straight/repos/straight.el/bootstrap.el" - (or (bound-and-true-p straight-base-dir) - user-emacs-directory))) - (bootstrap-version 7)) - (unless (file-exists-p bootstrap-file) - (with-current-buffer - (url-retrieve-synchronously "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" 'silent 'inhibit-cookies) - (goto-char (point-max)) - (eval-print-last-sexp))) - (load bootstrap-file nil 'nomessage)) - - (straight-use-package 'use-package) - ) -#+end_src - -Integrate use-package and straight -#+begin_src elisp :tangle ~/.emacs - (setq straight-use-package-by-default t) -#+end_src - -Make sure Org is installed (straight.el) -#+begin_src elisp :tangle ~/.emacs - (unless (file-directory-p "~/.emacs.d/straight/versions") (make-directory (concat user-emacs-directory "straight/versions"))) -#+end_src - -#+begin_src elisp :tangle ~/.emacs - (use-package org) -#+end_src - -A use-package declaration for simplifying your .emacs -#+begin_src elisp - (require 'use-package) -#+end_src - -* Custom file - -#+begin_src elisp - (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) - (when (file-exists-p custom-file) (load custom-file)) -#+end_src - -* System information - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar my-laptop-p (equal (system-name) "lilitop")) - (defvar my-server-p (and (equal (system-name) "localhost") (equal user-login-name "root"))) - (defvar my-phone-p (not (null (getenv "ANDROID_ROOT"))) - "If non-nil, GNU Emacs is running on Termux.") - (when my-phone-p (defvar gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")) - (global-auto-revert-mode) ; simplifies syncing -#+end_src - -* Persistent history - -#+begin_src elisp - (savehist-mode) -#+end_src - -* Backup and versioning - -#+begin_src emacs-lisp - (use-package magit - :ensure t - ) -#+end_src - -* Personal information - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (setq user-full-name "Amr Gharbeia") - (defvar email-address "amr@gharbeia.net") - (defvar calendar-latitude 39.0) - (defvar calendar-longitude -77.1) - (defvar calendar-location-name "Washington, DC") - (defvar calendar-time-zone -300) - (defvar calendar-standard-time-zone-name "EST") - (defvar calendar-daylight-time-zone-name "EDT") -#+end_src - -* Saving Emacs Sessions - -Close frame when done -#+begin_src elisp - (add-hook 'server-done-hook (lambda () (delete-frame))) -#+end_src - -Save desktop session -#+begin_src elisp - (desktop-save-mode t) -#+end_src - -* Security - -#+begin_src elisp :tangle no - (use-package password-store) -#+end_src - -#+begin_src elisp - (use-package auth-source - :config (auth-source-pass-enable) - ) -#+end_src - -* End matter - -#+begin_src elisp :tangle ~/.emacs - (provide '.emacs) - ;;; .emacs ends here -#+end_src - -#+begin_src elisp - (provide 'config) - ;;; config.el ends here -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (provide 'custom) - ;;; custom.el ends here -#+end_src diff --git a/projects/dotemacs/docs/emacs-gtd.org b/projects/dotemacs/docs/emacs-gtd.org deleted file mode 100644 index 1bf1ec1..0000000 --- a/projects/dotemacs/docs/emacs-gtd.org +++ /dev/null @@ -1,157 +0,0 @@ -#+TITLE: GTD & Agenda Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* Agenda - -Basic agenda settings -#+begin_src elisp - (setq org-deadline-warning-days 7) - (setq org-agenda-skip-additional-timestamps-same-entry t) - (setq org-agenda-span 'fortnight) - (setq org-agenda-tags-column 'auto) - (setq org-agenda-skip-scheduled-if-deadline-is-shown t) -#+end_src - -Agenda files -#+begin_src elisp - (setq org-agenda-files (list - (concat org-directory "inbox.org") - (concat org-directory "gtd.org") - ) - ) -#+end_src - -Better agenda views -#+begin_src elisp :tangle no - (use-package org-super-agenda) -#+end_src - -* To-do - -Basic todo -#+begin_src elisp - (setq org-todo-keywords - '( - (sequence "TODO(t)" "NEXT(n)" "WAIT(w@/!)" "|" "DONE(d!)" "CNCL(c@)") - ) - ) - - (setq org-todo-keyword-faces - '( - ("TODO" :foreground "red" :weight bold) - ("NEXT" :foreground "red" :weight bold) - ("WAIT" :foreground "yellow" :weight bold) - ("DONE" :foreground "green" :weight bold) - ("CNCL" :foreground "blue" :weight bold) - ) - ) - - (setq org-enforce-todo-dependencies t) - (setq org-tags-exclude-from-inheritance '("crypt" "!private")) -#+end_src - -Switch entry to 'DONE' when all subentries are done -#+begin_src elisp - (defun org-summary-todo (n-done n-not-done) - "Switch entry to 'DONE' when all subentries are done, to 'TODO' otherwise. - Uses N-DONE and N-NOT-DONE" - (let (org-log-done org-log-states) ; turn off logging - (org-todo (if (= n-not-done 0) "DONE" "TODO") - ) - ) - ) - - (add-hook 'org-after-todo-statistics-hook #'org-summary-todo) -#+end_src - -* Getting Things Done (GTD) -#+begin_src elisp - (use-package org-gtd - :defer t - :init (setq org-gtd-update-ack "4.0.0") - :after org - :config - (setq org-edna-use-inheritance t) - (org-edna-mode) - (setq org-gtd-keyword-mapping - '((todo . "TODO") - (next . "NEXT") - (wait . "WAIT") - (done . "DONE") - (canceled . "CNCL"))) - (setq org-gtd-custom-node-paths - '(("Actionable" . '("~/memex/gtd.org" "Actions")) - ("Incubate" . '("~/memex/gtd.org" "Incubate")))) - (org-gtd-mode) - :bind ( - ("C-c d c" . org-gtd-capture) - ("C-c d e" . org-gtd-engage) - ("C-c d p" . org-gtd-process-inbox) - :map org-gtd-clarify-map - ("C-c c" . org-gtd-organize) - ) - ) -#+end_src - -#+begin_src elisp - (defvar org-gtd-directory org-directory) - (defvar org-gtd-organize-hooks '(org-gtd-set-area-of-focus org-set-tags-command)) - (defvar org-gtd-organize-hooks '(org-gtd-set-area-of-focus)) - (defvar org-gtd-areas-of-focus '( - "Atoms" - "Bits" - "Cells" - "Flags" - "Business" - "Wealth" - "Learning" - "Skills" - "Privacy" - "Archive" - "Library" - "Writing" - "Health" - "Home" - "Family" - "Social" - "Egypt" - ) - ) - (defvar org-gtd-clarify-show-horizons 'right) -#+end_src - -Logging -#+begin_src elisp - (setq org-log-into-drawer "LOGBOOK") -#+end_src - -Clocking work in drawer -#+begin_src elisp :tangle no - (setq org-clock-into-drawer t) -#+end_src - -Habits -#+begin_src elisp :tangle no - (setq org-habit-graph-column 80) - (setq org-habit-show-habits-only-for-today nil) -#+end_src - -* Refile - -org-refile targets -#+begin_src elisp - (setq org-refile-targets '((nil :maxlevel . 9) - (org-agenda-files :maxlevel . 9) - ) - ) -#+end_src - -Set type of refile targets completion -#+begin_src elisp - (setq org-outline-path-complete-in-steps nil) -#+end_src - -Allow refiling to new parents created on the go after confirmation -#+begin_src elisp - (setq org-refile-allow-creating-parent-nodes 'confirm) -#+end_src \ No newline at end of file diff --git a/projects/dotemacs/docs/emacs-media.org b/projects/dotemacs/docs/emacs-media.org deleted file mode 100644 index 22237ff..0000000 --- a/projects/dotemacs/docs/emacs-media.org +++ /dev/null @@ -1,175 +0,0 @@ -#+TITLE: Media and Books Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* Read ebooks (calibredb) - -#+begin_src elisp - (use-package calibredb -:defer t - :config - (setq calibredb-format-all-the-icons t) - (setq calibredb-format-icons-in-terminal t) - ) -#+end_src - -#+begin_src elisp - ;; Forcefully reset the variable after loading calibredb - (defvar calibredb-root-dir (concat (getenv "HOME") "/library/books")) - (defvar calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir)) - ; (defvar calibredb-library-alist (concat (getenv "HOME") "/library/books")) - ;; (defvar calibredb-search-page-max-rows 1000) - (defvar calibredb-id-width 6) - (defvar calibredb-title-width 100) - (defvar calibredb-format-width 0) - (defvar calibredb-date-width 0) - (defvar calibredb-author-width 20) - (defvar calibredb-comment-width 0) - (defvar calibredb-tag-width 0) -#+end_src - -Some keybindings - -#+begin_src elisp ~/.emacs.d/custom.el - (defvar calibredb-show-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "?" #'calibredb-entry-dispatch) - (define-key map "o" #'calibredb-find-file) - (define-key map "O" #'calibredb-find-file-other-frame) - (define-key map "V" #'calibredb-open-file-with-default-tool) - (define-key map "s" #'calibredb-set-metadata-dispatch) - (define-key map "e" #'calibredb-export-dispatch) - (define-key map "q" #'calibredb-entry-quit) - (define-key map "y" #'calibredb-yank-dispatch) - (define-key map "," #'calibredb-quick-look) - (define-key map "." #'calibredb-dired-open) - (define-key map "\M-/" #'calibredb-rga) - (define-key map "\M-t" #'calibredb-set-metadata--tags) - (define-key map "\M-a" #'calibredb-set-metadata--author_sort) - (define-key map "\M-A" #'calibredb-set-metadata--authors) - (define-key map "\M-T" #'calibredb-set-metadata--title) - (define-key map "\M-c" #'calibredb-set-metadata--comments) - map) - "Keymap for `calibredb-show-mode'.") -#+end_src - -#+begin_src elisp - (defvar calibredb-search-mode-map - (let ((map (make-sparse-keymap))) - (define-key map [mouse-3] #'calibredb-search-mouse) - (define-key map (kbd "") #'calibredb-find-file) - (define-key map "?" #'calibredb-dispatch) - (define-key map "a" #'calibredb-add) - (define-key map "A" #'calibredb-add-dir) - (define-key map "c" #'calibredb-clone) - (define-key map "d" #'calibredb-remove) - (define-key map "D" #'calibredb-remove-marked-items) - (define-key map "j" #'calibredb-next-entry) - (define-key map "k" #'calibredb-previous-entry) - (define-key map "l" #'calibredb-virtual-library-list) - (define-key map "L" #'calibredb-library-list) - (define-key map "n" #'calibredb-virtual-library-next) - (define-key map "N" #'calibredb-library-next) - (define-key map "p" #'calibredb-virtual-library-previous) - (define-key map "P" #'calibredb-library-previous) - (define-key map "s" #'calibredb-set-metadata-dispatch) - (define-key map "S" #'calibredb-switch-library) - (define-key map "o" #'calibredb-find-file) - (define-key map "O" #'calibredb-find-file-other-frame) - (define-key map "v" #'calibredb-view) - (define-key map "V" #'calibredb-open-file-with-default-tool) - (define-key map "," #'calibredb-quick-look) - (define-key map "." #'calibredb-dired-open) - (define-key map "y" #'calibredb-yank-dispatch) - (define-key map "b" #'calibredb-catalog-bib-dispatch) - (define-key map "e" #'calibredb-export-dispatch) - (define-key map "r" #'calibredb-search-refresh-and-clear-filter) - (define-key map "R" #'calibredb-search-clear-filter) - (define-key map "q" #'calibredb-search-quit) - (define-key map "m" #'calibredb-mark-and-forward) - (define-key map "f" #'calibredb-toggle-favorite-at-point) - (define-key map "x" #'calibredb-toggle-archive-at-point) - (define-key map "h" #'calibredb-toggle-highlight-at-point) - (define-key map "u" #'calibredb-unmark-and-forward) - (define-key map "i" #'calibredb-edit-annotation) - (define-key map (kbd "") #'calibredb-unmark-and-backward) - (define-key map (kbd "") #'calibredb-toggle-view) - (define-key map (kbd "TAB") #'calibredb-toggle-view-at-point) - (define-key map "\M-n" #'calibredb-show-next-entry) - (define-key map "\M-p" #'calibredb-show-previous-entry) - (define-key map "/" #'calibredb-search-live-filter) - (define-key map "\M-t" #'calibredb-set-metadata--tags) - (define-key map "\M-a" #'calibredb-set-metadata--author_sort) - (define-key map "\M-A" #'calibredb-set-metadata--authors) - (define-key map "\M-T" #'calibredb-set-metadata--title) - (define-key map "\M-c" #'calibredb-set-metadata--comments) - map) - "Keymap for `calibredb-search-mode'.") -#+end_src - -* Annotate PDFs and EPUBs (org-noter) - -#+begin_src elisp :tangle no - (use-package org-noter) -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar org-noter-notes-search-path (list (concat org-directory "/library/books"))) - (defvar org-noter-default-notes-file-names '("books.org")) -#+end_src - -* Link PDFs (org-noter-pdftools) - -#+begin_src elisp - (use-package org-noter-pdftools - :after org-noter - :config - ;; Add a function to ensure precise note is inserted - (defun org-noter-pdftools-insert-precise-note (&optional toggle-no-questions) - (interactive "P") - (org-noter--with-valid-session - (let ((org-noter-insert-note-no-questions (if toggle-no-questions - (not org-noter-insert-note-no-questions) - org-noter-insert-note-no-questions)) - (org-pdftools-use-isearch-link t) - (org-pdftools-use-freepointer-annot t)) - (org-noter-insert-note (org-noter--get-precise-info))))) - - ;; fix https://github.com/weirdNox/org-noter/pull/93/commits/f8349ae7575e599f375de1be6be2d0d5de4e6cbf - (defun org-noter-set-start-location (&optional arg) - "When opening a session with this document, go to the current location. - With a prefix ARG, remove start location." - (interactive "P") - (org-noter--with-valid-session - (let ((inhibit-read-only t) - (ast (org-noter--parse-root)) - (location (org-noter--doc-approx-location (when (called-interactively-p 'any) 'interactive)))) - (with-current-buffer (org-noter--session-notes-buffer session) - (org-with-wide-buffer - (goto-char (org-element-property :begin ast)) - (if arg - (org-entry-delete nil org-noter-property-note-location) - (org-entry-put nil org-noter-property-note-location - (org-noter--pretty-print-location location)))))))) - (with-eval-after-load 'pdf-annot - (add-hook 'pdf-annot-activate-handler-functions #'org-noter-pdftools-jump-to-note) - ) - ) -#+end_src - -* View EPUBs (nov.el) - -#+begin_src elisp :tangle no - (use-package nov - :config - (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)) - ) -#+end_src - -* Zotero (helm-bibtex) -#+begin_src elisp :tangle no - (use-package helm-bibtex) -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar bibtex-completion-bibliography '("~/bibliography/zotero.bib")) -#+end_src \ No newline at end of file diff --git a/projects/dotemacs/docs/emacs-misc.org b/projects/dotemacs/docs/emacs-misc.org deleted file mode 100644 index 8a718fe..0000000 --- a/projects/dotemacs/docs/emacs-misc.org +++ /dev/null @@ -1,46 +0,0 @@ -#+TITLE: Miscellaneous Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* Browser (eww) - -#+begin_src elisp - (use-package eww - :bind* (("M-m g x" . eww) - ("M-m g :" . eww-browse-with-external-browser) - ("M-m g #" . eww-list-histories) - ("M-m g {" . eww-back-url) - ("M-m g }" . eww-forward-url)) - :config - (progn - (add-hook 'eww-mode-hook 'visual-line-mode) - ) - ) -#+end_src - -* Manage Docker in Emacs - -#+begin_src elisp - (use-package docker - :bind ("C-c d" . docker) - ) -#+end_src - -* Periodic table of the elements - -#+begin_src elisp :tangle no - (use-package chemtable) -#+end_src - -* Accounting (beancount) - -#+begin_src elisp :tangle no - (use-package beancount - :straight (beancount :type git :host github :repo "beancount/beancount-mode") - :config - (add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode)) - (add-hook 'beancount-mode-hook #'outline-minor-mode) - (define-key beancount-mode-map (kbd "C-c C-n") #'outline-next-visible-heading) - (define-key beancount-mode-map (kbd "C-c C-p") #'outline-previous-visible-heading) - (add-hook 'beancount-mode-hook #'flymake-bean-check-enable) - ) -#+end_src diff --git a/projects/dotemacs/docs/emacs-org.org b/projects/dotemacs/docs/emacs-org.org deleted file mode 100644 index a563fa4..0000000 --- a/projects/dotemacs/docs/emacs-org.org +++ /dev/null @@ -1,233 +0,0 @@ -#+TITLE: Org Mode Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* Org Mode - -** Basic setup - -#+begin_src elisp - (use-package org - :config - (defvar org-outline-path-complete-in-steps nil) - :bind (("C-c l" . org-store-link) - ("C-c a" . org-agenda) - ("C-c c" . org-capture) - :map org-mode-map) - ) -#+end_src - -#+begin_src elisp - (defvar org-directory (concat (getenv "HOME") "/memex/")) -#+end_src - -** Looks - -Basic -#+begin_src elisp - (defvar org-pretty-entities t) ; Improve org mode looks - (defvar org-hide-emphasis-markers t) ; Hide emphasis markup - (defvar org-num-mode nil) - (defvar org-startup-folded 'shw2levels) -#+end_src - -Indentation of headers -#+begin_src elisp - (defvar org-startup-indented t) ; Indent org heirarchy - (defvar org-adapt-indentation t) - (defvar org-hide-leading-stars t) ; Minimal Outline - (defvar org-odd-levels-only nil) -#+end_src - -Indentation of lists -#+begin_src elisp - (setq org-list-demote-modify-bullet t) -#+end_src - -Org-modern -#+begin_src elisp - (use-package org-modern - :ensure t - :config - ;; Choose some fonts - (set-face-attribute 'default nil :family "sans-serif") - (set-face-attribute 'variable-pitch nil :family "sans-serif") - (set-face-attribute 'org-modern-symbol nil :family "Iosevka") - - ;; Edit settings - (defvar org-auto-align-tags nil) - (defvar org-tags-column 0) - (defvar org-catch-invisible-edits 'show-and-error) - (defvar org-special-ctrl-a/e t) - (defvar org-insert-heading-respect-content t) - - ;; Org styling, hide markup etc. - (defvar org-hide-emphasis-markers t) - (defvar org-pretty-entities t) - - ;; Agenda styling - (defvar org-agenda-tags-column 0) - (defvar org-agenda-block-separator ?─) - (defvar org-agenda-time-grid - '((daily today require-timed) - (800 1000 1200 1400 1600 1800 2000) - " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")) - (defvar org-agenda-current-time-string - "◀── now ─────────────────────────────────────────────────") - - ;; Ellipsis styling - (defvar org-ellipsis "…") - (set-face-attribute 'org-ellipsis nil :inherit 'default :box nil) - - (global-org-modern-mode) - ) -#+end_src - -Highlight Sourcecode Syntax -#+begin_src elisp - (setq org-src-fontify-natively t) - (setq org-src-tab-acts-natively t) -#+end_src - -Images -#+begin_src elisp - (setq org-startup-with-inline-images t) - (setq org-image-actual-width '(300)) -#+end_src - -** Capture - -#+begin_src elisp - (defvar org-default-notes-file (concat org-directory "inbox.org")) -#+end_src - -*** Org-protocol - -Linux configuration -#+begin_src bash :tangle no -[Desktop Entry] -Name=org-protocol -Comment=Intercept calls from emacsclient to trigger custom actions -Categories=Other; -Keywords=org-protocol; -Icon=emacs -Type=Application -Exec=emacsclient -- %u -Terminal=false -StartupWMClass=Emacs -MimeType=x-scheme-handler/org-protocol; -#+end_src - -#+begin_src bash :tangle no -update-desktop-database ~/.local/share/applications/ -#+end_src - -Basic configuration -#+begin_src elisp - (require 'org-protocol) - (setq org-protocol-default-buffer-for-file-links "*scratch*") ; fixes 'no buffers remain to edit error for org-protocol capturer -#+end_src - -Org-protocol templates -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar org-capture-templates '( - ("p" "Protocol" - entry - (file "inbox.org") - "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?" - ) - ("L" "Protocol Link" - entry - (file "inbox.org") - "* %? [[%:link][%:description]]\n:PROPERTIES:\n:TITLE: %:description\n:URI: %:link\n:CREATED: %U\n:END:" - :prepend nil - :empty-lines 1 - :created t - :kill-buffer t - ) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-protocol-default-template-key "L") -#+end_src - -Convert Orgzly captures to org-protocol captures standard -#+begin_src elisp - (defun my/org-convert-orgzly-to-org-protocol () - "Reformat Orgzly bookmark at point to org-protocol bookmark." - (interactive) - (when (org-at-heading-p) - (let ((headline (nth 4 (org-heading-components)))) - ;; Find and store the link. Delete the link line. - (search-forward-regexp "^https?://\\S-*" nil t) - (let ((link (match-string 0))) - (beginning-of-line) - (kill-line) - ;; Delete any trailing blank spaces - (org-back-to-heading) - (end-of-line) - (when (not (org-on-heading-p)) - (delete-char 1) - ) - ;; Set new headline - (goto-char (org-entry-beginning-position)) - (org-edit-headline (format "[[%s][%s]]" link headline)) - ;; Set new properties - (org-set-property "TITLE" headline) - (org-set-property "URI" link) - (message "Reformatted Orgzly bookmark at point to org-protocol bookmark") - ) - ) - ) - ) -#+end_src - -** Exporting - -#+begin_src elisp :tangle no - (setq org-export-with-smart-quotes t) - (setq org-export-backends '(beamer html latex md)) -#+end_src - -Export to EPUB -#+begin_src elisp :tangle no - (use-package ox-epub) -#+end_src - -** org-attach - -#+begin_src elisp - (defvar org-attach-id-dir (concat org-directory "/library")) -#+end_src - -** Enable shell scripting support in org-babel - -#+begin_src elisp - (defvar org-babel-do-load-languages 'org-babel-load-languages '((shell . t))) -#+end_src - -** Insert org-mode links from clipboard -#+begin_src elisp :tangle no - (use-package org-cliplink - :bind - (("C-x p i" . org-cliplink)) - ) -#+end_src - -** Deft -#+begin_src elisp :tangle no - (use-package deft - :commands (deft) - :init - (defvar deft-extensions '("org")) - (defvar deft-recursive nil) - (defvar deft-use-filename-as-title t) - :config - (defvar deft-directory org-directory) - (defvar deft-recursive t) - (defvar deft-strip-summary-regexp ":PROPERTIES:\n\\(.+\n\\)+:END:\n") - (defvar deft-use-filename-as-title t) - :bind ("C-c n d" . deft) - ) -#+end_src \ No newline at end of file diff --git a/projects/dotemacs/docs/emacs-roam.org b/projects/dotemacs/docs/emacs-roam.org deleted file mode 100644 index 7644206..0000000 --- a/projects/dotemacs/docs/emacs-roam.org +++ /dev/null @@ -1,140 +0,0 @@ -#+TITLE: Org-Roam Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* Org-roam - -** Basic org-roam setup - -#+begin_src elisp -(use-package org-roam - :init (setq org-roam-v2-ack t) ;; Acknowledge V2 upgrade - :after org - :config - (org-roam-db-autosync-enable) - (require 'org-roam-dailies) - :bind ( - ("C-c n f" . org-roam-node-find) - ("C-c n g" . org-roam-graph) - ("C-c n r" . org-roam-node-random) - ("C-c n h" . org-roam-node-convert-headline) - ("C-c n i" . org-roam-node-insert) - ("C-c n o" . org-id-get-create) - ("C-c n t" . org-roam-tag-add) - ("C-c n a" . org-roam-alias-add) - ("C-c n l" . org-roam-buffer-display-dedicated) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-roam-directory (concat org-directory "notes")) - (setq org-roam-dailies-directory (concat org-directory "daily")) -#+end_src - -#+begin_src elisp :tangle no - (use-package sqlite3) - (require 'sqlite3) -#+end_src - -Include subdirectories in org-roam -#+begin_src elisp - (setq org-roam-file-exclude-regexp "^[.][.]?/") -#+end_src - -** Display in org-roam-buffer -#+begin_src elisp :tangle no - (setq org-roam-mode-sections - (list #'org-roam-backlinks-section - #'org-roam-reflinks-section - #'org-roam-unlinked-references-section - ) - ) -#+end_src - -** Filter org-roam nodes find by tag - -#+begin_src elisp :tangle no - (defun my/org-roam-node-has-tag (node tag) - "Filter function to check if the given NODE has the specified TAG." - (member tag (org-roam-node-tags node)) - ) - - (defun my/org-roam-node-find-by-tag () - "Find and open an Org-roam node based on a specified tag." - (interactive) - (let ((tag (read-string "Enter tag: "))) - (org-roam-node-find nil nil (lambda (node) (my/org-roam-node-has-tag node tag)))) - ) -#+end_src - -** org-roam-capture templates -#+begin_src elisp - (setq org-roam-capture-templates - '( - ("L" "link" plain - (function org-roam--capture-get-point) - "%?" - :file-name "web/%<%Y-%m-%dT%H%M%S>.org" - :head "#+TITLE: ${title}\n#+CREATED: %<%Y-%m-%dT%H%M%S>" - :immediate-finish t - :unnarrowed t - ) - - ("h" "hugo post" plain - "%?" - :target (file+head "posts/${slug}.org" - "#+TITLE: ${title}\n#+DATE: %U\n#+HUGO_BASE_DIR: ~/gharbeia.net\n#+HUGO_SECTION: ./posts\n#+HUGO_AUTO_SET_LASTMOD: t\n#+HUGO_TAGS: article\n#+HUGO_DRAFT: true\n") - :immediate-finish t - :unnarrowed t - ) - - ("p" "person" plain - "%?" - :if-new (file+head "people/${slug}.org" - "#+TITLE: ${title}") - :immediate-finish t - :unnarrowed t - ) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-roam-dailies-capture-templates - '( - ("d" "daily" plain - "" - :target ("file+heaed %<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n\n") - :immediate-finish t - ) - ) - ) -#+end_src - -** Move org header to org-roam-daily - -#+begin_src elisp :tangle no - (defun my/org-move-entry-to-daily-notes () - "Move the current org-mode headline to the daily notes file based on its :CREATED: property." - (interactive) - (let* - ( - (created-prop (org-entry-get nil "CREATED")) - (created-date (when created-prop - (org-parse-time-string created-prop))) - (year (nth 5 created-date)) ; Extract year (6th element) - (month (nth 4 created-date)) ; Extract month (5th element) - (day (nth 3 created-date)) ; Extract day (4th element) - (target-date (format "%04d-%02d-%02d" year month day)) ; Format date string - (target-file (org-roam-dailies-goto target-date)) - ) - (when target-file - (org-cut-subtree) - (find-file target-file) - (goto-char (point-max)) - (unless (bolp) (newline)) - (org-paste-subtree) - ) - ) - ) -#+end_src \ No newline at end of file diff --git a/projects/dotemacs/docs/emacs-shell.org b/projects/dotemacs/docs/emacs-shell.org deleted file mode 100644 index 537cf6f..0000000 --- a/projects/dotemacs/docs/emacs-shell.org +++ /dev/null @@ -1,73 +0,0 @@ -#+TITLE: Shell Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* Shell - -** Bash completion - -#+begin_src elisp - (use-package bash-completion - :config - (require 'bash-completion) - (bash-completion-setup) - ) -#+end_src - -#+begin_src elisp -(defvar shell-dynamic-complete-functions t) -#+end_src - -** Eshell - -Add programmable bash completion to Emacs shell-mode -#+begin_src elisp :tangle no - (require 'bash-completion) - (add-hook 'eshell-mode-hook - (lambda () - (add-hook 'completion-at-point-functions - 'bash-completion-capf-nonexclusive nil t - ) - ) - ) -#+end_src - -Use colors in eshell -#+begin_src elisp :tangle no - (use-package xterm-color - :commands (xterm-color-filter) - ) - - (use-package eshell - :after xterm-color - :config - (define-key eshell-hist-mode-map (kbd "M-r") #'consult-history) - (add-hook 'eshell-mode-hook - (lambda () - (setenv "TERM" "xterm-256color"))) - (add-hook 'eshell-before-prompt-hook (setq xterm-color-preserve-properties t)) - (add-to-list 'eshell-preoutput-filter-functions 'xterm-color-filter) - (setq eshell-output-filter-functions - (remove 'eshell-handle-ansi-color eshell-output-filter-functions) - ) - ) -#+end_src - -Eshell completion -#+begin_src elisp :tangle no - (add-hook 'eshell-mode-hook - (lambda () - (add-hook 'completion-at-point-functions - 'bash-completion-capf-nonexclusive nil t))) -#+end_src - -Emulate A Terminal (EAT) -#+begin_src elisp :tangle no - (use-package eat - :config - ;; For `eat-eshell-mode'. - (add-hook 'eshell-load-hook #'eat-eshell-mode) - - ;; For `eat-eshell-visual-command-mode'. - (add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode) - ) -#+end_src \ No newline at end of file diff --git a/projects/dotemacs/docs/emacs-writing.org b/projects/dotemacs/docs/emacs-writing.org deleted file mode 100644 index e883f76..0000000 --- a/projects/dotemacs/docs/emacs-writing.org +++ /dev/null @@ -1,255 +0,0 @@ -#+TITLE: Reading and Writing Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/config.el - -* Text and Case - -** Convert DOuble capitals to single capitals - -#+begin_src elisp :tangle no - (defun my/dcaps-to-scaps () - "Convert word in DOuble CApitals to Single Capitals." - (interactive) - (and (= ?w (char-syntax (char-before))) - (save-excursion - (and (if (called-interactively-p) - (skip-syntax-backward "w") - (= -3 (skip-syntax-backward "w")) - ) - (let (case-fold-search) - (looking-at "\\b[[:upper:]]\\{2\\}[[:lower:]]") - ) - (capitalize-word 1) - ) - ) - ) - ) -#+end_src - -Then, let’s define a minor mode for it to be activated. -#+begin_src elisp :tangle no - (define-minor-mode my-dubcaps-mode - "Toggle 'my-dubcaps-mode' and convert words in DOuble CApitals to Single Capitals as you type." - :init-value nil - :lighter (" DC") - (if my-dubcaps-mode - (add-hook 'post-self-insert-hook #'my/dcaps-to-scaps nil 'local) - (remove-hook 'post-self-insert-hook #'my/dcaps-to-scaps 'local))) -#+end_src - - Finally, let’s add a hook so that it is on for all the text files Emacs opens. -#+begin_src elisp :tangle no - (add-hook 'text-mode-hook #'my-dubcaps-mode) -#+end_src - -Also, since we add a minor mode string (it might be useful sometimes), currently I prefer to diminish it. -#+begin_src elisp :tangle no - (defun my/diminish-dubcaps () - (interactive) - (diminish 'my-dubcaps-mode "")) - (add-hook 'my-dubcaps-mode-hook 'my/diminish-dubcaps) -#+end_src - -* Reading and Writing - -** Move correctly over camelCased words - -#+begin_src elisp - (subword-mode) -#+end_src - -** Understand the more common sentence with double space - -#+begin_src elisp - (setq sentence-end-double-space nil) -#+end_src - -** Join lines into paragraph - -#+begin_src elisp - (defun my/fill-or-unfill-paragraph (&optional unfill region) - "Fill paragraph (or REGION). With the prefix argument UNFILL, fill it instead." - (interactive (progn - (barf-if-buffer-read-only) - (list (if current-prefix-arg 'fill) t))) - (let ((fill-column (if unfill fill-column (point-max)))) - (fill-paragraph nil region))) - - (bind-key "M-q" 'my/fill-or-unfill-paragraph) -#+end_src - -#+begin_src elisp - (defun my/fill-or-unfill-all-paragraphs (&optional unfill) - "Fill or unfill all paragraphs in the current buffer. -With the prefix argument UNFILL, fill them instead." - (interactive (list (if current-prefix-arg 'fill))) - (let ((fill-column (if unfill fill-column (point-max)))) - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (fill-paragraph nil t) - (forward-paragraph))))) - -(bind-key "M-Q" 'my/fill-or-unfill-all-paragraphs) -#+end_src - -#+begin_src elisp - (remove-hook 'text-mode-hook #'turn-on-auto-fill) - (add-hook 'text-mode-hook 'turn-on-visual-line-mode) -#+end_src - -** Expand some words with auto-correct - - #+begin_src elisp :tangle no - (setq save-abbrevs 'silently) - (setq-default abbrev-mode t) - #+end_src - -** ediff - -#+begin_src elisp :tangle no - (setq ediff-window-setup-function 'ediff-setup-windows-plain) - (setq ediff-split-window-function 'split-window-horizontally) -#+end_src - -** tramp - -#+begin_src elisp :tangle no - (setq tramp-default-method "ssh" - tramp-backup-directory-alist backup-directory-alist - tramp-ssh-controlmaster-options "ssh") -#+end_src - -** Clean up space -#+begin_src elisp :tangle no - (bind-key "M-SPC" 'cycle-spacing) -#+end_src - -** Transform links into org links - -#+begin_src elisp :tangle no - (defun my/transform-html-links-to-org () - "Transform all HTML links in the current buffer into 'org-mode' links." - (interactive) - (goto-char (point-min)) - (while (re-search-forward "\\(.*?\\)" nil t) - (replace-match (org-make-link-string (match-string 1) (match-string 2))))) -#+end_src - -** Count words per minute -#+begin_src elisp :tangle no - (require 'org-clock) - (defun my/org-entry-wpm () - (interactive) - (save-restriction - (save-excursion - (org-narrow-to-subtree) - (goto-char (point-min)) - (let* ((words (count-words-region (point-min) (point-max))) - - (minutes (org-clock-sum-current-item)) - (wpm (/ words minutes))) - (message "WPM: %d (words: %d, minutes: %d)" wpm words minutes) - (kill-new (number-to-string wpm)) - ) - ) - ) - ) -#+end_src - -** Enable dict mode - #+begin_src elisp :tangle no - (setq dictionary-server "automatic") - #+end_src - -** Pick out passive voice and weasel words -#+begin_src elisp :tangle no - (use-package writegood-mode - :diminish writegood-mode - :config - (progn (add-hook 'text-mode-hook 'writegood-mode)) - ) -#+end_src - -** Org-babel docker -#+begin_src elisp :tangle no - (use-package ob-docker-build - :straight (ob-docker-build :type git :host github :repo "ifitzpat/ob-docker-build") - :defer t - :config - (add-to-list 'org-babel-load-languages '(docker-build . t)) - (org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages) - ) -#+end_src - -* Spelling and syntax - -** Spell checking - -This requires installation of hunspell -#+begin_src bash :tangle no - sudo apt install hunspell -#+end_src - -#+begin_src elisp - (use-package flyspell - :config (setq ispell-program-name "hunspell" - ispell-default-dictionary "en_US" - ) - :diminish (flyspell-mode . "φ") - :hook (text-mode . flyspell-mode) - :bind ( - ("M-" . flyspell-buffer) - ("" . flyspell-word) - ("C-;" . flyspell-auto-correct-previous-word) - ) - ) -#+end_src - -** Flyspell correct -#+begin_src elisp :tangle no - (use-package flyspell-correct - :after flyspell - :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-wrapper)) - ) -#+end_src - -** Flycheck - -Needs external checkers installed - -#+begin_src elisp - (use-package flycheck - :init (global-flycheck-mode) - :diminish (flycheck-mode . "") - :config - (add-hook 'after-init-hook #'global-flycheck-mode) - (setq flycheck-emacs-lisp-load-path 'inherit) - (setq flycheck-emacs-lisp-load-path (concat user-emacs-directory "straight/build")) - ) -#+end_src - -** Flycheck bash -#+begin_src bash :tangle no - sudo apt install devscripts -#+end_src - -#+begin_src elisp :tangle no - (use-package flycheck-checkbashisms - :config - (flycheck-checkbashisms-setup) - ) -#+end_src - -** Yaml -#+begin_src elisp :tangle no - (use-package yaml-mode - :config - (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) - (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode)) - ) -#+end_src - -** Docker -#+begin_src elisp :tangle no - (use-package docker-compose-mode) -#+end_src \ No newline at end of file diff --git a/projects/dotemacs/docs/emacs.org b/projects/dotemacs/docs/emacs.org deleted file mode 100644 index edbad52..0000000 --- a/projects/dotemacs/docs/emacs.org +++ /dev/null @@ -1,2138 +0,0 @@ -:PROPERTIES: -:ID: e67fd24d-6988-4c95-935e-c8604810212b -:END: -#+title: Emacs -#+property: header-args :tangle ~/.emacs.d/config.el - -* DONE early-init.el - -For straight.el to pick up before package.el - -#+begin_src elisp :tangle ~/.emacs.d/early-init.el - (setq package-enable-at-startup nil) -#+end_src - -* DONE [7/7] .emacs -:LOGBOOK: -- State "DONE" from "DONE" [2025-05-30 Fri 15:00] -- State "DONE" from "DONE" [2025-05-30 Fri 15:00] -- State "DONE" from "DONE" [2025-05-30 Fri 15:00] -- State "DONE" from "DONE" [2024-07-19 Fri 16:07] -- State "DONE" from "DONE" [2024-07-19 Fri 16:07] -- State "DONE" from "DONE" [2024-07-19 Fri 14:40] -- State "DONE" from "DONE" [2024-07-19 Fri 14:40] -- State "DONE" from "DONE" [2024-07-09 Tue 12:11] -- State "DONE" from "TODO" [2023-07-02 Sun 15:02] -:END: -**** DONE Front matter - -#+begin_src elisp :tangle ~/.emacs - ;;; .emacs --- Global settings - ;;; Commentary: - ;;; Code: - - ;; -*- lexical-binding: t; -*- -#+end_src - -**** DONE Garbage collector - increase threshold to 500 MB to ease startup - -#+begin_src elisp :tangle ~/.emacs - (setq gc-cons-threshold (* 500 1024 1024)) -#+end_src - -**** DONE [3/3] Package.el -***** CNCL List package archives and initialize them (package.el) - -#+begin_src elisp :tangle no - (require 'package) - (setq package-archives '( - ("gnu" . "https://elpa.gnu.org/packages/") - ("melpa" . "https://melpa.org/packages/") - ("nongnu" . "https://elpa.nongnu.org/nongnu/") - ) - ) - (setq package-install-upgrade-built-in t) - (setq package-check-signature "allow-unsigned") - (gnu-elpa-keyring-update) - (package-initialize) - (package-refresh-contents) -#+end_src - -***** CNCL Install use-package (package.el) - -#+begin_src elisp :tangle no - (unless (package-installed-p 'use-package) - (package-refresh-contents) - (package-install 'use-package) - ) - - (eval-when-compile (require 'use-package)) ;; allow byte-compile while using use-package -#+end_src - -***** CNCL Make sure Org is installed (package.el) - -#+begin_src elisp :tangle no - (unless (package-installed-p 'org) - (package-install 'org) - ) -#+end_src - -**** DONE [3/3] Straight.el -***** DONE Bootstrap Straight.el and install use-package - -#+begin_src elisp :tangle ~/.emacs - (setq straight-repository-branch "develop") ;; Using develop branch temporarily to fix the org-roam-dailies issue. From https://github.com/org-roam/org-roam/issues/2361#issuecomment-1671601796 - - (eval-and-compile - (defvar bootstrap-version) - (let ((bootstrap-file - (expand-file-name "straight/repos/straight.el/bootstrap.el" - (or (bound-and-true-p straight-base-dir) - user-emacs-directory))) - (bootstrap-version 7)) - (unless (file-exists-p bootstrap-file) - (with-current-buffer - (url-retrieve-synchronously "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" 'silent 'inhibit-cookies) - (goto-char (point-max)) - (eval-print-last-sexp))) - (load bootstrap-file nil 'nomessage)) - - (straight-use-package 'use-package) - ) -#+end_src - -#+RESULTS: -: t - -***** DONE Integrate use-package and straight -#+begin_src elisp :tangle ~/.emacs - (setq straight-use-package-by-default t) -#+end_src - -***** DONE Make sure Org is installed (straight.el) -[[https://github.com/org-roam/org-roam/issues/2361][Freezing Org@9.5.5]] fixes the issue with org-roam resulting in 'Wrong type argument: integer-or-marker-p, nil' - - #+begin_src elisp :tangle ~/.emacs - (unless (file-directory-p "~/.emacs.d/straight/versions") (make-directory (concat user-emacs-directory "straight/versions"))) -#+end_src - -#+begin_src elisp :tangle no - ; This goes in ~/.emacs.d/straight/versions/default.el - ;; (("org" . "8ef6205a560cd3a92f8c5f8fe34953b80121c2cb")) ; org@9.5.5 - ;; (("org" . "5890aca3d29e593640b728308096a052998355b1")) ; org@9.6.7 - :gamma -#+end_src - -#+begin_src elisp :tangle no - :tangle ~/.emacs.d/straight/versions/default.el - (("org-roam" . "d4c606078752ac7c1c8a492a042564f4294a23a6")) -#+end_src - -#+begin_src elisp :tangle ~/.emacs - (use-package org) -#+end_src - -**** DONE Tangle emacs.org - -#+begin_src elisp :tangle ~/.emacs - (require 'ob-tangle) - - ;; Specify the input file and the output directory - (defvar config-org-file "~/org/6_system/emacs.org") - (defvar config-el-file "~/.emacs.d/config.el") - (defvar org-use-property-inheritance t) - - ;; Tangle emacs.org into config.el and load config.el - (org-babel-tangle-file config-org-file) - (load-file config-el-file) -#+end_src - -**** DONE Garbage collector - decrease threshold to 5 MB -#+begin_src elisp :tangle ~/.emacs - (add-hook 'after-init-hook (lambda () (setq gc-cons-threshold (* 5 1024 1024)))) -#+end_src - -**** DONE End matter -#+begin_src elisp :tangle ~/.emacs - (provide '.emacs) - ;;; .emacs ends here -#+end_src - -* TODO [8/11] config.el and custom.el - -This Emacs configuration file is a fork of [[https://sriramkswamy.github.io/dotemacs/][Sri Ramkswamy's]] and [[https://pages.sachachua.com/.emacs.d/Sacha.html][Sacha Chusa's]] settings. I am sure there is much more to learn from them as I go. Worth revisiting. - -** DONE Front matter -#+begin_src elisp - ;;; Package --- Summary - ;;; Commentary: - ;;; Code: - - ;; -*- lexical-binding: t; -*- -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - ;;; Package --- Summary - ;;; Commentary: - ;;; Code: - - ;; -*- lexical-binding: t; -*- -#+end_src - -** DONE [9/9] Startup and general configurations - :LOGBOOK: - - State "DONE" from "DONE" [2024-07-20 Sat 11:55] - - State "DONE" from "TODO" [2024-07-19 Fri 15:10] - - State "DONE" from "TODO" [2024-07-10 Wed 10:45] - :END: - -*** DONE Run Emacs as a server - -#+begin_src elisp :tangle ~/.emacs.d/early-init.el - (require 'server) - (unless (server-running-p) (server-start)) - (defvar server-max-buffers 100) -#+end_src - -*** DONE Custom file - -#+begin_src elisp - (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) - (when (file-exists-p custom-file) (load custom-file)) -#+end_src - -*** DONE [[https://github.com/jwiegley/use-package][use-package]] -:PROPERTIES: -:CLOSED: [2023-01-22 Sun 09:36] -:END: -:LOGBOOK: -- State "DONE" from "CNCL" [2024-07-16 Tue 18:02] -:END: - -"A use-package declaration for simplifying your .emacs" - -#+begin_src elisp - (require 'use-package) -;; (require 'bind-key) - ;; (require 'use-package-ensure) - ;; (setq use-package-always-ensure t) ; Ensure use-package installs all packages by default. Use :ensure nil to override. - ;; (package-install-selected-packages) -#+end_src - -*** CNCL [[https://github.com/quelpa/quelpa][Quelpa]] - -#+begin_src elisp :tangle no - (unless (package-installed-p 'quelpa) - (with-temp-buffer - (url-insert-file-contents "https://raw.githubusercontent.com/quelpa/quelpa/master/quelpa.el") - (eval-buffer) - (quelpa-self-upgrade))) -#+end_src - -*** DONE System information -:LOGBOOK: -- State "DONE" from "TODO" [2023-08-28 Mon 18:46] -- State "DONE" from "DONE" [2023-08-28 Mon 18:43] -- State "DONE" from "NEXT" [2023-08-03 Thu 13:03] -:END: - -I took this from [[https://pages.sachachua.com/.emacs.d/Sacha.html][Sacha's settings]]. This allows for tweaking configuations according to platform. I intend to use more of this more as I develop Emacs configs across platforms. - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar my-laptop-p (equal (system-name) "lilitop")) - (defvar my-server-p (and (equal (system-name) "localhost") (equal user-login-name "root"))) - (defvar my-phone-p (not (null (getenv "ANDROID_ROOT"))) - "If non-nil, GNU Emacs is running on Termux.") - (when my-phone-p (defvar gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")) - (global-auto-revert-mode) ; simplifies syncing -#+end_src - -*** DONE Persistent history - -#+begin_src elisp - (savehist-mode) -#+end_src - -*** TODO Backup and versioning -#+begin_src emacs-lisp - (use-package magit - :ensure t - ) -#+end_src - -*** DONE Personal information - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (setq user-full-name "Amr Gharbeia") - (defvar email-address "amr@gharbeia.net") - (defvar calendar-latitude 39.0) - (defvar calendar-longitude -77.1) - (defvar calendar-location-name "Washington, DC") - (defvar calendar-time-zone -300) - (defvar calendar-standard-time-zone-name "EST") - (defvar calendar-daylight-time-zone-name "EDT") -#+end_src - -** TODO [2/3] Advanced Features -*** TODO [0/2] Text -**** TODO [0/1] Case -***** TODO Convert DOuble capitals to single capitals -:LOGBOOK: -- State "DONE" from "TODO" [2024-06-27 Thu 13:02] -- State "DONE" from "NEXT" [2023-08-09 Wed 13:51] -:END: - -#+begin_src elisp :tangle no - (defun my/dcaps-to-scaps () - "Convert word in DOuble CApitals to Single Capitals." - (interactive) - (and (= ?w (char-syntax (char-before))) - (save-excursion - (and (if (called-interactively-p) - (skip-syntax-backward "w") - (= -3 (skip-syntax-backward "w")) - ) - (let (case-fold-search) - (looking-at "\\b[[:upper:]]\\{2\\}[[:lower:]]") - ) - (capitalize-word 1) - ) - ) - ) - ) -#+end_src - -Then, let’s define a minor mode for it to be activated. - -#+begin_src elisp :tangle no - (define-minor-mode my-dubcaps-mode - "Toggle 'my-dubcaps-mode' and convert words in DOuble CApitals to Single Capitals as you type." - :init-value nil - :lighter (" DC") - (if my-dubcaps-mode - (add-hook 'post-self-insert-hook #'my/dcaps-to-scaps nil 'local) - (remove-hook 'post-self-insert-hook #'my/dcaps-to-scaps 'local))) -#+end_src - - Finally, let’s add a hook so that it is on for all the text files Emacs opens. - -#+begin_src elisp :tangle no - (add-hook 'text-mode-hook #'my-dubcaps-mode) -#+end_src - -Also, since we add a minor mode string (it might be useful sometimes), currently I prefer to diminish it. - -#+begin_src elisp :tangle no - (defun my/diminish-dubcaps () - (interactive) - (diminish 'my-dubcaps-mode "")) - (add-hook 'my-dubcaps-mode-hook 'my/diminish-dubcaps) -#+end_src - -**** TODO Text Mode [0/1] -***** TODO Outline Mode [0/1] -****** TODO [4/10] Org Mode - :LOGBOOK: - - State "DONE" from "TODO" [2024-02-28 Wed 16:49] - :END: - -******* DONE Basic setup - -#+begin_src elisp - (use-package org - :config - (defvar org-outline-path-complete-in-steps nil) - :bind (("C-c l" . org-store-link) - ("C-c a" . org-agenda) - ("C-c c" . org-capture) - :map org-mode-map) - ) -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/config.el - (defvar org-directory (concat (getenv "HOME") "/org/")) -#+end_src - -******* TODO [5/6] Looks - :LOGBOOK: - - State "DONE" from "TODO" [2024-07-19 Fri 15:58] - - State "DONE" from "TODO" [2024-07-16 Tue 21:51] - :END: - -******** DONE Basic - -#+begin_src elisp - (defvar org-pretty-entities t) ; Improve org mode looks - (defvar org-hide-emphasis-markers t) ; Hide emphasis markup - (defvar org-num-mode nil) - (defvar org-startup-folded 'shw2levels) -#+end_src - -******** DONE Indentation of headers - :LOGBOOK: - - State "DONE" from "TODO" [2025-06-22 Sun 13:44] - - State "DONE" from "TODO" [2024-07-16 Tue 21:27] - - State "DONE" from [2023-08-28 Mon 18:17] - :END: - -#+begin_src elisp - (defvar org-startup-indented t) ; Indent org heirarchy - (defvar org-adapt-indentation t) - (defvar org-hide-leading-stars t) ; Minimal Outline - (defvar org-odd-levels-only nil) -#+end_src - -******** DONE Indentation of lists -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:45] -- State "DONE" from [2024-02-11 Sun 13:15] -:END: - -#+begin_src elisp - (setq org-list-demote-modify-bullet t) -#+end_src - -******** DONE [[https://github.com/minad/org-modern][Org-modern]] -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:45] -- State "DONE" from "TODO" [2024-07-16 Tue 21:27] -- State "DONE" from "TODO" [2024-06-27 Thu 13:06] -:END: - -#+begin_src elisp - (use-package org-modern - :ensure t - :config - ;; Choose some fonts - (set-face-attribute 'default nil :family "sans-serif") - (set-face-attribute 'variable-pitch nil :family "sans-serif") - (set-face-attribute 'org-modern-symbol nil :family "Iosevka") - - ;; Edit settings - (defvar org-auto-align-tags nil) - (defvar org-tags-column 0) - (defvar org-catch-invisible-edits 'show-and-error) - (defvar org-special-ctrl-a/e t) - (defvar org-insert-heading-respect-content t) - - ;; Org styling, hide markup etc. - (defvar org-hide-emphasis-markers t) - (defvar org-pretty-entities t) - - ;; Agenda styling - (defvar org-agenda-tags-column 0) - (defvar org-agenda-block-separator ?─) - (defvar org-agenda-time-grid - '((daily today require-timed) - (800 1000 1200 1400 1600 1800 2000) - " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")) - (defvar org-agenda-current-time-string - "◀── now ─────────────────────────────────────────────────") - - ;; Ellipsis styling - (defvar org-ellipsis "…") - (set-face-attribute 'org-ellipsis nil :inherit 'default :box nil) - - (global-org-modern-mode) - ) - #+end_src - -******** DONE Highlight Sourcecode Syntax -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:46] -:END: - -#+begin_src elisp - (setq org-src-fontify-natively t) - (setq org-src-tab-acts-natively t) -#+end_src - -******** TODO Images -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 15:34] -:END: - -#+begin_src elisp - (setq org-startup-with-inline-images t) - (setq org-image-actual-width '(300)) -#+end_src - -******* TODO [4/5] Agenda -******** DONE Basic agenda settings -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:57] -- State "DONE" from "TODO" [2024-07-19 Fri 15:52] -:END: - -#+begin_src elisp - (setq org-deadline-warning-days 7) - (setq org-agenda-skip-additional-timestamps-same-entry t) - (setq org-agenda-span 'fortnight) - (setq org-agenda-tags-column 'auto) - (setq org-agenda-skip-scheduled-if-deadline-is-shown t) -#+end_src - -******** DONE Agenda files -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:57] -:END: - -#+begin_src elisp - (setq org-agenda-files (list - (concat org-directory "/0_inbox/inbox.org") - (concat org-directory "/0_inbox/org-gtd-tasks.org") - ) - ) -#+end_src - -******** DONE [[https://github.com/alphapapa/org-super-agenda][Better agenda views]] -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:58] -:END: - -#+begin_src elisp :tangle no - (use-package org-super-agenda) -#+end_src - -******** TODO [4/6] To-do -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 15:53] -:END: - -********* DONE Basic todo -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 15:53] -:END: - -#+begin_src elisp - (setq org-todo-keywords - '( - (sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") - (sequence "WAIT(w@/!)" "|" "CNCL(c@)") - ) - ) - - (setq org-todo-keyword-faces - '( - ("TODO" :foreground "red" :weight bold) - ("NEXT" :foreground "red" :weight bold) - ("WAIT" :foreground "yellow" :weight bold) - ("DONE" :foreground "green" :weight bold) - ("CNCL" :foreground "blue" :weight bold) - ) - ) - - (setq org-enforce-todo-dependencies t) - (setq org-tags-exclude-from-inheritance '("crypt" "!private")) -#+end_src - -********* DONE Switch entry to 'DONE' when all subentries are done - -#+begin_src elisp - (defun org-summary-todo (n-done n-not-done) - "Switch entry to 'DONE' when all subentries are done, to 'TODO' otherwise. - Uses N-DONE and N-NOT-DONE" - (let (org-log-done org-log-states) ; turn off logging - (org-todo (if (= n-not-done 0) "DONE" "TODO") - ) - ) - ) - - (add-hook 'org-after-todo-statistics-hook #'org-summary-todo) -#+end_src - -********* DONE [[https://github.com/Trevoke/org-gtd.el][Getting Things Done (GTD)]] -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:58] -:END: - -I am now relying on [[https://github.com/Trevoke/org-gtd.el][org-gtd]] to create a GTD workflow: -1. everything comes into ~/org/inbox.org -2. Items are clarified with textual context, then with including: - - a horizon - - tags - - Items are then goes into one of the following buckets: - - - a single action - - a project - - an action within an existing project - - a sometime/maybe - - a habit - - a knowledge/reference item - - discarded as trash - -3. The above categories are all now headers in ~/org-gtd-tasks.org, but should each have their own file in the future. -4. All actions are states - - - TODO (instead of NEXT. Will decide if I will use next per the orthdoxy) - - WAIT - - DONE - - CNCL - - I also used to have MAYBE and STARTED tags. Maybe to avoid having a different pool for it (GTD is old, relies on paper and is therefore sequential. Computers solved this problem). STARTED was the tag for the things I am doing, because my NEXT (TODO) list is huge at the moment, mainly because of decades of backlog. -5. Reference is ~/org/library.org. I am beginning to think I might split this further as it grows. My main ~/library is massive, obviously. -6. Calendar is still half connected to org-mode and GTD. Need to find a way to connect across devices. [[https://github.com/dengste/org-caldav][org-caldav]] looks promising. - -#+begin_src elisp - (use-package org-gtd - :defer t - :init (setq org-gtd-update-ack "3.0.0") - :after org - :config - ;; Keeping these two settings on instead of enabling (org-gtd-mode) until this issue is resolved https://github.om/Trevoke/org-gtd.el/issues/198 - (setq org-edna-use-inheritance t) - (org-edna-mode) - ;; (org-gtd-mode) - :bind ( - ("C-c d c" . org-gtd-capture) - ("C-c d e" . org-gtd-engage) - ("C-c d p" . org-gtd-process-inbox) - :map org-gtd-clarify-map - ("C-c c" . org-gtd-organize) - ) - ) -#+end_src - -#+begin_src elisp - (defvar org-gtd-directory org-directory) - (defvar org-gtd-organize-hooks '(org-gtd-set-area-of-focus org-set-tags-command)) - (defvar org-gtd-organize-hooks '(org-gtd-set-area-of-focus)) - (defvar org-gtd-areas-of-focus '( - "Atoms" - "Bits" - "Cells" - "Flags" - "Business" - "Wealth" - "Learning" - "Skills" - "Privacy" - "Archive" - "Library" - "Writing" - "Health" - "Home" - "Family" - "Social" - "Egypt" - ) - ) - (defvar org-gtd-clarify-show-horizons 'right) -#+end_src - -********* DONE Logging - -#+begin_src elisp - (setq org-log-into-drawer "LOGBOOK") -#+end_src - -********* TODO Clocking work in drawer -:LOGBOOK: -- State "DONE" from "NEXT" [2023-08-03 Thu 13:16] -:END: - -#+begin_src elisp :tangle no - (setq org-clock-into-drawer t) -#+end_src - -********* TODO Habits -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-16 Tue 21:36] -- State "DONE" from "TODO" [2023-07-31 Mon 14:33] -:END: - -#+begin_src elisp :tangle no - (setq org-habit-graph-column 80) - (setq org-habit-show-habits-only-for-today nil) -#+end_src - -******** DONE [3/3] Reifle -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:59] -:END: -*********** DONE org-refile targets -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:59] -- State "DONE" from "TODO" [2024-07-16 Tue 21:38] -- State "DONE" from "TODO" [2023-07-07 Fri 16:51] -:END: - -Allow refiling to agenda files, nine headers deep, either in current buffer or in agenda files. - -#+begin_src elisp - (setq org-refile-targets '((nil :maxlevel . 9) - (org-agenda-files :maxlevel . 9) - ) - ) -#+end_src - -*********** DONE Set type of refile targets completion -:LOGBOOK: -- State "DONE" from "TODO" [2025-06-22 Sun 13:59] -- State "DONE" from "TODO" [2023-07-07 Fri 16:50] -:END: - - This setting is related to the completion of refile targets. If set to `t`, you build the path in steps by selecting one note at a time. This might be useful with deep hierarchies, but can be slow. When set to `nil`, you can enter the path directly, and Org-Mode uses a Helm-like interface to auto-complete the path. This can be faster, but possibly more difficult with deep hierarchies. - -#+begin_src elisp - (setq org-outline-path-complete-in-steps nil) -#+end_src - -*********** DONE Allow refiling to new parents created on the go after confirmation -:LOGBOOK: -- State "DONE" from "TODO" [2023-07-07 Fri 16:50] -:END: - -#+begin_src elisp - (setq org-refile-allow-creating-parent-nodes 'confirm) -#+end_src - -******* TODO [1/2] Capture -:LOGBOOK: -- State "DONE" from "DONE" [2024-07-19 Fri 15:50] -- State "DONE" from "DONE" [2023-08-17 Thu 14:06] -- State "DONE" from "DONE" [2023-08-11 Fri 14:16] -- State "DONE" from "TODO" [2023-07-05 Wed 16:51] -:END: - -#+begin_src elisp :tangle ~/.emacs.d/config.el - (defvar org-default-notes-file (concat org-directory "/0_inbox/inbox.org")) -#+end_src - -******** DONE [4/4] Org-protocol -:LOGBOOK: -- State "DONE" from "DONE" [2024-07-19 Fri 15:49] -- State "DONE" from "TODO" [2023-07-05 Wed 13:21] -:END: - -********* DONE Linux configuration -For GNU/Linux setup, put this in ~/.local/share/applications/org-protocol.desktop -or in /usr/share/applications to set up system-wide. - -#+begin_src bash :tangle no -[Desktop Entry] -Name=org-protocol -Comment=Intercept calls from emacsclient to trigger custom actions -Categories=Other; -Keywords=org-protocol; -Icon=emacs -Type=Application -Exec=emacsclient -- %u -Terminal=false -StartupWMClass=Emacs -MimeType=x-scheme-handler/org-protocol; -#+end_src - -then update the cache database of MIME types handled by desktop files: - -#+begin_src bash :tangle no -update-desktop-database ~/.local/share/applications/ -#+end_src - -********* DONE Basic configuration - -#+begin_src elisp - (require 'org-protocol) - (setq org-protocol-default-buffer-for-file-links "*scratch*") ; fixes 'no buffers remain to edit error for org-protocol capturer - #+end_src - -********* DONE Org-protocol templates - -And finally, here are the capture templates for org-protocol captures. - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar org-capture-templates '( - ("p" "Protocol" - entry - (file "0_inbox/inbox.org") - "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?" - ) - ("L" "Protocol Link" - entry - (file "0_inbox/inbox.org") - "* %? [[%:link][%:description]]\n:PROPERTIES:\n:TITLE: %:description\n:URI: %:link\n:CREATED: %U\n:END:" - :prepend nil - :empty-lines 1 - :created t - :kill-buffer t - ) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-protocol-default-template-key "L") -#+end_src - -********* DONE Convert Orgzly captures to org-protocol captures standard -:LOGBOOK: -- State "DONE" from "TODO" [2023-07-10 Mon 11:52] -:END: - -This will create clickable titles, create "TITLE", " URL", and "CREATED" properties - -#+begin_src elisp - (defun my/org-convert-orgzly-to-org-protocol () - "Reformat Orgzly bookmark at point to org-protocol bookmark." - (interactive) - (when (org-at-heading-p) - (let ((headline (nth 4 (org-heading-components)))) - ;; Find and store the link. Delete the link line. - (search-forward-regexp "^https?://\\S-*" nil t) - (let ((link (match-string 0))) - (beginning-of-line) - (kill-line) - ;; Delete any trailing blank spaces - (org-back-to-heading) - (end-of-line) - (when (not (org-on-heading-p)) - (delete-char 1) - ) - ;; Set new headline - (goto-char (org-entry-beginning-position)) - (org-edit-headline (format "[[%s][%s]]" link headline)) - ;; Set new properties - (org-set-property "TITLE" headline) - (org-set-property "URI" link) - (message "Reformatted Orgzly bookmark at point to org-protocol bookmark") - ) - ) - ) - ) -#+end_src - -******** TODO org-roam-capture templates -:LOGBOOK: -- State "DONE" from "TODO" [2023-08-19 Sat 18:17] -:END: - -#+begin_src elisp - (setq org-roam-capture-templates - '( - ("L" "link" plain - (function org-roam--capture-get-point) - "%?" - :file-name "web/%<%Y-%m-%dT%H%M%S>.org" - :head "#+TITLE: ${title}\n#+CREATED: %<%Y-%m-%dT%H%M%S>" - :immediate-finish t - :unnarrowed t - ) - - ("h" "hugo post" plain - "%?" - :target (file+head "posts/${slug}.org" - "#+TITLE: ${title}\n#+DATE: %U\n#+HUGO_BASE_DIR: ~/gharbeia.net\n#+HUGO_SECTION: ./posts\n#+HUGO_AUTO_SET_LASTMOD: t\n#+HUGO_TAGS: article\n#+HUGO_DRAFT: true\n") - :immediate-finish t - :unnarrowed t - ) - - ("p" "person" plain - "%?" - :if-new (file+head "people/${slug}.org" - "#+TITLE: ${title}") - :immediate-finish t - :unnarrowed t - ) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-roam-dailies-capture-templates - '( - ("d" "daily" plain - "" - :target ("file+heaed %<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n\n") - :immediate-finish t - ) - ) - ) -#+end_src - -******* TODO [1/5] Org-roam -******** TODO Basic org-roam setup -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-16 Tue 21:30] -- State "DONE" from "TODO" [2023-07-05 Wed 17:11] -:END: - -#+begin_src elisp -(use-package org-roam - :init (setq org-roam-v2-ack t) ;; Acknowledge V2 upgrade - :after org - :config - (org-roam-db-autosync-enable) - (require 'org-roam-dailies) - :bind ( - ("C-c n f" . org-roam-node-find) - ("C-c n g" . org-roam-graph) - ("C-c n r" . org-roam-node-random) - ("C-c n h" . org-roam-node-convert-headline) - ("C-c n i" . org-roam-node-insert) - ("C-c n o" . org-id-get-create) - ("C-c n t" . org-roam-tag-add) - ("C-c n a" . org-roam-alias-add) - ("C-c n l" . org-roam-buffer-display-dedicated) - ) - ) - #+end_src - -#+begin_src elisp - (use-package org-roam -; :straight (:files (:defaults "extensions/*")) - :init (setq org-roam-v2-ack t) ;; Acknowledge V2 upgrade - :after org - :config - (org-roam-db-autosync-enable) - (require 'org-roam-dailies) - (setq org-roam-mode-sections - (list #'org-roam-backlinks-section - #'org-roam-reflinks-section - #'org-roam-unlinked-references-section - ) - ) - (add-to-list 'display-buffer-alist - '("\\*org-roam\\*" - (display-buffer-in-side-window) - (side . right) - (slot . 0) - (window-width . 0.33) - (window-parameters . ((no-other-window . t) - (no-delete-other-windows . t))))) - :bind ( - ("C-c n f" . org-roam-node-find) - ("C-c n g" . org-roam-graph) - ("C-c n r" . org-roam-node-random) - ("C-c n h" . org-roam-node-convert-headline) - ("C-c n i" . org-roam-node-insert) - ("C-c n o" . org-id-get-create) - ("C-c n t" . org-roam-tag-add) - ("C-c n a" . org-roam-alias-add) - ("C-c n l" . org-roam-buffer-display-dedicated) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-roam-directory (concat org-directory "/1_thinking")) - (setq org-roam-dailies-directory (concat org-directory "/0_inbox/daily")) -#+end_src - -#+begin_src elisp :tangle no - (use-package sqlite3) - (require 'sqlite3) -#+end_src - -******** DONE Include subdirectories in org-roam -:PROPERTIES: - :CREATED: [2023-07-06 Thu 03:18] - :END: -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 16:45] -- State "DONE" from "TODO" [2023-07-06 Thu 12:54] -:END: - -#+begin_src elisp - (setq org-roam-file-exclude-regexp "^[.][.]?/") -#+end_src - -******** TODO Configure what display in org-roam-buffer -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 16:47] -:END: - -Note that computing unlinked references may be slow, and has not been added in by default. - - #+begin_src elisp :tangle no - (setq org-roam-mode-sections - (list #'org-roam-backlinks-section - #'org-roam-reflinks-section - #'org-roam-unlinked-references-section - ) - ) -#+end_src - -******** TODO [[https://emacs.stackexchange.com/questions/61290/how-to-see-files-of-a-particular-tag-in-org-roam][Filter org-roam nodes find by tag]] -:PROPERTIES: - :TITLE: org mode - How to see files of a particular tag in org-roam? - Emacs Stack Exchange - :URI: https://emacs.stackexchange.com/questions/61290/how-to-see-files-of-a-particular-tag-in-org-roam - :CREATED: [2023-08-19 Sat 12:47] - :END: -:LOGBOOK: -- State "DONE" from "TODO" [2023-08-19 Sat 18:13] -:END: - -#+begin_src elisp :tangle no - (defun my/org-roam-node-has-tag (node tag) - "Filter function to check if the given NODE has the specified TAG." - (member tag (org-roam-node-tags node)) - ) - - (defun my/org-roam-node-find-by-tag () - "Find and open an Org-roam node based on a specified tag." - (interactive) - (let ((tag (read-string "Enter tag: "))) - (org-roam-node-find nil nil (lambda (node) (my/org-roam-node-has-tag node tag)))) - ) -#+end_src - -******** TODO [0/3] Move org header to org-roam-daily -********* TODO OpenAI -#+begin_src elisp :tangle no - (defun my/org-move-entry-to-daily-notes () - "Move the current org-mode headline to the daily notes file based on its :CREATED: property." - (interactive) - (let* - ( - (created-prop (org-entry-get nil "CREATED")) - (created-date (when created-prop - (org-parse-time-string created-prop))) - (year (nth 5 created-date)) ; Extract year (6th element) - (month (nth 4 created-date)) ; Extract month (5th element) - (day (nth 3 created-date)) ; Extract day (4th element) - (target-date (format "%04d-%02d-%02d" year month day)) ; Format date string - (target-file (org-roam-dailies-goto target-date)) - ) - (when target-file - (org-cut-subtree) - (find-file target-file) - (goto-char (point-max)) - (unless (bolp) (newline)) - (org-paste-subtree) - ) - ) - ) -#+end_src - -#+begin_src elisp :tangle no - (defun my/org-move-entry-to-daily-notes () - "Move the current org-mode headline to the daily notes file based on its :CREATED: property." - (interactive) - (let* - ( - (created-prop (org-entry-get nil "CREATED")) - (created-date (when created-prop - (org-parse-time-string created-prop))) - (year (nth 5 created-date)) ; Extract year (6th element) - (month (nth 4 created-date)) ; Extract month (5th element) - (day (nth 3 created-date)) ; Extract day (4th element) - (target-date (format "%04d-%02d-%02d" year month day)) ; Format date string - ;(target-date "2024-01-01") - (target-file (concat org-roam-dailies-directory "/" target-date ".org")) - (find-file target-file) - ) - ) - (when target-file - (org-cut-subtree) - (find-file target-file) - (org-id-get-create) - ;; #+title: target-date - (goto-char (point-max)) - (unless (bolp) (newline)) - (org-paste-subtree) - ) - ) -#+end_src - -********* TODO [[https://git.ikl.sh/132ikl/dotfiles/src/branch/main/.doom.d/lisp/refile.el][Modified rose Refile to org-roam-dailies]] - -Arrived to from [[https://www.reddit.com/r/OrgRoam/comments/ruc59q/tips_for_refiling_into_org_roam_dailies/][this conversation]] - -Here's a breakdown of the functions and their roles: - -0. org-roam-dailies--capture - -#+begin_src elisp :tangle no - (defun org-roam-dailies--capture (time &optional goto keys) - "Capture an entry in a daily-note for TIME, creating it if necessary. -When GOTO is non-nil, go the note without creating an entry. - -ELisp programs can set KEYS to a string associated with a template. -In this case, interactive selection will be bypassed." - (let ((org-roam-directory (expand-file-name org-roam-dailies-directory org-roam-directory)) - (org-roam-dailies-directory "./")) - (org-roam-capture- :goto (when goto '(4)) - :keys keys - :node (org-roam-node-create) - :templates org-roam-dailies-capture-templates - :props (list :override-default-time time))) - (when goto (run-hooks 'org-roam-dailies-find-file-hook))) -#+end_src - - -1. `my/refile`: This function refiles a single headline by finding the file, reverting the buffer, and replacing fuzzy links with roam: links. - -#+begin_src elisp :tangle no - ;;; lisp/refile.el -*- lexical-binding: t; -*- - (defun my/refile () - "Refiles a headline (and its subtree) with a CREATED property to its corresponding daily." - (interactive) - (revert-buffer t t) - ;; replace fuzzy links with roam: links (exclude non-fuzzy links, ie. links with `:') - (while (re-search-forward "\\[\\[\\([^:]+?\\)\\]\\]" nil t) - (replace-match "[[roam:\\1]]" nil nil)) - ; (org-roam-link-replace-all) ;; TODO create blank page if non-existent - ;; remove blank lines because i think they are ugly - (while (re-search-forward "\n+" nil t) - (replace-match "\n" nil nil)) - (let ((entries (org-map-entries #'my/refile--inbox-headline nil 'file))) - (message (format "Refiled %d headline(s)" (seq-count #'identity entries))) - ) - ) -#+end_src - -2. `my/refile--inbox-headline`: This function refiles a headline at the current point by deleting the CREATED property and capturing the headline using org-capture. - -#+begin_src elisp :tangle no - (defun my/refile--inbox-headline () - "Refile headline at POINT." - (setq org-map-continue-from (point)) - (if-let (capture-template (my/refile--get-template)) - (my/refile--capture capture-template) - (my/refile--to-node))) -#+end_src - -3. `my/refile--capture`: This function runs org-capture on an inbox heading and inserts the result into the buffer. - -#+begin_src elisp :tangle no - (defun my/refile--capture (capture-template) - "Run 'org-capture' on inbox heading using CAPTURE-TEMPLATE." - ;; (org-entry-delete nil "CREATED") - (let ((keys (car capture-template)) - (heading (cdr capture-template)) - (entry (org-no-properties (org-get-entry)))) - (org-capture nil keys) - (insert heading "\n" entry)) - (org-capture-finalize) - (org-cut-subtree) - ) -#+end_src - -4. `my/refile--get-template`: This function parses the capture template prefix from the heading and returns a cons cell containing the keys and heading. - -#+begin_src elisp :tangle no - (defun my/refile--get-template () - "Parse capture template prefix from heading." - (when-let* ((raw-heading (org-no-properties (org-get-heading))) - (match (string-match "@\\(\\w+\\) \\(.+\\)$" raw-heading)) - (keys (match-string-no-properties 1 raw-heading)) - (heading (match-string-no-properties 2 raw-heading))) - (cons keys heading)) - ) -#+end_src - -5. `my/refile--to-node`: This function refiles a headline to an Org-roam node. - -#+begin_src elisp :tangle no - (defun my/refile--to-node () - "Refiles non-capture headings to org-roam node." - (if-let ((to (+org/entry-get-delete "TO"))) - (my/refile--org-roam-node (org-roam-node-from-title-or-alias to)) - (my/refile--to-daily))) -#+end_src - -6. `my/refile--to-daily`: This function refiles a headline to a daily node based on its CREATED property. - -#+begin_src elisp :tangle no - (defun my/refile--to-daily () - "Refile headline at POINT to the associated daily node based on its `CREATED' property." - (when-let* ((created (org-entry-get nil "CREATED")) - (time (org-time-string-to-time created)) - (daily-node (my/refile--get-daily-node time))) - (org-entry-delete nil "CREATED") - (my/refile--org-roam-node daily-node))) -#+end_src - -7. `my/refile--get-daily-node`: This function returns the Org-roam node for a given time. - -#+begin_src elisp :tangle no - (defun my/refile--get-daily-node (time) - "Return org-roam node for TIME." - (save-window-excursion - (org-roam-dailies--capture time t) - (org-roam-node-at-point))) -#+end_src - -8. `my/refile--org-roam-node`: This function refiles a node to an Org-roam node. - - The `my/refile--org-roam-node` function is quite long and complex, but it seems to be responsible for refiling a node to an Org-roam node. It takes several arguments, including the node to refile, and uses several org-roam functions to perform the refiling. - -#+begin_src elisp :tangle no - (defun my/refile--org-roam-node (node) - "Refile NODE at point to an Org-roam node. - If region is active, then use it instead of the node at point. - Implementation of `org-roam-refile' from org-roam PR #2388." - (interactive - (list (org-roam-node-read nil nil nil 'require-match))) - (let* ((regionp (org-region-active-p)) - (region-start (and regionp (region-beginning))) - (region-end (and regionp (region-end))) - (file (org-roam-node-file node)) - (nbuf (or (find-buffer-visiting file) - (find-file-noselect file))) - level reversed) - (if (equal (org-roam-node-at-point) node) - (user-error "Target is the same as current node") - (if regionp - (progn - (org-kill-new (buffer-substring region-start region-end)) - (org-save-markers-in-region region-start region-end)) - (progn - (if (org-before-first-heading-p) - (org-roam-demote-entire-buffer)) - (org-copy-subtree 1 nil t))) - (with-current-buffer nbuf - (org-with-wide-buffer - (goto-char (org-roam-node-point node)) - (setq level (org-get-valid-level (funcall outline-level) 1) - reversed (org-notes-order-reversed-p)) - (goto-char - (if reversed - (or (outline-next-heading) (point-max)) - (or (save-excursion (org-get-next-sibling)) - (org-end-of-subtree t t) - (point-max)))) - (unless (bolp) (newline)) - (org-paste-subtree level nil nil t) - (and org-auto-align-tags - (let ((org-loop-over-headlines-in-active-region nil)) - (org-align-tags))) - (when (fboundp 'deactivate-mark) (deactivate-mark)))) - (if regionp - (delete-region (point) (+ (point) (- region-end region-start))) - (org-preserve-local-variables - (delete-region - (and (org-back-to-heading t) (point)) - (min (1+ (buffer-size)) (org-end-of-subtree t t) (point))))) - ;; If the buffer end-up empty after the refile, kill it and delete its - ;; associated file. - (when (eq (buffer-size) 0) - (if (buffer-file-name) - (delete-file (buffer-file-name))) - (set-buffer-modified-p nil) - ;; If this was done during capture, abort the capture process. - (when (and org-capture-mode - (buffer-base-buffer (current-buffer))) - (org-capture-kill)) - (kill-buffer (current-buffer)))))) -#+end_src - -#+begin_src elisp :tangle no - (defun +org/entry-get-delete (entry) - (prog1 (org-entry-get nil entry) (org-entry-delete nil entry))) -#+end_src - -********* TODO [[https://systemcrafters.net/build-a-second-brain-in-emacs/5-org-roam-hacks/#automatically-copy-or-move-completed-tasks-to-dailies][Automatically copy (or move) completed tasks to dailies]] -#+begin_src elisp :tangle no - (defun my/org-roam-copy-todo-to-today () - (interactive) - (let ((org-refile-keep t) ;; Set this to nil to delete the original! - (org-roam-dailies-capture-templates - '(("t" "tasks" entry "%?" - :if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n" ("Tasks"))))) - (org-after-refile-insert-hook #'save-buffer) - today-file - pos) - (save-window-excursion - (org-roam-dailies--capture (current-time) t) - (setq today-file (buffer-file-name)) - (setq pos (point))) - - ;; Only refile if the target file is different than the current file - (unless (equal (file-truename today-file) - (file-truename (buffer-file-name))) - (org-refile nil nil (list "Tasks" today-file nil pos))))) - - (add-to-list 'org-after-todo-state-change-hook - (lambda () - (when (equal org-state "DONE") - (my/org-roam-copy-todo-to-today)))) -#+end_src - -******* DONE Exporting [1/1] -:LOGBOOK: -- State "DONE" from "TODO" [2025-03-24 Mon 17:31] -:END: - -From [[https://sriramkswamy.github.io/dotemacs/#orgheadline29][Sriramkswamy]]: - -#+BEGIN_QUOTE -Org has a powerful exporting feature. Let’s select the various formats to export and also mention how exactly we need it to export to LaTeX with syntax highlighting. I have also taken a good looking CSS configuration from [[http://gongzhitaao.org/orgcss/][Zhitao Gong]] and I use it for exporting by putting it [[https://sriramkswamy.github.io/dotemacs/org.css][in the same folder as my org file]] and adding #+HTML_HEAD: to the top of my org file. -#+END_QUOTE - -#+begin_src elisp :tangle no - (setq org-export-with-smart-quotes t) - (setq org-export-backends '(beamer html latex md)) -#+end_src - -******** DONE Export to EPUB -:LOGBOOK: -- State "DONE" from [2025-03-24 Mon 17:31] -:END: - -#+begin_src elisp :tangle no - (use-package ox-epub - ) - #+end_src - -******* DONE org-attach - -#+begin_src elisp :tangle ~/.emacs.d/config.el - (defvar org-attach-id-dir (concat org-directory "/library")) -#+end_src - -******* DONE Enable shell scripting support in org-babel - -#+begin_src elisp - (defvar org-babel-do-load-languages 'org-babel-load-languages '((shell . t))) -#+end_src - -******* TODO [[https://github.com/rexim/org-cliplink][Insert org-mode links from clipboard]] -:PROPERTIES: -:TITLE: GitHub - rexim/org-cliplink: Insert org-mode links from clipboard -:URI: https://github.com/rexim/org-cliplink -:CREATED: [2023-02-13 Mon 12:45] -:END: -:LOGBOOK: -- State "DONE" from "TODO" [2023-08-18 Fri 13:10] -:END: - -#+begin_src elisp :tangle no - (use-package org-cliplink - :bind - (("C-x p i" . org-cliplink)) - ) -#+end_src - -******* TODO Deft - -#+begin_src elisp :tangle no - (use-package deft - :commands (deft) - :init - (defvar deft-extensions '("org")) - (defvar deft-recursive nil) - (defvar deft-use-filename-as-title t) - :config - (defvar deft-directory org-directory) - (defvar deft-recursive t) - (defvar deft-strip-summary-regexp ":PROPERTIES:\n\\(.+\n\\)+:END:\n") - (defvar deft-use-filename-as-title t) - :bind ("C-c n d" . deft) - ) -#+end_src - -*** DONE [3/3] Shell -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 15:34] -- State "DONE" from "TODO" [2024-07-09 Tue 17:11] -:END: -***** DONE Bash completion -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-16 Tue 20:35] -- State "DONE" from "TODO" [2023-08-18 Fri 13:02] -:END: - -#+begin_src elisp - (use-package bash-completion - :config - (require 'bash-completion) - (bash-completion-setup) - ) -#+end_src - -#+begin_src elisp -(defvar shell-dynamic-complete-functions t) -#+end_src - -***** DONE [3/3] Eshell -****** CNCL [[https://github.com/szermatt/emacs-bash-completion][Add programmable bash completion to Emacs shell-mode]] -:PROPERTIES: -:TITLE: GitHub - szermatt/emacs-bash-completion: Add programmable bash completion to Emacs shell-mode -:URI: https://github.com/szermatt/emacs-bash-completion -:CREATED: [2023-01-27 Fri 21:00] -:END: -:LOGBOOK: -- State "DONE" from "TODO" [2024-02-28 Wed 16:30] -:END: - -#+begin_src elisp :tangle no - (require 'bash-completion) - (add-hook 'eshell-mode-hook - (lambda () - (add-hook 'completion-at-point-functions - 'bash-completion-capf-nonexclusive nil t - ) - ) - ) -#+end_src - -****** CNCL Use colors in eshell - :LOGBOOK: - - State "DONE" from "TODO" [2023-08-28 Mon 18:56] - :END: - - -#+begin_src elisp :tangle no - (use-package xterm-color - :commands (xterm-color-filter) - ) - - (use-package eshell - :after xterm-color - :config - (define-key eshell-hist-mode-map (kbd "M-r") #'consult-history) - (add-hook 'eshell-mode-hook - (lambda () - (setenv "TERM" "xterm-256color"))) - (add-hook 'eshell-before-prompt-hook (setq xterm-color-preserve-properties t)) - (add-to-list 'eshell-preoutput-filter-functions 'xterm-color-filter) - (setq eshell-output-filter-functions - (remove 'eshell-handle-ansi-color eshell-output-filter-functions) - ) - ) -#+end_src - -****** CNCL Eshell completion - -#+begin_src elisp :tangle no - (add-hook 'eshell-mode-hook - (lambda () - (add-hook 'completion-at-point-functions - 'bash-completion-capf-nonexclusive nil t))) -#+end_src - -***** CNCL Emulate A Terminal (EAT) -:LOGBOOK: -- State "CNCL" from "TODO" [2024-04-01 Mon 15:52] \\ - Moved to shell and eshell. Eat is not in repositories currently. -- State "DONE" from [2023-08-30 Wed 20:43] -:END: - -#+begin_src elisp :tangle no - (use-package eat - :config - ;; For `eat-eshell-mode'. - (add-hook 'eshell-load-hook #'eat-eshell-mode) - - ;; For `eat-eshell-visual-command-mode'. - (add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode) - ) -#+end_src - -*** DONE [2/2] Saving Emacs Sessions - :LOGBOOK: - - State "DONE" from "TODO" [2024-07-19 Fri 15:08] - - State "DONE" from "DONE" [2024-02-28 Wed 16:26] - :END: -**** DONE Close frame when done -:LOGBOOK: -- State "DONE" from "NEXT" [2023-08-03 Thu 13:21] -:END: - -When a server buffer is done, the current window (frame) should be closed. This is useful in scenarios where Emacs is used as an external editor (for instance, from a version control system). When you're done editing, the frame closes automatically. If this is the only frame, Emacs will exit. - -#+begin_src elisp - (add-hook 'server-done-hook (lambda () (delete-frame))) -#+end_src - -**** DONE Save desktop session - -#+begin_src elisp - (desktop-save-mode t) -#+end_src - -** TODO [8/21] Reading and Writing -:LOGBOOK: -- State "DONE" from "TODO" [2023-07-06 Thu 12:32] -:END: - -*** DONE Move correctly over camelCased words -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 16:04] -:END: - -#+begin_src elisp - (subword-mode) -#+end_src - -*** DONE Understand the more common sentence with double space -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 16:04] -:END: - -#+begin_src elisp - (setq sentence-end-double-space nil) -#+end_src - -*** DONE [[https://pages.sachachua.com/.emacs.d/Sacha.html#orgcb6a264][Join lines into paragraph]] -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 16:03] -- State "DONE" from "TODO" [2023-07-06 Thu 12:31] -:END: - -#+begin_src elisp - (defun my/fill-or-unfill-paragraph (&optional unfill region) - "Fill paragraph (or REGION). With the prefix argument UNFILL, fill it instead." - (interactive (progn - (barf-if-buffer-read-only) - (list (if current-prefix-arg 'fill) t))) - (let ((fill-column (if unfill fill-column (point-max)))) - (fill-paragraph nil region))) - - (bind-key "M-q" 'my/fill-or-unfill-paragraph) -#+end_src - -#+begin_src elisp - (defun my/fill-or-unfill-all-paragraphs (&optional unfill) - "Fill or unfill all paragraphs in the current buffer. -With the prefix argument UNFILL, fill them instead." - (interactive (list (if current-prefix-arg 'fill))) - (let ((fill-column (if unfill fill-column (point-max)))) - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (fill-paragraph nil t) - (forward-paragraph))))) - -(bind-key "M-Q" 'my/fill-or-unfill-all-paragraphs) -#+end_src - -#+begin_src elisp - (remove-hook 'text-mode-hook #'turn-on-auto-fill) - (add-hook 'text-mode-hook 'turn-on-visual-line-mode) -#+end_src - -*** TODO Expand some words with auto-correct - - #+begin_src elisp :tangle no - (setq save-abbrevs 'silently) - (setq-default abbrev-mode t) - #+end_src - -*** TODO ediff - -#+begin_src elisp :tangle no - (setq ediff-window-setup-function 'ediff-setup-windows-plain) - (setq ediff-split-window-function 'split-window-horizontally) -#+end_src - -*** TODO tramp - -#+begin_src elisp :tangle no - (setq tramp-default-method "ssh" - tramp-backup-directory-alist backup-directory-alist - tramp-ssh-controlmaster-options "ssh") -#+end_src - -*** TODO [[https://pages.sachachua.com/.emacs.d/Sacha.html#org9d2ca0e][Clean up space]] -:LOGBOOK: -- State "DONE" from "TODO" [2023-07-06 Thu 12:32] -:END: - -#+begin_src elisp :tangle no - (bind-key "M-SPC" 'cycle-spacing) -#+end_src - -*** TODO Transform links into org links -:LOGBOOK: -- State "DONE" from [2023-08-19 Sat 19:41] -:END: - -#+begin_src elisp :tangle no - (defun my/transform-html-links-to-org () - "Transform all HTML links in the current buffer into 'org-mode' links." - (interactive) - (goto-char (point-min)) - (while (re-search-forward "\\(.*?\\)" nil t) - (replace-match (org-make-link-string (match-string 1) (match-string 2))))) -#+end_src - -*** TODO Count words per minute -:LOGBOOK: -- State "DONE" from "TODO" [2023-07-06 Thu 12:32] -:END: - -#+begin_src elisp :tangle no - (require 'org-clock) - (defun my/org-entry-wpm () - (interactive) - (save-restriction - (save-excursion - (org-narrow-to-subtree) - (goto-char (point-min)) - (let* ((words (count-words-region (point-min) (point-max))) - (minutes (org-clock-sum-current-item)) - (wpm (/ words minutes))) - (message "WPM: %d (words: %d, minutes: %d)" wpm words minutes) - (kill-new (number-to-string wpm)) - ) - ) - ) - ) -#+end_src - -*** TODO Enable dict mode - - #+begin_src elisp :tangle no - (setq dictionary-server "automatic") - #+end_src - -*** TODO Pick out passive voice and weasel words -:LOGBOOK: -- State "DONE" from "NEXT" [2023-08-09 Wed 13:52] -:END: - -#+begin_src elisp :tangle no - (use-package writegood-mode - :diminish writegood-mode - :config - (progn (add-hook 'text-mode-hook 'writegood-mode)) - ) -#+end_src - -*** TODO [[https://github.com/ifitzpat/ob-docker-build][Org-babel docker]] -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-09 Tue 16:58] -:END: - -#+begin_src elisp :tangle no - (use-package ob-docker-build - :straight (ob-docker-build :type git :host github :repo "ifitzpat/ob-docker-build") - :defer t - :config - (add-to-list 'org-babel-load-languages '(docker-build . t)) - (org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages) - ) -#+end_src - -*** TODO [1/6] Spelling and syntax -**** DONE Spell checking -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 16:51] -- State "DONE" from "TODO" [2023-07-05 Wed 16:09] -:END: - -This requires installation of hunspell -#+begin_src bash :tangle no - sudo apt install hunspell -#+end_src - -#+begin_src elisp - (use-package flyspell - :config (setq ispell-program-name "hunspell" - ispell-default-dictionary "en_US" - ) - :diminish (flyspell-mode . "φ") - :hook (text-mode . flyspell-mode) - :bind ( - ("M-" . flyspell-buffer) - ("" . flyspell-word) - ("C-;" . flyspell-auto-correct-previous-word) - ) - ) -#+end_src - -**** TODO [[https://github.com/d12frosted/flyspell-correct][Flyspell correct]] -:LOGBOOK: -- State "DONE" from [2024-07-02 Tue 13:13] -:END: - -#+begin_src elisp :tangle no - (use-package flyspell-correct - :after flyspell - :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-wrapper)) - ) -#+end_src - -**** TODO [[https://www.flycheck.org/][Flycheck]] -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 14:30] -- State "DONE" from "TODO" [2024-07-02 Tue 13:13] -:END: - -Needs external checkers installed - -#+begin_src elisp - (use-package flycheck - :init (global-flycheck-mode) - :diminish (flycheck-mode . "") - :config - (add-hook 'after-init-hook #'global-flycheck-mode) - (setq flycheck-emacs-lisp-load-path 'inherit) - (setq flycheck-emacs-lisp-load-path (concat user-emacs-directory "straight/build")) - ) -#+end_src - -**** TODO [[https://github.com/cuonglm/flycheck-checkbashisms][Flycheck bash]] -#+begin_src bash :tangle no - sudo apt install devscripts -#+end_src - -#+begin_src elisp :tangle no - (use-package flycheck-checkbashisms - :config - (flycheck-checkbashisms-setup) - ) -#+end_src - -**** TODO [[https://github.com/yoshiki/yaml-mode][Yaml]] -:LOGBOOK: -- State "DONE" from "TODO" [2024-06-27 Thu 13:03] -:END: - -#+begin_src elisp :tangle no - (use-package yaml-mode - :config - (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) - (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode)) - ) -#+end_src - -**** TODO Docker -:LOGBOOK: -- State "DONE" from "TODO" [2024-06-27 Thu 13:03] -:END: -#+begin_src elisp :tangle no - (use-package docker-compose-mode) -#+end_src - -*** DONE [[https://github.com/chenyanming/calibredb.el][Read ebooks]] -:PROPERTIES: -:CREATED: [2023-01-14 Sat 16:38] -:END: -:LOGBOOK: -- State "DONE" from "NEXT" [2023-08-09 Wed 13:27] -:END: - -#+begin_src elisp - (use-package calibredb -:defer t - :config - (setq calibredb-format-all-the-icons t) - (setq calibredb-format-icons-in-terminal t) - ) -#+end_src - -#+begin_src elisp - ;; Forcefully reset the variable after loading calibredb - (defvar calibredb-root-dir (concat (getenv "HOME") "/library/books")) - (defvar calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir)) - ; (defvar calibredb-library-alist (concat (getenv "HOME") "/library/books")) - ;; (defvar calibredb-search-page-max-rows 1000) - (defvar calibredb-id-width 6) - (defvar calibredb-title-width 100) - (defvar calibredb-format-width 0) - (defvar calibredb-date-width 0) - (defvar calibredb-author-width 20) - (defvar calibredb-comment-width 0) - (defvar calibredb-tag-width 0) -#+end_src - -Some keybindings - -#+begin_src elisp ~/.emacs.d/custom.el - (defvar calibredb-show-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "?" #'calibredb-entry-dispatch) - (define-key map "o" #'calibredb-find-file) - (define-key map "O" #'calibredb-find-file-other-frame) - (define-key map "V" #'calibredb-open-file-with-default-tool) - (define-key map "s" #'calibredb-set-metadata-dispatch) - (define-key map "e" #'calibredb-export-dispatch) - (define-key map "q" #'calibredb-entry-quit) - (define-key map "y" #'calibredb-yank-dispatch) - (define-key map "," #'calibredb-quick-look) - (define-key map "." #'calibredb-dired-open) - (define-key map "\M-/" #'calibredb-rga) - (define-key map "\M-t" #'calibredb-set-metadata--tags) - (define-key map "\M-a" #'calibredb-set-metadata--author_sort) - (define-key map "\M-A" #'calibredb-set-metadata--authors) - (define-key map "\M-T" #'calibredb-set-metadata--title) - (define-key map "\M-c" #'calibredb-set-metadata--comments) - map) - "Keymap for `calibredb-show-mode'.") -#+end_src - -#+begin_src elisp - (defvar calibredb-search-mode-map - (let ((map (make-sparse-keymap))) - (define-key map [mouse-3] #'calibredb-search-mouse) - (define-key map (kbd "") #'calibredb-find-file) - (define-key map "?" #'calibredb-dispatch) - (define-key map "a" #'calibredb-add) - (define-key map "A" #'calibredb-add-dir) - (define-key map "c" #'calibredb-clone) - (define-key map "d" #'calibredb-remove) - (define-key map "D" #'calibredb-remove-marked-items) - (define-key map "j" #'calibredb-next-entry) - (define-key map "k" #'calibredb-previous-entry) - (define-key map "l" #'calibredb-virtual-library-list) - (define-key map "L" #'calibredb-library-list) - (define-key map "n" #'calibredb-virtual-library-next) - (define-key map "N" #'calibredb-library-next) - (define-key map "p" #'calibredb-virtual-library-previous) - (define-key map "P" #'calibredb-library-previous) - (define-key map "s" #'calibredb-set-metadata-dispatch) - (define-key map "S" #'calibredb-switch-library) - (define-key map "o" #'calibredb-find-file) - (define-key map "O" #'calibredb-find-file-other-frame) - (define-key map "v" #'calibredb-view) - (define-key map "V" #'calibredb-open-file-with-default-tool) - (define-key map "," #'calibredb-quick-look) - (define-key map "." #'calibredb-dired-open) - (define-key map "y" #'calibredb-yank-dispatch) - (define-key map "b" #'calibredb-catalog-bib-dispatch) - (define-key map "e" #'calibredb-export-dispatch) - (define-key map "r" #'calibredb-search-refresh-and-clear-filter) - (define-key map "R" #'calibredb-search-clear-filter) - (define-key map "q" #'calibredb-search-quit) - (define-key map "m" #'calibredb-mark-and-forward) - (define-key map "f" #'calibredb-toggle-favorite-at-point) - (define-key map "x" #'calibredb-toggle-archive-at-point) - (define-key map "h" #'calibredb-toggle-highlight-at-point) - (define-key map "u" #'calibredb-unmark-and-forward) - (define-key map "i" #'calibredb-edit-annotation) - (define-key map (kbd "") #'calibredb-unmark-and-backward) - (define-key map (kbd "") #'calibredb-toggle-view) - (define-key map (kbd "TAB") #'calibredb-toggle-view-at-point) - (define-key map "\M-n" #'calibredb-show-next-entry) - (define-key map "\M-p" #'calibredb-show-previous-entry) - (define-key map "/" #'calibredb-search-live-filter) - (define-key map "\M-t" #'calibredb-set-metadata--tags) - (define-key map "\M-a" #'calibredb-set-metadata--author_sort) - (define-key map "\M-A" #'calibredb-set-metadata--authors) - (define-key map "\M-T" #'calibredb-set-metadata--title) - (define-key map "\M-c" #'calibredb-set-metadata--comments) - map) - "Keymap for `calibredb-search-mode'.") -#+end_src - -*** DONE Annotate [[https://github.com/org-noter/org-noter][PDFs and EPUBs]] -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 14:35] -- State "DONE" from "NEXT" [2023-08-09 Wed 15:06] -:END: -#+begin_src elisp :tangle no - (use-package org-noter) -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar org-noter-notes-search-path (list (concat org-directory "/library/books"))) - (defvar org-noter-default-notes-file-names '("books.org")) -#+end_src - -*** DONE [[https://github.com/fuxialexander/org-pdftools][Link PDFs]] - -:PROPERTIES: -:TITLE: GitHub - fuxialexander/org-pdftools: A custom org link type for pdf-tools -:URI: https://github.com/fuxialexander/org-pdftools -:CREATED: [2023-01-28 Sat 11:04] -:END: -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 16:54] -- State "DONE" from "NEXT" [2023-08-12 Sat 14:05] -:END: - -#+begin_src elisp - (use-package org-noter-pdftools - :after org-noter - :config - ;; Add a function to ensure precise note is inserted - (defun org-noter-pdftools-insert-precise-note (&optional toggle-no-questions) - (interactive "P") - (org-noter--with-valid-session - (let ((org-noter-insert-note-no-questions (if toggle-no-questions - (not org-noter-insert-note-no-questions) - org-noter-insert-note-no-questions)) - (org-pdftools-use-isearch-link t) - (org-pdftools-use-freepointer-annot t)) - (org-noter-insert-note (org-noter--get-precise-info))))) - - ;; fix https://github.com/weirdNox/org-noter/pull/93/commits/f8349ae7575e599f375de1be6be2d0d5de4e6cbf - (defun org-noter-set-start-location (&optional arg) - "When opening a session with this document, go to the current location. - With a prefix ARG, remove start location." - (interactive "P") - (org-noter--with-valid-session - (let ((inhibit-read-only t) - (ast (org-noter--parse-root)) - (location (org-noter--doc-approx-location (when (called-interactively-p 'any) 'interactive)))) - (with-current-buffer (org-noter--session-notes-buffer session) - (org-with-wide-buffer - (goto-char (org-element-property :begin ast)) - (if arg - (org-entry-delete nil org-noter-property-note-location) - (org-entry-put nil org-noter-property-note-location - (org-noter--pretty-print-location location)))))))) - (with-eval-after-load 'pdf-annot - (add-hook 'pdf-annot-activate-handler-functions #'org-noter-pdftools-jump-to-note) - ) - ) -#+end_src - -*** DONE [[https://depp.brause.cc/nov.el/][View EPUBs]] :books: -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 14:37] -- State "DONE" from "NEXT" [2023-08-09 Wed 13:19] -:END: -#+begin_src elisp :tangle no - (use-package nov - :config - (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)) - ) -#+end_src - -*** TODO [[https://github.com/tmalsburg/helm-bibtex][Zotero]] -#+begin_src elisp :tangle no - (use-package helm-bibtex) -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar bibtex-completion-bibliography '("~/bibliography/zotero.bib")) -#+end_src - -** DONE [2/2] Security -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-16 Tue 21:49] -- State "DONE" from "TODO" [2024-07-09 Tue 14:16] -:END: -*** DONE Password-store -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-16 Tue 21:49] -- State "DONE" from "TODO" [2023-07-06 Thu 11:44] -:END: -#+begin_src elisp :tangle no - (use-package password-store) -#+end_src - -*** DONE Auth source -:LOGBOOK: -- State "DONE" from "TODO" [2023-07-06 Thu 11:45] -:END: -#+begin_src elisp - (use-package auth-source - :config (auth-source-pass-enable) - ) -#+end_src - -** TODO [2/3] AI -*** DONE [[https://github.com/s-kostyaev/ellama][Ellama]] -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 17:27] -- State "DONE" from "TODO" [2024-06-27 Thu 07:40] -:END: - -#+begin_src elisp :tangle no - ;; YOU DON'T NEED NONE OF THIS CODE FOR SIMPLE INSTALL - ;; IT IS AN EXAMPLE OF CUSTOMIZATION. - (use-package ellama - :init - (require 'llm-openai) - ;; setup key bindings - (setq ellama-keymap-prefix "C-c e") - ) -#+end_src - -#+begin_src elisp ~/.emacs.d/custom.el :tangle no - (setopt ellama-providers - '( - ;; Ollama Provider (added here with a name) - ("ollama" . (make-llm-ollama - ;; Consider a dedicated embedding model if gemma isn't ideal for it. - :chat-model "gemma3:latest" - :embedding-model "gemma3:latest" ; Or e.g., "nomic-embed-text" - :default-chat-non-standard-params '(("num_ctx" . 8192)))) - - ("openai" . (make-llm-openai - :key (auth-source-pass-get "api-key" "www/openai.com/amr@gharbeia.net") - :chat-model "gpt-4o" - :embedding-model "text-embedding-3-large")) - - ("google" . (make-llm-google - :key (auth-source-pass-get "gemini-api-key" "www/google.com/amr.gharbeia") - :chat-model "latest" ; Use "latest" or specific version - :embedding-model "text-embedding-004")) ; Or gecko, but 004 is newer - - ("groq" . (make-llm-openai-compatible - :url "https://api.groq.com/openai/v1" - :key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net") - ;; Check Groq console for available models, these might change - :chat-model "llama3-70b-8192" ; Example, verify on Groq - :embedding-model "llama3-70b-8192")) ; Groq might not offer dedicated embedding models via this API - )) - - ;; --- Set Active Providers --- - ;; Choose your default provider from the list above by its name - (setopt ellama-provider "ollama") ; Or "ollama", "openai", "groq" - - ;; You can specify different providers for different tasks if needed - (setopt ellama-translation-provider "ollama") - (setopt ellama-naming-provider "ollama") - (setopt ellama-naming-scheme 'ellama-generate-name-by-llm) - - ;; --- Ensure auth-source is configured --- - ;; (require 'auth-source) - ;; (setq auth-sources '("~/.authinfo.gpg" "~/.authinfo" "~/.netrc")) - ;; Make sure your API keys are correctly stored in one of these files. - ;; Example .authinfo.gpg entry for OpenAI: - ;; machine www/openai.com/amr@gharbeia.net login amr@gharbeia.net password YOUR_OPENAI_API_KEY - ;; Example .authinfo.gpg entry for Google Gemini: - ;; machine www/google.com/amr.gharbeia login amr.gharbeia password YOUR_GEMINI_API_KEY - ;; Example .authinfo.gpg entry for Groq: - ;; machine www/console.groq.com/groq@amr.gharbeia.net login groq@amr.gharbeia.net password YOUR_GROQ_API_KEY - - (setq llm-debug t) -#+end_src - -#+begin_src elisp - (use-package ellama - :ensure t - :bind ("C-c e" . ellama) - ;; send last message in chat buffer with C-c C-c - :hook (org-ctrl-c-ctrl-c-final . ellama-chat-send-last-message) - :init (setopt ellama-auto-scroll t) - :config - ;; show ellama context in header line in all buffers - (ellama-context-header-line-global-mode +1) - ;; show ellama session id in header line in all buffers - (ellama-session-header-line-global-mode +1)) -#+end_src - -*** CNCL GPTel - :LOGBOOK: - - State "CNCL" from "DONE" [2024-04-01 Mon 15:32] \\ - Moved to Ellama - - State "DONE" from "TODO" [2024-02-28 Wed 16:49] - :END: - #+begin_src elisp :tangle no - (use-package gptel) - #+end_src - - #+begin_src elisp :tangle no - (setq gptel-api-key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net")) - #+end_src - -#+begin_src elisp :tangle no - (gptel-make-openai "Groq" ;Any name you want - :host "api.groq.com" - :endpoint "/openai/v1/chat/completions" - :stream t - :key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net") ;can be a function that returns the key - :models '(llama-3.1-70b-versatile - llama-3.1-8b-instant - llama3-70b-8192 - llama3-8b-8192 - mixtral-8x7b-32768 - gemma-7b-it)) -#+end_src - -*** TODO [[https://github.com/s-kostyaev/elisa][Elisa]] - -#+begin_src elisp :tangle no - (use-package elisa - :init - (setopt elisa-limit 5) - (require 'llm-ollama) - (setopt elisa-embeddings-provider (make-llm-ollama :embedding-model "nomic-embed-text")) - (setopt elisa-chat-provider (make-llm-ollama - :chat-model "sskostyaev/openchat:8k-rag" - :embedding-model "nomic-embed-text")) - ) -#+end_src - -** DONE [[https://github.com/beancount/beancount-mode/][Accounting]] -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 15:07] -- State "DONE" from "TODO" [2024-06-27 Thu 07:43] -:END: - -#+begin_src elisp :tangle no - (use-package beancount - :straight (beancount :type git :host github :repo "beancount/beancount-mode") - :config - (add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode)) - (add-hook 'beancount-mode-hook #'outline-minor-mode) - (define-key beancount-mode-map (kbd "C-c C-n") #'outline-next-visible-heading) - (define-key beancount-mode-map (kbd "C-c C-p") #'outline-previous-visible-heading) - (add-hook 'beancount-mode-hook #'flymake-bean-check-enable) - ) -#+end_src - -On package.el, it is a manual install so far - -#+begin_src elisp :tangle no - (make-directory (expand-file-name "manual-packages/" user-emacs-directory) t) - (make-directory (expand-file-name "beancount/" (concat user-emacs-directory "manual-packages")) t) - (add-to-list 'load-path "~/.emacs.d/manual-packages/beancount-mode") - (require 'beancount) - (add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode)) - (add-hook 'beancount-mode-hook #'outline-minor-mode) - (define-key beancount-mode-map (kbd "C-c C-n") #'outline-next-visible-heading) - (define-key beancount-mode-map (kbd "C-c C-p") #'outline-previous-visible-heading) - (add-hook 'beancount-mode-hook #'flymake-bean-check-enable) - #+end_src - -#+begin_src bash :tangle no - cd ~/.emacs.d/manual-packages/ - git clone https://github.com/beancount/beancount-mode/ -#+end_src - -** DONE Browser -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 17:28] -- State "DONE" from "TODO" [2023-07-07 Fri 15:29] -:END: -#+begin_src elisp - (use-package eww - :bind* (("M-m g x" . eww) - ("M-m g :" . eww-browse-with-external-browser) - ("M-m g #" . eww-list-histories) - ("M-m g {" . eww-back-url) - ("M-m g }" . eww-forward-url)) - :config - (progn - (add-hook 'eww-mode-hook 'visual-line-mode) - ) - ) -#+end_src - -** DONE [[https://github.com/Silex/docker.el][Manage Docker in Emacs]] -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 17:29] -:END: - -#+begin_src elisp - (use-package docker - :bind ("C-c d" . docker) - ) -#+end_src - -** DONE [[https://github.com/sergiruiztrepat/chemtable][Periodic table of the elements]] :chemistry: -:PROPERTIES: -:CREATED: [2023-01-27 Fri 21:12] -:TITLE: GitHub - sergiruiztrepat/chemtable: Periodic table of the elements -:URI: https://github.com/sergiruiztrepat/chemtable -:END: -:LOGBOOK: -- State "DONE" from "TODO" [2024-07-19 Fri 17:29] -- State "DONE" from "TODO" [2023-08-21 Mon 13:27] -:END: - -#+begin_src elisp :tangle no - (use-package chemtable) -#+end_src - -** DONE End matter -#+begin_src elisp - (provide 'config) - ;;; config.el ends here -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (provide 'custom) - ;;; custom.el ends here -#+end_src - - diff --git a/system/dotemacs.el b/projects/dotemacs/dotemacs.el similarity index 85% rename from system/dotemacs.el rename to projects/dotemacs/dotemacs.el index c96f46d..9f1bac3 100644 --- a/system/dotemacs.el +++ b/projects/dotemacs/dotemacs.el @@ -1,7 +1,10 @@ -(let ((config-dir "~/memex/system/")) +(let ((config-dir "~/memex/projects/dotemacs/modules/")) ;; Load the core settings, including package management and essential setup. (org-babel-load-file (expand-file-name "emacs-core.org" config-dir)) + ;; Load UI and theme settings + (org-babel-load-file (expand-file-name "emacs-ui.org" config-dir)) + ;; Load early init settings (if separate and not fully covered by core) ;; (org-babel-load-file (expand-file-name "emacs-early-init.org" config-dir)) diff --git a/system/dotemacs.org b/projects/dotemacs/dotemacs.org similarity index 89% rename from system/dotemacs.org rename to projects/dotemacs/dotemacs.org index 92c1a2e..1ec1f27 100644 --- a/system/dotemacs.org +++ b/projects/dotemacs/dotemacs.org @@ -6,10 +6,13 @@ This file loads the modular Emacs configuration files. It should be the primary way Emacs is configured, replacing or integrating with the original `~/.emacs`, `~/.emacs.d/init.el`, `~/.emacs.d/early-init.el`, and `~/.emacs.d/config.el`. #+begin_src emacs-lisp -(let ((config-dir "~/memex/system/")) +(let ((config-dir "~/memex/projects/dotemacs/modules/")) ;; Load the core settings, including package management and essential setup. (org-babel-load-file (expand-file-name "emacs-core.org" config-dir)) + ;; Load UI and theme settings + (org-babel-load-file (expand-file-name "emacs-ui.org" config-dir)) + ;; Load early init settings (if separate and not fully covered by core) ;; (org-babel-load-file (expand-file-name "emacs-early-init.org" config-dir)) diff --git a/system/emacs-ai.el b/projects/dotemacs/modules/emacs-ai.el similarity index 100% rename from system/emacs-ai.el rename to projects/dotemacs/modules/emacs-ai.el diff --git a/projects/dotemacs/modules/emacs-ai.org b/projects/dotemacs/modules/emacs-ai.org index a369801..d2eb688 100644 --- a/projects/dotemacs/modules/emacs-ai.org +++ b/projects/dotemacs/modules/emacs-ai.org @@ -1,21 +1,120 @@ -#+TITLE: Emacs AI Configuration -#+property: header-args :tangle ~/.emacs.d/modules/ai.el +#+TITLE: AI Configuration +#+PROPERTY: header-args :tangle yes -* ellama -#+begin_src elisp +* AI Settings + +** Ellama + +#+begin_src elisp :tangle yes + ;; YOU DON'T NEED NONE OF THIS CODE FOR SIMPLE INSTALL + ;; IT IS AN EXAMPLE OF CUSTOMIZATION. (use-package ellama - :ensure t - :bind ("C-c e" . ellama) - :hook (org-ctrl-c-ctrl-c-final . ellama-chat-send-last-message) - :init (setopt ellama-auto-scroll t) - :config - (ellama-context-header-line-global-mode +1) - (ellama-session-header-line-global-mode +1) + :init + (require 'llm-openai) + ;; setup key bindings + (setq ellama-keymap-prefix "C-c e") ) #+end_src -* Providers -#+begin_src elisp +#+begin_src elisp :tangle yes + (setopt ellama-providers + '( + ;; Ollama Provider (added here with a name) + ("ollama" . (make-llm-ollama + ;; Consider a dedicated embedding model if gemma isn't ideal for it. + :chat-model "gemma3:latest" + :embedding-model "gemma3:latest" ; Or e.g., "nomic-embed-text" + :default-chat-non-standard-params '(("num_ctx" . 8192)))) + + ("openai" . (make-llm-openai + :key (auth-source-pass-get "api-key" "www/openai.com/amr@gharbeia.net") + :chat-model "gpt-4o" + :embedding-model "text-embedding-3-large")) + + ("groq" . (make-llm-openai-compatible + :url "https://api.groq.com/openai/v1" + :key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net") + ;; Check Groq console for available models, these might change + :chat-model "llama3-70b-8192" ; Example, verify on Groq + :embedding-model "llama3-70b-8192")) ; Groq might not offer dedicated embedding models via this API + )) + + ;; --- Set Active Providers --- + ;; Choose your default provider from the list above by its name + (setopt ellama-provider "ollama") ; Or "ollama", "openai", "groq" + + ;; You can specify different providers for different tasks if needed + (setopt ellama-translation-provider "ollama") + (setopt ellama-naming-provider "ollama") + (setopt ellama-naming-scheme 'ellama-generate-name-by-llm) + (setq llm-debug t) - ;; Note: API keys should be handled via auth-source as seen in original config #+end_src + +#+begin_src elisp + (use-package ellama + :ensure t + :bind ("C-c e" . ellama) + ;; send last message in chat buffer with C-c C-c + :hook (org-ctrl-c-ctrl-c-final . ellama-chat-send-last-message) + :init (setopt ellama-auto-scroll t) + :config + ;; show ellama context in header line in all buffers + (ellama-context-header-line-global-mode +1) + ;; show ellama session id in header line in all buffers + (ellama-session-header-line-global-mode +1)) +#+end_src + +** GPTel + +#+begin_src elisp :tangle yes + (use-package gptel) +#+end_src + +#+begin_src elisp :tangle yes + (setq gptel-api-key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net")) +#+end_src + +#+begin_src elisp :tangle yes + (gptel-make-openai "Groq" ;Any name you want + :host "api.groq.com" + :endpoint "/openai/v1/chat/completions" + :stream t + :key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net") ;can be a function that returns the key + :models '(llama-3.1-70b-versatile + llama-3.1-8b-instant + llama3-70b-8192 + llama3-8b-8192 + mixtral-8x7b-32768 + gemma-7b-it)) +#+end_src + +** Elisa + +#+begin_src elisp :tangle yes + (use-package elisa + :defer t + :init + (setopt elisa-limit 5) + (require 'llm-ollama) + (setopt elisa-embeddings-provider (make-llm-ollama :embedding-model "nomic-embed-text")) + (setopt elisa-chat-provider (make-llm-ollama + :chat-model "sskostyaev/openchat:8k-rag" + :embedding-model "nomic-embed-text")) + ) +#+end_src + +** OpenCortex (Local Foundry) + +#+begin_src elisp :tangle yes + (use-package opencortex + :straight nil + :load-path "~/.local/share/opencortex/src" + :commands (opencortex-connect opencortex-disconnect) + :init + (setq opencortex-host "127.0.0.1") + (setq opencortex-port 9105) + (setq opencortex-executable-path "~/.local/share/opencortex/bin/opencortex-server") + :config + (message "opencortex: Local brain configured at %s" opencortex-executable-path)) +#+end_src \ No newline at end of file diff --git a/system/emacs-core.el b/projects/dotemacs/modules/emacs-core.el similarity index 62% rename from system/emacs-core.el rename to projects/dotemacs/modules/emacs-core.el index 510e735..263003c 100644 --- a/system/emacs-core.el +++ b/projects/dotemacs/modules/emacs-core.el @@ -16,6 +16,36 @@ (unless (file-directory-p (expand-file-name "~/.emacs.d/straight/versions")) (make-directory (expand-file-name "~/.emacs.d/straight/versions") t)) (use-package org) +(use-package ef-themes + :config + ;; If you like two specific themes and want to switch between them, you + ;; can specify them in `ef-themes-to-toggle' and then invoke the command + ;; `ef-themes-toggle'. All the themes are included in the variable + ;; `ef-themes-collection'. + (setq ef-themes-to-toggle '(ef-summer ef-winter)) + + (setq ef-themes-headings ; read the manual's entry or the doc string + '((0 variable-pitch light 1.9) + (1 variable-pitch light 1.8) + (2 variable-pitch regular 1.7) + (3 variable-pitch regular 1.6) + (4 variable-pitch regular 1.5) + (5 variable-pitch 1.4) ; absence of weight means `bold' + (6 variable-pitch 1.3) + (7 variable-pitch 1.2) + (t variable-pitch 1.1))) + + ;; They are nil by default... + (setq ef-themes-mixed-fonts t) + (setq ef-themes-variable-pitch-ui t) + + ;; Disable all other themes to avoid awkward blending: + (mapc #'disable-theme custom-enabled-themes) + + ;; Load the theme of choice: + (load-theme 'ef-winter :no-confirm) + ) + (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) (when (file-exists-p custom-file) (load custom-file)) @@ -49,7 +79,7 @@ (add-hook 'server-done-hook (lambda () (delete-frame))) -(desktop-save-mode t) +;; (desktop-save-mode t) (use-package password-store) diff --git a/projects/dotemacs/modules/emacs-core.org b/projects/dotemacs/modules/emacs-core.org index 79553c8..2204761 100644 --- a/projects/dotemacs/modules/emacs-core.org +++ b/projects/dotemacs/modules/emacs-core.org @@ -1,55 +1,199 @@ -#+TITLE: Emacs Core Configuration -#+property: header-args :tangle ~/.emacs.d/modules/core.el +#+TITLE: Core Emacs Configuration +#+PROPERTY: header-args :tangle yes -* early-init.el -For straight.el to pick up before package.el +* Initialization Bootstrap -#+begin_src elisp :tangle ~/.emacs.d/early-init.el - (setq package-enable-at-startup nil) -#+end_src +This section tangles directly to ~/.emacs to bootstrap the entire system. -* Straight.el Bootstrap #+begin_src elisp :tangle ~/.emacs + ;;; .emacs --- Global settings -*- lexical-binding: t; -*- + + (setq gc-cons-threshold (* 500 1024 1024)) + (add-hook 'after-init-hook (lambda () (setq gc-cons-threshold (* 5 1024 1024)))) + (setq straight-repository-branch "develop") - (eval-and-compile - (defvar bootstrap-version) - (let ((bootstrap-file - (expand-file-name "straight/repos/straight.el/bootstrap.el" - (or (bound-and-true-p straight-base-dir) - user-emacs-directory))) - (bootstrap-version 7)) - (unless (file-exists-p bootstrap-file) - (with-current-buffer - (url-retrieve-synchronously "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" 'silent 'inhibit-cookies) - (goto-char (point-max)) - (eval-print-last-sexp))) - (load bootstrap-file nil 'nomessage)) - - (straight-use-package 'use-package) - ) + + (eval-and-compile + (defvar bootstrap-version) + (let ((bootstrap-file + (expand-file-name "straight/repos/straight.el/bootstrap.el" + (or (bound-and-true-p straight-base-dir) + user-emacs-directory))) + (bootstrap-version 7)) + (unless (file-exists-p bootstrap-file) + (with-current-buffer + (url-retrieve-synchronously "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" 'silent 'inhibit-cookies) + (goto-char (point-max)) + (eval-print-last-sexp))) + (load bootstrap-file nil 'nomessage)) + + (straight-use-package 'use-package) + (straight-use-package 'org)) + (setq straight-use-package-by-default t) + + (require 'ob-tangle) + + ;; Load the modular configuration starting from dotemacs.org + (org-babel-load-file (expand-file-name "~/memex/projects/dotemacs/dotemacs.org")) + + (provide '.emacs) #+end_src -* Server and Performance -#+begin_src elisp :tangle ~/.emacs.d/early-init.el - (require 'server) - (unless (server-running-p) (server-start)) - (defvar server-max-buffers 100) -#+end_src +* Front matter +#+begin_src elisp + ;;; emacs-core.el --- Summary + ;;; Commentary: + ;;; Code: + + ;; -*- lexical-binding: t; -*- +#+end_src + +* Garbage collector + +Increase threshold to 500 MB to ease startup #+begin_src elisp (setq gc-cons-threshold (* 500 1024 1024)) +#+end_src + +Decrease threshold to 5 MB after init +#+begin_src elisp (add-hook 'after-init-hook (lambda () (setq gc-cons-threshold (* 5 1024 1024)))) #+end_src -* System Information -#+begin_src elisp :tangle ~/.emacs.d/custom.el +* Straight.el and use-package + +Integrate use-package and straight +#+begin_src elisp + (setq straight-use-package-by-default t) + (require 'use-package) + (straight-use-package 'diminish) + (require 'diminish) +#+end_src + +Make sure Org is installed (straight.el) +#+begin_src elisp + (unless (file-directory-p (expand-file-name "~/.emacs.d/straight/versions")) (make-directory (expand-file-name "~/.emacs.d/straight/versions") t)) + (use-package org) +#+end_src + +* UI and Themes + +#+begin_src elisp + (use-package ef-themes + :config + ;; If you like two specific themes and want to switch between them, you + ;; can specify them in `ef-themes-to-toggle' and then invoke the command + ;; `ef-themes-toggle'. All the themes are included in the variable + ;; `ef-themes-collection'. + (setq ef-themes-to-toggle '(ef-summer ef-winter)) + + (setq ef-themes-headings ; read the manual's entry or the doc string + '((0 variable-pitch light 1.9) + (1 variable-pitch light 1.8) + (2 variable-pitch regular 1.7) + (3 variable-pitch regular 1.6) + (4 variable-pitch regular 1.5) + (5 variable-pitch 1.4) ; absence of weight means `bold' + (6 variable-pitch 1.3) + (7 variable-pitch 1.2) + (t variable-pitch 1.1))) + + ;; They are nil by default... + (setq ef-themes-mixed-fonts t) + (setq ef-themes-variable-pitch-ui t) + + ;; Disable all other themes to avoid awkward blending: + (mapc #'disable-theme custom-enabled-themes) + + ;; Load the theme of choice: + (load-theme 'ef-winter :no-confirm) + ) +#+end_src + +* Custom file + +#+begin_src elisp + (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) + (when (file-exists-p custom-file) (load custom-file)) +#+end_src + +* System information + +#+begin_src elisp (defvar my-laptop-p (equal (system-name) "lilitop")) (defvar my-server-p (and (equal (system-name) "localhost") (equal user-login-name "root"))) (defvar my-phone-p (not (null (getenv "ANDROID_ROOT"))) "If non-nil, GNU Emacs is running on Termux.") (when my-phone-p (defvar gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")) - (global-auto-revert-mode) - (savehist-mode) - (desktop-save-mode t) + (global-auto-revert-mode) ; simplifies syncing +#+end_src + +* Persistent history + +#+begin_src elisp + (savehist-mode) +#+end_src + +* Disable Syntax Checkers (Diagnostic) + +#+begin_src elisp + (when (fboundp 'flycheck-mode) + (setq flycheck-global-modes nil) + (global-flycheck-mode -1)) + (when (fboundp 'flymake-mode) + (setq help-at-pt-display-when-idle t) + ;; Disable flymake in all buffers + (add-hook 'find-file-hook (lambda () (flymake-mode -1)))) +#+end_src + +* Backup and versioning + +#+begin_src emacs-lisp + (use-package magit) +#+end_src + +* Personal information + +#+begin_src elisp + (setq user-full-name "Amr Gharbeia") + (defvar email-address "amr@gharbeia.net") + (defvar calendar-latitude 39.0) + (defvar calendar-longitude -77.1) + (defvar calendar-location-name "Washington, DC") + (defvar calendar-time-zone -300) + (defvar calendar-standard-time-zone-name "EST") + (defvar calendar-daylight-time-zone-name "EDT") +#+end_src + +* Saving Emacs Sessions + +Close frame when done +#+begin_src elisp + (add-hook 'server-done-hook (lambda () (delete-frame))) +#+end_src + +Save desktop session +#+begin_src elisp + ;; (desktop-save-mode t) +#+end_src + +* Security + +#+begin_src elisp + (use-package password-store) +#+end_src + +#+begin_src elisp + (use-package auth-source + :config (auth-source-pass-enable) + ) +#+end_src + +* End matter + +#+begin_src elisp + (provide 'emacs-core) + ;;; emacs-core.el ends here #+end_src diff --git a/projects/dotemacs/docs/emacs-early-init.org b/projects/dotemacs/modules/emacs-early-init.org similarity index 100% rename from projects/dotemacs/docs/emacs-early-init.org rename to projects/dotemacs/modules/emacs-early-init.org diff --git a/system/emacs-gtd.el b/projects/dotemacs/modules/emacs-gtd.el similarity index 100% rename from system/emacs-gtd.el rename to projects/dotemacs/modules/emacs-gtd.el diff --git a/projects/dotemacs/modules/emacs-gtd.org b/projects/dotemacs/modules/emacs-gtd.org index c642dba..486e42b 100644 --- a/projects/dotemacs/modules/emacs-gtd.org +++ b/projects/dotemacs/modules/emacs-gtd.org @@ -1,30 +1,112 @@ -#+TITLE: Emacs GTD Configuration -#+property: header-args :tangle ~/.emacs.d/modules/gtd.el +#+TITLE: GTD & Agenda Configuration +#+PROPERTY: header-args :tangle yes -* org-gtd +* Agenda + +Basic agenda settings #+begin_src elisp - (use-package org-gtd - :defer t - :init (setq org-gtd-update-ack "3.0.0") - :after org - :config - (setq org-edna-use-inheritance t) - (org-edna-mode) - :bind ( - ("C-c d c" . org-gtd-capture) - ("C-c d e" . org-gtd-engage) - ("C-c d p" . org-gtd-process-inbox) - :map org-gtd-clarify-map - ("C-c c" . org-gtd-organize) - ) - ) + (setq org-deadline-warning-days 7) + (setq org-agenda-skip-additional-timestamps-same-entry t) + (setq org-agenda-span 'fortnight) + (setq org-agenda-tags-column 'auto) + (setq org-agenda-skip-scheduled-if-deadline-is-shown t) #+end_src -* GTD Directory and Areas +Agenda files #+begin_src elisp - (defvar org-gtd-directory org-directory) - (defvar org-gtd-organize-hooks '(org-gtd-set-area-of-focus)) - (defvar org-gtd-areas-of-focus '( + (setq org-agenda-files (list + (concat org-directory "/inbox.org") + (concat org-directory "/gtd.org") + (concat org-directory "/org-gtd-tasks.org") + ) + ) + +#+end_src + +Better agenda views +#+begin_src elisp :tangle yes + (use-package org-super-agenda) +#+end_src + +* To-do + +Basic todo +#+begin_src elisp + (setq org-todo-keywords + '( + (sequence "TODO(t)" "NEXT(n)" "WAIT(w@/!)" "|" "DONE(d!)" "CNCL(c@)") + ) + ) + + (setq org-todo-keyword-faces + '( + ("TODO" :foreground "red" :weight bold) + ("NEXT" :foreground "red" :weight bold) + ("WAIT" :foreground "yellow" :weight bold) + ("DONE" :foreground "green" :weight bold) + ("CNCL" :foreground "blue" :weight bold) + ) + ) + + (setq org-enforce-todo-dependencies t) + (setq org-tags-exclude-from-inheritance '("crypt" "!private")) +#+end_src + +Switch entry to 'DONE' when all subentries are done +#+begin_src elisp + (defun org-summary-todo (n-done n-not-done) + "Switch entry to 'DONE' when all subentries are done, to 'TODO' otherwise. + Uses N-DONE and N-NOT-DONE" + (let (org-log-done org-log-states) ; turn off logging + (org-todo (if (= n-not-done 0) "DONE" "TODO") + ) + ) + ) + + ;; (add-hook 'org-after-todo-statistics-hook #'org-summary-todo) +#+end_src + +* Getting Things Done (GTD) + +#+begin_src elisp + (use-package f) + (use-package dash) + (use-package s) + (use-package org-edna + :config + (setq org-edna-use-inheritance t) + (org-edna-mode)) + + (use-package org-gtd + :straight (org-gtd :type git :host github :repo "Trevoke/org-gtd.el") + :demand t + :init (setq org-gtd-update-ack "4.0.0") + :config + (setq org-gtd-keyword-mapping + '((todo . "TODO") + (next . "NEXT") + (wait . "WAIT") + (done . "DONE") + (canceled . "CNCL"))) + (setq org-gtd-custom-node-paths + (list (list "Actionable" (expand-file-name "~/memex/gtd.org") "Actions") + (list "Legacy" (expand-file-name "~/memex/org-gtd-tasks.org") "Actions") + (list "Projects" (expand-file-name "~/memex/gtd.org") "Projects") + (list "Incubate" (expand-file-name "~/memex/gtd.org") "Incubate"))) + (org-gtd-mode) + ) + + (global-set-key (kbd "C-c d c") #'org-gtd-capture) + (global-set-key (kbd "C-c d e") #'org-gtd-engage) + (global-set-key (kbd "C-c d p") #'org-gtd-process-inbox) + (with-eval-after-load 'org-gtd + (define-key org-gtd-clarify-map (kbd "C-c c") #'org-gtd-organize)) +#+end_src + +#+begin_src elisp + (setq org-gtd-directory org-directory) + (setq org-gtd-organize-hooks '(org-gtd-set-area-of-focus)) + (setq org-gtd-areas-of-focus '( "Atoms" "Bits" "Cells" @@ -44,5 +126,41 @@ "Egypt" ) ) - (defvar org-gtd-clarify-show-horizons 'right) + (setq org-gtd-clarify-show-horizons 'right) #+end_src + +Logging +#+begin_src elisp + (setq org-log-into-drawer "LOGBOOK") +#+end_src + +Clocking work in drawer +#+begin_src elisp :tangle yes + (setq org-clock-into-drawer t) +#+end_src + +Habits +#+begin_src elisp :tangle yes + (setq org-habit-graph-column 80) + (setq org-habit-show-habits-only-for-today nil) +#+end_src + +* Refile + +org-refile targets +#+begin_src elisp + (setq org-refile-targets '((nil :maxlevel . 9) + (org-agenda-files :maxlevel . 9) + ) + ) +#+end_src + +Set type of refile targets completion +#+begin_src elisp + (setq org-outline-path-complete-in-steps nil) +#+end_src + +Allow refiling to new parents created on the go after confirmation +#+begin_src elisp + (setq org-refile-allow-creating-parent-nodes 'confirm) +#+end_src \ No newline at end of file diff --git a/system/emacs-media.el b/projects/dotemacs/modules/emacs-media.el similarity index 92% rename from system/emacs-media.el rename to projects/dotemacs/modules/emacs-media.el index 163e021..f44b963 100644 --- a/system/emacs-media.el +++ b/projects/dotemacs/modules/emacs-media.el @@ -21,6 +21,9 @@ (setq org-noter-notes-search-path (list (expand-file-name "~/memex/library/books"))) (setq org-noter-default-notes-file-names '("books.org"))) +(setq org-noter-notes-search-path (list (concat org-directory "/library/books"))) +(setq org-noter-default-notes-file-names '("books.org")) + (use-package org-noter-pdftools :after org-noter :config @@ -62,3 +65,5 @@ With a prefix ARG, remove start location." ) (use-package helm-bibtex) + +(setq bibtex-completion-bibliography '("~/bibliography/zotero.bib")) diff --git a/projects/dotemacs/modules/emacs-media.org b/projects/dotemacs/modules/emacs-media.org index e80a680..19cbfcf 100644 --- a/projects/dotemacs/modules/emacs-media.org +++ b/projects/dotemacs/modules/emacs-media.org @@ -1,39 +1,101 @@ -#+TITLE: Emacs Media and E-books Configuration -#+property: header-args :tangle ~/.emacs.d/modules/media.el +#+TITLE: Media and Books Configuration +#+PROPERTY: header-args :tangle yes + +* Read ebooks (calibredb) -* calibredb #+begin_src elisp (use-package calibredb :defer t :config - (setq calibredb-format-all-the-icons t) - (setq calibredb-format-icons-in-terminal t) - ) + (setq calibredb-format-all-the-icons t) + (setq calibredb-format-icons-in-terminal t)) +#+end_src - (defvar calibredb-root-dir (concat (getenv "HOME") "/library/books")) +#+begin_src elisp + (defvar calibredb-root-dir (expand-file-name "~/memex/library/books")) (defvar calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir)) (defvar calibredb-id-width 6) (defvar calibredb-title-width 100) - (defvar calibredb-author-width 20) #+end_src -* nov.el (EPUB Viewer) +* PDF Tools + #+begin_src elisp + (use-package pdf-tools + :mode ("\\.pdf\\'" . pdf-view-mode) + :config + (pdf-tools-install :no-query) + (setq-default pdf-view-display-size 'fit-page) + (setq pdf-annot-activate-created-annotations t)) +#+end_src + +* Annotate PDFs and EPUBs (org-noter) + +#+begin_src elisp + (use-package org-noter + :config + (setq org-noter-notes-search-path (list (expand-file-name "~/memex/library/books"))) + (setq org-noter-default-notes-file-names '("books.org"))) +#+end_src + +#+begin_src elisp :tangle yes + (setq org-noter-notes-search-path (list (concat org-directory "/library/books"))) + (setq org-noter-default-notes-file-names '("books.org")) +#+end_src + +* Link PDFs (org-noter-pdftools) + +#+begin_src elisp + (use-package org-noter-pdftools + :after org-noter + :config + ;; Add a function to ensure precise note is inserted + (defun org-noter-pdftools-insert-precise-note (&optional toggle-no-questions) + (interactive "P") + (org-noter--with-valid-session + (let ((org-noter-insert-note-no-questions (if toggle-no-questions + (not org-noter-insert-note-no-questions) + org-noter-insert-note-no-questions)) + (org-pdftools-use-isearch-link t) + (org-pdftools-use-freepointer-annot t)) + (org-noter-insert-note (org-noter--get-precise-info))))) + + ;; fix https://github.com/weirdNox/org-noter/pull/93/commits/f8349ae7575e599f375de1be6be2d0d5de4e6cbf + (defun org-noter-set-start-location (&optional arg) + "When opening a session with this document, go to the current location. + With a prefix ARG, remove start location." + (interactive "P") + (org-noter--with-valid-session + (let ((inhibit-read-only t) + (ast (org-noter--parse-root)) + (location (org-noter--doc-approx-location (when (called-interactively-p 'any) 'interactive)))) + (with-current-buffer (org-noter--session-notes-buffer session) + (org-with-wide-buffer + (goto-char (org-element-property :begin ast)) + (if arg + (org-entry-delete nil org-noter-property-note-location) + (org-entry-put nil org-noter-property-note-location + (org-noter--pretty-print-location location)))))))) + (with-eval-after-load 'pdf-annot + (add-hook 'pdf-annot-activate-handler-functions #'org-noter-pdftools-jump-to-note) + ) + ) +#+end_src + +* View EPUBs (nov.el) + +#+begin_src elisp :tangle yes (use-package nov :config (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)) ) #+end_src -* org-noter and PDF Tools -#+begin_src elisp - (use-package org-noter) - - (use-package org-noter-pdftools - :after org-noter - :config - (with-eval-after-load 'pdf-annot - (add-hook 'pdf-annot-activate-handler-functions #'org-noter-pdftools-jump-to-note) - ) - ) +* Zotero (helm-bibtex) +#+begin_src elisp :tangle yes + (use-package helm-bibtex) #+end_src + +#+begin_src elisp :tangle yes + (setq bibtex-completion-bibliography '("~/bibliography/zotero.bib")) +#+end_src \ No newline at end of file diff --git a/system/emacs-misc.el b/projects/dotemacs/modules/emacs-misc.el similarity index 100% rename from system/emacs-misc.el rename to projects/dotemacs/modules/emacs-misc.el diff --git a/system/emacs-misc.org b/projects/dotemacs/modules/emacs-misc.org similarity index 100% rename from system/emacs-misc.org rename to projects/dotemacs/modules/emacs-misc.org diff --git a/system/emacs-org.bash b/projects/dotemacs/modules/emacs-org.bash similarity index 100% rename from system/emacs-org.bash rename to projects/dotemacs/modules/emacs-org.bash diff --git a/system/emacs-org.el b/projects/dotemacs/modules/emacs-org.el similarity index 82% rename from system/emacs-org.el rename to projects/dotemacs/modules/emacs-org.el index b320bf6..e91d15c 100644 --- a/system/emacs-org.el +++ b/projects/dotemacs/modules/emacs-org.el @@ -68,6 +68,24 @@ (require 'org-protocol) (setq org-protocol-default-buffer-for-file-links "*scratch*") ; fixes 'no buffers remain to edit error for org-protocol capturer +(setq org-capture-templates '( + ("p" "Protocol" + entry + (file "inbox.org") + "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?" + ) + ("L" "Protocol Link" + entry + (file "inbox.org") + "* %? [[%:link][%:description]]\n:PROPERTIES:\n:TITLE: %:description\n:URI: %:link\n:CREATED: %U\n:END:" + :prepend nil + :empty-lines 1 + :created t + :kill-buffer t + ) + ) + ) + (setq org-protocol-default-template-key "L") (defun my/org-convert-orgzly-to-org-protocol () diff --git a/projects/dotemacs/modules/emacs-org.org b/projects/dotemacs/modules/emacs-org.org index 99d3ee2..c7edf40 100644 --- a/projects/dotemacs/modules/emacs-org.org +++ b/projects/dotemacs/modules/emacs-org.org @@ -1,7 +1,10 @@ -#+TITLE: Emacs Org-mode Configuration -#+property: header-args :tangle ~/.emacs.d/modules/org.el +#+TITLE: Org Mode Configuration +#+PROPERTY: header-args :tangle yes + +* Org Mode + +** Basic setup -* Core Org Setup #+begin_src elisp (use-package org :config @@ -11,41 +14,130 @@ ("C-c c" . org-capture) :map org-mode-map) ) - (defvar org-directory (concat (getenv "HOME") "/org/")) #+end_src -* Agenda #+begin_src elisp - (setq org-deadline-warning-days 7) - (setq org-agenda-skip-additional-timestamps-same-entry t) - (setq org-agenda-span 'fortnight) - (setq org-agenda-tags-column 'auto) - (setq org-agenda-skip-scheduled-if-deadline-is-shown t) - (setq org-agenda-files (list - (concat org-directory "/0_inbox/inbox.org") - (concat org-directory "/0_inbox/org-gtd-tasks.org") - ) - ) + (setq org-directory (expand-file-name "~/memex/")) #+end_src -* Capture and Protocol +** Looks + +Basic +#+begin_src elisp + (defvar org-pretty-entities t) ; Improve org mode looks + (defvar org-hide-emphasis-markers t) ; Hide emphasis markup + (defvar org-num-mode nil) + (defvar org-startup-folded 'shw2levels) +#+end_src + +Indentation of headers +#+begin_src elisp + (defvar org-startup-indented t) ; Indent org heirarchy + (defvar org-adapt-indentation t) + (defvar org-hide-leading-stars t) ; Minimal Outline + (defvar org-odd-levels-only nil) +#+end_src + +Indentation of lists +#+begin_src elisp + (setq org-list-demote-modify-bullet t) +#+end_src + +Org-modern +#+begin_src elisp + (use-package org-modern + :ensure t + :config + ;; Choose some fonts + (set-face-attribute 'default nil :family "sans-serif") + (set-face-attribute 'variable-pitch nil :family "sans-serif") + (set-face-attribute 'org-modern-symbol nil :family "Iosevka") + + ;; Edit settings + (defvar org-auto-align-tags nil) + (defvar org-tags-column 0) + (defvar org-catch-invisible-edits 'show-and-error) + (defvar org-special-ctrl-a/e t) + (defvar org-insert-heading-respect-content t) + + ;; Org styling, hide markup etc. + (defvar org-hide-emphasis-markers t) + (defvar org-pretty-entities t) + + ;; Agenda styling + (defvar org-agenda-tags-column 0) + (defvar org-agenda-block-separator ?─) + (defvar org-agenda-time-grid + '((daily today require-timed) + (800 1000 1200 1400 1600 1800 2000) + " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")) + (defvar org-agenda-current-time-string + "◀── now ─────────────────────────────────────────────────") + + ;; Ellipsis styling + (defvar org-ellipsis "…") + (set-face-attribute 'org-ellipsis nil :inherit 'default :box nil) + + (global-org-modern-mode) + ) +#+end_src + +Highlight Sourcecode Syntax +#+begin_src elisp + (setq org-src-fontify-natively t) + (setq org-src-tab-acts-natively t) +#+end_src + +Images +#+begin_src elisp + (setq org-startup-with-inline-images t) + (setq org-image-actual-width '(300)) +#+end_src + +** Capture + +#+begin_src elisp + (defvar org-default-notes-file (concat org-directory "inbox.org")) +#+end_src + +*** Org-protocol + +Linux configuration +#+begin_src bash :tangle yes +[Desktop Entry] +Name=org-protocol +Comment=Intercept calls from emacsclient to trigger custom actions +Categories=Other; +Keywords=org-protocol; +Icon=emacs +Type=Application +Exec=emacsclient -- %u +Terminal=false +StartupWMClass=Emacs +MimeType=x-scheme-handler/org-protocol; +#+end_src + +#+begin_src bash :tangle yes +update-desktop-database ~/.local/share/applications/ +#+end_src + +Basic configuration #+begin_src elisp (require 'org-protocol) - (setq org-protocol-default-buffer-for-file-links "*scratch*") - (defvar org-default-notes-file (concat org-directory "/0_inbox/inbox.org")) - (setq org-protocol-default-template-key "L") + (setq org-protocol-default-buffer-for-file-links "*scratch*") ; fixes 'no buffers remain to edit error for org-protocol capturer #+end_src -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar org-capture-templates '( +Org-protocol templates +#+begin_src elisp :tangle yes + (setq org-capture-templates '( ("p" "Protocol" entry - (file "0_inbox/inbox.org") + (file "inbox.org") "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?" ) ("L" "Protocol Link" entry - (file "0_inbox/inbox.org") + (file "inbox.org") "* %? [[%:link][%:description]]\n:PROPERTIES:\n:TITLE: %:description\n:URI: %:link\n:CREATED: %U\n:END:" :prepend nil :empty-lines 1 @@ -56,14 +148,86 @@ ) #+end_src -* TODO Settings #+begin_src elisp - (setq org-todo-keywords - '( - (sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") - (sequence "WAIT(w@/!)" "|" "CNCL(c@)") - ) - ) - (setq org-enforce-todo-dependencies t) - (setq org-log-into-drawer "LOGBOOK") + (setq org-protocol-default-template-key "L") #+end_src + +Convert Orgzly captures to org-protocol captures standard +#+begin_src elisp + (defun my/org-convert-orgzly-to-org-protocol () + "Reformat Orgzly bookmark at point to org-protocol bookmark." + (interactive) + (when (org-at-heading-p) + (let ((headline (nth 4 (org-heading-components)))) + ;; Find and store the link. Delete the link line. + (search-forward-regexp "^https?://\\S-*" nil t) + (let ((link (match-string 0))) + (beginning-of-line) + (kill-line) + ;; Delete any trailing blank spaces + (org-back-to-heading) + (end-of-line) + (when (not (org-on-heading-p)) + (delete-char 1) + ) + ;; Set new headline + (goto-char (org-entry-beginning-position)) + (org-edit-headline (format "[[%s][%s]]" link headline)) + ;; Set new properties + (org-set-property "TITLE" headline) + (org-set-property "URI" link) + (message "Reformatted Orgzly bookmark at point to org-protocol bookmark") + ) + ) + ) + ) +#+end_src + +** Exporting + +#+begin_src elisp :tangle yes + (setq org-export-with-smart-quotes t) + (setq org-export-backends '(beamer html latex md)) +#+end_src + +Export to EPUB +#+begin_src elisp :tangle yes + (use-package ox-epub) +#+end_src + +** org-attach + +#+begin_src elisp + (setq org-attach-id-dir (concat org-directory "/library")) +#+end_src + +** Enable shell scripting support in org-babel + +#+begin_src elisp + (defvar org-babel-do-load-languages 'org-babel-load-languages '((shell . t))) +#+end_src + +** Insert org-mode links from clipboard +#+begin_src elisp :tangle yes + (use-package org-cliplink + :bind + (("C-x p i" . org-cliplink)) + ) +#+end_src + +** Deft +#+begin_src elisp :tangle yes + (use-package deft + :commands (deft) + :init + (defvar deft-extensions '("org")) + (defvar deft-recursive nil) + (defvar deft-use-filename-as-title t) + :config + (defvar deft-directory org-directory) + (defvar deft-recursive t) + (defvar deft-strip-summary-regexp ":PROPERTIES:\n\\(.+\n\\)+:END:\n") + (defvar deft-use-filename-as-title t) + :bind ("C-c n d" . deft) + ) +#+end_src \ No newline at end of file diff --git a/system/emacs-roam.el b/projects/dotemacs/modules/emacs-roam.el similarity index 100% rename from system/emacs-roam.el rename to projects/dotemacs/modules/emacs-roam.el diff --git a/projects/dotemacs/modules/emacs-roam.org b/projects/dotemacs/modules/emacs-roam.org index f9cad9b..11505bc 100644 --- a/projects/dotemacs/modules/emacs-roam.org +++ b/projects/dotemacs/modules/emacs-roam.org @@ -1,42 +1,73 @@ -#+TITLE: Emacs Org-roam Configuration -#+property: header-args :tangle ~/.emacs.d/modules/roam.el +#+TITLE: Org-Roam Configuration +#+PROPERTY: header-args :tangle yes + +* Org-roam + +** Basic org-roam setup -* org-roam Setup #+begin_src elisp - (use-package org-roam - :init (setq org-roam-v2-ack t) - :after org - :config - (org-roam-db-autosync-enable) - (require 'org-roam-dailies) - (setq org-roam-mode-sections - (list #'org-roam-backlinks-section - #'org-roam-reflinks-section - #'org-roam-unlinked-references-section - ) - ) - :bind ( - ("C-c n f" . org-roam-node-find) - ("C-c n g" . org-roam-graph) - ("C-c n r" . org-roam-node-random) - ("C-c n h" . org-roam-node-convert-headline) - ("C-c n i" . org-roam-node-insert) - ("C-c n o" . org-id-get-create) - ("C-c n t" . org-roam-tag-add) - ("C-c n a" . org-roam-alias-add) - ("C-c n l" . org-roam-buffer-display-dedicated) - ) - ) +(use-package org-roam + :init (setq org-roam-v2-ack t) ;; Acknowledge V2 upgrade + :after org + :config + (org-roam-db-autosync-enable) + (require 'org-roam-dailies) + :bind ( + ("C-c n f" . org-roam-node-find) + ("C-c n g" . org-roam-graph) + ("C-c n r" . org-roam-node-random) + ("C-c n h" . org-roam-node-convert-headline) + ("C-c n i" . org-roam-node-insert) + ("C-c n o" . org-id-get-create) + ("C-c n t" . org-roam-tag-add) + ("C-c n a" . org-roam-alias-add) + ("C-c n l" . org-roam-buffer-display-dedicated) + ) + ) #+end_src -* Directories #+begin_src elisp - (setq org-roam-directory (concat org-directory "/1_thinking")) - (setq org-roam-dailies-directory (concat org-directory "/0_inbox/daily")) + (setq org-roam-directory (expand-file-name (concat org-directory "notes"))) + (setq org-roam-dailies-directory (expand-file-name (concat org-directory "daily"))) +#+end_src + +#+begin_src elisp :tangle yes + (use-package sqlite3) + (require 'sqlite3) +#+end_src + +Include subdirectories in org-roam +#+begin_src elisp (setq org-roam-file-exclude-regexp "^[.][.]?/") #+end_src -* Capture Templates +** Display in org-roam-buffer +#+begin_src elisp :tangle yes + (setq org-roam-mode-sections + (list #'org-roam-backlinks-section + #'org-roam-reflinks-section + #'org-roam-unlinked-references-section + ) + ) +#+end_src + +** Filter org-roam nodes find by tag + +#+begin_src elisp :tangle yes + (defun my/org-roam-node-has-tag (node tag) + "Filter function to check if the given NODE has the specified TAG." + (member tag (org-roam-node-tags node)) + ) + + (defun my/org-roam-node-find-by-tag () + "Find and open an Org-roam node based on a specified tag." + (interactive) + (let ((tag (read-string "Enter tag: "))) + (org-roam-node-find nil nil (lambda (node) (my/org-roam-node-has-tag node tag)))) + ) +#+end_src + +** org-roam-capture templates #+begin_src elisp (setq org-roam-capture-templates '( @@ -48,6 +79,7 @@ :immediate-finish t :unnarrowed t ) + ("h" "hugo post" plain "%?" :target (file+head "posts/${slug}.org" @@ -55,6 +87,7 @@ :immediate-finish t :unnarrowed t ) + ("p" "person" plain "%?" :if-new (file+head "people/${slug}.org" @@ -64,7 +97,9 @@ ) ) ) +#+end_src +#+begin_src elisp (setq org-roam-dailies-capture-templates '( ("d" "daily" plain @@ -75,3 +110,31 @@ ) ) #+end_src + +** Move org header to org-roam-daily + +#+begin_src elisp :tangle yes + (defun my/org-move-entry-to-daily-notes () + "Move the current org-mode headline to the daily notes file based on its :CREATED: property." + (interactive) + (let* + ( + (created-prop (org-entry-get nil "CREATED")) + (created-date (when created-prop + (org-parse-time-string created-prop))) + (year (nth 5 created-date)) ; Extract year (6th element) + (month (nth 4 created-date)) ; Extract month (5th element) + (day (nth 3 created-date)) ; Extract day (4th element) + (target-date (format "%04d-%02d-%02d" year month day)) ; Format date string + (target-file (org-roam-dailies-goto target-date)) + ) + (when target-file + (org-cut-subtree) + (find-file target-file) + (goto-char (point-max)) + (unless (bolp) (newline)) + (org-paste-subtree) + ) + ) + ) +#+end_src \ No newline at end of file diff --git a/system/emacs-shell.el b/projects/dotemacs/modules/emacs-shell.el similarity index 100% rename from system/emacs-shell.el rename to projects/dotemacs/modules/emacs-shell.el diff --git a/projects/dotemacs/modules/emacs-shell.org b/projects/dotemacs/modules/emacs-shell.org index f91964d..b5df1fe 100644 --- a/projects/dotemacs/modules/emacs-shell.org +++ b/projects/dotemacs/modules/emacs-shell.org @@ -1,18 +1,86 @@ -#+TITLE: Emacs Shell Configuration -#+property: header-args :tangle ~/.emacs.d/modules/shell.el +#+TITLE: Shell Configuration +#+PROPERTY: header-args :tangle yes + +* Shell + +** Bash completion -* Bash Completion #+begin_src elisp (use-package bash-completion :config (require 'bash-completion) (bash-completion-setup) ) - - (defvar shell-dynamic-complete-functions t) #+end_src -* Frame Management #+begin_src elisp - (add-hook 'server-done-hook (lambda () (delete-frame))) +(defvar shell-dynamic-complete-functions t) #+end_src + +** Eshell + +Add programmable bash completion to Emacs shell-mode +#+begin_src elisp :tangle yes + (require 'bash-completion) + (add-hook 'eshell-mode-hook + (lambda () + (add-hook 'completion-at-point-functions + 'bash-completion-capf-nonexclusive nil t + ) + ) + ) +#+end_src + +Use colors in eshell +#+begin_src elisp :tangle yes + (use-package xterm-color + :commands (xterm-color-filter) + ) + + (use-package eshell + :after xterm-color + :config + (define-key eshell-hist-mode-map (kbd "M-r") #'consult-history) + (add-hook 'eshell-mode-hook + (lambda () + (setenv "TERM" "xterm-256color"))) + (add-hook 'eshell-before-prompt-hook (setq xterm-color-preserve-properties t)) + (add-to-list 'eshell-preoutput-filter-functions 'xterm-color-filter) + (setq eshell-output-filter-functions + (remove 'eshell-handle-ansi-color eshell-output-filter-functions) + ) + ) +#+end_src + +Eshell completion +#+begin_src elisp :tangle yes + (add-hook 'eshell-mode-hook + (lambda () + (add-hook 'completion-at-point-functions + 'bash-completion-capf-nonexclusive nil t))) +#+end_src + +Emulate A Terminal (EAT) +#+begin_src elisp :tangle yes + (use-package eat + :config + ;; For `eat-eshell-mode'. + (add-hook 'eshell-load-hook #'eat-eshell-mode) + + ;; For `eat-eshell-visual-command-mode'. + (add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode) + ) +#+end_src + +* Server Actuation (Bash Integration) + +Ensure that emacsclient always opens in a GUI frame by default when called from the shell. + +#+begin_src bash :tangle ~/.bash_aliases + # Use emacsclient to open files in the GUI, starting daemon if needed + alias em="emacsclient -c -a ''" + + # Set emacsclient as the default editor + export EDITOR="emacsclient -c -a ''" + export VISUAL="emacsclient -c -a ''" +#+end_src \ No newline at end of file diff --git a/projects/dotemacs/modules/emacs-ui.el b/projects/dotemacs/modules/emacs-ui.el new file mode 100644 index 0000000..51c0c75 --- /dev/null +++ b/projects/dotemacs/modules/emacs-ui.el @@ -0,0 +1,16 @@ +(when (fboundp 'tool-bar-mode) (tool-bar-mode -1)) +(when (fboundp 'menu-bar-mode) (menu-bar-mode -1)) +(when (fboundp 'scroll-bar-mode) (scroll-bar-mode -1)) + +(setq inhibit-startup-screen t) +(setq initial-scratch-message nil) + +(set-face-attribute 'default nil :family "sans-serif" :height 120) +(set-face-attribute 'variable-pitch nil :family "sans-serif") + +(use-package org-modern + :ensure t + :config + (set-face-attribute 'org-modern-symbol nil :family "Iosevka") + (global-org-modern-mode) + ) diff --git a/projects/dotemacs/modules/emacs-ui.org b/projects/dotemacs/modules/emacs-ui.org index f7a2c93..7b1f916 100644 --- a/projects/dotemacs/modules/emacs-ui.org +++ b/projects/dotemacs/modules/emacs-ui.org @@ -1,59 +1,32 @@ #+TITLE: Emacs UI Configuration -#+property: header-args :tangle ~/.emacs.d/modules/ui.el +#+PROPERTY: header-args :tangle yes * Appearance + +Basic UI settings for a cleaner look. + #+begin_src elisp - (defvar org-pretty-entities t) ; Improve org mode looks - (defvar org-hide-emphasis-markers t) ; Hide emphasis markup - (defvar org-num-mode nil) - (defvar org-startup-folded 'shw2levels) - (defvar org-startup-indented t) ; Indent org heirarchy - (defvar org-adapt-indentation t) - (defvar org-hide-leading-stars t) ; Minimal Outline - (defvar org-odd-levels-only nil) + (when (fboundp 'tool-bar-mode) (tool-bar-mode -1)) + (when (fboundp 'menu-bar-mode) (menu-bar-mode -1)) + (when (fboundp 'scroll-bar-mode) (scroll-bar-mode -1)) + + (setq inhibit-startup-screen t) + (setq initial-scratch-message nil) #+end_src -* Org-modern +* Fonts + +#+begin_src elisp + (set-face-attribute 'default nil :family "sans-serif" :height 120) + (set-face-attribute 'variable-pitch nil :family "sans-serif") +#+end_src + +* Org-modern (UI elements) #+begin_src elisp (use-package org-modern :ensure t :config - ;; Choose some fonts - (set-face-attribute 'default nil :family "sans-serif") - (set-face-attribute 'variable-pitch nil :family "sans-serif") (set-face-attribute 'org-modern-symbol nil :family "Iosevka") - - ;; Edit settings - (defvar org-auto-align-tags nil) - (defvar org-tags-column 0) - (defvar org-catch-invisible-edits 'show-and-error) - (defvar org-special-ctrl-a/e t) - (defvar org-insert-heading-respect-content t) - - ;; Org styling, hide markup etc. - (defvar org-hide-emphasis-markers t) - (defvar org-pretty-entities t) - - ;; Agenda styling - (defvar org-agenda-tags-column 0) - (defvar org-agenda-block-separator ?─) - (defvar org-agenda-time-grid - '((daily today require-timed) - (800 1000 1200 1400 1600 1800 2000) - " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")) - (defvar org-agenda-current-time-string - "◀── now ─────────────────────────────────────────────────") - - ;; Ellipsis styling - (defvar org-ellipsis "…") - (set-face-attribute 'org-ellipsis nil :inherit 'default :box nil) - - (global-org-modern-mode) + (global-org-modern-mode) ) #+end_src - -* Syntax Highlighting -#+begin_src elisp - (setq org-src-fontify-natively t) - (setq org-src-tab-acts-natively t) -#+end_src diff --git a/system/emacs-writing.bash b/projects/dotemacs/modules/emacs-writing.bash similarity index 100% rename from system/emacs-writing.bash rename to projects/dotemacs/modules/emacs-writing.bash diff --git a/system/emacs-writing.el b/projects/dotemacs/modules/emacs-writing.el similarity index 100% rename from system/emacs-writing.el rename to projects/dotemacs/modules/emacs-writing.el diff --git a/projects/dotemacs/modules/emacs-writing.org b/projects/dotemacs/modules/emacs-writing.org index 863c80b..f1476cc 100644 --- a/projects/dotemacs/modules/emacs-writing.org +++ b/projects/dotemacs/modules/emacs-writing.org @@ -1,7 +1,195 @@ -#+TITLE: Emacs Writing Configuration -#+property: header-args :tangle ~/.emacs.d/modules/writing.el +#+TITLE: Reading and Writing Configuration +#+PROPERTY: header-args :tangle yes + +* Text and Case + +** Convert DOuble capitals to single capitals + +#+begin_src elisp :tangle yes + (defun my/dcaps-to-scaps () + "Convert word in DOuble CApitals to Single Capitals." + (interactive) + (and (= ?w (char-syntax (char-before))) + (save-excursion + (and (if (called-interactively-p) + (skip-syntax-backward "w") + (= -3 (skip-syntax-backward "w")) + ) + (let (case-fold-search) + (looking-at "\\b[[:upper:]]\\{2\\}[[:lower:]]") + ) + (capitalize-word 1) + ) + ) + ) + ) +#+end_src + +Then, let’s define a minor mode for it to be activated. +#+begin_src elisp :tangle yes + (define-minor-mode my-dubcaps-mode + "Toggle 'my-dubcaps-mode' and convert words in DOuble CApitals to Single Capitals as you type." + :init-value nil + :lighter (" DC") + (if my-dubcaps-mode + (add-hook 'post-self-insert-hook #'my/dcaps-to-scaps nil 'local) + (remove-hook 'post-self-insert-hook #'my/dcaps-to-scaps 'local))) +#+end_src + + Finally, let’s add a hook so that it is on for all the text files Emacs opens. +#+begin_src elisp :tangle yes + (add-hook 'text-mode-hook #'my-dubcaps-mode) +#+end_src + +Also, since we add a minor mode string (it might be useful sometimes), currently I prefer to diminish it. +#+begin_src elisp :tangle yes + (defun my/diminish-dubcaps () + (interactive) + (diminish 'my-dubcaps-mode "")) + (add-hook 'my-dubcaps-mode-hook 'my/diminish-dubcaps) +#+end_src + +* Reading and Writing + +** Move correctly over camelCased words + +#+begin_src elisp + (subword-mode) +#+end_src + +** Understand the more common sentence with double space + +#+begin_src elisp + (setq sentence-end-double-space nil) +#+end_src + +** Join lines into paragraph + +#+begin_src elisp + (defun my/fill-or-unfill-paragraph (&optional unfill region) + "Fill paragraph (or REGION). With the prefix argument UNFILL, fill it instead." + (interactive (progn + (barf-if-buffer-read-only) + (list (if current-prefix-arg 'fill) t))) + (let ((fill-column (if unfill fill-column (point-max)))) + (fill-paragraph nil region))) + + (bind-key "M-q" 'my/fill-or-unfill-paragraph) +#+end_src + +#+begin_src elisp + (defun my/fill-or-unfill-all-paragraphs (&optional unfill) + "Fill or unfill all paragraphs in the current buffer. +With the prefix argument UNFILL, fill them instead." + (interactive (list (if current-prefix-arg 'fill))) + (let ((fill-column (if unfill fill-column (point-max)))) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (fill-paragraph nil t) + (forward-paragraph))))) + +(bind-key "M-Q" 'my/fill-or-unfill-all-paragraphs) +#+end_src + +#+begin_src elisp + (remove-hook 'text-mode-hook #'turn-on-auto-fill) + (add-hook 'text-mode-hook 'turn-on-visual-line-mode) +#+end_src + +** Expand some words with auto-correct + + #+begin_src elisp :tangle yes + (setq save-abbrevs 'silently) + (setq-default abbrev-mode t) + #+end_src + +** ediff + +#+begin_src elisp :tangle yes + (setq ediff-window-setup-function 'ediff-setup-windows-plain) + (setq ediff-split-window-function 'split-window-horizontally) +#+end_src + +** tramp + +#+begin_src elisp :tangle yes + (setq tramp-default-method "ssh" + tramp-backup-directory-alist backup-directory-alist + tramp-ssh-controlmaster-options "ssh") +#+end_src + +** Clean up space +#+begin_src elisp :tangle yes + (bind-key "M-SPC" 'cycle-spacing) +#+end_src + +** Transform links into org links + +#+begin_src elisp :tangle yes + (defun my/transform-html-links-to-org () + "Transform all HTML links in the current buffer into 'org-mode' links." + (interactive) + (goto-char (point-min)) + (while (re-search-forward "\\(.*?\\)" nil t) + (replace-match (org-make-link-string (match-string 1) (match-string 2))))) +#+end_src + +** Count words per minute +#+begin_src elisp :tangle yes + (require 'org-clock) + (defun my/org-entry-wpm () + (interactive) + (save-restriction + (save-excursion + (org-narrow-to-subtree) + (goto-char (point-min)) + (let* ((words (count-words-region (point-min) (point-max))) + + (minutes (org-clock-sum-current-item)) + (wpm (/ words minutes))) + (message "WPM: %d (words: %d, minutes: %d)" wpm words minutes) + (kill-new (number-to-string wpm)) + ) + ) + ) + ) +#+end_src + +** Enable dict mode + #+begin_src elisp :tangle yes + (setq dictionary-server "automatic") + #+end_src + +** Pick out passive voice and weasel words +#+begin_src elisp :tangle yes + (use-package writegood-mode + :diminish writegood-mode + :config + (progn (add-hook 'text-mode-hook 'writegood-mode)) + ) +#+end_src + +** Org-babel docker +#+begin_src elisp :tangle yes + (use-package ob-docker-build + :straight (ob-docker-build :type git :host github :repo "ifitzpat/ob-docker-build") + :defer t + :config + (add-to-list 'org-babel-load-languages '(docker-build . t)) + (org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages) + ) +#+end_src + +* Spelling and syntax + +** Spell checking + +This requires installation of hunspell +#+begin_src bash :tangle yes + sudo apt install hunspell +#+end_src -* Spell Checking #+begin_src elisp (use-package flyspell :config (setq ispell-program-name "hunspell" @@ -17,32 +205,50 @@ ) #+end_src -* Syntax Checking +** Flyspell correct +#+begin_src elisp :tangle yes + (use-package flyspell-correct + :after flyspell + :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-wrapper)) + ) +#+end_src + +** Flycheck + +Needs external checkers installed + #+begin_src elisp (use-package flycheck - :init (global-flycheck-mode) + :defer t :diminish (flycheck-mode . "") :config - (add-hook 'after-init-hook #'global-flycheck-mode) (setq flycheck-emacs-lisp-load-path 'inherit) - (setq flycheck-emacs-lisp-load-path (concat user-emacs-directory "straight/build")) + (setq flycheck-emacs-lisp-load-path (concat user-emacs-directory "straight/build"))) + +#+end_src + +** Flycheck bash +#+begin_src bash :tangle yes + sudo apt install devscripts +#+end_src + +#+begin_src elisp :tangle yes + (use-package flycheck-checkbashisms + :config + (flycheck-checkbashisms-setup) + ) +#+end_src + +** Yaml +#+begin_src elisp :tangle yes + (use-package yaml-mode + :config + (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) + (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode)) ) #+end_src -* Text Manipulation -#+begin_src elisp - (subword-mode) - (setq sentence-end-double-space nil) - - (defun my/fill-or-unfill-paragraph (&optional unfill region) - "Fill paragraph (or REGION). With the prefix argument UNFILL, fill it instead." - (interactive (progn - (barf-if-buffer-read-only) - (list (if current-prefix-arg 'fill) t))) - (let ((fill-column (if unfill fill-column (point-max)))) - (fill-paragraph nil region))) - - (bind-key "M-q" 'my/fill-or-unfill-paragraph) - - (add-hook 'text-mode-hook 'turn-on-visual-line-mode) -#+end_src +** Docker +#+begin_src elisp :tangle yes + (use-package docker-compose-mode) +#+end_src \ No newline at end of file diff --git a/system/ATOMIC_NOTES_SETUP.org b/projects/dotemacs/templates/ATOMIC_NOTES_SETUP.org similarity index 100% rename from system/ATOMIC_NOTES_SETUP.org rename to projects/dotemacs/templates/ATOMIC_NOTES_SETUP.org diff --git a/system/templates.org b/projects/dotemacs/templates/templates.org similarity index 100% rename from system/templates.org rename to projects/dotemacs/templates/templates.org diff --git a/projects/infrastructure/docs/qubes-npu-setup.org b/projects/infrastructure/docs/qubes-npu-setup.org new file mode 100644 index 0000000..d78d2d9 --- /dev/null +++ b/projects/infrastructure/docs/qubes-npu-setup.org @@ -0,0 +1,90 @@ +#+TITLE: Qubes NPU Setup - sys-ai +#+AUTHOR: Amr +#+CREATED: [2026-04-24 Fri] +#+BEGIN_COMMENT +Documentation for setting up sys-ai Qube with AMD Ryzen AI NPU for llama.cpp. +#+END_COMMENT + +* Hardware + +- *Laptop:* Framework Laptop 13 (AMD) +- *CPU:* AMD Ryzen AI 5 340 (6 cores, no SMT) +- *NPU:* AMD XDNA2 (Strix Point) - c2:00.1 / dom0:00_08.2-00_00.1 +- *RAM:* 96GB total + +* Current Progress + +** DONE [X] Create sys-ai AppVM (HVM, 64GB, 2 vCPUs) + +#+begin_src bash +# Run in dom0 +qvm-create --label purple --property netvm=sys-firewall --property memory=65536 --property vcpus=2 --property virt_mode=HVM sys-ai +#+end_src + +** DONE [X] Attach NPU PCI device to sys-ai + +#+begin_src bash +# Run in dom0 +qvm-pci attach -o no-strict-reset=true sys-ai dom0:00_08.2-00_00.1 --persistent +#+end_src + +** TODO [ ] Fix repository configuration in sys-ai + +*Status:* Package repositories missing in fedora-43-ai template. Fedora 43 uses DNF5 with different repo paths. + +*Next Step:* Qubes OS templates typically get packages installed via `qubes-vm-update` or dom0 commands. Try the Qubes way to install packages. + +** TODO [ ] Verify NPU is accessible inside sys-ai + +#+begin_src bash +# Install pciutils +sudo dnf install pciutils + +# Check NPU is visible +lspci | grep -i neural +#+end_src + +** TODO [ ] Install AMD NPU drivers in sys-ai + +#+begin_src bash +# Enable Copr repository +sudo dnf copr enable xanderlent/amd-npu-driver + +# Install drivers +sudo dnf install xrt xdna-driver tcsh + +# Setup environment +source /usr/xrt/setup.sh + +# Verify NPU detection +xrt-smi examine +#+end_src + +** TODO [ ] Build llama.cpp with AMD XDNA2 NPU backend + +#+begin_src bash +# Install build dependencies +sudo dnf install cmake gcc-c++ python3.11 git + +# Clone NPU fork +git clone https://github.com/BrandedTamarasu-glitch/OllamaAMDNPU.git +cd OllamaAMDNPU + +# Build with NPU backend +cmake -B build -DGGML_XDNA=ON -DGGML_BACKEND_DL=ON -DBUILD_SHARED_LIBS=ON +cmake --build build --parallel +#+end_src + +** TODO [ ] Download model and test inference + +#+begin_src bash +# Download GGUF model (Qwen3 1B or 3B quantized) +# ... model download command ... + +# Run with NPU offload +./build/bin/llama-cli -m model.gguf -p "Hello" -n 256 --npu-split 1 +#+end_src + +* Next Step + +Run the repository fix commands from the "Fix repository" step above. diff --git a/projects/opencortex b/projects/opencortex index 5a16436..d177a12 160000 --- a/projects/opencortex +++ b/projects/opencortex @@ -1 +1 @@ -Subproject commit 5a164363b83ee8ed3876f1339f7616cb2f2b8cac +Subproject commit d177a12469877f3239ba07dc5590f258a05ce4e2 diff --git a/projects/opencortex-contrib b/projects/opencortex-contrib index 5b6f4c1..2db53fa 160000 --- a/projects/opencortex-contrib +++ b/projects/opencortex-contrib @@ -1 +1 @@ -Subproject commit 5b6f4c18d17e0366ac6491c4c514007270aa4aca +Subproject commit 2db53fae177e1adae86b1c9e0765529f2fcb8b13 diff --git a/quicklisp.lisp b/quicklisp.lisp new file mode 100644 index 0000000..6cda472 --- /dev/null +++ b/quicklisp.lisp @@ -0,0 +1,1757 @@ +;;;; +;;;; This is quicklisp.lisp, the quickstart file for Quicklisp. To use +;;;; it, start Lisp, then (load "quicklisp.lisp") +;;;; +;;;; Quicklisp is beta software and comes with no warranty of any kind. +;;;; +;;;; For more information about the Quicklisp beta, see: +;;;; +;;;; http://www.quicklisp.org/beta/ +;;;; +;;;; If you have any questions or comments about Quicklisp, please +;;;; contact: +;;;; +;;;; Zach Beane +;;;; + +(cl:in-package #:cl-user) +(cl:defpackage #:qlqs-user + (:use #:cl)) +(cl:in-package #:qlqs-user) + +(defpackage #:qlqs-info + (:export #:*version*)) + +(defvar qlqs-info:*version* "2015-01-28") + +(defpackage #:qlqs-impl + (:use #:cl) + (:export #:*implementation*) + (:export #:definterface + #:defimplementation) + (:export #:lisp + #:abcl + #:allegro + #:ccl + #:clasp + #:clisp + #:cmucl + #:cormanlisp + #:ecl + #:gcl + #:lispworks + #:mkcl + #:scl + #:sbcl)) + +(defpackage #:qlqs-impl-util + (:use #:cl #:qlqs-impl) + (:export #:call-with-quiet-compilation)) + +(defpackage #:qlqs-network + (:use #:cl #:qlqs-impl) + (:export #:open-connection + #:write-octets + #:read-octets + #:close-connection + #:with-connection)) + +(defpackage #:qlqs-progress + (:use #:cl) + (:export #:make-progress-bar + #:start-display + #:update-progress + #:finish-display)) + +(defpackage #:qlqs-http + (:use #:cl #:qlqs-network #:qlqs-progress) + (:export #:fetch + #:*proxy-url* + #:*maximum-redirects* + #:*default-url-defaults*)) + +(defpackage #:qlqs-minitar + (:use #:cl) + (:export #:unpack-tarball)) + +(defpackage #:quicklisp-quickstart + (:use #:cl #:qlqs-impl #:qlqs-impl-util #:qlqs-http #:qlqs-minitar) + (:export #:install + #:help + #:*proxy-url* + #:*asdf-url* + #:*quicklisp-tar-url* + #:*setup-url* + #:*help-message* + #:*after-load-message* + #:*after-initial-setup-message*)) + + +;;; +;;; Defining implementation-specific packages and functionality +;;; + +(in-package #:qlqs-impl) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defun error-unimplemented (&rest args) + (declare (ignore args)) + (error "Not implemented"))) + +(defmacro neuter-package (name) + `(eval-when (:compile-toplevel :load-toplevel :execute) + (let ((definition (fdefinition 'error-unimplemented))) + (do-external-symbols (symbol ,(string name)) + (unless (fboundp symbol) + (setf (fdefinition symbol) definition)))))) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defun feature-expression-passes-p (expression) + (cond ((keywordp expression) + (member expression *features*)) + ((consp expression) + (case (first expression) + (or + (some 'feature-expression-passes-p (rest expression))) + (and + (every 'feature-expression-passes-p (rest expression))))) + (t (error "Unrecognized feature expression -- ~S" expression))))) + + +(defmacro define-implementation-package (feature package-name &rest options) + (let* ((output-options '((:use) + (:export #:lisp))) + (prep (cdr (assoc :prep options))) + (class-option (cdr (assoc :class options))) + (class (first class-option)) + (superclasses (rest class-option)) + (import-options '()) + (effectivep (feature-expression-passes-p feature))) + (dolist (option options) + (ecase (first option) + ((:prep :class)) + ((:import-from + :import) + (push option import-options)) + ((:export + :shadow + :intern + :documentation) + (push option output-options)) + ((:reexport-from) + (push (cons :export (cddr option)) output-options) + (push (cons :import-from (cdr option)) import-options)))) + `(eval-when (:compile-toplevel :load-toplevel :execute) + ,@(when effectivep + prep) + (defclass ,class ,superclasses ()) + (defpackage ,package-name ,@output-options + ,@(when effectivep + import-options)) + ,@(when effectivep + `((setf *implementation* (make-instance ',class)))) + ,@(unless effectivep + `((neuter-package ,package-name)))))) + +(defmacro definterface (name lambda-list &body options) + (let* ((forbidden (intersection lambda-list lambda-list-keywords)) + (gf-options (remove :implementation options :key #'first)) + (implementations (set-difference options gf-options))) + (when forbidden + (error "~S not allowed in definterface lambda list" forbidden)) + (flet ((method-option (class body) + `(:method ((*implementation* ,class) ,@lambda-list) + ,@body))) + (let ((generic-name (intern (format nil "%~A" name)))) + `(eval-when (:compile-toplevel :load-toplevel :execute) + (defgeneric ,generic-name (lisp ,@lambda-list) + ,@gf-options + ,@(mapcar (lambda (implementation) + (destructuring-bind (class &rest body) + (rest implementation) + (method-option class body))) + implementations)) + (defun ,name ,lambda-list + (,generic-name *implementation* ,@lambda-list))))))) + +(defmacro defimplementation (name-and-options + lambda-list &body body) + (destructuring-bind (name &key (for t) qualifier) + (if (consp name-and-options) + name-and-options + (list name-and-options)) + (unless for + (error "You must specify an implementation name.")) + (let ((generic-name (find-symbol (format nil "%~A" name)))) + (unless (and generic-name + (fboundp generic-name)) + (error "~S does not name an implementation function" name)) + `(defmethod ,generic-name + ,@(when qualifier (list qualifier)) + ,(list* `(*implementation* ,for) lambda-list) ,@body)))) + + +;;; Bootstrap implementations + +(defvar *implementation* nil) +(defclass lisp () ()) + + +;;; Allegro Common Lisp + +(define-implementation-package :allegro #:qlqs-allegro + (:documentation + "Allegro Common Lisp - http://www.franz.com/products/allegrocl/") + (:class allegro) + (:reexport-from #:socket + #:make-socket) + (:reexport-from #:excl + #:read-vector)) + + +;;; Armed Bear Common Lisp + +(define-implementation-package :abcl #:qlqs-abcl + (:documentation + "Armed Bear Common Lisp - http://common-lisp.net/project/armedbear/") + (:class abcl) + (:reexport-from #:system + #:make-socket + #:get-socket-stream)) + +;;; Clozure CL + +(define-implementation-package :ccl #:qlqs-ccl + (:documentation + "Clozure Common Lisp - http://www.clozure.com/clozurecl.html") + (:class ccl) + (:reexport-from #:ccl + #:make-socket)) + + +;;; CLASP + +(define-implementation-package :clasp #:qlqs-clasp + (:documentation "CLASP - http://github.com/drmeister/clasp") + (:class clasp) + (:prep + (require 'sockets)) + (:intern #:host-network-address) + (:reexport-from #:sb-bsd-sockets + #:get-host-by-name + #:host-ent-address + #:socket-connect + #:socket-make-stream + #:inet-socket)) + + +;;; GNU CLISP + +(define-implementation-package :clisp #:qlqs-clisp + (:documentation "GNU CLISP - http://clisp.cons.org/") + (:class clisp) + (:reexport-from #:socket + #:socket-connect) + (:reexport-from #:ext + #:read-byte-sequence)) + + +;;; CMUCL + +(define-implementation-package :cmu #:qlqs-cmucl + (:documentation "CMU Common Lisp - http://www.cons.org/cmucl/") + (:class cmucl) + (:reexport-from #:ext + #:*gc-verbose*) + (:reexport-from #:system + #:make-fd-stream) + (:reexport-from #:extensions + #:connect-to-inet-socket)) + +(defvar qlqs-cmucl:*gc-verbose* nil) + + +;;; Scieneer CL + +(define-implementation-package :scl #:qlqs-scl + (:documentation "Scieneer Common Lisp - http://www.scieneer.com/scl/") + (:class scl) + (:reexport-from #:system + #:make-fd-stream) + (:reexport-from #:extensions + #:connect-to-inet-socket)) + +;;; ECL + +(define-implementation-package :ecl #:qlqs-ecl + (:documentation "ECL - http://ecls.sourceforge.net/") + (:class ecl) + (:prep + (require 'sockets)) + (:intern #:host-network-address) + (:reexport-from #:sb-bsd-sockets + #:get-host-by-name + #:host-ent-address + #:socket-connect + #:socket-make-stream + #:inet-socket)) + + +;;; LispWorks + +(define-implementation-package :lispworks #:qlqs-lispworks + (:documentation "LispWorks - http://www.lispworks.com/") + (:class lispworks) + (:prep + (require "comm")) + (:reexport-from #:comm + #:open-tcp-stream + #:get-host-entry)) + + +;;; SBCL + +(define-implementation-package :sbcl #:qlqs-sbcl + (:class sbcl) + (:documentation + "Steel Bank Common Lisp - http://www.sbcl.org/") + (:prep + (require 'sb-bsd-sockets)) + (:intern #:host-network-address) + (:reexport-from #:sb-ext + #:compiler-note) + (:reexport-from #:sb-bsd-sockets + #:get-host-by-name + #:inet-socket + #:host-ent-address + #:socket-connect + #:socket-make-stream)) + +;;; MKCL + +(define-implementation-package :mkcl #:qlqs-mkcl + (:class mkcl) + (:documentation + "ManKai Common Lisp - http://common-lisp.net/project/mkcl/") + (:prep + (require 'sockets)) + (:intern #:host-network-address) + (:reexport-from #:sb-bsd-sockets + #:get-host-by-name + #:inet-socket + #:host-ent-address + #:socket-connect + #:socket-make-stream)) + +;;; +;;; Utility function +;;; + +(in-package #:qlqs-impl-util) + +(definterface call-with-quiet-compilation (fun) + (:implementation t + (let ((*load-verbose* nil) + (*compile-verbose* nil) + (*load-print* nil) + (*compile-print* nil)) + (handler-bind ((warning #'muffle-warning)) + (funcall fun))))) + +(defimplementation (call-with-quiet-compilation :for sbcl :qualifier :around) + (fun) + (declare (ignorable fun)) + (handler-bind ((qlqs-sbcl:compiler-note #'muffle-warning)) + (call-next-method))) + +(defimplementation (call-with-quiet-compilation :for cmucl :qualifier :around) + (fun) + (declare (ignorable fun)) + (let ((qlqs-cmucl:*gc-verbose* nil)) + (call-next-method))) + + +;;; +;;; Low-level networking implementations +;;; + +(in-package #:qlqs-network) + +(definterface host-address (host) + (:implementation t + host) + (:implementation mkcl + (qlqs-mkcl:host-ent-address (qlqs-mkcl:get-host-by-name host))) + (:implementation sbcl + (qlqs-sbcl:host-ent-address (qlqs-sbcl:get-host-by-name host)))) + +(definterface open-connection (host port) + (:implementation t + (declare (ignorable host port)) + (error "Sorry, quicklisp in implementation ~S is not supported yet." + (lisp-implementation-type))) + (:implementation allegro + (qlqs-allegro:make-socket :remote-host host + :remote-port port)) + (:implementation abcl + (let ((socket (qlqs-abcl:make-socket host port))) + (qlqs-abcl:get-socket-stream socket :element-type '(unsigned-byte 8)))) + (:implementation ccl + (qlqs-ccl:make-socket :remote-host host + :remote-port port)) + (:implementation clasp + (let* ((endpoint (qlqs-clasp:host-ent-address + (qlqs-clasp:get-host-by-name host))) + (socket (make-instance 'qlqs-clasp:inet-socket + :protocol :tcp + :type :stream))) + (qlqs-clasp:socket-connect socket endpoint port) + (qlqs-clasp:socket-make-stream socket + :element-type '(unsigned-byte 8) + :input t + :output t + :buffering :full))) + (:implementation clisp + (qlqs-clisp:socket-connect port host :element-type '(unsigned-byte 8))) + (:implementation cmucl + (let ((fd (qlqs-cmucl:connect-to-inet-socket host port))) + (qlqs-cmucl:make-fd-stream fd + :element-type '(unsigned-byte 8) + :binary-stream-p t + :input t + :output t))) + (:implementation scl + (let ((fd (qlqs-scl:connect-to-inet-socket host port))) + (qlqs-scl:make-fd-stream fd + :element-type '(unsigned-byte 8) + :input t + :output t))) + (:implementation ecl + (let* ((endpoint (qlqs-ecl:host-ent-address + (qlqs-ecl:get-host-by-name host))) + (socket (make-instance 'qlqs-ecl:inet-socket + :protocol :tcp + :type :stream))) + (qlqs-ecl:socket-connect socket endpoint port) + (qlqs-ecl:socket-make-stream socket + :element-type '(unsigned-byte 8) + :input t + :output t + :buffering :full))) + (:implementation lispworks + (qlqs-lispworks:open-tcp-stream host port + :direction :io + :errorp t + :read-timeout nil + :element-type '(unsigned-byte 8) + :timeout 5)) + (:implementation mkcl + (let* ((endpoint (qlqs-mkcl:host-ent-address + (qlqs-mkcl:get-host-by-name host))) + (socket (make-instance 'qlqs-mkcl:inet-socket + :protocol :tcp + :type :stream))) + (qlqs-mkcl:socket-connect socket endpoint port) + (qlqs-mkcl:socket-make-stream socket + :element-type '(unsigned-byte 8) + :input t + :output t + :buffering :full))) + (:implementation sbcl + (let* ((endpoint (qlqs-sbcl:host-ent-address + (qlqs-sbcl:get-host-by-name host))) + (socket (make-instance 'qlqs-sbcl:inet-socket + :protocol :tcp + :type :stream))) + (qlqs-sbcl:socket-connect socket endpoint port) + (qlqs-sbcl:socket-make-stream socket + :element-type '(unsigned-byte 8) + :input t + :output t + :buffering :full)))) + +(definterface read-octets (buffer connection) + (:implementation t + (read-sequence buffer connection)) + (:implementation allegro + (qlqs-allegro:read-vector buffer connection)) + (:implementation clisp + (qlqs-clisp:read-byte-sequence buffer connection + :no-hang nil + :interactive t))) + +(definterface write-octets (buffer connection) + (:implementation t + (write-sequence buffer connection) + (finish-output connection))) + +(definterface close-connection (connection) + (:implementation t + (ignore-errors (close connection)))) + +(definterface call-with-connection (host port fun) + (:implementation t + (let (connection) + (unwind-protect + (progn + (setf connection (open-connection host port)) + (funcall fun connection)) + (when connection + (close connection)))))) + +(defmacro with-connection ((connection host port) &body body) + `(call-with-connection ,host ,port (lambda (,connection) ,@body))) + + +;;; +;;; A text progress bar +;;; + +(in-package #:qlqs-progress) + +(defclass progress-bar () + ((start-time + :initarg :start-time + :accessor start-time) + (end-time + :initarg :end-time + :accessor end-time) + (progress-character + :initarg :progress-character + :accessor progress-character) + (character-count + :initarg :character-count + :accessor character-count + :documentation "How many characters wide is the progress bar?") + (characters-so-far + :initarg :characters-so-far + :accessor characters-so-far) + (update-interval + :initarg :update-interval + :accessor update-interval + :documentation "Update the progress bar display after this many + internal-time units.") + (last-update-time + :initarg :last-update-time + :accessor last-update-time + :documentation "The display was last updated at this time.") + (total + :initarg :total + :accessor total + :documentation "The total number of units tracked by this progress bar.") + (progress + :initarg :progress + :accessor progress + :documentation "How far in the progress are we?") + (pending + :initarg :pending + :accessor pending + :documentation "How many raw units should be tracked in the next + display update?")) + (:default-initargs + :progress-character #\= + :character-count 50 + :characters-so-far 0 + :update-interval (floor internal-time-units-per-second 4) + :last-update-time 0 + :total 0 + :progress 0 + :pending 0)) + +(defgeneric start-display (progress-bar)) +(defgeneric update-progress (progress-bar unit-count)) +(defgeneric update-display (progress-bar)) +(defgeneric finish-display (progress-bar)) +(defgeneric elapsed-time (progress-bar)) +(defgeneric units-per-second (progress-bar)) + +(defmethod start-display (progress-bar) + (setf (last-update-time progress-bar) (get-internal-real-time)) + (setf (start-time progress-bar) (get-internal-real-time)) + (fresh-line) + (finish-output)) + +(defmethod update-display (progress-bar) + (incf (progress progress-bar) (pending progress-bar)) + (setf (pending progress-bar) 0) + (setf (last-update-time progress-bar) (get-internal-real-time)) + (let* ((showable (floor (character-count progress-bar) + (/ (total progress-bar) (progress progress-bar)))) + (needed (- showable (characters-so-far progress-bar)))) + (setf (characters-so-far progress-bar) showable) + (dotimes (i needed) + (write-char (progress-character progress-bar))) + (finish-output))) + +(defmethod update-progress (progress-bar unit-count) + (incf (pending progress-bar) unit-count) + (let ((now (get-internal-real-time))) + (when (< (update-interval progress-bar) + (- now (last-update-time progress-bar))) + (update-display progress-bar)))) + +(defmethod finish-display (progress-bar) + (update-display progress-bar) + (setf (end-time progress-bar) (get-internal-real-time)) + (terpri) + (format t "~:D bytes in ~$ seconds (~$KB/sec)" + (total progress-bar) + (elapsed-time progress-bar) + (/ (units-per-second progress-bar) 1024)) + (finish-output)) + +(defmethod elapsed-time (progress-bar) + (/ (- (end-time progress-bar) (start-time progress-bar)) + internal-time-units-per-second)) + +(defmethod units-per-second (progress-bar) + (if (plusp (elapsed-time progress-bar)) + (/ (total progress-bar) (elapsed-time progress-bar)) + 0)) + +(defun kb/sec (progress-bar) + (/ (units-per-second progress-bar) 1024)) + + + +(defparameter *uncertain-progress-chars* "?") + +(defclass uncertain-size-progress-bar (progress-bar) + ((progress-char-index + :initarg :progress-char-index + :accessor progress-char-index) + (units-per-char + :initarg :units-per-char + :accessor units-per-char)) + (:default-initargs + :total 0 + :progress-char-index 0 + :units-per-char (floor (expt 1024 2) 50))) + +(defmethod update-progress :after ((progress-bar uncertain-size-progress-bar) + unit-count) + (incf (total progress-bar) unit-count)) + +(defmethod progress-character ((progress-bar uncertain-size-progress-bar)) + (let ((index (progress-char-index progress-bar))) + (prog1 + (char *uncertain-progress-chars* index) + (setf (progress-char-index progress-bar) + (mod (1+ index) (length *uncertain-progress-chars*)))))) + +(defmethod update-display ((progress-bar uncertain-size-progress-bar)) + (setf (last-update-time progress-bar) (get-internal-real-time)) + (multiple-value-bind (chars pend) + (floor (pending progress-bar) (units-per-char progress-bar)) + (setf (pending progress-bar) pend) + (dotimes (i chars) + (write-char (progress-character progress-bar)) + (incf (characters-so-far progress-bar)) + (when (<= (character-count progress-bar) + (characters-so-far progress-bar)) + (terpri) + (setf (characters-so-far progress-bar) 0) + (finish-output))) + (finish-output))) + +(defun make-progress-bar (total) + (if (or (not total) (zerop total)) + (make-instance 'uncertain-size-progress-bar) + (make-instance 'progress-bar :total total))) + +;;; +;;; A simple HTTP client +;;; + +(in-package #:qlqs-http) + +;;; Octet data + +(deftype octet () + '(unsigned-byte 8)) + +(defun make-octet-vector (size) + (make-array size :element-type 'octet + :initial-element 0)) + +(defun octet-vector (&rest octets) + (make-array (length octets) :element-type 'octet + :initial-contents octets)) + +;;; ASCII characters as integers + +(defun acode (char) + (cond ((eql char :cr) + 13) + ((eql char :lf) + 10) + (t + (let ((code (char-code char))) + (if (<= 0 code 127) + code + (error "Character ~S is not in the ASCII character set" + char)))))) + +(defvar *whitespace* + (list (acode #\Space) (acode #\Tab) (acode :cr) (acode :lf))) + +(defun whitep (code) + (member code *whitespace*)) + +(defun ascii-vector (string) + (let ((vector (make-octet-vector (length string)))) + (loop for char across string + for code = (char-code char) + for i from 0 + if (< 127 code) do + (error "Invalid character for ASCII -- ~A" char) + else + do (setf (aref vector i) code)) + vector)) + +(defun ascii-subseq (vector start end) + "Return a subseq of octet-specialized VECTOR as a string." + (let ((string (make-string (- end start)))) + (loop for i from 0 + for j from start below end + do (setf (char string i) (code-char (aref vector j)))) + string)) + +(defun ascii-downcase (code) + (if (<= 65 code 90) + (+ code 32) + code)) + +(defun ascii-equal (a b) + (eql (ascii-downcase a) (ascii-downcase b))) + +(defmacro acase (value &body cases) + (flet ((convert-case-keys (keys) + (mapcar (lambda (key) + (etypecase key + (integer key) + (character (char-code key)) + (symbol + (ecase key + (:cr 13) + (:lf 10) + ((t) t))))) + (if (consp keys) keys (list keys))))) + `(case ,value + ,@(mapcar (lambda (case) + (destructuring-bind (keys &rest body) + case + `(,(if (eql keys t) + t + (convert-case-keys keys)) + ,@body))) + cases)))) + +;;; Pattern matching (for finding headers) + +(defclass matcher () + ((pattern + :initarg :pattern + :reader pattern) + (pos + :initform 0 + :accessor match-pos) + (matchedp + :initform nil + :accessor matchedp))) + +(defun reset-match (matcher) + (setf (match-pos matcher) 0 + (matchedp matcher) nil)) + +(define-condition match-failure (error) ()) + +(defun match (matcher input &key (start 0) end error) + (let ((i start) + (end (or end (length input))) + (match-end (length (pattern matcher)))) + (with-slots (pattern pos) + matcher + (loop + (cond ((= pos match-end) + (let ((match-start (- i pos))) + (setf pos 0) + (setf (matchedp matcher) t) + (return (values match-start (+ match-start match-end))))) + ((= i end) + (return nil)) + ((= (aref pattern pos) + (aref input i)) + (incf i) + (incf pos)) + (t + (if error + (error 'match-failure) + (if (zerop pos) + (incf i) + (setf pos 0))))))))) + +(defun ascii-matcher (string) + (make-instance 'matcher + :pattern (ascii-vector string))) + +(defun octet-matcher (&rest octets) + (make-instance 'matcher + :pattern (apply 'octet-vector octets))) + +(defun acode-matcher (&rest codes) + (make-instance 'matcher + :pattern (make-array (length codes) + :element-type 'octet + :initial-contents + (mapcar 'acode codes)))) + + +;;; "Connection Buffers" are a kind of callback-driven, +;;; pattern-matching chunky stream. Callbacks can be called for a +;;; certain number of octets or until one or more patterns are seen in +;;; the input. cbufs automatically refill themselves from a +;;; connection as needed. + +(defvar *cbuf-buffer-size* 8192) + +(define-condition end-of-data (error) ()) + +(defclass cbuf () + ((data + :initarg :data + :accessor data) + (connection + :initarg :connection + :accessor connection) + (start + :initarg :start + :accessor start) + (end + :initarg :end + :accessor end) + (eofp + :initarg :eofp + :accessor eofp)) + (:default-initargs + :data (make-octet-vector *cbuf-buffer-size*) + :connection nil + :start 0 + :end 0 + :eofp nil) + (:documentation "A CBUF is a connection buffer that keeps track of + incoming data from a connection. Several functions make it easy to + treat a CBUF as a kind of chunky, callback-driven stream.")) + +(define-condition cbuf-progress () + ((size + :initarg :size + :accessor cbuf-progress-size + :initform 0))) + +(defun call-processor (fun cbuf start end) + (signal 'cbuf-progress :size (- end start)) + (funcall fun (data cbuf) start end)) + +(defun make-cbuf (connection) + (make-instance 'cbuf :connection connection)) + +(defun make-stream-writer (stream) + "Create a callback for writing data to STREAM." + (lambda (data start end) + (write-sequence data stream :start start :end end))) + +(defgeneric size (cbuf) + (:method ((cbuf cbuf)) + (- (end cbuf) (start cbuf)))) + +(defgeneric emptyp (cbuf) + (:method ((cbuf cbuf)) + (zerop (size cbuf)))) + +(defgeneric refill (cbuf) + (:method ((cbuf cbuf)) + (when (eofp cbuf) + (error 'end-of-data)) + (setf (start cbuf) 0) + (setf (end cbuf) + (read-octets (data cbuf) + (connection cbuf))) + (cond ((emptyp cbuf) + (setf (eofp cbuf) t) + (error 'end-of-data)) + (t (size cbuf))))) + +(defun process-all (fun cbuf) + (unless (emptyp cbuf) + (call-processor fun cbuf (start cbuf) (end cbuf)))) + +(defun multi-cmatch (matchers cbuf) + (let (start end) + (dolist (matcher matchers (values start end)) + (multiple-value-bind (s e) + (match matcher (data cbuf) + :start (start cbuf) + :end (end cbuf)) + (when (and s (or (null start) (< s start))) + (setf start s + end e)))))) + +(defun cmatch (matcher cbuf) + (if (consp matcher) + (multi-cmatch matcher cbuf) + (match matcher (data cbuf) :start (start cbuf) :end (end cbuf)))) + +(defun call-until-end (fun cbuf) + (handler-case + (loop + (process-all fun cbuf) + (refill cbuf)) + (end-of-data () + (return-from call-until-end)))) + +(defun show-cbuf (context cbuf) + (format t "cbuf: ~A ~D - ~D~%" context (start cbuf) (end cbuf))) + +(defun call-for-n-octets (n fun cbuf) + (let ((remaining n)) + (loop + (when (<= remaining (size cbuf)) + (let ((end (+ (start cbuf) remaining))) + (call-processor fun cbuf (start cbuf) end) + (setf (start cbuf) end) + (return))) + (process-all fun cbuf) + (decf remaining (size cbuf)) + (refill cbuf)))) + +(defun call-until-matching (matcher fun cbuf) + (loop + (multiple-value-bind (start end) + (cmatch matcher cbuf) + (when start + (call-processor fun cbuf (start cbuf) end) + (setf (start cbuf) end) + (return))) + (process-all fun cbuf) + (refill cbuf))) + +(defun ignore-data (data start end) + (declare (ignore data start end))) + +(defun skip-until-matching (matcher cbuf) + (call-until-matching matcher 'ignore-data cbuf)) + + +;;; Creating HTTP requests as octet buffers + +(defclass octet-sink () + ((storage + :initarg :storage + :accessor storage)) + (:default-initargs + :storage (make-array 1024 :element-type 'octet + :fill-pointer 0 + :adjustable t)) + (:documentation "A simple stream-like target for collecting + octets.")) + +(defun add-octet (octet sink) + (vector-push-extend octet (storage sink))) + +(defun add-octets (octets sink &key (start 0) end) + (setf end (or end (length octets))) + (loop for i from start below end + do (add-octet (aref octets i) sink))) + +(defun add-string (string sink) + (loop for char across string + for code = (char-code char) + do (add-octet code sink))) + +(defun add-strings (sink &rest strings) + (mapc (lambda (string) (add-string string sink)) strings)) + +(defun add-newline (sink) + (add-octet 13 sink) + (add-octet 10 sink)) + +(defun sink-buffer (sink) + (subseq (storage sink) 0)) + +(defvar *proxy-url* nil) + +(defun full-proxy-path (host port path) + (format nil "~:[http~;https~]://~A~:[:~D~;~*~]~A" + (= port 443) + host + (or (= port 80) + (= port 443)) + port + path)) + +(defun make-request-buffer (host port path &key (method "GET")) + (setf method (string method)) + (when *proxy-url* + (setf path (full-proxy-path host port path))) + (let ((sink (make-instance 'octet-sink))) + (flet ((add-line (&rest strings) + (apply #'add-strings sink strings) + (add-newline sink))) + (add-line method " " path " HTTP/1.1") + (add-line "Host: " host (if (= port 80) "" + (format nil ":~D" port))) + (add-line "Connection: close") + ;; FIXME: get this version string from somewhere else. + (add-line "User-Agent: quicklisp-bootstrap/" + qlqs-info:*version*) + (add-newline sink) + (sink-buffer sink)))) + +(defun sink-until-matching (matcher cbuf) + (let ((sink (make-instance 'octet-sink))) + (call-until-matching + matcher + (lambda (buffer start end) + (add-octets buffer sink :start start :end end)) + cbuf) + (sink-buffer sink))) + + +;;; HTTP headers + +(defclass header () + ((data + :initarg :data + :accessor data) + (status + :initarg :status + :accessor status) + (name-starts + :initarg :name-starts + :accessor name-starts) + (name-ends + :initarg :name-ends + :accessor name-ends) + (value-starts + :initarg :value-starts + :accessor value-starts) + (value-ends + :initarg :value-ends + :accessor value-ends))) + +(defmethod print-object ((header header) stream) + (print-unreadable-object (header stream :type t) + (prin1 (status header) stream))) + +(defun matches-at (pattern target pos) + (= (mismatch pattern target :start2 pos) (length pattern))) + +(defun header-value-indexes (field-name header) + (loop with data = (data header) + with pattern = (ascii-vector (string-downcase field-name)) + for start across (name-starts header) + for i from 0 + when (matches-at pattern data start) + return (values (aref (value-starts header) i) + (aref (value-ends header) i)))) + +(defun ascii-header-value (field-name header) + (multiple-value-bind (start end) + (header-value-indexes field-name header) + (when start + (ascii-subseq (data header) start end)))) + +(defun all-field-names (header) + (map 'list + (lambda (start end) + (ascii-subseq (data header) start end)) + (name-starts header) + (name-ends header))) + +(defun headers-alist (header) + (mapcar (lambda (name) + (cons name (ascii-header-value name header))) + (all-field-names header))) + +(defmethod describe-object :after ((header header) stream) + (format stream "~&Decoded headers:~% ~S~%" (headers-alist header))) + +(defun content-length (header) + (let ((field-value (ascii-header-value "content-length" header))) + (when field-value + (let ((value (ignore-errors (parse-integer field-value)))) + (or value + (error "Content-Length header field value is not a number -- ~A" + field-value)))))) + +(defun chunkedp (header) + (string= (ascii-header-value "transfer-encoding" header) "chunked")) + +(defun location (header) + (ascii-header-value "location" header)) + +(defun status-code (vector) + (let* ((space (position (acode #\Space) vector)) + (c1 (- (aref vector (incf space)) 48)) + (c2 (- (aref vector (incf space)) 48)) + (c3 (- (aref vector (incf space)) 48))) + (+ (* c1 100) + (* c2 10) + (* c3 1)))) + +(defun force-downcase-field-names (header) + (loop with data = (data header) + for start across (name-starts header) + for end across (name-ends header) + do (loop for i from start below end + for code = (aref data i) + do (setf (aref data i) (ascii-downcase code))))) + +(defun skip-white-forward (pos vector) + (position-if-not 'whitep vector :start pos)) + +(defun skip-white-backward (pos vector) + (let ((nonwhite (position-if-not 'whitep vector :end pos :from-end t))) + (if nonwhite + (1+ nonwhite) + pos))) + +(defun contract-field-value-indexes (header) + "Header field values exclude leading and trailing whitespace; adjust +the indexes in the header accordingly." + (loop with starts = (value-starts header) + with ends = (value-ends header) + with data = (data header) + for i from 0 + for start across starts + for end across ends + do + (setf (aref starts i) (skip-white-forward start data)) + (setf (aref ends i) (skip-white-backward end data)))) + +(defun next-line-pos (vector) + (let ((pos 0)) + (labels ((finish (&optional (i pos)) + (return-from next-line-pos i)) + (after-cr (code) + (acase code + (:lf (finish pos)) + (t (finish (1- pos))))) + (pending (code) + (acase code + (:cr #'after-cr) + (:lf (finish pos)) + (t #'pending)))) + (let ((state #'pending)) + (loop + (setf state (funcall state (aref vector pos))) + (incf pos)))))) + +(defun make-hvector () + (make-array 16 :fill-pointer 0 :adjustable t)) + +(defun process-header (vector) + "Create a HEADER instance from the octet data in VECTOR." + (let* ((name-starts (make-hvector)) + (name-ends (make-hvector)) + (value-starts (make-hvector)) + (value-ends (make-hvector)) + (header (make-instance 'header + :data vector + :status 999 + :name-starts name-starts + :name-ends name-ends + :value-starts value-starts + :value-ends value-ends)) + (mark nil) + (pos (next-line-pos vector))) + (unless pos + (error "Unable to process HTTP header")) + (setf (status header) (status-code vector)) + (labels ((save (value vector) + (vector-push-extend value vector)) + (mark () + (setf mark pos)) + (clear-mark () + (setf mark nil)) + (finish () + (if mark + (save mark value-ends) + (save pos value-ends)) + (force-downcase-field-names header) + (contract-field-value-indexes header) + (return-from process-header header)) + (in-new-line (code) + (acase code + ((#\Tab #\Space) (setf mark nil) #'in-value) + (t + (when mark + (save mark value-ends)) + (clear-mark) + (save pos name-starts) + (in-name code)))) + (after-cr (code) + (acase code + (:lf #'in-new-line) + (t (in-new-line code)))) + (pending-value (code) + (acase code + ((#\Tab #\Space) #'pending-value) + (:cr #'after-cr) + (:lf #'in-new-line) + (t (save pos value-starts) #'in-value))) + (in-name (code) + (acase code + (#\: + (save pos name-ends) + (save (1+ pos) value-starts) + #'in-value) + ((:cr :lf) + (finish)) + ((#\Tab #\Space) + (error "Unexpected whitespace in header field name")) + (t + (unless (<= 0 code 127) + (error "Unexpected non-ASCII header field name")) + #'in-name))) + (in-value (code) + (acase code + (:lf (mark) #'in-new-line) + (:cr (mark) #'after-cr) + (t #'in-value)))) + (let ((state #'in-new-line)) + (loop + (incf pos) + (when (<= (length vector) pos) + (error "No header found in response")) + (setf state (funcall state (aref vector pos)))))))) + + +;;; HTTP URL parsing + +(defclass url () + ((hostname + :initarg :hostname + :accessor hostname + :initform nil) + (port + :initarg :port + :accessor port + :initform 80) + (path + :initarg :path + :accessor path + :initform "/"))) + +(defun parse-urlstring (urlstring) + (setf urlstring (string-trim " " urlstring)) + (let* ((pos (mismatch urlstring "http://" :test 'char-equal)) + (mark pos) + (url (make-instance 'url))) + (labels ((save () + (subseq urlstring mark pos)) + (mark () + (setf mark pos)) + (finish () + (return-from parse-urlstring url)) + (hostname-char-p (char) + (position char "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_." + :test 'char-equal)) + (at-start (char) + (case char + (#\/ + (setf (port url) nil) + (mark) + #'in-path) + (t + #'in-host))) + (in-host (char) + (case char + ((#\/ :end) + (setf (hostname url) (save)) + (mark) + #'in-path) + (#\: + (setf (hostname url) (save)) + (mark) + #'in-port) + (t + (unless (hostname-char-p char) + (error "~S is not a valid URL" urlstring)) + #'in-host))) + (in-port (char) + (case char + ((#\/ :end) + (setf (port url) + (parse-integer urlstring + :start (1+ mark) + :end pos)) + (mark) + #'in-path) + (t + (unless (digit-char-p char) + (error "Bad port in URL ~S" urlstring)) + #'in-port))) + (in-path (char) + (case char + ((#\# :end) + (setf (path url) (save)) + (finish))) + #'in-path)) + (let ((state #'at-start)) + (loop + (when (<= (length urlstring) pos) + (funcall state :end) + (finish)) + (setf state (funcall state (aref urlstring pos))) + (incf pos)))))) + +(defun url (thing) + (if (stringp thing) + (parse-urlstring thing) + thing)) + +(defgeneric request-buffer (method url) + (:method (method url) + (setf url (url url)) + (make-request-buffer (hostname url) (port url) (path url) + :method method))) + +(defun urlstring (url) + (format nil "~@[http://~A~]~@[:~D~]~A" + (hostname url) + (and (/= 80 (port url)) (port url)) + (path url))) + +(defmethod print-object ((url url) stream) + (print-unreadable-object (url stream :type t) + (prin1 (urlstring url) stream))) + +(defun merge-urls (url1 url2) + (setf url1 (url url1)) + (setf url2 (url url2)) + (make-instance 'url + :hostname (or (hostname url1) + (hostname url2)) + :port (or (port url1) + (port url2)) + :path (or (path url1) + (path url2)))) + + +;;; Requesting an URL and saving it to a file + +(defparameter *maximum-redirects* 10) +(defvar *default-url-defaults* (url "http://src.quicklisp.org/")) + +(defun read-http-header (cbuf) + (let ((header-data (sink-until-matching (list (acode-matcher :lf :lf) + (acode-matcher :cr :cr) + (acode-matcher :cr :lf :cr :lf)) + cbuf))) + (process-header header-data))) + +(defun read-chunk-header (cbuf) + (let* ((header-data (sink-until-matching (acode-matcher :cr :lf) cbuf)) + (end (or (position (acode :cr) header-data) + (position (acode #\;) header-data)))) + (values (parse-integer (ascii-subseq header-data 0 end) :radix 16)))) + +(defun save-chunk-response (stream cbuf) + "For a chunked response, read all chunks and write them to STREAM." + (let ((fun (make-stream-writer stream)) + (matcher (acode-matcher :cr :lf))) + (loop + (let ((chunk-size (read-chunk-header cbuf))) + (when (zerop chunk-size) + (return)) + (call-for-n-octets chunk-size fun cbuf) + (skip-until-matching matcher cbuf))))) + +(defun save-response (file header cbuf) + (with-open-file (stream file + :direction :output + :if-exists :supersede + :element-type 'octet) + (let ((content-length (content-length header))) + (cond ((chunkedp header) + (save-chunk-response stream cbuf)) + (content-length + (call-for-n-octets content-length + (make-stream-writer stream) + cbuf)) + (t + (call-until-end (make-stream-writer stream) cbuf)))))) + +(defun call-with-progress-bar (size fun) + (let ((progress-bar (make-progress-bar size))) + (start-display progress-bar) + (flet ((update (condition) + (update-progress progress-bar + (cbuf-progress-size condition)))) + (handler-bind ((cbuf-progress #'update)) + (funcall fun))) + (finish-display progress-bar))) + +(defun fetch (url file &key (follow-redirects t) quietly + (maximum-redirects *maximum-redirects*)) + "Request URL and write the body of the response to FILE." + (setf url (merge-urls url *default-url-defaults*)) + (setf file (merge-pathnames file)) + (let ((redirect-count 0) + (original-url url) + (connect-url (or (url *proxy-url*) url)) + (stream (if quietly + (make-broadcast-stream) + *trace-output*))) + (loop + (when (<= maximum-redirects redirect-count) + (error "Too many redirects for ~A" original-url)) + (with-connection (connection (hostname connect-url) (port connect-url)) + (let ((cbuf (make-instance 'cbuf :connection connection)) + (request (request-buffer "GET" url))) + (write-octets request connection) + (let ((header (read-http-header cbuf))) + (loop while (= (status header) 100) + do (setf header (read-http-header cbuf))) + (cond ((= (status header) 200) + (let ((size (content-length header))) + (format stream "~&; Fetching ~A~%" url) + (if (and (numberp size) + (plusp size)) + (format stream "; ~$KB~%" (/ size 1024)) + (format stream "; Unknown size~%")) + (if quietly + (save-response file header cbuf) + (call-with-progress-bar (content-length header) + (lambda () + (save-response file header cbuf)))))) + ((not (<= 300 (status header) 399)) + (error "Unexpected status for ~A: ~A" + url (status header)))) + (if (and follow-redirects (<= 300 (status header) 399)) + (let ((new-urlstring (ascii-header-value "location" header))) + (when (not new-urlstring) + (error "Redirect code ~D received, but no Location: header" + (status header))) + (incf redirect-count) + (setf url (merge-urls new-urlstring + url)) + (format stream "~&; Redirecting to ~A~%" url)) + (return (values header (and file (probe-file file))))))))))) + + +;;; A primitive tar unpacker + +(in-package #:qlqs-minitar) + +(defun make-block-buffer () + (make-array 512 :element-type '(unsigned-byte 8) :initial-element 0)) + +(defun skip-n-blocks (n stream) + (let ((block (make-block-buffer))) + (dotimes (i n) + (read-sequence block stream)))) + +(defun ascii-subseq (vector start end) + (let ((string (make-string (- end start)))) + (loop for i from 0 + for j from start below end + do (setf (char string i) (code-char (aref vector j)))) + string)) + +(defun block-asciiz-string (block start length) + (let* ((end (+ start length)) + (eos (or (position 0 block :start start :end end) + end))) + (ascii-subseq block start eos))) + +(defun prefix (header) + (when (plusp (aref header 345)) + (block-asciiz-string header 345 155))) + +(defun name (header) + (block-asciiz-string header 0 100)) + +(defun payload-size (header) + (values (parse-integer (block-asciiz-string header 124 12) :radix 8))) + +(defun nth-block (n file) + (with-open-file (stream file :element-type '(unsigned-byte 8)) + (let ((block (make-block-buffer))) + (skip-n-blocks (1- n) stream) + (read-sequence block stream) + block))) + +(defun payload-type (code) + (case code + (0 :file) + (48 :file) + (53 :directory) + (t :unsupported))) + +(defun full-path (header) + (let ((prefix (prefix header)) + (name (name header))) + (if prefix + (format nil "~A/~A" prefix name) + name))) + +(defun save-file (file size stream) + (multiple-value-bind (full-blocks partial) + (truncate size 512) + (ensure-directories-exist file) + (with-open-file (outstream file + :direction :output + :if-exists :supersede + :element-type '(unsigned-byte 8)) + (let ((block (make-block-buffer))) + (dotimes (i full-blocks) + (read-sequence block stream) + (write-sequence block outstream)) + (when (plusp partial) + (read-sequence block stream) + (write-sequence block outstream :end partial)))))) + +(defun unpack-tarball (tarfile &key (directory *default-pathname-defaults*)) + (let ((block (make-block-buffer))) + (with-open-file (stream tarfile :element-type '(unsigned-byte 8)) + (loop + (let ((size (read-sequence block stream))) + (when (zerop size) + (return)) + (unless (= size 512) + (error "Bad size on tarfile")) + (when (every #'zerop block) + (return)) + (let* ((payload-code (aref block 156)) + (payload-type (payload-type payload-code)) + (tar-path (full-path block)) + (full-path (merge-pathnames tar-path directory)) + (payload-size (payload-size block))) + (case payload-type + (:file + (save-file full-path payload-size stream)) + (:directory + (ensure-directories-exist full-path)) + (t + (warn "Unknown tar block payload code -- ~D" payload-code) + (skip-n-blocks (ceiling (payload-size block) 512) stream))))))))) + +(defun contents (tarfile) + (let ((block (make-block-buffer)) + (result '())) + (with-open-file (stream tarfile :element-type '(unsigned-byte 8)) + (loop + (let ((size (read-sequence block stream))) + (when (zerop size) + (return (nreverse result))) + (unless (= size 512) + (error "Bad size on tarfile")) + (when (every #'zerop block) + (return (nreverse result))) + (let* ((payload-type (payload-type (aref block 156))) + (tar-path (full-path block)) + (payload-size (payload-size block))) + (skip-n-blocks (ceiling payload-size 512) stream) + (case payload-type + (:file + (push tar-path result)) + (:directory + (push tar-path result))))))))) + + +;;; +;;; The actual bootstrapping work +;;; + +(in-package #:quicklisp-quickstart) + +(defvar *home* + (merge-pathnames (make-pathname :directory '(:relative "quicklisp")) + (user-homedir-pathname))) + +(defun qmerge (pathname) + (merge-pathnames pathname *home*)) + +(defun renaming-fetch (url file) + (let ((tmpfile (qmerge "tmp/fetch.dat"))) + (fetch url tmpfile) + (rename-file tmpfile file))) + +(defvar *quickstart-parameters* nil + "This plist is populated with parameters that may carry over to the + initial configuration of the client, e.g. :proxy-url + or :initial-dist-url") + +(defvar *quicklisp-hostname* "beta.quicklisp.org") + +(defvar *client-info-url* + (format nil "http://~A/client/quicklisp.sexp" + *quicklisp-hostname*)) + +(defclass client-info () + ((setup-url + :reader setup-url + :initarg :setup-url) + (asdf-url + :reader asdf-url + :initarg :asdf-url) + (client-tar-url + :reader client-tar-url + :initarg :client-tar-url) + (version + :reader version + :initarg :version) + (plist + :reader plist + :initarg :plist) + (source-file + :reader source-file + :initarg :source-file))) + +(defmethod print-object ((client-info client-info) stream) + (print-unreadable-object (client-info stream :type t) + (prin1 (version client-info) stream))) + +(defun safely-read (stream) + (let ((*read-eval* nil)) + (read stream))) + +(defun fetch-client-info-plist (url) + "Fetch and return the client info data at URL." + (let ((local-client-info-file (qmerge "tmp/client-info.sexp"))) + (ensure-directories-exist local-client-info-file) + (renaming-fetch url local-client-info-file) + (with-open-file (stream local-client-info-file) + (list* :source-file local-client-info-file + (safely-read stream))))) + +(defun fetch-client-info (url) + (let ((plist (fetch-client-info-plist url))) + (destructuring-bind (&key setup asdf client-tar version + source-file + &allow-other-keys) + plist + (unless (and setup asdf client-tar version) + (error "Invalid data from client info URL -- ~A" url)) + (make-instance 'client-info + :setup-url (getf setup :url) + :asdf-url (getf asdf :url) + :client-tar-url (getf client-tar :url) + :version version + :plist plist + :source-file source-file)))) + +(defun client-info-url-from-version (version) + (format nil "http://~A/client/~A/client-info.sexp" + *quicklisp-hostname* + version)) + +(defun distinfo-url-from-version (version) + (format nil "http://~A/dist/~A/distinfo.txt" + *quicklisp-hostname* + version)) + +(defvar *help-message* + (format nil "~&~% ==== quicklisp quickstart install help ====~%~% ~ + quicklisp-quickstart:install can take the following ~ + optional arguments:~%~% ~ + :path \"/path/to/installation/\"~%~% ~ + :proxy \"http://your.proxy:port/\"~%~% ~ + :client-url ~%~% ~ + :client-version ~%~% ~ + :dist-url ~%~% ~ + :dist-version ~%~%")) + +(defvar *after-load-message* + (format nil "~&~% ==== quicklisp quickstart ~A loaded ====~%~% ~ + To continue with installation, evaluate: (quicklisp-quickstart:install)~%~% ~ + For installation options, evaluate: (quicklisp-quickstart:help)~%~%" + qlqs-info:*version*)) + +(defvar *after-initial-setup-message* + (with-output-to-string (*standard-output*) + (format t "~&~% ==== quicklisp installed ====~%~%") + (format t " To load a system, use: (ql:quickload \"system-name\")~%~%") + (format t " To find systems, use: (ql:system-apropos \"term\")~%~%") + (format t " To load Quicklisp every time you start Lisp, use: (ql:add-to-init-file)~%~%") + (format t " For more information, see http://www.quicklisp.org/beta/~%~%"))) + +(defun initial-install (&key (client-url *client-info-url*) dist-url) + (setf *quickstart-parameters* + (list :proxy-url *proxy-url* + :initial-dist-url dist-url)) + (ensure-directories-exist (qmerge "tmp/")) + (let ((client-info (fetch-client-info client-url)) + (tmptar (qmerge "tmp/quicklisp.tar")) + (setup (qmerge "setup.lisp")) + (asdf (qmerge "asdf.lisp"))) + (renaming-fetch (client-tar-url client-info) tmptar) + (unpack-tarball tmptar :directory (qmerge "./")) + (renaming-fetch (setup-url client-info) setup) + (renaming-fetch (asdf-url client-info) asdf) + (rename-file (source-file client-info) (qmerge "client-info.sexp")) + (load setup :verbose nil :print nil) + (write-string *after-initial-setup-message*) + (finish-output))) + +(defun help () + (write-string *help-message*) + t) + +(defun non-empty-file-namestring (pathname) + (let ((string (file-namestring pathname))) + (unless (or (null string) + (equal string "")) + string))) + +(defun install (&key ((:path *home*) *home*) + ((:proxy *proxy-url*) *proxy-url*) + client-url + client-version + dist-url + dist-version) + (setf *home* (merge-pathnames *home* (truename *default-pathname-defaults*))) + (let ((name (non-empty-file-namestring *home*))) + (when name + (warn "Making ~A part of the install pathname directory" + name) + ;; This corrects a pathname like "/foo/bar" to "/foo/bar/" and + ;; "foo" to "foo/" + (setf *home* + (make-pathname :defaults *home* + :directory (append (pathname-directory *home*) + (list name)))))) + (let ((setup-file (qmerge "setup.lisp"))) + (when (probe-file setup-file) + (multiple-value-bind (result proceed) + (with-simple-restart (load-setup "Load ~S" setup-file) + (error "Quicklisp has already been installed. Load ~S instead." + setup-file)) + (declare (ignore result)) + (when proceed + (return-from install (load setup-file)))))) + (if (find-package '#:ql) + (progn + (write-line "!!! Quicklisp has already been set up. !!!") + (write-string *after-initial-setup-message*) + t) + (call-with-quiet-compilation + (lambda () + (let ((client-url (or client-url + (and client-version + (client-info-url-from-version client-version)) + *client-info-url*)) + ;; It's ok for dist-url to be nil; there's a default in + ;; the client + (dist-url (or dist-url + (and dist-version + (distinfo-url-from-version dist-version))))) + (initial-install :client-url client-url + :dist-url dist-url)))))) + +(write-string *after-load-message*) + +;;; End of quicklisp.lisp diff --git a/attachments/04/399bd0-62da-4c89-97fa-845b32c9e26c/birth-info-Nari.pdf b/resources/04/399bd0-62da-4c89-97fa-845b32c9e26c/birth-info-Nari.pdf similarity index 100% rename from attachments/04/399bd0-62da-4c89-97fa-845b32c9e26c/birth-info-Nari.pdf rename to resources/04/399bd0-62da-4c89-97fa-845b32c9e26c/birth-info-Nari.pdf diff --git a/attachments/04/399bd0-62da-4c89-97fa-845b32c9e26c/birthwheel.png b/resources/04/399bd0-62da-4c89-97fa-845b32c9e26c/birthwheel.png similarity index 100% rename from attachments/04/399bd0-62da-4c89-97fa-845b32c9e26c/birthwheel.png rename to resources/04/399bd0-62da-4c89-97fa-845b32c9e26c/birthwheel.png diff --git a/attachments/b0/948e67-3348-48e5-abd3-b880595bb2fb/birth-info-N.pdf b/resources/b0/948e67-3348-48e5-abd3-b880595bb2fb/birth-info-N.pdf similarity index 100% rename from attachments/b0/948e67-3348-48e5-abd3-b880595bb2fb/birth-info-N.pdf rename to resources/b0/948e67-3348-48e5-abd3-b880595bb2fb/birth-info-N.pdf diff --git a/attachments/b0/948e67-3348-48e5-abd3-b880595bb2fb/birthwheel.png b/resources/b0/948e67-3348-48e5-abd3-b880595bb2fb/birthwheel.png similarity index 100% rename from attachments/b0/948e67-3348-48e5-abd3-b880595bb2fb/birthwheel.png rename to resources/b0/948e67-3348-48e5-abd3-b880595bb2fb/birthwheel.png diff --git a/attachments/b6/e0e53c-0dff-419a-9e86-5d905cbe21b0/DNExplanation.gif b/resources/b6/e0e53c-0dff-419a-9e86-5d905cbe21b0/DNExplanation.gif similarity index 100% rename from attachments/b6/e0e53c-0dff-419a-9e86-5d905cbe21b0/DNExplanation.gif rename to resources/b6/e0e53c-0dff-419a-9e86-5d905cbe21b0/DNExplanation.gif diff --git a/attachments/bd/da77a5-efb1-43f5-8b38-ad1be0dbc47b/Digital-Crime-Scenes_Afsaneh-Rigot-2022.pdf b/resources/bd/da77a5-efb1-43f5-8b38-ad1be0dbc47b/Digital-Crime-Scenes_Afsaneh-Rigot-2022.pdf similarity index 100% rename from attachments/bd/da77a5-efb1-43f5-8b38-ad1be0dbc47b/Digital-Crime-Scenes_Afsaneh-Rigot-2022.pdf rename to resources/bd/da77a5-efb1-43f5-8b38-ad1be0dbc47b/Digital-Crime-Scenes_Afsaneh-Rigot-2022.pdf diff --git a/attachments/f5/f4e365-bc1b-4bbb-bfe8-ac18027f0136/birth-info-A.pdf b/resources/f5/f4e365-bc1b-4bbb-bfe8-ac18027f0136/birth-info-A.pdf similarity index 100% rename from attachments/f5/f4e365-bc1b-4bbb-bfe8-ac18027f0136/birth-info-A.pdf rename to resources/f5/f4e365-bc1b-4bbb-bfe8-ac18027f0136/birth-info-A.pdf diff --git a/attachments/f5/f4e365-bc1b-4bbb-bfe8-ac18027f0136/horoscope-chart4def-700__radix_astroseek-15-10-1979_05-15.png b/resources/f5/f4e365-bc1b-4bbb-bfe8-ac18027f0136/horoscope-chart4def-700__radix_astroseek-15-10-1979_05-15.png similarity index 100% rename from attachments/f5/f4e365-bc1b-4bbb-bfe8-ac18027f0136/horoscope-chart4def-700__radix_astroseek-15-10-1979_05-15.png rename to resources/f5/f4e365-bc1b-4bbb-bfe8-ac18027f0136/horoscope-chart4def-700__radix_astroseek-15-10-1979_05-15.png diff --git a/attachments/محكمة-القضاء-الإداري-في-القاهرة-الدعوى-63089-لسنة-66-قضائية.pdf b/resources/محكمة-القضاء-الإداري-في-القاهرة-الدعوى-63089-لسنة-66-قضائية.pdf similarity index 100% rename from attachments/محكمة-القضاء-الإداري-في-القاهرة-الدعوى-63089-لسنة-66-قضائية.pdf rename to resources/محكمة-القضاء-الإداري-في-القاهرة-الدعوى-63089-لسنة-66-قضائية.pdf diff --git a/system/#fleet-dashboard.org# b/system/#fleet-dashboard.org# deleted file mode 100644 index 0762ee7..0000000 --- a/system/#fleet-dashboard.org# +++ /dev/null @@ -1,355 +0,0 @@ -#+TITLE: LLM Fleet Dashboard -#+author: Sol (Agent) - -* Model Fleet - -| Provider | Model ID | Context | -|------------+---------------------------------------------------------------+---------| -| OpenRouter | google/gemma-4-26b-a4b-it | 262144 | -| OpenRouter | google/gemma-4-31b-it | 262144 | -| OpenRouter | qwen/qwen3.6-plus:free | 1000000 | -| OpenRouter | z-ai/glm-5v-turbo | 202752 | -| OpenRouter | arcee-ai/trinity-large-thinking | 262144 | -| OpenRouter | x-ai/grok-4.20-multi-agent | 2000000 | -| OpenRouter | x-ai/grok-4.20 | 2000000 | -| OpenRouter | google/lyria-3-pro-preview | 1048576 | -| OpenRouter | google/lyria-3-clip-preview | 1048576 | -| OpenRouter | kwaipilot/kat-coder-pro-v2 | 256000 | -| OpenRouter | rekaai/reka-edge | 16384 | -| OpenRouter | xiaomi/mimo-v2-omni | 262144 | -| OpenRouter | xiaomi/mimo-v2-pro | 1048576 | -| OpenRouter | minimax/minimax-m2.7 | 204800 | -| OpenRouter | openai/gpt-5.4-nano | 400000 | -| OpenRouter | openai/gpt-5.4-mini | 400000 | -| OpenRouter | mistralai/mistral-small-2603 | 262144 | -| OpenRouter | z-ai/glm-5-turbo | 202752 | -| OpenRouter | nvidia/nemotron-3-super-120b-a12b:free | 262144 | -| OpenRouter | nvidia/nemotron-3-super-120b-a12b | 262144 | -| OpenRouter | bytedance-seed/seed-2.0-lite | 262144 | -| OpenRouter | qwen/qwen3.5-9b | 256000 | -| OpenRouter | openai/gpt-5.4-pro | 1050000 | -| OpenRouter | openai/gpt-5.4 | 1050000 | -| OpenRouter | inception/mercury-2 | 128000 | -| OpenRouter | openai/gpt-5.3-chat | 128000 | -| OpenRouter | google/gemini-3.1-flash-lite-preview | 1048576 | -| OpenRouter | bytedance-seed/seed-2.0-mini | 262144 | -| OpenRouter | google/gemini-3.1-flash-image-preview | 65536 | -| OpenRouter | qwen/qwen3.5-35b-a3b | 262144 | -| OpenRouter | qwen/qwen3.5-27b | 262144 | -| OpenRouter | qwen/qwen3.5-122b-a10b | 262144 | -| OpenRouter | qwen/qwen3.5-flash-02-23 | 1000000 | -| OpenRouter | liquid/lfm-2-24b-a2b | 32768 | -| OpenRouter | google/gemini-3.1-pro-preview-customtools | 1048576 | -| OpenRouter | openai/gpt-5.3-codex | 400000 | -| OpenRouter | aion-labs/aion-2.0 | 131072 | -| OpenRouter | google/gemini-3.1-pro-preview | 1048576 | -| OpenRouter | anthropic/claude-sonnet-4.6 | 1000000 | -| OpenRouter | qwen/qwen3.5-plus-02-15 | 1000000 | -| OpenRouter | qwen/qwen3.5-397b-a17b | 262144 | -| OpenRouter | minimax/minimax-m2.5:free | 196608 | -| OpenRouter | minimax/minimax-m2.5 | 196608 | -| OpenRouter | z-ai/glm-5 | 80000 | -| OpenRouter | qwen/qwen3-max-thinking | 262144 | -| OpenRouter | anthropic/claude-opus-4.6 | 1000000 | -| OpenRouter | qwen/qwen3-coder-next | 262144 | -| OpenRouter | openrouter/free | 200000 | -| OpenRouter | stepfun/step-3.5-flash:free | 256000 | -| OpenRouter | stepfun/step-3.5-flash | 262144 | -| OpenRouter | arcee-ai/trinity-large-preview:free | 131000 | -| OpenRouter | moonshotai/kimi-k2.5 | 262144 | -| OpenRouter | upstage/solar-pro-3 | 128000 | -| OpenRouter | minimax/minimax-m2-her | 65536 | -| OpenRouter | writer/palmyra-x5 | 1040000 | -| OpenRouter | liquid/lfm-2.5-1.2b-thinking:free | 32768 | -| OpenRouter | liquid/lfm-2.5-1.2b-instruct:free | 32768 | -| OpenRouter | openai/gpt-audio | 128000 | -| OpenRouter | openai/gpt-audio-mini | 128000 | -| OpenRouter | z-ai/glm-4.7-flash | 202752 | -| OpenRouter | openai/gpt-5.2-codex | 400000 | -| OpenRouter | allenai/olmo-3.1-32b-instruct | 65536 | -| OpenRouter | bytedance-seed/seed-1.6-flash | 262144 | -| OpenRouter | bytedance-seed/seed-1.6 | 262144 | -| OpenRouter | minimax/minimax-m2.1 | 196608 | -| OpenRouter | z-ai/glm-4.7 | 202752 | -| OpenRouter | google/gemini-3-flash-preview | 1048576 | -| OpenRouter | mistralai/mistral-small-creative | 32768 | -| OpenRouter | xiaomi/mimo-v2-flash | 262144 | -| OpenRouter | nvidia/nemotron-3-nano-30b-a3b:free | 256000 | -| OpenRouter | nvidia/nemotron-3-nano-30b-a3b | 262144 | -| OpenRouter | openai/gpt-5.2-chat | 128000 | -| OpenRouter | openai/gpt-5.2-pro | 400000 | -| OpenRouter | openai/gpt-5.2 | 400000 | -| OpenRouter | mistralai/devstral-2512 | 262144 | -| OpenRouter | relace/relace-search | 256000 | -| OpenRouter | z-ai/glm-4.6v | 131072 | -| OpenRouter | nex-agi/deepseek-v3.1-nex-n1 | 131072 | -| OpenRouter | essentialai/rnj-1-instruct | 32768 | -| OpenRouter | openrouter/bodybuilder | 128000 | -| OpenRouter | openai/gpt-5.1-codex-max | 400000 | -| OpenRouter | amazon/nova-2-lite-v1 | 1000000 | -| OpenRouter | mistralai/ministral-14b-2512 | 262144 | -| OpenRouter | mistralai/ministral-8b-2512 | 262144 | -| OpenRouter | mistralai/ministral-3b-2512 | 131072 | -| OpenRouter | mistralai/mistral-large-2512 | 262144 | -| OpenRouter | arcee-ai/trinity-mini:free | 131072 | -| OpenRouter | arcee-ai/trinity-mini | 131072 | -| OpenRouter | deepseek/deepseek-v3.2-speciale | 163840 | -| OpenRouter | deepseek/deepseek-v3.2 | 163840 | -| OpenRouter | prime-intellect/intellect-3 | 131072 | -| OpenRouter | anthropic/claude-opus-4.5 | 200000 | -| OpenRouter | allenai/olmo-3-32b-think | 65536 | -| OpenRouter | google/gemini-3-pro-image-preview | 65536 | -| OpenRouter | x-ai/grok-4.1-fast | 2000000 | -| OpenRouter | deepcogito/cogito-v2.1-671b | 128000 | -| OpenRouter | openai/gpt-5.1 | 400000 | -| OpenRouter | openai/gpt-5.1-chat | 128000 | -| OpenRouter | openai/gpt-5.1-codex | 400000 | -| OpenRouter | openai/gpt-5.1-codex-mini | 400000 | -| OpenRouter | moonshotai/kimi-k2-thinking | 131072 | -| OpenRouter | amazon/nova-premier-v1 | 1000000 | -| OpenRouter | perplexity/sonar-pro-search | 200000 | -| OpenRouter | mistralai/voxtral-small-24b-2507 | 32000 | -| OpenRouter | openai/gpt-oss-safeguard-20b | 131072 | -| OpenRouter | nvidia/nemotron-nano-12b-v2-vl:free | 128000 | -| OpenRouter | nvidia/nemotron-nano-12b-v2-vl | 131072 | -| OpenRouter | minimax/minimax-m2 | 196608 | -| OpenRouter | qwen/qwen3-vl-32b-instruct | 131072 | -| OpenRouter | ibm-granite/granite-4.0-h-micro | 131000 | -| OpenRouter | openai/gpt-5-image-mini | 400000 | -| OpenRouter | anthropic/claude-haiku-4.5 | 200000 | -| OpenRouter | qwen/qwen3-vl-8b-thinking | 131072 | -| OpenRouter | qwen/qwen3-vl-8b-instruct | 131072 | -| OpenRouter | openai/gpt-5-image | 400000 | -| OpenRouter | openai/o3-deep-research | 200000 | -| OpenRouter | openai/o4-mini-deep-research | 200000 | -| OpenRouter | nvidia/llama-3.3-nemotron-super-49b-v1.5 | 131072 | -| OpenRouter | baidu/ernie-4.5-21b-a3b-thinking | 131072 | -| OpenRouter | google/gemini-2.5-flash-image | 32768 | -| OpenRouter | qwen/qwen3-vl-30b-a3b-thinking | 131072 | -| OpenRouter | qwen/qwen3-vl-30b-a3b-instruct | 131072 | -| OpenRouter | openai/gpt-5-pro | 400000 | -| OpenRouter | z-ai/glm-4.6 | 204800 | -| OpenRouter | anthropic/claude-sonnet-4.5 | 1000000 | -| OpenRouter | deepseek/deepseek-v3.2-exp | 163840 | -| OpenRouter | thedrummer/cydonia-24b-v4.1 | 131072 | -| OpenRouter | relace/relace-apply-3 | 256000 | -| OpenRouter | google/gemini-2.5-flash-lite-preview-09-2025 | 1048576 | -| OpenRouter | qwen/qwen3-vl-235b-a22b-thinking | 131072 | -| OpenRouter | qwen/qwen3-vl-235b-a22b-instruct | 262144 | -| OpenRouter | qwen/qwen3-max | 262144 | -| OpenRouter | qwen/qwen3-coder-plus | 1000000 | -| OpenRouter | openai/gpt-5-codex | 400000 | -| OpenRouter | deepseek/deepseek-v3.1-terminus | 163840 | -| OpenRouter | x-ai/grok-4-fast | 2000000 | -| OpenRouter | alibaba/tongyi-deepresearch-30b-a3b | 131072 | -| OpenRouter | qwen/qwen3-coder-flash | 1000000 | -| OpenRouter | qwen/qwen3-next-80b-a3b-thinking | 131072 | -| OpenRouter | qwen/qwen3-next-80b-a3b-instruct:free | 262144 | -| OpenRouter | qwen/qwen3-next-80b-a3b-instruct | 262144 | -| OpenRouter | meituan/longcat-flash-chat | 131072 | -| OpenRouter | qwen/qwen-plus-2025-07-28:thinking | 1000000 | -| OpenRouter | qwen/qwen-plus-2025-07-28 | 1000000 | -| OpenRouter | nvidia/nemotron-nano-9b-v2:free | 128000 | -| OpenRouter | nvidia/nemotron-nano-9b-v2 | 131072 | -| OpenRouter | moonshotai/kimi-k2-0905 | 131072 | -| OpenRouter | qwen/qwen3-30b-a3b-thinking-2507 | 131072 | -| OpenRouter | x-ai/grok-code-fast-1 | 256000 | -| OpenRouter | nousresearch/hermes-4-70b | 131072 | -| OpenRouter | nousresearch/hermes-4-405b | 131072 | -| OpenRouter | deepseek/deepseek-chat-v3.1 | 32768 | -| OpenRouter | openai/gpt-4o-audio-preview | 128000 | -| OpenRouter | mistralai/mistral-medium-3.1 | 131072 | -| OpenRouter | baidu/ernie-4.5-21b-a3b | 120000 | -| OpenRouter | baidu/ernie-4.5-vl-28b-a3b | 30000 | -| OpenRouter | z-ai/glm-4.5v | 65536 | -| OpenRouter | ai21/jamba-large-1.7 | 256000 | -| OpenRouter | openai/gpt-5-chat | 128000 | -| OpenRouter | openai/gpt-5 | 400000 | -| OpenRouter | openai/gpt-5-mini | 400000 | -| OpenRouter | openai/gpt-5-nano | 400000 | -| OpenRouter | openai/gpt-oss-120b:free | 131072 | -| OpenRouter | openai/gpt-oss-120b | 131072 | -| OpenRouter | openai/gpt-oss-20b:free | 131072 | -| OpenRouter | openai/gpt-oss-20b | 131072 | -| OpenRouter | anthropic/claude-opus-4.1 | 200000 | -| OpenRouter | mistralai/codestral-2508 | 256000 | -| OpenRouter | qwen/qwen3-coder-30b-a3b-instruct | 160000 | -| OpenRouter | qwen/qwen3-30b-a3b-instruct-2507 | 262144 | -| OpenRouter | z-ai/glm-4.5 | 131072 | -| OpenRouter | z-ai/glm-4.5-air:free | 131072 | -| OpenRouter | z-ai/glm-4.5-air | 131072 | -| OpenRouter | qwen/qwen3-235b-a22b-thinking-2507 | 131072 | -| OpenRouter | z-ai/glm-4-32b | 128000 | -| OpenRouter | qwen/qwen3-coder:free | 262000 | -| OpenRouter | qwen/qwen3-coder | 262144 | -| OpenRouter | bytedance/ui-tars-1.5-7b | 128000 | -| OpenRouter | google/gemini-2.5-flash-lite | 1048576 | -| OpenRouter | qwen/qwen3-235b-a22b-2507 | 262144 | -| OpenRouter | switchpoint/router | 131072 | -| OpenRouter | moonshotai/kimi-k2 | 131072 | -| OpenRouter | mistralai/devstral-medium | 131072 | -| OpenRouter | mistralai/devstral-small | 131072 | -| OpenRouter | cognitivecomputations/dolphin-mistral-24b-venice-edition:free | 32768 | -| OpenRouter | x-ai/grok-4 | 256000 | -| OpenRouter | google/gemma-3n-e2b-it:free | 8192 | -| OpenRouter | tencent/hunyuan-a13b-instruct | 131072 | -| OpenRouter | tngtech/deepseek-r1t2-chimera | 163840 | -| OpenRouter | morph/morph-v3-large | 262144 | -| OpenRouter | morph/morph-v3-fast | 81920 | -| OpenRouter | baidu/ernie-4.5-vl-424b-a47b | 123000 | -| OpenRouter | baidu/ernie-4.5-300b-a47b | 123000 | -| OpenRouter | inception/mercury | 128000 | -| OpenRouter | mistralai/mistral-small-3.2-24b-instruct | 128000 | -| OpenRouter | minimax/minimax-m1 | 1000000 | -| OpenRouter | google/gemini-2.5-flash | 1048576 | -| OpenRouter | google/gemini-2.5-pro | 1048576 | -| OpenRouter | openai/o3-pro | 200000 | -| OpenRouter | x-ai/grok-3-mini | 131072 | -| OpenRouter | x-ai/grok-3 | 131072 | -| OpenRouter | google/gemini-2.5-pro-preview | 1048576 | -| OpenRouter | deepseek/deepseek-r1-0528 | 163840 | -| OpenRouter | anthropic/claude-opus-4 | 200000 | -| OpenRouter | anthropic/claude-sonnet-4 | 200000 | -| OpenRouter | google/gemma-3n-e4b-it:free | 8192 | -| OpenRouter | google/gemma-3n-e4b-it | 32768 | -| OpenRouter | mistralai/mistral-medium-3 | 131072 | -| OpenRouter | google/gemini-2.5-pro-preview-05-06 | 1048576 | -| OpenRouter | arcee-ai/spotlight | 131072 | -| OpenRouter | arcee-ai/maestro-reasoning | 131072 | -| OpenRouter | arcee-ai/virtuoso-large | 131072 | -| OpenRouter | arcee-ai/coder-large | 32768 | -| OpenRouter | inception/mercury-coder | 128000 | -| OpenRouter | meta-llama/llama-guard-4-12b | 163840 | -| OpenRouter | qwen/qwen3-30b-a3b | 40960 | -| OpenRouter | qwen/qwen3-8b | 40960 | -| OpenRouter | qwen/qwen3-14b | 40960 | -| OpenRouter | qwen/qwen3-32b | 40960 | -| OpenRouter | qwen/qwen3-235b-a22b | 131072 | -| OpenRouter | openai/o4-mini-high | 200000 | -| OpenRouter | openai/o3 | 200000 | -| OpenRouter | openai/o4-mini | 200000 | -| OpenRouter | qwen/qwen2.5-coder-7b-instruct | 32768 | -| OpenRouter | openai/gpt-4.1 | 1047576 | -| OpenRouter | openai/gpt-4.1-mini | 1047576 | -| OpenRouter | openai/gpt-4.1-nano | 1047576 | -| OpenRouter | eleutherai/llemma_7b | 4096 | -| OpenRouter | alfredpros/codellama-7b-instruct-solidity | 4096 | -| OpenRouter | x-ai/grok-3-mini-beta | 131072 | -| OpenRouter | x-ai/grok-3-beta | 131072 | -| OpenRouter | nvidia/llama-3.1-nemotron-ultra-253b-v1 | 131072 | -| OpenRouter | meta-llama/llama-4-maverick | 1048576 | -| OpenRouter | meta-llama/llama-4-scout | 327680 | -| OpenRouter | qwen/qwen2.5-vl-32b-instruct | 128000 | -| OpenRouter | deepseek/deepseek-chat-v3-0324 | 163840 | -| OpenRouter | openai/o1-pro | 200000 | -| OpenRouter | mistralai/mistral-small-3.1-24b-instruct | 131072 | -| OpenRouter | allenai/olmo-2-0325-32b-instruct | 128000 | -| OpenRouter | google/gemma-3-4b-it:free | 32768 | -| OpenRouter | google/gemma-3-4b-it | 131072 | -| OpenRouter | google/gemma-3-12b-it:free | 32768 | -| OpenRouter | google/gemma-3-12b-it | 131072 | -| OpenRouter | cohere/command-a | 256000 | -| OpenRouter | openai/gpt-4o-mini-search-preview | 128000 | -| OpenRouter | openai/gpt-4o-search-preview | 128000 | -| OpenRouter | rekaai/reka-flash-3 | 65536 | -| OpenRouter | google/gemma-3-27b-it:free | 131072 | -| OpenRouter | google/gemma-3-27b-it | 131072 | -| OpenRouter | thedrummer/skyfall-36b-v2 | 32768 | -| OpenRouter | perplexity/sonar-reasoning-pro | 128000 | -| OpenRouter | perplexity/sonar-pro | 200000 | -| OpenRouter | perplexity/sonar-deep-research | 128000 | -| OpenRouter | qwen/qwq-32b | 131072 | -| OpenRouter | google/gemini-2.0-flash-lite-001 | 1048576 | -| OpenRouter | anthropic/claude-3.7-sonnet | 200000 | -| OpenRouter | anthropic/claude-3.7-sonnet:thinking | 200000 | -| OpenRouter | mistralai/mistral-saba | 32768 | -| OpenRouter | meta-llama/llama-guard-3-8b | 131072 | -| OpenRouter | openai/o3-mini-high | 200000 | -| OpenRouter | google/gemini-2.0-flash-001 | 1048576 | -| OpenRouter | qwen/qwen-vl-plus | 131072 | -| OpenRouter | aion-labs/aion-1.0 | 131072 | -| OpenRouter | aion-labs/aion-1.0-mini | 131072 | -| OpenRouter | aion-labs/aion-rp-llama-3.1-8b | 32768 | -| OpenRouter | qwen/qwen-vl-max | 131072 | -| OpenRouter | qwen/qwen-turbo | 131072 | -| OpenRouter | qwen/qwen2.5-vl-72b-instruct | 32768 | -| OpenRouter | qwen/qwen-plus | 1000000 | -| OpenRouter | qwen/qwen-max | 32768 | -| OpenRouter | openai/o3-mini | 200000 | -| OpenRouter | mistralai/mistral-small-24b-instruct-2501 | 32768 | -| OpenRouter | deepseek/deepseek-r1-distill-qwen-32b | 32768 | -| OpenRouter | perplexity/sonar | 127072 | -| OpenRouter | deepseek/deepseek-r1-distill-llama-70b | 131072 | -| OpenRouter | deepseek/deepseek-r1 | 64000 | -| OpenRouter | minimax/minimax-01 | 1000192 | -| OpenRouter | microsoft/phi-4 | 16384 | -| OpenRouter | sao10k/l3.1-70b-hanami-x1 | 16000 | -| OpenRouter | deepseek/deepseek-chat | 163840 | -| OpenRouter | sao10k/l3.3-euryale-70b | 131072 | -| OpenRouter | openai/o1 | 200000 | -| OpenRouter | cohere/command-r7b-12-2024 | 128000 | -| OpenRouter | meta-llama/llama-3.3-70b-instruct:free | 65536 | -| OpenRouter | meta-llama/llama-3.3-70b-instruct | 131072 | -| OpenRouter | amazon/nova-lite-v1 | 300000 | -| OpenRouter | amazon/nova-micro-v1 | 128000 | -| OpenRouter | amazon/nova-pro-v1 | 300000 | -| OpenRouter | openai/gpt-4o-2024-11-20 | 128000 | -| OpenRouter | mistralai/mistral-large-2411 | 131072 | -| OpenRouter | mistralai/mistral-large-2407 | 131072 | -| OpenRouter | mistralai/pixtral-large-2411 | 131072 | -| OpenRouter | qwen/qwen-2.5-coder-32b-instruct | 32768 | -| OpenRouter | thedrummer/unslopnemo-12b | 32768 | -| OpenRouter | anthropic/claude-3.5-haiku | 200000 | -| OpenRouter | anthracite-org/magnum-v4-72b | 16384 | -| OpenRouter | qwen/qwen-2.5-7b-instruct | 32768 | -| OpenRouter | nvidia/llama-3.1-nemotron-70b-instruct | 131072 | -| OpenRouter | inflection/inflection-3-pi | 8000 | -| OpenRouter | inflection/inflection-3-productivity | 8000 | -| OpenRouter | thedrummer/rocinante-12b | 32768 | -| OpenRouter | meta-llama/llama-3.2-3b-instruct:free | 131072 | -| OpenRouter | meta-llama/llama-3.2-3b-instruct | 80000 | -| OpenRouter | meta-llama/llama-3.2-1b-instruct | 60000 | -| OpenRouter | meta-llama/llama-3.2-11b-vision-instruct | 131072 | -| OpenRouter | qwen/qwen-2.5-72b-instruct | 32768 | -| OpenRouter | cohere/command-r-08-2024 | 128000 | -| OpenRouter | cohere/command-r-plus-08-2024 | 128000 | -| OpenRouter | sao10k/l3.1-euryale-70b | 131072 | -| OpenRouter | nousresearch/hermes-3-llama-3.1-70b | 131072 | -| OpenRouter | nousresearch/hermes-3-llama-3.1-405b:free | 131072 | -| OpenRouter | nousresearch/hermes-3-llama-3.1-405b | 131072 | -| OpenRouter | sao10k/l3-lunaris-8b | 8192 | -| OpenRouter | openai/gpt-4o-2024-08-06 | 128000 | -| OpenRouter | meta-llama/llama-3.1-8b-instruct | 16384 | -| OpenRouter | meta-llama/llama-3.1-70b-instruct | 131072 | -| OpenRouter | mistralai/mistral-nemo | 131072 | -| OpenRouter | openai/gpt-4o-mini-2024-07-18 | 128000 | -| OpenRouter | openai/gpt-4o-mini | 128000 | -| OpenRouter | google/gemma-2-27b-it | 8192 | -| OpenRouter | google/gemma-2-9b-it | 8192 | -| OpenRouter | sao10k/l3-euryale-70b | 8192 | -| OpenRouter | nousresearch/hermes-2-pro-llama-3-8b | 8192 | -| OpenRouter | openai/gpt-4o | 128000 | -| OpenRouter | openai/gpt-4o:extended | 128000 | -| OpenRouter | openai/gpt-4o-2024-05-13 | 128000 | -| OpenRouter | meta-llama/llama-3-8b-instruct | 8192 | -| OpenRouter | meta-llama/llama-3-70b-instruct | 8192 | -| OpenRouter | mistralai/mixtral-8x22b-instruct | 65536 | -| OpenRouter | microsoft/wizardlm-2-8x22b | 65535 | -| OpenRouter | openai/gpt-4-turbo | 128000 | -| OpenRouter | anthropic/claude-3-haiku | 200000 | -| OpenRouter | mistralai/mistral-large | 128000 | -| OpenRouter | openai/gpt-3.5-turbo-0613 | 4095 | -| OpenRouter | openai/gpt-4-turbo-preview | 128000 | -| OpenRouter | mistralai/mixtral-8x7b-instruct | 32768 | -| OpenRouter | alpindale/goliath-120b | 6144 | -| OpenRouter | openrouter/auto | 2000000 | -| OpenRouter | openai/gpt-4-1106-preview | 128000 | -| OpenRouter | mistralai/mistral-7b-instruct-v0.1 | 2824 | -| OpenRouter | openai/gpt-3.5-turbo-instruct | 4095 | -| OpenRouter | openai/gpt-3.5-turbo-16k | 16385 | -| OpenRouter | mancer/weaver | 8000 | -| OpenRouter | undi95/remm-slerp-l2-13b | 6144 | -| OpenRouter | gryphe/mythomax-l2-13b | 4096 | -| OpenRouter | openai/gpt-4-0314 | 8191 | -| OpenRouter | openai/gpt-3.5-turbo | 16385 | -| OpenRouter | openai/gpt-4 | 8191 | diff --git a/system/.#fleet-dashboard.org b/system/.#fleet-dashboard.org deleted file mode 120000 index da010b7..0000000 --- a/system/.#fleet-dashboard.org +++ /dev/null @@ -1 +0,0 @@ -user@amr.3392:1775060113 \ No newline at end of file diff --git a/system/debug-screenshot.png b/system/debug-screenshot.png deleted file mode 100644 index 8d1880f..0000000 Binary files a/system/debug-screenshot.png and /dev/null differ diff --git a/system/emacs-ai.org b/system/emacs-ai.org deleted file mode 100644 index 0a39b17..0000000 --- a/system/emacs-ai.org +++ /dev/null @@ -1,120 +0,0 @@ -#+TITLE: AI Configuration -#+PROPERTY: header-args :tangle yes - -* AI Settings - -** Ellama - -#+begin_src elisp :tangle yes - ;; YOU DON'T NEED NONE OF THIS CODE FOR SIMPLE INSTALL - ;; IT IS AN EXAMPLE OF CUSTOMIZATION. - (use-package ellama - :init - (require 'llm-openai) - ;; setup key bindings - (setq ellama-keymap-prefix "C-c e") - ) -#+end_src - -#+begin_src elisp ~/.emacs.d/custom.el :tangle yes - (setopt ellama-providers - '( - ;; Ollama Provider (added here with a name) - ("ollama" . (make-llm-ollama - ;; Consider a dedicated embedding model if gemma isn't ideal for it. - :chat-model "gemma3:latest" - :embedding-model "gemma3:latest" ; Or e.g., "nomic-embed-text" - :default-chat-non-standard-params '(("num_ctx" . 8192)))) - - ("openai" . (make-llm-openai - :key (auth-source-pass-get "api-key" "www/openai.com/amr@gharbeia.net") - :chat-model "gpt-4o" - :embedding-model "text-embedding-3-large")) - - ("groq" . (make-llm-openai-compatible - :url "https://api.groq.com/openai/v1" - :key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net") - ;; Check Groq console for available models, these might change - :chat-model "llama3-70b-8192" ; Example, verify on Groq - :embedding-model "llama3-70b-8192")) ; Groq might not offer dedicated embedding models via this API - )) - - ;; --- Set Active Providers --- - ;; Choose your default provider from the list above by its name - (setopt ellama-provider "ollama") ; Or "ollama", "openai", "groq" - - ;; You can specify different providers for different tasks if needed - (setopt ellama-translation-provider "ollama") - (setopt ellama-naming-provider "ollama") - (setopt ellama-naming-scheme 'ellama-generate-name-by-llm) - - (setq llm-debug t) -#+end_src - -#+begin_src elisp - (use-package ellama - :ensure t - :bind ("C-c e" . ellama) - ;; send last message in chat buffer with C-c C-c - :hook (org-ctrl-c-ctrl-c-final . ellama-chat-send-last-message) - :init (setopt ellama-auto-scroll t) - :config - ;; show ellama context in header line in all buffers - (ellama-context-header-line-global-mode +1) - ;; show ellama session id in header line in all buffers - (ellama-session-header-line-global-mode +1)) -#+end_src - -** GPTel - -#+begin_src elisp :tangle yes - (use-package gptel) -#+end_src - -#+begin_src elisp :tangle yes - (setq gptel-api-key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net")) -#+end_src - -#+begin_src elisp :tangle yes - (gptel-make-openai "Groq" ;Any name you want - :host "api.groq.com" - :endpoint "/openai/v1/chat/completions" - :stream t - :key (auth-source-pass-get "api-key" "www/console.groq.com/groq@amr.gharbeia.net") ;can be a function that returns the key - :models '(llama-3.1-70b-versatile - llama-3.1-8b-instant - llama3-70b-8192 - llama3-8b-8192 - mixtral-8x7b-32768 - gemma-7b-it)) -#+end_src - -** Elisa - -#+begin_src elisp :tangle yes - (use-package elisa - :defer t - :init - (setopt elisa-limit 5) - (require 'llm-ollama) - (setopt elisa-embeddings-provider (make-llm-ollama :embedding-model "nomic-embed-text")) - (setopt elisa-chat-provider (make-llm-ollama - :chat-model "sskostyaev/openchat:8k-rag" - :embedding-model "nomic-embed-text")) - ) -#+end_src - -** OpenCortex (Local Foundry) - -#+begin_src elisp :tangle yes - (use-package opencortex - :straight nil - :load-path "~/.local/share/opencortex/src" - :commands (opencortex-connect opencortex-disconnect) - :init - (setq opencortex-host "127.0.0.1") - (setq opencortex-port 9105) - (setq opencortex-executable-path "~/.local/share/opencortex/bin/opencortex-server") - :config - (message "opencortex: Local brain configured at %s" opencortex-executable-path)) -#+end_src \ No newline at end of file diff --git a/system/emacs-core.org b/system/emacs-core.org deleted file mode 100644 index 20be7a8..0000000 --- a/system/emacs-core.org +++ /dev/null @@ -1,165 +0,0 @@ -#+TITLE: Core Emacs Configuration -#+PROPERTY: header-args :tangle yes - -* Initialization Bootstrap - -This section tangles directly to ~/.emacs to bootstrap the entire system. - -#+begin_src elisp :tangle ~/.emacs - ;;; .emacs --- Global settings -*- lexical-binding: t; -*- - - (setq gc-cons-threshold (* 500 1024 1024)) - (add-hook 'after-init-hook (lambda () (setq gc-cons-threshold (* 5 1024 1024)))) - - (setq straight-repository-branch "develop") - - (eval-and-compile - (defvar bootstrap-version) - (let ((bootstrap-file - (expand-file-name "straight/repos/straight.el/bootstrap.el" - (or (bound-and-true-p straight-base-dir) - user-emacs-directory))) - (bootstrap-version 7)) - (unless (file-exists-p bootstrap-file) - (with-current-buffer - (url-retrieve-synchronously "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" 'silent 'inhibit-cookies) - (goto-char (point-max)) - (eval-print-last-sexp))) - (load bootstrap-file nil 'nomessage)) - - (straight-use-package 'use-package) - (straight-use-package 'org)) - - (setq straight-use-package-by-default t) - - (require 'ob-tangle) - - ;; Load the modular configuration starting from dotemacs.org - (org-babel-load-file (expand-file-name "~/memex/system/dotemacs.org")) - - (provide '.emacs) -#+end_src - -* Front matter - -#+begin_src elisp - ;;; emacs-core.el --- Summary - ;;; Commentary: - ;;; Code: - - ;; -*- lexical-binding: t; -*- -#+end_src - -* Garbage collector - -Increase threshold to 500 MB to ease startup -#+begin_src elisp - (setq gc-cons-threshold (* 500 1024 1024)) -#+end_src - -Decrease threshold to 5 MB after init -#+begin_src elisp - (add-hook 'after-init-hook (lambda () (setq gc-cons-threshold (* 5 1024 1024)))) -#+end_src - -* Straight.el and use-package - -Integrate use-package and straight -#+begin_src elisp - (setq straight-use-package-by-default t) - (require 'use-package) - (straight-use-package 'diminish) - (require 'diminish) -#+end_src - -Make sure Org is installed (straight.el) -#+begin_src elisp - (unless (file-directory-p (expand-file-name "~/.emacs.d/straight/versions")) (make-directory (expand-file-name "~/.emacs.d/straight/versions") t)) - (use-package org) -#+end_src - -* Custom file - -#+begin_src elisp - (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) - (when (file-exists-p custom-file) (load custom-file)) -#+end_src - -* System information - -#+begin_src elisp - (defvar my-laptop-p (equal (system-name) "lilitop")) - (defvar my-server-p (and (equal (system-name) "localhost") (equal user-login-name "root"))) - (defvar my-phone-p (not (null (getenv "ANDROID_ROOT"))) - "If non-nil, GNU Emacs is running on Termux.") - (when my-phone-p (defvar gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")) - (global-auto-revert-mode) ; simplifies syncing -#+end_src - -* Persistent history - -#+begin_src elisp - (savehist-mode) -#+end_src - -* Disable Syntax Checkers (Diagnostic) - -#+begin_src elisp - (when (fboundp 'flycheck-mode) - (setq flycheck-global-modes nil) - (global-flycheck-mode -1)) - (when (fboundp 'flymake-mode) - (setq help-at-pt-display-when-idle t) - ;; Disable flymake in all buffers - (add-hook 'find-file-hook (lambda () (flymake-mode -1)))) -#+end_src - -* Backup and versioning - -#+begin_src emacs-lisp - (use-package magit) -#+end_src - -* Personal information - -#+begin_src elisp - (setq user-full-name "Amr Gharbeia") - (defvar email-address "amr@gharbeia.net") - (defvar calendar-latitude 39.0) - (defvar calendar-longitude -77.1) - (defvar calendar-location-name "Washington, DC") - (defvar calendar-time-zone -300) - (defvar calendar-standard-time-zone-name "EST") - (defvar calendar-daylight-time-zone-name "EDT") -#+end_src - -* Saving Emacs Sessions - -Close frame when done -#+begin_src elisp - (add-hook 'server-done-hook (lambda () (delete-frame))) -#+end_src - -Save desktop session -#+begin_src elisp - (desktop-save-mode t) -#+end_src - -* Security - -#+begin_src elisp - (use-package password-store) -#+end_src - -#+begin_src elisp - (use-package auth-source - :config (auth-source-pass-enable) - ) -#+end_src - -* End matter - -#+begin_src elisp - (provide 'emacs-core) - ;;; emacs-core.el ends here -#+end_src diff --git a/system/emacs-early-init.org b/system/emacs-early-init.org deleted file mode 100644 index bc26c1c..0000000 --- a/system/emacs-early-init.org +++ /dev/null @@ -1,18 +0,0 @@ -#+TITLE: Early Init Configuration -#+PROPERTY: header-args :tangle ~/.emacs.d/early-init.el - -* early-init.el - -For straight.el to pick up before package.el - -#+begin_src elisp - (setq package-enable-at-startup nil) -#+end_src - -* Run Emacs as a server - -#+begin_src elisp - (require 'server) - (unless (server-running-p) (server-start)) - (defvar server-max-buffers 100) -#+end_src \ No newline at end of file diff --git a/system/emacs-gtd.org b/system/emacs-gtd.org deleted file mode 100644 index 486e42b..0000000 --- a/system/emacs-gtd.org +++ /dev/null @@ -1,166 +0,0 @@ -#+TITLE: GTD & Agenda Configuration -#+PROPERTY: header-args :tangle yes - -* Agenda - -Basic agenda settings -#+begin_src elisp - (setq org-deadline-warning-days 7) - (setq org-agenda-skip-additional-timestamps-same-entry t) - (setq org-agenda-span 'fortnight) - (setq org-agenda-tags-column 'auto) - (setq org-agenda-skip-scheduled-if-deadline-is-shown t) -#+end_src - -Agenda files -#+begin_src elisp - (setq org-agenda-files (list - (concat org-directory "/inbox.org") - (concat org-directory "/gtd.org") - (concat org-directory "/org-gtd-tasks.org") - ) - ) - -#+end_src - -Better agenda views -#+begin_src elisp :tangle yes - (use-package org-super-agenda) -#+end_src - -* To-do - -Basic todo -#+begin_src elisp - (setq org-todo-keywords - '( - (sequence "TODO(t)" "NEXT(n)" "WAIT(w@/!)" "|" "DONE(d!)" "CNCL(c@)") - ) - ) - - (setq org-todo-keyword-faces - '( - ("TODO" :foreground "red" :weight bold) - ("NEXT" :foreground "red" :weight bold) - ("WAIT" :foreground "yellow" :weight bold) - ("DONE" :foreground "green" :weight bold) - ("CNCL" :foreground "blue" :weight bold) - ) - ) - - (setq org-enforce-todo-dependencies t) - (setq org-tags-exclude-from-inheritance '("crypt" "!private")) -#+end_src - -Switch entry to 'DONE' when all subentries are done -#+begin_src elisp - (defun org-summary-todo (n-done n-not-done) - "Switch entry to 'DONE' when all subentries are done, to 'TODO' otherwise. - Uses N-DONE and N-NOT-DONE" - (let (org-log-done org-log-states) ; turn off logging - (org-todo (if (= n-not-done 0) "DONE" "TODO") - ) - ) - ) - - ;; (add-hook 'org-after-todo-statistics-hook #'org-summary-todo) -#+end_src - -* Getting Things Done (GTD) - -#+begin_src elisp - (use-package f) - (use-package dash) - (use-package s) - (use-package org-edna - :config - (setq org-edna-use-inheritance t) - (org-edna-mode)) - - (use-package org-gtd - :straight (org-gtd :type git :host github :repo "Trevoke/org-gtd.el") - :demand t - :init (setq org-gtd-update-ack "4.0.0") - :config - (setq org-gtd-keyword-mapping - '((todo . "TODO") - (next . "NEXT") - (wait . "WAIT") - (done . "DONE") - (canceled . "CNCL"))) - (setq org-gtd-custom-node-paths - (list (list "Actionable" (expand-file-name "~/memex/gtd.org") "Actions") - (list "Legacy" (expand-file-name "~/memex/org-gtd-tasks.org") "Actions") - (list "Projects" (expand-file-name "~/memex/gtd.org") "Projects") - (list "Incubate" (expand-file-name "~/memex/gtd.org") "Incubate"))) - (org-gtd-mode) - ) - - (global-set-key (kbd "C-c d c") #'org-gtd-capture) - (global-set-key (kbd "C-c d e") #'org-gtd-engage) - (global-set-key (kbd "C-c d p") #'org-gtd-process-inbox) - (with-eval-after-load 'org-gtd - (define-key org-gtd-clarify-map (kbd "C-c c") #'org-gtd-organize)) -#+end_src - -#+begin_src elisp - (setq org-gtd-directory org-directory) - (setq org-gtd-organize-hooks '(org-gtd-set-area-of-focus)) - (setq org-gtd-areas-of-focus '( - "Atoms" - "Bits" - "Cells" - "Flags" - "Business" - "Wealth" - "Learning" - "Skills" - "Privacy" - "Archive" - "Library" - "Writing" - "Health" - "Home" - "Family" - "Social" - "Egypt" - ) - ) - (setq org-gtd-clarify-show-horizons 'right) -#+end_src - -Logging -#+begin_src elisp - (setq org-log-into-drawer "LOGBOOK") -#+end_src - -Clocking work in drawer -#+begin_src elisp :tangle yes - (setq org-clock-into-drawer t) -#+end_src - -Habits -#+begin_src elisp :tangle yes - (setq org-habit-graph-column 80) - (setq org-habit-show-habits-only-for-today nil) -#+end_src - -* Refile - -org-refile targets -#+begin_src elisp - (setq org-refile-targets '((nil :maxlevel . 9) - (org-agenda-files :maxlevel . 9) - ) - ) -#+end_src - -Set type of refile targets completion -#+begin_src elisp - (setq org-outline-path-complete-in-steps nil) -#+end_src - -Allow refiling to new parents created on the go after confirmation -#+begin_src elisp - (setq org-refile-allow-creating-parent-nodes 'confirm) -#+end_src \ No newline at end of file diff --git a/system/emacs-media.org b/system/emacs-media.org deleted file mode 100644 index 296641c..0000000 --- a/system/emacs-media.org +++ /dev/null @@ -1,101 +0,0 @@ -#+TITLE: Media and Books Configuration -#+PROPERTY: header-args :tangle yes - -* Read ebooks (calibredb) - -#+begin_src elisp - (use-package calibredb - :defer t - :config - (setq calibredb-format-all-the-icons t) - (setq calibredb-format-icons-in-terminal t)) -#+end_src - -#+begin_src elisp - (defvar calibredb-root-dir (expand-file-name "~/memex/library/books")) - (defvar calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir)) - (defvar calibredb-id-width 6) - (defvar calibredb-title-width 100) -#+end_src - -* PDF Tools - -#+begin_src elisp - (use-package pdf-tools - :mode ("\\.pdf\\'" . pdf-view-mode) - :config - (pdf-tools-install :no-query) - (setq-default pdf-view-display-size 'fit-page) - (setq pdf-annot-activate-created-annotations t)) -#+end_src - -* Annotate PDFs and EPUBs (org-noter) - -#+begin_src elisp - (use-package org-noter - :config - (setq org-noter-notes-search-path (list (expand-file-name "~/memex/library/books"))) - (setq org-noter-default-notes-file-names '("books.org"))) -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar org-noter-notes-search-path (list (concat org-directory "/library/books"))) - (defvar org-noter-default-notes-file-names '("books.org")) -#+end_src - -* Link PDFs (org-noter-pdftools) - -#+begin_src elisp - (use-package org-noter-pdftools - :after org-noter - :config - ;; Add a function to ensure precise note is inserted - (defun org-noter-pdftools-insert-precise-note (&optional toggle-no-questions) - (interactive "P") - (org-noter--with-valid-session - (let ((org-noter-insert-note-no-questions (if toggle-no-questions - (not org-noter-insert-note-no-questions) - org-noter-insert-note-no-questions)) - (org-pdftools-use-isearch-link t) - (org-pdftools-use-freepointer-annot t)) - (org-noter-insert-note (org-noter--get-precise-info))))) - - ;; fix https://github.com/weirdNox/org-noter/pull/93/commits/f8349ae7575e599f375de1be6be2d0d5de4e6cbf - (defun org-noter-set-start-location (&optional arg) - "When opening a session with this document, go to the current location. - With a prefix ARG, remove start location." - (interactive "P") - (org-noter--with-valid-session - (let ((inhibit-read-only t) - (ast (org-noter--parse-root)) - (location (org-noter--doc-approx-location (when (called-interactively-p 'any) 'interactive)))) - (with-current-buffer (org-noter--session-notes-buffer session) - (org-with-wide-buffer - (goto-char (org-element-property :begin ast)) - (if arg - (org-entry-delete nil org-noter-property-note-location) - (org-entry-put nil org-noter-property-note-location - (org-noter--pretty-print-location location)))))))) - (with-eval-after-load 'pdf-annot - (add-hook 'pdf-annot-activate-handler-functions #'org-noter-pdftools-jump-to-note) - ) - ) -#+end_src - -* View EPUBs (nov.el) - -#+begin_src elisp :tangle yes - (use-package nov - :config - (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)) - ) -#+end_src - -* Zotero (helm-bibtex) -#+begin_src elisp :tangle yes - (use-package helm-bibtex) -#+end_src - -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar bibtex-completion-bibliography '("~/bibliography/zotero.bib")) -#+end_src \ No newline at end of file diff --git a/system/emacs-org.org b/system/emacs-org.org deleted file mode 100644 index 2284fc0..0000000 --- a/system/emacs-org.org +++ /dev/null @@ -1,233 +0,0 @@ -#+TITLE: Org Mode Configuration -#+PROPERTY: header-args :tangle yes - -* Org Mode - -** Basic setup - -#+begin_src elisp - (use-package org - :config - (defvar org-outline-path-complete-in-steps nil) - :bind (("C-c l" . org-store-link) - ("C-c a" . org-agenda) - ("C-c c" . org-capture) - :map org-mode-map) - ) -#+end_src - -#+begin_src elisp - (setq org-directory (expand-file-name "~/memex/")) -#+end_src - -** Looks - -Basic -#+begin_src elisp - (defvar org-pretty-entities t) ; Improve org mode looks - (defvar org-hide-emphasis-markers t) ; Hide emphasis markup - (defvar org-num-mode nil) - (defvar org-startup-folded 'shw2levels) -#+end_src - -Indentation of headers -#+begin_src elisp - (defvar org-startup-indented t) ; Indent org heirarchy - (defvar org-adapt-indentation t) - (defvar org-hide-leading-stars t) ; Minimal Outline - (defvar org-odd-levels-only nil) -#+end_src - -Indentation of lists -#+begin_src elisp - (setq org-list-demote-modify-bullet t) -#+end_src - -Org-modern -#+begin_src elisp - (use-package org-modern - :ensure t - :config - ;; Choose some fonts - (set-face-attribute 'default nil :family "sans-serif") - (set-face-attribute 'variable-pitch nil :family "sans-serif") - (set-face-attribute 'org-modern-symbol nil :family "Iosevka") - - ;; Edit settings - (defvar org-auto-align-tags nil) - (defvar org-tags-column 0) - (defvar org-catch-invisible-edits 'show-and-error) - (defvar org-special-ctrl-a/e t) - (defvar org-insert-heading-respect-content t) - - ;; Org styling, hide markup etc. - (defvar org-hide-emphasis-markers t) - (defvar org-pretty-entities t) - - ;; Agenda styling - (defvar org-agenda-tags-column 0) - (defvar org-agenda-block-separator ?─) - (defvar org-agenda-time-grid - '((daily today require-timed) - (800 1000 1200 1400 1600 1800 2000) - " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")) - (defvar org-agenda-current-time-string - "◀── now ─────────────────────────────────────────────────") - - ;; Ellipsis styling - (defvar org-ellipsis "…") - (set-face-attribute 'org-ellipsis nil :inherit 'default :box nil) - - (global-org-modern-mode) - ) -#+end_src - -Highlight Sourcecode Syntax -#+begin_src elisp - (setq org-src-fontify-natively t) - (setq org-src-tab-acts-natively t) -#+end_src - -Images -#+begin_src elisp - (setq org-startup-with-inline-images t) - (setq org-image-actual-width '(300)) -#+end_src - -** Capture - -#+begin_src elisp - (defvar org-default-notes-file (concat org-directory "inbox.org")) -#+end_src - -*** Org-protocol - -Linux configuration -#+begin_src bash :tangle yes -[Desktop Entry] -Name=org-protocol -Comment=Intercept calls from emacsclient to trigger custom actions -Categories=Other; -Keywords=org-protocol; -Icon=emacs -Type=Application -Exec=emacsclient -- %u -Terminal=false -StartupWMClass=Emacs -MimeType=x-scheme-handler/org-protocol; -#+end_src - -#+begin_src bash :tangle yes -update-desktop-database ~/.local/share/applications/ -#+end_src - -Basic configuration -#+begin_src elisp - (require 'org-protocol) - (setq org-protocol-default-buffer-for-file-links "*scratch*") ; fixes 'no buffers remain to edit error for org-protocol capturer -#+end_src - -Org-protocol templates -#+begin_src elisp :tangle ~/.emacs.d/custom.el - (defvar org-capture-templates '( - ("p" "Protocol" - entry - (file "inbox.org") - "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?" - ) - ("L" "Protocol Link" - entry - (file "inbox.org") - "* %? [[%:link][%:description]]\n:PROPERTIES:\n:TITLE: %:description\n:URI: %:link\n:CREATED: %U\n:END:" - :prepend nil - :empty-lines 1 - :created t - :kill-buffer t - ) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-protocol-default-template-key "L") -#+end_src - -Convert Orgzly captures to org-protocol captures standard -#+begin_src elisp - (defun my/org-convert-orgzly-to-org-protocol () - "Reformat Orgzly bookmark at point to org-protocol bookmark." - (interactive) - (when (org-at-heading-p) - (let ((headline (nth 4 (org-heading-components)))) - ;; Find and store the link. Delete the link line. - (search-forward-regexp "^https?://\\S-*" nil t) - (let ((link (match-string 0))) - (beginning-of-line) - (kill-line) - ;; Delete any trailing blank spaces - (org-back-to-heading) - (end-of-line) - (when (not (org-on-heading-p)) - (delete-char 1) - ) - ;; Set new headline - (goto-char (org-entry-beginning-position)) - (org-edit-headline (format "[[%s][%s]]" link headline)) - ;; Set new properties - (org-set-property "TITLE" headline) - (org-set-property "URI" link) - (message "Reformatted Orgzly bookmark at point to org-protocol bookmark") - ) - ) - ) - ) -#+end_src - -** Exporting - -#+begin_src elisp :tangle yes - (setq org-export-with-smart-quotes t) - (setq org-export-backends '(beamer html latex md)) -#+end_src - -Export to EPUB -#+begin_src elisp :tangle yes - (use-package ox-epub) -#+end_src - -** org-attach - -#+begin_src elisp - (setq org-attach-id-dir (concat org-directory "/library")) -#+end_src - -** Enable shell scripting support in org-babel - -#+begin_src elisp - (defvar org-babel-do-load-languages 'org-babel-load-languages '((shell . t))) -#+end_src - -** Insert org-mode links from clipboard -#+begin_src elisp :tangle yes - (use-package org-cliplink - :bind - (("C-x p i" . org-cliplink)) - ) -#+end_src - -** Deft -#+begin_src elisp :tangle yes - (use-package deft - :commands (deft) - :init - (defvar deft-extensions '("org")) - (defvar deft-recursive nil) - (defvar deft-use-filename-as-title t) - :config - (defvar deft-directory org-directory) - (defvar deft-recursive t) - (defvar deft-strip-summary-regexp ":PROPERTIES:\n\\(.+\n\\)+:END:\n") - (defvar deft-use-filename-as-title t) - :bind ("C-c n d" . deft) - ) -#+end_src \ No newline at end of file diff --git a/system/emacs-roam.org b/system/emacs-roam.org deleted file mode 100644 index 11505bc..0000000 --- a/system/emacs-roam.org +++ /dev/null @@ -1,140 +0,0 @@ -#+TITLE: Org-Roam Configuration -#+PROPERTY: header-args :tangle yes - -* Org-roam - -** Basic org-roam setup - -#+begin_src elisp -(use-package org-roam - :init (setq org-roam-v2-ack t) ;; Acknowledge V2 upgrade - :after org - :config - (org-roam-db-autosync-enable) - (require 'org-roam-dailies) - :bind ( - ("C-c n f" . org-roam-node-find) - ("C-c n g" . org-roam-graph) - ("C-c n r" . org-roam-node-random) - ("C-c n h" . org-roam-node-convert-headline) - ("C-c n i" . org-roam-node-insert) - ("C-c n o" . org-id-get-create) - ("C-c n t" . org-roam-tag-add) - ("C-c n a" . org-roam-alias-add) - ("C-c n l" . org-roam-buffer-display-dedicated) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-roam-directory (expand-file-name (concat org-directory "notes"))) - (setq org-roam-dailies-directory (expand-file-name (concat org-directory "daily"))) -#+end_src - -#+begin_src elisp :tangle yes - (use-package sqlite3) - (require 'sqlite3) -#+end_src - -Include subdirectories in org-roam -#+begin_src elisp - (setq org-roam-file-exclude-regexp "^[.][.]?/") -#+end_src - -** Display in org-roam-buffer -#+begin_src elisp :tangle yes - (setq org-roam-mode-sections - (list #'org-roam-backlinks-section - #'org-roam-reflinks-section - #'org-roam-unlinked-references-section - ) - ) -#+end_src - -** Filter org-roam nodes find by tag - -#+begin_src elisp :tangle yes - (defun my/org-roam-node-has-tag (node tag) - "Filter function to check if the given NODE has the specified TAG." - (member tag (org-roam-node-tags node)) - ) - - (defun my/org-roam-node-find-by-tag () - "Find and open an Org-roam node based on a specified tag." - (interactive) - (let ((tag (read-string "Enter tag: "))) - (org-roam-node-find nil nil (lambda (node) (my/org-roam-node-has-tag node tag)))) - ) -#+end_src - -** org-roam-capture templates -#+begin_src elisp - (setq org-roam-capture-templates - '( - ("L" "link" plain - (function org-roam--capture-get-point) - "%?" - :file-name "web/%<%Y-%m-%dT%H%M%S>.org" - :head "#+TITLE: ${title}\n#+CREATED: %<%Y-%m-%dT%H%M%S>" - :immediate-finish t - :unnarrowed t - ) - - ("h" "hugo post" plain - "%?" - :target (file+head "posts/${slug}.org" - "#+TITLE: ${title}\n#+DATE: %U\n#+HUGO_BASE_DIR: ~/gharbeia.net\n#+HUGO_SECTION: ./posts\n#+HUGO_AUTO_SET_LASTMOD: t\n#+HUGO_TAGS: article\n#+HUGO_DRAFT: true\n") - :immediate-finish t - :unnarrowed t - ) - - ("p" "person" plain - "%?" - :if-new (file+head "people/${slug}.org" - "#+TITLE: ${title}") - :immediate-finish t - :unnarrowed t - ) - ) - ) -#+end_src - -#+begin_src elisp - (setq org-roam-dailies-capture-templates - '( - ("d" "daily" plain - "" - :target ("file+heaed %<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n\n") - :immediate-finish t - ) - ) - ) -#+end_src - -** Move org header to org-roam-daily - -#+begin_src elisp :tangle yes - (defun my/org-move-entry-to-daily-notes () - "Move the current org-mode headline to the daily notes file based on its :CREATED: property." - (interactive) - (let* - ( - (created-prop (org-entry-get nil "CREATED")) - (created-date (when created-prop - (org-parse-time-string created-prop))) - (year (nth 5 created-date)) ; Extract year (6th element) - (month (nth 4 created-date)) ; Extract month (5th element) - (day (nth 3 created-date)) ; Extract day (4th element) - (target-date (format "%04d-%02d-%02d" year month day)) ; Format date string - (target-file (org-roam-dailies-goto target-date)) - ) - (when target-file - (org-cut-subtree) - (find-file target-file) - (goto-char (point-max)) - (unless (bolp) (newline)) - (org-paste-subtree) - ) - ) - ) -#+end_src \ No newline at end of file diff --git a/system/emacs-shell.org b/system/emacs-shell.org deleted file mode 100644 index 2559400..0000000 --- a/system/emacs-shell.org +++ /dev/null @@ -1,73 +0,0 @@ -#+TITLE: Shell Configuration -#+PROPERTY: header-args :tangle yes - -* Shell - -** Bash completion - -#+begin_src elisp - (use-package bash-completion - :config - (require 'bash-completion) - (bash-completion-setup) - ) -#+end_src - -#+begin_src elisp -(defvar shell-dynamic-complete-functions t) -#+end_src - -** Eshell - -Add programmable bash completion to Emacs shell-mode -#+begin_src elisp :tangle yes - (require 'bash-completion) - (add-hook 'eshell-mode-hook - (lambda () - (add-hook 'completion-at-point-functions - 'bash-completion-capf-nonexclusive nil t - ) - ) - ) -#+end_src - -Use colors in eshell -#+begin_src elisp :tangle yes - (use-package xterm-color - :commands (xterm-color-filter) - ) - - (use-package eshell - :after xterm-color - :config - (define-key eshell-hist-mode-map (kbd "M-r") #'consult-history) - (add-hook 'eshell-mode-hook - (lambda () - (setenv "TERM" "xterm-256color"))) - (add-hook 'eshell-before-prompt-hook (setq xterm-color-preserve-properties t)) - (add-to-list 'eshell-preoutput-filter-functions 'xterm-color-filter) - (setq eshell-output-filter-functions - (remove 'eshell-handle-ansi-color eshell-output-filter-functions) - ) - ) -#+end_src - -Eshell completion -#+begin_src elisp :tangle yes - (add-hook 'eshell-mode-hook - (lambda () - (add-hook 'completion-at-point-functions - 'bash-completion-capf-nonexclusive nil t))) -#+end_src - -Emulate A Terminal (EAT) -#+begin_src elisp :tangle yes - (use-package eat - :config - ;; For `eat-eshell-mode'. - (add-hook 'eshell-load-hook #'eat-eshell-mode) - - ;; For `eat-eshell-visual-command-mode'. - (add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode) - ) -#+end_src \ No newline at end of file diff --git a/system/emacs-writing.org b/system/emacs-writing.org deleted file mode 100644 index f1476cc..0000000 --- a/system/emacs-writing.org +++ /dev/null @@ -1,254 +0,0 @@ -#+TITLE: Reading and Writing Configuration -#+PROPERTY: header-args :tangle yes - -* Text and Case - -** Convert DOuble capitals to single capitals - -#+begin_src elisp :tangle yes - (defun my/dcaps-to-scaps () - "Convert word in DOuble CApitals to Single Capitals." - (interactive) - (and (= ?w (char-syntax (char-before))) - (save-excursion - (and (if (called-interactively-p) - (skip-syntax-backward "w") - (= -3 (skip-syntax-backward "w")) - ) - (let (case-fold-search) - (looking-at "\\b[[:upper:]]\\{2\\}[[:lower:]]") - ) - (capitalize-word 1) - ) - ) - ) - ) -#+end_src - -Then, let’s define a minor mode for it to be activated. -#+begin_src elisp :tangle yes - (define-minor-mode my-dubcaps-mode - "Toggle 'my-dubcaps-mode' and convert words in DOuble CApitals to Single Capitals as you type." - :init-value nil - :lighter (" DC") - (if my-dubcaps-mode - (add-hook 'post-self-insert-hook #'my/dcaps-to-scaps nil 'local) - (remove-hook 'post-self-insert-hook #'my/dcaps-to-scaps 'local))) -#+end_src - - Finally, let’s add a hook so that it is on for all the text files Emacs opens. -#+begin_src elisp :tangle yes - (add-hook 'text-mode-hook #'my-dubcaps-mode) -#+end_src - -Also, since we add a minor mode string (it might be useful sometimes), currently I prefer to diminish it. -#+begin_src elisp :tangle yes - (defun my/diminish-dubcaps () - (interactive) - (diminish 'my-dubcaps-mode "")) - (add-hook 'my-dubcaps-mode-hook 'my/diminish-dubcaps) -#+end_src - -* Reading and Writing - -** Move correctly over camelCased words - -#+begin_src elisp - (subword-mode) -#+end_src - -** Understand the more common sentence with double space - -#+begin_src elisp - (setq sentence-end-double-space nil) -#+end_src - -** Join lines into paragraph - -#+begin_src elisp - (defun my/fill-or-unfill-paragraph (&optional unfill region) - "Fill paragraph (or REGION). With the prefix argument UNFILL, fill it instead." - (interactive (progn - (barf-if-buffer-read-only) - (list (if current-prefix-arg 'fill) t))) - (let ((fill-column (if unfill fill-column (point-max)))) - (fill-paragraph nil region))) - - (bind-key "M-q" 'my/fill-or-unfill-paragraph) -#+end_src - -#+begin_src elisp - (defun my/fill-or-unfill-all-paragraphs (&optional unfill) - "Fill or unfill all paragraphs in the current buffer. -With the prefix argument UNFILL, fill them instead." - (interactive (list (if current-prefix-arg 'fill))) - (let ((fill-column (if unfill fill-column (point-max)))) - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (fill-paragraph nil t) - (forward-paragraph))))) - -(bind-key "M-Q" 'my/fill-or-unfill-all-paragraphs) -#+end_src - -#+begin_src elisp - (remove-hook 'text-mode-hook #'turn-on-auto-fill) - (add-hook 'text-mode-hook 'turn-on-visual-line-mode) -#+end_src - -** Expand some words with auto-correct - - #+begin_src elisp :tangle yes - (setq save-abbrevs 'silently) - (setq-default abbrev-mode t) - #+end_src - -** ediff - -#+begin_src elisp :tangle yes - (setq ediff-window-setup-function 'ediff-setup-windows-plain) - (setq ediff-split-window-function 'split-window-horizontally) -#+end_src - -** tramp - -#+begin_src elisp :tangle yes - (setq tramp-default-method "ssh" - tramp-backup-directory-alist backup-directory-alist - tramp-ssh-controlmaster-options "ssh") -#+end_src - -** Clean up space -#+begin_src elisp :tangle yes - (bind-key "M-SPC" 'cycle-spacing) -#+end_src - -** Transform links into org links - -#+begin_src elisp :tangle yes - (defun my/transform-html-links-to-org () - "Transform all HTML links in the current buffer into 'org-mode' links." - (interactive) - (goto-char (point-min)) - (while (re-search-forward "\\(.*?\\)" nil t) - (replace-match (org-make-link-string (match-string 1) (match-string 2))))) -#+end_src - -** Count words per minute -#+begin_src elisp :tangle yes - (require 'org-clock) - (defun my/org-entry-wpm () - (interactive) - (save-restriction - (save-excursion - (org-narrow-to-subtree) - (goto-char (point-min)) - (let* ((words (count-words-region (point-min) (point-max))) - - (minutes (org-clock-sum-current-item)) - (wpm (/ words minutes))) - (message "WPM: %d (words: %d, minutes: %d)" wpm words minutes) - (kill-new (number-to-string wpm)) - ) - ) - ) - ) -#+end_src - -** Enable dict mode - #+begin_src elisp :tangle yes - (setq dictionary-server "automatic") - #+end_src - -** Pick out passive voice and weasel words -#+begin_src elisp :tangle yes - (use-package writegood-mode - :diminish writegood-mode - :config - (progn (add-hook 'text-mode-hook 'writegood-mode)) - ) -#+end_src - -** Org-babel docker -#+begin_src elisp :tangle yes - (use-package ob-docker-build - :straight (ob-docker-build :type git :host github :repo "ifitzpat/ob-docker-build") - :defer t - :config - (add-to-list 'org-babel-load-languages '(docker-build . t)) - (org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages) - ) -#+end_src - -* Spelling and syntax - -** Spell checking - -This requires installation of hunspell -#+begin_src bash :tangle yes - sudo apt install hunspell -#+end_src - -#+begin_src elisp - (use-package flyspell - :config (setq ispell-program-name "hunspell" - ispell-default-dictionary "en_US" - ) - :diminish (flyspell-mode . "φ") - :hook (text-mode . flyspell-mode) - :bind ( - ("M-" . flyspell-buffer) - ("" . flyspell-word) - ("C-;" . flyspell-auto-correct-previous-word) - ) - ) -#+end_src - -** Flyspell correct -#+begin_src elisp :tangle yes - (use-package flyspell-correct - :after flyspell - :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-wrapper)) - ) -#+end_src - -** Flycheck - -Needs external checkers installed - -#+begin_src elisp - (use-package flycheck - :defer t - :diminish (flycheck-mode . "") - :config - (setq flycheck-emacs-lisp-load-path 'inherit) - (setq flycheck-emacs-lisp-load-path (concat user-emacs-directory "straight/build"))) - -#+end_src - -** Flycheck bash -#+begin_src bash :tangle yes - sudo apt install devscripts -#+end_src - -#+begin_src elisp :tangle yes - (use-package flycheck-checkbashisms - :config - (flycheck-checkbashisms-setup) - ) -#+end_src - -** Yaml -#+begin_src elisp :tangle yes - (use-package yaml-mode - :config - (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) - (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode)) - ) -#+end_src - -** Docker -#+begin_src elisp :tangle yes - (use-package docker-compose-mode) -#+end_src \ No newline at end of file diff --git a/system/no ; This file is for loading other modules, not for tangling itself. b/system/no ; This file is for loading other modules, not for tangling itself. deleted file mode 100644 index d9af9d4..0000000 --- a/system/no ; This file is for loading other modules, not for tangling itself. +++ /dev/null @@ -1,16 +0,0 @@ -(let ((config-dir "~/memex/system/")) - ;; Load the core settings, including package management and essential setup. - (org-babel-load-file (expand-file-name "emacs-core.org" config-dir)) - - ;; Load early init settings (if separate and not fully covered by core) - (org-babel-load-file (expand-file-name "emacs-early-init.org" config-dir)) - - ;; Load other modules in a logical order - (org-babel-load-file (expand-file-name "emacs-org.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-gtd.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-roam.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-writing.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-media.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-shell.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-ai.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-misc.org" config-dir))) diff --git a/system/test_cli.py b/system/test_cli.py new file mode 100644 index 0000000..a740b54 --- /dev/null +++ b/system/test_cli.py @@ -0,0 +1,46 @@ +import socket +import struct + +def frame_message(msg_string): + payload = msg_string.encode('utf-8') + return f"{len(payload):06x}".encode('ascii') + payload + +def read_framed(sock): + header = b'' + while len(header) < 6: + chunk = sock.recv(6 - len(header)) + if not chunk: + return None + header += chunk + length = int(header, 16) + data = b'' + while len(data) < length: + chunk = sock.recv(length - len(data)) + if not chunk: + return None + data += chunk + return data.decode('utf-8') + +msg = '(:TYPE :REQUEST :PAYLOAD (:ACTION :MESSAGE :TEXT "hello") :META (:SOURCE :CLI :SESSION-ID "test1"))' + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.connect(('127.0.0.1', 9105)) +sock.settimeout(10.0) + +# Read handshake +handshake = read_framed(sock) +print("HANDSHAKE:", handshake) + +# Read status +status = read_framed(sock) +print("STATUS:", status) + +# Send message +sock.sendall(frame_message(msg)) +print("SENT:", msg) + +# Read response +response = read_framed(sock) +print("RESPONSE:", response) + +sock.close() diff --git a/system/yes ; Enable tangling so org-babel-load-file can generate the .el file. b/system/yes ; Enable tangling so org-babel-load-file can generate the .el file. deleted file mode 100644 index d9af9d4..0000000 --- a/system/yes ; Enable tangling so org-babel-load-file can generate the .el file. +++ /dev/null @@ -1,16 +0,0 @@ -(let ((config-dir "~/memex/system/")) - ;; Load the core settings, including package management and essential setup. - (org-babel-load-file (expand-file-name "emacs-core.org" config-dir)) - - ;; Load early init settings (if separate and not fully covered by core) - (org-babel-load-file (expand-file-name "emacs-early-init.org" config-dir)) - - ;; Load other modules in a logical order - (org-babel-load-file (expand-file-name "emacs-org.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-gtd.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-roam.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-writing.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-media.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-shell.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-ai.org" config-dir)) - (org-babel-load-file (expand-file-name "emacs-misc.org" config-dir)))