Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#6 Setup the Config Command #12

Merged
merged 3 commits into from
Apr 24, 2024
Merged
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
112 changes: 111 additions & 1 deletion src/commands/config.gleam
Original file line number Diff line number Diff line change
@@ -1,11 +1,121 @@
//// Command to write the config file for the specific user's environment

import gleam/bool
import gleam/int
import gleam/io
import gleam/option.{None, Some}
import gleam/string
import glint.{type CommandInput, type Glint}
import util/commands/watch_tool
import util/env.{ConfigOption}
import util/terminal

/// The 'config' command logic
fn do(_input: CommandInput) {
Nil
// Basic information for user to understand what's going on
io.println(
"Welcome, this command is for entering the config information for your Plex Media Server.\n"
<> "You can enter 'exit' at any time to leave the command, this will abort all operations.\n\n"
<> "Required options are indicated by the '*' suffixed at the end of the prompt.\n"
<> "Defaults are indicated by 'default=X'.\n"
<> "Existing config information has priority over default and is indicated by 'current=X'\n"
<> "If the prompt doesn't have a default then entering nothing will unset it regardless of the current value.\n\n",
)

// Current config information if present
let current_base_config = env.get_base_config(should_panic: False)

// Handle the variables for showing the current information
let current_hostname =
"*"
<> case current_base_config.hostname {
// Empty string is the default therefore don't show it
"" -> ""
current -> " 'current=" <> current <> "'"
}
let current_port =
" 'default=32400'"
<> case current_base_config.port {
// Default port is 32400
32_400 -> ""
current -> " 'current=" <> int.to_string(current) <> "'"
}
let current_username =
" 'default=me'"
<> case current_base_config.username {
// Default username is me
"me" -> ""
current -> " 'current=" <> current <> "'"
}
let current_https =
" 'default=False'"
<> case current_base_config.https {
// Default https is False
False -> ""
current -> " 'current=" <> bool.to_string(current) <> "'"
}
let current_check_users = case current_base_config.check_users {
// Empty string is the default therefore don't show it
[""] | [] -> ""
current -> " 'current=" <> string.join(current, ",") <> "'"
}

// Ask for the base config information
let hostname =
terminal.prompt("Enter your hostname" <> current_hostname, default: None)
let port =
terminal.prompt_int(
"Enter your port" <> current_port,
default: Some(current_base_config.port),
)
let username =
terminal.prompt(
"Enter your username" <> current_username,
default: Some(current_base_config.username),
)
let https =
terminal.confirm(
"Do you use HTTPS?" <> current_https,
default: Some(current_base_config.https),
)
let check_users =
terminal.prompt(
"Enter the users to check (example='user1,user2')" <> current_check_users,
// This is not a required option, so the default is an empty string
default: Some(""),
)

case
env.set_config(ConfigOption(
hostname: Some(hostname),
port: Some(port),
username: Some(username),
https: Some(https),
check_users: Some(string.split(check_users, ",")),
// This doesn't handle token, this will keep whatever is there
token: None,
))
{
Ok(_) -> {
io.println(
"\n\nConfig information saved successfully\n"
<> "hostname: "
<> hostname
<> "\n"
<> "port: "
<> int.to_string(port)
<> "\nusername: "
<> username
<> "\nhttps: "
<> bool.to_string(https)
<> "\ncheck_users: "
<> check_users,
)
}
Error(err) -> {
io.println("\n\nError saving config information: " <> string.inspect(err))
}
}
}

/// Add the 'config' command to the glint instance
Expand Down
4 changes: 2 additions & 2 deletions src/commands/sample.gleam
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//// Hidden sample command.

import gleam/io
import gleam/option.{Some}
import gleam/option.{None, Some}
import glint.{type CommandInput, type Glint}
import util/terminal

/// Runs the basic terminal code for testing the command and terminal logic
fn do(_input: CommandInput) {
let hello = terminal.prompt("Type something")
let hello = terminal.prompt("Type something", None)
case hello {
"something" -> {
io.println("Oh you think you're funny huh?")
Expand Down
4 changes: 2 additions & 2 deletions src/util/env.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ pub fn set_config(input: ConfigOption) -> Result(Nil, FileError) {
contents: "hostname='"
<> new_hostname
<> "'\n"
<> "port="
<> "port='"
<> new_port
<> "\n"
<> "'\n"
<> "username='"
<> new_username
<> "'\n"
Expand Down
73 changes: 67 additions & 6 deletions src/util/terminal.gleam
Original file line number Diff line number Diff line change
@@ -1,21 +1,60 @@
//// This module is a wrapper for the survey module to handle input and output within the terminal.

import gleam/int
import gleam/option.{type Option, None, Some}
import gleam/string
import shellout
import survey

/// To prevent having input all arguments this function handles only showing the prompt
fn question(text display: String) -> survey.Survey {
fn question(
text display: String,
default default: Option(String),
) -> survey.Survey {
survey.new_question(
prompt: display <> ":",
help: None,
default: None,
default: default,
validate: None,
transform: None,
)
}

/// Traditional question but will return a string with "exit" or string representation of an int
fn question_int(
text display: String,
default default: Option(Int),
) -> survey.Survey {
let default_as_string = case default {
Some(num) -> Some(int.to_string(num))
None -> None
}
survey.new_question(
prompt: display <> ":",
help: None,
default: default_as_string,
validate: Some(fn(response) {
// Represents the response as a string
let sanitised_result =
string.lowercase(response)
|> string.trim
// Represents the response as a number
let result_as_number = int.parse(sanitised_result)
case sanitised_result, result_as_number {
// If the user types exit, that is valid
"exit", _ -> True
// If the user types a number, that is valid
_, Ok(_) -> True
_, _ -> False
}
}),
transform: Some(fn(response) {
string.lowercase(response)
|> string.trim
}),
)
}

/// To handle custom confirmations (This will allow the use of exit)
fn confirmation(
text display: String,
Expand All @@ -32,7 +71,7 @@ fn confirmation(
}
}
survey.new_question(
prompt: display <> " " <> default_string,
prompt: display <> " " <> default_string <> ":",
help: None,
default: default_value,
validate: Some(fn(response) {
Expand All @@ -59,12 +98,15 @@ fn confirmation(
}

/// Will prompt the user within the terminal. Returns a string response of their answer.
pub fn prompt(text display: String) -> String {
pub fn prompt(text display: String, default default: Option(String)) -> String {
let assert survey.StringAnswer(response) =
question(display)
question(display, default)
|> survey.ask(help: False)
// If the user types 'exit' close the application
case string.lowercase(response) {
case
string.lowercase(response)
|> string.trim
{
"exit" -> {
exit()
// Still need to return a string even though it exits
Expand All @@ -74,6 +116,25 @@ pub fn prompt(text display: String) -> String {
}
}

/// Will prompt the user within the terminal. Returns an int response of their answer.
/// If the user doesn't enter a number, it will prompt them until they do.
pub fn prompt_int(text display: String, default default: Option(Int)) -> Int {
let assert survey.StringAnswer(response) =
question_int(display, default)
|> survey.ask(help: False)
let response_int = int.parse(response)
case response, response_int {
"exit", _ -> {
exit()
// Still need to return an int even though it exits
0
}
_, Ok(num) -> num
// Impossible to get to but needed for the compiler
_, _ -> 0
}
}

/// Will confirm the user within the terminal. Returns a boolean response of their answer.
pub fn confirm(text display: String, default default: Option(Bool)) -> Bool {
let assert survey.StringAnswer(response) =
Expand Down
Loading