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 
 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.escape) 201 _cmd_plugin.export(self.replace_aliases) 202 203 self.xyz.pm.register(_cmd_plugin) 204 205 self.context = _cmd_plugin.ns.pfull 206 207 return _cmd_plugin
208 209 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 210
211 - def selectable(self):
212 return True
213 214 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 215
216 - def rows(self, (maxcol,), focus=False):
217 """ 218 Return the number of lines that will be rendered 219 """ 220 221 return 1
222 223 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 224
225 - def render(self, (maxcol,), focus=False):
226 """ 227 Render the command line 228 """ 229 230 if self.prompt is not None: 231 _canv_prompt = self.prompt.render((maxcol,)) 232 _prompt_len = len(self.prompt) 233 else: 234 _canv_prompt = lowui.Text(u"").render((maxcol,)) 235 _prompt_len = 0 236 237 _data = [bstring(x) for x in self._get_visible(maxcol)] 238 _text_len = abs(maxcol - _prompt_len) 239 240 _canv_text = lowui.AttrWrap(lowui.Text("".join(_data)), 241 self._text_attr).render((maxcol,)) 242 243 _canvases = [] 244 245 if _prompt_len > 0: 246 _canvases.append((_canv_prompt, None, False, _prompt_len)) 247 248 _canvases.append((_canv_text, 0, True, _text_len)) 249 250 canv = lowui.CanvasJoin(_canvases) 251 canv.cursor = self.get_cursor_coords((maxcol,)) 252 253 return canv
254 255 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 256
257 - def _get_visible(self, maxcol):
258 """ 259 Calculate and return currently visible piece of cmd data 260 """ 261 262 maxcol -= 1 263 264 _plen = len(self.prompt) 265 _dlen = len(self._data) 266 _xindex = _plen + self._index 267 268 if self._vindex >= maxcol: 269 self._vindex = maxcol - 1 270 271 if _plen + _dlen >= maxcol: 272 _off = _xindex - maxcol 273 _to = _xindex 274 275 if _off < 0: 276 _off = 0 277 _to = maxcol - _plen + 1 278 279 _data = self._data[_off:_to] 280 else: 281 _data = self._data 282 283 return _data
284 285 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 286
287 - def get_cursor_coords(self, (maxcol,)):
288 """ 289 Return the (x,y) coordinates of cursor within widget. 290 """ 291 292 return len(self.prompt) + self._vindex, 0
293 294 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 295
296 - def _put_object(self, char):
297 self._data.insert(self._index, char) 298 self._index += 1 299 self._vindex += 1
300 301 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 302
303 - def keypress(self, size, key):
304 """ 305 Process pressed key 306 """ 307 308 _meth = self.xyz.km.process(key) 309 310 if _meth is not None: 311 return _meth() 312 else: 313 _good = [x for x in key if len(x) == 1] 314 315 if _good: 316 try: 317 map(lambda x: self._put_object(x), _good) 318 except Exception, e: 319 xyzlog.error(_(ustring(str(e)))) 320 xyzlog.debug(ustring(traceback.format_exc())) 321 else: 322 self._invalidate()
323 324 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 325
326 - def _save_undo(self):
327 """ 328 Save undo data 329 """ 330 331 self._undo.push((self._index, copy.copy(self._data)))
332 333 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 334
335 - def _restore_undo(self):
336 """ 337 Restore one undo level 338 """ 339 340 if self._undo: 341 self._index, self._data = self._undo.pop() 342 self._vindex = self._index
343 344 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 345
346 - def _save_history(self):
347 """ 348 Save typed command history 349 """ 350 351 # Prevent duplicating entries 352 if not self._history.tail() == self._data: 353 self._history.push(copy.copy(self._data)) 354 355 self._hindex = len(self._history)
356 357 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 358
359 - def _clear_cmd(self):
360 """ 361 Internal clear 362 """ 363 364 self._data = [] 365 self._index = 0 366 self._vindex = 0
367 368 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 369
370 - def _move_cursor(self, direction, chars=None, topred=None):
371 """ 372 Generic cursor moving procedure 373 @param direction: LEFT or RIGHT 374 @param chars: Number of character to move or END to move to the end 375 in corresponding direction 376 @param topred: Predicate function which must return True if char 377 under the cursor is endpoint in move 378 """ 379 380 _newindex = None 381 382 # Using predicate 383 if callable(topred): 384 if direction == self.LEFT: 385 _range = range(self._index - 1, 0, -1) 386 else: 387 _range = range(self._index + 1, len(self._data)) 388 389 for i in _range: 390 if topred(self._data[i]): 391 _newindex = i 392 break 393 394 if _newindex is None: 395 # To start or end, depending on direction 396 return self._move_cursor(direction, chars=self.END) 397 398 elif direction == self.LEFT: 399 if chars == self.END: 400 _newindex = 0 401 elif chars is not None and self._index >= chars: 402 _newindex = self._index - chars 403 404 elif direction == self.RIGHT: 405 if chars == self.END: 406 _newindex = len(self._data) 407 408 elif (self._index + chars) <= len(self._data): 409 _newindex = self._index + chars 410 411 if _newindex is not None: 412 self._index = _newindex 413 self._vindex = _newindex 414 self._invalidate()
415 416 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 417 418 @refresh
419 - def _delete(self, direction, chars=None, topred=None):
420 """ 421 Generic delete procedure 422 @param direction: LEFT, RIGHT or UNDER 423 @param chars: Number of characters to delete 424 @param topred: Predicate function which must return True if char 425 under the cursor is endpoint in delete 426 """ 427 428 _newindex = None 429 _delindex = None 430 _newdata = None 431 432 if callable(topred): 433 if direction == self.LEFT: 434 _range = range(self._index - 1, 0, -1) 435 else: 436 _range = range(self._index + 1, len(self._data)) 437 438 _found = False 439 440 for i in _range: 441 if topred(self._data[i]): 442 _found = True 443 if direction == self.LEFT: 444 _newindex = i 445 _newdata = self._data[:_newindex] + \ 446 self._data[self._index:] 447 else: 448 _newdata = self._data[:self._index] + self._data[i:] 449 450 self._save_undo() 451 break 452 453 if not _found: 454 return self._delete(direction, chars=self.END) 455 456 elif direction == self.UNDER: 457 if self._index >= 0 and self._index < len(self._data): 458 _delindex = self._index 459 460 elif direction == self.LEFT: 461 if chars == self.END: 462 self._save_undo() 463 _newdata = self._data[self._index:] 464 _newindex = 0 465 elif chars is not None and self._index >= chars: 466 _newindex = self._index - chars 467 _delindex = _newindex 468 469 elif direction == self.RIGHT: 470 if chars == self.END: 471 self._save_undo() 472 _newdata = self._data[:self._index] 473 474 if _newindex is not None: 475 self._index = _newindex 476 self._vindex = _newindex 477 if _newdata is not None: 478 self._data = _newdata 479 if _delindex is not None: 480 del(self._data[_delindex])
481 482 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 483 484 # Public methods 485
486 - def del_char_left(self):
487 """ 488 Delete single character left to the cursor 489 """ 490 491 self._delete(self.LEFT, chars=1)
492 493 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 494
495 - def del_char(self):
496 """ 497 Delete single character under the cursor 498 """ 499 500 return self._delete(self.UNDER)
501 502 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 503
504 - def del_word_left(self):
505 """ 506 Delete a word left to the cursor 507 """ 508 509 return self._delete(self.LEFT, topred=lambda x: x.isspace())
510 511 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 512
513 - def del_word_right(self):
514 """ 515 Delete a word right to the cursor 516 """ 517 518 return self._delete(self.RIGHT, topred=lambda x: x.isspace())
519 520 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 521
522 - def clear(self):
523 """ 524 Clear the whole cmd line 525 """ 526 527 self._save_undo() 528 self._clear_cmd() 529 self._invalidate()
530 531 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 532
533 - def clear_left(self):
534 """ 535 Clear the cmd line from the cursor to the left 536 """ 537 538 self._delete(self.LEFT, chars=self.END)
539 540 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 541
542 - def clear_right(self):
543 """ 544 Clear the cmd line from the cursor to the right 545 """ 546 547 return self._delete(self.RIGHT, chars=self.END)
548 549 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 550
551 - def cursor_begin(self):
552 """ 553 Move cursor to the beginning of the command line 554 """ 555 556 self._move_cursor(self.LEFT, chars=self.END)
557 558 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 559
560 - def cursor_end(self):
561 """ 562 Move cursor to the end of the command line 563 """ 564 565 self._move_cursor(self.RIGHT, chars=self.END)
566 567 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 568
569 - def cursor_left(self):
570 """ 571 Move cursor left 572 """ 573 574 self._move_cursor(self.LEFT, chars=1)
575 576 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 577
578 - def cursor_right(self):
579 """ 580 Move cursor right 581 """ 582 583 self._move_cursor(self.RIGHT, chars=1)
584 585 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 586
587 - def cursor_word_left(self):
588 """ 589 Move cursor one word left 590 """ 591 592 self._move_cursor(self.LEFT, topred=lambda x: x.isspace())
593 594 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 595
596 - def cursor_word_right(self):
597 """ 598 Move cursor one word right 599 """ 600 601 self._move_cursor(self.RIGHT, topred=lambda x: x.isspace())
602 603 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 604
605 - def execute(self):
606 """ 607 Execute cmd contents 608 """ 609 610 # We're inside non-local VFS, execution is not allowed 611 612 if XYZ.call(":sys:panel:vfs_driver"): 613 xyzlog.error( 614 _(u"Unable to execute commands on non-local filesystems")) 615 return 616 617 if not self._data: 618 return 619 620 self._save_history() 621 _data = self.replace_aliases("".join(self._data)) 622 _cmd, _rest = split_cmd(_data) 623 624 # Do not run shell, execute internal command 625 if _cmd in self.xyz.conf["commands"]: 626 try: 627 if _rest is None: 628 arg = _rest 629 else: 630 arg = bstring(_rest) 631 632 self.xyz.conf["commands"][_cmd](arg) 633 except Exception, e: 634 xyzlog.error(_("Error executing internal command %s: %s") % 635 (_cmd, ustring(str(e)))) 636 else: 637 if not hasattr(self, "_execf"): 638 self._execf = self.xyz.pm.from_load(":core:shell", "execute") 639 640 if not hasattr(self, "_reloadf"): 641 self._reloadf =self.xyz.pm.from_load(":sys:panel", 642 "reload_all") 643 644 self._execf(_data) 645 self._reloadf() 646 647 self._clear_cmd() 648 self._invalidate()
649 650 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 651
652 - def replace_aliases(self, data):
653 """ 654 Check if first word of the command line (which is supposed to be a 655 command to execute) is in our aliases table, if it is, replace it. 656 657 @param data: String 658 """ 659 660 cmd, _ = split_cmd(data) 661 662 try: 663 raw_alias = self.xyz.conf["aliases"][cmd] 664 665 if isinstance(raw_alias, basestring): 666 alias = raw_alias 667 elif is_func(raw_alias): 668 alias = raw_alias() 669 else: 670 xyzlog.error(_(u"Invalid alias type: %s") % 671 ustring(str(type(raw_alias)))) 672 return data 673 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):
839 """ 840 Put arbitrary string to cmd line starting from the cursor position 841 """ 842 843 return self._put_engine(obj)
844 845 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 846
847 - def _put_engine(self, obj):
848 """ 849 Put list content to cmd 850 """ 851 852 map(lambda x: self._put_object(x), 853 self.escape([bstring(x) for x in ustring(obj)]) + [" "]) 854 self._invalidate()
855 856 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 857
858 - def escape(self, obj, join=False):
859 """ 860 Escape filename 861 @param obj: String to escape 862 @param join: If False return list otherwise return joined string 863 """ 864 865 result = [] 866 toescape = [" ", "'", '"', "*", "?", "\\", "&", "#", 867 "(", ")", 868 "[", "]", 869 "{", "}", 870 ] 871 872 for x in obj: 873 if x in toescape: 874 result.extend(["\\", x]) 875 else: 876 result.append(x) 877 878 if join: 879 return "".join(result) 880 else: 881 return result
882 883 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 884
885 - def _set_prompt(self, new):
886 """ 887 Set command line prompt 888 """ 889 890 self.prompt = Prompt(new, self._attr(u"prompt")) 891 self._invalidate()
892
893 #++++++++++++++++++++++++++++++++++++++++++++++++ 894 895 -def split_cmd(cmdline):
896 """ 897 Return command name and the rest of the command line 898 """ 899 900 _r = cmdline.split(" ", 1) 901 902 if len(_r) == 1: 903 return _r[0], None 904 else: 905 return _r[0], _r[1]
906