diff --git a/TeXmacs/progs/generic/generic-edit.scm b/TeXmacs/progs/generic/generic-edit.scm index 41f903a0d4..4439804d1e 100644 --- a/TeXmacs/progs/generic/generic-edit.scm +++ b/TeXmacs/progs/generic/generic-edit.scm @@ -675,9 +675,10 @@ (tm-define (kbd-cut) (clipboard-cut "primary")) (tm-define (kbd-paste) - (clipboard-paste "primary") - (when (defined? 'tutorial-notify-action) - (tutorial-notify-action "paste"))) + (with ok (clipboard-paste "primary") + (when (and ok (defined? 'tutorial-notify-action)) + (tutorial-notify-action "paste")) + ok)) (tm-define (kbd-paste-verbatim) (clipboard-paste-import "verbatim" "primary")) (tm-define (kbd-cancel) @@ -729,13 +730,14 @@ image-and-ocr-paste (tm-define (paste-as-markdown) (if (community-stem?) - (begin - (clipboard-paste-import "verbatim" "primary") - (kbd-return) - (let* ((latex-code (string-load (unix->url "$TEXMACS_PATH/plugins/account/data/md.tex"))) - (parsed-latex (parse-latex latex-code)) - (texmacs-latex (latex->texmacs parsed-latex))) - (insert texmacs-latex))) + (with ok (clipboard-paste-import "verbatim" "primary") + (when ok + (kbd-return) + (let* ((latex-code (string-load (unix->url "$TEXMACS_PATH/plugins/account/data/md.tex"))) + (parsed-latex (parse-latex latex-code)) + (texmacs-latex (latex->texmacs parsed-latex))) + (insert texmacs-latex))) + ok) (clipboard-paste-import "markdown" "primary"))) #| @@ -750,12 +752,17 @@ paste-as-texmacs (when (not (defined? 'ocr-to-latex-by-cursor)) (use-modules (liii ocr))) (with img-tree (tree-ref (clipboard-get "primary") 1) - (cond ((tree-is? img-tree 'image) - (ocr-to-latex-by-cursor img-tree)) + (cond ((tree-is? img-tree 'image) + (ocr-to-latex-by-cursor img-tree) + #t) ((and (tree-is? img-tree 'with) (not (null? (tree-ref img-tree 2)))) (let* ((sub-img-tree (tree-ref img-tree 2))) - (when (tree-is? sub-img-tree 'image) - (ocr-to-latex-by-cursor img-tree))))))) + (if (tree-is? sub-img-tree 'image) + (begin + (ocr-to-latex-by-cursor sub-img-tree) + #t) + #f))) + (else #f)))) #| smart-format-paste @@ -800,15 +807,19 @@ TODO: 在文本模式中,可以自动识别剪贴板中的内容,并智能 (ocr-paste) (track-event "OCR_RECOGNIZE" '())) (with mode (get-env "mode") - (cond ((== mode "prog") - (clipboard-paste-import "code" "primary") - (track-event "MAGIC_PASTE" '(("mode" . "prog")))) - ((== mode "math") - (clipboard-paste-import "latex" "primary") - (track-event "MAGIC_PASTE" '(("mode" . "math")))) - (else - (smart-format-paste) - (track-event "MAGIC_PASTE" '(("mode" . "text"))))))) + (with ok (cond ((== mode "prog") + (clipboard-paste-import "code" "primary")) + ((== mode "math") + (clipboard-paste-import "latex" "primary")) + (else + (smart-format-paste))) + (when ok + (cond ((== mode "prog") + (track-event "MAGIC_PASTE" '(("mode" . "prog")))) + ((== mode "math") + (track-event "MAGIC_PASTE" '(("mode" . "math")))) + (else + (track-event "MAGIC_PASTE" '(("mode" . "text"))))))))) (when (defined? 'tutorial-notify-action) (tutorial-notify-action "ocr-paste"))) diff --git a/TeXmacs/progs/utils/edit/selections.scm b/TeXmacs/progs/utils/edit/selections.scm index b967558fc4..9194b9cf0f 100644 --- a/TeXmacs/progs/utils/edit/selections.scm +++ b/TeXmacs/progs/utils/edit/selections.scm @@ -68,8 +68,9 @@ (tm-define (clipboard-paste-import format which) (let ((temp (clipboard-get-import))) (clipboard-set-import format) - (clipboard-paste which) - (clipboard-set-import temp))) + (with ok (clipboard-paste which) + (clipboard-set-import temp) + ok))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Structured selections diff --git a/TeXmacs/tests/1010_1.scm b/TeXmacs/tests/1010_1.scm new file mode 100644 index 0000000000..3c3ca02ebe --- /dev/null +++ b/TeXmacs/tests/1010_1.scm @@ -0,0 +1,113 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; MODULE : 1010_1.scm +;; DESCRIPTION : Tests for clipboard-paste-import return value +;; COPYRIGHT : (C) 2026 Yuki +;; +;; This software falls under the GNU general public license version 3 or later. +;; It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE +;; in the root directory or . +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(import (liii check)) + +(check-set-mode! 'report-failed) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 辅助函数 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (headless?) + (not (defined? 'qt-version))) + +(define (clear-clipboard) + (clipboard-clear "primary")) + +(define (setup-clipboard text) + (insert text) + (select-all) + (clipboard-copy "primary") + (selection-cancel)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 测试用例 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 测试:剪贴板为空时,粘贴返回失败 +(define (test-paste-empty-clipboard) + (catch #t + (lambda () + (clear-clipboard) + (check (clipboard-paste-import "verbatim" "primary") => #f)) + (lambda args + (display "剪贴板不可用,跳过空剪贴板粘贴测试\n")))) + +;; 测试:剪贴板有内容时,verbatim 格式粘贴返回成功 +(define (test-paste-with-content) + (catch #t + (lambda () + (clear-clipboard) + (setup-clipboard "test-content-1010") + (check (clipboard-paste-import "verbatim" "primary") => #t) + ;; 清理:撤销 paste 和 setup 时插入的内容 + (undo 0) + (undo 0)) + (lambda args + (display "剪贴板不可用,跳过有内容粘贴测试\n")))) + +;; 测试:剪贴板有内容时,code 格式粘贴返回成功 +(define (test-paste-code-format) + (catch #t + (lambda () + (clear-clipboard) + (setup-clipboard "def hello(): pass") + (check (clipboard-paste-import "code" "primary") => #t) + (undo 0) + (undo 0)) + (lambda args + (display "剪贴板不可用,跳过 code 格式粘贴测试\n")))) + +;; 测试:剪贴板有内容时,latex 格式粘贴返回成功 +(define (test-paste-latex-format) + (catch #t + (lambda () + (clear-clipboard) + (setup-clipboard "$E = mc^2$") + (check (clipboard-paste-import "latex" "primary") => #t) + (undo 0) + (undo 0)) + (lambda args + (display "剪贴板不可用,跳过 latex 格式粘贴测试\n")))) + +;; 测试:kbd-paste 返回值为布尔值 +(define (test-kbd-paste-return-type) + (catch #t + (lambda () + (clear-clipboard) + (setup-clipboard "kbd-paste-test") + (check (boolean? (kbd-paste)) => #t) + (undo 0) + (undo 0)) + (lambda args + (display "剪贴板不可用,跳过 kbd-paste 测试\n")))) + +;; 测试:clipboard-paste-import 函数存在 +(define (test-paste-import-exists) + (check (procedure? clipboard-paste-import) => #t)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 入口 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(tm-define (test_1010_1) + (test-paste-import-exists) + (if (headless?) + (display "检测到无头模式,跳过剪贴板相关测试\n") + (begin + (test-paste-empty-clipboard) + (test-paste-with-content) + (test-paste-code-format) + (test-paste-latex-format) + (test-kbd-paste-return-type))) + (check-report)) diff --git a/src/Edit/Replace/edit_select.cpp b/src/Edit/Replace/edit_select.cpp index e1114ea6b5..e84f88a858 100644 --- a/src/Edit/Replace/edit_select.cpp +++ b/src/Edit/Replace/edit_select.cpp @@ -681,14 +681,17 @@ edit_select_rep::selection_get (string key) { return t; } -void +bool edit_select_rep::selection_paste (string key) { tree t; string s; - (void) ::get_selection (key, t, s, selection_import); + if (!::get_selection (key, t, s, selection_import)) return false; if (inside_active_graphics ()) { - if (is_tuple (t, "texmacs", 3)) call ("graphics-paste", t[1]); - return; + if (is_tuple (t, "texmacs", 3)) { + call ("graphics-paste", t[1]); + return true; + } + return false; } if (is_tuple (t, "extern", 1)) { string mode= get_env_string (MODE); @@ -721,6 +724,7 @@ edit_select_rep::selection_paste (string key) { } if (mode == "math" && is_compound (doc, "math", 1)) doc= doc[0]; insert_tree (doc); + return true; } if (is_tuple (t, "texmacs", 3)) { string mode= get_env_string (MODE); @@ -729,12 +733,15 @@ edit_select_rep::selection_paste (string key) { t= tuple ("texmacs", t[1][0], "text", lan); if (is_compound (t[1], "math", 1) && mode == "math") t= tuple ("texmacs", t[1][0], "math", lan); - if (mode == "math" && t[2] == "text") + if (mode == "math" && t[2] == "text") { set_message ("Error: invalid paste of text into a formula", "paste"); + return false; + } else if (mode == "prog" && t[2] == "math") { tree in= tuple (lan, t[1]); tree r = stree_to_tree (call ("plugin-math-input", tree_to_stree (in))); insert_tree (r); + return true; } else { if ((t[2] != mode) && (t[2] != "src") && (mode != "src") && @@ -752,8 +759,10 @@ edit_select_rep::selection_paste (string key) { else table_write_subtable (fp, row, col, t[1]); } else insert_tree (t[1]); + return true; } } + return false; } void diff --git a/src/Edit/Replace/edit_select.hpp b/src/Edit/Replace/edit_select.hpp index df009345e0..c1f818b8a6 100644 --- a/src/Edit/Replace/edit_select.hpp +++ b/src/Edit/Replace/edit_select.hpp @@ -86,7 +86,7 @@ class edit_select_rep : virtual public editor_rep { void selection_set_paths (path start, path end); void selection_set_range_set (range_set sel); void selection_copy (string key= "primary"); - void selection_paste (string key= "primary"); + bool selection_paste (string key= "primary"); void selection_clear (string key= "primary"); void selection_cancel (); void selection_set_import (string fm); diff --git a/src/Edit/editor.hpp b/src/Edit/editor.hpp index 61f8899fac..406eb284c0 100644 --- a/src/Edit/editor.hpp +++ b/src/Edit/editor.hpp @@ -533,7 +533,7 @@ class editor_rep : public simple_widget_rep { virtual void selection_set_paths (path start, path end) = 0; virtual void selection_set_range_set (range_set sel) = 0; virtual void selection_copy (string key= "primary") = 0; - virtual void selection_paste (string key= "primary") = 0; + virtual bool selection_paste (string key= "primary") = 0; virtual void selection_clear (string key= "primary") = 0; virtual void selection_cancel () = 0; virtual void selection_set_import (string fm) = 0; diff --git a/src/Scheme/Glue/build-glue-editor.scm b/src/Scheme/Glue/build-glue-editor.scm index 21d1b40a3c..158436f600 100644 --- a/src/Scheme/Glue/build-glue-editor.scm +++ b/src/Scheme/Glue/build-glue-editor.scm @@ -245,7 +245,7 @@ (cpp-clipboard-cut selection_cut (void string)) (clipboard-cut-at cut (void path)) (clipboard-cut-between cut (void path path)) - (cpp-clipboard-paste selection_paste (void string)) + (cpp-clipboard-paste selection_paste (bool string)) (selection-move selection_move (void)) (clipboard-clear selection_clear (void string)) (selection-cancel selection_cancel (void)) diff --git a/src/Scheme/Glue/glue_editor.lua b/src/Scheme/Glue/glue_editor.lua index 143d8b1c86..1a3d8ff1e4 100644 --- a/src/Scheme/Glue/glue_editor.lua +++ b/src/Scheme/Glue/glue_editor.lua @@ -1487,7 +1487,7 @@ function main() { scm_name = "cpp-clipboard-paste", cpp_name = "selection_paste", - ret_type = "void", + ret_type = "bool", arg_list = { "string" }