@@ -2,6 +2,14 @@ import vscode from 'vscode';
22import { detectLanguage } from './processors/detectLanguage' ;
33import { fileHeaders } from './processors/fileHeaders' ;
44import { languages } from './processors/languages' ;
5+ import { config } from '../config' ;
6+
7+ var decoder = new TextDecoder ( "utf8" ) ;
8+
9+ function getNotebookDocument ( document :vscode . TextDocument ) :vscode . NotebookDocument | undefined {
10+ return vscode . workspace . notebookDocuments
11+ . find ( x => x . uri . path === document . uri . path ) ;
12+ }
513
614export async function preparePrompt ( document :vscode . TextDocument , position :vscode . Position , context :vscode . InlineCompletionContext ) {
715
@@ -11,6 +19,75 @@ export async function preparePrompt(document: vscode.TextDocument, position: vsc
1119let prefix = text . slice ( 0 , offset ) ;
1220let suffix :string = text . slice ( offset ) ;
1321
22+ let notebookConfig = config . notebook ;
23+
24+ // If this is a notebook, add the surrounding cells to the prefix and suffix
25+ let notebookDocument = getNotebookDocument ( document ) ;
26+ let language = detectLanguage ( document . uri . fsPath , document . languageId ) ;
27+ let commentStart :string | undefined = undefined ;
28+ if ( language ) {
29+ commentStart = languages [ language ] . comment ?. start ;
30+ }
31+
32+ if ( notebookDocument ) {
33+ let beforeCurrentCell = true ;
34+
35+ let prefixCells = "" ;
36+ let suffixCells = "" ;
37+
38+ notebookDocument . getCells ( ) . forEach ( ( cell ) => {
39+ let out = "" ;
40+
41+ if ( cell . document . uri . fragment === document . uri . fragment ) {
42+ beforeCurrentCell = false ; // switch to suffix mode
43+ return ;
44+ }
45+
46+ // add the markdown cell output to the prompt as a comment
47+ if ( cell . kind === vscode . NotebookCellKind . Markup && commentStart ) {
48+ if ( notebookConfig . includeMarkup ) {
49+ for ( const line of cell . document . getText ( ) . split ( '\n' ) ) {
50+ out += `\n${ commentStart } ${ line } ` ;
51+ }
52+ }
53+ } else {
54+ out += cell . document . getText ( ) ;
55+ }
56+
57+ // if there is any outputs add them to the prompt as a comment
58+ const addCellOutputs = notebookConfig . includeCellOutputs
59+ && beforeCurrentCell
60+ && cell . kind === vscode . NotebookCellKind . Code
61+ && commentStart ;
62+ if ( addCellOutputs ) {
63+ let cellOutputs = cell . outputs
64+ . map ( x => x . items
65+ . filter ( x => x . mime === 'text/plain' )
66+ . map ( x => decoder . decode ( x . data ) )
67+ . map ( x => x . slice ( 0 , notebookConfig . cellOutputLimit ) . split ( '\n' ) ) )
68+ . flat ( 3 ) ;
69+
70+ if ( cellOutputs . length > 0 ) {
71+ out += `\n${ commentStart } Output:` ;
72+ for ( const line of cellOutputs ) {
73+ out += `\n${ commentStart } ${ line } ` ;
74+ }
75+ }
76+ }
77+
78+ // update the prefix/suffix
79+ if ( beforeCurrentCell ) {
80+ prefixCells += out ;
81+ } else {
82+ suffixCells += out ;
83+ }
84+
85+ } ) ;
86+
87+ prefix = prefixCells + prefix ;
88+ suffix = suffix + suffixCells ;
89+ }
90+
1491// Trim suffix
1592// If suffix is too small it is safe to assume that it could be ignored which would allow us to use
1693// more powerful completition instead of in middle one
@@ -22,7 +99,6 @@ export async function preparePrompt(document: vscode.TextDocument, position: vsc
2299// NOTE: Most networks don't have a concept of filenames and expected language, but we expect that some files in training set has something in title that
23100// would indicate filename and language
24101// NOTE: If we can't detect language, we could ignore this since the number of languages that need detection is limited
25- let language = detectLanguage ( document . uri . fsPath , document . languageId ) ;
26102if ( language ) {
27103prefix = fileHeaders ( prefix , document . uri . fsPath , languages [ language ] ) ;
28104}