I have been trying to learn McCLIM and it has been quite difficult given the terseness of the documentation. After reading the manual I haven't been able to figure out how to associate a click to a pane and run a command. I am aware I can define commands such as:
(define-app-command (com-say :name t) ()
(format t "Hello world!"))
And type Say into the command box to get it to do something. I would like to click a pane and have it output this hello world string when clicked.
What do I need to set up in order to enable click listeners on a given pane?
There are at least two ways you can do that. The first would be using presentations and presentation-to-command-translator and second would use gadgets (aka. widgets) like push-button. I guess you haven't learned about presentations yet, so I would show you how to do it with gadgets.
The below example would have a pane and a push button. when you click the button, you would see "Hello World!" output to the pane.
;;;; First Load McCLIM, then save this in a file and load it.
(in-package #:clim-user)
(define-application-frame example ()
()
(:panes
(app :application
:scroll-bars :vertical
:width 400
:height 400)
(button :push-button
:label "Greetings"
:activate-callback
(lambda (pane &rest args)
(declare (ignore pane args))
;; In McCLIM, `t` or *standard-output is bound to the first pane of
;; type :application, in this case `app` pane.
(format t "Hello World!~%" ))))
(:layouts
(default (vertically () app button))))
(defun run ()
(run-frame-top-level (make-application-frame 'example)))
(clim-user::run)
P.S. One way to learn how to do something in McCLIM is to run and look at clim-demos. Once you find something interesting and want to know how it is done, look at its source in Examples directory of McCLIM source.
For Help, it is much better to use IRC chat (#clim on libera.chat) where multiple McCLIM devs hang out.
EDIT: Second example with presentation-to-command-translator, clicking anywhere in the pane would output "Hello World!" in the pane.
(in-package #:clim-user)
(define-application-frame example ()
()
(:pane :application
:width 400
:display-time nil))
;; Note the `:display-time nil` option above, without it default McCLIM command-loop
;; will clear the pane after each time the command is run. It wasn't needed in previous
;; example because there were no commands involved.
(define-example-command (com-say :name t)
()
(format t "Hello World!~%"))
(define-presentation-to-command-translator say-hello
(blank-area com-say example :gesture :select)
(obj)
nil)
(defun run ()
(run-frame-top-level (make-application-frame 'example)))
(clim-user::run)
Related
When I am in calendar and want to jump to the entry in org-agenda, I press 'c'.
Would it be possible to have the DAY view as the standard so when I jump I only see one day, and not the whole week which is more cluttered? Thanks!
You can do it in various ways. In the spirit of "teaching someone to fish", the first thing that you have to do is figure out what c in the calendar does. So open the calendar, place the cursor on a date and say C-h c c which will tell you that c in the calendar runs the command
org-calendar-goto-agenda. So the next step is to do C-h f org-calendar-goto-agenda and read its documentation. Then click on the link in that documentation to go to the code and read it.
So here are three alternatives:
The code of the function is pretty simple:
(defun org-calendar-goto-agenda ()
"Compute the Org agenda for the calendar date displayed at the cursor.
This is a command t (org-agenda-span 1))hat has to be installed in `calendar-mode-map'."
(interactive)
;; Temporarily disable sticky agenda since user clearly wants to
;; refresh view anyway.
(let ((org-agenda-buffer-tmp-name "*Org Agenda(a)*")
(org-agenda-sticky nil))
(org-agenda-list nil (calendar-absolute-from-gregorian
(calendar-cursor-to-date))
nil)))
You can modify the function to make the agenda view to be just one day, by setting the variable org-agenda-span to 1 locally:
(defun org-calendar-goto-agenda ()
"Compute the Org agenda for the calendar date displayed at the cursor.
This is a command t (org-agenda-span 1))hat has to be installed in `calendar-mode-map'."
(interactive)
;; Temporarily disable sticky agenda since user clearly wants to
;; refresh view anyway.
(let ((org-agenda-buffer-tmp-name "*Org Agenda(a)*")
(org-agenda-sticky nil)
(org-agenda-span 1))
(org-agenda-list nil (calendar-absolute-from-gregorian
(calendar-cursor-to-date))
nil)))
The trouble with this is that you have now forked the Org mode code and you will need to make this change to the code every time you update. That might be appropriate in some cases, but you should avoid it if at all possible.
You can define your own command and bind it to c in the calendar:
(defun my-org-calendar-goto-agenda ()
(interactive)
(let ((org-agenda-span 1))
(org-calendar-goto-agenda)))
(define-key calendar-mode-map (kbd "c") #'my-org-calendar-goto-agenda)
That works pretty well. You have to remember to undo the keymap modification to restore the original state if you want to try the third method below:
(define-key calendar-mode-map (kbd "c") #'org-calendar-goto-agenda)
You can add an advice to the org-calendar-goto-agenda command. This is a formalization of the second option above: it is slightly more "advanced" but it is a powerful way of dealing with questions of this sort: you are given a function that does almost what you want and you want to customize it so that it does exactly what you want. This method cannot always be used, but it can be used in this case and it provides a simple example:
(defun org-calendar-goto-agenda-around (orig-fun &rest args)
(let ((org-agenda-span 1))
(apply orig-fun args)))
(advice-add 'org-calendar-goto-agenda :around #'org-calendar-goto-agenda-around)
The idea is that you define an around function that does something around the call of the original function (in this case, it let-binds org-agenda-span to 1, just like the other methods and then calls the original function in this new let-bound environment). Then we modify the original function by installing the advice. If you do C-h f org-calendar-goto-agenda now, you will see that there is some added information:
This function has :around advice: ‘org-calendar-goto-agenda-around’.
This is probably the cleanest way to do what you want. You can also easily remove the advice with
(advice-remove 'org-calendar-goto-agenda #'org-calendar-goto-agenda-around)
so this method allows you to experiment fairly easily. This is my recommended solution.
I would like this to happen when I right click the launcher...icon..and select quit..and choose file exit. I would like this command to be run right before emacs exits....so when I right click the launcher icon and select quit then this command "wg-update-workgroup" is run then Emacs exits..I've tried learning about hooks but don't get how to add one....If someone can give me exact code I put into my initialization file I would be very grateful....tried binding a function to a key but get weird command p error.
Here's the code:
(add-hook 'kill-emacs-hook
(lambda ()
(wg-update-workgroup)))
UPD
It seems that the code isn't working for you since wg-update-workgroup needs an argument.
You have to test this yourself, since I don't really want to get familiar with the package.
Solution 1:
(add-hook 'kill-emacs-hook
(lambda ()
(wg-update-all-workgroups)))
Solution 2:
(add-hook 'kill-emacs-hook
(lambda ()
(call-interactively 'wg-update-workgroup)))
UPD: disregard everything from above:)
I'm pretty sure this is what you want:
(setq wg-query-for-save-on-emacs-exit nil)
(push (lambda()(or (ignore-errors
(wg-update-all-workgroups-and-save)) t))
kill-emacs-query-functions)
The first statement removes the extremely annoying y/n query about saving
workgroups on exit. The second statement saves everything unconditionally on exit.
Just to list my full configuration:
(require 'workgroups)
(workgroups-mode 1)
(setq wg-query-for-save-on-emacs-exit nil)
(wg-load "~/wg")
(push (lambda()(or (ignore-errors
(wg-update-all-workgroups-and-save)) t))
kill-emacs-query-functions)
You're right to be baffled. The issue is this: when Emacs begins exiting, workgroups.el cleans itself up earlier than 'kill-emacs-hook. What you want is this:
(add-hook 'kill-emacs-query-functions 'wg-update-all-workgroups)
The hook variable should then look something like this:
(wg-update-all-workgroups wg-emacs-exit-query)
I recommend using 'wg-update-all-workgroups rather than 'wg-update-workgroup if, like me, you have more than one workgroup saved in a given workgroups file.
IMO workgroups.el is the best Emacs session manager. Somebody new has just taken it over. I'm excited that a new version with even more features may be forthcoming:
https://github.com/pashinin/workgroups2/
we can get help with "C-h ..." and emacs show a Help buffer,and jump to other place with the link . How can I make something like that with elisp, link to another buffer or show something else?
The builtin Button package provides a convenient way. For example,
(require 'button)
(insert-button "foo" 'action (lambda (x) (find-file user-init-file)))
will insert a button/link labeled "foo" that when activated (by pressing Enter while point is over the label or middle clicking) will bring up the init file.
Here is another example that mimics a www link,
(insert-button "fsf"
'action (lambda (x) (browse-url (button-get x 'url)))
'url "http://www.fsf.org")
See Elisp Reference Manual 38.17 Buttons.
You are looking at "clickable text"
Read this for more explanation.
Or this if you are going to be using org-mode.
I'm learning LISP for a class. I have a basic workflow setup in Ubuntu with my LISP file in VIM and an interactive LISP prompt in a terminal that I'm using to test code as I write it. Is there a way to get LISP to load a specific file every time I type a command? It's getting a bit tiring having to constantly input (load 'initial-code.cl) (yes, even when I am using the terminal's history).
Can always try:
(let (fn)
(defun l (&optional filename)
(if filename
(setf fn filename))
(load fn)))
Works like this:
[2]> (l "x.lisp")
;; Loading file x.lisp ...
;; Loaded file x.lisp
T
[3]> (l)
;; Loading file x.lisp ...
;; Loaded file x.lisp
T
[4]>
Pretty simple.
You can also do something like:
(defun go ()
(load "project.lisp")
(yourfunc 'your 'parameters))
Then you just type (go) and it reloads your file and calls your main entry point.
Or even combine them:
(defun gogo (&rest args)
(l) ;; call (l "file.lisp") first to initialize it
(apply #'yourfunc args))
then you can change your parameters easily
(gogo 1 2)
(gogo 2 4)
Ya know, it's lisp. Don't like something, change it.
With more time, you can write a simple wrapper that can build these on the fly. But you get the idea.
Most Lisp programmers would encourage you to use SLIME.
If you like Eclipse, there is also a Lisp plugin.
I know this doesn't really answer your question, but at least you can be aware of some alternatives.
You can try slimv, it is like slime for vim.
I'm making an outline for my thesis using org-mode, and I'd like to show all headings up to a certain level (e.g. all level-1 and level-2 headings).
I haven't found anything about that in the org-mode manual. Cycling shows either only level-1 headings, or all headings, which is too much information in my outline right now.
Thanks,
daniel.
Update: I found a workaround for his: set the variable org-cycle-max-level. This is a global setting, though.
Just stumbled on this question. One year later but what the heck.. There are commands for this that allows you to show headings to a certain level.
One command is C-<n> C-c tab will show subheadings up to level <n> (<n>=1,2,3...).
Another command is C-<n> S-tab which will operate on the whole buffer. It shows all headings up to level <n> (<n>=1,2,3...)
I found a solution that suits me: The command org-content shows the folder hierarchy, and giving it a numeric argument does exactly what I want: limit the maximum level shown. In my example, I wanted to show 2 levels, so I can do C-2 M-x org-content <RET>.
I also added my own command to my .emacs init file, binding that command to C-c m
(defun org-show-two-levels ()
(interactive)
(org-content 2))
(add-hook 'org-mode-hook
(lambda ()
(define-key org-mode-map "\C-cm" 'org-show-two-levels)))
If the prefix arguments from M. Kullman's answer take too much mental capacity for you (a limited resource when you are thinking hard about something else at the same time) then you can use the following functions to expand contract headings
(defvar hf-org-depth-point nil)
(defvar hf-org-depth-depth nil)
(defun hf-org-depth-increase ()
(interactive)
(hf-org-depth-incr 1))
(defun hf-org-depth-decrease ()
(interactive)
(hf-org-depth-incr -1))
(defun hf-org-depth-incr (incr)
(when (not (equal (point) hf-org-depth-point))
(setq hf-org-depth-point nil)
(setq hf-org-depth-depth 0))a
(setq hf-org-depth-point (point))
(setq hf-org-depth-depth (max (+ hf-org-depth-depth incr) 0))
(hide-subtree)
(show-children hf-org-depth-depth))
```
I am way late to the party, but let us add a simple way for posterity. Simply use Cycle Global Visibility (<backtab>). If your headings are open, it will close them. However, if you apply it repeatedly with all headings collapsed, they will open to the level you want.
I use it from the keyboard by <SHIFT>+<TAB>. You can also find it in the Org menu (in Emacs) under Show/Hide -> Cycle Global Visibility ()