├── .github └── FUNDING.yml ├── .gitignore ├── CHANGELOG.org ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.org ├── custom.el ├── early-init-private.el ├── early-init.el ├── images ├── borgholm-castle.jpg └── roadsign.jpg ├── init.el ├── private.el └── screenshots ├── git_gutter.png ├── magit_spellcheck.png ├── main2.png ├── replace.png ├── thesaurus.png └── word_definition.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [freetonik] 2 | patreon: rakhim 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | elpa/ 2 | recentf 3 | request/ 4 | smex-items 5 | tmp/ 6 | projectile-bookmarks.eld 7 | bookmarks 8 | auto-save-list/ 9 | README.html 10 | /transient/ 11 | -------------------------------------------------------------------------------- /CHANGELOG.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Changelog 2 | 3 | ** 0.0.5 (Jul 17, 2020) 4 | - switched from =undo-tree= to =undo-fu= for simpler and more robust undo/redo 5 | - switched from =ag= to =ripgrep= 6 | ** 0.0.4 (Jan 1, 2019) 7 | - fixed contract region 8 | ** 0.0.3 (Sep 20, 2018) 9 | - I, J, K, L for navigation 10 | - =emmet= 11 | - scroll other window bindings 12 | ** 0.0.2 (Sep 19, 2018) 13 | - =ivy= and =counsel= instead of =Helm= 14 | - simpler =Neotree= 15 | - added =git-gutter= 16 | - added word definition lookup 17 | ** 0.0.1 (Sep 12, 2018) 18 | - first release 19 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at castlemacs@rakhim.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rakhim Davletkaliyev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+SETUPFILE: ~/code/org-themes/org-html-themes/setup/theme-readtheorg.setup 2 | #+LANGUAGE: en 3 | #+TITLE: Castlemacs: modern, minimalist Emacs for macOS ⌘ 4 | 5 | [[https://img.shields.io/github/tag/freetonik/castlemacs.svg?label=release&style=flat-square]] 6 | [[https://img.shields.io/badge/license-MIT-green.svg?style=flat-square]] 7 | 8 | [[./screenshots/main2.png]] 9 | 10 | ----- 11 | 12 | [[#installation][Installation]] | [[CHANGELOG.org][Changelog]] 13 | 14 | ----- 15 | 16 | * Features 17 | - Compatibility with common macOS keybindings 18 | - Ergonomic keybindings that follow simple, sensible rules 19 | - Easy windows management and movement 20 | - Easy movement between points in the file and between files 21 | - Multiple cursors, project manager, Git front end, file tree, terminal 22 | - Handy spellchecker, built-in thesaurus and word definition lookup 23 | - A handful of tiny, useful helper functions 24 | 25 | * Table of Contents 26 | :PROPERTIES: 27 | :TOC: this 28 | :END: 29 | - [[#intro][Intro]] 30 | - [[#core-principles][Core principles]] 31 | - [[#faq][FAQ]] 32 | - [[#installation][Installation]] 33 | - [[#install-emacs][Install Emacs]] 34 | - [[#alternative-version-advanced][Alternative version (advanced)]] 35 | - [[#install-dependencies][Install dependencies]] 36 | - [[#install-castlemacs][Install Castlemacs]] 37 | - [[#setup-keyboard][Setup keyboard]] 38 | - [[#note-to-mojave-users][Note to Mojave users]] 39 | - [[#usage][Usage]] 40 | - [[#modifier-keys][Modifier keys]] 41 | - [[#basics][Basics]] 42 | - [[#navigation][Navigation]] 43 | - [[#basic-movement][Basic movement]] 44 | - [[#moving-text][Moving text]] 45 | - [[#simple-jumping-within-text][Simple jumping within text]] 46 | - [[#smart-jumping-within-buffer-and-between-buffers][Smart jumping within buffer and between buffers]] 47 | - [[#search-and-replace][Search and replace]] 48 | - [[#editing][Editing]] 49 | - [[#words-and-lines][Words and lines]] 50 | - [[#deleting-text][Deleting text]] 51 | - [[#multiple-cursors][Multiple cursors]] 52 | - [[#indentation][Indentation]] 53 | - [[#region][Region]] 54 | - [[#window-management][Window Management]] 55 | - [[#splitting-windows][Splitting windows]] 56 | - [[#moving-between-windows][Moving between windows]] 57 | - [[#restoring-window-configuration][Restoring window configuration]] 58 | - [[#project-management][Project Management]] 59 | - [[#git][Git]] 60 | - [[#git-gutter][Git gutter]] 61 | - [[#magit][Magit]] 62 | - [[#terminal-shell][Terminal (shell)]] 63 | - [[#file-tree-and-open-buffers][File tree and open buffers]] 64 | - [[#programming][Programming]] 65 | - [[#languages-and-modes][Languages and modes]] 66 | - [[#code-completion][Code completion]] 67 | - [[#emmet][Emmet]] 68 | - [[#spellchecking-thesaurus-definition][Spellchecking, thesaurus, definition]] 69 | - [[#spellchecking][Spellchecking]] 70 | - [[#thesaurus][Thesaurus]] 71 | - [[#word-definition][Word definition]] 72 | - [[#org-mode][Org mode]] 73 | - [[#why-this-name][Why this name?]] 74 | 75 | * Intro 76 | 77 | Emacs is +an extensible, customizable text editor+ a framework for creating any text editor you want. The goal of Castlemacs is to build a simple, modern and minimalist Emacs setup tailored to macOS while following these 78 | 79 | ** Core principles 80 | 81 | 1. *Be beginner-friendly*. Anyone should be able to start using Castlemacs just like they can start using VS Code, Sublime, etc. 82 | 2. *Respect macOS.* Common system-wide keybindings work as you expect. 83 | 3. *Respect Emacs.* Never break vanilla Emacs compatibility. Always provide a way to go "full Emacs" if user so desires. 84 | 4. *No layers of complexity.* No custom configuration layers, no DSL, nothing new. Simple =init.el=, packages installed and configured via =use-package=. 85 | 5. *Go minimal when possible*. For example, use lightweight =avy= instead of full-featured =Helm=. 86 | 87 | * FAQ 88 | 89 | *Is Castlemacs compatible with non-macOS systems?* 90 | Yes! /Nothing/ binds Castlemacs to macOS except for some conventions. As long as you have some key on your keyboard that can play a role of =Super= (e.g. =windows= key), you're good to go. 91 | 92 | *I don't know Emacs. Can I use Castlemacs or is it hard?*. You don't need to know Emacs, but it will help. The goal of this project is to make a setup that is suitable for absolute beginners. 93 | 94 | *Is this similar to Spacemacs?* 95 | No. Spacemacs is a big, custom distribution with additional layers on top of Emacs. Castlemacs is simply a pre-configured Emacs. You don't need to learn anything new if you know your way around Emacs. 96 | 97 | *Will Castlemacs support ?* 98 | Probably, unless it goes against the Core Principles. Feel free to open an issue. 99 | 100 | *Does this setup work well in the terminal?* 101 | It works, but it is not built for terminal use, since one of the Core Principles is to behave like a native macOS application. 102 | 103 | *Why is it called Castlemacs?* See [[#why-this-name][Why this name?]] 104 | 105 | *Where do I store my private config?* You can store your regular private config in =private.el=. This file will not be changed in Castlemacs, so you don't have worry about conflicts. 106 | 107 | *Why does Castlemacs uses the system clipboard separately from the kill ring?* Kill ring system is powerful, but potentially confusing for newcomers. The way it is integrated with the system clipboard by default makes it even more confusing. For these reasons Castlemacs uses the system clipboard only (via the usual macOS key combinations), and keeps the kill ring system independently available to those who want it. 108 | 109 | * Installation 110 | 111 | ** Install Emacs 112 | 113 | Download Emacs from [[https://emacsformacosx.com/][emacsformacosx.com]]. That's it! 114 | 115 | *** Alternative version (advanced) 116 | 117 | The "simplest way" is the canonical Emacs distribution for macOS. However, it has a number of disadvantages: 118 | 119 | - Due to some build options related to graphics, certain extensions like Powerline produce incorrect colors (RGB space issue) 120 | - No emoji support (if you're into this kind of stuff) 121 | - No sub-pixel smooth scrolling 122 | - No native support for =org-protocol= 123 | 124 | If these are important to you, consider installing Mitsuharu Yamamoto's port instead. 125 | 126 | #+BEGIN_SRC sh 127 | brew tap railwaycat/emacsmacport 128 | brew install emacs-mac --with-natural-title-bar 129 | ln -s /usr/local/opt/emacs-mac/Emacs.app /Applications 130 | #+END_SRC 131 | 132 | ** Install dependencies 133 | 134 | Castlemacs relies on [[https://github.com/BurntSushi/ripgrep][ripgrep]] to quickly search within a project. Install it: 135 | 136 | #+BEGIN_SRC sh 137 | brew install ripgrep 138 | #+END_SRC 139 | 140 | Castlemacs requires =aspell=, a Free and Open Source spell checker. Install it: 141 | 142 | #+BEGIN_SRC sh 143 | brew install aspell 144 | #+END_SRC 145 | 146 | We also need `gnutls` — GNU Transport Layer Security (TLS) Library: 147 | 148 | #+BEGIN_SRC sh 149 | brew install gnutls 150 | #+END_SRC 151 | 152 | ** Install Castlemacs 153 | 154 | Backup current Emacs config (if exists), then clone Castlemacs from Github: 155 | 156 | #+BEGIN_SRC sh 157 | mv ~/.emacs.d ~/.emacs.d.bak 158 | git clone https://github.com/freetonik/castlemacs ~/.emacs.d 159 | #+END_SRC 160 | 161 | Launch Emacs and wait for several minutes. On the first launch it will download and install packages. When it's done and the status line in the bottom stops outputting text, restart Emacs. 162 | 163 | Don't worry about warning messages on the first launch, they will go away after first restart. 164 | 165 | ** Setup keyboard 166 | 167 | *I highly recommend changing Caps Lock to Control* by going to System Preferences → Keyboard → Modifier Keys. This way you will have a more comfortable Control under your left pinky. 168 | 169 | If you use Japanese Magic Keyboard, then you don't have to do anything, since =control= is in a good place already. 170 | 171 | ** Note to Mojave users 172 | 173 | In macOS Mojave Emacs build might fail due to some changes in Xcode command line tools. Xcode command line tools *must* be pointed to the release version of Xcode 10 instead of the beta version. Use xcode-select to accomplish this. 174 | 175 | * Usage 176 | 177 | ** Modifier keys 178 | 179 | Castlemacs takes advantage of two facts: 180 | 181 | 1. =Command= key is used in macOS for all major system shortcuts, so users have muscle memory; 182 | 2. Emacs recognizes a =Super= key, but almost never uses it by default. 183 | 184 | So, =Command= key becomes =Super= 185 | 186 | | Name | On Mac keyboard | Emacs key | 187 | |---------+-----------------+-----------| 188 | | Super | Command ⌘ | =s= | 189 | | Meta | Left Alt ⌥ | =M= | 190 | | Control | Control ⌃ | =C= | 191 | 192 | In this document we'll refer to keys with their common macOS names: Cmd, Alt, Ctrl. 193 | 194 | ** Basics 195 | 196 | Basic combinations with =Command= work as expected. 197 | 198 | | Binding | Description | Emacs default | 199 | |---------------+--------------------------+---------------| 200 | | =Escape= | Cancel current action | =C-g= | 201 | | =Cmd-z= | Undo | =c-_= | 202 | | =Cmd-Shift-z= | Redo | N/A | 203 | | =Cmd-s= | Save file | =C-x C-s= | 204 | | =Cmd-Shift-s= | Save file as | =C-x C-w= | 205 | | =Cmd-o= | Open file | =C-x C-f= | 206 | | =Cmd-a= | Select whole buffer | =C-x h= | 207 | | =Cmd-q= | Quit Emacs | =C-x C-c= | 208 | | =Cmd-Shift-p= | Open command palette | =M-x= | 209 | | =Ctrl-x c= | Open private config file | N/A | 210 | | =Ctrl-x C= | Open init config file | N/A | 211 | 212 | ** Navigation 213 | 214 | *** Basic movement 215 | 216 | Buttons I, J, K, L form a natural alternative to arrow keys. You can move around by holding Cmd while using these keys, without leaving the home row (press Cmd with your right thumb). 217 | 218 | (See http://tonsky.me/blog/cursor-keys/ for some background and motivation.) 219 | 220 | | Binding | Description | Emacs default | Alternative | 221 | |---------+-------------+---------------+-------------| 222 | | =Cmd-i= | Go up | =C-p= | Arrow UP | 223 | | =Cmd-k= | Go down | =C-n= | Arrow DOWN | 224 | | =Cmd-j= | Go left | =C-b= | Arrow LEFT | 225 | | =Cmd-l= | Go right | =C-f= | Arrow RIGHT | 226 | 227 | *** Moving text 228 | 229 | Hold =Alt= to move current line up or down. This is sometimes called "bubbling". 230 | 231 | | Binding | Description | 232 | |------------+----------------| 233 | | =Alt-UP= | Move line up | 234 | | =Alt-DOWN= | Move line down | 235 | 236 | *** Simple jumping within text 237 | 238 | =Cmd= or =Fn= with arrows work just like everywhere else in macOS. Holding =Shift= selects the region under movement. 239 | 240 | | Binding | Description | Emacs default | 241 | |---------------+------------------------+---------------| 242 | | =Cmd-LEFT= | Beginning of line† | =C-a= | 243 | | =Cmd-RIGHT= | End of line | =C-e= | 244 | | =Cmd-UP= | Beginning of buffer | =M-<= | 245 | | =Cmd-DOWN= | End of buffer | =M->= | 246 | | =Fn-UP= | Page up | =C-v= | 247 | | =Fn-DOWN= | Page down | =M-v= | 248 | | =Fn-Alt-UP= | Page up other window | =C-M-v= | 249 | | =Fn-Alt-DOWN= | Page down other window | =C-M-S-v= | 250 | 251 | † "Beginning of line" is a smart command. It moves cursor to the first non-whitespace character. Press it again, and it moves cursor to the real beginning of line. You can keep pressing it to jump cursor between those two positions. 252 | 253 | *** Smart jumping within buffer and between buffers 254 | 255 | Many commands in Emacs write the current position into a mark ring. For example, if you were editing line 6, then performed a search with =Cmd+f=, did something and want to come back, press =Cmd+,= to go back to line 6. =Cmd+.= to go forward. 256 | 257 | | Binding | Description | Emacs default | 258 | |---------+--------------------+---------------| 259 | | =Cmd-⸴= | Go to prev. mark | =C-u SPC= | 260 | | =Cmd-.= | Go to next mark | N/A | 261 | | =Cmd-<= | Go to prev. buffer | =C-x LEFT= | 262 | | =Cmd->= | Go to next buffer | =C-x RIGHT= | 263 | 264 | Holding =Shift= 'lifts' the meaning of this movement, and instead of jumping to a previous/next position in the current buffer, it jumps to a previous/next buffer in current window. 265 | 266 | ** Search and replace 267 | 268 | | Binding | Description | Emacs default | 269 | |-------------+----------------+---------------| 270 | | =Cmd-f= | Search in file | =C-s= | 271 | | =Cmd-r= | Visual replace | N/A | 272 | | =Cmd-Alt-f= | Visual replace | N/A | 273 | 274 | [[./screenshots/replace.png]] 275 | 276 | ** Editing 277 | 278 | *** Words and lines 279 | 280 | | Binding | Description | Emacs default | 281 | |-----------------+-------------------------------------------------+---------------| 282 | | =Cmd-RET= | New line below | N/A | 283 | | =Cmd-Shift-RET= | New line above | N/A | 284 | | =Cmd-/= | Comment line | =C-x C-;= | 285 | | =Cmd-j= | Join with next line or join all lines in region | N/A | 286 | | =Alt-u= | Upcase current word or region | =M-u (same)= | 287 | | =Alt-l= | Downcase current word or region | =M-l (same)= | 288 | | =Alt-c= | Capitalize word | =M-c (same)= | 289 | 290 | *** Deleting text 291 | 292 | | Binding | Description | Emacs default | 293 | |-----------------------+-----------------------+---------------| 294 | | =Alt-BACKSPACE= | Delete word backwards | N/A | 295 | | =Alt-Shift-BACKSPACE= | Delete word forwards | =M-d= | 296 | | =Cmd-BACKSPACE= | Delete current line | N/A | 297 | | =Ctrl-k= | Delete to end of line | =Ctrl-k= | 298 | | =Ctrl-d= | Delete character | =Ctrl-d= | 299 | 300 | 301 | *** Multiple cursors 302 | 303 | | Binding | Description | 304 | |---------------+-----------------------------------| 305 | | =Cmd-d= | Select next occurrence† | 306 | | =Cmd-Shift-d= | Select all occurrences | 307 | | =Alt-Cmd-d= | Add cursor to each line in region | 308 | 309 | † When no text is selected, =Cmd-d= adds new cursor to the next line. 310 | 311 | While multiple cursors are active: 312 | 313 | | Binding | Description | 314 | |----------------------+--------------------------------------------| 315 | | =C-g= or =ESC= | Quit multiple cursors mode | 316 | | =Ctrl-’= | Hide/show lines where cursors are active | 317 | | =Ctrl-v= and =Alt-v= | Scroll the screen to center on each cursor | 318 | 319 | Learn about all features of multiple cursors at https://github.com/magnars/multiple-cursors.el 320 | 321 | *** Indentation 322 | 323 | Emacs is pretty good at indenting stuff automatically. Pressing =TAB= on a line or region will indent it as needed. Castlemacs assumes that we never use tabs, only spaces, and use 2 spaces by default in most languages. 324 | 325 | | Binding | Description | 326 | |-----------+----------------------------------------------| 327 | | =TAB= | Indent current line or region correctly | 328 | | =C-x TAB= | Rigidly change indentation of line or region | 329 | 330 | 331 | *** Region 332 | 333 | Command with apostrophe expands selection. Holding shift contracts it. 334 | 335 | | Binding | Description | 336 | |---------------+-----------------| 337 | | =Cmd-’= | Expand region | 338 | | =Cmd-Shift-’= | Contract region | 339 | 340 | ** Window Management 341 | 342 | Note that in Emacs-talk, a pane is called a =window=. 343 | 344 | *** Splitting windows 345 | 346 | These bindings are based on default Emacs conventions, but save you one keypress. Also, =Cmd-w= closes current window just like a browser tab. 347 | 348 | | Binding | Description | Emacs default | 349 | |---------+---------------------+---------------| 350 | | =Cmd-1= | Kill other windows | =C-x 1= | 351 | | =Cmd-2= | Split horizontally | =C-x 2= | 352 | | =Cmd-3= | Split vertically | =C-x 3= | 353 | | =Cmd-0= | Kill current window | =C-x 0= | 354 | | =Cmd-w= | Kill current window | =C-x 0= | 355 | 356 | *** Moving between windows 357 | 358 | Move left and right just like in iTerm. Hold shift to make it up and down. 359 | 360 | | Binding | Description | Alternative | 361 | |---------------+-------------+------------------| 362 | | =Cmd-[= | Move left | =Ctrl-Cmd-LEFT= | 363 | | =Cmd-]= | Move right | =Ctrl-Cmd-RIGHT= | 364 | | =Cmd-Shift-[= | Move up | =Ctrl-Cmd-UP= | 365 | | =Cmd-Shift-]= | Move down | =Ctrl-Cmd-DOWN= | 366 | 367 | *** Restoring window configuration 368 | 369 | This is =winner-mode=. It captures the current window configuration and allows you to restore it after it gets changed by some Emacs action. 370 | 371 | | Binding | Description | Emacs default | 372 | |-------------+-----------------------------------------+---------------| 373 | | =Cmd-Alt-[= | Restore previous configuration | C-c LEFT | 374 | | =Cmd-Alt-]= | Go to next configuration (undo restore) | C-c RIGHT | 375 | 376 | ** Project Management 377 | 378 | 379 | Castlemacs uses [[https://github.com/bbatsov/projectile][Projectile]] for project management. There are a lot of features, and most of them are discoverable from the so-called "command map". 380 | 381 | | Binding | Description | Emacs default | 382 | |------------------+-----------------------------+---------------| 383 | | =Ctrl-Cmd-p= | Open projectile command map | =C-c p= | 384 | | =Ctrl-Cmd-p= =p= | Switch project | =C-c p p= | 385 | | =Cmd-p= | Find file in project | =C-c p f= | 386 | | =Cmd-Shift-f= | Search in project | =C-c p s s= | 387 | 388 | Note that 'Emacs default' doesn't make much sense in this context, since Projectile is not part of Emacs. I try to provide commonly used combinations for these cases: =C-c p= is what Projectile's author suggests, for example, and many configs follow this suggestion. 389 | 390 | While in search mode: 391 | 392 | | Binding | Description | 393 | |--------------+---------------------------| 394 | | =Ctrl-Alt-m= | Preview current file | 395 | | =Ctrl-Alt-n= | Next file and preview | 396 | | =Ctrl-Alt-p= | Previous file and preview | 397 | | =ESC= | Quit search | 398 | 399 | ** Git 400 | 401 | *** Git gutter 402 | 403 | Changes to the current file are shown in the gutter on left side. You can change the appearance of those symbols: search for =git-gutter= section in =init.el=. To see a list of all available colors run =Alt-x counsel-colors-emacs=. See [[https://github.com/syohex/emacs-git-gutter][Git-gutter docs]] for more info. 404 | 405 | [[./screenshots/git_gutter.png]] 406 | 407 | *** Magit 408 | 409 | Castlemacs uses [[https://magit.vc/][Magit]], a wonderful package that aspires to be a complete Git porcelain. 410 | 411 | | Binding | Description | 412 | |---------+--------------| 413 | | =Cmd-g= | Magit status | 414 | 415 | From this status window you can do everything. Here are the basic commands available within Magit status window: 416 | 417 | | Binding | Description | 418 | |---------+-----------------------------| 419 | | =s= | Stage current file or chunk | 420 | | =c= | Open commit window | 421 | | =F= | Open pull window | 422 | | =P= | Open push window | 423 | 424 | There are cheat sheets available within Magit. Refer to [[https://magit.vc/manual/][Magit User Manuals]] for more info. 425 | 426 | ** Terminal (shell) 427 | 428 | There is a toggleable popup shell which is actually a full blown terminal emulator (=ansi-term=). It uses your system default shell and loads the appropriate environment. 429 | 430 | | Binding | Description | 431 | |---------+--------------| 432 | | =Cmd-== | Toggle shell | 433 | 434 | ** File tree and open buffers 435 | 436 | | Binding | Description | 437 | |-----------------+----------------------------------------------| 438 | | =Cmd-b= | Switch to another buffer or open recent file | 439 | | =Cmd-Shift-b-== | Toggle filetree | 440 | 441 | ** Programming 442 | 443 | *** Languages and modes 444 | 445 | Emacs supports many programming languages by default. Castlemacs adds support for YAML, Markdown, Web mode (HTML, CSS, PHP, templating, etc), Emmet. 446 | 447 | Feel free to add more features by sending a PR or opening an issue. 448 | 449 | *** Code completion 450 | 451 | Code completion popup shows up immediately when possible. When popup is active: 452 | 453 | | Binding | Description | 454 | |-------------+-------------------------------------------| 455 | | =Enter= | Select current candidate | 456 | | =Alt-DIGIT= | Quickly complete with one of first 10 | 457 | | =TAB= | Complete common part | 458 | | =F1= | Show documentation for selected candidate | 459 | | =Ctrl-w= | Show source for selected candidate | 460 | | | | 461 | 462 | Note that not all backends support the last two commands. 463 | 464 | This feature is provided by Company mode package. Learn more about Company mode at http://company-mode.github.io/ 465 | 466 | *** Emmet 467 | 468 | | Binding | Description | 469 | |--------------------------+--------------| 470 | | =Ctrl-Enter= or =Ctrl-j= | Expand Emmet | 471 | 472 | Learn more about [[https://github.com/smihica/emmet-mode][emmet mode]]. 473 | 474 | ** Spellchecking, thesaurus, definition 475 | 476 | *** Spellchecking 477 | 478 | Spellchecking requires an external command to be available. See [[#install-dependencies][Install dependencies]]. 479 | 480 | | Binding | Description | Emacs default | 481 | |---------------+--------------------------------+---------------| 482 | | =Cmd-\= | Correct current word via popup | N/A | 483 | | =Cmd-Ctlr-\= | Correct current word via list | =M-$= | 484 | 485 | The last three lines in the popup allow to add current word to your personal dictionary or accept it as correct for current session (as long as Emacs is open) or current buffer. 486 | 487 | When correcting via list, you can press =i= to quickly add the word to your personal dictionary. 488 | 489 | Note that personal dictionary is located at =~/.aspell.LANG.pws= by default. 490 | 491 | *** Thesaurus 492 | 493 | You can quickly search for synonyms. This requires an internet connection since the package uses https://www.powerthesaurus.org/ as backend. 494 | 495 | | Binding | Description | 496 | |---------------+-------------------------------------| 497 | | =Cmd-Shift-\= | Search for synonyms of current word | 498 | 499 | Select a synonym and press =Enter= to replace word. 500 | 501 | [[./screenshots/thesaurus.png]] 502 | 503 | *** Word definition 504 | 505 | This requires an internet connection. 506 | 507 | | Binding | Description | 508 | |---------+---------------------| 509 | | =Alt-\= | Define current word | 510 | 511 | [[./screenshots/word_definition.png]] 512 | 513 | 514 | ** Org mode 515 | 516 | Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system. Learn more about Org at https://orgmode.org/. (Caution! This is a black hole!) 517 | 518 | Castlemacs provides some nice defaults: 519 | 520 | - Visually indent sections 521 | - Tab in source blocks acts like in corresponding major mode 522 | - Code highlighting works in code blocks 523 | - When TODO changes state, history goes to logbook 524 | - When TODO becomes DONE, current time and date are recorded 525 | - Shift selection with arrows work (unless you're in a spot where Org mode's default actions kick in) 526 | 527 | Put your org files in =~/org=. If you use Dropbox or similar cloud provider, I suggest storing your actual org folder there, and providing a symlink like so: 528 | 529 | #+BEGIN_SRC 530 | ln -s ~/Dropbox/Org ~/org 531 | #+END_SRC 532 | 533 | Org agenda looks inside all the files in =~/org= 534 | 535 | 536 | * Why this name? 537 | 538 | Castlemacs takes advantage of the heavily used Command key on macOS. The Command key icon ⌘ is a 'looped square': it's known as /the place of interest sign/ when used on information signs, a practice which started in Finland in the 1950s, spreading to the other Nordic countries in the 1960s. 539 | 540 | The symbol is derived from a shape of a castle. Here, for example, is the Borgholm Castle in Sweden: 541 | 542 | [[./images/borgholm-castle.jpg]] 543 | 544 | [[./images/roadsign.jpg]] 545 | -------------------------------------------------------------------------------- /custom.el: -------------------------------------------------------------------------------- 1 | ;; This file is used for the built-in customization UI in Emacs (M-x customize) 2 | ;; This file will not be affected by Castlemacs updates 3 | -------------------------------------------------------------------------------- /early-init-private.el: -------------------------------------------------------------------------------- 1 | ;; This is your private configuration file for pre-init things. It is loaded automatically, so feel free to add whatever you want. 2 | ;; This file will not be affected by Castlemacs updates. 3 | -------------------------------------------------------------------------------- /early-init.el: -------------------------------------------------------------------------------- 1 | ;; For Emacs 27 and above 2 | (setq package-enable-at-startup nil) 3 | -------------------------------------------------------------------------------- /images/borgholm-castle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freetonik/castlemacs/2b86de744d3af2f35a34293166c166d12ce8ee22/images/borgholm-castle.jpg -------------------------------------------------------------------------------- /images/roadsign.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freetonik/castlemacs/2b86de744d3af2f35a34293166c166d12ce8ee22/images/roadsign.jpg -------------------------------------------------------------------------------- /init.el: -------------------------------------------------------------------------------- 1 | ;;; -*- lexical-binding: t -*- 2 | 3 | 4 | ;; ==== 5 | ;; INIT 6 | 7 | 8 | ;; Package system and sources. 9 | (require 'package) 10 | (let* ((no-ssl (and (memq system-type '(windows-nt ms-dos)) 11 | (not (gnutls-available-p)))) 12 | (proto (if no-ssl "http" "https"))) 13 | ;; Comment/uncomment these two lines to enable/disable MELPA and MELPA Stable as desired 14 | (add-to-list 'package-archives (cons "melpa" (concat proto "://melpa.org/packages/")) t) 15 | ;;(add-to-list 'package-archives (cons "melpa-stable" (concat proto "://stable.melpa.org/packages/")) t) 16 | (when (< emacs-major-version 24) 17 | ;; For important compatibility libraries like cl-lib 18 | (add-to-list 'package-archives '("gnu" . (concat proto "://elpa.gnu.org/packages/"))))) 19 | 20 | (package-initialize) 21 | 22 | 23 | ;; We will use 'use-package' to install and configure packages. 24 | (unless (package-installed-p 'use-package) 25 | (package-refresh-contents) 26 | (package-install 'use-package)) 27 | (eval-when-compile (require 'use-package)) 28 | 29 | 30 | ;; No need to out 'ensure' everywhere, since we don't use anything else to install packages. 31 | (setq use-package-always-ensure t) 32 | 33 | 34 | ;; Pass system shell environment to Emacs. This is important primarily for shell inside Emacs, but also things like Org mode export to Tex PDF don't work, since it relies on running external command pdflatex, which is loaded from PATH. 35 | (use-package exec-path-from-shell 36 | :ensure t) 37 | (when (memq window-system '(mac ns)) 38 | (exec-path-from-shell-initialize)) 39 | 40 | 41 | ;; Store custom-file separately, don't freak out when it's not found 42 | (setq custom-file "~/.emacs.d/custom.el") 43 | (load custom-file 'noerror) 44 | 45 | 46 | ;; Set path for private config. private.el is not part of Castlemacs and you can use it for your personal 47 | ;; additions. Do not change init.el yourself, it will make updates harder. 48 | (add-hook 49 | 'after-init-hook 50 | (lambda () 51 | (let ((private-file (concat user-emacs-directory "private.el"))) 52 | (when (file-exists-p private-file) 53 | (load-file private-file))))) 54 | 55 | 56 | ;; ============= 57 | ;; MODIFIER KEYS 58 | 59 | 60 | ;; Both command keys are 'Super' 61 | (setq mac-right-command-modifier 'super) 62 | (setq mac-command-modifier 'super) 63 | 64 | 65 | ;; Option or Alt is naturally 'Meta' 66 | (setq mac-option-modifier 'meta) 67 | 68 | 69 | ;; Right Alt (option) can be used to enter symbols like em dashes '—' and euros '€' and stuff. 70 | (setq mac-right-option-modifier 'nil) 71 | 72 | ;; Control is control, and you also need to change Caps Lock to Control in the Keyboard 73 | ;; preferences in macOS. 74 | 75 | 76 | ;; ============= 77 | ;; SANE DEFAULTS 78 | 79 | 80 | ;; Smoother and nicer scrolling 81 | (setq scroll-margin 10 82 | scroll-step 1 83 | next-line-add-newlines nil 84 | scroll-conservatively 10000 85 | scroll-preserve-screen-position 1) 86 | 87 | (setq mouse-wheel-follow-mouse 't) 88 | (setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) 89 | 90 | 91 | ;; Use ESC as universal get me out of here command 92 | (define-key key-translation-map (kbd "ESC") (kbd "C-g")) 93 | 94 | 95 | ;; Don't bother with auto save and backups. 96 | (setq auto-save-default nil) 97 | (setq make-backup-files nil) 98 | 99 | 100 | ;; Warn only when opening files bigger than 100MB 101 | (setq large-file-warning-threshold 100000000) 102 | 103 | 104 | ;; Move file to trash instead of removing. 105 | (setq-default delete-by-moving-to-trash t) 106 | 107 | 108 | ;; Revert (update) buffers automatically when underlying files are changed externally. 109 | (global-auto-revert-mode t) 110 | 111 | (setq 112 | inhibit-startup-message t ; Don't show the startup message... 113 | inhibit-startup-screen t ; ... or screen 114 | cursor-in-non-selected-windows t ; Hide the cursor in inactive windows 115 | 116 | echo-keystrokes 0.1 ; Show keystrokes right away, don't show the message in the scratch buffer 117 | initial-scratch-message nil ; Empty scratch buffer 118 | initial-major-mode 'org-mode ; Org mode by default 119 | sentence-end-double-space nil ; Sentences should end in one space, come on! 120 | confirm-kill-emacs 'y-or-n-p ; y and n instead of yes and no when quitting 121 | help-window-select t ; Select help window so it's easy to quit it with 'q' 122 | ) 123 | 124 | (fset 'yes-or-no-p 'y-or-n-p) ; y and n instead of yes and no everywhere else 125 | (delete-selection-mode 1) ; Delete selected text when typing 126 | (global-unset-key (kbd "s-p")) ; Don't print 127 | 128 | 129 | ;; We need Emacs kill ring and system clipboard to be independent. Simpleclip is the solution to that. 130 | (use-package simpleclip 131 | :config 132 | (simpleclip-mode 1)) 133 | 134 | 135 | ;; Things you'd expect from macOS app. 136 | (global-set-key (kbd "s-s") 'save-buffer) ;; save 137 | (global-set-key (kbd "s-S") 'write-file) ;; save as 138 | (global-set-key (kbd "s-q") 'save-buffers-kill-emacs) ;; quit 139 | (global-set-key (kbd "s-a") 'mark-whole-buffer) ;; select all 140 | ;; (global-set-key (kbd "s-z") 'undo) 141 | 142 | 143 | ;; Delete trailing spaces and add new line in the end of a file on save. 144 | (add-hook 'before-save-hook 'delete-trailing-whitespace) 145 | (setq require-final-newline t) 146 | 147 | 148 | ;; Linear undo and redo. 149 | (use-package undo-fu) 150 | (global-set-key (kbd "s-z") 'undo-fu-only-undo) 151 | (global-set-key (kbd "s-Z") 'undo-fu-only-redo) 152 | 153 | 154 | ;; ======= 155 | ;; VISUALS 156 | 157 | 158 | ;; Enable transparent title bar on macOS 159 | (when (memq window-system '(mac ns)) 160 | (add-to-list 'default-frame-alist '(ns-appearance . light)) ;; {light, dark} 161 | (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))) 162 | 163 | 164 | ;; Font 165 | (when (member "menlo" (font-family-list)) 166 | (set-face-attribute 'default nil :font "Menlo 15")) 167 | (setq-default line-spacing 2) 168 | 169 | 170 | ;; Nice and simple default light theme. 171 | (load-theme 'tsdh-light) 172 | 173 | 174 | ;; Pretty icons 175 | (use-package all-the-icons) 176 | ;; MUST DO M-x all-the-icons-install-fonts after 177 | 178 | 179 | ;; Hide toolbar and scroll bar 180 | (tool-bar-mode -1) 181 | (scroll-bar-mode -1) 182 | 183 | 184 | ;; Always wrap lines 185 | (global-visual-line-mode 1) 186 | 187 | 188 | ;; Highlight current line 189 | (global-hl-line-mode 1) 190 | 191 | 192 | ;; Show parens and other pairs. 193 | (use-package smartparens 194 | :diminish 195 | :config 196 | (require 'smartparens-config) 197 | (smartparens-global-mode t) 198 | (show-smartparens-global-mode t)) 199 | 200 | 201 | ;; Hide minor modes from modeline 202 | (use-package rich-minority 203 | :config 204 | (rich-minority-mode 1) 205 | (setf rm-blacklist "")) 206 | 207 | 208 | ;; Set colors to distinguish between active and inactive windows 209 | (set-face-attribute 'mode-line nil :background "SlateGray1") 210 | (set-face-attribute 'mode-line-inactive nil :background "grey93") 211 | 212 | 213 | ;; File tree 214 | (use-package neotree 215 | :config 216 | (setq neo-window-width 32 217 | neo-create-file-auto-open t 218 | neo-banner-message nil 219 | neo-show-updir-line t 220 | neo-window-fixed-size nil 221 | neo-vc-integration nil 222 | neo-mode-line-type 'neotree 223 | neo-smart-open t 224 | neo-show-hidden-files t 225 | neo-mode-line-type 'none 226 | neo-auto-indent-point t) 227 | (setq neo-theme (if (display-graphic-p) 'nerd 'arrow)) 228 | (setq neo-hidden-regexp-list '("venv" "\\.pyc$" "~$" "\\.git" "__pycache__" ".DS_Store")) 229 | (global-set-key (kbd "s-B") 'neotree-toggle)) ;; Cmd+Shift+b toggle tree 230 | 231 | 232 | ;; Show vi-like tilde in the fringe on empty lines. 233 | (use-package vi-tilde-fringe 234 | :config 235 | (global-vi-tilde-fringe-mode 1)) 236 | 237 | 238 | ;; Show full path in the title bar. 239 | (setq-default frame-title-format "%b (%f)") 240 | 241 | 242 | ;; Never use tabs, use spaces instead. 243 | (setq tab-width 2) 244 | (setq js-indent-level 2) 245 | (setq css-indent-offset 2) 246 | (setq c-basic-offset 2) 247 | (setq-default indent-tabs-mode nil) 248 | (setq-default c-basic-offset 2) 249 | (setq-default tab-width 2) 250 | (setq-default c-basic-indent 2) 251 | 252 | 253 | ;; Show keybindings cheatsheet 254 | (use-package which-key 255 | :config 256 | (which-key-mode) 257 | (setq which-key-idle-delay 0.5)) 258 | 259 | 260 | ;; Disable blinking cursor. 261 | (blink-cursor-mode 0) 262 | 263 | 264 | ;; ================ 265 | ;; BASIC NAVIGATION 266 | 267 | 268 | ;; Move around with Cmd+i/j/k/l. This is not for everybody, and it takes away four very well placed 269 | ;; key combinations, but if you get used to using these keys instead of arrows, it will be worth it, 270 | ;; I promise. 271 | (global-set-key (kbd "s-i") 'previous-line) 272 | (global-set-key (kbd "s-k") 'next-line) 273 | (global-set-key (kbd "s-j") 'left-char) 274 | (global-set-key (kbd "s-l") 'right-char) 275 | 276 | 277 | ;; Kill line with CMD-Backspace. Note that thanks to Simpleclip, killing doesn't rewrite the system clipboard. 278 | ;; Kill one word with Alt+Backspace. 279 | ;; Kill forward word with Alt-Shift-Backspace. 280 | (global-set-key (kbd "s-") 'kill-whole-line) 281 | (global-set-key (kbd "M-S-") 'kill-word) 282 | 283 | 284 | ;; Use Cmd for movement and selection. 285 | (global-set-key (kbd "s-") (kbd "C-e")) ;; End of line 286 | (global-set-key (kbd "S-s-") (kbd "C-S-e")) ;; Select to end of line 287 | (global-set-key (kbd "s-") (kbd "M-m")) ;; Beginning of line (first non-whitespace character) 288 | (global-set-key (kbd "S-s-") (kbd "M-S-m")) ;; Select to beginning of line 289 | 290 | (global-set-key (kbd "s-") 'beginning-of-buffer) ;; First line 291 | (global-set-key (kbd "s-") 'end-of-buffer) ;; Last line 292 | 293 | 294 | ;; Thanks to Bozhidar Batsov 295 | ;; http://emacsredux.com/blog/2013/]05/22/smarter-navigation-to-the-beginning-of-a-line/ 296 | (defun smarter-move-beginning-of-line (arg) 297 | "Move point back to indentation of beginning of line. 298 | 299 | Move point to the first non-whitespace character on this line. 300 | If point is already there, move to the beginning of the line. 301 | Effectively toggle between the first non-whitespace character and 302 | the beginning of the line. 303 | 304 | If ARG is not nil or 1, move forward ARG - 1 lines first. If 305 | point reaches the beginning or end of the buffer, stop there." 306 | (interactive "^p") 307 | (setq arg (or arg 1)) 308 | 309 | ;; Move lines first 310 | (when (/= arg 1) 311 | (let ((line-move-visual nil)) 312 | (forward-line (1- arg)))) 313 | 314 | (let ((orig-point (point))) 315 | (back-to-indentation) 316 | (when (= orig-point (point)) 317 | (move-beginning-of-line 1)))) 318 | 319 | (global-set-key (kbd "C-a") 'smarter-move-beginning-of-line) 320 | (global-set-key (kbd "s-") 'smarter-move-beginning-of-line) 321 | 322 | 323 | ;; Many commands in Emacs write the current position into mark ring. 324 | ;; These custom functions allow for quick movement backward and forward. 325 | ;; For example, if you were editing line 6, then did a search with Cmd+f, did something and want to come back, 326 | ;; press Cmd+, to go back to line 6. Cmd+. to go forward. 327 | ;; These keys are chosen because they are the same buttons as < and >, think of them as arrows. 328 | (defun my-pop-local-mark-ring () 329 | (interactive) 330 | (set-mark-command t)) 331 | 332 | (defun unpop-to-mark-command () 333 | "Unpop off mark ring. Does nothing if mark ring is empty." 334 | (interactive) 335 | (when mark-ring 336 | (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring)) 337 | (set-marker (mark-marker) (car (last mark-ring)) (current-buffer)) 338 | (when (null (mark t)) (ding)) 339 | (setq mark-ring (nbutlast mark-ring)) 340 | (goto-char (marker-position (car (last mark-ring)))))) 341 | 342 | (global-set-key (kbd "s-,") 'my-pop-local-mark-ring) 343 | (global-set-key (kbd "s-.") 'unpop-to-mark-command) 344 | 345 | 346 | ;; Same keys with Shift will move you back and forward between open buffers. 347 | (global-set-key (kbd "s-<") 'previous-buffer) 348 | (global-set-key (kbd "s->") 'next-buffer) 349 | 350 | 351 | ;; ============ 352 | ;; TEXT EDITING 353 | 354 | 355 | ;; Expand-region allows to gradually expand selection inside words, sentences, expressions, etc. 356 | (use-package expand-region 357 | :config 358 | (global-set-key (kbd "s-'") 'er/expand-region) ;; Cmd+' (apostrophe) to expand 359 | (global-set-key (kbd "s-\"") 'er/contract-region)) ;; Cmd+" (same, but with shift) to contract 360 | 361 | 362 | ;; Move-text lines around with meta-up/down. 363 | (use-package move-text 364 | :config 365 | (move-text-default-bindings)) 366 | 367 | 368 | ;; Quickly insert new lines above or below the current line, with correct indentation. 369 | (defun smart-open-line () 370 | "Insert an empty line after the current line. Position the cursor at its beginning, according to the current mode." 371 | (interactive) 372 | (move-end-of-line nil) 373 | (newline-and-indent)) 374 | 375 | (defun smart-open-line-above () 376 | "Insert an empty line above the current line. Position the cursor at it's beginning, according to the current mode." 377 | (interactive) 378 | (move-beginning-of-line nil) 379 | (newline-and-indent) 380 | (forward-line -1) 381 | (indent-according-to-mode)) 382 | 383 | (global-set-key (kbd "s-") 'smart-open-line) ;; Cmd+Return new line below 384 | (global-set-key (kbd "s-S-") 'smart-open-line-above) ;; Cmd+Shift+Return new line above 385 | 386 | 387 | ;; Upcase and lowercase word or region, if selected. 388 | ;; To capitalize or un-capitalize word use Alt+c and Alt+l 389 | (global-set-key (kbd "M-u") 'upcase-dwim) ;; Alt+u upcase 390 | (global-set-key (kbd "M-l") 'downcase-dwim) ;; Alt-l lowercase 391 | 392 | 393 | ;; Comment line or region. 394 | (global-set-key (kbd "s-/") 'comment-line) 395 | 396 | 397 | ;; Visually find and replace text 398 | (use-package visual-regexp 399 | :config 400 | (define-key global-map (kbd "M-s-f") 'vr/replace) 401 | (define-key global-map (kbd "s-r") 'vr/replace)) ;; Cmd+r find and replace 402 | 403 | 404 | ;; Multiple cursors. Similar to Sublime or VS Code. 405 | (use-package multiple-cursors 406 | :config 407 | (setq mc/always-run-for-all 1) 408 | (global-set-key (kbd "s-d") 'mc/mark-next-like-this) ;; Cmd+d select next occurrence of region 409 | (global-set-key (kbd "s-D") 'mc/mark-all-dwim) ;; Cmd+Shift+d select all occurrences 410 | (global-set-key (kbd "M-s-d") 'mc/edit-beginnings-of-lines) ;; Alt+Cmd+d add cursor to each line in region 411 | (define-key mc/keymap (kbd "") nil)) 412 | 413 | 414 | ;; ================= 415 | ;; WINDOW MANAGEMENT 416 | 417 | 418 | ;; This is rather radical, but saves from a lot of pain in the ass. 419 | ;; When split is automatic, always split windows vertically 420 | (setq split-height-threshold 0) 421 | (setq split-width-threshold nil) 422 | 423 | 424 | ;; Go to other windows easily with one keystroke Cmd-something. 425 | (global-set-key (kbd "s-1") (kbd "C-x 1")) ;; Cmd-1 kill other windows (keep 1) 426 | (global-set-key (kbd "s-2") (kbd "C-x 2")) ;; Cmd-2 split horizontally 427 | (global-set-key (kbd "s-3") (kbd "C-x 3")) ;; Cmd-3 split vertically 428 | (global-set-key (kbd "s-0") (kbd "C-x 0")) ;; Cmd-0... 429 | (global-set-key (kbd "s-w") (kbd "C-x 0")) ;; ...and Cmd-w to close current window 430 | 431 | 432 | ;; Move between windows with Control-Command-Arrow and with =Cmd= just like in iTerm. 433 | (use-package windmove 434 | :config 435 | (global-set-key (kbd "") 'windmove-left) ;; Ctrl+Cmd+left go to left window 436 | (global-set-key (kbd "s-[") 'windmove-left) ;; Cmd+[ go to left window 437 | 438 | (global-set-key (kbd "") 'windmove-right) ;; Ctrl+Cmd+right go to right window 439 | (global-set-key (kbd "s-]") 'windmove-right) ;; Cmd+] go to right window 440 | 441 | (global-set-key (kbd "") 'windmove-up) ;; Ctrl+Cmd+up go to upper window 442 | (global-set-key (kbd "s-{") 'windmove-up) ;; Cmd+Shift+[ go to upper window 443 | 444 | (global-set-key (kbd "") 'windmove-down) ;; Ctrl+Cmd+down go to down window 445 | (global-set-key (kbd "s-}") 'windmove-down)) ;; Cmd+Shift+] got to down window 446 | 447 | 448 | ;; Enable winner mode to quickly restore window configurations 449 | (winner-mode 1) 450 | (global-set-key (kbd "M-s-[") 'winner-undo) 451 | (global-set-key (kbd "M-s-]") 'winner-redo) 452 | 453 | 454 | ;; ================== 455 | ;; PROJECT MANAGEMENT 456 | 457 | 458 | ;; Use Projectile for project management. 459 | (use-package projectile 460 | :config 461 | (define-key projectile-mode-map (kbd "C-s-p") 'projectile-command-map) ;; Ctrl+Cmd+p show projectile menu 462 | (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map) 463 | (projectile-mode +1) 464 | ) 465 | 466 | 467 | ;; ========================================== 468 | ;; MENUS AND COMPLETION (not code completion) 469 | 470 | 471 | ;; Use minimalist Ivy for most things. 472 | (use-package ivy 473 | :diminish ;; don't show Ivy in minor mode list 474 | :config 475 | (ivy-mode 1) ;; enable Ivy everywhere 476 | (setq ivy-use-virtual-buffers t) ;; show bookmarks and recent files in buffer list 477 | (setq ivy-count-format "(%d/%d) ") 478 | (setq enable-recursive-minibuffers t) 479 | 480 | (setq ivy-re-builders-alist 481 | '((swiper . ivy--regex-plus) 482 | (t . ivy--regex-fuzzy))) ;; enable fuzzy searching everywhere except for Swiper 483 | 484 | (global-set-key (kbd "s-b") 'ivy-switch-buffer) ;; Cmd+b show buffers and recent files 485 | (global-set-key (kbd "M-s-b") 'ivy-resume)) ;; Alt+Cmd+b resume whatever Ivy was doing 486 | 487 | 488 | ;; Swiper is a better local finder. 489 | (use-package swiper 490 | :config 491 | (global-set-key "\C-s" 'swiper) ;; Default Emacs Isearch forward... 492 | (global-set-key "\C-r" 'swiper) ;; ... and Isearch backward replaced with Swiper 493 | (global-set-key (kbd "s-f") 'swiper)) ;; Cmd+f find text 494 | 495 | 496 | ;; Better menus with Counsel (a layer on top of Ivy) 497 | (use-package counsel 498 | :config 499 | (global-set-key (kbd "M-x") 'counsel-M-x) ;; Alt+x run command 500 | (global-set-key (kbd "s-P") 'counsel-M-x) ;; Cmd+Shift+p run command 501 | (global-set-key (kbd "C-x C-f") 'counsel-find-file) ;; Replace built-in Emacs 'find file' (open file) with Counsel 502 | (global-set-key (kbd "s-o") 'counsel-find-file)) ;; Cmd+o open file 503 | 504 | (use-package smex) ;; show recent commands when invoking Alt-x (or Cmd+Shift+p) 505 | (use-package flx) ;; enable fuzzy matching 506 | (use-package avy) ;; enable avy for quick navigation 507 | 508 | 509 | ;; Make Ivy a bit more friendly by adding information to ivy buffers, e.g. description of commands in Alt-x, meta info when switching buffers, etc. 510 | (use-package ivy-rich 511 | :config 512 | (ivy-rich-mode 1) 513 | (setq ivy-rich-path-style 'abbrev)) ;; Abbreviate paths using abbreviate-file-name (e.g. replace “/home/username” with “~”) 514 | 515 | 516 | ;; Integrate Projectile with Counsel 517 | (use-package counsel-projectile 518 | :config 519 | (counsel-projectile-mode 1) 520 | (global-set-key (kbd "C-x C-f") 'counsel-find-file) 521 | (global-set-key (kbd "s-p") 'counsel-projectile-find-file) ;; Cmd+p open file in current project 522 | (global-set-key (kbd "s-F") 'counsel-projectile-rg)) ;; Cmd+Shift+F search in current git repository 523 | 524 | 525 | (setq projectile-completion-system 'ivy) ;; Use Ivy in Projectile 526 | 527 | 528 | ;; ======================== 529 | ;; VERSION CONTROL WITH GIT 530 | 531 | 532 | ;; Magit 533 | (use-package magit 534 | :config 535 | (global-set-key (kbd "s-g") 'magit-status)) ;; Cmd+g for git status 536 | 537 | 538 | ;; Show changes in the gutter 539 | (use-package git-gutter 540 | :diminish 541 | :config 542 | (global-git-gutter-mode 't) 543 | (set-face-background 'git-gutter:modified 'nil) ;; background color 544 | (set-face-foreground 'git-gutter:added "green4") 545 | (set-face-foreground 'git-gutter:deleted "red")) 546 | 547 | 548 | ;; ======== 549 | ;; TERMINAL 550 | 551 | 552 | (use-package shell-pop 553 | :config 554 | (custom-set-variables 555 | '(shell-pop-shell-type (quote ("ansi-term" "*ansi-term*" (lambda nil (ansi-term shell-pop-term-shell))))) 556 | '(shell-pop-universal-key "s-="))) 557 | 558 | 559 | ;; =============== 560 | ;; CODE COMPLETION 561 | 562 | 563 | (use-package company 564 | :config 565 | (setq company-idle-delay 0.1) 566 | (setq company-global-modes '(not org-mode)) 567 | (setq company-minimum-prefix-length 1) 568 | (add-hook 'after-init-hook 'global-company-mode)) 569 | 570 | 571 | ;; Set the company completion vocabulary to css and html when in web-mode. 572 | (defun my-web-mode-hook () 573 | (set (make-local-variable 'company-backends) '(company-css company-web-html company-yasnippet company-files))) 574 | 575 | 576 | ;; =========================== 577 | ;; SPELLCHECKING AND THESAURUS 578 | 579 | 580 | ;; Spellchecking requires an external command to be available. Install aspell on your Mac, then make it the default checker for Emacs' ispell. Note that personal dictionary is located at ~/.aspell.LANG.pws by default. 581 | (setq ispell-program-name "aspell") 582 | 583 | 584 | ;; Popup window for spellchecking 585 | (use-package flyspell-correct) 586 | (use-package flyspell-correct-popup) 587 | 588 | 589 | ;; Enable spellcheck on the fly for all text modes. This includes org, latex and LaTeX. 590 | (add-hook 'text-mode-hook 'flyspell-mode) 591 | (add-hook 'prog-mode-hook 'flyspell-prog-mode) 592 | 593 | 594 | ;; Enable right mouse click on macOS to see the list of suggestions. 595 | (eval-after-load "flyspell" 596 | '(progn 597 | (define-key flyspell-mouse-map [down-mouse-3] #'flyspell-correct-word) 598 | (define-key flyspell-mouse-map [mouse-3] #'undefined))) 599 | 600 | 601 | ;; Spellcheck current word 602 | (define-key flyspell-mode-map (kbd "s-\\") 'flyspell-correct-previous-word-generic) ;; Cmd+\ spellcheck word with popup 603 | (define-key flyspell-mode-map (kbd "C-s-\\") 'ispell-word) ;; Ctrl+Cmd+\ spellcheck word using built UI 604 | 605 | 606 | ;; Search for synonyms 607 | (use-package powerthesaurus 608 | :config 609 | (global-set-key (kbd "s-|") 'powerthesaurus-lookup-word-dwim)) ;; Cmd+Shift+\ search thesaurus 610 | 611 | 612 | ;; Word definition search 613 | (use-package define-word 614 | :config 615 | (global-set-key (kbd "M-\\") 'define-word-at-point)) 616 | 617 | 618 | ;; =========== 619 | ;; PROGRAMMING 620 | 621 | 622 | (use-package yaml-mode) 623 | (use-package haml-mode) 624 | (use-package markdown-mode) 625 | 626 | 627 | ;; Web-mode is an autonomous emacs major-mode for editing web templates. 628 | ;; HTML documents can embed parts (CSS / JavaScript) and blocks (client / server side). 629 | (use-package web-mode 630 | :config 631 | (setq web-mode-markup-indent-offset 2) 632 | (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode)) 633 | (add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode)) 634 | (add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode)) 635 | (add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode)) 636 | (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode)) 637 | (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode)) 638 | (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)) 639 | (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)) 640 | (add-to-list 'auto-mode-alist '("\\.js?\\'" . web-mode)) 641 | (add-to-list 'auto-mode-alist '("\\.css?\\'" . web-mode)) 642 | (add-to-list 'auto-mode-alist '("\\.xml?\\'" . web-mode))) 643 | 644 | 645 | ;; Emmet 646 | (use-package emmet-mode 647 | :commands emmet-mode 648 | :init 649 | (setq emmet-indentation 2) 650 | (setq emmet-move-cursor-between-quotes t) 651 | :config 652 | (add-hook 'sgml-mode-hook 'emmet-mode) ;; Auto-start on any markup modes 653 | (add-hook 'css-mode-hook 'emmet-mode)) ;; enable Emmet's css abbreviation. 654 | ;; Ctrl+j or Ctrl+Enter to expand 655 | 656 | 657 | ;; ======== 658 | ;; ORG MODE 659 | 660 | 661 | ;; Some basic Org defaults 662 | (use-package org 663 | :config 664 | (setq org-startup-indented t) ;; Visually indent sections. This looks better for smaller files. 665 | (setq org-src-tab-acts-natively t) ;; Tab in source blocks should act like in major mode 666 | (setq org-src-preserve-indentation t) 667 | (setq org-log-into-drawer t) ;; State changes for todos and also notes should go into a Logbook drawer 668 | (setq org-src-fontify-natively t) ;; Code highlighting in code blocks 669 | (setq org-log-done 'time) ;; Add closed date when todo goes to DONE state 670 | (setq org-support-shift-select t)) ;; Allow shift selection with arrows. 671 | 672 | 673 | ;; Store all my org files in ~/org. 674 | (setq org-directory "~/org") 675 | 676 | 677 | ;; And all of those files should be in included agenda. 678 | (setq org-agenda-files '("~/org")) 679 | 680 | 681 | ;; Open config file by pressing C-x and then C 682 | (global-set-key (kbd "C-x C") (lambda () (interactive) (find-file "~/.emacs.d/init.el"))) 683 | 684 | ;; Open private config file by pressing C-x and then c 685 | ;; Contain custom settings to private.el to ensure easy Castlemacs updates. 686 | (global-set-key (kbd "C-x c") (lambda () (interactive) (find-file "~/.emacs.d/private.el"))) 687 | 688 | ;; ======= 689 | ;; THE END 690 | -------------------------------------------------------------------------------- /private.el: -------------------------------------------------------------------------------- 1 | ;; This is your private configuration file. It is loaded automatically, so feel free to add whatever you want. 2 | ;; This file will not be affected by Castlemacs updates. 3 | -------------------------------------------------------------------------------- /screenshots/git_gutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freetonik/castlemacs/2b86de744d3af2f35a34293166c166d12ce8ee22/screenshots/git_gutter.png -------------------------------------------------------------------------------- /screenshots/magit_spellcheck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freetonik/castlemacs/2b86de744d3af2f35a34293166c166d12ce8ee22/screenshots/magit_spellcheck.png -------------------------------------------------------------------------------- /screenshots/main2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freetonik/castlemacs/2b86de744d3af2f35a34293166c166d12ce8ee22/screenshots/main2.png -------------------------------------------------------------------------------- /screenshots/replace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freetonik/castlemacs/2b86de744d3af2f35a34293166c166d12ce8ee22/screenshots/replace.png -------------------------------------------------------------------------------- /screenshots/thesaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freetonik/castlemacs/2b86de744d3af2f35a34293166c166d12ce8ee22/screenshots/thesaurus.png -------------------------------------------------------------------------------- /screenshots/word_definition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freetonik/castlemacs/2b86de744d3af2f35a34293166c166d12ce8ee22/screenshots/word_definition.png --------------------------------------------------------------------------------