* Defining functions on the fly @ 2015-06-15 9:24 Andreas Röhler 2015-06-15 9:32 ` Dmitry Gutov ` (3 more replies) 0 siblings, 4 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-15 9:24 UTC (permalink / raw) To: help-gnu-emacs Hi, have a bunch of subroutines which are useful in several modes - beginning/end of expressions, string positions, comments etc. Now every mode should get its own prefix. Can't write (defun (concat "current-prefix-" foo) ()) as defun expects a symbol. Exists "fset" - is there a recommended way to go? Thanks, Andreas ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 9:24 Defining functions on the fly Andreas Röhler @ 2015-06-15 9:32 ` Dmitry Gutov 2015-06-15 9:47 ` Alexis ` (2 subsequent siblings) 3 siblings, 0 replies; 43+ messages in thread From: Dmitry Gutov @ 2015-06-15 9:32 UTC (permalink / raw) To: Andreas Röhler, help-gnu-emacs On 06/15/2015 12:24 PM, Andreas Röhler wrote: > Exists "fset" - is there a recommended way to go? Probably not. You might want to look at `cl-labels'. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 9:24 Defining functions on the fly Andreas Röhler 2015-06-15 9:32 ` Dmitry Gutov @ 2015-06-15 9:47 ` Alexis 2015-06-15 10:20 ` Andreas Röhler 2015-06-15 10:00 ` Tassilo Horn [not found] ` <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org> 3 siblings, 1 reply; 43+ messages in thread From: Alexis @ 2015-06-15 9:47 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > Now every mode should get its own prefix. Can't write > > (defun (concat "current-prefix-" foo) ()) > > as defun expects a symbol. i'm probably misunderstanding you, but does: (defun (intern (concat "current-prefix-" foo) ... do what you need? Alexis. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 9:47 ` Alexis @ 2015-06-15 10:20 ` Andreas Röhler 2015-06-15 10:37 ` Alexis ` (2 more replies) 0 siblings, 3 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-15 10:20 UTC (permalink / raw) To: help-gnu-emacs Am 15.06.2015 um 11:47 schrieb Alexis: > > Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > >> Now every mode should get its own prefix. Can't write >> >> (defun (concat "current-prefix-" foo) ()) >> >> as defun expects a symbol. > > i'm probably misunderstanding you, but does: > > (defun (intern (concat "current-prefix-" foo) ... > > do what you need? > > > Alexis. > Seems (intern... is not evaluated at this point: (defvar pfxd "pfxd-") (defun (intern (concat pfxd "-foo")) ()) --> Debugger entered--Lisp error: (wrong-type-argument symbolp (intern (concat pfxd "-foo"))) defalias((intern (concat pfxd "-foo")) (lambda nil nil)) eval((defalias (quote (intern (concat pfxd "-foo"))) (function (lambda nil nil))) nil) eval-last-sexp-1(nil) eval-last-sexp(nil) call-interactively(eval-last-sexp nil nil) command-execute(eval-last-sexp) ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 10:20 ` Andreas Röhler @ 2015-06-15 10:37 ` Alexis 2015-06-15 10:41 ` Michael Heerdegen 2015-06-15 10:42 ` Tassilo Horn 2 siblings, 0 replies; 43+ messages in thread From: Alexis @ 2015-06-15 10:37 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > Seems (intern... is not evaluated at this point: > > (defvar pfxd "pfxd-") > > (defun (intern (concat pfxd "-foo")) ()) You're right, sorry! When i use `intern' like this, it's in the context of quasiquoting, e.g.: (eval `(defun ,(intern (concat "ewmctrl-select-window-" chosen-char "-for-action")) () ,(concat "Select window '" chosen-char "' for an action.") (interactive) (ewmctrl--dispatch-action ,chosen-char))) Alexis. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 10:20 ` Andreas Röhler 2015-06-15 10:37 ` Alexis @ 2015-06-15 10:41 ` Michael Heerdegen 2015-06-15 10:42 ` Tassilo Horn 2 siblings, 0 replies; 43+ messages in thread From: Michael Heerdegen @ 2015-06-15 10:41 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > Seems (intern... is not evaluated at this point: > > (defvar pfxd "pfxd-") > > (defun (intern (concat pfxd "-foo")) ()) > > --> > > Debugger entered--Lisp error: (wrong-type-argument symbolp (intern That's expected. You need to use `defalias' if you want to specify the function name at run time. Or use a macro. Michael. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 10:20 ` Andreas Röhler 2015-06-15 10:37 ` Alexis 2015-06-15 10:41 ` Michael Heerdegen @ 2015-06-15 10:42 ` Tassilo Horn 2015-06-15 11:01 ` Alexis 2015-06-15 11:19 ` Michael Heerdegen 2 siblings, 2 replies; 43+ messages in thread From: Tassilo Horn @ 2015-06-15 10:42 UTC (permalink / raw) To: Andreas Röhler; +Cc: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: >> i'm probably misunderstanding you, but does: >> >> (defun (intern (concat "current-prefix-" foo) ... >> >> do what you need? > > Seems (intern... is not evaluated at this point: > > (defvar pfxd "pfxd-") > > (defun (intern (concat pfxd "-foo")) ()) > > --> > > Debugger entered--Lisp error: (wrong-type-argument symbolp (intern (concat pfxd > "-foo"))) > defalias((intern (concat pfxd "-foo")) (lambda nil nil)) This might depend on emacs version. At least with the current git version, `defalias' evaluates its first argument: (defalias (intern "foo-bar") #'forward-sexp) ;; Works fine But as Pascal already said, duplicating your function is not a good idea. Defining aliases is a bit better if you persist on prefixed versions although I the only benefit I can see is a slightly better discoverability through C-h f <prefix>-TAB. Bye, Tassilo ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 10:42 ` Tassilo Horn @ 2015-06-15 11:01 ` Alexis 2015-06-15 11:19 ` Michael Heerdegen 1 sibling, 0 replies; 43+ messages in thread From: Alexis @ 2015-06-15 11:01 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tsdh@gnu.org> writes: > But as Pascal already said, duplicating your function is not a > good idea. Defining aliases is a bit better if you persist on > prefixed versions although I the only benefit I can see is a > slightly better discoverability through C-h f <prefix>-TAB. Related: i created the snippet i pasted from `ewmctrl' so that when users do C-h m, they can read a helpfully-named function for a dynamically-generated keybinding, rather than "??". i imagine there's probably a Better Way To Do It™, though. :-) Alexis. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 10:42 ` Tassilo Horn 2015-06-15 11:01 ` Alexis @ 2015-06-15 11:19 ` Michael Heerdegen 2015-06-15 11:24 ` Tassilo Horn 1 sibling, 1 reply; 43+ messages in thread From: Michael Heerdegen @ 2015-06-15 11:19 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tsdh@gnu.org> writes: > > (defvar pfxd "pfxd-") > > > > (defun (intern (concat pfxd "-foo")) ()) > > > > --> > > > > Debugger entered--Lisp error: (wrong-type-argument symbolp (intern > > (concat pfxd > > "-foo"))) > > defalias((intern (concat pfxd "-foo")) (lambda nil nil)) > > This might depend on emacs version. At least with the current git > version, `defalias' evaluates its first argument: > > (defalias (intern "foo-bar") #'forward-sexp) ;; Works fine In the example above, in the expansion of the `defun' call the first argument to defalias is the (unevaluated!) list: (intern (concat pfxd "-foo")) The corresponding call to defalias will also fail on trunk. Michael. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 11:19 ` Michael Heerdegen @ 2015-06-15 11:24 ` Tassilo Horn 2015-06-15 11:31 ` Michael Heerdegen 0 siblings, 1 reply; 43+ messages in thread From: Tassilo Horn @ 2015-06-15 11:24 UTC (permalink / raw) To: Michael Heerdegen; +Cc: help-gnu-emacs Michael Heerdegen <michael_heerdegen@web.de> writes: >> > Debugger entered--Lisp error: (wrong-type-argument symbolp (intern >> > (concat pfxd >> > "-foo"))) >> > defalias((intern (concat pfxd "-foo")) (lambda nil nil)) >> >> This might depend on emacs version. At least with the current git >> version, `defalias' evaluates its first argument: >> >> (defalias (intern "foo-bar") #'forward-sexp) ;; Works fine > > In the example above, in the expansion of the `defun' call the first > argument to defalias is the (unevaluated!) list: > > (intern (concat pfxd "-foo")) > > The corresponding call to defalias will also fail on trunk. Ah, yes, so that's basically as if (defalias '(intern (concat pfxd "-foo")) ...) had been written. Bye, Tassilo ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 11:24 ` Tassilo Horn @ 2015-06-15 11:31 ` Michael Heerdegen 0 siblings, 0 replies; 43+ messages in thread From: Michael Heerdegen @ 2015-06-15 11:31 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tsdh@gnu.org> writes: > Ah, yes, so that's basically as if > > (defalias '(intern (concat pfxd "-foo")) ...) > > had been written. Yip: (macroexpand '(defun (concat "current-prefix-" foo) ())) ==> (defalias '(concat "current-prefix-" foo) #'(lambda nil nil)) The "problem" is that the defun macro (intentionally) adds a quote, so that (defun name ..) expands to (defalias 'name ...) and `name' doesn't get evaluated. If the defun macro would not add that quote, you would have to write (defun 'name ...) but (defun (intern name) ...) would work then. Michael. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 9:24 Defining functions on the fly Andreas Röhler 2015-06-15 9:32 ` Dmitry Gutov 2015-06-15 9:47 ` Alexis @ 2015-06-15 10:00 ` Tassilo Horn 2015-06-15 10:33 ` Andreas Röhler [not found] ` <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org> 3 siblings, 1 reply; 43+ messages in thread From: Tassilo Horn @ 2015-06-15 10:00 UTC (permalink / raw) To: Andreas Röhler; +Cc: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: Hi Andreas, > have a bunch of subroutines which are useful in several modes - > beginning/end of expressions, string positions, comments etc. > > Now every mode should get its own prefix. I don't quite get what you are trying to achieve. If your beginning-of-expression function is useful in a-mode, b-mode, and c-mode, what's the purpose of defining it three times? If you really want to have separate {a,b,c}-beginning-of-expression functions, then you could do it by defining aliases. (dolist (prefix (list "a" "b" "c")) (defalias (intern (concat prefix "-beginning-of-expression")) #'beginning-of-expression)) Bye, Tassilo ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 10:00 ` Tassilo Horn @ 2015-06-15 10:33 ` Andreas Röhler 0 siblings, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-15 10:33 UTC (permalink / raw) To: help-gnu-emacs Am 15.06.2015 um 12:00 schrieb Tassilo Horn: > Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > > Hi Andreas, > >> have a bunch of subroutines which are useful in several modes - >> beginning/end of expressions, string positions, comments etc. >> >> Now every mode should get its own prefix. > I don't quite get what you are trying to achieve. If your > beginning-of-expression function is useful in a-mode, b-mode, and > c-mode, what's the purpose of defining it three times? AFAIU tab-completion of mode's symbols requires it equally prefixed. > If you really want to have separate {a,b,c}-beginning-of-expression > functions, then you could do it by defining aliases. > > (dolist (prefix (list "a" "b" "c")) > (defalias (intern (concat prefix "-beginning-of-expression")) > #'beginning-of-expression)) > > That works, thanks! ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] ` <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org> @ 2015-06-15 12:52 ` Stefan Monnier 2015-06-16 5:59 ` Andreas Röhler [not found] ` <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 43+ messages in thread From: Stefan Monnier @ 2015-06-15 12:52 UTC (permalink / raw) To: help-gnu-emacs > i'm probably misunderstanding you, but does: > (defun (intern (concat "current-prefix-" foo) ... > do what you need? (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but not with defun. In any case, some concrete example of what he needs to do would go a long way. Stefan ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 12:52 ` Stefan Monnier @ 2015-06-16 5:59 ` Andreas Röhler 2015-06-16 7:01 ` Tassilo Horn [not found] ` <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org> 1 sibling, 1 reply; 43+ messages in thread From: Andreas Röhler @ 2015-06-16 5:59 UTC (permalink / raw) To: help-gnu-emacs Am 15.06.2015 um 14:52 schrieb Stefan Monnier: >> i'm probably misunderstanding you, but does: >> (defun (intern (concat "current-prefix-" foo) ... >> do what you need? > (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but > not with defun. In any case, some concrete example of what he needs to > do would go a long way. > > > Stefan Currently Emacs provides some scheme to fontify source code and some basic moves: linewise, symbol, word, paragraph, sexp. There is no idea of statement, block/loop or expression and a poor top-level --beginning/end-of-defun. Just trying to implement a kind of default for this. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 5:59 ` Andreas Röhler @ 2015-06-16 7:01 ` Tassilo Horn 2015-06-16 9:22 ` Andreas Röhler ` (3 more replies) 0 siblings, 4 replies; 43+ messages in thread From: Tassilo Horn @ 2015-06-16 7:01 UTC (permalink / raw) To: Andreas Röhler; +Cc: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: >>> i'm probably misunderstanding you, but does: >>> (defun (intern (concat "current-prefix-" foo) ... >>> do what you need? >> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but >> not with defun. In any case, some concrete example of what he needs to >> do would go a long way. >> >> >> Stefan > > Currently Emacs provides some scheme to fontify source code and some > basic moves: linewise, symbol, word, paragraph, sexp. > > There is no idea of statement, block/loop or expression and a poor > top-level --beginning/end-of-defun. There is: `forward-sexp' and `backward-sexp'. Although the name sexp is a bit lisp-specific, sexp-based motion has been implemented for more C-like languages, too. For example, it works well for shell scripts and Ruby programs. See (info "(elisp) SMIE") for how to add sexp-based motion to your favorite programming language mode. Bye, Tassilo ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 7:01 ` Tassilo Horn @ 2015-06-16 9:22 ` Andreas Röhler 2015-06-16 11:12 ` Tassilo Horn 2015-06-16 9:42 ` Andreas Röhler ` (2 subsequent siblings) 3 siblings, 1 reply; 43+ messages in thread From: Andreas Röhler @ 2015-06-16 9:22 UTC (permalink / raw) To: help-gnu-emacs Am 16.06.2015 um 09:01 schrieb Tassilo Horn: > Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > >>>> i'm probably misunderstanding you, but does: >>>> (defun (intern (concat "current-prefix-" foo) ... >>>> do what you need? >>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but >>> not with defun. In any case, some concrete example of what he needs to >>> do would go a long way. >>> >>> >>> Stefan >> Currently Emacs provides some scheme to fontify source code and some >> basic moves: linewise, symbol, word, paragraph, sexp. >> >> There is no idea of statement, block/loop or expression and a poor >> top-level --beginning/end-of-defun. > There is: `forward-sexp' and `backward-sexp'. Although the name sexp is > a bit lisp-specific, sexp-based motion has been implemented for more > C-like languages, too. For example, it works well for shell scripts Unfortunatly couldn't experience this. There are several common cases within shell-script, where calls to navigate sexp would raise an error. That's why language-modes have to implement a couple of most basic things. See http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00013.html ### vorhanden() { for i in "blah" "blub"; do # some comment (note: for compatibility) if [ ! -x $i ]; then ### with cursor last line "if", C-M-b jumps to "for", but should end at "do" From "for" -> Debugger entered--Lisp error: (scan-error "Containing expression ends prematurely" 13 13) signal(scan-error ("Containing expression ends prematurely" 13 13)) smie-forward-sexp-command(-1) forward-sexp(-1) backward-sexp(1) call-interactively(backward-sexp nil nil) command-execute(backward-sexp) There are many more spots in this example to trigger error or unexpected moves. Or take this: ### if [ $# == 0 ]; then # some comment (note: for compatibility) set "" `find . -maxdepth 1 -type f -name "*.txt" | sed 's/..\(.*\)/\1/'` for i in $*; do # some comment (note: for compatibility) pass done fi ### With cursor at third line, "set", expression is not recognised at all, C-M-f stops at the end of symbol "set" That's a fakir's mode :) ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 9:22 ` Andreas Röhler @ 2015-06-16 11:12 ` Tassilo Horn 2015-06-16 11:40 ` Andreas Röhler [not found] ` <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 43+ messages in thread From: Tassilo Horn @ 2015-06-16 11:12 UTC (permalink / raw) To: Andreas Röhler; +Cc: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: >> There is: `forward-sexp' and `backward-sexp'. Although the name sexp >> is a bit lisp-specific, sexp-based motion has been implemented for >> more C-like languages, too. For example, it works well for shell >> scripts > > Unfortunatly couldn't experience this. There are several common cases > within shell-script, where calls to navigate sexp would raise an > error. > > That's why language-modes have to implement a couple of most basic things. See > > http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00013.html I agree with Stefan and Arthur on this particular issue. > ### > > vorhanden() { > for i in "blah" "blub"; > do > # some comment (note: for compatibility) > if [ ! -x $i ]; then > > ### > > with cursor last line "if", C-M-b jumps to "for", but should end at > "do" No. `do ... done' is no valid expression, i.e., it cannot stand on its own but is only valid together with for, while, until, or repeat. > From "for" -> > > Debugger entered--Lisp error: (scan-error "Containing expression ends > prematurely" 13 13) > signal(scan-error ("Containing expression ends prematurely" 13 13)) > smie-forward-sexp-command(-1) > forward-sexp(-1) > backward-sexp(1) > call-interactively(backward-sexp nil nil) > command-execute(backward-sexp) Indeed, here I'd expect it to move to the beginning of the function definition. > Or take this: > > ### > > if [ $# == 0 ]; then > # some comment (note: for compatibility) > set "" `find . -maxdepth 1 -type f -name "*.txt" | sed 's/..\(.*\)/\1/'` > > for i in $*; do > # some comment (note: for compatibility) > pass > done > > fi > > ### > > With cursor at third line, "set", expression is not recognised at all, > C-M-f stops at the end of symbol "set" Well, "command arg arg arg" in shell scripts is equivalent to (command arg arg arg) in lisp with the distinction that with the lisp syntax's parentheses you have a choice to move over the complete expression (when point is on the opening paren) or inside it (when point is on the "command"). Because the shell syntax doesn't have delimiters for the funcall or at least the argument list, there's not much you can do. > That's a fakir's mode :) Well, you can extend it quite easily and declaratively by modifying `sh-smie-sh-grammar', and then your improvements are transparently available to anything which uses sexp-based motion. I don't see how you can get the same benefits with tons and tons of special-case functions. Bye, Tassilo ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 11:12 ` Tassilo Horn @ 2015-06-16 11:40 ` Andreas Röhler 2015-06-16 13:10 ` Tassilo Horn [not found] ` <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org> 1 sibling, 1 reply; 43+ messages in thread From: Andreas Röhler @ 2015-06-16 11:40 UTC (permalink / raw) To: help-gnu-emacs Am 16.06.2015 um 13:12 schrieb Tassilo Horn: >> ### >> >> vorhanden() { >> for i in "blah" "blub"; >> do >> # some comment (note: for compatibility) >> if [ ! -x $i ]; then >> >> ### >> >> with cursor last line "if", C-M-b jumps to "for", but should end at >> "do" > No. `do ... done' is no valid expression, i.e., it cannot stand on its > own but is only valid together with for, while, until, or repeat. It's not the point to care for that. It's about editing, reading, understanding the source. What about a single "return" statement in code? Nonetheless, will reflect this case again WRT the mode in question. > >> From "for" -> >> >> Debugger entered--Lisp error: (scan-error "Containing expression ends >> prematurely" 13 13) >> signal(scan-error ("Containing expression ends prematurely" 13 13)) >> smie-forward-sexp-command(-1) >> forward-sexp(-1) >> backward-sexp(1) >> call-interactively(backward-sexp nil nil) >> command-execute(backward-sexp) > Indeed, here I'd expect it to move to the beginning of the function > definition. > >> Or take this: >> >> ### >> >> if [ $# == 0 ]; then >> # some comment (note: for compatibility) >> set "" `find . -maxdepth 1 -type f -name "*.txt" | sed 's/..\(.*\)/\1/'` >> >> for i in $*; do >> # some comment (note: for compatibility) >> pass >> done >> >> fi >> >> ### >> >> With cursor at third line, "set", expression is not recognised at all, >> C-M-f stops at the end of symbol "set" > Well, "command arg arg arg" in shell scripts is equivalent to (command > arg arg arg) in lisp with the distinction that with the lisp syntax's > parentheses you have a choice to move over the complete expression (when > point is on the opening paren) or inside it (when point is on the > "command"). Because the shell syntax doesn't have delimiters for the > funcall or at least the argument list, there's not much you can do. Wrong. We have the language's syntax and may follow it. Also these languages often are quite similar, thus aiming for some generics. > >> That's a fakir's mode :) > Well, you can extend it quite easily and declaratively by modifying > `sh-smie-sh-grammar', and then your improvements are transparently > available to anything which uses sexp-based motion. I'll look for that. For the moment see a couple of mode's out there with open smie-related bugs. See at elixir-mode or tuareg-mode for example. > I don't see how you > can get the same benefits with tons and tons of special-case functions. > > These tons are not written by me but by the folks in language-modes. Auto-generating some stuff would reduce the costs. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 11:40 ` Andreas Röhler @ 2015-06-16 13:10 ` Tassilo Horn 2015-06-16 15:46 ` Andreas Röhler [not found] ` <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 43+ messages in thread From: Tassilo Horn @ 2015-06-16 13:10 UTC (permalink / raw) To: Andreas Röhler; +Cc: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: >> No. `do ... done' is no valid expression, i.e., it cannot stand on >> its own but is only valid together with for, while, until, or repeat. > > It's not the point to care for that. Well, when you say you want to move by expression or statement then it seems legit to do exactly that and not move by half of a statement. > It's about editing, reading, understanding the source. I can understand that moving to the do wouldn't be bad with respect to editing because it's nearer, e.g., two smaller steps might be better than one large step which might already be too much. But the same time you argue that `forward-sexp' in a string should jump to its end instead of moving word-wise in its contents first. > What about a single "return" statement in code? What's up with a single return statement in code? > Nonetheless, will reflect this case again WRT the mode in question. I don't get what you are trying to tell me. >>> With cursor at third line, "set", expression is not recognised at >>> all, C-M-f stops at the end of symbol "set" >> Well, "command arg arg arg" in shell scripts is equivalent to >> (command arg arg arg) in lisp with the distinction that with the lisp >> syntax's parentheses you have a choice to move over the complete >> expression (when point is on the opening paren) or inside it (when >> point is on the "command"). Because the shell syntax doesn't have >> delimiters for the funcall or at least the argument list, there's not >> much you can do. > > Wrong. We have the language's syntax and may follow it. I don't get what you mean. > Also these languages often are quite similar, thus aiming for some > generics. That's the whole purpose of SMIE: conveniently navigating/editing code of different languages by defining what's a sexp in these languages using a simple grammar. Then the generic interface is just the set of sexp-commands. Bye, Tassilo ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 13:10 ` Tassilo Horn @ 2015-06-16 15:46 ` Andreas Röhler [not found] ` <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-16 15:46 UTC (permalink / raw) To: help-gnu-emacs Am 16.06.2015 um 15:10 schrieb Tassilo Horn: > Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > >>> No. `do ... done' is no valid expression, i.e., it cannot stand on >>> its own but is only valid together with for, while, until, or repeat. >> It's not the point to care for that. > Well, when you say you want to move by expression or statement then it > seems legit to do exactly that and not move by half of a statement. > >> It's about editing, reading, understanding the source. > I can understand that moving to the do wouldn't be bad with respect to > editing because it's nearer, e.g., two smaller steps might be better > than one large step which might already be too much. But the same time > you argue that `forward-sexp' in a string should jump to its end instead > of moving word-wise in its contents first. Because forward-word is implemented already and forward-sexp is redundant in this circumstances, while goto-end/start of string is missing. [ ... ] ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] ` <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org> @ 2015-06-16 22:34 ` Stefan Monnier 0 siblings, 0 replies; 43+ messages in thread From: Stefan Monnier @ 2015-06-16 22:34 UTC (permalink / raw) To: help-gnu-emacs > while goto-end/start of string is missing. I think these would map naturally to a dwimish extension of (backward-)up-list. Actually, IIRC expand-region provides exactly that. Stefan ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] ` <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org> @ 2015-06-16 16:13 ` Pascal J. Bourguignon 2015-06-16 18:30 ` Andreas Röhler 0 siblings, 1 reply; 43+ messages in thread From: Pascal J. Bourguignon @ 2015-06-16 16:13 UTC (permalink / raw) To: help-gnu-emacs Andreas, you might be interested in reading: https://www.ics.uci.edu/~taylor/ics228/SynGen.pdf and Teitelbaum, T.; T. Reps (September 1981). "The Cornell Program Synthesizer: A syntax-directed programming environment". Communications of the ACM 24 (9): 563–573. doi:10.1145/358746.358755. if you can get your hands on it. Check also: https://en.wikipedia.org/wiki/Structure_editor Basically, you could generate the whole mode all the structured editing commands, from a grammar of the language you want to edit. And since you could include in the grammar, grammars of other languages when you have such escape, such as html scripts, or php, etc, you would get automatically "multi-mode" structured editing modes. Now, when you generate code (eg. a programming language compiler), it is perfectly normal to have parts that are generated, and functions and stubs that are written once for all for all the programs: a run-time library. Your code generate would naturally bind mode commands whose name would be prefixed by the name of the grammar (= the mode), but the run-time library would be the same for all those generated mode, and would have a library prefix instead. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 16:13 ` Pascal J. Bourguignon @ 2015-06-16 18:30 ` Andreas Röhler 0 siblings, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-16 18:30 UTC (permalink / raw) To: help-gnu-emacs Am 16.06.2015 um 18:13 schrieb Pascal J. Bourguignon: > Andreas, you might be interested in reading: > > https://www.ics.uci.edu/~taylor/ics228/SynGen.pdf > > and > > Teitelbaum, T.; T. Reps (September 1981). "The Cornell Program > Synthesizer: A syntax-directed programming > environment". Communications of the ACM 24 (9): > 563–573. doi:10.1145/358746.358755. > > if you can get your hands on it. > > Check also: https://en.wikipedia.org/wiki/Structure_editor > > Basically, you could generate the whole mode all the structured editing > commands, from a grammar of the language you want to edit. > > And since you could include in the grammar, grammars of other languages > when you have such escape, such as html scripts, or php, etc, you would > get automatically "multi-mode" structured editing modes. > > > Now, when you generate code (eg. a programming language compiler), it is > perfectly normal to have parts that are generated, and functions and > stubs that are written once for all for all the programs: a run-time > library. > > Your code generate would naturally bind mode commands whose name would > be prefixed by the name of the grammar (= the mode), but the run-time > library would be the same for all those generated mode, and would have a > library prefix instead. > Thanks. Will not dig into further here, as it's a vast area - let's go back to the real thing :) ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 7:01 ` Tassilo Horn 2015-06-16 9:22 ` Andreas Röhler @ 2015-06-16 9:42 ` Andreas Röhler [not found] ` <mailman.5084.1434446560.904.help-gnu-emacs@gnu.org> [not found] ` <mailman.5085.1434447782.904.help-gnu-emacs@gnu.org> 3 siblings, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-16 9:42 UTC (permalink / raw) To: help-gnu-emacs Am 16.06.2015 um 09:01 schrieb Tassilo Horn: > Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > >>>> i'm probably misunderstanding you, but does: >>>> (defun (intern (concat "current-prefix-" foo) ... >>>> do what you need? >>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but >>> not with defun. In any case, some concrete example of what he needs to >>> do would go a long way. >>> >>> >>> Stefan >> Currently Emacs provides some scheme to fontify source code and some >> basic moves: linewise, symbol, word, paragraph, sexp. >> >> There is no idea of statement, block/loop or expression and a poor >> top-level --beginning/end-of-defun. > There is: `forward-sexp' and `backward-sexp'. Expect sexp-navigation behaving the the following way: - if inside a form, go to the end resp. start - if at end of form, forward same level if form exist, or get level following point, or EOB - if at beginning of form, backward same level if form exist, or get level preceding point, or BOB Resp. when inside a literal, go to start resp. end. When in inside a comment, leave it, treat it like whitespace, repeat the command. Beside other shortcomings, for now docstring of forward-sexp says: "This command assumes point is not in a string or comment." A restriction, which is not acceptable. ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5084.1434446560.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] ` <mailman.5084.1434446560.904.help-gnu-emacs@gnu.org> @ 2015-06-16 9:50 ` Pascal J. Bourguignon 2015-06-16 10:26 ` Andreas Röhler [not found] ` <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 43+ messages in thread From: Pascal J. Bourguignon @ 2015-06-16 9:50 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > Am 16.06.2015 um 09:01 schrieb Tassilo Horn: >> Andreas Röhler <andreas.roehler@easy-emacs.de> writes: >> >>>>> i'm probably misunderstanding you, but does: >>>>> (defun (intern (concat "current-prefix-" foo) ... >>>>> do what you need? >>>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but >>>> not with defun. In any case, some concrete example of what he needs to >>>> do would go a long way. >>>> >>>> >>>> Stefan >>> Currently Emacs provides some scheme to fontify source code and some >>> basic moves: linewise, symbol, word, paragraph, sexp. >>> >>> There is no idea of statement, block/loop or expression and a poor >>> top-level --beginning/end-of-defun. >> There is: `forward-sexp' and `backward-sexp'. Although the name sexp is >> a bit lisp-specific, sexp-based motion has been implemented for more >> C-like languages, too. For example, it works well for shell scripts > > Unfortunatly couldn't experience this. There are several common cases > within shell-script, where calls to navigate sexp would raise an > error. > > That's why language-modes have to implement a couple of most basic > things. See > > http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00013.html > > ### > > vorhanden() { > for i in "blah" "blub"; > do > # some comment (note: for compatibility) > if [ ! -x $i ]; then > > ### > > with cursor last line "if", C-M-b jumps to "for", but should end at "do" > From "for" -> > > Debugger entered--Lisp error: (scan-error "Containing expression ends > prematurely" 13 13) > signal(scan-error ("Containing expression ends prematurely" 13 13)) > smie-forward-sexp-command(-1) > forward-sexp(-1) > backward-sexp(1) > call-interactively(backward-sexp nil nil) > command-execute(backward-sexp) > > There are many more spots in this example to trigger error or > unexpected moves. > > Or take this: > > ### > > if [ $# == 0 ]; then > # some comment (note: for compatibility) > set "" `find . -maxdepth 1 -type f -name "*.txt" | sed > s/..\(.*\)/\1/'` > > for i in $*; do > # some comment (note: for compatibility) > pass > done > > fi > > ### > > With cursor at third line, "set", expression is not recognised at all, > C-M-f stops at the end of symbol "set" > > That's a fakir's mode :) There are hooks to customize those general commands to specific modes! For example, instead of writing: bash-forward-sexp sh-forward-sexp pascal-forward-sexp ada-forward-sexp etc, each mode will just bind a specific forward sexp function to the hook variable: forward-sexp-function, and forward-sexp will call it. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 9:50 ` Pascal J. Bourguignon @ 2015-06-16 10:26 ` Andreas Röhler [not found] ` <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-16 10:26 UTC (permalink / raw) To: help-gnu-emacs Am 16.06.2015 um 11:50 schrieb Pascal J. Bourguignon: > Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > >> Am 16.06.2015 um 09:01 schrieb Tassilo Horn: >>> Andreas Röhler <andreas.roehler@easy-emacs.de> writes: >>> >>>>>> i'm probably misunderstanding you, but does: >>>>>> (defun (intern (concat "current-prefix-" foo) ... >>>>>> do what you need? >>>>> (defalias (intern (concat "current-prefix-" foo) ...) ...) can work, but >>>>> not with defun. In any case, some concrete example of what he needs to >>>>> do would go a long way. >>>>> >>>>> >>>>> Stefan >>>> Currently Emacs provides some scheme to fontify source code and some >>>> basic moves: linewise, symbol, word, paragraph, sexp. >>>> >>>> There is no idea of statement, block/loop or expression and a poor >>>> top-level --beginning/end-of-defun. >>> There is: `forward-sexp' and `backward-sexp'. Although the name sexp is >>> a bit lisp-specific, sexp-based motion has been implemented for more >>> C-like languages, too. For example, it works well for shell scripts >> Unfortunatly couldn't experience this. There are several common cases >> within shell-script, where calls to navigate sexp would raise an >> error. >> >> That's why language-modes have to implement a couple of most basic >> things. See >> >> http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00013.html >> >> ### >> >> vorhanden() { >> for i in "blah" "blub"; >> do >> # some comment (note: for compatibility) >> if [ ! -x $i ]; then >> >> ### >> >> with cursor last line "if", C-M-b jumps to "for", but should end at "do" >> From "for" -> >> >> Debugger entered--Lisp error: (scan-error "Containing expression ends >> prematurely" 13 13) >> signal(scan-error ("Containing expression ends prematurely" 13 13)) >> smie-forward-sexp-command(-1) >> forward-sexp(-1) >> backward-sexp(1) >> call-interactively(backward-sexp nil nil) >> command-execute(backward-sexp) >> >> There are many more spots in this example to trigger error or >> unexpected moves. >> >> Or take this: >> >> ### >> >> if [ $# == 0 ]; then >> # some comment (note: for compatibility) >> set "" `find . -maxdepth 1 -type f -name "*.txt" | sed >> s/..\(.*\)/\1/'` >> >> for i in $*; do >> # some comment (note: for compatibility) >> pass >> done >> >> fi >> >> ### >> >> With cursor at third line, "set", expression is not recognised at all, >> C-M-f stops at the end of symbol "set" >> >> That's a fakir's mode :) > There are hooks to customize those general commands to specific modes! > For example, instead of writing: > > bash-forward-sexp > sh-forward-sexp > pascal-forward-sexp > ada-forward-sexp > > etc, each mode will just bind a specific forward sexp function to the > hook variable: forward-sexp-function, and forward-sexp will call it. > > That's a consideration at the command- resp. key-binding level. Nonetheless mode-specific functions are needed to bind then. For now these language mode often invent very basic things in parallel: string-strip, in-string-p etc. Also creating bugs and quirks that way. Beyond that we can generalize top-level, block, expression and statement -- at least to some extend. ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] ` <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org> @ 2015-06-16 11:35 ` Pascal J. Bourguignon 0 siblings, 0 replies; 43+ messages in thread From: Pascal J. Bourguignon @ 2015-06-16 11:35 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > Am 16.06.2015 um 11:50 schrieb Pascal J. Bourguignon: >> There are hooks to customize those general commands to specific modes! >> For example, instead of writing: >> >> bash-forward-sexp >> sh-forward-sexp >> pascal-forward-sexp >> ada-forward-sexp >> >> etc, each mode will just bind a specific forward sexp function to the >> hook variable: forward-sexp-function, and forward-sexp will call it. >> >> > > That's a consideration at the command- resp. key-binding level. > Nonetheless mode-specific functions are needed to bind then. Of course, and mode-specific functions will have a mode-specific prefix in their name. But if you have functions that are not mode-specific, like, (generate-parser mode-specific-grammar), or (parse-to-point mode-specific-grammar), you DO NOT DUPLICATE those functions with names such as pascal-generate-parser pascal-parse-to-point ada-generate-parser ada-parse-to-point c-generate-parser c-parse-to-point bash-generate-parser bash-parse-to-point This is dumb. What you do is to call those general functions from your mode-specific functions (that since they are specific and different for each mode, do not contain duplicated code). What you could do, for those generic functions, is to put them in a nice re-usable library, give a name to the library, and prefix them by the name of the library. Eg. if you name the library bovidae, then you will have: bovidae-generate-parser bovidae-parse-to-point but you would not duplicate those functions with names such as: pascal-bovidae-generate-parser pascal-bovidae-parse-to-point ada-bovidae-generate-parser ada-bovidae-parse-to-point c-bovidae-generate-parser c-bovidae-parse-to-point bash-bovidae-generate-parser bash-bovidae-parse-to-point This would be dumb. > For now these language mode often invent very basic things in > parallel: string-strip, in-string-p etc. > Also creating bugs and quirks that way. Then factorize that out in a common library! > Beyond that we can generalize top-level, block, expression and > statement -- at least to some extend. You already have a few such functions: beginning-of-defun end-of-defun indent-defun mark-defun narrow-to-defun Also, I've noticed a remark in the thread. Some languages distinguish statements and expressions (and sometimes also declarations or definitions), but some other languages only have expressions. The laters are much more usable and agreable, and more easily edited also. When parsing a program, you naturally obtain parse trees labelled with the kind statement, expression, definition, etc. But when editing, you might want to flatten all this down to expressions (sexp), as if you were editing lisp, because it is easier. But you could provide tools to convert between statements and expressions. For example, if you kill a C statement (selection shown with []): [ x=a+b; ] if(a==b){ x=0; }else{ y=42; } then move into an expression context (point shown with |): if(|a==b){ x=0; }else{ y=42; } and yank, the statement x=a+b; could be transformed into an expression (semicolon removed): if((x=a+b),|(a==b)){ x=0; }else{ y=42; } And backward, an expression: x=[ (a==b)?0:42 ]; killed and yanked into statement context: { | } would transform it into a statment: { if(a==b){ return 0; }else{ return 42; } } -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5085.1434447782.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] ` <mailman.5085.1434447782.904.help-gnu-emacs@gnu.org> @ 2015-06-16 22:32 ` Stefan Monnier 0 siblings, 0 replies; 43+ messages in thread From: Stefan Monnier @ 2015-06-16 22:32 UTC (permalink / raw) To: help-gnu-emacs > Expect sexp-navigation behaving the the following way: > - if inside a form, go to the end resp. start > - if at end of form, forward same level if form exist, or get level > following point, or EOB > - if at beginning of form, backward same level if form exist, or get level > preceding point, or BOB Indeed, the for/backward-sexp function is rather low-level (it's a bit more focused on Elisp usage than on interactive usage) and it's very reasonable to want to provide higher-level commands on top of it, that "do what I mean" in more cases. Stefan ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] ` <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org> @ 2015-06-16 22:23 ` Stefan Monnier 2015-06-17 6:13 ` Andreas Röhler [not found] ` <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 43+ messages in thread From: Stefan Monnier @ 2015-06-16 22:23 UTC (permalink / raw) To: help-gnu-emacs > Currently Emacs provides some scheme to fontify source code and some basic > moves: linewise, symbol, word, paragraph, sexp. > There is no idea of statement, block/loop or expression and a poor > top-level --beginning/end-of-defun. Since we don't need to define functions dynamically for "linewise, symbol, word, paragraph, sexp", I don't see how "statement, block/loop or expression and a poor top-level --beginning/end-of-defun" would require dynamic definition of functions. IOW, I still don't really see what you're trying to do. Stefan BTW: For languages that use SMIE, the sexp movement typically moves by statement/subexpressions. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 22:23 ` Stefan Monnier @ 2015-06-17 6:13 ` Andreas Röhler [not found] ` <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-17 6:13 UTC (permalink / raw) To: help-gnu-emacs Am 17.06.2015 um 00:23 schrieb Stefan Monnier: >> Currently Emacs provides some scheme to fontify source code and some basic >> moves: linewise, symbol, word, paragraph, sexp. >> There is no idea of statement, block/loop or expression and a poor >> top-level --beginning/end-of-defun. > Since we don't need to define functions dynamically for "linewise, > symbol, word, paragraph, sexp", These are very basic things based on character-syntax tables. Expression is limited that way - see the difficulties around triple-quoted-string. > I don't see how "statement, block/loop > or expression and a poor top-level --beginning/end-of-defun" would > require dynamic definition of functions. Because these functions depend on grammar of the goal-language. [ ... ] ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] ` <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org> @ 2015-06-17 14:30 ` Stefan Monnier 2015-06-17 16:40 ` Andreas Röhler 0 siblings, 1 reply; 43+ messages in thread From: Stefan Monnier @ 2015-06-17 14:30 UTC (permalink / raw) To: help-gnu-emacs > Because these functions depend on grammar of the goal-language. Indeed, that's why forward-sexp is supplemented by forward-sexp-function, making it possible for the major mode to provide an implementation that does a more sophisticated sort of parsing than that supported by plain old syntax-tables. Stefan ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-17 14:30 ` Stefan Monnier @ 2015-06-17 16:40 ` Andreas Röhler 0 siblings, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-17 16:40 UTC (permalink / raw) To: help-gnu-emacs Am 17.06.2015 um 16:30 schrieb Stefan Monnier: >> Because these functions depend on grammar of the goal-language. > Indeed, that's why forward-sexp is supplemented by > forward-sexp-function, making it possible for the major mode to provide > an implementation that does a more sophisticated sort of parsing than > that supported by plain old syntax-tables. > > > Stefan BTW you may remember a discussion around beginning-of-defun resp. beginning-of-defun-raw. The point was: once a beginning-of-defun-function is set by a language, let it go with it, don't interfere. ^ permalink raw reply [flat|nested] 43+ messages in thread
[parent not found: <mailman.5020.1434360277.904.help-gnu-emacs@gnu.org>]
* Re: Defining functions on the fly [not found] <mailman.5020.1434360277.904.help-gnu-emacs@gnu.org> @ 2015-06-15 9:57 ` Pascal J. Bourguignon 2015-06-15 11:21 ` Andreas Röhler 2015-06-15 23:51 ` Gene 1 sibling, 1 reply; 43+ messages in thread From: Pascal J. Bourguignon @ 2015-06-15 9:57 UTC (permalink / raw) To: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > have a bunch of subroutines which are useful in several modes - > beginning/end of expressions, string positions, comments etc. > > Now every mode should get its own prefix. And every human shoud get its own brain, but apparently some are missed. Just call your function (named as you wish) from the several modes, DO NOT DUPLICATE THEM! -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 9:57 ` Pascal J. Bourguignon @ 2015-06-15 11:21 ` Andreas Röhler 2015-06-15 11:52 ` Tassilo Horn 0 siblings, 1 reply; 43+ messages in thread From: Andreas Röhler @ 2015-06-15 11:21 UTC (permalink / raw) To: help-gnu-emacs Am 15.06.2015 um 11:57 schrieb Pascal J. Bourguignon: [ ... ] Just call your function (named as you wish) from the several modes, DO NOT DUPLICATE THEM! It's not about duplication, but derivation. The original DTRT in most cases. Point of interest are the exceptions - see for example in Elixir https://github.com/elixir-lang/emacs-elixir/issues/185 "\"foo\"" |> String.strip(?") Where the doublquote after question mark makes Emacs think it's a string-start - which isn't. So have to tweak some routines when loading it. BTW this seems an occasion to use eieio and inheritance, right? ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 11:21 ` Andreas Röhler @ 2015-06-15 11:52 ` Tassilo Horn 2015-06-15 12:06 ` Andreas Röhler 2015-06-15 12:43 ` Andreas Röhler 0 siblings, 2 replies; 43+ messages in thread From: Tassilo Horn @ 2015-06-15 11:52 UTC (permalink / raw) To: Andreas Röhler; +Cc: help-gnu-emacs Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > It's not about duplication, but derivation. The original DTRT in most > cases. > > Point of interest are the exceptions - see for example in Elixir > > https://github.com/elixir-lang/emacs-elixir/issues/185 > > "\"foo\"" |> String.strip(?") > > Where the doublquote after question mark makes Emacs think it's a > string-start - which isn't. String recognition in emacs is usually done using syntax tables, so get the elixir syntax table right and then you don't need any workarounds. In this case, it seems plain syntax tables aren't enough, though, so the elisp docs explain how to override certain characters' syntax on demand. ,----[ (info "(elisp)Syntax Properties") ] | When the syntax table is not flexible enough to specify the syntax of a | language, you can override the syntax table for specific character | occurrences in the buffer, by applying a ‘syntax-table’ text property. | *Note Text Properties::, for how to apply text properties. `---- So basically, you (or elixir-mode) will want to define a `syntax-propertize-function' which finds occurrences of ?" and gives "/" (character quote) syntax to the ? in which the usual "\"" (string quotes) syntax of `"' would be ineffective for this single double quote. ,----[ (info "(elisp)Syntax Class Table") ] | Character quotes: ‘/’ | Characters used to quote the following character so that it loses | its normal syntactic meaning. This differs from an escape | character in that only the character immediately following is ever | affected. | | Characters in this class count as part of words if | ‘words-include-escapes’ is non-‘nil’. *Note Word Motion::. `---- Bye, Tassilo ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 11:52 ` Tassilo Horn @ 2015-06-15 12:06 ` Andreas Röhler 2015-06-15 12:43 ` Andreas Röhler 1 sibling, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-15 12:06 UTC (permalink / raw) To: help-gnu-emacs Am 15.06.2015 um 13:52 schrieb Tassilo Horn: > Andreas Röhler <andreas.roehler@easy-emacs.de> writes: > >> It's not about duplication, but derivation. The original DTRT in most >> cases. >> >> Point of interest are the exceptions - see for example in Elixir >> >> https://github.com/elixir-lang/emacs-elixir/issues/185 >> >> "\"foo\"" |> String.strip(?") >> >> Where the doublquote after question mark makes Emacs think it's a >> string-start - which isn't. > String recognition in emacs is usually done using syntax tables, so get > the elixir syntax table right and then you don't need any workarounds. > In this case, it seems plain syntax tables aren't enough, though, so the > elisp docs explain how to override certain characters' syntax on demand. > > ,----[ (info "(elisp)Syntax Properties") ] > | When the syntax table is not flexible enough to specify the syntax of a > | language, you can override the syntax table for specific character > | occurrences in the buffer, by applying a ‘syntax-table’ text property. > | *Note Text Properties::, for how to apply text properties. > `---- > > So basically, you (or elixir-mode) will want to define a > `syntax-propertize-function' which finds occurrences of ?" and gives "/" > (character quote) syntax to the ? in which the usual "\"" (string > quotes) syntax of `"' would be ineffective for this single double quote. > > ,----[ (info "(elisp)Syntax Class Table") ] > | Character quotes: ‘/’ > | Characters used to quote the following character so that it loses > | its normal syntactic meaning. This differs from an escape > | character in that only the character immediately following is ever > | affected. > | > | Characters in this class count as part of words if > | ‘words-include-escapes’ is non-‘nil’. *Note Word Motion::. > `---- > > Bye, > Tassilo Thanks again. Will see if a better example comes across WRT original question. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 11:52 ` Tassilo Horn 2015-06-15 12:06 ` Andreas Röhler @ 2015-06-15 12:43 ` Andreas Röhler 1 sibling, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-15 12:43 UTC (permalink / raw) To: help-gnu-emacs This seems to work, some function going to char 1: (dolist (ele (list "a" "b")) ;; think some conditions here, which will select the final lambda (fset (intern-soft (car (read-from-string ele))) #'(lambda ()(goto-char 1)))) ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly [not found] <mailman.5020.1434360277.904.help-gnu-emacs@gnu.org> 2015-06-15 9:57 ` Pascal J. Bourguignon @ 2015-06-15 23:51 ` Gene 2015-06-16 1:14 ` Stefan Monnier 2015-06-16 5:47 ` Andreas Röhler 1 sibling, 2 replies; 43+ messages in thread From: Gene @ 2015-06-15 23:51 UTC (permalink / raw) To: help-gnu-emacs On Monday, June 15, 2015 at 5:24:40 AM UTC-4, Andreas Röhler wrote: > Hi, > > have a bunch of subroutines which are useful in several modes - > beginning/end of expressions, string positions, comments etc. > > Now every mode should get its own prefix. > Can't write > > (defun (concat "current-prefix-" foo) ()) > > as defun expects a symbol. > > Exists "fset" - is there a recommended way to go? I recommend using lambda to experimentally develop what you think of as a function of the sort defun is typically used typically used to define. Once the function's actual definition is done via lambda it can be bound to a symbol via fset (fset (function name-of-function) (lambda (arg) "docstring" ; Body goes here ) ) Of course the anonymous version of the function can be used via higher order functions such as `apply' and `mapcar' so function development and testing can be furthered before one gets around to deciding to keep it around and name it for convenient future use. This strategy is pretty much applicable in Scheme as well (define name-of-function (lambda (arg) ;body ) ) I hope this helps. Gene ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 23:51 ` Gene @ 2015-06-16 1:14 ` Stefan Monnier 2015-06-17 0:24 ` Gene 2015-06-16 5:47 ` Andreas Röhler 1 sibling, 1 reply; 43+ messages in thread From: Stefan Monnier @ 2015-06-16 1:14 UTC (permalink / raw) To: help-gnu-emacs > (fset (function name-of-function) [...] > (define name-of-function Actually, `fset' is more like Scheme's `set!', so if it's the *definition* of a function, you should use `defalias' which is more like Scheme's `define'. Stefan ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-16 1:14 ` Stefan Monnier @ 2015-06-17 0:24 ` Gene 2015-06-17 1:12 ` Stefan Monnier 0 siblings, 1 reply; 43+ messages in thread From: Gene @ 2015-06-17 0:24 UTC (permalink / raw) To: help-gnu-emacs On Monday, June 15, 2015 at 9:14:56 PM UTC-4, Stefan Monnier wrote: > > (fset (function name-of-function) > [...] > > (define name-of-function > > Actually, `fset' is more like Scheme's `set!', How so? `define' is typically used if or when a symbol has yet to be bound to either a lambda function or value. set! is used to destructively re-bind something to a symbol already bound to something. > so if it's the *definition* of a function, you should use `defalias' > which is more like Scheme's `define'. I don't see it that way, but if works to one's satisfaction then why not? I've taken to developing functions via lambda, then -- when I've got things hammered out the way I want them I use fset -- typically insight a wrapper in which the name of the function is available as, say, `func-name' to programmatically name the previously anonymous function. (let ; function forge ( (func-name (quote non-anon ; arbitrary name. We could have used `gensym' to have emacs generate a symbol for us )) ) (fset func-name (lambda ( arg1 ; we can document the arg name this way arg2 ; This is a seperate line to document this arg ) "docstring" (list arg1 arg2) );lambda );fset ; (if (functionp func-name) (symbol-function func-name) (message (concat "function " func-name " not defined")) ) ) ;let > > > Stefan I tend to use defalias for functions which already have names. When I'm dreaming up a new name which doesn't collide with an extant named function known to function-name space I have no problem with using fset as if scheme's `define' as per a pristine, virgin binding. Gene ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-17 0:24 ` Gene @ 2015-06-17 1:12 ` Stefan Monnier 0 siblings, 0 replies; 43+ messages in thread From: Stefan Monnier @ 2015-06-17 1:12 UTC (permalink / raw) To: help-gnu-emacs >> > (fset (function name-of-function) >> [...] >> > (define name-of-function >> Actually, `fset' is more like Scheme's `set!', > How so? Exactly in the sense you describe: > `define' is typically used if or when a symbol has yet to be bound to > either a lambda function or value. > set! is used to destructively re-bind something to a symbol already > bound to something. `defun' macroexpands to `defalias' rather than to `fset'. >> so if it's the *definition* of a function, you should use `defalias' >> which is more like Scheme's `define'. > I don't see it that way, but if works to one's satisfaction then why not? Actually, they don't do the same thing. E.g. fset will throw away/override any advice you may have applied to that function, whereas defalias will combine the new definition with the pieces of advice. Stefan ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: Defining functions on the fly 2015-06-15 23:51 ` Gene 2015-06-16 1:14 ` Stefan Monnier @ 2015-06-16 5:47 ` Andreas Röhler 1 sibling, 0 replies; 43+ messages in thread From: Andreas Röhler @ 2015-06-16 5:47 UTC (permalink / raw) To: help-gnu-emacs Am 16.06.2015 um 01:51 schrieb Gene: > On Monday, June 15, 2015 at 5:24:40 AM UTC-4, Andreas Röhler wrote: >> Hi, >> >> have a bunch of subroutines which are useful in several modes - >> beginning/end of expressions, string positions, comments etc. >> >> Now every mode should get its own prefix. >> Can't write >> >> (defun (concat "current-prefix-" foo) ()) >> >> as defun expects a symbol. >> >> Exists "fset" - is there a recommended way to go? > I recommend using lambda to experimentally develop what you think of as a function of the sort defun is typically used typically used to define. > > Once the function's actual definition is done via lambda it can be bound to a symbol via fset > > (fset (function name-of-function) > (lambda (arg) > "docstring" > ; Body goes here > ) > ) > > Of course the anonymous version of the function can be used via higher order functions such as `apply' and `mapcar' so function development and testing can be furthered before one gets around to deciding to keep it around and name it for convenient future use. > > This strategy is pretty much applicable in Scheme as well > > (define name-of-function > (lambda (arg) > ;body > ) > ) > > I hope this helps. > > Gene > It does, thanks! ^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2015-06-17 16:40 UTC | newest] Thread overview: 43+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-06-15 9:24 Defining functions on the fly Andreas Röhler 2015-06-15 9:32 ` Dmitry Gutov 2015-06-15 9:47 ` Alexis 2015-06-15 10:20 ` Andreas Röhler 2015-06-15 10:37 ` Alexis 2015-06-15 10:41 ` Michael Heerdegen 2015-06-15 10:42 ` Tassilo Horn 2015-06-15 11:01 ` Alexis 2015-06-15 11:19 ` Michael Heerdegen 2015-06-15 11:24 ` Tassilo Horn 2015-06-15 11:31 ` Michael Heerdegen 2015-06-15 10:00 ` Tassilo Horn 2015-06-15 10:33 ` Andreas Röhler [not found] ` <mailman.5022.1434361680.904.help-gnu-emacs@gnu.org> 2015-06-15 12:52 ` Stefan Monnier 2015-06-16 5:59 ` Andreas Röhler 2015-06-16 7:01 ` Tassilo Horn 2015-06-16 9:22 ` Andreas Röhler 2015-06-16 11:12 ` Tassilo Horn 2015-06-16 11:40 ` Andreas Röhler 2015-06-16 13:10 ` Tassilo Horn 2015-06-16 15:46 ` Andreas Röhler [not found] ` <mailman.5109.1434469628.904.help-gnu-emacs@gnu.org> 2015-06-16 22:34 ` Stefan Monnier [not found] ` <mailman.5090.1434454815.904.help-gnu-emacs@gnu.org> 2015-06-16 16:13 ` Pascal J. Bourguignon 2015-06-16 18:30 ` Andreas Röhler 2015-06-16 9:42 ` Andreas Röhler [not found] ` <mailman.5084.1434446560.904.help-gnu-emacs@gnu.org> 2015-06-16 9:50 ` Pascal J. Bourguignon 2015-06-16 10:26 ` Andreas Röhler [not found] ` <mailman.5087.1434450412.904.help-gnu-emacs@gnu.org> 2015-06-16 11:35 ` Pascal J. Bourguignon [not found] ` <mailman.5085.1434447782.904.help-gnu-emacs@gnu.org> 2015-06-16 22:32 ` Stefan Monnier [not found] ` <mailman.5075.1434434385.904.help-gnu-emacs@gnu.org> 2015-06-16 22:23 ` Stefan Monnier 2015-06-17 6:13 ` Andreas Röhler [not found] ` <mailman.5137.1434522533.904.help-gnu-emacs@gnu.org> 2015-06-17 14:30 ` Stefan Monnier 2015-06-17 16:40 ` Andreas Röhler [not found] <mailman.5020.1434360277.904.help-gnu-emacs@gnu.org> 2015-06-15 9:57 ` Pascal J. Bourguignon 2015-06-15 11:21 ` Andreas Röhler 2015-06-15 11:52 ` Tassilo Horn 2015-06-15 12:06 ` Andreas Röhler 2015-06-15 12:43 ` Andreas Röhler 2015-06-15 23:51 ` Gene 2015-06-16 1:14 ` Stefan Monnier 2015-06-17 0:24 ` Gene 2015-06-17 1:12 ` Stefan Monnier 2015-06-16 5:47 ` Andreas Röhler
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).