Package libxyz :: Package ui :: Module cmd
[hide private]
[frames] | no frames]

Source Code for Module libxyz.ui.cmd

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov ~syhpoon <syhpoon@syhpoon.name> 2008 
  4  # 
  5  # This file is part of XYZCommander. 
  6  # XYZCommander is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # XYZCommander is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 13  # GNU Lesser Public License for more details. 
 14  # You should have received a copy of the GNU Lesser Public License 
 15  # along with XYZCommander. If not, see <http://www.gnu.org/licenses/>. 
 16   
 17  import copy 
 18  import traceback 
 19  import re 
 20   
 21  import libxyz.core 
 22   
 23  from libxyz.ui import lowui 
 24  from libxyz.ui import Prompt 
 25  from libxyz.ui import XYZListBox 
 26  from libxyz.ui import NumEntry 
 27  from libxyz.ui import Keys 
 28  from libxyz.ui.utils import refresh 
 29  from libxyz.core.utils import ustring, bstring, is_func, split_cmd 
 30  from libxyz.core.dsl import XYZ 
 31  from libxyz.exceptions import XYZRuntimeError 
32 33 -class Cmd(lowui.FlowWidget):
34 """ 35 Command line widget 36 """ 37 38 resolution = (u"cmd",) 39 40 LEFT = u"left" 41 RIGHT = u"right" 42 END = u"end" 43 UNDER = u"under" 44
45 - def __init__(self, xyz):
46 """ 47 @param xyz: XYZData instance 48 49 Resources used: text, prompt 50 """ 51 52 super(Cmd, self).__init__() 53 54 self.xyz = xyz 55 self._attr = lambda x: xyz.skin.attr(self.resolution, x) 56 57 self._keys = Keys() 58 59 self._text_attr = self._attr(u"text") 60 self._data = [] 61 # Internal cursor index. Value is in range(0,len(self._data)) 62 self._index = 0 63 # Virtual cursor index. Value is in range(0,maxcol) 64 self._vindex = 0 65 self._hindex = 0 66 67 self.context = None 68 self._panel = self.xyz.pm.load(":sys:panel") 69 70 self._plugin = self._init_plugin() 71 self._ud = libxyz.core.UserData() 72 self._history_file = "history" 73 74 _conf = self._plugin.conf 75 self.prompt = Prompt(_conf[u"prompt"], self._attr(u"prompt")) 76 self._undo = libxyz.core.Queue(_conf[u"undo_depth"]) 77 self._history = libxyz.core.Queue(_conf[u"history_depth"]) 78 79 self.xyz.hm.register("event:conf_update", self._update_conf_hook) 80 self.xyz.hm.register("event:startup", self._load_history_hook) 81 self.xyz.hm.register("event:shutdown", self._save_history_hook)
82 83 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 84
85 - def _update_conf_hook(self, var, val, sect):
86 """ 87 Hook for update conf event 88 """ 89 90 # Not ours 91 if sect != "plugins" or var != self._plugin.ns.pfull: 92 return 93 94 mapping = { 95 "prompt": lambda x: self._set_prompt(x), 96 "undo_depth": lambda x: self._undo.set_size(x), 97 "history_depth": lambda x: self._history.set_size(x), 98 } 99 100 for k, v in val.iteritems(): 101 if k in mapping: 102 mapping[k](v)
103 104 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105
106 - def _save_history_hook(self):
107 """ 108 Save history at shutdown 109 """ 110 111 f = None 112 try: 113 f = self._ud.openfile(self._history_file, "w", "data") 114 f.write("\n".join([bstring(u"".join(x)) for x in self._history])) 115 except XYZRuntimeError, e: 116 if f: 117 f.close() 118 119 xyzlog.info(_(u"Unable to open history data file: %s") 120 % ustring(str(e))) 121 else: 122 if f: 123 f.close()
124 125 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 126
127 - def _load_history_hook(self):
128 """ 129 Load history at startup 130 """ 131 132 f = None 133 134 try: 135 f = self._ud.openfile(self._history_file, "r", "data") 136 data = f.readlines() 137 138 if len(data) > self._history.maxsize: 139 data = data[-self._history.maxsize] 140 141 self._history.clear() 142 143 for line in data: 144 self._history.push([x for x in ustring(line.rstrip())]) 145 except Exception: 146 pass 147 148 if f: 149 f.close()
150 151 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 152
153 - def _init_plugin(self):
154 """ 155 Init virtual plugin 156 """ 157 158 _cmd_plugin = libxyz.core.plugins.VirtualPlugin(self.xyz, u"cmd") 159 _cmd_plugin.AUTHOR = u"Max E. Kuznecov <syhpoon@syhpoon.name>" 160 _cmd_plugin.VERSION = u"0.1" 161 _cmd_plugin.BRIEF_DESCRIPTION = u"Command line plugin" 162 _cmd_plugin.FULL_DESCRIPTION = u"Command line plugin. "\ 163 u"It allows to enter, edit and "\ 164 u"execute commands." 165 _cmd_plugin.DOC = u"Configuration variables:\n"\ 166 u"undo_depth - Specifies how many undo levels to "\ 167 u"keep. Default - 10\n"\ 168 u"history_depth - Specifies how many entered "\ 169 u"commands to keep. Default - 50\n"\ 170 u"prompt - Command line prompt. Default - '$ '" 171 172 _cmd_plugin.export(self.del_char) 173 _cmd_plugin.export(self.del_char_left) 174 _cmd_plugin.export(self.del_word_left) 175 _cmd_plugin.export(self.del_word_right) 176 _cmd_plugin.export(self.clear) 177 _cmd_plugin.export(self.clear_left) 178 _cmd_plugin.export(self.clear_right) 179 _cmd_plugin.export(self.cursor_begin) 180 _cmd_plugin.export(self.cursor_end) 181 _cmd_plugin.export(self.cursor_left) 182 _cmd_plugin.export(self.cursor_right) 183 _cmd_plugin.export(self.cursor_word_left) 184 _cmd_plugin.export(self.cursor_word_right) 185 _cmd_plugin.export(self.is_empty) 186 _cmd_plugin.export(self.undo) 187 _cmd_plugin.export(self.undo_clear) 188 _cmd_plugin.export(self.execute) 189 _cmd_plugin.export(self.history_prev) 190 _cmd_plugin.export(self.history_next) 191 _cmd_plugin.export(self.history_clear) 192 _cmd_plugin.export(self.show_history) 193 _cmd_plugin.export(self.put_active_object) 194 _cmd_plugin.export(self.put_active_object_path) 195 _cmd_plugin.export(self.put_inactive_object) 196 _cmd_plugin.export(self.put_inactive_object_path) 197 _cmd_plugin.export(self.put_active_cwd) 198 _cmd_plugin.export(self.put_inactive_cwd) 199 _cmd_plugin.export(self.put) 200 _cmd_plugin.export(self.get) 201 _cmd_plugin.export(self.append) 202 _cmd_plugin.export(self.escape) 203 _cmd_plugin.export(self.replace_aliases) 204 205 self.xyz.pm.register(_cmd_plugin) 206 207 self.context = _cmd_plugin.ns.pfull 208 209 return _cmd_plugin
210 211 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 212
213 - def selectable(self):
214 return True
215 216 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 217
218 - def rows(self, (maxcol,), focus=False):
219 """ 220 Return the number of lines that will be rendered 221 """ 222 223 return 1
224 225 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 226
227 - def render(self, (maxcol,), focus=False):
228 """ 229 Render the command line 230 """ 231 232 if self.prompt is not None: 233 _canv_prompt = self.prompt.render((maxcol,)) 234 _prompt_len = len(self.prompt) 235 else: 236 _canv_prompt = lowui.Text(u"").render((maxcol,)) 237 _prompt_len = 0 238 239 _data = [bstring(x) for x in self._get_visible(maxcol)] 240 _text_len = abs(maxcol - _prompt_len) 241 242 _canv_text = lowui.AttrWrap(lowui.Text("".join(_data)), 243 self._text_attr).render((maxcol,)) 244 245 _canvases = [] 246 247 if _prompt_len > 0: 248 _canvases.append((_canv_prompt, None, False, _prompt_len)) 249 250 _canvases.append((_canv_text, 0, True, _text_len)) 251 252 canv = lowui.CanvasJoin(_canvases) 253 canv.cursor = self.get_cursor_coords((maxcol,)) 254 255 return canv
256 257 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 258
259 - def _get_visible(self, maxcol):
260 """ 261 Calculate and return currently visible piece of cmd data 262 """ 263 264 maxcol -= 1 265 266 _plen = len(self.prompt) 267 _dlen = len(self._data) 268 _xindex = _plen + self._index 269 270 if self._vindex >= maxcol: 271 self._vindex = maxcol - 1 272 273 if _plen + _dlen >= maxcol: 274 _off = _xindex - maxcol 275 _to = _xindex 276 277 if _off < 0: 278 _off = 0 279 _to = maxcol - _plen + 1 280 281 _data = self._data[_off:_to] 282 else: 283 _data = self._data 284 285 return _data
286 287 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 288
289 - def get_cursor_coords(self, (maxcol,)):
290 """ 291 Return the (x,y) coordinates of cursor within widget. 292 """ 293 294 return len(self.prompt) + self._vindex, 0
295 296 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 297
298 - def _put_object(self, char):
299 self._data.insert(self._index, ustring(char)) 300 self._index += 1 301 self._vindex += 1
302 303 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 304
305 - def keypress(self, size, key):
306 """ 307 Process pressed key 308 """ 309 310 _meth = self.xyz.km.process(key) 311 312 if _meth is not None: 313 return _meth() 314 else: 315 _good = [x for x in key if len(x) == 1] 316 317 if _good: 318 try: 319 map(lambda x: self._put_object(x), _good) 320 except Exception, e: 321 xyzlog.error(_(ustring(str(e)))) 322 xyzlog.debug(ustring(traceback.format_exc())) 323 else: 324 self._invalidate()
325 326 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 327
328 - def _save_undo(self):
329 """ 330 Save undo data 331 """ 332 333 self._undo.push((self._index, copy.copy(self._data)))
334 335 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 336
337 - def _restore_undo(self):
338 """ 339 Restore one undo level 340 """ 341 342 if self._undo: 343 self._index, self._data = self._undo.pop() 344 self._vindex = self._index
345 346 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 347
348 - def _save_history(self):
349 """ 350 Save typed command history 351 """ 352 353 # Prevent duplicating entries 354 if not self._history.tail() == self._data: 355 self._history.push(copy.copy(self._data)) 356 357 self._hindex = len(self._history)
358 359 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 360
361 - def _clear_cmd(self):
362 """ 363 Internal clear 364 """ 365 366 self._data = [] 367 self._index = 0 368 self._vindex = 0
369 370 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 371
372 - def _move_cursor(self, direction, chars=None, topred=None):
373 """ 374 Generic cursor moving procedure 375 @param direction: LEFT or RIGHT 376 @param chars: Number of character to move or END to move to the end 377 in corresponding direction 378 @param topred: Predicate function which must return True if char 379 under the cursor is endpoint in move 380 """ 381 382 _newindex = None 383 384 # Using predicate 385 if callable(topred): 386 if direction == self.LEFT: 387 _range = range(self._index - 1, 0, -1) 388 else: 389 _range = range(self._index + 1, len(self._data)) 390 391 for i in _range: 392 if topred(self._data[i]): 393 _newindex = i 394 break 395 396 if _newindex is None: 397 # To start or end, depending on direction 398 return self._move_cursor(direction, chars=self.END) 399 400 elif direction == self.LEFT: 401 if chars == self.END: 402 _newindex = 0 403 elif chars is not None and self._index >= chars: 404 _newindex = self._index - chars 405 406 elif direction == self.RIGHT: 407 if chars == self.END: 408 _newindex = len(self._data) 409 410 elif (self._index + chars) <= len(self._data): 411 _newindex = self._index + chars 412 413 if _newindex is not None: 414 self._index = _newindex 415 self._vindex = _newindex 416 self._invalidate()
417 418 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 419 420 @refresh
421 - def _delete(self, direction, chars=None, topred=None):
422 """ 423 Generic delete procedure 424 @param direction: LEFT, RIGHT or UNDER 425 @param chars: Number of characters to delete 426 @param topred: Predicate function which must return True if char 427 under the cursor is endpoint in delete 428 """ 429 430 _newindex = None 431 _delindex = None 432 _newdata = None 433 434 if callable(topred): 435 if direction == self.LEFT: 436 _range = range(self._index - 1, 0, -1) 437 else: 438 _range = range(self._index + 1, len(self._data)) 439 440 _found = False 441 442 for i in _range: 443 if topred(self._data[i]): 444 _found = True 445 if direction == self.LEFT: 446 _newindex = i 447 _newdata = self._data[:_newindex] + \ 448 self._data[self._index:] 449 else: 450 _newdata = self._data[:self._index] + self._data[i:] 451 452 self._save_undo() 453 break 454 455 if not _found: 456 return self._delete(direction, chars=self.END) 457 458 elif direction == self.UNDER: 459 if self._index >= 0 and self._index < len(self._data): 460 _delindex = self._index 461 462 elif direction == self.LEFT: 463 if chars == self.END: 464 self._save_undo() 465 _newdata = self._data[self._index:] 466 _newindex = 0 467 elif chars is not None and self._index >= chars: 468 _newindex = self._index - chars 469 _delindex = _newindex 470 471 elif direction == self.RIGHT: 472 if chars == self.END: 473 self._save_undo() 474 _newdata = self._data[:self._index] 475 476 if _newindex is not None: 477 self._index = _newindex 478 self._vindex = _newindex 479 if _newdata is not None: 480 self._data = _newdata 481 if _delindex is not None: 482 del(self._data[_delindex])
483 484 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 485 486 # Public methods 487
488 - def del_char_left(self):
489 """ 490 Delete single character left to the cursor 491 """ 492 493 self._delete(self.LEFT, chars=1)
494 495 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 496
497 - def del_char(self):
498 """ 499 Delete single character under the cursor 500 """ 501 502 return self._delete(self.UNDER)
503 504 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 505
506 - def del_word_left(self):
507 """ 508 Delete a word left to the cursor 509 """ 510 511 return self._delete(self.LEFT, topred=lambda x: x.isspace())
512 513 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 514
515 - def del_word_right(self):
516 """ 517 Delete a word right to the cursor 518 """ 519 520 return self._delete(self.RIGHT, topred=lambda x: x.isspace())
521 522 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 523
524 - def clear(self):
525 """ 526 Clear the whole cmd line 527 """ 528 529 self._save_undo() 530 self._clear_cmd() 531 self._invalidate()
532 533 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 534
535 - def clear_left(self):
536 """ 537 Clear the cmd line from the cursor to the left 538 """ 539 540 self._delete(self.LEFT, chars=self.END)
541 542 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 543
544 - def clear_right(self):
545 """ 546 Clear the cmd line from the cursor to the right 547 """ 548 549 return self._delete(self.RIGHT, chars=self.END)
550 551 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 552
553 - def cursor_begin(self):
554 """ 555 Move cursor to the beginning of the command line 556 """ 557 558 self._move_cursor(self.LEFT, chars=self.END)
559 560 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 561
562 - def cursor_end(self):
563 """ 564 Move cursor to the end of the command line 565 """ 566 567 self._move_cursor(self.RIGHT, chars=self.END)
568 569 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 570
571 - def cursor_left(self):
572 """ 573 Move cursor left 574 """ 575 576 self._move_cursor(self.LEFT, chars=1)
577 578 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 579
580 - def cursor_right(self):
581 """ 582 Move cursor right 583 """ 584 585 self._move_cursor(self.RIGHT, chars=1)
586 587 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 588
589 - def cursor_word_left(self):
590 """ 591 Move cursor one word left 592 """ 593 594 self._move_cursor(self.LEFT, topred=lambda x: x.isspace())
595 596 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 597
598 - def cursor_word_right(self):
599 """ 600 Move cursor one word right 601 """ 602 603 self._move_cursor(self.RIGHT, topred=lambda x: x.isspace())
604 605 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 606
607 - def execute(self):
608 """ 609 Execute cmd contents 610 """ 611 612 # We're inside non-local VFS, execution is not allowed 613 if XYZ.call(":sys:panel:vfs_driver"): 614 xyzlog.error( 615 _(u"Unable to execute commands on non-local filesystems")) 616 return 617 618 if not self._data: 619 return 620 621 self._save_history() 622 _data = self.replace_aliases(bstring(u"".join(self._data))) 623 _cmd, _rest = _split_cmd(_data) 624 625 # Do not run shell, execute internal command 626 if _cmd in self.xyz.conf["commands"]: 627 try: 628 if _rest is None: 629 arg = _rest 630 else: 631 arg = _rest 632 633 self.xyz.conf["commands"][_cmd](arg) 634 except Exception, e: 635 xyzlog.error(_("Error executing internal command %s: %s") % 636 (_cmd, ustring(str(e)))) 637 else: 638 if not hasattr(self, "_execf"): 639 self._execf = self.xyz.pm.from_load(":core:shell", "execute") 640 641 if not hasattr(self, "_reloadf"): 642 self._reloadf = self.xyz.pm.from_load(":sys:panel", 643 "reload_all") 644 645 self._execf(_data) 646 self._reloadf() 647 648 self._clear_cmd() 649 self._invalidate()
650 651 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 652
653 - def replace_aliases(self, data):
654 """ 655 Check if first word of the command line (which is supposed to be a 656 command to execute) is in our aliases table, if it is, replace it. 657 658 @param data: String 659 """ 660 661 cmd, _ = _split_cmd(data) 662 663 try: 664 raw_alias = self.xyz.conf["aliases"][cmd] 665 666 if isinstance(raw_alias, basestring): 667 alias = raw_alias 668 elif is_func(raw_alias): 669 alias = raw_alias() 670 else: 671 xyzlog.error(_(u"Invalid alias type: %s") % 672 ustring(str(type(raw_alias)))) 673 return data 674 675 return re.sub(r"^%s" % cmd, alias, data) 676 except KeyError: 677 return data 678 except Exception, e: 679 xyzlog.error(_(u"Unable to replace an alias %s: %s") % 680 (ustring(cmd), ustring(str(e)))) 681 return data
682 683 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 684 685
686 - def is_empty(self):
687 """ 688 Return True if cmd is empty, i.e. has no contents 689 """ 690 691 return self._data == []
692 693 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 694
695 - def undo(self):
696 """ 697 Restore one level from undo buffer 698 """ 699 700 self._restore_undo() 701 self._invalidate()
702 703 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 704
705 - def undo_clear(self):
706 """ 707 Clear undo buffer 708 """ 709 710 self._undo.clear() 711 self._invalidate()
712 713 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 714
715 - def history_prev(self):
716 """ 717 Scroll through list of saved commands backward 718 """ 719 720 if self._hindex > 0: 721 self._hindex -= 1 722 self._data = copy.copy(self._history[self._hindex]) 723 self.cursor_end()
724 725 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 726
727 - def history_next(self):
728 """ 729 Scroll through list of saved commands forward 730 """ 731 732 if self._hindex < len(self._history) - 1: 733 self._hindex += 1 734 self._data = copy.copy(self._history[self._hindex]) 735 self.cursor_end()
736 737 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 738
739 - def history_clear(self):
740 """ 741 Clear commands history 742 """ 743 744 self._history.clear()
745 746 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 747
748 - def show_history(self):
749 """ 750 Show commands history list 751 """ 752 753 def _enter_cb(num): 754 if num >= len(self._history): 755 return 756 757 self._data = copy.copy(self._history[num]) 758 self.cursor_end()
759 760 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 761 762 _sel_attr = self.xyz.skin.attr(XYZListBox.resolution, u"selected") 763 764 _wdata = [] 765 766 for i in range(len(self._history)): 767 _wdata.append(NumEntry(u"".join([ustring(x) for x in 768 self._history[i]]), 769 _sel_attr, i, 770 enter_cb=_enter_cb)) 771 772 _walker = lowui.SimpleListWalker(_wdata) 773 _walker.focus = len(_walker) - 1 774 775 _dim = tuple([x - 2 for x in self.xyz.screen.get_cols_rows()]) 776 777 _ek = [self._keys.ENTER] 778 779 XYZListBox(self.xyz, self.xyz.top, _walker, _(u"History"), 780 _dim).show(exit_keys=_ek)
781 782 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 783
784 - def put_active_object(self):
785 """ 786 Put currently selected VFS object name in panel to cmd line 787 """ 788 789 return self._put_engine(self._panel.get_selected().name)
790 791 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 792
793 - def put_active_object_path(self):
794 """ 795 Put currently selected VFS object full path in panel to cmd line 796 """ 797 798 return self._put_engine(self._panel.get_selected().path)
799 800 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 801
802 - def put_inactive_object(self):
803 """ 804 Put selected VFS object name in inactive panel to cmd line 805 """ 806 807 return self._put_engine(self._panel.get_selected(False).name)
808 809 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 810
811 - def put_inactive_object_path(self):
812 """ 813 Put selected VFS object full path in inactive panel to cmd line 814 """ 815 816 return self._put_engine(self._panel.get_selected(False).path)
817 818 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 819
820 - def put_active_cwd(self):
821 """ 822 Put current working directory of active panel to cmd line 823 """ 824 825 return self._put_engine(self._panel.cwd())
826 827 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 828
829 - def put_inactive_cwd(self):
830 """ 831 Put current working directory of inactive panel to cmd line 832 """ 833 834 return self._put_engine(self._panel.cwd(False))
835 836 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 837
838 - def put(self, obj, space=True):
839 """ 840 Put arbitrary string to cmd line starting from the cursor position 841 @param space: Flag indicating whether to append space char after the obj 842 """ 843 844 return self._put_engine(obj, space=space)
845 846 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 847
848 - def get(self):
849 """ 850 Get cmd contents 851 """ 852 853 return bstring(u"".join(self._data))
854 855 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 856
857 - def append(self, obj):
858 """ 859 Append arbitrary string at the end of cmd 860 """ 861 862 self.cursor_end() 863 self.put(obj, space=False)
864 865 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 866
867 - def _put_engine(self, obj, space=True):
868 """ 869 Put list content to cmd 870 """ 871 872 if space: 873 extra = [u" "] 874 else: 875 extra = [] 876 877 map(lambda x: self._put_object(x), 878 self.escape([x for x in ustring(obj)]) + extra) 879 self._invalidate()
880 881 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 882
883 - def escape(self, obj, join=False):
884 """ 885 Escape filename 886 @param obj: String to escape 887 @param join: If False return list otherwise return joined string 888 """ 889 890 result = [] 891 toescape = [u" ", u"'", u'"', u"*", u"?", u"\\", u"&", u"#", 892 u"(", ")", 893 u"[", "]", 894 u"{", "}", 895 ] 896 897 if isinstance(obj, basestring): 898 obj = ustring(obj) 899 900 for x in obj: 901 if x in toescape: 902 result.extend([u"\\", x]) 903 else: 904 result.append(x) 905 906 if join: 907 return u"".join(result) 908 else: 909 return result
910 911 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 912
913 - def _set_prompt(self, new):
914 """ 915 Set command line prompt 916 """ 917 918 self.prompt = Prompt(new, self._attr(u"prompt")) 919 self._invalidate()
920
921 #++++++++++++++++++++++++++++++++++++++++++++++++ 922 923 -def _split_cmd(cmdline):
924 """ 925 Return command name and the rest of the command line 926 """ 927 928 _r = split_cmd(cmdline) 929 930 if len(_r) == 1: 931 return _r[0], None 932 else: 933 return _r[0], _r[1]
934