Skip to content
Open
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
22 changes: 15 additions & 7 deletions TeXmacs/progs/doc/help-funcs.scm
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,23 @@
(load-buffer (get-remote-planet-url)))

;; 加载Mogan欢迎页面
(tm-define (mogan-welcome)
;; 根据当前语言设置加载相应语言的Mogan欢迎文档
;; 获取Mogan欢迎文档路径
;; 返回值: 文档路径字符串
(define (mogan-welcome-path)
(let* ((lan (string-take (language-to-locale (get-output-language)) 2))
(path (string-append "$TEXMACS_PATH/doc/about/mogan/stem." lan ".tmu"))
(en_doc (string-append "$TEXMACS_PATH/doc/about/mogan/stem.en.tmu")))
;; 优先加载本地化语言文档,如果不存在则加载英语文档
(if (url-exists? path)
(load-buffer (system->url path))
(load-buffer (system->url en_doc)))))
(if (url-exists? path) path en_doc)))

(tm-define (mogan-welcome)
;; 根据当前语言设置加载相应语言的Mogan欢迎文档
(load-buffer (system->url (mogan-welcome-path))))

;; 启动时加载欢迎文档,复用当前空白缓冲区
(tm-define (mogan-welcome-startup)
;; @brief 启动阶段加载欢迎文档,避免多出“无标题”缓冲区。
;; 例:首次启动时只显示欢迎文档。
(load-buffer-into-current (system->url (mogan-welcome-path))))

;; 加载Xmacs星球页面
(tm-define (xmacs-planet)
Expand Down Expand Up @@ -220,4 +228,4 @@
((url-exists? local_lan_doc) (load-buffer local_lan_doc))
((url-exists? lan_doc) (load-buffer lan_doc))
((url-exists? local_en_doc) (load-buffer local_en_doc))
(else (load-buffer en_doc)))))
(else (load-buffer en_doc)))))
68 changes: 55 additions & 13 deletions TeXmacs/progs/texmacs/texmacs/tm-files.scm
Original file line number Diff line number Diff line change
Expand Up @@ -548,19 +548,11 @@
((in? :new-window opts)
(open-buffer-in-window name (buffer-get name) ""))
(else
;; Remember current buffer to check if it's an unmodified scratch buffer
(let ((prev-buffer (current-buffer)))
(with wins (buffer->windows-of-tabpage name)
(if (and (!= wins '())
(in? (current-window) wins))
(switch-to-buffer* name)
(switch-to-buffer name)))
;; Close the previous unmodified scratch buffer after loading new file
(when (and prev-buffer
(!= prev-buffer name)
(url-scratch? prev-buffer)
(not (buffer-modified? prev-buffer)))
(cpp-buffer-close prev-buffer)))))
(with wins (buffer->windows-of-tabpage name)
(if (and (!= wins '())
(in? (current-window) wins))
(switch-to-buffer* name)
(switch-to-buffer name)))))
(buffer-notify-recent name)
;; Remember directory for file dialog
(remember-file-dialog-directory name)
Expand Down Expand Up @@ -625,6 +617,56 @@
(load-buffer-check-permissions name opts)))))
(load-buffer-check-permissions name opts)))

(tm-define (load-buffer-into-current name . opts)
;; @brief 启动阶段复用当前空白缓冲区加载文档,避免多出“无标题”缓冲区。
;; 例:双击文件启动时,当前空白缓冲区会被重命名并加载目标文档。
(let ((cur (current-buffer)))
(if (and cur (url-scratch? cur) (not (buffer-modified? cur))
(url-exists? name))
(letrec
;; @brief 复用当前缓冲区加载指定文档,保持与正常加载一致的提示行为。
;; 例:遇到 autosave 时仍然弹出恢复确认框。
((load-into-current
(lambda (target)
(let* ((doc (tree-import target (url-format target))))
(buffer-rename cur name)
(buffer-set name doc)
(load-buffer-open name opts))))
Comment on lines +631 to +634
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load-buffer-into-current uses tree-import and then renames/overwrites the current scratch buffer without checking for import failure. Elsewhere (e.g., revert-buffer-revert) the code checks (== t (tm->tree "error")) to surface an error message. Consider adding a similar check before buffer-rename/buffer-set, so a corrupted/unsupported file doesn’t silently replace the current buffer with an error tree.

Copilot uses AI. Check for mistakes.
(load-check-permissions
(lambda ()
(let* ((path (url->system name))
(vname `(verbatim ,(utf8->cork path))))
(cond ((and (not (url-test? name "f")) (url-exists? name))
(with msg "The file cannot be loaded or created:"
(begin
(debug-message "debug-io" (string-append msg "\n" path))
(notify-now `(concat ,msg "<br>" ,vname)))))
((and (url-test? name "f") (not (url-test? name "r")))
(with msg `(concat ,(translate "You do not have read access to") " " ,vname)
(show-message msg "Load file")))
((buffer-exists? name)
;; 复用当前空白缓冲区前,优先切换到已打开的目标缓冲区。
(load-buffer-open name opts)
(buffer-close cur))
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load-buffer-into-current closes cur unconditionally in the (buffer-exists? name) branch. When options include :background, load-buffer-open is a no-op (see its (in? :background opts) branch), so this will close the current scratch buffer even though no buffer switch occurred. Consider either rejecting/ignoring :background (and :new-window) for this helper, or only calling buffer-close cur when you actually switched away from cur (i.e., not in background mode).

Suggested change
(buffer-close cur))
;; 仅在非后台、非新窗口模式下,才关闭当前缓冲区。
(if (and (nin? :background opts)
(nin? :new-window opts))
(buffer-close cur)))

Copilot uses AI. Check for mistakes.
(else (load-into-current name)))))))
(if (and (autosave-propose name) (nin? :strict opts))
(with question (if (autosave-rescue? name)
"Rescue file from crash?"
"Load more recent autosave file?")
(user-confirm question #t
(lambda (answ)
(if answ
(let* ((autosave-name (autosave-propose name))
(format (url-format name))
(doc (tree-import autosave-name format)))
(buffer-rename cur name)
(buffer-set name doc)
(load-buffer-open name opts)
(buffer-pretend-modified name))
(load-check-permissions)))))
(load-check-permissions)))
(apply load-buffer-main (cons name opts)))))

(tm-define (load-buffer-main name . opts)
;;(display* "load-buffer-main " name ", " opts "\n")
(if (and (not (url-exists? name))
Expand Down
53 changes: 0 additions & 53 deletions devel/222_34.md

This file was deleted.

21 changes: 21 additions & 0 deletions devel/222_42.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 222_42 启动时避免多出“无标题”缓冲区

### 如何测试
1. 删除 `%APPDATA%\moganlab\system\settings.scm` 后启动
预期:仅显示欢迎文档,不出现额外“无标题”
2. 从文件管理器用软件打开 `.tmu` 文件
预期:仅显示目标文件,不出现额外“无标题”
3. 无参数启动(非首次)
预期:显示一个空白文档

## 2026/02/10

### What
- 启动时复用空白缓冲区加载欢迎文档,避免多出“无标题”缓冲区
- 通过“打开方式”启动文件时,复用空白缓冲区加载目标文档
- 若有启动文件参数,则不再加载欢迎文档

### Why
- 启动阶段必须先有可用视图,避免崩溃
- 用户打开欢迎文档或直接打开文件时,不应额外出现“无标题”文档

22 changes: 16 additions & 6 deletions src/System/Boot/init_texmacs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,9 @@ init_texmacs () {
void
load_welcome_doc () {
if (DEBUG_STD) debug_boot << "Loading welcome message...\n";
string cmd= "(mogan-welcome)";
/// @brief 启动阶段加载欢迎文档,复用空白缓冲区以避免多出“无标题”文档。
/// 例:首次启动时仅显示欢迎文档。
string cmd= "(mogan-welcome-startup)";
exec_delayed (scheme_cmd (cmd));
}

Expand Down Expand Up @@ -899,6 +901,9 @@ TeXmacs_main (int argc, char** argv) {
server sv (app_type::RESEARCH);
string where = "";
bool first_file= true;
/// @brief 启动时是否已有外部文件待打开(例如:双击文件或命令行传入)。
/// 目的:若已打开文件,则不再显示欢迎文档,避免多余缓冲区。
bool has_startup_file= false;
for (i= 1; i < argc; i++) {
if (argv[i] == NULL) break;
string s= argv[i];
Expand All @@ -909,9 +914,10 @@ TeXmacs_main (int argc, char** argv) {
if (!is_rooted (u)) u= resolve (url_pwd (), "") * u;
string b= scm_quote (as_string (u));
string cmd;
has_startup_file= true;
// only open window once
if (first_file) {
cmd = "(load-buffer " * b * " " * where * ")";
cmd = "(load-buffer-into-current " * b * " " * where * ")";
first_file= false;
}
else {
Expand All @@ -929,15 +935,19 @@ TeXmacs_main (int argc, char** argv) {
i++;
}
}
if (install_status == 1 || install_status == 2) {
load_welcome_doc ();
}

if (number_buffers () == 0) {
/// @brief 启动时确保至少有一个窗口与缓冲区可用。
/// 例:无论打开文件或欢迎文档,都需要有效视图避免崩溃。
if (DEBUG_STD) debug_boot << "Creating 'no name' buffer...\n";
open_window ();
}

/// @brief 仅在无启动文件时加载欢迎文档,避免“打开文件 + 欢迎文档”并存。
/// 例:从文件管理器“打开方式”启动时,不应额外弹出欢迎文档。
if ((install_status == 1 || install_status == 2) && !has_startup_file) {
load_welcome_doc ();
}

if (DEBUG_BENCH) lolly::system::bench_print (std_bench);
bench_reset ("initialize texmacs");
bench_reset ("initialize plugins");
Expand Down