Closed sivark closed 5 years ago
Thanks back!
Long story short: yes, this is very much the mindset of Next!
Some of those ideas are already possible, at least from the REPL. The user interface is still at a very early stage of development however, so for now not much of it is possible without significant work on the Lisp side.
Note that in Next terminology, "tabs" are "buffers" :)
Some things I'd like to see implemented, hopefully not to far in the future:
Fuzzy-search by URL, Title, metadata (with some tag system) and content. That's right, we could filter buffers by words found in their body.
Implement some Emacs' Helm/Ivy-style features for the minibuffer: multiple-selection, multiple sources, customizable actions, etc.
Hooks: the user will be able to customize the behaviour of what happens when a new URL is loaded / a new buffer is created. It would then be possible to create groups for buffers.
Modes (like in Emacs): for instance there would be a Hacker News mode, a Wikipedia mode (where you'd have special features for tables as you mentioned), etc. You'd be able to filter buffers by modes.
Extensive history support is definitely on the table. You'd be able to lookup your history by date, domain, URL, mode, etc. With multi-source support in the minibuffer, it would be possible to fuzzy search both among the live buffers and the history.
Interaction with external processes (e.g. saving in BibTeX): this is already possible. Have a look at https://next.atlas.engineer/article/emacs-hacks.org to give you an idea. I think the bibtex thing is a good idea, we could add it upstream. Feel free to open an issue to detail the specifics, or send a pull request :)
Exporting HTML to disks: Would be easy to implement. In Lisp, you can
get retrieve the body of the current buffer by sending it the
(document body |outerHTML|)
parenscript for instance. If you want the
HTML header as well, I'm not sure this is doable only with Javascript,
we might have to work with the platform ports (e.g. WebKit).
Importing a list of URLs: Already implemented. Either as a "next
In the end, anything that's exposed to the Lisp core is programmable, and only your imagination is the limit!
- A good data structure to represent the contents (and any metadata) of each tab.
HTML header information is a bit lacking at the moment I think. We can add more metadata (such as access time) to the BUFFER class.
- A collection of tabs stored in an iterable data structure. Probably a list of lists i.e. leaves of a tree. A browser window can simply point to specific locations on this collection. (This formulation would be amenable to the possibility of multiple windows or frames, etc.)
Buffers are already stored as a list in the BUFFERS slot in the REMOTE-INTERFACE class. Not sure we would need a tree though. I think subdividing buffers into groups can be done at a different level of abstraction.
We already have multiple-window support. I did not understand what you meant with "point to specific locations on this collection."
- The equivalent of a
filter
function to traverse the iterable, and filter tabs using a user-defined function (maybe a lambda)
As mentioned above, we will have some very powerful fuzzy-search features, including filtering by content (HTML body) and modes.
Instead of user-defined filters, I'm thinking that user-defined sources would be more generic. See Emacs Helm-mini for a good example of this.
- A
map
function. Produce the URL or title of every tab. Maybe reload/refresh an iterable of tabs every hour. Maybe one could use this to eg: implement a tiny ad-hoc crawler (Given a collection of pages, collect the links in each page, filter them by some criteria, then open those links in new tabs, and do all this three levels deep)
All this is already doable: you can use the Common Lisp map
, mapcar
and friends over (buffer *interface*)
and do what you want! :)
- Given that I mentioned
filter
andmap
, what aboutreduce
? I can't currently think of a particularly useful way to reduce a collection of tabs beyond just concatenating their HTML content.
Yup, same, can't think of anything but buffer concatenation, and that alone is an interesting idea! :D
- Export/import this iterable.
You mean the resulting Common Lisp function? This is already doable:
write a bunch of higher-order-functions in your
~/.config/next/init.lisp
, and define the desired command in there. Is
this what you meant?
- Access to a library ecosystem which will provide useful functions like parsing HTML, processing strings (eg: fuzzy search, or mis-spelled words, or non-dictionary words to collect proper nouns), etc. Eg: If I could access a table from Wikipedia and convert it into the lisp equivalent of a dataframe, then I can start doing my own data analysis on the fly ;-)
Good news: All the Common Lisp eco-system is available to you! DOM and string manipulation, etc. there is so much out there!
If so, please help me get started :-)
You can start reading the above article I've sent you. If you are
serious about hacking with Next, you'll need some knowledge of Common
Lisp (if you know Emacs, you already know a useful bunch). I think a good
starting point to get started with the Lisp core source is the
buffer.lisp
file. Documentation is still lacking, we are working on it!
Note that these weeks we have been rewriting a big chunk of the API, so expect some important changes in the Next release.
Thanks for the extensive feedback!
Thanks for the prompt response and useful suggestions.
In the end, anything that's exposed to the Lisp core is programmable, and only your imagination is the limit!
I like the sound of this!
Some of those ideas are already possible, at least from the REPL. The user interface is still at a very early stage of development however, so for now not much of it is possible without significant work on the Lisp side.
You can start reading the above article I've sent you. If you are serious about hacking with Next, you'll need some knowledge of Common Lisp (if you know Emacs, you already know a useful bunch). I think a good starting point to get started with the Lisp core source is the
buffer.lisp
file.
I haven't really programmed with Common Lisp or used Emacs much, but I've played around a little with Racket, so I'm absolutely happy to get my hands dirty with Lisp in a REPL, and start learning.
Concretely, IIUC: To access the BUFFER class and the BUFFERS slot in the REMOTE-INTERFACE class in a REPL, I need to set up Emacs with Slime, based on https://next.atlas.engineer/documentation#slime-with-a-compiled-version-of-next
So, I tried following the manual, to connect to the swank
server using slime
(I'm actually using the common-lisp layer in spacemacs, since I'm kinda new to Emacs). I'm using the compiled version of Next browser available on AUR.
I can start a swank server from Next (verified by looking at the console output of next --verbose
), but I'm not able to connect to it from slime. Here's the error message I see in Emacs:
SWANK/BACKEND:SLDB-BREAK-ON-RETURN not implemented
[Condition of type SIMPLE-ERROR]
Restarts:
0: [ABORT] Return to sldb level 2.
1: [ABORT] Return to sldb level 1.
2: [*ABORT] Return to SLIME's top level.
3: [ABORT] abort thread (#<THREAD "worker" RUNNING {10061FB523}>)
Backtrace:
0: (SWANK/BACKEND:SLDB-BREAK-ON-RETURN 0)
1: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK/BACKEND:SLDB-BREAK-ON-RETURN 0) #<NULL-LEXENV>)
2: (EVAL (SWANK/BACKEND:SLDB-BREAK-ON-RETURN 0))
3: (SWANK:EVAL-FOR-EMACS (SWANK/BACKEND:SLDB-BREAK-ON-RETURN 0) "COMMON-LISP-USER" 4)
4: (SWANK::SLDB-LOOP 2)
5: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT :IN "/var/cache/pacman/pkg/next-browser-git9193/next-browser-git/src/next-browser/quicklisp/dists/quicklisp/software/slime-v2.23/swank/sbcl.lisp") ..
6: (SWANK::DEBUG-IN-EMACS #<SIMPLE-ERROR "~S not implemented" {10066D8FF3}>)
7: (SWANK:INVOKE-SLIME-DEBUGGER #<SIMPLE-ERROR "~S not implemented" {10066D8FF3}>)
8: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<CLOSURE (LAMBDA NIL :IN SWANK:SWANK-DEBUGGER-HOOK) {10066D947B}>)
9: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/var/cache/pacman/pkg/next-browser-git9193/next-browser-git/src/next-browser/quicklisp/dists/quicklisp/software/slime-v2.23/swank/sbcl.lisp") #<FUNCTI..
10: (SWANK:SWANK-DEBUGGER-HOOK #<SIMPLE-ERROR "~S not implemented" {10066D8FF3}> #<unused argument>)
11: (SB-DEBUG::RUN-HOOK *DEBUGGER-HOOK* #<SIMPLE-ERROR "~S not implemented" {10066D8FF3}>)
12: (INVOKE-DEBUGGER #<SIMPLE-ERROR "~S not implemented" {10066D8FF3}>)
13: (ERROR "~S not implemented" SWANK/BACKEND:SLDB-BREAK-ON-RETURN)
14: (SWANK/BACKEND:SLDB-BREAK-ON-RETURN 0)
15: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK/BACKEND:SLDB-BREAK-ON-RETURN 0) #<NULL-LEXENV>)
16: (EVAL (SWANK/BACKEND:SLDB-BREAK-ON-RETURN 0))
17: (SWANK:EVAL-FOR-EMACS (SWANK/BACKEND:SLDB-BREAK-ON-RETURN 0) "COMMON-LISP-USER" 3)
18: (SWANK::SLDB-LOOP 1)
19: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGING-ENVIRONMENT :IN "/var/cache/pacman/pkg/next-browser-git9193/next-browser-git/src/next-browser/quicklisp/dists/quicklisp/software/slime-v2.23/swank/sbcl.lisp") ..
20: (SWANK::DEBUG-IN-EMACS #<SIMPLE-ERROR "Can't locate module: ~s" {100635EC03}>)
21: (SWANK:INVOKE-SLIME-DEBUGGER #<SIMPLE-ERROR "Can't locate module: ~s" {100635EC03}>)
22: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<CLOSURE (LAMBDA NIL :IN SWANK:SWANK-DEBUGGER-HOOK) {100635F18B}>)
23: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/var/cache/pacman/pkg/next-browser-git9193/next-browser-git/src/next-browser/quicklisp/dists/quicklisp/software/slime-v2.23/swank/sbcl.lisp") #<FUNCTI..
24: (SWANK:SWANK-DEBUGGER-HOOK #<SIMPLE-ERROR "Can't locate module: ~s" {100635EC03}> #<unused argument>)
25: (SB-DEBUG::RUN-HOOK *DEBUGGER-HOOK* #<SIMPLE-ERROR "Can't locate module: ~s" {100635EC03}>)
26: (INVOKE-DEBUGGER #<SIMPLE-ERROR "Can't locate module: ~s" {100635EC03}>)
27: (ERROR "Can't locate module: ~s" SWANK-IO-PACKAGE::SWANK-INDENTATION)
28: (SWANK::MODULE-FILENAME SWANK-IO-PACKAGE::SWANK-INDENTATION)
29: (SWANK:SWANK-REQUIRE (SWANK-IO-PACKAGE::SWANK-SBCL-EXTS SWANK-IO-PACKAGE::SWANK-INDENTATION SWANK-IO-PACKAGE::SWANK-TRACE-DIALOG SWANK-IO-PACKAGE::SWANK-PACKAGE-FU SWANK-IO-PACKAGE::SWANK-PRESENTATION..
30: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK:SWANK-REQUIRE (QUOTE (SWANK-IO-PACKAGE::SWANK-SBCL-EXTS SWANK-IO-PACKAGE::SWANK-INDENTATION SWANK-IO-PACKAGE::SWANK-TRACE-DIALOG SWANK-IO-PACKAGE::SWANK-PACKAGE-FU..
31: (EVAL (SWANK:SWANK-REQUIRE (QUOTE (SWANK-IO-PACKAGE::SWANK-SBCL-EXTS SWANK-IO-PACKAGE::SWANK-INDENTATION SWANK-IO-PACKAGE::SWANK-TRACE-DIALOG SWANK-IO-PACKAGE::SWANK-PACKAGE-FU SWANK-IO-PACKAGE::SWANK..
32: (SWANK:EVAL-FOR-EMACS (SWANK:SWANK-REQUIRE (QUOTE (SWANK-IO-PACKAGE::SWANK-SBCL-EXTS SWANK-IO-PACKAGE::SWANK-INDENTATION SWANK-IO-PACKAGE::SWANK-TRACE-DIALOG SWANK-IO-PACKAGE::SWANK-PACKAGE-FU SWANK-I..
33: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
34: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<FUNCTION (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {522BD16B}>)
35: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/var/cache/pacman/pkg/next-browser-git9193/next-browser-git/src/next-browser/quicklisp/dists/quicklisp/software/slime-v2.23/swank/sbcl.lisp") #<FUNCTI..
36: ((LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD))
37: ((FLET SB-UNIX::BODY :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
38: ((FLET "WITHOUT-INTERRUPTS-BODY-4" :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
39: ((FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
40: ((FLET "WITHOUT-INTERRUPTS-BODY-1" :IN SB-THREAD::CALL-WITH-MUTEX))
41: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE) {7F4884356D6B}> #<SB-THREAD:MUTEX "thread result lock" owner: #<SB-THREAD:THR..
42: (SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE #<SB-THREAD:THREAD "worker" RUNNING {10061FB523}> NIL #<CLOSURE (LAMBDA NIL :IN SWANK::SPAWN-WORKER-THREAD) {10061FB4CB}> NIL)
43: ("foreign function: call_into_lisp")
44: ("foreign function: new_thread_trampoline")
Superficially (to me), this looks like a previously reported & solved issue but the version of Next I'm using is from after that issue was solved.
I could share the output of the slime-events buffer if need be.
Great to see you getting started!
And yes, you understood correctly! ;)
Regarding your issue, please report
The backtrace shows that SLDB cannot be invoked properly, so there is mostly likely an issue with your SLIME installation, or with the AUR package.
You could try the following:
Thanks for that suggestion @Ambrevar !
I managed to get the Slime/Swank connection working by running Next from source (still using spacemacs, so that doesn't seem to be a dealbreaker, for anyone who comes across this later). So it's probably something with the AUR package being dated. Thanks for that suggestion.
Now for the fun stuff! (in case another Lisp/Next newbie comes across this in the future, this is a demonstration that the connection works and we can access the tabs from Slime)
;; "Sourcing" the contents of the module
(in-package :next)
;; *interface* is an instance of REMOTE-INTERFACE
;; Whose buffers slot is a hash map of buffers
;; This will print the respective URL of each buffer
(maphash (lambda (k v)
(print (cons k (name v))))
(buffers *interface*))
- Fuzzy-search by URL, Title, metadata (with some tag system) and content. That's right, we could filter buffers by words found in their body.
Would this be by executing js in each buffer (using parenscript), or by getting the contents of the buffer and processing it in lisp?
Basic question: I can start next from the SBCL shell, but running the same commands as a script seems to fail. Any idea why this might be the case?
~> cat start-next.lisp
#!/usr/bin/sbcl --script
;; Execute this in sbcl
;; For loading from lisp source
(require :asdf)
(asdf:load-asd "/home/username/next-browser/next.asd")
;; Load the Next module
(ql:quickload :next)
;; Start a browser window
(next:start)
;; Start Swank server
;; (in-package :next)
;; (start-swank)
~> ./start-next.lisp
While evaluating the form starting at line 4, column 0
of #P" /home/username/next-browser/next.asd":
Unhandled MISSING-DEPENDENCY in thread #<SB-THREAD:THREAD "main thread" RUNNING {10005205B3}>: Component "trivial-features" not found, required by NIL
Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10005205B3}>
0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK Component "trivial-features" not found, required by NIL #<unused argument> :QUIT T)
1: (SB-DEBUG::RUN-HOOK SB-EXT:*INVOKE-DEBUGGER-HOOK* Component "trivial-features" not found, required by NIL)
2: (INVOKE-DEBUGGER Component "trivial-features" not found, required by NIL)
3: (ERROR MISSING-DEPENDENCY :REQUIRED-BY NIL :REQUIRES "trivial-features")
4: (ASDF/FIND-COMPONENT:RESOLVE-DEPENDENCY-NAME NIL "trivial-features" NIL)
5: ((LAMBDA NIL :IN ASDF/PARSE-DEFSYSTEM:REGISTER-SYSTEM-DEFINITION))
6: (SB-INT:SIMPLE-EVAL-IN-LEXENV (DEFSYSTEM :NEXT :VERSION "1.2.0" :AUTHOR "Atlas Engineer LLC" :LICENSE "BSD 3-Clause" :SERIAL T :DEFSYSTEM-DEPENDS-ON ("trivial-features") ...) #<NULL-LEXENV>)
7: (SB-EXT:EVAL-TLF (DEFSYSTEM :NEXT :VERSION "1.2.0" :AUTHOR "Atlas Engineer LLC" :LICENSE "BSD 3-Clause" :SERIAL T :DEFSYSTEM-DEPENDS-ON ("trivial-features") ...) 0 NIL)
8: ((LABELS SB-FASL::EVAL-FORM :IN SB-INT:LOAD-AS-SOURCE) (DEFSYSTEM :NEXT :VERSION "1.2.0" :AUTHOR "Atlas Engineer LLC" :LICENSE "BSD 3-Clause" :SERIAL T :DEFSYSTEM-DEPENDS-ON ("trivial-features") ...) 0)
9: ((LAMBDA (SB-KERNEL:FORM &KEY :CURRENT-INDEX &ALLOW-OTHER-KEYS) :IN SB-INT:LOAD-AS-SOURCE) (DEFSYSTEM :NEXT :VERSION "1.2.0" :AUTHOR "Atlas Engineer LLC" :LICENSE "BSD 3-Clause" :SERIAL T :DEFSYSTEM-DEPENDS-ON ("trivial-features") ...) :CURRENT-INDEX 0)
10: (SB-C::%DO-FORMS-FROM-INFO #<CLOSURE (LAMBDA (SB-KERNEL:FORM &KEY :CURRENT-INDEX &ALLOW-OTHER-KEYS) :IN SB-INT:LOAD-AS-SOURCE) {1004CCC1EB}> #<SB-C::SOURCE-INFO {1004CCC1A3}> SB-C::INPUT-ERROR-IN-LOAD)
11: (SB-INT:LOAD-AS-SOURCE #<SB-INT:FORM-TRACKING-STREAM for "file /home/username/next-browser/next.asd" {1004CCA323}> :VERBOSE NIL :PRINT NIL :CONTEXT "loading")
12: ((FLET SB-FASL::THUNK :IN LOAD))
13: (SB-FASL::CALL-WITH-LOAD-BINDINGS #<CLOSURE (FLET SB-FASL::THUNK :IN LOAD) {7FE4068ADA8B}> #<SB-INT:FORM-TRACKING-STREAM for "file /home/username/next-browser/next.asd" {1004CCA323}>)
14: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-INT:FORM-TRACKING-STREAM for "file /home/username/next-browser/next.asd" {1004CCA323}> NIL)
15: (LOAD #P"/home/username/next-browser/next.asd" :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :UTF-8)
16: (CALL-WITH-MUFFLED-CONDITIONS #<CLOSURE (LAMBDA NIL :IN LOAD*) {1004CC7BBB}> ("Overwriting already existing readtable ~S." #(#:FINALIZERS-OFF-WARNING :ASDF-FINALIZERS)))
17: ((FLET "THUNK" :IN PERFORM))
18: (SB-IMPL::%WITH-STANDARD-IO-SYNTAX #<CLOSURE (FLET "THUNK" :IN PERFORM) {7FE4068ADDDB}>)
19: ((:METHOD PERFORM (DEFINE-OP SYSTEM)) #<DEFINE-OP > #<ASDF/SYSTEM:UNDEFINED-SYSTEM "next">) [fast-method]
20: ((SB-PCL::EMF PERFORM) #<unused argument> #<unused argument> #<DEFINE-OP > #<ASDF/SYSTEM:UNDEFINED-SYSTEM "next">)
21: ((LAMBDA NIL :IN ASDF/ACTION:CALL-WHILE-VISITING-ACTION))
22: ((:METHOD PERFORM-WITH-RESTARTS :AROUND (T T)) #<DEFINE-OP > #<ASDF/SYSTEM:UNDEFINED-SYSTEM "next">) [fast-method]
23: ((:METHOD PERFORM-PLAN (T)) #<SEQUENTIAL-PLAN {1004CC1C03}>) [fast-method]
24: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
25: ((:METHOD PERFORM-PLAN :AROUND (T)) #<SEQUENTIAL-PLAN {1004CC1C03}>) [fast-method]
26: ((:METHOD OPERATE (OPERATION COMPONENT)) #<DEFINE-OP > #<ASDF/SYSTEM:UNDEFINED-SYSTEM "next"> :PLAN-CLASS NIL :PLAN-OPTIONS NIL) [fast-method]
27: ((SB-PCL::EMF OPERATE) #<unused argument> #<unused argument> #<DEFINE-OP > #<ASDF/SYSTEM:UNDEFINED-SYSTEM "next">)
28: ((LAMBDA NIL :IN OPERATE))
29: ((:METHOD OPERATE :AROUND (T T)) #<DEFINE-OP > #<ASDF/SYSTEM:UNDEFINED-SYSTEM "next">) [fast-method]
30: ((LAMBDA NIL :IN FIND-SYSTEM))
31: (ASDF/SESSION:CONSULT-ASDF-CACHE (FIND-SYSTEM "next") #<CLOSURE (LAMBDA NIL :IN FIND-SYSTEM) {1004C2333B}>)
32: ((:METHOD FIND-COMPONENT (STRING T)) "next" (NIL) :REGISTERED NIL) [fast-method]
33: ((:METHOD OPERATE (OPERATION T)) #<DEFINE-OP > ("next")) [fast-method]
34: ((SB-PCL::EMF OPERATE) #<unused argument> #<unused argument> #<DEFINE-OP > ("next"))
35: ((LAMBDA NIL :IN OPERATE))
36: ((:METHOD OPERATE :AROUND (T T)) #<DEFINE-OP > ("next")) [fast-method]
37: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<CLOSURE (LAMBDA NIL :IN OPERATE) {1004C1738B}> :OVERRIDE T :KEY NIL :OVERRIDE-CACHE T :OVERRIDE-FORCING NIL)
38: ((LAMBDA NIL :IN OPERATE))
39: ((:METHOD OPERATE :AROUND (T T)) #<DEFINE-OP > #<ASDF/SYSTEM:UNDEFINED-SYSTEM "next">) [fast-method]
40: ((LAMBDA NIL :IN LOAD-ASD))
41: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<CLOSURE (LAMBDA NIL :IN LOAD-ASD) {1002FCBE4B}> :OVERRIDE NIL :KEY NIL :OVERRIDE-CACHE NIL :OVERRIDE-FORCING NIL)
42: (SB-INT:SIMPLE-EVAL-IN-LEXENV (LOAD-ASD "/home/username/next-browser/next.asd") #<NULL-LEXENV>)
43: (SB-EXT:EVAL-TLF (LOAD-ASD "/home/username/next-browser/next.asd") 1 NIL)
44: ((LABELS SB-FASL::EVAL-FORM :IN SB-INT:LOAD-AS-SOURCE) (LOAD-ASD "/home/username/next-browser/next.asd") 1)
45: ((LAMBDA (SB-KERNEL:FORM &KEY :CURRENT-INDEX &ALLOW-OTHER-KEYS) :IN SB-INT:LOAD-AS-SOURCE) (LOAD-ASD "/home/username/next-browser/next.asd") :CURRENT-INDEX 1)
46: (SB-C::%DO-FORMS-FROM-INFO #<CLOSURE (LAMBDA (SB-KERNEL:FORM &KEY :CURRENT-INDEX &ALLOW-OTHER-KEYS) :IN SB-INT:LOAD-AS-SOURCE) {10018784CB}> #<SB-C::SOURCE-INFO {1001878483}> SB-C::INPUT-ERROR-IN-LOAD)
47: (SB-INT:LOAD-AS-SOURCE #<SB-SYS:FD-STREAM for "file /home/username/start-next.lisp" {100186E8C3}> :VERBOSE NIL :PRINT NIL :CONTEXT "loading")
48: ((FLET SB-FASL::THUNK :IN LOAD))
49: (SB-FASL::CALL-WITH-LOAD-BINDINGS #<CLOSURE (FLET SB-FASL::THUNK :IN LOAD) {7FE4068AF69B}> #<SB-SYS:FD-STREAM for "file /home/username/start-next.lisp" {100186E8C3}>)
50: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-SYS:FD-STREAM for "file /home/username/start-next.lisp" {100186E8C3}> NIL)
51: (LOAD #<SB-SYS:FD-STREAM for "file /home/username/start-next.lisp" {100186E8C3}> :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :DEFAULT)
52: ((FLET SB-IMPL::LOAD-SCRIPT :IN SB-IMPL::PROCESS-SCRIPT) #<SB-SYS:FD-STREAM for "file /home/username/start-next.lisp" {100186E8C3}>)
53: ((FLET SB-UNIX::BODY :IN SB-IMPL::PROCESS-SCRIPT))
54: ((FLET "WITHOUT-INTERRUPTS-BODY-2" :IN SB-IMPL::PROCESS-SCRIPT))
55: (SB-IMPL::PROCESS-SCRIPT "./start-next.lisp")
56: (SB-IMPL::TOPLEVEL-INIT)
57: ((FLET SB-UNIX::BODY :IN SB-EXT:SAVE-LISP-AND-DIE))
58: ((FLET "WITHOUT-INTERRUPTS-BODY-14" :IN SB-EXT:SAVE-LISP-AND-DIE))
59: ((LABELS SB-IMPL::RESTART-LISP :IN SB-EXT:SAVE-LISP-AND-DIE))
unhandled condition in --disable-debugger mode, quitting
;
; compilation unit aborted
; caught 1 fatal ERROR condition
Thanks for the feedback!
AUR package: I wrote it, but I don't use Arch Linux anymore and I don't have easy access to it, so I'm afraid I won't maintain it just as well as the Guix packge for instance. If you are up for it, you could adopt it and fix it if there is any issue. I'd be happy to help if you have any question of course.
Hacking example: yes, this is exactly how you do it! This kind of examples should be more exposed to the user, e.g. as part of the contextual documentation. I'm planning on overhauling the documentation system as soon as possible.
Fuzzy search: Excellent question, the two approaches are indeed possible. I'm not sure which one would be faster and speed might be critical here (e.g. with hundreds of buffers). Experience will tell!
SBCL script: this is because the --script flag disables the loading of your ~/.sbclrc, and the latter contains the Quicklisp setup for loading the trivial-features third-party package.
I'm not very familiar with SBCL scripts, but I guess something as simple as adding
(load "~/.sbclrc")
before loading next.asd would be enough.
That said, you should not need this script at all. It's easier to simply generate a binary and run it.
Using the distributed Makefile, you can run
make next
(Run make
for more documentation.)
Or, if you want to do it manually in your favourite Lisp environment:
(asdf:make :next)
should work.
-- Pierre Neidhardt https://ambrevar.xyz/
@Ambrevar How modes would work?
Modes are a work-in-progress and for now they are simply classes with key bindings and some specific slots. I have been thinking quite a lot about what a mode could do and I hope to implement it in the near future. More discussions coming ;)
I use a combo of tree style tab extension https://github.com/piroor/treestyletab and tab session manager https://github.com/sienori/Tab-Session-Manager on Firefox. A great combo, almost perfect. Question is Can tab/buffers be kept tree style, maybe an org tree... a tree of tabs will behave like a visual browsing history, helps to show the thinking behind how you got from one to the other sometimes. Also, I am running tab session manager, to save the sessiond and relevant meta data, on Firefox,... but on different laptops,... currently 3, and synchronising the saved sessions in a shared repository, so potentially I could open a session(s) on a different computer. So my question is, can the same be done, maybe through a cloud or a git repo, and could the name or indentifier of the computer on which the sesssion was saved be optionally included in session metadata, to sort the different sessions, not just by time and place?
Thanks for the suggestions, some good ideas in there!
The tree view of buffers is probably an easy one: it should be enough to
add a parent
field to the buffer
class and store the buffer there.
Then we can easily reconstruct the trees by looping over all the
buffers. Some buffers can get detached from their parents if it gets
deleted, but that's OK I guess.
Regarding the session synchronization: Yes you can synchronize
~/.local/share/next/session.lisp via git and use it on different
instance. To identify the various sessions, I suggest that we add the
option to include arbitrary fields, e.g. the user can include a
(identifier "my-hostname")
pair.
Thanks for a very interesting browser concept!
This is more in the spirit of a workflow question, and possibly feature requests, rather than an issue. Feel free to redirect to a more appropriate place.
I seek more control and deliberation in the way I interact with the information I'm accessing through my browser. As a start, I would like to manage my tabs programmatically (by performing operations based on their content). Here are some scenarios I'm envisioning...
I have over 500 tabs in Firefox. I want to organize them, starting with a triage process. Split them into three buckets: Hacker News, (Arxiv or PDFs), Rest. Lot of the Hacker News tabs can be closed after a glance -- so flit through each of those pages sequentially, while deciding to keep open, or close. The second group requires careful perusing, so I might save them for another time. Bonus if I could register all of them with a useful database such as Zotero/Bibtex/whatever, and clear out the tabs (reduce clutter). Hopefully, by now the number of websites has reduced to a more manageable number.
Alternatively, I might want to organize my tabs by theme -- pertaining to specific goals/projects. Maybe perform a (fuzzy) search among the contents of all my tabs, and select/filter all tabs with certain keywords. Maybe I would like to cluster my tabs by their content. (Eg: I currently have over fifty open tabs which are Emacs related references). Once I have a collection, I might want to export the URLs or HTML content (to disk), and correspondingly, import a list of URLs. I could share these lists over email, for effective collaboration!
Or maybe filter by metadata (if Next decides to store any; that discussion might be a digression). Eg: Tabs opened last Sunday, or clustered by browsing history (using gaps in opening time), or tabs which have stayed open longer than a month.
I desire an interface where I can create solutions like these on the fly. Conceptually, this might involve:
filter
function to traverse the iterable, and filter tabs using a user-defined function (maybe a lambda)map
function. Produce the URL or title of every tab. Maybe reload/refresh an iterable of tabs every hour. Maybe one could use this to eg: implement a tiny ad-hoc crawler (Given a collection of pages, collect the links in each page, filter them by some criteria, then open those links in new tabs, and do all this three levels deep)filter
andmap
, what aboutreduce
? I can't currently think of a particularly useful way to reduce a collection of tabs beyond just concatenating their HTML content.So, is this compatible with the vision for Next? Are you formulating the solution in a different mental framework? Are some of these things already possible? If so, please help me get started :-) Cheers!