pmacs3/method/buffers.py

209 lines
8.0 KiB
Python

import os, commands, re, tempfile
from subprocess import Popen, PIPE, STDOUT
import buffer, default, dirutil, regex, util, window
from point import Point
from method import Method, Argument, arg
class OpenFile(Method):
'''Open file in a new buffer, or go to file's open buffer'''
args = [arg('filename', dt="path", p="Open File: ", dv=default.path_dirname,
ld=True, h="file to open")]
def _execute(self, w, **vargs):
b = w.application.open_path(vargs['filename'])
SwitchBuffer().execute(w, buffername=b.name())
class OpenAesFile(Method):
'''Open AES encrypted file in a new buffer, or go to file's open buffer'''
args = [arg('filename', dt="path", p="Open AES File: ",
dv=default.path_dirname, h="file to open"),
arg('password', p="Use AES Password: ",
h="the AES password the file was encrypted with")]
def _execute(self, w, **vargs):
b = w.application.open_path(vargs['filename'], 'aes', vargs['password'])
SwitchBuffer().execute(w, buffername=b.name())
return
class ViewBufferParent(Method):
def _execute(self, w, **vargs):
b = w.buffer
if not hasattr(b, 'path'):
w.set_error('Buffer has no path')
elif b.path == '/':
w.set_error("Root directory has no parent")
else:
path = os.path.dirname(b.path)
w.application.methods['open-file'].execute(w, filename=path)
class SwitchBuffer(Method):
'''Switch to a different'''
args = [arg('buffername', dt="buffer", p="Switch To Buffer: ",
dv=default.last_buffer, h="name of the buffer to switch to")]
def _pre_execute(self, w, **vargs):
a = w.application
if len(a.bufferlist.buffers) < 1:
raise Exception, "No other buffers"
def _execute(self, w, **vargs):
name = vargs['buffername']
buf = None
if w.application.has_buffer_name(name):
b = w.application.bufferlist.get_buffer_by_name(name)
w.application.switch_buffer(b)
else:
w.set_error("buffer %r was not found" % name)
class KillBuffer(Method):
'''Close the current buffer'''
force = False
args = [arg('buffername', dt="buffer", p="Kill Buffer: ",
dv=default.current_buffer, h="name of the buffer to kill")]
def _execute(self, w, **vargs):
name = vargs['buffername']
a = w.application
if name not in a.bufferlist.buffer_names:
raise Exception("Buffer %r does not exist" % name)
elif len(a.bufferlist.buffers) == 1:
raise Exception("Can't close only open buffer")
self._to_kill = a.bufferlist.buffer_names[name]
self._old_window = w
if self.force or not self._to_kill.changed():
self._doit()
else:
self._prompt = "Buffer has unsaved changes; kill anyway? "
a.open_mini_buffer(self._prompt, self._callback)
def _doit(self):
a = self._old_window.application
b = self._to_kill
a.close_buffer(b)
def _callback(self, v):
a = self._old_window.application
if v == 'yes':
self._doit()
a.close_mini_buffer()
elif v == 'no':
a.close_mini_buffer()
else:
a.close_mini_buffer()
a.set_error('Please type "yes" or "no"')
class ForceKillBuffer(KillBuffer):
'''Close the current buffer, automatically discarding any changes'''
force=True
class ListBuffers(Method):
'''List all open buffers in a new buffer'''
def _execute(self, w, **vargs):
bl = w.application.bufferlist
bnames = [b.name() for b in bl.buffers]
bnames.sort()
data = '\n'.join(bnames)
w.application.data_buffer("*Buffers*", data, switch_to=True)
class SaveBufferAs(Method):
'''Save the contents of a buffer to the specified path'''
args = [arg('path', dt="path", p="Write file: ", ld=True,
dv=default.current_working_dir, h="new path to use")]
def _execute(self, w, **vargs):
a = w.application
curr_buffer = w.buffer
curr_buffer_name = curr_buffer.name()
data = curr_buffer.make_string()
path = os.path.realpath(os.path.expanduser(vargs['path']))
w.set_error("got %r (%d)" % (path, len(data)))
if a.has_buffer_name(path):
w.set_error("buffer for %r is already open" % path)
return
a.new_file_buffer(path, data, switch_to=True)
a.methods['kill-buffer'].execute(w, buffername=curr_buffer_name)
w.set_error('Wrote %r' % path)
class SaveBuffer(Method):
'''Save the contents of a buffer'''
def _execute(self, w, **vargs):
a = w.application
if not w.buffer.changed():
w.set_error("(No changes need to be saved)")
return
try:
w.buffer.save()
w.set_error("Wrote %s" % (w.buffer.path))
except buffer.FileGoneError, e:
w.buffer.save(force=True)
w.set_error("File had disappeared! Wrote %s" % (w.buffer.path))
except buffer.FileChangedError, e:
self._old_window = w
self._prompt = "File changed on-disk; reload(r), overwrite(o) or diff(d)? "
a.open_mini_buffer(self._prompt, self._callback)
def _callback(self, v):
w = self._old_window
a = w.application
a.close_mini_buffer()
if v in ('reload', 'r'):
a.methods['reload-buffer'].execute(w)
elif v in ('overwrite', 'o'):
a.methods['overwrite-buffer'].execute(w)
elif v in ('diff', 'd'):
path1 = w.buffer.path
tf = tempfile.NamedTemporaryFile(delete=False)
tf.write(w.buffer.make_string())
tf.close()
path2 = tf.name
a.methods['diff'].execute(w, path1=path1, path2=path2)
os.unlink(path2)
w.set_error("File changed on disk; showing differences")
else:
a.open_mini_buffer(self._prompt, self._callback)
a.set_error('Please type reload(r), overwrite(o) or diff(d)')
class ReloadBuffer(Method):
'''Reload the contents of a buffer from the filesystem'''
def _execute(self, w, **vargs):
w.buffer.reload()
w.set_error("Buffer contents reloaded from %r" % w.buffer.path)
class OverwriteBuffer(Method):
'''Unconditionally overwrite path with the contents of the buffer'''
def _execute(self, w, **vargs):
w.buffer.save(force=True)
w.set_error("Wrote %s" % (w.buffer.path))
class ToggleTabs(Method):
'''Toggle whether to write tabs out or not (defaults to false)'''
def _execute(self, w, **vargs):
b = w.buffer
b.writetabs = not b.writetabs
if b.writetabs:
w.set_error("Buffer will save tabs")
else:
w.set_error("Buffer will not save tabs")
class Pwd(Method):
'''Print the buffer's current working directory'''
def _execute(self, w, **vargs):
home = os.getenv('HOME')
if hasattr(w.buffer, 'path'):
cwd = os.path.dirname(w.buffer.path) + '/'
if cwd.startswith(home):
cwd = cwd.replace(home, '~')
w.set_error("Directory %s" % cwd)
else:
w.set_error("Directory %s/" % os.getcwd())
class GetBufferCodec(Method):
'''Print the buffer's current codec'''
def _execute(self, w, **vargs):
w.set_error('Codec is %r' % w.buffer.codec)
class SetBufferCodec(Method):
'''Print the buffer's current codec'''
args = [arg('codec', p="Codec Name: ",
dv=lambda w: w.buffer.codec, h="name of the codec to use")]
def _execute(self, w, **vargs):
codec = vargs['codec']
try:
u''.encode(codec)
except:
w.set_error('%r is not a valid codec' % codec)
return
w.set_error('Reassigning codec to %r' % codec)
u = w.buffer.make_string()
s = u.encode(w.buffer.codec)
w.buffer.codec = codec
u = s.decode(codec)
w.buffer.set_data(u, force=True)