0

So I have a defun that I made that is supposed to copy every thing that is between double quotes and then make a list of everything that was copied. I don't know what the problem is, but it doesn't seem to work with every list of quoted text.

There is a change log that would be something like this format.

"Type1" changed ~such and such data.

"Type2" changed ~such and such data.

And then I would like my defun to simply copy the text between the double quotes and then spit them out into a summary change log that would go something like this.

Changes were made to the following types.

Type1

Type2

etc.

The purpose of this is to write a change log. Everything that has changed is supposed to be between quotation marks. The defun is supposed to print out Changes were made to the following types then a separate new line and then the list of everything that was quoted. It is possible that there could be dozens of "types" within hundreds of lines of text that need to be recorded in a change log. It is imperative that this change log list is accurate at the end.

I am not sure if the problem is in my copy-region-as-kill loop, or in my "yank" loop. I made it copy the quoted text three times and then delete the duplicate lines in an attempt to get this to work. That got it to work with one specific list, but it does not work with all of them. Here is my defun.

(defun change-log()
  "I created this to automatically copy all \"Types\" during categorization maintenance. It will also automatically create the change log for you at the end of the text file."
  (interactive)
  (setq x 1)
  (while (search-forward "\"" nil t)
    (setq pos (point))
    (set-mark-command nil) 
    (search-forward "\"" nil t)
    (backward-char)
    (setq pos2 (point))
    (kill-ring-save (region-beginning) (region-end))
     (kill-ring-save pos pos2)
     (kill-ring-save pos pos2)
    (forward-char)
    (setq x (1+ x)))
  (setq x (1+ x))
  (setq x (* x 3))
  (setq y (1+ x))
  (end-of-buffer)
  (insert "\n")
  (insert "\n")
  (insert "Changes were made to the following types.")
  (insert "\n")
  (insert "\n")
  (setq pos (point))
  (yank x)
  (insert "\n")
  (while (> x 0)
    (yank x)
    (insert "\n")
    (setq x (1- x)))
  (yank y)
  (insert "\n")
  (yank x)
   (setq pos2 (point))
   (delete-duplicate-lines pos pos2)
   (backward-paragraph)
   (while (search-forward-regexp "\\.$" nil t)
     (replace-match "" nil))
   (auto-whitespace-remove)
   (forward-paragraph)
   (set-mark-command nil)
   (backward-paragraph))
  • Define "does not work". It's not clear what you are trying to do, to start with. State what you expect to have happen and what happens instead. – Drew Feb 20 '18 at 22:40
  • I put right in there what the defunct is reading and what the expected output is. – CigEmacs Feb 20 '18 at 23:44
  • I am trying to copy everything between double quotes and then spit it back out into a list at the end. – CigEmacs Feb 20 '18 at 23:44
  • This part is described, but you don't describe in which way your code fails to do what you want. This said, I can already recommend you don't use the kill-ring (instead, use something like (push (buffer-substring pos pos2) mythingies) to collect the elements into a list called mythingies and later then use (dolist (mythingy mythingies) (insert mythingy)) to use those elements. Also, please declare your variables with let so as to avoid modifying global variables. Try M-x byte-compile-file RET RET and look at the warnings you get. – Stefan Feb 22 '18 at 8:06
  • All of that was addressed in @sds's answer. I now have a commented defun that works perfectly, but I am not familiar with the rules here and I am unsure if it is appropriate to edit this to post the defun that works after I have already accepted an answer. – CigEmacs Feb 22 '18 at 13:33
0

Since it is not very clear (to put it mildly) what you are trying to accomplish, and you do not offer any test cases, I cannot pinpoint any bugs in your code.

However, I can make several suggestions that would make your life easier.

Major

Do not use interactive commands in code

You are using kill-ring-save and yank. This is a very bad idea: these functions do a lot of complicated things (like interprogram communications) and operate on kill ring of limited size.

Use buffer-substring-no-properties and insert instead.

Avoid globals.

Bind all your variables (e.g., x and y) in your code with let. Give them meaningful names (pos is okay).

Minor

Indentation

Please do fix your indentation. Emacs can help (use TAB). Your code is hard to read.

Shorten your code

The shorter the code, the easier it is to parse and understand (ceteris paribus).

  • Replacing multiple consecutive insert statements with a single one is a good idea.

  • setq can set many variables in one form

  • incf is very useful

Read the tutorial

An Introduction to Programming in Emacs Lisp is well worth your time.

  • Just a couple of nits: (a) I remember reading somewhere on emacs-devel that using a single call to setq for setting multiple variables is only supported for backward compatibility, i.e. it is generally unfavourable; and (b) incf implies cl.el, which is deprecated - better recommend cl-incf from cl-lib.el. Otherwise, good points. – Basil Feb 20 '18 at 20:05
  • @Basil: What you say about setq is nonsense. You may have read that somewhere from someone, but they were wrong on both counts: (1) it is not only for backward compatibility and (2) it is not unfavorable (that's my opinion). Its only drawback is the need for slightly more editing when you make some kinds of change. It is no more unfavorable than using let with multiple bindings. – Drew Feb 20 '18 at 22:29
  • @Drew Maybe I should have emphasised the nit-iness of my comment more. – Basil Feb 20 '18 at 22:30
  • @Drew That it is defined in cl.el, rather than cl-lib.el. See (cl) Organization. – Basil Feb 20 '18 at 22:33
  • Thanks, you led me to an answer. Using (insert "\n" (buffer-substring pos pos2)) worked just fine outside of a while loop. However, inside of a while loop it causes Emacs to crash. I can insert literally anything else within the loop (for example, just a new line without the substring), and it doesn't cause the crash. I believe this is a new issue that doesn't have anything to do with my original problem and might possibly be a bug. I'm trying to figure it out now. – CigEmacs Feb 21 '18 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.