Commits

Iñigo Serna committed a0701cf

PowerCLI: insert stored (from config) or history command (Ctrl-G). Improve load/save handling of new options not present in preferences. Fix bug: only store one copy of the same entry in history.

* lfm/messages.py (EntryLine.manage_keys): PowerCLI: implemented insert
stored (from config) or history command, key shortcut Ctrl-G
* lfm/messages.py (Entry.run):
* lfm/messages.py (DoubleEntry.run):

* lfm/config.py: add PowerCLI stored favs commands
* lfm/config.py: powercli_favs
* lfm/config.py (Config.load):
* lfm/config.py (Config.save):

* lfm/config.py: use ConfigParser instead of SafeConfigParser
* lfm/config.py (Config.load):
* lfm/config.py (Config.load): load default config at start
* lfm/config.py (Config.save): save default config if nothing configured

* lfm/messages.py (EntryLine.manage_keys): use __insert_item instead of select_item
* lfm/messages.py (EntryLine.manage_keys.__select_item): delete unused function

* lfm/messages.py (SelectItem.__init__): accept title
* lfm/messages.py (SelectItem.show):
* lfm/messages.py (EntryLine.manage_keys.__insert_item):
* lfm/messages.py (EntryLine.manage_keys): use title in SelectItem

* lfm/lfm.py (PowerCLI.display): only store one copy of the same entry in history
* lfm/messages.py (Entry.run):
* lfm/messages.py (DoubleEntry.run):

  • Participants
  • Parent commits 734a872

Comments (0)

Files changed (6)

+Mon May 16 15:50:18 201	1  Iñigo Serna  <inigoserna@gmail.com>
+
+	* lfm/messages.py (EntryLine.manage_keys): PowerCLI: implemented insert
+	stored (from config) or history command, key shortcut Ctrl-G
+	* lfm/messages.py (Entry.run):
+	* lfm/messages.py (DoubleEntry.run):
+
+Mon May 16 15:41:56 2011  Iñigo Serna  <inigoserna@gmail.com>
+
+	* lfm/config.py: add PowerCLI stored favs commands
+	* lfm/config.py: powercli_favs
+	* lfm/config.py (Config.load):
+ 	* lfm/config.py (Config.save):
+
+Mon May 16 15:35:49 2011  Iñigo Serna  <inigoserna@gmail.com>
+
+	* lfm/config.py: use ConfigParser instead of SafeConfigParser
+	* lfm/config.py (Config.load):
+	* lfm/config.py (Config.load): load default config at start
+	* lfm/config.py (Config.save): save default config if nothing configured
+
+Mon May 16 02:48:09 2011  Iñigo Serna  <inigoserna@gmail.com>
+
+	* lfm/messages.py (EntryLine.manage_keys): use __insert_item instead of select_item
+	* lfm/messages.py (EntryLine.manage_keys.__select_item): delete unused function
+
+Mon May 16 02:44:31 2011  Iñigo Serna  <inigoserna@gmail.com>
+
+	* lfm/messages.py (SelectItem.__init__): accept title
+	* lfm/messages.py (SelectItem.show):
+	* lfm/messages.py (EntryLine.manage_keys.__insert_item):
+	* lfm/messages.py (EntryLine.manage_keys): use title in SelectItem
+
+Mon May 16 01:19:37 2011  Iñigo Serna  <inigoserna@gmail.com>
+
+	* lfm/lfm.py (PowerCLI.display): only store one copy of the same entry in history
+	* lfm/messages.py (Entry.run):
+	* lfm/messages.py (DoubleEntry.run):
+
 Mon May 16 00:27:24 2011  Iñigo Serna  <inigoserna@gmail.com>
 
 	* lfm/lfm.py (HISTORY_FILE): history file
         - Ctrl-O: insert other pane path at position
         - Ctrl-D, Ctrl-\: insert bookmark at position
         - Ctrl-Y: insert previous path at position
+        - Ctrl-G: insert PowerCLI stored (from config) or history command (only PowerCLI)
 
 + ***SelectItem* window**
     - up, k, K
 ============================================================================
-Last update:	Time-stamp: <2011-05-16 00:33:03 inigo>
+Last update:	Time-stamp: <2011-05-16 15:49:24 inigo>
 ============================================================================
 
-- F11: PowerCLI
-  . Stored commands
-  . History
+- Global Menu:
+  . new option: delete history, file?
+  . bug in regerate programs?
 
 
 General:
 ========
 High Priority:
   + enhancements:
-    - test and improve PowerCLI
     - don't like much how recursive chmod/chown/chgrp currently works
       . split in 2 different features chmod and chown/chgrp ?
     - support for languages with wide chars
 
 Medium Priority:
   + enhancements:
-    - pyview: tail mode:
-      . option -f, document
-      . powercli: |: run as tail -f, substitute run sync by default, document
+    - pyview: use mmap
     - substitute curses.color_pair(X) for COL_XXX
   + ui:
     - speed up cursor movement => curses.panel
       . quick view
       . info view
   + new features:
-    - copy or move to: allow bookmarks: $b1
+    - pyview: tail mode:
+      . option -f, document
+      . powercli: |: run as tail -f, substitute run sync by default, document
     - diff and sync dirs: use filecmp.dircmp or rsync
 
 Low Priority (maybe some day):
     . cli
   . save persistent between sessions => ~/.lfm_history
     . config flag to enable/disable
+- PowerCLI: insert stored (from config) or history command => Ctrl-G
+- preferences: improve load/save handling of new options not present in ~/.lfmrc
 - fixed bugs:
   . pyview:
     . last char is not shown if file size is small
     that break search
   . find: show wrong matches if results contain directories or files with spaces
   . create_link, edit_link: don't show error if canceled
+  . only store one copy of the same entry in history
 
 - DOCS:
   . README FAQ: added information about fuse ssh, ftp and webdav
 
 import os, os.path
 import codecs
-from ConfigParser import SafeConfigParser
+from ConfigParser import ConfigParser
 
 from __init__ import LFM_NAME, sysprogs, g_encoding
 from files import SORTTYPE_byName
               'pdf': ('pdf', 'ps'),
               'ebook': ('epub', 'chm', 'mobi', 'prc', 'azw', 'lit', 'fb2') }
 bookmarks = [u'/'] * 10
+powercli_favs = [u'mv "$f" "{$f.replace(\'\', \'\')}"',
+                 u'pyview "$f" %',
+                 u'find "$d" -name "*" -print0 | xargs --null grep -EHcni "TODO|WARNING|FIXME|BUG"',
+                 u'find "$d" -name "*" -print0 | xargs --null grep -EHcni "TODO|WARNING|FIXME|BUG" >output.txt &',
+                 u'cp $s "$o"',
+                 u'',
+                 u'',
+                 u'',
+                 u'',
+                 u'']
 colors = { 'title': ('yellow', 'blue'),
            'files': ('white', 'black'),
            'current_file': ('blue', 'cyan'),
 
     def __init__(self):
         self.file = os.path.abspath(os.path.expanduser(CONFIG_FILE))
-        self.file_start = '#' * 10 + ' ' + LFM_NAME + ' ' + \
+        self.file_start = u'#' * 10 + ' ' + LFM_NAME + ' ' + \
                           'Configuration File' + ' ' + '#' * 10
         self.progs = {} # make a copy
         for k, v in defaultprogs.items():
         if title and title != self.file_start:
             return -2
         # load config and validate sections
-        cfg = SafeConfigParser()
+        cfg = ConfigParser()
         cfg.read(self.file)
-        for sect in ('Programs', 'File Types', 'Bookmarks', 'Colors',
-                     'Options', 'Misc', 'Confirmations', 'Files'):
+        for sect in ('Programs', 'File Types', 'Bookmarks', 'PowerCLI commands',
+                     'Colors', 'Options', 'Misc', 'Confirmations', 'Files'):
             if not cfg.has_section(sect):
                 print 'Section "%s" does not exist, creating' % sect
                 cfg.add_section(sect)
         # programs
+        self.progs = defaultprogs.copy()
         for typ, prog in cfg.items('Programs'):
             self.progs[typ] = prog
         # file types
+        self.filetypes = filetypes.copy()
         for typ, exts in cfg.items('File Types'):
             lst = [t.strip() for t in exts.split(',')]
             self.filetypes[typ] = tuple(lst)
         # bookmarks
+        self.bookmarks = bookmarks[:]
         for num, path in cfg.items('Bookmarks'):
             try:
                 num = int(num)
                 if os.path.isdir(os.path.expanduser(path)):
                     self.bookmarks[num] = decode(path)
                 elif not path:
-                    self.bookmarks[num] = u'/'
+                    self.bookmarks[num] = bookmarks[num]
                 else:
                     print 'Incorrect directory in bookmark[%d]: %s' % \
                           (num, path)
             else:
                 print 'Bad bookmark number:', num
+        # PowerCLI stored commands
+        self.powercli_favs = powercli_favs[:]
+        for num, cmd in cfg.items('PowerCLI commands'):
+            try:
+                num = int(num)
+            except ValueError:
+                print 'Bad PowerCLI command number:', num
+                continue
+            if 0 <= num <= 9:
+                self.powercli_favs[num] = cmd
+            else:
+                print 'Bad PowerCLI command number:', num
         # colours
+        self.colors = colors.copy()
         for sec, color in cfg.items('Colors'):
             if not self.colors.has_key(sec):
                 print 'Bad object name:', sec
                 (fg, bg) = color.split(' ', 2)
                 self.colors[sec.lower()] = (fg.lower(), bg.lower())
         # options
+        self.options = options.copy()
         for what, val in cfg.items('Options'):
             try:
                 val = int(val)
         if self.options['num_panes'] != 1 or self.options['num_panes'] != 2:
             self.options['num_panes'] = 2
         # misc
+        self.misc = misc.copy()
         for what, val in cfg.items('Misc'):
             if not isinstance(val, str):
                 print 'Bad option value: %s => %s' % (what, val)
                         continue
                     self.misc[what] = val
         # confirmations
+        self.confirmations = confirmations.copy()
         for what, val in cfg.items('Confirmations'):
             try:
                 val = int(val)
                 else:
                     self.confirmations[what] = val
         # File types for color
+        self.files_ext = files_ext.copy()
         for typ, exts in cfg.items('Files'):
             lst = [t.strip() for t in exts.split(',')]
             self.files_ext[typ] = tuple(lst)
         buf = self.file_start + '\n'
         # progs
         buf += '\n[Programs]\n'
-        for k, v in sorted(self.progs.items()):
+        args = self.progs if hasattr(self, 'progs') else defaultprogs
+        for k, v in sorted(args.items()):
             buf += '%s: %s\n' % (k, v)
         # filetypes
         buf += '\n[File Types]\n'
-        for k, vs in sorted(self.filetypes.items()):
+        args = self.filetypes if hasattr(self, 'filetypes') else filetypes
+        for k, vs in sorted(args.items()):
             buf += '%s: %s\n' % (k, ', '.join(vs))
         # bookmarks
         buf += '\n[Bookmarks]\n'
-        for i, b in enumerate(self.bookmarks):
+        args = self.bookmarks if hasattr(self, 'bookmarks') else bookmarks
+        for i, b in enumerate(args):
             buf += '%d: %s\n' % (i, encode(b))
+        # PowerCLI stored commands
+        buf += '\n[PowerCLI commands]\n'
+        args = self.powercli_favs if hasattr(self, 'power_favs') else powercli_favs
+        for i, c in enumerate(args):
+            buf += '%d: %s\n' % (i, encode(c))
         # colours
         buf += '\n[Colors]\n'
-        for k, v in sorted(self.colors.items()):
+        args = self.colors if hasattr(self, 'colors') else colors
+        for k, v in sorted(args.items()):
             buf += '%s: %s %s\n' % (k, v[0], v[1])
         # options
         buf += '\n[Options]\n'
         buf += '# automatic_file_encoding_conversion: never = -1, ask = 0, always = 1\n'
         buf += '# sort:\tNone = 0, byName = 1, byName_rev = 2, bySize = 3,\n'
         buf += '# \tbySize_rev = 4, byDate = 5, byDate_rev = 6\n'
-        for k, v in sorted(self.options.items()):
+        args = self.options if hasattr(self, 'options') else options
+        for k, v in sorted(args.items()):
             buf += '%s: %s\n' % (k, v)
         # misc
         buf += '\n[Misc]\n'
         buf += '# diff_type: context, unified, ndiff\n'
-        for k, v in sorted(self.misc.items()):
+        args = self.misc if hasattr(self, 'misc') else misc
+        for k, v in sorted(args.items()):
             buf += '%s: %s\n' % (k, v)
         # confirmations
         buf += '\n[Confirmations]\n'
-        for k, v in sorted(self.confirmations.items()):
+        args = self.confirmations if hasattr(self, 'confirmations') else confirmations
+        for k, v in sorted(args.items()):
             buf += '%s: %s\n' % (k, v)
         # File types for color
         buf += '\n[Files]\n'
-        for k, vs in sorted(self.files_ext.items()):
+        args = self.files_ext if hasattr(self, 'files_ext') else files_ext
+        for k, vs in sorted(args.items()):
             buf += '%s: %s\n' % (k, ', '.join(vs))
         # write to file
         f = codecs.open(self.file, 'w', encoding=g_encoding)
 # -*- coding: utf-8 -*-
 
 # Copyright (C) 2001-11  Iñigo Serna
-# Time-stamp: <2011-05-16 00:23:14 inigo>
+# Time-stamp: <2011-05-16 01:52:21 inigo>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
             self.execute(cmd, tab)
             if len(messages.history['cli']) >= messages.MAX_HISTORY:
                 messages.history['cli'].remove(messages.history['cli'][0])
+            if messages.history['cli'].count(cmd) >= 1:
+                messages.history['cli'].remove(cmd)
             messages.history['cli'].append(cmd)
 
 
                 pos +=1
             return pos if pos < l  else l
 
-        def __select_item(entries, pos0, cli=False):
+        def __select_item(entries, pos0, title='', cli=False):
             if not entries:
                 curses.beep()
                 return
                     x = x0 + 2
                 if cli:
                     y = app.maxh / 2
-                selected = SelectItem(entries, y+1, x-2).run()
+                selected = SelectItem(entries, y+1, x-2, title=title).run()
                 if cli:
                     app.lpane.display()
                     app.rpane.display()
                 cursor_show2()
                 return selected
 
-        def __insert_item(title, entries):
-            ret = MenuWin(title, entries).run()
-            if ret != -1:
-                if self.cli:
-                    ret = '"' + ret + '"'
-                self.text = self.text[:self.pos] + ret + self.text[self.pos:]
-                self.pos += len(ret)
-            cursor_show2()
-            if self.cli:
-                app.lpane.display()
-                app.rpane.display()
-                return False
-            else:
-                app.display()
-                return True
-
         while True:
             self.show()
             ch = self.entry.getch()
             elif ch == 0x14 and not self.cli:             # Ctrl-T, no CLI
                 if self.with_complete:
                     base, entries = files.complete(self.text, self.panelpath)
-                    selected = __select_item(entries, len(self.text), False)
+                    selected = __select_item(entries, len(self.text), 'Complete', False)
                     if selected is not None and selected != -1:
                         self.text = os.path.join(base, selected)
                         self.pos = len(self.text)
                 if pos0 == 0 or not entries:
                     base = None
                     entries = files.complete_programs(text)
-                selected = __select_item(entries, pos0, True)
+                selected = __select_item(entries, pos0, 'Complete', True)
                 if selected is not None and selected != -1:
                     if base is None: # system program
                         selected += ' '
                     buf = '"' + buf + '"'
                 self.text = self.text[:self.pos] + buf + self.text[self.pos:]
                 self.pos += len(buf)
-            elif ch in (0x04, 0x1C):            # Ctrl-D, Ctrl-\
-                if __insert_item('Select bookmark', app.prefs.bookmarks):
-                    return 0x1C # hack, to update screen
-            elif ch == 0x19:                    # Ctrl-Y
+            elif ch in (0x04, 0x1C):             # Ctrl-D, Ctrl-\
+                selected = __select_item(app.prefs.bookmarks, self.pos, 'Bookmarks', self.cli)
+                if selected is not None and selected != -1:
+                    self.text = self.text[:self.pos] + selected + self.text[self.pos:]
+                    self.pos = len(self.text)
+                return 0x1C # hack, to update screen
+            elif ch == 0x19:                     # Ctrl-Y
                 items = app.act_pane.act_tab.history[::-1]
                 items.extend(app.noact_pane.act_tab.history[::-1])
                 if items:
-                    if __insert_item('Select previous path', items):
-                        return 0x19 # hack, to update screen
+                    selected = __select_item(items, self.pos, 'Previous paths', self.cli)
+                    if selected is not None and selected != -1:
+                        self.text = self.text[:self.pos] + selected + self.text[self.pos:]
+                        self.pos = len(self.text)
+                    return 0x19 # hack, to update screen
+            elif ch == 0x07 and self.cli:        # Ctr-G
+                BOOKMARKS_STR, HISTORY_STR = '----- Stored:  -----', '----- History: -----'
+                entries = [BOOKMARKS_STR]
+                entries.extend([c for c in app.prefs.powercli_favs if c])
+                entries.append(HISTORY_STR)
+                entries.extend(history['cli'][:])
+                selected = __select_item(entries, 0, 'Commands', True)
+                if selected not in (None, -1, '', BOOKMARKS_STR, HISTORY_STR):
+                    self.text, self.pos = selected, len(selected)
+                    return 0x07 # hack, to update screen
             # chars and edit keys
             elif ch == curses.KEY_IC:            # insert
                 self.ins = not self.ins
                     self.active_widget = self.entry
                     self.btns.active = 0
                     cursor_show2()
-            elif ans in (0x14, 0x19, 0x1C):    # Ctrl-T, Ctrl-Y, Ctrl-\
+            elif ans in (0x07, 0x14, 0x19, 0x1C): # Ctrl-G, Ctrl-T, Ctrl-Y, Ctrl-\
                 # this is a hack, we need to return to refresh Entry
                 return [self.entry.text]
             elif ans == 10:              # return values
                     hist = history[self.with_history]
                     if len(hist) >= MAX_HISTORY:
                         hist.remove(hist[0])
+                    if hist.count(self.entry.text) >= 1:
+                        hist.remove(self.entry.text)
                     hist.append(self.entry.text)
         self.pwin.hide()
         return answer
                     self.btns.active = 2
                     cursor_hide()
                     answer = False
-            elif ans in (0x14, 0x19, 0x1C):    # Ctrl-T, Ctrl-Y, Ctrl-\
+            elif ans in (0x07, 0x14, 0x19, 0x1C): # Ctrl-G, Ctrl-T, Ctrl-Y, Ctrl-\
                 # this is a hack, we need to return to refresh Entry
                 return [self.entry1.text, self.entry2.text, self.active_entry_i]
             elif ans == 10:    # return values
                     hist = history[self.with_history1]
                     if len(hist) >= MAX_HISTORY:
                         hist.remove(hist[0])
+                    if hist.count(self.entry1.text) >= 1:
+                        hist.remove(self.entry1.text)
                     hist.append(self.entry1.text)
             if self.with_history2 in history.keys():
                 if self.entry2.text and self.entry2.text != '*':
                     hist = history[self.with_history2]
                     if len(hist) >= MAX_HISTORY:
                         hist.remove(hist[0])
+                    if hist.count(self.entry2.text) >= 1:
+                        hist.remove(self.entry2.text)
                     hist.append(self.entry2.text)
             ans1 = os.path.expanduser(self.entry1.text)
             ans2 = os.path.expanduser(self.entry2.text)
 class SelectItem(object):
     """A window to select an item"""
 
-    def __init__(self, entries, y0, x0, entry_i = ''):
+    def __init__(self, entries, y0, x0, entry_i='', title=''):
         h = (app.maxh-1) - (y0+1) + 1
 #         h = min(h, len(entries)+5)
-        w = max(max(map(len, entries)), int(app.maxw/5)) + 4
+        w = max(max(map(len, entries)), len(title)+4, int(app.maxw/5)) + 4
         try:
             win = curses.newwin(h, w, y0, x0)
             self.pwin = curses.panel.new_panel(win)
             self.entry_i = self.entries.index(entry_i)
         except:
             self.entry_i = 0
+        self.title = title
 
 
     def show(self):
         y, x = win.getbegyx()
         h, w = win.getmaxyx()
         h0, w0 = h - 2, w - 3
+        if self.title != '':
+            win.addstr(0, int((w-len(self.title)-2)/2), ' %s ' % utils.encode(self.title))
         nels = len(self.entries)
         entry_a = int(self.entry_i/h0) * h0
         for i in xrange(h0):