all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* let*: Wrong type argument: stringp, nil
@ 2021-09-24 14:52 Hongyi Zhao
  2021-09-24 14:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-25 10:09 ` Stephen Berman
  0 siblings, 2 replies; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-24 14:52 UTC (permalink / raw)
  To: help-gnu-emacs

According to the idea represented here [1], I wrote the following
function to activate the python virtual environment automatically
using the content of the ".python-version" file located in the project
directory of the current opened python file:

(defun pyvenv-autoload ()
    (require 'projectile)
    (let* ((pdir (file-name-directory buffer-file-name)) (pfile
(concat pdir ".python-version")))
      (if (file-exists-p pfile)
          (pyvenv-workon (with-temp-buffer
                           (insert-file-contents pfile)
                           (nth 0 (split-string (buffer-string))))))))
(add-hook 'python-mode-hook 'pyvenv-autoload)

It seems the corresponding python virtual environment can be activated
automatically when I open the python file in Emacs. But when I try to
evaluate the file, the following message will be triggered, and defeat
the evaluate operation:

let*: Wrong type argument: stringp, nil

[1] https://github.com/jorgenschaefer/pyvenv/issues/51#issuecomment-253902450

Any hints for fixing this problem?

Regards
-- 
Assoc. Prof. Hongyi Zhao <hongyi.zhao@gmail.com>
Theory and Simulation of Materials
Hebei Vocational University of Technology and Engineering
No. 473, Quannan West Street, Xindu District, Xingtai, Hebei province



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-24 14:52 let*: Wrong type argument: stringp, nil Hongyi Zhao
@ 2021-09-24 14:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-25  1:29   ` Hongyi Zhao
  2021-09-25 10:09 ` Stephen Berman
  1 sibling, 1 reply; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-24 14:57 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

> let*: Wrong type argument: stringp, nil
>
> Any hints for fixing this problem?

Indeed, inside a `let*', a variable is used in a function that
expects a string. However either the variable is set to nil,
or it isn't set at all. nil isn't a string so the function
cannot operate, thus the error.

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-24 14:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-25  1:29   ` Hongyi Zhao
  2021-09-25 23:42     ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-25  1:29 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

On Fri, Sep 24, 2021 at 10:58 PM Emanuel Berg via Users list for the
GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote:
>
> Hongyi Zhao wrote:
>
> > let*: Wrong type argument: stringp, nil
> >
> > Any hints for fixing this problem?
>
> Indeed, inside a `let*', a variable is used in a function that
> expects a string. However either the variable is set to nil,
> or it isn't set at all. nil isn't a string so the function
> cannot operate, thus the error.

How to fix it or use a more robust method?

Best, HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-24 14:52 let*: Wrong type argument: stringp, nil Hongyi Zhao
  2021-09-24 14:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-25 10:09 ` Stephen Berman
  2021-09-25 10:45   ` Hongyi Zhao
  1 sibling, 1 reply; 35+ messages in thread
From: Stephen Berman @ 2021-09-25 10:09 UTC (permalink / raw)
  To: Hongyi Zhao; +Cc: help-gnu-emacs

On Fri, 24 Sep 2021 22:52:45 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:

> According to the idea represented here [1], I wrote the following
> function to activate the python virtual environment automatically
> using the content of the ".python-version" file located in the project
> directory of the current opened python file:
>
> (defun pyvenv-autoload ()
>     (require 'projectile)
>     (let* ((pdir (file-name-directory buffer-file-name)) (pfile
> (concat pdir ".python-version")))
>       (if (file-exists-p pfile)
>           (pyvenv-workon (with-temp-buffer
>                            (insert-file-contents pfile)
>                            (nth 0 (split-string (buffer-string))))))))
> (add-hook 'python-mode-hook 'pyvenv-autoload)
>
> It seems the corresponding python virtual environment can be activated
> automatically when I open the python file in Emacs. But when I try to
> evaluate the file, the following message will be triggered, and defeat
> the evaluate operation:
>
> let*: Wrong type argument: stringp, nil
>
> [1] https://github.com/jorgenschaefer/pyvenv/issues/51#issuecomment-253902450
>
> Any hints for fixing this problem?

Evidently buffer-file-name is nil when the sexp `(file-name-directory
buffer-file-name)' is evaluated, which indicates the current buffer when
that function is called is not visiting a file (e.g., you get the same
error when you evaluate `(file-name-directory buffer-file-name)' in
*scratch*).

Steve Berman



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-25 10:09 ` Stephen Berman
@ 2021-09-25 10:45   ` Hongyi Zhao
  2021-09-25 11:04     ` Stephen Berman
  0 siblings, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-25 10:45 UTC (permalink / raw)
  To: Stephen Berman; +Cc: help-gnu-emacs

On Sat, Sep 25, 2021 at 6:09 PM Stephen Berman <stephen.berman@gmx.net> wrote:
>
> On Fri, 24 Sep 2021 22:52:45 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> > According to the idea represented here [1], I wrote the following
> > function to activate the python virtual environment automatically
> > using the content of the ".python-version" file located in the project
> > directory of the current opened python file:
> >
> > (defun pyvenv-autoload ()
> >     (require 'projectile)
> >     (let* ((pdir (file-name-directory buffer-file-name)) (pfile
> > (concat pdir ".python-version")))
> >       (if (file-exists-p pfile)
> >           (pyvenv-workon (with-temp-buffer
> >                            (insert-file-contents pfile)
> >                            (nth 0 (split-string (buffer-string))))))))
> > (add-hook 'python-mode-hook 'pyvenv-autoload)
> >
> > It seems the corresponding python virtual environment can be activated
> > automatically when I open the python file in Emacs. But when I try to
> > evaluate the file, the following message will be triggered, and defeat
> > the evaluate operation:
> >
> > let*: Wrong type argument: stringp, nil
> >
> > [1] https://github.com/jorgenschaefer/pyvenv/issues/51#issuecomment-253902450
> >
> > Any hints for fixing this problem?
>
> Evidently buffer-file-name is nil when the sexp `(file-name-directory
> buffer-file-name)' is evaluated, which indicates the current buffer when
> that function is called is not visiting a file (e.g., you get the same
> error when you evaluate `(file-name-directory buffer-file-name)' in
> *scratch*).

Thank you for pointing this out. Based on your above comment, I fixed
the problem with the code below, and it does the trick:

(defun pyvenv-autoload ()
    (require 'projectile)
    (if (buffer-file-name)
      (let* ((pdir (file-name-directory buffer-file-name)) (pfile
(concat pdir ".python-version")))
        (if (file-exists-p pfile)
          (pyvenv-workon (with-temp-buffer
                           (insert-file-contents pfile)
                           (nth 0 (split-string (buffer-string)))))))))
(add-hook 'python-mode-hook 'pyvenv-autoload)

BTW, can I use `when' to write the above code?

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-25 10:45   ` Hongyi Zhao
@ 2021-09-25 11:04     ` Stephen Berman
  2021-09-25 13:49       ` Hongyi Zhao
  0 siblings, 1 reply; 35+ messages in thread
From: Stephen Berman @ 2021-09-25 11:04 UTC (permalink / raw)
  To: Hongyi Zhao; +Cc: help-gnu-emacs

On Sat, 25 Sep 2021 18:45:28 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:

> On Sat, Sep 25, 2021 at 6:09 PM Stephen Berman <stephen.berman@gmx.net> wrote:
>>
>> On Fri, 24 Sep 2021 22:52:45 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>>
>> > According to the idea represented here [1], I wrote the following
>> > function to activate the python virtual environment automatically
>> > using the content of the ".python-version" file located in the project
>> > directory of the current opened python file:
>> >
>> > (defun pyvenv-autoload ()
>> >     (require 'projectile)
>> >     (let* ((pdir (file-name-directory buffer-file-name)) (pfile
>> > (concat pdir ".python-version")))
>> >       (if (file-exists-p pfile)
>> >           (pyvenv-workon (with-temp-buffer
>> >                            (insert-file-contents pfile)
>> >                            (nth 0 (split-string (buffer-string))))))))
>> > (add-hook 'python-mode-hook 'pyvenv-autoload)
>> >
>> > It seems the corresponding python virtual environment can be activated
>> > automatically when I open the python file in Emacs. But when I try to
>> > evaluate the file, the following message will be triggered, and defeat
>> > the evaluate operation:
>> >
>> > let*: Wrong type argument: stringp, nil
>> >
>> > [1] https://github.com/jorgenschaefer/pyvenv/issues/51#issuecomment-253902450
>> >
>> > Any hints for fixing this problem?
>>
>> Evidently buffer-file-name is nil when the sexp `(file-name-directory
>> buffer-file-name)' is evaluated, which indicates the current buffer when
>> that function is called is not visiting a file (e.g., you get the same
>> error when you evaluate `(file-name-directory buffer-file-name)' in
>> *scratch*).
>
> Thank you for pointing this out. Based on your above comment, I fixed
> the problem with the code below, and it does the trick:
>
> (defun pyvenv-autoload ()
>     (require 'projectile)
>     (if (buffer-file-name)
>       (let* ((pdir (file-name-directory buffer-file-name)) (pfile
> (concat pdir ".python-version")))
>         (if (file-exists-p pfile)
>           (pyvenv-workon (with-temp-buffer
>                            (insert-file-contents pfile)
>                            (nth 0 (split-string (buffer-string)))))))))
> (add-hook 'python-mode-hook 'pyvenv-autoload)
>
> BTW, can I use `when' to write the above code?

Certainly, indeed `when' is typically favored over `if' when there's no
'else' branch, as in the above code.  On the other hand, since the point
of the function is activate a virtual environment on visiting a Python
file, you might want to add an 'else' branch that returns a suitable
message when the current buffer is not visiting a file.  Without that,
in such a case the function just returns nil, so there's no indication
the activation failed.

BTW, your code would be easier to read if you began the second clause of
the let* on a new line:

         (let* ((pdir (file-name-directory buffer-file-name))
                (pfile (concat pdir ".python-version")))

Steve Berman



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-25 11:04     ` Stephen Berman
@ 2021-09-25 13:49       ` Hongyi Zhao
  2021-09-25 14:45         ` Stephen Berman
  0 siblings, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-25 13:49 UTC (permalink / raw)
  To: Stephen Berman; +Cc: help-gnu-emacs

On Sat, Sep 25, 2021 at 7:05 PM Stephen Berman <stephen.berman@gmx.net> wrote:
>
> On Sat, 25 Sep 2021 18:45:28 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> > On Sat, Sep 25, 2021 at 6:09 PM Stephen Berman <stephen.berman@gmx.net> wrote:
> >>
> >> On Fri, 24 Sep 2021 22:52:45 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
> >>
> >> > According to the idea represented here [1], I wrote the following
> >> > function to activate the python virtual environment automatically
> >> > using the content of the ".python-version" file located in the project
> >> > directory of the current opened python file:
> >> >
> >> > (defun pyvenv-autoload ()
> >> >     (require 'projectile)
> >> >     (let* ((pdir (file-name-directory buffer-file-name)) (pfile
> >> > (concat pdir ".python-version")))
> >> >       (if (file-exists-p pfile)
> >> >           (pyvenv-workon (with-temp-buffer
> >> >                            (insert-file-contents pfile)
> >> >                            (nth 0 (split-string (buffer-string))))))))
> >> > (add-hook 'python-mode-hook 'pyvenv-autoload)
> >> >
> >> > It seems the corresponding python virtual environment can be activated
> >> > automatically when I open the python file in Emacs. But when I try to
> >> > evaluate the file, the following message will be triggered, and defeat
> >> > the evaluate operation:
> >> >
> >> > let*: Wrong type argument: stringp, nil
> >> >
> >> > [1] https://github.com/jorgenschaefer/pyvenv/issues/51#issuecomment-253902450
> >> >
> >> > Any hints for fixing this problem?
> >>
> >> Evidently buffer-file-name is nil when the sexp `(file-name-directory
> >> buffer-file-name)' is evaluated, which indicates the current buffer when
> >> that function is called is not visiting a file (e.g., you get the same
> >> error when you evaluate `(file-name-directory buffer-file-name)' in
> >> *scratch*).
> >
> > Thank you for pointing this out. Based on your above comment, I fixed
> > the problem with the code below, and it does the trick:
> >
> > (defun pyvenv-autoload ()
> >     (require 'projectile)
> >     (if (buffer-file-name)
> >       (let* ((pdir (file-name-directory buffer-file-name)) (pfile
> > (concat pdir ".python-version")))
> >         (if (file-exists-p pfile)
> >           (pyvenv-workon (with-temp-buffer
> >                            (insert-file-contents pfile)
> >                            (nth 0 (split-string (buffer-string)))))))))
> > (add-hook 'python-mode-hook 'pyvenv-autoload)
> >
> > BTW, can I use `when' to write the above code?
>
> Certainly, indeed `when' is typically favored over `if' when there's no
> 'else' branch, as in the above code.

But the actual demand exceeds the simple processing above, I mean, the
real project maybe located under a specific folder with multiple level
subdirectories. In this case, when I open a python file, the function
should do the following: Search the current directory and its parent
directories at all levels in turn. Once the ".python-version" file is
found, activate the corresponding environment and exit the cycle;
Otherwise, continue to search upwards until the  certain top level
directory, say, $HOME. Based on the above requirements and the code
snippets given here [1-2], I finally figured out the following
solution:

-------
(defun parent-directory (dir)
  (unless (equal (getenv "HOME") dir)
    ;file-truename or directory-file-name
    (file-name-directory (directory-file-name dir))))


(defun find-file-in-heirarchy (current-dir fname)
  "Search for a file named FNAME upwards through the directory
hierarchy, starting from CURRENT-DIR"
  (let ((file (concat current-dir fname))
        (parent (parent-directory (expand-file-name current-dir))))
    (if (file-exists-p file)
        file
      (when parent
        (find-file-in-heirarchy parent fname)))))


(defun try/pyvenv-workon ()
  (when (buffer-file-name)
      (let ((file (find-file-in-heirarchy (buffer-file-name)
".python-version")))
        (when (file-exists-p file)
          (pyvenv-workon (with-temp-buffer
                           (insert-file-contents file)
                             (nth 0 (split-string
(buffer-string)))))))))

(add-hook 'python-mode-hook 'try/pyvenv-workon)
-------

It works like a charm. But any suggestions/enhancements/comments will
be greatly appreciated.

[1] https://stackoverflow.com/a/14096693  (*)
[2] http://sodaware.sdf.org/notes/emacs-lisp-find-file-upwards/

* Indicated that this is my main reference source code.

>  On the other hand, since the point
> of the function is activate a virtual environment on visiting a Python
> file, you might want to add an 'else' branch that returns a suitable
> message when the current buffer is not visiting a file.  Without that,
> in such a case the function just returns nil, so there's no indication
> the activation failed.

Good advice.

> BTW, your code would be easier to read if you began the second clause of
> the let* on a new line:
>
>          (let* ((pdir (file-name-directory buffer-file-name))
>                 (pfile (concat pdir ".python-version")))

Good advice, again.

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-25 13:49       ` Hongyi Zhao
@ 2021-09-25 14:45         ` Stephen Berman
  2021-09-25 15:03           ` Hongyi Zhao
  0 siblings, 1 reply; 35+ messages in thread
From: Stephen Berman @ 2021-09-25 14:45 UTC (permalink / raw)
  To: Hongyi Zhao; +Cc: help-gnu-emacs

On Sat, 25 Sep 2021 21:49:38 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:

[...]
> But the actual demand exceeds the simple processing above, I mean, the
> real project maybe located under a specific folder with multiple level
> subdirectories. In this case, when I open a python file, the function
> should do the following: Search the current directory and its parent
> directories at all levels in turn. Once the ".python-version" file is
> found, activate the corresponding environment and exit the cycle;
> Otherwise, continue to search upwards until the  certain top level
> directory, say, $HOME. Based on the above requirements and the code
> snippets given here [1-2], I finally figured out the following
> solution:
>
> -------
> (defun parent-directory (dir)
>   (unless (equal (getenv "HOME") dir)
>     ;file-truename or directory-file-name
>     (file-name-directory (directory-file-name dir))))
>
>
> (defun find-file-in-heirarchy (current-dir fname)
>   "Search for a file named FNAME upwards through the directory
> hierarchy, starting from CURRENT-DIR"
>   (let ((file (concat current-dir fname))
>         (parent (parent-directory (expand-file-name current-dir))))
>     (if (file-exists-p file)
>         file
>       (when parent
>         (find-file-in-heirarchy parent fname)))))
>
>
> (defun try/pyvenv-workon ()
>   (when (buffer-file-name)
>       (let ((file (find-file-in-heirarchy (buffer-file-name)
> ".python-version")))
>         (when (file-exists-p file)
>           (pyvenv-workon (with-temp-buffer
>                            (insert-file-contents file)
>                              (nth 0 (split-string
> (buffer-string)))))))))
>
> (add-hook 'python-mode-hook 'try/pyvenv-workon)
> -------
>
> It works like a charm. But any suggestions/enhancements/comments will
> be greatly appreciated.
>
> [1] https://stackoverflow.com/a/14096693  (*)
> [2] http://sodaware.sdf.org/notes/emacs-lisp-find-file-upwards/
>
> * Indicated that this is my main reference source code.

Doesn't using the built-in Emacs function `locate-dominating-file', as
mentioned in the stackoverflow thread, work just as well as
`find-file-in-heirarchy'?

Steve Berman



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-25 14:45         ` Stephen Berman
@ 2021-09-25 15:03           ` Hongyi Zhao
  2021-09-28  3:08             ` Hongyi Zhao
  0 siblings, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-25 15:03 UTC (permalink / raw)
  To: Stephen Berman; +Cc: help-gnu-emacs

On Sat, Sep 25, 2021 at 10:45 PM Stephen Berman <stephen.berman@gmx.net> wrote:
>
> On Sat, 25 Sep 2021 21:49:38 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> [...]
> > But the actual demand exceeds the simple processing above, I mean, the
> > real project maybe located under a specific folder with multiple level
> > subdirectories. In this case, when I open a python file, the function
> > should do the following: Search the current directory and its parent
> > directories at all levels in turn. Once the ".python-version" file is
> > found, activate the corresponding environment and exit the cycle;
> > Otherwise, continue to search upwards until the  certain top level
> > directory, say, $HOME. Based on the above requirements and the code
> > snippets given here [1-2], I finally figured out the following
> > solution:
> >
> > -------
> > (defun parent-directory (dir)
> >   (unless (equal (getenv "HOME") dir)
> >     ;file-truename or directory-file-name
> >     (file-name-directory (directory-file-name dir))))
> >
> >
> > (defun find-file-in-heirarchy (current-dir fname)
> >   "Search for a file named FNAME upwards through the directory
> > hierarchy, starting from CURRENT-DIR"
> >   (let ((file (concat current-dir fname))
> >         (parent (parent-directory (expand-file-name current-dir))))
> >     (if (file-exists-p file)
> >         file
> >       (when parent
> >         (find-file-in-heirarchy parent fname)))))
> >
> >
> > (defun try/pyvenv-workon ()
> >   (when (buffer-file-name)
> >       (let ((file (find-file-in-heirarchy (buffer-file-name)
> > ".python-version")))
> >         (when (file-exists-p file)
> >           (pyvenv-workon (with-temp-buffer
> >                            (insert-file-contents file)
> >                              (nth 0 (split-string
> > (buffer-string)))))))))
> >
> > (add-hook 'python-mode-hook 'try/pyvenv-workon)
> > -------
> >
> > It works like a charm. But any suggestions/enhancements/comments will
> > be greatly appreciated.
> >
> > [1] https://stackoverflow.com/a/14096693  (*)
> > [2] http://sodaware.sdf.org/notes/emacs-lisp-find-file-upwards/
> >
> > * Indicated that this is my main reference source code.
>
> Doesn't using the built-in Emacs function `locate-dominating-file', as
> mentioned in the stackoverflow thread, work just as well as
> `find-file-in-heirarchy'?

According to my current test, it can indeed work very well. But I
don't know if there are edge cases which this solution doesn't treated
correctly. The built-in Emacs function `locate-dominating-file' relies
on several other predefined functions, and It has been tested and
iterated a lot. So, maybe it's more robust.

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-25  1:29   ` Hongyi Zhao
@ 2021-09-25 23:42     ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 0 replies; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-25 23:42 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

>> Indeed, inside a `let*', a variable is used in a function that
>> expects a string. However either the variable is set to nil,
>> or it isn't set at all. nil isn't a string so the function
>> cannot operate, thus the error.
>
> How to fix it or use a more robust method?

Send a string, not nil.

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-25 15:03           ` Hongyi Zhao
@ 2021-09-28  3:08             ` Hongyi Zhao
  2021-09-28  3:21               ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-28  8:02               ` Yuri Khan
  0 siblings, 2 replies; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-28  3:08 UTC (permalink / raw)
  To: Stephen Berman; +Cc: help-gnu-emacs

On Sat, Sep 25, 2021 at 11:03 PM Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> On Sat, Sep 25, 2021 at 10:45 PM Stephen Berman <stephen.berman@gmx.net> wrote:
> >
> > On Sat, 25 Sep 2021 21:49:38 +0800 Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
> >
> > [...]
> > > But the actual demand exceeds the simple processing above, I mean, the
> > > real project maybe located under a specific folder with multiple level
> > > subdirectories. In this case, when I open a python file, the function
> > > should do the following: Search the current directory and its parent
> > > directories at all levels in turn. Once the ".python-version" file is
> > > found, activate the corresponding environment and exit the cycle;
> > > Otherwise, continue to search upwards until the  certain top level
> > > directory, say, $HOME. Based on the above requirements and the code
> > > snippets given here [1-2], I finally figured out the following
> > > solution:
> > >
> > > -------
> > > (defun parent-directory (dir)
> > >   (unless (equal (getenv "HOME") dir)
> > >     ;file-truename or directory-file-name
> > >     (file-name-directory (directory-file-name dir))))
> > >
> > >
> > > (defun find-file-in-heirarchy (current-dir fname)
> > >   "Search for a file named FNAME upwards through the directory
> > > hierarchy, starting from CURRENT-DIR"
> > >   (let ((file (concat current-dir fname))
> > >         (parent (parent-directory (expand-file-name current-dir))))
> > >     (if (file-exists-p file)
> > >         file
> > >       (when parent
> > >         (find-file-in-heirarchy parent fname)))))
> > >
> > >
> > > (defun try/pyvenv-workon ()
> > >   (when (buffer-file-name)
> > >       (let ((file (find-file-in-heirarchy (buffer-file-name)
> > > ".python-version")))
> > >         (when (file-exists-p file)
> > >           (pyvenv-workon (with-temp-buffer
> > >                            (insert-file-contents file)
> > >                              (nth 0 (split-string
> > > (buffer-string)))))))))
> > >
> > > (add-hook 'python-mode-hook 'try/pyvenv-workon)
> > > -------
> > >
> > > It works like a charm. But any suggestions/enhancements/comments will
> > > be greatly appreciated.
> > >
> > > [1] https://stackoverflow.com/a/14096693  (*)
> > > [2] http://sodaware.sdf.org/notes/emacs-lisp-find-file-upwards/
> > >
> > > * Indicated that this is my main reference source code.
> >
> > Doesn't using the built-in Emacs function `locate-dominating-file', as
> > mentioned in the stackoverflow thread, work just as well as
> > `find-file-in-heirarchy'?
>
> According to my current test, it can indeed work very well. But I
> don't know if there are edge cases which this solution doesn't treated
> correctly. The built-in Emacs function `locate-dominating-file' relies
> on several other predefined functions, and It has been tested and
> iterated a lot. So, maybe it's more robust.

Now I'm trying another test code snippet based on the idea posted here [1]:

(defun desperately-pyvenv-workon()
 "Traveling up the path, find a `.python-version' and activate the
 corresponding virtualenv."
 (interactive)
 (with-temp-buffer
    (unless (equal(getenv "HOME") default-directory)
    (while (not (file-exists-p ".python-version"))
          (cd "..")
    ))
    (when(file-exists-p ".python-version")
      (message(expand-file-name ".python-version")))))

(desperately-pyvenv-workon)


[1] https://emacs.stackexchange.com/a/7477

But when I test the above code in scratch buffer, it seems to be stuck
in an endless loop and running there all the time. Any hints for this
problem?

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-28  3:08             ` Hongyi Zhao
@ 2021-09-28  3:21               ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-28  3:24                 ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-28  5:25                 ` Hongyi Zhao
  2021-09-28  8:02               ` Yuri Khan
  1 sibling, 2 replies; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-28  3:21 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

> Now I'm trying another test code snippet based on the idea
> posted here [1]:
>
> (defun desperately-pyvenv-workon()
>  "Traveling up the path, find a `.python-version' and activate the
>  corresponding virtualenv."
>  (interactive)
>  (with-temp-buffer
>     (unless (equal(getenv "HOME") default-directory)
>     (while (not (file-exists-p ".python-version"))
>           (cd "..")
>     ))
>     (when(file-exists-p ".python-version")
>       (message(expand-file-name ".python-version")))))
>
> (desperately-pyvenv-workon)
>
> [1] https://emacs.stackexchange.com/a/7477
>
> But when I test the above code in scratch buffer, it seems to be stuck
> in an endless loop and running there all the time.

Eval this

  (cd "..")

enough times and it alternates between "/" and "/../"
indefinitely, maybe that's what happens?

(But I don't know why, or what it tries to say with "/../"
which should be equivalent to "/" ... in the shell, cd from /
does not lead to /../ but will stay in /)

Also, if you are just looking for a file, isn't there better
ways to do that?

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-28  3:21               ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-28  3:24                 ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-28  5:25                 ` Hongyi Zhao
  1 sibling, 0 replies; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-28  3:24 UTC (permalink / raw)
  To: help-gnu-emacs

> Also, if you are just looking for a file, isn't there better
> ways to do that?

https://www.emacswiki.org/emacs/LocateFilesAnywhere

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-28  3:21               ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-28  3:24                 ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-28  5:25                 ` Hongyi Zhao
  2021-09-28  7:20                   ` Emanuel Berg via Users list for the GNU Emacs text editor
  1 sibling, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-28  5:25 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

On Tue, Sep 28, 2021 at 11:22 AM Emanuel Berg via Users list for the
GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote:
>
> Hongyi Zhao wrote:
>
> > Now I'm trying another test code snippet based on the idea
> > posted here [1]:
> >
> > (defun desperately-pyvenv-workon()
> >  "Traveling up the path, find a `.python-version' and activate the
> >  corresponding virtualenv."
> >  (interactive)
> >  (with-temp-buffer
> >     (unless (equal(getenv "HOME") default-directory)
> >     (while (not (file-exists-p ".python-version"))
> >           (cd "..")
> >     ))
> >     (when(file-exists-p ".python-version")
> >       (message(expand-file-name ".python-version")))))
> >
> > (desperately-pyvenv-workon)
> >
> > [1] https://emacs.stackexchange.com/a/7477
> >
> > But when I test the above code in scratch buffer, it seems to be stuck
> > in an endless loop and running there all the time.
>
> Eval this
>
>   (cd "..")
>
> enough times and it alternates between "/" and "/../"
> indefinitely, maybe that's what happens?
>
> (But I don't know why, or what it tries to say with "/../"
> which should be equivalent to "/" ... in the shell, cd from /
> does not lead to /../ but will stay in /)

They are really equivalent:

werner@X10DAi-00:/$ realpath -e /../
/
werner@X10DAi-00:/$ realpath -e /
/



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-28  5:25                 ` Hongyi Zhao
@ 2021-09-28  7:20                   ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 0 replies; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-28  7:20 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

>> Eval this
>>
>>   (cd "..")
>>
>> enough times and it alternates between "/" and "/../"
>> indefinitely, maybe that's what happens?
>>
>> (But I don't know why, or what it tries to say with "/../"
>> which should be equivalent to "/" ... in the shell, cd from /
>> does not lead to /../ but will stay in /)
>
> They are really equivalent:
>
> werner@X10DAi-00:/$ realpath -e /../
> /
> werner@X10DAi-00:/$ realpath -e /
> /

Yeah, looks like a bug this. Harmless and technically not
incorrect perhaps but suboptimal/confusing, especially the
alternating back and forth.

(cd "..") at / should be a no-op that returns "/" IMO.

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-28  3:08             ` Hongyi Zhao
  2021-09-28  3:21               ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-28  8:02               ` Yuri Khan
  2021-09-28  8:24                 ` Hongyi Zhao
  2021-09-29  1:43                 ` Hongyi Zhao
  1 sibling, 2 replies; 35+ messages in thread
From: Yuri Khan @ 2021-09-28  8:02 UTC (permalink / raw)
  To: Hongyi Zhao; +Cc: help-gnu-emacs, Stephen Berman

On Tue, 28 Sept 2021 at 10:08, Hongyi Zhao <hongyi.zhao@gmail.com> wrote:

> Now I'm trying another test code snippet based on the idea posted here [1]:
>
>     (while (not (file-exists-p ".python-version"))
>           (cd "..")
>     ))
>
> But when I test the above code in scratch buffer, it seems to be stuck
> in an endless loop and running there all the time. Any hints for this
> problem?

You’re not handling the case here that you reached the root directory
without finding a .python-version file.

You will really get better results if you use locate-dominating-file.
If you’re trying to learn, learn by reading that function. As a bonus,
it does not mess with the buffer’s default directory.



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-28  8:02               ` Yuri Khan
@ 2021-09-28  8:24                 ` Hongyi Zhao
  2021-09-29  1:43                 ` Hongyi Zhao
  1 sibling, 0 replies; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-28  8:24 UTC (permalink / raw)
  To: Yuri Khan; +Cc: help-gnu-emacs, Stephen Berman

On Tue, Sep 28, 2021 at 4:02 PM Yuri Khan <yuri.v.khan@gmail.com> wrote:
>
> On Tue, 28 Sept 2021 at 10:08, Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> > Now I'm trying another test code snippet based on the idea posted here [1]:
> >
> >     (while (not (file-exists-p ".python-version"))
> >           (cd "..")
> >     ))
> >
> > But when I test the above code in scratch buffer, it seems to be stuck
> > in an endless loop and running there all the time. Any hints for this
> > problem?
>
> You’re not handling the case here that you reached the root directory
> without finding a .python-version file.
>
> You will really get better results if you use locate-dominating-file.
> If you’re trying to learn, learn by reading that function. As a bonus,
> it does not mess with the buffer’s default directory.

Thanks for the tip! I will give up further attempts on this path. If
available, I will first try to use and learn by reading the source
code of the Emacs built-in functions.

Best, HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-28  8:02               ` Yuri Khan
  2021-09-28  8:24                 ` Hongyi Zhao
@ 2021-09-29  1:43                 ` Hongyi Zhao
  2021-09-29  2:03                   ` Hongyi Zhao
  2021-09-29  4:35                   ` Emanuel Berg via Users list for the GNU Emacs text editor
  1 sibling, 2 replies; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29  1:43 UTC (permalink / raw)
  To: Yuri Khan; +Cc: help-gnu-emacs, Stephen Berman

On Tue, Sep 28, 2021 at 4:02 PM Yuri Khan <yuri.v.khan@gmail.com> wrote:
>
> On Tue, 28 Sept 2021 at 10:08, Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> > Now I'm trying another test code snippet based on the idea posted here [1]:
> >
> >     (while (not (file-exists-p ".python-version"))
> >           (cd "..")
> >     ))
> >
> > But when I test the above code in scratch buffer, it seems to be stuck
> > in an endless loop and running there all the time. Any hints for this
> > problem?
>
> You’re not handling the case here that you reached the root directory
> without finding a .python-version file.
>
> You will really get better results if you use locate-dominating-file.
> If you’re trying to learn, learn by reading that function. As a bonus,
> it does not mess with the buffer’s default directory.

I work out the following code snippets using locate-dominating-file,
and it works as expected:

(defun try/pyvenv-workon ()
  (when (locate-dominating-file (buffer-file-name) ".python-version")
      ;https://emacs.stackexchange.com/questions/9474/let-statement-throws-error-on-assigning-a-form-to-a-variable
      (let ((file (concat (locate-dominating-file (buffer-file-name)
".python-version") ".python-version")))
           (pyvenv-workon (with-temp-buffer
                           (insert-file-contents file)
                             (nth 0 (split-string (buffer-string))))))))


BTW, should I use `let' or `let*' here?

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  1:43                 ` Hongyi Zhao
@ 2021-09-29  2:03                   ` Hongyi Zhao
  2021-09-29  3:02                     ` Hongyi Zhao
  2021-09-29  4:35                   ` Emanuel Berg via Users list for the GNU Emacs text editor
  1 sibling, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29  2:03 UTC (permalink / raw)
  To: Yuri Khan; +Cc: help-gnu-emacs, Stephen Berman

On Wed, Sep 29, 2021 at 9:43 AM Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> On Tue, Sep 28, 2021 at 4:02 PM Yuri Khan <yuri.v.khan@gmail.com> wrote:
> >
> > On Tue, 28 Sept 2021 at 10:08, Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
> >
> > > Now I'm trying another test code snippet based on the idea posted here [1]:
> > >
> > >     (while (not (file-exists-p ".python-version"))
> > >           (cd "..")
> > >     ))
> > >
> > > But when I test the above code in scratch buffer, it seems to be stuck
> > > in an endless loop and running there all the time. Any hints for this
> > > problem?
> >
> > You’re not handling the case here that you reached the root directory
> > without finding a .python-version file.
> >
> > You will really get better results if you use locate-dominating-file.
> > If you’re trying to learn, learn by reading that function. As a bonus,
> > it does not mess with the buffer’s default directory.
>
> I work out the following code snippets using locate-dominating-file,
> and it works as expected:
>
> (defun try/pyvenv-workon ()
>   (when (locate-dominating-file (buffer-file-name) ".python-version")

The following form should be used here:

(when (and (buffer-file-name) (locate-dominating-file
(buffer-file-name) ".python-version"))

>       ;https://emacs.stackexchange.com/questions/9474/let-statement-throws-error-on-assigning-a-form-to-a-variable
>       (let ((file (concat (locate-dominating-file (buffer-file-name)
> ".python-version") ".python-version")))
>            (pyvenv-workon (with-temp-buffer
>                            (insert-file-contents file)
>                              (nth 0 (split-string (buffer-string))))))))
>
>
> BTW, should I use `let' or `let*' here?
>
> HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  2:03                   ` Hongyi Zhao
@ 2021-09-29  3:02                     ` Hongyi Zhao
  2021-09-29  3:57                       ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29  3:02 UTC (permalink / raw)
  To: Yuri Khan; +Cc: help-gnu-emacs, Stephen Berman

On Wed, Sep 29, 2021 at 10:03 AM Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> On Wed, Sep 29, 2021 at 9:43 AM Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
> >
> > On Tue, Sep 28, 2021 at 4:02 PM Yuri Khan <yuri.v.khan@gmail.com> wrote:
> > >
> > > On Tue, 28 Sept 2021 at 10:08, Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
> > >
> > > > Now I'm trying another test code snippet based on the idea posted here [1]:
> > > >
> > > >     (while (not (file-exists-p ".python-version"))
> > > >           (cd "..")
> > > >     ))
> > > >
> > > > But when I test the above code in scratch buffer, it seems to be stuck
> > > > in an endless loop and running there all the time. Any hints for this
> > > > problem?
> > >
> > > You’re not handling the case here that you reached the root directory
> > > without finding a .python-version file.
> > >
> > > You will really get better results if you use locate-dominating-file.
> > > If you’re trying to learn, learn by reading that function. As a bonus,
> > > it does not mess with the buffer’s default directory.
> >
> > I work out the following code snippets using locate-dominating-file,
> > and it works as expected:
> >
> > (defun try/pyvenv-workon ()
> >   (when (locate-dominating-file (buffer-file-name) ".python-version")
>
> The following form should be used here:
>
> (when (and (buffer-file-name) (locate-dominating-file
> (buffer-file-name) ".python-version"))
>
> >       ;https://emacs.stackexchange.com/questions/9474/let-statement-throws-error-on-assigning-a-form-to-a-variable
> >       (let ((file (concat (locate-dominating-file (buffer-file-name)
> > ".python-version") ".python-version")))
> >            (pyvenv-workon (with-temp-buffer
> >                            (insert-file-contents file)
> >                              (nth 0 (split-string (buffer-string))))))))

The complete code for this purpose is as following now:

  (defun try/pyvenv-workon ()
    (when (and (buffer-file-name)
               (locate-dominating-file (buffer-file-name) ".python-version"))
      (let ((file (concat (locate-dominating-file (buffer-file-name)
".python-version") ".python-version")))
        (pyvenv-workon
          (with-temp-buffer
            (insert-file-contents file)
            (nth 0 (split-string (buffer-string))))))))

But I wonder if I can solve this problem by using
`locate-dominating-file' only once?

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  3:02                     ` Hongyi Zhao
@ 2021-09-29  3:57                       ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-29  6:15                         ` Hongyi Zhao
  0 siblings, 1 reply; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-29  3:57 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

>   (defun try/pyvenv-workon ()
>     (when (and (buffer-file-name)
>                (locate-dominating-file (buffer-file-name) ".python-version"))
>       (let ((file (concat (locate-dominating-file (buffer-file-name)
> ".python-version") ".python-version")))
>         (pyvenv-workon
>           (with-temp-buffer
>             (insert-file-contents file)
>             (nth 0 (split-string (buffer-string))))))))

Use `let' so you don't have to hard-code the same data three
times.

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  1:43                 ` Hongyi Zhao
  2021-09-29  2:03                   ` Hongyi Zhao
@ 2021-09-29  4:35                   ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-29  6:17                     ` Hongyi Zhao
  1 sibling, 1 reply; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-29  4:35 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

> (defun try/pyvenv-workon ()
>   (when (locate-dominating-file (buffer-file-name) ".python-version")
>       ;https://emacs.stackexchange.com/questions/9474/let-statement-throws-error-on-assigning-a-form-to-a-variable
>       (let ((file (concat (locate-dominating-file (buffer-file-name)
> ".python-version") ".python-version")))
>            (pyvenv-workon (with-temp-buffer
>                            (insert-file-contents file)
>                              (nth 0 (split-string (buffer-string))))))))
>
> BTW, should I use `let' or `let*' here?

`let*' always works, `let' works when there is no references
to previous bindings in any binding...

So if it works and you have let, you have done the
right thing!

In theory, because of the independence of the individual
bindings with let, it can be used to compute in parallel - but
I don't think that actually happens - an urban legend ...

In your code you only have "file" so while both would work,
let* is unnecessary ...

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  3:57                       ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-29  6:15                         ` Hongyi Zhao
  2021-09-29  6:29                           ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29  6:15 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

On Wed, Sep 29, 2021 at 11:58 AM Emanuel Berg via Users list for the
GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote:
>
> Hongyi Zhao wrote:
>
> >   (defun try/pyvenv-workon ()
> >     (when (and (buffer-file-name)
> >                (locate-dominating-file (buffer-file-name) ".python-version"))
> >       (let ((file (concat (locate-dominating-file (buffer-file-name)
> > ".python-version") ".python-version")))
> >         (pyvenv-workon
> >           (with-temp-buffer
> >             (insert-file-contents file)
> >             (nth 0 (split-string (buffer-string))))))))
>
> Use `let' so you don't have to hard-code the same data three
> times.

The code I’ve modified looks like this:

  (defun try/pyvenv-workon ()
    (when (buffer-file-name)
      (let ((file (concat (locate-dominating-file (buffer-file-name)
".python-version") ".python-version")))
        (when (file-exists-p file)
          (pyvenv-workon
            (with-temp-buffer
              (insert-file-contents file)
              (nth 0 (split-string (buffer-string)))))))))

Any further improvement tips?

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  4:35                   ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-29  6:17                     ` Hongyi Zhao
  0 siblings, 0 replies; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29  6:17 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

On Wed, Sep 29, 2021 at 12:35 PM Emanuel Berg via Users list for the
GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote:
>
> Hongyi Zhao wrote:
>
> > (defun try/pyvenv-workon ()
> >   (when (locate-dominating-file (buffer-file-name) ".python-version")
> >       ;https://emacs.stackexchange.com/questions/9474/let-statement-throws-error-on-assigning-a-form-to-a-variable
> >       (let ((file (concat (locate-dominating-file (buffer-file-name)
> > ".python-version") ".python-version")))
> >            (pyvenv-workon (with-temp-buffer
> >                            (insert-file-contents file)
> >                              (nth 0 (split-string (buffer-string))))))))
> >
> > BTW, should I use `let' or `let*' here?
>
> `let*' always works, `let' works when there is no references
> to previous bindings in any binding...
>
> So if it works and you have let, you have done the
> right thing!
>
> In theory, because of the independence of the individual
> bindings with let, it can be used to compute in parallel - but
> I don't think that actually happens - an urban legend ...
>
> In your code you only have "file" so while both would work,
> let* is unnecessary ...

Wonderful explanation. Got it. Thank you very much again.

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  6:15                         ` Hongyi Zhao
@ 2021-09-29  6:29                           ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-29  7:37                             ` Hongyi Zhao
  2021-09-29  9:14                             ` Yuri Khan
  0 siblings, 2 replies; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-29  6:29 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

> The code I’ve modified looks like this:
>
>   (defun try/pyvenv-workon ()
>     (when (buffer-file-name)
>       (let ((file (concat (locate-dominating-file (buffer-file-name)
> ".python-version") ".python-version")))
>         (when (file-exists-p file)
>           (pyvenv-workon
>             (with-temp-buffer
>               (insert-file-contents file)
>               (nth 0 (split-string (buffer-string)))))))))
>
> Any further improvement tips?

concat -> format

".python-version" hardcoded twice

nth 0 -> car

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  6:29                           ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-29  7:37                             ` Hongyi Zhao
  2021-09-29  8:21                               ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-29  9:14                             ` Yuri Khan
  1 sibling, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29  7:37 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

On Wed, Sep 29, 2021 at 2:29 PM Emanuel Berg via Users list for the
GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote:
> concat -> format
>
> ".python-version" hardcoded twice
>
> nth 0 -> car

Thanks again. Then, is there room for further improvement in the following code?

  (defun try/pyvenv-workon ()
    (when (buffer-file-name)
      (let* ((python-version ".python-version")
             (venvdir (locate-dominating-file (buffer-file-name)
python-version)))
        (when venvdir
          (pyvenv-workon
            (with-temp-buffer
              (insert-file-contents (format "%s%s" venvdir python-version))
              (car (split-string (buffer-string)))))))))

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  7:37                             ` Hongyi Zhao
@ 2021-09-29  8:21                               ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-29  9:02                                 ` Hongyi Zhao
  0 siblings, 1 reply; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-29  8:21 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

> Thanks again. Then, is there room for further improvement in
> the following code?
>
>   (defun try/pyvenv-workon ()
>     (when (buffer-file-name)
>       (let* ((python-version ".python-version")
>              (venvdir (locate-dominating-file (buffer-file-name)
> python-version)))
>         (when venvdir
>           (pyvenv-workon
>             (with-temp-buffer
>               (insert-file-contents (format "%s%s" venvdir python-version))
>               (car (split-string (buffer-string)))))))))

Looks good to me.

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  8:21                               ` Emanuel Berg via Users list for the GNU Emacs text editor
@ 2021-09-29  9:02                                 ` Hongyi Zhao
  0 siblings, 0 replies; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29  9:02 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

On Wed, Sep 29, 2021 at 4:21 PM Emanuel Berg via Users list for the
GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote:
> Looks good to me.

Thank you for your comment and help. In order to be more in line with
the actual situation, I replaced the variable name `venvdir'  with
`project-dir':

  (defun try/pyvenv-workon ()
    (when (buffer-file-name)
      (let* ((python-version ".python-version")
             (project-dir (locate-dominating-file (buffer-file-name)
python-version)))
        (when project-dir
          (pyvenv-workon
            (with-temp-buffer
              (insert-file-contents (format "%s%s" project-dir python-version))
              (car (split-string (buffer-string)))))))))

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  6:29                           ` Emanuel Berg via Users list for the GNU Emacs text editor
  2021-09-29  7:37                             ` Hongyi Zhao
@ 2021-09-29  9:14                             ` Yuri Khan
  2021-09-29 10:29                               ` Hongyi Zhao
  2021-09-30  3:38                               ` Emanuel Berg via Users list for the GNU Emacs text editor
  1 sibling, 2 replies; 35+ messages in thread
From: Yuri Khan @ 2021-09-29  9:14 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

On Wed, 29 Sept 2021 at 13:29, Emanuel Berg via Users list for the GNU
Emacs text editor <help-gnu-emacs@gnu.org> wrote:
> >       (let ((file (concat (locate-dominating-file (buffer-file-name)
> > ".python-version") ".python-version")))

> concat -> format

Why use either, when you have a perfectly good expand-file-name?



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  9:14                             ` Yuri Khan
@ 2021-09-29 10:29                               ` Hongyi Zhao
  2021-09-29 12:29                                 ` Yuri Khan
  2021-09-30  3:38                               ` Emanuel Berg via Users list for the GNU Emacs text editor
  1 sibling, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29 10:29 UTC (permalink / raw)
  To: Yuri Khan; +Cc: help-gnu-emacs, Emanuel Berg

On Wed, Sep 29, 2021 at 5:14 PM Yuri Khan <yuri.v.khan@gmail.com> wrote:
>
> On Wed, 29 Sept 2021 at 13:29, Emanuel Berg via Users list for the GNU
> Emacs text editor <help-gnu-emacs@gnu.org> wrote:
> > >       (let ((file (concat (locate-dominating-file (buffer-file-name)
> > > ".python-version") ".python-version")))
>
> > concat -> format
>
> Why use either, when you have a perfectly good expand-file-name?

Good advice, so change to the following:

  (defun try/pyvenv-workon ()
    (when (buffer-file-name)
      (let* ((python-version ".python-version")
             (project-dir (locate-dominating-file (buffer-file-name)
python-version)))
        (when project-dir
          (pyvenv-workon
            (with-temp-buffer
              (insert-file-contents (expand-file-name python-version))
              (car (split-string (buffer-string)))))))))

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29 10:29                               ` Hongyi Zhao
@ 2021-09-29 12:29                                 ` Yuri Khan
  2021-09-29 12:49                                   ` Hongyi Zhao
  0 siblings, 1 reply; 35+ messages in thread
From: Yuri Khan @ 2021-09-29 12:29 UTC (permalink / raw)
  To: Hongyi Zhao; +Cc: help-gnu-emacs, Emanuel Berg

On Wed, 29 Sept 2021 at 17:29, Hongyi Zhao <hongyi.zhao@gmail.com> wrote:

>   (defun try/pyvenv-workon ()
>     (when (buffer-file-name)
>       (let* ((python-version ".python-version")
>              (project-dir (locate-dominating-file (buffer-file-name)
> python-version)))
>         (when project-dir
>           (pyvenv-workon
>             (with-temp-buffer
>               (insert-file-contents (expand-file-name python-version))

You probably wanted (expand-file-name python-version project-dir) here.

>               (car (split-string (buffer-string)))))))))



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29 12:29                                 ` Yuri Khan
@ 2021-09-29 12:49                                   ` Hongyi Zhao
  2021-10-08  3:36                                     ` Hongyi Zhao
  0 siblings, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-09-29 12:49 UTC (permalink / raw)
  To: Yuri Khan; +Cc: help-gnu-emacs, Emanuel Berg

On Wed, Sep 29, 2021 at 8:30 PM Yuri Khan <yuri.v.khan@gmail.com> wrote:
>
> On Wed, 29 Sept 2021 at 17:29, Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> >   (defun try/pyvenv-workon ()
> >     (when (buffer-file-name)
> >       (let* ((python-version ".python-version")
> >              (project-dir (locate-dominating-file (buffer-file-name)
> > python-version)))
> >         (when project-dir
> >           (pyvenv-workon
> >             (with-temp-buffer
> >               (insert-file-contents (expand-file-name python-version))
>
> You probably wanted (expand-file-name python-version project-dir) here.

Good catch! You're absolutely right. Thanks again for your help.

>
> >               (car (split-string (buffer-string)))))))))



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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29  9:14                             ` Yuri Khan
  2021-09-29 10:29                               ` Hongyi Zhao
@ 2021-09-30  3:38                               ` Emanuel Berg via Users list for the GNU Emacs text editor
  1 sibling, 0 replies; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-09-30  3:38 UTC (permalink / raw)
  To: help-gnu-emacs

Yuri Khan wrote:

>>>       (let ((file (concat (locate-dominating-file (buffer-file-name)
>>> ".python-version") ".python-version")))
>>
>> concat -> format
>
> Why use either, when you have a perfectly good
> expand-file-name?

Right, just looked at the syntax :$

I do that all the time BTW ...

-- 
underground experts united
https://dataswamp.org/~incal




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

* Re: let*: Wrong type argument: stringp, nil
  2021-09-29 12:49                                   ` Hongyi Zhao
@ 2021-10-08  3:36                                     ` Hongyi Zhao
  2021-10-10 14:05                                       ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 1 reply; 35+ messages in thread
From: Hongyi Zhao @ 2021-10-08  3:36 UTC (permalink / raw)
  To: Yuri Khan; +Cc: help-gnu-emacs, Emanuel Berg

On Wed, Sep 29, 2021 at 8:49 PM Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> On Wed, Sep 29, 2021 at 8:30 PM Yuri Khan <yuri.v.khan@gmail.com> wrote:
> >
> > On Wed, 29 Sept 2021 at 17:29, Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
> >
> > >   (defun try/pyvenv-workon ()
> > >     (when (buffer-file-name)
> > >       (let* ((python-version ".python-version")
> > >              (project-dir (locate-dominating-file (buffer-file-name)
> > > python-version)))
> > >         (when project-dir
> > >           (pyvenv-workon
> > >             (with-temp-buffer
> > >               (insert-file-contents (expand-file-name python-version))
> >
> > You probably wanted (expand-file-name python-version project-dir) here.
>
> Good catch! You're absolutely right. Thanks again for your help.
>
> >
> > >               (car (split-string (buffer-string)))))))))

Here is another implementation based on s and f given by pyenv-mode-auto [1]:

(require 's)
(require 'f)
(require 'pyenv-mode)

(defun pyenv-mode-auto-hook ()
"Automatically activates pyenv version if .python-version file exists."
(f-traverse-upwards
(lambda (path)
(let ((pyenv-version-path (f-expand ".python-version" path)))
(if (f-exists? pyenv-version-path)
(progn
(pyenv-mode-set (car (s-lines (s-trim (f-read-text pyenv-version-path
'utf-8)))))
t))))))

(add-hook 'find-file-hook 'pyenv-mode-auto-hook)

(provide 'pyenv-mode-auto)


[1] https://github.com/ssbb/pyenv-mode-auto/blob/347b94cd5ad22e33cc41be661c102d4548767858/pyenv-mode-auto.el#L35-L51

HZ



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

* Re: let*: Wrong type argument: stringp, nil
  2021-10-08  3:36                                     ` Hongyi Zhao
@ 2021-10-10 14:05                                       ` Emanuel Berg via Users list for the GNU Emacs text editor
  0 siblings, 0 replies; 35+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-10-10 14:05 UTC (permalink / raw)
  To: help-gnu-emacs

Hongyi Zhao wrote:

> Here is another implementation based on s and f given by
> pyenv-mode-auto [...]
>
> (require 's)
> (require 'f)

What is that, string and file modules? It usually doesn't look
like that in Lisp.

> (f-exists? [...]

This reminds me of some other Lisp dialect where you'd have an
exclamation mark last if the function hade side-effects.
So maybe a question mark last is their way of doing our `-p'
(or vice versa depending on who was first).

While I don't want to make too big a thing of it, conventions
like these are probably better not to mix. (Ours look better,
also. Less disruptive.)

-- 
underground experts united
https://dataswamp.org/~incal




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

end of thread, other threads:[~2021-10-10 14:05 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-24 14:52 let*: Wrong type argument: stringp, nil Hongyi Zhao
2021-09-24 14:57 ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-25  1:29   ` Hongyi Zhao
2021-09-25 23:42     ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-25 10:09 ` Stephen Berman
2021-09-25 10:45   ` Hongyi Zhao
2021-09-25 11:04     ` Stephen Berman
2021-09-25 13:49       ` Hongyi Zhao
2021-09-25 14:45         ` Stephen Berman
2021-09-25 15:03           ` Hongyi Zhao
2021-09-28  3:08             ` Hongyi Zhao
2021-09-28  3:21               ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-28  3:24                 ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-28  5:25                 ` Hongyi Zhao
2021-09-28  7:20                   ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-28  8:02               ` Yuri Khan
2021-09-28  8:24                 ` Hongyi Zhao
2021-09-29  1:43                 ` Hongyi Zhao
2021-09-29  2:03                   ` Hongyi Zhao
2021-09-29  3:02                     ` Hongyi Zhao
2021-09-29  3:57                       ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-29  6:15                         ` Hongyi Zhao
2021-09-29  6:29                           ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-29  7:37                             ` Hongyi Zhao
2021-09-29  8:21                               ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-29  9:02                                 ` Hongyi Zhao
2021-09-29  9:14                             ` Yuri Khan
2021-09-29 10:29                               ` Hongyi Zhao
2021-09-29 12:29                                 ` Yuri Khan
2021-09-29 12:49                                   ` Hongyi Zhao
2021-10-08  3:36                                     ` Hongyi Zhao
2021-10-10 14:05                                       ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-30  3:38                               ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-29  4:35                   ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-09-29  6:17                     ` Hongyi Zhao

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.