Documentation ¶
Overview ¶
Package goexec executes cells with Go code for the gonb kernel.
It defines a State object, that carries all the globals defined so far. It provides the ExecuteCell method, to run a new cell.
Index ¶
- Constants
- Variables
- func CurrentWorkingDirectoryForPid(pid int) (string, error)
- func DeclareStringConst(decls *Declarations, name, value string)
- func DeclareVariable(decls *Declarations, name, value string)
- func GoRoot() (string, error)
- func IsEmptyLines(lines []string, skipLines Set[int]) bool
- func JupyterErrorSplit(err error) (string, string, []string)
- func JupyterRootDirectory() (string, error)
- func TrimGonbCommentPrefix(line string) string
- type CellIdAndLine
- type CellLines
- type Constant
- type Cursor
- type Declarations
- func (d *Declarations) ClearCursor()
- func (d *Declarations) Copy() *Declarations
- func (d *Declarations) DropFuncInit()
- func (d *Declarations) MergeFrom(d2 *Declarations)
- func (d *Declarations) RenderConstants(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
- func (d *Declarations) RenderFunctions(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
- func (d *Declarations) RenderImports(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
- func (d *Declarations) RenderTypes(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
- func (d *Declarations) RenderVariables(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
- type ElementType
- type Function
- type GonbError
- type Import
- type State
- func (s *State) AlternativeDefinitionsPath() string
- func (s *State) AutoCompleteOptionsInCell(cellLines []string, skipLines map[int]struct{}, cursorLine, cursorCol int, ...) (err error)
- func (s *State) AutoTrack() (err error)
- func (s *State) BinaryPath() string
- func (s *State) CodePath() string
- func (s *State) Compile(msg kernel.Message, fileToCellIdAndLines []CellIdAndLine) error
- func (s *State) DefaultCellTestArgs() (args []string)
- func (s *State) DisplayErrorWithContext(msg kernel.Message, fileToCellIdAndLine []CellIdAndLine, errorMsg string, ...) error
- func (s *State) EnumerateUpdatedFiles(fn func(filePath string) error) (err error)
- func (s *State) Execute(msg kernel.Message, fileToCellIdAndLine []CellIdAndLine) error
- func (s *State) ExecuteCell(msg kernel.Message, cellId int, lines []string, skipLines Set[int]) error
- func (s *State) ExecuteWasm(msg kernel.Message) error
- func (s *State) ExportWasmConstants(decls *Declarations)
- func (s *State) GoImports(msg kernel.Message, decls *Declarations, mainDecl *Function, ...) (cursorInFile Cursor, updatedFileToCellIdAndLine []CellIdAndLine, err error)
- func (s *State) GoModInit() error
- func (s *State) GoWorkFix(msg kernel.Message) (err error)
- func (s *State) InspectIdentifierInCell(lines []string, skipLines map[int]struct{}, cursorLine, cursorCol int) (mimeMap kernel.MIMEMap, err error)
- func (s *State) ListTracked() []string
- func (s *State) MakeWasmSubdir() (err error)
- func (s *State) PostExecuteCell()
- func (s *State) RemoveCode() error
- func (s *State) RemoveWasmConstants(decls *Declarations)
- func (s *State) Reset()
- func (s *State) SetCellTests(decls *Declarations)
- func (s *State) Stop() error
- func (s *State) Track(fileOrDirPath string) (err error)
- func (s *State) Untrack(fileOrDirPath string) (err error)
- type TypeDecl
- type Variable
- type WriterWithCursor
- func (w *WriterWithCursor) Cursor() Cursor
- func (w *WriterWithCursor) CursorPlusDelta(delta Cursor) (fileCursor Cursor)
- func (w *WriterWithCursor) Error() error
- func (w *WriterWithCursor) FillLinesGap(fileToCellIdAndLine []CellIdAndLine) []CellIdAndLine
- func (w *WriterWithCursor) Write(content string)
- func (w *WriterWithCursor) Writef(format string, args ...any)
Constants ¶
const ( MainGo = "main.go" MainTestGo = "main_test.go" )
const ( // GoGetWorkspaceIssue is an err output by `go get` due to it not interpreting correctly `go.work`. GoGetWorkspaceIssue = "cannot find module providing package" // GoGetWorkspaceNote is the note that explains the issue with `go get` and `go work`. GoGetWorkspaceNote = `` /* 299-byte string literal not displayed */ )
const ( // GonbTempDirEnvName is the name of the environment variable that is set with // the temporary directory used to compile user's Go code. // It can be used by the executed Go code or by the bash scripts (started with `!`). GonbTempDirEnvName = "GONB_TMP_DIR" // InitFunctionPrefix -- functions named with this prefix will be rendered as // a separate `func init()`. InitFunctionPrefix = "init_" )
const ( JupyterSessionNameEnv = "JPY_SESSION_NAME" JupyterPidEnv = "JPY_PARENT_PID" JupyterFilesSubdir = "jupyter_files" CompiledWasmName = "gonb_cell.wasm" )
const GonbCommentPrefix = "//gonb:"
GonbCommentPrefix allows one to enter the special commands (`%%`, `!`) prefixed as a Go comment, so it doesn't conflict with Go IDEs. Particularly useful if using Jupytext.
const LinesForErrorContext = 3
LinesForErrorContext indicates how many lines to display in the error context, before and after the offending line. Hard-coded for now, but it could be made configurable.
const NoCursorLine = int(-1)
Variables ¶
var ( ParseError = fmt.Errorf("failed to parse cell contents") CursorLost = fmt.Errorf("cursor position not rendered in main.go") )
var NoCursor = Cursor{Line: NoCursorLine, Col: 0}
Functions ¶
func CurrentWorkingDirectoryForPid ¶
CurrentWorkingDirectoryForPid returns the "cwd" or an error.
func DeclareStringConst ¶
func DeclareStringConst(decls *Declarations, name, value string)
DeclareStringConst creates a const definition in `decls` for a string value.
func DeclareVariable ¶
func DeclareVariable(decls *Declarations, name, value string)
DeclareVariable creates a variable definition in `decls`. `value` is copied verbatim, so any type of variable goes.
func IsEmptyLines ¶ added in v0.10.0
IsEmptyLines returns true is all lines are marked to skip, or if all lines not marked as skip are empty.
func JupyterErrorSplit ¶
JupyterErrorSplit takes an error and formats it into the components Jupyter protocol uses for it.
It special cases the GonbError, where it adds each sub-error in the "traceback" repeated field.
func JupyterRootDirectory ¶
JupyterRootDirectory returns Jupyter's root directory. This is needed to build the URL from where it serves static files.
Unfortunately, this isn't directly provided by Jupyter. It does provide its PID number, but get the "cwd" (current-working-directory) differs for different OSes.
See question here: https://stackoverflow.com/questions/46247964/way-to-get-jupyter-server-root-directory/58988310#58988310
func TrimGonbCommentPrefix ¶ added in v0.10.2
TrimGonbCommentPrefix removes a prefixing "//gonb:" (GonbCommentPrefix) from line, if there is such a prefix. This is optionally used to escape special commands.
Types ¶
type CellIdAndLine ¶
type CellIdAndLine struct {
Id, Line int
}
CellIdAndLine points to a line within a cell. Id is the execution number of the cell, as given to ExecuteCell.
func MakeFileToCellIdAndLine ¶
func MakeFileToCellIdAndLine(cellId int, fileToCellLine []int) (fileToCellIdAndLine []CellIdAndLine)
MakeFileToCellIdAndLine converts a cellId and a slice of cell line numbers for a file to a slice of CellIdAndLine.
type CellLines ¶
type CellLines struct { // Id of the cell where the definition comes from. It is set to -1 if the declaration was automatically // created (for instance by goimports). Id int // Lines has one value per line used in the declaration. The point to the cell line where it was declared. // Some of these numbers may be NoCursorLine (-1) indicating that they are inserted automatically and don't. // have corresponding Lines in any cell. // // If Id is -1, Lines will be nil, which indicates the content didn't come from any cell. Lines []int }
CellLines identifies a cell (by its execution id) and the Lines corresponding to a declaration.
func (CellLines) Append ¶
func (c CellLines) Append(fileToCellIdAndLine []CellIdAndLine) []CellIdAndLine
Append id and line numbers to fileToCellIdAndLine, a slice of `CellIdAndLine`. This is used when rendering a declaration to a file.
type Constant ¶
type Constant struct { Cursor CellLines Key string TypeDefinition, ValueDefinition string // Can be empty, if used as iota. CursorInKey, CursorInType, CursorInValue bool Next, Prev *Constant // Next and previous declaration in same Const block. }
Constant represents the declaration of a constant. Because when appearing in block they inherit its definition form the previous line, we need to preserve the blocks. For this, we use Next/Prev links.
func (*Constant) Render ¶
func (c *Constant) Render(w *WriterWithCursor, cursor *Cursor, fileToCellIdAndLine []CellIdAndLine) []CellIdAndLine
Render Constant declaration (without the `const` keyword).
type Cursor ¶
type Cursor struct {
Line, Col int
}
Cursor represents a cursor position in a cell or file. The Col is given as bytes in the line expected to be encoded as UTF-8.
func (*Cursor) ClearCursor ¶
func (c *Cursor) ClearCursor()
ClearCursor resets the cursor to an invalid state. This method is needed for the structs that embed Cursor.
func (Cursor) CursorFrom ¶
CursorFrom returns a new Cursor adjusted
type Declarations ¶
type Declarations struct { Functions map[string]*Function Variables map[string]*Variable Types map[string]*TypeDecl Imports map[string]*Import Constants map[string]*Constant }
Declarations is a collection of declarations that we carry over from one cell to another.
func NewDeclarations ¶
func NewDeclarations() *Declarations
func (*Declarations) ClearCursor ¶
func (d *Declarations) ClearCursor()
ClearCursor wherever declaration it may be.
func (*Declarations) Copy ¶
func (d *Declarations) Copy() *Declarations
Copy returns a new deep copy of the declarations.
func (*Declarations) DropFuncInit ¶
func (d *Declarations) DropFuncInit()
DropFuncInit drops declarations of `func init()`: the parser generates this for the `func init_*`, and it shouldn't be considered new declarations if reading from generated code.
func (*Declarations) MergeFrom ¶
func (d *Declarations) MergeFrom(d2 *Declarations)
MergeFrom declarations in d2.
func (*Declarations) RenderConstants ¶
func (d *Declarations) RenderConstants(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
RenderConstants without comments for all constants in Declarations.
Constants are trickier to render because when they are defined in a block, using `iota`, their ordering matters. So we re-render them in the same order and blocks as they were originally parsed.
The ordering is given by the sort order of the first element of each `const` block.
func (*Declarations) RenderFunctions ¶
func (d *Declarations) RenderFunctions(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
RenderFunctions without comments, for all functions in Declarations.
func (*Declarations) RenderImports ¶
func (d *Declarations) RenderImports(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
RenderImports writes out `import ( ... )` for all imports in Declarations.
func (*Declarations) RenderTypes ¶
func (d *Declarations) RenderTypes(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
RenderTypes without comments.
func (*Declarations) RenderVariables ¶
func (d *Declarations) RenderVariables(w *WriterWithCursor, fileToCellIdAndLine []CellIdAndLine) (Cursor, []CellIdAndLine)
RenderVariables writes out `var ( ... )` for all variables in Declarations.
type ElementType ¶
type ElementType int
const ( Invalid ElementType = iota FunctionType ImportType VarType ConstType )
func (ElementType) String ¶
func (i ElementType) String() string
type Function ¶
type Function struct { Cursor CellLines Key string Name, Receiver string Definition string // Multi-line definition, includes comments preceding definition. }
Function definition, parsed from a notebook cell.
type GonbError ¶
type GonbError struct { Lines []errorLine // contains filtered or unexported fields }
GonbError is a special type of error that wraps a collection of errors returned by the Go compiler or `go get` or `go imports`.
Each error line (`GonbError.Lines`) holds some context stored in its own errorLine object. And it is also a wrapper for the failed execution error.
It can be rendered to HTML in the notebook with `GonbError.PublishWithHTML`.
func (*GonbError) Error ¶
Error implements golang `error` interface. In Jupyter protocol, it corresponds to the "evalue" field (as in "error value").
func (*GonbError) Name ¶
Name corresponds to field "ename" in Jupyter. Hardcoded in "ERROR" for now.
func (*GonbError) PublishWithHTML ¶
PublishWithHTML reports the GonbError as an HTML report in Jupyter.
type Import ¶
type Import struct { Cursor CellLines Key string Path, Alias string CursorInPath, CursorInAlias bool }
Import represents an import to be included -- if not used it's automatically removed by `goimports`.
type State ¶
type State struct { // Kernel is set when actually connecting to JupyterServer. // In tests its left as nil. Kernel *kernel.Kernel // Temporary directory where Go program is build at each execution. UniqueID, Package, TempDir string // Building and executing go code configuration: Args []string // Args to be passed to the program, after being executed. GoBuildFlags []string // Flags to be passed to `go build`, in State.Compile. AutoGet bool // Whether to do a "go get" before compiling, to fetch missing external modules. // Global elements defined mapped by their keys. Definitions *Declarations // CellIsTest indicates whether the current cell is to be compiled with `go test` (as opposed to `go build`). // This also triggers writing the code to `main_test.go` as opposed to `main.go`. // Usually this is set and reset after the execution -- the default being the normal build. CellIsTest bool CellTests []string // Tests defined in this cell. Only used if CellIsTest==true. CellHasBenchmarks bool // CellIsWasm indicates whether the current cell is to be compiled for WebAssembly (wasm). CellIsWasm bool WasmDir, WasmUrl, WasmDivId string // Comms represents the communication with the front-end. Comms *comms.State // CaptureFile is the file where to write any cell output. It is closed and set to nil at the end of the cell // executions. // If nil, no output is to be captured. CaptureFile io.WriteCloser // contains filtered or unexported fields }
State holds information about Go code execution for this kernel. It's a singleton (for now). It hols the directory, ids, configuration, command line arguments to use and currently defined Go code.
That is, if the user runs a cell that defines, let's say `func f(x int) int { return x+1 }`, the definition of `f` will be stored in Definitions field.
func New ¶
New returns an empty State object, that can be used to execute Cells.
If preserveTempDir is set to true, the temporary directory is logged, and it's preserved when the kernel exits -- helpful for debugging.
If rawError is true, the parsing of compiler errors doesn't generate HTML, instead it uses only text.
The kernel object passed in `k` can be nil for testing, but this may lead to some leaking goroutines, that stop when the kernel stops.
func (*State) AlternativeDefinitionsPath ¶
AlternativeDefinitionsPath is the path to a temporary file that holds the memorize definitions, when we are not able to include them in the `main.go`, because the current cell is not parseable.
func (*State) AutoCompleteOptionsInCell ¶
func (s *State) AutoCompleteOptionsInCell(cellLines []string, skipLines map[int]struct{}, cursorLine, cursorCol int, reply *kernel.CompleteReply) (err error)
AutoCompleteOptionsInCell implements a `complete_request` from Jupyter, using `gopls`. It updates `main.go` with the cell contents (given as Lines)
func (*State) AutoTrack ¶
AutoTrack adds automatic tracked directories. It looks at go.mod and go.work for redirects to the local filesystem.
func (*State) BinaryPath ¶
BinaryPath is the path to the generated binary file.
func (*State) CodePath ¶
CodePath is the path to where the code is going to be saved. Either `main.go` or `main_test.go` file.
func (*State) Compile ¶
func (s *State) Compile(msg kernel.Message, fileToCellIdAndLines []CellIdAndLine) error
Compile compiles the currently generate go files in State.TempDir to a binary named State.Package.
If errors in compilation happen, linesPos is used to adjust line numbers to their content in the current cell.
func (*State) DefaultCellTestArgs ¶
DefaultCellTestArgs generate the default `go test` arguments, if none is given. It includes `-test.v` and `-test.run` matching the tests defined in the current cell.
func (*State) DisplayErrorWithContext ¶
func (s *State) DisplayErrorWithContext(msg kernel.Message, fileToCellIdAndLine []CellIdAndLine, errorMsg string, err error) error
DisplayErrorWithContext in an HTML div, with a mouse-over pop-up window listing the Lines with the error, and highlighting the exact position.
Except if `rawError` is set to true (see `New() *State`): in which case the enriched GonbError is returned instead, for a textual report back.
Any errors within here are logged and simply ignored, since this is already used to report errors.
func (*State) EnumerateUpdatedFiles ¶
EnumerateUpdatedFiles calls fn for each file that has been updated since the last call. If `fn` returns an err, then the enumerations is interrupted and the err is returned.
func (*State) Execute ¶
func (s *State) Execute(msg kernel.Message, fileToCellIdAndLine []CellIdAndLine) error
Execute cell code already prepared to `${GONB_TMP_DIR}/main.go`.
If errors in execution happen, fileToCellIdAndLine helps to map the `main.go` line numbers to cell id and line, so errors can be annotated.
If s.CellIsWasm is true, it passes through State.ExecuteWasm.
func (*State) ExecuteCell ¶
func (s *State) ExecuteCell(msg kernel.Message, cellId int, lines []string, skipLines Set[int]) error
ExecuteCell takes the contents of a cell, parses it, merges new declarations with the ones from previous definitions, render a final main.go code with the whole content, compiles and runs it.
skipLines are Lines that should not be considered as Go code. Typically, these are the special commands (like `%%`, `%args`, `%reset`, or bash Lines starting with `!`).
func (*State) ExecuteWasm ¶
ExecuteWasm expects `wasm_exec.js` and CompiledWasmName to be in the directory pointed to `s.WasmDir` already.
func (*State) ExportWasmConstants ¶
func (s *State) ExportWasmConstants(decls *Declarations)
func (*State) GoImports ¶
func (s *State) GoImports(msg kernel.Message, decls *Declarations, mainDecl *Function, fileToCellIdAndLine []CellIdAndLine) (cursorInFile Cursor, updatedFileToCellIdAndLine []CellIdAndLine, err error)
GoImports execute `goimports` which adds imports to non-declared imports automatically. It also runs "go get" to download any missing dependencies.
It returns the updated cursorInFile and fileToCellIdAndLines that reflect any changes in `main.go`.
func (*State) GoModInit ¶
GoModInit removes current `go.mod` if it already exists, and recreate it with `go mod init`.
func (*State) GoWorkFix ¶
GoWorkFix takes all modules in `go.work` "use" clauses, and add them as "replace" clauses in `go.mod`. This is needed for `go get` to work.
func (*State) InspectIdentifierInCell ¶
func (s *State) InspectIdentifierInCell(lines []string, skipLines map[int]struct{}, cursorLine, cursorCol int) (mimeMap kernel.MIMEMap, err error)
InspectIdentifierInCell implements an `inspect_request` from Jupyter, using `gopls`. It updates `main.go` with the cell contents (given as Lines)
func (*State) ListTracked ¶
func (*State) MakeWasmSubdir ¶
MakeWasmSubdir creates a subdirectory named `.wasm/<notebook name>/` in the same directory as the notebook, if it is not yet created.
It also copies current Go compiler `wasm_exec.js` file to this directory, if it's not there already.
Path and URL to access it are stored in s.WasmDir and s.WasmUrl.
func (*State) PostExecuteCell ¶
func (s *State) PostExecuteCell()
PostExecuteCell reset state that is valid only for the duration of a cell. This includes s.CellIsTest and s.Args.
func (*State) RemoveCode ¶
RemoveCode removes the code files (`main.go` or `main_test.go`). Usually used just before creating creating a new version.
func (*State) RemoveWasmConstants ¶
func (s *State) RemoveWasmConstants(decls *Declarations)
func (*State) Reset ¶
func (s *State) Reset()
Reset clears all the memorized Go declarations. It becomes as if no cells had been executed so far -- except for configurations and arguments that remain unchanged.
It is connected to the special command `%reset`.
func (*State) SetCellTests ¶
func (s *State) SetCellTests(decls *Declarations)
SetCellTests sets the test functions (Test...) defined in this cell. The default for `%test` is to run only the current tests, this is the function that given the new declarations created in this cells, figures out which are those tests.
type TypeDecl ¶
type TypeDecl struct { Cursor CellLines Key string // Same as the name here. TypeDefinition string // Type definition which includes the name. CursorInType bool }
TypeDecl definition, parsed from a notebook cell.
type Variable ¶
type Variable struct { Cursor CellLines CursorInName, CursorInType, CursorInValue bool Key, Name string TypeDefinition, ValueDefinition string // Type definition may be empty. // TupleDefinitions are present when multiple variables are tied to the same definition as in `var a, b, c = someFunc()`. TupleDefinitions []*Variable }
Variable definition, parsed from a notebook cell.
There is one special case, where one variable entry will define multiple variables, when we have line like:
var a, b, c = someFuncThatReturnsATuple()
For such cases, one set TupleDefinitions in order ("a", "b", "c"). And we define the following behavior:
- Only the first element of TupleDefinitions is rendered, but it renders the tuple definition.
- If any of the elements of the tuple is redefined or removed, all elements are removed.
This means that if "a" is redefined, "b" and "c" disappear. And that if "b" or "c" are redefined, it will yield and error, that is subtle to track.
type WriterWithCursor ¶
type WriterWithCursor struct {
Line, Col int
// contains filtered or unexported fields
}
WriterWithCursor keep tabs of the current line/col of the file (presumably) being written.
func NewWriterWithCursor ¶
func NewWriterWithCursor(w io.Writer) *WriterWithCursor
NewWriterWithCursor that keeps tabs of current line/col of the file (presumably) being written.
func (*WriterWithCursor) Cursor ¶
func (w *WriterWithCursor) Cursor() Cursor
Cursor returns the current position in the file, at the end of what has been written so far.
func (*WriterWithCursor) CursorPlusDelta ¶
func (w *WriterWithCursor) CursorPlusDelta(delta Cursor) (fileCursor Cursor)
CursorPlusDelta returns the expected cursor position in the current file, assuming the original cursor is cursorDelta away from the current position in the file (stored in w).
Semantically it's equivalent to `w.Cursor() + cursorDelta`.
func (*WriterWithCursor) Error ¶
func (w *WriterWithCursor) Error() error
Error returns first err that happened during writing.
func (*WriterWithCursor) FillLinesGap ¶
func (w *WriterWithCursor) FillLinesGap(fileToCellIdAndLine []CellIdAndLine) []CellIdAndLine
FillLinesGap append NoCursorLine (-1) line indices to fileToCellIdAndLine slice, up to the current line.
func (*WriterWithCursor) Write ¶
func (w *WriterWithCursor) Write(content string)
Write writes the given content and keeps track of cursor. Errors can be retrieved with Error.
func (*WriterWithCursor) Writef ¶
func (w *WriterWithCursor) Writef(format string, args ...any)
Writef write with formatted text. Errors can be retrieved with Error.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package goplsclient runs `gopls` (1) in the background uses it to retrieve definitions of symbols and auto-complete.
|
Package goplsclient runs `gopls` (1) in the background uses it to retrieve definitions of symbols and auto-complete. |