- Learn
- AI Code Editors
- GitHub Copilot
- Mastering Code Completions
Learn techniques to get accurate, useful code suggestions from GitHub Copilot's inline completions.
Mastering Code Completions
GitHub Copilot's inline completions are its core feature. This lesson covers techniques to get better suggestions and use them efficiently.
How Completions Work
Copilot analyzes context to suggest code:
┌────────────────────────────────────┐
│ Context Copilot Considers: │
│ │
│ 1. Current file content │
│ 2. Cursor position │
│ 3. Open editor tabs │
│ 4. File name and extension │
│ 5. Recent edits │
│ 6. Import statements │
│ 7. Comments and docstrings │
└────────────────────────────────────┘
↓
AI Model
↓
┌────────────────────────────────────┐
│ Suggestion displayed as ghost text │
└────────────────────────────────────┘
Accepting Suggestions
Full Acceptance
Press Tab to accept the entire suggestion:
// You type:
function validateEmail(email: string)
// Copilot suggests (gray text):
function validateEmail(email: string): boolean {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return regex.test(email)
}
// Press Tab → suggestion becomes real code
Partial Acceptance
Accept word-by-word:
| Shortcut | Action |
|---|---|
Cmd/Ctrl+→ | Accept next word |
Cmd+Shift+→ | Accept next line (VS Code) |
# Copilot suggests:
def process_order(order_id, customer_email, items):
# Press Cmd+→ three times to accept:
def process_order(order_id, customer_email
Cycling Through Suggestions
Multiple suggestions may be available:
| Shortcut | Action |
|---|---|
Alt+] | Next suggestion |
Alt+[ | Previous suggestion |
Ctrl+Enter | Open completions panel |
// Open panel to see all options:
// Option 1: const users = await db.users.findMany()
// Option 2: const users = await fetch('/api/users')
// Option 3: const users = await prisma.user.findMany()
Crafting Better Context
1. Descriptive Names
Names strongly influence suggestions:
# Vague name → generic suggestion
def process(d):
pass
# Descriptive name → specific suggestion
def parse_json_response(response_data: dict):
# Copilot suggests JSON-specific parsing
2. Type Annotations
Types guide the suggestion:
// Without types
function format(data) {
// Generic suggestions
}
// With types → specific suggestions
function formatCurrency(amount: number, currency: string): string {
// Copilot knows this should return formatted currency string
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency
}).format(amount)
}
3. Leading Comments
Describe what you want:
// Function to fetch user data from API with retry logic
// Uses exponential backoff, max 3 retries
// Returns null if all retries fail
async function fetchUserWithRetry(userId) {
// Copilot generates implementation matching description
}
4. Example-Driven Development
Show an example, get similar code:
# Convert temperature
def celsius_to_fahrenheit(c):
return (c * 9/5) + 32
# Copilot infers pattern
def fahrenheit_to_celsius(f):
return (f - 32) * 5/9 # Generated automatically
Context Optimization
Keep Relevant Files Open
Copilot reads open tabs:
Good: Open files you're working with
├── user.model.ts (open)
├── user.service.ts (open)
├── user.controller.ts (editing)
└── auth.middleware.ts (open)
Copilot sees patterns across these files
Use Imports as Context
Imports signal available tools:
// These imports tell Copilot what's available
import { prisma } from '@/lib/prisma'
import { z } from 'zod'
import { NextResponse } from 'next/server'
export async function POST(request: Request) {
// Copilot suggests Prisma + Zod + Next.js patterns
}
File Structure Matters
File names and paths provide context:
/src/components/UserProfile.tsx
→ Copilot expects a React component
/src/api/routes/auth/login.ts
→ Copilot expects authentication logic
/tests/user.service.test.ts
→ Copilot expects test code
Common Patterns
Function Generation
# Pattern: Comment → implementation
# Validate that password contains uppercase, lowercase, number, and special char
def validate_password(password: str) -> tuple[bool, str]:
if len(password) < 8:
return False, "Password must be at least 8 characters"
if not any(c.isupper() for c in password):
return False, "Password must contain uppercase letter"
# ... Copilot continues
Boilerplate Completion
// Start typing common patterns
export default function UserProfile() {
const [user, setUser] = useState<User | null>(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
// Copilot suggests fetch logic
}, [])
// ... Copilot completes the component
Test Generation
describe('calculateTotal', () => {
it('calculates total for empty cart', () => {
expect(calculateTotal([])).toBe(0)
})
// Copilot suggests more test cases:
it('calculates total for single item', () => {
expect(calculateTotal([{ price: 10, quantity: 2 }])).toBe(20)
})
it('applies discount correctly', () => {
// ...
})
})
Type Definitions
// Describe the shape
interface Product {
id: string
name: string
price: number
// Copilot suggests common fields:
description: string
category: string
imageUrl: string
inStock: boolean
createdAt: Date
updatedAt: Date
}
Avoiding Poor Suggestions
When Suggestions Are Wrong
If suggestions aren't helpful:
- Add more context: Comments, types, better names
- Cycle options: Press
Alt+]for alternatives - Start differently: Change the first few characters
- Use chat: Ask Copilot Chat for the code
Red Flags in Suggestions
Watch for:
// ❌ Hardcoded credentials
const apiKey = "sk_live_actual_key_here" // Never accept this
// ❌ Deprecated patterns
var self = this; // Old pattern, reject
// ❌ Security issues
const query = `SELECT * FROM users WHERE id = ${userId}` // SQL injection
// ❌ Wrong library versions
import { useRouter } from 'next/router' // vs 'next/navigation' in App Router
Staying in Control
Copilot is a suggestion tool, not auto-pilot:
✓ Review before accepting
✓ Understand what the code does
✓ Test the implementation
✓ Check for edge cases
✗ Don't blindly accept long suggestions
✗ Don't skip code review
Efficiency Techniques
Multi-Cursor Completions
Use multiple cursors for parallel suggestions:
// Place cursors on multiple lines
const firstName█
const lastName█
const email█
// Copilot suggests completion for each
Snippet-Style Usage
Start patterns to get completions:
// Type "useState" → get full hook
const [█
// Copilot suggests:
const [value, setValue] = useState('')
Inline Edits
Select code, press Cmd+I, describe changes:
Original: const total = items.map(i => i.price).reduce((a, b) => a + b)
Prompt: "Add tax calculation at 8.5%"
Result: const total = items.map(i => i.price).reduce((a, b) => a + b) * 1.085
Keyboard Workflow
Efficient completion workflow:
1. Type context (function name, comment)
2. Wait briefly for suggestion
3. Review ghost text
4. If good: Tab to accept
If close: Cmd+→ for partial accept
If wrong: Alt+] for next option
5. Continue typing
Speed Settings
Adjust suggestion timing:
{
// Show suggestions faster
"editor.quickSuggestions": {
"other": true,
"comments": true,
"strings": true
},
// Delay before showing (milliseconds)
"editor.quickSuggestionsDelay": 10
}
Summary
- Accept with Tab: Full suggestion acceptance
- Partial accept:
Cmd+→for word-by-word - Cycle suggestions:
Alt+]andAlt+[ - Better context: Descriptive names, types, comments
- Open relevant files: Copilot uses open tabs
- Review suggestions: Don't accept blindly
- Use shortcuts: Build muscle memory
Next Steps
Completions handle single-line and short multi-line code. For longer conversations and complex questions, let's explore Copilot Chat.