Project 6: The HTML Tag Wrapper (Surround Simulation)

Wrap plain text lines in HTML tags using text objects, registers, and marks without plugins.

Quick Reference

Attribute Value
Difficulty Level 3: Advanced
Time Estimate 6-10 hours
Main Programming Language HTML
Alternative Programming Languages XML
Coolness Level Level 3: Precision editing
Business Potential 3: Front-end editor
Prerequisites Insert/append commands, registers, marks
Key Topics Linewise edits, registers in insert mode, marks

1. Learning Objectives

By completing this project, you will:

  1. Wrap each line of text in HTML tags without plugins.
  2. Use I and A to insert at line boundaries efficiently.
  3. Use registers and Ctrl-r in Insert mode to reuse tag text.
  4. Use marks to jump between positions during multi-step edits.
  5. Build a repeatable workflow for structural wrapping.

2. All Theory Needed (Per-Concept Breakdown)

2.1 Line-Boundary Insert and Append

Fundamentals

I inserts at the first non-blank character of a line, while A appends at the end of the line. These are essential when you need to add prefixes and suffixes around existing text. In the HTML wrapper project, you will add <li> at the start of each line and </li> at the end, which maps perfectly to I and A.

Deep Dive into the concept

Line-boundary commands are faster and safer than moving manually to the beginning or end of the line. I respects indentation, which is useful when wrapping nested lists. A always moves to the line end, which is ideal for appending closing tags. When combined with . for repeat, you can wrap multiple lines with a minimal keystroke sequence.

How this fits on projects

  • You will use I<li> and A</li> for each line.
  • You will repeat the sequence with j ..

Definitions & key terms

  • I: Insert at first non-blank character.
  • A: Append at end of line.
  • Line boundary: The start or end of a line.

Mental model diagram (ASCII)

[Line text]
 ^ I inserts here
          ^ A inserts here

How it works (step-by-step)

  1. Move to a target line.
  2. Press I to insert prefix.
  3. Press <Esc> to return to Normal.
  4. Press A to append suffix.
  5. Repeat with j ..

Minimal concrete example

I<li><Esc>A</li><Esc>
j.

Common misconceptions

  • “I just use 0 and i”: I is faster and respects indentation.
  • “A is same as $a”: A is a single command and repeatable.
  • “Insert mode is slow”: Insert at boundaries minimizes movement.

Check-your-understanding questions

  1. What is the difference between I and i?
  2. Why is A better than $a for repeatability?
  3. How do you repeat a line-boundary edit?

Check-your-understanding answers

  1. I inserts at first non-blank char; i inserts at cursor.
  2. A is a single command, making dot repeat simpler.
  3. Use . on the next line after moving down.

Real-world applications

  • Wrapping lines in tags or quotes.
  • Adding comment markers at line start/end.
  • Batch-editing list items.

Where you’ll apply it

References

  • :help I
  • :help A

Key insights

Line-boundary commands turn wrapping into a two-keystroke pattern.

Summary

I and A are the fastest way to add prefix/suffix pairs to lines. They are ideal for structural wrapping tasks.

Homework/Exercises to practice the concept

  1. Add * to the beginning of five lines using I.
  2. Append ; to the end of five lines using A and ..

Solutions to the homework/exercises

  1. Move line by line, use I* <Esc> then j ..
  2. Use A;<Esc> then j ..

2.2 Registers in Insert Mode (Ctrl-r)

Fundamentals

Registers store text. In Insert mode, you can insert register contents using Ctrl-r followed by the register name. This is vital when you want to reuse the same tag multiple times without retyping. For example, you can yank <li> into register a and insert it repeatedly.

Deep Dive into the concept

Insert-mode register paste is efficient because it avoids leaving Insert mode. You can use the unnamed register (") or named registers ("a, "b). This means you can keep multiple tag snippets ready. The deeper skill is understanding how registers are overwritten: deletes and yanks replace the unnamed register, but named registers persist until overwritten. This allows you to protect your tag snippets while editing.

How this fits on projects

  • You will use Ctrl-r to insert repeated tag text.
  • You will store tags in a named register to avoid overwrite.

Definitions & key terms

  • Register: Storage slot for text.
  • Insert-mode paste: Ctrl-r followed by a register name.
  • Unnamed register: Default register overwritten by deletes/yanks.

Mental model diagram (ASCII)

"a contains <li>
Insert mode: Ctrl-r a -> inserts <li>

Register insert flow

How it works (step-by-step)

  1. Yank the tag into a named register: "ayy.
  2. Enter Insert mode at the desired location.
  3. Press Ctrl-r then a to insert.
  4. Continue editing without leaving Insert mode.

Minimal concrete example

"ayiw          " yank word into register a
I<C-r>a<Esc>   " insert register a at line start

Common misconceptions

  • “Registers only matter for macros”: They are crucial for repeated text.
  • “Insert mode cannot paste”: Ctrl-r works in Insert mode.
  • “Unnamed register is safe”: It is overwritten often.

Check-your-understanding questions

  1. How do you paste register a in Insert mode?
  2. Why use named registers instead of the unnamed register?
  3. What happens to the unnamed register after a delete?

Check-your-understanding answers

  1. Ctrl-r a.
  2. Named registers are preserved; unnamed is overwritten.
  3. It is replaced by the deleted text.

Real-world applications

  • Reusing HTML tags or snippets.
  • Inserting boilerplate text quickly.
  • Copying consistent prefixes across lines.

Where you’ll apply it

  • See Section 3.7 Real World Outcome and Section 5.8 Hints in Layers in this project.
  • Also used in: Project 5: Log Parser.

References

  • :help i_CTRL-R
  • “Practical Vim” Ch. 10

Key insights

Registers turn repeated typing into a single keystroke.

Summary

Insert-mode register paste is a precision tool for repeated text. It keeps you in flow and avoids retyping.

Homework/Exercises to practice the concept

  1. Yank <li> into register a and insert it on three lines.
  2. Store </li> in register b and paste it at line ends.

Solutions to the homework/exercises

  1. "ayiW, then I<C-r>a<Esc>.
  2. "byiW, then A<C-r>b<Esc>.

2.3 Marks and Jumping Between Positions

Fundamentals

Marks let you save a location and jump back to it. Use ma to set mark a, then jump to it with 'a (line) or `a (exact position). This is useful when you need to add opening and closing tags at different places (like wrapping a list with <ul> and </ul>).

Deep Dive into the concept

Marks are especially useful in multi-step edits where you need to return to a specific point after moving elsewhere. In the HTML wrapper project, you might set a mark at the top of the list, move to the bottom to insert </ul>, then jump back to insert <ul> at the start. Marks reduce the mental load of navigation, making your edits more reliable.

How this fits on projects

  • You will use marks to jump between the top and bottom of a list.
  • You will use exact-position jumps to avoid losing context.

Definitions & key terms

  • Mark: A named location in the buffer.
  • Line mark ('a): Jump to the marked line.
  • Exact mark (`a): Jump to the exact column.

Mental model diagram (ASCII)

Top of list --ma--> mark a
Bottom of list --`a--> return

Mark jump flow

How it works (step-by-step)

  1. Set a mark with ma.
  2. Move elsewhere in the file.
  3. Return with `a or 'a.
  4. Continue editing from the marked position.

Minimal concrete example

ma
G
O</ul><Esc>
`a
O<ul><Esc>

Common misconceptions

  • “Marks are temporary”: They persist until overwritten.
  • “You only need marks in big files”: They help even in small edits.
  • a and ‘a are the same”: One is exact, one is line-based.

Check-your-understanding questions

  1. What is the difference between 'a and `a?
  2. How do you set a mark?
  3. Why are marks useful for paired edits?

Check-your-understanding answers

  1. 'a jumps to the line; `a jumps to the exact column.
  2. Use m followed by a letter.
  3. They let you return to a known position quickly.

Real-world applications

  • Wrapping sections with tags.
  • Jumping between related code blocks.
  • Placing anchors for navigation.

Where you’ll apply it

  • See Section 3.7 Real World Outcome and Section 5.10 Implementation Phases in this project.
  • Also used in: Project 9: Code Navigator.

References

  • :help mark
  • “Learning the vi and Vim Editors” Ch. 3

Key insights

Marks are bookmarks for editing, not just navigation.

Summary

Marks give you reliable jump points, which is essential for multi-step structural edits.

Homework/Exercises to practice the concept

  1. Set a mark at the top of a list, jump to the bottom, then return.
  2. Use marks to insert paired tags at two locations.

Solutions to the homework/exercises

  1. ma, G, `a.
  2. Set mark, insert closing tag, return, insert opening tag.

3. Project Specification

3.1 What You Will Build

You will take a list of plain lines and wrap each line in <li> tags, then wrap the list in <ul> tags. The deliverable is a before/after file plus a command log.

3.2 Functional Requirements

  1. Input File: Create list.txt with at least 10 lines.
  2. Line Wrapping: Use I and A to add <li> and </li>.
  3. Outer Tags: Insert <ul> and </ul> using marks.
  4. Register Usage: Use at least one named register with Ctrl-r.
  5. Command Log: Record key sequences.

3.3 Non-Functional Requirements

  • Consistency: Every line is wrapped correctly.
  • Repeatability: Use j . to repeat edits where possible.
  • Clarity: Output HTML is readable and indented.

3.4 Example Usage / Output

Before:
Apples
Oranges

Commands:
I<li><Esc>A</li><Esc>
j.

After:
<li>Apples</li>
<li>Oranges</li>

3.5 Data Formats / Schemas / Protocols

Plain text list input. Output is valid HTML:

<ul>
  <li>Apples</li>
  <li>Oranges</li>
</ul>

3.6 Edge Cases

  • Empty lines in the list.
  • Lines with leading/trailing spaces.
  • Very long list items.

3.7 Real World Outcome

You will produce a valid HTML list with clean tags and consistent indentation.

3.7.1 How to Run (Copy/Paste)

vim list.txt

3.7.2 Golden Path Demo (Deterministic)

  1. On first line: I<li><Esc>A</li><Esc>.
  2. On next line: j ..
  3. Insert <ul> and </ul> using marks.

Expected output:

<ul>
<li>Apples</li>
<li>Oranges</li>
</ul>

3.7.3 Failure Demo (Deterministic)

If you forget <Esc> between I and A, you will insert the closing tag at the wrong location, producing malformed HTML.

3.7.4 If CLI

Not applicable.

3.7.5 If Web App

Not applicable.

3.7.6 If API

Not applicable.

3.7.7 If Library

Not applicable.

3.7.8 If TUI

+------------------------------+
| list.txt                     |
| Apples                       |
| Oranges                      |
|                              |
| -- NORMAL --                 |
+------------------------------+

p06_list_screen

List screen

Key interactions:

  • I and A for wrapping
  • Ctrl-r for register paste
  • ma to set a mark and `a to jump back

4. Solution Architecture

4.1 High-Level Design

+-----------+    +-------------------+    +-----------+
| list.txt  | -> | Vim Line Wrapping | -> | list.html |
+-----------+    +-------------------+    +-----------+

HTML wrap pipeline

4.2 Key Components

Component Responsibility Key Decisions
Input file Provide list lines At least 10 items
Wrapping sequence Insert tags Use I and A
Marks Jump between boundaries Use ma and `a

4.3 Data Structures (No Full Code)

WrapStep:
- insert_prefix
- insert_suffix
- repeat_next_line

4.4 Algorithm Overview

Key Algorithm: Line Wrapper

  1. Insert <li> at line start.
  2. Append </li> at line end.
  3. Move down and repeat.

Complexity Analysis:

  • Time: O(k) per line
  • Space: O(1)

5. Implementation Guide

5.1 Development Environment Setup

vim --version

5.2 Project Structure

html-wrapper/
|-- list.txt
|-- list.html
`-- command_log.md

5.3 The Core Question You’re Answering

“How do I wrap text in structure without plugins?”

5.4 Concepts You Must Understand First

  1. I and A for line boundary edits
  2. Registers and Ctrl-r
  3. Marks for jumping

5.5 Questions to Guide Your Design

  1. Should I store the tag text in a register?
  2. Where should I set marks to add <ul> boundaries?
  3. How do I repeat line wrapping efficiently?

5.6 Thinking Exercise

Find the shortest repeatable sequence to wrap five lines with <p> tags.

5.7 The Interview Questions They’ll Ask

  1. “How do you paste from a register in Insert mode?”
  2. “What is the difference between 'a and `a?”
  3. “What does I do?”

5.8 Hints in Layers

Hint 1: Use I and A They map directly to prefix/suffix edits.

Hint 2: Use registers Store <li> and </li> in named registers.

Hint 3: Use marks Set a mark at the top before jumping to the bottom.

Hint 4: Repeat with . j . repeats the last line-wrap.

5.9 Books That Will Help

Topic Book Chapter
Insert mode “Practical Vim” Ch. 3
Registers “Practical Vim” Ch. 10
Marks “Learning the vi and Vim Editors” Ch. 3

5.10 Implementation Phases

Phase 1: Prepare Input (1-2 hours)

Goals:

  • Create a list with 10+ items.

Tasks:

  1. Write list.txt with sample items.
  2. Add blank lines to test edge cases.

Checkpoint: File opens cleanly in Vim.

Phase 2: Wrap Lines (2-4 hours)

Goals:

  • Wrap each line in <li> tags.

Tasks:

  1. Wrap first line with I<li> and A</li>.
  2. Repeat with j ..

Checkpoint: All lines are wrapped correctly.

Phase 3: Add Outer Tags (1-2 hours)

Goals:

  • Add <ul> and </ul>.

Tasks:

  1. Set a mark at top.
  2. Jump to bottom and insert </ul>.
  3. Jump back and insert <ul>.

Checkpoint: HTML list is valid.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Tag insertion Manual typing / registers Registers Faster and safer
Outer tag placement Manual search / marks Marks Precise jumping
Indentation None / manual Manual (2 spaces) Readability

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Structural correctness Tags match pairs Validate HTML visually
Repeatability j . works Wrap 5 lines quickly
Edge cases Empty lines Ensure no blank tags

6.2 Critical Test Cases

  1. Line with leading whitespace.
  2. Empty line (should be skipped or wrapped deliberately).
  3. Very long line with punctuation.

6.3 Test Data

Apples
Oranges

Bananas

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

Pitfall Symptom Solution
Missing <Esc> Closing tag in wrong place Always return to Normal mode
Wrong register Inserted incorrect tag Use named registers
Lost position Inserted <ul> in wrong spot Use marks to return

7.2 Debugging Strategies

  • Undo and redo with a cleaner sequence.
  • Use :set showmode to verify mode transitions.

7.3 Performance Traps

  • Moving to line ends manually instead of using A.
  • Retyping tags instead of using registers.

8. Extensions & Challenges

8.1 Beginner Extensions

  • Wrap lines with <p> tags.
  • Indent the wrapped list by two spaces.

8.2 Intermediate Extensions

  • Convert the list into an ordered list (<ol>).
  • Use a macro to wrap lines automatically.

8.3 Advanced Extensions

  • Wrap paragraphs with <section> tags.
  • Use marks and registers to wrap nested lists.

9. Real-World Connections

9.1 Industry Applications

  • Quick HTML structuring in static sites.
  • Converting text exports into HTML lists.
  • Static site generators that consume Markdown/HTML.
  • Vim users building HTML without plugins.

9.3 Interview Relevance

  • Demonstrates precision editing and workflow design.

10. Resources

10.1 Essential Reading

  • “Practical Vim” Ch. 3 and 10
  • “Learning the vi and Vim Editors” Ch. 3

10.2 Video Resources

  • Vim registers and marks tutorials

10.3 Tools & Documentation

  • :help I
  • :help i_CTRL-R
  • :help mark

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain I vs i.
  • I can paste a register in Insert mode.
  • I can jump to marks reliably.

11.2 Implementation

  • All lines wrapped with <li> tags.
  • <ul> and </ul> added correctly.
  • Command log completed.

11.3 Growth

  • I can apply the same workflow to XML or Markdown.
  • I can explain the workflow to a teammate.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Wrapped 10+ lines in <li> tags without plugins.
  • Added <ul> and </ul> using marks.
  • Used at least one named register.

Full Completion:

  • All minimum criteria plus:
  • Used j . to wrap at least 5 lines.
  • Indented the list cleanly.

Excellence (Going Above & Beyond):

  • Wrapped nested lists and maintained indentation.
  • Created a reusable sequence documented in the log.