176 lines
5.1 KiB
Go
176 lines
5.1 KiB
Go
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"
|
||
}
|