Basic Editing

Purpose and Scope

Visual Studio Code is an editor-first workbench: the primary user journey is opening code, typing, selecting, navigating, saving, and applying small or large transformations without leaving the editor. The public Basic Editing documentation emphasizes keyboard-first writing, multiple selections, search-oriented editing, and language-aware assistance as the baseline experience. In this repository slice, the editing story is visible through the startup path that opens files into the desktop application, the code action taxonomy that powers quick fixes and source actions, and newer AI-assisted edit pipelines that convert chat output into concrete text or notebook edits.

This page focuses on core editing behavior from a developer-maintainer perspective. It does not try to replace the end-user shortcut reference; instead, it explains how common editing concepts map to source-level extension points and services. “Basic editing” here includes direct text input, selections, cursor-oriented workflows, code actions such as quick fixes and organize imports, and reviewable generated edits. Those areas share one important constraint: even when a feature is initiated by a command, an extension, or a chat response, it ultimately needs to resolve into editor state, ranges, decorations, text edits, or notebook edit operations that the workbench can display and apply.

Sources: cli/src/bin/code/main.rs, src/vs/code/electron-main/main.ts, src/vs/editor/contrib/codeAction/common/types.ts, src/vs/workbench/contrib/chat/common/editing/chatCodeMapperService.ts, src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingCodeEditorIntegration.ts, extensions/copilot/src/extension/completions-core/vscode-node/extension/src/codeReferencing/index.ts

Relevant Source Files

  • cli/src/bin/code/main.rs — Rust entrypoint for the code command. It parses integrated or standalone CLI forms, builds command context, routes subcommands, and starts the desktop application for normal editing sessions.
  • src/vs/code/electron-main/main.ts — Electron main-process startup path. It imports argument parsing, file path handling, environment services, lifecycle services, file services, and the CodeApplication used to bring the workbench to life.
  • src/vs/editor/contrib/codeAction/common/types.ts — Shared code action definitions. It names action kinds such as quick fixes, refactors, source actions, organize imports, and fix-all, and defines filtering behavior used before actions are shown or applied.
  • src/vs/workbench/contrib/chat/common/editing/chatCodeMapperService.ts — Service contract for mapping code blocks produced by chat into TextEdit[] or notebook cell edit operations. It also defines provider registration and cancellation-aware dispatch.
  • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingCodeEditorIntegration.ts — Workbench/editor integration for chat-generated edits. Its imports show the editor-facing objects involved: code editors, ranges, selections, decorations, overlay widgets, view zones, diff rendering, minimap and overview ruler decorations, and accessible diff viewing.
  • extensions/copilot/src/extension/completions-core/vscode-node/extension/src/codeReferencing/index.ts — Copilot completions code-referencing integration. It turns public code reference tracking on or off based on Copilot token capabilities and registers engagement tracking only when enabled.

Core Editing Model

At the product level, basic editing starts with the editor surface: a text editor receives input, displays selections and cursors, and exposes commands for changing the document. Official documentation calls out keyboard shortcuts and multiple selections because they are the fastest path from intent to text changes. Multi-cursor editing is especially important because each cursor acts independently at its position, letting a user make parallel changes across repeated structures. That user-facing behavior depends on the editor being able to represent positions, ranges, and selections precisely, then reveal and decorate the right regions as commands run.

The selected source evidence shows these primitives indirectly through the integration points that consume them. Chat edit integration imports ICodeEditor, Position, Range, LineRange, and Selection, which are the same kinds of objects needed to express where edits belong and how changed lines should be shown. It also imports ITextModel, editor decoration collections, inline decorations, minimap positions, overview ruler lanes, and tracked range stickiness. Those names matter because basic editing is not just text replacement; the workbench must preserve a coherent visual state around pending changes, accepted changes, rejected changes, and accessibility-oriented diff review.

Sources: src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingCodeEditorIntegration.ts

Code Actions and Formatting-Adjacent Edits

Many “basic” edits are not manually typed. A user may select a light bulb, invoke a quick fix, organize imports, run a refactor, or trigger a save participant. The shared code action definitions provide the vocabulary for those actions. CodeActionKind defines hierarchical kinds for quickfix, refactor, refactor.extract, refactor.inline, refactor.move, refactor.rewrite, notebook, source, source.organizeImports, source.fixAll, and refactor.surround. These names are the source-level contract that lets providers classify edits while the UI and commands ask for the right subset.

Filtering is part of the editing experience because the editor should not show every possible action in every context. CodeActionFilter can include a kind, exclude kinds, include source actions, and require preferred actions. The filtering helpers check whether a provider’s kind intersects the requested kind and intentionally avoid returning source actions unless requested. That distinction protects users from broad file- or workspace-level changes when they only asked for a local quick fix. It also explains why organize-imports and fix-all behavior feels adjacent to formatting: they may transform source text on save or command invocation, but they are still governed by explicit action kinds and filters.

Sources: src/vs/editor/contrib/codeAction/common/types.ts

AI-Assisted Editing Flow

AI-assisted editing uses the same editor substrate but adds an intermediate mapping step. Chat output may contain code blocks rather than direct text model operations, so ICodeMapperService defines a provider contract that translates those blocks into edits. A request carries codeBlocks, optional chat request metadata, a chat session resource, and an optional location. The response object exposes two callbacks: textEdit(resource, textEdit[]) for normal source files and notebookEdit(resource, edit[]) for notebook cells. This keeps the chat layer from assuming that every generated change targets a plain text document.

The implementation of CodeMapperService is deliberately small: providers are registered, stored, disposed, and called through mapCode. Dispatch is cancellation-aware, returning no result if the token is canceled after a provider runs. The service currently returns after invoking the first available provider, which makes provider order significant and keeps a single mapping decision responsible for a request. For maintainers, the key point is that AI text is not applied directly from chat markdown; it is mediated through a service that emits normal editor and notebook edit operations.

Sources: src/vs/workbench/contrib/chat/common/editing/chatCodeMapperService.ts

Review, Decorations, and Code References

Generated edits must be understandable before they are accepted. The chat editor integration imports diff editor components, line rendering helpers, accessible diff viewer models, add/delete decorations, minimap gutter colors, overview ruler colors, overlay widgets, view zones, and menu toolbars. That collection shows how the workbench turns pending edits into an inspectable editing experience: changed ranges can be decorated inline, represented in the minimap and overview ruler, rendered as inserted or deleted lines, and exposed through an accessible diff viewer. The same editing primitives therefore serve both manual review and automated edit workflows.

Copilot completions add another safety and transparency dimension through code referencing. The CodeReference class registers a token listener outside test mode, checks whether the Copilot token enables code quotes, and disposes any active subscriptions when public code references are disabled. When enabled, it logs that public code references are active and registers a CodeRefEngagementTracker. This does not change the mechanics of typing or accepting a completion, but it affects the surrounding editing experience by enabling engagement tracking for public-code-reference features only when the authenticated token allows it.

Sources: src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingCodeEditorIntegration.ts, extensions/copilot/src/extension/completions-core/vscode-node/extension/src/codeReferencing/index.ts

Startup Path into an Editing Session

Opening an editor usually begins before the workbench exists. The Rust code binary collects raw arguments, tries legacy parsing, chooses integrated or standalone CLI parsing, migrates launcher paths, creates command context, and routes commands. For a normal invocation with no subcommand, it builds base Code arguments and starts the desktop application. Other command branches add arguments for extension management, status, version switching, web serving, tunnels, and agent operations. For basic editing, the important path is the default one: command-line intent becomes a set of Code arguments passed into the desktop startup path.

The Electron main process then owns application startup. Its imports show the responsibilities required before editing can begin: parse main-process arguments, handle paths with line and column information, sanitize file paths, manage environment and lifecycle services, install logging, provide disk-backed file services, and create the CodeApplication. This is why commands such as opening a file at a particular line belong to the editing story. The CLI and main process translate shell-level input into a running workbench that can create editor groups, reveal selections, load file models, and hand control to editor contributions.

Sources: cli/src/bin/code/main.rs, src/vs/code/electron-main/main.ts

Compact Reference

ComponentPublic contract visible in sourceEditing relevance
CodeActionKindQuickFix, Refactor, RefactorExtract, RefactorInline, RefactorMove, RefactorRewrite, Notebook, Source, SourceOrganizeImports, SourceFixAll, SurroundWithNames the categories behind light bulbs, refactors, organize imports, and fix-all workflows.
CodeActionAutoApplyifSingle, first, neverDescribes how an action command may choose whether to apply a result automatically.
CodeActionTriggerSourcerefactor, lightbulb, source action, quick fix action, save participants, problems view, and related valuesRecords where an edit-producing code action was invoked from.
CodeActionFilterinclude, excludes, includeSourceActions, onlyIncludePreferredActionsControls which actions are eligible for a specific command or UI surface.
ICodeMapperRequestcodeBlocks, optional chatRequestId, chatRequestModel, chatSessionResource, locationCarries generated code and chat context into the mapper.
ICodeMapperResponsetextEdit(resource, textEdit[]), notebookEdit(resource, edit[])Emits concrete file or notebook edit operations.
ICodeMapperProviderdisplayName, mapCode(request, response, token)Extension point for converting generated code blocks into edits.
CodeReference.register()Token listener registration outside test modeEnables public code reference tracking only when Copilot token metadata allows it.
code CLI default pathparse arguments, build base Code args, call desktop startupOpens editing sessions from shell commands and file arguments.

Practical Next Steps

When debugging a basic editing issue, first identify whether the problem is direct editor behavior, a code action, startup argument handling, or AI-generated edits. For light bulb, organize-imports, fix-all, and refactor issues, start with the code action kind and filter because an action may be intentionally hidden unless source actions or preferred actions are requested. For chat or Copilot edits, inspect whether the generated content becomes TextEdit[] or notebook edits, then look at the editor integration that renders changes for review. For file-opening problems, follow the CLI-to-Electron path before investigating workbench editor state.

Related pages that usually provide the next layer of detail are intellisense-code-navigation for language-backed editor assistance, inline-chat-and-ai-edits for generated edit review, settings-and-keybindings for shortcut and preference customization, snippets for reusable text insertion, and command-line-interface for shell-level entrypoints into editing sessions. Together, those pages separate the core editor surface from the commands, extensions, and AI services that can produce edits on top of it.