This is probably silly but I don't have enough Elisp knowledge to understand what is going on with respect to quoting and evaluation.
Suppose I have this Elisp code:
(add-to-list 'default-frame-alist '(width . 100))
(add-to-list 'default-frame-alist '(height . 50))
It will result in the expected default-frame-alist value:
((height 50)
(width 100))
But now if I have this:
(setq my-frame-width 100)
(setq my-frame-height 50)
(add-to-list 'default-frame-alist '(width . my-frame-width))
(add-to-list 'default-frame-alist '(height . my-frame-height))
It will result in -
((height my-frame-height)
(width my-frame-width))
and, judging from the frame geometry, never evaluates those variables. How do I make the actual values of my-frame-width and height appear in this alist? Do I have too many quotes? But I cannot remove any from the add-to-list evaluations...
Try this:
(setq my-frame-width 100)
(setq my-frame-height 50)
(add-to-list 'default-frame-alist `(width . ,my-frame-width))
(add-to-list 'default-frame-alist `(height . ,my-frame-height))
Using backquote instead of quote allows you to use , to force the evaluation of a parameter.
See the Elisp reference manual. Type C-x info, search for the elisp reference manual, then search for backquote within that.
As an alternative to the backquote operator in mch's answer, you can use the cons function. This function will build a cons cell with the first argument as its car and the second argument as its cdr. The dotted pair notation in your code is shorthand for this. So we could rewrite your code this way:
(setq my-frame-width 100)
(setq my-frame-height 50)
(add-to-list 'default-frame-alist (cons 'width my-frame-width))
(add-to-list 'default-frame-alist (cons 'height my-frame-height))
This way, you can quote the symbols you want to appear literally (like width and height) and evaluate the symbols whose values you need (like my-frame-width and my-frame-height). I prefer this method because it is more straight-forward. However, that is certainly a matter of opinion. Here is some more information on cons and list for future reference.
Related
I have a list consisting of two different kind of elements:
String designators
Cons cells, whose car and cdr are both string designators
I would like this list to be printed with the following structure: all elements separated by commas, and each cons cell (a . b) is printed as a=b.
The real goal is to generate Tikz/LaTeX code using Common Lisp, and this specific part of the code is just there to generate "options" (to an environment, a package, a command ...)
Example:
>>> (format nil "<cool-format-string>" '(draw (color . red) dashed (fill . gray)))
[draw, color=red, dashed, fill=gray]
I know about iteration directives, conditional ones, etc, in format. The only problem is that I want to print my list elements differently according to their type, not according to their numerical value or their 'truth' (nil vs anything else)
Besides writing a custom directive with ~/, is there a way to use another construction which would do something akin to the conditional directive, but using a custom predicate ?
(defun dotted-pair-p (x)
(and (listp x) (not (listp (cdr x)))))
(defun print-fancy (lst)
(let ((res (mapcar (lambda (x) (if (dotted-pair-p x)
(format nil "~a=~a" (car x) (cdr x))
(format nil "~a" x)))
lst)))
;; add the ', ' inbetween the strings
;; and put the result in between "[]"
(format nil "[~{~a~^, ~}]" res)))
(print-fancy '(draw (color . red) dashed (fill . gray)))
;; "[DRAW, COLOR=RED, DASHED, FILL=GRAY]"
I have the following code. It creates text to mtext without moving the text blocks in autocad. I want to have this script but combine the text lines into one block within a certain area. As in create a block of mtext within 5 units north and south of a certain layer's text blocks.
(defun C:T1MJ ; = Text or Attribute Definition to 1-line Mtext, retaining Justification
(/ *error* cmde doc tss inc tent tobj tins tjust)
(defun *error* (errmsg)
(if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
(princ (strcat "\nError: " errmsg))
); if
(vla-endundomark doc)
(setvar 'cmdecho cmde)
(princ)
); defun - *error*
(setq
cmde (getvar 'cmdecho)
doc (vla-get-activedocument (vlax-get-acad-object))
); setq
(vla-startundomark doc)
(setvar 'cmdecho 0)
(prompt "\nTo change Text/Attribute to 1-line Mtext, preserving Justification,")
(if (setq tss (ssget "_:L" '((0 . "TEXT,ATTDEF"))))
(repeat (setq inc (sslength tss))
(setq
tent (ssname tss (setq inc (1- inc)))
tobj (vlax-ename->vla-object tent)
tins (vlax-get tobj 'TextAlignmentPoint)
tjust (vla-get-Alignment tobj)
); setq
(cond
((= tjust 0) (setq tjust 7 tins (vlax-get tobj 'InsertionPoint))); Left
((< tjust 3) (setq tjust (+ tjust 7))); 1/2 [Center/Right] to 8/9
((= tjust 4) (setq tjust 5)); Middle to Middle-Center
((member tjust '(3 5)); Aligned/Fit
(setq
tjust 8 ; to Bottom-Center
tins (mapcar '/ (mapcar '+ (vlax-get tobj 'InsertionPoint) tins) '(2 2 2))
; with new insertion point
); setq
); Aligned/Fit
((setq tjust (- tjust 5))); all vertical-horizontal pair justifications
); cond
(if (= (vla-get-TextString tobj) "") (vla-put-TextString tobj (vla-get-TagString tobj)))
;; if no default content, disappears after TXT2MTXT: impose Tag value for it
;; [to use Prompt value instead, change end to (vla-get-PromptString tobj).]
(command "_.txt2mtxt" tent ""); convert, then
(setq tobj (vlax-ename->vla-object (entlast))); replace Text as object with new Mtext
(vla-put-AttachmentPoint tobj tjust); original Text's justification [or equiv.]
(vlax-put tobj 'InsertionPoint tins); original Text's insertion
); repeat
); if
(setvar 'cmdecho cmde)
(vla-endundomark doc)
(princ)
); defun -- T1MJ
(vl-load-com)
(prompt "\nType T1MJ to change Text/Attribute-Definitions to 1-line Mtext, preserving Justification.")
I am not a lisp programmer so I can't give you a direct answer but I am about to describe a concept to you that you should be able to replicate.
If you look here at this web resource it discusses one of the Express Tools: TXT2MTXT
Now, this is a command line routine and it takes a selection set and converts the TEXT into a MTEXT object:
So, I can't see why you can't use lisp to make a localized selection set of your text objects and then pass this selection set to the TXT2MTXT command. I know it is possible to do this kind of thing with lisp. I just don't know the mechanics. I know VBA.
I hope this is of assistance to you in resolve your issue. It doesn't show the code but it describes the concept of how to do what you want.
I'm using emacs on both Mac OS X and Ubuntu. My .emacs is mostly the same for both platforms, with a couple of lines concerning local fonts and other OS-related stuff. As I usually do additions to my .emacs files, I would like to sync them in a quasi-automatic manner.
My question is---is there a way in Lisp to add a conditional procedure to detect the running OS? Something like (pseudo-code):
If OS X:
run this and that command;
If Linux:
run that other command;
Fi
Thanks in advance.
Following bmeric's advice, this solution worked for me:
(cond
((string-equal system-type "gnu/linux")
;; window size
(add-to-list 'default-frame-alist '(left . 0))
(add-to-list 'default-frame-alist '(top . 0))
(add-to-list 'default-frame-alist '(height . 32))
(add-to-list 'default-frame-alist '(width . 70))
)
((string-equal system-type "darwin")
;; window size
(add-to-list 'default-frame-alist '(left . 0))
(add-to-list 'default-frame-alist '(top . 0))
(add-to-list 'default-frame-alist '(height . 63))
(add-to-list 'default-frame-alist '(width . 100))
)
)
You can use system-type variable.
I'm trying to make a recursive definition that reads and execute user expressions, such as (3 + 5). Everything is working, except of one problem with the arithmetic symbol.
I managed to replicate the error in a simpler example:
(define v '(1 + 3))
((cadr v) 2 4)
The (cadr v) is the + symbol, but for some reason the procedure can't be executed on the two arguments that followed. Am I missing something?
I think that's because
(cadr v)
returns '+ not + (literal + not a + function).
You need to evaluate it before applying it to arguments.
This should work:
((eval (cadr v)) 2 4)
^evaluates the '+ to +
edit
This worked in racket in interactive mode.
I'm not really sure what's the difference, but made it work in r5rs mode in racket (a script):
#lang r5rs
;required by r5rs
(define user-initial-environment (scheme-report-environment 5))
(define v '(1 + 2))
;eval expects a quoted expression
;(it seems that if it's a function it has to have arguments too)
;and evaluation environment.
((eval (cadr v) user-initial-environment) 2 4)
As others have pointed out, the problem is that the list you've constructed contains the symbol plus, rather than the function plus.
At its heart, this is the same reason that '(a b) returns a list of two symbols, rather than signalling an unbound identifier error; the quote starts a term in a "data language" where legal identifiers are interpreted as symbols, rather than as variable references.
The question, of course, is what you should do about it. Some here have suggested using 'eval'; this is probably a bad idea, for reasons that I think Matthew Flatt captures elegantly in his blog post on the topic.
Instead, you should probably write a simple mapping function. Here's the way I'd write it. If you use my code in an assignment, be sure to credit me :).
#lang racket
;; a mapping from symbols to operators
(define operator-hash
(hash '+ +
'- -
'* *))
;; ... and whatever other operators you want.
;; example of using it:
(hash-ref operator-hash '+) ;; ==> +
Try this:
(define v '(1 + 3))
(let ((operator (eval (cadr v)))
(operand1 (car v))
(operand2 (caddr v)))
(apply operator (list operand1 operand2)))
You can do it this way with eval in Guile:
(define (infix-eval v)
(eval (list (cadr v)(car v)(caddr v))
(interaction-environment)))
> (infix-eval '(1 + 2))
3
Rather than using interaction-environment, you could supply another environment for evaluation, where you could also define some other symbols not found in standard Scheme, so that expressions like (7 % 3) and (2 ^ 6) would also work.
I often find myself converting code like this:
before do
:something
end
to
before { :something }
Is there a way to automate this task in emacs? I use ruby-mode and rinary, but they're not too helpful here.
ruby-mode in Emacs 24.3 and newer has the command ruby-toggle-block.
The default binding is C-c {.
I am sure it can be made shorter and better, but for now I've got the following:
(defun ruby-get-containing-block ()
(let ((pos (point))
(block nil))
(save-match-data
(save-excursion
(catch 'break
;; If in the middle of or at end of do, go back until at start
(while (and (not (looking-at "do"))
(string-equal (word-at-point) "do"))
(backward-char 1))
;; Keep searching for the containing block (i.e. the block that begins
;; before our point, and ends after it)
(while (not block)
(if (looking-at "do\\|{")
(let ((start (point)))
(ruby-forward-sexp)
(if (> (point) pos)
(setq block (cons start (point)))
(goto-char start))))
(if (not (search-backward-regexp "do\\|{" (point-min) t))
(throw 'break nil))))))
block))
(defun ruby-goto-containing-block-start ()
(interactive)
(let ((block (ruby-get-containing-block)))
(if block
(goto-char (car block)))))
(defun ruby-flip-containing-block-type ()
(interactive)
(save-excursion
(let ((block (ruby-get-containing-block)))
(goto-char (car block))
(save-match-data
(let ((strings (if (looking-at "do")
(cons
(if (= 3 (count-lines (car block) (cdr block)))
"do\\( *|[^|]+|\\)? *\n *\\(.*?\\) *\n *end"
"do\\( *|[^|]+|\\)? *\\(\\(.*\n?\\)+\\) *end")
"{\\1 \\2 }")
(cons
"{\\( *|[^|]+|\\)? *\\(\\(.*\n?\\)+\\) *}"
(if (= 1 (count-lines (car block) (cdr block)))
"do\\1\n\\2\nend"
"do\\1\\2end")))))
(when (re-search-forward (car strings) (cdr block) t)
(replace-match (cdr strings) t)
(delete-trailing-whitespace (match-beginning 0) (match-end 0))
(indent-region (match-beginning 0) (match-end 0))))))))
There are two functions to be bound to keys: ruby-goto-containing-block-start and ruby-flip-containing-block-type.
Either command works anywhere inside a block, and hopefully they can skip blocks that should be skipped - although that shouldn't be an issue if you are converting to a short block format.
The ruby-flip-containing-block-type collapses three line do .. end blocks to single line {} and vice versa. If the blocks are not exactly 3 lines and 1 line long, it should leave them alone.
I am using this on my ruby setup now, so I would appreciate improvements.
You could use a regular expression that crosses newlines.
/do(C-q C-j\?)*(.*)(C-q C-j\?)*end/
and replace with
{\2 }
Something like that could work. You could then customize it until it does exactly what you need and bind it to a macro so that you can whip it out and impress your friends anytime!
I tested the above regexes in vi (my editor of choice) and they worked. So something similar should work for you.
For more information, make sure to checkout the emacs wiki!
Here is a function. I am an elisp beginner. It only goes one way; from do to {. let me know if it works for you.