Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# 🚀 SWIM – The Java‑powered Vim‑style Editor

🚀 **SWIM** stands for *Strange Variety Vi Improved* – the ultimate modal text editor built on the Java platform. 🌐 It delivers the power and speed of Vim, the flexibility of Java, and the extensibility of a full language‑server ecosystem—all in a single, lightweight JAR. 💡

🛠️ Feature | 💡 What it gives you |
|----------------|--------------------------|
| 📌 **Vim‑style modal editing** | Classic keystrokes, visual and block selections, powerful motions. |
| ⚙️ **Pure Java implementation** | Runs on any JVM, no native dependencies, simple `mvn` build. |
| 🌐 **Native Java LSP integration** | Auto‑completion, go‑to‑definition, refactoring for Java (and LaTeX, etc.) right out of the box. |
| 🚀 **Extensible** | Add custom modes or plugins in Java – treat the editor as a platform, not a product. |
| 🔧 **Zero‑configuration** | One command to launch, alias support for quick launching. |
| 🧪 **Lightweight** | Less than 50 MB, no external libraries besides the standard JDK. |
## Quick Start

```bash
# 1. Make sure you have JDK 25+ installed.
# 2. Build the project:
$ mvn clean package

# 3. Run SWIM with a file:
$ java -XX:+UseZGC -cp "target/swim-0.0.1-SNAPSHOT.jar:target/libs/*" org.fisk.swim.Swim <file>

# 4. For convenience, create an alias:
$ alias swim='java -XX:+UseZGC -cp "<swim_path>/target/swim-0.0.1-SNAPSHOT.jar:<swim_path>/target/libs/*" org.fisk.swim.Swim'
# Then simply:
$ swim <file>
```

## Modal Editing – The Essentials

SWIM uses the same keybindings that make Vim legendary. Below are the core motions and commands you’ll use every day.

### Normal Mode

| Key | Action |
|-----|--------|
| `h/j/k/l` | Move cursor left/down/up/right |
| `0/$` | Move to start/end of line |
| `gg/G` | Go to first/last line |
| `f/F` | Find next/previous character |
| `w/b/e` | Move by words |
| `d{motion}` | Delete |
| `y{motion}` | Yank |
| `p/P` | Paste |
| `u` | Undo |
| `Ctrl‑r` | Redo |
| `i` | Enter **Insert** mode |
| `v/V` | Enter **Visual** / **Visual Line** mode |
| `Ctrl‑v` | Visual Block mode |
| `:` | Command‑line prompt |
| `/` or `?` | Search |

### Insert Mode

All the usual text entry – just type! Escape (`Esc`) returns you to Normal mode.

### Visual Mode

Same motion keys as Normal, plus:

| Key | Action |
|-----|--------|
| `d` | Delete selection |
| `y` | Yank selection |
| `c` | Change selection (delete + Insert) |

## Java‑LSP Power‑Ups

SWIM’s `:JavaLSP` namespace exposes powerful refactorings. In Normal mode, prefix commands with `<Space>e`:

| Shortcut | Description |
|----------|-------------|
| `<Space>e i` | Organize imports |
| `<Space>e f` | Make field `final` |
| `<Space>e a` | Generate accessors |
| `<Space>e s` | Generate `toString()` |
| `<Space>e l` | Show code lens |

Feel free to create your own custom commands by wiring up a Java handler.

## Extending SWIM

The entire codebase is open source. To add a new language‑server or mode, simply:

1. Implement a new `LanguageMode`.
2. Register it via `LanguageModeProvider`.
3. Build and test.

Because the editor is written in Java, you can drop in existing libraries or even build a UI plug‑in.


2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.22.1</version>
<version>2.25.4</version>
</dependency>
<dependency>
<groupId>org.eclipse.lsp4j</groupId>
Expand Down
File renamed without changes.
53 changes: 47 additions & 6 deletions src/main/java/org/fisk/swim/Swim.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,62 @@
import java.io.PrintStream;
import java.nio.file.Path;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.config.LoggerConfig;

import org.fisk.swim.event.IOThread;
import org.fisk.swim.terminal.TerminalContext;
import org.fisk.swim.ui.Window;
import org.fisk.swim.utils.LogFactory;
import org.slf4j.Logger;

public class Swim {
private static final Logger _log = LogFactory.createLog();
private static Logger _log;

private static void setupLogging() {
try {
File file = new File("/tmp/swim.log");
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
System.setErr(ps);
// Get the current PID
String pid = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
String fileName = "/tmp/swim-" + pid + ".log";

// Programmatically add or update the File Appender
LoggerContext context = (LoggerContext) LogManager.getContext(false);
Configuration config = context.getConfiguration();

PatternLayout layout = PatternLayout.newBuilder()
.withPattern("%d [%t] %-5p %c - %m%n")
.build();

FileAppender appender = FileAppender.newBuilder()
.setName("FileAppender")
.withFileName(fileName)
.setLayout(layout)
.setConfiguration(config)
.build();
appender.start();
config.addAppender(appender);

// Attach to root logger so ALL loggers write here
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);

// Remove all existing appenders
for (String appenderName : loggerConfig.getAppenders().keySet()) {
loggerConfig.removeAppender(appenderName);
}

loggerConfig.addAppender(appender, Level.DEBUG, null);

// Ensure desired log level
loggerConfig.setLevel(Level.DEBUG);

context.updateLoggers();

_log = LogManager.getLogger(Swim.class);
} catch (Throwable e) {
}
}
Expand Down
15 changes: 0 additions & 15 deletions src/main/resources/main.jpm

This file was deleted.

2 changes: 0 additions & 2 deletions src/main/resources/simplelogger.properties

This file was deleted.