Skip to content
Merged
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
1 change: 1 addition & 0 deletions NimEdit.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ bin = @["app/nimedit"]
# [Deps]
requires: "nim >= 0.19.0, sdl2#head, dialogs >= 1.0"
requires: "https://github.com/nim-lang/sdl3"
requires: "https://github.com/nim-lang/uirelays >= 0.8.0"
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,40 @@
NimEdit is the new upcoming slim IDE/editor for the Nim programming language.

![shot1.png](https://bitbucket.org/repo/ee5daK/images/675518804-shot1.png)
![shot1.png](https://bitbucket.org/repo/ee5daK/images/675518804-shot1.png)

# Installation

NimEdit now uses the new [uirelays](https://github.com/nim-lang/uirelays) library for drawing and font rendering. This library talks directly to your
OS and has no dependencies. But it can also use an SDL 3 backend via `-d:sdl3`.

To install the required dependencies use:

```nim
nimble install
```

## Windows

NimEdit uses the Windows API for drawing and font rendering. To the best of my knowledge nothing special
needs to be installed. (Corrections welcome!)


## Linux

On Linux we use X11:

```
sudo apt install libx11-dev libxft-dev
```

You may need to install good fonts via:

```
sudo apt install fonts-freefont-ttf fonts-dejavu-core
```


## OSX

NimEdit uses a Cocoa-based wrapper which does not require anything beyond the typical frameworks. To the best of my knowledge nothing special needs to be installed. (Corrections welcome!)

1 change: 1 addition & 0 deletions app/console.nim
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ proc startsWithIgnoreCase(s, prefix: string): bool =
var i = 0
while true:
if i >= prefix.len: return true
if i >= s.len: return false
if s[i].toLowerAscii != prefix[i].toLowerAscii: return false
inc(i)

Expand Down
117 changes: 54 additions & 63 deletions app/nimedit.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ import
std/[strutils, critbits, os, times, browsers, tables, hashes, intsets,
exitprocs]
from parseutils import parseInt
import basetypes, screen, input
when defined(sdl2):
import sdl2_driver
else:
import sdl3_driver
import uirelays/[coords, screen, input, backend]
import buffertype except Action
import buffer, styles, unicode, highlighters, console
import nimscript/common, nimscript/keydefs, languages, themes,
Expand Down Expand Up @@ -541,11 +537,8 @@ proc pollEvents*(someConsoleRunning, windowHasFocus: bool): seq[input.Event] =
while input.pollEvent(e):
result.add e

proc ctrlKeyPressed*(): bool =
modCtrl in input.getModState()

proc shiftKeyPressed*(): bool =
modShift in input.getModState()
proc ctrlKeyPressed*(e: Event): bool = CtrlPressed in e.mods
proc shiftKeyPressed*(e: Event): bool = ShiftPressed in e.mods

proc loadTheme(ed: SharedState) =
loadTheme(ed.cfgColors, ed.theme, ed.mgr, ed.fontM)
Expand All @@ -556,39 +549,39 @@ proc loadTheme(ed: SharedState) =

proc eventToKeySet(e: input.Event): set[Key] =
result = {}
if e.kind == evKeyDown: discard
elif e.kind == evKeyUp: result.incl(Key.KeyReleased)
if e.kind == KeyDownEvent: discard
elif e.kind == KeyUpEvent: result.incl(Key.KeyReleased)
else: return
# Map KeyCode to Key enum for the keybinding system
case e.key
of keyA..keyZ:
result.incl(Key(ord(Key.A) + ord(e.key) - ord(keyA)))
of key0..key9:
result.incl(Key(ord(Key.N0) + ord(e.key) - ord(key0)))
of keyF1..keyF12:
result.incl(Key(ord(Key.F1) + ord(e.key) - ord(keyF1)))
of keyEnter: result.incl Key.Enter
of keySpace: result.incl Key.Space
of keyEsc: result.incl Key.Esc
of keyDelete: result.incl Key.Del
of keyBackspace: result.incl Key.Backspace
of keyInsert: result.incl Key.Ins
of keyPageUp: result.incl Key.PageUp
of keyPageDown: result.incl Key.PageDown
of keyCapslock: result.incl Key.Capslock
of keyTab: result.incl Key.Tab
of keyLeft: result.incl Key.Left
of keyRight: result.incl Key.Right
of keyUp: result.incl Key.Up
of keyDown: result.incl Key.Down
of keyComma: result.incl Key.Comma
of keyPeriod: result.incl Key.Period
of KeyA..KeyZ:
result.incl(Key(ord(Key.A) + ord(e.key) - ord(KeyA)))
of Key0..Key9:
result.incl(Key(ord(Key.N0) + ord(e.key) - ord(Key0)))
of KeyF1..KeyF12:
result.incl(Key(ord(Key.F1) + ord(e.key) - ord(KeyF1)))
of KeyEnter: result.incl Key.Enter
of KeySpace: result.incl Key.Space
of KeyEsc: result.incl Key.Esc
of KeyDelete: result.incl Key.Del
of KeyBackspace: result.incl Key.Backspace
of KeyInsert: result.incl Key.Ins
of KeyPageUp: result.incl Key.PageUp
of KeyPageDown: result.incl Key.PageDown
of KeyCapslock: result.incl Key.Capslock
of KeyTab: result.incl Key.Tab
of KeyLeft: result.incl Key.Left
of KeyRight: result.incl Key.Right
of KeyUp: result.incl Key.Up
of KeyDown: result.incl Key.Down
of KeyComma: result.incl Key.Comma
of KeyPeriod: result.incl Key.Period
else: discard
when defined(macosx):
if modGui in e.mods: result.incl Key.Apple
if modCtrl in e.mods: result.incl Key.Ctrl
if modShift in e.mods: result.incl Key.Shift
if modAlt in e.mods: result.incl Key.Alt
if GuiPressed in e.mods: result.incl Key.Apple
if CtrlPressed in e.mods: result.incl Key.Ctrl
if ShiftPressed in e.mods: result.incl Key.Shift
if AltPressed in e.mods: result.incl Key.Alt

proc produceHelp(ed: Editor): string =
proc getArg(a: Command): string =
Expand Down Expand Up @@ -674,7 +667,7 @@ proc closeWindow(ed: Editor) =
left.next = left.next.next
ed.sh.activeWindow = left

proc runAction(ed: Editor; action: Action; arg: string): bool =
proc runAction(ed: Editor; action: Action; arg: string; shiftKeyPressed: bool): bool =
template console: untyped = ed.console

case action
Expand Down Expand Up @@ -748,7 +741,7 @@ proc runAction(ed: Editor; action: Action; arg: string): bool =
main.insertEnter()
trackSpot(ed.sh.hotspots, main)
elif focus==prompt:
if ed.runCmd(prompt.fullText, shiftKeyPressed()):
if ed.runCmd(prompt.fullText, shiftKeyPressed):
saveOpenTabs(ed)
result = true
elif focus==console:
Expand Down Expand Up @@ -901,33 +894,34 @@ proc processEvents(events: out seq[Event]; ed: Editor): bool =

for e in events:
case e.kind
of evQuit:
of QuitEvent:
if handleQuitEvent(ed):
result = true
break
of evWindowResize:
of WindowResizeEvent:
ed.screenW = e.x
ed.screenH = e.y
layout(ed)
of evWindowFocusLost:
of WindowFocusLostEvent:
sh.windowHasFocus = false
of evWindowFocusGained:
of WindowFocusGainedEvent:
sh.windowHasFocus = true
of evWindowClose:
of WindowCloseEvent:
if sh.firstWindow.next.isNil:
if handleQuitEvent(ed):
result = true
break
else:
closeWindow(sh.activeWindow)
of evMouseDown:
of MouseDownEvent:
var clicks = e.clicks
if clicks == 0 or clicks > 5: clicks = 1
if ctrlKeyPressed(): inc(clicks)
if ctrlKeyPressed(e): inc(clicks)
let p = point(e.x, e.y)
if ed.mainRect.contains(p) and ed.main.scrollingEnabled:
if ed.mainRect.contains(p):
var rawMainRect = ed.mainRect
rawMainRect.w -= scrollBarWidth
if ed.main.scrollingEnabled:
rawMainRect.w -= scrollBarWidth
if focus == main and rawMainRect.contains(p):
main.setCursorFromMouse(ed.mainRect, p, clicks)
else:
Expand All @@ -943,13 +937,13 @@ proc processEvents(events: out seq[Event]; ed: Editor): bool =
ed.sh.clickOnFilename = clicks >= 2
else:
focus = console
of evMouseWheel:
of MouseWheelEvent:
# use last known mouse position for target determination
focus.scrollLines(-e.y*3)
of evTextInput:
of TextInputEvent:
var surpress = false
if e.text[0] == ' ' and e.text[1] == '\0':
if ctrlKeyPressed():
if ctrlKeyPressed(e):
surpress = true
if not surpress:
var textStr = ""
Expand All @@ -967,10 +961,10 @@ proc processEvents(events: out seq[Event]; ed: Editor): bool =
else:
focus.insertSingleKey(textStr)
if focus==main: trackSpot(ed.sh.hotspots, main)
of evKeyDown, evKeyUp:
of KeyDownEvent, KeyUpEvent:
let ks = eventToKeySet(e)
let cmd = sh.keymapping.getOrDefault(ks)
if ed.runAction(cmd.action, cmd.arg):
if ed.runAction(cmd.action, cmd.arg, shiftKeyPressed(e)):
result = true
break
else: discard
Expand All @@ -986,7 +980,7 @@ proc draw(events: sink seq[input.Event]; ed: Editor) =
if activeTab != nil:
var rightClick = false
for e in events:
if e.kind == evMouseDown and e.button == mbRight:
if e.kind == MouseDownEvent and e.button == RightButton:
rightClick = true
break
if rightClick:
Expand Down Expand Up @@ -1085,9 +1079,9 @@ proc mainProc(ed: Editor) =
scriptContext.setupApi(sh)
compileActions(sh.cfgActions)

loadTheme(sh)
createSdlWindow(ed, 1u32)
input.startTextInput()
loadTheme(sh)


include nimscript/keybindings #XXX TODO: nimscript instead of include

Expand Down Expand Up @@ -1138,9 +1132,9 @@ proc mainProc(ed: Editor) =
else:
DefaultTimeOut
# reduce CPU usage:
delay(20)
sleep(20)
let newTicks = getTicks()
if newTicks - oldTicks > timeout.uint32:
if newTicks - oldTicks > timeout:
oldTicks = newTicks

inc sh.idle
Expand All @@ -1160,9 +1154,6 @@ proc mainProc(ed: Editor) =



when defined(sdl2):
initSdl2Driver()
else:
initSdl3Driver()
initBackend()
mainProc(Editor())
input.quitRequest()
2 changes: 1 addition & 1 deletion app/prims.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import basetypes, screen
import uirelays/[coords, screen]
from math import sin, cos, PI

type
Expand Down
8 changes: 4 additions & 4 deletions app/scrollbar.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Draws a vertical scrollbar for a buffer.

import buffertype, themes
import basetypes, screen, input, tabbar
import uirelays/[coords, screen, input], tabbar

const scrollBarWidth* = 15

Expand Down Expand Up @@ -48,15 +48,15 @@ proc drawScrollBar*(b: Buffer; t: InternalTheme; events: seq[Event];
for e in events:
case state.usingScrollbar
of false:
if e.kind == evMouseDown:
if e.kind == MouseDownEvent:
let p = point(e.x, e.y)
if grip.contains(p):
state = ScrollBarState(usingScrollbar: true,
initiallyGrippedAt: e.y.int - grip.y)
of true:
if e.kind == evMouseUp:
if e.kind == MouseUpEvent:
state = ScrollBarState(usingScrollbar: false)
elif e.kind == evMouseMove:
elif e.kind == MouseMoveEvent:
let
mousePosRelativeToScrollbar = e.y - grip.y
yMovement = mousePosRelativeToScrollbar - state.initiallyGrippedAt
Expand Down
Loading