use std::collections::HashMap;
#[derive(Clone)]
pub struct TypeScriptConfiguration {
pub single_quotes: bool,
pub line_width: u32,
pub use_tabs: bool,
pub indent_width: u8,
pub arrow_function_expression_use_parentheses: UseParentheses,
pub arrow_function_expression_brace_position: BracePosition,
pub class_declaration_brace_position: BracePosition,
pub class_expression_brace_position: BracePosition,
pub constructor_brace_position: BracePosition,
pub do_while_statement_brace_position: BracePosition,
pub enum_declaration_brace_position: BracePosition,
pub get_accessor_brace_position: BracePosition,
pub if_statement_brace_position: BracePosition,
pub interface_declaration_brace_position: BracePosition,
pub for_statement_brace_position: BracePosition,
pub for_in_statement_brace_position: BracePosition,
pub for_of_statement_brace_position: BracePosition,
pub function_declaration_brace_position: BracePosition,
pub function_expression_brace_position: BracePosition,
pub method_brace_position: BracePosition,
pub module_declaration_brace_position: BracePosition,
pub set_accessor_brace_position: BracePosition,
pub switch_case_brace_position: BracePosition,
pub switch_statement_brace_position: BracePosition,
pub try_statement_brace_position: BracePosition,
pub while_statement_brace_position: BracePosition,
pub call_expression_force_multi_line_arguments: bool,
pub new_expression_force_multi_line_arguments: bool,
pub arrow_function_expression_force_multi_line_parameters: bool,
pub call_signature_force_multi_line_parameters: bool,
pub construct_signature_force_multi_line_parameters: bool,
pub constructor_force_multi_line_parameters: bool,
pub constructor_type_force_multi_line_parameters: bool,
pub function_declaration_force_multi_line_parameters: bool,
pub function_expression_force_multi_line_parameters: bool,
pub function_type_force_multi_line_parameters: bool,
pub get_accessor_force_multi_line_parameters: bool,
pub method_force_multi_line_parameters: bool,
pub method_signature_force_multi_line_parameters: bool,
pub set_accessor_force_multi_line_parameters: bool,
pub enum_declaration_member_spacing: MemberSpacing,
pub if_statement_next_control_flow_position: NextControlFlowPosition,
pub try_statement_next_control_flow_position: NextControlFlowPosition,
pub binary_expression_operator_position: OperatorPosition,
pub conditional_expression_operator_position: OperatorPosition,
pub break_statement_semi_colon: bool,
pub call_signature_semi_colon: bool,
pub class_property_semi_colon: bool,
pub construct_signature_semi_colon: bool,
pub constructor_semi_colon: bool,
pub continue_statement_semi_colon: bool,
pub debugger_statement_semi_colon: bool,
pub do_while_statement_semi_colon: bool,
pub empty_statement_semi_colon: bool,
pub export_all_declaration_semi_colon: bool,
pub export_assignment_semi_colon: bool,
pub export_default_expression_semi_colon: bool,
pub export_named_declaration_semi_colon: bool,
pub expression_statement_semi_colon: bool,
pub function_declaration_semi_colon: bool,
pub get_accessor_semi_colon: bool,
pub import_declaration_semi_colon: bool,
pub import_equals_semi_colon: bool,
pub index_signature_semi_colon: bool,
pub mapped_type_semi_colon: bool,
pub method_semi_colon: bool,
pub method_signature_semi_colon: bool,
pub module_declaration_semi_colon: bool,
pub namespace_export_declaration_semi_colon: bool,
pub property_signature_semi_colon: bool,
pub return_statement_semi_colon: bool,
pub set_accessor_semi_colon: bool,
pub throw_statement_semi_colon: bool,
pub type_alias_semi_colon: bool,
pub variable_statement_semi_colon: bool,
pub if_statement_single_body_position: SingleBodyPosition,
pub for_statement_single_body_position: SingleBodyPosition,
pub for_in_statement_single_body_position: SingleBodyPosition,
pub for_of_statement_single_body_position: SingleBodyPosition,
pub while_statement_single_body_position: SingleBodyPosition,
pub array_expression_trailing_commas: TrailingCommas,
pub array_pattern_trailing_commas: TrailingCommas,
pub enum_declaration_trailing_commas: TrailingCommas,
pub object_expression_trailing_commas: TrailingCommas,
pub tuple_type_trailing_commas: TrailingCommas,
pub if_statement_use_braces: UseBraces,
pub for_statement_use_braces: UseBraces,
pub for_of_statement_use_braces: UseBraces,
pub for_in_statement_use_braces: UseBraces,
pub while_statement_use_braces: UseBraces,
pub binary_expression_space_surrounding_bitwise_and_arithmetic_operator: bool,
pub construct_signature_space_after_new_keyword: bool,
pub constructor_space_before_parentheses: bool,
pub constructor_type_space_after_new_keyword: bool,
pub do_while_statement_space_after_while_keyword: bool,
pub export_declaration_space_surrounding_named_exports: bool,
pub for_statement_space_after_for_keyword: bool,
pub for_statement_space_after_semi_colons: bool,
pub for_in_statement_space_after_for_keyword: bool,
pub for_of_statement_space_after_for_keyword: bool,
pub function_declaration_space_before_parentheses: bool,
pub function_expression_space_before_parentheses: bool,
pub get_accessor_space_before_parentheses: bool,
pub if_statement_space_after_if_keyword: bool,
pub import_declaration_space_surrounding_named_imports: bool,
pub jsx_expression_container_space_surrounding_expression: bool,
pub method_space_before_parentheses: bool,
pub set_accessor_space_before_parentheses: bool,
pub type_annotation_space_before_colon: bool,
pub type_assertion_space_before_expression: bool,
pub while_statement_space_after_while_keyword: bool,
}
#[derive(Clone, PartialEq, Copy)]
pub enum TrailingCommas {
Never,
Always,
OnlyMultiLine,
}
#[derive(Clone, PartialEq, Copy)]
pub enum BracePosition {
Maintain,
SameLine,
NextLine,
NextLineIfHanging,
}
#[derive(Clone, PartialEq, Copy)]
pub enum MemberSpacing {
Maintain,
NewLine,
BlankLine,
}
#[derive(Clone, PartialEq, Copy)]
pub enum NextControlFlowPosition {
Maintain,
SameLine,
NextLine,
}
#[derive(Clone, PartialEq, Copy)]
pub enum OperatorPosition {
Maintain,
SameLine,
NextLine,
}
#[derive(Clone, PartialEq, Copy)]
pub enum SingleBodyPosition {
Maintain,
SameLine,
NextLine,
}
#[derive(Clone, PartialEq, Copy)]
pub enum UseBraces {
Maintain,
WhenNotSingleLine,
Always,
PreferNone,
}
#[derive(Clone, PartialEq, Copy)]
pub enum UseParentheses {
Maintain,
Force,
PreferNone,
}
pub fn resolve_config(config: &HashMap<String, String>) -> TypeScriptConfiguration {
let mut config = config.clone();
let semi_colons = get_value(&mut config, "semiColons", true);
let force_multi_line_arguments = get_value(&mut config, "forceMultiLineArguments", false);
let force_multi_line_parameters = get_value(&mut config, "forceMultiLineParameters", false);
let brace_position = get_brace_position(&mut config, "bracePosition", BracePosition::NextLineIfHanging);
let next_control_flow_position = get_next_control_flow_position(&mut config, "nextControlFlowPosition", NextControlFlowPosition::NextLine);
let operator_position = get_operator_position(&mut config, "operatorPosition", OperatorPosition::NextLine);
let single_body_position = get_single_body_position(&mut config, "singleBodyPosition", SingleBodyPosition::Maintain);
let trailing_commas = get_trailing_commas(&mut config, "trailingCommas", TrailingCommas::Never);
let use_braces = get_use_braces(&mut config, "useBraces", UseBraces::WhenNotSingleLine);
let resolved_config = TypeScriptConfiguration {
line_width: get_value(&mut config, "lineWidth", 120),
use_tabs: get_value(&mut config, "useTabs", false),
indent_width: get_value(&mut config, "indentWidth", 4),
single_quotes: get_value(&mut config, "singleQuotes", false),
arrow_function_expression_use_parentheses: get_use_parentheses(&mut config, "arrowFunctionExpression.useParentheses", UseParentheses::Maintain),
arrow_function_expression_brace_position: get_brace_position(&mut config, "arrowFunctionExpression.bracePosition", brace_position),
class_declaration_brace_position: get_brace_position(&mut config, "classDeclaration.bracePosition", brace_position),
class_expression_brace_position: get_brace_position(&mut config, "classExpression.bracePosition", brace_position),
constructor_brace_position: get_brace_position(&mut config, "constructor.bracePosition", brace_position),
do_while_statement_brace_position: get_brace_position(&mut config, "doWhileStatement.bracePosition", brace_position),
enum_declaration_brace_position: get_brace_position(&mut config, "enumDeclaration.bracePosition", brace_position),
for_statement_brace_position: get_brace_position(&mut config, "forStatement.bracePosition", brace_position),
for_in_statement_brace_position: get_brace_position(&mut config, "forInStatement.bracePosition", brace_position),
for_of_statement_brace_position: get_brace_position(&mut config, "forOfStatement.bracePosition", brace_position),
get_accessor_brace_position: get_brace_position(&mut config, "getAccessor.bracePosition", brace_position),
if_statement_brace_position: get_brace_position(&mut config, "ifStatement.bracePosition", brace_position),
interface_declaration_brace_position: get_brace_position(&mut config, "interfaceDeclaration.bracePosition", brace_position),
function_declaration_brace_position: get_brace_position(&mut config, "functionDeclaration.bracePosition", brace_position),
function_expression_brace_position: get_brace_position(&mut config, "functionExpression.bracePosition", brace_position),
method_brace_position: get_brace_position(&mut config, "method.bracePosition", brace_position),
module_declaration_brace_position: get_brace_position(&mut config, "moduleDeclaration.bracePosition", brace_position),
set_accessor_brace_position: get_brace_position(&mut config, "setAccessor.bracePosition", brace_position),
switch_case_brace_position: get_brace_position(&mut config, "switchCase.bracePosition", brace_position),
switch_statement_brace_position: get_brace_position(&mut config, "switchStatement.bracePosition", brace_position),
try_statement_brace_position: get_brace_position(&mut config, "tryStatement.bracePosition", brace_position),
while_statement_brace_position: get_brace_position(&mut config, "whileStatement.bracePosition", brace_position),
call_expression_force_multi_line_arguments: get_value(&mut config, "callExpression.forceMultiLineArguments", force_multi_line_arguments),
new_expression_force_multi_line_arguments: get_value(&mut config, "newExpression.forceMultiLineArguments", force_multi_line_arguments),
arrow_function_expression_force_multi_line_parameters: get_value(&mut config, "arrowFunctionExpression.forceMultiLineParameters", force_multi_line_parameters),
call_signature_force_multi_line_parameters: get_value(&mut config, "callSignature.forceMultiLineParameters", force_multi_line_parameters),
construct_signature_force_multi_line_parameters: get_value(&mut config, "constructSignature.forceMultiLineParameters", force_multi_line_parameters),
constructor_force_multi_line_parameters: get_value(&mut config, "constructor.forceMultiLineParameters", force_multi_line_parameters),
constructor_type_force_multi_line_parameters: get_value(&mut config, "constructorType.forceMultiLineParameters", force_multi_line_parameters),
function_declaration_force_multi_line_parameters: get_value(&mut config, "functionDeclaration.forceMultiLineParameters", force_multi_line_parameters),
function_expression_force_multi_line_parameters: get_value(&mut config, "functionExpression.forceMultiLineParameters", force_multi_line_parameters),
function_type_force_multi_line_parameters: get_value(&mut config, "functionType.forceMultiLineParameters", force_multi_line_parameters),
get_accessor_force_multi_line_parameters: get_value(&mut config, "getAccessor.forceMultiLineParameters", force_multi_line_parameters),
method_force_multi_line_parameters: get_value(&mut config, "method.forceMultiLineParameters", force_multi_line_parameters),
method_signature_force_multi_line_parameters: get_value(&mut config, "methodSignature.forceMultiLineParameters", force_multi_line_parameters),
set_accessor_force_multi_line_parameters: get_value(&mut config, "setAccessor.forceMultiLineParameters", force_multi_line_parameters),
enum_declaration_member_spacing: get_member_spacing(&mut config, "enumDeclaration.memberSpacing", MemberSpacing::Maintain),
if_statement_next_control_flow_position: get_next_control_flow_position(&mut config, "ifStatement.nextControlFlowPosition", next_control_flow_position),
try_statement_next_control_flow_position: get_next_control_flow_position(&mut config, "tryStatement.nextControlFlowPosition", next_control_flow_position),
binary_expression_operator_position: get_operator_position(&mut config, "binaryExpression.operatorPosition", operator_position),
conditional_expression_operator_position: get_operator_position(&mut config, "conditionalExpression.operatorPosition", operator_position),
break_statement_semi_colon: get_value(&mut config, "breakStatement.semiColon", semi_colons),
call_signature_semi_colon: get_value(&mut config, "callSignature.semiColon", semi_colons),
class_property_semi_colon: get_value(&mut config, "classProperty.semiColon", semi_colons),
construct_signature_semi_colon: get_value(&mut config, "constructSignature.semiColon", semi_colons),
constructor_semi_colon: get_value(&mut config, "constructor.semiColon", semi_colons),
continue_statement_semi_colon: get_value(&mut config, "continueStatement.semiColon", semi_colons),
debugger_statement_semi_colon: get_value(&mut config, "debuggerStatement.semiColon", semi_colons),
do_while_statement_semi_colon: get_value(&mut config, "doWhileStatement.semiColon", semi_colons),
empty_statement_semi_colon: get_value(&mut config, "emptyStatement.semiColon", semi_colons),
export_all_declaration_semi_colon: get_value(&mut config, "exportAllDeclaration.semiColon", semi_colons),
export_assignment_semi_colon: get_value(&mut config, "exportAssignment.semiColon", semi_colons),
export_default_expression_semi_colon: get_value(&mut config, "exportDefaultExpression.semiColon", semi_colons),
export_named_declaration_semi_colon: get_value(&mut config, "exportNamedDeclaration.semiColon", semi_colons),
expression_statement_semi_colon: get_value(&mut config, "expressionStatement.semiColon", semi_colons),
function_declaration_semi_colon: get_value(&mut config, "functionDeclaration.semiColon", semi_colons),
get_accessor_semi_colon: get_value(&mut config, "getAccessor.semiColon", semi_colons),
import_declaration_semi_colon: get_value(&mut config, "importDeclaration.semiColon", semi_colons),
import_equals_semi_colon: get_value(&mut config, "importEqualsDeclaration.semiColon", semi_colons),
index_signature_semi_colon: get_value(&mut config, "indexSignature.semiColon", semi_colons),
mapped_type_semi_colon: get_value(&mut config, "mappedType.semiColon", semi_colons),
method_semi_colon: get_value(&mut config, "method.semiColon", semi_colons),
method_signature_semi_colon: get_value(&mut config, "methodSignature.semiColon", semi_colons),
module_declaration_semi_colon: get_value(&mut config, "moduleDeclaration.semiColon", semi_colons),
namespace_export_declaration_semi_colon: get_value(&mut config, "namespaceExportDeclaration.semiColon", semi_colons),
property_signature_semi_colon: get_value(&mut config, "propertySignature.semiColon", semi_colons),
return_statement_semi_colon: get_value(&mut config, "returnStatement.semiColon", semi_colons),
set_accessor_semi_colon: get_value(&mut config, "setAccessor.semiColon", semi_colons),
throw_statement_semi_colon: get_value(&mut config, "throwStatement.semiColon", semi_colons),
type_alias_semi_colon: get_value(&mut config, "typeAlias.semiColon", semi_colons),
variable_statement_semi_colon: get_value(&mut config, "variableStatement.semiColon", semi_colons),
if_statement_single_body_position: get_single_body_position(&mut config, "ifStatement.singleBodyPosition", single_body_position),
for_statement_single_body_position: get_single_body_position(&mut config, "forStatement.singleBodyPosition", single_body_position),
for_in_statement_single_body_position: get_single_body_position(&mut config, "forInStatement.singleBodyPosition", single_body_position),
for_of_statement_single_body_position: get_single_body_position(&mut config, "forOfStatement.singleBodyPosition", single_body_position),
while_statement_single_body_position: get_single_body_position(&mut config, "whileStatement.singleBodyPosition", single_body_position),
array_expression_trailing_commas: get_trailing_commas(&mut config, "arrayExpression.trailingCommas", trailing_commas),
array_pattern_trailing_commas: get_trailing_commas(&mut config, "arrayPattern.trailingCommas", trailing_commas),
enum_declaration_trailing_commas: get_trailing_commas(&mut config, "enumDeclaration.trailingCommas", trailing_commas),
object_expression_trailing_commas: get_trailing_commas(&mut config, "objectExpression.trailingCommas", trailing_commas),
tuple_type_trailing_commas: get_trailing_commas(&mut config, "tupleType.trailingCommas", trailing_commas),
if_statement_use_braces: get_use_braces(&mut config, "ifStatement.useBraces", use_braces),
for_statement_use_braces: get_use_braces(&mut config, "forStatement.useBraces", use_braces),
for_in_statement_use_braces: get_use_braces(&mut config, "forInStatement.useBraces", use_braces),
for_of_statement_use_braces: get_use_braces(&mut config, "forOfStatement.useBraces", use_braces),
while_statement_use_braces: get_use_braces(&mut config, "whileStatement.useBraces", use_braces),
binary_expression_space_surrounding_bitwise_and_arithmetic_operator: get_value(&mut config, "binaryExpression.spaceSurroundingBitwiseAndArithmeticOperator", true),
construct_signature_space_after_new_keyword: get_value(&mut config, "constructSignature.spaceAfterNewKeyword", false),
constructor_space_before_parentheses: get_value(&mut config, "constructor.spaceBeforeParentheses", false),
constructor_type_space_after_new_keyword: get_value(&mut config, "constructorType.spaceAfterNewKeyword", false),
do_while_statement_space_after_while_keyword: get_value(&mut config, "doWhileStatement.spaceAfterWhileKeyword", true),
export_declaration_space_surrounding_named_exports: get_value(&mut config, "exportDeclaration.spaceSurroundingNamedExports", true),
for_statement_space_after_for_keyword: get_value(&mut config, "forStatement.spaceAfterForKeyword", true),
for_statement_space_after_semi_colons: get_value(&mut config, "forStatement.spaceAfterSemiColons", true),
for_in_statement_space_after_for_keyword: get_value(&mut config, "forInStatement.spaceAfterForKeyword", true),
for_of_statement_space_after_for_keyword: get_value(&mut config, "forOfStatement.spaceAfterForKeyword", true),
function_declaration_space_before_parentheses: get_value(&mut config, "functionDeclaration.spaceBeforeParentheses", false),
function_expression_space_before_parentheses: get_value(&mut config, "functionExpression.spaceBeforeParentheses", false),
get_accessor_space_before_parentheses: get_value(&mut config, "getAccessor.spaceBeforeParentheses", false),
if_statement_space_after_if_keyword: get_value(&mut config, "ifStatement.spaceAfterIfKeyword", true),
import_declaration_space_surrounding_named_imports: get_value(&mut config, "importDeclaration.spaceSurroundingNamedImports", true),
jsx_expression_container_space_surrounding_expression: get_value(&mut config, "jsxExpressionContainer.spaceSurroundingExpression", false),
method_space_before_parentheses: get_value(&mut config, "method.spaceBeforeParentheses", false),
set_accessor_space_before_parentheses: get_value(&mut config, "setAccessor.spaceBeforeParentheses", false),
type_annotation_space_before_colon: get_value(&mut config, "typeAnnotation.spaceBeforeColon", false),
type_assertion_space_before_expression: get_value(&mut config, "typeAssertion.spaceBeforeExpression", true),
while_statement_space_after_while_keyword: get_value(&mut config, "whileStatement.spaceAfterWhileKeyword", true),
};
if !config.is_empty() {
panic!("Unhandled configuration value(s): {}", config.keys().map(|x| x.to_owned()).collect::<Vec<String>>().join(", "));
}
return resolved_config;
}
fn get_value<T>(
config: &mut HashMap<String, String>,
prop: &str,
default_value: T
) -> T where T : std::str::FromStr, <T as std::str::FromStr>::Err : std::fmt::Debug {
let value = config.get(prop).map(|x| x.parse::<T>().unwrap()).unwrap_or(default_value);
config.remove(prop);
return value;
}
fn get_trailing_commas(
config: &mut HashMap<String, String>,
prop: &str,
default_value: TrailingCommas
) -> TrailingCommas {
let value = config.get(prop).map(|x| x.parse::<String>().unwrap());
config.remove(prop);
if let Some(value) = value {
match value.as_ref() {
"always" => TrailingCommas::Always,
"never" => TrailingCommas::Never,
"onlyMultiLine" => TrailingCommas::OnlyMultiLine,
"" => default_value,
_ => panic!("Invalid configuration option {}.", value)
}
} else {
default_value
}
}
fn get_brace_position(
config: &mut HashMap<String, String>,
prop: &str,
default_value: BracePosition
) -> BracePosition {
let value = config.get(prop).map(|x| x.parse::<String>().unwrap());
config.remove(prop);
if let Some(value) = value {
match value.as_ref() {
"maintain" => BracePosition::Maintain,
"sameLine" => BracePosition::SameLine,
"nextLine" => BracePosition::NextLine,
"nextLineIfHanging" => BracePosition::NextLineIfHanging,
"" => default_value,
_ => panic!("Invalid configuration option {}.", value)
}
} else {
default_value
}
}
fn get_member_spacing(
config: &mut HashMap<String, String>,
prop: &str,
default_value: MemberSpacing
) -> MemberSpacing {
let value = config.get(prop).map(|x| x.parse::<String>().unwrap());
config.remove(prop);
if let Some(value) = value {
match value.as_ref() {
"maintain" => MemberSpacing::Maintain,
"blankline" => MemberSpacing::BlankLine,
"newline" => MemberSpacing::NewLine,
"" => default_value,
_ => panic!("Invalid configuration option {}.", value)
}
} else {
default_value
}
}
fn get_next_control_flow_position(
config: &mut HashMap<String, String>,
prop: &str,
default_value: NextControlFlowPosition
) -> NextControlFlowPosition {
let value = config.get(prop).map(|x| x.parse::<String>().unwrap());
config.remove(prop);
if let Some(value) = value {
match value.as_ref() {
"maintain" => NextControlFlowPosition::Maintain,
"sameLine" => NextControlFlowPosition::SameLine,
"nextLine" => NextControlFlowPosition::NextLine,
"" => default_value,
_ => panic!("Invalid configuration option {}.", value)
}
} else {
default_value
}
}
fn get_operator_position(
config: &mut HashMap<String, String>,
prop: &str,
default_value: OperatorPosition
) -> OperatorPosition {
let value = config.get(prop).map(|x| x.parse::<String>().unwrap());
config.remove(prop);
if let Some(value) = value {
match value.as_ref() {
"maintain" => OperatorPosition::Maintain,
"sameLine" => OperatorPosition::SameLine,
"nextLine" => OperatorPosition::NextLine,
"" => default_value,
_ => panic!("Invalid configuration option {}.", value)
}
} else {
default_value
}
}
fn get_single_body_position(
config: &mut HashMap<String, String>,
prop: &str,
default_value: SingleBodyPosition
) -> SingleBodyPosition {
let value = config.get(prop).map(|x| x.parse::<String>().unwrap());
config.remove(prop);
if let Some(value) = value {
match value.as_ref() {
"maintain" => SingleBodyPosition::Maintain,
"sameLine" => SingleBodyPosition::SameLine,
"nextLine" => SingleBodyPosition::NextLine,
"" => default_value,
_ => panic!("Invalid configuration option {}.", value)
}
} else {
default_value
}
}
fn get_use_braces(
config: &mut HashMap<String, String>,
prop: &str,
default_value: UseBraces
) -> UseBraces {
let value = config.get(prop).map(|x| x.parse::<String>().unwrap());
config.remove(prop);
if let Some(value) = value {
match value.as_ref() {
"maintain" => UseBraces::Maintain,
"whenNotSingleLine" => UseBraces::WhenNotSingleLine,
"always" => UseBraces::Always,
"preferNone" => UseBraces::PreferNone,
"" => default_value,
_ => panic!("Invalid configuration option {}.", value)
}
} else {
default_value
}
}
fn get_use_parentheses(
config: &mut HashMap<String, String>,
prop: &str,
default_value: UseParentheses
) -> UseParentheses {
let value = config.get(prop).map(|x| x.parse::<String>().unwrap());
config.remove(prop);
if let Some(value) = value {
match value.as_ref() {
"maintain" => UseParentheses::Maintain,
"force" => UseParentheses::Force,
"preferNone" => UseParentheses::PreferNone,
"" => default_value,
_ => panic!("Invalid configuration option {}.", value)
}
} else {
default_value
}
}