history.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. IKernel, KernelMessage
  5. } from 'jupyter-js-services';
  6. import {
  7. IDisposable
  8. } from 'phosphor/lib/core/disposable';
  9. import {
  10. clearSignalData
  11. } from 'phosphor/lib/core/signaling';
  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. * Construct a new console history object.
  54. */
  55. constructor(options?: ConsoleHistory.IOptions) {
  56. this._history = [];
  57. if (options.kernel) {
  58. this.kernel = options.kernel;
  59. }
  60. }
  61. /**
  62. * Get whether the console history manager is disposed.
  63. *
  64. * #### Notes
  65. * This is a read-only property.
  66. */
  67. get isDisposed(): boolean {
  68. return this._history === null;
  69. }
  70. /**
  71. * The current kernel supplying navigation history.
  72. */
  73. get kernel(): IKernel {
  74. return this._kernel;
  75. }
  76. set kernel(newValue: IKernel) {
  77. if (newValue === this._kernel) {
  78. return;
  79. }
  80. this._kernel = newValue;
  81. if (!this._kernel) {
  82. this._history.length = 0;
  83. return;
  84. }
  85. this._kernel.history(Private.initialRequest).then(v => this.onHistory(v));
  86. }
  87. /**
  88. * Dispose of the resources held by the console history manager.
  89. */
  90. dispose(): void {
  91. if (this.isDisposed) {
  92. return;
  93. }
  94. clearSignalData(this);
  95. this._history.length = 0;
  96. this._history = null;
  97. }
  98. /**
  99. * Get the previous item in the console history.
  100. *
  101. * @returns A Promise for console command text or `undefined` if unavailable.
  102. */
  103. back(): Promise<string> {
  104. let content = this._history[--this._cursor];
  105. this._cursor = Math.max(0, this._cursor);
  106. return Promise.resolve(content);
  107. }
  108. /**
  109. * Get the next item in the console history.
  110. *
  111. * @returns A Promise for console command text or `undefined` if unavailable.
  112. */
  113. forward(): Promise<string> {
  114. let content = this._history[++this._cursor];
  115. this._cursor = Math.min(this._history.length, this._cursor);
  116. return Promise.resolve(content);
  117. }
  118. /**
  119. * Add a new item to the bottom of history.
  120. *
  121. * @param item The item being added to the bottom of history.
  122. *
  123. * #### Notes
  124. * If the item being added is undefined or empty, it is ignored. If the item
  125. * being added is the same as the last item in history, it is ignored as well
  126. * so that the console's history will consist of no contiguous repetitions.
  127. * This behavior varies from some shells, but the Jupyter Qt Console is
  128. * implemented this way.
  129. */
  130. push(item: string): void {
  131. if (item && item !== this._history[this._history.length - 1]) {
  132. this._history.push(item);
  133. }
  134. // Reset the history navigation cursor back to the bottom.
  135. this._cursor = this._history.length;
  136. }
  137. /**
  138. * Populate the history collection on history reply from a kernel.
  139. *
  140. * @param value The kernel message history reply.
  141. *
  142. * #### Notes
  143. * History entries have the shape:
  144. * [session: number, line: number, input: string]
  145. * Contiguous duplicates are stripped out of the API response.
  146. */
  147. protected onHistory(value: KernelMessage.IHistoryReplyMsg): void {
  148. this._history = [];
  149. let last = '';
  150. let current = '';
  151. for (let i = 0; i < value.content.history.length; i++) {
  152. current = (value.content.history[i] as string[])[2];
  153. if (current !== last) {
  154. this._history.push(last = current);
  155. }
  156. }
  157. // Reset the history navigation cursor back to the bottom.
  158. this._cursor = this._history.length;
  159. }
  160. private _cursor = 0;
  161. private _history: string[] = null;
  162. private _kernel: IKernel = null;
  163. }
  164. /**
  165. * A namespace for ConsoleHistory statics.
  166. */
  167. export
  168. namespace ConsoleHistory {
  169. /**
  170. * The initialization options for a console history object.
  171. */
  172. export
  173. interface IOptions {
  174. /**
  175. * The kernel instance to query for history.
  176. */
  177. kernel?: IKernel;
  178. }
  179. }
  180. /**
  181. * A namespace for private data.
  182. */
  183. namespace Private {
  184. export
  185. const initialRequest: KernelMessage.IHistoryRequest = {
  186. output: false,
  187. raw: true,
  188. hist_access_type: 'tail',
  189. n: 500
  190. };
  191. }