{"id":13894637,"url":"https://github.com/chimay/torus","last_synced_at":"2025-07-17T09:33:47.476Z","repository":{"id":153608476,"uuid":"170978418","full_name":"chimay/torus","owner":"chimay","description":"Switching buffers and buffer groups at will in emacs. Based on MTorus : rewritten from scratch","archived":false,"fork":false,"pushed_at":"2023-04-19T09:29:43.000Z","size":803,"stargazers_count":48,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-07T18:31:13.334Z","etag":null,"topics":["buffer","emacs","group"],"latest_commit_sha":null,"homepage":"","language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chimay.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-02-16T08:02:51.000Z","updated_at":"2024-05-30T20:27:45.000Z","dependencies_parsed_at":"2023-06-26T01:56:07.203Z","dependency_job_id":null,"html_url":"https://github.com/chimay/torus","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimay%2Ftorus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimay%2Ftorus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimay%2Ftorus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimay%2Ftorus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chimay","download_url":"https://codeload.github.com/chimay/torus/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226248375,"owners_count":17595159,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["buffer","emacs","group"],"created_at":"2024-08-06T18:01:40.276Z","updated_at":"2024-11-24T23:31:18.640Z","avatar_url":"https://github.com/chimay.png","language":"Emacs Lisp","funding_links":[],"categories":["Emacs Lisp"],"sub_categories":[],"readme":"\n#+STARTUP: showall\n\n#+TAGS: TOC(t)\n\n* Table of contents                                                     :TOC_2_gh:\n- [[#news][News]]\n- [[#introduction][Introduction]]\n  - [[#history][History]]\n  - [[#goal][Goal]]\n- [[#installation][Installation]]\n  - [[#melpa][MELPA]]\n  - [[#el-get][El-get]]\n- [[#step-by-step][Step by Step]]\n  - [[#first-circles][First Circles]]\n  - [[#moving-around][Moving around]]\n  - [[#square-the-circle][Square the Circle]]\n  - [[#splits][Splits]]\n- [[#key-bindings][Key Bindings]]\n  - [[#levels][Levels]]\n  - [[#list-of-bindings][List of bindings]]\n  - [[#shortcuts][Shortcuts]]\n- [[#mouse][Mouse]]\n  - [[#on-the-tab-bar][On the tab bar]]\n- [[#configuration][Configuration]]\n  - [[#use-package][Use-package]]\n- [[#changelog][Changelog]]\n- [[#author--licence][Author \u0026 Licence]]\n- [[#warning][Warning]]\n\n* News\n\nVersion 2 is out ! Check the =README.org= of branch =version-2= on github or,\nif you have a local clone :\n\n#+BEGIN_SRC\ngit checkout version-2\n#+END_SRC\n\n\n* Introduction\n\nIf you ever dreamed about creating and switching buffer groups at will\nin Emacs, [[https://github.com/chimay/torus][Torus]] is the tool you want.\n\nIn short, this plugin let you organize your buffers by creating as\nmany buffer groups as you need, add the buffers you want to it and\nquickly navigate between :\n\n  - Buffers of the same group\n\n  - Buffer groups\n\n  - Workspaces, ie sets of buffer groups\n\nNote that :\n\n  - A location is a pair (filename . position)\n\n  - A buffer group, in fact a location group, is called a circle\n\n  - A set of buffer groups is called a torus (a circle of circles)\n\n\n** History\n\nThis project is inspired by MTorus. You can find the original sources\non the links below :\n\n  - The repository of Stefan Kamphausen, the orignal author, is\n    available at https://www.skamphausen.de/cgi-bin/ska/mtorus\n\n  - The rewrite by Sebastian Freundt is available on\n    https://sourceforge.net/projects/mtorus.berlios/\n\n  - I’ve a personal fork of the second one :\n    https://github.com/chimay/mtorus, but I won’t maintain it anymore\n\nThe code I forked is complex, so I decided to write a new version from\nscratch, easier to maintain and enjoying more recent features of\nemacs.\n\n\n** Goal\n\nTorus helps you to organize your files in groups that you create\nyourself, following your workflow. You only add the files you want,\nwhere you want. For instance, if you have a \"organize\" group with\nagenda \u0026 todo files, you can quickly alternate them, or display them\nin two windows. Then, if you suddenly got an idea to tune emacs, you\nswitch to the \"emacs\" group with your favorites configuration files in\nit. Same process, to cycle, alternate or display the files. Note that\nthe torus containing all these groups can be saved on a file and\nloaded later. Over time, your groups will grow and adapt to your\nstyle.\n\n\n* Installation\n\n\n** MELPA\n\nTorus is available on MELPA. If you have this line on your init file :\n\n#+begin_src emacs-lisp\n  (add-to-list 'package-archives '(\"melpa\" . \"http://melpa.org/packages/\"))\n#+end_src\n\nyou should be able to install it from the packages menu\n(~M-x list-packages~).\n\n\n** El-get\n\nIf you use el-get, just create a recipe file ~torus.rcp~ :\n\n#+begin_src emacs-lisp\n  (:name torus\n\t :website \"http://github.com/chimay/torus\"\n\t :description \"Torus : Circle of Circles of buffers\"\n\t :type github\n\t :pkgname \"chimay/torus\")\n#+end_src\n\nand add it to a directory present in ~el-get-recipe-path~. Then, use\n~M-x el-get-install \u003cRET\u003e torus~ or add :\n\n#+begin_src emacs-lisp\n(el-get-bundle torus)\n#+end_src\n\nto your init file.\n\n\n* Step by Step\n\n\n** First Circles\n\nLet’s say we have the files =Juice=, =Tea=, =Coffe=. The first thing\nto do is to create a group (a circle) which will contain them. So, we\nlaunch ~torus-add-circle~ and answer =Drinks= to the prompt. Then, we\ngo to =Juice= and use ~torus-add-location~ to add it to the circle.\nSame process with =Tea= and =Coffee=. We now have a circle =Drink=\ncontaining three files.\n\nIf your files are not already opened in buffers, just use\n~torus-add-file~ to add them in the circle.\n\nIf you want to create another circle, let’s say =Fruits=, simply\nlaunch ~torus-add-circle~ again, and enter another name. You can then\nadd the files =Apple=, =Pear= and =Orange= to it. You can even also\nadd =Juice=, a file can be added to more than one circle.\n\nNow, suppose that in the =Juice= file, you have a Pineapple and a\nMango sections, and you want to compare them. Just go to the Pineapple\nsection, use ~torus-add-location~. It will add the location\n(=Juice . pineapple-position=) to the current circle. Then, go to\nthe Mango section, and do the same. The (=Juice . mango-position=)\nwill also be added to the circle. You can then easily alternate both,\nor display them in split windows.\n\n\n** Moving around\n\nYou can cycle the files of a circle with ~torus-next-location~ and\n~torus-previous-location~. You can also switch file with completion by using\n~torus-switch-location~. It works well with Helm.\n\nTo cycle the circles, use ~torus-next-circle~ and\n~torus-previous-circle~. To go to a given circle with completion, use\n~torus-switch-circle~.\n\n\n** Square the Circle\n\nOver time, the number of circles will grow. Completion is great, but\nif you just want to alternate the two last circles in history, you’ll\nprobably prefer ~ŧorus-alternate-circles~. You can also alternate two\nlast files inside the same circle with\n~torus-alternate-in-same-circle~. So, you have the square :\n\n| circle 1, file 1 | circle 1, file 2 |\n| circle 2, file 3 | circle 2, file 4 |\n\nat your fingertips.\n\nFinally, ~torus-alternate-in-same-torus~ alternate two last history\nfiles, regardless of their circles.\n\n\n** Splits\n\nIf you prefix a torus navigation function by C-u, the asked file will\nbe opened in a new window below. With C-u C-u, it will be in a new\nwindow on the right.\n\nIf you want to see all the circle files in separate windows, use\n~torus-layout-menu~ and chose between horizontal, vertical or grid\nsplits. You also have layouts with main window on left, right, top or\nbottom side.\n\nYour choice is remembered by torus for the current circle. You can\nswith back to one window using the same layout function. The special\nchoice \"manual\" ask Torus not to interfere in your layout.\n\nThe maximum number of windows generated by the split functions\nare conxtrolled by the vars ~torus-maximum-horizontal-split~ and\n~torus-maximum-vertical-split~.\n\n\n* Key Bindings\n\nAll bindings are available after the prefix key =\u003csuper-t\u003e= by\ndefault. You can see them by pressing \u003csuper-t\u003e\u003cC-h\u003e, or by installing\n[[https://github.com/justbur/emacs-which-key][which-key]]. You can also define your own :\n\n#+begin_src emacs-lisp\n  (define-key torus-map (kbd \"i\") 'torus-info)\n#+end_src\n\n\n** Levels\n\nThe option ~torus-binding-level~, an integer between 0 and 3, decide\nhow many functions will be bound to keys : the higher it is, the more\nbindings available. Level 1 or 2 is fine for most usages.\n\n  - Level 0\n\n    + Adding\n\n    + Deleting\n\n    + Moving around\n\n    + Save and load\n\n  - Level 1\n\n    + History\n\n    + Renaming\n\n    + Moving and copying things\n\n    + Join\n\n    + Layout\n\n  - Level 2\n\n    + Reverse\n\n    + Prefix\n\n    + Autogroup\n\n  - Level 3 : you surely don’t want to use these\n\n    + Print main internal variables\n\n    + Reset main internal variables\n\n    + Miscellaneous\n\n\n** List of bindings\n\nEnter the prefix key, then :\n\n  - =c= : create a new circle, add it to the torus\n\n  - =l= : create the current location (file . position) to the current circle\n\n  - =f= : add a file to the current circle ; more precisely, location (file . 1)\n\n  - =i= : info about the current circle\n\n  - =p= : print main variables content\n\n  - =\u003cdown\u003e= : next file (location) in circle\n\n  - =\u003cup\u003e= : previous file in circle\n\n  - ~=~ : switch file in circle\n\n  - =\u003cright\u003e= : next circle\n\n  - =\u003cleft\u003e= : previous circle\n\n  - =\u003cspace\u003e= : switch circle\n\n  - =s= : search file in all circles\n\n  - =\u003cPageDown\u003e= : older file in file history\n\n  - =\u003cPageUp\u003e= : newer file in file history\n\n  - =a= : alternate menu\n\n    + =m= : alternate last two visited files in all toruses (meta torus)\n\n    + =t= : alternate last two visited files in current torus\n\n    + =c= : alternate last two visited files in current circle\n\n    + =T= : alternate last two toruses\n\n    + =C= : alternate last two circles\n\n  - =^= : alternate last two visited files in history of current torus\n\n  - =\u003c= : alternate last two circles in history\n\n  - =\u003e= : alternate last two files in same circle in history\n\n  - =h= : search in the file history\n\n  - =n= : rename circle\n\n  - =d= : delete file from circle\n\n  - =D= : delete circle from torus\n\n  - =w= : write torus to a file as Lisp code (with \".el\" extension)\n\n  - =r= : read torus from a torus file\n\n  - =e= : edit a torus file ; ask to load its content after saving it\n\n  - =m= : move file in circle (not on disk)\n\n  - =M= : move circle in torus\n\n  - =v= : move file to another circle\n\n  - =y= : copy, add the (file . position) to another circle\n\n  - =j= : join the files of two circles, a new circle is created to\n    contain them\n\n  - =#= : layout menu\n\n    + =m= : manual mode, leave unchanged\n\n    + =o= : only one window, delete the others\n\n    + =h= : split horizontally to display all files of the circles\n\n    + =v= : split vertically to display all files of the circles\n\n    + =g= : split in a grid to display all files of the circles\n\n  - =o= : reverse menu\n\n    + =l= : reverse location order (file order) in a circle\n\n    + =c= : reverse circle order in the torus\n\n    + =d= : deep reverse : reverse both locations and circle\n\n  - =:= : prefix circles names\n\n  - =!= : batch menu (be careful with this)\n\n    + =e= : eval Elisp code on each file of the current circle\n\n    + =c= : eval Elisp command on each file of the current circle\n\n    + =!= : eval Shell command on each file of the current circle\n\n    + =\u0026= : eval Async Shell command on each file of the current circle\n\n\n*** Torus operations\n\nYou can create new toruses, beginning with a copy of the current\ntorus, and switch easily between them. A list of toruses, called Meta\nTorus, is available. Some actions, like joining or autogrouping, also\ncreate new toruses.\n\n  - =+= : add a new torus to the torus list (variable ~torus-meta~)\n\n  - =*= : add a new torus as a copy of the current torus\n\n  - =C-n= : next torus\n\n  - =C-p= : previous torus\n\n  - =@= : switch torus\n\n  - =S= : search file in all toruses\n\n  - =N= : rename torus\n\n  - =M-m= : move torus in meta torus\n\n  - =V= : move circle to another torus\n\n  - =Y= : copy circle to another torus\n\n  - =J= : join the circles of two toruses, a new torus is created to\n    contain them\n\n  - =g= : autogroup files in a new torus\n\n    + =p= : group files by path\n\n    + =d= : group files by directories\n\n    + =e= : group files by extensions\n\n  - =-= : delete a torus\n\n\n** Shortcuts\n\nI strongly suggest that you bind the functions you use most to quick\nshortcuts. Here are some examples :\n\n#+begin_src emacs-lisp\n  (global-set-key (kbd \"\u003cS-s-insert\u003e\") 'torus-add-circle)\n  (global-set-key (kbd \"\u003cs-insert\u003e\") 'torus-add-location)\n\n  (global-set-key (kbd \"\u003cs-delete\u003e\") 'torus-delete-location)\n  (global-set-key (kbd \"\u003cS-s-delete\u003e\") 'torus-delete-circle)\n\n  (global-set-key (kbd \"\u003cC-prior\u003e\") 'torus-previous-location)\n  (global-set-key (kbd \"\u003cC-next\u003e\") 'torus-next-location)\n\n  (global-set-key (kbd \"\u003cC-home\u003e\") 'torus-previous-circle)\n  (global-set-key (kbd \"\u003cC-end\u003e\") 'torus-next-circle)\n\n  (global-set-key (kbd \"s-SPC\") 'torus-switch-circle)\n  (global-set-key (kbd \"s-=\") 'torus-switch-location)\n  (global-set-key (kbd \"s-^\") 'torus-switch-torus)\n\n  (global-set-key (kbd \"s-*\") 'torus-search)\n  (global-set-key (kbd \"s-/\") 'torus-search-history)\n\n  (global-set-key (kbd \"\u003cS-prior\u003e\") 'torus-history-newer)\n  (global-set-key (kbd \"\u003cS-next\u003e\") 'torus-history-older)\n\n  (global-set-key (kbd \"C-^\") 'torus-alternate-in-same-torus)\n\n  (global-set-key (kbd \"\u003cS-home\u003e\") 'torus-alternate-circles)\n  (global-set-key (kbd \"\u003cS-end\u003e\") 'torus-alternate-in-same-circle)\n#+end_src\n\n\n* Mouse\n\n\n** On the tab bar\n\nIf you set ~torus-display-tab-bar~ to ~t~, a minimalist tab bar will\ntake place on the top of your torus buffers. Appearence :\n\n#+begin_example\ncurrent-torus-name \u003e\u003e current-circle-name \u003e current-location | location-2 | location-3 | ...\n#+end_example\n\nYou can click on it to navigate :\n\n  - Torus name region\n\n    + Left click : switch torus with completion\n\n    + Right click : meta search on all files of all toruses\n\n    + Wheel : next / previous torus\n\n  - Circle name region\n\n    + Left click : switch circle with completion\n\n    + Right click : search on all files of the current torus\n\n    + Wheel : next / previous circle\n\n  - Location region\n\n    + Left click\n\n      * Current location : alternate two last locations in same circle\n\n      * Other locations : go to that location\n\n    + Right click : switch location with completion\n\n    + Wheel : next / previous location\n\n\n* Configuration\n\nHere is a sample configuration :\n\n#+begin_src emacs-lisp\n\n  (require 'torus)\n\n  (setq torus-prefix-key \"s-t\")\n\n  ;; Range 0 -\u003e 3\n  ;; The bigger it is, the more bindings.\n  (setq torus-binding-level 1)\n\n  ;; Created if non existent\n  (setq torus-dirname \"~/.emacs.d/torus/\")\n\n  ;; Set it to t if you want autoload of torus on Emacs startup\n  (setq torus-load-on-startup t)\n\n  ;; Set it to t if you want autosave of torus on Emacs exit\n  (setq torus-save-on-exit t)\n\n  ;; Where to auto load \u0026 save torus\n  (setq torus-autoread-file \"~/.emacs.d/torus/last.el\")\n  (setq torus-autowrite-file torus-autoread-file)\n\n  ;; Number of backups you want\n  ;; They will be numbered your-file.el.1 to your-file.el.N\n  (setq torus-backup-number 5)\n\n  (setq torus-history-maximum-elements 30)\n\n  (setq torus-maximum-horizontal-split 3)\n  (setq torus-maximum-vertical-split 4)\n\n  ;; Format :\n  ;; torus \u003e\u003e circle \u003e [ file:line ] | file:line | file:line | ...\n  (setq torus-display-tab-bar t)\n\n  (torus-init)\n\n  (torus-install-default-bindings)\n\n#+end_src\n\n\n** Use-package\n\nIf you declare Torus with ~use-package~ and want the start/quit hooks\nto load/save your torus file, you’ll have to add a ~:hook~ section to\nthe declaration :\n\n#+begin_src emacs-lisp\n  (use-package torus\n    :bind-keymap (\"s-t\" . torus-map)\n    :bind ((\"\u003cS-s-insert\u003e\" . torus-add-circle)\n\t   (\"\u003cs-insert\u003e\" . torus-add-location)\n\t   (\"\u003cs-delete\u003e\" . torus-delete-location)\n\t   (\"\u003cS-s-delete\u003e\" . torus-delete-circle)\n\t   (\"\u003cC-prior\u003e\" . torus-previous-location)\n\t   (\"\u003cC-next\u003e\" . torus-next-location)\n\t   (\"\u003cC-home\u003e\" . torus-previous-circle)\n\t   (\"\u003cC-end\u003e\" . torus-next-circle)\n\t   (\"\u003cS-prior\u003e\" . torus-history-newer)\n\t   (\"\u003cS-next\u003e\" . torus-history-older)\n\t   (\"C-^\" . torus-alternate-in-same-torus)\n\t   (\"\u003cS-home\u003e\" . torus-alternate-circles)\n\t   (\"\u003cS-end\u003e\" . torus-alternate-in-same-circle)\n\t   (\"s-SPC\" . torus-switch-circle)\n\t   (\"s-=\" . torus-switch-location)\n\t   (\"s-^\" . torus-switch-torus)\n\t   (\"s-*\" . torus-search)\n\t   (\"s-/\" . torus-search-history)\n\t   :map torus-map\n\t   (\"t\" . torus-copy-to-circle))\n    :hook ((emacs-startup . torus-start)\n\t   (kill-emacs . torus-quit))\n    :custom ((torus-prefix-key \"s-t\")\n\t     (torus-binding-level 3)\n\t     (torus-verbosity 1)\n\t     (torus-dirname (concat user-emacs-directory (file-name-as-directory \"torus\")))\n\t     (torus-load-on-startup t)\n\t     (torus-save-on-exit t)\n\t     (torus-autoread-file (concat torus-dirname \"last.el\"))\n\t     (torus-autowrite-file torus-autoread-file)\n\t     (torus-backup-number 5)\n\t     (torus-history-maximum-elements 30)\n\t     (torus-maximum-horizontal-split 3)\n\t     (torus-maximum-vertical-split 4)\n\t     (torus-display-tab-bar t)\n\t     (torus-separator-torus-circle \" \u003e\u003e \")\n\t     (torus-separator-circle-location \" \u003e \")\n\t     (torus-prefix-separator \"/\")\n\t     (torus-join-separator \" \u0026 \"))\n    :config\n    (torus-init)\n    (torus-install-default-bindings))\n#+end_src\n\n\n* Changelog\n\n  - version 1.10\n\n    + search in all toruses\n\n    + previous and next torus\n\n    + move torus\n\n    + copy \u0026 move circle to torus\n\n    + mouse support in tab bar\n\n    + batch operations\n\n  - version 1.9 : backup of torus files\n\n  - version 1.8 : tab bar\n\n  - version 1.7 : autogroups, layout\n\n  - version 1.6 : join, ready for MELPA\n\n  - version 1.2 - 1.5 : move, copy, reverse, history, split, alternate\n\n  - version 1.1 : input history\n\n  - version 1.0 : switch\n\n  - before : lost in the mist of prehistory\n\n\n* Author \u0026 Licence\n\n  - Copyright (C) 2019 Chimay\n  - Licensed under GPL v2\n\n\n* Warning\n\nDespite abundant testing, some bugs might remain, so be careful.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchimay%2Ftorus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchimay%2Ftorus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchimay%2Ftorus/lists"}