[PATCH] python/thread: always return a string in get_subject/authors

2011-05-09 Thread Anton Khirnov
Now None is returned when those don't exist, which is inconvenient to
deal with.
---
 bindings/python/notmuch/thread.py |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index eebd6cb..cf26957 100644
--- a/bindings/python/notmuch/thread.py
+++ b/bindings/python/notmuch/thread.py
@@ -281,7 +281,8 @@ class Thread(object):
 
 if self._thread is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
-return Thread._get_authors(self._thread)
+ret = Thread._get_authors(self._thread)
+return ret if ret else ''
 
 def get_subject(self):
 Returns the Subject of 'thread'
@@ -291,7 +292,8 @@ class Thread(object):
 
 if self._thread is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
-return Thread._get_subject(self._thread)
+ret = Thread._get_subject(self._thread)
+return ret if ret else ''
 
 def get_newest_date(self):
 Returns time_t of the newest message date
-- 
1.7.4.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] python/thread: always return a string in get_subject/authors

2011-05-09 Thread Anton Khirnov
On Mon, 09 May 2011 09:20:41 -0300, David Bremner da...@tethera.net wrote:
 On Mon,  9 May 2011 09:06:34 +0200, Anton Khirnov an...@khirnov.net wrote:
  Now None is returned when those don't exist, which is inconvenient to
  deal with.
 
 I'm not using the python bindings, but from a philosophical point of
 view, this change makes me a bit uncomfortable since it apparently
 merges two cases together, and makes an error (no Subject)
 indistinguishable from an odd situation (Subject of empty string).
 Or am I missing something here?

The question is whether this is really a problem.

For a single message, it might make sense to distinguish between 'no
header' and 'empty header'.

But those aren't message headers, those are thread properties. And I'd
argue that a thread always has authors and a subject (possibly empty).

--
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH] lib/message-file: plug three memleaks.

2011-05-09 Thread Anton Khirnov
---
 lib/message-file.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/lib/message-file.c b/lib/message-file.c
index 7722832..99505c1 100644
--- a/lib/message-file.c
+++ b/lib/message-file.c
@@ -341,12 +341,17 @@ notmuch_message_file_get_header (notmuch_message_file_t 
*message,
strncpy(combined_header,header_sofar,hdrsofar);
*(combined_header+hdrsofar) = ' ';
strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1);
+   free (decoded_value);
g_hash_table_insert (message-headers, header, combined_header);
}
} else {
if (header_sofar == NULL) {
/* Only insert if we don't have a value for this header, yet. */
g_hash_table_insert (message-headers, header, decoded_value);
+   } else {
+   free (header);
+   free (decoded_value);
+   decoded_value = header_sofar;
}
}
/* if we found a match we can bail - unless of course we are
-- 
1.7.5.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [RFC/PATCH] Vim client rewrite

2011-05-16 Thread Anton Khirnov

On Mon, 16 May 2011 14:36:07 +0300, Felipe Contreras 
felipe.contre...@gmail.com wrote:
 On Sun, May 15, 2011 at 10:15 PM,  an...@khirnov.net wrote:
  my attempts to make the vim client more usable somehow spiraled out of
  control and turned into a huge rewrite. The intermediate results I
  hereby present for your amusement and comments.
  (attached as whole files, since the patch would be unreadable)
 
  The main point of the rewrite is splitting of a large part of the code
  into Python. This should have the following advantages:
  1) python-notmuch bindings can be used, which should allow for cleaner
    and more reliable code than running the binary and parsing its output
    with regexps.
    (also provides a nice use case for python-notmuch)
  2) Python's huge standard library makes implementing some features MUCH 
  easier.
  3) More people know Python than vimscript, thus making the client
    development easier
 
  The code is α quality, but should be close to usable.
  It already has some features not present in the mainline vim client,
  like attachments (viewing and sending, saving to file should be trivial
  to add, will be done when I have some time), better support for unicode
  and more.
 
  Some UI features from the mainline versions that I didn't use were
  removed and customization options are somewhat lacking atm. This is of
  course to be improved later, depending on the responses.
 
  Comments, bugreports and fixes very much welcome.
 
 Do you have a git repo where to fetch these changes? Or can you
 provide a series of patches with 'git format-patch'?
 

Ah right, forgot to mention it.
git://git.khirnov.net/git/notmuch
branch vim.

--
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [RFC] vim plugin rewrite II

2012-01-15 Thread Anton Khirnov

On Sat, 14 Jan 2012 22:15:07 -0400, David Bremner da...@tethera.net wrote:
 On Sat, 14 Jan 2012 08:54:43 +0100, an...@khirnov.net wrote:
  
  The advantages over current vim client are still the following:
  * sending and displaying/saving attachments
  * much better unicode support
  * tag name and search commands completion
  * proper representation of the thread structure
  * easier to extend thanks to python's massive standard library
  
  Please comment.
 
 Hi Anton;
 
 I'm not a vim user, so I probably can't say anything very helpful, but
 it does sound like some nice improvements.  Hopefully one of our vim
 front-end users can comment a bit more.  One thing I wondered about is
 if your version is still completely synchronous, with the resulting
 problems dealing with large (say, more than 1 messages) search
 results?
 

Yes, it's still synchronous. I suppose making it asynchronous shouldn't
be all that hard, i just never found enough time and motivation for that
(it was never a huge problem here).

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [RFC] vim plugin rewrite II

2012-01-16 Thread Anton Khirnov

On Mon, 16 Jan 2012 09:34:59 -0800, Jameson Graef Rollins 
jroll...@finestructure.net wrote:
 On Sun, 15 Jan 2012 16:34:08 +0100, Anton Khirnov an...@khirnov.net wrote:
  Yes, it's still synchronous. I suppose making it asynchronous shouldn't
  be all that hard, i just never found enough time and motivation for that
  (it was never a huge problem here).
 
 My understanding was that vim was not actually capable of loading files
 asynchronously.  That would be very interesting if it was.
 

It should be possible to run the query in a separate python thread which
would write the results into the vim buffer.

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [RFC] vim plugin rewrite II

2012-05-02 Thread Anton Khirnov

Hi,
sorry for the late reply, I see you already reached the same point as
me, except with ruby ;) Yay for competition.

On Thu, 19 Apr 2012 19:36:56 +0300, Felipe Contreras 
felipe.contre...@gmail.com wrote:
 On Wed, Apr 18, 2012 at 5:42 PM, Felipe Contreras
 felipe.contre...@gmail.com wrote:
  On Wed, Apr 18, 2012 at 5:21 PM, Felipe Contreras
  felipe.contre...@gmail.com wrote:
  On Sat, Jan 14, 2012 at 9:54 AM,  an...@khirnov.net wrote:
  branch vim. Simply copy vim/plugin/{nm_vim.py,notmuch-vimpy.vim} to the
  vim plugins dir and vim/syntax/{nm_vimpy*} to the vim syntax dir and run
  :NMVimpy() in vim. You'll need vim with python support and
  python-notmuch bindings.
 
  I gave this a try, copying those files makes vim crash for me.
 
  I probably need to install notmuch's python bindings, but either way
  it shouldn't crash.
 
  All right, with the bindings it works, but if it cannot find the
  database, it crashes too.
 
  And this slows by 5 times the startup time of vim for me:
 
  vim -c 'quit'  0.47s user 0.02s system 99% cpu 0.501 total
  vim -c 'quit'  0.08s user 0.01s system 96% cpu 0.092 total
 
  It is interesting, but I personally I would not use if it's going to
  slow vim for everything else, there must be a way to solve that. Also,
  would be nice if you rebased your branch on top of the latest release.
 
 I fixed the issue this way:
 
 --- notmuch-vimpy.vim 2012-04-18 22:38:16.193358898 +0300
 +++ notmuch-vimpy-mod.vim 2012-04-19 17:07:19.390693437 +0300
 @@ -29,11 +29,7 @@
  finish
  endif
 
 - init the python layer
 -let s:python_path = expand('sfile:p:h')
 -python import sys
 -exec python sys.path += [r' . s:python_path . ']
 -python import vim, nm_vim
 +let s:notmuch_loaded = 1
 
  command! NMVimpy call NMVimpy()
 
 @@ -815,7 +811,11 @@
   --- command handler {{{1
 
  function! NMVimpy()
 -call SIDNM_cmd_folders(g:nm_vimpy_folders)
 + let s:python_path = expand('sfile:p:h')
 + python import sys
 + exec python sys.path += [r' . s:python_path . ']
 + python import vim, nm_vim
 + call SIDNM_cmd_folders(g:nm_vimpy_folders)
  endfunction
 
  Custom foldtext() for show buffers, which indents folds to
 @@ -859,5 +859,3 @@
  python nm_vim.vim_get_tags()
  return prefix . substitute(taglist, \n, \n . prefix, g)
  endfunction
 -
 -let s:notmuch_loaded = 1
 

Thanks, looks good.

 I was seriously considering to concentrate on this plugin instead of
 the current one, but I'm afraid every little error causes a crash,
 even when a subprocess fails (e.g. msmtp), so it's not really usable
 for me. Not to mention that it's really hard to debug, because every
 bug causes a crash, and sometimes I get random crashes with no
 information about what caused it at all.
 
 I am starting to work on a version that uses ruby, and it doesn't seem
 to have these issues, but lets see. I'm still not sure if we should
 depend on ruby/python bindings, maybe there's a way to make them
 optional.
 
 Anyway, if you find a way to improve the crash issues, let me know, so
 far it's the only real issue I see with this plug-in.

That is weird, I'm not getting any crashes here. On any exception in the
python code it prints the backtrace and continues normally. I don't
think I've ever seen it actually crash (not counting my ultimately
unsuccessfull attempts at threading). I wonder what could cause this.

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [ANN] New awesome vim plug-in using Ruby bindings

2012-05-02 Thread Anton Khirnov

On Mon, 23 Apr 2012 04:12:32 +0300, Felipe Contreras 
felipe.contre...@gmail.com wrote:
 Hi,
 
 I've never been particularly happy with the code of the vim plug-in,
 but it sort of did the job, after some fixes, and has been working
 great so far for most of my needs even though it's clearly very rough
 on the edges.
 
 However, I'm recently in need of been able to read HTML mails, and
 just trying to add that code was a nightmare, so I decided to look for
 alternatives, including Anton's Python vim plug-in (which is nice, but
 doesn't have support for that), and even learning emacs, to use what
 most people here use (but it turns out the HTML messages don't work
 correctly there either). I also tried the various mutt+notmuch
 options, and none fit the bill.
 
 So, since I'm a big fan of Ruby, I decided to try my luck writing a
 plug-in from scratch. It took me one weekend, but I'm pretty happy
 with the result. This plug-in has already essentially all the
 functionality of the current one, but it's much, *much* simpler (only
 600) lines of code.
 
 And in addition has many more features:
 
  * Gradual searches; you don't have to wait for the whole search to finish,
sort of like the 'less' command

How did you do that? When I tried to do this in my version, I got hit by
vim not being threadsafe.

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: Vim plugins

2012-08-06 Thread Anton Khirnov

On Mon, 6 Aug 2012 23:29:08 +0100 (BST), Sepp Tannhuber 
sepp.tannhu...@yahoo.de wrote:
 Hi Anton,
 
 thanks for answering. Finally I found it. My next problem is that I have 
 absolutely no idea how to use it.
 I followed the instructions I have found in this mailing list and copied the 
 syntax files into my ~/.vim/syntax
 and the two plugin files into my ~/.vim/plugin folders.
 
 Then I called
     vi -c 'NMVimpy()'
 The result is
     E492: Not an editor command: NMVimpy()
 
 I tried
     vi -c ':nm_vimpy()'
 as well. And vi answers
     No mapping found
 

I invoke it as vim -c :NMVimpy

 Is there a README file or any other kind of documentation for your script?
 

I wish. Patches welcome ;)

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: Vim plugins

2012-08-07 Thread Anton Khirnov

On Tue, 7 Aug 2012 09:35:02 +0100 (BST), Sepp Tannhuber 
sepp.tannhu...@yahoo.de wrote:
 That's strange. I suppose there must be a function called
   NMVimpy
 in one of your scripts. But
   grep -R NMVimpy *
 in your notmuch directory does not find anything. I am completely at a loss.
 

vim/plugin/notmuch-vimpy.vim, line 817

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: Vim plugins

2012-08-10 Thread Anton Khirnov

On Thu, 9 Aug 2012 09:49:19 +0100 (BST), Sepp Tannhuber 
sepp.tannhu...@yahoo.de wrote:
 Dear Anton,
 
 for some reason the file did not exist here. Perhaps I deleted it 
 accidentally. So I cloned the
 repository again. And there it is.
 Now I'm trying if it is useful for me. I changed some code that I can use 
 python-ranger to
 attach files:
 ##
 function! s:NM_compose_attach()
 
 if filereadable('/tmp/chosendir')
 silent !ranger --choosefiles=/tmp/chosenfiles --choosedir=/tmp/chosendir 
 $(cat /tmp/chosendir)
 else
 silent !ranger --choosefiles=/tmp/chosenfiles --choosedir=/tmp/chosendir
 endif
 if filereadable('/tmp/chosenfiles')
 let attachments = readfile('/tmp/chosenfiles')
 call system('rm /tmp/chosenfiles')
 for attach in attachments
 python nm_vim.get_current_buffer().attach(vim.eval('attach'))
 endfor
 call append(10, map(attachments, 'Attach: .escape(v:val, \t\\)'))
 redraw!
 endif
 endfunction
 ##
 It's even possible to mark and attach multiple files at once.
 

Looks useful, but needs more work I think.
First, I think it should be a new function, so there are separate
'attach one file'/'attach multiple files' commands.
Second, using hardcoded filenames would break horribly with multiple
instances of the client running.

 Is it possible suppress the message returned by
     python nm_vim.get_current_buffer()?
  

What message?

 And do you have an idea what's the reason for the following message?
 
 ##
 :call SNR33_NM_folders_show_search('')       Exception in thread Thread-1:  
                               
 Traceback (most recent call last):
   File /usr/lib/python2.7/threading.py, line 551, in __bootstrap_inner
     self.run()
   File /usr/lib/python2.7/threading.py, line 504, in run
     self.__target(*self.__args, **self.__kwargs)
   File /home/sepp/.vim/plugin/nm_vim.py, line 195, in _refresh_thread
     authors, subj, tags)).encode('utf-8')
 UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: 
 ordinal not in range(128)
 ##
 

Should be fixed now.

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH] lib/message-file: plug three memleaks.

2011-04-15 Thread Anton Khirnov
---
 lib/message-file.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/lib/message-file.c b/lib/message-file.c
index 7722832..b7b3286 100644
--- a/lib/message-file.c
+++ b/lib/message-file.c
@@ -341,12 +341,17 @@ notmuch_message_file_get_header (notmuch_message_file_t 
*message,
strncpy(combined_header,header_sofar,hdrsofar);
*(combined_header+hdrsofar) = ' ';
strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1);
+   free(decoded_value);
g_hash_table_insert (message->headers, header, combined_header);
}
} else {
if (header_sofar == NULL) {
/* Only insert if we don't have a value for this header, yet. */
g_hash_table_insert (message->headers, header, decoded_value);
+   } else {
+   free(header);
+   free(decoded_value);
+   decoded_value = header_sofar;
}
}
/* if we found a match we can bail - unless of course we are
-- 
1.7.4.1



[PATCH] lib/message-file: plug three memleaks.

2011-05-09 Thread Anton Khirnov
On Fri, 15 Apr 2011 16:43:58 +0200, Anton Khirnov  wrote:
> ---
>  lib/message-file.c |5 +
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/lib/message-file.c b/lib/message-file.c
> index 7722832..b7b3286 100644
> --- a/lib/message-file.c
> +++ b/lib/message-file.c
> @@ -341,12 +341,17 @@ notmuch_message_file_get_header (notmuch_message_file_t 
> *message,
>   strncpy(combined_header,header_sofar,hdrsofar);
>   *(combined_header+hdrsofar) = ' ';
>   strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1);
> + free(decoded_value);
>   g_hash_table_insert (message->headers, header, combined_header);
>   }
>   } else {
>   if (header_sofar == NULL) {
>   /* Only insert if we don't have a value for this header, yet. */
>   g_hash_table_insert (message->headers, header, decoded_value);
> + } else {
> + free(header);
> + free(decoded_value);
> + decoded_value = header_sofar;
>   }
>   }
>   /* if we found a match we can bail - unless of course we are
> -- 
> 1.7.4.1
> 
> ___
> notmuch mailing list
> notmuch at notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch

ping

--
Anton Khirnov


[PATCH] python/thread: always return a string in get_subject/authors

2011-05-09 Thread Anton Khirnov
Now None is returned when those don't exist, which is inconvenient to
deal with.
---
 bindings/python/notmuch/thread.py |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index eebd6cb..cf26957 100644
--- a/bindings/python/notmuch/thread.py
+++ b/bindings/python/notmuch/thread.py
@@ -281,7 +281,8 @@ class Thread(object):
 """
 if self._thread is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
-return Thread._get_authors(self._thread)
+ret = Thread._get_authors(self._thread)
+return ret if ret else ''

 def get_subject(self):
 """Returns the Subject of 'thread'
@@ -291,7 +292,8 @@ class Thread(object):
 """
 if self._thread is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
-return Thread._get_subject(self._thread)
+ret = Thread._get_subject(self._thread)
+return ret if ret else ''

 def get_newest_date(self):
 """Returns time_t of the newest message date
-- 
1.7.4.4



[PATCH] python/thread: always return a string in get_subject/authors

2011-05-09 Thread Anton Khirnov
On Mon, 09 May 2011 09:20:41 -0300, David Bremner  wrote:
> On Mon,  9 May 2011 09:06:34 +0200, Anton Khirnov  
> wrote:
> > Now None is returned when those don't exist, which is inconvenient to
> > deal with.
> 
> I'm not using the python bindings, but from a philosophical point of
> view, this change makes me a bit uncomfortable since it apparently
> merges two cases together, and makes an error (no Subject)
> indistinguishable from an odd situation (Subject of empty string).
> Or am I missing something here?

The question is whether this is really a problem.

For a single message, it might make sense to distinguish between 'no
header' and 'empty header'.

But those aren't message headers, those are thread properties. And I'd
argue that a thread always has authors and a subject (possibly empty).

--
Anton Khirnov


[PATCH] lib/message-file: plug three memleaks.

2011-05-09 Thread Anton Khirnov
---
 lib/message-file.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/lib/message-file.c b/lib/message-file.c
index 7722832..99505c1 100644
--- a/lib/message-file.c
+++ b/lib/message-file.c
@@ -341,12 +341,17 @@ notmuch_message_file_get_header (notmuch_message_file_t 
*message,
strncpy(combined_header,header_sofar,hdrsofar);
*(combined_header+hdrsofar) = ' ';
strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1);
+   free (decoded_value);
g_hash_table_insert (message->headers, header, combined_header);
}
} else {
if (header_sofar == NULL) {
/* Only insert if we don't have a value for this header, yet. */
g_hash_table_insert (message->headers, header, decoded_value);
+   } else {
+   free (header);
+   free (decoded_value);
+   decoded_value = header_sofar;
}
}
/* if we found a match we can bail - unless of course we are
-- 
1.7.5.1



[RFC/PATCH] Vim client rewrite

2011-05-16 Thread Anton Khirnov

On Mon, 16 May 2011 14:36:07 +0300, Felipe Contreras  wrote:
> On Sun, May 15, 2011 at 10:15 PM,   wrote:
> > my attempts to make the vim client more usable somehow spiraled out of
> > control and turned into a huge rewrite. The intermediate results I
> > hereby present for your amusement and comments.
> > (attached as whole files, since the patch would be unreadable)
> >
> > The main point of the rewrite is splitting of a large part of the code
> > into Python. This should have the following advantages:
> > 1) python-notmuch bindings can be used, which should allow for cleaner
> > ? and more reliable code than running the binary and parsing its output
> > ? with regexps.
> > ? (also provides a nice use case for python-notmuch)
> > 2) Python's huge standard library makes implementing some features MUCH 
> > easier.
> > 3) More people know Python than vimscript, thus making the client
> > ? development easier
> >
> > The code is ? quality, but should be close to usable.
> > It already has some features not present in the mainline vim client,
> > like attachments (viewing and sending, saving to file should be trivial
> > to add, will be done when I have some time), better support for unicode
> > and more.
> >
> > Some UI features from the mainline versions that I didn't use were
> > removed and customization options are somewhat lacking atm. This is of
> > course to be improved later, depending on the responses.
> >
> > Comments, bugreports and fixes very much welcome.
> 
> Do you have a git repo where to fetch these changes? Or can you
> provide a series of patches with 'git format-patch'?
> 

Ah right, forgot to mention it.
git://git.khirnov.net/git/notmuch
branch vim.

--
Anton Khirnov


[RFC] vim plugin rewrite II

2012-01-15 Thread Anton Khirnov

On Sat, 14 Jan 2012 22:15:07 -0400, David Bremner  wrote:
> On Sat, 14 Jan 2012 08:54:43 +0100, anton at khirnov.net wrote:
> > 
> > The advantages over current vim client are still the following:
> > * sending and displaying/saving attachments
> > * much better unicode support
> > * tag name and search commands completion
> > * proper representation of the thread structure
> > * easier to extend thanks to python's massive standard library
> > 
> > Please comment.
> 
> Hi Anton;
> 
> I'm not a vim user, so I probably can't say anything very helpful, but
> it does sound like some nice improvements.  Hopefully one of our vim
> front-end users can comment a bit more.  One thing I wondered about is
> if your version is still completely synchronous, with the resulting
> problems dealing with large (say, more than 1 messages) search
> results?
> 

Yes, it's still synchronous. I suppose making it asynchronous shouldn't
be all that hard, i just never found enough time and motivation for that
(it was never a huge problem here).

-- 
Anton Khirnov


[RFC] vim plugin rewrite II

2012-01-16 Thread Anton Khirnov

On Mon, 16 Jan 2012 09:34:59 -0800, Jameson Graef Rollins  wrote:
> On Sun, 15 Jan 2012 16:34:08 +0100, Anton Khirnov  
> wrote:
> > Yes, it's still synchronous. I suppose making it asynchronous shouldn't
> > be all that hard, i just never found enough time and motivation for that
> > (it was never a huge problem here).
> 
> My understanding was that vim was not actually capable of loading files
> asynchronously.  That would be very interesting if it was.
> 

It should be possible to run the query in a separate python thread which
would write the results into the vim buffer.

-- 
Anton Khirnov


[RFC] vim plugin rewrite II

2012-05-02 Thread Anton Khirnov

Hi,
sorry for the late reply, I see you already reached the same point as
me, except with ruby ;) Yay for competition.

On Thu, 19 Apr 2012 19:36:56 +0300, Felipe Contreras  wrote:
> On Wed, Apr 18, 2012 at 5:42 PM, Felipe Contreras
>  wrote:
> > On Wed, Apr 18, 2012 at 5:21 PM, Felipe Contreras
> >  wrote:
> >> On Sat, Jan 14, 2012 at 9:54 AM, ? wrote:
> >>> branch vim. Simply copy vim/plugin/{nm_vim.py,notmuch-vimpy.vim} to the
> >>> vim plugins dir and vim/syntax/{nm_vimpy*} to the vim syntax dir and run
> >>> :NMVimpy() in vim. You'll need vim with python support and
> >>> python-notmuch bindings.
> >>
> >> I gave this a try, copying those files makes vim crash for me.
> >>
> >> I probably need to install notmuch's python bindings, but either way
> >> it shouldn't crash.
> >
> > All right, with the bindings it works, but if it cannot find the
> > database, it crashes too.
> >
> > And this slows by 5 times the startup time of vim for me:
> >
> > vim -c 'quit' ?0.47s user 0.02s system 99% cpu 0.501 total
> > vim -c 'quit' ?0.08s user 0.01s system 96% cpu 0.092 total
> >
> > It is interesting, but I personally I would not use if it's going to
> > slow vim for everything else, there must be a way to solve that. Also,
> > would be nice if you rebased your branch on top of the latest release.
> 
> I fixed the issue this way:
> 
> --- notmuch-vimpy.vim 2012-04-18 22:38:16.193358898 +0300
> +++ notmuch-vimpy-mod.vim 2012-04-19 17:07:19.390693437 +0300
> @@ -29,11 +29,7 @@
>  finish
>  endif
> 
> -" init the python layer
> -let s:python_path = expand(':p:h')
> -python import sys
> -exec "python sys.path += [r'" . s:python_path . "']"
> -python import vim, nm_vim
> +let s:notmuch_loaded = 1
> 
>  command! NMVimpy call NMVimpy()
> 
> @@ -815,7 +811,11 @@
>  " --- command handler {{{1
> 
>  function! NMVimpy()
> -call NM_cmd_folders(g:nm_vimpy_folders)
> + let s:python_path = expand(':p:h')
> + python import sys
> + exec "python sys.path += [r'" . s:python_path . "']"
> + python import vim, nm_vim
> + call NM_cmd_folders(g:nm_vimpy_folders)
>  endfunction
> 
>  "Custom foldtext() for show buffers, which indents folds to
> @@ -859,5 +859,3 @@
>  python nm_vim.vim_get_tags()
>  return prefix . substitute(taglist, "\n", "\n" . prefix, "g")
>  endfunction
> -
> -let s:notmuch_loaded = 1
> 

Thanks, looks good.

> I was seriously considering to concentrate on this plugin instead of
> the current one, but I'm afraid every little error causes a crash,
> even when a subprocess fails (e.g. msmtp), so it's not really usable
> for me. Not to mention that it's really hard to debug, because every
> bug causes a crash, and sometimes I get random crashes with no
> information about what caused it at all.
> 
> I am starting to work on a version that uses ruby, and it doesn't seem
> to have these issues, but lets see. I'm still not sure if we should
> depend on ruby/python bindings, maybe there's a way to make them
> optional.
> 
> Anyway, if you find a way to improve the crash issues, let me know, so
> far it's the only real issue I see with this plug-in.

That is weird, I'm not getting any crashes here. On any exception in the
python code it prints the backtrace and continues normally. I don't
think I've ever seen it actually crash (not counting my ultimately
unsuccessfull attempts at threading). I wonder what could cause this.

-- 
Anton Khirnov


[ANN] New awesome vim plug-in using Ruby bindings

2012-05-02 Thread Anton Khirnov

On Mon, 23 Apr 2012 04:12:32 +0300, Felipe Contreras  wrote:
> Hi,
> 
> I've never been particularly happy with the code of the vim plug-in,
> but it sort of did the job, after some fixes, and has been working
> great so far for most of my needs even though it's clearly very rough
> on the edges.
> 
> However, I'm recently in need of been able to read HTML mails, and
> just trying to add that code was a nightmare, so I decided to look for
> alternatives, including Anton's Python vim plug-in (which is nice, but
> doesn't have support for that), and even learning emacs, to use what
> most people here use (but it turns out the HTML messages don't work
> correctly there either). I also tried the various mutt+notmuch
> options, and none fit the bill.
> 
> So, since I'm a big fan of Ruby, I decided to try my luck writing a
> plug-in from scratch. It took me one weekend, but I'm pretty happy
> with the result. This plug-in has already essentially all the
> functionality of the current one, but it's much, *much* simpler (only
> 600) lines of code.
> 
> And in addition has many more features:
> 
>  * Gradual searches; you don't have to wait for the whole search to finish,
>sort of like the 'less' command

How did you do that? When I tried to do this in my version, I got hit by
vim not being threadsafe.

-- 
Anton Khirnov


Vim plugins

2012-08-06 Thread Anton Khirnov

Hi,

On Sun, 5 Aug 2012 14:52:44 +0100 (BST), Sepp Tannhuber  wrote:
> Dear all,
> 
> I would like to check the available vim plugins. At least I found three:
> - the original one
> - Felipe's ruby plugin
> - Anton's python plugin
> 
> First of all can you tell me where I find the files of the python plugin?
> I tried
> ? $ git clone git://git.khirnov.net/git/notmuch
> But I cannot find the python files in the vim directory. What am I doing 
> wrong?
> 

you have to checkout the vim branch, then the files are in vim/plugin

I deleted all other branches from my repo now so nobody else gets
confused like this.

-- 
Anton Khirnov


Vim plugins

2012-08-07 Thread Anton Khirnov

On Mon, 6 Aug 2012 23:29:08 +0100 (BST), Sepp Tannhuber  wrote:
> Hi Anton,
> 
> thanks for answering. Finally I found it. My next problem is that I have 
> absolutely no idea how to use it.
> I followed the instructions I have found in this mailing list and copied the 
> syntax files into my ~/.vim/syntax
> and the two plugin files?into my ~/.vim/plugin folders.
> 
> Then I called
> ? ? vi -c 'NMVimpy()'
> The result is
> ? ? E492: Not an editor command: NMVimpy()
> 
> I tried
> ? ? vi -c ':nm_vimpy()'
> as well. And vi answers
> ? ? No mapping found
> 

I invoke it as vim -c :NMVimpy

> Is there a README file or any other kind of documentation for your script?
> 

I wish. Patches welcome ;)

-- 
Anton Khirnov


Vim plugins

2012-08-07 Thread Anton Khirnov

On Tue, 7 Aug 2012 09:35:02 +0100 (BST), Sepp Tannhuber  wrote:
> That's strange. I suppose there must be a function called
> ? NMVimpy
> in one of your scripts. But
> ? grep -R NMVimpy *
> in your notmuch directory does not find anything. I am completely at a loss.
> 

vim/plugin/notmuch-vimpy.vim, line 817

-- 
Anton Khirnov


Vim plugins

2012-08-10 Thread Anton Khirnov

On Thu, 9 Aug 2012 09:49:19 +0100 (BST), Sepp Tannhuber  wrote:
> Dear Anton,
> 
> for some reason the file did not exist here. Perhaps I deleted it 
> accidentally. So I cloned the
> repository again. And there it is.
> Now I'm trying?if it is useful for me. I changed some code that I can use 
> python-ranger to
> attach files:
> ##
> function! s:NM_compose_attach()
> 
> if filereadable('/tmp/chosendir')
> silent !ranger --choosefiles=/tmp/chosenfiles --choosedir=/tmp/chosendir 
> "$(cat /tmp/chosendir)"
> else
> silent !ranger --choosefiles=/tmp/chosenfiles --choosedir=/tmp/chosendir
> endif
> if filereadable('/tmp/chosenfiles')
> let attachments = readfile('/tmp/chosenfiles')
> call system('rm /tmp/chosenfiles')
> for attach in attachments
> python nm_vim.get_current_buffer().attach(vim.eval('attach'))
> endfor
> call append(10, map(attachments, '"Attach: ".escape(v:val," \t\\")'))
> redraw!
> endif
> endfunction
> ##
> It's even possible to mark and attach multiple files at once.
> 

Looks useful, but needs more work I think.
First, I think it should be a new function, so there are separate
'attach one file'/'attach multiple files' commands.
Second, using hardcoded filenames would break horribly with multiple
instances of the client running.

> Is it possible suppress the message returned by
> ? ? python nm_vim.get_current_buffer()?
> ?

What message?

> And do you have?an idea?what's the reason for the following message?
> 
> ##
> :call 33_NM_folders_show_search('') ? ? ? Exception in thread Thread-1: 
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
> Traceback (most recent call last):
> ? File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
> ? ? self.run()
> ? File "/usr/lib/python2.7/threading.py", line 504, in run
> ? ? self.__target(*self.__args, **self.__kwargs)
> ? File "/home/sepp/.vim/plugin/nm_vim.py", line 195, in _refresh_thread
> ? ? authors, subj, tags)).encode('utf-8')
> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: 
> ordinal not in range(128)
> ##
> 

Should be fixed now.

-- 
Anton Khirnov


status of the new python bindings

2020-05-07 Thread Anton Khirnov
Hi,
I've started tinkering with the "new" Python bindings (python-cffi /
python-notmuch2) and have a couple questions/comments about them:

1) What is the logic behind choosing whether something is exported as
a property or as a method? E.g. Database.needs_upgrade is a property,
while Database.revision() is a method. In my own python code, I tend to
use @property for things that are "cheap" - i.e. do not involve
(significant) IO or heavy computation and methods for those that do. But
both of the above attributes involve library calls, presumably(?) of
similar complexity. Would be nice if this was consistent.

2) Atomic transactions are now exported as a context manager, which is
nice and convenient for the usual use cases, but AFAIU does not have the
same power. E.g. my tagging script does the tagging as a single atomic
transaction and has a "dry-run" mode in which it omits the end_atomic()
call, which is documented to throw away all the changes. This seems to
not be possible with the new bindings.
Would it be okay to add bindings for explicitly calling
start/end_atomic()? Or is my approach considered invalid?

3) There seem to be no bindings for notmuch_database_set_config().

4) The setup for building the documentation seems to be missing.

Anything else of note that remains to be implemented?

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
https://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 1/2] python/notmuch2: do not destroy messages owned by a query

2020-05-08 Thread Anton Khirnov
Any messages retrieved from a query - either directly via
search_messages() or indirectly via thread objects - are owned by that
query. Retrieving the same message (i.e. corresponding to the same
message ID / database object) several times will always yield the same
C object.

The caller is allowed to destroy message objects owned by a query before
the query itself - which can save memory for long-lived queries.
However, that message must then never be retrieved again from that
query.

The python-notmuch2 bindings will currently destroy every message object
in Message._destroy(), which will lead to an invalid free if the same
message is then retrieved again. E.g. the following python program leads
to libtalloc abort()ing:

import notmuch2
db   = notmuch2.Database(mode = notmuch2.Database.MODE.READ_ONLY)
t= next(db.threads('*'))
msgs = list(zip(t.toplevel(), t.toplevel()))
msgs = list(zip(t.toplevel(), t.toplevel()))

Fix this issue by creating a subclass of Message, which is used for
"standalone" message which have to be freed by the caller. Message class
is then used only for messages descended from a query, which do not need
to be freed by the caller.
---
 bindings/python-cffi/notmuch2/_database.py |  6 ++--
 bindings/python-cffi/notmuch2/_message.py  | 42 ++
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/bindings/python-cffi/notmuch2/_database.py 
b/bindings/python-cffi/notmuch2/_database.py
index 95f59ca0..f14eac78 100644
--- a/bindings/python-cffi/notmuch2/_database.py
+++ b/bindings/python-cffi/notmuch2/_database.py
@@ -399,7 +399,7 @@ class Database(base.NotmuchObject):
   capi.lib.NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID]
 if ret not in ok:
 raise errors.NotmuchError(ret)
-msg = message.Message(self, msg_pp[0], db=self)
+msg = message.StandaloneMessage(self, msg_pp[0], db=self)
 if sync_flags:
 msg.tags.from_maildir_flags()
 return self.AddedMessage(
@@ -468,7 +468,7 @@ class Database(base.NotmuchObject):
 msg_p = msg_pp[0]
 if msg_p == capi.ffi.NULL:
 raise LookupError
-msg = message.Message(self, msg_p, db=self)
+msg = message.StandaloneMessage(self, msg_p, db=self)
 return msg
 
 def get(self, filename):
@@ -501,7 +501,7 @@ class Database(base.NotmuchObject):
 msg_p = msg_pp[0]
 if msg_p == capi.ffi.NULL:
 raise LookupError
-msg = message.Message(self, msg_p, db=self)
+msg = message.StandaloneMessage(self, msg_p, db=self)
 return msg
 
 @property
diff --git a/bindings/python-cffi/notmuch2/_message.py 
b/bindings/python-cffi/notmuch2/_message.py
index c5fdbf6d..416ce7ca 100644
--- a/bindings/python-cffi/notmuch2/_message.py
+++ b/bindings/python-cffi/notmuch2/_message.py
@@ -14,7 +14,7 @@ __all__ = ['Message']
 
 
 class Message(base.NotmuchObject):
-"""An email message stored in the notmuch database.
+"""An email message stored in the notmuch database retrieved via a query.
 
 This should not be directly created, instead it will be returned
 by calling methods on :class:`Database`.  A message keeps a
@@ -61,22 +61,10 @@ class Message(base.NotmuchObject):
 
 @property
 def alive(self):
-if not self._parent.alive:
-return False
-try:
-self._msg_p
-except errors.ObjectDestroyedError:
-return False
-else:
-return True
-
-def __del__(self):
-self._destroy()
+return self._parent.alive
 
 def _destroy(self):
-if self.alive:
-capi.lib.notmuch_message_destroy(self._msg_p)
-self._msg_p = None
+pass
 
 @property
 def messageid(self):
@@ -375,6 +363,30 @@ class Message(base.NotmuchObject):
 if isinstance(other, self.__class__):
 return self.messageid == other.messageid
 
+class StandaloneMessage(Message):
+"""An email message stored in the notmuch database.
+
+This subclass of Message is used for messages that are retrieved from the
+database directly and are not owned by a query.
+"""
+@property
+def alive(self):
+if not self._parent.alive:
+return False
+try:
+self._msg_p
+except errors.ObjectDestroyedError:
+return False
+else:
+return True
+
+def __del__(self):
+self._destroy()
+
+def _destroy(self):
+if self.alive:
+capi.lib.notmuch_message_destroy(self._msg_p)
+self._msg_p = None
 
 class FilenamesIter(base.NotmuchIter):
 """Iterator for binary filenames objects."""
-- 
2.20.1

___
notmuch mailing list
notmuch@notmuchmail.org
https://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 2/2] python/notmuch2: add bindings for the database config strings

2020-05-08 Thread Anton Khirnov
---
 bindings/python-cffi/notmuch2/_build.py| 17 +
 bindings/python-cffi/notmuch2/_config.py   | 84 ++
 bindings/python-cffi/notmuch2/_database.py | 23 ++
 3 files changed, 124 insertions(+)
 create mode 100644 bindings/python-cffi/notmuch2/_config.py

diff --git a/bindings/python-cffi/notmuch2/_build.py 
b/bindings/python-cffi/notmuch2/_build.py
index 5e1fcac1..f269f2a1 100644
--- a/bindings/python-cffi/notmuch2/_build.py
+++ b/bindings/python-cffi/notmuch2/_build.py
@@ -314,6 +314,23 @@ ffibuilder.cdef(
 notmuch_indexopts_get_decrypt_policy (const notmuch_indexopts_t 
*indexopts);
 void
 notmuch_indexopts_destroy (notmuch_indexopts_t *options);
+
+notmuch_status_t
+notmuch_database_set_config (notmuch_database_t *db, const char *key, 
const char *value);
+notmuch_status_t
+notmuch_database_get_config (notmuch_database_t *db, const char *key, char 
**value);
+notmuch_status_t
+notmuch_database_get_config_list (notmuch_database_t *db, const char 
*prefix, notmuch_config_list_t **out);
+notmuch_bool_t
+notmuch_config_list_valid (notmuch_config_list_t *config_list);
+const char *
+notmuch_config_list_key (notmuch_config_list_t *config_list);
+const char *
+notmuch_config_list_value (notmuch_config_list_t *config_list);
+void
+notmuch_config_list_move_to_next (notmuch_config_list_t *config_list);
+void
+notmuch_config_list_destroy (notmuch_config_list_t *config_list);
 """
 )
 
diff --git a/bindings/python-cffi/notmuch2/_config.py 
b/bindings/python-cffi/notmuch2/_config.py
new file mode 100644
index ..58383c16
--- /dev/null
+++ b/bindings/python-cffi/notmuch2/_config.py
@@ -0,0 +1,84 @@
+import collections.abc
+
+import notmuch2._base as base
+import notmuch2._capi as capi
+import notmuch2._errors as errors
+
+__all__ = ['ConfigMapping']
+
+class ConfigIter(base.NotmuchIter):
+def __init__(self, parent, iter_p):
+super().__init__(
+parent, iter_p,
+fn_destroy=capi.lib.notmuch_config_list_destroy,
+fn_valid=capi.lib.notmuch_config_list_valid,
+fn_get=capi.lib.notmuch_config_list_key,
+fn_next=capi.lib.notmuch_config_list_move_to_next)
+
+def __next__(self):
+item = super().__next__()
+return base.BinString.from_cffi(item)
+
+class ConfigMapping(base.NotmuchObject, collections.abc.MutableMapping):
+"""The config key/value pairs stored in the database.
+
+The entries are exposed as a :class:`collections.abc.MutableMapping` 
object.
+Note that setting a value to an empty string is the same as deleting it.
+
+:param parent: the parent object
+:param ptr_name: the name of the attribute on the parent which will
+   return the memory pointer.  This allows this object to
+   access the pointer via the parent's descriptor and thus
+   trigger :class:`MemoryPointer`'s memory safety.
+"""
+
+def __init__(self, parent, ptr_name):
+self._parent = parent
+self._ptr = lambda: getattr(parent, ptr_name)
+
+@property
+def alive(self):
+return self._parent.alive
+
+def _destroy(self):
+pass
+
+def __getitem__(self, key):
+if isinstance(key, str):
+key = key.encode('utf-8')
+val_pp = capi.ffi.new('char**')
+ret = capi.lib.notmuch_database_get_config(self._ptr(), key, val_pp)
+if ret != capi.lib.NOTMUCH_STATUS_SUCCESS:
+raise errors.NotmuchError(ret)
+if val_pp[0] == "":
+capi.lib.free(val_pp[0])
+raise KeyError
+val = base.BinString.from_cffi(val_pp[0])
+capi.lib.free(val_pp[0])
+return val
+
+def __setitem__(self, key, val):
+if isinstance(key, str):
+key = key.encode('utf-8')
+if isinstance(val, str):
+val = val.encode('utf-8')
+ret = capi.lib.notmuch_database_set_config(self._ptr(), key, val)
+if ret != capi.lib.NOTMUCH_STATUS_SUCCESS:
+raise errors.NotmuchError(ret)
+
+def __delitem__(self, key):
+self[key] = ""
+
+def __iter__(self):
+"""Return an iterator over the config items.
+
+:raises NullPointerError: If the iterator can not be created.
+"""
+configlist_pp = capi.ffi.new('notmuch_config_list_t**')
+ret = capi.lib.notmuch_database_get_config_list(self._ptr(), b'', 
configlist_pp)
+if ret != capi.lib.NOTMUCH_STATUS_SUCCESS:
+raise errors.NotmuchError(ret)
+return ConfigIter(self._parent, configlist_pp[0])
+
+def __len__(self):
+return sum(1 for t in self)
diff --git a/bindings/python-cffi/notmuch2/_database.py 
b/bindings/python-cffi/notmuch2/_database.py
index f14eac78..fc55fea8 100644
--- a/bindings/python-cffi/notmuch2/_database.py
+++ b/bindings/python-cffi/notmuch2/_database.py
@@ -7,6 +7,7 @@ import pathlib
 import weakref
 
 import 

Re: [PATCH 1/2] python/notmuch2: do not destroy messages owned by a query

2020-05-21 Thread Anton Khirnov
ping

-- 
Anton Khirnov
___
notmuch mailing list
notmuch@notmuchmail.org
https://notmuchmail.org/mailman/listinfo/notmuch