Hot answers tagged

13

Well, s-expressions are essentially “abstract syntax”, in the sense that they are merely a concrete syntax for abstract syntax trees, and thus any language can be represented as s-expressions, and manipulated with s-expression commands. Hence, syntax-ppss speaking of “Sexps” is simply the Lisp way to talk about abstract syntax trees. Practically, though, ...


10

Rather than up-list I'd recommend you use (syntax-ppss) which will return to you some parsing state. This will include info about whether you're inside a string or a comment, the position of the last open "paren" etc... E.g. you can find the kind of paren with (let ((ppss (syntax-ppss))) (when (nth 1 ppss) (char-after (nth 1 ppss)))) and it should ...


9

You can have a look at the built-in library SMIE (stands for Simple-Minded Indentation Engine). Despite the name, indentation is only one of the features it provides. This is the method used by many modes (including ruby-mode, mentioned in a comment), to provide sexp movement and indentation. Deploying SMIE for a language is roughly a two-steps job: define ...


8

Emacs's built-in date parser is parse-time-string in parse-time.el, called by date-to-time. It understands English month and weekday names and several combinations of elements in various orders, but not expressions like “next Wednesday”. The date input formats in the GNU date command provided on non-embedded Linux and Cygwin are implemented in the source of ...


5

Try this: (save-excursion (up-list) (char-before)) Note that up-list can throw, so you need to handle errors as well.


5

Some remarks at first: This question should not only be about finding the end of a string. Also finding the beginning of a string is quite complicated if you want to do it right. There may be double-quote characters ?\" within the program text that must be ignored. Furthermore there may be single double-quote characters within comments that also must be ...


4

Does this do what you want? (split-string-and-unquote "program arg1 arg2 \"long argument with spaces\" \"arg\"3") There seemed to be an error in your string with an unmatched \" at the end that caused this function to not work. I am not sure if it makes sense to have the single " in there or not. If it does, you might have to write your own parser.


4

I use this regexp string: "\"\\(?:[^\\\"]\\|\\\\\\(?:.\\|[\n]\\)\\)*\"". It matches two " chars enclosing zero or more occurrences of either a non-", non-backslash or a backslash followed by any character (including " and newline). For example: (re-search-forward "\"\\(?:[^\\\"]\\|\\\\\\(?:.\\|[\n]\\)\\)*\"" nil 'NO-ERROR)


4

Behold: (defun fancy-split (input) (let (tokens) (with-temp-buffer (insert input) (goto-char (point-min)) (while (not (eobp)) (cond ((looking-at "{") (forward-char) (let ((start (point))) (if (search-forward "}" nil t) (let ((token (buffer-substring start (1- (point)))))...


4

Adding to @lunaryorn's answer, I think syntax-ppss just rely on the robustness of emacs's syntax table system, which works for comment and string in most languages. But if the language has syntax that syntax table can't capture, and if the mode did't build a parser to add syntax properties to the right places, syntax-ppss would fail. Try this in html-mode: ...


2

I made a library for this Once defined, a bunch of commands are available, moving forward, backward, copy etc. Defining --in pseudo-code--: (put 'MY-FORM 'beginning-op-at (lambda () MY-FORWARD-MOVE-CODE)) (put 'MY-FORM 'end-op-at (lambda () MY-BACKWARD-MOVE-CODE)) When done, it's should be available, i.e. copied and returned like this (...


2

I made an Elisp only solution: You can call it using M-x dow-time and in code using (dow-time 3) (defvar dow-time-days '(("Monday" . 1) ("Tuesday" . 2) ("Wednesday" . 3) ("Thursday" . 4) ("Friday" . 5) ("Saturday" . 6) ...


2

Here's something you could do using PEG parser. PEG parsers are a formalism allowing for generation of parsers without a tedious process like the one associated with YACC-style parsers. PEG-style parsers cannot capture some context-free languages, but due to easy augmentation with user code, they may often capture even some complex context-sensitive ...


2

Here's a recursive function that returns the name as a list of its components. (defun name-to-list (name &optional acc) "Takes a BibTeX-style name and returns a list of the name components." (if (string-equal name "") (nreverse (mapcar (lambda (part) (string-trim part "[ {]+" "[ }]+")) acc)) ...


2

I think you should be able to do something like this: emacsclient -e '(pp (with-temp-buffer (insert-file-contents "my-file-containing sexp") (read (current-buffer))))' The problem is that this will print a string (e.g., "[foo\n bar]"), so to see it on the screen you will need echo -e $(emacsclient ...) You can control the behavior of pp with many ...


2

There is the general rule that any widely used programming language such as R has an Emacs language mode and those modes also have functions that parse function arguments. For R there is the huge package Emacs Speaks Statistics. There is a parser ess-r-syntax. The comment marks it as "not yet stable". But, there are 4 people working on it including senior ...


1

Under the theory that some answer is better than none, I've posted my hacky solution to this, however I would welcome a better answer than this one. (defun find-next-fcn-arg-separator () "Find the next argument separator in a function call. Move point to the next function argument separator. Point is expected to be at the opening parenthesis of the ...


1

Since there doesn't appear to be a function for the job, I wrote one: (defun shell-command-line-to-argument-list (command-line) (let (args arg inquote) (with-temp-buffer (insert command-line) (goto-char (point-min)) (while (not (eobp)) (cond ((looking-at "\\s-+") (cond ((not inquote) (when ...


1

While the preferable answer IMO was given by Stefan, here an example which includes a solution not relying on syntax-table WRT delimiters: It uses something like (skip-chars-backward "^{\(\[\]\)}") and a stack. See source here https://github.com/emacs-berlin/general-close


Only top voted, non community-wiki answers of a minimum length are eligible