Show More
@@ -26,6 +26,7 b' import threading' | |||||
26 |
|
26 | |||
27 | # Our own packages |
|
27 | # Our own packages | |
28 | from IPython.core.error import StdinNotImplementedError |
|
28 | from IPython.core.error import StdinNotImplementedError | |
|
29 | from IPython.core.magic import Magics, register_magics, line_magic | |||
29 | from IPython.config.configurable import Configurable |
|
30 | from IPython.config.configurable import Configurable | |
30 | from IPython.external.decorator import decorator |
|
31 | from IPython.external.decorator import decorator | |
31 | from IPython.testing.skipdoctest import skip_doctest |
|
32 | from IPython.testing.skipdoctest import skip_doctest | |
@@ -74,13 +75,13 b' class HistoryAccessor(Configurable):' | |||||
74 | hist_file = Unicode(config=True, |
|
75 | hist_file = Unicode(config=True, | |
75 | help="""Path to file to use for SQLite history database. |
|
76 | help="""Path to file to use for SQLite history database. | |
76 |
|
77 | |||
77 |
By default, IPython will put the history database in the IPython |
|
78 | By default, IPython will put the history database in the IPython | |
78 |
directory. If you would rather share one history among |
|
79 | profile directory. If you would rather share one history among | |
79 | you ca set this value in each, so that they are consistent. |
|
80 | profiles, you ca set this value in each, so that they are consistent. | |
80 |
|
81 | |||
81 |
Due to an issue with fcntl, SQLite is known to misbehave on some NFS |
|
82 | Due to an issue with fcntl, SQLite is known to misbehave on some NFS | |
82 |
If you see IPython hanging, try setting this to something on a |
|
83 | mounts. If you see IPython hanging, try setting this to something on a | |
83 | e.g:: |
|
84 | local disk, e.g:: | |
84 |
|
85 | |||
85 | ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite |
|
86 | ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite | |
86 |
|
87 | |||
@@ -153,7 +154,8 b' class HistoryAccessor(Configurable):' | |||||
153 | def init_db(self): |
|
154 | def init_db(self): | |
154 | """Connect to the database, and create tables if necessary.""" |
|
155 | """Connect to the database, and create tables if necessary.""" | |
155 | # use detect_types so that timestamps return datetime objects |
|
156 | # use detect_types so that timestamps return datetime objects | |
156 |
self.db = sqlite3.connect(self.hist_file, |
|
157 | self.db = sqlite3.connect(self.hist_file, | |
|
158 | detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) | |||
157 | self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer |
|
159 | self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer | |
158 | primary key autoincrement, start timestamp, |
|
160 | primary key autoincrement, start timestamp, | |
159 | end timestamp, num_cmds integer, remark text)""") |
|
161 | end timestamp, num_cmds integer, remark text)""") | |
@@ -216,7 +218,8 b' class HistoryAccessor(Configurable):' | |||||
216 | Returns |
|
218 | Returns | |
217 | ------- |
|
219 | ------- | |
218 |
|
220 | |||
219 |
(session_id [int], start [datetime], end [datetime], num_cmds [int], |
|
221 | (session_id [int], start [datetime], end [datetime], num_cmds [int], | |
|
222 | remark [unicode]) | |||
220 |
|
223 | |||
221 | Sessions that are running or did not exit cleanly will have `end=None` |
|
224 | Sessions that are running or did not exit cleanly will have `end=None` | |
222 | and `num_cmds=None`. |
|
225 | and `num_cmds=None`. | |
@@ -512,7 +515,8 b' class HistoryManager(HistoryAccessor):' | |||||
512 | session += self.session_number |
|
515 | session += self.session_number | |
513 | if session==self.session_number: # Current session |
|
516 | if session==self.session_number: # Current session | |
514 | return self._get_range_session(start, stop, raw, output) |
|
517 | return self._get_range_session(start, stop, raw, output) | |
515 |
return super(HistoryManager, self).get_range(session, start, stop, raw, |
|
518 | return super(HistoryManager, self).get_range(session, start, stop, raw, | |
|
519 | output) | |||
516 |
|
520 | |||
517 | ## ---------------------------- |
|
521 | ## ---------------------------- | |
518 | ## Methods for storing history: |
|
522 | ## Methods for storing history: | |
@@ -611,7 +615,9 b' class HistoryManager(HistoryAccessor):' | |||||
611 | print("ERROR! Session/line number was not unique in", |
|
615 | print("ERROR! Session/line number was not unique in", | |
612 | "database. History logging moved to new session", |
|
616 | "database. History logging moved to new session", | |
613 | self.session_number) |
|
617 | self.session_number) | |
614 | try: # Try writing to the new session. If this fails, don't recurse |
|
618 | try: | |
|
619 | # Try writing to the new session. If this fails, don't | |||
|
620 | # recurse | |||
615 | self._writeout_input_cache(conn) |
|
621 | self._writeout_input_cache(conn) | |
616 | except sqlite3.IntegrityError: |
|
622 | except sqlite3.IntegrityError: | |
617 | pass |
|
623 | pass | |
@@ -718,264 +724,270 b' def _format_lineno(session, line):' | |||||
718 | return "%s#%s" % (session, line) |
|
724 | return "%s#%s" % (session, line) | |
719 |
|
725 | |||
720 |
|
726 | |||
721 | @skip_doctest |
|
727 | @register_magics | |
722 | def magic_history(self, parameter_s = ''): |
|
728 | class HistoryMagics(Magics): | |
723 | """Print input history (_i<n> variables), with most recent last. |
|
|||
724 |
|
729 | |||
725 | %history [-o -p -t -n] [-f filename] [range | -g pattern | -l number] |
|
730 | @skip_doctest | |
|
731 | @line_magic | |||
|
732 | def history(self, parameter_s = ''): | |||
|
733 | """Print input history (_i<n> variables), with most recent last. | |||
726 |
|
734 | |||
727 | By default, input history is printed without line numbers so it can be |
|
735 | %history [-o -p -t -n] [-f filename] [range | -g pattern | -l number] | |
728 | directly pasted into an editor. Use -n to show them. |
|
|||
729 |
|
736 | |||
730 | By default, all input history from the current session is displayed. |
|
737 | By default, input history is printed without line numbers so it can be | |
731 | Ranges of history can be indicated using the syntax: |
|
738 | directly pasted into an editor. Use -n to show them. | |
732 | 4 : Line 4, current session |
|
|||
733 | 4-6 : Lines 4-6, current session |
|
|||
734 | 243/1-5: Lines 1-5, session 243 |
|
|||
735 | ~2/7 : Line 7, session 2 before current |
|
|||
736 | ~8/1-~6/5 : From the first line of 8 sessions ago, to the fifth line |
|
|||
737 | of 6 sessions ago. |
|
|||
738 | Multiple ranges can be entered, separated by spaces |
|
|||
739 |
|
739 | |||
740 | The same syntax is used by %macro, %save, %edit, %rerun |
|
740 | By default, all input history from the current session is displayed. | |
|
741 | Ranges of history can be indicated using the syntax: | |||
|
742 | 4 : Line 4, current session | |||
|
743 | 4-6 : Lines 4-6, current session | |||
|
744 | 243/1-5: Lines 1-5, session 243 | |||
|
745 | ~2/7 : Line 7, session 2 before current | |||
|
746 | ~8/1-~6/5 : From the first line of 8 sessions ago, to the fifth line | |||
|
747 | of 6 sessions ago. | |||
|
748 | Multiple ranges can be entered, separated by spaces | |||
741 |
|
749 | |||
742 | Options: |
|
750 | The same syntax is used by %macro, %save, %edit, %rerun | |
743 |
|
751 | |||
744 | -n: print line numbers for each input. |
|
752 | Options: | |
745 | This feature is only available if numbered prompts are in use. |
|
|||
746 |
|
753 | |||
747 |
|
|
754 | -n: print line numbers for each input. | |
|
755 | This feature is only available if numbered prompts are in use. | |||
748 |
|
756 | |||
749 | -p: print classic '>>>' python prompts before each input. This is useful |
|
757 | -o: also print outputs for each input. | |
750 | for making documentation, and in conjunction with -o, for producing |
|
|||
751 | doctest-ready output. |
|
|||
752 |
|
758 | |||
753 | -r: (default) print the 'raw' history, i.e. the actual commands you typed. |
|
759 | -p: print classic '>>>' python prompts before each input. This is | |
|
760 | useful for making documentation, and in conjunction with -o, for | |||
|
761 | producing doctest-ready output. | |||
754 |
|
762 | |||
755 | -t: print the 'translated' history, as IPython understands it. IPython |
|
763 | -r: (default) print the 'raw' history, i.e. the actual commands you | |
756 | filters your input and converts it all into valid Python source before |
|
764 | typed. | |
757 | executing it (things like magics or aliases are turned into function |
|
|||
758 | calls, for example). With this option, you'll see the native history |
|
|||
759 | instead of the user-entered version: '%cd /' will be seen as |
|
|||
760 | 'get_ipython().magic("%cd /")' instead of '%cd /'. |
|
|||
761 |
|
765 | |||
762 | -g: treat the arg as a pattern to grep for in (full) history. |
|
766 | -t: print the 'translated' history, as IPython understands it. | |
763 | This includes the saved history (almost all commands ever written). |
|
767 | IPython filters your input and converts it all into valid Python | |
764 | Use '%hist -g' to show full saved history (may be very long). |
|
768 | source before executing it (things like magics or aliases are turned | |
|
769 | into function calls, for example). With this option, you'll see the | |||
|
770 | native history instead of the user-entered version: '%cd /' will be | |||
|
771 | seen as 'get_ipython().magic("%cd /")' instead of '%cd /'. | |||
765 |
|
772 | |||
766 | -l: get the last n lines from all sessions. Specify n as a single arg, or |
|
773 | -g: treat the arg as a pattern to grep for in (full) history. | |
767 | the default is the last 10 lines. |
|
774 | This includes the saved history (almost all commands ever written). | |
|
775 | Use '%hist -g' to show full saved history (may be very long). | |||
768 |
|
776 | |||
769 | -f FILENAME: instead of printing the output to the screen, redirect it to |
|
777 | -l: get the last n lines from all sessions. Specify n as a single | |
770 | the given file. The file is always overwritten, though *when it can*, |
|
778 | arg, or the default is the last 10 lines. | |
771 | IPython asks for confirmation first. In particular, running the command |
|
|||
772 | "history -f FILENAME" from the IPython Notebook interface will replace |
|
|||
773 | FILENAME even if it already exists *without* confirmation. |
|
|||
774 |
|
779 | |||
775 | Examples |
|
780 | -f FILENAME: instead of printing the output to the screen, redirect | |
776 | -------- |
|
781 | it to the given file. The file is always overwritten, though *when | |
777 | :: |
|
782 | it can*, IPython asks for confirmation first. In particular, running | |
778 |
|
783 | the command 'history -f FILENAME' from the IPython Notebook | ||
779 | In [6]: %hist -n 4-6 |
|
784 | interface will replace FILENAME even if it already exists *without* | |
780 | 4:a = 12 |
|
785 | confirmation. | |
781 | 5:print a**2 |
|
|||
782 | 6:%hist -n 4-6 |
|
|||
783 |
|
||||
784 | """ |
|
|||
785 |
|
||||
786 | if not self.shell.displayhook.do_full_cache: |
|
|||
787 | print('This feature is only available if numbered prompts are in use.') |
|
|||
788 | return |
|
|||
789 | opts,args = self.parse_options(parameter_s,'noprtglf:',mode='string') |
|
|||
790 |
|
||||
791 | # For brevity |
|
|||
792 | history_manager = self.shell.history_manager |
|
|||
793 |
|
||||
794 | def _format_lineno(session, line): |
|
|||
795 | """Helper function to format line numbers properly.""" |
|
|||
796 | if session in (0, history_manager.session_number): |
|
|||
797 | return str(line) |
|
|||
798 | return "%s/%s" % (session, line) |
|
|||
799 |
|
||||
800 | # Check if output to specific file was requested. |
|
|||
801 | try: |
|
|||
802 | outfname = opts['f'] |
|
|||
803 | except KeyError: |
|
|||
804 | outfile = io.stdout # default |
|
|||
805 | # We don't want to close stdout at the end! |
|
|||
806 | close_at_end = False |
|
|||
807 | else: |
|
|||
808 | if os.path.exists(outfname): |
|
|||
809 | try: |
|
|||
810 | ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname) |
|
|||
811 | except StdinNotImplementedError: |
|
|||
812 | ans = True |
|
|||
813 | if not ans: |
|
|||
814 | print('Aborting.') |
|
|||
815 | return |
|
|||
816 | print("Overwriting file.") |
|
|||
817 | outfile = io_open(outfname, 'w', encoding='utf-8') |
|
|||
818 | close_at_end = True |
|
|||
819 |
|
||||
820 | print_nums = 'n' in opts |
|
|||
821 | get_output = 'o' in opts |
|
|||
822 | pyprompts = 'p' in opts |
|
|||
823 | # Raw history is the default |
|
|||
824 | raw = not('t' in opts) |
|
|||
825 |
|
||||
826 | default_length = 40 |
|
|||
827 | pattern = None |
|
|||
828 |
|
||||
829 | if 'g' in opts: # Glob search |
|
|||
830 | pattern = "*" + args + "*" if args else "*" |
|
|||
831 | hist = history_manager.search(pattern, raw=raw, output=get_output) |
|
|||
832 | print_nums = True |
|
|||
833 | elif 'l' in opts: # Get 'tail' |
|
|||
834 | try: |
|
|||
835 | n = int(args) |
|
|||
836 | except ValueError, IndexError: |
|
|||
837 | n = 10 |
|
|||
838 | hist = history_manager.get_tail(n, raw=raw, output=get_output) |
|
|||
839 | else: |
|
|||
840 | if args: # Get history by ranges |
|
|||
841 | hist = history_manager.get_range_by_str(args, raw, get_output) |
|
|||
842 | else: # Just get history for the current session |
|
|||
843 | hist = history_manager.get_range(raw=raw, output=get_output) |
|
|||
844 |
|
||||
845 | # We could be displaying the entire history, so let's not try to pull it |
|
|||
846 | # into a list in memory. Anything that needs more space will just misalign. |
|
|||
847 | width = 4 |
|
|||
848 |
|
||||
849 | for session, lineno, inline in hist: |
|
|||
850 | # Print user history with tabs expanded to 4 spaces. The GUI clients |
|
|||
851 | # use hard tabs for easier usability in auto-indented code, but we want |
|
|||
852 | # to produce PEP-8 compliant history for safe pasting into an editor. |
|
|||
853 | if get_output: |
|
|||
854 | inline, output = inline |
|
|||
855 | inline = inline.expandtabs(4).rstrip() |
|
|||
856 |
|
||||
857 | multiline = "\n" in inline |
|
|||
858 | line_sep = '\n' if multiline else ' ' |
|
|||
859 | if print_nums: |
|
|||
860 | print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width), |
|
|||
861 | line_sep), file=outfile, end=u'') |
|
|||
862 | if pyprompts: |
|
|||
863 | print(u">>> ", end=u"", file=outfile) |
|
|||
864 | if multiline: |
|
|||
865 | inline = "\n... ".join(inline.splitlines()) + "\n..." |
|
|||
866 | print(inline, file=outfile) |
|
|||
867 | if get_output and output: |
|
|||
868 | print(output, file=outfile) |
|
|||
869 |
|
||||
870 | if close_at_end: |
|
|||
871 | outfile.close() |
|
|||
872 |
|
||||
873 |
|
||||
874 | def magic_rep(self, arg): |
|
|||
875 | r"""Repeat a command, or get command to input line for editing. |
|
|||
876 |
|
||||
877 | %recall and %rep are equivalent. |
|
|||
878 |
|
786 | |||
879 | - %recall (no arguments): |
|
787 | Examples | |
|
788 | -------- | |||
|
789 | :: | |||
880 |
|
790 | |||
881 | Place a string version of last computation result (stored in the special '_' |
|
791 | In [6]: %hist -n 4-6 | |
882 | variable) to the next input prompt. Allows you to create elaborate command |
|
792 | 4:a = 12 | |
883 | lines without using copy-paste:: |
|
793 | 5:print a**2 | |
|
794 | 6:%hist -n 4-6 | |||
884 |
|
795 | |||
885 | In[1]: l = ["hei", "vaan"] |
|
796 | """ | |
886 | In[2]: "".join(l) |
|
|||
887 | Out[2]: heivaan |
|
|||
888 | In[3]: %rep |
|
|||
889 | In[4]: heivaan_ <== cursor blinking |
|
|||
890 |
|
||||
891 | %recall 45 |
|
|||
892 |
|
||||
893 | Place history line 45 on the next input prompt. Use %hist to find |
|
|||
894 | out the number. |
|
|||
895 |
|
797 | |||
896 | %recall 1-4 |
|
798 | if not self.shell.displayhook.do_full_cache: | |
|
799 | print('This feature is only available if numbered prompts ' | |||
|
800 | 'are in use.') | |||
|
801 | return | |||
|
802 | opts,args = self.parse_options(parameter_s,'noprtglf:',mode='string') | |||
897 |
|
803 | |||
898 | Combine the specified lines into one cell, and place it on the next |
|
804 | # For brevity | |
899 | input prompt. See %history for the slice syntax. |
|
805 | history_manager = self.shell.history_manager | |
900 |
|
806 | |||
901 | %recall foo+bar |
|
807 | def _format_lineno(session, line): | |
|
808 | """Helper function to format line numbers properly.""" | |||
|
809 | if session in (0, history_manager.session_number): | |||
|
810 | return str(line) | |||
|
811 | return "%s/%s" % (session, line) | |||
902 |
|
812 | |||
903 | If foo+bar can be evaluated in the user namespace, the result is |
|
813 | # Check if output to specific file was requested. | |
904 | placed at the next input prompt. Otherwise, the history is searched |
|
814 | try: | |
905 | for lines which contain that substring, and the most recent one is |
|
815 | outfname = opts['f'] | |
906 | placed at the next input prompt. |
|
816 | except KeyError: | |
907 | """ |
|
817 | outfile = io.stdout # default | |
908 | if not arg: # Last output |
|
818 | # We don't want to close stdout at the end! | |
909 | self.shell.set_next_input(str(self.shell.user_ns["_"])) |
|
819 | close_at_end = False | |
910 |
|
|
820 | else: | |
911 | # Get history range |
|
821 | if os.path.exists(outfname): | |
912 | histlines = self.shell.history_manager.get_range_by_str(arg) |
|
822 | try: | |
913 | cmd = "\n".join(x[2] for x in histlines) |
|
823 | ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname) | |
914 | if cmd: |
|
824 | except StdinNotImplementedError: | |
915 | self.shell.set_next_input(cmd.rstrip()) |
|
825 | ans = True | |
916 | return |
|
826 | if not ans: | |
917 |
|
827 | print('Aborting.') | ||
918 | try: # Variable in user namespace |
|
828 | return | |
919 | cmd = str(eval(arg, self.shell.user_ns)) |
|
829 | print("Overwriting file.") | |
920 | except Exception: # Search for term in history |
|
830 | outfile = io_open(outfname, 'w', encoding='utf-8') | |
921 | histlines = self.shell.history_manager.search("*"+arg+"*") |
|
831 | close_at_end = True | |
922 | for h in reversed([x[2] for x in histlines]): |
|
832 | ||
923 | if 'rep' in h: |
|
833 | print_nums = 'n' in opts | |
924 | continue |
|
834 | get_output = 'o' in opts | |
925 | self.shell.set_next_input(h.rstrip()) |
|
835 | pyprompts = 'p' in opts | |
|
836 | # Raw history is the default | |||
|
837 | raw = not('t' in opts) | |||
|
838 | ||||
|
839 | pattern = None | |||
|
840 | ||||
|
841 | if 'g' in opts: # Glob search | |||
|
842 | pattern = "*" + args + "*" if args else "*" | |||
|
843 | hist = history_manager.search(pattern, raw=raw, output=get_output) | |||
|
844 | print_nums = True | |||
|
845 | elif 'l' in opts: # Get 'tail' | |||
|
846 | try: | |||
|
847 | n = int(args) | |||
|
848 | except (ValueError, IndexError): | |||
|
849 | n = 10 | |||
|
850 | hist = history_manager.get_tail(n, raw=raw, output=get_output) | |||
|
851 | else: | |||
|
852 | if args: # Get history by ranges | |||
|
853 | hist = history_manager.get_range_by_str(args, raw, get_output) | |||
|
854 | else: # Just get history for the current session | |||
|
855 | hist = history_manager.get_range(raw=raw, output=get_output) | |||
|
856 | ||||
|
857 | # We could be displaying the entire history, so let's not try to pull | |||
|
858 | # it into a list in memory. Anything that needs more space will just | |||
|
859 | # misalign. | |||
|
860 | width = 4 | |||
|
861 | ||||
|
862 | for session, lineno, inline in hist: | |||
|
863 | # Print user history with tabs expanded to 4 spaces. The GUI | |||
|
864 | # clients use hard tabs for easier usability in auto-indented code, | |||
|
865 | # but we want to produce PEP-8 compliant history for safe pasting | |||
|
866 | # into an editor. | |||
|
867 | if get_output: | |||
|
868 | inline, output = inline | |||
|
869 | inline = inline.expandtabs(4).rstrip() | |||
|
870 | ||||
|
871 | multiline = "\n" in inline | |||
|
872 | line_sep = '\n' if multiline else ' ' | |||
|
873 | if print_nums: | |||
|
874 | print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width), | |||
|
875 | line_sep), file=outfile, end=u'') | |||
|
876 | if pyprompts: | |||
|
877 | print(u">>> ", end=u"", file=outfile) | |||
|
878 | if multiline: | |||
|
879 | inline = "\n... ".join(inline.splitlines()) + "\n..." | |||
|
880 | print(inline, file=outfile) | |||
|
881 | if get_output and output: | |||
|
882 | print(output, file=outfile) | |||
|
883 | ||||
|
884 | if close_at_end: | |||
|
885 | outfile.close() | |||
|
886 | ||||
|
887 | @line_magic | |||
|
888 | def rep(self, arg): | |||
|
889 | r"""Repeat a command, or get command to input line for editing. | |||
|
890 | ||||
|
891 | %recall and %rep are equivalent. | |||
|
892 | ||||
|
893 | - %recall (no arguments): | |||
|
894 | ||||
|
895 | Place a string version of last computation result (stored in the | |||
|
896 | special '_' variable) to the next input prompt. Allows you to create | |||
|
897 | elaborate command lines without using copy-paste:: | |||
|
898 | ||||
|
899 | In[1]: l = ["hei", "vaan"] | |||
|
900 | In[2]: "".join(l) | |||
|
901 | Out[2]: heivaan | |||
|
902 | In[3]: %rep | |||
|
903 | In[4]: heivaan_ <== cursor blinking | |||
|
904 | ||||
|
905 | %recall 45 | |||
|
906 | ||||
|
907 | Place history line 45 on the next input prompt. Use %hist to find | |||
|
908 | out the number. | |||
|
909 | ||||
|
910 | %recall 1-4 | |||
|
911 | ||||
|
912 | Combine the specified lines into one cell, and place it on the next | |||
|
913 | input prompt. See %history for the slice syntax. | |||
|
914 | ||||
|
915 | %recall foo+bar | |||
|
916 | ||||
|
917 | If foo+bar can be evaluated in the user namespace, the result is | |||
|
918 | placed at the next input prompt. Otherwise, the history is searched | |||
|
919 | for lines which contain that substring, and the most recent one is | |||
|
920 | placed at the next input prompt. | |||
|
921 | """ | |||
|
922 | if not arg: # Last output | |||
|
923 | self.shell.set_next_input(str(self.shell.user_ns["_"])) | |||
|
924 | return | |||
|
925 | # Get history range | |||
|
926 | histlines = self.shell.history_manager.get_range_by_str(arg) | |||
|
927 | cmd = "\n".join(x[2] for x in histlines) | |||
|
928 | if cmd: | |||
|
929 | self.shell.set_next_input(cmd.rstrip()) | |||
926 | return |
|
930 | return | |
927 | else: |
|
|||
928 | self.shell.set_next_input(cmd.rstrip()) |
|
|||
929 | print("Couldn't evaluate or find in history:", arg) |
|
|||
930 |
|
931 | |||
|
932 | try: # Variable in user namespace | |||
|
933 | cmd = str(eval(arg, self.shell.user_ns)) | |||
|
934 | except Exception: # Search for term in history | |||
|
935 | histlines = self.shell.history_manager.search("*"+arg+"*") | |||
|
936 | for h in reversed([x[2] for x in histlines]): | |||
|
937 | if 'rep' in h: | |||
|
938 | continue | |||
|
939 | self.shell.set_next_input(h.rstrip()) | |||
|
940 | return | |||
|
941 | else: | |||
|
942 | self.shell.set_next_input(cmd.rstrip()) | |||
|
943 | print("Couldn't evaluate or find in history:", arg) | |||
931 |
|
944 | |||
932 | def magic_rerun(self, parameter_s=''): |
|
945 | @line_magic | |
933 | """Re-run previous input |
|
946 | def rerun(self, parameter_s=''): | |
|
947 | """Re-run previous input | |||
934 |
|
948 | |||
935 | By default, you can specify ranges of input history to be repeated |
|
949 | By default, you can specify ranges of input history to be repeated | |
936 | (as with %history). With no arguments, it will repeat the last line. |
|
950 | (as with %history). With no arguments, it will repeat the last line. | |
937 |
|
951 | |||
938 | Options: |
|
952 | Options: | |
939 |
|
953 | |||
940 | -l <n> : Repeat the last n lines of input, not including the |
|
954 | -l <n> : Repeat the last n lines of input, not including the | |
941 | current command. |
|
955 | current command. | |
942 |
|
956 | |||
943 | -g foo : Repeat the most recent line which contains foo |
|
957 | -g foo : Repeat the most recent line which contains foo | |
944 | """ |
|
958 | """ | |
945 | opts, args = self.parse_options(parameter_s, 'l:g:', mode='string') |
|
959 | opts, args = self.parse_options(parameter_s, 'l:g:', mode='string') | |
946 | if "l" in opts: # Last n lines |
|
960 | if "l" in opts: # Last n lines | |
947 | n = int(opts['l']) |
|
961 | n = int(opts['l']) | |
948 | hist = self.shell.history_manager.get_tail(n) |
|
962 | hist = self.shell.history_manager.get_tail(n) | |
949 | elif "g" in opts: # Search |
|
963 | elif "g" in opts: # Search | |
950 | p = "*"+opts['g']+"*" |
|
964 | p = "*"+opts['g']+"*" | |
951 | hist = list(self.shell.history_manager.search(p)) |
|
965 | hist = list(self.shell.history_manager.search(p)) | |
952 | for l in reversed(hist): |
|
966 | for l in reversed(hist): | |
953 | if "rerun" not in l[2]: |
|
967 | if "rerun" not in l[2]: | |
954 | hist = [l] # The last match which isn't a %rerun |
|
968 | hist = [l] # The last match which isn't a %rerun | |
955 | break |
|
969 | break | |
956 | else: |
|
970 | else: | |
957 | hist = [] # No matches except %rerun |
|
971 | hist = [] # No matches except %rerun | |
958 | elif args: # Specify history ranges |
|
972 | elif args: # Specify history ranges | |
959 | hist = self.shell.history_manager.get_range_by_str(args) |
|
973 | hist = self.shell.history_manager.get_range_by_str(args) | |
960 | else: # Last line |
|
974 | else: # Last line | |
961 | hist = self.shell.history_manager.get_tail(1) |
|
975 | hist = self.shell.history_manager.get_tail(1) | |
962 | hist = [x[2] for x in hist] |
|
976 | hist = [x[2] for x in hist] | |
963 | if not hist: |
|
977 | if not hist: | |
964 | print("No lines in history match specification") |
|
978 | print("No lines in history match specification") | |
965 | return |
|
979 | return | |
966 | histlines = "\n".join(hist) |
|
980 | histlines = "\n".join(hist) | |
967 | print("=== Executing: ===") |
|
981 | print("=== Executing: ===") | |
968 | print(histlines) |
|
982 | print(histlines) | |
969 | print("=== Output: ===") |
|
983 | print("=== Output: ===") | |
970 | self.shell.run_cell("\n".join(hist), store_history=False) |
|
984 | self.shell.run_cell("\n".join(hist), store_history=False) | |
971 |
|
985 | |||
972 |
|
986 | |||
973 | def init_ipython(ip): |
|
987 | def init_ipython(ip): | |
974 | ip.define_magic("rep", magic_rep) |
|
988 | ip.magics_manager.register(HistoryMagics) | |
975 |
ip.define_magic( |
|
989 | #ip.define_magic('hist', HistoryMagics.history) | |
976 |
ip.define_magic( |
|
990 | #ip.define_magic('recall', HistoryMagics.rep) | |
977 | ip.define_magic("hist", magic_history) # Alternative name |
|
|||
978 | ip.define_magic("history", magic_history) |
|
|||
979 |
|
991 | |||
980 | # XXX - ipy_completers are in quarantine, need to be updated to new apis |
|
992 | # XXX - ipy_completers are in quarantine, need to be updated to new apis | |
981 | #import ipy_completers |
|
993 | #import ipy_completers |
General Comments 0
You need to be logged in to leave comments.
Login now