1

I have written a Python function that takes a string input and performs a semantic search in my org-roam-directory and outputs the results in the following format after 2 seconds of computation:

[{'score': 0.9137982130050659, 'file:': '/Users/user/org/example.org', 'content': 'In this article, we introduce a new algorithm.'}, {'score': 0.9033759832382202, 'file:': '/Users/user/org/statistical_model.org', 'content': 'Statistical Model for Denoising.'}]

So it is essentially a list of dictionary with score, file location, and content. I can call the Python function in the command line by invoking: /Users/user/org/anaconda3/bin/python /Users/user/org/sentence-transformer.py "algorithm and model" and then it gives me the above printed output in the terminal.

I want to present this output in the Emacs minibuffer just like consult-ripgrep, and be able to select one of the options and open the file's content in another buffer.

I am currently trying to do this in Elisp as follows:

(defun open-file-from-python-script (input-string)
  (interactive "sEnter input string: ")
  (let* ((python-script-path "/Users/user/org/sentence-transformer.py")
         (output-string (shell-command-to-string (concat "/Users/user/org/anaconda3/bin/python " python-script-path " " input-string)))
         (output-list (json-read-from-string output-string))
         (file-path (completing-read "Select a file: " output-list :key #'cdr :predicate #'stringp)))
    (find-file file-path)))

However, it does not work and only outputs: Bad String Format: 10

I am not too familiar with Elisp so I was wondering how to do this properly?

Drew
  • 75,699
  • 9
  • 109
  • 225
user39819
  • 11
  • 2
  • https://emacs.stackexchange.com/tags/elisp/info – Drew Jan 28 '23 at 17:39
  • Can you clarify (in the question) what you mean by "does not work"? – Drew Jan 28 '23 at 17:39
  • It would be handy to add a notification about this 'follow up' question to your previous related question [here](https://emacs.stackexchange.com/questions/75565/how-to-present-my-semantic-search-model-results-in-minibuffer-to-select-them-and). Anyway, `json-read-from-string` expects a json object as argument, so I guess you can best convert your dictionary to json, e.g. using `json.dumps`. Also make sure that your script outputs (i.e. prints) that json string. I'm not sure what causes that error message, maybe try `M-x toggle-debug-on-error`. – dalanicolai Jan 28 '23 at 21:05

1 Answers1

1

Using your example value, you can output (print) a 'valid' json structure using dumps() from the python json module.

Subsequently, because json-read-from-string returns a vector after parsing that output, you should use the 'generic' seq-map function to map over that vector.

By printing your example value via print(json.dumps(value)) from a test file named 'test.py', the files can be listed using the following code

(defun open-file-from-python-script ()
  (interactive)
  (let* ((output-list (json-read-from-string (shell-command-to-string "python test.py")))
         (files-list (seq-map #'cdadr output-list))
         (file-path (completing-read "Select a file: " files-list)))
    (find-file file-path)))

B.t.w. if your Emacs was compiled with libjansson, then you could use json-parse-string for parsing the json.

dalanicolai
  • 6,108
  • 7
  • 23