Commit 558eb84f authored by Ulf Jasper's avatar Ulf Jasper
Browse files

Newsticker: Add commands to rearrange treeview groups and document them. (Bug#12560)

2014-09-24  Ulf Jasper  <ulf.jasper@web.de>

	* newsticker.texi: Reworked.  Document new treeview group
	commands.  Remove VERSION, UPDATED, use EMACSVER instead.  Use
	term 'feed reader'.

2014-09-24  Ulf Jasper  <ulf.jasper@web.de>

	* automated/newsticker-tests.el
	(newsticker--group-find-parent-group),
	(newsticker--group-do-rename-group): New tests.

2014-09-24  Ulf Jasper  <ulf.jasper@web.de>

	* net/newst-treeview.el (newsticker--treeview-do-get-node-by-id):
	Renamed `newsticker--treeview-do-get-node' to
	`newsticker--treeview-do-get-node-by-id'.
	(newsticker--treeview-get-node-by-id): Renamed
	`newsticker--treeview-get-node' to
	`newsticker--treeview-get-node-by-id'.
	(newsticker--treeview-get-current-node): Renamed `
	`newsticker--treeview-get-node' to
	`newsticker--treeview-get-node-by-id'.
	(newsticker--treeview-buffer-init)
	(newsticker--treeview-buffer-init): Disable buffer undo.
	(newsticker--treeview-unfold-node): Adapted to modified
	`newsticker--group-find-parent-group'.
	(newsticker--group-do-find-group): Renamed
	`newsticker--group-do-find-group-for-feed' to
	`newsticker--group-do-find-group'.  Now works for both, groups and
	feeds.
	(newsticker--group-find-parent-group): Renamed
	`newsticker--group-find-group-for-feed' to
	`newsticker--group-find-parent-group'.  Now works for both, groups
	and feeds.
	(newsticker--group-do-get-parent-group)
	(newsticker--group-get-parent-group): Removed.
	(newsticker-group-add-group): Changed interactive prompts.
	(newsticker-group-add-group): Finally jump to added group.
	(newsticker-group-delete-group): Finally jump to current feed.
	(newsticker--group-do-rename-group, newsticker-group-rename-group)
	(newsticker--get-group-names, newsticker--group-names): New.
	(newsticker-group-move-feed): Finally jump to moved feed.
	(newsticker-group-shift-feed-down, newsticker-group-shift-feed-up)
	(newsticker-group-shift-group-down)
	(newsticker-group-shift-group-up, newsticker--group-shift): New
	(newsticker--group-manage-orphan-feeds): Renamed
	`newsticker--group-find-group-for-feed' to
	`newsticker--group-find-parent-group'.
	(newsticker-treeview-mode-map): New keybindings for new shift commands.
	(newsticker-treeview-tree-do-click): Renamed
	`newsticker--treeview-get-node' to
	`newsticker--treeview-get-node-by-id'.

	* net/newst-backend.el (newsticker--item-list)
	(newsticker--item-position, newsticker--prev-message)
	(newsticker--scrollable-text): Moved to newst-ticker.el.

	* net/newst-ticker.el (newsticker--item-list)
	(newsticker--item-position, newsticker--prev-message)
	(newsticker--scrollable-text): Moved from newst-backend.el.
parent cb617064
2014-09-24 Ulf Jasper <ulf.jasper@web.de>
* newsticker.texi: Reworked. Document new treeview group
commands. Remove VERSION, UPDATED, use EMACSVER instead. Use
term 'feed reader'.
2014-09-04 Paul Eggert <eggert@cs.ucla.edu>
Less chatter in 'make' output.
......
This diff is collapsed.
2014-09-24 Ulf Jasper <ulf.jasper@web.de>
* net/newst-treeview.el (newsticker--treeview-do-get-node-by-id):
Renamed `newsticker--treeview-do-get-node' to
`newsticker--treeview-do-get-node-by-id'.
(newsticker--treeview-get-node-by-id): Renamed
`newsticker--treeview-get-node' to
`newsticker--treeview-get-node-by-id'.
(newsticker--treeview-get-current-node): Renamed `
`newsticker--treeview-get-node' to
`newsticker--treeview-get-node-by-id'.
(newsticker--treeview-buffer-init)
(newsticker--treeview-buffer-init): Disable buffer undo.
(newsticker--treeview-unfold-node): Adapted to modified
`newsticker--group-find-parent-group'.
(newsticker--group-do-find-group): Renamed
`newsticker--group-do-find-group-for-feed' to
`newsticker--group-do-find-group'. Now works for both, groups and
feeds.
(newsticker--group-find-parent-group): Renamed
`newsticker--group-find-group-for-feed' to
`newsticker--group-find-parent-group'. Now works for both, groups
and feeds.
(newsticker--group-do-get-parent-group)
(newsticker--group-get-parent-group): Removed.
(newsticker-group-add-group): Changed interactive prompts.
(newsticker-group-add-group): Finally jump to added group.
(newsticker-group-delete-group): Finally jump to current feed.
(newsticker--group-do-rename-group, newsticker-group-rename-group)
(newsticker--get-group-names, newsticker--group-names): New.
(newsticker-group-move-feed): Finally jump to moved feed.
(newsticker-group-shift-feed-down, newsticker-group-shift-feed-up)
(newsticker-group-shift-group-down)
(newsticker-group-shift-group-up, newsticker--group-shift): New
(newsticker--group-manage-orphan-feeds): Renamed
`newsticker--group-find-group-for-feed' to
`newsticker--group-find-parent-group'.
(newsticker-treeview-mode-map): New keybindings for new shift commands.
(newsticker-treeview-tree-do-click): Renamed
`newsticker--treeview-get-node' to
`newsticker--treeview-get-node-by-id'.
* net/newst-backend.el (newsticker--item-list)
(newsticker--item-position, newsticker--prev-message)
(newsticker--scrollable-text): Moved to newst-ticker.el.
* net/newst-ticker.el (newsticker--item-list)
(newsticker--item-position, newsticker--prev-message)
(newsticker--scrollable-text): Moved from newst-backend.el.
2014-09-22 Kan-Ru Chen <kanru@kanru.info>
 
* window.el (fit-window-to-buffer): When counting buffer width,
......
......@@ -6,7 +6,7 @@
;; Filename: newst-backend.el
;; URL: http://www.nongnu.org/newsticker
;; Keywords: News, RSS, Atom
;; Time-stamp: "13. Mai 2011, 20:47:05 (ulf)"
;; Time-stamp: "23. September 2014, 19:51:10 (ulf)"
;; Package: newsticker
;; ======================================================================
......@@ -483,14 +483,6 @@ that can be added."
;; ======================================================================
;;; Internal variables
;; ======================================================================
(defvar newsticker--item-list nil
"List of newsticker items.")
(defvar newsticker--item-position 0
"Actual position in list of newsticker items.")
(defvar newsticker--prev-message "There was no previous message yet!"
"Last message that the newsticker displayed.")
(defvar newsticker--scrollable-text ""
"The text which is scrolled smoothly in the echo area.")
(defvar newsticker--buffer-uptodate-p nil
"Tells whether the newsticker buffer is up to date.")
(defvar newsticker--latest-update-time (current-time)
......
......@@ -6,7 +6,7 @@
;; Filename: newst-ticker.el
;; URL: http://www.nongnu.org/newsticker
;; Keywords: News, RSS, Atom
;; Time-stamp: "6. Dezember 2009, 19:16:00 (ulf)"
;; Time-stamp: "24. September 2014, 19:07:25 (ulf)"
;; Package: newsticker
;; ======================================================================
......@@ -37,6 +37,14 @@
(require 'newst-backend)
(defvar newsticker--item-list nil
"List of newsticker items.")
(defvar newsticker--item-position 0
"Actual position in list of newsticker items.")
(defvar newsticker--prev-message "There was no previous message yet!"
"Last message that the newsticker displayed.")
(defvar newsticker--scrollable-text ""
"The text which is scrolled smoothly in the echo area.")
(defvar newsticker--ticker-timer nil
"Timer for newsticker ticker.")
......
......@@ -238,23 +238,23 @@ their id stays constant."
(newsticker--treeview-do-get-node-of-feed feed-name
newsticker--treeview-vfeed-tree)))
(defun newsticker--treeview-do-get-node (id startnode)
(defun newsticker--treeview-do-get-node-by-id (id startnode)
"Recursively search node with ID starting from STARTNODE."
(if (newsticker--treeview-ids-eq id (widget-get startnode :nt-id))
(throw 'found startnode)
(let ((children (widget-get startnode :children)))
(dolist (w children)
(newsticker--treeview-do-get-node id w)))))
(newsticker--treeview-do-get-node-by-id id w)))))
(defun newsticker--treeview-get-node (id)
(defun newsticker--treeview-get-node-by-id (id)
"Return node with ID in newsticker treeview tree."
(catch 'found
(newsticker--treeview-do-get-node id newsticker--treeview-feed-tree)
(newsticker--treeview-do-get-node id newsticker--treeview-vfeed-tree)))
(newsticker--treeview-do-get-node-by-id id newsticker--treeview-feed-tree)
(newsticker--treeview-do-get-node-by-id id newsticker--treeview-vfeed-tree)))
(defun newsticker--treeview-get-current-node ()
"Return current node in newsticker treeview tree."
(newsticker--treeview-get-node newsticker--treeview-current-node-id))
(newsticker--treeview-get-node-by-id newsticker--treeview-current-node-id))
;; ======================================================================
......@@ -1166,12 +1166,14 @@ Arguments IGNORE are ignored."
(unless newsticker--selection-overlay
(with-current-buffer (newsticker--treeview-list-buffer)
(setq buffer-undo-list t)
(setq newsticker--selection-overlay (make-overlay (point-min)
(point-max)))
(overlay-put newsticker--selection-overlay 'face
'newsticker-treeview-selection-face)))
(unless newsticker--tree-selection-overlay
(with-current-buffer (newsticker--treeview-tree-buffer)
(setq buffer-undo-list t)
(setq newsticker--tree-selection-overlay (make-overlay (point-min)
(point-max)))
(overlay-put newsticker--tree-selection-overlay 'face
......@@ -1218,7 +1220,7 @@ Note: does not update the layout."
(newsticker-treeview-save))
(defun newsticker-treeview-save ()
"Save newsticker data including treeview settings."
"Save treeview group settings."
(interactive)
(let ((coding-system-for-write 'utf-8)
(buf (find-file-noselect (concat newsticker-dir "/groups"))))
......@@ -1598,10 +1600,8 @@ Return t if a new feed was activated, nil otherwise."
"Recursively show subtree above the node that represents FEED-NAME."
(let ((node (newsticker--treeview-get-node-of-feed feed-name)))
(unless node
(let* ((group-name (or (car (newsticker--group-find-group-for-feed
feed-name))
(newsticker--group-get-parent-group
feed-name))))
(let* ((group-name (car (newsticker--group-find-parent-group
feed-name))))
(newsticker--treeview-unfold-node group-name))
(setq node (newsticker--treeview-get-node-of-feed feed-name)))
(when node
......@@ -1625,20 +1625,31 @@ Return t if a new feed was activated, nil otherwise."
;; ======================================================================
;;; Groups
;; ======================================================================
(defun newsticker--group-do-find-group-for-feed (feed-name node)
"Recursively find FEED-NAME in NODE."
(if (member feed-name (cdr node))
(throw 'found node)
(mapc (lambda (n)
(if (listp n)
(newsticker--group-do-find-group-for-feed feed-name n)))
(cdr node))))
(defun newsticker--group-find-group-for-feed (feed-name)
"Find group containing FEED-NAME."
(defun newsticker--group-do-find-group (feed-or-group-name parent-node node)
"Recursively find FEED-OR-GROUP-NAME in PARENT-NODE or NODE."
(cond ((stringp node)
(when (string= feed-or-group-name node)
(throw 'found parent-node)))
((listp node)
(cond ((string= feed-or-group-name (car node))
(throw 'found parent-node))
((member feed-or-group-name (cdr node))
(throw 'found node))
(t
(mapc (lambda (n)
(if (listp n)
(newsticker--group-do-find-group
feed-or-group-name node n)))
(cdr node)))))))
(defun newsticker--group-find-parent-group (feed-or-group-name)
"Find group containing FEED-OR-GROUP-NAME."
(catch 'found
(newsticker--group-do-find-group-for-feed feed-name
newsticker-groups)
(mapc (lambda (n)
(newsticker--group-do-find-group feed-or-group-name
newsticker-groups
n))
newsticker-groups)
nil))
(defun newsticker--group-do-get-group (name node)
......@@ -1659,26 +1670,6 @@ Return t if a new feed was activated, nil otherwise."
newsticker-groups)
nil))
(defun newsticker--group-do-get-parent-group (name node parent)
"Recursively find parent group for NAME from NODE which is a child of PARENT."
(if (string= name (car node))
(throw 'found parent)
(mapc (lambda (n)
(if (listp n)
(newsticker--group-do-get-parent-group name n (car node))))
(cdr node))))
(defun newsticker--group-get-parent-group (name)
"Find parent group for group named NAME."
(catch 'found
(mapc (lambda (n)
(if (listp n)
(newsticker--group-do-get-parent-group
name n (car newsticker-groups))))
newsticker-groups)
nil))
(defun newsticker--group-get-subgroups (group &optional recursive)
"Return list of subgroups for GROUP.
If RECURSIVE is non-nil recursively get subgroups and return a nested list."
......@@ -1714,9 +1705,9 @@ return a nested list."
(defun newsticker-group-add-group (name parent)
"Add group NAME to group PARENT."
(interactive
(list (read-string "Group Name: ")
(list (read-string "Name of new group: ")
(let ((completion-ignore-case t))
(completing-read "Parent Group: " (newsticker--group-all-groups)
(completing-read "Name of parent group (optional): " (newsticker--group-all-groups)
nil t))))
(if (newsticker--group-get-group name)
(error "Group %s exists already" name))
......@@ -1726,46 +1717,154 @@ return a nested list."
(unless p
(error "Parent %s does not exist" parent))
(setcdr p (cons (list name) (cdr p))))
(newsticker--treeview-tree-update))
(newsticker--treeview-tree-update)
(newsticker-treeview-jump newsticker--treeview-current-feed))
(defun newsticker-group-delete-group (name)
"Delete group NAME."
(interactive
(list (let ((completion-ignore-case t))
(completing-read "Delete group: "
(newsticker--group-names)
nil t (car (newsticker--group-find-parent-group
newsticker--treeview-current-feed))))))
(let ((parent-group (newsticker--group-find-parent-group name)))
(unless parent-group
(error "Parent %s does not exist" parent-group))
(setcdr parent-group (cl-delete-if (lambda (g)
(and (listp g)
(string= name (car g))))
(cdr parent-group)))
(newsticker--group-manage-orphan-feeds)
(newsticker--treeview-tree-update)
(newsticker-treeview-update)
(newsticker-treeview-jump newsticker--treeview-current-feed)))
(defun newsticker--group-do-rename-group (old-name new-name)
"Actually rename group OLD-NAME to NEW-NAME."
(let ((parent-group (newsticker--group-find-parent-group old-name)))
(unless parent-group
(error "Parent of %s does not exist" old-name))
(mapcar (lambda (elt)
(cond ((and (listp elt)
(string= old-name (car elt)))
(cons new-name (cdr elt)))
(t
elt))) parent-group)))
(defun newsticker-group-rename-group (old-name new-name)
"Rename group OLD-NAME to NEW-NAME."
(interactive
(list (let* ((completion-ignore-case t))
(completing-read "Rename group: "
(newsticker--group-names)
nil t (car (newsticker--group-find-parent-group
newsticker--treeview-current-feed))))
(read-string "Rename to: ")))
(setq newsticker-groups (newsticker--group-do-rename-group old-name new-name))
(newsticker--group-manage-orphan-feeds)
(newsticker--treeview-tree-update)
(newsticker-treeview-update)
(newsticker-treeview-jump newsticker--treeview-current-feed))
(defun newsticker--get-group-names (lst)
"Do get the group names from LST."
(delete nil (cons (car lst)
(apply 'append
(mapcar (lambda (e)
(cond ((listp e)
(newsticker--get-group-names e))
(t
nil)))
(cdr lst))))))
(defun newsticker--group-names ()
"Get names of all newsticker groups."
(newsticker--get-group-names newsticker-groups))
(defun newsticker-group-move-feed (name group-name &optional no-update)
"Move feed NAME to group GROUP-NAME.
Update treeview afterwards unless NO-UPDATE is non-nil."
(interactive
(let ((completion-ignore-case t))
(list (completing-read "Feed Name: "
(mapcar 'car newsticker-url-list)
(list (completing-read "Name of feed or group to move: "
(append (mapcar 'car newsticker-url-list)
(newsticker--group-names))
nil t newsticker--treeview-current-feed)
(completing-read "Group Name: " (newsticker--group-all-groups)
(completing-read "Name of new parent group: " (newsticker--group-names)
nil t))))
(let ((group (if (and group-name (not (string= group-name "")))
(newsticker--group-get-group group-name)
newsticker-groups)))
(let* ((group (if (and group-name (not (string= group-name "")))
(newsticker--group-get-group group-name)
newsticker-groups))
(moving-group-p (member name (newsticker--group-names)))
(moved-thing (if moving-group-p
(newsticker--group-get-group name)
name)))
(unless group
(error "Group %s does not exist" group-name))
(while (let ((old-group
(newsticker--group-find-group-for-feed name)))
(newsticker--group-find-parent-group name)))
(when old-group
(delete name old-group))
(delete moved-thing old-group))
old-group))
(setcdr group (cons name (cdr group)))
(setcdr group (cons moved-thing (cdr group)))
(unless no-update
(newsticker--treeview-tree-update)
(newsticker-treeview-update))))
(newsticker-treeview-update)
(newsticker-treeview-jump name))))
(defun newsticker-group-delete-group (name)
"Remove group NAME."
(interactive
(let ((completion-ignore-case t))
(list (completing-read "Group Name: " (newsticker--group-all-groups)
nil t))))
(let* ((g (newsticker--group-get-group name))
(p (or (newsticker--group-get-parent-group name)
newsticker-groups)))
(unless g
(error "Group %s does not exist" name))
(delete g p))
(newsticker--treeview-tree-update))
(defun newsticker-group-shift-feed-down ()
"Shift current feed down in its group."
(interactive)
(newsticker--group-shift 1))
(defun newsticker-group-shift-feed-up ()
"Shift current feed down in its group."
(interactive)
(newsticker--group-shift -1))
(defun newsticker-group-shift-group-down ()
"Shift current group down in its group."
(interactive)
(newsticker--group-shift 1 t))
(defun newsticker-group-shift-group-up ()
"Shift current group down in its group."
(interactive)
(newsticker--group-shift -1 t))
(defun newsticker--group-shift (delta &optional move-group)
"Shift current feed or group within its parent group.
DELTA is an integer which specifies the direction and the amount
of the shift. If MOVE-GROUP is nil the currently selected feed
`newsticker--treeview-current-feed' is shifted, if it is t then
the current feed's parent group is shifted.."
(let* ((cur-feed newsticker--treeview-current-feed)
(thing (if move-group
(newsticker--group-find-parent-group cur-feed)
cur-feed))
(parent-group (newsticker--group-find-parent-group
(if move-group (car thing) thing))))
(unless parent-group
(error "Group not found!"))
(let* ((siblings (cdr parent-group))
(pos (cl-position thing siblings :test 'equal))
(tpos (+ pos delta ))
(new-pos (max 0 (min (length siblings) tpos)))
(beg (cl-subseq siblings 0 (min pos new-pos)))
(end (cl-subseq siblings (+ 1 (max pos new-pos))))
(p (elt siblings new-pos)))
(when (not (= pos new-pos))
(setcdr parent-group
(cl-concatenate 'list
beg
(if (> delta 0)
(list p thing)
(list thing p))
end))
(newsticker--treeview-tree-update)
(newsticker-treeview-update)
(newsticker-treeview-jump cur-feed)))))
(defun newsticker--count-groups (group)
"Recursively count number of subgroups of GROUP."
......@@ -1812,7 +1911,7 @@ Return t if groups have changed, nil otherwise."
(let ((new-feed nil)
(grouped-feeds (newsticker--count-grouped-feeds newsticker-groups)))
(mapc (lambda (f)
(unless (newsticker--group-find-group-for-feed (car f))
(unless (newsticker--group-find-parent-group (car f))
(setq new-feed t)
(newsticker-group-move-feed (car f) nil t)))
(append newsticker-url-list-defaults newsticker-url-list))
......@@ -1914,6 +2013,12 @@ Return t if groups have changed, nil otherwise."
;;(define-key map "\C-m" 'newsticker-treeview-scroll-item)
(define-key map "\M-m" 'newsticker-group-move-feed)
(define-key map "\M-a" 'newsticker-group-add-group)
(define-key map "\M-d" 'newsticker-group-delete-group)
(define-key map "\M-r" 'newsticker-group-rename-group)
(define-key map [M-down] 'newsticker-group-shift-feed-down)
(define-key map [M-up] 'newsticker-group-shift-feed-up)
(define-key map [M-S-down] 'newsticker-group-shift-group-down)
(define-key map [M-S-up] 'newsticker-group-shift-group-up)
map)
"Mode map for newsticker treeview.")
......@@ -1972,10 +2077,10 @@ POS gives the position where EVENT occurred."
(newsticker-treeview-show-item))
(t
;; click in tree buffer
(let ((w (newsticker--treeview-get-node nt-id)))
(let ((w (newsticker--treeview-get-node-by-id nt-id)))
(when w
(newsticker--treeview-tree-update-tag w t t)
(setq w (newsticker--treeview-get-node nt-id))
(setq w (newsticker--treeview-get-node-by-id nt-id))
(widget-put w :nt-selected t)
(widget-apply w :action event)
(newsticker--treeview-set-current-node w))))))
......
2014-09-24 Ulf Jasper <ulf.jasper@web.de>
* automated/newsticker-tests.el
(newsticker--group-find-parent-group),
(newsticker--group-do-rename-group): New tests.
2014-09-09 Eli Zaretskii <eliz@gnu.org>
* automated/fns-tests.el (fns-tests-collate-sort): Bind
......
......@@ -143,6 +143,26 @@ Signals an error if something goes wrong."
(should (equal '("Feeds" "feed3" "feed2" "feed1")
newsticker-groups))))
(ert-deftest newsticker--group-find-parent-group ()
"Test `newsticker--group-find-parent-group'."
(let ((newsticker-groups '("g1" "f1a" ("g2" "f2" ("g3" "f3a" "f3b")) "f1b")))
;; feeds
(should (equal "g1" (car (newsticker--group-find-parent-group "f1a"))))
(should (equal "g1" (car (newsticker--group-find-parent-group "f1b"))))
(should (equal "g2" (car (newsticker--group-find-parent-group "f2"))))
(should (equal "g3" (car (newsticker--group-find-parent-group "f3b"))))
;; groups
(should (equal "g1" (car (newsticker--group-find-parent-group "g2"))))
(should (equal "g2" (car (newsticker--group-find-parent-group "g3"))))))
(ert-deftest newsticker--group-do-rename-group ()
"Test `newsticker--group-do-rename-group'."
(let ((newsticker-groups '("g1" "f1a" ("g2" "f2" ("g3" "f3a" "f3b")) "f1b")))
(should (equal '("g1" "f1a" ("h2" "f2" ("g3" "f3a" "f3b")) "f1b")
(newsticker--group-do-rename-group "g2" "h2")))
))
(provide 'newsticker-tests)
;;; newsticker-tests.el ends here
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment