history.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. IDisposable
  5. } from 'phosphor-disposable';
  6. import {
  7. clearSignalData
  8. } from 'phosphor-signaling';
  9. import {
  10. IKernel, KernelMessage
  11. } from 'jupyter-js-services';
  12. /**
  13. * The definition of a console history manager object.
  14. */
  15. export
  16. interface IConsoleHistory extends IDisposable {
  17. /**
  18. * The current kernel supplying navigation history.
  19. */
  20. kernel: IKernel;
  21. /**
  22. * Get the previous item in the console history.
  23. *
  24. * @returns A Promise for console command text or `undefined` if unavailable.
  25. */
  26. back(): Promise<string>;
  27. /**
  28. * Get the next item in the console history.
  29. *
  30. * @returns A Promise for console command text or `undefined` if unavailable.
  31. */
  32. forward(): Promise<string>;
  33. /**
  34. * Add a new item to the bottom of history.
  35. *
  36. * @param item The item being added to the bottom of history.
  37. *
  38. * #### Notes
  39. * If the item being added is undefined or empty, it is ignored. If the item
  40. * being added is the same as the last item in history, it is ignored as well
  41. * so that the console's history will consist of no contiguous repetitions.
  42. * This behavior varies from some shells, but the Jupyter Qt Console is
  43. * implemented this way.
  44. */
  45. push(item: string): void;
  46. }
  47. /**
  48. * A console history manager object.
  49. */
  50. export
  51. class ConsoleHistory implements IConsoleHistory {
  52. /**
  53. * Get whether the console history manager is disposed.
  54. *
  55. * #### Notes
  56. * This is a read-only property.
  57. */
  58. get isDisposed(): boolean {
  59. return this._history === null;
  60. }
  61. /**
  62. * The current kernel supplying navigation history.
  63. */
  64. get kernel(): IKernel {
  65. return this._kernel;
  66. }
  67. set kernel(newValue: IKernel) {
  68. if (newValue === this._kernel) {
  69. return;
  70. }
  71. let contents = Private.initialRequest;
  72. this._kernel = newValue;
  73. this._kernel.history(contents).then((value: KernelMessage.IHistoryReplyMsg) => {
  74. this._history = [];
  75. let last = '';
  76. let current = '';
  77. for (let i = 0; i < value.content.history.length; i++) {
  78. // History entries have the shape:
  79. // [session: number, line: number, input: string]
  80. // Contiguous duplicates are stripped out of the API response.
  81. current = (value.content.history[i] as string[])[2];
  82. if (current !== last) {
  83. this._history.push(last = current);
  84. }
  85. }
  86. // Reset the history navigation cursor back to the bottom.
  87. this._cursor = this._history.length;
  88. });
  89. }
  90. /**
  91. * Construct a new console history object.
  92. */
  93. constructor(kernel: IKernel) {
  94. this._history = [];
  95. if (kernel) {
  96. this.kernel = kernel;
  97. }
  98. }
  99. /**
  100. * Get the previous item in the console history.
  101. *
  102. * @returns A Promise for console command text or `undefined` if unavailable.
  103. */
  104. back(): Promise<string> {
  105. let content = this._history[--this._cursor];
  106. this._cursor = Math.max(0, this._cursor);
  107. return Promise.resolve(content);
  108. }
  109. /**
  110. * Dispose of the resources held by the console history manager.
  111. */
  112. dispose(): void {
  113. if (this.isDisposed) {
  114. return;
  115. }
  116. clearSignalData(this);
  117. this._history.length = 0;
  118. this._history = null;
  119. }
  120. /**
  121. * Get the next item in the console history.
  122. *
  123. * @returns A Promise for console command text or `undefined` if unavailable.
  124. */
  125. forward(): Promise<string> {
  126. let content = this._history[++this._cursor];
  127. this._cursor = Math.min(this._history.length, this._cursor);
  128. return Promise.resolve(content);
  129. }
  130. /**
  131. * Add a new item to the bottom of history.
  132. *
  133. * @param item The item being added to the bottom of history.
  134. *
  135. * #### Notes
  136. * If the item being added is undefined or empty, it is ignored. If the item
  137. * being added is the same as the last item in history, it is ignored as well
  138. * so that the console's history will consist of no contiguous repetitions.
  139. * This behavior varies from some shells, but the Jupyter Qt Console is
  140. * implemented this way.
  141. */
  142. push(item: string): void {
  143. if (item && item !== this._history[this._history.length - 1]) {
  144. this._history.push(item);
  145. }
  146. // Reset the history navigation cursor back to the bottom.
  147. this._cursor = this._history.length;
  148. }
  149. private _cursor = 0;
  150. private _history: string[] = null;
  151. private _kernel: IKernel = null;
  152. }
  153. /**
  154. * A namespace for private data.
  155. */
  156. namespace Private {
  157. export
  158. const initialRequest: KernelMessage.IHistoryRequest = {
  159. output: false,
  160. raw: true,
  161. hist_access_type: 'tail',
  162. n: 500
  163. };
  164. }