Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reopen tab #365

Closed
wants to merge 18 commits into from
Closed

Reopen tab #365

wants to merge 18 commits into from

Conversation

4t0m
Copy link
Contributor

@4t0m 4t0m commented Sep 10, 2019

Please let me know if anything needs fixing. I wasn't totally sure about where to define things or what names to use.

For some reason, when I change the variables on my machine, something is failing to update somewhere and I am getting errors in slime because undefined variables are being invoked. I figure we can just change the name here when the code reaches an approvable state.

Fixes #253.

@4t0m
Copy link
Contributor Author

4t0m commented Sep 10, 2019

Hmm. I'm currently working on bringing this up to date with master. Probably best to ignore this for now.

@Ambrevar
Copy link
Member

Thanks so much for working on this, and welcome to the still very small circle of Next contributors! :)

I had a quick look and it's looking good! I'll go for a proper review after you've rebased.

I just had an idea: you could add a command which prompts the user with the minibuffer which URL to restore. Awesome, nah? :)

Also instead of storing just the URL, I recommend you store both the URL and the title so that it displays in the minibuffer just like for other buffers.

@Ambrevar
Copy link
Member

Also as mentioned in #253, "buffer history" could be confused with the history of visited URLs for a given buffer. I suggest to use the term "recent buffers" instead, or something like that.

@4t0m
Copy link
Contributor Author

4t0m commented Sep 10, 2019

Thanks for the notes! I'll change the variable shortly, and saving the title as well sounds like a good idea.

I was also thinking of doing something like what you describe with the minibuffer. In that case, should the buffers be removed from the ring (as they normally are)?

I don't think there's a neat way to remove things from the middle of the ring, but it's not as if there will be any performance issues as a result.

@4t0m
Copy link
Contributor Author

4t0m commented Sep 10, 2019

Also instead of storing just the URL, I recommend you store both the URL and the title so that it displays in the minibuffer just like for other buffers.

Do you mean like how urls and titles are shown for the current buffer? I don't see where the minibuffer displays both title and url during selection.

I'm looking into what I'll have to do to display/return something other than a url string.

@Ambrevar
Copy link
Member

Ambrevar commented Sep 11, 2019 via email

@4t0m
Copy link
Contributor Author

4t0m commented Sep 11, 2019

Ah yes, it seems like I was looking at an older version. I see it now.

Do you mean shifting left/right by setting the value of the array at index for each element? Would it be faster to create a new ring with the starting array of the concatenation of all elements before the deleted value and all elements after the deleted value1? Or set :items to such an array?

Another thing: How does one close the minibuffer? Right now it's remaining open after reopening a buffer, and I can't see what I'm doing differently from delete-buffer (which seems to close the minibuffer after running).

And finally: should adding the recent-buffer to the ring be part of rpc-delete as it currently is, or is it better as a hook?

Thanks!


1 With an extra nil element in one of the arrays to preserve the total length, I guess?

@4t0m
Copy link
Contributor Author

4t0m commented Sep 11, 2019

Okay it doesn't seem like concatenating is any better. I'll do as you described!

@4t0m
Copy link
Contributor Author

4t0m commented Sep 11, 2019

Hmm, it seems kind of tedious to delete a buffer from the ring when there are duplicates, since I don't know how to determine the index. Is there a way for me to get the minibuffer to return the index of the selected item (the index in the original list passed to fuzzy-match)? Or maybe there's a better way.

Also, is this worth it? :P

libraries/ring/ring.lisp Show resolved Hide resolved
#:make
#:pop-most-recent
#:item-count))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spurious new line?

next.asd Outdated
@@ -50,6 +50,7 @@
(:file "window")
(:file "minibuffer")
(:file "keymap")
(:file "recent-buffer")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about "recent-buffers" with an "s"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@@ -603,6 +603,7 @@ Return most recent entry in RING."
(ring:insert ring clipboard-content)))
(string (ring:ref ring 0)))


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spurious new line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed.

@@ -0,0 +1,37 @@
;;; recent-buffer.lisp --- lisp subroutines for creating and managing recent buffers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shorter: "Manage list of recent buffers"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

(setf (recent-buffers interface)
(ring:make :size (recent-buffers-length interface))))
;; (make-instance 'ring :items (make-array (recent-buffers-length interface)
;; :initial-element nil))))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about removing this initialize-instance, removing recent-buffers-length and setting the initform of recent-buffers:

:initform (ring:make :size 50)

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, people would set a custom length by putting something like the following in their init.lisp?

(setf (get-default 'remote-interface 'recent-buffersl) (ring:make :size n)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is how we used to do it, but I want to deprecate (setf (get-default ...)).
Instead we can set it in after-init-hook (or any appropriate hook).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also see #381

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@@ -243,6 +243,10 @@ by Next when the user session dbus instance is not available.")
(minibuffer-generic-history :accessor minibuffer-generic-history :initform (ring:make))
(minibuffer-search-history :accessor minibuffer-search-history :initform (ring:make))
(minibuffer-set-url-history :accessor minibuffer-set-url-history :initform (ring:make))
(recent-buffers-length :accessor recent-buffers-length :initform 50
:documentation "The maximum length of the recent-buffers.")
(recent-buffers :accessor recent-buffers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should always set an :initform (unless you know what you are doing) to prevent "unbound slot" errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think fixed.

;; (make-instance 'ring :items (make-array (recent-buffers-length interface)
;; :initial-element nil))))

(defmethod add-buffer-to-recent-buffers-ring ((interface remote-interface) (buffer buffer))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the shorter add-to-recent-buffers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

;; :initial-element nil))))

(defmethod add-buffer-to-recent-buffers-ring ((interface remote-interface) (buffer buffer))
"Add the url of a given buffer to the buffers ring."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

url -> URL
"to the `recent-buffers' ring"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

((name :accessor name :initarg :name
:initform nil)
(title :accessor title :initarg :title
:initform nil)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are trying to increase typing in Next, so could you specify the slot types here?
:type string should do :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think fixed.

@Ambrevar
Copy link
Member

  • Closing the minibuffer: Hmm this should not be a problem. I'll do more testing later.

  • Should we use hooks? Maybe, but I think this will be part of a bigger refactoring process around hooks later (I'm thinking of using hooks to customize everything). I suggest we leave it as it is for now.

  • Delete duplicates: I think it's a good idea to delete them, because duplicates serve no purpose here and their presence shortens the list of meaninful "dead buffers".

An easy way to do it would be

(delete-duplicates my-sequence
                   :test (lambda (rb1 rb2)
                           (and (string= (name rb1) (name rb2))
                                (string= (title rb1) (title rb2)))))

Or maybe less costly, you would only delete the elements equal to the one you are adding in add-to-recent-buffers.

@Ambrevar
Copy link
Member

Regarding the minibuffer not closing: it's now fixed on master.

@Ambrevar
Copy link
Member

Ambrevar commented Sep 12, 2019 via email

@jmercouris
Copy link
Member

Is plusp more readable than (< 0 ...)?

plusp is not more readable, it is however more specific and should be used instead of the magic number of 0, it conveys a more specific meaning (like using when vs unless, etc).

@4t0m
Copy link
Contributor Author

4t0m commented Sep 18, 2019

Okay, I think it's working and ~complete.

One thing I wasn't sure how to handle was echo-ing to the minibuffer. The following doesn't seem to be working for me.

(define-command undo-buffer-deletion ()
  "Open a new buffer with the URL of the most recently deleted buffer."

  (if (plusp (ring:item-count (recent-buffers *interface*)))
      (make-buffers (list (name (ring:pop-most-recent (recent-buffers *interface*)))))
      (echo "There are no recently-deleted buffers.")))

Also, should we add some keybindings?
Maybe 'u' and 'U' for VI-MODE? (And something else for normal mode?)

@@ -17,6 +17,7 @@

(defmethod index ((ring ring) index)
"Return index converted to internal ring index, where items are ordered from newest to oldest."
;; TODO: shouldn't that read "oldest to newest", since index 0 is the oldest?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, index 0 in the internal array is the oldest item, so this line is confusing to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The index method returns a "virtual" index. The internal index 0 is not the oldest item is there has been a wraparound.

For instance, in a ring of size 3,

  • in [a b]: a at index 0 is indeed the oldest element.
  • in [a b c], you add d, then you get [d b c]: there d at index 0 is the newest element.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah got it.

@4t0m 4t0m requested a review from Ambrevar September 18, 2019 20:20
@@ -29,7 +30,7 @@ Return NEW-ITEM."
(mod (+ (head-index ring) (item-count ring))
(size ring)))
new-item)
(if (= (item-count ring) (length (items ring)))
(if (= (item-count ring) (size ring))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! ;)

(mod index (size ring)))
(aref (items ring)
(mod (1+ index) (size ring)))))
(setf (aref (items ring) (mod end (size ring))) nil))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use something like (replace (items ring) (items ring) :start2 1).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having sort of a hard time visualizing how this handles wrap arounds. Would you need to replace once from start to end, once from 0 to start, and then separately set element that wraps around?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, this might not be worth the complexity of having to deal with the internal index.
I'll think about it.

(mod index (size ring)))
(aref (items ring)
(mod (1- index) (size ring)))))
(setf (aref (items ring) (mod end (size ring))) nil))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, with :start1.

(setf (aref (items ring) (mod end (size ring))) nil))

(defmethod delete-index ((ring ring) index)
"Delete the item at (internal oldest-first) index and move items to fill the space."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I think it's confusing that this is the only function where index is the internal index. Why not using the ring virtual index instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No big deal though, we might merge the ring library into cl-containers later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this current version?

(defmethod external-index ((ring ring) internal-index)
  (1- (+ (- (head-index ring)
             internal-index)
         (item-count ring))))

(defmethod delete-index ((ring ring) index)
  "Delete the item at external index and move items to fill the space."
  (let* ((internal-index (index ring index))
         (deleted-item (aref (items ring) (mod internal-index (size ring))))
         (head (head-index ring))
         (midpoint (mod (floor (+ head (item-count ring)) 2)
                        (size ring))))
    (if (< midpoint internal-index)
        (shift-left ring internal-index (+ head (item-count ring)))
        (progn
          (shift-right ring internal-index head)
          (setf (head-index ring) (mod (1+ (head-index ring)) (size ring)))))
    (decf (item-count ring))
    deleted-item))

(defmethod delete-match ((ring ring) match-test)
  (let ((match-index (position-if match-test (items ring))))
    (when match-index (delete-index ring (external-index ring match-index)))))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I'm afraid external-index might add extra confusion to the library. I think we should try to keep it to just one "index" method and keep the "internal index" within that method only.
No problem, I'll merge and tweak the code until I find a nice and simple way to put this together.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another idea: Maybe we should run `position-if' on the output of ring:recent-list, and then delete the index that returns?

@Ambrevar
Copy link
Member

Good job! It's mostly ready for merging, the only nit is if you could try using the replace function instead, that could make the code significantly shorter.

Regarding the issue with echo: Don't worry about it, this is a known issue, it will be solved when we implement a status buffer and a Messages buffer. Stay tuned ;)

@Ambrevar
Copy link
Member

Let me know when you grow tired of working on this issue, I can complete the finishing touches if need be, no problem! :)

@4t0m
Copy link
Contributor Author

4t0m commented Sep 19, 2019

Please feel free to make any edits/finishing touches. This is my first time using common lisp so I've been enjoying learning how it all works, but I am also eager to look at other issues.

@Ambrevar
Copy link
Member

Ambrevar commented Sep 19, 2019 via email

@Ambrevar
Copy link
Member

Ambrevar commented Sep 21, 2019

I've rebased and merged in befea72.
Thanks for this great and very useful contribution!

A small tip to ease the burden or merging: when catching up with master, dont "merge", but "rebase against master" instead. This way all your commits will be packed together instead of being spread around merge branches.

Also I noticed that you'd used different authors. I've picked one which does not seem to be recognized by GitHub, sorry :p

Last but not least: Would you like to be included in the list of contributors in M-x about?

@Ambrevar Ambrevar closed this Sep 21, 2019
@4t0m
Copy link
Contributor Author

4t0m commented Sep 24, 2019

Awesome :). I'll rebase in the future and hopefully figure out what's going on with the authorship thing.

I'd love to be included on the list of contributors.

@Ambrevar
Copy link
Member

Ambrevar commented Sep 25, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Reopen closed tab
4 participants