Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "codeforge",
"private": true,
"version": "26.3.0",
"version": "26.4.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "CodeForge"
version = "26.3.0"
version = "26.4.0"
description = "CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发者、学生和编程爱好者设计。"
authors = ["devlive-community"]
edition = "2024"
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "CodeForge",
"version": "26.3.0",
"version": "26.4.0",
"identifier": "org.devlive.codeforge",
"build": {
"beforeDevCommand": "pnpm dev",
Expand Down
34 changes: 34 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,38 @@ const copyAsMarkdown = async () => {
}
}

// 转换整篇的缩进:空格 ↔ 制表符(按 tab 宽度换算)
const convertIndentation = (toTabs: boolean) => {
const view = editorView.value
if (!view) {
return
}
const size = editorConfig.value?.tab_size ?? 2
const original = view.state.doc.toString()
const out = original.split('\n').map((line: string) => {
const m = line.match(/^[ \t]+/)
if (!m) {
return line
}
// 把行首空白展开为列数(tab 计为 size 列)
let cols = 0
for (const ch of m[0]) {
cols += ch === '\t' ? size : 1
}
const rest = line.slice(m[0].length)
return toTabs
? '\t'.repeat(Math.floor(cols / size)) + ' '.repeat(cols % size) + rest
: ' '.repeat(cols) + rest
}).join('\n')
if (out === original) {
return
}
const head = Math.min(view.state.selection.main.head, out.length)
view.dispatch({changes: {from: 0, to: view.state.doc.length, insert: out}, selection: {anchor: head}})
view.focus()
toast.success(t('app.indentConverted'))
}

// AI 自然语言生成 / 选区改写
const showGenerate = ref(false)
const generateSelection = ref('')
Expand Down Expand Up @@ -2193,6 +2225,8 @@ const paletteCommands = computed<PaletteCommand[]>(() => [
{id: 'removeDuplicateLines', label: t('command.removeDuplicateLines'), group: t('command.groupText'), icon: ListChecks, run: () => removeDuplicateLines()},
{id: 'trimTrailingWhitespace', label: t('command.trimTrailingWhitespace'), group: t('command.groupText'), icon: Eraser, run: () => trimTrailingWhitespace()},
{id: 'copyAsMarkdown', label: t('command.copyAsMarkdown'), group: t('command.groupText'), icon: Code2, run: () => copyAsMarkdown()},
{id: 'indentToSpaces', label: t('command.indentToSpaces'), group: t('command.groupText'), icon: Eraser, run: () => convertIndentation(false)},
{id: 'indentToTabs', label: t('command.indentToTabs'), group: t('command.groupText'), icon: Eraser, run: () => convertIndentation(true)},
{id: 'toggleAutoReveal', label: t('command.toggleAutoReveal'), icon: FolderOpen, run: () => toggleAutoReveal()},
{id: 'toggleSidebar', label: t('command.toggleSidebar'), icon: PanelLeft, hint: hintOf('toggleSidebar'), run: () => toggleSidebar()},
{id: 'toggleZen', label: t('command.toggleZen'), icon: Minimize2, run: () => toggleZen()},
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,8 @@
"removeDuplicateLines": "Remove duplicate lines",
"trimTrailingWhitespace": "Trim trailing whitespace",
"copyAsMarkdown": "Copy as Markdown code block",
"indentToSpaces": "Convert indentation to spaces",
"indentToTabs": "Convert indentation to tabs",
"compareClipboard": "Compare with clipboard",
"groupText": "Text",
"toggleAutoReveal": "Toggle: auto-reveal active file",
Expand Down Expand Up @@ -1324,6 +1326,7 @@
"multiEngine": "This type has multiple run engines; selected \"{name}\", switch manually in the dropdown",
"pathCopied": "Path copied",
"copiedMarkdown": "Copied as Markdown code block",
"indentConverted": "Indentation converted",
"clipboardEmpty": "Clipboard is empty",
"clipboardReadFailed": "Failed to read clipboard: ",
"copyFailed": "Copy failed: ",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,8 @@
"removeDuplicateLines": "删除重复行",
"trimTrailingWhitespace": "去除行尾空白",
"copyAsMarkdown": "复制为 Markdown 代码块",
"indentToSpaces": "转换缩进为空格",
"indentToTabs": "转换缩进为制表符",
"compareClipboard": "与剪贴板比较",
"groupText": "文本",
"toggleAutoReveal": "切换:自动定位当前文件",
Expand Down Expand Up @@ -1324,6 +1326,7 @@
"multiEngine": "该类型可用多个运行引擎,已选「{name}」,可在下拉手动切换",
"pathCopied": "已复制路径",
"copiedMarkdown": "已复制为 Markdown 代码块",
"indentConverted": "已转换缩进",
"clipboardEmpty": "剪贴板为空",
"clipboardReadFailed": "读取剪贴板失败: ",
"copyFailed": "复制失败: ",
Expand Down
Loading