MISC: enhance code step 4 (flatten packages & merge kotlin files)
This commit is contained in:
parent
6780c29f94
commit
47d2999207
568
.editorconfig
Normal file
568
.editorconfig
Normal file
@ -0,0 +1,568 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
max_line_length = 120
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 2
|
||||||
|
ij_formatter_off_tag = @fmt:off
|
||||||
|
ij_formatter_on_tag = @fmt:on
|
||||||
|
ij_formatter_tags_enabled = false
|
||||||
|
ij_smart_tabs = true
|
||||||
|
ij_visual_guides = none
|
||||||
|
ij_wrap_on_typing = false
|
||||||
|
|
||||||
|
[*.java]
|
||||||
|
ij_java_align_consecutive_assignments = false
|
||||||
|
ij_java_align_consecutive_variable_declarations = false
|
||||||
|
ij_java_align_group_field_declarations = false
|
||||||
|
ij_java_align_multiline_annotation_parameters = false
|
||||||
|
ij_java_align_multiline_array_initializer_expression = false
|
||||||
|
ij_java_align_multiline_assignment = false
|
||||||
|
ij_java_align_multiline_binary_operation = false
|
||||||
|
ij_java_align_multiline_chained_methods = false
|
||||||
|
ij_java_align_multiline_extends_list = false
|
||||||
|
ij_java_align_multiline_for = true
|
||||||
|
ij_java_align_multiline_method_parentheses = false
|
||||||
|
ij_java_align_multiline_parameters = true
|
||||||
|
ij_java_align_multiline_parameters_in_calls = false
|
||||||
|
ij_java_align_multiline_parenthesized_expression = false
|
||||||
|
ij_java_align_multiline_records = true
|
||||||
|
ij_java_align_multiline_resources = true
|
||||||
|
ij_java_align_multiline_ternary_operation = false
|
||||||
|
ij_java_align_multiline_text_blocks = false
|
||||||
|
ij_java_align_multiline_throws_list = false
|
||||||
|
ij_java_align_subsequent_simple_methods = false
|
||||||
|
ij_java_align_throws_keyword = false
|
||||||
|
ij_java_annotation_parameter_wrap = off
|
||||||
|
ij_java_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_java_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_java_array_initializer_wrap = off
|
||||||
|
ij_java_assert_statement_colon_on_next_line = false
|
||||||
|
ij_java_assert_statement_wrap = off
|
||||||
|
ij_java_assignment_wrap = off
|
||||||
|
ij_java_binary_operation_sign_on_next_line = false
|
||||||
|
ij_java_binary_operation_wrap = off
|
||||||
|
ij_java_blank_lines_after_anonymous_class_header = 0
|
||||||
|
ij_java_blank_lines_after_class_header = 0
|
||||||
|
ij_java_blank_lines_after_imports = 1
|
||||||
|
ij_java_blank_lines_after_package = 1
|
||||||
|
ij_java_blank_lines_around_class = 1
|
||||||
|
ij_java_blank_lines_around_field = 0
|
||||||
|
ij_java_blank_lines_around_field_in_interface = 0
|
||||||
|
ij_java_blank_lines_around_initializer = 1
|
||||||
|
ij_java_blank_lines_around_method = 1
|
||||||
|
ij_java_blank_lines_around_method_in_interface = 0
|
||||||
|
ij_java_blank_lines_before_class_end = 0
|
||||||
|
ij_java_blank_lines_before_imports = 1
|
||||||
|
ij_java_blank_lines_before_method_body = 0
|
||||||
|
ij_java_blank_lines_before_package = 0
|
||||||
|
ij_java_block_brace_style = end_of_line
|
||||||
|
ij_java_block_comment_at_first_column = true
|
||||||
|
ij_java_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_java_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_java_call_parameters_wrap = off
|
||||||
|
ij_java_case_statement_on_separate_line = true
|
||||||
|
ij_java_catch_on_new_line = false
|
||||||
|
ij_java_class_annotation_wrap = split_into_lines
|
||||||
|
ij_java_class_brace_style = end_of_line
|
||||||
|
ij_java_class_count_to_use_import_on_demand = 5
|
||||||
|
ij_java_class_names_in_javadoc = 1
|
||||||
|
ij_java_do_not_indent_top_level_class_members = false
|
||||||
|
ij_java_do_not_wrap_after_single_annotation = false
|
||||||
|
ij_java_do_while_brace_force = never
|
||||||
|
ij_java_doc_add_blank_line_after_description = true
|
||||||
|
ij_java_doc_add_blank_line_after_param_comments = false
|
||||||
|
ij_java_doc_add_blank_line_after_return = false
|
||||||
|
ij_java_doc_add_p_tag_on_empty_lines = true
|
||||||
|
ij_java_doc_align_exception_comments = true
|
||||||
|
ij_java_doc_align_param_comments = true
|
||||||
|
ij_java_doc_do_not_wrap_if_one_line = true
|
||||||
|
ij_java_doc_enable_formatting = true
|
||||||
|
ij_java_doc_enable_leading_asterisks = true
|
||||||
|
ij_java_doc_indent_on_continuation = false
|
||||||
|
ij_java_doc_keep_empty_lines = true
|
||||||
|
ij_java_doc_keep_empty_parameter_tag = true
|
||||||
|
ij_java_doc_keep_empty_return_tag = true
|
||||||
|
ij_java_doc_keep_empty_throws_tag = true
|
||||||
|
ij_java_doc_keep_invalid_tags = true
|
||||||
|
ij_java_doc_param_description_on_new_line = false
|
||||||
|
ij_java_doc_preserve_line_breaks = false
|
||||||
|
ij_java_doc_use_throws_not_exception_tag = true
|
||||||
|
ij_java_else_on_new_line = false
|
||||||
|
ij_java_enum_constants_wrap = off
|
||||||
|
ij_java_extends_keyword_wrap = off
|
||||||
|
ij_java_extends_list_wrap = off
|
||||||
|
ij_java_field_annotation_wrap = split_into_lines
|
||||||
|
ij_java_finally_on_new_line = false
|
||||||
|
ij_java_for_brace_force = never
|
||||||
|
ij_java_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_java_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_java_for_statement_wrap = off
|
||||||
|
ij_java_generate_final_locals = false
|
||||||
|
ij_java_generate_final_parameters = false
|
||||||
|
ij_java_if_brace_force = never
|
||||||
|
ij_java_imports_layout = *,|,javax.**,java.**,|,$*
|
||||||
|
ij_java_indent_case_from_switch = true
|
||||||
|
ij_java_insert_inner_class_imports = false
|
||||||
|
ij_java_insert_override_annotation = true
|
||||||
|
ij_java_keep_blank_lines_before_right_brace = 2
|
||||||
|
ij_java_keep_blank_lines_between_package_declaration_and_header = 2
|
||||||
|
ij_java_keep_blank_lines_in_code = 2
|
||||||
|
ij_java_keep_blank_lines_in_declarations = 2
|
||||||
|
ij_java_keep_control_statement_in_one_line = true
|
||||||
|
ij_java_keep_first_column_comment = true
|
||||||
|
ij_java_keep_indents_on_empty_lines = false
|
||||||
|
ij_java_keep_line_breaks = true
|
||||||
|
ij_java_keep_multiple_expressions_in_one_line = false
|
||||||
|
ij_java_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_java_keep_simple_classes_in_one_line = false
|
||||||
|
ij_java_keep_simple_lambdas_in_one_line = true
|
||||||
|
ij_java_keep_simple_methods_in_one_line = false
|
||||||
|
ij_java_label_indent_absolute = false
|
||||||
|
ij_java_label_indent_size = 0
|
||||||
|
ij_java_lambda_brace_style = end_of_line
|
||||||
|
ij_java_layout_static_imports_separately = true
|
||||||
|
ij_java_line_comment_add_space = true
|
||||||
|
ij_java_line_comment_at_first_column = false
|
||||||
|
ij_java_method_annotation_wrap = normal
|
||||||
|
ij_java_method_brace_style = end_of_line
|
||||||
|
ij_java_method_call_chain_wrap = off
|
||||||
|
ij_java_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_java_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_java_method_parameters_wrap = off
|
||||||
|
ij_java_modifier_list_wrap = false
|
||||||
|
ij_java_names_count_to_use_import_on_demand = 3
|
||||||
|
ij_java_new_line_after_lparen_in_record_header = false
|
||||||
|
ij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.*
|
||||||
|
ij_java_parameter_annotation_wrap = off
|
||||||
|
ij_java_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_java_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_java_place_assignment_sign_on_next_line = false
|
||||||
|
ij_java_prefer_longer_names = true
|
||||||
|
ij_java_prefer_parameters_wrap = false
|
||||||
|
ij_java_record_components_wrap = normal
|
||||||
|
ij_java_repeat_synchronized = true
|
||||||
|
ij_java_replace_instanceof_and_cast = false
|
||||||
|
ij_java_replace_null_check = true
|
||||||
|
ij_java_replace_sum_lambda_with_method_ref = true
|
||||||
|
ij_java_resource_list_new_line_after_left_paren = false
|
||||||
|
ij_java_resource_list_right_paren_on_new_line = false
|
||||||
|
ij_java_resource_list_wrap = off
|
||||||
|
ij_java_rparen_on_new_line_in_record_header = false
|
||||||
|
ij_java_space_after_closing_angle_bracket_in_type_argument = false
|
||||||
|
ij_java_space_after_colon = true
|
||||||
|
ij_java_space_after_comma = true
|
||||||
|
ij_java_space_after_comma_in_type_arguments = true
|
||||||
|
ij_java_space_after_for_semicolon = true
|
||||||
|
ij_java_space_after_quest = true
|
||||||
|
ij_java_space_after_type_cast = true
|
||||||
|
ij_java_space_before_annotation_array_initializer_left_brace = false
|
||||||
|
ij_java_space_before_annotation_parameter_list = false
|
||||||
|
ij_java_space_before_array_initializer_left_brace = false
|
||||||
|
ij_java_space_before_catch_keyword = true
|
||||||
|
ij_java_space_before_catch_left_brace = true
|
||||||
|
ij_java_space_before_catch_parentheses = true
|
||||||
|
ij_java_space_before_class_left_brace = true
|
||||||
|
ij_java_space_before_colon = true
|
||||||
|
ij_java_space_before_colon_in_foreach = true
|
||||||
|
ij_java_space_before_comma = false
|
||||||
|
ij_java_space_before_do_left_brace = true
|
||||||
|
ij_java_space_before_else_keyword = true
|
||||||
|
ij_java_space_before_else_left_brace = true
|
||||||
|
ij_java_space_before_finally_keyword = true
|
||||||
|
ij_java_space_before_finally_left_brace = true
|
||||||
|
ij_java_space_before_for_left_brace = true
|
||||||
|
ij_java_space_before_for_parentheses = true
|
||||||
|
ij_java_space_before_for_semicolon = false
|
||||||
|
ij_java_space_before_if_left_brace = true
|
||||||
|
ij_java_space_before_if_parentheses = true
|
||||||
|
ij_java_space_before_method_call_parentheses = false
|
||||||
|
ij_java_space_before_method_left_brace = true
|
||||||
|
ij_java_space_before_method_parentheses = false
|
||||||
|
ij_java_space_before_opening_angle_bracket_in_type_parameter = false
|
||||||
|
ij_java_space_before_quest = true
|
||||||
|
ij_java_space_before_switch_left_brace = true
|
||||||
|
ij_java_space_before_switch_parentheses = true
|
||||||
|
ij_java_space_before_synchronized_left_brace = true
|
||||||
|
ij_java_space_before_synchronized_parentheses = true
|
||||||
|
ij_java_space_before_try_left_brace = true
|
||||||
|
ij_java_space_before_try_parentheses = true
|
||||||
|
ij_java_space_before_type_parameter_list = false
|
||||||
|
ij_java_space_before_while_keyword = true
|
||||||
|
ij_java_space_before_while_left_brace = true
|
||||||
|
ij_java_space_before_while_parentheses = true
|
||||||
|
ij_java_space_inside_one_line_enum_braces = false
|
||||||
|
ij_java_space_within_empty_array_initializer_braces = false
|
||||||
|
ij_java_space_within_empty_method_call_parentheses = false
|
||||||
|
ij_java_space_within_empty_method_parentheses = false
|
||||||
|
ij_java_spaces_around_additive_operators = true
|
||||||
|
ij_java_spaces_around_assignment_operators = true
|
||||||
|
ij_java_spaces_around_bitwise_operators = true
|
||||||
|
ij_java_spaces_around_equality_operators = true
|
||||||
|
ij_java_spaces_around_lambda_arrow = true
|
||||||
|
ij_java_spaces_around_logical_operators = true
|
||||||
|
ij_java_spaces_around_method_ref_dbl_colon = false
|
||||||
|
ij_java_spaces_around_multiplicative_operators = true
|
||||||
|
ij_java_spaces_around_relational_operators = true
|
||||||
|
ij_java_spaces_around_shift_operators = true
|
||||||
|
ij_java_spaces_around_type_bounds_in_type_parameters = true
|
||||||
|
ij_java_spaces_around_unary_operator = false
|
||||||
|
ij_java_spaces_within_angle_brackets = false
|
||||||
|
ij_java_spaces_within_annotation_parentheses = false
|
||||||
|
ij_java_spaces_within_array_initializer_braces = false
|
||||||
|
ij_java_spaces_within_braces = false
|
||||||
|
ij_java_spaces_within_brackets = false
|
||||||
|
ij_java_spaces_within_cast_parentheses = false
|
||||||
|
ij_java_spaces_within_catch_parentheses = false
|
||||||
|
ij_java_spaces_within_for_parentheses = false
|
||||||
|
ij_java_spaces_within_if_parentheses = false
|
||||||
|
ij_java_spaces_within_method_call_parentheses = false
|
||||||
|
ij_java_spaces_within_method_parentheses = false
|
||||||
|
ij_java_spaces_within_parentheses = false
|
||||||
|
ij_java_spaces_within_record_header = false
|
||||||
|
ij_java_spaces_within_switch_parentheses = false
|
||||||
|
ij_java_spaces_within_synchronized_parentheses = false
|
||||||
|
ij_java_spaces_within_try_parentheses = false
|
||||||
|
ij_java_spaces_within_while_parentheses = false
|
||||||
|
ij_java_special_else_if_treatment = true
|
||||||
|
ij_java_subclass_name_suffix = Impl
|
||||||
|
ij_java_ternary_operation_signs_on_next_line = false
|
||||||
|
ij_java_ternary_operation_wrap = off
|
||||||
|
ij_java_test_name_suffix = Test
|
||||||
|
ij_java_throws_keyword_wrap = off
|
||||||
|
ij_java_throws_list_wrap = off
|
||||||
|
ij_java_use_external_annotations = false
|
||||||
|
ij_java_use_fq_class_names = false
|
||||||
|
ij_java_use_relative_indents = false
|
||||||
|
ij_java_use_single_class_imports = true
|
||||||
|
ij_java_variable_annotation_wrap = off
|
||||||
|
ij_java_visibility = public
|
||||||
|
ij_java_while_brace_force = never
|
||||||
|
ij_java_while_on_new_line = false
|
||||||
|
ij_java_wrap_comments = false
|
||||||
|
ij_java_wrap_first_method_in_call_chain = false
|
||||||
|
ij_java_wrap_long_lines = false
|
||||||
|
|
||||||
|
[*.properties]
|
||||||
|
ij_properties_align_group_field_declarations = false
|
||||||
|
ij_properties_keep_blank_lines = false
|
||||||
|
ij_properties_key_value_delimiter = equals
|
||||||
|
ij_properties_spaces_around_key_value_delimiter = false
|
||||||
|
|
||||||
|
[*.proto]
|
||||||
|
ij_proto_keep_indents_on_empty_lines = false
|
||||||
|
|
||||||
|
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.jspx,*.pom,*.rng,*.tagx,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
|
||||||
|
ij_xml_align_attributes = true
|
||||||
|
ij_xml_align_text = false
|
||||||
|
ij_xml_attribute_wrap = normal
|
||||||
|
ij_xml_block_comment_at_first_column = true
|
||||||
|
ij_xml_keep_blank_lines = 1
|
||||||
|
ij_xml_keep_indents_on_empty_lines = false
|
||||||
|
ij_xml_keep_line_breaks = true
|
||||||
|
ij_xml_keep_line_breaks_in_text = true
|
||||||
|
ij_xml_keep_whitespaces = false
|
||||||
|
ij_xml_keep_whitespaces_around_cdata = preserve
|
||||||
|
ij_xml_keep_whitespaces_inside_cdata = false
|
||||||
|
ij_xml_line_comment_at_first_column = true
|
||||||
|
ij_xml_space_after_tag_name = false
|
||||||
|
ij_xml_space_around_equals_in_attribute = false
|
||||||
|
ij_xml_space_inside_empty_tag = false
|
||||||
|
ij_xml_text_wrap = normal
|
||||||
|
|
||||||
|
[{*.gant,*.gradle,*.groovy,*.gy}]
|
||||||
|
ij_groovy_align_group_field_declarations = false
|
||||||
|
ij_groovy_align_multiline_array_initializer_expression = false
|
||||||
|
ij_groovy_align_multiline_assignment = false
|
||||||
|
ij_groovy_align_multiline_binary_operation = false
|
||||||
|
ij_groovy_align_multiline_chained_methods = false
|
||||||
|
ij_groovy_align_multiline_extends_list = false
|
||||||
|
ij_groovy_align_multiline_for = true
|
||||||
|
ij_groovy_align_multiline_list_or_map = true
|
||||||
|
ij_groovy_align_multiline_method_parentheses = false
|
||||||
|
ij_groovy_align_multiline_parameters = true
|
||||||
|
ij_groovy_align_multiline_parameters_in_calls = false
|
||||||
|
ij_groovy_align_multiline_resources = true
|
||||||
|
ij_groovy_align_multiline_ternary_operation = false
|
||||||
|
ij_groovy_align_multiline_throws_list = false
|
||||||
|
ij_groovy_align_named_args_in_map = true
|
||||||
|
ij_groovy_align_throws_keyword = false
|
||||||
|
ij_groovy_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_groovy_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_groovy_array_initializer_wrap = off
|
||||||
|
ij_groovy_assert_statement_wrap = off
|
||||||
|
ij_groovy_assignment_wrap = off
|
||||||
|
ij_groovy_binary_operation_wrap = off
|
||||||
|
ij_groovy_blank_lines_after_class_header = 0
|
||||||
|
ij_groovy_blank_lines_after_imports = 1
|
||||||
|
ij_groovy_blank_lines_after_package = 1
|
||||||
|
ij_groovy_blank_lines_around_class = 1
|
||||||
|
ij_groovy_blank_lines_around_field = 0
|
||||||
|
ij_groovy_blank_lines_around_field_in_interface = 0
|
||||||
|
ij_groovy_blank_lines_around_method = 1
|
||||||
|
ij_groovy_blank_lines_around_method_in_interface = 1
|
||||||
|
ij_groovy_blank_lines_before_imports = 1
|
||||||
|
ij_groovy_blank_lines_before_method_body = 0
|
||||||
|
ij_groovy_blank_lines_before_package = 0
|
||||||
|
ij_groovy_block_brace_style = end_of_line
|
||||||
|
ij_groovy_block_comment_at_first_column = true
|
||||||
|
ij_groovy_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_groovy_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_groovy_call_parameters_wrap = off
|
||||||
|
ij_groovy_catch_on_new_line = false
|
||||||
|
ij_groovy_class_annotation_wrap = split_into_lines
|
||||||
|
ij_groovy_class_brace_style = end_of_line
|
||||||
|
ij_groovy_class_count_to_use_import_on_demand = 5
|
||||||
|
ij_groovy_do_while_brace_force = never
|
||||||
|
ij_groovy_else_on_new_line = false
|
||||||
|
ij_groovy_enum_constants_wrap = off
|
||||||
|
ij_groovy_extends_keyword_wrap = off
|
||||||
|
ij_groovy_extends_list_wrap = off
|
||||||
|
ij_groovy_field_annotation_wrap = off
|
||||||
|
ij_groovy_finally_on_new_line = false
|
||||||
|
ij_groovy_for_brace_force = never
|
||||||
|
ij_groovy_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_groovy_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_groovy_for_statement_wrap = off
|
||||||
|
ij_groovy_if_brace_force = never
|
||||||
|
ij_groovy_import_annotation_wrap = 2
|
||||||
|
ij_groovy_imports_layout = *,|,javax.**,java.**,|,$*
|
||||||
|
ij_groovy_indent_case_from_switch = true
|
||||||
|
ij_groovy_indent_label_blocks = true
|
||||||
|
ij_groovy_insert_inner_class_imports = false
|
||||||
|
ij_groovy_keep_blank_lines_before_right_brace = 2
|
||||||
|
ij_groovy_keep_blank_lines_in_code = 2
|
||||||
|
ij_groovy_keep_blank_lines_in_declarations = 2
|
||||||
|
ij_groovy_keep_control_statement_in_one_line = true
|
||||||
|
ij_groovy_keep_first_column_comment = true
|
||||||
|
ij_groovy_keep_indents_on_empty_lines = false
|
||||||
|
ij_groovy_keep_line_breaks = true
|
||||||
|
ij_groovy_keep_multiple_expressions_in_one_line = false
|
||||||
|
ij_groovy_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_groovy_keep_simple_classes_in_one_line = true
|
||||||
|
ij_groovy_keep_simple_lambdas_in_one_line = true
|
||||||
|
ij_groovy_keep_simple_methods_in_one_line = true
|
||||||
|
ij_groovy_label_indent_absolute = false
|
||||||
|
ij_groovy_label_indent_size = 0
|
||||||
|
ij_groovy_lambda_brace_style = end_of_line
|
||||||
|
ij_groovy_layout_static_imports_separately = true
|
||||||
|
ij_groovy_line_comment_add_space = false
|
||||||
|
ij_groovy_line_comment_at_first_column = true
|
||||||
|
ij_groovy_method_annotation_wrap = off
|
||||||
|
ij_groovy_method_brace_style = end_of_line
|
||||||
|
ij_groovy_method_call_chain_wrap = off
|
||||||
|
ij_groovy_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_groovy_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_groovy_method_parameters_wrap = off
|
||||||
|
ij_groovy_modifier_list_wrap = false
|
||||||
|
ij_groovy_names_count_to_use_import_on_demand = 3
|
||||||
|
ij_groovy_parameter_annotation_wrap = off
|
||||||
|
ij_groovy_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_groovy_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_groovy_prefer_parameters_wrap = false
|
||||||
|
ij_groovy_resource_list_new_line_after_left_paren = false
|
||||||
|
ij_groovy_resource_list_right_paren_on_new_line = false
|
||||||
|
ij_groovy_resource_list_wrap = off
|
||||||
|
ij_groovy_space_after_assert_separator = true
|
||||||
|
ij_groovy_space_after_colon = true
|
||||||
|
ij_groovy_space_after_comma = true
|
||||||
|
ij_groovy_space_after_comma_in_type_arguments = true
|
||||||
|
ij_groovy_space_after_for_semicolon = true
|
||||||
|
ij_groovy_space_after_quest = true
|
||||||
|
ij_groovy_space_after_type_cast = true
|
||||||
|
ij_groovy_space_before_annotation_parameter_list = false
|
||||||
|
ij_groovy_space_before_array_initializer_left_brace = false
|
||||||
|
ij_groovy_space_before_assert_separator = false
|
||||||
|
ij_groovy_space_before_catch_keyword = true
|
||||||
|
ij_groovy_space_before_catch_left_brace = true
|
||||||
|
ij_groovy_space_before_catch_parentheses = true
|
||||||
|
ij_groovy_space_before_class_left_brace = true
|
||||||
|
ij_groovy_space_before_closure_left_brace = true
|
||||||
|
ij_groovy_space_before_colon = true
|
||||||
|
ij_groovy_space_before_comma = false
|
||||||
|
ij_groovy_space_before_do_left_brace = true
|
||||||
|
ij_groovy_space_before_else_keyword = true
|
||||||
|
ij_groovy_space_before_else_left_brace = true
|
||||||
|
ij_groovy_space_before_finally_keyword = true
|
||||||
|
ij_groovy_space_before_finally_left_brace = true
|
||||||
|
ij_groovy_space_before_for_left_brace = true
|
||||||
|
ij_groovy_space_before_for_parentheses = true
|
||||||
|
ij_groovy_space_before_for_semicolon = false
|
||||||
|
ij_groovy_space_before_if_left_brace = true
|
||||||
|
ij_groovy_space_before_if_parentheses = true
|
||||||
|
ij_groovy_space_before_method_call_parentheses = false
|
||||||
|
ij_groovy_space_before_method_left_brace = true
|
||||||
|
ij_groovy_space_before_method_parentheses = false
|
||||||
|
ij_groovy_space_before_quest = true
|
||||||
|
ij_groovy_space_before_switch_left_brace = true
|
||||||
|
ij_groovy_space_before_switch_parentheses = true
|
||||||
|
ij_groovy_space_before_synchronized_left_brace = true
|
||||||
|
ij_groovy_space_before_synchronized_parentheses = true
|
||||||
|
ij_groovy_space_before_try_left_brace = true
|
||||||
|
ij_groovy_space_before_try_parentheses = true
|
||||||
|
ij_groovy_space_before_while_keyword = true
|
||||||
|
ij_groovy_space_before_while_left_brace = true
|
||||||
|
ij_groovy_space_before_while_parentheses = true
|
||||||
|
ij_groovy_space_in_named_argument = true
|
||||||
|
ij_groovy_space_in_named_argument_before_colon = false
|
||||||
|
ij_groovy_space_within_empty_array_initializer_braces = false
|
||||||
|
ij_groovy_space_within_empty_method_call_parentheses = false
|
||||||
|
ij_groovy_spaces_around_additive_operators = true
|
||||||
|
ij_groovy_spaces_around_assignment_operators = true
|
||||||
|
ij_groovy_spaces_around_bitwise_operators = true
|
||||||
|
ij_groovy_spaces_around_equality_operators = true
|
||||||
|
ij_groovy_spaces_around_lambda_arrow = true
|
||||||
|
ij_groovy_spaces_around_logical_operators = true
|
||||||
|
ij_groovy_spaces_around_multiplicative_operators = true
|
||||||
|
ij_groovy_spaces_around_regex_operators = true
|
||||||
|
ij_groovy_spaces_around_relational_operators = true
|
||||||
|
ij_groovy_spaces_around_shift_operators = true
|
||||||
|
ij_groovy_spaces_within_annotation_parentheses = false
|
||||||
|
ij_groovy_spaces_within_array_initializer_braces = false
|
||||||
|
ij_groovy_spaces_within_braces = true
|
||||||
|
ij_groovy_spaces_within_brackets = false
|
||||||
|
ij_groovy_spaces_within_cast_parentheses = false
|
||||||
|
ij_groovy_spaces_within_catch_parentheses = false
|
||||||
|
ij_groovy_spaces_within_for_parentheses = false
|
||||||
|
ij_groovy_spaces_within_gstring_injection_braces = false
|
||||||
|
ij_groovy_spaces_within_if_parentheses = false
|
||||||
|
ij_groovy_spaces_within_list_or_map = false
|
||||||
|
ij_groovy_spaces_within_method_call_parentheses = false
|
||||||
|
ij_groovy_spaces_within_method_parentheses = false
|
||||||
|
ij_groovy_spaces_within_parentheses = false
|
||||||
|
ij_groovy_spaces_within_switch_parentheses = false
|
||||||
|
ij_groovy_spaces_within_synchronized_parentheses = false
|
||||||
|
ij_groovy_spaces_within_try_parentheses = false
|
||||||
|
ij_groovy_spaces_within_tuple_expression = false
|
||||||
|
ij_groovy_spaces_within_while_parentheses = false
|
||||||
|
ij_groovy_special_else_if_treatment = true
|
||||||
|
ij_groovy_ternary_operation_wrap = off
|
||||||
|
ij_groovy_throws_keyword_wrap = off
|
||||||
|
ij_groovy_throws_list_wrap = off
|
||||||
|
ij_groovy_use_flying_geese_braces = false
|
||||||
|
ij_groovy_use_fq_class_names = false
|
||||||
|
ij_groovy_use_fq_class_names_in_javadoc = true
|
||||||
|
ij_groovy_use_relative_indents = false
|
||||||
|
ij_groovy_use_single_class_imports = true
|
||||||
|
ij_groovy_variable_annotation_wrap = off
|
||||||
|
ij_groovy_while_brace_force = never
|
||||||
|
ij_groovy_while_on_new_line = false
|
||||||
|
ij_groovy_wrap_long_lines = false
|
||||||
|
|
||||||
|
[{*.kt,*.kts}]
|
||||||
|
ij_kotlin_align_in_columns_case_branch = false
|
||||||
|
ij_kotlin_align_multiline_binary_operation = false
|
||||||
|
ij_kotlin_align_multiline_extends_list = false
|
||||||
|
ij_kotlin_align_multiline_method_parentheses = false
|
||||||
|
ij_kotlin_align_multiline_parameters = true
|
||||||
|
ij_kotlin_align_multiline_parameters_in_calls = false
|
||||||
|
ij_kotlin_allow_trailing_comma = true
|
||||||
|
ij_kotlin_allow_trailing_comma_on_call_site = true
|
||||||
|
ij_kotlin_assignment_wrap = off
|
||||||
|
ij_kotlin_blank_lines_after_class_header = 0
|
||||||
|
ij_kotlin_blank_lines_around_block_when_branches = 0
|
||||||
|
ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1
|
||||||
|
ij_kotlin_block_comment_at_first_column = true
|
||||||
|
ij_kotlin_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_kotlin_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_kotlin_call_parameters_wrap = off
|
||||||
|
ij_kotlin_catch_on_new_line = false
|
||||||
|
ij_kotlin_class_annotation_wrap = split_into_lines
|
||||||
|
ij_kotlin_continuation_indent_for_chained_calls = true
|
||||||
|
ij_kotlin_continuation_indent_for_expression_bodies = true
|
||||||
|
ij_kotlin_continuation_indent_in_argument_lists = true
|
||||||
|
ij_kotlin_continuation_indent_in_elvis = true
|
||||||
|
ij_kotlin_continuation_indent_in_if_conditions = true
|
||||||
|
ij_kotlin_continuation_indent_in_parameter_lists = true
|
||||||
|
ij_kotlin_continuation_indent_in_supertype_lists = true
|
||||||
|
ij_kotlin_else_on_new_line = false
|
||||||
|
ij_kotlin_enum_constants_wrap = off
|
||||||
|
ij_kotlin_extends_list_wrap = off
|
||||||
|
ij_kotlin_field_annotation_wrap = on_every_item
|
||||||
|
ij_kotlin_finally_on_new_line = false
|
||||||
|
ij_kotlin_if_rparen_on_new_line = false
|
||||||
|
ij_kotlin_import_nested_classes = false
|
||||||
|
ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^
|
||||||
|
ij_kotlin_insert_whitespaces_in_simple_one_line_method = true
|
||||||
|
ij_kotlin_keep_blank_lines_before_right_brace = 2
|
||||||
|
ij_kotlin_keep_blank_lines_in_code = 2
|
||||||
|
ij_kotlin_keep_blank_lines_in_declarations = 2
|
||||||
|
ij_kotlin_keep_first_column_comment = true
|
||||||
|
ij_kotlin_keep_indents_on_empty_lines = false
|
||||||
|
ij_kotlin_keep_line_breaks = true
|
||||||
|
ij_kotlin_lbrace_on_next_line = false
|
||||||
|
ij_kotlin_line_comment_add_space = false
|
||||||
|
ij_kotlin_line_comment_at_first_column = true
|
||||||
|
ij_kotlin_method_annotation_wrap = normal
|
||||||
|
ij_kotlin_method_call_chain_wrap = off
|
||||||
|
ij_kotlin_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_kotlin_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_kotlin_method_parameters_wrap = off
|
||||||
|
ij_kotlin_name_count_to_use_star_import = 5
|
||||||
|
ij_kotlin_name_count_to_use_star_import_for_members = 3
|
||||||
|
ij_kotlin_packages_to_use_import_on_demand = java.util.*,io.ktor.**,java.awt.*,javax.swing.*
|
||||||
|
ij_kotlin_parameter_annotation_wrap = off
|
||||||
|
ij_kotlin_space_after_comma = true
|
||||||
|
ij_kotlin_space_after_extend_colon = true
|
||||||
|
ij_kotlin_space_after_type_colon = true
|
||||||
|
ij_kotlin_space_before_catch_parentheses = true
|
||||||
|
ij_kotlin_space_before_comma = false
|
||||||
|
ij_kotlin_space_before_extend_colon = true
|
||||||
|
ij_kotlin_space_before_for_parentheses = true
|
||||||
|
ij_kotlin_space_before_if_parentheses = true
|
||||||
|
ij_kotlin_space_before_lambda_arrow = true
|
||||||
|
ij_kotlin_space_before_type_colon = false
|
||||||
|
ij_kotlin_space_before_when_parentheses = true
|
||||||
|
ij_kotlin_space_before_while_parentheses = true
|
||||||
|
ij_kotlin_spaces_around_additive_operators = true
|
||||||
|
ij_kotlin_spaces_around_assignment_operators = true
|
||||||
|
ij_kotlin_spaces_around_equality_operators = true
|
||||||
|
ij_kotlin_spaces_around_function_type_arrow = true
|
||||||
|
ij_kotlin_spaces_around_logical_operators = true
|
||||||
|
ij_kotlin_spaces_around_multiplicative_operators = true
|
||||||
|
ij_kotlin_spaces_around_range = false
|
||||||
|
ij_kotlin_spaces_around_relational_operators = true
|
||||||
|
ij_kotlin_spaces_around_unary_operator = false
|
||||||
|
ij_kotlin_spaces_around_when_arrow = true
|
||||||
|
ij_kotlin_variable_annotation_wrap = off
|
||||||
|
ij_kotlin_while_on_new_line = false
|
||||||
|
ij_kotlin_wrap_elvis_expressions = 1
|
||||||
|
ij_kotlin_wrap_expression_body_functions = 0
|
||||||
|
ij_kotlin_wrap_first_method_in_call_chain = false
|
||||||
|
|
||||||
|
[{*.har,*.json}]
|
||||||
|
ij_json_keep_blank_lines_in_code = 0
|
||||||
|
ij_json_keep_indents_on_empty_lines = false
|
||||||
|
ij_json_keep_line_breaks = true
|
||||||
|
ij_json_space_after_colon = true
|
||||||
|
ij_json_space_after_comma = true
|
||||||
|
ij_json_space_before_colon = true
|
||||||
|
ij_json_space_before_comma = false
|
||||||
|
ij_json_spaces_within_braces = false
|
||||||
|
ij_json_spaces_within_brackets = false
|
||||||
|
ij_json_wrap_long_lines = false
|
||||||
|
|
||||||
|
[{*.markdown,*.md}]
|
||||||
|
ij_markdown_force_one_space_after_blockquote_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_header_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_list_bullet = true
|
||||||
|
ij_markdown_force_one_space_between_words = true
|
||||||
|
ij_markdown_keep_indents_on_empty_lines = false
|
||||||
|
ij_markdown_max_lines_around_block_elements = 1
|
||||||
|
ij_markdown_max_lines_around_header = 1
|
||||||
|
ij_markdown_max_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_min_lines_around_block_elements = 1
|
||||||
|
ij_markdown_min_lines_around_header = 1
|
||||||
|
ij_markdown_min_lines_between_paragraphs = 1
|
||||||
|
|
||||||
|
[{*.yaml,*.yml}]
|
||||||
|
ij_yaml_keep_indents_on_empty_lines = false
|
||||||
|
ij_yaml_keep_line_breaks = true
|
||||||
|
ij_yaml_space_before_colon = true
|
||||||
|
ij_yaml_spaces_within_braces = true
|
||||||
|
ij_yaml_spaces_within_brackets = true
|
@ -125,22 +125,22 @@
|
|||||||
</activity-alias>
|
</activity-alias>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.support.AboutActivity"
|
android:name=".ui.other.AboutActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/about"
|
android:label="@string/about"
|
||||||
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.crash.CrashActivity"
|
android:name=".ui.other.CrashActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/error"
|
android:label="@string/error"
|
||||||
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.setup.SetupActivity"
|
android:name=".ui.other.SetupActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.bonus.BonusActivity"
|
android:name=".ui.other.BonusActivity"
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
||||||
@ -159,12 +159,6 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/pref_customization_color_scheme"
|
android:label="@string/pref_customization_color_scheme"
|
||||||
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
||||||
<activity
|
|
||||||
android:name=".ui.support.HelpActivity"
|
|
||||||
android:exported="false"
|
|
||||||
android:label="@string/faq"
|
|
||||||
android:theme="@style/AppTheme.NoActionBar.Dark"/>
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.settings.SettingActivity"
|
android:name=".ui.settings.SettingActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
@ -191,4 +185,4 @@
|
|||||||
android:value="true"/>
|
android:value="true"/>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -9,8 +9,8 @@ import android.view.Gravity
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import io.neoterm.component.NeoInitializer
|
import io.neoterm.component.NeoInitializer
|
||||||
import io.neoterm.frontend.config.NeoPreference
|
import io.neoterm.component.config.NeoPreference
|
||||||
import io.neoterm.ui.bonus.BonusActivity
|
import io.neoterm.ui.other.BonusActivity
|
||||||
import io.neoterm.utils.CrashHandler
|
import io.neoterm.utils.CrashHandler
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,4 +73,4 @@ class App : Application() {
|
|||||||
return app!!
|
return app!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,9 @@ import io.neoterm.component.font.FontComponent
|
|||||||
import io.neoterm.component.pm.PackageComponent
|
import io.neoterm.component.pm.PackageComponent
|
||||||
import io.neoterm.component.profile.ProfileComponent
|
import io.neoterm.component.profile.ProfileComponent
|
||||||
import io.neoterm.component.session.SessionComponent
|
import io.neoterm.component.session.SessionComponent
|
||||||
|
import io.neoterm.component.session.ShellProfile
|
||||||
import io.neoterm.component.userscript.UserScriptComponent
|
import io.neoterm.component.userscript.UserScriptComponent
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.utils.NLog
|
||||||
import io.neoterm.frontend.logging.NLog
|
|
||||||
import io.neoterm.frontend.session.shell.ShellProfile
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
@ -39,4 +38,4 @@ object NeoInitializer {
|
|||||||
val profileComp = ComponentManager.getComponent<ProfileComponent>()
|
val profileComp = ComponentManager.getComponent<ProfileComponent>()
|
||||||
profileComp.registerProfile(ShellProfile.PROFILE_META_NAME, ShellProfile::class.java)
|
profileComp.registerProfile(ShellProfile.PROFILE_META_NAME, ShellProfile::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package io.neoterm.component.codegen
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class CodeGenParameter
|
|
@ -1,12 +1,8 @@
|
|||||||
package io.neoterm.component.codegen
|
package io.neoterm.component.codegen
|
||||||
|
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenObject
|
import io.neoterm.component.NeoComponent
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenerator
|
|
||||||
import io.neoterm.frontend.component.NeoComponent
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class CodeGenComponent : NeoComponent {
|
class CodeGenComponent : NeoComponent {
|
||||||
override fun onServiceInit() {
|
override fun onServiceInit() {
|
||||||
}
|
}
|
||||||
@ -23,3 +19,4 @@ class CodeGenComponent : NeoComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CodeGenParameter
|
@ -1,15 +1,9 @@
|
|||||||
package io.neoterm.component.codegen.generators
|
package io.neoterm.component.codegen
|
||||||
|
|
||||||
import io.neoterm.component.codegen.CodeGenParameter
|
import io.neoterm.component.ComponentManager
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenObject
|
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenerator
|
|
||||||
import io.neoterm.component.colorscheme.NeoColorScheme
|
import io.neoterm.component.colorscheme.NeoColorScheme
|
||||||
import io.neoterm.component.config.ConfigureComponent
|
import io.neoterm.component.config.ConfigureComponent
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class NeoColorGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter) {
|
class NeoColorGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter) {
|
||||||
override fun getGeneratorName(): String {
|
override fun getGeneratorName(): String {
|
||||||
return "NeoColorScheme-Generator"
|
return "NeoColorScheme-Generator"
|
||||||
@ -44,7 +38,7 @@ class NeoColorGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter)
|
|||||||
" ${NeoColorScheme.COLOR_META_VERSION}: ${
|
" ${NeoColorScheme.COLOR_META_VERSION}: ${
|
||||||
colorScheme.colorVersion
|
colorScheme.colorVersion
|
||||||
?: component.getLoaderVersion()
|
?: component.getLoaderVersion()
|
||||||
}\n"
|
}\n",
|
||||||
)
|
)
|
||||||
builder.append("\n")
|
builder.append("\n")
|
||||||
}
|
}
|
||||||
@ -61,4 +55,14 @@ class NeoColorGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter)
|
|||||||
|
|
||||||
builder.append(" }\n")
|
builder.append(" }\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NeoProfileGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter) {
|
||||||
|
override fun getGeneratorName(): String {
|
||||||
|
return "NeoProfile-Generator"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateCode(codeGenObject: CodeGenObject): String {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
package io.neoterm.component.codegen.generators
|
|
||||||
|
|
||||||
import io.neoterm.component.codegen.CodeGenParameter
|
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenObject
|
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenerator
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class NeoProfileGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter) {
|
|
||||||
override fun getGeneratorName(): String {
|
|
||||||
return "NeoProfile-Generator"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun generateCode(codeGenObject: CodeGenObject): String {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,10 @@
|
|||||||
package io.neoterm.component.codegen.interfaces
|
package io.neoterm.component.codegen
|
||||||
|
|
||||||
import io.neoterm.component.codegen.CodeGenParameter
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
abstract class CodeGenerator(parameter: CodeGenParameter) {
|
abstract class CodeGenerator(parameter: CodeGenParameter) {
|
||||||
abstract fun getGeneratorName(): String
|
abstract fun getGeneratorName(): String
|
||||||
|
|
||||||
abstract fun generateCode(codeGenObject: CodeGenObject): String
|
abstract fun generateCode(codeGenObject: CodeGenObject): String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CodeGenObject {
|
||||||
|
fun getCodeGenerator(parameter: CodeGenParameter): CodeGenerator
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
package io.neoterm.component.codegen.interfaces
|
|
||||||
|
|
||||||
import io.neoterm.component.codegen.CodeGenParameter
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
interface CodeGenObject {
|
|
||||||
fun getCodeGenerator(parameter: CodeGenParameter): CodeGenerator
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package io.neoterm.component.colorscheme
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
object DefaultColorScheme : NeoColorScheme() {
|
|
||||||
init {
|
|
||||||
/* NOTE: Keep in sync with assets/colors/Default.nl */
|
|
||||||
colorName = "Default"
|
|
||||||
|
|
||||||
foregroundColor = "#ffffff"
|
|
||||||
backgroundColor = "#14181c"
|
|
||||||
cursorColor = "#a9aaa9"
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,20 +4,17 @@ import android.content.Context
|
|||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.App
|
import io.neoterm.App
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
|
import io.neoterm.component.ComponentManager
|
||||||
|
import io.neoterm.component.ConfigFileBasedComponent
|
||||||
import io.neoterm.component.codegen.CodeGenComponent
|
import io.neoterm.component.codegen.CodeGenComponent
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.component.config.NeoPreference
|
||||||
import io.neoterm.frontend.component.helper.ConfigFileBasedComponent
|
import io.neoterm.component.config.NeoTermPath
|
||||||
import io.neoterm.frontend.config.NeoPreference
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
|
|
||||||
import io.neoterm.utils.extractAssetsDir
|
import io.neoterm.utils.extractAssetsDir
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ColorSchemeComponent : ConfigFileBasedComponent<NeoColorScheme>(NeoTermPath.COLORS_PATH) {
|
class ColorSchemeComponent : ConfigFileBasedComponent<NeoColorScheme>(NeoTermPath.COLORS_PATH) {
|
||||||
companion object {
|
companion object {
|
||||||
fun colorFile(colorName: String): File {
|
fun colorFile(colorName: String): File {
|
||||||
@ -120,4 +117,5 @@ class ColorSchemeComponent : ConfigFileBasedComponent<NeoColorScheme>(NeoTermPat
|
|||||||
throw RuntimeException("Failed to save file ${colorFile.absolutePath}")
|
throw RuntimeException("Failed to save file ${colorFile.absolutePath}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,23 +3,15 @@ package io.neoterm.component.colorscheme
|
|||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.backend.TerminalColorScheme
|
import io.neoterm.backend.TerminalColorScheme
|
||||||
import io.neoterm.backend.TerminalColors
|
import io.neoterm.backend.TerminalColors
|
||||||
|
import io.neoterm.component.ConfigFileBasedObject
|
||||||
|
import io.neoterm.component.codegen.CodeGenObject
|
||||||
import io.neoterm.component.codegen.CodeGenParameter
|
import io.neoterm.component.codegen.CodeGenParameter
|
||||||
import io.neoterm.component.codegen.generators.NeoColorGenerator
|
import io.neoterm.component.codegen.CodeGenerator
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenObject
|
import io.neoterm.component.codegen.NeoColorGenerator
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenerator
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
import io.neoterm.component.config.ConfigureComponent
|
import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.utils.NLog
|
||||||
import io.neoterm.frontend.component.helper.ConfigFileBasedObject
|
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
|
||||||
import io.neoterm.frontend.logging.NLog
|
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
|
|
||||||
import org.jetbrains.annotations.TestOnly
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
open class NeoColorScheme : CodeGenObject, ConfigFileBasedObject {
|
open class NeoColorScheme : CodeGenObject, ConfigFileBasedObject {
|
||||||
companion object {
|
companion object {
|
||||||
const val COLOR_PREFIX = "color"
|
const val COLOR_PREFIX = "color"
|
||||||
@ -173,24 +165,15 @@ open class NeoColorScheme : CodeGenObject, ConfigFileBasedObject {
|
|||||||
private fun getColorByVisitor(visitor: ConfigVisitor, colorName: String): String? {
|
private fun getColorByVisitor(visitor: ConfigVisitor, colorName: String): String? {
|
||||||
return visitor.getStringValue(COLOR_PATH, colorName)
|
return visitor.getStringValue(COLOR_PATH, colorName)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestOnly
|
object DefaultColorScheme : NeoColorScheme() {
|
||||||
fun testLoadConfigure(file: File): Boolean {
|
init {
|
||||||
val loaderService = ComponentManager.getComponent<ConfigureComponent>()
|
/* NOTE: Keep in sync with assets/colors/Default.nl */
|
||||||
|
colorName = "Default"
|
||||||
|
|
||||||
val configure: NeoConfigureFile?
|
foregroundColor = "#ffffff"
|
||||||
try {
|
backgroundColor = "#14181c"
|
||||||
configure = loaderService.newLoader(file).loadConfigure()
|
cursorColor = "#a9aaa9"
|
||||||
if (configure == null) {
|
|
||||||
throw RuntimeException("Parse configuration failed.")
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
NLog.e("ExtraKey", "Failed to load extra key config: ${file.absolutePath}: ${e.localizedMessage}")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val visitor = configure.getVisitor()
|
|
||||||
onConfigLoaded(visitor)
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,13 @@
|
|||||||
package io.neoterm.frontend.component
|
package io.neoterm.component
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
/**
|
interface NeoComponent {
|
||||||
* @author kiva
|
fun onServiceInit()
|
||||||
*/
|
fun onServiceDestroy()
|
||||||
|
fun onServiceObtained()
|
||||||
|
}
|
||||||
|
|
||||||
object ComponentManager {
|
object ComponentManager {
|
||||||
private val COMPONENTS = ConcurrentHashMap<Class<out NeoComponent>, NeoComponent>()
|
private val COMPONENTS = ConcurrentHashMap<Class<out NeoComponent>, NeoComponent>()
|
||||||
|
|
||||||
@ -43,3 +46,7 @@ object ComponentManager {
|
|||||||
return componentInterface.newInstance()
|
return componentInterface.newInstance()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ComponentDuplicateException(serviceName: String) : RuntimeException("Service $serviceName duplicate")
|
||||||
|
class ComponentNotFoundException(serviceName: String) : RuntimeException("Component `$serviceName' not found")
|
||||||
|
|
@ -1,22 +0,0 @@
|
|||||||
package io.neoterm.component.completion
|
|
||||||
|
|
||||||
import io.neoterm.component.completion.provider.FileCompletionProvider
|
|
||||||
import io.neoterm.component.completion.provider.ProgramCompletionProvider
|
|
||||||
import io.neoterm.frontend.completion.CompletionManager
|
|
||||||
import io.neoterm.frontend.component.NeoComponent
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class CompletionComponent : NeoComponent {
|
|
||||||
override fun onServiceInit() {
|
|
||||||
CompletionManager.registerProvider(FileCompletionProvider())
|
|
||||||
CompletionManager.registerProvider(ProgramCompletionProvider())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceDestroy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceObtained() {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,20 @@
|
|||||||
package io.neoterm.frontend.completion
|
package io.neoterm.component.completion
|
||||||
|
|
||||||
import io.neoterm.frontend.completion.model.CompletionResult
|
import io.neoterm.component.NeoComponent
|
||||||
import io.neoterm.frontend.completion.provider.ICandidateProvider
|
|
||||||
|
class CompletionComponent : NeoComponent {
|
||||||
|
override fun onServiceInit() {
|
||||||
|
CompletionManager.registerProvider(FileCompletionProvider())
|
||||||
|
CompletionManager.registerProvider(ProgramCompletionProvider())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceDestroy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceObtained() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
object CompletionManager {
|
object CompletionManager {
|
||||||
private val candidateProviders = mutableMapOf<String, ICandidateProvider>()
|
private val candidateProviders = mutableMapOf<String, ICandidateProvider>()
|
||||||
|
|
||||||
@ -37,4 +46,23 @@ object CompletionManager {
|
|||||||
return ProviderDetector(candidateProviders.values
|
return ProviderDetector(candidateProviders.values
|
||||||
.takeWhile { it.canComplete(text) })
|
.takeWhile { it.canComplete(text) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ProviderDetector(val providers: List<ICandidateProvider>) : MarkScoreListener {
|
||||||
|
private var detectedProvider: ICandidateProvider? = null
|
||||||
|
|
||||||
|
override fun onMarkScore(score: Int) {
|
||||||
|
// TODO: Save provider score
|
||||||
|
}
|
||||||
|
|
||||||
|
fun detectBest(): ICandidateProvider? {
|
||||||
|
// TODO: detect best
|
||||||
|
detectedProvider = if (providers.isEmpty())
|
||||||
|
null
|
||||||
|
else
|
||||||
|
providers[0]
|
||||||
|
|
||||||
|
return detectedProvider
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
|||||||
package io.neoterm.frontend.completion.model
|
package io.neoterm.component.completion
|
||||||
|
|
||||||
import io.neoterm.frontend.completion.listener.MarkScoreListener
|
class CompletionCandidate(val completeString: String) {
|
||||||
|
var displayName: String = completeString
|
||||||
|
var description: String? = null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class CompletionResult(val candidates: List<CompletionCandidate>, var scoreMarker: MarkScoreListener) {
|
class CompletionResult(val candidates: List<CompletionCandidate>, var scoreMarker: MarkScoreListener) {
|
||||||
fun markScore(score: Int) {
|
fun markScore(score: Int) {
|
||||||
scoreMarker.onMarkScore(score)
|
scoreMarker.onMarkScore(score)
|
||||||
@ -13,4 +13,5 @@ class CompletionResult(val candidates: List<CompletionCandidate>, var scoreMarke
|
|||||||
fun hasResult(): Boolean {
|
fun hasResult(): Boolean {
|
||||||
return candidates.isNotEmpty()
|
return candidates.isNotEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
|||||||
|
package io.neoterm.component.completion
|
||||||
|
|
||||||
|
interface MarkScoreListener {
|
||||||
|
fun onMarkScore(score: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnAutoCompleteListener {
|
||||||
|
fun onCompletionRequired(newText: String?)
|
||||||
|
fun onKeyCode(keyCode: Int, keyMod: Int)
|
||||||
|
fun onCleanUp()
|
||||||
|
fun onFinishCompletion(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnCandidateSelectedListener {
|
||||||
|
fun onCandidateSelected(candidate: CompletionCandidate)
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
package io.neoterm.component.completion.provider
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ProgramCompletionProvider : FileCompletionProvider() {
|
|
||||||
override val providerName: String
|
|
||||||
get() = "NeoTermProvider.ProgramCompletionProvider"
|
|
||||||
|
|
||||||
|
|
||||||
override fun generateDesc(file: File): String? {
|
|
||||||
return if (file.canExecute()) "<Program>" else super.generateDesc(file)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +1,18 @@
|
|||||||
package io.neoterm.component.completion.provider
|
package io.neoterm.component.completion
|
||||||
|
|
||||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
|
||||||
import io.neoterm.frontend.completion.provider.ICandidateProvider
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
interface ICandidateProvider {
|
||||||
* @author kiva
|
val providerName: String
|
||||||
*/
|
fun provideCandidates(text: String): List<CompletionCandidate>
|
||||||
|
fun canComplete(text: String): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
open class FileCompletionProvider : ICandidateProvider {
|
open class FileCompletionProvider : ICandidateProvider {
|
||||||
override val providerName: String
|
override val providerName: String
|
||||||
get() = "NeoTermProvider.FileCompletionProvider"
|
get() = "NeoTermProvider.FileCompletionProvider"
|
||||||
|
|
||||||
override fun provideCandidates(text: String): List<CompletionCandidate>? {
|
override fun provideCandidates(text: String): List<CompletionCandidate> {
|
||||||
var file = File(text)
|
var file = File(text)
|
||||||
var filter: ((File) -> Boolean)? = null
|
var filter: ((File) -> Boolean)? = null
|
||||||
|
|
||||||
@ -33,20 +33,14 @@ open class FileCompletionProvider : ICandidateProvider {
|
|||||||
return if (filter != null) path.listFiles(filter) else path.listFiles()
|
return if (filter != null) path.listFiles(filter) else path.listFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateCandidateList(file: File, filter: ((File) -> Boolean)?): List<CompletionCandidate>? {
|
private fun generateCandidateList(file: File, filter: ((File) -> Boolean)?) =
|
||||||
if (file.canRead()) {
|
if (file.canRead()) listDirectory(file, filter).map {
|
||||||
val candidates = mutableListOf<CompletionCandidate>()
|
val candidate = CompletionCandidate(it.name)
|
||||||
listDirectory(file, filter)
|
candidate.description = generateDesc(it)
|
||||||
.mapTo(candidates, {
|
candidate.displayName = generateDisplayName(it)
|
||||||
val candidate = CompletionCandidate(it.name)
|
candidate
|
||||||
candidate.description = generateDesc(it)
|
}.toList()
|
||||||
candidate.displayName = generateDisplayName(it)
|
else listOf()
|
||||||
candidate
|
|
||||||
})
|
|
||||||
return candidates
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun generateDisplayName(file: File): String {
|
open fun generateDisplayName(file: File): String {
|
||||||
return if (file.isDirectory) "${file.name}/" else file.name
|
return if (file.isDirectory) "${file.name}/" else file.name
|
||||||
@ -56,3 +50,13 @@ open class FileCompletionProvider : ICandidateProvider {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ProgramCompletionProvider : FileCompletionProvider() {
|
||||||
|
override val providerName: String
|
||||||
|
get() = "NeoTermProvider.ProgramCompletionProvider"
|
||||||
|
|
||||||
|
|
||||||
|
override fun generateDesc(file: File): String? {
|
||||||
|
return if (file.canExecute()) "<Program>" else super.generateDesc(file)
|
||||||
|
}
|
||||||
|
}
|
@ -1,33 +0,0 @@
|
|||||||
package io.neoterm.component.config
|
|
||||||
|
|
||||||
import io.neoterm.component.config.loaders.NeoLangConfigureLoader
|
|
||||||
import io.neoterm.component.config.loaders.OldConfigureLoader
|
|
||||||
import io.neoterm.frontend.component.NeoComponent
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ConfigureComponent : NeoComponent {
|
|
||||||
val CONFIG_LOADER_VERSION = 20
|
|
||||||
|
|
||||||
override fun onServiceInit() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceDestroy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceObtained() {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLoaderVersion(): Int {
|
|
||||||
return CONFIG_LOADER_VERSION
|
|
||||||
}
|
|
||||||
|
|
||||||
fun newLoader(configFile: File): IConfigureLoader {
|
|
||||||
return when (configFile.extension) {
|
|
||||||
"nl" -> NeoLangConfigureLoader(configFile)
|
|
||||||
else -> OldConfigureLoader(configFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package io.neoterm.component.config
|
|
||||||
|
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
interface IConfigureLoader {
|
|
||||||
fun loadConfigure(): NeoConfigureFile?
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.config
|
package io.neoterm.component.config
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
@ -6,18 +6,59 @@ import android.preference.PreferenceManager
|
|||||||
import android.system.ErrnoException
|
import android.system.ErrnoException
|
||||||
import android.system.Os
|
import android.system.Os
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
import io.neolang.parser.NeoLangParser
|
||||||
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.App
|
import io.neoterm.App
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.frontend.logging.NLog
|
import io.neoterm.component.NeoComponent
|
||||||
import io.neoterm.services.NeoTermService
|
import io.neoterm.services.NeoTermService
|
||||||
|
import io.neoterm.utils.NLog
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
class ConfigureComponent : NeoComponent {
|
||||||
|
override fun onServiceInit() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
override fun onServiceDestroy() {
|
||||||
* @author kiva
|
}
|
||||||
*/
|
|
||||||
|
override fun onServiceObtained() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLoaderVersion(): Int {
|
||||||
|
return CONFIG_LOADER_VERSION
|
||||||
|
}
|
||||||
|
|
||||||
|
fun newLoader(configFile: File): IConfigureLoader {
|
||||||
|
return when (configFile.extension) {
|
||||||
|
"nl" -> NeoLangConfigureLoader(configFile)
|
||||||
|
else -> OldConfigureLoader(configFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val CONFIG_LOADER_VERSION = 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class NeoConfigureFile(val configureFile: File) {
|
||||||
|
private val configParser = NeoLangParser()
|
||||||
|
protected open var configVisitor: ConfigVisitor? = null
|
||||||
|
|
||||||
|
fun getVisitor() = configVisitor ?: throw IllegalStateException("Configure file not loaded or parse failed.")
|
||||||
|
|
||||||
|
open fun parseConfigure() = kotlin.runCatching {
|
||||||
|
val programCode = String(Files.readAllBytes(configureFile.toPath()))
|
||||||
|
configParser.setInputSource(programCode)
|
||||||
|
|
||||||
|
val ast = configParser.parse()
|
||||||
|
val astVisitor = ast.visit().getVisitor(ConfigVisitor::class.java) ?: return false
|
||||||
|
astVisitor.start()
|
||||||
|
configVisitor = astVisitor.getCallback()
|
||||||
|
}.isSuccess
|
||||||
|
}
|
||||||
|
|
||||||
object NeoPreference {
|
object NeoPreference {
|
||||||
const val KEY_HAPPY_EGG = "neoterm_fun_happy"
|
const val KEY_HAPPY_EGG = "neoterm_fun_happy"
|
@ -1,10 +1,28 @@
|
|||||||
package io.neoterm.frontend.config
|
package io.neoterm.component.config
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
|
||||||
/**
|
object DefaultValues {
|
||||||
* @author kiva
|
const val fontSize = 30
|
||||||
*/
|
|
||||||
|
const val enableBell = false
|
||||||
|
const val enableVibrate = false
|
||||||
|
const val enableExecveWrapper = true
|
||||||
|
const val enableAutoCompletion = false
|
||||||
|
const val enableFullScreen = false
|
||||||
|
const val enableAutoHideToolbar = false
|
||||||
|
const val enableSwitchNextTab = false
|
||||||
|
const val enableExtraKeys = true
|
||||||
|
const val enableExplicitExtraKeysWeight = false
|
||||||
|
const val enableBackButtonBeMappedToEscape = false
|
||||||
|
const val enableSpecialVolumeKeys = false
|
||||||
|
const val enableWordBasedIme = false
|
||||||
|
|
||||||
|
const val loginShell = "bash"
|
||||||
|
const val initialCommand = ""
|
||||||
|
const val defaultFont = "SourceCodePro"
|
||||||
|
}
|
||||||
|
|
||||||
object NeoTermPath {
|
object NeoTermPath {
|
||||||
@SuppressLint("SdCardPath")
|
@SuppressLint("SdCardPath")
|
||||||
const val ROOT_PATH = "/data/data/io.neoterm/files"
|
const val ROOT_PATH = "/data/data/io.neoterm/files"
|
||||||
@ -32,4 +50,4 @@ object NeoTermPath {
|
|||||||
init {
|
init {
|
||||||
DEFAULT_MAIN_PACKAGE_SOURCE = SOURCE
|
DEFAULT_MAIN_PACKAGE_SOURCE = SOURCE
|
||||||
}
|
}
|
||||||
}
|
}
|
194
app/src/main/java/io/neoterm/component/config/loaders.kt
Normal file
194
app/src/main/java/io/neoterm/component/config/loaders.kt
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
package io.neoterm.component.config
|
||||||
|
|
||||||
|
import io.neolang.runtime.type.NeoLangValue
|
||||||
|
import io.neolang.visitor.ConfigVisitor
|
||||||
|
import io.neoterm.component.colorscheme.NeoColorScheme
|
||||||
|
import io.neoterm.component.extrakey.NeoExtraKey
|
||||||
|
import io.neoterm.frontend.session.view.extrakey.TextButton
|
||||||
|
import io.neoterm.utils.NLog
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.FileReader
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
interface IConfigureLoader {
|
||||||
|
fun loadConfigure(): NeoConfigureFile?
|
||||||
|
}
|
||||||
|
|
||||||
|
class NeoLangConfigureLoader(private val configFile: File) : IConfigureLoader {
|
||||||
|
override fun loadConfigure(): NeoConfigureFile? {
|
||||||
|
val configureFile = NeoConfigureFile(configFile)
|
||||||
|
return if (configureFile.parseConfigure()) configureFile else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OldConfigureLoader(private val configFile: File) : IConfigureLoader {
|
||||||
|
override fun loadConfigure(): NeoConfigureFile? {
|
||||||
|
return when (configFile.extension) {
|
||||||
|
"eks" -> returnConfigure(OldExtraKeysConfigureFile(configFile))
|
||||||
|
"color" -> returnConfigure(OldColorSchemeConfigureFile(configFile))
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun returnConfigure(configureFile: NeoConfigureFile): NeoConfigureFile? {
|
||||||
|
return if (configureFile.parseConfigure()) configureFile else null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class OldColorSchemeConfigureFile(configureFile: File) : NeoConfigureFile(configureFile) {
|
||||||
|
override var configVisitor: ConfigVisitor? = null
|
||||||
|
|
||||||
|
override fun parseConfigure(): Boolean {
|
||||||
|
try {
|
||||||
|
val visitor = ConfigVisitor()
|
||||||
|
visitor.onStart()
|
||||||
|
visitor.onEnterContext(NeoColorScheme.CONTEXT_META_NAME)
|
||||||
|
|
||||||
|
visitor.getCurrentContext()
|
||||||
|
.defineAttribute(NeoColorScheme.COLOR_META_NAME, NeoLangValue(configureFile.nameWithoutExtension))
|
||||||
|
.defineAttribute(NeoColorScheme.COLOR_META_VERSION, NeoLangValue("1.0"))
|
||||||
|
|
||||||
|
visitor.onEnterContext(NeoColorScheme.CONTEXT_COLOR_NAME)
|
||||||
|
|
||||||
|
return FileInputStream(configureFile).use {
|
||||||
|
val prop = Properties()
|
||||||
|
prop.load(it)
|
||||||
|
prop.forEach {
|
||||||
|
visitor.getCurrentContext().defineAttribute(it.key as String, NeoLangValue(it.value as String))
|
||||||
|
}
|
||||||
|
visitor.onFinish()
|
||||||
|
this.configVisitor = visitor
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
this.configVisitor = null
|
||||||
|
NLog.e("ConfigureLoader", "Error while loading old config", e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configureFile) {
|
||||||
|
override var configVisitor: ConfigVisitor? = null
|
||||||
|
|
||||||
|
override fun parseConfigure(): Boolean {
|
||||||
|
try {
|
||||||
|
val config = parseOldConfig(BufferedReader(FileReader(configureFile)))
|
||||||
|
return generateVisitor(config)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
NLog.e("ConfigureLoader", "Failed to load old extra keys config: ${e.localizedMessage}")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateVisitor(config: NeoExtraKey): Boolean {
|
||||||
|
configVisitor = ConfigVisitor()
|
||||||
|
val visitor = configVisitor!!
|
||||||
|
visitor.onStart()
|
||||||
|
visitor.onEnterContext(NeoExtraKey.EKS_META_CONTEXT_NAME)
|
||||||
|
visitor.getCurrentContext()
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_VERSION, NeoLangValue(config.version))
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_WITH_DEFAULT, NeoLangValue(config.withDefaultKeys))
|
||||||
|
|
||||||
|
// program
|
||||||
|
visitor.onEnterContext(NeoExtraKey.EKS_META_PROGRAM)
|
||||||
|
config.programNames.forEachIndexed { index, program ->
|
||||||
|
visitor.getCurrentContext().defineAttribute(index.toString(), NeoLangValue(program))
|
||||||
|
}
|
||||||
|
visitor.onExitContext()
|
||||||
|
|
||||||
|
// key
|
||||||
|
visitor.onEnterContext(NeoExtraKey.EKS_META_KEY)
|
||||||
|
config.shortcutKeys.forEachIndexed { index, button ->
|
||||||
|
if (button is TextButton) {
|
||||||
|
visitor.onEnterContext(index.toString())
|
||||||
|
visitor.getCurrentContext()
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_WITH_ENTER, NeoLangValue(button.withEnter))
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_DISPLAY, NeoLangValue(button.buttonKeys!!))
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_CODE, NeoLangValue(button.buttonKeys!!))
|
||||||
|
visitor.onExitContext()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visitor.onExitContext()
|
||||||
|
|
||||||
|
visitor.onFinish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseOldConfig(source: BufferedReader): NeoExtraKey {
|
||||||
|
val config = NeoExtraKey()
|
||||||
|
var line: String? = source.readLine()
|
||||||
|
|
||||||
|
while (line != null) {
|
||||||
|
line = line.trim().trimEnd()
|
||||||
|
if (line.isEmpty() || line.startsWith("#")) {
|
||||||
|
line = source.readLine()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.startsWith(NeoExtraKey.EKS_META_VERSION)) {
|
||||||
|
parseHeader(line, config)
|
||||||
|
} else if (line.startsWith(NeoExtraKey.EKS_META_PROGRAM)) {
|
||||||
|
parseProgram(line, config)
|
||||||
|
} else if (line.startsWith("define")) {
|
||||||
|
parseKeyDefine(line, config)
|
||||||
|
} else if (line.startsWith(NeoExtraKey.EKS_META_WITH_DEFAULT)) {
|
||||||
|
parseWithDefault(line, config)
|
||||||
|
}
|
||||||
|
line = source.readLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.version < 0) {
|
||||||
|
throw RuntimeException("Not a valid shortcut config file")
|
||||||
|
}
|
||||||
|
if (config.programNames.size == 0) {
|
||||||
|
throw RuntimeException("At least one program name should be given")
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseWithDefault(line: String, config: NeoExtraKey) {
|
||||||
|
val value = line.substring(NeoExtraKey.EKS_META_WITH_DEFAULT.length).trim().trimEnd()
|
||||||
|
config.withDefaultKeys = value == "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseKeyDefine(line: String, config: NeoExtraKey) {
|
||||||
|
val keyDefine = line.substring("define".length).trim().trimEnd()
|
||||||
|
val keyValues = keyDefine.split(" ")
|
||||||
|
if (keyValues.size < 2) {
|
||||||
|
throw RuntimeException("Bad define")
|
||||||
|
}
|
||||||
|
|
||||||
|
val buttonText = keyValues[0]
|
||||||
|
val withEnter = keyValues[1] == "true"
|
||||||
|
|
||||||
|
config.shortcutKeys.add(TextButton(buttonText, withEnter))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseProgram(line: String, config: NeoExtraKey) {
|
||||||
|
val programNames = line.substring(NeoExtraKey.EKS_META_PROGRAM.length).trim().trimEnd()
|
||||||
|
if (programNames.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (name in programNames.split(" ")) {
|
||||||
|
config.programNames.add(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseHeader(line: String, config: NeoExtraKey) {
|
||||||
|
val version: Int
|
||||||
|
val versionString = line.substring(NeoExtraKey.EKS_META_VERSION.length).trim().trimEnd()
|
||||||
|
try {
|
||||||
|
version = Integer.parseInt(versionString)
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
throw RuntimeException("Bad version '$versionString'")
|
||||||
|
}
|
||||||
|
|
||||||
|
config.version = version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
package io.neoterm.component.config.loaders
|
|
||||||
|
|
||||||
import io.neoterm.component.config.IConfigureLoader
|
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class NeoLangConfigureLoader(private val configFile: File) : IConfigureLoader {
|
|
||||||
override fun loadConfigure(): NeoConfigureFile? {
|
|
||||||
val configureFile = NeoConfigureFile(configFile)
|
|
||||||
return if (configureFile.parseConfigure()) configureFile else null
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package io.neoterm.component.config.loaders
|
|
||||||
|
|
||||||
import io.neolang.runtime.type.NeoLangValue
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
|
||||||
import io.neoterm.component.colorscheme.NeoColorScheme
|
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
|
||||||
import io.neoterm.frontend.logging.NLog
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class OldColorSchemeConfigureFile(configureFile: File) : NeoConfigureFile(configureFile) {
|
|
||||||
override var configVisitor: ConfigVisitor? = null
|
|
||||||
|
|
||||||
override fun parseConfigure(): Boolean {
|
|
||||||
try {
|
|
||||||
val visitor = ConfigVisitor()
|
|
||||||
visitor.onStart()
|
|
||||||
visitor.onEnterContext(NeoColorScheme.CONTEXT_META_NAME)
|
|
||||||
|
|
||||||
visitor.getCurrentContext()
|
|
||||||
.defineAttribute(NeoColorScheme.COLOR_META_NAME, NeoLangValue(configureFile.nameWithoutExtension))
|
|
||||||
.defineAttribute(NeoColorScheme.COLOR_META_VERSION, NeoLangValue("1.0"))
|
|
||||||
|
|
||||||
visitor.onEnterContext(NeoColorScheme.CONTEXT_COLOR_NAME)
|
|
||||||
|
|
||||||
return FileInputStream(configureFile).use {
|
|
||||||
val prop = Properties()
|
|
||||||
prop.load(it)
|
|
||||||
prop.forEach {
|
|
||||||
visitor.getCurrentContext().defineAttribute(it.key as String, NeoLangValue(it.value as String))
|
|
||||||
}
|
|
||||||
visitor.onFinish()
|
|
||||||
this.configVisitor = visitor
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e: Exception) {
|
|
||||||
this.configVisitor = null
|
|
||||||
NLog.e("ConfigureLoader", "Error while loading old config", e)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package io.neoterm.component.config.loaders
|
|
||||||
|
|
||||||
import io.neoterm.component.config.IConfigureLoader
|
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class OldConfigureLoader(private val configFile: File) : IConfigureLoader {
|
|
||||||
override fun loadConfigure(): NeoConfigureFile? {
|
|
||||||
return when (configFile.extension) {
|
|
||||||
"eks" -> returnConfigure(OldExtraKeysConfigureFile(configFile))
|
|
||||||
"color" -> returnConfigure(OldColorSchemeConfigureFile(configFile))
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun returnConfigure(configureFile: NeoConfigureFile): NeoConfigureFile? {
|
|
||||||
return if (configureFile.parseConfigure()) configureFile else null
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,135 +0,0 @@
|
|||||||
package io.neoterm.component.config.loaders
|
|
||||||
|
|
||||||
import io.neolang.runtime.type.NeoLangValue
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
|
||||||
import io.neoterm.component.extrakey.NeoExtraKey
|
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
|
||||||
import io.neoterm.frontend.logging.NLog
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.button.TextButton
|
|
||||||
import java.io.BufferedReader
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileReader
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configureFile) {
|
|
||||||
override var configVisitor: ConfigVisitor? = null
|
|
||||||
|
|
||||||
override fun parseConfigure(): Boolean {
|
|
||||||
try {
|
|
||||||
val config = parseOldConfig(BufferedReader(FileReader(configureFile)))
|
|
||||||
return generateVisitor(config)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
NLog.e("ConfigureLoader", "Failed to load old extra keys config: ${e.localizedMessage}")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateVisitor(config: NeoExtraKey): Boolean {
|
|
||||||
configVisitor = ConfigVisitor()
|
|
||||||
val visitor = configVisitor!!
|
|
||||||
visitor.onStart()
|
|
||||||
visitor.onEnterContext(NeoExtraKey.EKS_META_CONTEXT_NAME)
|
|
||||||
visitor.getCurrentContext()
|
|
||||||
.defineAttribute(NeoExtraKey.EKS_META_VERSION, NeoLangValue(config.version))
|
|
||||||
.defineAttribute(NeoExtraKey.EKS_META_WITH_DEFAULT, NeoLangValue(config.withDefaultKeys))
|
|
||||||
|
|
||||||
// program
|
|
||||||
visitor.onEnterContext(NeoExtraKey.EKS_META_PROGRAM)
|
|
||||||
config.programNames.forEachIndexed { index, program ->
|
|
||||||
visitor.getCurrentContext().defineAttribute(index.toString(), NeoLangValue(program))
|
|
||||||
}
|
|
||||||
visitor.onExitContext()
|
|
||||||
|
|
||||||
// key
|
|
||||||
visitor.onEnterContext(NeoExtraKey.EKS_META_KEY)
|
|
||||||
config.shortcutKeys.forEachIndexed { index, button ->
|
|
||||||
if (button is TextButton) {
|
|
||||||
visitor.onEnterContext(index.toString())
|
|
||||||
visitor.getCurrentContext()
|
|
||||||
.defineAttribute(NeoExtraKey.EKS_META_WITH_ENTER, NeoLangValue(button.withEnter))
|
|
||||||
.defineAttribute(NeoExtraKey.EKS_META_DISPLAY, NeoLangValue(button.buttonKeys!!))
|
|
||||||
.defineAttribute(NeoExtraKey.EKS_META_CODE, NeoLangValue(button.buttonKeys!!))
|
|
||||||
visitor.onExitContext()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visitor.onExitContext()
|
|
||||||
|
|
||||||
visitor.onFinish()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseOldConfig(source: BufferedReader): NeoExtraKey {
|
|
||||||
val config = NeoExtraKey()
|
|
||||||
var line: String? = source.readLine()
|
|
||||||
|
|
||||||
while (line != null) {
|
|
||||||
line = line.trim().trimEnd()
|
|
||||||
if (line.isEmpty() || line.startsWith("#")) {
|
|
||||||
line = source.readLine()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.startsWith(NeoExtraKey.EKS_META_VERSION)) {
|
|
||||||
parseHeader(line, config)
|
|
||||||
} else if (line.startsWith(NeoExtraKey.EKS_META_PROGRAM)) {
|
|
||||||
parseProgram(line, config)
|
|
||||||
} else if (line.startsWith("define")) {
|
|
||||||
parseKeyDefine(line, config)
|
|
||||||
} else if (line.startsWith(NeoExtraKey.EKS_META_WITH_DEFAULT)) {
|
|
||||||
parseWithDefault(line, config)
|
|
||||||
}
|
|
||||||
line = source.readLine()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.version < 0) {
|
|
||||||
throw RuntimeException("Not a valid shortcut config file")
|
|
||||||
}
|
|
||||||
if (config.programNames.size == 0) {
|
|
||||||
throw RuntimeException("At least one program name should be given")
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseWithDefault(line: String, config: NeoExtraKey) {
|
|
||||||
val value = line.substring(NeoExtraKey.EKS_META_WITH_DEFAULT.length).trim().trimEnd()
|
|
||||||
config.withDefaultKeys = value == "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseKeyDefine(line: String, config: NeoExtraKey) {
|
|
||||||
val keyDefine = line.substring("define".length).trim().trimEnd()
|
|
||||||
val keyValues = keyDefine.split(" ")
|
|
||||||
if (keyValues.size < 2) {
|
|
||||||
throw RuntimeException("Bad define")
|
|
||||||
}
|
|
||||||
|
|
||||||
val buttonText = keyValues[0]
|
|
||||||
val withEnter = keyValues[1] == "true"
|
|
||||||
|
|
||||||
config.shortcutKeys.add(TextButton(buttonText, withEnter))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseProgram(line: String, config: NeoExtraKey) {
|
|
||||||
val programNames = line.substring(NeoExtraKey.EKS_META_PROGRAM.length).trim().trimEnd()
|
|
||||||
if (programNames.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (name in programNames.split(" ")) {
|
|
||||||
config.programNames.add(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseHeader(line: String, config: NeoExtraKey) {
|
|
||||||
val version: Int
|
|
||||||
val versionString = line.substring(NeoExtraKey.EKS_META_VERSION.length).trim().trimEnd()
|
|
||||||
try {
|
|
||||||
version = Integer.parseInt(versionString)
|
|
||||||
} catch (e: NumberFormatException) {
|
|
||||||
throw RuntimeException("Bad version '$versionString'")
|
|
||||||
}
|
|
||||||
|
|
||||||
config.version = version
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +1,16 @@
|
|||||||
package io.neoterm.frontend.component.helper
|
package io.neoterm.component
|
||||||
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.component.config.ConfigureComponent
|
import io.neoterm.component.config.ConfigureComponent
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.utils.NLog
|
||||||
import io.neoterm.frontend.component.NeoComponent
|
|
||||||
import io.neoterm.frontend.logging.NLog
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileFilter
|
import java.io.FileFilter
|
||||||
|
|
||||||
/**
|
interface ConfigFileBasedObject {
|
||||||
* @author kiva
|
@Throws(RuntimeException::class)
|
||||||
*/
|
fun onConfigLoaded(configVisitor: ConfigVisitor)
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ConfigFileBasedComponent<out T : ConfigFileBasedObject>(protected val baseDir: String) : NeoComponent {
|
abstract class ConfigFileBasedComponent<out T : ConfigFileBasedObject>(protected val baseDir: String) : NeoComponent {
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = ConfigFileBasedComponent::class.java.simpleName
|
private val TAG = ConfigFileBasedComponent::class.java.simpleName
|
||||||
@ -60,4 +60,5 @@ abstract class ConfigFileBasedComponent<out T : ConfigFileBasedObject>(protected
|
|||||||
abstract fun onCheckComponentFiles()
|
abstract fun onCheckComponentFiles()
|
||||||
|
|
||||||
abstract fun onCreateComponentObject(configVisitor: ConfigVisitor): T
|
abstract fun onCreateComponentObject(configVisitor: ConfigVisitor): T
|
||||||
}
|
}
|
||||||
|
|
@ -3,16 +3,13 @@ package io.neoterm.component.extrakey
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.App
|
import io.neoterm.App
|
||||||
import io.neoterm.frontend.component.helper.ConfigFileBasedComponent
|
import io.neoterm.component.ConfigFileBasedComponent
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
import io.neoterm.component.config.NeoTermPath
|
||||||
import io.neoterm.frontend.logging.NLog
|
import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
|
||||||
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
|
import io.neoterm.utils.NLog
|
||||||
import io.neoterm.utils.extractAssetsDir
|
import io.neoterm.utils.extractAssetsDir
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ExtraKeyComponent : ConfigFileBasedComponent<NeoExtraKey>(NeoTermPath.EKS_PATH) {
|
class ExtraKeyComponent : ConfigFileBasedComponent<NeoExtraKey>(NeoTermPath.EKS_PATH) {
|
||||||
override val checkComponentFileWhenObtained
|
override val checkComponentFileWhenObtained
|
||||||
get() = true
|
get() = true
|
||||||
@ -68,4 +65,4 @@ class ExtraKeyComponent : ConfigFileBasedComponent<NeoExtraKey>(NeoTermPath.EKS_
|
|||||||
registerShortcutKeys(it)
|
registerShortcutKeys(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,10 @@
|
|||||||
package io.neoterm.component.extrakey
|
package io.neoterm.component.extrakey
|
||||||
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.component.config.ConfigureComponent
|
import io.neoterm.component.ConfigFileBasedObject
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
|
||||||
import io.neoterm.frontend.component.helper.ConfigFileBasedObject
|
import io.neoterm.frontend.session.view.extrakey.IExtraButton
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
import io.neoterm.frontend.session.view.extrakey.TextButton
|
||||||
import io.neoterm.frontend.logging.NLog
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.button.IExtraButton
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.button.TextButton
|
|
||||||
import org.jetbrains.annotations.TestOnly
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
@ -86,24 +80,4 @@ class NeoExtraKey : ConfigFileBasedObject {
|
|||||||
private fun getMetaByVisitor(visitor: ConfigVisitor, metaName: String): String? {
|
private fun getMetaByVisitor(visitor: ConfigVisitor, metaName: String): String? {
|
||||||
return visitor.getStringValue(EKS_META_CONTEXT_PATH, metaName)
|
return visitor.getStringValue(EKS_META_CONTEXT_PATH, metaName)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@TestOnly
|
|
||||||
fun testLoadConfigure(file: File): Boolean {
|
|
||||||
val loaderService = ComponentManager.getComponent<ConfigureComponent>()
|
|
||||||
|
|
||||||
val configure: NeoConfigureFile?
|
|
||||||
try {
|
|
||||||
configure = loaderService.newLoader(file).loadConfigure()
|
|
||||||
if (configure == null) {
|
|
||||||
throw RuntimeException("Parse configuration failed.")
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
NLog.e("ExtraKey", "Failed to load extra key config: ${file.absolutePath}: ${e.localizedMessage}")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val visitor = configure.getVisitor()
|
|
||||||
onConfigLoaded(visitor)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,18 +4,15 @@ import android.content.Context
|
|||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import io.neoterm.App
|
import io.neoterm.App
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.frontend.component.NeoComponent
|
import io.neoterm.component.NeoComponent
|
||||||
import io.neoterm.frontend.config.DefaultValues
|
import io.neoterm.component.config.DefaultValues
|
||||||
import io.neoterm.frontend.config.NeoPreference
|
import io.neoterm.component.config.NeoPreference
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
import io.neoterm.component.config.NeoTermPath
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
|
import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
|
||||||
import io.neoterm.utils.extractAssetsDir
|
import io.neoterm.utils.extractAssetsDir
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class FontComponent : NeoComponent {
|
class FontComponent : NeoComponent {
|
||||||
private lateinit var DEFAULT_FONT: NeoFont
|
private lateinit var DEFAULT_FONT: NeoFont
|
||||||
private lateinit var fonts: MutableMap<String, NeoFont>
|
private lateinit var fonts: MutableMap<String, NeoFont>
|
||||||
@ -126,4 +123,5 @@ class FontComponent : NeoComponent {
|
|||||||
fonts.put(defaultFont, DEFAULT_FONT)
|
fonts.put(defaultFont, DEFAULT_FONT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,10 @@
|
|||||||
package io.neoterm.component.font
|
package io.neoterm.component.font
|
||||||
|
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
|
import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class NeoFont {
|
class NeoFont {
|
||||||
private var fontFile: File? = null
|
private var fontFile: File? = null
|
||||||
private var typeface: Typeface? = null
|
private var typeface: Typeface? = null
|
||||||
@ -36,4 +33,4 @@ class NeoFont {
|
|||||||
}
|
}
|
||||||
return typeface
|
return typeface
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,21 +0,0 @@
|
|||||||
package io.neoterm.component.pm
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum class Architecture {
|
|
||||||
ALL, ARM, AARCH64, X86, X86_64;
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun parse(arch: String): Architecture {
|
|
||||||
return when (arch) {
|
|
||||||
"arm" -> ARM
|
|
||||||
"aarch64" -> AARCH64
|
|
||||||
"x86" -> X86
|
|
||||||
"x86_64" -> X86_64
|
|
||||||
else -> ALL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
package io.neoterm.component.pm;
|
package io.neoterm.component.pm;
|
||||||
|
|
||||||
import io.neoterm.frontend.component.NeoComponent;
|
import io.neoterm.component.NeoComponent;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package io.neoterm.component.pm
|
|
||||||
|
|
||||||
import io.neoterm.App
|
|
||||||
import io.neoterm.R
|
|
||||||
import io.neoterm.framework.NeoTermDatabase
|
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class SourceManager internal constructor() {
|
|
||||||
private val database = NeoTermDatabase.instance("sources")
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (database.findAll<Source>(Source::class.java).isEmpty()) {
|
|
||||||
App.get().resources.getStringArray(R.array.pref_package_source_values)
|
|
||||||
.forEach {
|
|
||||||
database.saveBean(Source(it, "stable main", true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addSource(sourceUrl: String, repo: String, enabled: Boolean) {
|
|
||||||
database.saveBean(Source(sourceUrl, repo, enabled))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeSource(sourceUrl: String) {
|
|
||||||
database.deleteBeanByWhere(Source::class.java, "url == '$sourceUrl'")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateAll(sources: List<Source>) {
|
|
||||||
database.dropAllTable()
|
|
||||||
database.saveBeans(sources)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAllSources(): List<Source> {
|
|
||||||
return database.findAll<Source>(Source::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getEnabledSources(): List<Source> {
|
|
||||||
return getAllSources().filter { it.enabled }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMainPackageSource(): String {
|
|
||||||
return getEnabledSources()
|
|
||||||
.map { it.repo }
|
|
||||||
.singleOrNull { it.trim() == "stable main" }
|
|
||||||
?: NeoTermPath.DEFAULT_MAIN_PACKAGE_SOURCE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun applyChanges() {
|
|
||||||
database.vacuum()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,20 @@
|
|||||||
package io.neoterm.component.pm
|
package io.neoterm.component.pm
|
||||||
|
|
||||||
/**
|
enum class Architecture {
|
||||||
* @author kiva
|
ALL, ARM, AARCH64, X86, X86_64;
|
||||||
*/
|
|
||||||
|
companion object {
|
||||||
|
fun parse(arch: String): Architecture {
|
||||||
|
return when (arch) {
|
||||||
|
"arm" -> ARM
|
||||||
|
"aarch64" -> AARCH64
|
||||||
|
"x86" -> X86
|
||||||
|
"x86_64" -> X86_64
|
||||||
|
else -> ALL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class NeoPackageInfo {
|
class NeoPackageInfo {
|
||||||
var packageName: String? = null
|
var packageName: String? = null
|
||||||
@ -21,4 +33,3 @@ class NeoPackageInfo {
|
|||||||
var homePage: String? = null
|
var homePage: String? = null
|
||||||
var description: String? = null
|
var description: String? = null
|
||||||
}
|
}
|
||||||
|
|
@ -1,16 +1,16 @@
|
|||||||
package io.neoterm.component.pm
|
package io.neoterm.component.pm
|
||||||
|
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.App
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
import io.neoterm.R
|
||||||
import io.neoterm.frontend.logging.NLog
|
import io.neoterm.component.ComponentManager
|
||||||
|
import io.neoterm.component.config.NeoTermPath
|
||||||
|
import io.neoterm.framework.NeoTermDatabase
|
||||||
|
import io.neoterm.utils.NLog
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
object SourceHelper {
|
object SourceHelper {
|
||||||
fun syncSource() {
|
fun syncSource() {
|
||||||
val sourceManager = ComponentManager.getComponent<PackageComponent>().sourceManager
|
val sourceManager = ComponentManager.getComponent<PackageComponent>().sourceManager
|
||||||
@ -71,4 +71,50 @@ object SourceHelper {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SourceManager internal constructor() {
|
||||||
|
private val database = NeoTermDatabase.instance("sources")
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (database.findAll<Source>(Source::class.java).isEmpty()) {
|
||||||
|
App.get().resources.getStringArray(R.array.pref_package_source_values)
|
||||||
|
.forEach {
|
||||||
|
database.saveBean(Source(it, "stable main", true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addSource(sourceUrl: String, repo: String, enabled: Boolean) {
|
||||||
|
database.saveBean(Source(sourceUrl, repo, enabled))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeSource(sourceUrl: String) {
|
||||||
|
database.deleteBeanByWhere(Source::class.java, "url == '$sourceUrl'")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateAll(sources: List<Source>) {
|
||||||
|
database.dropAllTable()
|
||||||
|
database.saveBeans(sources)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllSources(): List<Source> {
|
||||||
|
return database.findAll(Source::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getEnabledSources(): List<Source> {
|
||||||
|
return getAllSources().filter { it.enabled }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMainPackageSource(): String {
|
||||||
|
return getEnabledSources()
|
||||||
|
.map { it.repo }
|
||||||
|
.singleOrNull { it.trim() == "stable main" }
|
||||||
|
?: NeoTermPath.DEFAULT_MAIN_PACKAGE_SOURCE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyChanges() {
|
||||||
|
database.vacuum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,11 @@
|
|||||||
package io.neoterm.component.profile
|
package io.neoterm.component.profile
|
||||||
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.frontend.component.helper.ConfigFileBasedComponent
|
import io.neoterm.component.ConfigFileBasedComponent
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
import io.neoterm.component.config.NeoTermPath
|
||||||
import io.neoterm.frontend.logging.NLog
|
import io.neoterm.utils.NLog
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ProfileComponent : ConfigFileBasedComponent<NeoProfile>(NeoTermPath.PROFILE_PATH) {
|
class ProfileComponent : ConfigFileBasedComponent<NeoProfile>(NeoTermPath.PROFILE_PATH) {
|
||||||
override val checkComponentFileWhenObtained
|
override val checkComponentFileWhenObtained
|
||||||
get() = true
|
get() = true
|
||||||
@ -63,4 +60,4 @@ class ProfileComponent : ConfigFileBasedComponent<NeoProfile>(NeoTermPath.PROFIL
|
|||||||
fun unregisterProfile(metaName: String) {
|
fun unregisterProfile(metaName: String) {
|
||||||
profileRegistry.remove(metaName)
|
profileRegistry.remove(metaName)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,21 +1,18 @@
|
|||||||
package io.neoterm.component.profile
|
package io.neoterm.component.profile
|
||||||
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neolang.visitor.ConfigVisitor
|
||||||
|
import io.neoterm.component.ComponentManager
|
||||||
|
import io.neoterm.component.ConfigFileBasedObject
|
||||||
|
import io.neoterm.component.codegen.CodeGenObject
|
||||||
import io.neoterm.component.codegen.CodeGenParameter
|
import io.neoterm.component.codegen.CodeGenParameter
|
||||||
import io.neoterm.component.codegen.generators.NeoProfileGenerator
|
import io.neoterm.component.codegen.CodeGenerator
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenObject
|
import io.neoterm.component.codegen.NeoProfileGenerator
|
||||||
import io.neoterm.component.codegen.interfaces.CodeGenerator
|
|
||||||
import io.neoterm.component.config.ConfigureComponent
|
import io.neoterm.component.config.ConfigureComponent
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.component.config.NeoConfigureFile
|
||||||
import io.neoterm.frontend.component.helper.ConfigFileBasedObject
|
import io.neoterm.utils.NLog
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
|
||||||
import io.neoterm.frontend.logging.NLog
|
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
abstract class NeoProfile : CodeGenObject, ConfigFileBasedObject {
|
abstract class NeoProfile : CodeGenObject, ConfigFileBasedObject {
|
||||||
companion object {
|
companion object {
|
||||||
private const val PROFILE_NAME = "name"
|
private const val PROFILE_NAME = "name"
|
||||||
@ -70,4 +67,4 @@ abstract class NeoProfile : CodeGenObject, ConfigFileBasedObject {
|
|||||||
protected fun ConfigVisitor.getProfileBoolean(key: String): Boolean? {
|
protected fun ConfigVisitor.getProfileBoolean(key: String): Boolean? {
|
||||||
return this.getBooleanValue(profileMetaPath, key)
|
return this.getBooleanValue(profileMetaPath, key)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,18 +4,10 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import io.neoterm.Globals
|
import io.neoterm.Globals
|
||||||
import io.neoterm.frontend.component.NeoComponent
|
import io.neoterm.component.NeoComponent
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
import io.neoterm.component.config.NeoTermPath
|
||||||
import io.neoterm.frontend.logging.NLog
|
import io.neoterm.utils.NLog
|
||||||
import io.neoterm.frontend.session.shell.ShellParameter
|
|
||||||
import io.neoterm.frontend.session.shell.ShellTermSession
|
|
||||||
import io.neoterm.frontend.session.xorg.XParameter
|
|
||||||
import io.neoterm.frontend.session.xorg.XSession
|
|
||||||
import io.neoterm.frontend.session.xorg.client.XSessionData
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class SessionComponent : NeoComponent {
|
class SessionComponent : NeoComponent {
|
||||||
companion object {
|
companion object {
|
||||||
private var IS_LIBRARIES_LOADED = false
|
private var IS_LIBRARIES_LOADED = false
|
||||||
@ -50,7 +42,7 @@ class SessionComponent : NeoComponent {
|
|||||||
} catch (error: UnsatisfiedLinkError) {
|
} catch (error: UnsatisfiedLinkError) {
|
||||||
NLog.e(
|
NLog.e(
|
||||||
"SessionComponent", "Error loading lib " + soPath
|
"SessionComponent", "Error loading lib " + soPath
|
||||||
+ ", reason: " + error.localizedMessage
|
+ ", reason: " + error.localizedMessage
|
||||||
)
|
)
|
||||||
result = false
|
result = false
|
||||||
}
|
}
|
||||||
@ -109,4 +101,4 @@ class SessionComponent : NeoComponent {
|
|||||||
.profile(parameter.shellProfile)
|
.profile(parameter.shellProfile)
|
||||||
.create(context)
|
.create(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,163 @@
|
|||||||
package io.neoterm.frontend.session.shell
|
package io.neoterm.component.session
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.App
|
import io.neoterm.App
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
import io.neoterm.bridge.SessionId
|
||||||
import io.neoterm.frontend.session.shell.client.TermSessionCallback
|
import io.neoterm.component.ComponentManager
|
||||||
|
import io.neoterm.component.colorscheme.ColorSchemeComponent
|
||||||
|
import io.neoterm.component.config.DefaultValues
|
||||||
|
import io.neoterm.component.config.NeoPreference
|
||||||
|
import io.neoterm.component.config.NeoTermPath
|
||||||
|
import io.neoterm.component.font.FontComponent
|
||||||
|
import io.neoterm.component.profile.NeoProfile
|
||||||
|
import io.neoterm.frontend.session.terminal.TermSessionCallback
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
class ShellParameter {
|
||||||
|
var sessionId: SessionId? = null
|
||||||
|
var executablePath: String? = null
|
||||||
|
var arguments: Array<String>? = null
|
||||||
|
var cwd: String? = null
|
||||||
|
var initialCommand: String? = null
|
||||||
|
var env: Array<Pair<String, String>>? = null
|
||||||
|
var sessionCallback: TerminalSession.SessionChangedCallback? = null
|
||||||
|
var systemShell: Boolean = false
|
||||||
|
var shellProfile: ShellProfile? = null
|
||||||
|
|
||||||
|
fun executablePath(executablePath: String?): ShellParameter {
|
||||||
|
this.executablePath = executablePath
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun arguments(arguments: Array<String>?): ShellParameter {
|
||||||
|
this.arguments = arguments
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun currentWorkingDirectory(cwd: String?): ShellParameter {
|
||||||
|
this.cwd = cwd
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun initialCommand(initialCommand: String?): ShellParameter {
|
||||||
|
this.initialCommand = initialCommand
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun environment(env: Array<Pair<String, String>>?): ShellParameter {
|
||||||
|
this.env = env
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun callback(callback: TerminalSession.SessionChangedCallback?): ShellParameter {
|
||||||
|
this.sessionCallback = callback
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun systemShell(systemShell: Boolean): ShellParameter {
|
||||||
|
this.systemShell = systemShell
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun profile(shellProfile: ShellProfile): ShellParameter {
|
||||||
|
this.shellProfile = shellProfile
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun session(sessionId: SessionId?): ShellParameter {
|
||||||
|
this.sessionId = sessionId
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun willCreateNewSession(): Boolean {
|
||||||
|
return sessionId?.equals(SessionId.NEW_SESSION) ?: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
class ShellProfile : NeoProfile() {
|
||||||
|
companion object {
|
||||||
|
const val PROFILE_META_NAME = "profile-shell"
|
||||||
|
|
||||||
|
private const val LOGIN_SHELL = "login-shell"
|
||||||
|
private const val INITIAL_COMMAND = "init-command"
|
||||||
|
private const val BELL = "bell"
|
||||||
|
private const val VIBRATE = "vibrate"
|
||||||
|
private const val EXECVE_WRAPPER = "execve-wrapper"
|
||||||
|
private const val SPECIAL_VOLUME_KEYS = "special-volume-keys"
|
||||||
|
private const val AUTO_COMPLETION = "auto-completion"
|
||||||
|
private const val BACK_KEY_TO_ESC = "back-key-esc"
|
||||||
|
private const val EXTRA_KEYS = "extra-keys"
|
||||||
|
private const val FONT = "font"
|
||||||
|
private const val COLOR_SCHEME = "color-scheme"
|
||||||
|
private const val WORD_BASED_IME = "word-based-ime"
|
||||||
|
|
||||||
|
fun create(): ShellProfile {
|
||||||
|
return ShellProfile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val profileMetaName = PROFILE_META_NAME
|
||||||
|
|
||||||
|
var loginShell = DefaultValues.loginShell
|
||||||
|
var initialCommand = DefaultValues.initialCommand
|
||||||
|
|
||||||
|
var enableBell = DefaultValues.enableBell
|
||||||
|
var enableVibrate = DefaultValues.enableVibrate
|
||||||
|
var enableExecveWrapper = DefaultValues.enableExecveWrapper
|
||||||
|
var enableSpecialVolumeKeys = DefaultValues.enableSpecialVolumeKeys
|
||||||
|
var enableAutoCompletion = DefaultValues.enableAutoCompletion
|
||||||
|
var enableBackKeyToEscape = DefaultValues.enableBackButtonBeMappedToEscape
|
||||||
|
var enableExtraKeys = DefaultValues.enableExtraKeys
|
||||||
|
var enableWordBasedIme = DefaultValues.enableWordBasedIme
|
||||||
|
|
||||||
|
var profileFont: String
|
||||||
|
var profileColorScheme: String
|
||||||
|
|
||||||
|
init {
|
||||||
|
val fontComp = ComponentManager.getComponent<FontComponent>()
|
||||||
|
val colorComp = ComponentManager.getComponent<ColorSchemeComponent>()
|
||||||
|
|
||||||
|
profileFont = fontComp.getCurrentFontName()
|
||||||
|
profileColorScheme = colorComp.getCurrentColorSchemeName()
|
||||||
|
|
||||||
|
loginShell = NeoPreference.getLoginShellPath()
|
||||||
|
initialCommand = NeoPreference.getInitialCommand()
|
||||||
|
enableBell = NeoPreference.isBellEnabled()
|
||||||
|
enableVibrate = NeoPreference.isVibrateEnabled()
|
||||||
|
enableExecveWrapper = NeoPreference.isExecveWrapperEnabled()
|
||||||
|
enableSpecialVolumeKeys = NeoPreference.isSpecialVolumeKeysEnabled()
|
||||||
|
enableAutoCompletion = NeoPreference.isAutoCompletionEnabled()
|
||||||
|
enableBackKeyToEscape = NeoPreference.isBackButtonBeMappedToEscapeEnabled()
|
||||||
|
enableExtraKeys = NeoPreference.isExtraKeysEnabled()
|
||||||
|
enableWordBasedIme = NeoPreference.isWordBasedImeEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConfigLoaded(configVisitor: ConfigVisitor) {
|
||||||
|
super.onConfigLoaded(configVisitor)
|
||||||
|
loginShell = configVisitor.getProfileString(LOGIN_SHELL, loginShell)
|
||||||
|
initialCommand = configVisitor.getProfileString(INITIAL_COMMAND, initialCommand)
|
||||||
|
enableBell = configVisitor.getProfileBoolean(BELL, enableBell)
|
||||||
|
enableVibrate = configVisitor.getProfileBoolean(VIBRATE, enableVibrate)
|
||||||
|
enableExecveWrapper = configVisitor.getProfileBoolean(EXECVE_WRAPPER, enableExecveWrapper)
|
||||||
|
enableSpecialVolumeKeys = configVisitor.getProfileBoolean(SPECIAL_VOLUME_KEYS, enableSpecialVolumeKeys)
|
||||||
|
enableAutoCompletion = configVisitor.getProfileBoolean(AUTO_COMPLETION, enableAutoCompletion)
|
||||||
|
enableBackKeyToEscape = configVisitor.getProfileBoolean(BACK_KEY_TO_ESC, enableBackKeyToEscape)
|
||||||
|
enableExtraKeys = configVisitor.getProfileBoolean(EXTRA_KEYS, enableExtraKeys)
|
||||||
|
enableWordBasedIme = configVisitor.getProfileBoolean(WORD_BASED_IME, enableWordBasedIme)
|
||||||
|
profileFont = configVisitor.getProfileString(FONT, profileFont)
|
||||||
|
profileColorScheme = configVisitor.getProfileString(COLOR_SCHEME, profileColorScheme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
*/
|
*/
|
||||||
@ -244,4 +394,4 @@ open class ShellTermSession private constructor(
|
|||||||
return "${NeoTermPath.USR_PATH}/bin:${NeoTermPath.USR_PATH}/bin/applets"
|
return "${NeoTermPath.USR_PATH}/bin:${NeoTermPath.USR_PATH}/bin/applets"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.session.xorg
|
package io.neoterm.component.session
|
||||||
|
|
||||||
import android.app.UiModeManager
|
import android.app.UiModeManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -7,6 +7,7 @@ import android.content.pm.PackageManager
|
|||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.inputmethodservice.Keyboard
|
import android.inputmethodservice.Keyboard
|
||||||
import android.inputmethodservice.KeyboardView
|
import android.inputmethodservice.KeyboardView
|
||||||
|
import android.os.Build
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.view.*
|
import android.view.*
|
||||||
@ -15,14 +16,11 @@ import android.widget.EditText
|
|||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import io.neoterm.*
|
import io.neoterm.*
|
||||||
import io.neoterm.frontend.session.xorg.client.XSessionData
|
|
||||||
import io.neoterm.xorg.NeoXorgViewClient
|
import io.neoterm.xorg.NeoXorgViewClient
|
||||||
import io.neoterm.xorg.R
|
import io.neoterm.xorg.R
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
class XParameter
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
class XSession constructor(private val mActivity: AppCompatActivity, val mSessionData: XSessionData) :
|
class XSession constructor(private val mActivity: AppCompatActivity, val mSessionData: XSessionData) :
|
||||||
NeoXorgViewClient {
|
NeoXorgViewClient {
|
||||||
@ -64,17 +62,11 @@ class XSession constructor(private val mActivity: AppCompatActivity, val mSessio
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getContext() = mActivity
|
override fun getContext() = mActivity
|
||||||
|
|
||||||
override fun isKeyboardWithoutTextInputShown() = mSessionData.keyboardWithoutTextInputShown
|
override fun isKeyboardWithoutTextInputShown() = mSessionData.keyboardWithoutTextInputShown
|
||||||
|
|
||||||
override fun isPaused() = mSessionData.isPaused
|
override fun isPaused() = mSessionData.isPaused
|
||||||
|
|
||||||
override fun runOnUiThread(runnable: Runnable?) = mActivity.runOnUiThread(runnable)
|
override fun runOnUiThread(runnable: Runnable?) = mActivity.runOnUiThread(runnable)
|
||||||
|
|
||||||
override fun getGLView() = mSessionData.glView
|
override fun getGLView() = mSessionData.glView
|
||||||
|
|
||||||
override fun getWindow() = mActivity.window!!
|
override fun getWindow() = mActivity.window!!
|
||||||
|
|
||||||
override fun getWindowManager() = mActivity.windowManager!!
|
override fun getWindowManager() = mActivity.windowManager!!
|
||||||
|
|
||||||
override fun showScreenKeyboardWithoutTextInputField(keyboard: Int) {
|
override fun showScreenKeyboardWithoutTextInputField(keyboard: Int) {
|
||||||
@ -244,7 +236,7 @@ class XSession constructor(private val mActivity: AppCompatActivity, val mSessio
|
|||||||
|
|
||||||
val screenKeyboard = EditText(
|
val screenKeyboard = EditText(
|
||||||
mActivity, null,
|
mActivity, null,
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||||
android.R.style.TextAppearance_Material_Widget_EditText
|
android.R.style.TextAppearance_Material_Widget_EditText
|
||||||
else android.R.style.TextAppearance_Widget_EditText
|
else android.R.style.TextAppearance_Widget_EditText
|
||||||
)
|
)
|
||||||
@ -349,10 +341,10 @@ class XSession constructor(private val mActivity: AppCompatActivity, val mSessio
|
|||||||
|
|
||||||
override fun setSystemMousePointerVisible(visible: Int) {
|
override fun setSystemMousePointerVisible(visible: Int) {
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||||
glView?.pointerIcon = android.view.PointerIcon.getSystemIcon(
|
glView?.pointerIcon = PointerIcon.getSystemIcon(
|
||||||
mActivity,
|
mActivity,
|
||||||
if (visible == 0) android.view.PointerIcon.TYPE_NULL
|
if (visible == 0) PointerIcon.TYPE_NULL
|
||||||
else android.view.PointerIcon.TYPE_DEFAULT
|
else PointerIcon.TYPE_DEFAULT
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -417,5 +409,18 @@ class XSession constructor(private val mActivity: AppCompatActivity, val mSessio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class XSessionData {
|
||||||
|
var videoLayout: FrameLayout? = null
|
||||||
|
var audioThread: NeoAudioThread? = null
|
||||||
|
var screenKeyboard: View? = null
|
||||||
|
var glView: NeoGLView? = null
|
||||||
|
|
||||||
|
var isPaused = false
|
||||||
|
var client: NeoXorgViewClient? = null
|
||||||
|
|
||||||
|
var keyboardWithoutTextInputShown = false
|
||||||
|
var screenKeyboardHintMessage: String? = null
|
||||||
|
var textInput = LinkedList<Int>()
|
||||||
}
|
}
|
@ -1,8 +0,0 @@
|
|||||||
package io.neoterm.component.userscript
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class UserScript(val scriptFile: File)
|
|
@ -3,17 +3,16 @@ package io.neoterm.component.userscript
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.system.Os
|
import android.system.Os
|
||||||
import io.neoterm.App
|
import io.neoterm.App
|
||||||
import io.neoterm.frontend.component.NeoComponent
|
import io.neoterm.component.NeoComponent
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
import io.neoterm.component.config.NeoTermPath
|
||||||
import io.neoterm.frontend.logging.NLog
|
import io.neoterm.utils.NLog
|
||||||
import io.neoterm.utils.extractAssetsDir
|
import io.neoterm.utils.extractAssetsDir
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
class UserScript(val scriptFile: File)
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class UserScriptComponent : NeoComponent {
|
class UserScriptComponent : NeoComponent {
|
||||||
private var userScripts = listOf<UserScript>()
|
var userScripts = listOf<UserScript>()
|
||||||
private val scriptDir = File(NeoTermPath.USER_SCRIPT_PATH)
|
private val scriptDir = File(NeoTermPath.USER_SCRIPT_PATH)
|
||||||
|
|
||||||
override fun onServiceInit() = checkForFiles()
|
override fun onServiceInit() = checkForFiles()
|
@ -9,7 +9,7 @@ import io.neoterm.App;
|
|||||||
import io.neoterm.framework.database.*;
|
import io.neoterm.framework.database.*;
|
||||||
import io.neoterm.framework.database.bean.TableInfo;
|
import io.neoterm.framework.database.bean.TableInfo;
|
||||||
import io.neoterm.framework.reflection.Reflect;
|
import io.neoterm.framework.reflection.Reflect;
|
||||||
import io.neoterm.frontend.logging.NLog;
|
import io.neoterm.utils.NLog;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.completion.view
|
package io.neoterm.frontend.completion
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
@ -11,11 +11,11 @@ import android.widget.PopupWindow
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalColors
|
import io.neoterm.backend.TerminalColors
|
||||||
|
import io.neoterm.component.ComponentManager
|
||||||
import io.neoterm.component.colorscheme.ColorSchemeComponent
|
import io.neoterm.component.colorscheme.ColorSchemeComponent
|
||||||
import io.neoterm.frontend.completion.listener.OnCandidateSelectedListener
|
import io.neoterm.component.completion.CompletionCandidate
|
||||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
import io.neoterm.component.completion.OnCandidateSelectedListener
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
@ -41,14 +41,13 @@ class CandidatePopupWindow(val context: Context) {
|
|||||||
// Ensure that the popup window will not cover the IME.
|
// Ensure that the popup window will not cover the IME.
|
||||||
val rootView = popWindow.contentView
|
val rootView = popWindow.contentView
|
||||||
if (rootView is MaxHeightView) {
|
if (rootView is MaxHeightView) {
|
||||||
val maxHeight = terminalView.height
|
rootView.maxHeight = terminalView.height
|
||||||
rootView.setMaxHeight(maxHeight)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
popWindow.showAtLocation(
|
popWindow.showAtLocation(
|
||||||
terminalView, Gravity.BOTTOM.and(Gravity.START),
|
terminalView, Gravity.BOTTOM.and(Gravity.START),
|
||||||
terminalView.cursorAbsoluteX,
|
terminalView.cursorAbsoluteX,
|
||||||
terminalView.cursorAbsoluteY
|
terminalView.cursorAbsoluteY,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,12 +68,12 @@ class CandidatePopupWindow(val context: Context) {
|
|||||||
val listView = contentView.findViewById<ListView>(R.id.popup_complete_candidate_list)
|
val listView = contentView.findViewById<ListView>(R.id.popup_complete_candidate_list)
|
||||||
candidateAdapter = CandidateAdapter(this)
|
candidateAdapter = CandidateAdapter(this)
|
||||||
listView.adapter = candidateAdapter
|
listView.adapter = candidateAdapter
|
||||||
listView.setOnItemClickListener({ _, _, position, _ ->
|
listView.setOnItemClickListener { _, _, position, _ ->
|
||||||
val selectedItem = candidates?.get(position)
|
val selectedItem = candidates?.get(position)
|
||||||
if (selectedItem != null) {
|
if (selectedItem != null) {
|
||||||
onCandidateSelectedListener?.onCandidateSelected(selectedItem)
|
onCandidateSelectedListener?.onCandidateSelected(selectedItem)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
candidateListView = listView
|
candidateListView = listView
|
||||||
popupWindow.contentView = contentView
|
popupWindow.contentView = contentView
|
||||||
@ -143,4 +142,4 @@ class CandidatePopupWindow(val context: Context) {
|
|||||||
description.setTextColor(textColor)
|
description.setTextColor(textColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.completion.view
|
package io.neoterm.frontend.completion
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
@ -6,18 +6,11 @@ import android.view.View
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
|
||||||
class MaxHeightView : LinearLayout {
|
class MaxHeightView : LinearLayout {
|
||||||
|
var maxHeight = -1
|
||||||
|
|
||||||
private var maxHeight = -1
|
constructor(context: Context) : super(context)
|
||||||
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||||
constructor(context: Context) : super(context) {}
|
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
|
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {}
|
|
||||||
|
|
||||||
fun setMaxHeight(maxHeight: Int) {
|
|
||||||
this.maxHeight = maxHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
var finalHeightMeasureSpec = heightMeasureSpec
|
var finalHeightMeasureSpec = heightMeasureSpec
|
||||||
@ -53,4 +46,4 @@ class MaxHeightView : LinearLayout {
|
|||||||
|
|
||||||
super.onMeasure(widthMeasureSpec, finalHeightMeasureSpec)
|
super.onMeasure(widthMeasureSpec, finalHeightMeasureSpec)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,25 +0,0 @@
|
|||||||
package io.neoterm.frontend.completion
|
|
||||||
|
|
||||||
import io.neoterm.frontend.completion.listener.MarkScoreListener
|
|
||||||
import io.neoterm.frontend.completion.provider.ICandidateProvider
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ProviderDetector(val providers: List<ICandidateProvider>) : MarkScoreListener {
|
|
||||||
private var detectedProvider: ICandidateProvider? = null
|
|
||||||
|
|
||||||
override fun onMarkScore(score: Int) {
|
|
||||||
// TODO: Save provider score
|
|
||||||
}
|
|
||||||
|
|
||||||
fun detectBest(): ICandidateProvider? {
|
|
||||||
// TODO: detect best
|
|
||||||
detectedProvider = if (providers.isEmpty())
|
|
||||||
null
|
|
||||||
else
|
|
||||||
providers[0]
|
|
||||||
|
|
||||||
return detectedProvider
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package io.neoterm.frontend.completion.listener
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
interface MarkScoreListener {
|
|
||||||
fun onMarkScore(score: Int)
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package io.neoterm.frontend.completion.listener
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kiva
|
|
||||||
* *
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
interface OnAutoCompleteListener {
|
|
||||||
fun onCompletionRequired(newText: String?)
|
|
||||||
|
|
||||||
fun onKeyCode(keyCode: Int, keyMod: Int)
|
|
||||||
|
|
||||||
fun onCleanUp()
|
|
||||||
|
|
||||||
fun onFinishCompletion(): Boolean
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package io.neoterm.frontend.completion.listener
|
|
||||||
|
|
||||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
interface OnCandidateSelectedListener {
|
|
||||||
fun onCandidateSelected(candidate: CompletionCandidate)
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package io.neoterm.frontend.completion.model
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class CompletionCandidate(var completeString: String) {
|
|
||||||
var displayName: String = completeString
|
|
||||||
var description: String? = null
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package io.neoterm.frontend.completion.provider
|
|
||||||
|
|
||||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
interface ICandidateProvider {
|
|
||||||
val providerName: String
|
|
||||||
|
|
||||||
fun provideCandidates(text: String): List<CompletionCandidate>?
|
|
||||||
|
|
||||||
fun canComplete(text: String): Boolean
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.neoterm.frontend.component
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ComponentDuplicateException(serviceName: String) : RuntimeException("Service $serviceName duplicate")
|
|
@ -1,7 +0,0 @@
|
|||||||
package io.neoterm.frontend.component
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ComponentNotFoundException(serviceName: String) : RuntimeException("Component `$serviceName' not found") {
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package io.neoterm.frontend.component
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
interface NeoComponent {
|
|
||||||
fun onServiceInit()
|
|
||||||
fun onServiceDestroy()
|
|
||||||
fun onServiceObtained()
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package io.neoterm.frontend.component.helper
|
|
||||||
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
interface ConfigFileBasedObject {
|
|
||||||
@Throws(RuntimeException::class)
|
|
||||||
fun onConfigLoaded(configVisitor: ConfigVisitor)
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package io.neoterm.frontend.config
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
object DefaultValues {
|
|
||||||
const val fontSize = 30
|
|
||||||
|
|
||||||
const val enableBell = false
|
|
||||||
const val enableVibrate = false
|
|
||||||
const val enableExecveWrapper = true
|
|
||||||
const val enableAutoCompletion = false
|
|
||||||
const val enableFullScreen = false
|
|
||||||
const val enableAutoHideToolbar = false
|
|
||||||
const val enableSwitchNextTab = false
|
|
||||||
const val enableExtraKeys = true
|
|
||||||
const val enableExplicitExtraKeysWeight = false
|
|
||||||
const val enableBackButtonBeMappedToEscape = false
|
|
||||||
const val enableSpecialVolumeKeys = false
|
|
||||||
const val enableWordBasedIme = false
|
|
||||||
|
|
||||||
const val loginShell = "bash"
|
|
||||||
const val initialCommand = ""
|
|
||||||
const val defaultFont = "SourceCodePro"
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package io.neoterm.frontend.config
|
|
||||||
|
|
||||||
import io.neolang.parser.NeoLangParser
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
open class NeoConfigureFile(val configureFile: File) {
|
|
||||||
private val configParser = NeoLangParser()
|
|
||||||
open protected var configVisitor: ConfigVisitor? = null
|
|
||||||
|
|
||||||
fun getVisitor() = configVisitor ?: throw IllegalStateException("Configure file not loaded or parse failed.")
|
|
||||||
|
|
||||||
open fun parseConfigure() = kotlin.runCatching {
|
|
||||||
val programCode = String(Files.readAllBytes(configureFile.toPath()))
|
|
||||||
configParser.setInputSource(programCode)
|
|
||||||
|
|
||||||
val ast = configParser.parse()
|
|
||||||
val astVisitor = ast.visit().getVisitor(ConfigVisitor::class.java) ?: return false
|
|
||||||
astVisitor.start()
|
|
||||||
configVisitor = astVisitor.getCallback()
|
|
||||||
}.isSuccess
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package io.neoterm.frontend.floating
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import io.neoterm.R
|
|
||||||
import io.neoterm.backend.TerminalSession
|
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
|
||||||
import io.neoterm.frontend.terminal.TerminalViewClient
|
|
||||||
import io.neoterm.utils.Terminals
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class WindowTermView(val context: Context) {
|
|
||||||
@SuppressLint("InflateParams")
|
|
||||||
var rootView: View = LayoutInflater.from(context).inflate(R.layout.ui_term_dialog, null, false)
|
|
||||||
private set
|
|
||||||
var terminalView: TerminalView = rootView.findViewById<TerminalView>(R.id.terminal_view_dialog)
|
|
||||||
private set
|
|
||||||
|
|
||||||
init {
|
|
||||||
Terminals.setupTerminalView(terminalView)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTerminalViewClient(terminalViewClient: TerminalViewClient?) {
|
|
||||||
terminalView.setTerminalViewClient(terminalViewClient)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun attachSession(terminalSession: TerminalSession?) {
|
|
||||||
terminalView.attachSession(terminalSession)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setInputMethodEnabled(enabled: Boolean) {
|
|
||||||
terminalView.isFocusable = enabled
|
|
||||||
terminalView.isFocusableInTouchMode = enabled
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +1,23 @@
|
|||||||
package io.neoterm.frontend.floating
|
package io.neoterm.frontend.floating
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.frontend.session.shell.ShellParameter
|
import io.neoterm.component.session.ShellParameter
|
||||||
import io.neoterm.frontend.session.shell.ShellTermSession
|
import io.neoterm.component.session.ShellTermSession
|
||||||
import io.neoterm.frontend.session.shell.client.BasicSessionCallback
|
import io.neoterm.frontend.session.terminal.BasicSessionCallback
|
||||||
import io.neoterm.frontend.session.shell.client.BasicViewClient
|
import io.neoterm.frontend.session.terminal.BasicViewClient
|
||||||
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
|
import io.neoterm.frontend.session.view.TerminalViewClient
|
||||||
import io.neoterm.utils.Terminals
|
import io.neoterm.utils.Terminals
|
||||||
|
|
||||||
typealias DialogSessionFinished = (TerminalDialog, TerminalSession?) -> Unit
|
typealias DialogSessionFinished = (TerminalDialog, TerminalSession?) -> Unit
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class TerminalDialog(val context: Context) {
|
class TerminalDialog(val context: Context) {
|
||||||
private val termWindowView = WindowTermView(context)
|
private val termWindowView = WindowTermView(context)
|
||||||
private val terminalSessionCallback: BasicSessionCallback
|
private val terminalSessionCallback: BasicSessionCallback
|
||||||
@ -92,4 +94,29 @@ class TerminalDialog(val context: Context) {
|
|||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WindowTermView(val context: Context) {
|
||||||
|
@SuppressLint("InflateParams")
|
||||||
|
var rootView: View = LayoutInflater.from(context).inflate(R.layout.ui_term_dialog, null, false)
|
||||||
|
private set
|
||||||
|
var terminalView: TerminalView = rootView.findViewById<TerminalView>(R.id.terminal_view_dialog)
|
||||||
|
private set
|
||||||
|
|
||||||
|
init {
|
||||||
|
Terminals.setupTerminalView(terminalView)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTerminalViewClient(terminalViewClient: TerminalViewClient?) {
|
||||||
|
terminalView.setTerminalViewClient(terminalViewClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun attachSession(terminalSession: TerminalSession?) {
|
||||||
|
terminalView.attachSession(terminalSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setInputMethodEnabled(enabled: Boolean) {
|
||||||
|
terminalView.isFocusable = enabled
|
||||||
|
terminalView.isFocusableInTouchMode = enabled
|
||||||
|
}
|
||||||
|
}
|
@ -1,68 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell
|
|
||||||
|
|
||||||
import io.neoterm.backend.TerminalSession
|
|
||||||
import io.neoterm.bridge.SessionId
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ShellParameter {
|
|
||||||
var sessionId: SessionId? = null
|
|
||||||
var executablePath: String? = null
|
|
||||||
var arguments: Array<String>? = null
|
|
||||||
var cwd: String? = null
|
|
||||||
var initialCommand: String? = null
|
|
||||||
var env: Array<Pair<String, String>>? = null
|
|
||||||
var sessionCallback: TerminalSession.SessionChangedCallback? = null
|
|
||||||
var systemShell: Boolean = false
|
|
||||||
var shellProfile: ShellProfile? = null
|
|
||||||
|
|
||||||
fun executablePath(executablePath: String?): ShellParameter {
|
|
||||||
this.executablePath = executablePath
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun arguments(arguments: Array<String>?): ShellParameter {
|
|
||||||
this.arguments = arguments
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun currentWorkingDirectory(cwd: String?): ShellParameter {
|
|
||||||
this.cwd = cwd
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initialCommand(initialCommand: String?): ShellParameter {
|
|
||||||
this.initialCommand = initialCommand
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun environment(env: Array<Pair<String, String>>?): ShellParameter {
|
|
||||||
this.env = env
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun callback(callback: TerminalSession.SessionChangedCallback?): ShellParameter {
|
|
||||||
this.sessionCallback = callback
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun systemShell(systemShell: Boolean): ShellParameter {
|
|
||||||
this.systemShell = systemShell
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun profile(shellProfile: ShellProfile): ShellParameter {
|
|
||||||
this.shellProfile = shellProfile
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun session(sessionId: SessionId?): ShellParameter {
|
|
||||||
this.sessionId = sessionId
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun willCreateNewSession(): Boolean {
|
|
||||||
return sessionId?.equals(SessionId.NEW_SESSION) ?: true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell
|
|
||||||
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
|
||||||
import io.neoterm.component.colorscheme.ColorSchemeComponent
|
|
||||||
import io.neoterm.component.font.FontComponent
|
|
||||||
import io.neoterm.component.profile.NeoProfile
|
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
|
||||||
import io.neoterm.frontend.config.DefaultValues
|
|
||||||
import io.neoterm.frontend.config.NeoPreference
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ShellProfile : NeoProfile() {
|
|
||||||
companion object {
|
|
||||||
const val PROFILE_META_NAME = "profile-shell"
|
|
||||||
|
|
||||||
private const val LOGIN_SHELL = "login-shell"
|
|
||||||
private const val INITIAL_COMMAND = "init-command"
|
|
||||||
private const val BELL = "bell"
|
|
||||||
private const val VIBRATE = "vibrate"
|
|
||||||
private const val EXECVE_WRAPPER = "execve-wrapper"
|
|
||||||
private const val SPECIAL_VOLUME_KEYS = "special-volume-keys"
|
|
||||||
private const val AUTO_COMPLETION = "auto-completion"
|
|
||||||
private const val BACK_KEY_TO_ESC = "back-key-esc"
|
|
||||||
private const val EXTRA_KEYS = "extra-keys"
|
|
||||||
private const val FONT = "font"
|
|
||||||
private const val COLOR_SCHEME = "color-scheme"
|
|
||||||
private const val WORD_BASED_IME = "word-based-ime"
|
|
||||||
|
|
||||||
fun create(): ShellProfile {
|
|
||||||
return ShellProfile()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val profileMetaName = PROFILE_META_NAME
|
|
||||||
|
|
||||||
var loginShell = DefaultValues.loginShell
|
|
||||||
var initialCommand = DefaultValues.initialCommand
|
|
||||||
|
|
||||||
var enableBell = DefaultValues.enableBell
|
|
||||||
var enableVibrate = DefaultValues.enableVibrate
|
|
||||||
var enableExecveWrapper = DefaultValues.enableExecveWrapper
|
|
||||||
var enableSpecialVolumeKeys = DefaultValues.enableSpecialVolumeKeys
|
|
||||||
var enableAutoCompletion = DefaultValues.enableAutoCompletion
|
|
||||||
var enableBackKeyToEscape = DefaultValues.enableBackButtonBeMappedToEscape
|
|
||||||
var enableExtraKeys = DefaultValues.enableExtraKeys
|
|
||||||
var enableWordBasedIme = DefaultValues.enableWordBasedIme
|
|
||||||
|
|
||||||
var profileFont: String
|
|
||||||
var profileColorScheme: String
|
|
||||||
|
|
||||||
init {
|
|
||||||
val fontComp = ComponentManager.getComponent<FontComponent>()
|
|
||||||
val colorComp = ComponentManager.getComponent<ColorSchemeComponent>()
|
|
||||||
|
|
||||||
profileFont = fontComp.getCurrentFontName()
|
|
||||||
profileColorScheme = colorComp.getCurrentColorSchemeName()
|
|
||||||
|
|
||||||
loginShell = NeoPreference.getLoginShellPath()
|
|
||||||
initialCommand = NeoPreference.getInitialCommand()
|
|
||||||
enableBell = NeoPreference.isBellEnabled()
|
|
||||||
enableVibrate = NeoPreference.isVibrateEnabled()
|
|
||||||
enableExecveWrapper = NeoPreference.isExecveWrapperEnabled()
|
|
||||||
enableSpecialVolumeKeys = NeoPreference.isSpecialVolumeKeysEnabled()
|
|
||||||
enableAutoCompletion = NeoPreference.isAutoCompletionEnabled()
|
|
||||||
enableBackKeyToEscape = NeoPreference.isBackButtonBeMappedToEscapeEnabled()
|
|
||||||
enableExtraKeys = NeoPreference.isExtraKeysEnabled()
|
|
||||||
enableWordBasedIme = NeoPreference.isWordBasedImeEnabled()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onConfigLoaded(configVisitor: ConfigVisitor) {
|
|
||||||
super.onConfigLoaded(configVisitor)
|
|
||||||
loginShell = configVisitor.getProfileString(LOGIN_SHELL, loginShell)
|
|
||||||
initialCommand = configVisitor.getProfileString(INITIAL_COMMAND, initialCommand)
|
|
||||||
enableBell = configVisitor.getProfileBoolean(BELL, enableBell)
|
|
||||||
enableVibrate = configVisitor.getProfileBoolean(VIBRATE, enableVibrate)
|
|
||||||
enableExecveWrapper = configVisitor.getProfileBoolean(EXECVE_WRAPPER, enableExecveWrapper)
|
|
||||||
enableSpecialVolumeKeys = configVisitor.getProfileBoolean(SPECIAL_VOLUME_KEYS, enableSpecialVolumeKeys)
|
|
||||||
enableAutoCompletion = configVisitor.getProfileBoolean(AUTO_COMPLETION, enableAutoCompletion)
|
|
||||||
enableBackKeyToEscape = configVisitor.getProfileBoolean(BACK_KEY_TO_ESC, enableBackKeyToEscape)
|
|
||||||
enableExtraKeys = configVisitor.getProfileBoolean(EXTRA_KEYS, enableExtraKeys)
|
|
||||||
enableWordBasedIme = configVisitor.getProfileBoolean(WORD_BASED_IME, enableWordBasedIme)
|
|
||||||
profileFont = configVisitor.getProfileString(FONT, profileFont)
|
|
||||||
profileColorScheme = configVisitor.getProfileString(COLOR_SCHEME, profileColorScheme)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client
|
|
||||||
|
|
||||||
import io.neoterm.backend.TerminalSession
|
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
open class BasicSessionCallback(var terminalView: TerminalView) : TerminalSession.SessionChangedCallback {
|
|
||||||
override fun onTextChanged(changedSession: TerminalSession?) {
|
|
||||||
if (changedSession != null) {
|
|
||||||
terminalView.onScreenUpdated()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTitleChanged(changedSession: TerminalSession?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSessionFinished(finishedSession: TerminalSession?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClipboardText(session: TerminalSession?, text: String?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBell(session: TerminalSession?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onColorsChanged(session: TerminalSession?) {
|
|
||||||
if (session != null) {
|
|
||||||
terminalView.onScreenUpdated()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.media.SoundPool
|
|
||||||
import android.os.Vibrator
|
|
||||||
import io.neoterm.R
|
|
||||||
import io.neoterm.frontend.session.shell.ShellTermSession
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class BellController constructor() {
|
|
||||||
companion object {
|
|
||||||
private val BELL_DELAY_MS = 100
|
|
||||||
}
|
|
||||||
|
|
||||||
private var bellId: Int = 0
|
|
||||||
private var soundPool: SoundPool? = null
|
|
||||||
private var lastBellTime = 0L
|
|
||||||
|
|
||||||
fun bellOrVibrate(context: Context, session: ShellTermSession) {
|
|
||||||
val currentTime = System.currentTimeMillis()
|
|
||||||
if (currentTime - lastBellTime < BELL_DELAY_MS) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
lastBellTime = currentTime
|
|
||||||
|
|
||||||
if (session.shellProfile.enableBell) {
|
|
||||||
if (soundPool == null) {
|
|
||||||
soundPool = SoundPool.Builder().setMaxStreams(1).build()
|
|
||||||
bellId = soundPool!!.load(context, R.raw.bell, 1)
|
|
||||||
}
|
|
||||||
soundPool?.play(bellId, 1f, 1f, 0, 0, 1f)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session.shellProfile.enableVibrate) {
|
|
||||||
val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
|
||||||
vibrator.vibrate(100)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,165 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.KeyEvent
|
|
||||||
import io.neoterm.BuildConfig
|
|
||||||
import io.neoterm.frontend.completion.CompletionManager
|
|
||||||
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
|
|
||||||
import io.neoterm.frontend.completion.listener.OnCandidateSelectedListener
|
|
||||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
|
||||||
import io.neoterm.frontend.completion.model.CompletionResult
|
|
||||||
import io.neoterm.frontend.completion.view.CandidatePopupWindow
|
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class TermCompleteListener(var terminalView: TerminalView?) : OnAutoCompleteListener, OnCandidateSelectedListener {
|
|
||||||
private val inputStack = Stack<Char>()
|
|
||||||
private var popupWindow: CandidatePopupWindow? = null
|
|
||||||
private var lastCompletedIndex = 0
|
|
||||||
|
|
||||||
override fun onKeyCode(keyCode: Int, keyMod: Int) {
|
|
||||||
when (keyCode) {
|
|
||||||
KeyEvent.KEYCODE_DEL -> {
|
|
||||||
popChar()
|
|
||||||
fixLastCompletedIndex()
|
|
||||||
triggerCompletion()
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyEvent.KEYCODE_ENTER -> {
|
|
||||||
clearChars()
|
|
||||||
popupWindow?.dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fixLastCompletedIndex() {
|
|
||||||
val currentText = getCurrentEditingText()
|
|
||||||
lastCompletedIndex = minOf(lastCompletedIndex, currentText.length - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCompletionRequired(newText: String?) {
|
|
||||||
if (newText == null || newText.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pushString(newText)
|
|
||||||
triggerCompletion()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCleanUp() {
|
|
||||||
popupWindow?.dismiss()
|
|
||||||
popupWindow?.cleanup()
|
|
||||||
popupWindow = null
|
|
||||||
terminalView = null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFinishCompletion(): Boolean {
|
|
||||||
val popWindow = popupWindow ?: return false
|
|
||||||
|
|
||||||
if (popWindow.isShowing()) {
|
|
||||||
popWindow.dismiss()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCandidateSelected(candidate: CompletionCandidate) {
|
|
||||||
val session = terminalView?.currentSession ?: return
|
|
||||||
val textNeedCompletion = getCurrentEditingText().substring(lastCompletedIndex + 1)
|
|
||||||
val newText = candidate.completeString
|
|
||||||
|
|
||||||
val deleteLength = newText.indexOf(textNeedCompletion) + textNeedCompletion.length
|
|
||||||
if (deleteLength > 0) {
|
|
||||||
for (i in 0 until deleteLength) {
|
|
||||||
session.write("\b")
|
|
||||||
popChar()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.e(
|
|
||||||
"NeoTerm-AC", "currentEditing: $textNeedCompletion, " +
|
|
||||||
"deleteLength: $deleteLength, completeString: $newText"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pushString(newText)
|
|
||||||
session.write(newText)
|
|
||||||
// Trigger next completion
|
|
||||||
lastCompletedIndex = inputStack.size
|
|
||||||
triggerCompletion()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun triggerCompletion() {
|
|
||||||
val text = getCurrentEditingText()
|
|
||||||
if (text.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = CompletionManager.tryCompleteFor(text)
|
|
||||||
if (!result.hasResult()) {
|
|
||||||
// A provider accepted the task
|
|
||||||
// But no candidates are provided
|
|
||||||
// Give it zero angrily!
|
|
||||||
result.markScore(0)
|
|
||||||
onFinishCompletion()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
showAutoCompleteCandidates(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showAutoCompleteCandidates(result: CompletionResult) {
|
|
||||||
val termView = terminalView
|
|
||||||
var popWindow = popupWindow
|
|
||||||
|
|
||||||
if (termView == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (popWindow == null) {
|
|
||||||
popWindow = CandidatePopupWindow(termView.context)
|
|
||||||
popWindow.onCandidateSelectedListener = this
|
|
||||||
this.popupWindow = popWindow
|
|
||||||
}
|
|
||||||
|
|
||||||
popWindow.candidates = result.candidates
|
|
||||||
popWindow.show(termView)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCurrentEditingText(): String {
|
|
||||||
val builder = StringBuilder()
|
|
||||||
val size = inputStack.size
|
|
||||||
var start = inputStack.lastIndexOf(' ')
|
|
||||||
if (start < 0) {
|
|
||||||
// Yes, it is -1, we will do `start + 1` below.
|
|
||||||
start = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
IntRange(start + 1, size - 1)
|
|
||||||
.map { inputStack[it] }
|
|
||||||
.takeWhile { !(it == 0.toChar() || it == ' ') }
|
|
||||||
.forEach { builder.append(it) }
|
|
||||||
return builder.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun clearChars() {
|
|
||||||
inputStack.clear()
|
|
||||||
lastCompletedIndex = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun popChar() {
|
|
||||||
if (inputStack.isNotEmpty()) {
|
|
||||||
inputStack.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun pushString(string: String) {
|
|
||||||
string.toCharArray().forEach { pushChar(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun pushChar(char: Char) {
|
|
||||||
inputStack.push(char)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client
|
|
||||||
|
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
|
||||||
import io.neoterm.backend.TerminalSession
|
|
||||||
import io.neoterm.frontend.session.shell.ShellTermSession
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class TermSessionCallback : TerminalSession.SessionChangedCallback {
|
|
||||||
var termSessionData: TermSessionData? = null
|
|
||||||
|
|
||||||
var bellController: BellController? = null
|
|
||||||
|
|
||||||
override fun onTextChanged(changedSession: TerminalSession?) {
|
|
||||||
termSessionData?.termView?.onScreenUpdated()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTitleChanged(changedSession: TerminalSession?) {
|
|
||||||
if (changedSession?.title != null) {
|
|
||||||
termSessionData?.termUI?.requireUpdateTitle(changedSession.title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSessionFinished(finishedSession: TerminalSession?) {
|
|
||||||
termSessionData?.termUI?.requireOnSessionFinished()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClipboardText(session: TerminalSession?, text: String?) {
|
|
||||||
val termView = termSessionData?.termView
|
|
||||||
if (termView != null) {
|
|
||||||
val clipboard = termView.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
clipboard.primaryClip = ClipData.newPlainText("", text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBell(session: TerminalSession?) {
|
|
||||||
val termView = termSessionData?.termView ?: return
|
|
||||||
val shellSession = session as ShellTermSession
|
|
||||||
|
|
||||||
if (bellController == null) {
|
|
||||||
bellController = BellController()
|
|
||||||
}
|
|
||||||
|
|
||||||
bellController?.bellOrVibrate(termView.context, shellSession)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onColorsChanged(session: TerminalSession?) {
|
|
||||||
val termView = termSessionData?.termView
|
|
||||||
if (session != null && termView != null) {
|
|
||||||
termView.onScreenUpdated()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
interface TermUiPresenter {
|
|
||||||
fun requireClose()
|
|
||||||
fun requireToggleFullScreen()
|
|
||||||
fun requirePaste()
|
|
||||||
fun requireUpdateTitle(title: String?)
|
|
||||||
fun requireOnSessionFinished()
|
|
||||||
fun requireHideIme()
|
|
||||||
fun requireFinishAutoCompletion(): Boolean
|
|
||||||
fun requireCreateNew()
|
|
||||||
fun requireSwitchToPrevious()
|
|
||||||
fun requireSwitchToNext()
|
|
||||||
fun requireSwitchTo(index: Int)
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client.event
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class CreateNewSessionEvent
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client.event
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class SwitchIndexedSessionEvent(val index: Int)
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client.event
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class SwitchSessionEvent(val toNext: Boolean)
|
|
@ -1,9 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client.event
|
|
||||||
|
|
||||||
import io.neoterm.ui.term.tab.TermTab
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TabCloseEvent(var termTab: TermTab)
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client.event
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class TitleChangedEvent(val title: String)
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client.event
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ToggleFullScreenEvent()
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.shell.client.event
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ToggleImeEvent
|
|
@ -1,15 +1,12 @@
|
|||||||
package io.neoterm.frontend.session.shell.client
|
package io.neoterm.frontend.session.terminal
|
||||||
|
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
|
import io.neoterm.component.completion.OnAutoCompleteListener
|
||||||
import io.neoterm.frontend.session.shell.ShellProfile
|
import io.neoterm.component.session.ShellProfile
|
||||||
import io.neoterm.frontend.session.shell.ShellTermSession
|
import io.neoterm.component.session.ShellTermSession
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
|
import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class TermSessionData {
|
class TermSessionData {
|
||||||
var termSession: TerminalSession? = null
|
var termSession: TerminalSession? = null
|
||||||
var sessionCallback: TermSessionCallback? = null
|
var sessionCallback: TermSessionCallback? = null
|
||||||
@ -58,4 +55,18 @@ class TermSessionData {
|
|||||||
this.termView = termView
|
this.termView = termView
|
||||||
this.extraKeysView = eks
|
this.extraKeysView = eks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface TermUiPresenter {
|
||||||
|
fun requireClose()
|
||||||
|
fun requireToggleFullScreen()
|
||||||
|
fun requirePaste()
|
||||||
|
fun requireUpdateTitle(title: String?)
|
||||||
|
fun requireOnSessionFinished()
|
||||||
|
fun requireHideIme()
|
||||||
|
fun requireFinishAutoCompletion(): Boolean
|
||||||
|
fun requireCreateNew()
|
||||||
|
fun requireSwitchToPrevious()
|
||||||
|
fun requireSwitchToNext()
|
||||||
|
fun requireSwitchTo(index: Int)
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package io.neoterm.frontend.session.terminal
|
||||||
|
|
||||||
|
import io.neoterm.ui.term.TermTab
|
||||||
|
|
||||||
|
class CreateNewSessionEvent
|
||||||
|
class SwitchIndexedSessionEvent(val index: Int)
|
||||||
|
class SwitchSessionEvent(val toNext: Boolean)
|
||||||
|
class TabCloseEvent(val termTab: TermTab)
|
||||||
|
class TitleChangedEvent(val title: String)
|
||||||
|
class ToggleFullScreenEvent
|
||||||
|
class ToggleImeEvent
|
@ -1,17 +1,40 @@
|
|||||||
package io.neoterm.frontend.session.shell.client
|
package io.neoterm.frontend.session.terminal
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.frontend.config.NeoPreference
|
import io.neoterm.component.config.NeoPreference
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
import io.neoterm.frontend.terminal.TerminalViewClient
|
import io.neoterm.frontend.session.view.TerminalViewClient
|
||||||
|
|
||||||
|
open class BasicSessionCallback(var terminalView: TerminalView) : TerminalSession.SessionChangedCallback {
|
||||||
|
override fun onTextChanged(changedSession: TerminalSession?) {
|
||||||
|
if (changedSession != null) {
|
||||||
|
terminalView.onScreenUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTitleChanged(changedSession: TerminalSession?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSessionFinished(finishedSession: TerminalSession?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClipboardText(session: TerminalSession?, text: String?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBell(session: TerminalSession?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onColorsChanged(session: TerminalSession?) {
|
||||||
|
if (session != null) {
|
||||||
|
terminalView.onScreenUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class BasicViewClient(val terminalView: TerminalView) : TerminalViewClient {
|
class BasicViewClient(val terminalView: TerminalView) : TerminalViewClient {
|
||||||
override fun onScale(scale: Float): Float {
|
override fun onScale(scale: Float): Float {
|
||||||
if (scale < 0.9f || scale > 1.1f) {
|
if (scale < 0.9f || scale > 1.1f) {
|
@ -1,20 +1,30 @@
|
|||||||
package io.neoterm.frontend.session.shell.client
|
package io.neoterm.frontend.session.terminal
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
|
import android.media.SoundPool
|
||||||
|
import android.os.Vibrator
|
||||||
|
import android.util.Log
|
||||||
import android.view.InputDevice
|
import android.view.InputDevice
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import io.neoterm.BuildConfig
|
||||||
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.KeyHandler
|
import io.neoterm.backend.KeyHandler
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
|
import io.neoterm.component.ComponentManager
|
||||||
|
import io.neoterm.component.completion.*
|
||||||
|
import io.neoterm.component.config.NeoPreference
|
||||||
import io.neoterm.component.extrakey.ExtraKeyComponent
|
import io.neoterm.component.extrakey.ExtraKeyComponent
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.component.session.ShellTermSession
|
||||||
import io.neoterm.frontend.config.NeoPreference
|
import io.neoterm.frontend.completion.CandidatePopupWindow
|
||||||
import io.neoterm.frontend.session.shell.ShellTermSession
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
import io.neoterm.frontend.terminal.TerminalViewClient
|
import io.neoterm.frontend.session.view.TerminalViewClient
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
@ -267,4 +277,234 @@ class TermViewClient(val context: Context) : TerminalViewClient {
|
|||||||
NeoPreference.store(NeoPreference.KEY_FONT_SIZE, fontSize)
|
NeoPreference.store(NeoPreference.KEY_FONT_SIZE, fontSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
class TermSessionCallback : TerminalSession.SessionChangedCallback {
|
||||||
|
var termSessionData: TermSessionData? = null
|
||||||
|
|
||||||
|
var bellController: BellController? = null
|
||||||
|
|
||||||
|
override fun onTextChanged(changedSession: TerminalSession?) {
|
||||||
|
termSessionData?.termView?.onScreenUpdated()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTitleChanged(changedSession: TerminalSession?) {
|
||||||
|
if (changedSession?.title != null) {
|
||||||
|
termSessionData?.termUI?.requireUpdateTitle(changedSession.title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSessionFinished(finishedSession: TerminalSession?) {
|
||||||
|
termSessionData?.termUI?.requireOnSessionFinished()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClipboardText(session: TerminalSession?, text: String?) {
|
||||||
|
val termView = termSessionData?.termView
|
||||||
|
if (termView != null) {
|
||||||
|
val clipboard = termView.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
clipboard.primaryClip = ClipData.newPlainText("", text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBell(session: TerminalSession?) {
|
||||||
|
val termView = termSessionData?.termView ?: return
|
||||||
|
val shellSession = session as ShellTermSession
|
||||||
|
|
||||||
|
if (bellController == null) {
|
||||||
|
bellController = BellController()
|
||||||
|
}
|
||||||
|
|
||||||
|
bellController?.bellOrVibrate(termView.context, shellSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onColorsChanged(session: TerminalSession?) {
|
||||||
|
val termView = termSessionData?.termView
|
||||||
|
if (session != null && termView != null) {
|
||||||
|
termView.onScreenUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BellController {
|
||||||
|
companion object {
|
||||||
|
private val BELL_DELAY_MS = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
private var bellId: Int = 0
|
||||||
|
private var soundPool: SoundPool? = null
|
||||||
|
private var lastBellTime = 0L
|
||||||
|
|
||||||
|
fun bellOrVibrate(context: Context, session: ShellTermSession) {
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
if (currentTime - lastBellTime < BELL_DELAY_MS) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastBellTime = currentTime
|
||||||
|
|
||||||
|
if (session.shellProfile.enableBell) {
|
||||||
|
if (soundPool == null) {
|
||||||
|
soundPool = SoundPool.Builder().setMaxStreams(1).build()
|
||||||
|
bellId = soundPool!!.load(context, R.raw.bell, 1)
|
||||||
|
}
|
||||||
|
soundPool?.play(bellId, 1f, 1f, 0, 0, 1f)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.shellProfile.enableVibrate) {
|
||||||
|
val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||||
|
vibrator.vibrate(100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TermCompleteListener(var terminalView: TerminalView?) : OnAutoCompleteListener, OnCandidateSelectedListener {
|
||||||
|
private val inputStack = Stack<Char>()
|
||||||
|
private var popupWindow: CandidatePopupWindow? = null
|
||||||
|
private var lastCompletedIndex = 0
|
||||||
|
|
||||||
|
override fun onKeyCode(keyCode: Int, keyMod: Int) {
|
||||||
|
when (keyCode) {
|
||||||
|
KeyEvent.KEYCODE_DEL -> {
|
||||||
|
popChar()
|
||||||
|
fixLastCompletedIndex()
|
||||||
|
triggerCompletion()
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyEvent.KEYCODE_ENTER -> {
|
||||||
|
clearChars()
|
||||||
|
popupWindow?.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fixLastCompletedIndex() {
|
||||||
|
val currentText = getCurrentEditingText()
|
||||||
|
lastCompletedIndex = minOf(lastCompletedIndex, currentText.length - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCompletionRequired(newText: String?) {
|
||||||
|
if (newText == null || newText.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pushString(newText)
|
||||||
|
triggerCompletion()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleanUp() {
|
||||||
|
popupWindow?.dismiss()
|
||||||
|
popupWindow?.cleanup()
|
||||||
|
popupWindow = null
|
||||||
|
terminalView = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinishCompletion(): Boolean {
|
||||||
|
val popWindow = popupWindow ?: return false
|
||||||
|
|
||||||
|
if (popWindow.isShowing()) {
|
||||||
|
popWindow.dismiss()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCandidateSelected(candidate: CompletionCandidate) {
|
||||||
|
val session = terminalView?.currentSession ?: return
|
||||||
|
val textNeedCompletion = getCurrentEditingText().substring(lastCompletedIndex + 1)
|
||||||
|
val newText = candidate.completeString
|
||||||
|
|
||||||
|
val deleteLength = newText.indexOf(textNeedCompletion) + textNeedCompletion.length
|
||||||
|
if (deleteLength > 0) {
|
||||||
|
for (i in 0 until deleteLength) {
|
||||||
|
session.write("\b")
|
||||||
|
popChar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.e(
|
||||||
|
"NeoTerm-AC",
|
||||||
|
"currentEditing: $textNeedCompletion, " +
|
||||||
|
"deleteLength: $deleteLength, completeString: $newText"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pushString(newText)
|
||||||
|
session.write(newText)
|
||||||
|
// Trigger next completion
|
||||||
|
lastCompletedIndex = inputStack.size
|
||||||
|
triggerCompletion()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun triggerCompletion() {
|
||||||
|
val text = getCurrentEditingText()
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = CompletionManager.tryCompleteFor(text)
|
||||||
|
if (!result.hasResult()) {
|
||||||
|
// A provider accepted the task
|
||||||
|
// But no candidates are provided
|
||||||
|
// Give it zero angrily!
|
||||||
|
result.markScore(0)
|
||||||
|
onFinishCompletion()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showAutoCompleteCandidates(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showAutoCompleteCandidates(result: CompletionResult) {
|
||||||
|
val termView = terminalView
|
||||||
|
var popWindow = popupWindow
|
||||||
|
|
||||||
|
if (termView == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (popWindow == null) {
|
||||||
|
popWindow = CandidatePopupWindow(termView.context)
|
||||||
|
popWindow.onCandidateSelectedListener = this
|
||||||
|
this.popupWindow = popWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
popWindow.candidates = result.candidates
|
||||||
|
popWindow.show(termView)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCurrentEditingText(): String {
|
||||||
|
val builder = StringBuilder()
|
||||||
|
val size = inputStack.size
|
||||||
|
var start = inputStack.lastIndexOf(' ')
|
||||||
|
if (start < 0) {
|
||||||
|
// Yes, it is -1, we will do `start + 1` below.
|
||||||
|
start = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
IntRange(start + 1, size - 1)
|
||||||
|
.map { inputStack[it] }
|
||||||
|
.takeWhile { !(it == 0.toChar() || it == ' ') }
|
||||||
|
.forEach { builder.append(it) }
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearChars() {
|
||||||
|
inputStack.clear()
|
||||||
|
lastCompletedIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun popChar() {
|
||||||
|
if (inputStack.isNotEmpty()) {
|
||||||
|
inputStack.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun pushString(string: String) {
|
||||||
|
string.toCharArray().forEach { pushChar(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun pushChar(char: Char) {
|
||||||
|
inputStack.push(char)
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.terminal
|
package io.neoterm.frontend.session.view
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.GestureDetector
|
import android.view.GestureDetector
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.terminal;
|
package io.neoterm.frontend.session.view;
|
||||||
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.terminal;
|
package io.neoterm.frontend.session.view;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
@ -23,7 +23,7 @@ import android.view.inputmethod.InputConnection;
|
|||||||
import android.widget.Scroller;
|
import android.widget.Scroller;
|
||||||
import io.neoterm.R;
|
import io.neoterm.R;
|
||||||
import io.neoterm.backend.*;
|
import io.neoterm.backend.*;
|
||||||
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener;
|
import io.neoterm.component.completion.OnAutoCompleteListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View displaying and interacting with a {@link TerminalSession}.
|
* View displaying and interacting with a {@link TerminalSession}.
|
||||||
@ -1032,45 +1032,38 @@ public final class TerminalView extends View {
|
|||||||
@Override
|
@Override
|
||||||
public void onDestroyActionMode(ActionMode mode) {
|
public void onDestroyActionMode(ActionMode mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
mActionMode = startActionMode(new ActionMode.Callback2() {
|
||||||
mActionMode = startActionMode(new ActionMode.Callback2() {
|
@Override
|
||||||
@Override
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
return callback.onCreateActionMode(mode, menu);
|
||||||
return callback.onCreateActionMode(mode, menu);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||||
return callback.onActionItemClicked(mode, item);
|
return callback.onActionItemClicked(mode, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyActionMode(ActionMode mode) {
|
|
||||||
// Ignore.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
|
|
||||||
int x1 = Math.round(mSelX1 * mRenderer.mFontWidth);
|
|
||||||
int x2 = Math.round(mSelX2 * mRenderer.mFontWidth);
|
|
||||||
int y1 = Math.round((mSelY1 - mTopRow) * mRenderer.mFontLineSpacing);
|
|
||||||
int y2 = Math.round((mSelY2 + 1 - mTopRow) * mRenderer.mFontLineSpacing);
|
|
||||||
outRect.set(Math.min(x1, x2), y1, Math.max(x1, x2), y2);
|
|
||||||
}
|
|
||||||
}, ActionMode.TYPE_FLOATING);
|
|
||||||
} else {
|
|
||||||
mActionMode = startActionMode(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyActionMode(ActionMode mode) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
|
||||||
|
int x1 = Math.round(mSelX1 * mRenderer.mFontWidth);
|
||||||
|
int x2 = Math.round(mSelX2 * mRenderer.mFontWidth);
|
||||||
|
int y1 = Math.round((mSelY1 - mTopRow) * mRenderer.mFontLineSpacing);
|
||||||
|
int y2 = Math.round((mSelY2 + 1 - mTopRow) * mRenderer.mFontLineSpacing);
|
||||||
|
outRect.set(Math.min(x1, x2), y1, Math.max(x1, x2), y2);
|
||||||
|
}
|
||||||
|
}, ActionMode.TYPE_FLOATING);
|
||||||
invalidate();
|
invalidate();
|
||||||
} else {
|
} else {
|
||||||
mActionMode.finish();
|
mActionMode.finish();
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.terminal;
|
package io.neoterm.frontend.session.view;
|
||||||
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
@ -11,7 +11,6 @@ import io.neoterm.backend.TerminalSession;
|
|||||||
* <p/>
|
* <p/>
|
||||||
*/
|
*/
|
||||||
public interface TerminalViewClient {
|
public interface TerminalViewClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function on scale events according to {@link ScaleGestureDetector#getScaleFactor()}.
|
* Callback function on scale events according to {@link ScaleGestureDetector#getScaleFactor()}.
|
||||||
*/
|
*/
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.terminal.extrakey.combine
|
package io.neoterm.frontend.session.view.extrakey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <Ctrl> <Alt> <Delete>
|
* <Ctrl> <Alt> <Delete>
|
||||||
@ -26,4 +26,4 @@ class CombinedSequence private constructor() {
|
|||||||
return seq
|
return seq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package io.neoterm.frontend.terminal.extrakey
|
package io.neoterm.frontend.session.view.extrakey
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
@ -7,21 +7,15 @@ import android.view.*
|
|||||||
import android.widget.GridLayout
|
import android.widget.GridLayout
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
|
import io.neoterm.component.ComponentManager
|
||||||
|
import io.neoterm.component.config.NeoPreference
|
||||||
|
import io.neoterm.component.config.NeoTermPath
|
||||||
import io.neoterm.component.extrakey.ExtraKeyComponent
|
import io.neoterm.component.extrakey.ExtraKeyComponent
|
||||||
import io.neoterm.frontend.component.ComponentManager
|
import io.neoterm.frontend.session.terminal.ToggleImeEvent
|
||||||
import io.neoterm.frontend.config.NeoPreference
|
|
||||||
import io.neoterm.frontend.config.NeoTermPath
|
|
||||||
import io.neoterm.frontend.session.shell.client.event.ToggleImeEvent
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.button.ControlButton
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.button.IExtraButton
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.button.RepeatableButton
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.button.StatedControlButton
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.impl.ArrowButton
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val ESC = ControlButton(IExtraButton.KEY_ESC)
|
private val ESC = ControlButton(IExtraButton.KEY_ESC)
|
||||||
private val TAB = ControlButton(IExtraButton.KEY_TAB)
|
private val TAB = ControlButton(IExtraButton.KEY_TAB)
|
||||||
@ -68,7 +62,7 @@ class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(contex
|
|||||||
init {
|
init {
|
||||||
alpha = DEFAULT_ALPHA
|
alpha = DEFAULT_ALPHA
|
||||||
gravity = Gravity.TOP
|
gravity = Gravity.TOP
|
||||||
orientation = LinearLayout.VERTICAL
|
orientation = VERTICAL
|
||||||
typeface = Typeface.createFromAsset(context.assets, "eks_font.ttf")
|
typeface = Typeface.createFromAsset(context.assets, "eks_font.ttf")
|
||||||
extraKeyComponent = ComponentManager.getComponent<ExtraKeyComponent>()
|
extraKeyComponent = ComponentManager.getComponent<ExtraKeyComponent>()
|
||||||
|
|
@ -0,0 +1,222 @@
|
|||||||
|
package io.neoterm.frontend.session.view.extrakey
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.ToggleButton
|
||||||
|
import androidx.appcompat.widget.AppCompatButton
|
||||||
|
import io.neoterm.R
|
||||||
|
import io.neoterm.frontend.session.view.TerminalView
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class ControlButton(text: String) : TextButton(text, false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class IExtraButton : View.OnClickListener {
|
||||||
|
|
||||||
|
var buttonKeys: CombinedSequence? = null
|
||||||
|
var displayText: String? = null
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "${this.javaClass.simpleName} { display: $displayText, code: ${buttonKeys?.keys} }"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract override fun onClick(view: View)
|
||||||
|
|
||||||
|
abstract fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KEY_ESC = "Esc"
|
||||||
|
const val KEY_TAB = "Tab"
|
||||||
|
const val KEY_CTRL = "Ctrl"
|
||||||
|
const val KEY_ALT = "Alt"
|
||||||
|
const val KEY_PAGE_UP = "PgUp"
|
||||||
|
const val KEY_PAGE_DOWN = "PgDn"
|
||||||
|
const val KEY_HOME = "Home"
|
||||||
|
const val KEY_END = "End"
|
||||||
|
const val KEY_ARROW_UP_TEXT = "Up"
|
||||||
|
const val KEY_ARROW_DOWN_TEXT = "Down"
|
||||||
|
const val KEY_ARROW_LEFT_TEXT = "Left"
|
||||||
|
const val KEY_ARROW_RIGHT_TEXT = "Right"
|
||||||
|
const val KEY_SHOW_ALL_BUTTONS = "···"
|
||||||
|
const val KEY_TOGGLE_IME = "Im"
|
||||||
|
|
||||||
|
const val KEY_ARROW_UP = "▲"
|
||||||
|
const val KEY_ARROW_DOWN = "▼"
|
||||||
|
const val KEY_ARROW_LEFT = "◀"
|
||||||
|
const val KEY_ARROW_RIGHT = "▶"
|
||||||
|
|
||||||
|
var NORMAL_TEXT_COLOR = 0xFFFFFFFF.toInt()
|
||||||
|
var SELECTED_TEXT_COLOR = 0xFF80DEEA.toInt()
|
||||||
|
|
||||||
|
fun sendKey(view: View, keyName: String) {
|
||||||
|
var keyCode = 0
|
||||||
|
var chars = ""
|
||||||
|
when (keyName) {
|
||||||
|
KEY_ESC -> keyCode = KeyEvent.KEYCODE_ESCAPE
|
||||||
|
KEY_TAB -> keyCode = KeyEvent.KEYCODE_TAB
|
||||||
|
KEY_ARROW_UP -> keyCode = KeyEvent.KEYCODE_DPAD_UP
|
||||||
|
KEY_ARROW_LEFT -> keyCode = KeyEvent.KEYCODE_DPAD_LEFT
|
||||||
|
KEY_ARROW_RIGHT -> keyCode = KeyEvent.KEYCODE_DPAD_RIGHT
|
||||||
|
KEY_ARROW_DOWN -> keyCode = KeyEvent.KEYCODE_DPAD_DOWN
|
||||||
|
KEY_ARROW_UP_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_UP
|
||||||
|
KEY_ARROW_LEFT_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_LEFT
|
||||||
|
KEY_ARROW_RIGHT_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_RIGHT
|
||||||
|
KEY_ARROW_DOWN_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_DOWN
|
||||||
|
KEY_PAGE_UP -> keyCode = KeyEvent.KEYCODE_PAGE_UP
|
||||||
|
KEY_PAGE_DOWN -> keyCode = KeyEvent.KEYCODE_PAGE_DOWN
|
||||||
|
KEY_HOME -> keyCode = KeyEvent.KEYCODE_MOVE_HOME
|
||||||
|
KEY_END -> keyCode = KeyEvent.KEYCODE_MOVE_END
|
||||||
|
"―" -> chars = "-"
|
||||||
|
else -> chars = keyName
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyCode > 0) {
|
||||||
|
view.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, keyCode))
|
||||||
|
view.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, keyCode))
|
||||||
|
} else if (chars.isNotEmpty()) {
|
||||||
|
val terminalView = view.findViewById<TerminalView>(R.id.terminal_view)
|
||||||
|
val session = terminalView.currentSession
|
||||||
|
session?.write(chars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
open class RepeatableButton(buttonText: String) : ControlButton(buttonText) {
|
||||||
|
|
||||||
|
override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
|
||||||
|
return RepeatableButtonWidget(context, attrs, defStyleAttr)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RepeatableButtonWidget(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) :
|
||||||
|
AppCompatButton(context!!, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Milliseconds how long we trigger an action
|
||||||
|
* when long pressing
|
||||||
|
*/
|
||||||
|
private val LONG_CLICK_ACTION_INTERVAL = 100L
|
||||||
|
|
||||||
|
private var isMotionEventUp = true
|
||||||
|
|
||||||
|
var mHandler: Handler = object : Handler(Looper.getMainLooper()) {
|
||||||
|
override fun handleMessage(msg: android.os.Message) {
|
||||||
|
if (!isMotionEventUp && isEnabled) {
|
||||||
|
performClick()
|
||||||
|
this.sendEmptyMessageDelayed(0, LONG_CLICK_ACTION_INTERVAL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.setOnLongClickListener {
|
||||||
|
isMotionEventUp = false
|
||||||
|
mHandler.sendEmptyMessage(0)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
this.setOnTouchListener { _, event ->
|
||||||
|
if (event.action == MotionEvent.ACTION_UP) {
|
||||||
|
isMotionEventUp = true
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun performClick(): Boolean {
|
||||||
|
return super.performClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class StatedControlButton @JvmOverloads constructor(text: String, var initState: Boolean = false) :
|
||||||
|
ControlButton(text) {
|
||||||
|
var toggleButton: ToggleButton? = null
|
||||||
|
|
||||||
|
override fun onClick(view: View) {
|
||||||
|
setStatus(toggleButton?.isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
|
||||||
|
val outerButton = ToggleButton(context, null, android.R.attr.buttonBarButtonStyle)
|
||||||
|
|
||||||
|
outerButton.isClickable = true
|
||||||
|
if (initState) {
|
||||||
|
outerButton.isChecked = true
|
||||||
|
outerButton.setTextColor(SELECTED_TEXT_COLOR)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.toggleButton = outerButton
|
||||||
|
return outerButton
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setStatus(status: Boolean?) {
|
||||||
|
val button = toggleButton
|
||||||
|
if (button != null && status != null) {
|
||||||
|
button.isChecked = status
|
||||||
|
button.setTextColor(
|
||||||
|
if (status) SELECTED_TEXT_COLOR
|
||||||
|
else NORMAL_TEXT_COLOR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readState(): Boolean {
|
||||||
|
val button = toggleButton ?: return false
|
||||||
|
|
||||||
|
if (button.isPressed) return true
|
||||||
|
val result = button.isChecked
|
||||||
|
if (result) {
|
||||||
|
button.isChecked = false
|
||||||
|
button.setTextColor(NORMAL_TEXT_COLOR)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class TextButton constructor(text: String, val withEnter: Boolean = false) : IExtraButton() {
|
||||||
|
init {
|
||||||
|
this.buttonKeys = CombinedSequence.solveString(text)
|
||||||
|
this.displayText = text
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(view: View) {
|
||||||
|
buttonKeys!!.keys.forEach {
|
||||||
|
sendKey(view, it)
|
||||||
|
}
|
||||||
|
if (withEnter) {
|
||||||
|
sendKey(view, "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
|
||||||
|
return Button(context, attrs, defStyleAttr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
class ArrowButton(arrowText: String) : RepeatableButton(arrowText)
|
@ -1,8 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.xorg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class XParameter {
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package io.neoterm.frontend.session.xorg.client
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import io.neoterm.NeoAudioThread
|
|
||||||
import io.neoterm.NeoGLView
|
|
||||||
import io.neoterm.xorg.NeoXorgViewClient
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class XSessionData {
|
|
||||||
var videoLayout: FrameLayout? = null
|
|
||||||
var audioThread: NeoAudioThread? = null
|
|
||||||
var screenKeyboard: View? = null
|
|
||||||
var glView: NeoGLView? = null
|
|
||||||
|
|
||||||
var isPaused = false
|
|
||||||
var client: NeoXorgViewClient? = null
|
|
||||||
|
|
||||||
var keyboardWithoutTextInputShown = false
|
|
||||||
var screenKeyboardHintMessage: String? = null
|
|
||||||
var textInput = LinkedList<Int>()
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package io.neoterm.frontend.terminal.extrakey.button
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
open class ControlButton(text: String) : TextButton(text, false)
|
|
@ -1,85 +0,0 @@
|
|||||||
package io.neoterm.frontend.terminal.extrakey.button
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.KeyEvent
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.Button
|
|
||||||
import io.neoterm.R
|
|
||||||
import io.neoterm.frontend.terminal.TerminalView
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.combine.CombinedSequence
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
abstract class IExtraButton : View.OnClickListener {
|
|
||||||
|
|
||||||
var buttonKeys: CombinedSequence? = null
|
|
||||||
var displayText: String? = null
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "${this.javaClass.simpleName} { display: $displayText, code: ${buttonKeys?.keys} }"
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract override fun onClick(view: View)
|
|
||||||
|
|
||||||
abstract fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val KEY_ESC = "Esc"
|
|
||||||
val KEY_TAB = "Tab"
|
|
||||||
val KEY_CTRL = "Ctrl"
|
|
||||||
val KEY_ALT = "Alt"
|
|
||||||
val KEY_PAGE_UP = "PgUp"
|
|
||||||
val KEY_PAGE_DOWN = "PgDn"
|
|
||||||
val KEY_HOME = "Home"
|
|
||||||
val KEY_END = "End"
|
|
||||||
val KEY_ARROW_UP_TEXT = "Up"
|
|
||||||
val KEY_ARROW_DOWN_TEXT = "Down"
|
|
||||||
val KEY_ARROW_LEFT_TEXT = "Left"
|
|
||||||
val KEY_ARROW_RIGHT_TEXT = "Right"
|
|
||||||
val KEY_SHOW_ALL_BUTTONS = "···"
|
|
||||||
val KEY_TOGGLE_IME = "Im"
|
|
||||||
|
|
||||||
val KEY_ARROW_UP = "▲"
|
|
||||||
val KEY_ARROW_DOWN = "▼"
|
|
||||||
val KEY_ARROW_LEFT = "◀"
|
|
||||||
val KEY_ARROW_RIGHT = "▶"
|
|
||||||
|
|
||||||
var NORMAL_TEXT_COLOR = 0xFFFFFFFF.toInt()
|
|
||||||
var SELECTED_TEXT_COLOR = 0xFF80DEEA.toInt()
|
|
||||||
|
|
||||||
fun sendKey(view: View, keyName: String) {
|
|
||||||
var keyCode = 0
|
|
||||||
var chars = ""
|
|
||||||
when (keyName) {
|
|
||||||
KEY_ESC -> keyCode = KeyEvent.KEYCODE_ESCAPE
|
|
||||||
KEY_TAB -> keyCode = KeyEvent.KEYCODE_TAB
|
|
||||||
KEY_ARROW_UP -> keyCode = KeyEvent.KEYCODE_DPAD_UP
|
|
||||||
KEY_ARROW_LEFT -> keyCode = KeyEvent.KEYCODE_DPAD_LEFT
|
|
||||||
KEY_ARROW_RIGHT -> keyCode = KeyEvent.KEYCODE_DPAD_RIGHT
|
|
||||||
KEY_ARROW_DOWN -> keyCode = KeyEvent.KEYCODE_DPAD_DOWN
|
|
||||||
KEY_ARROW_UP_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_UP
|
|
||||||
KEY_ARROW_LEFT_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_LEFT
|
|
||||||
KEY_ARROW_RIGHT_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_RIGHT
|
|
||||||
KEY_ARROW_DOWN_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_DOWN
|
|
||||||
KEY_PAGE_UP -> keyCode = KeyEvent.KEYCODE_PAGE_UP
|
|
||||||
KEY_PAGE_DOWN -> keyCode = KeyEvent.KEYCODE_PAGE_DOWN
|
|
||||||
KEY_HOME -> keyCode = KeyEvent.KEYCODE_MOVE_HOME
|
|
||||||
KEY_END -> keyCode = KeyEvent.KEYCODE_MOVE_END
|
|
||||||
"―" -> chars = "-"
|
|
||||||
else -> chars = keyName
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyCode > 0) {
|
|
||||||
view.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, keyCode))
|
|
||||||
view.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, keyCode))
|
|
||||||
} else if (chars.isNotEmpty()) {
|
|
||||||
val terminalView = view.findViewById<TerminalView>(R.id.terminal_view)
|
|
||||||
val session = terminalView.currentSession
|
|
||||||
session?.write(chars)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
package io.neoterm.frontend.terminal.extrakey.button
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.widget.Button
|
|
||||||
import androidx.appcompat.widget.AppCompatButton
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
open class RepeatableButton(buttonText: String) : ControlButton(buttonText) {
|
|
||||||
|
|
||||||
override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
|
|
||||||
return RepeatableButtonWidget(context, attrs, defStyleAttr)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RepeatableButtonWidget(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) :
|
|
||||||
AppCompatButton(context!!, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Milliseconds how long we trigger an action
|
|
||||||
* when long pressing
|
|
||||||
*/
|
|
||||||
private val LONG_CLICK_ACTION_INTERVAL = 100L
|
|
||||||
|
|
||||||
private var isMotionEventUp = true
|
|
||||||
|
|
||||||
var mHandler: Handler = object : Handler(Looper.getMainLooper()) {
|
|
||||||
override fun handleMessage(msg: android.os.Message) {
|
|
||||||
if (!isMotionEventUp && isEnabled) {
|
|
||||||
performClick()
|
|
||||||
this.sendEmptyMessageDelayed(0, LONG_CLICK_ACTION_INTERVAL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
this.setOnLongClickListener {
|
|
||||||
isMotionEventUp = false
|
|
||||||
mHandler.sendEmptyMessage(0)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
this.setOnTouchListener { _, event ->
|
|
||||||
if (event.action == MotionEvent.ACTION_UP) {
|
|
||||||
isMotionEventUp = true
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun performClick(): Boolean {
|
|
||||||
return super.performClick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
package io.neoterm.frontend.terminal.extrakey.button
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.Button
|
|
||||||
import android.widget.ToggleButton
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
open class StatedControlButton @JvmOverloads constructor(text: String, var initState: Boolean = false) :
|
|
||||||
ControlButton(text) {
|
|
||||||
var toggleButton: ToggleButton? = null
|
|
||||||
|
|
||||||
override fun onClick(view: View) {
|
|
||||||
setStatus(toggleButton?.isChecked)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
|
|
||||||
val outerButton = ToggleButton(context, null, android.R.attr.buttonBarButtonStyle)
|
|
||||||
|
|
||||||
outerButton.isClickable = true
|
|
||||||
if (initState) {
|
|
||||||
outerButton.isChecked = true
|
|
||||||
outerButton.setTextColor(IExtraButton.SELECTED_TEXT_COLOR)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.toggleButton = outerButton
|
|
||||||
return outerButton
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setStatus(status: Boolean?) {
|
|
||||||
val button = toggleButton
|
|
||||||
if (button != null && status != null) {
|
|
||||||
button.isChecked = status
|
|
||||||
button.setTextColor(
|
|
||||||
if (status) SELECTED_TEXT_COLOR
|
|
||||||
else NORMAL_TEXT_COLOR
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun readState(): Boolean {
|
|
||||||
val button = toggleButton ?: return false
|
|
||||||
|
|
||||||
if (button.isPressed) return true
|
|
||||||
val result = button.isChecked
|
|
||||||
if (result) {
|
|
||||||
button.isChecked = false
|
|
||||||
button.setTextColor(NORMAL_TEXT_COLOR)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package io.neoterm.frontend.terminal.extrakey.button
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.Button
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.combine.CombinedSequence
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
|
|
||||||
open class TextButton constructor(text: String, val withEnter: Boolean = false) : IExtraButton() {
|
|
||||||
init {
|
|
||||||
this.buttonKeys = CombinedSequence.solveString(text)
|
|
||||||
this.displayText = text
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClick(view: View) {
|
|
||||||
buttonKeys!!.keys.forEach {
|
|
||||||
sendKey(view, it)
|
|
||||||
}
|
|
||||||
if (withEnter) {
|
|
||||||
sendKey(view, "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
|
|
||||||
return Button(context, attrs, defStyleAttr)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package io.neoterm.frontend.terminal.extrakey.impl
|
|
||||||
|
|
||||||
import io.neoterm.frontend.terminal.extrakey.button.RepeatableButton
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ArrowButton(arrowText: String) : RepeatableButton(arrowText)
|
|
@ -14,11 +14,11 @@ import androidx.core.app.NotificationCompat
|
|||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.EmulatorDebug
|
import io.neoterm.backend.EmulatorDebug
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.frontend.logging.NLog
|
import io.neoterm.component.session.ShellParameter
|
||||||
import io.neoterm.frontend.session.shell.ShellParameter
|
import io.neoterm.component.session.XParameter
|
||||||
import io.neoterm.frontend.session.xorg.XParameter
|
import io.neoterm.component.session.XSession
|
||||||
import io.neoterm.frontend.session.xorg.XSession
|
|
||||||
import io.neoterm.ui.term.NeoTermActivity
|
import io.neoterm.ui.term.NeoTermActivity
|
||||||
|
import io.neoterm.utils.NLog
|
||||||
import io.neoterm.utils.Terminals
|
import io.neoterm.utils.Terminals
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
package io.neoterm.setup
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
interface ResultListener {
|
|
||||||
fun onResult(error: Exception?)
|
|
||||||
}
|
|
@ -5,8 +5,8 @@ import android.system.Os;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import io.neoterm.backend.EmulatorDebug;
|
import io.neoterm.backend.EmulatorDebug;
|
||||||
import io.neoterm.frontend.config.NeoTermPath;
|
import io.neoterm.component.config.NeoTermPath;
|
||||||
import io.neoterm.frontend.logging.NLog;
|
import io.neoterm.utils.NLog;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -8,8 +8,6 @@ import java.io.InputStream;
|
|||||||
*/
|
*/
|
||||||
public interface SourceConnection {
|
public interface SourceConnection {
|
||||||
InputStream getInputStream() throws IOException;
|
InputStream getInputStream() throws IOException;
|
||||||
|
|
||||||
int getSize();
|
int getSize();
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user