all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Is it alright to define-derived-mode dynamically?
@ 2020-12-24  7:19 Jean Louis
  2020-12-24 14:44 ` Stefan Monnier
  0 siblings, 1 reply; 5+ messages in thread
From: Jean Louis @ 2020-12-24  7:19 UTC (permalink / raw)
  To: Help GNU Emacs

I wonder if it is alright to define the derived mode dynamically
within a function:

(defun rcd-db-report (title entries &optional tabulated-list-format
  tabulated-list-sort-key mode-map)
  (let* ((tabulated-list-format (or tabulated-list-format [("ID" 10 t) ("Button" 20 t)]))
	 (title "Database"))
    (let* ((buffer title)
	   (buffer (get-buffer-create buffer)))
      (switch-to-buffer-other-window buffer)
      (setq tabulated-list-format tabulated-list-format)
      (setq tabulated-list-sort-key tabulated-list-sort-key)
      (setq tabulated-list-entries entries)
      (define-derived-mode rcd-db-list tabulated-list-mode "Database List" "Database List Report"
	(hl-line-mode)
	(use-local-map mode-map) 
	(setq tabulated-list-padding 1)
	(tabulated-list-init-header)
	(tabulated-list-print t))
      (rcd-db-list))))

As I would like to pass the keymap as mode-map to be each time
different, but I wonder if it is alright defining derived mode in a
function. So far it works.

I can see that I may define function within a function as well, but I
wonder if that is alright.




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Is it alright to define-derived-mode dynamically?
  2020-12-24  7:19 Is it alright to define-derived-mode dynamically? Jean Louis
@ 2020-12-24 14:44 ` Stefan Monnier
  2020-12-25 10:42   ` Jean Louis
  0 siblings, 1 reply; 5+ messages in thread
From: Stefan Monnier @ 2020-12-24 14:44 UTC (permalink / raw)
  To: help-gnu-emacs

> I wonder if it is alright to define the derived mode dynamically
> within a function:

For your own personal use, it may work just fine.
For an ELisp package that you expect other people to use, it'll bite
them sooner or later.

> (defun rcd-db-report (title entries &optional tabulated-list-format
>   tabulated-list-sort-key mode-map)
[...]
>       (define-derived-mode rcd-db-list tabulated-list-mode "Database List" "Database List Report"
> 	  (hl-line-mode)
> 	  (use-local-map mode-map)
[...]
>       (rcd-db-list))))

First:
- It should be called `rcd-db-list-mode`.
- Don't use global variables's names for local variables.
- I doubt the mode needs `hl-line-mode`.  If *you* like it, then
  use something like (add-hook 'tabulated-list-mode-mode #'hl-line-mode) in
  your init file.

And you can do:

    (define-derived-mode rcd-db-list-mode tabulated-list-mode "Database List"
      "Major mode to manipulate Database List reports."
      [...])

    (defun rcd-db-report ( title entries &optional list-format
                           list-sort-key mode-map)
      [...]
      (rcd-db-list-mode)
      (use-local-map mode-map))

> I can see that I may define function within a function as well, but I
> wonder if that is alright.

`defun` manipulates the global environment (not just some environment
local to your `rcd-db-report`), and it throws away any previous
definition of the function, which is often not alright.


        Stefan




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Is it alright to define-derived-mode dynamically?
  2020-12-24 14:44 ` Stefan Monnier
@ 2020-12-25 10:42   ` Jean Louis
  2020-12-25 17:34     ` Stefan Monnier
  0 siblings, 1 reply; 5+ messages in thread
From: Jean Louis @ 2020-12-25 10:42 UTC (permalink / raw)
  To: help-gnu-emacs

Thank you Stefan, I followed your advise and disintegrated
functions. But it as tedious until I got it working.

(defun rcd-db-report (title entries tabulated-list-format table tabulated-list-sort-key)
  (let* ((title (generate-new-buffer-name (concat "RCD Database: " title))))
    (let* ((buffer title)
	   (buffer (get-buffer-create buffer))
	   (mode-map (rcd-db-table-mode-map table)))
      ;; (message "Keymap: %s" table)
      (switch-to-buffer-other-window buffer)
      (delete-other-windows)
      (rcd-db-list-mode) ;; TODO if I move it from this line, weird things happen
      (use-local-map mode-map) ;; TODO if I move it from this line, weird things happen
      (tabulated-list-init-header)
      (setq tabulated-list-padding 1))
      (setq tabulated-list-format tabulated-list-format)
      (setq tabulated-list-entries entries)
      (setq tabulated-list-sort-key tabulated-list-sort-key)
      ;;(tabulated-list-init-header)
      (tabulated-list-print t)))

I have noticed that I could not just place `use-local-map' anywhere I
wanted and by apparent random attempts I got it working. I do not know
where the problem was.

Problem was invoking another derived mode from tabulated-list-mode
where the other mode did appear and it was populated but it was not
visible. The text I could not see but entries were there and the lines
in existence, just everything white.

> First:
> - It should be called `rcd-db-list-mode`.

Done.

> - Don't use global variables's names for local variables.

Did you mean:

(defvar-local rcd-tabulated-marked-items nil
  "Collects IDs for tabulated list modes")

Now I use `defvar-local', so no need to to make it local additionally.

I use that variable to mark items in the list so that I may make mass
actions on various items.

I was first thinking that function `tabulated-list-put-tag' does that.
But it just places the tag. I cannot track the tag or process items by
using the tag. It seem to be just visual tool.

> - I doubt the mode needs `hl-line-mode`.  If *you* like it, then use
> something like (add-hook 'tabulated-list-mode-mode #'hl-line-mode)
> in your init file.

Done. I am using it that way now.

Cursor is harder visible, I have made some quick delete functions
without confirmation, so highlightin lines helps not to make mistake.

> And you can do:
> 
>     (define-derived-mode rcd-db-list-mode tabulated-list-mode "Database List"
>       "Major mode to manipulate Database List reports."
>       [...])
> 
>     (defun rcd-db-report ( title entries &optional list-format
>                            list-sort-key mode-map)
>       [...]
>       (rcd-db-list-mode)
>       (use-local-map mode-map))

Done.

I am doing that now, and you have noticed I guess so, that all that
was to invoke different keymaps for different SQL tables.

Thank you,
Jean



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Is it alright to define-derived-mode dynamically?
  2020-12-25 10:42   ` Jean Louis
@ 2020-12-25 17:34     ` Stefan Monnier
  2020-12-25 20:03       ` Jean Louis
  0 siblings, 1 reply; 5+ messages in thread
From: Stefan Monnier @ 2020-12-25 17:34 UTC (permalink / raw)
  To: help-gnu-emacs

> Problem was invoking another derived mode from tabulated-list-mode
> where the other mode did appear and it was populated but it was not
> visible. The text I could not see but entries were there and the lines
> in existence, just everything white.

There can only be one major mode active in a buffer at a time.
So whenever you call a major mode function, it "removes" the previously
set major mode.

>> - Don't use global variables's names for local variables.
>
> Did you mean:
>
> (defvar-local rcd-tabulated-marked-items nil
>   "Collects IDs for tabulated list modes")

So, I meant "local" as in let-bound variables or in your particular case
formal arguments of functions.


        Stefan




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Is it alright to define-derived-mode dynamically?
  2020-12-25 17:34     ` Stefan Monnier
@ 2020-12-25 20:03       ` Jean Louis
  0 siblings, 0 replies; 5+ messages in thread
From: Jean Louis @ 2020-12-25 20:03 UTC (permalink / raw)
  To: help-gnu-emacs

* Stefan Monnier <monnier@iro.umontreal.ca> [2020-12-25 20:35]:
> > Problem was invoking another derived mode from tabulated-list-mode
> > where the other mode did appear and it was populated but it was not
> > visible. The text I could not see but entries were there and the lines
> > in existence, just everything white.
> 
> There can only be one major mode active in a buffer at a time.
> So whenever you call a major mode function, it "removes" the previously
> set major mode.

Those were invocations of new buffers. Now it works, but I guess it
is related to `use-local-map' something as only when I moved its
position in the function it got repaired.

> >> - Don't use global variables's names for local variables.
> >
> > Did you mean:
> >
> > (defvar-local rcd-tabulated-marked-items nil
> >   "Collects IDs for tabulated list modes")
> 
> So, I meant "local" as in let-bound variables or in your particular case
> formal arguments of functions.

I remember what you mean now. It is in my case in 1-3 functions among
many. Do you think it is messing with program data? Or with
readability?

Often I will set global variable in let to temporarily change them,
like in this example `vterm-kill-buffer-on-exit'

(defun run-with-vterm (command)
  "Runs command with vterm"
  (let ((vterm-kill-buffer-on-exit t)
	(buffer (format "Running within vterm: %s" command))
	(vterm-shell command))
    (vterm buffer)))

Those formal arguments of functions they get cleaned up later when
function is perfected, they are more individually there for me to get
used to it until function is working well.




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-12-25 20:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-12-24  7:19 Is it alright to define-derived-mode dynamically? Jean Louis
2020-12-24 14:44 ` Stefan Monnier
2020-12-25 10:42   ` Jean Louis
2020-12-25 17:34     ` Stefan Monnier
2020-12-25 20:03       ` Jean Louis

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.