I'm trying to be able to draw ascii art in emacs picture-mode by moving left, down, up, and right with the j,h,k,l keys in evil-normal-mode.
To do this I used these bindings:
(nmap :keymaps 'picture-mode-map
"k" (lambda ()
(picture-movement-up)
(picture-self-insert (string-to-char ".")))
"j" (lambda ()
(picture-movement-down)
(picture-self-insert (string-to-char ".")))
"h" (lambda ()
(picture-movement-left)
(picture-self-insert (string-to-char ".")))
"l" (lambda ()
(picture-movement-right)
(picture-self-insert (string-to-char "."))))
What I expect is a single insertion of the . and for the motion to be changed with the corresponding picture-movement function.
However when I tried out these bindings the direction of text being inserted was right but 46 characters were inserted at once. And the character was they key I pressed, not the period.
For example when I pressed l I'd get llllllllllllllllllllllllllllllllllllllllllllll immediately instead of just a gradual succession of periods as I continued presssing l.
Why am I getting this behavior and how could I achieve my expected behavior?
The ASCII character . has the integer value 46. The picture-self-insert function passes its argument as a count, along with the value of the last-command-event variable, to the picture-insert function. For your case, this results in 46 insertions of the value of last-command-event, which happens to be whatever key you pressed.
In your lambda functions, replace (picture-self-insert (string-to-char ".")) with:
(picture-insert ?. 1)
This will perform 1 insertion of the . character.
Related
In short: (gethash 'PARIS pandemic-hash-table) is returning nil, despite 'PARIS being a key in the table; this seems to be related to quoting/evaluation of symbols during the hash-table creation in some way but I can't figure it out.
I'm playing with a graph search (testing for the shortest route between cities in the board game Pandemic; just for fun - trying to find optimal research lab placement in a way more sophisticated than 'has the most edges'). I'm using a hash table to hold the route data (nodes and edges), and, needed to input the data as a preliminary:
(defvar *nodes* '('San-Francisco 'Chicago 'Atlanta 'Washington 'Montreal 'New-York 'Madrid 'Paris 'London 'Essen 'Milan 'St-Petersburg))
(defvar *edges* '(('Chicago 'St-Petersburg)
('San-Francisco 'Atlanta 'Montreal)
('Chicago 'Washington)
('Atlanta 'Montreal 'New-York)
('Chicago 'Washington 'New-York)
('Montreal 'Washington 'Madrid 'London)
('New-York 'London 'Paris)
('Madrid 'Essen 'London 'Milan)
('Madrid 'Essen 'London 'New-York)
('London 'Paris 'Milan 'St-Petersburg)
('Paris 'Essen)
('Essen 'Chicago)))
(defvar *pandemic-node-hash* (make-hash-table))
(loop for node in *nodes*
for edges in *edges*
do (setf (gethash node *pandemic-node-hash*) edges))
If I look at the resulting hash table:
CL-USER> (loop for key being the hash-keys of *pandemic-node-hash*
do (print key))
'SAN-FRANCISCO
... ;other keys removed for brevity
'PARIS
NIL
So it's making the table (and the edges show up similarly), but, (gethash 'PARIS *pandemic-node-hash*) returns nil. If I then add another 'PARIS node directly (setf (gethash 'paris *pandemic-node-hash*) 'somevalue), and check the keys, I get:
(loop for key being the hash-keys of *pandemic-node-hash*
do (print key))
'other keys
'PARIS
PARIS
NIL
So, the problem has something to do with the evaluation of the symbols ('PARIS and friends) in the initial hash table creation loop, but I can't quite figure out what's going on or how to do that correctly. I'm guessing node evaluates to the un-evaluated symbol, passing that to gethash ... but what's the right way? Surely not (eval node)? Backtick the list, with commas in front of the symbols? (ugh).
Remember: 'foo is the short form for (quote foo). It's a list with two elements: the symbol CL:QUOTE and the symbol FOO.
(defun show-it (arg)
(print (list arg (type-of arg)))
(values))
Above is a smaller helper function for this answer.
CL-USER 37 > (show-it 'hamburg)
(HAMBURG SYMBOL)
Above shows that the function sees the symbol hamburg and not the value of a variable hamburg.
Not
CL-USER 38 > (show-it '('hamburg))
(((QUOTE HAMBURG)) CONS)
Above: the function sees a nested list, with a list, which has quote as a symbol.
Note: ((quote hamburg)) can be written shorter as('hamburg).
CL-USER 39 > (show-it (first '('hamburg)))
((QUOTE HAMBURG) CONS)
Above: if we get the first element, we get the list with the quote symbol.
Better
CL-USER 40 > (show-it '(hamburg))
((HAMBURG) CONS)
Above provides a list with one symbol, the symbol hamburg.
CL-USER 41 > (show-it (first '(hamburg)))
(HAMBURG SYMBOL)
Above gets the first element, which is the symbol hamburg.
Evaluation
Make sure that you understand evaluation in Lisp. quote blocks evaluation for the whole quoted expression and on all levels of those. Thus it makes no sense to quote contents inside a quoted list.
When passing arguments in a function call, then quoting is used to prevent lists and symbols to be evaluated. Thus quote creates literal data: literal symbols, literal lists, literal vectors, etc.
Thus quoting is a mechanism of code, not of data.
Code:
(first '(hamburg)) vs. (first (hamburg))
getting the first element of a literal list vs.
getting the first element of the result
of calling the function `hamburg`.
Data:
(paris hamburg berlin rome) vs. ('paris 'hamburg 'berlin 'rome)
A list of city names vs. a list of city names,
each nested in a list (quote ...)
Thus:
('paris 'hamburg 'berlin 'rome) makes no sense.
Why not
(dolist (node *nodes*)
(dolist (edges *edges*)
(setf (gethash node *pandemic-node-hash*) edges)))
But also you've double quoted your symbols (as someone else commented)
Why:
'(('Chicago 'St-Petersburg) ...)
when it should probably be just this (don't quote the list and each symbol)
'((Chicago St-Petersburg) ...)
You would see this if you evaluated: *edges*
How do we sort in a column view. In specific, I have a list of estimated taks, along with their priority, I want to be able to sort them based on any field, dynamically or atleast by specifying a field as a property.
AFAIK, you can't sort while you are in column view. But you exit column view (by typing "q"). They you can sort the entries by property with M-x org-sort (C-c ^). Type r for property and then enter the property you want to sort by.
E.g., let's say we begin with this:
* Test
** First task
:PROPERTIES:
:Effort: 1:30
:END:
** Second task
:PROPERTIES:
:Effort: 0:30
:END:
Navigate to "* Test" and type C-c ^ (or M-x org-sort). In this case, type "r" and then enter "Effort" to get the resulting order:
* Test
** Second task
:PROPERTIES:
:Effort: 0:30
:END:
** First task
:PROPERTIES:
:Effort: 1:30
:END:
Then enter column view again. (Note, you can also sort by priority --- you'll see the option when you invoke org-sort.)
Additionally, you can export your column view to a table and then sort the table by column:
http://orgmode.org/manual/Capturing-column-view.html
Wanting to sort in column view quite often, I wrote a command which does it by exiting column view, sorting, and then reentering column view:
(defun org-columns-sort (&optional arg)
"Sort entries from column view by value in current column.
This only sorts the children of the column view top level,
which is the entry with the current column view specification.
When ARG is non-nil (interactively with prefix), sort in
reverse order."
(interactive "P")
(let ((colname (get-char-property (point) 'org-columns-key))
(colnum (org-current-text-column)))
(org-columns-goto-top-level)
(org-columns-quit)
(org-sort-entries nil (if arg ?R ?r) nil nil colname)
(org-columns)
(outline-hide-sublevels
(1+ (org-current-level)))
(forward-char colnum)))
(org-defkey org-columns-map "^" #'org-columns-sort)
Or, if you want an alternative keybinding:
(defun org-columns-sort-reverse ()
"Calls `org-columns-sort' with non-nil argument."
(interactive)
(org-columns-sort t))
(org-defkey org-columns-map [(meta down)] #'org-columns-sort)
(org-defkey org-columns-map [(meta up)] #'org-columns-sort-reverse)
Suggestions for improvement are welcome. It doesn't quite restore the original folding and position. I tried storing (point-marker) and then use goto-char but somehow the marker gets lost.
Example: custom sort order
To get a nicer sort order for columns containing numbers or a mix of non-number strings and numbers, replace (org-sort-entries nil (if arg ?R ?r) nil nil colname) above with
(org-sort-entries nil (if arg ?F ?f)
(lambda () (org-entry-get nil colname))
#'my-org-columns-sort-function)
with
(defconst my-string-number-regex
(concat "^[+-]?\\(?:[0-9]+\\(?:[.,][0-9]*\\)?\\(?:e[+-]?[0-9]+\\)?"
"\\|[.,][0-9]+\\(?:e[+-]?[0-9]+\\)?\\)$")
"Matches integers and floats with exponent.
This allows for leading and trailing decimal point, leading zeros in base,
leading zeros in exponent, + signs, and , as alternative decimal separator.")
(defun my-org-columns-sort-function (x y)
"Returns non-nil if X should sort before Y (is less than Y).
This function gives a nice sort order when used with `org-columns-sort'.
Both arguments can be either a cons, a non-number string, or a
number-string. Across types the sort order is as mentioned.
Within types, `string-lessp` is used for non-number strings,
and `<` is used for number-strings."
(cond
((and (consp x)(consp y))
nil)
((and (consp x)(not (consp y)))
t)
((and (not (consp x))(consp y))
nil)
(t
(let ((sxp (not (string-match-p my-string-number-regex x)))
(syp (not (string-match-p my-string-number-regex y))))
(cond
((and sxp syp)
(string-lessp x y))
((and sxp (not syp))
t)
((and (not sxp) syp)
nil)
(t
(< (string-to-number x) (string-to-number y))))))))
See here if you want a less general pattern for matching numbers.
I evaluated the following elisp code in ielm:
(setq foo-hash (make-hash-table))
(puthash "location" "house" foo-hash)
(defun foo-start ()
(interactive)
(message (gethash "location" foo-hash)))
However when i run (foo-start) or (gethash "location" foo-hash) i get only nil echoed. Entering just foo-hash in ielm echoes: #s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data ("location" "house"))
Is that a bug or i am doing something wrong?
Emacs version: 24.0.95.1
Hash tables in elisp use eql for comparison by default. Strings won't be equal with eql unless they're the same object. You probably want to use equal, which compares the contents of the strings. Create your hash table with this:
(make-hash-table :test 'equal)
This is a follow-up to How to get C-x C-e to display the result in octal and hexadecimal by default?
Is there a way to get C-x C-e to to display the result in decimal and hexadecimal only?
e.g.
(+ 40 2)
should produce
42 (#x2a)
instead of
42 (#o52, #x2a, ?*)
You just need to rewrite/tweak the routine that creates the printed format for this. Add the following to your .emacs and you'll be good to go.
(require 'simple)
(defun eval-expression-print-format (value)
"Format VALUE as a result of evaluated expression.
Return a formatted string which is displayed in the echo area
in addition to the value printed by prin1 in functions which
display the result of expression evaluation."
(if (and (integerp value)
(or (not (memq this-command '(eval-last-sexp eval-print-last-sexp)))
(eq this-command last-command)
(if (boundp 'edebug-active) edebug-active)))
(let ((char-string
(if (or (if (boundp 'edebug-active) edebug-active)
(memq this-command '(eval-last-sexp eval-print-last-sexp)))
(prin1-char value))))
(format " (#x%x)" value value))))
I'm trying to write simple Emacs function to convert ids between C style ones and camelCase ones (i.e. c_style <-> cStyle). But for some reason, Emacs built in downcase function leaves the word intact. M-x downcase-word works fine so I completely lost. Any ideas are welcome.
(defun toggle-id-style ()
"Toggle between C-style ids and camel Case ones (i.e. c_style_id -> cStyleId and back)."
(interactive)
(save-excursion
(progn
(re-search-forward "[^A-Za-z0-9_]" nil t)
(let ((end (point))
(case-fold-search nil))
(progn
(re-search-backward "[^A-Za-z0-9_]" nil t)
(let* ((cstyle (if (string-match "_" (buffer-substring-no-properties (point) end)) t nil))
(regexp (if cstyle "_\\(\\w+\\)" "\\([A-Z][a-z0-9]+\\)") )
(func (if cstyle 'capitalize (lambda (s) (concat "_" (downcase s) ) ))))
(progn
(while (re-search-forward regexp end t)
(replace-match (funcall func (match-string 1)) nil nil)))))))))
;;M-x replace-regexp _\(\w+\) -> \,(capitalize \1) ;; c_style -> cStyle
;;M-x replace-regexp \([A-Z][a-z0-9]+\) -> _\,(downcase \1) ;;cStyle -> c_style
It works fine if I convert c_style but when I'm trying to convert cStyle I got c_Style as result. Yes, I've checked that this is due to downcase behaviour.
Your problem is the second argument to replace-match. From the documentation:
If second arg fixedcase is non-nil, do not alter case of replacement text.
Otherwise maybe capitalize the whole text, or maybe just word initials,
based on the replaced text.
If the replaced text has only capital letters
and has at least one multiletter word, convert newtext to all caps.
Otherwise if all words are capitalized in the replaced text,
capitalize each word in newtext.
You're passing nil for the fixedcase argument, which causes replace-match to capitalize the replacement when the text being replaced is capitalized. Pass t instead and this bit of the code will work.
I have two general comments about your code.
All of your uses of progn are unnecessary. The body of save-excursion is an implicit progn and so are the bodies of let and let*.
You search forwards and then backwards to try to find the bounds of the symbol underneath point. Emacs already has a thingatpt library to find things at or near the point. In your case you can just call (bounds-of-thing-at-point 'symbol) which returns a cons cell (START . END) giving the start and end positions of the symbol that was found.
I think you need the second arg of replace-match to be t instead of nil.