Help us shape the future of Go! Take the 2026 Go Developer Survey

completion

package
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package completion provides tab completion support for the basecamp CLI. It implements a file-based cache for projects, people, and accounts data that enables fast, offline-capable shell completions without requiring API calls.

Index

Constants

View Source
const (
	// CacheVersion is the current cache schema version.
	CacheVersion = 1

	// DefaultMaxAge is the default cache staleness threshold (1 hour).
	DefaultMaxAge = time.Hour

	// CacheFileName is the default cache file name.
	CacheFileName = "completion.json"
)

Variables

This section is empty.

Functions

func DefaultCacheDirFunc

func DefaultCacheDirFunc(cmd *cobra.Command) string

DefaultCacheDirFunc returns the cache directory by checking (in order): 1. --cache-dir flag on the root command 2. App config from context (set by PersistentPreRunE) 3. BASECAMP_CACHE_DIR environment variable 4. Default cache directory

This is the standard CacheDirFunc that all commands should use.

Limitation: During __complete, PersistentPreRunE doesn't run, so appctx is not set and config files are not loaded. This means cache_dir set in config files is NOT honored during completion—only --cache-dir flag and env vars work. This is intentional: loading config files adds latency that defeats fast completions. Users who set cache_dir in config should also set BASECAMP_CACHE_DIR.

Types

type Cache

type Cache struct {
	Projects          []CachedProject `json:"projects,omitempty"`
	People            []CachedPerson  `json:"people,omitempty"`
	Accounts          []CachedAccount `json:"accounts,omitempty"`
	ProjectsUpdatedAt time.Time       `json:"projects_updated_at"`
	PeopleUpdatedAt   time.Time       `json:"people_updated_at"`
	AccountsUpdatedAt time.Time       `json:"accounts_updated_at"`
	UpdatedAt         time.Time       `json:"updated_at"` // Legacy, kept for backwards compat
	Version           int             `json:"version"`    // Schema version for future migrations
}

Cache stores completion data with metadata for staleness detection.

type CacheDirFunc

type CacheDirFunc func(cmd *cobra.Command) string

CacheDirFunc returns the cache directory to use for completion. Takes the command to allow checking both context and flags at completion time.

type CachedAccount

type CachedAccount struct {
	ID   int64  `json:"id"`
	Name string `json:"name"`
}

CachedAccount holds account data for tab completion.

type CachedPerson

type CachedPerson struct {
	ID           int64  `json:"id"`
	Name         string `json:"name"`
	EmailAddress string `json:"email_address,omitempty"`
}

CachedPerson holds person data for tab completion.

type CachedProfile

type CachedProfile struct {
	Name    string
	BaseURL string
}

CachedProfile holds profile data for tab completion. Unlike other cached items, profiles come from config files, not API calls.

type CachedProject

type CachedProject struct {
	ID         int64     `json:"id"`
	Name       string    `json:"name"`
	Purpose    string    `json:"purpose,omitempty"` // "hq", "team", or empty
	Bookmarked bool      `json:"bookmarked,omitempty"`
	UpdatedAt  time.Time `json:"updated_at"`
}

CachedProject holds project data for tab completion. Fields are chosen to support ranking (HQ, Bookmarked, Recent) and display.

type Completer

type Completer struct {
	// contains filtered or unexported fields
}

Completer provides tab completion functions for the basecamp CLI. It reads from a file-based cache and does NOT initialize the full App or SDK.

func NewCompleter

func NewCompleter(getCacheDir CacheDirFunc) *Completer

NewCompleter creates a new Completer. The getCacheDir function is called at completion time to determine the cache directory. If nil, DefaultCacheDirFunc is used.

func (*Completer) AccountCompletion

func (c *Completer) AccountCompletion() cobra.CompletionFunc

AccountCompletion returns a Cobra completion function for account arguments. Accounts are sorted alphabetically by name. The --account flag takes an ID.

func (*Completer) PeopleCompletion

func (c *Completer) PeopleCompletion() cobra.CompletionFunc

PeopleCompletion returns a Cobra completion function for person arguments. People are sorted alphabetically by name, with "me" always first if it matches the filter.

func (*Completer) PeopleNameCompletion

func (c *Completer) PeopleNameCompletion() cobra.CompletionFunc

PeopleNameCompletion returns a Cobra completion function for person name arguments. People are sorted alphabetically by name, with "me" always first if it matches the filter.

func (*Completer) ProfileCompletion

func (c *Completer) ProfileCompletion() cobra.CompletionFunc

ProfileCompletion returns a Cobra completion function for profile arguments. Profiles come from the config file's profiles map. Since completion runs before PersistentPreRunE, we need to load the config directly here.

func (*Completer) ProjectCompletion

func (c *Completer) ProjectCompletion() cobra.CompletionFunc

ProjectCompletion returns a Cobra completion function for project arguments. Projects are ranked: HQ > Bookmarked > Recent > Alphabetical.

func (*Completer) ProjectNameCompletion

func (c *Completer) ProjectNameCompletion() cobra.CompletionFunc

ProjectNameCompletion returns a Cobra completion function for project name arguments. Unlike ProjectCompletion, this returns names instead of IDs for commands that accept names.

type RefreshResult

type RefreshResult struct {
	ProjectsCount int
	PeopleCount   int
	ProjectsErr   error
	PeopleErr     error
}

RefreshResult contains the outcome of a refresh operation.

func (RefreshResult) Error

func (r RefreshResult) Error() error

Error returns a combined error message if any operation failed.

func (RefreshResult) HasError

func (r RefreshResult) HasError() bool

HasError returns true if any refresh operation failed.

type Refresher

type Refresher struct {
	// contains filtered or unexported fields
}

Refresher handles background cache refresh operations.

func NewRefresher

func NewRefresher(store *Store, sdk *basecamp.AccountClient) *Refresher

NewRefresher creates a new cache refresher.

func (*Refresher) IsRefreshing

func (r *Refresher) IsRefreshing() bool

IsRefreshing returns true if a background refresh is in progress.

func (*Refresher) RefreshAll

func (r *Refresher) RefreshAll(ctx context.Context) RefreshResult

RefreshAll fetches fresh data from the API and updates the cache. This is a synchronous operation - use RefreshIfStale for async. On partial failure, preserves existing cached data for the failed portion. Returns RefreshResult with counts and any errors encountered.

func (*Refresher) RefreshIfStale

func (r *Refresher) RefreshIfStale(maxAge time.Duration)

RefreshIfStale triggers a background refresh if the cache is stale. Returns immediately - the refresh happens asynchronously. If a refresh is already in progress, this is a no-op.

func (*Refresher) RefreshPeople

func (r *Refresher) RefreshPeople(ctx context.Context) error

RefreshPeople fetches fresh people data and updates the cache.

func (*Refresher) RefreshProjects

func (r *Refresher) RefreshProjects(ctx context.Context) error

RefreshProjects fetches fresh project data and updates the cache.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store handles reading and writing the completion cache.

func NewStore

func NewStore(dir string) *Store

NewStore creates a new cache store. If dir is empty, it uses the default location (~/.cache/basecamp/).

func (*Store) Accounts

func (s *Store) Accounts() []CachedAccount

Accounts returns cached accounts, or nil if cache is empty/missing.

func (*Store) Clear

func (s *Store) Clear() error

Clear removes the cache file.

func (*Store) Dir

func (s *Store) Dir() string

Dir returns the cache directory path.

func (*Store) IsStale

func (s *Store) IsStale(maxAge time.Duration) bool

IsStale returns true if the cache is older than maxAge or incomplete. A cache is considered stale if: - It doesn't exist or can't be loaded - Either per-section timestamp is missing (legacy cache or incomplete) - The oldest section timestamp exceeds maxAge

func (*Store) Load

func (s *Store) Load() (*Cache, error)

Load reads the cache from disk. Returns an empty cache if the file doesn't exist or is invalid.

func (*Store) Path

func (s *Store) Path() string

Path returns the full path to the cache file.

func (*Store) People

func (s *Store) People() []CachedPerson

People returns cached people, or nil if cache is empty/missing.

func (*Store) Profiles

func (s *Store) Profiles() []CachedProfile

Profiles returns configured profiles for tab completion. Since profiles are defined in config files (not API-fetched), this loads the config directly rather than from the completion cache.

func (*Store) Projects

func (s *Store) Projects() []CachedProject

Projects returns cached projects, or nil if cache is empty/missing.

func (*Store) Save

func (s *Store) Save(cache *Cache) error

Save writes the cache to disk atomically. Sets ProjectsUpdatedAt, PeopleUpdatedAt, and UpdatedAt to now. AccountsUpdatedAt is NOT set here; use UpdateAccounts for that. Note: Works on a copy to avoid mutating the caller's cache instance.

func (*Store) UpdateAccounts

func (s *Store) UpdateAccounts(accounts []CachedAccount) error

UpdateAccounts updates just the accounts in the cache. Only updates AccountsUpdatedAt, preserving other timestamps. Note: Accounts are user-level (not account-scoped like projects/people), so they're refreshed separately via `basecamp me`.

func (*Store) UpdatePeople

func (s *Store) UpdatePeople(people []CachedPerson) error

UpdatePeople updates just the people in the cache. Only updates PeopleUpdatedAt, preserving ProjectsUpdatedAt.

func (*Store) UpdateProjects

func (s *Store) UpdateProjects(projects []CachedProject) error

UpdateProjects updates just the projects in the cache. Only updates ProjectsUpdatedAt, preserving PeopleUpdatedAt.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL