rubric/catalog/catalog.go
2026-04-06 11:02:36 +03:00

176 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package catalog
import (
"bufio"
"fmt"
"rubric/utils"
"strconv"
"strings"
)
// Book описывает один справочник верхнего уровня
type Book struct {
Key string
Aliases []string
Title string
Description string
Run func(scanner *bufio.Scanner) // передаём scanner чтобы не создавать новый
}
// All — список всех справочников
var All = []Book{
GoBook,
LinuxBook,
}
// Find ищет книгу по ключу или алиасу
func Find(key string) (Book, bool) {
key = strings.ToLower(strings.TrimSpace(key))
for _, b := range All {
if b.Key == key {
return b, true
}
for _, a := range b.Aliases {
if a == key {
return b, true
}
}
}
return Book{}, false
}
// ShowMainMenu отображает главное меню
func ShowMainMenu() {
utils.Header("rubric — интерактивный справочник")
fmt.Printf(" %s%sДоступные справочники:%s\n\n",
utils.ColorBold, utils.ColorWhite, utils.ColorReset)
for i, b := range All {
aliases := ""
if len(b.Aliases) > 0 {
aliases = fmt.Sprintf("%s [%s]%s",
utils.ColorDim, strings.Join(b.Aliases, ", "), utils.ColorReset)
}
fmt.Printf(" %s%s %2d.%s %s%-8s%s %s%-34s%s%s\n",
utils.ColorBold, utils.ColorCyan, i+1, utils.ColorReset,
utils.ColorYellow+utils.ColorBold, b.Key, utils.ColorReset,
utils.ColorWhite, b.Title, utils.ColorReset,
aliases,
)
fmt.Printf(" %s%s%s\n\n",
utils.ColorDim, b.Description, utils.ColorReset)
}
fmt.Printf(" %s%sВыберите справочник (номер / ключ / q — выход):%s ",
utils.ColorBold, utils.ColorGreen, utils.ColorReset)
}
// RunInteractive — главный интерактивный цикл
func RunInteractive(scanner *bufio.Scanner) {
for {
ShowMainMenu()
if !scanner.Scan() {
break
}
input := strings.TrimSpace(scanner.Text())
if input == "" {
continue
}
if input == "q" || input == "quit" || input == "exit" {
fmt.Printf("\n %s%sДо свидания!%s\n\n",
utils.ColorBold, utils.ColorCyan, utils.ColorReset)
return
}
// По номеру
if n, err := strconv.Atoi(input); err == nil {
if n >= 1 && n <= len(All) {
All[n-1].Run(scanner)
continue
}
fmt.Printf("\n %s%sНомер %d вне диапазона (1%d)%s\n",
utils.ColorBold, utils.ColorRed, n, len(All), utils.ColorReset)
continue
}
// По ключу
if b, ok := Find(input); ok {
b.Run(scanner)
continue
}
fmt.Printf("\n %s%sНе понял '%s'. Введите номер или ключ справочника.%s\n",
utils.ColorBold, utils.ColorRed, input, utils.ColorReset)
}
}
// ShowHelp — общая справка
func ShowHelp() {
utils.Header("rubric — справка по использованию")
utils.Section("Запуск")
utils.Command("./rubric", "главное меню")
utils.Command("./rubric -book go", "открыть справочник напрямую")
utils.Command("./rubric -book go -topic basics", "открыть конкретный раздел")
utils.Command("./rubric -list", "список всех справочников и разделов")
utils.Command("./rubric -help", "эта справка")
fmt.Println()
utils.Section("Доступные справочники")
for _, b := range All {
keys := append([]string{b.Key}, b.Aliases...)
fmt.Printf(" %s%s%-8s%s %-30s %sключи: %s%s\n",
utils.ColorBold, utils.ColorCyan, b.Key, utils.ColorReset,
b.Title,
utils.ColorDim, strings.Join(keys, ", "), utils.ColorReset,
)
}
utils.Footer()
}
// ListAll — краткий список всех справочников и их разделов
func ListAll() {
fmt.Printf("\n%s%srubric — все справочники:%s\n\n",
utils.ColorBold, utils.ColorCyan, utils.ColorReset)
for i, b := range All {
fmt.Printf(" %s%d.%s %s%s%s — %s\n",
utils.ColorDim, i+1, utils.ColorReset,
utils.ColorYellow+utils.ColorBold, b.Key, utils.ColorReset,
b.Title,
)
}
fmt.Println()
}
// PrintBackPrompt — подсказка "вернуться назад"
func PrintBackPrompt(scanner *bufio.Scanner) {
fmt.Printf("\n %s%s[Enter — вернуться в меню справочника, b — главное меню]%s ",
utils.ColorDim, utils.ColorCyan, utils.ColorReset)
if scanner.Scan() {
text := strings.TrimSpace(scanner.Text())
_ = text // "b" обрабатывается в вызывающем коде
}
}
// ReadLine читает строку из сканера
func ReadLine(scanner *bufio.Scanner) (string, bool) {
if !scanner.Scan() {
return "", false
}
return strings.TrimSpace(scanner.Text()), true
}
// IsBack возвращает true если пользователь хочет вернуться на уровень выше
func IsBack(s string) bool {
return s == "b" || s == "back" || s == "назад" || s == ".."
}
// IsQuit возвращает true если пользователь хочет выйти
func IsQuit(s string) bool {
return s == "q" || s == "quit" || s == "exit"
}