##// END OF EJS Templates
Update history magics to new API.
Fernando Perez -
Show More
@@ -26,6 +26,7 b' import threading'
26 26
27 27 # Our own packages
28 28 from IPython.core.error import StdinNotImplementedError
29 from IPython.core.magic import Magics, register_magics, line_magic
29 30 from IPython.config.configurable import Configurable
30 31 from IPython.external.decorator import decorator
31 32 from IPython.testing.skipdoctest import skip_doctest
@@ -74,13 +75,13 b' class HistoryAccessor(Configurable):'
74 75 hist_file = Unicode(config=True,
75 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 profile
78 directory. If you would rather share one history among profiles,
79 you ca set this value in each, so that they are consistent.
78 By default, IPython will put the history database in the IPython
79 profile directory. If you would rather share one history among
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 mounts.
82 If you see IPython hanging, try setting this to something on a local disk,
83 e.g::
82 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
83 mounts. If you see IPython hanging, try setting this to something on a
84 local disk, e.g::
84 85
85 86 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
86 87
@@ -153,7 +154,8 b' class HistoryAccessor(Configurable):'
153 154 def init_db(self):
154 155 """Connect to the database, and create tables if necessary."""
155 156 # use detect_types so that timestamps return datetime objects
156 self.db = sqlite3.connect(self.hist_file, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
157 self.db = sqlite3.connect(self.hist_file,
158 detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
157 159 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
158 160 primary key autoincrement, start timestamp,
159 161 end timestamp, num_cmds integer, remark text)""")
@@ -216,7 +218,8 b' class HistoryAccessor(Configurable):'
216 218 Returns
217 219 -------
218 220
219 (session_id [int], start [datetime], end [datetime], num_cmds [int], remark [unicode])
221 (session_id [int], start [datetime], end [datetime], num_cmds [int],
222 remark [unicode])
220 223
221 224 Sessions that are running or did not exit cleanly will have `end=None`
222 225 and `num_cmds=None`.
@@ -512,7 +515,8 b' class HistoryManager(HistoryAccessor):'
512 515 session += self.session_number
513 516 if session==self.session_number: # Current session
514 517 return self._get_range_session(start, stop, raw, output)
515 return super(HistoryManager, self).get_range(session, start, stop, raw, output)
518 return super(HistoryManager, self).get_range(session, start, stop, raw,
519 output)
516 520
517 521 ## ----------------------------
518 522 ## Methods for storing history:
@@ -611,7 +615,9 b' class HistoryManager(HistoryAccessor):'
611 615 print("ERROR! Session/line number was not unique in",
612 616 "database. History logging moved to new session",
613 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 621 self._writeout_input_cache(conn)
616 622 except sqlite3.IntegrityError:
617 623 pass
@@ -718,264 +724,270 b' def _format_lineno(session, line):'
718 724 return "%s#%s" % (session, line)
719 725
720 726
721 @skip_doctest
722 def magic_history(self, parameter_s = ''):
723 """Print input history (_i<n> variables), with most recent last.
727 @register_magics
728 class HistoryMagics(Magics):
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
728 directly pasted into an editor. Use -n to show them.
735 %history [-o -p -t -n] [-f filename] [range | -g pattern | -l number]
729 736
730 By default, all input history from the current session is displayed.
731 Ranges of history can be indicated using the syntax:
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
737 By default, input history is printed without line numbers so it can be
738 directly pasted into an editor. Use -n to show them.
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.
745 This feature is only available if numbered prompts are in use.
752 Options:
746 753
747 -o: also print outputs for each input.
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
750 for making documentation, and in conjunction with -o, for producing
751 doctest-ready output.
757 -o: also print outputs for each input.
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
756 filters your input and converts it all into valid Python source before
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 /'.
763 -r: (default) print the 'raw' history, i.e. the actual commands you
764 typed.
761 765
762 -g: treat the arg as a pattern to grep for in (full) history.
763 This includes the saved history (almost all commands ever written).
764 Use '%hist -g' to show full saved history (may be very long).
766 -t: print the 'translated' history, as IPython understands it.
767 IPython filters your input and converts it all into valid Python
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
767 the default is the last 10 lines.
773 -g: treat the arg as a pattern to grep for in (full) history.
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
770 the given file. The file is always overwritten, though *when it can*,
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.
777 -l: get the last n lines from all sessions. Specify n as a single
778 arg, or the default is the last 10 lines.
774 779
775 Examples
776 --------
777 ::
778
779 In [6]: %hist -n 4-6
780 4:a = 12
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.
780 -f FILENAME: instead of printing the output to the screen, redirect
781 it to the given file. The file is always overwritten, though *when
782 it can*, IPython asks for confirmation first. In particular, running
783 the command 'history -f FILENAME' from the IPython Notebook
784 interface will replace FILENAME even if it already exists *without*
785 confirmation.
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 '_'
882 variable) to the next input prompt. Allows you to create elaborate command
883 lines without using copy-paste::
791 In [6]: %hist -n 4-6
792 4:a = 12
793 5:print a**2
794 6:%hist -n 4-6
884 795
885 In[1]: l = ["hei", "vaan"]
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.
796 """
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
899 input prompt. See %history for the slice syntax.
804 # For brevity
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
904 placed at the next input prompt. Otherwise, the history is searched
905 for lines which contain that substring, and the most recent one is
906 placed at the next input prompt.
907 """
908 if not arg: # Last output
909 self.shell.set_next_input(str(self.shell.user_ns["_"]))
910 return
911 # Get history range
912 histlines = self.shell.history_manager.get_range_by_str(arg)
913 cmd = "\n".join(x[2] for x in histlines)
914 if cmd:
915 self.shell.set_next_input(cmd.rstrip())
916 return
917
918 try: # Variable in user namespace
919 cmd = str(eval(arg, self.shell.user_ns))
920 except Exception: # Search for term in history
921 histlines = self.shell.history_manager.search("*"+arg+"*")
922 for h in reversed([x[2] for x in histlines]):
923 if 'rep' in h:
924 continue
925 self.shell.set_next_input(h.rstrip())
813 # Check if output to specific file was requested.
814 try:
815 outfname = opts['f']
816 except KeyError:
817 outfile = io.stdout # default
818 # We don't want to close stdout at the end!
819 close_at_end = False
820 else:
821 if os.path.exists(outfname):
822 try:
823 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
824 except StdinNotImplementedError:
825 ans = True
826 if not ans:
827 print('Aborting.')
828 return
829 print("Overwriting file.")
830 outfile = io_open(outfname, 'w', encoding='utf-8')
831 close_at_end = True
832
833 print_nums = 'n' in opts
834 get_output = 'o' in opts
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 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=''):
933 """Re-run previous input
945 @line_magic
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
936 (as with %history). With no arguments, it will repeat the last line.
949 By default, you can specify ranges of input history to be repeated
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
941 current command.
954 -l <n> : Repeat the last n lines of input, not including the
955 current command.
942 956
943 -g foo : Repeat the most recent line which contains foo
944 """
945 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
946 if "l" in opts: # Last n lines
947 n = int(opts['l'])
948 hist = self.shell.history_manager.get_tail(n)
949 elif "g" in opts: # Search
950 p = "*"+opts['g']+"*"
951 hist = list(self.shell.history_manager.search(p))
952 for l in reversed(hist):
953 if "rerun" not in l[2]:
954 hist = [l] # The last match which isn't a %rerun
955 break
956 else:
957 hist = [] # No matches except %rerun
958 elif args: # Specify history ranges
959 hist = self.shell.history_manager.get_range_by_str(args)
960 else: # Last line
961 hist = self.shell.history_manager.get_tail(1)
962 hist = [x[2] for x in hist]
963 if not hist:
964 print("No lines in history match specification")
965 return
966 histlines = "\n".join(hist)
967 print("=== Executing: ===")
968 print(histlines)
969 print("=== Output: ===")
970 self.shell.run_cell("\n".join(hist), store_history=False)
957 -g foo : Repeat the most recent line which contains foo
958 """
959 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
960 if "l" in opts: # Last n lines
961 n = int(opts['l'])
962 hist = self.shell.history_manager.get_tail(n)
963 elif "g" in opts: # Search
964 p = "*"+opts['g']+"*"
965 hist = list(self.shell.history_manager.search(p))
966 for l in reversed(hist):
967 if "rerun" not in l[2]:
968 hist = [l] # The last match which isn't a %rerun
969 break
970 else:
971 hist = [] # No matches except %rerun
972 elif args: # Specify history ranges
973 hist = self.shell.history_manager.get_range_by_str(args)
974 else: # Last line
975 hist = self.shell.history_manager.get_tail(1)
976 hist = [x[2] for x in hist]
977 if not hist:
978 print("No lines in history match specification")
979 return
980 histlines = "\n".join(hist)
981 print("=== Executing: ===")
982 print(histlines)
983 print("=== Output: ===")
984 self.shell.run_cell("\n".join(hist), store_history=False)
971 985
972 986
973 987 def init_ipython(ip):
974 ip.define_magic("rep", magic_rep)
975 ip.define_magic("recall", magic_rep)
976 ip.define_magic("rerun", magic_rerun)
977 ip.define_magic("hist", magic_history) # Alternative name
978 ip.define_magic("history", magic_history)
988 ip.magics_manager.register(HistoryMagics)
989 #ip.define_magic('hist', HistoryMagics.history)
990 #ip.define_magic('recall', HistoryMagics.rep)
979 991
980 992 # XXX - ipy_completers are in quarantine, need to be updated to new apis
981 993 #import ipy_completers
General Comments 0
You need to be logged in to leave comments. Login now