🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

practicode

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

practicode - npm Package Compare versions

Comparing version
0.2.2
to
0.2.3
+5
-0
assets/i18n/en.json

@@ -32,2 +32,7 @@ {

"hint_result": "drag select to copy | F6 view | /next step | /home",
"learning_primary_next": "Enter: Next",
"learning_primary_run": "F5: Run",
"learning_primary_edit": "Enter: Edit",
"learning_primary_home": "Enter: Home",
"learning_primary_leave_code": "Esc: Leave editor",
"hint_idle": "/ command | ? help",

@@ -34,0 +39,0 @@ "hint_busy": "Working | q quit",

@@ -32,2 +32,7 @@ {

"hint_result": "arrastra para copiar | F6 vista | /next paso | /home",
"learning_primary_next": "Enter: Siguiente",
"learning_primary_run": "F5: Ejecutar",
"learning_primary_edit": "Enter: Volver al código",
"learning_primary_home": "Enter: Inicio",
"learning_primary_leave_code": "Esc: Salir del editor",
"hint_idle": "/ comando | ? ayuda",

@@ -34,0 +39,0 @@ "hint_busy": "Trabajando | q salir",

@@ -32,2 +32,7 @@ {

"hint_result": "ドラッグ選択でコピー | F6 表示 | /next ステップ | /home",
"learning_primary_next": "Enter: 次へ",
"learning_primary_run": "F5: 実行",
"learning_primary_edit": "Enter: コードへ",
"learning_primary_home": "Enter: ホームへ",
"learning_primary_leave_code": "Esc: 編集を終了",
"hint_idle": "/ コマンド | ? ヘルプ",

@@ -34,0 +39,0 @@ "hint_busy": "処理中 | q 終了",

@@ -32,2 +32,7 @@ {

"hint_result": "드래그 선택으로 복사 | F6 보기 | /next 단계 | /home",
"learning_primary_next": "Enter: 다음",
"learning_primary_run": "F5: 실행",
"learning_primary_edit": "Enter: 코드로",
"learning_primary_home": "Enter: 홈으로",
"learning_primary_leave_code": "Esc: 편집 끝내기",
"hint_idle": "/ 명령 | ? 도움말",

@@ -34,0 +39,0 @@ "hint_busy": "작업 중 | q 종료",

@@ -32,2 +32,7 @@ {

"hint_result": "拖拽选择复制 | F6 视图 | /next 步骤 | /home",
"learning_primary_next": "Enter:下一步",
"learning_primary_run": "F5:运行",
"learning_primary_edit": "Enter:返回代码",
"learning_primary_home": "Enter:返回首页",
"learning_primary_leave_code": "Esc:结束编辑",
"hint_idle": "/ 命令 | ? 帮助",

@@ -34,0 +39,0 @@ "hint_busy": "处理中 | q 退出",

+1
-1

@@ -456,3 +456,3 @@ # This file is automatically @generated by Cargo.

name = "practicode"
version = "0.2.2"
version = "0.2.3"
dependencies = [

@@ -459,0 +459,0 @@ "anyhow",

[package]
name = "practicode"
version = "0.2.2"
version = "0.2.3"
edition = "2024"

@@ -5,0 +5,0 @@ description = "Offline-first programming language lessons and coding practice in a Rust terminal UI."

{
"name": "practicode",
"version": "0.2.2",
"version": "0.2.3",
"description": "Offline-first programming language lessons and coding practice in a Rust terminal UI.",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -306,2 +306,13 @@ use super::*;

}
if self.mode == AppMode::Learn && !self.show_output && key.code == KeyCode::Enter {
match self.learning_session.step() {
LearningStep::Complete => self.action_home()?,
LearningStep::Exercise if self.learning_session.view() == LearningView::Result => {
self.action_edit()?
}
LearningStep::Exercise => {}
_ => self.action_next_learning()?,
}
return Ok(());
}
self.handle_global_shortcut(key)

@@ -308,0 +319,0 @@ }

@@ -283,4 +283,20 @@ use super::*;

};
let context = if step == LearningStep::Exercise {
String::new()
} else {
format!(
"\n\n## {}\n\n{}",
learning_step_label(language, LearningStep::Exercise),
learning_exercise(lesson, language)
)
};
let position = match step {
LearningStep::Review | LearningStep::Delta => 1,
LearningStep::Predict => 2,
LearningStep::Exercise => 3,
LearningStep::Reflect => 4,
LearningStep::Complete => unreachable!(),
};
format!(
"# {}: {title}\n\n{body}",
"# {position}/4 · {}: {title}\n\n{body}{context}",
learning_step_label(language, step)

@@ -287,0 +303,0 @@ )

@@ -16,2 +16,5 @@ use super::*;

}
if self.mode == AppMode::Learn {
return format!(" {} ", self.learning_primary_hint());
}
let lang = &self.state.settings.ui_language;

@@ -36,2 +39,12 @@ let key = match self.mode {

if self.mode == AppMode::Learn {
let primary = if self.task_rx.is_some()
|| self.editing_notes
|| self.focus == Focus::Command
|| self.list_cursor.is_some()
|| self.show_output
{
self.mode_hint()
} else {
self.learning_primary_hint()
};
let lesson = current_syntax_lesson(&self.state, &self.state.settings.language);

@@ -45,14 +58,14 @@ let (done, total) =

};
let context = if !self.show_output && self.focus == selected_focus {
let focus = if !self.show_output && self.focus == selected_focus {
format!(
"{}: {} | {}",
" | {}: {}",
ui_text(lang, "focus_active"),
learning_view_label(lang, self.learning_session.view()),
self.mode_hint()
)
} else {
self.mode_hint().to_string()
String::new()
};
return format!(
" PRACTICODE | {} | {} | {} | {done}/{total} | {context} | {}:{} ",
" {} | PRACTICODE | {} | {} | {} | {done}/{total}{focus} | {}:{} ",
primary,
ui_text(lang, "mode_learn"),

@@ -227,11 +240,4 @@ syntax_language_name(&self.state.settings.language),

}
if self.mode == AppMode::Learn
&& !self.show_output
&& self.learning_session.view() == LearningView::Result
&& self.focus != Focus::Command
{
return ui_text(lang, "hint_result");
}
if self.mode == AppMode::Learn && !self.show_output && self.focus != Focus::Command {
return ui_text(lang, "hint_learn");
return self.learning_primary_hint();
}

@@ -251,2 +257,20 @@ if self.mode == AppMode::Problems && !self.show_output && self.focus != Focus::Command {

fn learning_primary_hint(&self) -> &'static str {
let key = if self.focus == Focus::Code
&& self.learning_session.step() != LearningStep::Exercise
{
"learning_primary_leave_code"
} else {
match self.learning_session.step() {
LearningStep::Exercise if self.learning_session.view() == LearningView::Result => {
"learning_primary_edit"
}
LearningStep::Exercise => "learning_primary_run",
LearningStep::Complete => "learning_primary_home",
_ => "learning_primary_next",
}
};
ui_text(&self.state.settings.ui_language, key)
}
pub(super) fn help_text(&self) -> String {

@@ -253,0 +277,0 @@ let lang = &self.state.settings.ui_language;

@@ -849,3 +849,3 @@ use super::*;

assert!(!app.wants_mouse_capture());
assert!(app.status_text().contains("drag select to copy"));
assert!(app.status_text().contains("Enter: Next"));
app.focus_command();

@@ -1053,5 +1053,5 @@ assert!(app.wants_mouse_capture());

#[test]
fn compact_learning_status_keeps_every_primary_action_visible() {
fn compact_learning_status_leads_with_the_current_primary_action() {
for language in UI_LANGUAGES {
for width in [60, 80, 99, 100] {
for width in [60, 80, 99, 100, 121, 140] {
let mut app =

@@ -1062,14 +1062,10 @@ PracticodeApp::new(tmp_root(&format!("compact-status-{language}-{width}")))

app.action_learn("python").unwrap();
let terminal = draw_at(&mut app, width, 24);
let row = terminal.backend().buffer().area.height - 2;
let rendered = (0..width)
.map(|x| terminal.backend().buffer()[(x, row)].symbol())
.collect::<String>();
let _terminal = draw_at(&mut app, width, 24);
let rendered = app.status_text_for_width(width);
for action in ["/next", "F5", "F6", "F1"] {
assert!(
rendered.contains(action),
"{language} {width}: missing {action} in {rendered:?}"
);
}
let action = ui_text(language, "learning_primary_next");
assert!(
rendered.trim_start().starts_with(action),
"{language} {width}: {action} does not lead {rendered:?}"
);
}

@@ -1076,0 +1072,0 @@ }