Project 3: The Code Refactor (Change Operator)

Refactor real code by expressing edits as operator + motion sentences, then repeat them efficiently.

Quick Reference

Attribute Value
Difficulty Level 2: Intermediate
Time Estimate 1 weekend
Main Programming Language Any (Python/JS/C)
Alternative Programming Languages All
Coolness Level Level 2: Real code work
Business Potential 4: Refactor accelerator
Prerequisites Motions, basic search, text objects
Key Topics Change operator, dot repeat, code text objects

1. Learning Objectives

By completing this project, you will:

  1. Refactor identifiers using c and text objects instead of visual mode.
  2. Use dot repeat to apply the same change across multiple locations.
  3. Change function arguments and strings without breaking syntax.
  4. Design repeatable edits that scale across a file.
  5. Build confidence editing code without an IDE.

2. All Theory Needed (Per-Concept Breakdown)

2.1 The Change Operator and Dot Repeat

Fundamentals

The change operator (c) is Vim’s core refactor verb. It deletes a region and drops you into Insert mode in one command. This is more repeatable than a delete plus insert, because it is a single atomic change that can be replayed with .. Dot repeat is the mechanism that lets you apply one good change many times. In refactoring, repeatability is the difference between a one-off edit and a consistent transformation.

c can be combined with motions or text objects: cw changes a word, c$ changes to the end of the line, and ci( changes the inside of parentheses. Once you learn to express changes this way, the refactor becomes a series of small, repeatable sentences.

Deep Dive into the concept

The dot command repeats the last change, not the last movement. This is why you must design your edits to be a single change. For example, if you search to the next target and then run cw new, the change is the cw new part. The search is separate and does not interfere with .. This lets you use /target, cw new, then n . to refactor all matches.

Counts also work with change. 3cw changes three words, while c3w changes three words too; the difference is where the count applies in the grammar. In refactoring, you want consistency, so you usually prefer smaller targets and use dot repeat for repetition. The deeper skill is knowing which part of the change should be repeatable, and which part should be driven by search or motion.

How this fits on projects

  • You will use c + motion to rename identifiers.
  • You will use . with n to repeat changes across matches.

Definitions & key terms

  • Change operator (c): Delete then enter Insert mode.
  • Dot repeat (.): Repeats the last change command.
  • Atomic change: A single command that produces one edit.

Mental model diagram (ASCII)

Search -> Change -> Repeat
   /x      cw y      n .

Search change repeat

How it works (step-by-step)

  1. Search for the next target.
  2. Use c with a motion or text object.
  3. Enter the new text and return to Normal mode.
  4. Use n . to repeat on the next match.

Minimal concrete example

/timeout<Enter>
cw deadline<Esc>
 n .   " repeat change on next match

Common misconceptions

  • “Dot repeats everything”: It repeats only the last change.
  • “Change is just delete”: c is delete plus insert, which matters for repeatability.
  • “Visual mode is faster”: Operator + motion is usually fewer keys.

Check-your-understanding questions

  1. Why is cw + new text more repeatable than dw then i?
  2. What does C do?
  3. How would you repeat a change across multiple matches?

Check-your-understanding answers

  1. It is a single change and can be repeated with ..
  2. C is shorthand for c$ (change to end of line).
  3. Use /pattern, make the change once, then n ..

Real-world applications

  • Renaming variables and parameters.
  • Updating string literals across a file.
  • Fixing typos repeatedly.

Where you’ll apply it

References

  • :help change
  • “Practical Vim” Ch. 1

Key insights

One clean change plus dot repeat can refactor an entire file.

Summary

The change operator and dot repeat are the backbone of efficient refactoring. Learn to express your edits as one atomic change and repeat it.

Homework/Exercises to practice the concept

  1. Change the word “temp” to “tmp” in five places using n ..
  2. Use C to replace the end of a line with new text.

Solutions to the homework/exercises

  1. /temp then cw tmp<Esc> then n . repeatedly.
  2. Place cursor at start of suffix, press C, type new text.

2.2 Text Objects for Code Structures

Fundamentals

Code is full of structure: parentheses for arguments, braces for blocks, quotes for strings. Text objects let you target these structures directly. ci( changes the contents of a function call, ci" changes a string value, and ci{ changes the body of a block. This precision prevents accidental edits to delimiters.

The key idea is that text objects are context aware. You can be anywhere inside a string or argument list, and Vim will find the nearest matching delimiters. This is a huge advantage in refactoring, because you often land in the middle of the thing you want to change.

Deep Dive into the concept

Refactoring often requires changing the inside of a structure without touching its boundary. This is what i is for. When you want to replace the entire structure including its delimiters, use a instead. For example, to replace a function call entirely, ca( will delete the parentheses as well. The deeper skill is choosing the right scope so the change stays minimal and repeatable.

Text objects also chain well with operators beyond c: y to yank an argument list, d to delete a block, and gU to uppercase a string. This means you can use the same structural targeting across multiple kinds of changes without switching modes.

How this fits on projects

  • You will use ci( to refactor function arguments.
  • You will use ci" for string transformations.

Definitions & key terms

  • Inner object: The content inside delimiters (i(, i").
  • Around object: Content plus delimiters (a(, a").
  • Delimiter: The characters that define a structure.

Mental model diagram (ASCII)

call(arg1, arg2)
   i( -> arg1, arg2
   a( -> (arg1, arg2)

Argument text object

How it works (step-by-step)

  1. Place cursor inside the structure.
  2. Choose operator (c, d, y).
  3. Choose i or a based on whether delimiters should stay.
  4. Execute and verify the structure remains valid.

Minimal concrete example

ci( new_arg, new_arg2<Esc>
ci"new string<Esc>

Common misconceptions

  • “You must be on the delimiter”: You can be anywhere inside.
  • “Text objects are only for parentheses”: They work with quotes, blocks, tags.
  • iw is the same as w: It targets the word regardless of cursor position.

Check-your-understanding questions

  1. What does ci( do inside a function call?
  2. When would you use ca{?
  3. How do text objects help with repeatability?

Check-your-understanding answers

  1. It changes the text inside the parentheses.
  2. Use it when you want to replace a whole block including braces.
  3. They let you apply the same command regardless of cursor position.

Real-world applications

  • Updating argument lists during API changes.
  • Editing string literals safely.
  • Changing code blocks without breaking braces.

Where you’ll apply it

References

  • :help text-objects
  • “Practical Vim” Ch. 4

Key insights

Text objects turn syntax into safe editing targets.

Summary

When refactoring code, text objects are your safety net. They let you change what matters without breaking syntax.

Homework/Exercises to practice the concept

  1. Change three string literals using ci".
  2. Replace the contents of a function call using ci(.

Solutions to the homework/exercises

  1. Place cursor inside each string and run ci"new<Esc>.
  2. Place cursor inside parentheses and run ci(.

2.3 Search-Driven Refactoring Patterns

Fundamentals

Search turns refactoring into a pattern-driven process. Instead of moving manually to each target, you search for the next occurrence and apply the same change. This is the foundation of scalable refactoring in Vim. The n key lets you repeat the last search, and . lets you repeat the last change. Together, they form a loop: search, change, repeat.

Deep Dive into the concept

Search in Vim is regex-based, which means you can target precise patterns (like a function name followed by (). Even if you do not use advanced regex, the ability to repeat the search with n gives you a deterministic traversal of the file. This is important because refactoring is about consistency; if you skip a target, you create bugs.

A powerful pattern is “search, change, repeat”: /pattern, apply the change, then n . to repeat. This sequence ensures that your change remains consistent across occurrences. The deeper skill is designing the change so it is safe to repeat: avoid context-dependent edits, and make sure the cursor lands in the right place after each change.

How this fits on projects

  • You will use /identifier to reach targets.
  • You will apply n . to repeat the same change across the file.

Definitions & key terms

  • Search register: Stores the last search pattern.
  • Repeat search: n (forward) and N (backward).
  • Search-change loop: The pattern of /pattern then n ..

Mental model diagram (ASCII)

/target -> change -> n -> . -> n -> .

Search repeat loop

How it works (step-by-step)

  1. Search for the pattern.
  2. Make a single, clean change.
  3. Press n to jump to the next match.
  4. Press . to repeat the change.

Minimal concrete example

/oldName<Enter>
cw newName<Esc>
 n .

Common misconceptions

  • “Search is only for navigation”: It is part of the refactor loop.
  • “Dot repeat is risky”: It is safe if the change is atomic.
  • “Regex is required”: Simple searches work for many refactors.

Check-your-understanding questions

  1. Why does n . scale refactors?
  2. What happens if your change is not atomic?
  3. How can regex improve a refactor search?

Check-your-understanding answers

  1. It repeats the same change at each match.
  2. . will only repeat the last atomic change, which may be incomplete.
  3. Regex can target only the occurrences you intend to change.

Real-world applications

  • Renaming function calls across a file.
  • Updating string constants.
  • Changing patterns in config or code.

Where you’ll apply it

References

  • :help /
  • “Practical Vim” Ch. 12-13

Key insights

Search gives you a consistent path; dot gives you consistent edits.

Summary

Search-driven refactoring is the most reliable way to apply the same change across a file. The loop is simple but powerful.

Homework/Exercises to practice the concept

  1. Change every http to https using /http and n ..
  2. Use a regex search to target only function definitions.

Solutions to the homework/exercises

  1. /http then cw https<Esc> then n ..
  2. Search with /^def \w\+ and change the function name.

3. Project Specification

3.1 What You Will Build

You will refactor a small code file by renaming identifiers, updating strings, and modifying function arguments using Vim operators and text objects. The output is a “before” and “after” file plus a short command log.

3.2 Functional Requirements

  1. Input File: Create a source file with at least two functions and 30+ lines.
  2. Identifier Rename: Rename at least two variables using cw and ..
  3. String Changes: Update at least three string literals using ci".
  4. Argument Refactor: Change a function call’s argument list with ci(.
  5. Command Log: Record key command sequences used.

3.3 Non-Functional Requirements

  • Repeatability: Use dot repeat for at least one change sequence.
  • Safety: Keep the code syntactically correct.
  • Clarity: Log should explain why each command was chosen.

3.4 Example Usage / Output

Before:
name = "http://example.com"

Commands:
/http<Enter>
cw https<Esc>
 n .

After:
name = "https://example.com"

3.5 Data Formats / Schemas / Protocols

Use a real code file (Python/JS/C) with consistent formatting. Example pattern:

function buildUrl(host, path, query) {
  return "http://" + host + "/" + path + "?" + query;
}

3.6 Edge Cases

  • Identifiers that appear in comments as well as code.
  • Multiple variables with similar names.
  • String literals with escaped quotes.

3.7 Real World Outcome

You will have a refactored code file and a repeatable Vim workflow for future refactors.

3.7.1 How to Run (Copy/Paste)

vim refactor_demo.py

3.7.2 Golden Path Demo (Deterministic)

  1. Search for query.
  2. Use cw params<Esc>.
  3. Repeat with n ..

Expected output:

return f"https://{host}/{path}?{params}"

3.7.3 Failure Demo (Deterministic)

If you use dw instead of cw, you delete the word but do not replace it, leaving the code broken until you insert manually.

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

+-----------------------------------+
| refactor_demo.py                  |
| def build_url(host, path, |query):|
|     return "http://" + host + ... |
|                                   |
| -- NORMAL --                      |
+-----------------------------------+

p03_refactor_screen

Refactor screen

Key interactions:

  • /pattern to locate targets
  • ci( for argument lists
  • . for repeat

4. Solution Architecture

4.1 High-Level Design

+------------------+    +-------------------+    +------------------+
| Source File      | -> | Vim Refactor Ops  | -> | Updated Source   |
+------------------+    +-------------------+    +------------------+

Refactor pipeline

4.2 Key Components

Component Responsibility Key Decisions
Source file Provide realistic refactor target 30+ lines, multiple identifiers
Refactor plan Define what to change Use search-driven plan
Command log Record edits Focus on repeatable sequences

4.3 Data Structures (No Full Code)

RefactorStep:
- search_pattern
- change_command
- expected_result

4.4 Algorithm Overview

Key Algorithm: Search-Change-Repeat

  1. Search for the identifier.
  2. Change it with cw or ciw.
  3. Repeat with n ..

Complexity Analysis:

  • Time: O(k) keystrokes per change
  • Space: O(1)

5. Implementation Guide

5.1 Development Environment Setup

# No special setup needed beyond Vim
vim --version

5.2 Project Structure

code-refactor/
|-- refactor_demo.py
|-- refactor_demo_after.py
`-- command_log.md

5.3 The Core Question You’re Answering

“How do I refactor code by describing what to change instead of retyping?”

5.4 Concepts You Must Understand First

  1. Change operator (c) and dot repeat (.)
  2. Text objects for quotes and parentheses
  3. Search-driven refactoring patterns

5.5 Questions to Guide Your Design

  1. Can this refactor be expressed as a repeatable change?
  2. Should I use ciw or cw for this identifier?
  3. How will I confirm that I changed every occurrence?

5.6 Thinking Exercise

Write the shortest sequence to change all timeout to deadline.

5.7 The Interview Questions They’ll Ask

  1. “What does C do?”
  2. “How do you repeat a change across a file?”
  3. “What is the difference between cw and ciw?”

5.8 Hints in Layers

Hint 1: Use search + dot /timeout then cw deadline<Esc> then n ..

Hint 2: Use text objects ci" and ci( reduce mistakes.

Hint 3: Keep changes atomic One clean change is easier to repeat.

Hint 4: Validate Use a language linter or run tests after refactor.

5.9 Books That Will Help

Topic Book Chapter
Change operator “Practical Vim” Ch. 1
Text objects “Practical Vim” Ch. 4

5.10 Implementation Phases

Phase 1: Choose Refactor Target (1-2 hours)

Goals:

  • Pick a small file and define refactor steps.

Tasks:

  1. Create a file with at least two functions.
  2. List three changes you want to make.

Checkpoint: The plan includes identifiers, strings, and arguments.

Phase 2: Execute Changes (2-4 hours)

Goals:

  • Apply changes using operator + text objects.

Tasks:

  1. Rename two identifiers with cw and ..
  2. Change three strings with ci".
  3. Modify one argument list with ci(.

Checkpoint: File still runs or parses.

Phase 3: Repeat and Validate (1-2 hours)

Goals:

  • Use n . to apply repeated edits.

Tasks:

  1. Apply a search-change-repeat sequence at least 5 times.
  2. Record the commands in the log.

Checkpoint: All intended occurrences are changed.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Target selection Demo file / real code Small real file Realistic but controlled
Repeat strategy Manual / n . n . Consistency
Validation None / run tests Run tests Catch errors early

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Syntax checks Ensure code still parses Run interpreter / linter
Repeatability Confirm dot repeat works n . across matches
Coverage Ensure all targets changed Search for old name

6.2 Critical Test Cases

  1. Identifier rename: Old name no longer appears.
  2. String update: New string is correct and well-formed.
  3. Argument refactor: Function call still valid.

6.3 Test Data

build_url(host, path, query)
return "http://" + host

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

Pitfall Symptom Solution
Non-atomic changes . does not repeat correctly Use one command per change
Wrong scope Extra text changed Use text objects (ci(, ci")
Missing occurrences Old name still present Search for old name at end

7.2 Debugging Strategies

  • Use /oldName at the end to verify nothing remains.
  • Use u to undo and retry with a better motion.

7.3 Performance Traps

  • Editing with Visual mode instead of operator grammar.
  • Switching between Normal and Insert too often.

8. Extensions & Challenges

8.1 Beginner Extensions

  • Refactor a 20-line script.
  • Use C to change line endings.

8.2 Intermediate Extensions

  • Rename a function and update all call sites.
  • Refactor a dictionary key across a file.

8.3 Advanced Extensions

  • Combine search, change, and macros for a bigger refactor.
  • Apply the same refactor to two files in a row.

9. Real-World Connections

9.1 Industry Applications

  • Fast edits in production hotfixes.
  • Code reviews where quick refactors are needed.
  • Vim and Neovim community refactor workflows.
  • Large codebases where editor skill saves hours.

9.3 Interview Relevance

  • Demonstrates understanding of tooling efficiency and precision.

10. Resources

10.1 Essential Reading

  • “Practical Vim” Ch. 1 and 4

10.2 Video Resources

  • Vim refactoring tutorials

10.3 Tools & Documentation

  • :help change
  • :help text-objects

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain what . repeats.
  • I can use ci( and ci" confidently.
  • I can design a repeatable change.

11.2 Implementation

  • Refactor completed with command log.
  • Code still parses/runs.
  • Old identifiers removed.

11.3 Growth

  • I can apply the same workflow to a larger file.
  • I can teach search-change-repeat to another developer.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Renamed two identifiers using c and ..
  • Updated three strings using text objects.
  • Logged the commands used.

Full Completion:

  • All minimum criteria plus:
  • Verified no old names remain.
  • Applied one change across 5+ matches with n ..

Excellence (Going Above & Beyond):

  • Refactored a real project file and ran its tests successfully.
  • Recorded a short screencast of the workflow.