branch: externals/ellama commit 1d5f27e22bae540334adec7b6344d8eb35ca242f Author: Sergey Kostyaev <sskosty...@gmail.com> Commit: Sergey Kostyaev <sskosty...@gmail.com>
Refactor transformations and improve newline handling Refactored ellama--apply-transformations to use markers for beg/end to ensure stability during replacements. Added set-hard-newline-properties to handle hard newlines during text filling. Updated test cases to include a new test for markdown list to org list conversion. Fix #310 --- ellama.el | 77 ++++++++++++++++++++++++++++------------------------ tests/test-ellama.el | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 35 deletions(-) diff --git a/ellama.el b/ellama.el index bc1e02d18e..9b0b5d3424 100644 --- a/ellama.el +++ b/ellama.el @@ -521,7 +521,7 @@ It should be a function with single argument generated text string." (defun ellama--replace-bad-code-blocks (text) "Replace code src blocks in TEXT." (with-temp-buffer - (insert text) + (insert (propertize text 'hard t)) (goto-char (point-min)) ;; skip good code blocks (while (re-search-forward "#\\+BEGIN_SRC\\(.\\|\n\\)*?#\\+END_SRC" nil t)) @@ -539,40 +539,47 @@ It should be a function with single argument generated text string." (defun ellama--apply-transformations (beg end) "Apply md to org transformations for region BEG END." - ;; headings - (ellama--replace "^# " "* " beg end) - (ellama--replace "^## " "** " beg end) - (ellama--replace "^### " "*** " beg end) - (ellama--replace "^#### " "**** " beg end) - (ellama--replace "^##### " "***** " beg end) - (ellama--replace "^###### " "****** " beg end) - ;; bold - (ellama--replace "__\\(.+?\\)__" "*\\1*" beg end) - (ellama--replace "\\*\\*\\(.+?\\)\\*\\*" "*\\1*" beg end) - (ellama--replace "<b>\\(.+?\\)</b>" "*\\1*" beg end) - (ellama--replace "<i>\\(.+?\\)</i>" "/\\1/" beg end) - ;; underlined - (ellama--replace "<u>\\(.+?\\)</u>" "_\\1_" beg end) - ;; inline code - (ellama--replace "`\\(.+?\\)`" "~\\1~" beg end) - ;; italic - (when ellama-translate-italic - (ellama--replace "_\\(.+?\\)_" "/\\1/" beg end)) - ;; lists - (ellama--replace "^\\* " "+ " beg end) - ;; strikethrough - (ellama--replace "~~\\(.+?\\)~~" "+\\1+" beg end) - (ellama--replace "<s>\\(.+?\\)</s>" "+\\1+" beg end) - ;; badges - (ellama--replace "\\[\\!\\[.*?\\](\\(.*?\\))\\](\\(.*?\\))" "[[\\2][file:\\1]]" beg end) - ;;links - (ellama--replace "\\[\\(.*?\\)\\](\\(.*?\\))" "[[\\2][\\1]]" beg end) - - ;; filling long lines - (goto-char beg) - (when ellama-fill-paragraphs - (let ((use-hard-newlines t)) - (fill-region beg end nil t t)))) + (let ((beg-pos (make-marker)) + (end-pos (make-marker))) + (set-marker-insertion-type beg-pos t) + (set-marker-insertion-type end-pos t) + (set-marker beg-pos beg) + (set-marker end-pos end) + ;; bold + (ellama--replace "__\\(.+?\\)__" "*\\1*" beg-pos end-pos) + (ellama--replace "\\*\\*\\([^\*\n]+?\\)\\*\\*" "*\\1*" beg-pos end-pos) + (ellama--replace "<b>\\(.+?\\)</b>" "*\\1*" beg-pos end-pos) + (ellama--replace "<i>\\(.+?\\)</i>" "/\\1/" beg-pos end-pos) + ;; headings + (ellama--replace "^# " "* " beg-pos end-pos) + (ellama--replace "^## " "** " beg-pos end-pos) + (ellama--replace "^### " "*** " beg-pos end-pos) + (ellama--replace "^#### " "**** " beg-pos end-pos) + (ellama--replace "^##### " "***** " beg-pos end-pos) + (ellama--replace "^###### " "****** " beg-pos end-pos) + ;; underlined + (ellama--replace "<u>\\(.+?\\)</u>" "_\\1_" beg-pos end-pos) + ;; inline code + (ellama--replace "`\\(.+?\\)`" "~\\1~" beg-pos end-pos) + ;; italic + (when ellama-translate-italic + (ellama--replace "_\\(.+?\\)_" "/\\1/" beg-pos end-pos)) + ;; lists + (ellama--replace "^\\* " "+ " beg-pos end-pos) + ;; strikethrough + (ellama--replace "~~\\(.+?\\)~~" "+\\1+" beg-pos end-pos) + (ellama--replace "<s>\\(.+?\\)</s>" "+\\1+" beg-pos end-pos) + ;; badges + (ellama--replace "\\[\\!\\[.*?\\](\\(.*?\\))\\](\\(.*?\\))" "[[\\2][file:\\1]]" beg-pos end-pos) + ;;links + (ellama--replace "\\[\\(.*?\\)\\](\\(.*?\\))" "[[\\2][\\1]]" beg-pos end-pos) + + ;; filling long lines + (goto-char beg-pos) + (set-hard-newline-properties beg-pos end-pos) + (when ellama-fill-paragraphs + (let* ((use-hard-newlines t)) + (fill-region beg end-pos nil t t))))) (defun ellama--replace-outside-of-code-blocks (text) "Replace markdown elements in TEXT with org equivalents. diff --git a/tests/test-ellama.el b/tests/test-ellama.el index 5e7100e6c4..a83803b364 100644 --- a/tests/test-ellama.el +++ b/tests/test-ellama.el @@ -454,6 +454,54 @@ package main 1. *Initialization*: We create a boolean slice ~prime~ of size ~n+1~, where each index represents whether the number is prime (~true~) or not (~false~).")))) +(ert-deftest test-ellama-md-to-org-lists () + (let* ((fill-column 80) + (result (ellama--translate-markdown-to-org-filter "<think>Okay, the user asked me to create a list of fruits. Let me think about how to approach this.</think> Hereโs a comprehensive list of fruits, categorized for clarity: + +--- + +### **Common Fruits** +1. **Apple** +2. **Banana** +3. **Orange** +4. **Grape** +5. **Strawberry** +6. **Blueberry** + +--- + +### **Additional Notes** +- **Tomatoes** are technically fruits (part of the nightshade family). +- **Coconut** is a tropical fruit, often used in cooking. +- **Papaya** is a versatile fruit with nutritional value. + +Let me know if you'd like a simplified version or a specific category (e.g., by region, season, or type)! ๐๐"))) + (should (string= result "#+BEGIN_QUOTE +Okay, the user asked me to create a list of fruits. Let me think about how to +approach this. +#+END_QUOTE + Hereโs a comprehensive list of fruits, categorized for clarity: + +--- + +*** *Common Fruits* +1. *Apple* +2. *Banana* +3. *Orange* +4. *Grape* +5. *Strawberry* +6. *Blueberry* + +--- + +*** *Additional Notes* +- *Tomatoes* are technically fruits (part of the nightshade family). +- *Coconut* is a tropical fruit, often used in cooking. +- *Papaya* is a versatile fruit with nutritional value. + +Let me know if you'd like a simplified version or a specific category (e.g., by +region, season, or type)! ๐๐")))) + (defun ellama-test-max-common-prefix () "Test the `ellama-max-common-prefix` function." (should (equal (ellama-max-common-prefix "" "") ""))