Gnu Emacs 24.4 pretest on Windows. I want to modify the menu-bar menu of nxml-mode on the fly, appending a forest structure of known XML files (formed by the xi:include's of any XML files that get edited). Works fine except for the menu patching. That also actually works for a single file, but once it becomes a hierarchy (nested keymap), accessing the menu gives me the nefarious "Wow, indirect keymap entry" error, at which point it's time to quit Emacs because things are getting severely hosed (it's disturbing when Alt-Tab stops working). Humorously, I see someone once submitted a bug report requesting more intelligible error text, which was denied.
I dump the menu structure before and after I patch it, and I can't see what's wrong with the patched version. The dump is pretty tedious reading, but less so than the code that patches it, I reckon, which would likely only cause gasps of horror without eliciting a solution. Here's the before state of the relevant portion of the menu bar:
((Show\ Outline\ Only menu-item "Show Outline Only" nxml-hide-all-text-content)
(Show\ Everything menu-item "Show Everything" nxml-show-all)
(nil menu-item "---")
(Validation menu-item "Validation" rng-validate-mode :button (:toggle . rng-validate-mode))
(nil-4 menu-item "---")
(Set\ Schema menu-item "Set Schema" (keymap "Set Schema" (Automatically menu-item "Automatically" rng-auto-set-schema) (For\ Document\ Type menu-item "For Document Type" nil :filter #[257 "ÂÁ!À\"" ["For Document Type" (lambda (menu) (mapcar (lambda (type-id) (vector type-id (list (quote rng-set-document-type) type-id))) (rng-possible-type-ids))) easy-menu-filter-return] 4 " (fn MENU)"]) (Any\ Well-Formed\ XML menu-item "Any Well-Formed XML" rng-set-vacuous-schema) (File\.\.\. menu-item "File..." rng-set-schema-file)))
(Show\ Schema\ Location menu-item "Show Schema Location" rng-what-schema)
(Save\ Schema\ Location menu-item "Save Schema Location" rng-save-schema-location :help "Save the location of the schema currently being used for this buffer")
(nil-8 menu-item "---")
(First\ Error menu-item "First Error" rng-first-error :enable rng-validate-mode)
(Next\ Error menu-item "Next Error" rng-next-error :enable rng-validate-mode)
(nil-11 menu-item "---")
(Customize\ nXML menu-item "Customize nXML" menu-function-7 :key-sequence nil))
And here's the state after appending my menu stuff to the end:
((Show\ Outline\ Only menu-item "Show Outline Only" nxml-hide-all-text-content)
(Show\ Everything menu-item "Show Everything" nxml-show-all)
(nil menu-item "---")
(Validation menu-item "Validation" rng-validate-mode :button (:toggle . rng-validate-mode))
(nil-4 menu-item "---")
(Set\ Schema menu-item "Set Schema" (keymap "Set Schema" (Automatically menu-item "Automatically" rng-auto-set-schema) (For\ Document\ Type menu-item "For Document Type" nil :filter #[257 "ÂÁ!À\"" ["For Document Type" (lambda (menu) (mapcar (lambda (type-id) (vector type-id (list (quote rng-set-document-type) type-id))) (rng-possible-type-ids))) easy-menu-filter-return] 4 " (fn MENU)"]) (Any\ Well-Formed\ XML menu-item "Any Well-Formed XML" rng-set-vacuous-schema) (File\.\.\. menu-item "File..." rng-set-schema-file)))
(Show\ Schema\ Location menu-item "Show Schema Location" rng-what-schema)
(Save\ Schema\ Location menu-item "Save Schema Location" rng-save-schema-location :help "Save the location of the schema currently being used for this buffer")
(nil-8 menu-item "---")
(First\ Error menu-item "First Error" rng-first-error :enable rng-validate-mode)
(Next\ Error menu-item "Next Error" rng-next-error :enable rng-validate-mode)
(nil-11 menu-item "---")
(Customize\ nXML menu-item "Customize nXML" menu-function-7 :key-sequence nil)
(ppop-event-0 "intro.xml" (keymap "intro.xml" (ppop-event-4 menu-item "introswan.xml" nil) (ppop-event-3 menu-item "introgame.xml" nil) (ppop-event-2 menu-item "introclark.xml" nil) (ppop-event-1 menu-item "introroots.xml" nil))))
For clarity, this sexp was added to the list, just after the last list element (Customize\ nXML ...:
(ppop-event-0
"intro.xml"
(keymap "intro.xml"
(ppop-event-4 menu-item "introswan.xml" nil)
(ppop-event-3 menu-item "introgame.xml" nil)
(ppop-event-2 menu-item "introclark.xml" nil)
(ppop-event-1 menu-item "introroots.xml" nil)))
The intent was that the existing drop-down would have a new entry at the end with text "intro.xml" which should be produce another menu with the entries "introswan.xml", "introclark.xml", "introroots.xml" and "introgame.xml". I have set the callback functions for all added items to nil for brevity; putting the real function in does not avoid the error.
The structure for my sub-hierarchy seems identical to that of another sub-hierarchy on the same dropdown (see keymap "Set Schema"), which of course works. I can't see what's wrong or how the structure could be interpreted as an indirect keymap. And it seems to work fine for the case of a single file that requires no nested keymap. I am running out of things to try...
Relevant source emitting the message is in C, seen at: http://bzr.savannah.gnu.org/lh/emacs/emacs-24/annotate/head:/src/keymap.c#L789
I think the problem is that your ppop-event-0 binding is missing a menu-item symbol before its "intro.xml" "name". The end result is that your binding ends up looking like some old format which AFAIK is not used anywhere anymore (but it's extremely difficult to figure it out, hence my adding a nasty error there if/when we actually bump into such a thing, so as to try and make sure we hear from users).
I think this error message has been with us for long enough that we can say for sure that such indirect bindings aren't used any more and we can drop support for it (and hence the corresponding error, tho the end result may not be much more helpful for you).
See Emacs bug #14248, which Emacs Dev has chosen not to investigate and fix. But perhaps if you submit another bug, with your recipe to reproduce the problem, they will reconsider. M-x report-emacs-bug.
In particular, if you can trace the hosing of Emacs to this error then we can hope they will consider the problem more seriously. (My bug report (14248) was only about the error message being unhelpful.)
FWIW: There is no mention of "indirect keymap" in the Elisp manual, except for this sentence about where-is-internal in node Scanning Keymaps:
If NOINDIRECT is non-`nil', `where-is-internal' doesn't follow
indirect keymap bindings. This makes it possible to search for an
indirect definition itself.
Related
I use helm for Emacs with several sources and wonder how I can extract the list of all entries that the user has marked with Ctrl+Space. As an example, execute the following in your *scratch* buffer
(require 'helm)
(defun helm-test-action (candidate)
"Test."
(interactive)
(message (concat "candidate = " (prin1-to-string candidate)
"\n, helm-marked-candidates = " (prin1-to-string (helm-marked-candidates)))))
(defun helm-test-case ()
"Test."
(interactive)
(helm :sources (list (helm-build-sync-source "First Source"
:candidates '("one" "two" "three")
:action #'helm-test-action)
(helm-build-sync-source "Second Source"
:candidates '("four" "five")
:action #'helm-test-action))))
and then M-x helm-test-case.
When you mark, say, "one" and "four" with Ctrl+Space and press Enter, how do I retrieve the two marked entries from my action? It seems candidate is always the line on which the cursor has been placed and (helm-marked-candidates) yields the list of marked entries of the current source. How do I get the list of marked entries across all sources?
Thanks for your help,
HPF
The answer is to use (helm-marked-candidates :all-sources t). This returns a list of all marked entries or, if none has been marked, the entry under the cursor when you hit enter.
It makes sense, of course, only if all your sources contain candidates of the same form and if the default action is the same for all sources. It seems this requirement isn't enforced though.
Regards,
HPF
Could anyone give me some assistance, please, to make-sparse-keymap within the following example and create at least one sample entry within that new keymap.
I'd like to create sub-menus to better organize and add additional entries to those sub-menus. This example is borrowed from the function menu-bar-update-buffers within menu-bar.el, and I have adapted a modification of the function to work with a right-click pop-up context menu.
(setq lawlist-context-menu-command-entries
(list
'(command-separator "--")
(list
'next-buffer
'menu-item
"Next Buffer"
'next-buffer
:help "Switch to the \"next\" buffer in a cyclic order")
(list
'previous-buffer
'menu-item
"Previous Buffer"
'previous-buffer
:help "Switch to the \"previous\" buffer in a cyclic order")
(list
'select-named-buffer
'menu-item
"Select Named Buffer..."
'switch-to-buffer
:help "Prompt for a buffer name, and select that buffer in the current window")
(list
'list-all-buffers
'menu-item
"List All Buffers"
'list-buffers
:help "Pop up a window listing all Emacs buffers") ))
EDIT: Issue resolved -- I modified the example for creating the Frames menu folder as was done within menu-bar-update-buffers from menu-bar.el. See answer below.
I modified the example for creating the Frames menu folder as was done within menu-bar-update-buffers from menu-bar.el. Issue resolved. Instead of using make-sparse-keymap, just keymap is used instead.
(setq lawlist-context-menu-command-entries `(
(test-one-separator "--")
(test-one-folder-heading menu-item "TEST" ,(cons 'keymap (list
(list
'next-buffer
'menu-item
"Next Buffer"
'next-buffer
:help "Switch to the \"next\" buffer in a cyclic order")
(list
'previous-buffer
'menu-item
"Previous Buffer"
'previous-buffer
:help "Switch to the \"previous\" buffer in a cyclic order")
'(test-two-separator "--")
(list
'select-named-buffer
'menu-item
"Select Named Buffer..."
'switch-to-buffer
:help "Prompt for a buffer name, and select that buffer in the current window")
(list
'list-all-buffers
'menu-item
"List All Buffers"
'list-buffers
:help "Pop up a window listing all Emacs buffers"))))))
Emacs column-number-mode numbers columns from 0 which normally doesn't cause me any grief, but I'm working with some line/column based data files whose spec starts with '1', and it would be a lot easier if I could either get emacs to do that, or find some elisp to.
Thoughts welcome.
As of Emacs 26 (now released) there is a built in knob to fix this.
To use it, set
(setq column-number-indicator-zero-based nil)
in your .emacs
[Edited to reflect that Emacs 26 is now out.]
You cannot easily change Emacs to have 1-based column counting, the change would have to be in the C code.
However, you can calculate your own column and put that in the mode line. Note: this requires the use of the force-mode-line-update - which could potentially slow down your Emacs (just keep it in mind in case two years from now Emacs feels sluggish on some large buffer).
;; update the mode line to have line number and column number
(setq mode-line-position
'("%p (%l," (:eval (format "%d)" (1+ (current-column))))))
;; force the update of the mode line so the column gets updated
(add-hook 'post-command-hook 'force-mode-line-update)
Doc links of use are 'Variables Used In Mode Line' and 'Cursor Position Information'.
Well, it may be not the best answer, because I don't know emacs that good. I've edited mode-line-position, which is part of mode-line-format. Before use it, look to the original value, to know for sure that nothing is missing.
(setq mode-line-position
'((-3 #("%p" 0 2 (help-echo "Size indication mode
mouse-1: Display Line and Column Mode Menu" mouse-face mode-line-highlight local-map (keymap (mode-line keymap (down-mouse-1 keymap (column-number-mode menu-item "Display Column Numbers" column-number-mode :help "Toggle displaying column numbers in the mode-line" :button (:toggle . column-number-mode)) (line-number-mode menu-item "Display Line Numbers" line-number-mode :help "Toggle displaying line numbers in the mode-line" :button (:toggle . line-number-mode)) "Toggle Line and Column Number Display"))))))
(size-indication-mode (8 #(" of %I" 0 6 (help-echo "Size indication mode
mouse-1: Display Line and Column Mode Menu" mouse-face mode-line-highlight local-map (keymap (mode-line keymap (down-mouse-1 keymap (column-number-mode menu-item "Display Column Numbers" column-number-mode :help "Toggle displaying column numbers in the mode-line" :button (:toggle . column-number-mode)) (line-number-mode menu-item "Display Line Numbers" line-number-mode :help "Toggle displaying line numbers in the mode-line" :button (:toggle . line-number-mode)) "Toggle Line and Column Number Display")))))))
"(%l,[%c"
(:eval (format ",%d])" (1+ (current-column))))))
The main problem is that when you remove %c (column number) from mode-line-format, your (:eval (current-column)) works very slow. I don't know how to make it better.
I'm trying to install bookmarks and I get the error. When I tried byte-compiling the files it also failed. Is there a current git for bookmarks+. Error below:
Invalid function: bmkp-menu-bar-make-toggle
Here is the full trace:
Debugger entered--Lisp error: (invalid-function bmkp-menu-bar-make-toggle)
bmkp-menu-bar-make-toggle(t t "Highlight Jump using Crosshairs" "Crosshairs highlighting is %s" "Temporarily highlight visited bookmarks using crosshairs")
byte-code("\306\307\310 B#\210\306 \311\312\n\211\313\314\315%#\210\306 \316\312\211\317\320\321%#\210\306 \322\312\f\211\323\324\325%#\210\306 \326\312
\211\327\330\331%#\210\306 \332\312\211\333\334\335%#\207" [menu-bar-bookmark-map bmkp-options-menu bmkp-crosshairs-flag bmkp-bmenu-state-file bookmark-save-flag bmkp-save-new-location-flag define-key [options] "Toggle Option" [bmkp-crosshairs-flag] bmkp-menu-bar-make-toggle "Highlight Jump using Crosshairs" "Crosshairs highlighting is %s" "Temporarily highlight visited bookmarks using crosshairs" [bmkp-toggle-saving-menu-list-state] "Autosave *Bookmark List* Display State" "Autosaving of `*Bookmark List*' display state is %s" "Autosave `*Bookmark List*' state (aka \"menu list\") when you quit it" [bmkp-toggle-saving-bookmark-file] "Autosave Bookmark File" "Autosaving of bookmarks is %s" "Automatically save a bookmark after setting or changing it" [bmkp-save-new-location-flag] "Autosave after Relocating" "Autosaving relocated bookmarks is %s" "Automatically save a bookmark after automatically relocating it" [bmkp-prompt-for-tags-flag] "Prompt for Tags when Setting" "Prompting for tags when setting a bookmark is %s" "Prompt for tags when setting a bookmark interactively" bmkp-prompt-for-tags-flag] 9)
require(bookmark+-key)
eval-buffer(#<buffer *load*<2>> nil "/home/bigtyme/Dropbox/SyncedPrograms/emacs/loadPath/bookmarkplus/bookmark+.el" nil t) ; Reading at buffer position 5907
load-with-code-conversion("/home/bigtyme/Dropbox/SyncedPrograms/emacs/loadPath/bookmarkplus/bookmark+.el" "/home/bigtyme/Dropbox/SyncedPrograms/emacs/loadPath/bookmarkplus/bookmark+.el" nil t)
require(bookmark+)
eval-buffer(#<buffer *load*> nil "/home/bigtyme/.emacs" nil t) ; Reading at buffer position 1158
load-with-code-conversion("/home/bigtyme/.emacs" "/home/bigtyme/.emacs" t t)
load("~/.emacs" t t)
#[nil "\205\264
Sorted it out by just downloading the current git version. The version I downloaded from the wiki must have had a bug. Now I have no issues.
First, do what chrm recommends: get the latest source files.
Second, bmkp-menu-bar-make-toggle is a Lisp macro, defined in bookmark+-mac.el.
As always, before byte-compiling any of the source files, be sure you load the source file the defines the macros that those files use. In this case, load bookmark+-mac.el (not *.elc) before byte-compiling any of the Bookmark+ files.
I just tried it, and it works for me.
I downloaded bookmark+ from here. All eight files.
Just make sure all files are in a directory from your load-path.
The function (your Emacs can't find) "bmkp-menu-bar-make-toggle", is defined in "bookmark+-mac.el".
I was trying to answer another SO question when I hit upon some very odd behavior. Here's my little test case:
(make-variable-buffer-local
(defvar my-override-mode-on-save nil
"Can be set to automatically ignore read-only mode of a file when saving."))
(defadvice file-writable-p (around my-overide-file-writeable-p act)
"override file-writable-p if `my-override-mode-on-save' is set."
(or
my-override-mode-on-save
ad-do-it))
(defun my-override-toggle-read-only ()
"Toggle buffer's read-only status, keeping `my-override-mode-on-save' in sync."
(interactive)
(setq my-override-mode-on-save (not my-override-mode-on-save))
(toggle-read-only))
(defun tester-fn ()
(interactive)
(let ((xxx (file-writable-p "/tmp/foofoo"))
(yyy (file-writable-p "/tmp/fooxxfoo")))
(message (concat "XXX: " (if xxx "yes" "no") " - YYY: " (if yyy "yes" "no")))))
where:
/tmp/foofoo is a read-only file that I've visited and run my-override-toggle-read-only in.
/tmp/fooxxfoo does not exist.
/tmp is writable by the user I'm logged in as.
If I run tester-fn in a buffer where my-override-mode-on-save is set to t then I get an unexpected result: XXX: no - YYY: no. If I run tester-fn while in some other buffer (e.g. scratch) I get the expected response in the minibuffer: XXX: no - YYY: yes. Tracing the advice through the debugger shows it to be doing exactly what I think it should be doing, executing the parts I expect it to, skipping the parts I expect it to, returning the value I expect it to. However, tracing tester-fn through the debugger shows very different values being returned (nil & t if the variable evaluates as nil, nil & nil if the variable evaluates as non-nil). The nil & nil return is really what I find bizarre.
I have no clue what's happening here. Anyone know why I'm not getting the results I expect?
Your code looks good, except the one missing key. You need to set the return value appropriately:
(defadvice file-writable-p (around my-overide-file-writeable-p act)
"override file-writable-p if `my-override-mode-on-save' is set."
(setq ad-return-value
(or
my-override-mode-on-save
ad-do-it)))
This is documented in the advice manual.