Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.3.2] - 2026-06-20

### Changed
- Repo list now fills the full available terminal height instead of a fixed page size
- Page size adjusts automatically on terminal resize, search bar open/close, and filter/sort changes
- Removed `pageSize` config option β€” page size is determined entirely by terminal height

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ git-scope -h # Show help
* **πŸ“ Workspace Switch** β€” Switch root directories without quitting (`w`). Supports `~`, relative paths, and **symlinks**.
* **πŸ” Fuzzy Search** β€” Find any repo by name, path, or branch (`/`).
* **πŸ›‘οΈ Dirty Filter** β€” Instantly show only repos with uncommitted changes (`f`).
* **πŸ“„ Pagination** β€” Navigate large repo lists with page-by-page browsing (`[` / `]`). Shows 15 repos per page with a dynamic page indicator.
* **πŸ“„ Pagination** β€” Navigate large repo lists with page-by-page browsing (`[` / `]`). The list fills the available terminal height, with a dynamic page indicator when there are more repos than fit on screen.
* **πŸš€ Editor Jump** β€” Open the selected repo in VSCode, Neovim, Vim, or Helix (`Enter`).
* **⚑ Blazing Fast** β€” JSON caching ensures \~10ms launch time even with 50+ repos.
* **πŸ“Š Dashboard Stats** β€” See branch name, staged/unstaged counts, and last commit time.
Expand Down
15 changes: 4 additions & 11 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ import (

// Config holds the application configuration
type Config struct {
Roots []string `yaml:"roots"`
Ignore []string `yaml:"ignore"`
Editor string `yaml:"editor"`
PageSize int `yaml:"pageSize,omitempty"`
Roots []string `yaml:"roots"`
Ignore []string `yaml:"ignore"`
Editor string `yaml:"editor"`
}

// defaultConfig returns sensible defaults
Expand All @@ -38,8 +37,7 @@ func defaultConfig() *Config {
".venv",
"vendor",
},
Editor: "code",
PageSize: 15,
Editor: "code",
}
}

Expand All @@ -65,11 +63,6 @@ func Load(path string) (*Config, error) {
cfg.Roots[i] = expandPath(root)
}

// Ensure pageSize has a sensible value
if cfg.PageSize <= 0 {
cfg.PageSize = 15
}

return cfg, nil
}

Expand Down
13 changes: 6 additions & 7 deletions internal/nudge/nudge.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import (
"encoding/json"
"os"
"path/filepath"
)

// Version is the current app version - used to track per-version nudge
const Version = "1.3.0"
"github.com/Bharath-code/git-scope/internal/version"
)

// GitHubRepoURL is the URL to open when user presses S
const GitHubRepoURL = "https://github.com/Bharath-code/git-scope"
Expand Down Expand Up @@ -78,7 +77,7 @@ func ShouldShowNudge() bool {
state := loadState()

// Already seen for this version
if state.SeenVersion == Version {
if state.SeenVersion == version.Version {
return false
}

Expand All @@ -93,23 +92,23 @@ func ShouldShowNudge() bool {
// MarkShown marks the nudge as shown for the current version
func MarkShown() {
state := loadState()
state.SeenVersion = Version
state.SeenVersion = version.Version
state.Dismissed = false
_ = saveState(state)
}

// MarkDismissed marks the nudge as dismissed (any key pressed)
func MarkDismissed() {
state := loadState()
state.SeenVersion = Version
state.SeenVersion = version.Version
state.Dismissed = true
_ = saveState(state)
}

// MarkCompleted marks the nudge as completed (S pressed, GitHub opened)
func MarkCompleted() {
state := loadState()
state.SeenVersion = Version
state.SeenVersion = version.Version
state.Completed = true
_ = saveState(state)
}
8 changes: 3 additions & 5 deletions internal/tui/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ func NewModel(cfg *config.Config) Model {
sortMode: SortByDirty,
filterMode: FilterAll,
currentPage: 0,
pageSize: cfg.PageSize,
}
}

Expand Down Expand Up @@ -361,15 +360,14 @@ func formatNumber(n int) string {
return fmt.Sprintf("%d", n)
}

// resizeTable calculates and sets the correct table height based on UI state
// resizeTable calculates and sets the correct table height based on UI state.
func (m *Model) resizeTable() {
usedHeight := 12 // Header + Stats + Legend + Help + Padding
if m.state == StateSearching {
usedHeight += 3 // Search input
} else if m.searchQuery != "" {
usedHeight += 1 // Search badge
}

h := m.height - usedHeight
if h < 1 {
h = 1
Expand All @@ -380,6 +378,6 @@ func (m *Model) resizeTable() {
if h < 5 {
h = 5
}
m.pageSize = h // Update page size based on new height
m.updateTable() // Refresh table to apply new page size
m.pageSize = h
m.updateTable()
}
20 changes: 9 additions & 11 deletions internal/tui/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.repos = msg.repos
m.state = StateReady
m.resetPage()
m.updateTable()
m.resizeTable()

// Show helpful message if no repos found
if len(msg.repos) == 0 {
Expand All @@ -59,7 +59,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.repos = msg.repos
m.state = StateReady
m.resetPage()
m.updateTable()
m.resizeTable()

// Show helpful message about switched workspace
if len(msg.repos) == 0 {
Expand Down Expand Up @@ -189,7 +189,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.state == StateReady {
m.filterMode = (m.filterMode + 1) % 3
m.resetPage()
m.updateTable()
m.resizeTable()
m.statusMsg = "Filter: " + m.GetFilterModeName()
return m, nil
}
Expand All @@ -198,7 +198,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.state == StateReady {
m.sortMode = (m.sortMode + 1) % 4
m.resetPage()
m.updateTable()
m.resizeTable()
m.statusMsg = "Sorted by: " + m.GetSortModeName()
return m, nil
}
Expand All @@ -207,7 +207,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.state == StateReady {
m.sortMode = SortByDirty
m.resetPage()
m.updateTable()
m.resizeTable()
m.statusMsg = "Sorted by: Dirty First"
return m, nil
}
Expand All @@ -216,7 +216,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.state == StateReady {
m.sortMode = SortByName
m.resetPage()
m.updateTable()
m.resizeTable()
m.statusMsg = "Sorted by: Name"
return m, nil
}
Expand All @@ -225,7 +225,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.state == StateReady {
m.sortMode = SortByBranch
m.resetPage()
m.updateTable()
m.resizeTable()
m.statusMsg = "Sorted by: Branch"
return m, nil
}
Expand All @@ -234,7 +234,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.state == StateReady {
m.sortMode = SortByLastCommit
m.resetPage()
m.updateTable()
m.resizeTable()
m.statusMsg = "Sorted by: Recent"
return m, nil
}
Expand All @@ -247,7 +247,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.filterMode = FilterAll
m.resetPage()
m.resizeTable()
m.updateTable()
m.statusMsg = "Filters cleared"
return m, nil
}
Expand Down Expand Up @@ -372,10 +371,9 @@ func (m Model) handleSearchMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
// Apply search
m.searchQuery = m.textInput.Value()
m.state = StateReady
m.resizeTable()
m.textInput.Blur()
m.resetPage()
m.updateTable()
m.resizeTable()
if m.searchQuery != "" {
m.statusMsg = "Searching: " + m.searchQuery
} else {
Expand Down
5 changes: 3 additions & 2 deletions internal/tui/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"strings"

"github.com/Bharath-code/git-scope/internal/version"
"github.com/charmbracelet/lipgloss"
)

Expand Down Expand Up @@ -104,8 +105,8 @@ func (m Model) renderDashboard() string {

// Header with logo on its own line
logo := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#A78BFA")).Render("git-scope")
version := lipgloss.NewStyle().Foreground(lipgloss.Color("#6B7280")).Render(" v1.3.0")
b.WriteString(logo + version)
ver := lipgloss.NewStyle().Foreground(lipgloss.Color("#6B7280")).Render(" v" + version.Version)
b.WriteString(logo + ver)
b.WriteString("\n\n")

// Stats bar (always show first for consistent layout)
Expand Down
3 changes: 3 additions & 0 deletions internal/version/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package version

const Version = "1.3.2"