[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Advice on custom packages that conflict with tramp

From: Stefan Monnier
Subject: Re: Advice on custom packages that conflict with tramp
Date: Fri, 10 Mar 2023 11:19:18 -0500
User-agent: Gnus/5.13 (Gnus v5.13)

> One of the Tramp team members took a brief look at my packages and said
> that he did see at least one oddity in how I'm creating the shell buffers,
> being that it creates the shell buffer (so I can control the name) and then
> calls "shell" for that buffer.

I can't see where it "creates the shell buffer" before calling `shell`.

> (defun cycle-make-shell ()
>   "Implements a ring of *shell* buffers.  If current buffer is not a shell
> buffer, then it will just execute 'shell'.  If it IS a shell buffer, then
> create a new shell buffer, starting with '*shell-1*', but skipping to the
> next
> number if that already exists."
>   (interactive)
>   (let* ((bufname (buffer-name (current-buffer))))
>     (if (string-match "\*shell\\(\*\\|-\\([0-9][0-9]*\\)\*\\)" bufname)
                         ^         ^                      ^

BTW, why not check (derived-mode-p 'shell-mode) instead of checking the name?

>         (progn
>           (setq change-dir default-directory)
>           (setq done nil)

Here you change those two *global* variables.  Better define them
locally with `let`.  *Never* use `setq` on a variable unless you've
locally defined it with `let` or you globally defined it with `defvar`.

I recommend you regularly byte-compile your code (or use `flymake-mode`)
to benefit from the compiler's warnings.

>           (while (not done)
>             (progn
>               (setq new-bufname (next-bufname bufname "shell"))
>               (if (bufferp (get-buffer new-bufname))
>                   (setq bufname new-bufname)
>                 (setq done t)
>                 )
>               )
>             )
>           (if (bufferp (get-buffer "*shell*"))
>               (progn
>                 (set-buffer "*shell*")
>                 (rename-uniquely)
>                 (setq tmp-bufname (buffer-name))
>                 ))
>           (shell)
>  (sit-for 1)
>           (set-buffer "*shell*")
>           (rename-buffer new-bufname)
>           ;; Now we need to somehow change the directory to "change-dir".
>           (set-buffer tmp-bufname)
>           (rename-buffer "*shell*")
>           (set-buffer new-bufname)

If I were you, I'd change that function so that all your buffers are
named `*shell-N*` (i.e. you won't have one called `*shell*` any more).
Then you can just replace the above code with something like:


and call it a day.  It makes the other case (i.e. when you call that
command from a non-shell buffer) slightly more complicated since you
have to look for a shell buffer, but nothing too bad.
IOW something like:

    (defun my-cycle-make-shell ()
      (let ((dest nil))
        (unless (derived-mode-p 'shell-mode)
          (let ((bufs (buffer-list)))
            (while (and bufs (not dest))
              (if (with-current-buffer (car bufs)
                    (derived-mode-p 'shell-mode))
                  (setq dest (car bufs))
                (setq bufs (cdr bufs))))))
        (if dest
            (pop-to-buffer-same-window dest)

Of course, you can use something else than `rename-uniquely` if you
don't like the names it chooses :-)

> (defun cycle-find-shell (&optional string)
>   (interactive "sEnter directory substring: ")

AFAICT `string` is actually not searched as a substring but as a regexp.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]