3

I am trying to search backwards and find [ but skip all square brackets within strings. I came across (nth 3 (syntax-ppss)); but I can't figure out how to use it with let in the following code:

(defun ext-ess-symbol-at-point-modified ()
  "Return the name of a symbol to the left of \"[\"."
  (interactive)
  (save-excursion
    (let* ((cpoint (point))
           (sbt0 (search-backward "[" 1 t))
           (sbt1 (search-forward "]" cpoint t)))
      (if (and sbt0 (not sbt1))
          (progn (goto-char (1- sbt0))
                 (message "%s" (buffer-substring
                                (search-backward-regexp "^\\|[[:space:]]")
                                sbt0)))
        (error "Could not find open square bracket \"[\"")))))

I would like something along the lines of

(let* ((cpoint (point))
       (sbt0 (while (nth 3 (syntax-ppss))
               (search-backward "[" 1 t)))
1
  • Just to address your title - while always returns nil, so if you want to subsequently return something else you need to place the loop within some other construct, e.g. let/progn/etc.
    – Basil
    Mar 1, 2018 at 23:59

2 Answers 2

1

I would like something along the lines of

(let* ((cpoint (point))
       (sbt0 (while (nth 3 (syntax-ppss))
               (search-backward "[" 1 t)))

As Basil pointed out, you're looking for progn, e.g.:

(let* ((cpoint (point))
       (sbt0 (progn (while (nth 3 (syntax-ppss))
                      (search-backward "[" 1 t))
                    (point)))

Actually, I was wondering if there is a function that will get the location of the open square bracket to the left (even if it is on lines above). For example the first [ in

data2[col1 %in% data1[grepl("[[:num:]]+", some_col), another_col], point_here]

Try syntax-ppss: (goto-char (car (last (nth 9 (syntax-ppss)))))

(Avoiding wrong-type-argument when point is not within any brackes left as an exercise for the reader. Also, skipping over non-square parens.)

(syntax-ppss &optional POS)

Parse-Partial-Sexp State at POS, defaulting to point.
The returned value is the same as that of ‘parse-partial-sexp’ [...]

(parse-partial-sexp FROM TO &optional TARGETDEPTH STOPBEFORE OLDSTATE
COMMENTSTOP)

[...]    
Value is a list of elements describing final state of parsing:
 [...]
 9. List of positions of currently open parens, outermost first.
4
  • Thanks! I've written something that seems to work fine (no the code in my answer) but looked rather cumbersome. I will try to re-write using your advice above. Thanks again for the pointers!
    – Arktik
    Mar 4, 2018 at 12:20
  • I had checked whether a point was outside any brackets with: (< (nth 0 (syntax-ppss)) 1).
    – Arktik
    Mar 4, 2018 at 12:37
  • @A.Blizzard Switching syntax tables is possible, but you have to be careful about the syntax-ppss cache getting messed up (e.g., Bug#29710). I would recommend looping over the (reverse (nth 9 (syntax-ppss))) list until you reach a square bracket instead.
    – npostavs
    Mar 4, 2018 at 13:02
  • Yes, I think that's the way to go. Thanks again!
    – Arktik
    Mar 4, 2018 at 13:21
0

I've finally written this

(defun ext-ess-symbol-at-point-modified ()
  "Get the name of a symbol to the left of '[' from inside '[ ]'."
  (interactive)
  (save-excursion
    (let ((cpoint (point))
          (sbt0 (search-backward "[" 1 t)))
      (while (nth 3 (syntax-ppss))
        (setq sbt0 (search-backward "[" 1 t)))
      (setq sbt1 (search-forward "]" cpoint t))
      (when (and sbt1 (nth 3 (syntax-ppss)))
        (let (anynill)
          (while (not anynill)
            (setq sbt1 (search-forward "]" cpoint t))
            (unless (and sbt1 (nth 3 (syntax-ppss)))
              (setq anynill t)))))
      (if (and sbt0 (not sbt1))
          (message "%s" (buffer-substring
                          (+ (search-backward-regexp "[^[:alnum:]_.]") 1) sbt0))                             
        (error "Couldn't find open square bracket '['")))))

Not sure whether it's the best way. Couldn't figure out how to do it inside let.

Actually, I was wondering if there is a function that will get the location of the open square bracket to the left (even if it is on lines above). For example the first [ in

data2[col1 %in% data1[grepl("[[:num:]]+", some_col), another_col], point_here]

when the cursor is on point_here. And if inside square brackets of data1 then it will find the bracket in data1[. I would have thought there would be a ready function for finding open brackets?!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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