feat: updatedd to 0.8.0

This commit is contained in:
zaaarf 2024-10-17 02:51:53 +02:00
parent 70aeca3d17
commit 7464a69ee9
No known key found for this signature in database
GPG key ID: C91CFF9E2262BBA1
25 changed files with 304 additions and 134 deletions

View file

@ -21,7 +21,7 @@ repositories {
dependencies { dependencies {
implementation variantOf(libs.codemp) { implementation variantOf(libs.codemp) {
classifier osdetector.classifier classifier 'all'
} }
compileOnly libs.lombok compileOnly libs.lombok

View file

@ -1,5 +1,5 @@
[versions] [versions]
codemp = '0.7.3' codemp = '0.8.0'
lombok = '1.18.34' lombok = '1.18.34'
intellij-plugin = '2.0.1' intellij-plugin = '2.0.1'
git-version = '3.1.0' git-version = '3.1.0'

View file

@ -52,8 +52,8 @@ public class CodeMP {
.orElseThrow(IllegalStateException::new); .orElseThrow(IllegalStateException::new);
} }
public static void joinWorkspace(String workspaceId) throws ConnectionException { public static void attachWorkspace(String workspaceId) throws ConnectionException {
CodeMP.getClient("join workspace").joinWorkspace(workspaceId); CodeMP.getClient("attach workspace").attachWorkspace(workspaceId);
ACTIVE_WORKSPACE_ID = workspaceId; ACTIVE_WORKSPACE_ID = workspaceId;
} }

View file

@ -12,7 +12,6 @@ import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.Messages;
import mp.code.BufferController; import mp.code.BufferController;
import mp.code.data.TextChange;
import mp.code.exceptions.ControllerException; import mp.code.exceptions.ControllerException;
import mp.code.intellij.CodeMP; import mp.code.intellij.CodeMP;
import mp.code.intellij.util.FileUtil; import mp.code.intellij.util.FileUtil;
@ -20,16 +19,14 @@ import mp.code.intellij.util.InteractionUtil;
import mp.code.intellij.util.cb.BufferCallback; import mp.code.intellij.util.cb.BufferCallback;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalLong;
public class BufferAttachAction extends AnAction { public class BufferAttachAction extends AnAction {
@Override @Override
public void actionPerformed(@NotNull AnActionEvent e) { public void actionPerformed(@NotNull AnActionEvent e) {
Project proj = e.getProject(); Project proj = e.getProject();
String[] filetree = CodeMP.getActiveWorkspace().getFileTree(Optional.empty(), false); String[] filetree = CodeMP.getActiveWorkspace().searchBuffers(Optional.empty());
int choice = Messages.showChooseDialog( int choice = Messages.showChooseDialog(
"Attach to which buffer?", "Attach to which buffer?",
"CodeMP Buffer Attach", "CodeMP Buffer Attach",
@ -38,7 +35,6 @@ public class BufferAttachAction extends AnAction {
Messages.getQuestionIcon() Messages.getQuestionIcon()
); );
// TODO check out of bounds but should be guaranteed by intellij
String path = filetree[choice]; String path = filetree[choice];
Editor editor = FileUtil.getActiveEditorByPath(proj, path); Editor editor = FileUtil.getActiveEditorByPath(proj, path);

View file

@ -8,28 +8,27 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class WorkspaceJoinAction extends AnAction { public class WorkspaceAttachAction extends AnAction {
@Override @Override
public void actionPerformed(@NotNull AnActionEvent e) { public void actionPerformed(@NotNull AnActionEvent e) {
String[] availableWorkspaces = InteractionUtil.listWorkspaces(e.getProject(), true, true); String[] availableWorkspaces = InteractionUtil.listWorkspaces(e.getProject(), true, true);
if(availableWorkspaces.length == 0) { if(availableWorkspaces.length == 0) {
Messages.showErrorDialog( Messages.showErrorDialog(
"There are no available workspaces. Ensure you have rights to access at least one!", "There are no available workspaces. Ensure you have rights to access at least one!",
"CodeMP Join Workspace" "CodeMP Attach To Workspace"
); );
return; return;
} }
int choice = Messages.showDialog( // TODO NOT THE ONE int choice = Messages.showChooseDialog(
e.getProject(), "Please choose a workspace to attach to:",
"Please choose a workspace to join:", "CodeMP Attach Workspace",
"CodeMP Join Workspace",
availableWorkspaces, availableWorkspaces,
0, "",
Messages.getQuestionIcon() Messages.getQuestionIcon()
); );
InteractionUtil.joinWorkspace(e.getProject(), availableWorkspaces[choice], null); InteractionUtil.attachWorkspace(e.getProject(), availableWorkspaces[choice], null);
} }
@Override @Override

View file

@ -21,12 +21,11 @@ public class WorkspaceDeleteAction extends AnAction {
return; return;
} }
int choice = Messages.showDialog( // TODO NOT THE ONE int choice = Messages.showChooseDialog(
e.getProject(),
"Please choose a workspace to delete:", "Please choose a workspace to delete:",
"CodeMP Delete Workspace", "CodeMP Delete Workspace",
availableWorkspaces, availableWorkspaces,
0, "",
Messages.getQuestionIcon() Messages.getQuestionIcon()
); );

View file

@ -8,9 +8,6 @@ import mp.code.intellij.CodeMP;
import mp.code.intellij.util.InteractionUtil; import mp.code.intellij.util.InteractionUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
public class WorkspaceInviteAction extends AnAction { public class WorkspaceInviteAction extends AnAction {
@Override @Override
public void actionPerformed(@NotNull AnActionEvent e) { public void actionPerformed(@NotNull AnActionEvent e) {
@ -23,12 +20,11 @@ public class WorkspaceInviteAction extends AnAction {
return; return;
} }
int choice = Messages.showDialog( // TODO NOT THE ONE int choice = Messages.showChooseDialog(
e.getProject(),
"Please choose a workspace to invite to:", "Please choose a workspace to invite to:",
"CodeMP Invite To Workspace", "CodeMP Invite To Workspace",
availableWorkspaces, availableWorkspaces,
0, "",
Messages.getQuestionIcon() Messages.getQuestionIcon()
); );

View file

@ -12,7 +12,7 @@ import java.util.Objects;
public class WorkspaceLeaveAction extends AnAction { public class WorkspaceLeaveAction extends AnAction {
@Override @Override
public void actionPerformed(@NotNull AnActionEvent e) { public void actionPerformed(@NotNull AnActionEvent e) {
String workspaceId = CodeMP.getActiveWorkspace().getWorkspaceId(); String workspaceId = CodeMP.getActiveWorkspace().id();
InteractionUtil.leaveWorkspace(Objects.requireNonNull(e.getProject()), workspaceId, null); InteractionUtil.leaveWorkspace(Objects.requireNonNull(e.getProject()), workspaceId, null);
} }

View file

@ -1,13 +0,0 @@
package mp.code.intellij.exceptions.ide;
import mp.code.intellij.exceptions.CodeMPIJException;
/**
* Fired when trying to use {@link com.intellij.openapi.actionSystem.AnActionEvent}'s context
* from a state where that use is not supported.
*/
public class BadActionEventStateException extends CodeMPIJException {
public BadActionEventStateException(String s) {
super(s);
}
}

View file

@ -1,13 +0,0 @@
package mp.code.intellij.exceptions.ide;
import mp.code.intellij.exceptions.CodeMPIJException;
/**
* Thrown upon failure to detach from a buffer.
*/
public class BufferDetachException extends CodeMPIJException {
public BufferDetachException(String name) {
super(String.format("Could not detach from buffer named \"%s\"!", name));
}
}

View file

@ -14,7 +14,6 @@ import org.jetbrains.annotations.NotNull;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalLong;
public class BufferEventListener implements DocumentListener { public class BufferEventListener implements DocumentListener {
@ -51,8 +50,7 @@ public class BufferEventListener implements DocumentListener {
controller.send(new TextChange( controller.send(new TextChange(
changeOffset, changeOffset,
changeOffset + event.getOldFragment().length(), changeOffset + event.getOldFragment().length(),
newFragment.toString(), newFragment.toString()
OptionalLong.empty()
)); ));
} catch(ControllerException e) { } catch(ControllerException e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View file

@ -3,6 +3,7 @@ package mp.code.intellij.listeners;
import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import mp.code.data.Selection;
import mp.code.exceptions.ControllerException; import mp.code.exceptions.ControllerException;
import mp.code.intellij.CodeMP; import mp.code.intellij.CodeMP;
import mp.code.intellij.util.FileUtil; import mp.code.intellij.util.FileUtil;
@ -10,7 +11,6 @@ import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.event.CaretEvent; import com.intellij.openapi.editor.event.CaretEvent;
import com.intellij.openapi.editor.event.CaretListener; import com.intellij.openapi.editor.event.CaretListener;
import mp.code.data.Cursor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -21,7 +21,7 @@ public class CursorEventListener implements CaretListener {
@Override @Override
public void caretPositionChanged(@NotNull CaretEvent event) { public void caretPositionChanged(@NotNull CaretEvent event) {
// TODO instead of returning, should un-set remote ursor position (once) // TODO instead of returning, should un-set remote cursor position (once)
Caret caret = event.getCaret(); Caret caret = event.getCaret();
if(caret == null) return; if(caret == null) return;
@ -68,13 +68,12 @@ public class CursorEventListener implements CaretListener {
new Thread(() -> ApplicationManager.getApplication().runReadAction(() -> { new Thread(() -> ApplicationManager.getApplication().runReadAction(() -> {
try { try {
CodeMP.getActiveWorkspace().getCursor().send(new Cursor( CodeMP.getActiveWorkspace().cursor().send(new Selection(
startPos.line, startPos.line,
startPos.column, startPos.column,
endPos.line, endPos.line,
endPos.column, endPos.column,
FileUtil.getRelativePath(editor.getProject(), editor.getVirtualFile()), FileUtil.getRelativePath(editor.getProject(), editor.getVirtualFile())
null
)); ));
} catch(ControllerException e) { } catch(ControllerException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -87,8 +86,8 @@ public class CursorEventListener implements CaretListener {
new Thread(() -> ApplicationManager.getApplication().runReadAction(() -> { new Thread(() -> ApplicationManager.getApplication().runReadAction(() -> {
try { try {
CodeMP.getActiveWorkspace() CodeMP.getActiveWorkspace()
.getCursor() .cursor()
.send(new Cursor(0, 0, 0, 0, "", null)); .send(new Selection(0, 0, 0, 0, ""));
} catch(ControllerException e) { } catch(ControllerException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View file

@ -25,10 +25,8 @@ import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalLong;
public class CodeMPToolPanel extends JPanel { public class CodeMPToolPanel extends JPanel {
public CodeMPToolPanel(Project project) { public CodeMPToolPanel(Project project) {
@ -62,7 +60,7 @@ public class CodeMPToolPanel extends JPanel {
TreePath path = tree.getPathForLocation(e.getX(), e.getY()); TreePath path = tree.getPathForLocation(e.getX(), e.getY());
if(path == null) return; if(path == null) return;
String workspaceName = path.getLastPathComponent().toString(); String workspaceName = path.getLastPathComponent().toString();
InteractionUtil.joinWorkspace( InteractionUtil.attachWorkspace(
project, project,
workspaceName, workspaceName,
() -> CodeMPToolPanel.this.redraw(project) () -> CodeMPToolPanel.this.redraw(project)
@ -111,8 +109,7 @@ public class CodeMPToolPanel extends JPanel {
controller.get().send(new TextChange( controller.get().send(new TextChange(
0, 0,
0, 0,
ed.getDocument().getText(), ed.getDocument().getText()
OptionalLong.empty()
)); ));
ApplicationManager.getApplication().runWriteAction(() -> { ApplicationManager.getApplication().runWriteAction(() -> {
try { try {
@ -129,7 +126,7 @@ public class CodeMPToolPanel extends JPanel {
}), BorderLayout.NORTH); }), BorderLayout.NORTH);
Workspace ws = CodeMP.getActiveWorkspace(); Workspace ws = CodeMP.getActiveWorkspace();
JTree tree = drawTree(ws.getWorkspaceId(), ws.getFileTree(Optional.empty(), false)); JTree tree = drawTree(ws.id(), ws.searchBuffers(Optional.empty()));
tree.addMouseListener(new SimpleMouseListener() { tree.addMouseListener(new SimpleMouseListener() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
@ -158,7 +155,7 @@ public class CodeMPToolPanel extends JPanel {
this.add(tree, BorderLayout.CENTER); this.add(tree, BorderLayout.CENTER);
JList<String> userlist = new JBList<>(ws.userList()); JList<String> userlist = new JBList<>(CodeMP.HIGHLIGHTER_MAP.keySet()); // TODO shouldn't use this
this.add(userlist, BorderLayout.SOUTH); this.add(userlist, BorderLayout.SOUTH);
} }
} }

View file

@ -75,12 +75,12 @@ public class FileUtil {
return CodeMP.getClient("buffer access") return CodeMP.getClient("buffer access")
.getWorkspace(path.getWorkspaceName()) .getWorkspace(path.getWorkspaceName())
.flatMap(ws -> { .flatMap(ws -> {
String[] matches = ws.getFileTree(Optional.of(path.getRealPath()), true); String[] matches = ws.searchBuffers(Optional.of(path.getRealPath()));
if(matches.length == 0) return Optional.empty(); if(matches.length == 0) return Optional.empty();
Optional<BufferController> controller = ws.getBuffer(path.getRealPath()); Optional<BufferController> controller = ws.getBuffer(path.getRealPath());
if(controller.isPresent()) return controller; if(controller.isPresent()) return controller;
try { try {
return Optional.of(ws.attachToBuffer(path.getRealPath())); return Optional.of(ws.attachBuffer(path.getRealPath()));
} catch(ConnectionException e) { } catch(ConnectionException e) {
return Optional.empty(); return Optional.empty();
} }

View file

@ -25,6 +25,8 @@ import mp.code.intellij.listeners.CursorEventListener;
import mp.code.intellij.settings.CodeMPSettings; import mp.code.intellij.settings.CodeMPSettings;
import mp.code.intellij.ui.CodeMPToolPanel; import mp.code.intellij.ui.CodeMPToolPanel;
import mp.code.intellij.util.cb.CursorCallback; import mp.code.intellij.util.cb.CursorCallback;
import mp.code.intellij.util.cb.WorkspaceCallback;
import org.apache.commons.lang3.ArrayUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -121,17 +123,17 @@ public class InteractionUtil {
}); });
} }
public static void joinWorkspace(@NotNull Project project, @NotNull String workspaceId, @Nullable Runnable after) { public static void attachWorkspace(@NotNull Project project, @NotNull String workspaceId, @Nullable Runnable after) {
ProgressManager.getInstance().run(new Task.Backgroundable(project, String.format("Joining workspace %s...", workspaceId)) { ProgressManager.getInstance().run(new Task.Backgroundable(project, String.format("Joining workspace %s...", workspaceId)) {
@Override @Override
public void run(@NotNull ProgressIndicator indicator) { public void run(@NotNull ProgressIndicator indicator) {
try { try {
CodeMP.joinWorkspace(workspaceId); CodeMP.attachWorkspace(workspaceId);
MemoryManager.startWorkspaceLifetime(workspaceId); MemoryManager.startWorkspaceLifetime(workspaceId);
refreshToolWindow(project); refreshToolWindow(project);
} catch(ConnectionException e) { } catch(ConnectionException e) {
InteractionUtil.notifyError(project, String.format( InteractionUtil.notifyError(project, String.format(
"Failed to join workspace %s!", "Failed to attach to workspace %s!",
workspaceId workspaceId
), e); ), e);
return; return;
@ -145,10 +147,14 @@ public class InteractionUtil {
eventMulticaster.addDocumentListener(new BufferEventListener(), lifetime); eventMulticaster.addDocumentListener(new BufferEventListener(), lifetime);
eventMulticaster.addCaretListener(new CursorEventListener(), lifetime); eventMulticaster.addCaretListener(new CursorEventListener(), lifetime);
CodeMP.getActiveWorkspace().getCursor().callback(controller -> { CodeMP.getActiveWorkspace().cursor().callback(controller -> {
new CursorCallback(this.myProject).accept(controller); new CursorCallback(this.myProject).accept(controller);
}); });
CodeMP.getActiveWorkspace().callback(receiver -> {
new WorkspaceCallback(this.myProject).accept(receiver);
});
if(after != null) after.run(); if(after != null) after.run();
notifyInfo( notifyInfo(
@ -169,7 +175,7 @@ public class InteractionUtil {
client.deleteWorkspace(workspaceId); client.deleteWorkspace(workspaceId);
Optional<Workspace> ws = client.getWorkspace("workspace leave"); Optional<Workspace> ws = client.getWorkspace("workspace leave");
if(ws.isPresent() && ws.get().getWorkspaceId().equals(workspaceId)) { if(ws.isPresent() && ws.get().id().equals(workspaceId)) {
CodeMP.leaveWorkspace(); CodeMP.leaveWorkspace();
MemoryManager.endWorkspaceLifetime(workspaceId); MemoryManager.endWorkspaceLifetime(workspaceId);
} }
@ -181,11 +187,11 @@ public class InteractionUtil {
notifyInfo( notifyInfo(
project, project,
"Success", "Success",
String.format("Joined workspace %s!", workspaceId) String.format("Deleted workspace %s!", workspaceId)
); );
} catch(ConnectionException e) { } catch(ConnectionException e) {
InteractionUtil.notifyError(project, String.format( InteractionUtil.notifyError(project, String.format(
"Failed to join workspace %s!", "Failed to delete workspace %s!",
workspaceId workspaceId
), e); ), e);
} }
@ -210,10 +216,19 @@ public class InteractionUtil {
}); });
} }
public static String[] listWorkspaces(Project project, boolean owned, boolean invited) { public static String[] listWorkspaces(Project project, boolean owned, boolean joined) {
try { try {
Client client = CodeMP.getClient("drawActiveWorkspaces"); Client client = CodeMP.getClient("drawActiveWorkspaces");
return client.listWorkspaces(owned, invited);
String[] ownedWorkspaces;
if(owned) ownedWorkspaces = client.fetchOwnedWorkspaces();
else ownedWorkspaces = new String[0];
String[] joinedWorkspaces;
if(joined) joinedWorkspaces = client.fetchJoinedWorkspaces();
else joinedWorkspaces = new String[0];
return ArrayUtils.addAll(ownedWorkspaces, joinedWorkspaces);
} catch(ConnectionRemoteException exception) { } catch(ConnectionRemoteException exception) {
notifyError(project, "Failed to list workspaces!", exception); notifyError(project, "Failed to list workspaces!", exception);
return new String[0]; return new String[0];
@ -222,12 +237,12 @@ public class InteractionUtil {
public static Optional<BufferController> bufferAttach(Project project, Workspace workspace, String path) { public static Optional<BufferController> bufferAttach(Project project, Workspace workspace, String path) {
try { try {
BufferController controller = workspace.attachToBuffer(path); BufferController controller = workspace.attachBuffer(path);
MemoryManager.startBufferLifetime(workspace.getWorkspaceId(), path); MemoryManager.startBufferLifetime(workspace.id(), path);
notifyInfo(project, "Success!", String.format( notifyInfo(project, "Success!", String.format(
"Successfully attached to buffer %s on workspace %s!", "Successfully attached to buffer %s on workspace %s!",
path, path,
workspace.getWorkspaceId()) workspace.id())
); );
return Optional.of(controller); return Optional.of(controller);
} catch(ConnectionException e) { } catch(ConnectionException e) {

View file

@ -7,7 +7,7 @@ import com.intellij.openapi.project.Project;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import mp.code.BufferController; import mp.code.BufferController;
import mp.code.Extensions; import mp.code.Extensions;
import mp.code.data.TextChange; import mp.code.data.BufferUpdate;
import mp.code.exceptions.ControllerException; import mp.code.exceptions.ControllerException;
import mp.code.intellij.CodeMP; import mp.code.intellij.CodeMP;
import mp.code.intellij.util.FileUtil; import mp.code.intellij.util.FileUtil;
@ -30,35 +30,40 @@ public class BufferCallback implements Consumer<BufferController> {
ApplicationManager.getApplication().runReadAction(() -> { ApplicationManager.getApplication().runReadAction(() -> {
Editor editor = FileUtil.getActiveEditorByPath(this.project, bufferController.getName()); Editor editor = FileUtil.getActiveEditorByPath(this.project, bufferController.getName());
ApplicationManager.getApplication().invokeLaterOnWriteThread(() -> { ApplicationManager.getApplication().invokeLaterOnWriteThread(() -> {
List<TextChange> changeList = new ArrayList<>(); List<BufferUpdate> updateList = new ArrayList<>();
while(true) { while(true) {
Optional<TextChange> changeOptional; Optional<BufferUpdate> updateOptional;
try { try {
changeOptional = bufferController.tryRecv(); updateOptional = bufferController.tryRecv();
} catch(ControllerException ex) { } catch(ControllerException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
if(changeOptional.isEmpty()) if(updateOptional.isEmpty())
break; break;
TextChange change = changeOptional.get(); BufferUpdate update = updateOptional.get();
CodeMP.LOGGER.debug(String.format( CodeMP.LOGGER.debug(String.format(
"Received text change %s from offset %d to %d!", "Received text change %s from offset %d to %d!",
change.content, update.change.content,
change.start, update.change.startIdx,
change.end update.change.endIdx
)); ));
changeList.add(change); updateList.add(update);
} }
ApplicationManager.getApplication().runWriteAction(() -> { ApplicationManager.getApplication().runWriteAction(() -> {
CommandProcessor.getInstance().executeCommand( CommandProcessor.getInstance().executeCommand(
this.project, this.project,
() -> changeList.forEach((change) -> { () -> updateList.forEach((update) -> {
editor.getDocument().replaceString((int) change.start, (int) change.end, change.content); editor.getDocument().replaceString(
(int) update.change.startIdx,
(int) update.change.endIdx,
update.change.content
);
bufferController.ack(update.version);
// check for validity, force-sync if mismatch // check for validity, force-sync if mismatch
// TODO: prompt instead of doing it silently // TODO: prompt instead of doing it silently
if(change.hash.isPresent() && change.hash.getAsLong() != Extensions.hash(editor.getDocument().getText())) { if(update.hash.isPresent() && update.hash.getAsLong() != Extensions.hash(editor.getDocument().getText())) {
try { try {
editor.getDocument().setText(bufferController.getContent()); editor.getDocument().setText(bufferController.getContent());
} catch(ControllerException ignored) {} // ignore exception } catch(ControllerException ignored) {} // ignore exception

View file

@ -39,24 +39,24 @@ public class CursorCallback implements Consumer<CursorController> {
CodeMP.LOGGER.debug(String.format( CodeMP.LOGGER.debug(String.format(
"Cursor moved by user %s! Start pos: %dx %dy; end pos: %dx %dy in buffer %s!", "Cursor moved by user %s! Start pos: %dx %dy; end pos: %dx %dy in buffer %s!",
event.user, event.user,
event.startCol, event.selection.startCol,
event.startRow, event.selection.startRow,
event.endCol, event.selection.endCol,
event.endRow, event.selection.endRow,
event.buffer event.selection.buffer
)); ));
try { try {
ApplicationManager.getApplication().runReadAction(() -> { ApplicationManager.getApplication().runReadAction(() -> {
Editor editor = FileUtil.getActiveEditorByPath(this.project, event.buffer); Editor editor = FileUtil.getActiveEditorByPath(this.project, event.selection.buffer);
if(editor == null) { if(editor == null) {
RangeHighlighter previous = CodeMP.HIGHLIGHTER_MAP.remove(event.user); RangeHighlighter previous = CodeMP.HIGHLIGHTER_MAP.remove(event.user);
if(previous != null) previous.dispose(); if(previous != null) previous.dispose();
return; return;
} }
int startOffset = editor.getDocument().getLineStartOffset(event.startRow) + event.startCol; int startOffset = editor.getDocument().getLineStartOffset(event.selection.startRow) + event.selection.startCol;
int endOffset = editor.getDocument().getLineStartOffset(event.endRow) + event.endCol; int endOffset = editor.getDocument().getLineStartOffset(event.selection.endRow) + event.selection.endCol;
int documentLength = editor.getDocument().getTextLength(); int documentLength = editor.getDocument().getTextLength();
if(startOffset > documentLength || endOffset > documentLength) { if(startOffset > documentLength || endOffset > documentLength) {

View file

@ -0,0 +1,46 @@
package mp.code.intellij.util.cb;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.project.Project;
import lombok.RequiredArgsConstructor;
import mp.code.Workspace;
import mp.code.exceptions.ControllerException;
import mp.code.intellij.CodeMP;
import mp.code.intellij.util.InteractionUtil;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
@RequiredArgsConstructor
@SuppressWarnings("OptionalGetWithoutIsPresent")
public class WorkspaceCallback implements Consumer<Workspace> {
private static final Executor WORKSPACE_EXECUTOR = Executors.newSingleThreadExecutor();
private final Project project;
@Override
public void accept(Workspace workspace) {
WORKSPACE_EXECUTOR.execute(() -> {
try {
while(true) {
Optional<Workspace.Event> possibleEvent = workspace.tryRecv();
if(possibleEvent.isEmpty()) return;
Workspace.Event event = possibleEvent.get();
switch(event.getType()) {
case USER_JOIN, FILE_TREE_UPDATED -> {}
case USER_LEAVE -> {
RangeHighlighter prev = CodeMP.HIGHLIGHTER_MAP.remove(event.getUserLeft().get());
if(prev != null) prev.dispose();
InteractionUtil.refreshToolWindow(this.project);
}
}
InteractionUtil.refreshToolWindow(this.project);
}
} catch(ControllerException ex) {
InteractionUtil.notifyError(project, "Error receiving event", ex);
}
});
}
}

View file

@ -38,7 +38,7 @@ public class CodeMPDirectory extends CodeMPFile {
return CodeMP.getClient("get folder children") return CodeMP.getClient("get folder children")
.getWorkspace(this.path.getWorkspaceName()) .getWorkspace(this.path.getWorkspaceName())
.map(ws -> .map(ws ->
Arrays.stream(ws.getFileTree(Optional.of(this.path.getRealPath()), false)) Arrays.stream(ws.searchBuffers(Optional.of(this.path.getRealPath())))
.map(p -> new CodeMPPath(this.path.getWorkspaceName(), p)) .map(p -> new CodeMPPath(this.path.getWorkspaceName(), p))
.map(CodeMPPath::join) .map(CodeMPPath::join)
.map(this.fileSystem::findFileByPath) .map(this.fileSystem::findFileByPath)

View file

@ -51,11 +51,15 @@ public class CodeMPFile extends VirtualFile {
@Override @Override
public boolean isValid() { public boolean isValid() {
return false;
/* TODO
return CodeMP.getClient("validity check") return CodeMP.getClient("validity check")
.getWorkspace(this.path.getWorkspaceName()) .getWorkspace(this.path.getWorkspaceName())
.map(ws -> ws.getBuffer(this.path.getRealPath()).isPresent())
.map(ws -> ws.getFileTree(Optional.of(this.path.getRealPath()), true)) .map(ws -> ws.getFileTree(Optional.of(this.path.getRealPath()), true))
.map(buf -> buf.length != 0) .map(buf -> buf.length != 0)
.orElse(false); .orElse(false);
*/
} }
@Override @Override

View file

@ -68,10 +68,14 @@ public class CodeMPFileSystem extends VirtualFileSystem { // implements NonPhysi
} }
private CodeMPFile fileOrFolderByPath(CodeMPPath cmpPath) { private CodeMPFile fileOrFolderByPath(CodeMPPath cmpPath) {
return null;
/* TODO
return CodeMP.getClient("file seek") return CodeMP.getClient("file seek")
.getWorkspace(cmpPath.getWorkspaceName()) .getWorkspace(cmpPath.getWorkspaceName())
.filter(ws -> ws.getFileTree(Optional.ofNullable(cmpPath.getRealPath()), true).length != 0).map(ws -> new CodeMPFile(this, cmpPath)) .filter(ws -> ws.getFileTree(Optional.ofNullable(cmpPath.getRealPath()), true).length != 0).map(ws -> new CodeMPFile(this, cmpPath))
.orElseGet(() -> new CodeMPDirectory(this, cmpPath)); .orElseGet(() -> new CodeMPDirectory(this, cmpPath));
*/
} }
@ -132,7 +136,7 @@ public class CodeMPFileSystem extends VirtualFileSystem { // implements NonPhysi
if(ws.isPresent()) { if(ws.isPresent()) {
CodeMPPath newFilePath = parent.path.resolve(fileName); CodeMPPath newFilePath = parent.path.resolve(fileName);
ws.get().createBuffer(newFilePath.getRealPath()); ws.get().createBuffer(newFilePath.getRealPath());
ws.get().attachToBuffer(newFilePath.getRealPath()); ws.get().attachBuffer(newFilePath.getRealPath());
return new CodeMPFile(this, newFilePath); return new CodeMPFile(this, newFilePath);
} else { } else {
throw new IOException("failed to find workspace!"); // TODO do it better throw new IOException("failed to find workspace!"); // TODO do it better
@ -170,7 +174,7 @@ public class CodeMPFileSystem extends VirtualFileSystem { // implements NonPhysi
.orElseThrow(() -> new IOException("Non existing buffer for old file!")); .orElseThrow(() -> new IOException("Non existing buffer for old file!"));
BufferController destinationController = FileUtil.getRelevantBufferController(cfile.path) BufferController destinationController = FileUtil.getRelevantBufferController(cfile.path)
.orElseThrow(() -> new IOException("Non existing buffer for new file!")); .orElseThrow(() -> new IOException("Non existing buffer for new file!"));
destinationController.send(new TextChange(0, 0, oldController.getContent(), OptionalLong.empty())); destinationController.send(new TextChange(0, 0, oldController.getContent()));
return newFile; return newFile;
} catch(ControllerException ex) { } catch(ControllerException ex) {
throw new IOException(ex); throw new IOException(ex);

View file

@ -1,7 +1,7 @@
<idea-plugin> <idea-plugin>
<id>mp.code.intellij</id> <id>mp.code.intellij</id>
<name>CodeMP</name> <name>CodeMP</name>
<vendor email="me@zaaarf.foo" url="https://code.mp">CodeMP</vendor> <vendor email="support@codemp.dev" url="https://code.mp">CodeMP</vendor>
<description>A plugin for MultiPlayer code editing across different IDEs.</description> <description>A plugin for MultiPlayer code editing across different IDEs.</description>
@ -15,8 +15,8 @@
<group id="codemp.workspace" text="Workspace" popup="true"> <group id="codemp.workspace" text="Workspace" popup="true">
<action id="codemp.workspace.create" class="mp.code.intellij.actions.workspace.WorkspaceCreateAction" <action id="codemp.workspace.create" class="mp.code.intellij.actions.workspace.WorkspaceCreateAction"
text="Create Workspace"/> text="Create Workspace"/>
<action id="codemp.workspace.join" class="mp.code.intellij.actions.workspace.WorkspaceJoinAction" <action id="codemp.workspace.join" class="mp.code.intellij.actions.workspace.WorkspaceAttachAction"
text="Join Workspace"/> text="Attach To Workspace"/>
<action id="codemp.workspace.invite" class="mp.code.intellij.actions.workspace.WorkspaceInviteAction" <action id="codemp.workspace.invite" class="mp.code.intellij.actions.workspace.WorkspaceInviteAction"
text="Invite To Workspace"/> text="Invite To Workspace"/>
<action id="codemp.workspace.delete" class="mp.code.intellij.actions.workspace.WorkspaceDeleteAction" <action id="codemp.workspace.delete" class="mp.code.intellij.actions.workspace.WorkspaceDeleteAction"
@ -40,11 +40,14 @@
</actions> </actions>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<!--
<virtualFileSystem <virtualFileSystem
id="codemp_vfs" id="codemp_vfs"
key="codemp" key="codemp"
physical="false" physical="false"
implementationClass="mp.code.intellij.vfs.CodeMPFileSystem"/> implementationClass="mp.code.intellij.vfs.CodeMPFileSystem"/>
<workspaceModel.fileIndexContributor implementation="mp.code.intellij.vfs.CodeMPFileIndexContributor" />
-->
<notificationGroup id="CodeMP" displayType="BALLOON"/> <notificationGroup id="CodeMP" displayType="BALLOON"/>
<applicationService serviceImplementation="mp.code.intellij.settings.CodeMPSettings"/> <applicationService serviceImplementation="mp.code.intellij.settings.CodeMPSettings"/>
<applicationConfigurable <applicationConfigurable
@ -52,11 +55,11 @@
instance="mp.code.intellij.settings.CodeMPSettingsConfigurable" instance="mp.code.intellij.settings.CodeMPSettingsConfigurable"
id="mp.code.intellij.settings.CodeMPSettingsConfigurable" id="mp.code.intellij.settings.CodeMPSettingsConfigurable"
displayName="CodeMP"/> displayName="CodeMP"/>
<workspaceModel.fileIndexContributor implementation="mp.code.intellij.vfs.CodeMPFileIndexContributor" />
<toolWindow <toolWindow
id="CodeMP" id="CodeMP"
factoryClass="mp.code.intellij.ui.CodeMPWindowFactory" factoryClass="mp.code.intellij.ui.CodeMPWindowFactory"
anchor="right" anchor="right"
icon="/icons/codempToolWindow.svg"
doNotActivateOnStart="false" /> doNotActivateOnStart="false" />
</extensions> </extensions>
</idea-plugin> </idea-plugin>

View file

@ -2,13 +2,13 @@
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg <svg
width="100mm" width="99mm"
height="100mm" height="100mm"
viewBox="0 0 100 100" viewBox="0 0 99 100"
version="1.1" version="1.1"
id="svg1" id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="logo.svg" sodipodi:docname="codemp-bg-path.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -23,40 +23,53 @@
inkscape:pagecheckerboard="0" inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050" inkscape:deskcolor="#505050"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:zoom="1.3166807" inkscape:zoom="1.4142136"
inkscape:cx="94.935697" inkscape:cx="123.74368"
inkscape:cy="141.64406" inkscape:cy="215.31401"
inkscape:window-width="1870" inkscape:window-width="2510"
inkscape:window-height="1006" inkscape:window-height="1366"
inkscape:window-x="25" inkscape:window-x="25"
inkscape:window-y="45" inkscape:window-y="525"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="layer1" /> inkscape:current-layer="layer2" />
<defs <defs
id="defs1" /> id="defs1" />
<g <g
inkscape:label="Layer 1" inkscape:groupmode="layer"
id="layer2"
inkscape:label="bg"
transform="matrix(0.98644132,0,0,0.99829382,-2.055445e-4,-0.00373152)">
<ellipse
style="fill:#292835;fill-opacity:1;stroke:#201f29;stroke-width:0.99648;stroke-dasharray:none;stroke-opacity:1"
id="path1"
cx="50.194847"
cy="50.078178"
rx="49.671059"
ry="49.5756"
inkscape:label="circle" />
</g>
<g
inkscape:label="fg"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="matrix(0.98311673,0,0,0.98311673,-37.145524,-20.419013)" transform="matrix(0.85361601,0,0,0.85361601,-26.16631,-11.14309)">
style="stroke-width:0.50858661;stroke-dasharray:none;stroke:#000000;stroke-opacity:1;fill:#010101;fill-opacity:1">
<path <path
style="font-weight:bold;font-size:90.3111px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#010101;stroke:#000000;stroke-width:0.50858661;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1" style="font-weight:bold;font-size:33.8667px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#ada9a1;stroke-width:0.264583"
d="m 80.686333,71.922312 q 5.115277,1.940277 7.231943,5.409258 2.116667,3.468981 2.116667,9.995369 V 102.2024 q 0,2.82222 1.881481,3.99815 1.881481,1.11713 5.644443,1.11713 v 14.11111 q -10.524535,0 -16.580553,-4.70371 -5.997221,-4.7037 -5.997221,-14.52268 V 87.326939 q 0,-4.762499 -3.821758,-6.702777 -3.762963,-1.940277 -11.230091,-1.940277 V 64.572776 q 7.467128,0 11.230091,-1.940277 3.821758,-1.940278 3.821758,-6.702777 v -14.87546 q 0,-9.81898 5.997221,-14.522683 6.056018,-4.703703 16.580553,-4.703703 v 14.111109 q -3.762962,0 -5.644443,1.175925 -1.881481,1.11713 -1.881481,3.939352 v 14.87546 q 0,6.526388 -2.116667,9.995369 -2.116666,3.468981 -7.231943,5.409258 z"
id="text6"
inkscape:label="{"
aria-label="{" />
<path
style="font-weight:bold;font-size:33.8667px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#010101;stroke:#000000;stroke-width:0.50858661;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
d="m 103.39005,77.574239 v 8.995842 h 1.36701 q 1.89618,0 2.75608,-0.176389 1.49931,-0.308681 2.38125,-1.477258 0.904,-1.168578 0.904,-2.844274 0,-1.675696 -0.904,-2.844273 -0.88194,-1.168578 -2.38125,-1.477259 -0.8599,-0.176389 -2.75608,-0.176389 z m -5.644455,-5.291672 h 6.967365 q 3.2632,0 4.65226,0.33073 3.13091,0.749653 5.09324,3.285246 1.98438,2.513544 1.98438,6.173617 0,3.660073 -1.98438,6.195666 -1.96233,2.513544 -5.09324,3.263197 -1.38906,0.33073 -4.65226,0.33073 h -1.32291 v 11.465287 h -5.644455 z" d="m 103.39005,77.574239 v 8.995842 h 1.36701 q 1.89618,0 2.75608,-0.176389 1.49931,-0.308681 2.38125,-1.477258 0.904,-1.168578 0.904,-2.844274 0,-1.675696 -0.904,-2.844273 -0.88194,-1.168578 -2.38125,-1.477259 -0.8599,-0.176389 -2.75608,-0.176389 z m -5.644455,-5.291672 h 6.967365 q 3.2632,0 4.65226,0.33073 3.13091,0.749653 5.09324,3.285246 1.98438,2.513544 1.98438,6.173617 0,3.660073 -1.98438,6.195666 -1.96233,2.513544 -5.09324,3.263197 -1.38906,0.33073 -4.65226,0.33073 h -1.32291 v 11.465287 h -5.644455 z"
id="text4" id="text4"
inkscape:label="P" inkscape:label="P"
aria-label="P" /> aria-label="P" />
<path <path
style="font-weight:bold;font-size:33.8667px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#010101;stroke:#000000;stroke-width:0.50858661;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1" style="font-weight:bold;font-size:33.8667px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#ada9a1;stroke-width:0.264583"
d="M 103.24182,69.128189 H 97.597369 V 38.083715 h 5.644451 l 4.12309,9.657301 h 0.24254 l 4.10104,-9.657301 h 5.64445 v 31.044474 h -5.64445 V 49.372615 h -0.22048 l -2.80018,5.644449 h -2.42535 l -2.80017,-5.732644 h -0.22049 z" d="M 103.24182,69.128189 H 97.597369 V 38.083715 h 5.644451 l 4.12309,9.657301 h 0.24254 l 4.10104,-9.657301 h 5.64445 v 31.044474 h -5.64445 V 49.372615 h -0.22048 l -2.80018,5.644449 h -2.42535 l -2.80017,-5.732644 h -0.22049 z"
id="text5" id="text5"
inkscape:label="M" inkscape:label="M"
aria-label="M" /> aria-label="M" />
<path
style="font-weight:bold;font-size:90.3111px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#ada9a1;stroke-width:0.264583"
d="m 80.686333,71.922312 q 5.115277,1.940277 7.231943,5.409258 2.116667,3.468981 2.116667,9.995369 V 102.2024 q 0,2.82222 1.881481,3.99815 1.881481,1.11713 5.644443,1.11713 v 14.11111 q -10.524535,0 -16.580553,-4.70371 -5.997221,-4.7037 -5.997221,-14.52268 V 87.326939 q 0,-4.762499 -3.821758,-6.702777 -3.762963,-1.940277 -11.230091,-1.940277 V 64.572776 q 7.467128,0 11.230091,-1.940277 3.821758,-1.940278 3.821758,-6.702777 v -14.87546 q 0,-9.81898 5.997221,-14.522683 6.056018,-4.703703 16.580553,-4.703703 v 14.111109 q -3.762962,0 -5.644443,1.175925 -1.881481,1.11713 -1.881481,3.939352 v 14.87546 q 0,6.526388 -2.116667,9.995369 -2.116666,3.468981 -7.231943,5.409258 z"
id="text6"
inkscape:label="{"
aria-label="{" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333333 4.2333333"
version="1.1"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="codemp-white-path-tiny-nocircle-darkmode.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="24.737637"
inkscape:cx="4.6892111"
inkscape:cy="9.0348161"
inkscape:window-width="2510"
inkscape:window-height="1366"
inkscape:window-x="25"
inkscape:window-y="525"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="fg"
inkscape:groupmode="layer"
id="layer1"
transform="matrix(1.0016941,0,0,1.0016941,-31.06987,-13.439048)">
<path
style="font-weight:bold;font-size:33.8667px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#afb1b3;stroke-width:0.0112626;fill-opacity:1"
d="m 33.762897,15.785963 v 0.380851 h 0.0585 q 0.08115,0 0.117956,-0.0074 0.06417,-0.01307 0.10192,-0.06255 0.03869,-0.04948 0.03869,-0.120415 0,-0.07095 -0.03869,-0.120417 -0.03775,-0.04947 -0.10192,-0.06255 -0.03681,-0.0074 -0.117956,-0.0074 z m -0.241581,-0.224031 h 0.298201 q 0.139663,0 0.199115,0.01399 0.134001,0.03174 0.217988,0.139086 0.08493,0.106411 0.08493,0.26137 0,0.154954 -0.08493,0.262302 -0.08399,0.106412 -0.217988,0.138153 -0.05944,0.014 -0.199115,0.014 h -0.05663 v 0.485399 h -0.241581 z"
id="text4"
inkscape:label="P"
aria-label="P" />
<path
style="font-weight:bold;font-size:33.8667px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#adb1b3;stroke-width:0.0112626;fill-opacity:1"
d="m 33.756552,15.428385 h -0.24158 v -1.314313 h 0.24158 l 0.176468,0.408856 h 0.01041 l 0.175522,-0.408856 h 0.24158 v 1.314313 h -0.241614 v -0.83638 h -0.0094 l -0.119852,0.238965 h -0.10378 l -0.119853,-0.242699 h -0.0094 z"
id="text5"
inkscape:label="M"
aria-label="M" />
<path
style="font-weight:bold;font-size:90.3111px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#adb1b3;stroke-width:0.0112626;fill-opacity:1"
d="m 32.791187,15.546679 q 0.218932,0.08214 0.309524,0.229008 0.09058,0.146867 0.09058,0.42317 v 0.629776 q 0,0.119483 0.08053,0.169268 0.08053,0.0473 0.241579,0.0473 v 0.597416 q -0.450445,0 -0.709642,-0.199139 Q 32.54708,17.24434 32.54708,16.828639 v -0.629776 q 0,-0.201627 -0.163569,-0.283771 -0.161053,-0.08214 -0.480645,-0.08214 v -0.597415 q 0.319592,0 0.480645,-0.08214 0.163569,-0.08214 0.163569,-0.283773 v -0.629775 q 0,-0.415701 0.256678,-0.614838 0.259197,-0.199139 0.709642,-0.199139 v 0.597415 q -0.161054,0 -0.241579,0.04979 -0.08053,0.0473 -0.08053,0.166779 v 0.629774 q 0,0.276305 -0.09058,0.42317 -0.09058,0.146865 -0.309524,0.229009 z"
id="text6"
inkscape:label="{"
aria-label="{" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333333 4.2333333"
version="1.1"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="codemp-white-path-tiny-nocircle-lightmode.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="32.000001"
inkscape:cx="10.40625"
inkscape:cy="11.109375"
inkscape:window-width="2510"
inkscape:window-height="1366"
inkscape:window-x="25"
inkscape:window-y="525"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="fg"
inkscape:groupmode="layer"
id="layer1"
transform="matrix(1.0016941,0,0,1.0016941,-31.06987,-13.439048)">
<path
style="font-weight:bold;font-size:33.8667px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#6e6e6e;stroke-width:0.0112626;fill-opacity:1"
d="m 33.762897,15.785963 v 0.380851 h 0.0585 q 0.08115,0 0.117956,-0.0074 0.06417,-0.01307 0.10192,-0.06255 0.03869,-0.04948 0.03869,-0.120415 0,-0.07095 -0.03869,-0.120417 -0.03775,-0.04947 -0.10192,-0.06255 -0.03681,-0.0074 -0.117956,-0.0074 z m -0.241581,-0.224031 h 0.298201 q 0.139663,0 0.199115,0.01399 0.134001,0.03174 0.217988,0.139086 0.08493,0.106411 0.08493,0.26137 0,0.154954 -0.08493,0.262302 -0.08399,0.106412 -0.217988,0.138153 -0.05944,0.014 -0.199115,0.014 h -0.05663 v 0.485399 h -0.241581 z"
id="text4"
inkscape:label="P"
aria-label="P" />
<path
style="font-weight:bold;font-size:33.8667px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#6e6e6e;stroke-width:0.0112626;fill-opacity:1"
d="m 33.756552,15.428385 h -0.24158 v -1.314313 h 0.24158 l 0.176468,0.408856 h 0.01041 l 0.175522,-0.408856 h 0.24158 v 1.314313 h -0.241614 v -0.83638 h -0.0094 l -0.119852,0.238965 h -0.10378 l -0.119853,-0.242699 h -0.0094 z"
id="text5"
inkscape:label="M"
aria-label="M" />
<path
style="font-weight:bold;font-size:90.3111px;line-height:1.25;font-family:'Monoid HalfTight';-inkscape-font-specification:'Monoid HalfTight';fill:#6e6e6e;stroke-width:0.0112626;fill-opacity:1"
d="m 32.791187,15.546679 q 0.218932,0.08214 0.309524,0.229008 0.09058,0.146867 0.09058,0.42317 v 0.629776 q 0,0.119483 0.08053,0.169268 0.08053,0.0473 0.241579,0.0473 v 0.597416 q -0.450445,0 -0.709642,-0.199139 Q 32.54708,17.24434 32.54708,16.828639 v -0.629776 q 0,-0.201627 -0.163569,-0.283771 -0.161053,-0.08214 -0.480645,-0.08214 v -0.597415 q 0.319592,0 0.480645,-0.08214 0.163569,-0.08214 0.163569,-0.283773 v -0.629775 q 0,-0.415701 0.256678,-0.614838 0.259197,-0.199139 0.709642,-0.199139 v 0.597415 q -0.161054,0 -0.241579,0.04979 -0.08053,0.0473 -0.08053,0.166779 v 0.629774 q 0,0.276305 -0.09058,0.42317 -0.09058,0.146865 -0.309524,0.229009 z"
id="text6"
inkscape:label="{"
aria-label="{" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB