2024-02-10 19:02:11 +01:00
import * as vscode from 'vscode' ;
2024-08-21 18:56:48 +02:00
import * as codemp from '@codemp/codemp' ; // TODO why won't it work with a custom name???
2024-02-14 15:42:40 +01:00
import * as mapping from "./mapping" ;
import { LOGGER } from './extension' ;
2024-02-10 19:02:11 +01:00
2024-02-12 19:22:50 +01:00
2024-02-14 15:42:40 +01:00
let CACHE = new codemp . OpCache ( ) ;
let MAPPINGS = new mapping . BufferMappingContainer ( ) ;
2024-02-10 19:02:11 +01:00
let smallNumberDecorationType = vscode . window . createTextEditorDecorationType ( { } ) ;
2024-08-21 18:56:48 +02:00
let client : codemp.Client | null = null ;
let workspace : codemp.Workspace | null = null ;
let username : string ;
2024-02-12 19:22:50 +01:00
2024-02-10 19:02:11 +01:00
2024-02-12 19:22:50 +01:00
2024-08-21 18:56:48 +02:00
export async function connect ( ) {
2024-02-12 19:22:50 +01:00
let username = await vscode . window . showInputBox ( { prompt : "enter username" } ) ;
2024-08-21 18:56:48 +02:00
if ( username === null ) throw "choose an username" ;
client = await codemp . connect ( "http://codemp.alemi.dev:50053" , username ! , "lmaodefaultpassword" ) ;
2024-02-10 19:02:11 +01:00
}
export async function join() {
2024-02-12 19:22:50 +01:00
let workspace_id = await vscode . window . showInputBox ( { prompt : "workspace to attach (default to default)" } ) ;
2024-02-10 19:02:11 +01:00
//let editor = vscode.window.activeTextEditor;
2024-02-12 19:22:50 +01:00
if ( workspace_id === undefined ) return // user cancelled with ESC
if ( workspace_id . length == 0 ) workspace_id = "asd"
2024-02-10 19:02:11 +01:00
2024-02-12 19:22:50 +01:00
if ( client === null ) throw "connect first" ;
2024-08-21 18:56:48 +02:00
workspace = await client . join_workspace ( workspace_id )
2024-02-12 19:22:50 +01:00
let controller = workspace . cursor ( ) ;
2024-08-21 18:56:48 +02:00
controller . callback ( ( event : codemp.Cursor ) = > {
let range_start : vscode.Position = new vscode . Position ( event . startRow , event . startCol ) ; // -1?
let range_end : vscode.Position = new vscode . Position ( event . endRow , event . endCol ) ; // -1? idk if this works it's kinda funny, should test with someone with a working version of codemp
2024-02-10 19:02:11 +01:00
const decorationRange = new vscode . Range ( range_start , range_end ) ;
smallNumberDecorationType . dispose ( ) ;
smallNumberDecorationType = vscode . window . createTextEditorDecorationType ( {
borderWidth : '5px' ,
borderStyle : 'solid' ,
overviewRulerColor : 'blue' ,
overviewRulerLane : vscode.OverviewRulerLane.Right ,
light : {
// this color will be used in light color themes
borderColor : 'darkblue' //should create this color based on event.user (uuid)
} ,
dark : {
// this color will be used in dark color themes
borderColor : 'lightblue' //should create this color based on event.user (uuid)
}
} ) ;
2024-02-14 15:42:40 +01:00
let m = MAPPINGS . get_by_buffer ( event . buffer ) ;
if ( m === null ) return ;
m . editor . setDecorations ( smallNumberDecorationType , [ decorationRange ] ) ;
2024-02-10 19:02:11 +01:00
} ) ;
vscode . window . onDidChangeTextEditorSelection ( ( event : vscode.TextEditorSelectionChangeEvent ) = > {
if ( event . kind == vscode . TextEditorSelectionChangeKind . Command ) return ; // TODO commands might move cursor too
2024-02-12 19:22:50 +01:00
let buf = event . textEditor . document . uri ;
2024-02-10 19:02:11 +01:00
let selection : vscode.Selection = event . selections [ 0 ] // TODO there may be more than one cursor!!
let anchor : [ number , number ] = [ selection . anchor . line , selection . anchor . character ] ;
let position : [ number , number ] = [ selection . active . line , selection . active . character + 1 ] ;
2024-02-14 15:42:40 +01:00
let n = MAPPINGS . get_by_editor ( buf )
if ( n === null ) return ;
2024-08-21 18:56:48 +02:00
let cursor : codemp.Cursor = {
startRow : selection.anchor.line ,
startCol : selection.anchor.character ,
endRow : selection.active.line ,
endCol : selection.active.character + 1 ,
buffer : n.buffer.get_name ( ) ,
user : username
}
controller . send ( cursor ) ;
2024-02-10 19:02:11 +01:00
} ) ;
2024-02-12 19:22:50 +01:00
console . log ( "workspace id \n" ) ;
console . log ( workspace . id ( ) ) ;
2024-02-10 19:02:11 +01:00
vscode . window . showInformationMessage ( ` Connected to workspace @[ ${ workspace } ] ` ) ;
}
export async function createBuffer() {
let bufferName : any = ( await vscode . window . showInputBox ( { prompt : "path of the buffer to create" } ) ) ! ;
2024-02-12 19:22:50 +01:00
if ( workspace === null ) throw "join a workspace first"
workspace . create ( bufferName ) ;
2024-02-10 19:02:11 +01:00
console . log ( "new buffer created " , bufferName , "\n" ) ;
}
export async function attach() {
let buffer_name : any = ( await vscode . window . showInputBox ( { prompt : "buffer to attach to" } ) ) ! ;
2024-02-12 19:22:50 +01:00
if ( workspace === null ) throw "join a workspace first"
2024-08-21 18:56:48 +02:00
let buffer : codemp.BufferController = await workspace . attach ( buffer_name ) ;
2024-02-10 19:02:11 +01:00
console . log ( "attached to buffer" , buffer_name ) ;
console . log ( "buffer" , buffer ) ;
let editor = vscode . window . activeTextEditor ;
if ( editor === undefined ) {
let fileUri = buffer_name ;
let random = ( Math . random ( ) + 1 ) . toString ( 36 ) . substring ( 2 ) ;
const fileName = '' + random ;
//const newFileUri = vscode.Uri.file(fileName).with({ scheme: 'untitled', path: fileName });
//Create a document not a file so it's temp and it doesn't get saved
const newFileUri = vscode . Uri . file ( fileName ) . with ( { scheme : 'untitled' , path : "" } ) ;
//vscode.workspace.openTextDocument()
await vscode . workspace . openTextDocument ( newFileUri ) ;
2024-02-14 15:42:40 +01:00
vscode . commands . executeCommand ( 'vscode.open' , newFileUri ) ; //It should already be opened with the api command above idk why i do this?
2024-02-10 19:02:11 +01:00
//vscode.window.showInformationMessage(`Open a file first`);
//return;
}
editor = vscode . window . activeTextEditor ! ;
//console.log("Buffer = ", buffer, "\n");
vscode . window . showInformationMessage ( ` Connected to codemp workspace buffer @[ ${ buffer_name } ] ` ) ;
let file_uri : vscode.Uri = editor . document . uri ;
2024-02-14 15:42:40 +01:00
MAPPINGS . put ( new mapping . BufferMapping ( buffer , editor ) ) ;
2024-02-10 19:02:11 +01:00
vscode . workspace . onDidChangeTextDocument ( ( event :vscode.TextDocumentChangeEvent ) = > {
if ( event . document . uri != file_uri ) return ; // ?
for ( let change of event . contentChanges ) {
if ( CACHE . get ( buffer_name , change . rangeOffset , change . text , change . rangeOffset + change . rangeLength ) ) continue ;
2024-02-14 15:42:40 +01:00
LOGGER . info ( ` onDidChangeTextDocument(event: [ ${ change . rangeOffset } , ${ change . text } , ${ change . rangeOffset + change . rangeLength } ]) ` ) ;
2024-02-10 19:02:11 +01:00
buffer . send ( {
start : change.rangeOffset ,
2024-08-21 18:56:48 +02:00
end : change.rangeOffset + change . rangeLength ,
content : change.text
2024-02-10 19:02:11 +01:00
} ) ;
}
} ) ;
2024-08-21 18:56:48 +02:00
buffer . callback ( ( event : codemp.TextChange ) = > {
LOGGER . info ( ` buffer.callback(event: [ ${ event . start } , ${ event . content } , ${ event . end } ]) ` )
CACHE . put ( buffer_name , event . start , event . content , event . end ) ;
2024-02-10 19:02:11 +01:00
2024-02-14 15:42:40 +01:00
if ( editor === undefined ) { throw "Open an editor first" }
2024-02-10 19:02:11 +01:00
let range = new vscode . Range (
2024-08-21 18:56:48 +02:00
editor . document . positionAt ( event . start ) ,
editor . document . positionAt ( event . end )
2024-02-10 19:02:11 +01:00
)
editor . edit ( editBuilder = > {
editBuilder
. replace ( range , event . content )
2024-02-14 15:42:40 +01:00
} ) ;
2024-02-10 19:02:11 +01:00
} ) ;
}
2024-02-12 19:22:50 +01:00
/ * e x p o r t a s y n c f u n c t i o n d i s c o n n e c t B u f f e r ( ) { T O D O i s h o u l d j u s t s e t b u f f e r = n u l l
2024-02-10 19:02:11 +01:00
let buffer : string = ( await vscode . window . showInputBox ( { prompt : "buffer name for the file to disconnect from" } ) ) ! ;
codemp . disconnectBuffer ( buffer ) ;
vscode . window . showInformationMessage ( ` Disconnected from codemp workspace buffer @[ ${ buffer } ] ` ) ;
2024-02-12 19:22:50 +01:00
} * /
2024-02-10 19:02:11 +01:00
export async function sync() {
2024-02-14 15:42:40 +01:00
if ( workspace === null ) throw "join a workspace first" ;
2024-02-10 19:02:11 +01:00
let editor = vscode . window . activeTextEditor ;
2024-02-14 15:42:40 +01:00
if ( editor === undefined ) throw "no active editor to sync" ;
let k = MAPPINGS . get_by_editor ( editor . document . uri ) ;
if ( k === null ) throw "No such buffer managed by codemp"
2024-08-21 18:56:48 +02:00
let buffer = workspace . buffer_by_name ( k . buffer . get_name ( ) ) ;
2024-02-14 15:42:40 +01:00
if ( buffer == null ) throw "This buffer does not exist anymore" ;
2024-08-21 18:56:48 +02:00
let content = await buffer . content ( ) ;
2024-02-14 15:42:40 +01:00
let doc_len = editor . document . getText ( ) . length ;
let range = new vscode . Range (
editor . document . positionAt ( 0 ) ,
editor . document . positionAt ( doc_len )
) ;
2024-08-21 18:56:48 +02:00
CACHE . put ( k . buffer . get_name ( ) , 0 , content , doc_len ) ;
2024-02-14 15:42:40 +01:00
editor . edit ( editBuilder = > editBuilder . replace ( range , content ) ) ;
2024-02-10 19:02:11 +01:00
}
2024-02-12 19:22:50 +01:00
export async function listBuffers ( ) {
if ( workspace === null ) throw "join a workspace first"
let buffers = workspace . filetree ( ) ;
console . log ( buffers ) ; // improve UX
}
2024-02-10 19:02:11 +01:00
// This method is called when your extension is deactivated
export function deactivate() {
//Maybe i should disconnect from every workspace and buffer ??? // TODO
}
2024-02-14 15:42:40 +01:00
export function printOpCache() {
console . log ( "CACHE\n" ) ;
console . log ( CACHE . toString ( ) ) ;
2024-08-21 18:56:48 +02:00
}