Skip to content

Latest commit

 

History

History
413 lines (319 loc) · 9.39 KB

File metadata and controls

413 lines (319 loc) · 9.39 KB

Fase 3: Funcionalidad Avanzada - Plan de Implementación

Estado actual: Fase 2 completada ✅ Objetivo: Agregar funcionalidades avanzadas tipo Vim


Resumen de lo Completado (Fase 1 y 2)

✅ Fase 1

  • BufferManager con init y guards
  • FasAPI con Builder pattern
  • EditorState completamente implementado
  • HookRegistry arreglado con FasEventType
  • FasKeymap type-safe

✅ Fase 2

  • TerminalInput con raw mode
  • Key enum completo
  • Cursor con movimientos Vim (hjkl, w, b, e, 0, $, g, G)
  • Buffer operations (insert, delete, getText)
  • UndoManager funcional
  • UIRenderer con viewport y scroll
  • Comandos básicos (:w, :q, :e, :wq)
  • 4 modos implementados (normal, insert, visual, command)
  • Visual mode con yank/delete
  • Argumentos de línea de comandos

🎯 Fase 3: Features a Implementar

Prioridad 1: Counts (Repetición de Comandos)

Objetivo: Soportar 5j, 3w, 10x, 2dd

Implementación:

  1. Agregar campo count a EditorState
  2. Parser de números en normal mode
  3. Aplicar count a movimientos y comandos

Ejemplo de uso:

5j    → Bajar 5 líneas
3w    → Avanzar 3 palabras
10x   → Eliminar 10 caracteres
2dd   → Eliminar 2 líneas

Dificultad: ⭐⭐ (Media) Tiempo estimado: 2-3 horas


Prioridad 2: Búsqueda (/ y ?)

Objetivo: Búsqueda incremental con /pattern y ?pattern

Implementación:

  1. Agregar modo de búsqueda (search mode)
  2. Buffer de búsqueda para pattern
  3. Función de búsqueda en Buffer
  4. Highlight de matches
  5. Navegación con n/N

Ejemplo de uso:

/hello    → Buscar "hello" hacia adelante
?world    → Buscar "world" hacia atrás
n         → Siguiente match
N         → Match anterior

Componentes:

// SearchEngine.swift
public struct SearchEngine {
    public func search(
        pattern: String,
        in buffer: Buffer,
        from: BufferPosition,
        direction: SearchDirection
    ) -> [BufferPosition]

    public enum SearchDirection {
        case forward
        case backward
    }
}

Dificultad: ⭐⭐⭐ (Media-Alta) Tiempo estimado: 4-6 horas


Prioridad 3: Paste (p y P)

Objetivo: Pegar texto yankeado con p (después) y P (antes)

Implementación:

  1. Verificar que ya tenemos registers en EditorState
  2. Implementar comando p en normal mode
  3. Implementar comando P en normal mode
  4. Manejar paste de líneas completas vs caracteres

Ejemplo de uso:

yy    → Yank línea actual
p     → Paste después del cursor
P     → Paste antes del cursor

Dificultad: ⭐⭐ (Media) Tiempo estimado: 2-3 horas


Prioridad 4: Operators + Motions

Objetivo: Combinar operators (d, y, c) con motions (w, $, 2j)

Implementación:

  1. Parser de comandos compuestos
  2. Sistema de "pending operator"
  3. Aplicar operator al motion

Ejemplos:

d2w     → Delete 2 words
y$      → Yank hasta fin de línea
c3w     → Change 3 words
diw     → Delete inner word

Componentes:

// Operator.swift
public enum Operator {
    case delete
    case yank
    case change
    case visual
}

// Motion.swift
public enum Motion {
    case words(count: Int)
    case toEndOfLine
    case toStartOfLine
    case lines(count: Int)
}

// OperatorMotionParser.swift
public struct OperatorMotionParser {
    public func parse(_ input: String) -> (Operator, Motion)?
}

Dificultad: ⭐⭐⭐⭐ (Alta) Tiempo estimado: 6-8 horas


Prioridad 5: Marks (m{a-z} y '{a-z})

Objetivo: Marcar posiciones y saltar a ellas

Implementación:

  1. Agregar marks: [Character: BufferPosition] a EditorState
  2. Comando m{a-z} para marcar
  3. Comando '{a-z} para saltar

Ejemplo de uso:

ma      → Marcar posición como 'a'
'a      → Saltar a marca 'a'
``      → Saltar a posición anterior

Dificultad: ⭐⭐ (Media) Tiempo estimado: 2-3 horas


Prioridad 6: Sistema de Registros Completo

Objetivo: Registros nombrados y especiales

Implementación:

  1. Registros nombrados: "a a "z
  2. Registro sin nombre: ""
  3. Registro de sistema (clipboard): "+
  4. Registros de búsqueda: "/

Ejemplo de uso:

"ayy    → Yank línea al registro 'a'
"ap     → Paste desde registro 'a'
"+yy    → Yank al clipboard del sistema
"+p     → Paste desde clipboard

Componentes:

// RegisterManager.swift
public final class RegisterManager {
    private var registers: [String: String] = [:]

    public var unnamed: String {
        get { registers[""] ?? "" }
        set { registers[""] = newValue }
    }

    public var systemClipboard: String {
        get { NSPasteboard.general.string(forType: .string) ?? "" }
        set { NSPasteboard.general.setString(newValue, forType: .string) }
    }

    public subscript(name: String) -> String {
        get { registers[name] ?? "" }
        set { registers[name] = newValue }
    }
}

Dificultad: ⭐⭐⭐ (Media-Alta) Tiempo estimado: 3-4 horas


Prioridad 7: Macros (q{a-z} y @{a-z})

Objetivo: Grabar y reproducir secuencias de comandos

Implementación:

  1. Estado de grabación en EditorState
  2. Buffer de macro
  3. Grabar teclas durante q{a-z}
  4. Reproducir con @{a-z}
  5. Repetir última macro con @@

Ejemplo de uso:

qa      → Empezar a grabar en registro 'a'
...     → Ejecutar comandos
q       → Detener grabación
@a      → Ejecutar macro 'a'
@@      → Repetir última macro
3@a     → Ejecutar macro 'a' 3 veces

Componentes:

// MacroRecorder.swift
public final class MacroRecorder {
    private var isRecording: Bool = false
    private var currentRegister: Character?
    private var recordedKeys: [Key] = []

    public func startRecording(register: Character)
    public func stopRecording()
    public func recordKey(_ key: Key)
    public func playback(register: Character) -> [Key]
}

Dificultad: ⭐⭐⭐⭐ (Alta) Tiempo estimado: 5-7 horas


📋 Plan de Ejecución Recomendado

Semana 1

  1. Día 1-2: Implementar Counts (5j, 3w)
  2. Día 3-4: Implementar Paste (p, P)
  3. Día 5: Implementar Marks (m, ')

Semana 2

  1. Día 1-3: Implementar Búsqueda (/, ?, n, N)
  2. Día 4-5: Implementar Sistema de Registros

Semana 3

  1. Día 1-3: Implementar Operators + Motions (d2w, y$)
  2. Día 4-5: Implementar Macros (q, @)

Semana 4

  1. Testing exhaustivo de todas las features
  2. Bug fixes y refinamiento
  3. Documentación de uso

🎯 Objetivos de la Fase 3

Al completar la Fase 3, el editor debería poder:

✅ Repetir comandos con counts (5j, 3w) ✅ Buscar texto con / y ? ✅ Navegar búsqueda con n y N ✅ Pegar texto con p y P ✅ Combinar operators y motions (d2w, y$) ✅ Marcar posiciones y saltar (ma, 'a) ✅ Usar registros nombrados ("ayy, "ap) ✅ Copiar/pegar con clipboard del sistema ("+y, "+p) ✅ Grabar y ejecutar macros (qa, @a)


📊 Métricas de Éxito

Funcionalidad

  • Todos los counts funcionan (1-999)
  • Búsqueda encuentra todos los matches
  • Paste funciona con líneas y caracteres
  • Operators + motions son composables
  • Marks persisten durante la sesión
  • Registros mantienen contenido
  • Macros se pueden grabar y reproducir

Performance

  • Búsqueda < 100ms en archivos de 10,000 líneas
  • Paste instantáneo (< 50ms)
  • Macros ejecutan sin lag visible

UX

  • Feedback visual claro (modo, count, pending operator)
  • Mensajes de error descriptivos
  • Comportamiento idéntico a Vim en casos comunes

🔧 Estructura de Archivos Nueva

Sources/FasCore/
├── Search/
│   ├── SearchEngine.swift       # NEW
│   └── SearchMode.swift          # NEW
├── Operators/
│   ├── Operator.swift            # NEW
│   ├── Motion.swift              # NEW
│   └── OperatorMotionParser.swift # NEW
├── Registers/
│   └── RegisterManager.swift     # NEW
├── Macros/
│   └── MacroRecorder.swift       # NEW
└── State/
    └── EditorState.swift         # MODIFICAR (agregar fields)

🎓 Referencias

Vim Documentation

  • :help count
  • :help /
  • :help registers
  • :help recording

Código de Referencia

  • Neovim: /src/nvim/search.c
  • Kakoune: /src/registers.cc
  • Helix: /helix-term/src/keymap.rs

⚠️ Consideraciones Importantes

Counts

  • Reset count después de ejecutar comando
  • Validar que count > 0
  • Manejar overflow (count > 10000)

Búsqueda

  • Escapar caracteres especiales en regex
  • Wrap around al final del archivo
  • Highlight todos los matches

Paste

  • Detectar si es paste de línea o carácter
  • Ajustar cursor después de paste
  • Registrar en undo

Operators + Motions

  • Parser robusto que no confunda comandos
  • Timeout si usuario no completa el comando
  • Cancelar con ESC

Macros

  • No grabar comandos que entran/salen de macro mode
  • Límite de recursión para evitar loops infinitos
  • Guardar macros en archivo para persistencia

🚀 Comenzar con la Feature Más Fácil

Recomendación: Empezar con Paste (p y P) porque:

  1. Ya tenemos registers implementados
  2. Ya tenemos yank funcionando
  3. Es relativamente simple
  4. Da satisfacción inmediata (feature muy usada)

¿Quieres que empecemos con Paste?


Documento creado: 2025-10-10 Fase actual: Iniciando Fase 3 Próxima actualización: Después de completar primera feature