Emacs: run shell command with regex and Lisp function to start gud

417 Views Asked by At

I am tring to write some Emacs Lisp function to be able to simply compile and debug Java classes within Spacemacs using its Java layer (don't want to go into complex packages like jdee). The compile function is defined beblow and works as expected

(defun my-java-compile (command)
  (interactive (list (read-string
                      "Command: "
                      (concat
                           "javac"
                       " -d "
                       java-dest-path
                       " -cp "
                       java-class-path
                       " "
                       (file-name-nondirectory buffer-file-name)))))
  (unless (file-exists-p java-dest-path)
    (make-directory java-dest-path))
  (compilation-start command nil)
  )

The java-dest-path and java-class-path are local variables set in the .dir-locals.el in the root directory of the project.

The debug function is defined as:

;; get fully qualified class name
(defun get-fqcn ()
  (setq get-package-name-command
        (concat
         "gsed -n 's/^package\s\+\([^;\s]\+\);\s*$/\1/p' "
         buffer-file-name))
  (setq fqpn (shell-command-to-string get-package-name-command))
  (if (equal "" fqpn) (file-name-base buffer-file-name)
    (concat fqpn "." (file-name-base buffer-file-name)))
  )

(defun my-jdb (command)
  (interactive (list (read-string
            "Command: "
            (concat
              "jdb"
              " -classpath "
              java-class-path
              " "
              (get-fqcn)))))
  (helm-M-x nil jdb command)
  )  

I am still trying to make it work. Here are the two issues:

  1. when running shell-command-to-string function, the gsed -n 's/^package\s\+\([^;\s]\+\);\s*$/\1/p' java_file command returns an empty string "", while it returns the fully qualified package name as expected when running in a terminal. If I change it to gsed -n '/^package/p', the emacs function return the package line OK. So it seems shell-command-to-string could not handle the regular expression in gsed. Any work around?
  2. I could not find the function to trigger the gud or jdb . What would be the gud equivalent of compilation-start function?
1

There are 1 best solutions below

5
On BEST ANSWER
  1. The problem is that you want to include backslashes in your regexp, but backslashes are already used as escape characters in Emacs Lisp strings. Let's try displaying the string in the echo area:

    (message "%s" "gsed -n 's/^package\s\+\([^;\s]\+\);\s*$/\1/p' ")
    

    This displays:

    gsed -n 's/^package +([^; ]+); *$/^A/p' 
    

    So as you can see, the backslashes were "eaten" by the Emacs Lisp parser. We need to double the backslashes in order for them to appear literally in the string we send to gsed:

    "gsed -n 's/^package\\s\\+\\([^;\\s]\\+\\);\\s*$/\\1/p' "
    

    Alternatively, implement the search in Emacs Lisp:

    (save-excursion
      (goto-char (point-min))
      (search-forward-regexp "^package[[:blank:]]+\\([^;[:blank:]]+\\);")
      (match-string 1))
    
  2. The function for running jdb inside gud is jdb:

    (jdb command)