Skip to content

Commit 993e8d0

Browse files
feat: finish the input gpios
1 parent 7154457 commit 993e8d0

33 files changed

Lines changed: 3928 additions & 15 deletions

codes_and_assets/project_setup/create_tutorial.sh

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ set -euo pipefail
55
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
66
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
77
TUTORIALS_BASE="${REPO_ROOT}/codes_and_assets/stm32f1_tutorials"
8-
TEMPLATE_DIR="${TUTORIALS_BASE}/0_start_our_tutorial"
9-
TEMPLATE_PROJECT_NAME="stm32_demo"
108

119
# ── 颜色定义 ─────────────────────────────────────────────────────────────────
1210
readonly RED='\033[0;31m'
@@ -53,6 +51,44 @@ get_next_number() {
5351
echo $(( max + 1 ))
5452
}
5553

54+
# ── 根据编号查找教程目录名 ──────────────────────────────────────────────────
55+
find_tutorial_by_number() {
56+
local target_num="$1"
57+
for dir in "$TUTORIALS_BASE"/*; do
58+
[[ -d "$dir" ]] || continue
59+
local base
60+
base="$(basename "$dir")"
61+
if [[ "$base" =~ ^([0-9]+)_(.+)$ ]]; then
62+
local num="${BASH_REMATCH[1]}"
63+
if [[ "$num" -eq "$target_num" ]]; then
64+
echo "$base"
65+
return 0
66+
fi
67+
fi
68+
done
69+
return 1
70+
}
71+
72+
# ── 查找前一个教程目录(编号为 N-1 的) ─────────────────────────────────────
73+
find_previous_tutorial() {
74+
local target_num="$1"
75+
local prev_num=$(( target_num - 1 ))
76+
if [[ "$prev_num" -lt 0 ]]; then
77+
return 1
78+
fi
79+
find_tutorial_by_number "$prev_num"
80+
}
81+
82+
# ── 从目录名提取 CMake 项目名 ────────────────────────────────────────────────
83+
extract_cmake_name_from_dir() {
84+
local dir_name="$1"
85+
# 从 CMakeLists.txt 中提取 project(...) 名
86+
local cmake_file="${TUTORIALS_BASE}/${dir_name}/CMakeLists.txt"
87+
if [[ -f "$cmake_file" ]]; then
88+
grep -oP 'project\(\K[^ )]+' "$cmake_file" 2>/dev/null | head -1
89+
fi
90+
}
91+
5692
# ── 列出现有教程 ─────────────────────────────────────────────────────────────
5793
list_tutorials() {
5894
printf "\n${BOLD}Existing tutorials:${NC}\n"
@@ -74,7 +110,7 @@ show_help() {
74110
cat <<'EOF'
75111
Usage: create_tutorial.sh [OPTIONS]
76112
77-
Create a new STM32F1 tutorial project from the template (0_start_our_tutorial).
113+
Create a new STM32F1 tutorial project by copying from the previous tutorial (N-1).
78114
79115
Options:
80116
-n, --name NAME Create tutorial with specified name (non-interactive)
@@ -139,13 +175,11 @@ fi
139175

140176
# ── 预检查 ───────────────────────────────────────────────────────────────────
141177
[[ -d "$TUTORIALS_BASE" ]] || die "Tutorials base not found: ${TUTORIALS_BASE}"
142-
[[ -d "$TEMPLATE_DIR" ]] || die "Template not found: ${TEMPLATE_DIR}"
143178

144179
# ── 交互模式:自动推断名称 ──────────────────────────────────────────────────
145180
if [[ -z "$DIR_NAME" ]]; then
146181
list_tutorials
147182

148-
local next_num
149183
next_num="$(get_next_number)"
150184
printf "${BOLD}Next available number:${NC} ${CYAN}${next_num}${NC}\n\n"
151185

@@ -157,7 +191,6 @@ if [[ -z "$DIR_NAME" ]]; then
157191

158192
DIR_NAME="${next_num}_${desc}"
159193

160-
local cmake_name
161194
cmake_name="$(dir_name_to_cmake_name "$DIR_NAME")"
162195
printf "\n Directory: ${BOLD}${DIR_NAME}${NC}"
163196
printf "\n CMake name: ${BOLD}${cmake_name}${NC}\n\n"
@@ -172,6 +205,16 @@ validate_name "$DIR_NAME"
172205
TARGET_DIR="${TUTORIALS_BASE}/${DIR_NAME}"
173206
CMAKE_NAME="$(dir_name_to_cmake_name "$DIR_NAME")"
174207

208+
# ── 查找源教程(前一个编号) ─────────────────────────────────────────────────
209+
NEW_NUM="${DIR_NAME%%_*}"
210+
SOURCE_DIR_NAME="$(find_previous_tutorial "$NEW_NUM")" \
211+
|| die "No previous tutorial found for number ${NEW_NUM}. Cannot determine source."
212+
SOURCE_DIR="${TUTORIALS_BASE}/${SOURCE_DIR_NAME}"
213+
SOURCE_CMAKE_NAME="$(extract_cmake_name_from_dir "$SOURCE_DIR_NAME")"
214+
[[ -n "$SOURCE_CMAKE_NAME" ]] || SOURCE_CMAKE_NAME="$(dir_name_to_cmake_name "$SOURCE_DIR_NAME")"
215+
216+
msg_info "Source tutorial: ${SOURCE_DIR_NAME} (CMake project: ${SOURCE_CMAKE_NAME})"
217+
175218
# ── 检查目标是否已存在 ───────────────────────────────────────────────────────
176219
if [[ -d "$TARGET_DIR" ]]; then
177220
die "Directory already exists: ${TARGET_DIR}\nRemove it first or choose a different name."
@@ -181,8 +224,8 @@ fi
181224
if [[ "$DRY_RUN" == true ]]; then
182225
printf "\n${BOLD}[DRY RUN] Would perform:${NC}\n"
183226
printf " Create: %s\n" "$TARGET_DIR"
184-
printf " Copy: %s/ (excluding build/ .cache/)\n" "$TEMPLATE_DIR"
185-
printf " Replace: 'stm32_demo' -> '%s' in CMakeLists.txt and .vscode/launch.json\n" "$CMAKE_NAME"
227+
printf " Copy: %s/ (excluding build/ .cache/)\n" "$SOURCE_DIR"
228+
printf " Replace: '%s' -> '%s' in CMakeLists.txt and .vscode/launch.json\n" "$SOURCE_CMAKE_NAME" "$CMAKE_NAME"
186229
printf "\n"
187230
exit 0
188231
fi
@@ -202,15 +245,15 @@ COPY_STARTED=true
202245
msg_info "Creating: ${TARGET_DIR}"
203246

204247
if command -v rsync &>/dev/null; then
205-
rsync -a --exclude='build/' --exclude='.cache/' "$TEMPLATE_DIR/" "$TARGET_DIR/"
248+
rsync -a --exclude='build/' --exclude='.cache/' "$SOURCE_DIR/" "$TARGET_DIR/"
206249
else
207250
# 回退方案:逐项复制,排除 build/ 和 .cache/
208251
mkdir -p "$TARGET_DIR"
209-
for item in "$TEMPLATE_DIR"/*; do
252+
for item in "$SOURCE_DIR"/*; do
210253
cp -r "$item" "$TARGET_DIR/"
211254
done
212255
# 复制隐藏文件/目录
213-
for item in "$TEMPLATE_DIR"/.*; do
256+
for item in "$SOURCE_DIR"/.*; do
214257
base="$(basename "$item")"
215258
[[ "$base" == "." || "$base" == ".." || "$base" == ".cache" ]] && continue
216259
cp -r "$item" "$TARGET_DIR/"
@@ -220,19 +263,19 @@ fi
220263
msg_success "Files copied (build/ and .cache/ excluded)."
221264

222265
# ── 替换项目名: CMakeLists.txt ───────────────────────────────────────────────
223-
sed -i "s/project(${TEMPLATE_PROJECT_NAME} /project(${CMAKE_NAME} /" \
266+
sed -i "s/project(${SOURCE_CMAKE_NAME} /project(${CMAKE_NAME} /" \
224267
"${TARGET_DIR}/CMakeLists.txt"
225268
msg_success "CMakeLists.txt: project name -> ${CMAKE_NAME}"
226269

227270
# ── 替换项目名: .vscode/launch.json ─────────────────────────────────────────
228-
sed -i "s/${TEMPLATE_PROJECT_NAME}/${CMAKE_NAME}/g" \
271+
sed -i "s/${SOURCE_CMAKE_NAME}/${CMAKE_NAME}/g" \
229272
"${TARGET_DIR}/.vscode/launch.json"
230273
msg_success "launch.json: executable -> ${CMAKE_NAME}.elf"
231274

232275
# ── 验证替换结果 ─────────────────────────────────────────────────────────────
233-
if grep -rq "$TEMPLATE_PROJECT_NAME" "${TARGET_DIR}/CMakeLists.txt" \
276+
if grep -rq "$SOURCE_CMAKE_NAME" "${TARGET_DIR}/CMakeLists.txt" \
234277
"${TARGET_DIR}/.vscode/launch.json" 2>/dev/null; then
235-
msg_warn "Some occurrences of '${TEMPLATE_PROJECT_NAME}' remain. Manual review needed."
278+
msg_warn "Some occurrences of '${SOURCE_CMAKE_NAME}' remain. Manual review needed."
236279
fi
237280

238281
# ── 完成 ─────────────────────────────────────────────────────────────────────
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
---
2+
# .clang-format 配置文件
3+
# 用于 clangd 格式化和代码检查
4+
# 生成日期: 2026-02-15
5+
6+
# 基础风格: LLVM (简洁现代)
7+
BasedOnStyle: LLVM
8+
9+
# 缩进设置
10+
IndentWidth: 4
11+
UseTab: Never
12+
ColumnLimit: 100
13+
14+
# 大括号风格: 附加式 { 在语句末尾
15+
BreakBeforeBraces: Attach
16+
17+
# 指针/引用星号位置: 左侧 (int* a)
18+
PointerAlignment: Left
19+
DerivePointerAlignment: false
20+
21+
# 命名风格 (仅供参考,不影响已有代码)
22+
# 可以让 clangd 警告不符合命名规范的代码
23+
# 需要配合 clang-tidy 使用
24+
25+
# 函数声明: 返回类型和函数名在同一行
26+
AlwaysBreakAfterReturnType: None
27+
AlwaysBreakTemplateDeclarations: No
28+
29+
# 结构体初始化: 按位置赋值
30+
# C++11UnifiedBraceList: false 使用传统风格
31+
32+
# 预处理器缩进: 与代码对齐
33+
IndentPPDirectives: AfterHash
34+
35+
# 其他实用设置
36+
37+
# 在二元运算符后换行
38+
BreakBeforeBinaryOperators: None
39+
40+
# 在三元运算符后换行
41+
BreakBeforeTernaryOperators: true
42+
43+
# 连续赋值时的对齐
44+
AlignConsecutiveAssignments: false
45+
AlignConsecutiveDeclarations: false
46+
47+
# 转换类型周围的空格
48+
SpaceAfterCStyleCast: false
49+
50+
# 逻辑运算符周围的空格
51+
SpaceAfterLogicalNot: false
52+
53+
# 模板列表中的空格
54+
SpaceAfterTemplateKeyword: true
55+
56+
# 控制语句括号内的空格: if (x) 而非 if (x )
57+
SpaceBeforeParens: ControlStatements
58+
SpaceInEmptyParentheses: false
59+
60+
# 圆括号内的空格
61+
SpacesInParentheses: false
62+
SpacesInSquareBrackets: false
63+
64+
# 容器类型周围的空格
65+
SpacesInContainerLiterals: false
66+
67+
# lambda 相关
68+
SpaceBeforeAssignmentOperators: true
69+
SpaceBeforeCpp11BracedList: false
70+
71+
# 对齐
72+
AlignAfterOpenBracket: Align
73+
AlignEscapedNewlines: Left
74+
AlignOperands: true
75+
AlignTrailingComments: true
76+
77+
# 允许函数参数在同一行
78+
AllowAllArgumentsOnNextLine: true
79+
AllowAllConstructorInitializersOnNextLine: true
80+
AllowAllParametersOfDeclarationOnNextLine: true
81+
82+
# 允许短函数在一行
83+
AllowShortBlocksOnASingleLine: Never
84+
AllowShortCaseLabelsOnASingleLine: false
85+
AllowShortFunctionsOnASingleLine: Inline
86+
AllowShortIfStatementsOnASingleLine: Never
87+
AllowShortLoopsOnASingleLine: false
88+
89+
# 自动对齐注释
90+
ReflowComments: true
91+
92+
# 最大连续空行数
93+
MaxEmptyLinesToKeep: 1
94+
95+
# 命名空间缩进
96+
NamespaceIndentation: None
97+
98+
# 访问修饰符缩进
99+
IndentAccessModifiers: false
100+
IndentCaseLabels: true
101+
102+
# 换行符设置
103+
LineEnding: LF
104+
105+
# C/C++ 语言设置
106+
Language: Cpp
107+
Standard: c++17
108+
109+
# 包含块排序
110+
SortIncludes: true
111+
IncludeBlocks: Preserve
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build/
2+
.cache/
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "STM32 Debug",
6+
"type": "cortex-debug",
7+
"request": "launch",
8+
"servertype": "openocd",
9+
"cwd": "${workspaceRoot}",
10+
"executable": "build/button_control.elf",
11+
"configFiles": [
12+
"interface/stlink.cfg",
13+
"target/stm32f1x.cfg"
14+
],
15+
"runToEntryPoint": "main",
16+
"svdFile": ""
17+
}
18+
]
19+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"clangd.arguments": [
3+
"--query-driver=/usr/sbin/arm-none-eabi-g++,/usr/sbin/arm-none-eabi-gcc"
4+
]
5+
}

0 commit comments

Comments
 (0)