TODO 需要验证的问题

解决的问题 swift-mode build spm 项目,在repl 中debug spm 代码 ob-swift 默认使用 swift repl buffer ,达到共用 session 的效果 ob-swift 执行命令设置为 swift repl 需要验证的问题:ob-swift 是否和 swift-mode repl 共用 session

  1. 先编译 UnitDemo 项目 ,新建对话 进入 repl session
  2. 在 ob-swift 中使用默认的 session ,尝试 import UnitDemo 相关库。
  3. 整理 include 方法实现跨块的代码共享参数环境 Emacs: chaining org babel blocks Reddit - Dive into anything
  4. 整理 noweb 的用法,共享变量 Noweb Reference Syntax (The Org Manual)
  5. 整理 ob-babel 官方文档中的 header 参数的应用 Using Header Arguments (The Org Manual)
  6. swift-mode 使用自己的库

使用 :session 引入块环境

:PROPERTIES: nil:END:

1
2
3
4
let x = 1
let y = 2
let z = x + y
print(z)
1
let a = 1
1
2
3
print("test1----\(a)")
print("test2----\(a)")
print("test3----\(a)")

优化 ob-swift session 对话脚本问题

熟悉几个命令 start-process call-interactively

  1. 源库中使用使用 process
1
2
3
4
5
6
7
(let ((obname "*ob-swift-xx*"))
  (start-process obname obname "sudo swift repl")
  )
(let ((obname "*ob-swift-xx*"))
  (process-send-string obname (format "%s\n\"%s\"\n" "print(\"hello\")" ob-swift-eoe))
  (accept-process-output (get-process obname) nil nil 1)
  )
  1. fork库中 使用 swift-mode 方法 run-swift
1
2
3
4
5
6
7
(save-window-excursion
  (let ((obname "*swift-repl*"))
    (setq swift-mode:repl-buffer obname)
    (call-interactively 'run-swift)
    (get-buffer obname)
    )
  )

(call-interactively ‘run-swift) 方法执行之后,仍提示 no process 是什么原因

这可能是因为 run-swift 方法未能正确启动 Swift 进程。你可以尝试重新启动 Emacs 或检查你是否正确配置了 Swift 环境。你也可以尝试手动启动 Swift 进程以确保它能正常工作。

如何解决这个问题:ob-swift–eval-in-repl: Buffer ob-swift-my-session has no process

设置 ob-swift 默认 session 名称:session “Swift REPL [swift repl]

1
print(a)

使用 ob-swift 引入第三方库:借助swift-mode:debug-swift-module方法实现

借助 swift-mode:debug-swift-module 方法实现,该方法会新建进程和 swift-repl buffer 它名通过 swift repl 执行的命令命名,例如:`swift repl -i …` 查看进程列表: list-process 查看buffer: spc b B 通过这两个方法可以找到 repl buffer 的名称。

然后,设置 ob-swift 的 `:session` 的名称 *Swift REPL [swift repl -i ...]* ,这样,在运行代码块的时候,就可以和 swift-mode 共用环境。

1
import UnitLib

这样就可以在代码块中调用第三方库了。

处理 outdata 字符串,截取 //—- 之后的字符串,使用elisp 实现上述功能,举例说明

可以使用 split-string 函数将 outdata 字符串分割成多个行,并使用 nthcdrmember 函数来找到 //---- 之后的所有行。以下是一个示例实现:

在elisp 中通过在指定的字符串分割原始字符串,并得到最后部分,举例说明

可以使用=split-string=函数来分割字符串。例如,要在字符串"/usr/local/bin"中分割出最后一个部分"bin",可以使用如下代码:

1
2
(setq outdata "test2----\(a)\nprint(\"test3----\")\n//----\ntest1----1\n326> test2----1\n327> test3----1")
(car (last (split-string outdata "//----\n")))
1
2
3
test1----1
326> test2----1
327> test3----1

其中, (split-string "/usr/local/bin" "/") 将字符串 “usr/local/bin” 以 “” 为分隔符分割成一个字符串列表, last 函数返回列表中的最后一个元素,然后用 car 函数取出这个元素的值。

通过 :noweb 传值

1
const char * message1 = "hello from block 1";

1
const char * message2 = "hi from block 2";
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>

<<c1>>
<<c2>>

int main(void) {
  printf("%s\n", message1);
  printf("%s\n", message2);
  return 0;
}
1
2
hello from block 1
hi from block 2

通过 :var 跨源块传递值

  1. 第一步 声明块变量: ,#+name: c_hello
  2. 第二步 在块中引用: :var data=块变量

1
2
  #include <stdio.h>
  int main(void) { printf("hello C"); return 0; }
1
  echo hello from sh $data
1
hello from sh hello C

通过 :include 引用块环境

  1. 第一步 重写 adviced:org-babel-execute-src-block
  2. 第二步 声明块变量名: ,#+name: b1
  3. 第三步 引入块环境: :include 块变量名
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
       (defun adviced:org-babel-execute-src-block (&optional orig-fun arg info params)
         (let ((body (nth 1 info))
               (include (assoc :include (nth 2 info)))
               (named-blocks (org-element-map (org-element-parse-buffer)
                                 'src-block (lambda (item)
                                              (when (org-element-property :name item)
                                                (cons (org-element-property :name item)
                                                      item))))))
           (while include
             (unless (cdr include)
               (user-error ":include without value" (cdr include)))
             (unless (assoc (cdr include) named-blocks)
               (user-error "source block \"%s\" not found" (cdr include)))
             (setq body (concat (org-element-property :value (cdr (assoc (cdr include) named-blocks)))
                                body))
             (setf (nth 1 info) body)
             (setq include (assoc :include
                                  (org-babel-parse-header-arguments
                                   (org-element-property :parameters (cdr (assoc (cdr include) named-blocks)))))))
           (funcall orig-fun arg info params)))
    
       ;; 这段代码使用 =advice-add= 函数,在 =org-babel-execute-src-block= 周围添加了一个名为 =adviced:org-babel-execute-src-block= 的 advice。这意味着在执行 =org-babel-execute-src-block= 时,将首先执行此 advice 中定义的代码,然后再执行原始函数中的代码。
       (advice-add 'org-babel-execute-src-block :around 'adviced:org-babel-execute-src-block)
       解释一下这段代码
    

1
  const char * message1 = "hello from block 1";

1
  const char * message2 = "hello from block 2";
1
2
3
4
5
6
  #include <stdio.h>
  int main(void) {
    printf("%s\n", message1);
    printf("%s\n", message2);
    return 0;
  }
1
2
hello from block 1
hello from block 2

在运行代码时提示错误:use of undeclared identifier ‘message1’ printf("%s\n", message1);

这是因为 message1 的作用域仅限于 b1 块中,无法在 main 函数内部访问。可以将 message1 定义成全局变量或使用 #include 指令将 b1 块中的代码直接包含到 main 函数中。例如,将 b1 的代码直接放到 main 函数上方,或者在 main 函数中使用 #include "file.org::b1" 来包含 b1 块中的代码。

自定义 ob-babel

TODO 自定义 ob-swift

dotfiles/configuration.org at 71adbedf80d4985a14c674f14c386dc8232da824 · Nich…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
(defun org-babel-execute:swift (body params)
  "Execute a block of Swift code with org-babel."
  (message "executing Swift source code block")
  (ob-swift--eval body))

(defun ob-swift--eval (body)
  (with-temp-buffer
    (insert body)
    (shell-command-on-region (point-min) (point-max) "swift -" nil 't)
    (buffer-string)))

(provide 'ob-swift)

这是一个定义了 `org-babel-execute:swift` 函数的 Emacs Lisp 代码段,用于执行 Swift 代码块。下面是代码的注释说明:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
;; 定义一个名为 `org-babel-execute:swift` 的函数
;; 该函数接受两个参数,`body` 表示代码块中的代码字符串,
;; `params` 包含了代码块的参数列表和其他信息
(defun org-babel-execute:swift (body params)
  ;; 获取参数列表中 `:session` 参数的值,即 REPL 会话名称
  (let ((session (cdr (assoc :session params))))
    ;; 如果 `:session` 参数的值为 "none",表示不使用 REPL,
    ;; 直接调用 `ob-swift--eval` 函数执行代码
    (if (string= "none" session)
        (ob-swift--eval body)
      ;; 否则使用 `ob-swift--eval-in-repl` 函数在 REPL 中执行代码
      (ob-swift--eval-in-repl session body)))))

TODO 自定义AI ob-slack 对话模块

新建模块在 emacs-slack 基础上,新增 ob-babel 功能,例如在org-mode 中和指定的人聊天

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
(defun org-babel-execute:slack (body params)
  "Execute Slack message BODY with PARAMS."
  (let* ((user (cdr (assoc :user params)))
         (buffer-name (format "*Slack - %s*" user)))
    (if user
        (slack-user-buffer user) ; Enter private buffer with user
      (slack-buffer)) ; Enter default Slack buffer
    (insert body)
    (slack-send-message-or-comment)
    (slack-read-mode)))

(defvar org-babel-default-header-args:slack
  '((:user . "创客屋 : Claude") ; Default Slack user
    (:session . "none")
    (:results . "none"))
  "Default header arguments for slack blocks.")

(add-to-list 'org-babel-exec-map '("slack" . org-babel-execute:slack))
(add-to-list 'org-babel-prep-session-alist '(slack . org-babel-prep-session:slack))
1
Hi there! How's it going?