Simple implementation of a layered popup menu - emacs

The question is about the implementation of a popup menu, namely getting a multilevel submenu. The above code creates a simple menu with one nesting level (uncomment supPane1 and comment
;supSupPane). When trying to add another attachment (uncomment supSupPane and comment
;supPane1) the result is unexpected for me.
(let* ((Pane1 '("Разделы1" ("ПодПод1"."ПодПод1")("ПодПод2"."ПодПод2")("ПодПод3"."ПодПод3")("ПодПод4"."ПодПод4")))
(Pane2 '("Разделы2" ("ПодПод1"."ПодПод1")("ПодПод2"."ПодПод2")("ПодПод3"."ПодПод3")("ПодПод4"."ПодПод4")))
(Pane3 '("Разделы3" ("ПодПод1"."ПодПод1")("ПодПод2"."ПодПод2")("ПодПод3"."ПодПод3")("ПодПод4"."ПодПод4")))
(Pane4 '("Разделы4" ("ПодПод1"."ПодПод1")("ПодПод2"."ПодПод2")("ПодПод3"."ПодПод3")("ПодПод4"."ПодПод4")))
(supPane1 `("ЧудоМеню1" ,Pane1 ,Pane2 ,Pane3 ,Pane4))
(supPane2 `("ЧудоМеню2" ,Pane1 ,Pane2 ,Pane3 ,Pane4))
(supPane3 `("ЧудоМеню3" ,Pane1 ,Pane2 ,Pane3 ,Pane4))
(supPane4 `("ЧудоМеню4" ,Pane1 ,Pane2 ,Pane3 ,Pane4))
(supSupPane `("СупперЧудоМеню" ,supPane1 ,supPane2 ,supPane3 ,supPane4))
(выбзнч (x-popup-menu
(list '(50 50) (selected-frame))
supPane1)
;supSupPane)
))
(message "Ваш выбор это: %s" выбзнч))
Also, I'm interested in simply disabling the assigned keyboard shortcuts for quick menu access in the emacs search code. Thank.
There is a solution using the easy-menu-define macro.
(setq my-menu '())
(easy-menu-define my-menu nil "Моё Чудо Меню"
'("ПодМеню"
["ПодМенюВыбор1" "ПодМенюВыбор1" t]
["ПодМенюВыбор2" "ПодМенюВыбор2" t]
["ПодМенюВыбор3" "ПодМенюВыбор3" t]
("ПодПодМеню1"
["ПодПодМеню1Выбор1" "ПодПодМеню1Выбор1" t]
("ПодПодМеню1Выбор2Меню"
["ПодПодМеню1Выбор2МенюВыбор1" "ПодПодПодМеню1Выбор1" t]
["ПодПодМеню1Выбор2МенюВыбор2" "ПодПодПодМеню1Выбор2" t]
["ПодПодМеню1Выбор2МенюВыбор3" "ПодПодПодМеню1Выбор3" t]
["ПодПодМеню1Выбор2МенюВыбор4" "ПодПодПодМеню1Выбор4" t]
("ПодПодМеню1Выбор2МенюВыбор5Меню"
["ПодПодМеню1Выбор2МенюВыбор5МенюВыбор1" "ПодПодПодМеню1Выбор1" t]
["ПодПодМеню1Выбор2МенюВыбор5МенюВыбор2" "ПодПодПодМеню1Выбор2" t]
["ПодПодМеню1Выбор2МенюВыбор5МенюВыбор3" "ПодПодПодМеню1Выбор3" t]
["ПодПодМеню1Выбор2МенюВыбор5МенюВыбор4" "ПодПодПодМеню1Выбор4" t]
)
)
["ПодПодМеню1Выбор2" "ПодПодМеню1Выбор2" t]
["ПодПодМеню1Выбор3" "ПодПодМеню1Выбор3" t]
)
("ПодПодМеню2"
["ПодПодМеню2Выбор1" "ПодПодМеню2Выбор1" t]
("ПодПодПодМеню1"
["ПодПодПодМеню1Выбор1" "ПодПодПодМеню1Выбор1" t]
["ПодПодПодМеню1Выбор2" "ПодПодПодМеню1Выбор2" t]
("ПодПодПодМеню"
["ПодПодПодМеню1Выбор1" "ПодПодПодМеню1Выбор1" t]
["ПодПодПодМеню1Выбор2" "ПодПодПодМеню1Выбор2" t]
["ПодПодПодМеню1Выбор3" "ПодПодПодМеню1Выбор3" t]
)
["ПодПодПодМеню1Выбор3" "ПодПодПодМеню1Выбор3" t]
)
["ПодПодМеню2Выбор2" "ПодПодМеню2Выбор2" t]
["ПодПодМеню2Выбор3" "ПодПодМеню2Выбор3" t]
)))
(let* ((выбзнч (x-popup-menu
(list '(50 50) (selected-frame))
my-menu)
))
(message "Ваш выбор это: %s" выбзнч))
The menu is formed dynamically, so the use of this macro is no longer valid.
Let's analyze what menu the macro made
my-menu = >
(keymap "ПодМеню" (ПодМенюВыбор1 menu-item "ПодМенюВыбор1" menu-function-2 :key-sequence nil) (ПодМенюВыбор2 menu-item "ПодМенюВыбор2" menu-function-3 :key-sequence nil) (ПодМенюВыбор3 menu-item "ПодМенюВыбор3" menu-function-4 :key-sequence nil) (ПодПодМеню1 menu-item "ПодПодМеню1" (keymap "ПодПодМеню1" (ПодПодМеню1Выбор1 menu-item "ПодПодМеню1Выбор1" menu-function-5 :key-sequence nil) (ПодПодМеню1Выбор2Меню menu-item "ПодПодМеню1Выбор2Меню" ...) (ПодПодМеню1Выбор2 menu-item "ПодПодМеню1Выбор2" menu-function-10 :key-sequence nil) (ПодПодМеню1Выбор3 menu-item "ПодПодМеню1Выбор3" menu-function-11 :key-sequence nil))) (ПодПодМеню2 menu-item "ПодПодМеню2" (keymap "ПодПодМеню2" (ПодПодМеню2Выбор1 menu-item "ПодПодМеню2Выбор1" menu-function-12 :key-sequence nil) (ПодПодПодМеню1 menu-item "ПодПодПодМеню1" ...) (ПодПодМеню2Выбор2 menu-item "ПодПодМеню2Выбор2" menu-function-13 :key-sequence nil) (ПодПодМеню2Выбор3 menu-item "ПодПодМеню2Выбор3" menu-function-14 :key-sequence nil))))
What he has composed here is not clear at all. Let's study!
(ПодПодМеню1Выбор2Меню menu-item "ПодПодМеню1Выбор2Меню" ...)
The most interesting, as always hidden!

Thank you all, I figured it out myself.
(let ((выбзнч (x-popup-menu
(list '(0 0) (selected-frame))
'(keymap "Меню"
(ПодМенюВыбор1 menu-item "ПодМенюВыбор1" menu-function-2 :key-sequence nil)
(ПодМенюВыбор2 menu-item "ПодМенюВыбор2" menu-function-3 :key-sequence nil)
(ПодМенюВыбор3 menu-item "ПодМенюВыбор3" menu-function-4 :key-sequence nil)
(ПодМенюВыбор4 menu-item "ПодМенюВыбор4Меню" (keymap "ПодПодМеню"
(ПодПодМенюВыбор1 menu-item "ПодПодМенюВыбор1" menu-function-2 :key-sequence nil)
(ПодПодМенюВыбор2 menu-item "ПодПодМенюВыбор2" menu-function-3 :key-sequence nil)
(ПодПодМенюВыбор3 menu-item "ПодПодМенюВыбор3" menu-function-4 :key-sequence nil)
(ПодПодМенюВыбор4 menu-item "ПодПодМенюВыбор4Меню" (keymap "ПодПодПодМеню"
(ПодПодПодМенюВыбор1 menu-item "ПодПодПодМенюВыбор1" menu-function-2 :key-sequence nil)
(ПодПодПодМенюВыбор2 menu-item "ПодПодПодМенюВыбор2" menu-function-3 :key-sequence nil)
(ПодПодПодМенюВыбор3 menu-item "ПодПодПодМенюВыбор3Меню" (keymap "ПодПодПодПодМеню"
(ПодПодПодПодМенюВыбор1 menu-item "ПодПодПодПодМенюВыбор1" menu-function-2 :key-sequence nil)
(ПодПодПодПодМенюВыбор2 menu-item "ПодПодПодПодМенюВыбор2" menu-function-3 :key-sequence nil)
(ПодПодПодПодМенюВыбор3 menu-item "ПодПодПодПодМенюВыбор3" menu-function-4 :key-sequence nil)))))))))))
(message "Ваш выбор это: %s" выбзнч))

Related

How to pass the variable name as a string to a function? (ClojureScript)

Description of the situation
I want to make a form template for an element, but they must be dynamically created. The meta data involved in the Component should use the variable-name passed as it's meta-data.
Code
For example,
In the view,
(ns my.app
(:require [my.app.templating :as template])
(defn view-component [nOperacaoExtrato]
[:<>
(template/temp-form nOperacaoExtrato)])
The templating function,
(ns my.app.templating)
(defn temp-form
"Template input"
[dado]
#_(js/console.log (str "meta-data: " (meta #'dado)))
(let [nome-var (:name (meta #'dado))]
[:div.col
[:label
{:for (str "form1_" nome-var)}
"Natureza do Dispendio"]
[:p
{:class "form-control",
:id (str "form1_" nome-var)
:name (str "form1" nome-var)}
dado]]))
The result should be, something like this (because the variable passed is nOperacaoExtrato):
[:div.col
[:label
{:for "form1_re-fin-n-operacao-extrato-prop"}
"Nº da Operação no Extrato"]
[:p
{:class "form-control",
:id "form1_re-fin-n-operacao-extrato-prop",
:name "form1_re-fin-n-operacao-extrato-prop"}
(h/preencher-str nOperacaoExtrato)]]
The issue:
Both of these return null.
(meta #'data)
(meta data)
``
You should probably convert this function to a macro. Let me show you fellow Portuguese speaker:
src/cljs/user.cljc
(ns cljs.user)
(defn temp-form-fn
"Template input"
[dado nome-var]
[:div.col
[:label
{:for (str "form1_" nome-var)}
"Natureza do Dispendio"]
[:p
{:class "form-control",
:id (str "form1_" nome-var)
:name (str "form1" nome-var)}
dado]])
#?
(:clj
(defmacro temp-form
[dado]
`(temp-form-fn ~dado ~(name dado))))
Then in the repl:
cljs.user> (require '[cljs.user :refer-macros [temp-form]])
nil
cljs.user> (let [nOperacaoExtrato 1234]
(temp-form nOperacaoExtrato))
[:div.col
[:label {:for "form1_nOperacaoExtrato"} "Natureza do Dispendio"]
[:p
{:class "form-control",
:id "form1_nOperacaoExtrato",
:name "form1nOperacaoExtrato"}
1234]]

Why isn't my macro functioning in the same way as handwritten code?

So I have 2 router functions for learning to work with clack in common lisp. One is written without macros, and the other is written with macros that expand to match the first function, but only the non-macro version is working. The code below has (:use :trivia) from (ql:quickload 'trivia).
This one is written without any macros, and works:
(defun router (env)
(match env
((guard (property :path-info path)
(equalp "/" path))
(home env))
((guard (property :path-info path)
(equalp "/live/clicked" path))
(live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404 page not found"))))))
I decided I didn't like those guard clauses taking up so much space in the function definition, so I rewrote the function:
(defun router (env)
(match env
(route "/" (home env))
(route "/live/clicked" (live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404 page not found"))))))
route is defined as so:
(defmacro route (valid-path &body body)
(let ((path (gensym)))
`((guard (property :path-info ,path)
(equalp ,valid-path ,path))
,#body)))
With this new router function and macro, the function is always short-circuiting on the first clause. When macroexpanding the 2 (route ...) clauses, I receive this output, matching the function I wrote:
* `(defun router (env)
(match env
,(macroexpand '(route "/" (home env)))
,(macroexpand '(route "/live/clicked" (live-clicked env)))
((property :path-info path)
`(404 nil (,(format nil "404")))))))
(DEFUN ROUTER (ENV)
(MATCH ENV
((GUARD (PROPERTY :PATH-INFO #:G120) (EQUALP "/" #:G120)) (HOME ENV))
((GUARD (PROPERTY :PATH-INFO #:G121) (EQUALP "/live/clicked" #:G121)) (LIVE-CLICKED ENV))
((PROPERTY :PATH-INFO PATH) `(404 NIL (,(FORMAT NIL "404")))))
(home env) and (live-clicked env) are functions that return something similar to (backquote (200 nil (,(*form generating html*)))). env is the state of the web request, but in this instance it only needs to be (list :path-info "/live/clicked")
First of all, macroexpand should be
used for interactive debugging rather than in production code.
Its use inside defun (almost) never makes sense.
Second, to understand your second router, you should macroexpand its body
rather than the defun, i.e.,
(macroexpand '(match env
(route "/" (home env))
(route "/live/clicked" (live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404"))))))
You will see that route is not expanded because it is not in a "function position".
What you need to expand your route before match is expanded, i.e., you probably want a
wrapper around match (I removed gensym because you indicated in the comments that it is really
not necessary):
(defmacro my-match (what &body clauses)
(labels ((handle-clause (clause)
(if (eq (car clause) 'route)
(apply #'route (rest clause))
clause))
(route (valid-path &rest body)
`((guard (property :path-info path)
(equalp ,valid-path path))
,#body)))
`(match ,what ,#(mapcar #'handle-clause clauses))))
and then
(defun router (env)
(my-match env
(route "/" (home env))
(route "/live/clicked" (live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404 page not found"))))))
Testing:
(macroexpand '(my-match env
(route "/" (home env))
(route "/live/clicked" (live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404"))))))
==>
(MATCH ENV ((GUARD (PROPERTY :PATH-INFO PATH) (EQUALP "/" PATH)) (HOME ENV))
((GUARD (PROPERTY :PATH-INFO PATH) (EQUALP "/live/clicked" PATH))
(LIVE-CLICKED ENV))
((PROPERTY :PATH-INFO PATH) `(404 NIL (,(FORMAT NIL "404")))))
T
The pattern matcher you are using, Trivia, has a defpattern macro. That's what you must use to define a macro against the pattern language itself, rather than defmacro.

Generating inline javascript with cl-who, parenscript and hunchentoot

I'm trying to generate inline javascript, but I have to put the parenscript code inside (:script) and (str) tags using cl-who. ps, ps*, ps-inline and ps-inline* don't seem to make much difference to the generated js.
Is the usual way to write a macro to avoid code duplication, or is there a better way?
Here's my program:
(in-package #:ps-test)
(defmacro standard-page ((&key title) &body body)
`(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
(:html
:lang "en"
(:head
(:meta :http-equiv "Content-Type"
:content "text/html;charset=utf-8")
(:title ,title)
(:link :type "text/css"
:rel "stylesheet"
:href "/style.css"))
(:body
,#body))))
(defun main ()
(with-html-output (*standard-output* nil :indent t :prologue nil)
(standard-page (:title "Parenscript test")
(:div (str "Hello worldzors"))
(:script :type "text/javascript"
(str (ps (alert "Hello world as well")))))))
(define-easy-handler (docroot :uri "/") ()
(main))
(defun start-ps-test ()
(setf (html-mode) :html5)
(setf *js-string-delimiter* #\")
(start (make-instance 'hunchentoot:easy-acceptor :port 8080)))
(defun stop-ps-test ()
(stop *server*))
(defvar *server* (start-ps-test))
Macros are fine in this use case.
The trick is that macros are expanded in a specific order. Say
you define a js macro: when macroexpansion encounters
with-html-output, the inner call to your macros (js (alert "Ho Ho Ho")) looks like a function call, and is left as-is in the generated
code. If your js macro then expands into (:script ...), then the system will complain that :script is an unknown function (assuming you
didn't actually name a function like that). You should emit an
enclosing (who:htm ...) expression to interpret the code using
CL-WHO's code walker.
(defmacro js (code)
`(who:htm
(:script :type "text/javascript" (who:str (ps:ps ,code)))))
This only works in the context of an enclosing with-html-output.
For inline Javascript, you don't want to have a <script> tag around it,
and you can generally simply use ps-inline:
(who:with-html-output (*standard-output*)
(:a :href (ps:ps-inline (void 0))
"A link where the usual HREF behavior is canceled."))
;; prints:
;;
;; <a href='javascript:void(0)'>A link where the usual HREF behavior is canceled.</a>
But feel free to use a macro if you often do the same thing:
(defmacro link (&body body)
`(who:htm (:a :href #.(ps:ps-inline (void 0)) ,#body)))
(who:with-html-output (*standard-output*) (link "Link"))
;; prints:
;;
;; <a href='javascript:void(0)'>Link</a>

Emacs does not run after package updating

What should I do? After just updating packages my Emacs installation does not initialise. I tried the same process in two Macs with the same result. The error message (using --debug-init) is:
Debugger entered--Lisp error: (void-variable left)
powerline-reset()
require(powerline)
eval-buffer(#<buffer *load*-583073> nil "/Users/sergiobacelar/.emacs.d/starter-kit-misc.el" nil t) ; Reading at buffer position 2361
load-with-code-conversion("/Users/sergiobacelar/.emacs.d/starter-kit-misc.el" "/Users/sergiobacelar/.emacs.d/starter-kit-misc.el" nil nil)
load("/Users/sergiobacelar/.emacs.d/starter-kit-misc.el" nil nil t)
load-file("/Users/sergiobacelar/.emacs.d/starter-kit-misc.el")
org-babel-load-file("/Users/sergiobacelar/.emacs.d/starter-kit-misc.org")
starter-kit-load("starter-kit-misc.org")
eval-buffer(#<buffer *load*-903092> nil "/Users/sergiobacelar/.emacs.d/starter-kit.el" nil t) ; Reading at buffer position 3819
load-with-code-conversion("/Users/sergiobacelar/.emacs.d/starter-kit.el" "/Users/sergiobacelar/.emacs.d/starter-kit.el" nil nil)
load("/Users/sergiobacelar/.emacs.d/starter-kit.el" nil nil t)
load-file("/Users/sergiobacelar/.emacs.d/starter-kit.el")
org-babel-load-file("/Users/sergiobacelar/.emacs.d/starter-kit.org")
eval-buffer(#<buffer *load*> nil "/Users/sergiobacelar/.emacs.d/init.el" nil t) ; Reading at buffer position 2725
load-with-code-conversion("/Users/sergiobacelar/.emacs.d/init.el" "/Users/sergiobacelar/.emacs.d/init.el" t t)
load("/Users/sergiobacelar/.emacs.d/init" t t)
#[0 "\205\262 \306=\203\307\310Q\202; \311=\204\307\312Q\202;\313\307\314\315#\203*\316\202;\313\307\314\317#\203:\320\nB\321\202;\316\322\323\322\211#\210\322=\203a\324\325\326\307\327Q!\"\323\322\211#\210\322=\203`\210\203\243\330!\331\232\203\243\332!\211\333P\334!\203}\211\202\210\334!\203\207\202\210\314\262\203\241\335\"\203\237\336\337#\210\340\341!\210\266\f?\205\260\314\323\342\322\211#)\262\207" [init-file-user system-type delayed-warnings-list user-init-file inhibit-default-init inhibit-startup-screen ms-dos "~" "/_emacs" windows-nt "/.emacs" directory-files nil "^\\.emacs\\(\\.elc?\\)?$" "~/.emacs" "^_emacs\\(\\.elc?\\)?$" (initialization "`_emacs' init file is deprecated, please use `.emacs'") "~/_emacs" t load expand-file-name "init" file-name-as-directory "/.emacs.d" file-name-extension "elc" file-name-sans-extension ".el" file-exists-p file-newer-than-file-p message "Warning: %s is newer than %s" sit-for 1 "default"] 7 "\n\n(fn)"]()
command-line()
normal-top-level()
There is a solution for this in https://github.com/milkypostman/powerline/issues/79. It seems to be a known bug in powerline.el.

Emacs: how to stop jedi?

I regularly use jedi.el, it works great. But I don't know how to stop it !
I manually call it with jedi:setup (which turns jedi-mode on) and try to stop it with jedi-mode but it has no effect. It is unconvenient and it gets in the way with yasnippet.
Do you have a solution ? Thanks.
config: emacs24 and latest jedi.el version from melpa. Result of jedi:show-setup-info:
;; Emacs Lisp version:
(:emacs-version "24.3.1" :jedi-version "0.2.0alpha2" :python-environment-version "0.0.2alpha0")
;; Python version:
((:version "2.7.3 (default, Feb 27 2014, 19:58:35) \n[GCC 4.6.3]" :name "sys" :file nil)
(:version "0.7.0" :name "jedi" :file "/usr/local/lib/python2.7/dist-packages/jedi/__init__.pyc")
(:version "0.0.5" :name "epc" :file "/usr/local/lib/python2.7/dist-packages/epc/__init__.pyc")
(:version "0.0.3" :name "sexpdata" :file "/usr/local/lib/python2.7/dist-packages/sexpdata.pyc"))
;; Command line:
(:virtualenv "/usr/bin/virtualenv" :virtualenv-version "1.7.1.2\n")
;; Customization:
((jedi:complete-on-dot)
(jedi:doc-display-buffer . display-buffer)
(jedi:doc-hook view-mode)
(jedi:doc-mode . rst-mode)
(jedi:environment-root)
(jedi:environment-virtualenv)
(jedi:get-in-function-call-delay . 1000)
(jedi:get-in-function-call-timeout . 3000)
(jedi:goto-definition-config
(nil nil nil)
(t nil nil)
(nil definition nil)
(t definition nil)
(nil nil t)
(t nil t)
(nil definition t)
(t definition t))
(jedi:goto-definition-marker-ring-length . 16)
(jedi:imenu-create-index-function . jedi:create-nested-imenu-index)
(jedi:import-python-el-settings . t)
(jedi:install-imenu)
(jedi:install-python-jedi-dev-command "pip" "install" "--upgrade" "git+https://github.com/davidhalter/jedi.git#dev#egg=jedi")
(jedi:key-complete .
[C-tab])
(jedi:key-goto-definition .
[67108910])
(jedi:key-goto-definition-pop-marker .
[67108908])
(jedi:key-related-names . "r")
(jedi:key-show-doc . "d")
(jedi:server-args)
(jedi:server-command "python" "/home/vdardelx/.emacs.d/elpa/jedi-20140321.1323/jediepcserver.py")
(jedi:setup-keys)
(jedi:tooltip-method pos-tip popup)
(jedi:use-shortcuts)
(python-environment-default-root-name . "default")
(python-environment-directory . "~/.emacs.d/.python-environments")
(python-environment-virtualenv "virtualenv" "--system-site-packages" "--quiet"))
What aspect is conflicting with yasnippet? Is it the use of autocomplete-mode? (which seems to be the other broad consequence of running jedi:setup, and which isn't turned off again when jedi-mode is disabled.)
M-x autocomplete-mode will toggle that off again, or call (autocomplete-mode -1) in code.
You could write a function to disable both modes together, and call that to turn jedi off. A more robust approach would remember the state of autocomplete-mode at the time jedi was enabled in order to restore it afterwards, but it sounds like that's not critical in your case.