Package Pyblio :: Package Cite :: Package WP :: Module LyX
[hide private]
[frames] | no frames]

Source Code for Module Pyblio.Cite.WP.LyX

  1  # This file is part of pybliographer 
  2  #  
  3  # Copyright (C) 1998-2006 Frederic GOBRY 
  4  # Email : gobry@pybliographer.org 
  5  #           
  6  # This program is free software; you can redistribute it and/or 
  7  # modify it under the terms of the GNU General Public License 
  8  # as published by the Free Software Foundation; either version 2  
  9  # of the License, or (at your option) any later version. 
 10  #    
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details.  
 15  #  
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
 19   
 20  """ 
 21  Operations on a running LyX instance. 
 22   
 23  LyX only allows you to insert keys at the current cursor position. 
 24  """ 
 25   
 26  import os, string, select, signal 
 27   
 28  from gettext import gettext as _ 
 29   
 30  from Pyblio.Cite.WP import CommunicationError, OperationError 
 31   
32 -class LyX(object):
33 - def __init__(self, pipe='~/.lyx/lyxpipe'):
34 self.pipe = pipe 35 self.pin = None 36 self.pout = None 37 38 self.buffer = '' 39 return
40
41 - def connect(self):
42 """Establish connection with LyX. 43 44 Common failures are: nonexitent pipe, or LyX not running... 45 """ 46 if self.is_connected(): 47 return 48 49 pin = os.path.expanduser(self.pipe + '.in') 50 pout = os.path.expanduser(self.pipe + '.out') 51 52 def safe_connect(f, mode): 53 try: 54 fd = os.open(f, os.O_NONBLOCK | mode) 55 except OSError, msg: 56 if msg.errno == 6: 57 os.unlink(f) 58 raise CommunicationError(_("pipe %r is not connected to LyX") % f) 59 if msg.errno == 2: 60 raise CommunicationError(_("Cannot find pipe %r") % f) 61 else: 62 raise 63 return fd
64 65 self.pin = safe_connect(pin, os.O_WRONLY) 66 self.pout = safe_connect(pout, os.O_RDONLY) 67 68 self._send('hello', base='LYXSRV') 69 return
70
71 - def is_connected(self):
72 return self.pin is not None
73
74 - def disconnect(self):
75 if self.is_connected(): 76 self._send('bye', base='LYXSRV') 77 self._close() 78 return
79
80 - def cite(self, keys, db):
81 """ Insert the keys in the actual wordprocessor document. Each 82 key contains the actual key and a readable representation for 83 the reference. 84 85 Args: 86 keys: [(Pyblio.Store.Key, str)] 87 db: Pyblio.Store.Database 88 """ 89 if not self.is_connected(): 90 raise OperationError(_("Cannot cite when not connected")) 91 92 # For bibtex databases, we use the actual bibtex key as the 93 # citation key. This allows us to cite with pyblio and 94 # generate the actual bibliography with bibtex. Once we are 95 # able to superceed bibtex totally, we might adopt a more 96 # general scheme. 97 if db.schema.id != 'org.pybliographer/bibtex/0.1': 98 raise OperationError(_("LyX only allows citing from BibTeX")) 99 100 full = [str(db[key]['id'][0]) for (key, plain, extra) in keys] 101 102 self._send('citation-insert:' + ','.join(full)) 103 return
104
105 - def fetch(self):
106 return None
107
108 - def update_keys(self, keymap):
109 return
110
111 - def update_biblio(self):
112 return None
113
114 - def _close(self):
115 os.close(self.pin) 116 os.close(self.pout) 117 self.pin = None 118 self.pout = None 119 return
120
121 - def _send(self, msg, base='LYXCMD'):
122 """Send a command 'msg' to the LyX process. 123 124 Once a client has identified itself, it can issue commands in 125 its own context 'base'. 126 127 Args: 128 msg: string 129 base: string 130 """ 131 raw = msg.encode('latin-1', 'replace') 132 133 try: 134 os.write(self.pin, '%s:pyblio:%s\n' % (base, raw)) 135 except OSError, msg: 136 self._close() 137 raise CommunicationError(_("cannot perform operation (%s)") % msg) 138 139 # This message has no answer 140 if msg == 'bye': 141 return 142 143 answer = None 144 145 while 1: 146 r = select.select([self.pout], [], [], 2) 147 if not r[0]: 148 break 149 self.buffer += os.read(self.pout, 1024) 150 151 if '\n' in self.buffer: 152 answer, self.buffer = self.buffer.split('\n', 1) 153 break 154 155 # if the answer is empty or starts with "ERROR", there is sth 156 # wrong. 157 if not answer: 158 self._close() 159 raise CommunicationError(_("LyX did not answer to our request")) 160 161 parts = answer.split(':') 162 if parts[0] == 'ERROR': 163 raise OperationError(_("LyX rejected the command: %s") % parts[-1]) 164 return
165
166 - def __del__ (self):
167 self.disconnect() 168 return
169