docs: add developer-workflow.org and language examples
Complete workflow guide for Perl, Python, Go, Ansible, Terraform, Podman. Includes working example files in examples/ directory.
This commit is contained in:
59
examples/ansible/playbook.yml
Normal file
59
examples/ansible/playbook.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
# playbook.yml — Demonstrates core Ansible features for Doom Emacs workflow.
|
||||||
|
#
|
||||||
|
# Navigate: SPC s i (imenu for tasks), SPC s p (grep in project)
|
||||||
|
# Run: SPC m r (ansible-playbook), Lint: flycheck (ansible-lint)
|
||||||
|
|
||||||
|
- name: Configure web server
|
||||||
|
hosts: webservers
|
||||||
|
become: true
|
||||||
|
|
||||||
|
vars:
|
||||||
|
app_user: webapp
|
||||||
|
app_port: 8080
|
||||||
|
packages:
|
||||||
|
- nginx
|
||||||
|
- python3
|
||||||
|
- python3-pip
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Restart nginx
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: nginx
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install required packages
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "{{ packages }}"
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Create application user
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ app_user }}"
|
||||||
|
shell: /bin/bash
|
||||||
|
create_home: true
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Deploy nginx config from template
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: templates/nginx.conf.j2
|
||||||
|
dest: /etc/nginx/sites-available/app.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify: Restart nginx
|
||||||
|
|
||||||
|
- name: Enable site symlink
|
||||||
|
ansible.builtin.file:
|
||||||
|
src: /etc/nginx/sites-available/app.conf
|
||||||
|
dest: /etc/nginx/sites-enabled/app.conf
|
||||||
|
state: link
|
||||||
|
notify: Restart nginx
|
||||||
|
|
||||||
|
- name: Ensure nginx is running
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: nginx
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
44
examples/docker/Dockerfile
Normal file
44
examples/docker/Dockerfile
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Dockerfile — Multi-stage build for a Python application.
|
||||||
|
#
|
||||||
|
# Navigate: SPC s i (imenu), Lint: flycheck (hadolint)
|
||||||
|
# Build: SPC m b (podman build), Run: SPC m r (podman run)
|
||||||
|
#
|
||||||
|
# Build: podman build -t myapp:latest -f Dockerfile .
|
||||||
|
# Run: podman run --rm -p 8080:8080 myapp:latest
|
||||||
|
|
||||||
|
# --- Stage 1: Build dependencies ---
|
||||||
|
FROM python:3.12-slim AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# Install dependencies first (layer caching)
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
|
||||||
|
|
||||||
|
# --- Stage 2: Runtime image ---
|
||||||
|
FROM python:3.12-slim AS runtime
|
||||||
|
|
||||||
|
# Security: non-root user
|
||||||
|
RUN groupadd -r appuser && useradd -r -g appuser -d /app -s /sbin/nologin appuser
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy installed packages from builder
|
||||||
|
COPY --from=builder /install /usr/local
|
||||||
|
|
||||||
|
# Copy application code
|
||||||
|
COPY app/ ./app/
|
||||||
|
COPY main.py .
|
||||||
|
|
||||||
|
# Set ownership
|
||||||
|
RUN chown -R appuser:appuser /app
|
||||||
|
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# Healthcheck: verify the app responds
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||||
|
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')" || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["python", "main.py"]
|
||||||
105
examples/go/main.go
Normal file
105
examples/go/main.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
// main.go — Demonstrates core Go features for Doom Emacs workflow.
|
||||||
|
//
|
||||||
|
// Navigate: C-M-a/e (function boundaries), SPC s i (imenu), gd (definition)
|
||||||
|
// Format: SPC m f (goimports), Run: SPC m r, Test: SPC m t, Build: SPC m b
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Task represents a work item with priority.
|
||||||
|
type Task struct {
|
||||||
|
Title string
|
||||||
|
Priority int
|
||||||
|
Done bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summary returns a human-readable one-line description.
|
||||||
|
func (t *Task) Summary() string {
|
||||||
|
status := "TODO"
|
||||||
|
if t.Done {
|
||||||
|
status = "DONE"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("[%s] %s (p%d)", status, t.Title, t.Priority)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkDone marks the task as completed.
|
||||||
|
func (t *Task) MarkDone() {
|
||||||
|
t.Done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// filterByPriority returns undone tasks with priority >= minPriority.
|
||||||
|
func filterByPriority(tasks []*Task, minPriority int) []*Task {
|
||||||
|
var result []*Task
|
||||||
|
for _, t := range tasks {
|
||||||
|
if !t.Done && t.Priority >= minPriority {
|
||||||
|
result = append(result, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// countWords demonstrates a goroutine + channel pattern.
|
||||||
|
// It counts words in each input string concurrently.
|
||||||
|
func countWords(inputs []string) map[string]int {
|
||||||
|
type result struct {
|
||||||
|
input string
|
||||||
|
count int
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := make(chan result, len(inputs))
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
for _, s := range inputs {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(text string) {
|
||||||
|
defer wg.Done()
|
||||||
|
// Simulate work
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
ch <- result{input: text, count: len(strings.Fields(text))}
|
||||||
|
}(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close channel after all goroutines finish
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
counts := make(map[string]int)
|
||||||
|
for r := range ch {
|
||||||
|
counts[r.input] = r.count
|
||||||
|
}
|
||||||
|
return counts
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tasks := []*Task{
|
||||||
|
{Title: "Write tests", Priority: 2},
|
||||||
|
{Title: "Update docs", Priority: 1},
|
||||||
|
{Title: "Deploy v2", Priority: 2},
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks[0].MarkDone()
|
||||||
|
|
||||||
|
fmt.Println("Open tasks (priority >= 2):")
|
||||||
|
for _, t := range filterByPriority(tasks, 2) {
|
||||||
|
fmt.Println(" ", t.Summary())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Goroutine demo
|
||||||
|
sentences := []string{
|
||||||
|
"Go is a compiled language",
|
||||||
|
"Goroutines are lightweight threads",
|
||||||
|
"Channels enable safe communication",
|
||||||
|
}
|
||||||
|
counts := countWords(sentences)
|
||||||
|
fmt.Println("\nWord counts:")
|
||||||
|
for s, c := range counts {
|
||||||
|
fmt.Printf(" %q → %d words\n", s, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
65
examples/perl/example.pl
Normal file
65
examples/perl/example.pl
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
# example.pl — Demonstrates core Perl features for Doom Emacs workflow.
|
||||||
|
# Navigate: C-M-a/e (sub boundaries), SPC s i (imenu), gd (definition)
|
||||||
|
# Format: SPC m f (perltidy), Run: SPC m r, Debug: SPC m d
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Carp qw(croak);
|
||||||
|
|
||||||
|
# --- Subroutine with documentation ---
|
||||||
|
|
||||||
|
=head2 parse_config($filename)
|
||||||
|
|
||||||
|
Reads a simple key=value config file. Returns a hashref.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub parse_config {
|
||||||
|
my ($filename) = @_;
|
||||||
|
croak "Filename required" unless defined $filename;
|
||||||
|
|
||||||
|
my %config;
|
||||||
|
open my $fh, '<', $filename
|
||||||
|
or die "Cannot open '$filename': $!\n";
|
||||||
|
|
||||||
|
while (my $line = <$fh>) {
|
||||||
|
chomp $line;
|
||||||
|
next if $line =~ /^\s*(?:#|$)/; # skip comments and blanks
|
||||||
|
if ($line =~ /^(\w+)\s*=\s*(.*)$/) {
|
||||||
|
$config{$1} = $2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close $fh;
|
||||||
|
return \%config;
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Array, hash, references ---
|
||||||
|
|
||||||
|
my @languages = qw(Perl Python Go);
|
||||||
|
my %scores = (Perl => 95, Python => 90, Go => 88);
|
||||||
|
|
||||||
|
my $lang_ref = \@languages;
|
||||||
|
my $score_ref = \%scores;
|
||||||
|
|
||||||
|
printf "Languages: %s\n", join(', ', @{$lang_ref});
|
||||||
|
printf "Perl score: %d\n", $score_ref->{Perl};
|
||||||
|
|
||||||
|
# --- Regex demo ---
|
||||||
|
|
||||||
|
my $text = 'Error: connection refused at 2024-01-15 10:30:00';
|
||||||
|
if ($text =~ /^(Error|Warning):\s+(.+?)\s+at\s+(\d{4}-\d{2}-\d{2})/) {
|
||||||
|
printf "Level: %s, Message: %s, Date: %s\n", $1, $2, $3;
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Error handling with eval/die ---
|
||||||
|
|
||||||
|
eval {
|
||||||
|
my $cfg = parse_config('/tmp/nonexistent.cfg');
|
||||||
|
print "Loaded config\n";
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
warn "Caught error: $@";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "Done.\n";
|
||||||
70
examples/python/example.py
Normal file
70
examples/python/example.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""example.py — Demonstrates core Python features for Doom Emacs workflow.
|
||||||
|
|
||||||
|
Navigate: C-M-a/e (function boundaries), SPC s i (imenu), gd (definition)
|
||||||
|
Format: SPC m f (ruff format), Run: SPC m r
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Task:
|
||||||
|
"""A simple task with priority and tags."""
|
||||||
|
|
||||||
|
title: str
|
||||||
|
priority: int = 0
|
||||||
|
tags: list[str] = field(default_factory=list)
|
||||||
|
done: bool = False
|
||||||
|
|
||||||
|
def mark_done(self) -> None:
|
||||||
|
self.done = True
|
||||||
|
|
||||||
|
def summary(self) -> str:
|
||||||
|
status = "DONE" if self.done else "TODO"
|
||||||
|
tag_str = ", ".join(self.tags) if self.tags else "none"
|
||||||
|
return f"[{status}] {self.title} (p{self.priority}, tags: {tag_str})"
|
||||||
|
|
||||||
|
|
||||||
|
def filter_tasks(tasks: list[Task], *, min_priority: int = 0) -> list[Task]:
|
||||||
|
"""Return undone tasks with priority >= min_priority."""
|
||||||
|
return [t for t in tasks if not t.done and t.priority >= min_priority]
|
||||||
|
|
||||||
|
|
||||||
|
def load_tasks_from_file(path: str) -> list[Task]:
|
||||||
|
"""Load tasks from a simple text file (one title per line)."""
|
||||||
|
tasks: list[Task] = []
|
||||||
|
try:
|
||||||
|
with open(path, encoding="utf-8") as fh:
|
||||||
|
for i, line in enumerate(fh):
|
||||||
|
title = line.strip()
|
||||||
|
if title:
|
||||||
|
tasks.append(Task(title=title, priority=i % 3))
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"File not found: {path}, using demo tasks")
|
||||||
|
tasks = [
|
||||||
|
Task("Write tests", priority=2, tags=["dev"]),
|
||||||
|
Task("Update docs", priority=1, tags=["docs"]),
|
||||||
|
Task("Deploy v2", priority=2, tags=["ops", "dev"]),
|
||||||
|
]
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser(description="Task manager demo")
|
||||||
|
parser.add_argument("-f", "--file", default="tasks.txt", help="Task file")
|
||||||
|
parser.add_argument("-p", "--priority", type=int, default=1, help="Min priority")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
tasks = load_tasks_from_file(args.file)
|
||||||
|
tasks[0].mark_done()
|
||||||
|
|
||||||
|
important = filter_tasks(tasks, min_priority=args.priority)
|
||||||
|
print(f"Open tasks (priority >= {args.priority}):")
|
||||||
|
for task in important:
|
||||||
|
print(f" {task.summary()}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
39
examples/terraform/main.tf
Normal file
39
examples/terraform/main.tf
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# main.tf — Demonstrates core Terraform features for Doom Emacs workflow.
|
||||||
|
#
|
||||||
|
# Navigate: SPC s i (imenu), SPC s p (grep in project)
|
||||||
|
# Format: SPC m f (terraform fmt), Init: SPC m i, Plan: SPC m p
|
||||||
|
#
|
||||||
|
# Uses null_resource for a provider-free demo. Replace with real providers
|
||||||
|
# (aws, azurerm, google) for actual infrastructure.
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 1.5"
|
||||||
|
required_providers {
|
||||||
|
null = {
|
||||||
|
source = "hashicorp/null"
|
||||||
|
version = "~> 3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# A null resource that runs a local command — useful for demos and provisioning
|
||||||
|
resource "null_resource" "hello" {
|
||||||
|
triggers = {
|
||||||
|
message = var.greeting_message
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "local-exec" {
|
||||||
|
command = "echo '${var.greeting_message}' > /tmp/terraform-hello.txt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Output the greeting message for verification
|
||||||
|
output "greeting" {
|
||||||
|
description = "The greeting message written to file"
|
||||||
|
value = var.greeting_message
|
||||||
|
}
|
||||||
|
|
||||||
|
output "environment" {
|
||||||
|
description = "Current deployment environment"
|
||||||
|
value = var.environment
|
||||||
|
}
|
||||||
18
examples/terraform/variables.tf
Normal file
18
examples/terraform/variables.tf
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# variables.tf — Input variables for the Terraform demo.
|
||||||
|
|
||||||
|
variable "greeting_message" {
|
||||||
|
description = "Message to write to the output file"
|
||||||
|
type = string
|
||||||
|
default = "Hello from Terraform!"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "environment" {
|
||||||
|
description = "Deployment environment name"
|
||||||
|
type = string
|
||||||
|
default = "dev"
|
||||||
|
|
||||||
|
validation {
|
||||||
|
condition = contains(["dev", "staging", "prod"], var.environment)
|
||||||
|
error_message = "Environment must be dev, staging, or prod."
|
||||||
|
}
|
||||||
|
}
|
||||||
343
notes/developer-workflow.org
Normal file
343
notes/developer-workflow.org
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
#+TITLE: Developer Workflow v Doom Emacs
|
||||||
|
#+AUTHOR: Martin Sukaný
|
||||||
|
#+DATE: [2026-02-24 Tue]
|
||||||
|
#+OPTIONS: toc:3 num:t
|
||||||
|
#+STARTUP: overview
|
||||||
|
|
||||||
|
* Úvod
|
||||||
|
|
||||||
|
Tento dokument popisuje kompletní vývojářský workflow v Doom Emacs pro jazyky a nástroje, které Martin používá: Perl, Python, Go, Ansible, Terraform a Podman/Dockerfile. Ke každému jazyku najdeš: co nainstalovat, klávesové zkratky, příklad workflow a odkaz na ukázkový soubor v =examples/=.
|
||||||
|
|
||||||
|
* Instalace nástrojů
|
||||||
|
|
||||||
|
Všechny nástroje se instalují přes Homebrew (macOS). Na Linuxu použij příslušný package manager.
|
||||||
|
|
||||||
|
** Perl
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install perl
|
||||||
|
cpanm Perl::Tidy Perl::Critic Perl::LanguageServer
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
- =perltidy= — formatter (SPC m f)
|
||||||
|
- =perlcritic= — linter
|
||||||
|
- =Perl::LanguageServer= — LSP backend (volitelné)
|
||||||
|
|
||||||
|
** Python
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install python ruff pyright
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
- =ruff= — ultra-rychlý linter + formatter
|
||||||
|
- =pyright= — type-checking LSP server
|
||||||
|
|
||||||
|
** Go
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install go gopls
|
||||||
|
go install golang.org/x/tools/cmd/goimports@latest
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
- =gopls= — oficiální Go LSP
|
||||||
|
- =goimports= — formatter (gofmt + auto imports)
|
||||||
|
|
||||||
|
** Ansible
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install ansible ansible-lint
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
- =ansible-lint= — linter pro playbooky (flycheck integrace)
|
||||||
|
|
||||||
|
** Terraform
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install terraform terraform-ls
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
- =terraform-ls= — HashiCorp oficiální LSP server
|
||||||
|
|
||||||
|
** Podman / Dockerfile
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install podman hadolint
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
- =hadolint= — Dockerfile linter (flycheck integrace)
|
||||||
|
- =podman= — Docker-kompatibilní container runtime (daemonless)
|
||||||
|
|
||||||
|
* Keybindings přehled
|
||||||
|
|
||||||
|
Všechny keybindings jsou pod =SPC m= (localleader) — aktivní pouze v příslušném major mode.
|
||||||
|
|
||||||
|
| Jazyk | SPC m f | SPC m r | SPC m t / b | SPC m d | SPC m i / p |
|
||||||
|
|------------+-----------------+------------------+------------------+-----------+------------------|
|
||||||
|
| Perl | perltidy format | perl run | — | perldb | — |
|
||||||
|
| Python | ruff format | python3 run | — | M-x pdb | — |
|
||||||
|
| Go | goimports | go run | go test / build | M-x dlv | — |
|
||||||
|
| Ansible | — | ansible-playbook | — | — | — |
|
||||||
|
| Terraform | terraform fmt | — | — | — | init / plan |
|
||||||
|
| Dockerfile | — | podman run | podman build | — | — |
|
||||||
|
|
||||||
|
Obecné navigační zkratky (všechny jazyky):
|
||||||
|
|
||||||
|
| Zkratka | Akce |
|
||||||
|
|-------------+-----------------------------------|
|
||||||
|
| =C-M-a= | Začátek funkce/subroutine |
|
||||||
|
| =C-M-e= | Konec funkce/subroutine |
|
||||||
|
| =SPC s i= | Imenu — seznam funkcí v souboru |
|
||||||
|
| =gd= | Go to definition (LSP/tags) |
|
||||||
|
| =] e= / =[ e= | Další/předchozí flycheck error |
|
||||||
|
| =SPC s p= | Grep v projektu (ripgrep) |
|
||||||
|
| =SPC p f= | Najít soubor v projektu |
|
||||||
|
|
||||||
|
* Perl — workflow
|
||||||
|
|
||||||
|
** Co nainstalovat
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install perl
|
||||||
|
cpanm Perl::Tidy Perl::Critic Perl::LanguageServer
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Keybindings
|
||||||
|
|
||||||
|
| Zkratka | Akce |
|
||||||
|
|-----------+-----------------------------|
|
||||||
|
| =SPC m f= | Formátování přes perltidy |
|
||||||
|
| =SPC m r= | Spustit aktuální soubor |
|
||||||
|
| =SPC m d= | Spustit Perl debugger |
|
||||||
|
| =C-M-a= | Skok na začátek subroutine |
|
||||||
|
| =C-M-e= | Skok na konec subroutine |
|
||||||
|
| =SPC s i= | Imenu — seznam subs |
|
||||||
|
|
||||||
|
** Příklad workflow
|
||||||
|
|
||||||
|
1. Otevři soubor: =SPC p f= → vyber =example.pl=
|
||||||
|
2. Navigace po subs: =SPC s i= → vyber subroutine ze seznamu
|
||||||
|
3. Pohyb mezi subs: =C-M-a= (začátek), =C-M-e= (konec)
|
||||||
|
4. Formátování: =SPC m f= (perltidy celý buffer)
|
||||||
|
5. Spuštění: =SPC m r= — otevře compile buffer s výstupem
|
||||||
|
6. Debug: =SPC m d= → zadej soubor → v kódu přidej =$DB::single = 1;= pro breakpoint
|
||||||
|
7. Chyby: =] e= / =[ e= pro navigaci flycheck errors
|
||||||
|
|
||||||
|
** Ukázkový soubor
|
||||||
|
|
||||||
|
Viz =[[file:../examples/perl/example.pl][examples/perl/example.pl]]= — demonstruje strict/warnings, subroutines, hashe, regex, file I/O a error handling.
|
||||||
|
|
||||||
|
* Python — workflow
|
||||||
|
|
||||||
|
** Co nainstalovat
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install python ruff pyright
|
||||||
|
pip install pyvenv # volitelné, pro virtualenv management
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Keybindings
|
||||||
|
|
||||||
|
| Zkratka | Akce |
|
||||||
|
|-----------+-----------------------------|
|
||||||
|
| =SPC m f= | Formátování přes ruff |
|
||||||
|
| =SPC m r= | Spustit aktuální soubor |
|
||||||
|
| =gd= | Go to definition (pyright) |
|
||||||
|
| =K= | Hover docs (LSP) |
|
||||||
|
| =SPC s i= | Imenu — seznam tříd/funkcí |
|
||||||
|
|
||||||
|
** Příklad workflow
|
||||||
|
|
||||||
|
1. Otevři projekt: =SPC p p= → vyber Python projekt
|
||||||
|
2. Virtual env: =M-x pyvenv-activate= → vyber venv adresář
|
||||||
|
3. Navigace: =SPC s i= pro přehled tříd a funkcí
|
||||||
|
4. LSP: =gd= (definice), =K= (docs), =gr= (references)
|
||||||
|
5. Format: =SPC m f= — ruff format na celý soubor
|
||||||
|
6. Run: =SPC m r= — spustí =python3 buffer.py= v compile bufferu
|
||||||
|
7. Debug: =M-x pdb= → zadej =python3 -m pdb soubor.py=
|
||||||
|
8. Chyby: =] e= / =[ e= pro flycheck (ruff lint)
|
||||||
|
|
||||||
|
** Ukázkový soubor
|
||||||
|
|
||||||
|
Viz =[[file:../examples/python/example.py][examples/python/example.py]]= — demonstruje type hints, dataclass, list comprehension, argparse a exception handling.
|
||||||
|
|
||||||
|
* Go — workflow
|
||||||
|
|
||||||
|
** Co nainstalovat
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install go gopls
|
||||||
|
go install golang.org/x/tools/cmd/goimports@latest
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Keybindings
|
||||||
|
|
||||||
|
| Zkratka | Akce |
|
||||||
|
|-----------+------------------------------|
|
||||||
|
| =SPC m f= | Formátování (goimports) |
|
||||||
|
| =SPC m r= | go run aktuální soubor |
|
||||||
|
| =SPC m t= | go test ./... |
|
||||||
|
| =SPC m b= | go build ./... |
|
||||||
|
| =gd= | Go to definition (gopls) |
|
||||||
|
| =K= | Hover docs (gopls) |
|
||||||
|
|
||||||
|
** Příklad workflow
|
||||||
|
|
||||||
|
1. Nový projekt: =go mod init myproject= v terminálu
|
||||||
|
2. Otevři: =SPC p f= → =main.go=
|
||||||
|
3. LSP automaticky: gopls se spustí, poskytuje completion, diagnostiku, navigaci
|
||||||
|
4. Píšeš kód: goimports automaticky doplní importy při uložení
|
||||||
|
5. Run: =SPC m r= → =go run main.go=
|
||||||
|
6. Test: =SPC m t= → =go test ./...=
|
||||||
|
7. Build: =SPC m b= → =go build ./...=
|
||||||
|
|
||||||
|
** Ukázkový soubor
|
||||||
|
|
||||||
|
Viz =[[file:../examples/go/main.go][examples/go/main.go]]= — demonstruje struct, methods, error handling, goroutine a channel.
|
||||||
|
|
||||||
|
* Ansible — workflow
|
||||||
|
|
||||||
|
** Co nainstalovat
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install ansible ansible-lint
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Keybindings
|
||||||
|
|
||||||
|
| Zkratka | Akce |
|
||||||
|
|-----------+-------------------------------|
|
||||||
|
| =SPC m r= | Spustit ansible-playbook |
|
||||||
|
| =] e= | Další ansible-lint chyba |
|
||||||
|
| =SPC s p= | Grep v projektu (role, vars) |
|
||||||
|
|
||||||
|
** Příklad workflow
|
||||||
|
|
||||||
|
1. Otevři playbook: =SPC p f= → =playbook.yml=
|
||||||
|
2. Yaml-mode se aktivuje automaticky, ansible-lint přes flycheck
|
||||||
|
3. Navigace: =SPC s i= pro imenu (task names)
|
||||||
|
4. Spuštění: =SPC m r= — spustí =ansible-playbook playbook.yml=
|
||||||
|
5. Lint chyby: =] e= / =[ e= pro navigaci
|
||||||
|
|
||||||
|
** Ukázkový soubor
|
||||||
|
|
||||||
|
Viz =[[file:../examples/ansible/playbook.yml][examples/ansible/playbook.yml]]= — demonstruje apt install, user create, template copy, handlers a vars.
|
||||||
|
|
||||||
|
* Terraform — workflow
|
||||||
|
|
||||||
|
** Co nainstalovat
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install terraform terraform-ls
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Keybindings
|
||||||
|
|
||||||
|
| Zkratka | Akce |
|
||||||
|
|-----------+-------------------------|
|
||||||
|
| =SPC m f= | terraform fmt |
|
||||||
|
| =SPC m i= | terraform init |
|
||||||
|
| =SPC m p= | terraform plan |
|
||||||
|
| =gd= | Go to definition (LSP) |
|
||||||
|
|
||||||
|
** Příklad workflow
|
||||||
|
|
||||||
|
1. Nový projekt: vytvoř adresář, =main.tf= + =variables.tf=
|
||||||
|
2. Init: =SPC m i= — stáhne providery
|
||||||
|
3. LSP (terraform-ls): autocompletion pro resource typy, atributy, variables
|
||||||
|
4. Format: =SPC m f= — terraform fmt (kanonický styl)
|
||||||
|
5. Plan: =SPC m p= — ukáže co se změní
|
||||||
|
6. Apply: v terminálu =terraform apply=
|
||||||
|
|
||||||
|
** Ukázkové soubory
|
||||||
|
|
||||||
|
Viz =[[file:../examples/terraform/main.tf][examples/terraform/main.tf]]= a =[[file:../examples/terraform/variables.tf][examples/terraform/variables.tf]]= — demonstrují null provider, resource, variable, output a validation.
|
||||||
|
|
||||||
|
* Podman / Dockerfile — workflow
|
||||||
|
|
||||||
|
** Co nainstalovat
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
brew install podman hadolint
|
||||||
|
podman machine init # jednorázově
|
||||||
|
podman machine start
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Keybindings
|
||||||
|
|
||||||
|
| Zkratka | Akce |
|
||||||
|
|-----------+-----------------------------------|
|
||||||
|
| =SPC m b= | podman build (zeptá se na tag) |
|
||||||
|
| =SPC m r= | podman run (zeptá se na image) |
|
||||||
|
| =] e= | Další hadolint chyba |
|
||||||
|
|
||||||
|
** Příklad workflow
|
||||||
|
|
||||||
|
1. Otevři =Dockerfile=: dockerfile-mode se aktivuje automaticky
|
||||||
|
2. Hadolint: flycheck ukazuje best practices (DL3008, DL3059 atd.)
|
||||||
|
3. Build: =SPC m b= → zadej tag (např. =myapp:latest=) → compile buffer
|
||||||
|
4. Run: =SPC m r= → zadej image name → spustí container
|
||||||
|
|
||||||
|
** Ukázkový soubor
|
||||||
|
|
||||||
|
Viz =[[file:../examples/docker/Dockerfile][examples/docker/Dockerfile]]= — demonstruje multi-stage build, non-root user, HEALTHCHECK a layer caching.
|
||||||
|
|
||||||
|
* Go — učení (začátečník)
|
||||||
|
|
||||||
|
** Základní kroky
|
||||||
|
|
||||||
|
1. Vytvoř projekt:
|
||||||
|
#+begin_src bash
|
||||||
|
mkdir myproject && cd myproject
|
||||||
|
go mod init myproject
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
2. Struktura:
|
||||||
|
#+begin_example
|
||||||
|
myproject/
|
||||||
|
├── go.mod
|
||||||
|
├── main.go # vstupní bod
|
||||||
|
├── internal/ # interní balíčky
|
||||||
|
│ └── handler.go
|
||||||
|
└── pkg/ # veřejné balíčky
|
||||||
|
└── utils.go
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
3. Spusť: =go run main.go= (nebo =SPC m r= v Emacsu)
|
||||||
|
4. Test: =go test ./...= (nebo =SPC m t=)
|
||||||
|
5. Build: =go build -o myapp= (nebo =SPC m b=)
|
||||||
|
|
||||||
|
** Klíčové koncepty
|
||||||
|
|
||||||
|
- =package main= + =func main()= = vstupní bod
|
||||||
|
- Error handling: =if err != nil { return err }= (žádné exceptions)
|
||||||
|
- Goroutines: =go func()= pro souběžnost
|
||||||
|
- Channels: =ch := make(chan int)= pro komunikaci mezi goroutines
|
||||||
|
- Interfaces: implicitní implementace (duck typing)
|
||||||
|
|
||||||
|
** Příklad
|
||||||
|
|
||||||
|
Viz =[[file:../examples/go/main.go][examples/go/main.go]]= pro funkční ukázku všech konceptů.
|
||||||
|
|
||||||
|
* Obecné tipy
|
||||||
|
|
||||||
|
| Zkratka | Akce |
|
||||||
|
|---------------+-----------------------------------------|
|
||||||
|
| =SPC s p= | Grep v projektu (ripgrep) |
|
||||||
|
| =SPC p f= | Najít soubor v projektu |
|
||||||
|
| =SPC p p= | Přepnout projekt |
|
||||||
|
| =SPC g g= | Magit — git status |
|
||||||
|
| =SPC g B= | Git blame |
|
||||||
|
| =C-M-a= / =C-M-e= | Pohyb po funkcích (všechny jazyky) |
|
||||||
|
| =] e= / =[ e= | Flycheck: další/předchozí error |
|
||||||
|
| =SPC c x= | Flycheck: seznam všech errors |
|
||||||
|
| =SPC b b= | Přepnout buffer |
|
||||||
|
| =SPC w v= | Vertikální split |
|
||||||
|
| =SPC o t= | Otevřít terminál (vterm) |
|
||||||
|
|
||||||
|
** Compile buffer
|
||||||
|
|
||||||
|
Všechny =SPC m r/t/b= příkazy používají Emacs =compile= — výstup se zobrazí v compile bufferu. Klávesy v compile bufferu:
|
||||||
|
|
||||||
|
- =g= — znovu spustit
|
||||||
|
- =q= — zavřít
|
||||||
|
- =RET= na error řádku — skok na zdrojový kód
|
||||||
Reference in New Issue
Block a user