janito 1.9.0__py3-none-any.whl → 1.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- janito/__init__.py +1 -1
- janito/agent/api_exceptions.py +4 -0
- janito/agent/config.py +1 -1
- janito/agent/config_defaults.py +2 -26
- janito/agent/conversation.py +163 -122
- janito/agent/conversation_api.py +246 -168
- janito/agent/conversation_ui.py +1 -1
- janito/agent/{conversation_history.py → llm_conversation_history.py} +30 -1
- janito/agent/openai_client.py +38 -23
- janito/agent/openai_schema_generator.py +162 -129
- janito/agent/platform_discovery.py +134 -77
- janito/agent/profile_manager.py +5 -5
- janito/agent/rich_message_handler.py +80 -31
- janito/agent/templates/profiles/system_prompt_template_base.txt.j2 +20 -4
- janito/agent/test_openai_schema_generator.py +93 -0
- janito/agent/tool_base.py +7 -2
- janito/agent/tool_executor.py +54 -49
- janito/agent/tool_registry.py +5 -2
- janito/agent/tool_use_tracker.py +26 -5
- janito/agent/tools/__init__.py +8 -3
- janito/agent/tools/create_directory.py +3 -1
- janito/agent/tools/create_file.py +7 -1
- janito/agent/tools/fetch_url.py +40 -3
- janito/agent/tools/find_files.py +29 -14
- janito/agent/tools/get_file_outline/core.py +7 -8
- janito/agent/tools/get_file_outline/python_outline.py +139 -95
- janito/agent/tools/get_file_outline/search_outline.py +3 -1
- janito/agent/tools/get_lines.py +98 -64
- janito/agent/tools/move_file.py +59 -31
- janito/agent/tools/open_url.py +31 -0
- janito/agent/tools/present_choices.py +3 -1
- janito/agent/tools/python_command_runner.py +149 -0
- janito/agent/tools/python_file_runner.py +147 -0
- janito/agent/tools/python_stdin_runner.py +153 -0
- janito/agent/tools/remove_directory.py +3 -1
- janito/agent/tools/remove_file.py +5 -1
- janito/agent/tools/replace_file.py +12 -2
- janito/agent/tools/replace_text_in_file.py +195 -149
- janito/agent/tools/run_bash_command.py +30 -69
- janito/agent/tools/run_powershell_command.py +138 -105
- janito/agent/tools/search_text/__init__.py +1 -0
- janito/agent/tools/search_text/core.py +176 -0
- janito/agent/tools/search_text/match_lines.py +58 -0
- janito/agent/tools/search_text/pattern_utils.py +65 -0
- janito/agent/tools/search_text/traverse_directory.py +127 -0
- janito/agent/tools/validate_file_syntax/core.py +43 -30
- janito/agent/tools/validate_file_syntax/html_validator.py +21 -5
- janito/agent/tools/validate_file_syntax/markdown_validator.py +77 -34
- janito/agent/tools_utils/action_type.py +7 -0
- janito/agent/tools_utils/dir_walk_utils.py +3 -2
- janito/agent/tools_utils/formatting.py +47 -21
- janito/agent/tools_utils/gitignore_utils.py +89 -40
- janito/agent/tools_utils/test_gitignore_utils.py +46 -0
- janito/agent/tools_utils/utils.py +7 -1
- janito/cli/_print_config.py +63 -61
- janito/cli/arg_parser.py +13 -12
- janito/cli/cli_main.py +137 -147
- janito/cli/config_commands.py +112 -109
- janito/cli/main.py +152 -174
- janito/cli/one_shot.py +40 -26
- janito/i18n/__init__.py +1 -1
- janito/rich_utils.py +46 -8
- janito/shell/commands/__init__.py +2 -4
- janito/shell/commands/conversation_restart.py +3 -1
- janito/shell/commands/edit.py +3 -0
- janito/shell/commands/history_view.py +3 -3
- janito/shell/commands/lang.py +3 -0
- janito/shell/commands/livelogs.py +5 -3
- janito/shell/commands/prompt.py +6 -0
- janito/shell/commands/session.py +3 -0
- janito/shell/commands/session_control.py +3 -0
- janito/shell/commands/termweb_log.py +8 -0
- janito/shell/commands/tools.py +3 -0
- janito/shell/commands/track.py +36 -0
- janito/shell/commands/utility.py +13 -18
- janito/shell/commands/verbose.py +3 -4
- janito/shell/input_history.py +62 -0
- janito/shell/main.py +160 -181
- janito/shell/session/config.py +83 -75
- janito/shell/session/manager.py +0 -21
- janito/shell/ui/interactive.py +97 -75
- janito/termweb/static/editor.css +32 -33
- janito/termweb/static/editor.css.bak +140 -22
- janito/termweb/static/editor.html +12 -7
- janito/termweb/static/editor.html.bak +16 -11
- janito/termweb/static/editor.js +94 -40
- janito/termweb/static/editor.js.bak +97 -65
- janito/termweb/static/index.html +1 -2
- janito/termweb/static/index.html.bak +1 -1
- janito/termweb/static/termweb.css +1 -22
- janito/termweb/static/termweb.css.bak +6 -4
- janito/termweb/static/termweb.js +0 -6
- janito/termweb/static/termweb.js.bak +1 -2
- janito/tests/test_rich_utils.py +44 -0
- janito/web/app.py +0 -75
- {janito-1.9.0.dist-info → janito-1.11.0.dist-info}/METADATA +61 -42
- janito-1.11.0.dist-info/RECORD +163 -0
- {janito-1.9.0.dist-info → janito-1.11.0.dist-info}/WHEEL +1 -1
- janito/agent/providers.py +0 -77
- janito/agent/tools/run_python_command.py +0 -161
- janito/agent/tools/search_text.py +0 -204
- janito/shell/commands/sum.py +0 -49
- janito-1.9.0.dist-info/RECORD +0 -151
- {janito-1.9.0.dist-info → janito-1.11.0.dist-info}/entry_points.txt +0 -0
- {janito-1.9.0.dist-info → janito-1.11.0.dist-info}/licenses/LICENSE +0 -0
- {janito-1.9.0.dist-info → janito-1.11.0.dist-info}/top_level.txt +0 -0
janito/shell/session/config.py
CHANGED
@@ -12,90 +12,98 @@ def handle_config_shell(console, *args, **kwargs):
|
|
12
12
|
/config reset global
|
13
13
|
"""
|
14
14
|
if not args or args[0] not in ("show", "set", "reset"):
|
15
|
-
console
|
16
|
-
"[bold red]Usage:[/bold red] /config show | /config set local|global key=value | /config reset local|global"
|
17
|
-
)
|
15
|
+
_print_usage(console)
|
18
16
|
return
|
19
|
-
|
20
17
|
if args[0] == "show":
|
21
|
-
|
22
|
-
from janito.cli._print_config import print_full_config
|
23
|
-
|
24
|
-
print_full_config(
|
25
|
-
local_config,
|
26
|
-
global_config,
|
27
|
-
unified_config,
|
28
|
-
CONFIG_DEFAULTS,
|
29
|
-
console=console,
|
30
|
-
)
|
18
|
+
_show_config(console)
|
31
19
|
return
|
32
|
-
|
33
20
|
if args[0] == "reset":
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
21
|
+
_reset_config(console, args)
|
22
|
+
return
|
23
|
+
if args[0] == "set":
|
24
|
+
_set_config(console, args)
|
25
|
+
return
|
39
26
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
console.print(
|
62
|
-
"[bold yellow]Please use /restart for changes to take full effect.[/bold yellow]"
|
63
|
-
)
|
27
|
+
|
28
|
+
def _print_usage(console):
|
29
|
+
console.print(
|
30
|
+
"[bold red]Usage:[/bold red] /config show | /config set local|global key=value | /config reset local|global"
|
31
|
+
)
|
32
|
+
|
33
|
+
|
34
|
+
def _show_config(console):
|
35
|
+
from janito.cli._print_config import print_full_config
|
36
|
+
|
37
|
+
print_full_config(
|
38
|
+
local_config,
|
39
|
+
global_config,
|
40
|
+
unified_config,
|
41
|
+
CONFIG_DEFAULTS,
|
42
|
+
console=console,
|
43
|
+
)
|
44
|
+
|
45
|
+
|
46
|
+
def _reset_config(console, args):
|
47
|
+
if len(args) < 2 or args[1] not in ("local", "global"):
|
48
|
+
console.print("[bold red]Usage:[/bold red] /config reset local|global")
|
64
49
|
return
|
50
|
+
import os
|
51
|
+
from pathlib import Path
|
65
52
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
)
|
71
|
-
|
72
|
-
|
73
|
-
try:
|
74
|
-
key, val = args[2].split("=", 1)
|
75
|
-
except ValueError:
|
76
|
-
console.print("[bold red]Invalid format, expected key=val[/bold red]")
|
77
|
-
return
|
78
|
-
key = key.strip()
|
79
|
-
if key not in CONFIG_OPTIONS and not key.startswith("template."):
|
80
|
-
console.print(
|
81
|
-
f"[bold red]Invalid config key: '{key}'. Supported keys are: {', '.join(CONFIG_OPTIONS.keys())}"
|
82
|
-
)
|
83
|
-
return
|
84
|
-
val = val.strip()
|
85
|
-
if scope == "local":
|
86
|
-
local_config.set(key, val)
|
87
|
-
local_config.save()
|
88
|
-
runtime_config.set(key, val)
|
89
|
-
console.print(f"[green]Local config updated:[/green] {key} = {val}")
|
53
|
+
scope = args[1]
|
54
|
+
if scope == "local":
|
55
|
+
local_path = Path(".janito/config.json")
|
56
|
+
if local_path.exists():
|
57
|
+
os.remove(local_path)
|
58
|
+
console.print(f"[green]Removed local config file:[/green] {local_path}")
|
59
|
+
else:
|
90
60
|
console.print(
|
91
|
-
"[
|
61
|
+
f"[yellow]Local config file does not exist:[/yellow] {local_path}"
|
92
62
|
)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
console.print(f"[green]
|
63
|
+
elif scope == "global":
|
64
|
+
global_path = Path.home() / ".janito/config.json"
|
65
|
+
if global_path.exists():
|
66
|
+
os.remove(global_path)
|
67
|
+
console.print(f"[green]Removed global config file:[/green] {global_path}")
|
68
|
+
else:
|
98
69
|
console.print(
|
99
|
-
"[
|
70
|
+
f"[yellow]Global config file does not exist:[/yellow] {global_path}"
|
100
71
|
)
|
72
|
+
console.print(
|
73
|
+
"[bold yellow]Please use /restart for changes to take full effect.[/bold yellow]"
|
74
|
+
)
|
75
|
+
|
76
|
+
|
77
|
+
def _set_config(console, args):
|
78
|
+
if len(args) < 3 or args[1] not in ("local", "global"):
|
79
|
+
console.print("[bold red]Usage:[/bold red] /config set local|global key=value")
|
101
80
|
return
|
81
|
+
scope = args[1]
|
82
|
+
try:
|
83
|
+
key, val = args[2].split("=", 1)
|
84
|
+
except ValueError:
|
85
|
+
console.print("[bold red]Invalid format, expected key=val[/bold red]")
|
86
|
+
return
|
87
|
+
key = key.strip()
|
88
|
+
if key not in CONFIG_OPTIONS and not key.startswith("template."):
|
89
|
+
console.print(
|
90
|
+
f"[bold red]Invalid config key: '{key}'. Supported keys are: {', '.join(CONFIG_OPTIONS.keys())}"
|
91
|
+
)
|
92
|
+
return
|
93
|
+
val = val.strip()
|
94
|
+
if scope == "local":
|
95
|
+
local_config.set(key, val)
|
96
|
+
local_config.save()
|
97
|
+
runtime_config.set(key, val)
|
98
|
+
console.print(f"[green]Local config updated:[/green] {key} = {val}")
|
99
|
+
console.print(
|
100
|
+
"[bold yellow]Please use /restart for changes to take full effect.[/bold yellow]"
|
101
|
+
)
|
102
|
+
elif scope == "global":
|
103
|
+
global_config.set(key, val)
|
104
|
+
global_config.save()
|
105
|
+
runtime_config.set(key, val)
|
106
|
+
console.print(f"[green]Global config updated:[/green] {key} = {val}")
|
107
|
+
console.print(
|
108
|
+
"[bold yellow]Please use /restart for changes to take full effect.[/bold yellow]"
|
109
|
+
)
|
janito/shell/session/manager.py
CHANGED
@@ -89,27 +89,6 @@ def save_conversation(messages, prompts, usage_info=None, path=None):
|
|
89
89
|
json.dump(data, f, indent=2, default=usage_serializer)
|
90
90
|
|
91
91
|
|
92
|
-
def load_input_history():
|
93
|
-
history_dir = os.path.join(".janito", "input_history")
|
94
|
-
os.makedirs(history_dir, exist_ok=True)
|
95
|
-
today_str = datetime.now().strftime("%y%m%d")
|
96
|
-
history_file = os.path.join(history_dir, f"{today_str}.json")
|
97
|
-
try:
|
98
|
-
with open(history_file, "r", encoding="utf-8") as f:
|
99
|
-
return json.load(f)
|
100
|
-
except (FileNotFoundError, json.JSONDecodeError):
|
101
|
-
return []
|
102
|
-
|
103
|
-
|
104
|
-
def save_input_history(history_list):
|
105
|
-
history_dir = os.path.join(".janito", "input_history")
|
106
|
-
os.makedirs(history_dir, exist_ok=True)
|
107
|
-
today_str = datetime.now().strftime("%y%m%d")
|
108
|
-
history_file = os.path.join(history_dir, f"{today_str}.json")
|
109
|
-
with open(history_file, "w", encoding="utf-8") as f:
|
110
|
-
json.dump(history_list, f, indent=2)
|
111
|
-
|
112
|
-
|
113
92
|
def last_conversation_exists(path=".janito/last_conversation.json"):
|
114
93
|
if not os.path.exists(path):
|
115
94
|
return False
|
janito/shell/ui/interactive.py
CHANGED
@@ -17,15 +17,99 @@ def print_welcome(console, version=None, continue_id=None):
|
|
17
17
|
if runtime_config.get("vanilla_mode", False):
|
18
18
|
console.print(
|
19
19
|
f"[bold magenta]{tr('Welcome to Janito{version_str} in [white on magenta]VANILLA MODE[/white on magenta]! Tools, system prompt, and temperature are disabled unless overridden.', version_str=version_str)}[/bold magenta]\n"
|
20
|
-
f"[cyan]{tr('F12 = Quick Action (follows the recommended action)')}[/cyan]"
|
21
20
|
)
|
22
21
|
else:
|
23
22
|
console.print(
|
24
23
|
f"[bold green]{tr('Welcome to Janito{version_str}! Entering chat mode. Type /exit to exit.', version_str=version_str)}[/bold green]\n"
|
25
|
-
f"[cyan]{tr('F12 = Quick Action (follows the recommended action)')}[/cyan]"
|
26
24
|
)
|
27
25
|
|
28
26
|
|
27
|
+
def format_tokens(n, tag=None):
|
28
|
+
if n is None:
|
29
|
+
return "?"
|
30
|
+
if n < 1000:
|
31
|
+
val = str(n)
|
32
|
+
elif n < 1000000:
|
33
|
+
val = f"{n/1000:.1f}k"
|
34
|
+
else:
|
35
|
+
val = f"{n/1000000:.1f}M"
|
36
|
+
return f"<{tag}>{val}</{tag}>" if tag else val
|
37
|
+
|
38
|
+
|
39
|
+
def assemble_first_line(model_name, role_ref, style_ref):
|
40
|
+
model_part = f" {tr('Model')}: <model>{model_name}</model>" if model_name else ""
|
41
|
+
role_part = ""
|
42
|
+
vanilla_mode = runtime_config.get("vanilla_mode", False)
|
43
|
+
if role_ref and not vanilla_mode:
|
44
|
+
role = role_ref()
|
45
|
+
if role:
|
46
|
+
role_part = f"{tr('Role')}: <role>{role}</role>"
|
47
|
+
style_part = ""
|
48
|
+
if style_ref:
|
49
|
+
style = style_ref()
|
50
|
+
if style:
|
51
|
+
style_part = f"{tr('Style')}: <b>{style}</b>"
|
52
|
+
first_line_parts = []
|
53
|
+
if model_part:
|
54
|
+
first_line_parts.append(model_part)
|
55
|
+
if role_part:
|
56
|
+
first_line_parts.append(role_part)
|
57
|
+
if style_part:
|
58
|
+
first_line_parts.append(style_part)
|
59
|
+
return " | ".join(first_line_parts)
|
60
|
+
|
61
|
+
|
62
|
+
def assemble_second_line(
|
63
|
+
width,
|
64
|
+
last_usage_info_ref,
|
65
|
+
history_ref,
|
66
|
+
messages_ref,
|
67
|
+
session_id,
|
68
|
+
model_name,
|
69
|
+
role_ref,
|
70
|
+
style_ref,
|
71
|
+
):
|
72
|
+
usage = last_usage_info_ref()
|
73
|
+
prompt_tokens = usage.get("prompt_tokens") if usage else None
|
74
|
+
completion_tokens = usage.get("completion_tokens") if usage else None
|
75
|
+
total_tokens = usage.get("total_tokens") if usage else None
|
76
|
+
msg_count = len(history_ref()) if history_ref else len(messages_ref())
|
77
|
+
left = f" {tr('Messages')}: <msg_count>{msg_count}</msg_count>"
|
78
|
+
tokens_part = ""
|
79
|
+
if (
|
80
|
+
prompt_tokens is not None
|
81
|
+
or completion_tokens is not None
|
82
|
+
or total_tokens is not None
|
83
|
+
):
|
84
|
+
tokens_part = (
|
85
|
+
f" | {tr('Tokens')} - {tr('Prompt')}: {format_tokens(prompt_tokens, 'tokens_in')}, "
|
86
|
+
f"{tr('Completion')}: {format_tokens(completion_tokens, 'tokens_out')}, "
|
87
|
+
f"{tr('Total')}: {format_tokens(total_tokens, 'tokens_total')}"
|
88
|
+
)
|
89
|
+
session_part = (
|
90
|
+
f" | Session ID: <session_id>{session_id}</session_id>" if session_id else ""
|
91
|
+
)
|
92
|
+
second_line = f"{left}{tokens_part}{session_part}"
|
93
|
+
total_len = len(left) + len(tokens_part) + len(session_part)
|
94
|
+
first_line = assemble_first_line(model_name, role_ref, style_ref)
|
95
|
+
if first_line:
|
96
|
+
total_len += len(first_line) + 3
|
97
|
+
if total_len < width:
|
98
|
+
padding = " " * (width - total_len)
|
99
|
+
second_line = f"{left}{tokens_part}{session_part}{padding}"
|
100
|
+
return second_line
|
101
|
+
|
102
|
+
|
103
|
+
def assemble_bindings_line():
|
104
|
+
return (
|
105
|
+
f"<b> F12</b>: {tr('Quick Action')} | "
|
106
|
+
f"<b>Ctrl-Y</b>: {tr('Yes')} | "
|
107
|
+
f"<b>Ctrl-N</b>: {tr('No')} | "
|
108
|
+
f"<b>/help</b>: {tr('Help')} | "
|
109
|
+
f"<b>/restart</b>: {tr('Reset Conversation')}"
|
110
|
+
)
|
111
|
+
|
112
|
+
|
29
113
|
def get_toolbar_func(
|
30
114
|
messages_ref,
|
31
115
|
last_usage_info_ref,
|
@@ -39,82 +123,20 @@ def get_toolbar_func(
|
|
39
123
|
):
|
40
124
|
from prompt_toolkit.application.current import get_app
|
41
125
|
|
42
|
-
def format_tokens(n, tag=None):
|
43
|
-
if n is None:
|
44
|
-
return "?"
|
45
|
-
if n < 1000:
|
46
|
-
val = str(n)
|
47
|
-
elif n < 1000000:
|
48
|
-
val = f"{n/1000:.1f}k"
|
49
|
-
else:
|
50
|
-
val = f"{n/1000000:.1f}M"
|
51
|
-
return f"<{tag}>{val}</{tag}>" if tag else val
|
52
|
-
|
53
126
|
def get_toolbar():
|
54
127
|
width = get_app().output.get_size().columns
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
style_part = ""
|
66
|
-
if style_ref:
|
67
|
-
style = style_ref()
|
68
|
-
if style:
|
69
|
-
style_part = f"{tr('Style')}: <b>{style}</b>"
|
70
|
-
usage = last_usage_info_ref()
|
71
|
-
prompt_tokens = usage.get("prompt_tokens") if usage else None
|
72
|
-
completion_tokens = usage.get("completion_tokens") if usage else None
|
73
|
-
total_tokens = usage.get("total_tokens") if usage else None
|
74
|
-
first_line_parts = []
|
75
|
-
if model_part:
|
76
|
-
first_line_parts.append(model_part)
|
77
|
-
|
78
|
-
if role_part:
|
79
|
-
first_line_parts.append(role_part)
|
80
|
-
if style_part:
|
81
|
-
first_line_parts.append(style_part)
|
82
|
-
first_line = " | ".join(first_line_parts)
|
83
|
-
msg_count = len(history_ref()) if history_ref else len(messages_ref())
|
84
|
-
left = f" {tr('Messages')}: <msg_count>{msg_count}</msg_count>"
|
85
|
-
tokens_part = ""
|
86
|
-
if (
|
87
|
-
prompt_tokens is not None
|
88
|
-
or completion_tokens is not None
|
89
|
-
or total_tokens is not None
|
90
|
-
):
|
91
|
-
tokens_part = (
|
92
|
-
f" | {tr('Tokens')} - {tr('Prompt')}: {format_tokens(prompt_tokens, 'tokens_in')}, "
|
93
|
-
f"{tr('Completion')}: {format_tokens(completion_tokens, 'tokens_out')}, "
|
94
|
-
f"{tr('Total')}: {format_tokens(total_tokens, 'tokens_total')}"
|
95
|
-
)
|
96
|
-
# Move /help and /restart tips to key bindings/info line
|
97
|
-
# Compose second/status line (no help_part)
|
98
|
-
session_part = (
|
99
|
-
f" | Session ID: <session_id>{session_id}</session_id>"
|
100
|
-
if session_id
|
101
|
-
else ""
|
102
|
-
)
|
103
|
-
second_line = f"{left}{tokens_part}{session_part}"
|
104
|
-
total_len = len(left) + len(tokens_part) + len(session_part)
|
105
|
-
if first_line:
|
106
|
-
total_len += len(first_line) + 3
|
107
|
-
if total_len < width:
|
108
|
-
padding = " " * (width - total_len)
|
109
|
-
second_line = f"{left}{tokens_part}{session_part}{padding}"
|
110
|
-
# Add key bindings info as an extra line, now including /help and /restart
|
111
|
-
bindings_line = (
|
112
|
-
f"<b> F12</b>: {tr('Quick Action')} | "
|
113
|
-
f"<b>Ctrl-Y</b>: {tr('Yes')} | "
|
114
|
-
f"<b>Ctrl-N</b>: {tr('No')} | "
|
115
|
-
f"<b>/help</b>: {tr('Help')} | "
|
116
|
-
f"<b>/restart</b>: {tr('Reset Conversation')}"
|
128
|
+
first_line = assemble_first_line(model_name, role_ref, style_ref)
|
129
|
+
second_line = assemble_second_line(
|
130
|
+
width,
|
131
|
+
last_usage_info_ref,
|
132
|
+
history_ref,
|
133
|
+
messages_ref,
|
134
|
+
session_id,
|
135
|
+
model_name,
|
136
|
+
role_ref,
|
137
|
+
style_ref,
|
117
138
|
)
|
139
|
+
bindings_line = assemble_bindings_line()
|
118
140
|
if first_line:
|
119
141
|
toolbar_text = first_line + "\n" + second_line + "\n" + bindings_line
|
120
142
|
else:
|
janito/termweb/static/editor.css
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
/* Highlight active line in CodeMirror */
|
2
2
|
.CodeMirror-activeline-background {
|
3
|
-
background: #353b45
|
3
|
+
background: #353b45;
|
4
4
|
}
|
5
5
|
body.light-theme .CodeMirror-activeline-background {
|
6
|
-
background: #e0eaff
|
6
|
+
background: #e0eaff;
|
7
7
|
}
|
8
8
|
html, body {
|
9
9
|
height: 100%;
|
@@ -39,36 +39,22 @@ body.light-theme {
|
|
39
39
|
flex-direction: column;
|
40
40
|
height: 100%;
|
41
41
|
min-height: 0;
|
42
|
-
padding: 0
|
43
|
-
margin: 0
|
44
|
-
}
|
45
|
-
.CodeMirror {
|
46
|
-
flex: 1 1 auto;
|
47
|
-
height: 100% !important;
|
48
|
-
min-height: 0;
|
49
|
-
font-size: 1.1em;
|
50
|
-
background: #282a36;
|
51
|
-
color: #f8f8f2;
|
52
|
-
border-radius: 0;
|
53
|
-
border: none;
|
54
|
-
transition: background 0.2s, color 0.2s;
|
55
|
-
}
|
56
|
-
body.light-theme .CodeMirror {
|
57
|
-
background: #fff;
|
58
|
-
color: #222;
|
42
|
+
padding: 0;
|
43
|
+
margin: 0;
|
59
44
|
}
|
45
|
+
/* Removed custom .CodeMirror background/color to use CodeMirror's theme defaults */
|
60
46
|
.header {
|
61
47
|
background: #222;
|
62
48
|
color: #fff;
|
63
|
-
padding:
|
64
|
-
font-size:
|
49
|
+
padding: 4px 12px;
|
50
|
+
font-size: 0.95em;
|
65
51
|
font-weight: bold;
|
66
52
|
position: relative;
|
67
53
|
transition: background 0.2s, color 0.2s;
|
68
54
|
display: flex;
|
69
55
|
align-items: center;
|
70
56
|
justify-content: flex-end;
|
71
|
-
height:
|
57
|
+
height: 36px;
|
72
58
|
}
|
73
59
|
|
74
60
|
.header-title {
|
@@ -78,24 +64,39 @@ body.light-theme .CodeMirror {
|
|
78
64
|
transform: translate(-50%, -50%);
|
79
65
|
pointer-events: none;
|
80
66
|
font-weight: bold;
|
81
|
-
font-size: 1.
|
67
|
+
font-size: 1.05em;
|
68
|
+
display: flex;
|
69
|
+
align-items: center;
|
70
|
+
gap: 0.5em;
|
71
|
+
}
|
72
|
+
|
73
|
+
.filename-display {
|
74
|
+
font-weight: normal;
|
75
|
+
font-size: 0.98em;
|
76
|
+
color: #bbb;
|
77
|
+
margin-left: 0.5em;
|
78
|
+
pointer-events: auto;
|
79
|
+
text-overflow: ellipsis;
|
80
|
+
white-space: nowrap;
|
81
|
+
overflow: hidden;
|
82
|
+
max-width: 180px;
|
83
|
+
}
|
84
|
+
body.light-theme .filename-display {
|
85
|
+
color: #666;
|
82
86
|
}
|
83
87
|
|
84
88
|
.footer {
|
85
89
|
width: 100%;
|
86
90
|
background: #23272b;
|
87
91
|
color: #fff;
|
88
|
-
padding:
|
92
|
+
padding: 4px 12px;
|
89
93
|
box-sizing: border-box;
|
90
94
|
display: flex;
|
91
95
|
align-items: center;
|
92
96
|
justify-content: flex-start;
|
93
|
-
position: fixed;
|
94
|
-
bottom: 0;
|
95
|
-
left: 0;
|
96
|
-
z-index: 100;
|
97
97
|
border-top: 1px solid #333;
|
98
|
-
min-height:
|
98
|
+
min-height: 28px;
|
99
|
+
font-size: 0.95em;
|
99
100
|
}
|
100
101
|
|
101
102
|
.save-btn {
|
@@ -106,7 +107,6 @@ body.light-theme .CodeMirror {
|
|
106
107
|
margin-left: auto;
|
107
108
|
}
|
108
109
|
|
109
|
-
|
110
110
|
.save-btn {
|
111
111
|
background: #4caf50;
|
112
112
|
color: #fff;
|
@@ -121,8 +121,8 @@ body.light-theme .CodeMirror {
|
|
121
121
|
display: flex;
|
122
122
|
align-items: center;
|
123
123
|
justify-content: center;
|
124
|
-
|
125
|
-
|
124
|
+
height: 100%;
|
125
|
+
aspect-ratio: 1/1;
|
126
126
|
font-size: 1.3em;
|
127
127
|
line-height: 1;
|
128
128
|
padding: 0;
|
@@ -143,4 +143,3 @@ body.light-theme .header {
|
|
143
143
|
background: #eaeaea;
|
144
144
|
color: #222;
|
145
145
|
}
|
146
|
-
|
@@ -1,27 +1,145 @@
|
|
1
|
+
/* Highlight active line in CodeMirror */
|
2
|
+
.CodeMirror-activeline-background {
|
3
|
+
background: #353b45;
|
4
|
+
}
|
5
|
+
body.light-theme .CodeMirror-activeline-background {
|
6
|
+
background: #e0eaff;
|
7
|
+
}
|
8
|
+
html, body {
|
9
|
+
height: 100%;
|
10
|
+
margin: 0;
|
11
|
+
padding: 0;
|
12
|
+
}
|
13
|
+
body {
|
14
|
+
display: flex;
|
15
|
+
flex-direction: column;
|
16
|
+
min-height: 100vh;
|
17
|
+
background: #181a1b;
|
18
|
+
color: #eee;
|
19
|
+
transition: background 0.2s, color 0.2s;
|
20
|
+
}
|
21
|
+
body.light-theme {
|
22
|
+
background: #f5f5f5;
|
23
|
+
color: #222;
|
24
|
+
}
|
25
|
+
.main {
|
26
|
+
flex: 1 1 auto;
|
27
|
+
display: flex;
|
28
|
+
flex-direction: column;
|
29
|
+
justify-content: stretch;
|
30
|
+
align-items: stretch;
|
31
|
+
min-height: 0;
|
32
|
+
padding: 0;
|
33
|
+
margin: 0;
|
34
|
+
height: 100%;
|
35
|
+
}
|
36
|
+
.editor-pane {
|
37
|
+
flex: 1 1 auto;
|
38
|
+
display: flex;
|
39
|
+
flex-direction: column;
|
40
|
+
height: 100%;
|
41
|
+
min-height: 0;
|
42
|
+
padding: 0;
|
43
|
+
margin: 0;
|
44
|
+
}
|
45
|
+
/* Removed custom .CodeMirror background/color to use CodeMirror's theme defaults */
|
46
|
+
.header {
|
47
|
+
background: #222;
|
48
|
+
color: #fff;
|
49
|
+
padding: 4px 12px;
|
50
|
+
font-size: 0.95em;
|
51
|
+
font-weight: bold;
|
52
|
+
position: relative;
|
53
|
+
transition: background 0.2s, color 0.2s;
|
54
|
+
display: flex;
|
55
|
+
align-items: center;
|
56
|
+
justify-content: flex-end;
|
57
|
+
height: 36px;
|
58
|
+
}
|
59
|
+
|
60
|
+
.header-title {
|
61
|
+
position: absolute;
|
62
|
+
left: 50%;
|
63
|
+
top: 50%;
|
64
|
+
transform: translate(-50%, -50%);
|
65
|
+
pointer-events: none;
|
66
|
+
font-weight: bold;
|
67
|
+
font-size: 1.05em;
|
68
|
+
display: flex;
|
69
|
+
align-items: center;
|
70
|
+
gap: 0.5em;
|
71
|
+
}
|
72
|
+
|
73
|
+
.filename-display {
|
74
|
+
font-weight: normal;
|
75
|
+
font-size: 0.98em;
|
76
|
+
color: #bbb;
|
77
|
+
margin-left: 0.5em;
|
78
|
+
pointer-events: auto;
|
79
|
+
text-overflow: ellipsis;
|
80
|
+
white-space: nowrap;
|
81
|
+
overflow: hidden;
|
82
|
+
max-width: 180px;
|
83
|
+
}
|
84
|
+
body.light-theme .filename-display {
|
85
|
+
color: #666;
|
86
|
+
}
|
87
|
+
|
88
|
+
.footer {
|
89
|
+
width: 100%;
|
90
|
+
background: #23272b;
|
91
|
+
color: #fff;
|
92
|
+
padding: 4px 12px;
|
93
|
+
box-sizing: border-box;
|
94
|
+
display: flex;
|
95
|
+
align-items: center;
|
96
|
+
justify-content: flex-start;
|
97
|
+
border-top: 1px solid #333;
|
98
|
+
min-height: 28px;
|
99
|
+
font-size: 0.95em;
|
100
|
+
}
|
1
101
|
|
2
102
|
.save-btn {
|
3
|
-
|
4
|
-
|
103
|
+
/* No margin needed, align left in footer */
|
104
|
+
}
|
105
|
+
|
106
|
+
.theme-switcher {
|
107
|
+
margin-left: auto;
|
108
|
+
}
|
109
|
+
|
110
|
+
.save-btn {
|
111
|
+
background: #4caf50;
|
112
|
+
color: #fff;
|
113
|
+
border: none;
|
114
|
+
border-radius: 4px;
|
115
|
+
padding: 6px 14px;
|
116
|
+
cursor: pointer;
|
117
|
+
font-size: 1em;
|
118
|
+
}
|
119
|
+
|
120
|
+
.theme-switcher {
|
121
|
+
display: flex;
|
122
|
+
align-items: center;
|
123
|
+
justify-content: center;
|
124
|
+
width: 36px;
|
125
|
+
height: 36px;
|
126
|
+
font-size: 1.3em;
|
127
|
+
line-height: 1;
|
128
|
+
padding: 0;
|
129
|
+
background: #444;
|
130
|
+
color: #fff;
|
5
131
|
border: none;
|
6
|
-
border-radius:
|
7
|
-
padding: 12px 38px;
|
132
|
+
border-radius: 4px;
|
8
133
|
cursor: pointer;
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
text-shadow: 0 2px 8px #fff8, 0 1px 0 #fff8;
|
21
|
-
}
|
22
|
-
.save-btn:hover, .save-btn:focus {
|
23
|
-
background: linear-gradient(90deg, #00cfff 0%, #00ff99 100%);
|
24
|
-
color: #111;
|
25
|
-
box-shadow: 0 0 24px 6px rgba(0,255,153,0.45), 0 4px 24px 0 rgba(0,207,255,0.28);
|
26
|
-
outline: 3px solid #00ff99;
|
134
|
+
transition: background 0.2s, color 0.2s;
|
135
|
+
}
|
136
|
+
|
137
|
+
body.light-theme .theme-switcher {
|
138
|
+
background: #ddd;
|
139
|
+
color: #222;
|
140
|
+
}
|
141
|
+
|
142
|
+
body.light-theme .header {
|
143
|
+
background: #eaeaea;
|
144
|
+
color: #222;
|
27
145
|
}
|