# Script.go

```go
package core

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// Script 구조체는 스크립트 실행을 위한 기본적인 기능을 제공합니다.
type Script struct {
	Description string           // 스크립트 설명
	Options     map[string]Option // 스크립트 옵션들

	Args map[string]string // 스크립트 인자들
}

// Option 구조체는 스크립트 옵션을 표현합니다.
type Option struct {
	Short       string // 단축 옵션
	Example     string // 예제
	Description string // 설명
}

// NewScript 함수는 새로운 Script 구조체를 생성합니다.
func NewScript() *Script {
	return &Script{
		Options: make(map[string]Option),
		Args:    make(map[string]string),
	}
}

// SetArgs 함수는 Script 구조체의 인자들을 설정합니다.
func (s *Script) SetArgs(args map[string]string) {
	s.Args = args
}

// GetArgs 함수는 Script 구조체의 인자들을 반환합니다.
func (s *Script) GetArgs() map[string]string {
	return s.Args
}

// Print 함수는 주어진 객체를 표준 출력에 출력합니다.
func (s *Script) Print(obj interface{}) {
	fmt.Println(obj)
}

// Ask 함수는 사용자에게 메시지를 출력하고 사용자의 입력을 받습니다.
func (s *Script) Ask(msg string) string {
	if msg != "" {
		fmt.Println(msg)
	}

	reader := bufio.NewReader(os.Stdin)
	response, _ := reader.ReadString('\n')
	return strings.TrimSpace(response)
}

// Main 함수는 Script를 구현한 구조체에서 재정의되어야 합니다.
func (s *Script) Main() {
	// 하위 클래스에서 재정의될 메서드입니다.
}

// AddOption 함수는 Script 구조체에 새로운 옵션을 추가합니다.
func (s *Script) AddOption(key, short, example, description string) {
	s.Options[key] = Option{Short: short, Example: example, Description: description}
}

// Help 함수는 Script의 도움말을 출력합니다.
func (s *Script) Help() {
	base := os.Args[0]
	script := strings.TrimPrefix(base, "./")
	maxLength := 0

	// 기본적으로 help 옵션을 추가합니다.
	if _, exists := s.Options["help"]; !exists {
		s.AddOption("help", "h", "", "This help")
	}

	// 가장 긴 옵션의 길이를 계산합니다.
	for key, value := range s.Options {
		shortString := ""
		if value.Short != "" {
			shortString = "-" + value.Short
		}
		example := value.Example
		length := len(fmt.Sprintf("  %s --%s %s ", shortString, key, example))
		if length > maxLength {
			maxLength = length
		}
	}

	// 사용법을 출력합니다.
	fmt.Printf("\nUsage: %s %s -- [args...]\n", base, script)

	// 가장 처음 옵션에 대한 사용법을 출력합니다.
	for key, value := range s.Options {
		example := value.Example
		fmt.Printf("  %s %s --%s %s\n", base, script, key, example)
		break
	}

	// 옵션 목록을 출력합니다.
	fmt.Println("\nOptions: ")

	for key, value := range s.Options {
		shortString := ""
		if value.Short != "" {
			shortString = "-" + value.Short
		}
		example := value.Example
		description := value.Description
		prefix := fmt.Sprintf("  %s --%s %s ", shortString, key, example)
		fmt.Printf("%-*s %s\n", maxLength, prefix, description)
	}

	// 스크립트 설명을 출력합니다.
	fmt.Println()
	fmt.Println(s.Description)
}

```

\
해당 코드는 `Script`라는 구조체를 정의하여 스크립트 실행 환경을 제공하는 유틸리티입니다. 이 유틸리티는 스크립트의 설명, 옵션, 인자 등을 관리하며, 사용자와 상호작용을 도와줍니다. 주요 함수와 메서드에 대해 자세히 설명드리겠습니다.

#### Script 구조체

```go
type Script struct {
	Description string
	Options     map[string]Option
	Args        map[string]string
}
```

* `Description`: 스크립트에 대한 설명.
* `Options`: 스크립트에서 사용 가능한 옵션들을 저장하는 맵.
* `Args`: 스크립트에 전달된 인자들을 저장하는 맵.

#### Option 구조체

```go
type Option struct {
	Short       string
	Example     string
	Description string
}
```

* `Short`: 옵션의 짧은 형태(단일 문자).
* `Example`: 옵션의 예제 값.
* `Description`: 옵션에 대한 설명.

#### NewScript 함수

```go
func NewScript() *Script {
	return &Script{
		Options: make(map[string]Option),
		Args:    make(map[string]string),
	}
}
```

* **역할**: 새로운 `Script` 객체를 생성합니다.
* **동작 방식**: `Options`와 `Args`를 빈 맵으로 초기화한 `Script` 객체를 반환합니다.

#### SetArgs 메서드

```go
func (s *Script) SetArgs(args map[string]string) {
	s.Args = args
}
```

* **역할**: 스크립트의 인자(`Args`)를 설정합니다.
* **동작 방식**: 인자로 받은 `args` 맵을 `Args` 필드에 할당합니다.

#### GetArgs 메서드

```go
func (s *Script) GetArgs() map[string]string {
	return s.Args
}
```

* **역할**: 스크립트의 인자(`Args`)를 반환합니다.
* **동작 방식**: `Args` 필드를 반환합니다.

#### Print 메서드

```go
func (s *Script) Print(obj interface{}) {
	fmt.Println(obj)
}
```

* **역할**: 객체를 콘솔에 출력합니다.
* **동작 방식**: `fmt.Println`을 사용하여 `obj`를 출력합니다.

#### Ask 메서드

```go
func (s *Script) Ask(msg string) string {
	if msg != "" {
		fmt.Println(msg)
	}

	reader := bufio.NewReader(os.Stdin)
	response, _ := reader.ReadString('\n')
	return strings.TrimSpace(response)
}
```

* **역할**: 사용자에게 메시지를 출력하고 입력을 받습니다.
* **동작 방식**:
  * `msg`가 비어있지 않으면 메시지를 출력합니다.
  * `bufio.NewReader(os.Stdin)`을 사용하여 표준 입력에서 사용자 입력을 읽습니다.
  * 읽은 문자열에서 개행 문자를 제거하고 반환합니다.

#### Main 메서드

```go
func (s *Script) Main() {
	// To be overridden by subclasses
}
```

* **역할**: 스크립트의 메인 함수. 서브클래스에서 오버라이드됩니다.
* **동작 방식**: 기본적으로 아무 동작도 하지 않으며, 서브클래스에서 이 메서드를 구현해야 합니다.

#### AddOption 메서드

```go
func (s *Script) AddOption(key, short, example, description string) {
	s.Options[key] = Option{Short: short, Example: example, Description: description}
}
```

* **역할**: 새로운 옵션을 추가합니다.
* **동작 방식**: `key`를 기준으로 `Option` 객체를 생성하여 `Options` 맵에 추가합니다.

#### Help 메서드

```go
func (s *Script) Help() {
	base := os.Args[0]
	script := strings.TrimPrefix(base, "./")
	maxLength := 0

	if _, exists := s.Options["help"]; !exists {
		s.AddOption("help", "h", "", "This help")
	}

	for key, value := range s.Options {
		shortString := ""
		if value.Short != "" {
			shortString = "-" + value.Short
		}
		example := value.Example
		length := len(fmt.Sprintf("  %s --%s %s ", shortString, key, example))
		if length > maxLength {
			maxLength = length
		}
	}

	fmt.Printf("\nUsage: %s %s -- [args...]\n", base, script)

	for key, value := range s.Options {
		example := value.Example
		fmt.Printf("  %s %s --%s %s\n", base, script, key, example)
		break
	}

	fmt.Println("\nOptions: ")

	for key, value := range s.Options {
		shortString := ""
		if value.Short != "" {
			shortString = "-" + value.Short
		}
		example := value.Example
		description := value.Description
		prefix := fmt.Sprintf("  %s --%s %s ", shortString, key, example)
		fmt.Printf("%-*s %s\n", maxLength, prefix, description)
	}

	fmt.Println()
	fmt.Println(s.Description)
}
```

* **역할**: 스크립트의 도움말을 출력합니다.
* **동작 방식**:
  * `base`와 `script` 변수를 통해 실행 파일 이름을 가져옵니다.
  * `maxLength` 변수를 통해 옵션 문자열의 최대 길이를 계산합니다.
  * 기본적인 도움말 옵션(`help`)을 추가합니다.
  * 각 옵션의 길이를 계산하여 `maxLength`를 업데이트합니다.
  * 사용 예제(`Usage`)를 출력합니다.
  * 옵션 목록을 출력합니다.
  * 스크립트 설명을 출력합니다.

#### 코드 요약

이 코드는 `Script` 구조체를 통해 스크립트의 옵션과 인자, 사용자와의 상호작용을 관리하는 유틸리티를 제공합니다. 각 메서드는 스크립트 실행에 필요한 다양한 기능을 제공합니다. 이를 통해 스크립트를 더욱 체계적으로 관리하고 사용자에게 친화적인 인터페이스를 제공할 수 있습니다.
