How can I change the word at point using elisp? Something quite like (upcase-word) but using my own function?
Background: I've written a function that detects the base of the number at point and can convert it to any other base. What I would like to do is to change the number directly in the buffer.
TIA
Markus
Try this code. I've included a sample interactive function using upcase:
(defun change-word-at-point (fun)
(cl-destructuring-bind (beg . end)
(bounds-of-thing-at-point 'word)
(let ((str (buffer-substring-no-properties beg end)))
(delete-region beg end)
(insert (funcall fun str)))))
(defun upcase-word ()
(interactive)
(change-word-at-point 'upcase))
Related
I'm trying to add completion at point for frame-local variables from backtrace-frames during invocations of read--expression by debugger-eval-expression or edebug-eval-expression.
I constructed the following completion table to add frame-local variables to the already available table for local elisp variables,
;; completion table for locals in current frame
(defvar my-backtrace-locals-completion-table
(completion-table-in-turn
(completion-table-dynamic
(lambda (_string)
(when-let* ((idx (backtrace-get-index)) ;backtrace.el
(frame (nth idx backtrace-frames)))
(backtrace-frame-locals frame)))
'do-switch-buffer)
elisp--local-variables-completion-table)) ;elisp-mode.el
which seems to work fine, eg. to reproduce
(1) evaluate
;; debug-on-error = t
(let ((my-local-var '(1 2))) (mapcan #'car this-local-var))
(2) from debugger's second frame, evaluate with eval-expression
(funcall my-backtrace-locals-completion-table "my-" nil t)
returns expected ("my-local-var").
The problem is following the above steps, but calling instead calling debugger-eval-expression doesn't work. The environment where the table is evaluated isn't finding a backtrace-frame (with or without do-switch-buffer).
How can I define the table to be evaluated in the proper buffer?
emacs v27.0.50
The completion table above doesn't quite return the expected candidates for debugger-eval-expression. The environment where the expression is evaluated has locals from frames higher than, but not including, the one at point in the Backtrace buffer.
So, the available locals should be only those from higher frames, eg.
(eval-when-compile (require 'dash))
(defvar my-backtrace-locals-completion-table
(completion-table-dynamic
(lambda (_string)
(when backtrace-frames
(--mapcat
(-some->> (backtrace-frame-locals it) (--map (car it)))
(nthcdr (1+ (backtrace-get-index)) backtrace-frames))))
'do-switch-buffer))
Then, redefining debugger-eval-expression's interactive spec to use the new locals table in place of the normal elisp table provides the correct completions (passing the 'do-switch-buffer arg completion-table-dynamic to find completions in the original buffer).
(defun my-backtrace#eval (orig-fn exp &optional nframe)
(interactive
(let ((elisp--local-variables-completion-table
my-backtrace-locals-completion-table))
(list (read--expression "[my] Eval in stack frame: "))))
(apply orig-fn (list exp nframe)))
(advice-add 'debugger-eval-expression :around #'my-backtrace#eval)
This time my problem is mostly with Racklog. I guess. Could also be the Racket syntax this time.
The idea is rather simple. I have a logic-base made up of places and objects and I just wanted to try out printing all the objects using the %bag-of primitive.
My logic-base looks like this:
(define %contains
(%rel ()
[('bridge 'phaser)]
[('engine_room 'toolkit)]
[('toolkit 'screwdriver)]
[('toolkit 'tricorder)]
[('inventory '(communicator, no_tea))]
)
)
Now I have my predicate which is the following one. It should be simply called with the query "(%which () (%list_objects 'toolkit))" and then give out all the items inside the toolkit for example.
(define %list_objects
(%rel (place)
[(place)
(%which (objects)
(%let (x)
(%bag-of x (%contains place x)
objects)))]
)
)
The weird thing is when I just thake the part from the "%which (objects)...)" onwards and throw it directly into the listener, it works perfectly fine. But if I'm using it inside the predicate, it throws this exception:
"application: not a procedure;
expected a procedure that can be applied to arguments
given: '((objects screwdriver tricorder))
arguments...: [none]"
I tried rearranging the code several times, but right now I'm quite stumped about what I did wrong. I would appreciate a little hint what I as a total newbee to Scheme and Racket missed out here. My thanks in advance!
The problem is that the goal (%which ...) returns an answer (not a new relation). Therefore %list_objects can't be used in the way you want.
Maybe this works for you?
#lang racket
(require racklog)
(define %contains
(%rel ()
[('bridge 'phaser)]
[('engine_room 'toolkit)]
[('toolkit 'screwdriver)]
[('toolkit 'tricorder)]
[('inventory '(communicator, no_tea))]))
(define %list_objects
(%rel (place)
[(place)
(%let (x) (%contains place x))]))
(%which (x) (%list_objects x))
(%more)
(%which (bag) (%let (x) (%bag-of x (%list_objects x) bag)))
(define tools-in-toolkit (map cdar (%find-all (tool) (%contains 'toolkit tool))))
(define %in-toolkit
(%rel (tool)
[(tool) (%member tool tools-in-toolkit)]))
(%find-all (tool) (%in-toolkit tool))
Output:
'((x . bridge))
'((x . engine_room))
'((bag bridge engine_room toolkit toolkit inventory))
'(((tool . screwdriver)) ((tool . tricorder)))
I'm making a random sentence generator using Scheme (Pretty Big), and I'm having trouble defining temporary variables. I want to make something like this:
<NOUN1> <VERB1> <NOUN2> <but> <NOUN2> <VERB1> <NOUN2> <also>
Example: Sharks eat fish, but fish eat fish also.
I have word lists, and functions to choose a word from said list. Then, I use append to create a function. I am able to do:
(define (sentence)
(append (getNoun) '(and) (getNoun) (getVerb)))
However, I am unable to figure out a way to temporarily define a variable.
I have this so far:
(define (sentence1)
(append (getNoun)
(lambda (verb getVerb)
(noun getNoun))
(verb) (noun) '(but) (noun) (verb) (noun)))
Hints/Help please?
You are looking for let.
http://docs.racket-lang.org/reference/let.html
Here is an example usage:
(define (my-proc age)
(let ([age-plus-10 (+ age 10)])
(printf "age is ~a" age)
(printf "age-plus-10 is ~a" age-plus-10)))
Notice how we can temporarily define age-plus-10 and then use it later.
probably an easy question: I want to wrap the "(format ..)" function of Scheme in order to handle my debugging output (including the wrapping of the format-string).
As "format" takes a variable number of arguments my wrapper would need to do that too yielding the question on how I tell scheme to have an ellipsis-parameter and how to reference it.
I thought of something like this:
(define debugPrint
(lambda (formatString ELLIPSIS_PARAMETER)
(if debug
(format #t (string-append "<!--" formatString "-->") ELLIPSIS_PARAMETER)
()
)
)
)
Thank You for your help in advance!
There is dot notation for this:
(define (debugPrint formatString . params)
(if debug
(apply format #t (string-append "<!--" formatString "-->") params)
'()))
Take note on apply as dot notation wraps all parameters in list and when you use (debugPrint "~a: ~a" key name), the formatString will be bound to "~a: ~a" and params will be bound to (key name) (sure the values of key and name, not symbols ;).
(define bootstrap-c-code
(define (from-file file-name)
(let* ((ip (open-input-file file-name))
(res (read-text-file-from-input-port ip)))
(close-input-port ip)
res))
(from-file "llvm.c"))
Error : define: bad syntax (multiple expressions after identifier)
But I can't see anything wrong with it. Can someone explain / fix it please.
It's not clear what you intended with the above code. If you were trying to load a text file and leave the loaded value in a variable called bootstrap-c-code, then try this:
(define bootstrap-c-code
(let ((from-file
(lambda (file-name)
(let* ((ip (open-input-file file-name))
(res (read-text-file-from-input-port ip)))
(close-input-port ip)
res))))
(from-file "llvm.c")))
Of course, the from-file definition will only be visible inside the let, if you need to use it outside, define it outside of the whole expression. If you only need the functionality of from-file inside the let, you can obtain the same result in a much simpler way:
(define bootstrap-c-code
(let* ((ip (open-input-file "llvm.c"))
(res (read-text-file-from-input-port ip)))
(close-input-port ip)
res))
On the other hand, if what you intended was to create a procedure called bootstrap-c-code, then the correct syntax would be:
(define (bootstrap-c-code)
(define (from-file file-name)
(let* ((ip (open-input-file file-name))
(res (read-text-file-from-input-port ip)))
(close-input-port ip)
res))
(from-file "llvm.c"))
According to R5RS, internal definitions can occur only at the beginning of the of a bunch of forms like let, let*, lambda etc. In the case of your code, that is not the case since you have an internal definition inside a non-procedural define. You could fix it by making `bootstrap-c-code' bind to a procedure.