summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mercouris <john@mercouris.email>2017-11-17 15:35:00 +0100
committerGitHub <noreply@github.com>2017-11-17 15:35:00 +0100
commitc5f8cc3175922a473ff4089677c7a0e8df1d6728 (patch)
treef9631af2ddd854d18239860f5ef21ac95c8c2af7
parent0f583e8a9d5ca73cd00946bf20588687d928533f (diff)
parent6c69ce47f6ea9f9f3b2a9ff9d7c323db68a34ec7 (diff)
Merge pull request #11 from nEXT-Browser/cocoa-backend0.04
Cocoa backend
-rw-r--r--.gitignore13
-rw-r--r--assets/Info.plist26
-rw-r--r--assets/logo.xcfbin27117 -> 0 bytes
-rw-r--r--documents/MANUAL.org18
-rw-r--r--next/README.org190
-rw-r--r--next/lisp/base.lisp33
-rw-r--r--next/lisp/minibuffer.lisp46
-rw-r--r--next/lisp/qt.lisp537
-rw-r--r--next/main.cpp32
-rw-r--r--next/make.lisp117
-rw-r--r--next/next.asd10
-rw-r--r--next/next.pro13
-rw-r--r--next/run.lisp10
-rw-r--r--next/source/base.lisp52
-rw-r--r--next/source/bookmark.lisp (renamed from next/lisp/bookmark.lisp)0
-rw-r--r--next/source/buffer.lisp (renamed from next/lisp/buffer.lisp)9
-rw-r--r--next/source/cocoa/application.lisp89
-rw-r--r--next/source/cocoa/cocoa.lisp224
-rw-r--r--next/source/cocoa/utilities.lisp187
-rw-r--r--next/source/completion.lisp (renamed from next/lisp/completion.lisp)0
-rw-r--r--next/source/document-mode.lisp (renamed from next/lisp/document-mode.lisp)21
-rw-r--r--next/source/global.lisp14
-rw-r--r--next/source/keymap.lisp (renamed from next/lisp/keymap.lisp)3
-rw-r--r--next/source/macro.lisp (renamed from next/lisp/macro.lisp)8
-rw-r--r--next/source/minibuffer.lisp41
-rw-r--r--next/source/mode.lisp (renamed from next/lisp/mode.lisp)0
-rw-r--r--next/source/package.lisp (renamed from next/lisp/package.lisp)6
-rw-r--r--next/source/tree-history.lisp (renamed from next/lisp/tree-history.lisp)0
28 files changed, 731 insertions, 968 deletions
diff --git a/.gitignore b/.gitignore
index 1dab948c1..4c72fb2eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,23 +1,12 @@
-# C extensions
-*.so
-
# Ignore folders
archive/
offline/
-environment/
+online/
# Ignore info org files
info.org
info.org_archive
-# Qmake Stash
-*.qmake.stash
-
-# Ignore intermediary
-*.a
-*.o
-Makefile
-
# Ignore App
*.app
diff --git a/assets/Info.plist b/assets/Info.plist
new file mode 100644
index 000000000..7aa39c6a3
--- /dev/null
+++ b/assets/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>NSPrincipalClass</key>
+ <string>next-application</string>
+ <key>CFBundleIconFile</key>
+ <string>next.icns</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>nEXT Browser</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleExecutable</key>
+ <string>next</string>
+ <key>CFBundleIdentifier</key>
+ <string>next.browser</string>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <!--Include to allow all connections-->
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
+ </dict>
+</plist>
diff --git a/assets/logo.xcf b/assets/logo.xcf
deleted file mode 100644
index f3c9f5511..000000000
--- a/assets/logo.xcf
+++ /dev/null
Binary files differ
diff --git a/documents/MANUAL.org b/documents/MANUAL.org
index 3ac93d40a..950712745 100644
--- a/documents/MANUAL.org
+++ b/documents/MANUAL.org
@@ -106,21 +106,3 @@ The following keys exist as special keys:
1. ~C~: Control
2. ~S~: Super (Windows key, Command Key)
3. ~M~: Meta (Alt key, Option Key)
-
-*** Swapping the Modifier Keys
-nEXT is built with QT, and on Mac OS, QT will automatically modify
-what control, meta and caps lock as keycodes sent to the key-capturing
-system. In order to maintain consistency with other programs that you
-are familiar with, you may want to switch to the default emacs style
-keybindings; to do so; simply copy the snippet below into your
-init.lisp file.
-
-#+NAME: Emacs Style Modifier Keys
-#+BEGIN_SRC lisp
-(let ((original_control *control-key*)
- (original_meta *meta-key*)
- (original_alt *alt-key*))
- (setf *control-key* original_meta)
- (setf *meta-key* original_alt)
- (setf *super-key* original_control))
-#+END_SRC
diff --git a/next/README.org b/next/README.org
index 5b4d587e2..985d8829e 100644
--- a/next/README.org
+++ b/next/README.org
@@ -1,9 +1,9 @@
* Contents :TOC:
- [[#developer-installation][Developer Installation]]
- - [[#osx-instructions][OSX Instructions]]
+ - [[#macos-instructions][macOS Instructions]]
- [[#linux-instructions][Linux Instructions]]
- - [[#running-next][Running nEXT]]
- - [[#compiling-next-under-active-development][Compiling nEXT (under active development)]]
+ - [[#running-next-from-source][Running nEXT from Source]]
+ - [[#compiling-next][Compiling nEXT]]
- [[#release-timeline][Release Timeline]]
- [[#005][0.05]]
- [[#004][0.04]]
@@ -13,51 +13,22 @@
- [[#contributing][Contributing]]
* Developer Installation
-nEXT browser is built with ECL and EQL, and is designed to be cross
-platform compatible. To download a prebuilt-binary, please see the
+nEXT browser is built with CCL, and is designed to be cross platform
+compatible. Support for graphics is provided via Cocoa for macOS and
+GTK for Linux. To download a prebuilt-binary, please see the
"Releases" section of this repository.
-** OSX Instructions
-*** Installing Xcode Command Line Tools
-Before installing anything, install the Xcode Comand line tools. To
-install the Xcode Command Line tools on OSX execute the following in a
-terminal:
-
-~xcode-select --install~
-
-To verify that the command tools were successfully installed type:
-
-~xcode-select -p~
-
-the output of this command should be the path at which the command
-line tools are installed.
-
-*** Installing QT5 (Cross Platform GUI Toolkit)
-QT5 is available from a number of sources, the easiest is to install
-it via a package manager such as Macports or Brew. However you
-install, ensure that you install it with webkit support.
-
-You can install QT5 via Macports with the following command:
-
-~port install qt5~
-
-You can also install QT5 via the official qt installer:
-
-https://www.qt.io/download/
-
-To test your installation/version of QT, execute ~qmake --version~.
-
-*** Installing ECL (Embeddable Common Lisp)
-Compilable tarballs can be found on the ECL website:
-
-https://common-lisp.net/project/ecl/static/files/release/
-
-To verify your installation of ECL:
-
-- Execute ~/usr/local/bin/ecl~, it should show an ECL Prompt
-- Verify the contents of ~/usr/local/lib~ contain the ecl libraries.
-- Verify the contents of ~/usr/local/include/ecl~ contain the header files
-
+** macOS Instructions
+*** Installing CCL
+- Download CCL: [[https://ccl.clozure.com/download.html]], full
+ installation instructions can be found here:
+ [[https://ccl.clozure.com/install.html]]. Brief installation
+ instructions can be found below:
+
+1. Copy the downloaded CCL directory to ~/usr/local/src/ccl~
+2. Copy the script located at ~ccl/scripts/ccl64~ somewhere into your
+ executable path
+3. Optionally make an alias, or rename ~ccl64~ to ~ccl~
*** Installing Quicklisp
The official quicklisp website can provide updated links
to downloads, and instructions:
@@ -67,127 +38,30 @@ https://www.quicklisp.org
To install quicklisp:
- Download https://beta.quicklisp.org/quicklisp.lisp
-- Execute ~ecl --load quicklisp.lisp~ to load quicklisp
+- Execute ~ccl --load quicklisp.lisp~ to load quicklisp
- Evaluate in the REPL ~(quicklisp-quickstart:install)~ to install
-- Evalute in the REPL ~(ql:add-to-init-file)~ to add quicklisp to your ecl init file
+- Evalute in the REPL ~(ql:add-to-init-file)~ to add quicklisp to your ccl init file
more detailed instructions and other resources are readily available
on the quicklisp website.
-
-*** Installing EQL5 Library & Executable (Embedded QT Lisp)
-The source for EQL5 is available here:
-
-https://gitlab.com/eql/EQL5
-
-To build and install the EQL Library/Executable:
-
-1. Clone the Repository into a directory where you plan to keep the
- installation, this cannot be moved after installation.
-2. In ~src/~ exec: ~ecl -shell make.lisp~ This command generates
- ~src/libini_eql5.a~.
-3. Edit ~src/eql5.pro~ commenting out all QT modules you do not
- require.
-
- - The webkit module is required for nEXT.
-
-4. In ~src/~ exec: ~qmake eql5.pro~. This command generates
- the makefile.
-5. In ~src/~ exec: ~make~
-6. In ~src/~ exec: ~sudo make install~
-
-To test your installation exec ~eql5 -qgui~, you should presented
-with a REPL and a GUI.
-
-After the installation, the following should be completed:
-
-- ~/usr/local/bin~ contains an ~eql5~ executable
-- ~/usr/local/include~ contains a folder named ~eql5~
-- ~/usr/local/lib~ contains all built QT modules (selected in
- ~src/eql5.pro~) and libeql \*.dylib files
-
** Linux Instructions
-Due to the large variances in Linux distributions: file locations,
-package managers, and best practices, this installation guide attempts
-to make as few decisions as possible- instead opting to list the
-requirements necessary to build nEXT.
-
-*** Installing a compiler
-Install a C/C++ Compiler
-*** Installing QT5
-Install QT directly from QT: [[https://www.qt.io/download/][download QT]], or install via
-third party package manager sources, apt-get etc.
-*** Installing ECL (Embeddable Common Lisp)
-Compilable tarballs can be found on the ECL website: [[https://common-lisp.net/project/ecl/static/files/release/][download ECL]]
-*** Installing Quicklisp
-The official quicklisp website can provide updated links
-to downloads, and instructions:
-
-To install quicklisp:
-
-- Download https://beta.quicklisp.org/quicklisp.lisp
-- Execute ~ecl --load quicklisp.lisp~ to load quicklisp
-- Evaluate in the REPL ~(quicklisp-quickstart:install)~ to install
-- Evalute in the REPL ~(ql:add-to-init-file)~ to add quicklisp to your ecl init file
-
-more detailed instructions and other resources are readily available
-on the quicklisp website.
-*** Installing EQL5 Library & Executable (Embedded QT Lisp)
-The source for EQL5 is available here:
-
-https://gitlab.com/eql/EQL5
-
-To build and install the EQL Library/Executable:
-
-1. Clone the Repository into a directory where you plan to keep the
- installation, this cannot be moved after installation.
-2. In ~src/~ exec: ~ecl -shell make.lisp~ This command generates
- ~src/libini_eql5.a~.
-3. Edit ~src/eql5.pro~ commenting out all QT modules you do not
- require.
-
- - The webkit module is required for nEXT.
-
-4. In ~src/~ exec: ~qmake eql5.pro~. This command generates
- the makefile.
-5. In ~src/~ exec: ~make~
-6. In ~src/~ exec: ~sudo make install~
-
-To test your installation exec ~eql5 -qgui~, you should presented
-with a REPL and a GUI.
-
-After the installation, the following should be completed:
-
-- ~/usr/local/bin~ contains an ~eql5~ executable
-- ~/usr/local/include~ contains a folder named ~eql5~
-- ~/usr/local/lib~ contains all built QT modules (selected in
- ~src/eql5.pro~) and libeql \*.dylib files
-
-** Running nEXT
-From the directory ~next/~ execute the following command to run:
-
-1. ~eql5 run~
-
-You should be presented with a QT Window. To test that everything
-is working execute the following commands:
-
-1. ~C-l~
-2. A minibuffer should pop-up in which you can enter text
-
-From the terminal that you launched nEXT you'll be able to see output
-from the program. You can additionally create a REPL during runtime
-in the following way: ~eql5 run -qgui~.
+Instructions forthcoming pending GTK release.
+** Running nEXT from Source
+In a new Terminal execute the following:
-If an exception or crash occurs, you'll be presented with a REPL that
-you can use to debug the program.
+1. ~ccl~ to create a new CCL Repl
+2. Execute ~(require :asdf)~ if asdf is not already loaded
+3. Execute ~(asdf:load-asd "/path/to/next.asd")~, this will load the
+ nEXT system into your Lisp image
+4. Execute ~(next:start)~ to open your first nEXT Window.
-** Compiling nEXT (under active development)
-*** OSX Instructions
-From the directory ~next/~ execute the following commands to compile:
+** Compiling nEXT
+*** macOS Instructions
+From the CCL Source directory, execute
-1. ~eql5 make~
+1. ~ccl --no-init --load make.lisp~
+2. The compiled binary will be present in build/nEXT
-Now you should have a compiled next.app, simply execute this app to
-start nEXT browser.
* Release Timeline
Major releases are issued by incrementing the first digit. That is,
release 1.20, and 2.20 are one major release away from each other. Minor
diff --git a/next/lisp/base.lisp b/next/lisp/base.lisp
deleted file mode 100644
index b4e0c3308..000000000
--- a/next/lisp/base.lisp
+++ /dev/null
@@ -1,33 +0,0 @@
-;;;; base.lisp --- main entry point into nEXT
-
-(in-package :next)
-
-(defun start ()
- (ensure-directories-exist (uiop:physicalize-pathname #P"~/.next.d/"))
- (interface:initialize)
- (initialize-bookmark-db)
- ;; define the default keybindings
- (define-key global-map (kbd "C-x C-c") #'interface:quit)
- (define-key minibuffer-mode-map (kbd "Return") #'return-input)
- (define-key minibuffer-mode-map (kbd "C-g") #'cancel-input)
- (define-key minibuffer-mode-map (kbd "Escape") #'cancel-input)
- (define-key global-map (kbd "C-x b") (:input-complete switch-buffer buffer-complete))
- (define-key global-map (kbd "C-x k") (:input-complete delete-buffer buffer-complete))
- (define-key document-mode-map (kbd "S-f") (:input-complete history-forwards-query history-fowards-query-complete))
- (define-key document-mode-map (kbd "S-b") #'history-backwards)
- (define-key document-mode-map (kbd "C-f") #'history-forwards)
- (define-key document-mode-map (kbd "C-b") #'history-backwards)
- (define-key document-mode-map (kbd "C-p") #'scroll-up)
- (define-key document-mode-map (kbd "C-n") #'scroll-down)
- (define-key document-mode-map (kbd "C-l") (:input set-url))
- (define-key global-map (kbd "C-o") (:input set-url-new-buffer))
- (define-key global-map (kbd "S-s k") (:input-complete bookmark-delete bookmark-complete))
- (define-key document-mode-map (kbd "S-s o") (:input-complete set-url bookmark-complete))
- (define-key document-mode-map (kbd "S-s s") #'bookmark-current-page)
- ;; start the gui
- (interface:start)
- ;; create the default buffers
- (setf *minibuffer* (generate-new-buffer "minibuffer" (minibuffer-mode) nil))
- (setf *active-buffer* (generate-new-buffer "default" (document-mode)))
- ;; load the user configuration if it exists
- (load "~/.next.d/init.lisp" :if-does-not-exist nil))
diff --git a/next/lisp/minibuffer.lisp b/next/lisp/minibuffer.lisp
deleted file mode 100644
index 3c853d2f9..000000000
--- a/next/lisp/minibuffer.lisp
+++ /dev/null
@@ -1,46 +0,0 @@
-;;;; minibuffer.lisp --- major mode for input
-
-(in-package :next)
-
-(defvar minibuffer-mode-map (make-hash-table :test 'equalp))
-
-(defclass minibuffer-mode (mode) ())
-
-(defvar *minibuffer* nil
- "A variable to store the mini-buffer")
-
-(defparameter *minibuffer-completion-function* nil
- "A variable to store the function used to generate completion candidates")
-(defparameter *minibuffer-callback* nil
- "A variable to store the function upon completion of the minibuffer read")
-(defparameter *minibuffer-callback-buffer* nil
- "A variable to store the buffer which originally requested the minibuffer read")
-
-(defun input (callback-function &optional completion-function)
- (setf *minibuffer-callback* callback-function)
- (setf *minibuffer-completion-function* completion-function)
- (interface:minibuffer-set-completion-function completion-function)
- (setf *minibuffer-callback-buffer* *active-buffer*)
- (set-active-buffer *minibuffer*)
- (interface:minibuffer-show))
-
-(defun return-input ()
- (set-active-buffer *minibuffer-callback-buffer*)
- (if *minibuffer-completion-function*
- (funcall *minibuffer-callback*
- (nth 0 (funcall *minibuffer-completion-function*
- (interface:minibuffer-get-input))))
- (funcall *minibuffer-callback*
- (interface:minibuffer-get-input)))
- (interface:minibuffer-hide))
-
-(defun cancel-input ()
- (set-active-buffer *minibuffer-callback-buffer*)
- (interface:minibuffer-hide))
-
-(defun minibuffer-mode ()
- "Base mode for input"
- (make-instance 'minibuffer-mode
- :name "minibuffer"
- :keymap minibuffer-mode-map
- :view (interface:make-minibuffer)))
diff --git a/next/lisp/qt.lisp b/next/lisp/qt.lisp
deleted file mode 100644
index f47ec062a..000000000
--- a/next/lisp/qt.lisp
+++ /dev/null
@@ -1,537 +0,0 @@
-;;;; qt.lisp --- QT helper functions & data
-
-(in-package :interface)
-
-(defun initialize ()
- (eql:qrequire :webkit)
- (initialize-keycodes)
- (defvar *control-modifier* nil
- "A variable to store the status of the control key")
- (defvar *meta-modifier* nil
- "A variable to store the status of the alt/meta key")
- (defvar *super-modifier* nil
- "A variable to store the status of the super/cmd key")
- (eql:qadd-event-filter nil eql:|QEvent.KeyPress| 'key-press)
- (eql:qadd-event-filter nil eql:|QEvent.KeyRelease| 'key-release))
-
-(defun start ()
- (defparameter *window* (eql:qnew "QWidget" "windowTitle" "nEXT"))
- (defparameter *root-layout* (eql:qnew "QGridLayout"))
- (defparameter *stack-layout* (eql:qnew "QStackedLayout"))
- (defparameter *minibuffer* nil "reference for widget containing all minibuffer views")
- (defparameter *minibuffer-prompt* (eql:qnew "QLabel" "text" "input:"))
- (defparameter *minibuffer-input* (eql:qnew "QLineEdit"))
- (defparameter *minibuffer-completion* (eql:qnew "QListView"))
- (defparameter *minibuffer-completion-model* (eql:qnew "QStringListModel"))
- (defparameter *minibuffer-completion-function* nil)
- ;; remove margins around root widgets
- (eql:|setSpacing| *root-layout* 0)
- (eql:|setContentsMargins| *root-layout* 0 0 0 0)
- ;; arguments for grid layout: row, column, rowspan, colspan
- (eql:|addLayout| *root-layout* *stack-layout* 0 0 1 1)
- (eql:|setLayout| *window* *root-layout*)
- (eql:|show| *window*))
-
-(defun quit ()
- (eql:qquit))
-
-(defun set-visible-view (view)
- (eql:|setCurrentWidget| *stack-layout* view))
-
-(defun add-to-stack-layout (view)
- (eql:|addWidget| *stack-layout* view))
-
-(defun delete-view (view)
- (eql:qdelete view))
-
-(defun make-web-view ()
- (eql:qnew "QWebView"))
-
-(defun web-view-scroll-down (view distance)
- (eql:|scroll| (eql:|mainFrame| (eql:|page| view))
- 0 distance))
-
-(defun web-view-scroll-up (view distance)
- (eql:|scroll| (eql:|mainFrame| (eql:|page| view))
- 0 (- distance)))
-
-(defun web-view-set-url (view url)
- (eql:qlet ((url (eql:qnew "QUrl(QString)" url)))
- (eql:|setUrl| view url)))
-
-(defun web-view-set-url-loaded-callback (view function)
- (eql:qconnect (eql:|mainFrame| (eql:|page| view)) "loadFinished(bool)"
- function))
-
-(defun web-view-get-url (view)
- (eql:|toString| (eql:|url| view)))
-
-(defun make-minibuffer ()
- (let ((minibuffer (eql:qnew "QWidget")) (layout (eql:qnew "QGridLayout")))
- (eql:|addWidget| layout *minibuffer-prompt* 0 0 1 5)
- (eql:|addWidget| layout *minibuffer-input* 0 1 1 15)
- (eql:|addWidget| layout *minibuffer-completion* 1 1 1 15)
- (eql:|setLayout| minibuffer layout)
- (eql:|setModel| *minibuffer-completion* *minibuffer-completion-model*)
- (eql:qadd-event-filter *minibuffer-input* eql:|QEvent.KeyRelease| 'update-candidates)
- ;; add it to the main grid layout (*root-layout*)
- ;; arguments for grid layout: row, column, rowspan, colspan
- (eql:|addWidget| *root-layout* minibuffer 1 0 1 1)
- (eql:|hide| minibuffer)
- (setf *minibuffer* minibuffer)
- ;; return the widget
- *minibuffer*))
-
-(defun update-candidates (obj event)
- (declare (ignore obj)) ; supress unused warnings
- (declare (ignore event)) ; supress unused warnings
- (when *minibuffer-completion-function*
- (let ((candidates (funcall *minibuffer-completion-function* (minibuffer-get-input))))
- (eql:|setStringList| *minibuffer-completion-model* candidates)))
- nil)
-
-(defun minibuffer-set-completion-function (function)
- (setf *minibuffer-completion-function* function))
-
-(defun minibuffer-show ()
- (eql:|show| *minibuffer*)
- (eql:|setFocus| *minibuffer-input*))
-
-(defun minibuffer-hide ()
- (eql:|setText| *minibuffer-input* "")
- (eql:|hide| *minibuffer*))
-
-(defun minibuffer-get-input ()
- (eql:|text| *minibuffer-input*))
-
-(defun key-press (obj event)
- ;; Invoked upon key-press
- (declare (ignore obj)) ; supress unused warnings
- (let ((key (eql:|key| event)))
- (cond
- ((equalp key *control-key*)
- (setf *control-modifier* t))
- ((equalp key *meta-key*)
- (setf *meta-modifier* t))
- ((equalp key *super-key*)
- (setf *super-modifier* t))
- (t (next:push-key-chord
- *control-modifier*
- *meta-modifier*
- *super-modifier*
- (gethash key *keycode->character*))))))
-
-(defun key-release (obj event)
- ;; Invoked upon key-release
- (declare (ignore obj)) ; supress unused warnings
- (let ((key (eql:|key| event)))
- (cond
- ((equalp key *control-key*)
- (setf *control-modifier* nil))
- ((equalp key *meta-key*)
- (setf *meta-modifier* nil))
- ((equalp key *super-key*)
- (setf *super-modifier* nil))
- (t (return-from key-release)))))
-
-(defparameter *keycode->character* (make-hash-table :test 'equalp)
- "A character -> keycode hashmap for associating the QT keycodes")
-
-(defun keycode (character keycode)
- (setf (gethash character *keycode->character*) keycode))
-
-(defun initialize-keycodes ()
- (defparameter *control-key* 16777249) ; OSX: command
- (defparameter *meta-key* 16777250) ; OSX: control
- (defparameter *alt-key* 16777251) ; OSX: option
- (defparameter *super-key* 16777249) ; OSX: command
- (when (equalp (eql:|platformName.QGuiApplication|) "cocoa")
- (let ((original_control *control-key*)
- (original_meta *meta-key*)
- (original_alt *alt-key*))
- (setf *control-key* original_meta)
- (setf *meta-key* original_alt)
- (setf *super-key* original_control)))
- (keycode 48 "0")
- (keycode 49 "1")
- (keycode 50 "2")
- (keycode 51 "3")
- (keycode 52 "4")
- (keycode 53 "5")
- (keycode 54 "6")
- (keycode 55 "7")
- (keycode 56 "8")
- (keycode 57 "9")
- (keycode 198 "AE")
- (keycode 193 "Aacute")
- (keycode 194 "Acircumflex")
- (keycode 16777408 "AddFavorite")
- (keycode 196 "Adiaeresis")
- (keycode 192 "Agrave")
- (keycode 16781571 "AltGr")
- (keycode 16777251 "Alt")
- (keycode 38 "Ampersand")
- (keycode 32 "Any")
- (keycode 39 "Apostrophe")
- (keycode 16777415 "ApplicationLeft")
- (keycode 16777416 "ApplicationRight")
- (keycode 197 "Aring")
- (keycode 94 "AsciiCircum")
- (keycode 126 "AsciiTilde")
- (keycode 42 "Asterisk")
- (keycode 195 "Atilde")
- (keycode 64 "At")
- (keycode 16777478 "AudioCycleTrack")
- (keycode 16777474 "AudioForward")
- (keycode 16777476 "AudioRandomPlay")
- (keycode 16777475 "AudioRepeat")
- (keycode 16777413 "AudioRewind")
- (keycode 16777464 "Away")
- (keycode 65 "A")
- (keycode 16777414 "BackForward")
- (keycode 92 "Backslash")
- (keycode 16777219 "Backspace")
- (keycode 16777218 "Backtab")
- (keycode 16777313 "Back")
- (keycode 124 "Bar")
- (keycode 16777331 "BassBoost")
- (keycode 16777333 "BassDown")
- (keycode 16777332 "BassUp")
- (keycode 16777470 "Battery")
- (keycode 16777471 "Bluetooth")
- (keycode 16777495 "Blue")
- (keycode 16777417 "Book")
- (keycode 123 "BraceLeft")
- (keycode 125 "BraceRight")
- (keycode 91 "BracketLeft")
- (keycode 93 "BracketRight")
- (keycode 16777410 "BrightnessAdjust")
- (keycode 66 "B")
- (keycode 16777418 "CD")
- (keycode 16777419 "Calculator")
- (keycode 16777444 "Calendar")
- (keycode 17825796 "Call")
- (keycode 17825825 "CameraFocus")
- (keycode 17825824 "Camera")
- (keycode 16908289 "Cancel")
- (keycode 16777252 "CapsLock")
- (keycode 199 "Ccedilla")
- (keycode 16777497 "ChannelDown")
- (keycode 16777496 "ChannelUp")
- (keycode 16777421 "ClearGrab")
- (keycode 16777227 "Clear")
- (keycode 16777422 "Close")
- (keycode 16781623 "Codeinput")
- (keycode 58 "Colon")
- (keycode 44 "Comma")
- (keycode 16777412 "Community")
- (keycode 17825792 "Context1")
- (keycode 17825793 "Context2")
- (keycode 17825794 "Context3")
- (keycode 17825795 "Context4")
- (keycode 16777485 "ContrastAdjust")
- (keycode 16777249 "Control")
- (keycode 16777423 "Copy")
- (keycode 16777424 "Cut")
- (keycode 67 "C")
- (keycode 16777426 "DOS")
- (keycode 16777223 "Delete")
- (keycode 36 "Dollar")
- (keycode 16777237 "Down")
- (keycode 68 "D")
- (keycode 208 "ETH")
- (keycode 201 "Eacute")
- (keycode 202 "Ecircumflex")
- (keycode 203 "Ediaeresis")
- (keycode 200 "Egrave")
- (keycode 16777401 "Eject")
- (keycode 16777233 "End")
- (keycode 16777221 "Enter")
- (keycode 61 "Equal")
- (keycode 16777216 "Escape")
- (keycode 33 "Exclam")
- (keycode 16908291 "Execute")
- (keycode 16908298 "Exit")
- (keycode 16777429 "Explorer")
- (keycode 69 "E")
- (keycode 16777273 "F10")
- (keycode 16777274 "F11")
- (keycode 16777275 "F12")
- (keycode 16777276 "F13")
- (keycode 16777277 "F14")
- (keycode 16777278 "F15")
- (keycode 16777279 "F16")
- (keycode 16777280 "F17")
- (keycode 16777281 "F18")
- (keycode 16777282 "F19")
- (keycode 16777264 "F1")
- (keycode 16777283 "F20")
- (keycode 16777284 "F21")
- (keycode 16777285 "F22")
- (keycode 16777286 "F23")
- (keycode 16777287 "F24")
- (keycode 16777288 "F25")
- (keycode 16777289 "F26")
- (keycode 16777290 "F27")
- (keycode 16777291 "F28")
- (keycode 16777292 "F29")
- (keycode 16777265 "F2")
- (keycode 16777293 "F30")
- (keycode 16777294 "F31")
- (keycode 16777295 "F32")
- (keycode 16777296 "F33")
- (keycode 16777297 "F34")
- (keycode 16777298 "F35")
- (keycode 16777266 "F3")
- (keycode 16777267 "F4")
- (keycode 16777268 "F5")
- (keycode 16777269 "F6")
- (keycode 16777270 "F7")
- (keycode 16777271 "F8")
- (keycode 16777272 "F9")
- (keycode 16777361 "Favorites")
- (keycode 16777411 "Finance")
- (keycode 16777506 "Find")
- (keycode 17825798 "Flip")
- (keycode 16777314 "Forward")
- (keycode 70 "F")
- (keycode 16777430 "Game")
- (keycode 16777431 "Go")
- (keycode 62 "Greater")
- (keycode 16777493 "Green")
- (keycode 16777498 "Guide")
- (keycode 71 "G")
- (keycode 16777304 "Help")
- (keycode 16781603 "Henkan")
- (keycode 16777480 "Hibernate")
- (keycode 16777407 "History")
- (keycode 16777360 "HomePage")
- (keycode 16777232 "Home")
- (keycode 16777409 "HotLinks")
- (keycode 16777302 "Hyper_L")
- (keycode 16777303 "Hyper_R")
- (keycode 72 "H")
- (keycode 205 "Iacute")
- (keycode 206 "Icircumflex")
- (keycode 207 "Idiaeresis")
- (keycode 204 "Igrave")
- (keycode 16777499 "Info")
- (keycode 16777222 "Insert")
- (keycode 73 "I")
- (keycode 74 "J")
- (keycode 16777398 "KeyboardBrightnessDown")
- (keycode 16777397 "KeyboardBrightnessUp")
- (keycode 16777396 "KeyboardLightOnOff")
- (keycode 75 "K")
- (keycode 16777378 "Launch0")
- (keycode 16777379 "Launch1")
- (keycode 16777380 "Launch2")
- (keycode 16777381 "Launch3")
- (keycode 16777382 "Launch4")
- (keycode 16777383 "Launch5")
- (keycode 16777384 "Launch6")
- (keycode 16777385 "Launch7")
- (keycode 16777386 "Launch8")
- (keycode 16777387 "Launch9")
- (keycode 16777388 "LaunchA")
- (keycode 16777389 "LaunchB")
- (keycode 16777390 "LaunchC")
- (keycode 16777391 "LaunchD")
- (keycode 16777392 "LaunchE")
- (keycode 16777393 "LaunchF")
- (keycode 16777486 "LaunchG")
- (keycode 16777487 "LaunchH")
- (keycode 16777376 "LaunchMail")
- (keycode 16777377 "LaunchMedia")
- (keycode 16777234 "Left")
- (keycode 60 "Less")
- (keycode 16777405 "LightBulb")
- (keycode 16777433 "LogOff")
- (keycode 76 "L")
- (keycode 16777467 "MailForward")
- (keycode 16777434 "Market")
- (keycode 16781612 "Massyo")
- (keycode 16842751 "MediaLast")
- (keycode 16777347 "MediaNext")
- (keycode 16777349 "MediaPause")
- (keycode 16777344 "MediaPlay")
- (keycode 16777346 "MediaPrevious")
- (keycode 16777348 "MediaRecord")
- (keycode 16777345 "MediaStop")
- (keycode 16777350 "MediaTogglePlayPause")
- (keycode 16777435 "Meeting")
- (keycode 16777404 "Memo")
- (keycode 16777436 "MenuKB")
- (keycode 16777437 "MenuPB")
- (keycode 16777301 "Menu")
- (keycode 16777465 "Messenger")
- (keycode 16777250 "Meta")
- (keycode 16777491 "MicMute")
- (keycode 16777502 "MicVolumeDown")
- (keycode 16777501 "MicVolumeUp")
- (keycode 45 "Minus")
- (keycode 77 "M")
- (keycode 16777439 "News")
- (keycode 16777504 "New")
- (keycode 16842754 "No")
- (keycode 209 "Ntilde")
- (keycode 16777253 "NumLock")
- (keycode 35 "NumberSign")
- (keycode 78 "N")
- (keycode 211 "Oacute")
- (keycode 212 "Ocircumflex")
- (keycode 214 "Odiaeresis")
- (keycode 16777440 "OfficeHome")
- (keycode 210 "Ograve")
- (keycode 216 "Ooblique")
- (keycode 16777364 "OpenUrl")
- (keycode 16777505 "Open")
- (keycode 16777441 "Option")
- (keycode 213 "Otilde")
- (keycode 79 "O")
- (keycode 16777239 "PageDown")
- (keycode 16777238 "PageUp")
- (keycode 40 "ParenLeft")
- (keycode 41 "ParenRight")
- (keycode 16777442 "Paste")
- (keycode 16777224 "Pause")
- (keycode 37 "Percent")
- (keycode 46 "Period")
- (keycode 16777443 "Phone")
- (keycode 16777468 "Pictures")
- (keycode 16908293 "Play")
- (keycode 43 "Plus")
- (keycode 16777483 "PowerDown")
- (keycode 16777399 "PowerOff")
- (keycode 16781630 "PreviousCandidate")
- (keycode 16908290 "Printer")
- (keycode 16777225 "Print")
- (keycode 80 "P")
- (keycode 63 "Question")
- (keycode 34 "QuoteDbl")
- (keycode 96 "QuoteLeft")
- (keycode 81 "Q")
- (keycode 16777508 "Redo")
- (keycode 16777492 "Red")
- (keycode 16777316 "Refresh")
- (keycode 16777446 "Reload")
- (keycode 16777445 "Reply")
- (keycode 16777220 "Return")
- (keycode 16777236 "Right")
- (keycode 16781604 "Romaji")
- (keycode 16777447 "RotateWindows")
- (keycode 16777449 "RotationKB")
- (keycode 16777448 "RotationPB")
- (keycode 82 "R")
- (keycode 16777450 "Save")
- (keycode 16777402 "ScreenSaver")
- (keycode 16777254 "ScrollLock")
- (keycode 16777362 "Search")
- (keycode 16842752 "Select")
- (keycode 59 "Semicolon")
- (keycode 16777451 "Send")
- (keycode 16777500 "Settings")
- (keycode 16777248 "Shift")
- (keycode 16777406 "Shop")
- (keycode 16781628 "SingleCandidate")
- (keycode 47 "Slash")
- (keycode 16908292 "Sleep")
- (keycode 32 "Space")
- (keycode 16777452 "Spell")
- (keycode 16777453 "SplitScreen")
- (keycode 16777363 "Standby")
- (keycode 16777315 "Stop")
- (keycode 16777477 "Subtitle")
- (keycode 16777299 "Super_L")
- (keycode 16777300 "Super_R")
- (keycode 16777454 "Support")
- (keycode 16777484 "Suspend")
- (keycode 16777226 "SysReq")
- (keycode 83 "S")
- (keycode 222 "THORN")
- (keycode 16777217 "Tab")
- (keycode 16777455 "TaskPane")
- (keycode 16777456 "Terminal")
- (keycode 16777479 "Time")
- (keycode 16777420 "ToDoList")
- (keycode 17825799 "ToggleCallHangup")
- (keycode 16777457 "Tools")
- (keycode 16777482 "TopMenu")
- (keycode 16777490 "TouchpadOff")
- (keycode 16777489 "TouchpadOn")
- (keycode 16777488 "TouchpadToggle")
- (keycode 16781611 "Touroku")
- (keycode 16777458 "Travel")
- (keycode 16777335 "TrebleDown")
- (keycode 16777334 "TrebleUp")
- (keycode 84 "T")
- (keycode 16777473 "UWB")
- (keycode 218 "Uacute")
- (keycode 219 "Ucircumflex")
- (keycode 220 "Udiaeresis")
- (keycode 217 "Ugrave")
- (keycode 95 "Underscore")
- (keycode 16777507 "Undo")
- (keycode 16777235 "Up")
- (keycode 85 "U")
- (keycode 16777459 "Video")
- (keycode 16777481 "View")
- (keycode 17825800 "VoiceDial")
- (keycode 16777328 "VolumeDown")
- (keycode 16777329 "VolumeMute")
- (keycode 16777330 "VolumeUp")
- (keycode 86 "V")
- (keycode 16777472 "WLAN")
- (keycode 16777403 "WWW")
- (keycode 16777400 "WakeUp")
- (keycode 16777466 "WebCam")
- (keycode 16777460 "Word")
- (keycode 87 "W")
- (keycode 16777461 "Xfer")
- (keycode 88 "X")
- (keycode 221 "Yacute")
- (keycode 16777494 "Yellow")
- (keycode 16842753 "Yes")
- (keycode 89 "Y")
- (keycode 16777462 "ZoomIn")
- (keycode 16777463 "ZoomOut")
- (keycode 16908294 "Zoom")
- (keycode 90 "Z")
- (keycode 180 "acute")
- (keycode 166 "brokenbar")
- (keycode 184 "cedilla")
- (keycode 162 "cent")
- (keycode 169 "copyright")
- (keycode 164 "currency")
- (keycode 176 "degree")
- (keycode 168 "diaeresis")
- (keycode 247 "division")
- (keycode 161 "exclamdown")
- (keycode 171 "guillemotleft")
- (keycode 187 "guillemotright")
- (keycode 173 "hyphen")
- (keycode 16777432 "iTouch")
- (keycode 175 "macron")
- (keycode 186 "masculine")
- (keycode 215 "multiply")
- (keycode 181 "mu")
- (keycode 160 "nobreakspace")
- (keycode 172 "notsign")
- (keycode 189 "onehalf")
- (keycode 188 "onequarter")
- (keycode 185 "onesuperior")
- (keycode 170 "ordfeminine")
- (keycode 182 "paragraph")
- (keycode 183 "periodcentered")
- (keycode 177 "plusminus")
- (keycode 191 "questiondown")
- (keycode 174 "registered")
- (keycode 167 "section")
- (keycode 223 "ssharp")
- (keycode 163 "sterling")
- (keycode 190 "threequarters")
- (keycode 179 "threesuperior")
- (keycode 178 "twosuperior")
- (keycode 33554431 "unknown")
- (keycode 255 "ydiaeresis")
- (keycode 165 "yen"))
diff --git a/next/main.cpp b/next/main.cpp
deleted file mode 100644
index 41761e8d9..000000000
--- a/next/main.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#undef SLOT
-
-#include <ecl/ecl.h>
-#include <eql5/eql.h>
-#include <QApplication>
-#include <QTextCodec>
-#include <QSettings>
-#include <QTranslator>
-
-extern "C" void init_lib_NEXT__ALL_SYSTEMS(cl_object);
-
-int catch_all_qexec() {
- int ret = 0;
- CL_CATCH_ALL_BEGIN(ecl_process_env()) {
- ret = QApplication::exec(); }
- CL_CATCH_ALL_END;
- return ret; }
-
-int main(int argc, char** argv) {
-
- EQL::ini(argv);
-
- QApplication qapp(argc, argv);
-
- QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");
- QTextCodec::setCodecForLocale(utf8);
-
- EQL eql;
-
- eql.exec(init_lib_NEXT__ALL_SYSTEMS);
-
- return catch_all_qexec(); } // closing the main/last window will quit the program
diff --git a/next/make.lisp b/next/make.lisp
index f66f0b58b..31c7b4a5d 100644
--- a/next/make.lisp
+++ b/next/make.lisp
@@ -1,87 +1,46 @@
;;;; make.lisp --- create binary files for nEXT
-
-;;;; Pre-requisties:
-;;;; - dylibbundler (available via ports)
-;;;; - ecl (available at the official website)
-;;;; - eql (available at the official repository)
;;;;
;;;; See Next/next/README.org for more information on installing the
;;;; dependencies necessary to build nEXT from source
;;;;
;;;; Please note that this script must be run from the directory
-;;;; Next/next. It may be necessary to modify the paths or commands in
-;;;; the "Bundle OSX Dependencies" List.
-
-#-eql5
-(error "Please use the EQL5 executable (see README)")
-(require :cmp)
-(push "./" asdf:*central-registry*)
-(ql:quickload "next")
-
-;; build static library
-(asdf:make-build "next"
- :monolithic t
- :type :static-library
- :move-here "./")
-
-;; rename static library
-(let ((lib-name #+msvc "next.lib"
- #-msvc "libnext.a"))
- (when (probe-file lib-name)
- (delete-file lib-name))
- (rename-file (x:cc "next--all-systems"
- #+msvc ".lib"
- #-msvc ".a")
- lib-name))
-
-;; execute qmake
-(ext:run-program "qmake" nil :output t)
+;;;; Next/next.
-;; execute make
-(ext:run-program "make" nil :output t)
+(let ((quicklisp-init (merge-pathnames ".quicklisp/setup.lisp" (user-homedir-pathname))))
+ (when (probe-file quicklisp-init)
+ (load quicklisp-init)))
+(require :asdf)
-
-;;;; Cleanup Operations ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; delete tmp dir to force recompilation
-(uiop:delete-directory-tree
- (merge-pathnames (make-pathname
- :directory '(:relative "tmp"))
- (asdf:system-source-directory :next))
- :validate T
- :if-does-not-exist :ignore)
-;; delete libnext.a
-(uiop:delete-file-if-exists
- (format nil "~Alibnext.a" (asdf:system-source-directory :next)))
-;; delete Makefile
-(uiop:delete-file-if-exists
- (format nil "~AMakefile" (asdf:system-source-directory :next)))
-
-;;;; Prompt the User to Bundle Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(format *query-io* "[0] Quit [1] Bundle OSX Dependencies: ")
-(force-output *query-io*)
-(let ((input (read-line *query-io*)))
- (cond ((equalp input "0") )
- ((equalp input "1")
- (progn
- (ext:run-program
- "dylibbundler"
- '("-cd"
- "-b"
- "-x"
- "./next.app/Contents/MacOS/next"
- "-d"
- "./next.app/Contents/libs") :input t :output t)
-
- (ext:run-program
- "macdeployqt"
- '("./next.app/"
- "-libpath=/usr/local/lib") :output t)
-
- (ext:run-program
- "install_name_tool"
- '("-change"
- "@libdir@/libecl.16.1.dylib"
- "@executable_path/../libs/libecl.16.1.dylib"
- "./next.app/Contents/MacOS/next") :output t)))))
-
-(qquit)
+(push "./" asdf:*central-registry*)
+(ql:quickload "next" :silent t)
+
+(defparameter *source-dir* (make-pathname :name nil :type nil
+ :defaults *load-truename*))
+(defparameter *build-dir* (merge-pathnames "build/" *source-dir*))
+
+(defvar *bundle-dir*)
+(defvar *contents-dir*)
+(defvar *resources-dir*)
+(defvar *macos-dir*)
+
+(defun build-next (&optional (build-dir *build-dir*))
+ (let* ((*build-dir* build-dir)
+ (*bundle-dir* (merge-pathnames "nEXT.app/" *build-dir*))
+ (*contents-dir* (merge-pathnames "Contents/" *bundle-dir*))
+ (*resources-dir* (merge-pathnames "Resources/" *contents-dir*))
+ (*macos-dir* (merge-pathnames "MacOS/" *contents-dir*))
+ (*default-pathname-defaults* *source-dir*))
+ (ccl::ensure-directories-exist *resources-dir*)
+ (ccl::ensure-directories-exist (merge-pathnames "ccl/" *resources-dir*))
+ (ccl::ensure-directories-exist *macos-dir*)
+ (ccl::copy-file "../assets/Info.plist" (merge-pathnames "Info.plist" *contents-dir*)
+ :if-exists :supersede)
+ (ccl::copy-file "../assets/next.icns" (merge-pathnames "next.icns" *resources-dir*)
+ :if-exists :supersede)
+ (ccl::copy-file (ccl::kernel-path) (merge-pathnames "nEXT" *macos-dir*)
+ :if-exists :supersede
+ :preserve-attributes t)
+ (ccl::save-application (merge-pathnames "ccl/nEXT.image" *resources-dir*)
+ :application-class (find-symbol "COCOA-APPLICATION" "CCL"))))
+
+(build-next)
diff --git a/next/next.asd b/next/next.asd
index 2818c171f..30fc6b158 100644
--- a/next/next.asd
+++ b/next/next.asd
@@ -2,10 +2,14 @@
;;;; next.asd
(defsystem :next
:serial t
- :depends-on (:cl-strings :cl-string-match :puri :queues.simple-queue :sqlite)
- :pathname "lisp/"
+ :depends-on (:cl-strings :cl-string-match :puri :queues.simple-queue :sqlite
+ (:require "cocoa") (:require "webkit"))
+ :pathname "source/"
:components ((:file "package")
- (:file "qt")
+ (:file "global")
+ (:file "cocoa/utilities")
+ (:file "cocoa/cocoa")
+ (:file "cocoa/application")
(:file "macro")
(:file "mode")
(:file "keymap")
diff --git a/next/next.pro b/next/next.pro
deleted file mode 100644
index 7ccf58fed..000000000
--- a/next/next.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-QT += widgets printsupport uitools
-TEMPLATE = app
-ICON = ../assets/next.icns
-CONFIG += no_keywords release
-INCLUDEPATH += /usr/local/include
-INCLUDEPATH += /usr/local/include/eql
-LIBS += -lecl -L. -lnext -L/usr/local/lib -leql5 -leql5_webkit
-TARGET = next
-DESTDIR = ./
-OBJECTS_DIR = ./tmp/
-MOC_DIR = ./tmp/
-QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
-SOURCES += main.cpp
diff --git a/next/run.lisp b/next/run.lisp
deleted file mode 100644
index 32ca24d00..000000000
--- a/next/run.lisp
+++ /dev/null
@@ -1,10 +0,0 @@
-;;; run.lisp --- helper runner program to run from the command line
-;;; to launch nEXT simply `eql5 run.lisp`
-(push "./" asdf:*central-registry*)
-(ql:quickload "next")
-(asdf:load-system "next")
-
-(in-package #:next)
-
-;; start nEXT
-(start)
diff --git a/next/source/base.lisp b/next/source/base.lisp
new file mode 100644
index 000000000..161efe6e1
--- /dev/null
+++ b/next/source/base.lisp
@@ -0,0 +1,52 @@
+;;;; base.lisp --- main entry point into nEXT
+
+(in-package :next)
+
+(defun start ()
+ (ensure-directories-exist (uiop:physicalize-pathname #P"~/.next.d/"))
+ (initialize-bookmark-db)
+ (initialize-default-key-bindings)
+ (interface:initialize)
+ (interface:start)
+ ;; create the default buffers
+ (setf *minibuffer*
+ (make-instance 'buffer :name "minibuffer" :mode (minibuffer-mode)))
+ (set-visible-active-buffer (generate-new-buffer "default" (document-mode)))
+ ;; load the user configuration if it exists
+ (load "~/.next.d/init.lisp" :if-does-not-exist nil))
+
+(defun initialize-default-key-bindings ()
+ (define-key global-map (kbd "C-x C-c")
+ #'interface:kill)
+ (define-key global-map (kbd "C-x b")
+ (:input-complete *minibuffer* switch-buffer buffer-complete))
+ (define-key global-map (kbd "C-x k")
+ (:input-complete *minibuffer* delete-buffer buffer-complete))
+ (define-key global-map (kbd "M-l")
+ (:input *minibuffer* set-url-new-buffer))
+ (define-key global-map (kbd "S-b k")
+ (:input-complete *minibuffer* bookmark-delete bookmark-complete))
+ (define-key minibuffer-mode-map (kbd " ")
+ #'(lambda () (return-input (buffer-mode *minibuffer*))))
+ (define-key minibuffer-mode-map (kbd "C-g")
+ #'(lambda () (cancel-input (buffer-mode *minibuffer*))))
+ (define-key minibuffer-mode-map (kbd "Escape")
+ #'(lambda () (cancel-input (buffer-mode *minibuffer*))))
+ (define-key document-mode-map (kbd "M-f")
+ (:input-complete *minibuffer* history-forwards-query history-fowards-query-complete))
+ (define-key document-mode-map (kbd "M-b")
+ #'history-backwards)
+ (define-key document-mode-map (kbd "C-f")
+ #'history-forwards)
+ (define-key document-mode-map (kbd "C-b")
+ #'history-backwards)
+ (define-key document-mode-map (kbd "C-p")
+ #'scroll-up)
+ (define-key document-mode-map (kbd "C-n")
+ #'scroll-down)
+ (define-key document-mode-map (kbd "C-l")
+ (:input *minibuffer* set-url))
+ (define-key document-mode-map (kbd "S-b o")
+ (:input-complete *minibuffer* set-url bookmark-complete))
+ (define-key document-mode-map (kbd "S-b s")
+ #'bookmark-current-page))
diff --git a/next/lisp/bookmark.lisp b/next/source/bookmark.lisp
index 7606cfb82..7606cfb82 100644
--- a/next/lisp/bookmark.lisp
+++ b/next/source/bookmark.lisp
diff --git a/next/lisp/buffer.lisp b/next/source/buffer.lisp
index 9ac1683c3..88e9e13cf 100644
--- a/next/lisp/buffer.lisp
+++ b/next/source/buffer.lisp
@@ -2,25 +2,18 @@
(in-package :next)
-(defvar *buffers* ()
- "A list of all existing buffers")
-(defvar *active-buffer* ()
- "The currently active buffer")
-
(defclass buffer ()
((name :accessor buffer-name :initarg :name)
(mode :accessor buffer-mode :initarg :mode)
(view :accessor buffer-view :initarg :view)))
-(defun generate-new-buffer (name mode &optional (add-to-stack-layout t))
+(defun generate-new-buffer (name mode)
(let ((new-buffer
(make-instance 'buffer
:name name
:mode mode
:view (mode-view mode))))
(push new-buffer *buffers*)
- (when add-to-stack-layout
- (interface:add-to-stack-layout (buffer-view new-buffer)))
new-buffer))
(defun set-active-buffer (buffer)
diff --git a/next/source/cocoa/application.lisp b/next/source/cocoa/application.lisp
new file mode 100644
index 000000000..448ee2235
--- /dev/null
+++ b/next/source/cocoa/application.lisp
@@ -0,0 +1,89 @@
+(in-package "CCL")
+
+(defclass next-application (ns:ns-application) ()
+ (:metaclass ns:+ns-application))
+
+(objc:defmethod (#/sendEvent: :void) ((self next-application) event)
+ (if (eql #$NSKeyDown (#/type event))
+ (unless (interface:process-event event)
+ (call-next-method event))
+ (call-next-method event)))
+
+(defclass cocoa-ui-object (ui-object) ())
+
+(defclass cocoa-application (application)
+ ((standalone-p :initform nil :accessor cocoa-application-standalone-p)))
+
+(defparameter *cocoa-application*
+ (make-instance 'cocoa-application
+ :ui-object (make-instance 'cocoa-ui-object)))
+
+(defmethod application-error ((self cocoa-application) condition error-pointer)
+ (break-loop-handle-error condition error-pointer))
+
+(defmethod parse-application-arguments ((self cocoa-application))
+ (values nil nil nil nil))
+
+(defmethod toplevel-function ((self cocoa-application) init-file)
+ (declare (ignore init-file))
+ (setf (cocoa-application-standalone-p self) t)
+ (prepare-cocoa-application self)
+ (start-cocoa-application self))
+
+(defmethod prepare-cocoa-application ((self cocoa-application))
+ (call-in-initial-process #'(lambda ()
+ (setq *nsapp* (load-cocoa-application self))
+ (next:start))))
+
+(defmethod load-cocoa-application ((a cocoa-application))
+ (with-autorelease-pool
+ (let* ((bundle (#/mainBundle ns:ns-bundle))
+ (info (#/infoDictionary bundle))
+ (progname (#/objectForKey: info #@"CFBundleName")))
+ (unless (%null-ptr-p progname)
+ (#/setProcessName: (#/processInfo ns:ns-process-info) progname))
+ (let* ((appclass next-application)
+ (app (#/sharedApplication appclass)))
+ (when (%null-ptr-p app)
+ (error "Could not create shared instance of ~s"
+ (%get-cfstring classname)))
+ app))))
+
+(defun become-foreground-application ()
+ (rlet ((psn #>ProcessSerialNumber))
+ (#_GetCurrentProcess psn)
+ (#_TransformProcessType psn #$kProcessTransformToForegroundApplication)))
+
+(defun event-loop ()
+ (loop
+ (with-simple-restart (abort "Process the next event")
+ (#/run *nsapp*))))
+
+(defun run-event-loop ()
+ (%set-toplevel nil)
+ (assert (eq *current-process* *initial-process*))
+ (change-class *initial-process* 'cocoa-event-process)
+ (setf (process-name *initial-process*) "Cocoa event loop")
+ (with-process-whostate ("Active")
+ (event-loop)))
+
+;; After the lisp starts up, it creates a listener thread. The
+;; initial thead then goes to sleep, waking up about 3 times a second
+;; to do some housekeeping tasks.
+;;
+;; Because most of Cocoa needs to run on the initial thread, we
+;; interrupt the initial thread, and use %set-toplevel and toplevel
+;; (which are basically process-preset and process-reset for the
+;; initial process) to make it start running the Cocoa event loop. We
+;; create a new thread to do the housekeeping.
+
+(defmethod start-cocoa-application ((a cocoa-application))
+ (flet ((startup ()
+ (with-standard-initial-bindings
+ (process-run-function "housekeeping" #'housekeeping-loop)
+ (become-foreground-application)
+ (run-event-loop))))
+ (process-interrupt *initial-process*
+ #'(lambda ()
+ (%set-toplevel #'startup)
+ (toplevel)))))
diff --git a/next/source/cocoa/cocoa.lisp b/next/source/cocoa/cocoa.lisp
new file mode 100644
index 000000000..e66b4003f
--- /dev/null
+++ b/next/source/cocoa/cocoa.lisp
@@ -0,0 +1,224 @@
+;;;; cocoa.lisp --- cocoa helper functions & data
+
+(in-package :interface)
+
+(defparameter *window* nil)
+(defparameter *next-view* nil)
+
+(defclass minibuffer-view (ns:ns-view)
+ ((input-buffer :accessor input-buffer)
+ (completion-table :accessor completion-table)
+ (completion-controller :accessor completion-controller)
+ (completion-function :accessor completion-function))
+ (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self minibuffer-view)
+ &key &allow-other-keys)
+ (let* ((input-field (make-instance 'ns:ns-text-field))
+ (completion-controller (make-instance 'controller
+ :data ()))
+ (completion-column (#/autorelease (make-instance ns:ns-table-column
+ :column-title "Completion"
+ :identifier "Completion"
+ :min-width 80
+ :editable nil
+ :selectable t)))
+ (completion-table
+ (make-instance ns:ns-table-view
+ :allows-column-resizing nil
+ :column-autoresizing-style :uniform)))
+ (#/setDelegate: input-field self)
+ (#/addTableColumn: completion-table completion-column)
+ (#/setDataSource: completion-table completion-controller)
+ (setf (input-buffer self) input-field)
+ (setf (completion-table self) completion-table)
+ (setf (completion-controller self) completion-controller)
+ (#/addSubview: self input-field)
+ (#/addSubview: self completion-table)
+ (make-constraint :item1 input-field :att1 :center-x :relation := :item2 self :att2 :center-x)
+ (make-constraint :item1 input-field :att1 :width :relation := :item2 self :att2 :width)
+ (make-constraint :item1 input-field :att1 :top :relation := :item2 self :att2 :top)
+ (make-constraint :item1 input-field :att1 :height :relation := :const 20)
+ (make-constraint :item1 completion-table :att1 :top :relation := :item2 input-field :att2 :bottom)
+ (make-constraint :item1 completion-table :att1 :bottom :relation := :item2 self :att2 :bottom)
+ (make-constraint :item1 completion-table :att1 :width :relation := :item2 self :att2 :width)))
+
+(defmethod get-input ((self minibuffer-view))
+ (ns-to-lisp-string (#/stringValue (input-buffer self))))
+
+(defmethod process-set-completions ((self minibuffer-view))
+ "Process and set completions for the minibuffer"
+ (with-slots (completion-function completion-controller completion-table) self
+ (when (completion-function self)
+ (setf (data completion-controller) (funcall completion-function (get-input self)))
+ (#/reloadData completion-table))))
+
+(objc:defmethod (#/controlTextDidChange: :void) ((self minibuffer-view) notification)
+ (declare (ignore notification))
+ (process-set-completions self))
+
+(defclass next-web-view (ns:web-view)
+ ((load-finished-callback :accessor load-finished-callback))
+ (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/webView:didFinishLoadForFrame: :void)
+ ((self next-web-view)
+ (wvs :id)
+ (fl :id))
+ (declare (ignore wvs fl))
+ (funcall (load-finished-callback self)))
+
+(defclass fill-container-view (ns:ns-view)
+ ((fill-view :accessor fill-view
+ :initarg :fill-view))
+ (:default-initargs
+ :fill-view nil)
+ (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self fill-container-view)
+ &key (fill-view nil) &allow-other-keys)
+ (when (and fill-view (view-p fill-view))
+ (#/addSubview: self fill-view)
+ (constrain-size-relative-to fill-view self :rel :=)))
+
+(defmethod set-fill-view ((self fill-container-view) view)
+ (on-main-thread
+ (when (fill-view self)
+ (#/removeFromSuperview (fill-view self)))
+ (#/addSubview: self view)
+ (constrain-size-relative-to view self :rel :=))
+ (setf (fill-view self) view))
+
+(defclass next-view (ns:ns-view)
+ ((%fill-container-view :accessor fill-container-view)
+ (%minibuffer-view :accessor minibuffer-view)
+ (minibuffer-height-constraint :accessor minibuffer-height-constraint))
+ (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self next-view)
+ &key &allow-other-keys)
+ (let ((fvc (make-instance 'fill-container-view))
+ (mb (make-instance 'minibuffer-view)))
+ (#/addSubview: self fvc)
+ (#/addSubview: self mb)
+ (setf (fill-container-view self) fvc)
+ (setf (minibuffer-view self) mb)
+ (make-constraint :item1 fvc :att1 :top :relation := :item2 self :att2 :top)
+ (make-constraint :item1 fvc :att1 :width :relation := :item2 self :att2 :width)
+ (make-constraint :item1 fvc :att1 :bottom :relation := :item2 mb :att2 :top)
+ (make-constraint :item1 mb :att1 :bottom :relation := :item2 self :att2 :bottom)
+ (make-constraint :item1 mb :att1 :width :relation := :item2 self :att2 :width)
+ (setf (minibuffer-height-constraint self)
+ (make-constraint :item1 mb :att1 :height :relation := :const 0))))
+
+(defmethod hide-minibuffer ((self next-view))
+ (on-main-thread
+ (#/setConstant: (minibuffer-height-constraint self) 0)))
+
+(defmethod show-minibuffer ((self next-view))
+ (on-main-thread
+ (#/setConstant: (minibuffer-height-constraint self) 200)))
+
+(defclass next-window (ns:ns-window) ()
+ (:metaclass ns:+ns-object))
+
+(defun process-event (event)
+ (let* ((flags (#/modifierFlags event))
+ (character (ns-to-lisp-string (#/charactersIgnoringModifiers event))))
+ (next:push-key-chord
+ (> (logand flags #$NSControlKeyMask) 0)
+ (> (logand flags #$NSAlternateKeyMask) 0)
+ (> (logand flags #$NSCommandKeyMask) 0)
+ character)))
+
+(defun make-window ()
+ (gui::assume-cocoa-thread)
+ (ns:with-ns-rect (r 100.0 100.0 1024.0 768.0)
+ (ccl::with-autorelease-pool
+ (let* ((.window. (make-instance
+ 'next-window
+ :with-content-rect r
+ :style-mask (logior #$NSTitledWindowMask
+ #$NSClosableWindowMask
+ #$NSMiniaturizableWindowMask
+ #$NSResizableWindowMask)
+ :backing #$NSBackingStoreBuffered
+ :title "nEXT"
+ :defer t))
+ (.next-view. (make-instance 'next-view)))
+ (#/setContentView: .window. .next-view.)
+ (#/makeKeyAndOrderFront: .window. +null-ptr+)
+ (setf *window* .window.)
+ (setf *next-view* .next-view.)
+ *window*))))
+
+(defun initialize ())
+
+(defun start ()
+ (on-main-thread
+ (make-window)))
+
+(defun kill ()
+ (quit))
+
+(defun set-visible-view (view)
+ (set-fill-view (fill-container-view *next-view*) view))
+
+(defun make-web-view ()
+ (on-main-thread
+ (ccl::with-autorelease-pool
+ (let ((view (#/retain
+ (make-instance
+ 'next-web-view
+ :frame-name #@"frame"
+ :group-name #@"group"))))
+ (#/setFrameLoadDelegate: view view)
+ view))))
+
+(defun url-from-string (s)
+ (ccl::with-autorelease-pool
+ (#/retain (#/URLWithString: ns:ns-url (ccl::%make-nsstring (string s))))))
+
+(defun web-view-set-url (view url)
+ (on-main-thread
+ (let* ((nsurl (url-from-string url))
+ (webframe (#/mainFrame view))
+ (request (#/requestWithURL: ns:ns-url-request nsurl)))
+ (#/loadRequest: webframe request))))
+
+(defun delete-view (view)
+ (#/release view))
+
+(defun web-view-scroll-down (view scroll-distance)
+ (declare (ignore scroll-distance))
+ (on-main-thread
+ (#/stringByEvaluatingJavaScriptFromString: view #@"window.scrollBy(0, 100);")))
+
+(defun web-view-scroll-up (view scroll-distance)
+ (declare (ignore scroll-distance))
+ (on-main-thread
+ (#/stringByEvaluatingJavaScriptFromString: view #@"window.scrollBy(0, -100);")))
+
+(defun web-view-set-url-loaded-callback (view function)
+ (setf (load-finished-callback view) function))
+
+(defun web-view-get-url (view)
+ (ns-to-lisp-string (#/mainFrameURL view)))
+
+(defun make-minibuffer ()
+ (minibuffer-view *next-view*))
+
+(defun minibuffer-show ()
+ (show-minibuffer *next-view*)
+ (#/makeFirstResponder: *window* (input-buffer (minibuffer-view *next-view*)))
+ (process-set-completions (minibuffer-view *next-view*)))
+
+(defun minibuffer-hide ()
+ (hide-minibuffer *next-view*)
+ (#/makeFirstResponder: *window* (fill-container-view *next-view*)))
+
+(defun minibuffer-get-input ()
+ (get-input (minibuffer-view *next-view*)))
+
+(defun minibuffer-set-completion-function (function)
+ (setf (completion-function (minibuffer-view *next-view*)) function))
diff --git a/next/source/cocoa/utilities.lisp b/next/source/cocoa/utilities.lisp
new file mode 100644
index 000000000..04160424c
--- /dev/null
+++ b/next/source/cocoa/utilities.lisp
@@ -0,0 +1,187 @@
+;;;; cocoa-utilities.lisp
+
+
+#|
+The MIT license.
+
+Copyright (c) 2013 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(in-package :interface)
+
+(defmacro on-main-thread (&rest actions)
+ `(ccl::call-in-event-process
+ #'(lambda ()
+ ,@actions)))
+
+(defun ns-to-lisp-string (ns-str)
+ (if (and (not (eql (%null-ptr) ns-str)) (plusp (#/length ns-str)))
+ (ccl::%get-utf-8-cstring (#/UTF8String ns-str))
+ ""))
+
+(defun lisp-to-ns-string (lisp-str)
+ (ccl::%make-nsstring lisp-str))
+
+(defun view-p (thing)
+ (typep thing 'ns:ns-view))
+
+(defun obj-if-not-null (ns-obj)
+ (if (eql ns-obj (%null-ptr))
+ nil
+ ns-obj))
+
+(defmethod superview ((v ns:ns-view))
+ (obj-if-not-null (#/superview v)))
+
+(defmethod common-superview (v1 v2)
+ (cond ((and (view-p v1) (view-p v2))
+ (if (eql v1 v2)
+ (superview v1)
+ (obj-if-not-null (#/ancestorSharedWithView: v1 v2))))
+ ((view-p v1)
+ (superview v1))
+ ((view-p v2)
+ (superview v2))
+ (t
+ nil)))
+
+(defun relation-convert (rel-key)
+ (case rel-key
+ (:<= #$NSLayoutRelationLessThanOrEqual)
+ (:= #$NSLayoutRelationEqual)
+ (:>= #$NSLayoutRelationGreaterThanOrEqual)
+ (t #$NSLayoutRelationEqual)))
+
+(defun attribute-convert (att-key)
+ (case att-key
+ (:left #$NSLayoutAttributeLeft)
+ (:right #$NSLayoutAttributeRight)
+ (:top #$NSLayoutAttributeTop)
+ (:bottom #$NSLayoutAttributeBottom)
+ (:leading #$NSLayoutAttributeLeading)
+ (:trailing #$NSLayoutAttributeTrailing)
+ (:width #$NSLayoutAttributeWidth)
+ (:height #$NSLayoutAttributeHeight)
+ (:center-x #$NSLayoutAttributeCenterX)
+ (:center-y #$NSLayoutAttributeCenterY)
+ (:baseline #$NSLayoutAttributeBaseline)
+ (:none #$NSLayoutAttributeNotAnAttribute)
+ (t #$NSLayoutAttributeNotAnAttribute)))
+
+(defun make-constraint (&key
+ (install-view nil install-view-provided)
+ (priority nil)
+ item1
+ (att1 :width)
+ (relation :=)
+ (item2 nil)
+ (att2 nil) ;; defaults to att1 if item2 is not null
+ (mult 1)
+ (const 0))
+ (unless install-view-provided
+ (setf install-view (common-superview item1 item2)))
+ (when (and (view-p item1)
+ install-view
+ (not (eql item1 install-view))
+ (#/translatesAutoresizingMaskIntoConstraints item1))
+ ;; make sure no automatic constraints are used for this view
+ (#/setTranslatesAutoresizingMaskIntoConstraints: item1 #$NO))
+ (when (and (view-p item2)
+ install-view
+ (not (eql item2 install-view))
+ (#/translatesAutoresizingMaskIntoConstraints item2))
+ ;; make sure no automatic constraints are used for this view
+ (#/setTranslatesAutoresizingMaskIntoConstraints: item2 #$NO))
+ (let* ((rel (relation-convert relation))
+ (a1 (attribute-convert att1))
+ (a2 (cond (att2 (attribute-convert att2))
+ ((or (null item2) (eql item2 (%null-ptr))) (attribute-convert :none))
+ (t a1)))
+ (constraint (#/constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
+ ns:ns-layout-constraint
+ item1
+ a1
+ rel
+ (or item2 (%null-ptr))
+ a2
+ (gui::cgfloat mult)
+ (gui::cgfloat const))))
+ (when (numberp priority)
+ (#/setPriority: constraint (float priority)))
+ (when (view-p install-view)
+ (on-main-thread
+ (#/addConstraint: install-view constraint)))
+ constraint))
+
+(defmethod constrain-size-relative-to ((sized-view ns:ns-view) (relative-view ns:ns-view)
+ &key
+ (priority nil)
+ (install-view (common-superview sized-view relative-view))
+ (rel :=)
+ (width t)
+ (height t))
+ ;; constrains sized-view relative to the size of relative-view
+ ;; rel should be one of the keywords := :<= :>=
+ (let ((constraints nil))
+ (when width
+ (push (make-constraint
+ :priority priority
+ :install-view install-view
+ :item1 sized-view
+ :att1 :width
+ :relation rel
+ :item2 relative-view
+ :att2 :width)
+ constraints))
+ (when height
+ (push (make-constraint
+ :priority priority
+ :install-view install-view
+ :item1 sized-view
+ :att1 :height
+ :relation rel
+ :item2 relative-view
+ :att2 :height)
+ constraints))
+ constraints))
+
+(defclass controller (ns:ns-object)
+ ((data :accessor data
+ :initarg :data))
+ (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/numberOfRowsInTableView: #>NSInteger)
+ ((self controller) (tab :id))
+ ;; Assumes that objects is some type of sequence
+ ;; Subclass should override this method if that is not true.
+ (declare (ignore tab))
+ (with-slots (data) self
+ (length data)))
+
+(objc:defmethod (#/tableView:objectValueForTableColumn:row: :id)
+ ((self controller)
+ (tab :id)
+ (col :id)
+ (row #>NSInteger))
+ (declare (ignore tab col))
+ (lisp-to-ns-string (nth row (data self))))
diff --git a/next/lisp/completion.lisp b/next/source/completion.lisp
index 78382d689..78382d689 100644
--- a/next/lisp/completion.lisp
+++ b/next/source/completion.lisp
diff --git a/next/lisp/document-mode.lisp b/next/source/document-mode.lisp
index 4dc696cfe..cbe7a81ce 100644
--- a/next/lisp/document-mode.lisp
+++ b/next/source/document-mode.lisp
@@ -3,17 +3,15 @@
(in-package :next)
(defvar document-mode-map (make-hash-table :test 'equalp))
-(defvar scroll-distance 30
- "The distance scroll-down or scroll-up will scroll.")
(defclass document-mode (mode)
((history-active-node :accessor mode-history-active-node :initarg :active-node)))
(defun scroll-down ()
- (interface:web-view-scroll-down (buffer-view *active-buffer*) scroll-distance))
+ (interface:web-view-scroll-down (buffer-view *active-buffer*) *scroll-distance*))
(defun scroll-up ()
- (interface:web-view-scroll-up (buffer-view *active-buffer*) scroll-distance))
+ (interface:web-view-scroll-up (buffer-view *active-buffer*) *scroll-distance*))
(defun history-backwards ()
;; move up to parent node to iterate backwards in history tree
@@ -36,12 +34,17 @@
(defun history-fowards-query-complete (input)
;; provide completion candidates to the history-forwards-query function
- (let ((children (node-children (mode-history-active-node (buffer-mode *minibuffer-callback-buffer*)))))
+ (let ((children
+ ;; Find children of active document-mode instance
+ (node-children (mode-history-active-node
+ ;; Find active document-mode instance from minibuffer callback
+ (buffer-mode (minibuffer-callback-buffer
+ (buffer-mode *minibuffer*)))))))
(when children
(fuzzy-match input (mapcar #'node-data children)))))
(defun add-or-traverse-history (mode)
- ;; get url from mode-view's qwebview
+ ;; get url from mode-view's webview
(let ((url (interface:web-view-get-url (mode-view mode)))
(active-node (mode-history-active-node mode)))
;; only add element to the history if it is different than the current
@@ -79,11 +82,11 @@
(set-url-buffer url *active-buffer*)))
(defun normalize-url (input-url)
- "Will convert example.com to http://www.example.com"
+ "Will convert example.com to https://www.example.com"
(let ((url (puri:parse-uri input-url)))
(if (puri:uri-scheme url)
input-url
- (concatenate 'string "http://" input-url))))
+ (concatenate 'string "https://" input-url))))
(defun document-mode ()
"Base mode for interacting with documents"
@@ -95,6 +98,6 @@
:active-node root)))
(interface:web-view-set-url-loaded-callback
(mode-view mode)
- (lambda (ok) (add-or-traverse-history mode)))
+ (lambda () (add-or-traverse-history mode)))
;; return instance of mode
mode))
diff --git a/next/source/global.lisp b/next/source/global.lisp
new file mode 100644
index 000000000..15b5e8ee9
--- /dev/null
+++ b/next/source/global.lisp
@@ -0,0 +1,14 @@
+;;;; global.lisp --- global variable and parameter declarations
+
+(in-package :next)
+
+(defvar global-map (make-hash-table :test 'equalp)
+ "A global key map, available in every mode/buffer")
+(defvar *active-buffer* ()
+ "The currently active buffer")
+(defvar *minibuffer* nil
+ "A variable to store the mini-buffer")
+(defvar *buffers* ()
+ "A list of all existing buffers")
+(defvar *scroll-distance* 15
+ "The distance scroll-down or scroll-up will scroll.")
diff --git a/next/lisp/keymap.lisp b/next/source/keymap.lisp
index 0ed0a5123..3bd49c57e 100644
--- a/next/lisp/keymap.lisp
+++ b/next/source/keymap.lisp
@@ -11,9 +11,6 @@
(in-package :next)
-
-(defvar global-map (make-hash-table :test 'equalp)
- "A global key map, available in every mode/buffer")
(defvar *key-sequence-stack* ()
"A stack that keeps track of the key chords a user has inputted")
diff --git a/next/lisp/macro.lisp b/next/source/macro.lisp
index 1509b1551..ea75a6cd7 100644
--- a/next/lisp/macro.lisp
+++ b/next/source/macro.lisp
@@ -4,11 +4,11 @@
;; used to provide input to buffers, "function" must accept input from
;; the minibuffer
-(defmacro :input (function)
- `#'(lambda () (input #',function)))
+(defmacro :input (minibuffer function)
+ `#'(lambda () (input (buffer-mode ,minibuffer) #',function)))
;; used to provide input to buffers with an optional completion
;; function, the completion function must narrow a list of candidates
;; when given input
-(defmacro :input-complete (function completion)
- `#'(lambda () (input #',function #',completion)))
+(defmacro :input-complete (minibuffer function completion)
+ `#'(lambda () (input (buffer-mode ,minibuffer) #',function #',completion)))
diff --git a/next/source/minibuffer.lisp b/next/source/minibuffer.lisp
new file mode 100644
index 000000000..2717bd36d
--- /dev/null
+++ b/next/source/minibuffer.lisp
@@ -0,0 +1,41 @@
+;;;; minibuffer.lisp --- major mode for input
+
+(in-package :next)
+
+(defvar minibuffer-mode-map (make-hash-table :test 'equalp))
+
+(defclass minibuffer-mode (mode)
+ ((minibuffer-completion-function :accessor minibuffer-completion-function)
+ (minibuffer-callback-function :accessor minibuffer-callback-function)
+ (minibuffer-callback-buffer :accessor minibuffer-callback-buffer)))
+
+(defmethod input ((self minibuffer-mode) callback-function &optional completion-function)
+ (with-slots (minibuffer-callback-function minibuffer-completion-function minibuffer-callback-buffer) self
+ (setf minibuffer-callback-function callback-function)
+ (setf minibuffer-completion-function completion-function)
+ (setf minibuffer-callback-buffer *active-buffer*)
+ (interface:minibuffer-set-completion-function completion-function))
+ (set-active-buffer *minibuffer*)
+ (interface:minibuffer-show))
+
+(defmethod return-input ((self minibuffer-mode))
+ (set-active-buffer (minibuffer-callback-buffer self))
+ (with-slots (minibuffer-completion-function minibuffer-callback-function) self
+ (if minibuffer-completion-function
+ (funcall minibuffer-callback-function
+ (nth 0 (funcall minibuffer-completion-function
+ (interface:minibuffer-get-input))))
+ (funcall minibuffer-callback-function
+ (interface:minibuffer-get-input))))
+ (interface:minibuffer-hide))
+
+(defmethod cancel-input ((self minibuffer-mode))
+ (set-active-buffer (minibuffer-callback-buffer self))
+ (interface:minibuffer-hide))
+
+(defun minibuffer-mode ()
+ "Base mode for input"
+ (make-instance 'minibuffer-mode
+ :name "minibuffer"
+ :keymap minibuffer-mode-map
+ :view (interface:make-minibuffer)))
diff --git a/next/lisp/mode.lisp b/next/source/mode.lisp
index 43490a0f4..43490a0f4 100644
--- a/next/lisp/mode.lisp
+++ b/next/source/mode.lisp
diff --git a/next/lisp/package.lisp b/next/source/package.lisp
index 233608a04..a99dcabfa 100644
--- a/next/lisp/package.lisp
+++ b/next/source/package.lisp
@@ -9,13 +9,13 @@
#:push-key-chord))
(defpackage :interface
- (:use :common-lisp)
+ (:use :common-lisp :ccl)
(:export
#:initialize
#:start
- #:quit
+ #:kill
+ #:process-event
#:set-visible-view
- #:add-to-stack-layout
#:delete-view
#:make-web-view
#:web-view-scroll-down
diff --git a/next/lisp/tree-history.lisp b/next/source/tree-history.lisp
index 24019bdf1..24019bdf1 100644
--- a/next/lisp/tree-history.lisp
+++ b/next/source/tree-history.lisp