Compare commits

...

275 Commits

Author SHA1 Message Date
Zachary Yedidia
be8124154b Re-add literate supportg 2017-05-27 17:16:21 -04:00
Zachary Yedidia
f086cc8713 Temporarily remove literate folder 2017-05-27 17:14:22 -04:00
Zachary Yedidia
624daabc02 Add support for zyedidia/Literate 2017-05-27 16:55:59 -04:00
Zachary Yedidia
05a187e470 Update runtime 2017-05-27 16:38:03 -04:00
Zachary Yedidia
53da1ff1fe Merge pull request #680 from tommyshem/kotlin
Added kotlin highlighting and fixed swift line comment todo not highlighting
2017-05-27 16:32:32 -04:00
tommy
112c731c7a Added kotlin highlighting and fixed swift line comment todo not highlighting. 2017-05-26 01:59:51 +01:00
Zachary Yedidia
6cf6857602 Add comment 2017-05-22 11:21:17 -04:00
Zachary Yedidia
97e2fb1288 Use messenger error instead of termerror 2017-05-21 10:46:06 -04:00
Zachary Yedidia
d1e70b5abf Add suspend for linux only 2017-05-21 10:44:33 -04:00
Zachary Yedidia
a70fb9db7d Test suspend code 2017-05-21 10:30:26 -04:00
Zachary Yedidia
285503d009 Merge 2017-05-21 10:19:13 -04:00
Zachary Yedidia
f364965ac0 Create ftoptions option to disable auto settings
Closes #662
2017-05-19 18:17:38 -04:00
Zachary Yedidia
61cea4624e Merge pull request #675 from benjamreynolds/patch-1
Cleanup from merge conflicts in syntax/README
2017-05-19 16:25:59 -04:00
Benjamin Reynolds
2899e47591 Cleanup from merge conflicts in syntax/README 2017-05-19 12:33:41 -05:00
Zachary Yedidia
e7ee194acf Merge 2017-05-17 12:13:24 -04:00
Zachary Yedidia
6e5536eae9 Load colorscheme after loading plugins
Fixes #671
2017-05-17 12:12:58 -04:00
Zachary Yedidia
5514e53a0b Merge pull request #665 from tommyshem/viewtype-check
before saving check for view type and if scratch is true then do not save
2017-05-15 15:46:35 -04:00
tommy
d8dee90c10 check viewtype before saving and if scratch is true then do not save 2017-05-15 20:00:58 +01:00
Zachary Yedidia
dcee63771a Merge 2017-05-14 10:27:37 -04:00
Zachary Yedidia
b7133b302b Don't remember path on save if it is invalid
Fixes #656
2017-05-14 10:27:15 -04:00
Zachary Yedidia
061040f5d9 Merge pull request #661 from aerth/indentchar
use space for indentchar if empty, fixes #660
2017-05-12 21:15:19 -04:00
aerth
f6ccaadc0c use space for indentchar if empty, fixes #660 2017-05-12 16:32:24 -07:00
Tommy
7c80de7ee1 Caps lock issue#658 (#659)
* caps-lock-issue #658

* when esc key is pressed the message is cleared away
2017-05-10 10:02:17 -04:00
Zachary Yedidia
ef0f506b6f Allow upper case in 'Save changes' prompt
Fixes #658
2017-05-09 14:46:23 -04:00
Zachary Yedidia
3d63f0771a Merge pull request #654 from tommyshem/swift-linux-support
added swift linting to linux
2017-05-08 13:18:18 -04:00
tommy
20ad87611f added swift linting to linux 2017-05-08 17:14:33 +01:00
Zachary Yedidia
fa7839e287 Merge pull request #653 from Necklaces/master
Added ShiftHome + ShiftEnd to keybindings.md documentation
2017-05-07 11:20:49 -04:00
Nichlas Severinsen
2aec2c13b5 Added ShiftHome + ShiftEnd to keybindings.md documentation 2017-05-07 13:19:58 +02:00
Tommy
3eb0d71bd3 Updated swift syntax yaml file as missing keywords and some highlighting not working correctly. (#644)
* Updated the keywords and micros

* updated keywords  and  interpolation and unicode added to string

* add test swift file

* Delete swift-test.swift

delete swift test file
2017-05-05 15:14:50 -04:00
Zachary Yedidia
18f9b6f34e Add tabmovement option
This option makes micro treat spaces at the beginning of lines as if
they are tabs. This option only does anything if tabstospaces is already
on. E.g. micro will move over 4 spaces at once when at the start of a
line.

Closes #616
2017-05-05 12:04:18 -04:00
Zachary Yedidia
57110c98e4 Fix rare problem with tabs and horizontal scrolling 2017-05-05 11:34:14 -04:00
Zachary Yedidia
a6ee75a9cf Add SaveAll command and display + for modified tabs
Closes #651
2017-05-05 11:05:23 -04:00
Zachary Yedidia
8d1618692e Disallow view switching during a search
Closes #642

This commit also removes some unnecessary functions that weren't being
used.
2017-05-05 10:52:09 -04:00
Zachary Yedidia
960c6cae62 Properly draw split divider 2017-05-05 10:40:49 -04:00
Zachary Yedidia
67ec0d3c80 Correctly detect synatx ft from header 2017-05-03 11:04:56 -04:00
Zachary Yedidia
d3f32b5bc3 If softwrap is on the leftcol must be 0
Fixes #645
2017-05-02 20:12:37 -04:00
Zachary Yedidia
84e350aa6f Optimize memory usage for loading syntax files 2017-05-02 10:30:27 -04:00
Zachary Yedidia
80242f0e08 Update runtime 2017-04-29 16:01:51 -04:00
Zachary Yedidia
2a3ce12bd4 Add termtitle option and move autoclose utf8 code 2017-04-29 16:01:09 -04:00
Collin Warren
aed8ba105a Readded title setting. ( As per the tcell pull. ) (#600) 2017-04-29 15:51:31 -04:00
Zachary Yedidia
0e9bc0ed87 Update snap yaml 2017-04-29 15:50:38 -04:00
Zachary Yedidia
9a798fe220 Merge pull request #638 from popey/patch-1
Update micro to be classic confined snap
2017-04-29 15:48:45 -04:00
Zachary Yedidia
5c3d9db5c9 Merge pull request #639 from popey/patch-2
Add micro snap install instructions
2017-04-29 15:48:36 -04:00
timon999
5ee774892a Make autoclose plugin work with Non-Ascii Unicode characters (#641)
* Make autoclose plugin work with Non-Ascii Unicode characters

* Removed lines that I forgot to remove
2017-04-29 15:44:36 -04:00
Zachary Yedidia
b4dda8bad8 Use less memory when opening very large files 2017-04-29 14:12:00 -04:00
Zachary Yedidia
47324aea97 Merge 2017-04-28 11:07:28 -04:00
Zachary Yedidia
def2b28d4e Differentiate between help buffers and log buffers
Closes #636
2017-04-28 11:07:05 -04:00
Alan Pope
b7bc34906d Add micro snap install instructions
Adds the simple command line install instructions for snap enabled systems.
2017-04-28 11:11:37 +01:00
Alan Pope
bb08d5241e Update micro to be classicly confined snap
As a text editor, micro will need to be able to edit files outside the confined world snap gives it. So this PR changes the confinement model of micro from strict to classic, making it way more useful on snap enabled systems.
2017-04-28 11:04:08 +01:00
Zachary Yedidia
ab24523bff Fix problem with search and replace indices
Closes #637
2017-04-27 20:10:51 -04:00
Zachary Yedidia
b8debb5404 Merge pull request #585 from samdmarshall/add-yaml-linter
Add yaml linter
2017-04-22 18:53:11 -04:00
Zachary Yedidia
d0e39853c6 Fix issue with cursorline 2017-04-22 18:48:05 -04:00
Samantha Marshall
a0bfd99a5d Updating changes to be in-line with master
Merging in master
2017-04-22 14:22:38 -04:00
Zachary Yedidia
471a8b7c2b Fix crash if tabs extend past view width
Ref #631
2017-04-21 12:48:03 -04:00
Zachary Yedidia
591e5e3145 Fix colorcolumn being ignored
Closes #627
2017-04-18 13:33:19 -04:00
Zachary Yedidia
282e7b1828 Merge pull request #626 from Necklaces/master
Added more default bindings:
2017-04-16 11:39:49 -04:00
Zachary Yedidia
007b060cbd Speed up search and replace
Ref #625
2017-04-16 11:11:04 -04:00
Zachary Yedidia
8168a75bde Slightly speed up search and replace
This commit also adds a linter for literate
2017-04-16 10:43:13 -04:00
Nichlas Severinsen
5afda4e76c Added more default bindings:
- Shift+Home for selecting to start of line
- Shift+End for selecting to end of line
These already exist as Ctrl+Shift+Left/Right-arrow
2017-04-16 15:34:44 +02:00
Zachary Yedidia
88c712b848 Allow plugins to create runtime files from strings 2017-04-15 14:45:44 -04:00
Zachary Yedidia
fca63d02f9 Update runtime 2017-04-15 12:02:01 -04:00
Zachary Yedidia
330888cb3b Merge pull request #624 from Necklaces/master
Improved R syntax rules
2017-04-15 12:01:30 -04:00
Zachary Yedidia
23c24c776e Merge pull request #621 from aerth/patch-1
Use GOHOSTARCH/GOHOSTOS to get version, date, Resolves #620
2017-04-15 12:01:12 -04:00
Nichlas Severinsen
233fa9b25c Improved R syntax rules 2017-04-15 02:06:19 +02:00
Zachary Yedidia
9530d6ad20 Merge 2017-04-13 21:39:20 -04:00
Zachary Yedidia
6458d3cac4 Don't draw cursorline at cursor position
Fixes #622

If the cursorline is drawn at the cursor's position, then the cursor
doesn't display. I'm not really sure why this is a problem with the
gnome terminal, it didn't seem to happen on earlier versions.
2017-04-13 21:37:13 -04:00
aerth
6945aa34eb Use GOHOSTARCH/GOHOSTOS to get version, date, Resolves #620
For "install" target, get GOBIN using 'go env GOPATH'
instead of $GOPATH because new Go doesn't require $GOPATH be set
2017-04-12 10:42:39 -07:00
Zachary Yedidia
47c9cc2fea Merge pull request #619 from nicqrocks/patch-1
Add other Perl6 extensions
2017-04-11 09:45:33 -04:00
Nic
1e90cec6f3 Add other Perl6 extensions
Perl6 files will occasionally have the extensions `.pl6` and `.pm6` instead of just `.p6`.
2017-04-11 09:32:46 -04:00
Zachary Yedidia
843867717c Merge 2017-04-02 09:27:25 -04:00
Zachary Yedidia
dd87769090 Fix TabSwitch to work by tab name as well 2017-04-02 09:27:04 -04:00
Zachary Yedidia
398370424b Relocate cursor on search
This commit also fixes some true color colorscheme issues

Fixes #614
2017-03-31 10:39:10 -04:00
Zachary Yedidia
be2d3c9c1e Read extra new line
Ref #603
2017-03-29 12:01:01 -04:00
Zachary Yedidia
05aa30d1be Improve html syntax rules 2017-03-29 10:08:37 -04:00
Zachary Yedidia
1c2b57dfe8 Add support for limit-group to highlights region limits 2017-03-29 09:54:54 -04:00
Zachary Yedidia
47ef864295 Add skip statements to all strings 2017-03-29 09:45:16 -04:00
Zachary Yedidia
a517ea45bd Slight improvements to included region highlighting 2017-03-29 09:25:08 -04:00
Zachary Yedidia
342f3c223d Don't skip included rules in end 2017-03-29 09:21:54 -04:00
Zachary Yedidia
079cbe11f4 Fix incorrect crystal filetype detection
Closes #608
2017-03-28 19:26:14 -04:00
Zachary Yedidia
3e61bd4d49 Improve some more region highlighting 2017-03-28 17:18:06 -04:00
Zachary Yedidia
b517ed28c0 Fix region highlighting with empty rules 2017-03-28 15:18:38 -04:00
Zachary Yedidia
299712ead3 Add support for skipping and remove need for lookbehind 2017-03-27 20:53:08 -04:00
Zachary Yedidia
c24f75999a Better unicode support in highlight 2017-03-27 19:35:28 -04:00
Zachary Yedidia
bde48c051a Fix out of bounds error on syntax highlighting
Fixes #606
2017-03-27 16:26:32 -04:00
Zachary Yedidia
d087a890ba Fix some issues with unicode syntax highlighting
Closes #604
2017-03-27 14:40:42 -04:00
Zachary Yedidia
75d4e70560 Document the keepautoindent option
Closes #602
2017-03-27 13:22:34 -04:00
Zachary Yedidia
73ab25d008 Properly handle files that don't end with newlines
Closes #603
2017-03-27 13:15:00 -04:00
Zachary Yedidia
790ccd429c Merge 2017-03-27 11:45:48 -04:00
Zachary Yedidia
47fd1475b5 Fix indent char styling
Closes #598
2017-03-27 11:45:24 -04:00
Zachary Yedidia
251a2b7455 Merge pull request #601 from NicolaiSoeborg/patch-3
Fix merge conflict / syntax of colors.md
2017-03-27 11:30:42 -04:00
Nicolai Søborg
3c85d31c15 Fix merge conflict / syntax of colors.md
I've changed "can provide" to "must provide" for detection of filetypes (i.e. `detect:` as micro crashes if omitted)
2017-03-27 17:11:51 +02:00
Zachary Yedidia
2e6cbcb362 Merge branch 'view-refactor' 2017-03-26 20:40:53 -04:00
Zachary Yedidia
12d74b99e8 Merge branch 'master' into view-refactor 2017-03-26 20:40:03 -04:00
Zachary Yedidia
4cda7e2d92 Update syntax readme and docs 2017-03-26 18:58:08 -04:00
Zachary Yedidia
1350deae56 Fix small softwrap bug 2017-03-26 18:01:02 -04:00
Zachary Yedidia
df564e1b8b Update yaml syntax file 2017-03-26 17:45:58 -04:00
Zachary Yedidia
bb7ce4cbb3 Add memusage option to view memory usage 2017-03-26 17:37:04 -04:00
Zachary Yedidia
1655fde09b Fix precedence for python multi-comments 2017-03-26 17:24:02 -04:00
Zachary Yedidia
89d1f1c202 Proper unicode support 2017-03-26 17:20:53 -04:00
Zachary Yedidia
b23c507af5 Read one line for empty strings 2017-03-26 15:27:53 -04:00
Zachary Yedidia
15055440da Optimize how files are read into the buffer 2017-03-26 15:23:32 -04:00
Zachary Yedidia
e2b7c85955 Small optimization to state only highlighting 2017-03-26 13:03:43 -04:00
Zachary Yedidia
9c5ab2afbd Fix possible overflow error 2017-03-25 17:31:46 -04:00
Zachary Yedidia
d413562145 Add more performance and memory optimizations 2017-03-24 14:11:21 -04:00
Zachary Yedidia
87f54be13a Add support for lookbehind in region regexes
Use the 'regexp2' library for lookahead and lookbehind in region
start and end regular expressions to support things like closing quotes
that aren't preceded by backslashes.
2017-03-22 19:03:06 -04:00
Zachary Yedidia
bea1c5dc28 Fix another issue with horizontal scrolling 2017-03-22 12:28:02 -04:00
Zachary Yedidia
04b4dbbfee Improve performance on long lines 2017-03-22 11:58:43 -04:00
Zachary Yedidia
d55e7319da Fix small bug 2017-03-21 15:46:06 -04:00
Zachary Yedidia
54bb99d758 Improve new syntax files and fix a region glitch 2017-03-21 15:07:39 -04:00
Zachary Yedidia
b977bf5cca Add converted syntax files 2017-03-21 14:55:22 -04:00
Zachary Yedidia
fa7f89a400 Properly escape start and end regexes 2017-03-21 14:48:24 -04:00
Zachary Yedidia
523f75654d No tabs in yaml 2017-03-21 14:44:54 -04:00
Zachary Yedidia
e85ae907a0 Add syntax converter from old file format to new 2017-03-21 14:35:58 -04:00
Zachary Yedidia
b0e287498e Update runtime 2017-03-21 13:16:08 -04:00
Zachary Yedidia
8a33c98bc6 Support rule precedence just like the old format 2017-03-21 13:15:46 -04:00
Zachary Yedidia
59bf1a2260 Optimize the memory usage for syntax highlighting 2017-03-21 12:45:27 -04:00
Zachary Yedidia
214adcf611 Properly clear syntax highlighting when it is disabled 2017-03-20 17:40:33 -04:00
Zachary Yedidia
23152f0c50 Use bytes for highlight groups 2017-03-20 15:14:04 -04:00
Zachary Yedidia
2a4abbee24 Fix larger multiline region highlighting 2017-03-16 16:38:44 -04:00
Zachary Yedidia
f637268fa7 Fix small issue with regions 2017-03-16 13:15:12 -04:00
Zachary Yedidia
ea7f90713c Fix some small glitches with cursor positioning 2017-03-13 19:23:47 -04:00
Zachary Yedidia
53a19afe52 Fix error when opening directory
Fixes #587
2017-03-11 13:08:32 -05:00
Zachary Yedidia
ed6951a653 Check if file is dir before opening
Fixes #587
2017-03-09 12:56:24 -05:00
Zachary Yedidia
2e99f52133 Fix split divider style 2017-03-09 12:40:53 -05:00
Zachary Yedidia
da5542a557 Fix findNext and findPrevious with certain regexes
Fixes #576
2017-03-05 11:20:42 -05:00
Zachary Yedidia
1cd4b2c4dc Update go yaml file 2017-03-05 11:12:50 -05:00
Zachary Yedidia
253e86230c Build runtime 2017-03-03 11:49:53 -05:00
CaptainMcClellan
9f9b5def41 Added theming to the Vsplit divider. (#578)
* Added title setting (Requires tcell pull!) and optimized tab display.

* Changed tcell call to screen.

* Fixed bad reference for getting Buffer name.

* Themeable vsplit divider.

* Bugfix.
2017-03-03 11:48:51 -05:00
CaptainMcClellan
d949b58fc0 Legacy syntax overhaul 2 (#577)
* Added title setting (Requires tcell pull!) and optimized tab display.

* Added Clojure highlighting.

* Changed tcell call to screen.

* Fixed bad reference for getting Buffer name.

* Yet another massive syntax overhaul

* Tweaking and testing web syntax

* More webdev goodies

* Added html5 highlighting and strict html4 highlighting.

* Documentation update
2017-03-03 11:47:03 -05:00
Zachary Yedidia
ab74e56a40 Revert "Added title setting (Requires tcell pull!) and optimized tab display." (#581) 2017-03-03 11:43:44 -05:00
Zachary Yedidia
a537c584d0 Update README.md 2017-03-03 10:28:29 -05:00
Zachary Yedidia
98365b6bfb Fix block indent selection
Fixes #572
2017-03-02 19:46:23 -05:00
CaptainMcClellan
57c030d3b9 Added title setting (Requires tcell pull!) and optimized tab display. (#575)
* Added title setting (Requires tcell pull!) and optimized tab display.

* Changed tcell call to screen.

* Fixed bad reference for getting Buffer name.
2017-03-02 12:27:49 -05:00
Marius Messerschmidt
89acc703f5 Added a script to build debian packages (#563)
Signed-off-by: Marius Messerschmidt <marius.messerschmidt@googlemail.com>
2017-03-02 12:26:01 -05:00
Zachary Yedidia
6df2d7d822 Update runtime 2017-03-01 17:09:09 -05:00
Zachary Yedidia
3c192c2fb5 Use Go regex word boundaries 2017-03-01 17:08:56 -05:00
Zachary Yedidia
995a910f6a Update runtime
Also made a minor addition to ruby.micro which fixes #574.
2017-03-01 09:36:41 -05:00
CaptainMcClellan
c29e58e3d4 Syntax Highlight Overhaul (#568)
* Adds new syntax groups and docs
* Large refactor of syntax highlighting files

* Changed keybindings for changing tabs.

* Improved the documentation.

* Added F3 for find to default bindings.

* Massive overhaul of the syntax files

* Phase 1 color-scheme updates.

* The new colorschemes.

* Colorscheme and syntax updates.

* Tiny fix to the cmc theme.

* Another phase of colorschemes and testing gitconfig.

* Fixed haskell error

* Fortran fix

* Delete test.txt

Heh, sorry about forgetting to do this again.
2017-03-01 09:30:35 -05:00
Zachary Yedidia
924809b19b Merge pull request #570 from yursan9/yaml
Improve YAML highlighting
2017-02-28 19:05:12 -05:00
Yurizal Susanto
85e7055505 Small fix for space detection 2017-02-28 13:49:48 +07:00
Yurizal Susanto
fb6d554df6 Improve YAML highlighting 2017-02-28 07:16:41 +07:00
Zachary Yedidia
bd0c5c655e Add more syntax files and include syntax highlighter in the repo 2017-02-26 11:14:35 -05:00
Zachary Yedidia
e6e190942c Minor fixes 2017-02-26 11:14:35 -05:00
Zachary Yedidia
25ad139675 Remove old view code 2017-02-26 11:14:35 -05:00
Zachary Yedidia
a095644731 Minor fix to tab size 2017-02-26 11:14:35 -05:00
Zachary Yedidia
f197eca320 Improve horizontal scrolling 2017-02-26 11:14:35 -05:00
Zachary Yedidia
d602cb68ca Support include statements in syntax files 2017-02-26 11:14:35 -05:00
Zachary Yedidia
56e98ea5f4 Highlight selections 2017-02-26 11:14:35 -05:00
Zachary Yedidia
16d8a560bf Don't highlight if syntax is off 2017-02-26 11:14:35 -05:00
Zachary Yedidia
32325f99ad Support multiple splits 2017-02-26 11:14:35 -05:00
Zachary Yedidia
9b33a1058a Add cursorline support 2017-02-26 11:14:35 -05:00
Zachary Yedidia
ff5c8d7451 Draw tab characters correctly 2017-02-26 11:14:35 -05:00
Zachary Yedidia
1ba51e4f59 Fix newline state 2017-02-26 11:14:35 -05:00
Zachary Yedidia
7fe2b8ef2f Store highlighting matches in each line 2017-02-26 11:14:35 -05:00
Zachary Yedidia
7bb61307e0 Fix tab size 2017-02-26 11:14:35 -05:00
Zachary Yedidia
d0057121ef Start implementing syntax highlighting optimizations 2017-02-26 11:14:35 -05:00
Zachary Yedidia
18c4196354 Store states in linearray 2017-02-26 11:14:35 -05:00
Zachary Yedidia
2fcb40d5a9 Use new syntax highlighting engine from zyedidia/highlight
This changes all the syntax files in the runtime directory and also
changes how syntax highlighting is done from inside micro.
2017-02-26 11:14:35 -05:00
Zachary Yedidia
0adb601f3c Improve drawing 2017-02-26 11:14:35 -05:00
Zachary Yedidia
b669437296 Add gutter message drawing and better cursor locating 2017-02-26 11:14:35 -05:00
Zachary Yedidia
9ef27203f0 Add support for line numbers and cursor locations in the new view 2017-02-26 11:14:35 -05:00
Zachary Yedidia
d2a1d849c9 Calculate line number offset 2017-02-26 11:14:35 -05:00
Zachary Yedidia
712b383e2c Use the new cellview for displaying
Syntax highlighting is still not supported when using the new cellview.
2017-02-26 11:14:35 -05:00
Zachary Yedidia
94175d1aa6 Add beginning of cellview as well as improved ViewTypes
This is the beginning of the view refactor (#515). It's just
the start and is untested for now.
2017-02-26 11:14:35 -05:00
Zachary Yedidia
9b51069041 Merge pull request #564 from DanielPower/master
Replaced tmp directory with file directory
2017-02-26 10:59:33 -05:00
Zachary Yedidia
80ab81fefc Add tabswitch command
Fixes #566
2017-02-26 10:52:14 -05:00
Daniel Power
d00562d37a Replaced tmp directory with file directory 2017-02-26 02:21:19 -03:30
Zachary Yedidia
75a344ef56 Merge 2017-02-23 22:20:36 -05:00
Zachary Yedidia
ffebb58d92 Update autoclose 2017-02-23 22:20:33 -05:00
Zachary Yedidia
c9199ba1bd Merge 2017-02-23 16:32:57 -05:00
Zachary Yedidia
5024ecd640 Add colorscheme complete function
This function is not used at the moment.
2017-02-23 16:32:33 -05:00
Zachary Yedidia
a185d6f9a0 Merge pull request #556 from AndydeCleyre/feature/zsh-theme-syntax
recognize zsh-themes as zsh filetypes
2017-02-21 15:31:56 -05:00
Andy Kluger
690610d4b1 recognize zsh-themes as zsh filetypes 2017-02-21 14:56:57 -05:00
Zachary Yedidia
043f7cdc47 Fix various linter and vet warnings 2017-02-21 13:07:37 -05:00
Zachary Yedidia
4d1ad52405 Fix find and replace counter 2017-02-20 18:33:44 -05:00
Zachary Yedidia
7294424c3e Merge pull request #553 from samdmarshall/master
fixing bug in closing tabs and not being able to select tabs
2017-02-20 18:06:41 -05:00
Samantha Marshall
bb55fc4150 fixing bug in closing tabs and not being able to select tabs 2017-02-20 18:01:29 -05:00
Zachary Yedidia
263eec7368 Resize all tabs on EventResize
Fixes #552
2017-02-20 13:08:14 -05:00
Zachary Yedidia
7b03f5bab2 Fix bold highlighting not working right 2017-02-20 09:28:37 -05:00
Zachary Yedidia
0fd042dce6 Merge pull request #551 from samdmarshall/master
fixing hex number highlighting for nim
2017-02-19 16:15:56 -05:00
Samantha Marshall
e379239140 fixing hex number highlighting for nim 2017-02-19 16:04:42 -05:00
Zachary Yedidia
c1db99a5a5 Merge pull request #522 from samdmarshall/master
Redo of #516 -- Making micro a bit more user-friendly around the quitting behavior
2017-02-16 15:57:04 -05:00
Zachary Yedidia
fb2bf7a377 Merge pull request #520 from samdmarshall/tab-scrolling
adding tab scrolling and additional tab indicators
2017-02-16 15:51:19 -05:00
Zachary Yedidia
9404b731ec Don't trim arguments for 'set' 2017-02-15 12:56:40 -05:00
Zachary Yedidia
e682c0355b Update README.md 2017-02-14 20:45:06 -05:00
Zachary Yedidia
d8e7291cb2 Include third party license in releases 2017-02-11 11:44:23 -05:00
Zachary Yedidia
556a3eb18f Merge pull request #547 from ta2gch/third-party-licenses
Add third party licenses
2017-02-11 11:43:15 -05:00
TANIGUCHI Masaya
f9fcdb2e8b Add third party licenses 2017-02-12 01:23:36 +09:00
Zachary Yedidia
d695d12872 Update go highlighting 2017-02-10 21:00:31 -05:00
Zachary Yedidia
ced7164912 Merge pull request #545 from ta2gch/cpp
lambda expression in c++
2017-02-10 12:43:27 -05:00
Zachary Yedidia
ce3bdf63c0 Bump 2017-02-10 11:07:17 -05:00
TANIGUCHI Masaya
4c678c4936 add c++ linter 2017-02-08 15:11:23 +09:00
TANIGUCHI Masaya
18d128eb3d create c++ syntax 2017-02-08 15:06:22 +09:00
TANIGUCHI Masaya
97632e5573 add keywords 2017-02-08 14:36:39 +09:00
Zachary Yedidia
5dc8fe40ca Add option to disable use of a the primary clipboard
Closes #544
2017-02-07 19:21:25 -05:00
Zachary Yedidia
28af256be0 Fix stringwidth build 2017-02-03 07:32:48 -05:00
Zachary Yedidia
c3a165e61d Merge pull request #539 from samdmarshall/nim
Adding syntax and linter support for nim-lang
2017-02-02 23:00:12 -05:00
Zachary Yedidia
33e5dd4aed Update runtime 2017-01-27 10:32:58 -05:00
Samantha Marshall
9122f152d1 fixing thestart/end syntax 2017-01-27 08:40:41 -05:00
Samantha Marshall
2202b32f31 finishing up syntax file 2017-01-26 15:50:54 -05:00
Samantha Marshall
15ab0b2fed adding nim linter and syntax 2017-01-26 14:19:07 -05:00
Zachary Yedidia
a8b0f6d679 Merge pull request #531 from bazzilic/patch-1
Update README.md to mention chocolatey package
2017-01-25 14:32:14 -05:00
Zachary Yedidia
40411ea627 Merge pull request #533 from onodera-punpun/toml
Add toml syntax file
2017-01-25 14:32:04 -05:00
Zachary Yedidia
8a6a3127c6 Merge pull request #534 from onodera-punpun/go2
update go syntax file
2017-01-25 14:31:53 -05:00
Zachary Yedidia
f951c6f489 Merge pull request #535 from yursan9/patch-1
Correct the splitBottom option
2017-01-25 14:31:41 -05:00
Yurizal Susanto
82a3b8bb39 Correct the splitBottom option 2017-01-24 10:40:36 +07:00
onodera-punpun
c29ccfe011 update go syntax file 2017-01-23 20:06:39 +01:00
onodera-punpun
d48efbf442 Add toml syntax file 2017-01-23 20:01:26 +01:00
bazzilic
69ef6def38 Update README.md to mention chocolatey package 2017-01-23 14:41:52 +08:00
DanielPower
f7560c3311 Add gruvbox truecolor colorscheme (#530)
* Add gruvbox truecolor colorscheme

* Fixed typo in gruvbox-tv, added operator type in colorschemes

* Added operator type to all default themes

* Changed operator to symbol

* changed operator to symbol due to name conflict

* Removed unused 'operator' field. Fixed gutter-error color

* Restored the statement group and removed operator
2017-01-20 14:32:34 -05:00
Samantha Marshall
ea57d8b883 Adding additional Python and Objective-C linting (#524)
* adding mypy and pylint to the linter plugin

* adding objective-c linting

* updating runtime file
2017-01-17 16:34:11 -05:00
Samantha Marshall
a7e5a5b26c only prompt the user if they can close all buffers, otherwise it would be misleading 2017-01-10 10:18:49 -05:00
Samantha Marshall
ea0dda98ce adding different functionality for closing a tab versus quitting micro 2017-01-10 10:13:21 -05:00
Nicolai Søborg
41fb57e449 Fix: incorrect clipboard w/ CutLine, DeleteLine and Search (#508)
* Fix: incorrect clipboard w/ CutLine, DeleteLine and Search

* Refactor: Add Cursor.CopySelection(clipboard)
2017-01-09 18:28:45 -05:00
Samantha Marshall
3783f0a9f0 adding tab scrolling and additional tab indicators 2017-01-04 14:24:13 -05:00
Zachary Yedidia
ae566920b6 Merge pull request #518 from samdmarshall/key-unbinding
Key unbinding
2017-01-04 13:56:34 -05:00
Zachary Yedidia
036ed7b9ed Add SaveAs action
Fixes #509
2017-01-04 13:51:17 -05:00
Zachary Yedidia
5775b4c05d Fix gutter coloring for soft wrap
Fixes #511
2017-01-04 13:29:57 -05:00
Samantha Marshall
29502e7f41 simplify the code around unbinding keys 2017-01-02 11:28:47 -05:00
Samantha Marshall
362d8eabae Adding functionality to unbind keys
* adds new special-case keybinding to remove an existing default key binding.
* hides the show/close help text in the status line when no key is assigned to "ToggleHelp"
* updating documentation
2017-01-02 10:56:55 -05:00
Zachary Yedidia
a3c58e52fc Merge pull request #513 from samdmarshall/master
Adding embedded Info.plist to OS X builds
2016-12-29 18:55:28 -05:00
Zachary Yedidia
1edd161684 Merge pull request #510 from legionus/email-syntax
Add mail syntax highlighting
2016-12-28 17:30:47 -05:00
Samantha Marshall
7f95891a9a Adding embedded Info.plist to OS X builds. 2016-12-28 13:17:54 -05:00
Alexey Gladkov
80c6c8ef9f Add mail syntax highlighting 2016-12-28 18:18:19 +01:00
Zachary Yedidia
143339dd67 Merge 2016-12-26 10:34:41 -05:00
Zachary Yedidia
7611c13d12 Better fix for mouse clicking 2016-12-26 10:33:41 -05:00
Zachary Yedidia
d49e366413 Merge pull request #507 from NicolaiSoeborg/master
Fix travis build (new imports for gopher-luar)
2016-12-25 10:56:53 -05:00
Nicolai
ac5fbd9515 Fix travis build (new imports for gopher-luar)
See
24588ee686
2016-12-25 15:42:18 +01:00
Zachary Yedidia
aef75f9b83 Fix bug with mouse clicks
Fixes #504
2016-12-24 15:34:01 -05:00
Zachary Yedidia
faec861081 Update php rules 2016-12-23 18:25:47 -05:00
Nicolai
5a9a7a3835 Merge remote-tracking branch 'refs/remotes/zyedidia/master' 2016-12-24 00:24:12 +01:00
Zachary Yedidia
2649b673f7 Merge 2016-12-22 18:34:15 -05:00
Zachary Yedidia
7958dc0592 Update php syntax rules 2016-12-22 18:34:10 -05:00
Zachary Yedidia
379a49f944 Merge pull request #488 from McSwaggens/removewhitespaces-setting
Added removewhitespaces setting
2016-12-22 17:49:49 -05:00
Daniel Jones
a311e07106 Changed removewhitespaces setting to keepautoindent 2016-12-23 09:44:57 +11:00
Zachary Yedidia
496fab031c Merge 2016-12-22 16:38:24 -05:00
Zachary Yedidia
1a95f34b0e Fix prompts not displaying 2016-12-22 16:38:20 -05:00
Zachary Yedidia
d560de4b40 Merge pull request #499 from 10sr/addrmtrailingws
[Proposal] Add feature to trim trailing whitespaces on save
2016-12-22 15:45:55 -05:00
Zachary Yedidia
0d9fc601ac Merge pull request #489 from november-eleven/refactor/plugin-name
Enable human-friendly plugin name
2016-12-22 15:44:09 -05:00
Zachary Yedidia
325c9111eb Merge pull request #502 from samdmarshall/master
preventing messages from over-writing the current prompt text
2016-12-18 18:38:03 -05:00
Samantha Marshall
968d5be74e fixing test, was using incorrect assignment syntax 2016-12-18 15:29:22 -05:00
Samantha Marshall
71ee042218 preventing messages from over-writing the current prompt message 2016-12-18 15:14:18 -05:00
Zachary Yedidia
d826db89d6 Merge pull request #501 from samdmarshall/master
updating micro syntax to better work with micro syntax files
2016-12-17 20:56:01 -05:00
Samantha Marshall
7db856d39d updating micro syntax to better work with micro syntax files 2016-12-17 20:47:25 -05:00
Zachary Yedidia
f90054cf25 Merge pull request #500 from NicolaiSoeborg/patch-1
Fix: mouse clicking with softwrap
2016-12-17 19:50:13 -05:00
Nicolai Søborg
37ae99ccd9 Fix: mouse clicking with softwrap
When clicking on a long line with softwrap turned on, the cursor will show up in the wrong location (`screenY` will be wrong in `GetSoftWrapLocation`). This seems to fix it.
2016-12-18 00:27:06 +01:00
10sr
e71b49481b Update help for rmtrailingws 2016-12-17 11:33:48 +09:00
10sr
701d0dfe3d Add rmtrailingws feature 2016-12-17 11:33:48 +09:00
Zachary Yedidia
3f02e12539 Merge pull request #497 from 10sr/fixeolnewline
Fix bug that eofnewline does not work on save
2016-12-16 14:41:06 -05:00
10sr
5b689a5592 Fix bug that eofnewline does not work on save 2016-12-15 16:29:50 +09:00
Zachary Yedidia
2bc70890f0 Merge pull request #495 from ColinRioux/master
Minor fix to documentation
2016-12-14 15:13:18 -05:00
Colin Rioux
4e5aa4ecc8 Minor fix to documentation 2016-12-14 15:11:57 -05:00
Zachary Yedidia
5f50d79efa Update docs
Fixes #486
2016-12-14 10:30:03 -05:00
Zachary Yedidia
000197fd28 Merge pull request #493 from Theodus/tabs
Move to new tab when created
2016-12-13 12:30:42 -05:00
theodus
4cb26d2e8e move to new tab 2016-12-13 12:12:20 -05:00
Zachary Yedidia
1d41634272 Add missing word boundary to python regex
Fixes #490
2016-12-13 09:27:54 -05:00
Zachary Yedidia
32e8284505 Expand '~' in SaveAs
Fixes #491
2016-12-13 08:58:08 -05:00
Thomas LE ROUX
651cb89948 refactor(plugin): Enable human-friendly plugin name 2016-12-12 16:37:48 +01:00
Zachary Yedidia
63f18f033c Update runtime 2016-12-11 16:43:07 -05:00
Daniel Jones
0558de12c6 Added removewhitespaces setting 2016-12-11 23:01:10 +11:00
Zachary Yedidia
95293457fb Merge 2016-12-10 20:36:08 -05:00
Zachary Yedidia
d71ad04d98 Display colorscheme error message using TermMessage 2016-12-10 20:36:03 -05:00
Zachary Yedidia
7134cc8e1c Merge pull request #487 from NicolaiSoeborg/patch-1
Update plugin documentation
2016-12-10 20:16:28 -05:00
Nicolai Søborg
3de440338d Update plugin documentation 2016-12-11 01:24:49 +01:00
Zachary Yedidia
73d14f5d37 Merge pull request #485 from sirikid/syntax-fix
Initial OCaml support (integer and real literals, comments)
2016-12-09 10:41:38 -05:00
Zachary Yedidia
291b1d1efc Use shell to parse command when using JobStart
Also changed all occurrences of JobStart to JobSpawn in the linter
plugin.
2016-12-09 10:34:39 -05:00
Ivan Sokolov
57960bdc81 Initial OCaml support (integers and real literals, comments) 2016-12-08 18:11:56 +03:00
Zachary Yedidia
e1d231baa3 Merge pull request #478 from NicolaiSoeborg/master
Add syntax highlighting for Solidity
2016-12-07 21:30:54 -05:00
Zachary Yedidia
8436e2866f Merge pull request #481 from sirikid/syntax-fix
Simple fix for Pascal syntax highlighting
2016-12-07 21:30:05 -05:00
Zachary Yedidia
3ee87e8767 Merge pull request #480 from Theodus/master
improve pony syntax
2016-12-07 21:30:00 -05:00
Ivan Sokolov
11e9419258 Simple fix for Pascal syntax highlighting 2016-12-08 05:03:00 +03:00
theodus
cb7fe94b04 improve pony syntax 2016-12-07 17:09:24 -05:00
Zachary Yedidia
3f01f73ea9 Give error message if input is a directory
Fixes #479
2016-12-07 10:28:03 -05:00
Nicolai
c35650e51a Add syntax highlighting for Solidity 2016-12-06 21:52:37 +01:00
Nicolai
b0813f12e6 Merge remote-tracking branch 'refs/remotes/zyedidia/master' 2016-12-06 21:51:33 +01:00
294 changed files with 13549 additions and 4544 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ binaries/
tmp.sh
test/
.idea/
packages/

View File

@@ -1,6 +1,6 @@
Micro is licensed under the MIT "Expat" License:
Copyright (c) 2016: Zachary Yedidia.
Copyright (c) 2016: Zachary Yedidia, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

1108
LICENSE-THIRD-PARTY Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +1,36 @@
.PHONY: runtime
VERSION = $(shell go run tools/build-version.go)
HASH = $(shell git rev-parse --short HEAD)
DATE = $(shell go run tools/build-date.go)
GOBIN ?= $(GOPATH)/bin
VERSION := $(shell GOOS=$(shell go env GOHOSTOS) GOARCH=$(shell go env GOHOSTARCH) \
go run tools/build-version.go)
HASH := $(shell git rev-parse --short HEAD)
DATE := $(shell GOOS=$(shell go env GOHOSTOS) GOARCH=$(shell go env GOHOSTARCH) \
go run tools/build-date.go)
ADDITIONAL_GO_LINKER_FLAGS := $(shell GOOS=$(shell go env GOHOSTOS) \
GOARCH=$(shell go env GOHOSTARCH) \
go run tools/info-plist.go "$(VERSION)")
GOBIN ?= $(shell go env GOPATH)/bin
# Builds micro after checking dependencies but without updating the runtime
build: deps
go build -ldflags "-s -w -X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)'" ./cmd/micro
go build -ldflags "-s -w -X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)' $(ADDITIONAL_GO_LINKER_FLAGS)" ./cmd/micro
# Builds micro after building the runtime and checking dependencies
build-all: runtime build
# Builds micro without checking for dependencies
build-quick:
go build -ldflags "-s -w -X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)'" ./cmd/micro
go build -ldflags "-s -w -X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)' $(ADDITIONAL_GO_LINKER_FLAGS)" ./cmd/micro
# Same as 'build' but installs to $GOBIN afterward
install: deps
go install -ldflags "-s -w -X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)'" ./cmd/micro
go install -ldflags "-s -w -X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)' $(ADDITIONAL_GO_LINKER_FLAGS)" ./cmd/micro
# Same as 'build-all' but installs to $GOBIN afterward
install-all: runtime install
# Same as 'build-quick' but installs to $GOBIN afterward
install-quick:
go install -ldflags "-s -w -X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)'" ./cmd/micro
go install -ldflags "-s -w -X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)' $(ADDITIONAL_GO_LINKER_FLAGS)" ./cmd/micro
# Checks for dependencies
deps:

View File

@@ -36,7 +36,7 @@ You can also check out the website for Micro at https://micro-editor.github.io.
* Micro has a built-in plugin manager to automatically install, remove, and update all your plugins
* Persistent undo
* Automatic linting and error notifications
* Syntax highlighting (for over [75 languages](runtime/syntax)!)
* Syntax highlighting (for over [90 languages](runtime/syntax)!)
* Colorscheme support
* By default, micro comes with 16, 256, and true color themes.
* True color support (set the `MICRO_TRUECOLOR` env variable to 1 to enable it)
@@ -67,14 +67,26 @@ and you'll see all the stable releases with the corresponding binaries.
If you'd like to see more information after installing micro, run `micro -version`.
### Homebrew
### Package Managers
You can also install micro using Homebrew on Mac:
You can install micro using Homebrew on Mac:
```
brew install micro
```
On Windows, you can install micro through Chocolatey:
```
choco install micro
```
On Linux, you can install micro through [snap](https://snapcraft.io/docs/core/install)
```
snap install micro --beta
```
### Building from source
If your operating system does not have a binary release, but does run Go, you can build from source.
@@ -82,7 +94,7 @@ If your operating system does not have a binary release, but does run Go, you ca
Make sure that you have Go version 1.5 or greater (Go 1.4 will work if your version supports CGO) and that your `GOPATH` env variable is set (I recommand setting it to `~/go` if you don't have one).
```
go get -d github.com/zyedidia/micro
go get -d github.com/zyedidia/micro/...
cd $GOPATH/src/github.com/zyedidia/micro
make install
```
@@ -91,6 +103,10 @@ The binary will then be installed to `$GOPATH/bin` (or your `$GOBIN`).
You can install directly with `go get` (`go get -u github.com/zyedidia/micro/cmd/micro`) but this isn't recommended because it doesn't build micro with version information which is useful for the plugin manager.
### MacOS terminal
If you are using MacOS, you should consider using [iTerm2](http://iterm2.com/) instead of the default Mac terminal. The iTerm2 terminal has much better mouse support as well as better handling of key events. The newest versions also support true color.
### Linux clipboard support
On Linux, clipboard support requires the 'xclip' or 'xsel' commands to be installed.
@@ -107,7 +123,7 @@ If you don't have xclip or xsel, micro will use an internal clipboard for copy a
If you open micro and it doesn't seem like syntax highlighting is working, this is probably because
you are using a terminal which does not support 256 color. Try changing the colorscheme to `simple`
by running `> set colorscheme simple`.
by pressing CtrlE in micro and typing `set colorscheme simple`.
If you are using the default Ubuntu terminal, to enable 256 make sure your `TERM` variable is set
to `xterm-256color`.
@@ -158,6 +174,7 @@ a brief introduction to the more powerful configuration features micro offers.
If you find any bugs, please report them! I am also happy to accept pull requests from anyone.
You can use the [GitHub issue tracker](https://github.com/zyedidia/micro/issues) to report bugs, ask questions, or suggest new features.
You can use the [GitHub issue tracker](https://github.com/zyedidia/micro/issues)
to report bugs, ask questions, or suggest new features.
For a more informal setting to discuss the editor, you can join the [Gitter chat](https://gitter.im/zyedidia/micro).

View File

@@ -13,7 +13,7 @@ import (
// PreActionCall executes the lua pre callback if possible
func PreActionCall(funcName string, view *View) bool {
executeAction := true
for _, pl := range loadedPlugins {
for pl := range loadedPlugins {
ret, err := Call(pl+".pre"+funcName, view)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)
@@ -29,7 +29,7 @@ func PreActionCall(funcName string, view *View) bool {
// PostActionCall executes the lua plugin callback if possible
func PostActionCall(funcName string, view *View) bool {
relocate := true
for _, pl := range loadedPlugins {
for pl := range loadedPlugins {
ret, err := Call(pl+".on"+funcName, view)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)
@@ -111,7 +111,21 @@ func (v *View) CursorLeft(usePlugin bool) bool {
v.Cursor.Loc = v.Cursor.CurSelection[0]
v.Cursor.ResetSelection()
} else {
v.Cursor.Left()
tabstospaces := v.Buf.Settings["tabstospaces"].(bool)
tabmovement := v.Buf.Settings["tabmovement"].(bool)
if tabstospaces && tabmovement {
tabsize := int(v.Buf.Settings["tabsize"].(float64))
line := v.Buf.Line(v.Cursor.Y)
if v.Cursor.X-tabsize >= 0 && line[v.Cursor.X-tabsize:v.Cursor.X] == Spaces(tabsize) && IsStrWhitespace(line[0:v.Cursor.X-tabsize]) {
for i := 0; i < tabsize; i++ {
v.Cursor.Left()
}
} else {
v.Cursor.Left()
}
} else {
v.Cursor.Left()
}
}
if usePlugin {
@@ -130,7 +144,21 @@ func (v *View) CursorRight(usePlugin bool) bool {
v.Cursor.Loc = v.Cursor.CurSelection[1].Move(-1, v.Buf)
v.Cursor.ResetSelection()
} else {
v.Cursor.Right()
tabstospaces := v.Buf.Settings["tabstospaces"].(bool)
tabmovement := v.Buf.Settings["tabmovement"].(bool)
if tabstospaces && tabmovement {
tabsize := int(v.Buf.Settings["tabsize"].(float64))
line := v.Buf.Line(v.Cursor.Y)
if v.Cursor.X+tabsize < Count(line) && line[v.Cursor.X:v.Cursor.X+tabsize] == Spaces(tabsize) && IsStrWhitespace(line[0:v.Cursor.X]) {
for i := 0; i < tabsize; i++ {
v.Cursor.Right()
}
} else {
v.Cursor.Right()
}
} else {
v.Cursor.Right()
}
}
if usePlugin {
@@ -463,7 +491,8 @@ func (v *View) InsertNewline(usePlugin bool) bool {
v.Cursor.Right()
}
if IsSpacesOrTabs(v.Buf.Line(v.Cursor.Y - 1)) {
// Remove the whitespaces if keepautoindent setting is off
if IsSpacesOrTabs(v.Buf.Line(v.Cursor.Y-1)) && !v.Buf.Settings["keepautoindent"].(bool) {
line := v.Buf.Line(v.Cursor.Y - 1)
v.Buf.Remove(Loc{0, v.Cursor.Y - 1}, Loc{Count(line), v.Cursor.Y - 1})
}
@@ -587,14 +616,20 @@ func (v *View) IndentSelection(usePlugin bool) bool {
}
if v.Cursor.HasSelection() {
startY := v.Cursor.CurSelection[0].Y
endY := v.Cursor.CurSelection[1].Move(-1, v.Buf).Y
endX := v.Cursor.CurSelection[1].Move(-1, v.Buf).X
start := v.Cursor.CurSelection[0]
end := v.Cursor.CurSelection[1]
if end.Y < start.Y {
start, end = end, start
}
startY := start.Y
endY := end.Move(-1, v.Buf).Y
endX := end.Move(-1, v.Buf).X
for y := startY; y <= endY; y++ {
tabsize := len(v.Buf.IndentString())
v.Buf.Insert(Loc{0, y}, v.Buf.IndentString())
if y == startY && v.Cursor.CurSelection[0].X > 0 {
v.Cursor.SetSelectionStart(v.Cursor.CurSelection[0].Move(tabsize, v.Buf))
if y == startY && start.X > 0 {
v.Cursor.SetSelectionStart(start.Move(tabsize, v.Buf))
}
if y == endY {
v.Cursor.SetSelectionEnd(Loc{endX + tabsize + 1, endY})
@@ -642,17 +677,23 @@ func (v *View) OutdentSelection(usePlugin bool) bool {
}
if v.Cursor.HasSelection() {
startY := v.Cursor.CurSelection[0].Y
endY := v.Cursor.CurSelection[1].Move(-1, v.Buf).Y
endX := v.Cursor.CurSelection[1].Move(-1, v.Buf).X
start := v.Cursor.CurSelection[0]
end := v.Cursor.CurSelection[1]
if end.Y < start.Y {
start, end = end, start
}
startY := start.Y
endY := end.Move(-1, v.Buf).Y
endX := end.Move(-1, v.Buf).X
for y := startY; y <= endY; y++ {
for x := 0; x < len(v.Buf.IndentString()); x++ {
if len(GetLeadingWhitespace(v.Buf.Line(y))) == 0 {
break
}
v.Buf.Remove(Loc{0, y}, Loc{1, y})
if y == startY && v.Cursor.CurSelection[0].X > 0 {
v.Cursor.SetSelectionStart(v.Cursor.CurSelection[0].Move(-1, v.Buf))
if y == startY && start.X > 0 {
v.Cursor.SetSelectionStart(start.Move(-1, v.Buf))
}
if y == endY {
v.Cursor.SetSelectionEnd(Loc{endX - x, endY})
@@ -692,39 +733,39 @@ func (v *View) InsertTab(usePlugin bool) bool {
return true
}
// SaveAll saves all open buffers
func (v *View) SaveAll(usePlugin bool) bool {
if usePlugin && !PreActionCall("SaveAll", v) {
return false
}
for _, t := range tabs {
for _, v := range t.views {
v.Save(false)
}
}
if usePlugin {
return PostActionCall("SaveAll", v)
}
return false
}
// Save the buffer to disk
func (v *View) Save(usePlugin bool) bool {
if usePlugin && !PreActionCall("Save", v) {
return false
}
if v.Type == vtHelp {
// We can't save the help text
if v.Type.scratch == true {
// We can't save any view type with scratch set. eg help and log text
return false
}
// If this is an empty buffer, ask for a filename
if v.Buf.Path == "" {
v.SaveAs(false)
}
err := v.Buf.Save()
if err != nil {
if strings.HasSuffix(err.Error(), "permission denied") {
choice, _ := messenger.YesNoPrompt("Permission denied. Do you want to save this file using sudo? (y,n)")
if choice {
err = v.Buf.SaveWithSudo()
if err != nil {
messenger.Error(err.Error())
return false
}
messenger.Message("Saved " + v.Buf.Path)
}
messenger.Reset()
messenger.Clear()
} else {
messenger.Error(err.Error())
}
} else {
messenger.Message("Saved " + v.Buf.Path)
v.saveToFile(v.Buf.Path)
}
if usePlugin {
@@ -733,16 +774,42 @@ func (v *View) Save(usePlugin bool) bool {
return false
}
// This function saves the buffer to `filename` and changes the buffer's path and name
// to `filename` if the save is successful
func (v *View) saveToFile(filename string) {
err := v.Buf.SaveAs(filename)
if err != nil {
if strings.HasSuffix(err.Error(), "permission denied") {
choice, _ := messenger.YesNoPrompt("Permission denied. Do you want to save this file using sudo? (y,n)")
if choice {
err = v.Buf.SaveAsWithSudo(filename)
if err != nil {
messenger.Error(err.Error())
} else {
v.Buf.Path = filename
v.Buf.name = filename
messenger.Message("Saved " + filename)
}
}
messenger.Reset()
messenger.Clear()
} else {
messenger.Error(err.Error())
}
} else {
v.Buf.Path = filename
v.Buf.name = filename
messenger.Message("Saved " + filename)
}
}
// SaveAs saves the buffer to disk with the given name
func (v *View) SaveAs(usePlugin bool) bool {
filename, canceled := messenger.Prompt("Filename: ", "", "Save", NoCompletion)
if !canceled {
// the filename might or might not be quoted, so unquote first then join the strings.
filename = strings.Join(SplitCommandArgs(filename), " ")
v.Buf.Path = filename
v.Buf.name = filename
v.Save(true)
v.saveToFile(filename)
}
return false
@@ -778,7 +845,7 @@ func (v *View) FindNext(usePlugin bool) bool {
if v.Cursor.HasSelection() {
searchStart = ToCharPos(v.Cursor.CurSelection[1], v.Buf)
lastSearch = v.Cursor.GetSelection()
// lastSearch = v.Cursor.GetSelection()
} else {
searchStart = ToCharPos(v.Cursor.Loc, v.Buf)
}
@@ -851,7 +918,7 @@ func (v *View) Copy(usePlugin bool) bool {
}
if v.Cursor.HasSelection() {
clipboard.WriteAll(v.Cursor.GetSelection(), "clipboard")
v.Cursor.CopySelection("clipboard")
v.freshClip = true
messenger.Message("Copied selection")
}
@@ -902,7 +969,7 @@ func (v *View) Cut(usePlugin bool) bool {
}
if v.Cursor.HasSelection() {
clipboard.WriteAll(v.Cursor.GetSelection(), "clipboard")
v.Cursor.CopySelection("clipboard")
v.Cursor.DeleteSelection()
v.Cursor.ResetSelection()
v.freshClip = true
@@ -1368,7 +1435,7 @@ func (v *View) CommandMode(usePlugin bool) bool {
return false
}
// Escape leaves current mode / quits the editor
// Escape leaves current mode
func (v *View) Escape(usePlugin bool) bool {
// check if user is searching, or the last search is still active
if searching || lastSearch != "" {
@@ -1380,13 +1447,11 @@ func (v *View) Escape(usePlugin bool) bool {
messenger.Reset() // FIXME
return true
}
return v.Quit(usePlugin)
return false
}
// Quit quits the editor
// This behavior needs to be changed and should really only quit the editor if this
// is the last view
// However, since micro only supports one view for now, it doesn't really matter
// Quit this will close the current tab or view that is open
func (v *View) Quit(usePlugin bool) bool {
if usePlugin && !PreActionCall("Quit", v) {
return false
@@ -1409,9 +1474,7 @@ func (v *View) Quit(usePlugin bool) bool {
curTab--
}
if curTab == 0 {
// CurView().Resize(screen.Size())
CurView().ToggleTabbar()
CurView().matches = Match(CurView())
}
}
} else {
@@ -1446,18 +1509,23 @@ func (v *View) QuitAll(usePlugin bool) bool {
}
if closeAll {
for _, tab := range tabs {
for _, v := range tab.views {
v.CloseBuffer()
// only quit if all of the buffers can be closed and the user confirms that they actually want to quit everything
shouldQuit, _ := messenger.YesNoPrompt("Do you want to quit micro (all open files will be closed)?")
if shouldQuit {
for _, tab := range tabs {
for _, v := range tab.views {
v.CloseBuffer()
}
}
}
if usePlugin {
PostActionCall("QuitAll", v)
}
if usePlugin {
PostActionCall("QuitAll", v)
}
screen.Fini()
os.Exit(0)
screen.Fini()
os.Exit(0)
}
}
return false
@@ -1469,10 +1537,10 @@ func (v *View) AddTab(usePlugin bool) bool {
return false
}
tab := NewTabFromView(NewView(NewBuffer(strings.NewReader(""), "")))
tab := NewTabFromView(NewView(NewBufferFromString("", "")))
tab.SetNum(len(tabs))
tabs = append(tabs, tab)
curTab++
curTab = len(tabs) - 1
if len(tabs) == 2 {
for _, t := range tabs {
for _, v := range t.views {
@@ -1529,7 +1597,7 @@ func (v *View) VSplitBinding(usePlugin bool) bool {
return false
}
v.VSplit(NewBuffer(strings.NewReader(""), ""))
v.VSplit(NewBufferFromString("", ""))
if usePlugin {
return PostActionCall("VSplit", v)
@@ -1543,7 +1611,7 @@ func (v *View) HSplitBinding(usePlugin bool) bool {
return false
}
v.HSplit(NewBuffer(strings.NewReader(""), ""))
v.HSplit(NewBufferFromString("", ""))
if usePlugin {
return PostActionCall("HSplit", v)
@@ -1651,7 +1719,7 @@ func (v *View) PlayMacro(usePlugin bool) bool {
v.Buf.Insert(v.Cursor.Loc, string(t))
v.Cursor.Right()
for _, pl := range loadedPlugins {
for pl := range loadedPlugins {
_, err := Call(pl+".onRune", string(t), v)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)

View File

@@ -0,0 +1,36 @@
package main
import "syscall"
// Suspend sends micro to the background. This is the same as pressing CtrlZ in most unix programs.
// This only works on linux and has no default binding.
// This code was adapted from the suspend code in nsf/godit
func (v *View) Suspend(usePlugin bool) bool {
if usePlugin && !PreActionCall("Suspend", v) {
return false
}
screenWasNil := screen == nil
if !screenWasNil {
screen.Fini()
screen = nil
}
// suspend the process
pid := syscall.Getpid()
tid := syscall.Gettid()
err := syscall.Tgkill(pid, tid, syscall.SIGSTOP)
if err != nil {
TermMessage(err)
}
if !screenWasNil {
InitScreen()
}
if usePlugin {
return PostActionCall("Suspend", v)
}
return true
}

View File

@@ -0,0 +1,9 @@
// +build !linux
package main
func (v *View) Suspend(usePlugin bool) bool {
messenger.Error("Suspend is only supported on Linux")
return false
}

View File

@@ -98,6 +98,25 @@ func HelpComplete(input string) (string, []string) {
return chosen, suggestions
}
// ColorschemeComplete tab-completes names of colorschemes.
func ColorschemeComplete(input string) (string, []string) {
var suggestions []string
files := ListRuntimeFiles(RTColorscheme)
for _, f := range files {
if strings.HasPrefix(f.Name(), input) {
suggestions = append(suggestions, f.Name())
}
}
var chosen string
if len(suggestions) == 1 {
chosen = suggestions[0]
}
return chosen, suggestions
}
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
@@ -129,7 +148,7 @@ func OptionComplete(input string) (string, []string) {
return chosen, suggestions
}
// MakeCompletion registeres a function from a plugin for autocomplete commands
// MakeCompletion registers a function from a plugin for autocomplete commands
func MakeCompletion(function string) Completion {
pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function))
return Completion(-len(pluginCompletions))

View File

@@ -41,6 +41,8 @@ var bindingActions = map[string]func(*View, bool) bool{
"Delete": (*View).Delete,
"InsertTab": (*View).InsertTab,
"Save": (*View).Save,
"SaveAll": (*View).SaveAll,
"SaveAs": (*View).SaveAs,
"Find": (*View).Find,
"FindNext": (*View).FindNext,
"FindPrevious": (*View).FindPrevious,
@@ -88,6 +90,7 @@ var bindingActions = map[string]func(*View, bool) bool{
"HSplit": (*View).HSplitBinding,
"ToggleMacro": (*View).ToggleMacro,
"PlayMacro": (*View).PlayMacro,
"Suspend": (*View).Suspend,
// This was changed to InsertNewline but I don't want to break backwards compatibility
"InsertEnter": (*View).InsertNewline,
@@ -346,8 +349,19 @@ func BindKey(k, v string) {
if v == "ToggleHelp" {
helpBinding = k
}
if helpBinding == k && v != "ToggleHelp" {
helpBinding = ""
}
actionNames := strings.Split(v, ",")
if actionNames[0] == "UnbindKey" {
delete(bindings, key)
if len(actionNames) == 1 {
actionNames = make([]string, 0, 0)
} else {
actionNames = append(actionNames[:0], actionNames[1:]...)
}
}
actions := make([]func(*View, bool) bool, 0, len(actionNames))
for _, actionName := range actionNames {
actions = append(actions, findAction(actionName))
@@ -376,7 +390,9 @@ func DefaultBindings() map[string]string {
"CtrlLeft": "StartOfLine",
"CtrlRight": "EndOfLine",
"CtrlShiftLeft": "SelectToStartOfLine",
"ShiftHome": "SelectToStartOfLine",
"CtrlShiftRight": "SelectToEndOfLine",
"ShiftEnd": "SelectToEndOfLine",
"CtrlUp": "CursorStart",
"CtrlDown": "CursorEnd",
"CtrlShiftUp": "SelectToStart",
@@ -402,8 +418,8 @@ func DefaultBindings() map[string]string {
"CtrlV": "Paste",
"CtrlA": "SelectAll",
"CtrlT": "AddTab",
"CtrlRightSq": "PreviousTab",
"CtrlBackslash": "NextTab",
"Alt,": "PreviousTab",
"Alt.": "NextTab",
"Home": "StartOfLine",
"End": "EndOfLine",
"CtrlHome": "CursorStart",
@@ -432,6 +448,7 @@ func DefaultBindings() map[string]string {
// Integration with file managers
"F1": "ToggleHelp",
"F2": "Save",
"F3": "Find",
"F4": "Quit",
"F7": "Find",
"F10": "Quit",

View File

@@ -9,10 +9,14 @@ import (
"os/exec"
"os/signal"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"unicode/utf8"
"github.com/mitchellh/go-homedir"
"github.com/zyedidia/micro/cmd/micro/highlight"
)
// Buffer stores the text for files that are loaded into the text editor
@@ -41,8 +45,8 @@ type Buffer struct {
NumLines int
// Syntax highlighting rules
rules []SyntaxRule
syntaxDef *highlight.Def
highlighter *highlight.Highlighter
// Buffer local settings
Settings map[string]interface{}
@@ -57,11 +61,11 @@ type SerializedBuffer struct {
}
func NewBufferFromString(text, path string) *Buffer {
return NewBuffer(strings.NewReader(text), path)
return NewBuffer(strings.NewReader(text), int64(len(text)), path)
}
// NewBuffer creates a new buffer from a given reader with a given path
func NewBuffer(reader io.Reader, path string) *Buffer {
func NewBuffer(reader io.Reader, size int64, path string) *Buffer {
if path != "" {
for _, tab := range tabs {
for _, view := range tab.views {
@@ -73,7 +77,7 @@ func NewBuffer(reader io.Reader, path string) *Buffer {
}
b := new(Buffer)
b.LineArray = NewLineArray(reader)
b.LineArray = NewLineArray(size, reader)
b.Settings = DefaultLocalSettings()
for k, v := range globalSettings {
@@ -93,7 +97,6 @@ func NewBuffer(reader io.Reader, path string) *Buffer {
b.EventHandler = NewEventHandler(b)
b.Update()
b.FindFileType()
b.UpdateRules()
if _, err := os.Stat(configDir + "/buffers/"); os.IsNotExist(err) {
@@ -182,12 +185,68 @@ func (b *Buffer) GetName() string {
// UpdateRules updates the syntax rules and filetype for this buffer
// This is called when the colorscheme changes
func (b *Buffer) UpdateRules() {
b.rules = GetRules(b)
}
rehighlight := false
var files []*highlight.File
for _, f := range ListRuntimeFiles(RTSyntax) {
data, err := f.Data()
if err != nil {
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
} else {
file, err := highlight.ParseFile(data)
if err != nil {
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
continue
}
ftdetect, err := highlight.ParseFtDetect(file)
if err != nil {
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
continue
}
// FindFileType identifies this buffer's filetype based on the extension or header
func (b *Buffer) FindFileType() {
b.Settings["filetype"] = FindFileType(b)
ft := b.Settings["filetype"].(string)
if ft == "Unknown" || ft == "" {
if highlight.MatchFiletype(ftdetect, b.Path, b.lines[0].data) {
header := new(highlight.Header)
header.FileType = file.FileType
header.FtDetect = ftdetect
b.syntaxDef, err = highlight.ParseDef(file, header)
if err != nil {
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
continue
}
rehighlight = true
}
} else {
if file.FileType == ft {
header := new(highlight.Header)
header.FileType = file.FileType
header.FtDetect = ftdetect
b.syntaxDef, err = highlight.ParseDef(file, header)
if err != nil {
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
continue
}
rehighlight = true
}
}
files = append(files, file)
}
}
if b.syntaxDef != nil {
highlight.ResolveIncludes(b.syntaxDef, files)
}
files = nil
if b.highlighter == nil || rehighlight {
if b.syntaxDef != nil {
b.Settings["filetype"] = b.syntaxDef.FileType
b.highlighter = highlight.NewHighlighter(b.syntaxDef)
if b.Settings["syntax"].(bool) {
b.highlighter.HighlightStates(b)
}
}
}
}
// FileType returns the buffer's filetype
@@ -277,19 +336,31 @@ func (b *Buffer) Serialize() error {
// SaveAs saves the buffer to a specified path (filename), creating the file if it does not exist
func (b *Buffer) SaveAs(filename string) error {
b.FindFileType()
b.UpdateRules()
b.Path = filename
str := b.String()
dir, _ := homedir.Dir()
if b.Settings["rmtrailingws"].(bool) {
r, _ := regexp.Compile(`[ \t]+$`)
for lineNum, line := range b.Lines(0, b.NumLines) {
indices := r.FindStringIndex(line)
if indices == nil {
continue
}
startLoc := Loc{indices[0], lineNum}
b.deleteToEnd(startLoc)
}
b.Cursor.Relocate()
}
if b.Settings["eofnewline"].(bool) {
end := b.End()
if b.RuneAt(Loc{end.X - 1, end.Y}) != '\n' {
b.Insert(end, "\n")
}
}
str := b.String()
data := []byte(str)
err := ioutil.WriteFile(filename, data, 0644)
if err == nil {
b.Path = strings.Replace(filename, "~", dir, 1)
b.IsModified = false
b.ModTime, _ = GetModTime(filename)
return b.Serialize()
@@ -301,7 +372,6 @@ func (b *Buffer) SaveAs(filename string) error {
// SaveAsWithSudo is the same as SaveAs except it uses a neat trick
// with tee to use sudo so the user doesn't have to reopen micro with sudo
func (b *Buffer) SaveAsWithSudo(filename string) error {
b.FindFileType()
b.UpdateRules()
b.Path = filename
@@ -359,6 +429,11 @@ func (b *Buffer) remove(start, end Loc) string {
b.Update()
return sub
}
func (b *Buffer) deleteToEnd(start Loc) {
b.IsModified = true
b.LineArray.DeleteToEnd(start)
b.Update()
}
// Start returns the location of the first character in the buffer
func (b *Buffer) Start() Loc {
@@ -367,7 +442,7 @@ func (b *Buffer) Start() Loc {
// End returns the location of the last character in the buffer
func (b *Buffer) End() Loc {
return Loc{utf8.RuneCount(b.lines[b.NumLines-1]), b.NumLines - 1}
return Loc{utf8.RuneCount(b.lines[b.NumLines-1].data), b.NumLines - 1}
}
// RuneAt returns the rune at a given location in the buffer
@@ -384,7 +459,11 @@ func (b *Buffer) Line(n int) string {
if n >= len(b.lines) {
return ""
}
return string(b.lines[n])
return string(b.lines[n].data)
}
func (b *Buffer) LinesNum() int {
return len(b.lines)
}
// Lines returns an array of strings containing the lines from start to end
@@ -392,7 +471,7 @@ func (b *Buffer) Lines(start, end int) []string {
lines := b.lines[start:end]
var slice []string
for _, line := range lines {
slice = append(slice, string(line))
slice = append(slice, string(line.data))
}
return slice
}
@@ -411,7 +490,7 @@ func (b *Buffer) MoveLinesUp(start int, end int) {
if end == len(b.lines) {
b.Insert(
Loc{
utf8.RuneCount(b.lines[end-1]),
utf8.RuneCount(b.lines[end-1].data),
end - 1,
},
"\n"+b.Line(start-1),
@@ -446,3 +525,11 @@ func (b *Buffer) MoveLinesDown(start int, end int) {
Loc{0, end + 1},
)
}
// ClearMatches clears all of the syntax highlighting for this buffer
func (b *Buffer) ClearMatches() {
for i := range b.lines {
b.SetMatch(i, nil)
b.SetState(i, nil)
}
}

207
cmd/micro/cellview.go Normal file
View File

@@ -0,0 +1,207 @@
package main
import (
"github.com/mattn/go-runewidth"
"github.com/zyedidia/tcell"
)
func min(a, b int) int {
if a <= b {
return a
}
return b
}
func visualToCharPos(visualIndex int, lineN int, str string, buf *Buffer, tabsize int) (int, int, *tcell.Style) {
charPos := 0
var lineIdx int
var lastWidth int
var style *tcell.Style
var width int
var rw int
for i, c := range str {
// width := StringWidth(str[:i], tabsize)
if group, ok := buf.Match(lineN)[charPos]; ok {
s := GetColor(group.String())
style = &s
}
if width >= visualIndex {
return charPos, visualIndex - lastWidth, style
}
if i != 0 {
charPos++
lineIdx += rw
}
lastWidth = width
rw = 0
if c == '\t' {
rw = tabsize - (lineIdx % tabsize)
width += rw
} else {
rw = runewidth.RuneWidth(c)
width += rw
}
}
return -1, -1, style
}
type Char struct {
visualLoc Loc
realLoc Loc
char rune
// The actual character that is drawn
// This is only different from char if it's for example hidden character
drawChar rune
style tcell.Style
width int
}
type CellView struct {
lines [][]*Char
}
func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
tabsize := int(buf.Settings["tabsize"].(float64))
softwrap := buf.Settings["softwrap"].(bool)
indentrunes := []rune(buf.Settings["indentchar"].(string))
// if empty indentchar settings, use space
if indentrunes == nil || len(indentrunes) == 0 {
indentrunes = []rune(" ")
}
indentchar := indentrunes[0]
start := buf.Cursor.Y
if buf.Settings["syntax"].(bool) && buf.syntaxDef != nil {
if start > 0 && buf.lines[start-1].rehighlight {
buf.highlighter.ReHighlightLine(buf, start-1)
buf.lines[start-1].rehighlight = false
}
buf.highlighter.ReHighlightStates(buf, start)
buf.highlighter.HighlightMatches(buf, top, top+height)
}
c.lines = make([][]*Char, 0)
viewLine := 0
lineN := top
curStyle := defStyle
for viewLine < height {
if lineN >= len(buf.lines) {
break
}
lineStr := buf.Line(lineN)
line := []rune(lineStr)
colN, startOffset, startStyle := visualToCharPos(left, lineN, lineStr, buf, tabsize)
if colN < 0 {
colN = len(line)
}
viewCol := -startOffset
if startStyle != nil {
curStyle = *startStyle
}
// We'll either draw the length of the line, or the width of the screen
// whichever is smaller
lineLength := min(StringWidth(lineStr, tabsize), width)
c.lines = append(c.lines, make([]*Char, lineLength))
wrap := false
// We only need to wrap if the length of the line is greater than the width of the terminal screen
if softwrap && StringWidth(lineStr, tabsize) > width {
wrap = true
// We're going to draw the entire line now
lineLength = StringWidth(lineStr, tabsize)
}
for viewCol < lineLength {
if colN >= len(line) {
break
}
if group, ok := buf.Match(lineN)[colN]; ok {
curStyle = GetColor(group.String())
}
char := line[colN]
if viewCol >= 0 {
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, char, curStyle, 1}
}
if char == '\t' {
charWidth := tabsize - (viewCol+left)%tabsize
if viewCol >= 0 {
c.lines[viewLine][viewCol].drawChar = indentchar
c.lines[viewLine][viewCol].width = charWidth
indentStyle := curStyle
if group, ok := colorscheme["indent-char"]; ok {
indentStyle = group
}
c.lines[viewLine][viewCol].style = indentStyle
}
for i := 1; i < charWidth; i++ {
viewCol++
if viewCol >= 0 && viewCol < lineLength {
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
}
}
viewCol++
} else if runewidth.RuneWidth(char) > 1 {
charWidth := runewidth.RuneWidth(char)
if viewCol >= 0 {
c.lines[viewLine][viewCol].width = charWidth
}
for i := 1; i < charWidth; i++ {
viewCol++
if viewCol >= 0 && viewCol < lineLength {
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
}
}
viewCol++
} else {
viewCol++
}
colN++
if wrap && viewCol >= width {
viewLine++
// If we go too far soft wrapping we have to cut off
if viewLine >= height {
break
}
nextLine := line[colN:]
lineLength := min(StringWidth(string(nextLine), tabsize), width)
c.lines = append(c.lines, make([]*Char, lineLength))
viewCol = 0
}
}
if group, ok := buf.Match(lineN)[len(line)]; ok {
curStyle = GetColor(group.String())
}
// newline
viewLine++
lineN++
}
for i := top; i < top+height; i++ {
if i >= buf.NumLines {
break
}
buf.SetMatch(i, nil)
}
}

View File

@@ -15,6 +15,33 @@ type Colorscheme map[string]tcell.Style
// The current colorscheme
var colorscheme Colorscheme
// This takes in a syntax group and returns the colorscheme's style for that group
func GetColor(color string) tcell.Style {
st := defStyle
if color == "" {
return st
}
groups := strings.Split(color, ".")
if len(groups) > 1 {
curGroup := ""
for i, g := range groups {
if i != 0 {
curGroup += "."
}
curGroup += g
if style, ok := colorscheme[curGroup]; ok {
st = style
}
}
} else if style, ok := colorscheme[color]; ok {
st = style
} else {
st = StringToStyle(color)
}
return st
}
// ColorschemeExists checks if a given colorscheme exists
func ColorschemeExists(colorschemeName string) bool {
return FindRuntimeFile(RTColorscheme, colorschemeName) != nil
@@ -23,10 +50,11 @@ func ColorschemeExists(colorschemeName string) bool {
// InitColorscheme picks and initializes the colorscheme when micro starts
func InitColorscheme() {
colorscheme = make(Colorscheme)
defStyle = tcell.StyleDefault.
Foreground(tcell.ColorDefault).
Background(tcell.ColorDefault)
if screen != nil {
screen.SetStyle(tcell.StyleDefault.
Foreground(tcell.ColorDefault).
Background(tcell.ColorDefault))
screen.SetStyle(defStyle)
}
LoadDefaultColorscheme()
@@ -44,23 +72,9 @@ func LoadColorscheme(colorschemeName string) {
TermMessage(colorschemeName, "is not a valid colorscheme")
} else {
if data, err := file.Data(); err != nil {
fmt.Println("Error loading colorscheme:", err)
TermMessage("Error loading colorscheme:", err)
} else {
colorscheme = ParseColorscheme(string(data))
// Default style
defStyle = tcell.StyleDefault.
Foreground(tcell.ColorDefault).
Background(tcell.ColorDefault)
// There may be another default style defined in the colorscheme
// In that case we should use that one
if style, ok := colorscheme["default"]; ok {
defStyle = style
}
if screen != nil {
screen.SetStyle(defStyle)
}
}
}
}
@@ -94,6 +108,9 @@ func ParseColorscheme(text string) Colorscheme {
if link == "default" {
defStyle = style
}
if screen != nil {
screen.SetStyle(defStyle)
}
} else {
fmt.Println("Color-link statement is not valid:", line)
}
@@ -107,7 +124,13 @@ func ParseColorscheme(text string) Colorscheme {
// The 'extra' can be bold, reverse, or underline
func StringToStyle(str string) tcell.Style {
var fg, bg string
split := strings.Split(str, ",")
spaceSplit := strings.Split(str, " ")
var split []string
if len(spaceSplit) > 1 {
split = strings.Split(spaceSplit[1], ",")
} else {
split = strings.Split(str, ",")
}
if len(split) > 1 {
fg, bg = split[0], split[1]
} else {

View File

@@ -9,16 +9,21 @@ import (
"os/signal"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
humanize "github.com/dustin/go-humanize"
"github.com/mitchellh/go-homedir"
)
// A Command contains a action (a function to call) as well as information about how to autocomplete the command
type Command struct {
action func([]string)
completions []Completion
}
// A StrCommand is similar to a command but keeps the name of the action
type StrCommand struct {
action string
completions []Completion
@@ -49,6 +54,8 @@ func init() {
"Cd": Cd,
"Pwd": Pwd,
"Open": Open,
"TabSwitch": TabSwitch,
"MemUsage": MemUsage,
}
}
@@ -82,25 +89,27 @@ func MakeCommand(name, function string, completions ...Completion) {
// DefaultCommands returns a map containing micro's default commands
func DefaultCommands() map[string]StrCommand {
return map[string]StrCommand{
"set": {"Set", []Completion{OptionCompletion, NoCompletion}},
"setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}},
"show": {"Show", []Completion{OptionCompletion, NoCompletion}},
"bind": {"Bind", []Completion{NoCompletion}},
"run": {"Run", []Completion{NoCompletion}},
"quit": {"Quit", []Completion{NoCompletion}},
"save": {"Save", []Completion{NoCompletion}},
"replace": {"Replace", []Completion{NoCompletion}},
"vsplit": {"VSplit", []Completion{FileCompletion, NoCompletion}},
"hsplit": {"HSplit", []Completion{FileCompletion, NoCompletion}},
"tab": {"Tab", []Completion{FileCompletion, NoCompletion}},
"help": {"Help", []Completion{HelpCompletion, NoCompletion}},
"eval": {"Eval", []Completion{NoCompletion}},
"log": {"ToggleLog", []Completion{NoCompletion}},
"plugin": {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}},
"reload": {"Reload", []Completion{NoCompletion}},
"cd": {"Cd", []Completion{FileCompletion}},
"pwd": {"Pwd", []Completion{NoCompletion}},
"open": {"Open", []Completion{FileCompletion}},
"set": {"Set", []Completion{OptionCompletion, NoCompletion}},
"setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}},
"show": {"Show", []Completion{OptionCompletion, NoCompletion}},
"bind": {"Bind", []Completion{NoCompletion}},
"run": {"Run", []Completion{NoCompletion}},
"quit": {"Quit", []Completion{NoCompletion}},
"save": {"Save", []Completion{NoCompletion}},
"replace": {"Replace", []Completion{NoCompletion}},
"vsplit": {"VSplit", []Completion{FileCompletion, NoCompletion}},
"hsplit": {"HSplit", []Completion{FileCompletion, NoCompletion}},
"tab": {"Tab", []Completion{FileCompletion, NoCompletion}},
"help": {"Help", []Completion{HelpCompletion, NoCompletion}},
"eval": {"Eval", []Completion{NoCompletion}},
"log": {"ToggleLog", []Completion{NoCompletion}},
"plugin": {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}},
"reload": {"Reload", []Completion{NoCompletion}},
"cd": {"Cd", []Completion{FileCompletion}},
"pwd": {"Pwd", []Completion{NoCompletion}},
"open": {"Open", []Completion{FileCompletion}},
"tabswitch": {"TabSwitch", []Completion{NoCompletion}},
"memusage": {"MemUsage", []Completion{NoCompletion}},
}
}
@@ -133,12 +142,10 @@ func PluginCmd(args []string) {
removed := ""
for _, plugin := range args[1:] {
// check if the plugin exists.
for _, lp := range loadedPlugins {
if lp == plugin {
UninstallPlugin(plugin)
removed += plugin + " "
continue
}
if _, ok := loadedPlugins[plugin]; ok {
UninstallPlugin(plugin)
removed += plugin + " "
continue
}
}
if !IsSpaces(removed) {
@@ -189,6 +196,36 @@ func PluginCmd(args []string) {
}
}
// TabSwitch switches to a given tab either by name or by number
func TabSwitch(args []string) {
if len(args) > 0 {
num, err := strconv.Atoi(args[0])
if err != nil {
// Check for tab with this name
found := false
for _, t := range tabs {
v := t.views[t.CurView]
if v.Buf.GetName() == args[0] {
curTab = v.TabNum
found = true
}
}
if !found {
messenger.Error("Could not find tab: ", err)
}
} else {
num--
if num >= 0 && num < len(tabs) {
curTab = num
} else {
messenger.Error("Invalid tab index")
}
}
}
}
// Cd changes the current working directory
func Cd(args []string) {
if len(args) > 0 {
home, _ := homedir.Dir()
@@ -206,6 +243,21 @@ func Cd(args []string) {
}
}
// MemUsage prints micro's memory usage
// Alloc shows how many bytes are currently in use
// Sys shows how many bytes have been requested from the operating system
// NumGC shows how many times the GC has been run
// Note that Go commonly reserves more memory from the OS than is currently in-use/required
// Additionally, even if Go returns memory to the OS, the OS does not always claim it because
// there may be plenty of memory to spare
func MemUsage(args []string) {
var mem runtime.MemStats
runtime.ReadMemStats(&mem)
messenger.Message(fmt.Sprintf("Alloc: %v, Sys: %v, NumGC: %v", humanize.Bytes(mem.Alloc), humanize.Bytes(mem.Sys), mem.NumGC))
}
// Pwd prints the current working directory
func Pwd(args []string) {
wd, err := os.Getwd()
if err != nil {
@@ -215,6 +267,7 @@ func Pwd(args []string) {
}
}
// Open opens a new buffer with a given filename
func Open(args []string) {
if len(args) > 0 {
filename := args[0]
@@ -227,6 +280,7 @@ func Open(args []string) {
}
}
// ToggleLog toggles the log view
func ToggleLog(args []string) {
buffer := messenger.getBuffer()
if CurView().Type != vtLog {
@@ -242,6 +296,7 @@ func ToggleLog(args []string) {
}
}
// Reload reloads all files (syntax files, colorschemes...)
func Reload(args []string) {
LoadAll()
}
@@ -265,20 +320,27 @@ func Help(args []string) {
// If no file is given, it opens an empty buffer in a new split
func VSplit(args []string) {
if len(args) == 0 {
CurView().VSplit(NewBuffer(strings.NewReader(""), ""))
CurView().VSplit(NewBufferFromString("", ""))
} else {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
file, err := os.Open(filename)
fileInfo, _ := os.Stat(filename)
if err == nil && fileInfo.IsDir() {
messenger.Error(filename, " is a directory")
return
}
defer file.Close()
var buf *Buffer
if err != nil {
// File does not exist -- create an empty buffer with that name
buf = NewBuffer(strings.NewReader(""), filename)
buf = NewBufferFromString("", filename)
} else {
buf = NewBuffer(file, filename)
buf = NewBuffer(file, FSize(file), filename)
}
CurView().VSplit(buf)
}
@@ -288,20 +350,27 @@ func VSplit(args []string) {
// If no file is given, it opens an empty buffer in a new split
func HSplit(args []string) {
if len(args) == 0 {
CurView().HSplit(NewBuffer(strings.NewReader(""), ""))
CurView().HSplit(NewBufferFromString("", ""))
} else {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
file, err := os.Open(filename)
fileInfo, _ := os.Stat(filename)
if err == nil && fileInfo.IsDir() {
messenger.Error(filename, " is a directory")
return
}
defer file.Close()
var buf *Buffer
if err != nil {
// File does not exist -- create an empty buffer with that name
buf = NewBuffer(strings.NewReader(""), filename)
buf = NewBufferFromString("", filename)
} else {
buf = NewBuffer(file, filename)
buf = NewBuffer(file, FSize(file), filename)
}
CurView().HSplit(buf)
}
@@ -327,13 +396,27 @@ func NewTab(args []string) {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
file, _ := os.Open(filename)
file, err := os.Open(filename)
fileInfo, _ := os.Stat(filename)
if err == nil && fileInfo.IsDir() {
messenger.Error(filename, " is a directory")
return
}
defer file.Close()
tab := NewTabFromView(NewView(NewBuffer(file, filename)))
var buf *Buffer
if err != nil {
buf = NewBufferFromString("", filename)
} else {
buf = NewBuffer(file, FSize(file), filename)
}
tab := NewTabFromView(NewView(buf))
tab.SetNum(len(tabs))
tabs = append(tabs, tab)
curTab++
curTab = len(tabs) - 1
if len(tabs) == 2 {
for _, t := range tabs {
for _, v := range t.views {
@@ -351,8 +434,8 @@ func Set(args []string) {
return
}
option := strings.TrimSpace(args[0])
value := strings.TrimSpace(args[1])
option := args[0]
value := args[1]
SetOptionAndSettings(option, value)
}
@@ -364,8 +447,8 @@ func SetLocal(args []string) {
return
}
option := strings.TrimSpace(args[0])
value := strings.TrimSpace(args[1])
option := args[0]
value := args[1]
err := SetLocalOption(option, value, CurView())
if err != nil {
@@ -456,9 +539,6 @@ func Replace(args []string) {
break
}
view.Relocate()
if view.Buf.Settings["syntax"].(bool) {
view.matches = Match(view)
}
RedrawAll()
choice, canceled := messenger.YesNoPrompt("Perform replacement? (y,n)")
if canceled {
@@ -485,28 +565,25 @@ func Replace(args []string) {
}
}
} else {
bufStr := view.Buf.String()
matches := regex.FindAllStringIndex(bufStr, -1)
if matches != nil && len(matches) > 0 {
prevMatchCount := runePos(matches[0][0], bufStr)
searchCount := runePos(matches[0][1], bufStr) - prevMatchCount
from := FromCharPos(matches[0][0], view.Buf)
to := from.Move(searchCount, view.Buf)
adjust := Count(replace) - searchCount
view.Buf.Replace(from, to, replace)
if len(matches) > 1 {
for _, match := range matches[1:] {
found++
matchCount := runePos(match[0], bufStr)
searchCount = runePos(match[1], bufStr) - matchCount
from = from.Move(matchCount-prevMatchCount+adjust, view.Buf)
to = from.Move(searchCount, view.Buf)
// var deltas []Delta
for i := 0; i < view.Buf.LinesNum(); i++ {
// view.Buf.lines[i].data = regex.ReplaceAll(view.Buf.lines[i].data, []byte(replace))
for {
m := regex.FindIndex(view.Buf.lines[i].data)
if m != nil {
from := Loc{m[0], i}
to := Loc{m[1], i}
// deltas = append(deltas, Delta{replace, from, to})
view.Buf.Replace(from, to, replace)
prevMatchCount = matchCount
adjust = Count(replace) - searchCount
found++
} else {
break
}
}
}
// view.Buf.MultipleReplace(deltas)
}
view.Cursor.Relocate()

View File

@@ -29,6 +29,15 @@ func (c *Cursor) Goto(b Cursor) {
c.OrigSelection, c.CurSelection = b.OrigSelection, b.CurSelection
}
// CopySelection copies the user's selection to either "primary" or "clipboard"
func (c *Cursor) CopySelection(target string) {
if c.HasSelection() {
if target != "primary" || c.buf.Settings["useprimary"].(bool) {
clipboard.WriteAll(c.GetSelection(), target)
}
}
}
// ResetSelection resets the user's selection
func (c *Cursor) ResetSelection() {
c.CurSelection[0] = c.buf.Start()
@@ -38,19 +47,11 @@ func (c *Cursor) ResetSelection() {
// SetSelectionStart sets the start of the selection
func (c *Cursor) SetSelectionStart(pos Loc) {
c.CurSelection[0] = pos
// Copy to primary clipboard for linux
if c.HasSelection() {
clipboard.WriteAll(c.GetSelection(), "primary")
}
}
// SetSelectionEnd sets the end of the selection
func (c *Cursor) SetSelectionEnd(pos Loc) {
c.CurSelection[1] = pos
// Copy to primary clipboard for linux
if c.HasSelection() {
clipboard.WriteAll(c.GetSelection(), "primary")
}
}
// HasSelection returns whether or not the user has selected anything

View File

@@ -15,6 +15,8 @@ const (
TextEventInsert = 1
// TextEventRemove represents a deletion event
TextEventRemove = -1
TextEventReplace = 0
)
// TextEvent holds data for a manipulation on some text that can be undone
@@ -22,18 +24,31 @@ type TextEvent struct {
C Cursor
EventType int
Text string
Start Loc
End Loc
Deltas []Delta
Time time.Time
}
type Delta struct {
Text string
Start Loc
End Loc
}
// ExecuteTextEvent runs a text event
func ExecuteTextEvent(t *TextEvent, buf *Buffer) {
if t.EventType == TextEventInsert {
buf.insert(t.Start, []byte(t.Text))
for _, d := range t.Deltas {
buf.insert(d.Start, []byte(d.Text))
}
} else if t.EventType == TextEventRemove {
t.Text = buf.remove(t.Start, t.End)
for i, d := range t.Deltas {
t.Deltas[i].Text = buf.remove(d.Start, d.End)
}
} else if t.EventType == TextEventReplace {
for i, d := range t.Deltas {
t.Deltas[i].Text = buf.remove(d.Start, d.End)
buf.insert(d.Start, []byte(d.Text))
}
}
}
@@ -84,12 +99,11 @@ func (eh *EventHandler) Insert(start Loc, text string) {
e := &TextEvent{
C: eh.buf.Cursor,
EventType: TextEventInsert,
Text: text,
Start: start,
Deltas: []Delta{Delta{text, start, Loc{0, 0}}},
Time: time.Now(),
}
eh.Execute(e)
e.End = start.Move(Count(text), eh.buf)
e.Deltas[0].End = start.Move(Count(text), eh.buf)
}
// Remove creates a remove text event and executes it
@@ -97,8 +111,18 @@ func (eh *EventHandler) Remove(start, end Loc) {
e := &TextEvent{
C: eh.buf.Cursor,
EventType: TextEventRemove,
Start: start,
End: end,
Deltas: []Delta{Delta{"", start, end}},
Time: time.Now(),
}
eh.Execute(e)
}
// Multiple creates an multiple insertions executes them
func (eh *EventHandler) MultipleReplace(deltas []Delta) {
e := &TextEvent{
C: eh.buf.Cursor,
EventType: TextEventReplace,
Deltas: deltas,
Time: time.Now(),
}
eh.Execute(e)
@@ -117,7 +141,7 @@ func (eh *EventHandler) Execute(t *TextEvent) {
}
eh.UndoStack.Push(t)
for _, pl := range loadedPlugins {
for pl := range loadedPlugins {
ret, err := Call(pl+".onBeforeTextEvent", t)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)

View File

@@ -0,0 +1,18 @@
package highlight
import "regexp"
// DetectFiletype will use the list of syntax definitions provided and the filename and first line of the file
// to determine the filetype of the file
// It will return the corresponding syntax definition for the filetype
func MatchFiletype(ftdetect [2]*regexp.Regexp, filename string, firstLine []byte) bool {
if ftdetect[0].MatchString(filename) {
return true
}
if ftdetect[1] != nil {
return ftdetect[1].Match(firstLine)
}
return false
}

View File

@@ -0,0 +1,374 @@
package highlight
import (
"regexp"
"strings"
"unicode/utf8"
)
// RunePos returns the rune index of a given byte index
// This could cause problems if the byte index is between code points
func runePos(p int, str string) int {
if p < 0 {
return 0
}
if p >= len(str) {
return utf8.RuneCountInString(str)
}
return utf8.RuneCountInString(str[:p])
}
func combineLineMatch(src, dst LineMatch) LineMatch {
for k, v := range src {
if g, ok := dst[k]; ok {
if g == 0 {
dst[k] = v
}
} else {
dst[k] = v
}
}
return dst
}
// A State represents the region at the end of a line
type State *region
// LineStates is an interface for a buffer-like object which can also store the states and matches for every line
type LineStates interface {
Line(n int) string
LinesNum() int
State(lineN int) State
SetState(lineN int, s State)
SetMatch(lineN int, m LineMatch)
}
// A Highlighter contains the information needed to highlight a string
type Highlighter struct {
lastRegion *region
Def *Def
}
// NewHighlighter returns a new highlighter from the given syntax definition
func NewHighlighter(def *Def) *Highlighter {
h := new(Highlighter)
h.Def = def
return h
}
// LineMatch represents the syntax highlighting matches for one line. Each index where the coloring is changed is marked with that
// color's group (represented as one byte)
type LineMatch map[int]Group
func findIndex(regex *regexp.Regexp, skip *regexp.Regexp, str []rune, canMatchStart, canMatchEnd bool) []int {
regexStr := regex.String()
if strings.Contains(regexStr, "^") {
if !canMatchStart {
return nil
}
}
if strings.Contains(regexStr, "$") {
if !canMatchEnd {
return nil
}
}
var strbytes []byte
if skip != nil {
strbytes = skip.ReplaceAllFunc([]byte(string(str)), func(match []byte) []byte {
res := make([]byte, utf8.RuneCount(match))
return res
})
} else {
strbytes = []byte(string(str))
}
match := regex.FindIndex(strbytes)
if match == nil {
return nil
}
// return []int{match.Index, match.Index + match.Length}
return []int{runePos(match[0], string(str)), runePos(match[1], string(str))}
}
func findAllIndex(regex *regexp.Regexp, str []rune, canMatchStart, canMatchEnd bool) [][]int {
regexStr := regex.String()
if strings.Contains(regexStr, "^") {
if !canMatchStart {
return nil
}
}
if strings.Contains(regexStr, "$") {
if !canMatchEnd {
return nil
}
}
matches := regex.FindAllIndex([]byte(string(str)), -1)
for i, m := range matches {
matches[i][0] = runePos(m[0], string(str))
matches[i][1] = runePos(m[1], string(str))
}
return matches
}
func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchEnd bool, lineNum int, line []rune, curRegion *region, statesOnly bool) LineMatch {
// highlights := make(LineMatch)
if start == 0 {
if !statesOnly {
if _, ok := highlights[0]; !ok {
highlights[0] = curRegion.group
}
}
}
loc := findIndex(curRegion.end, curRegion.skip, line, start == 0, canMatchEnd)
if loc != nil {
if !statesOnly {
highlights[start+loc[0]] = curRegion.limitGroup
}
if curRegion.parent == nil {
if !statesOnly {
highlights[start+loc[1]] = 0
h.highlightRegion(highlights, start, false, lineNum, line[:loc[0]], curRegion, statesOnly)
}
h.highlightEmptyRegion(highlights, start+loc[1], canMatchEnd, lineNum, line[loc[1]:], statesOnly)
return highlights
}
if !statesOnly {
highlights[start+loc[1]] = curRegion.parent.group
h.highlightRegion(highlights, start, false, lineNum, line[:loc[0]], curRegion, statesOnly)
}
h.highlightRegion(highlights, start+loc[1], canMatchEnd, lineNum, line[loc[1]:], curRegion.parent, statesOnly)
return highlights
}
if len(line) == 0 || statesOnly {
if canMatchEnd {
h.lastRegion = curRegion
}
return highlights
}
firstLoc := []int{len(line), 0}
var firstRegion *region
for _, r := range curRegion.rules.regions {
loc := findIndex(r.start, nil, line, start == 0, canMatchEnd)
if loc != nil {
if loc[0] < firstLoc[0] {
firstLoc = loc
firstRegion = r
}
}
}
if firstLoc[0] != len(line) {
highlights[start+firstLoc[0]] = firstRegion.limitGroup
h.highlightRegion(highlights, start, false, lineNum, line[:firstLoc[0]], curRegion, statesOnly)
h.highlightRegion(highlights, start+firstLoc[1], canMatchEnd, lineNum, line[firstLoc[1]:], firstRegion, statesOnly)
return highlights
}
fullHighlights := make([]Group, len([]rune(string(line))))
for i := 0; i < len(fullHighlights); i++ {
fullHighlights[i] = curRegion.group
}
for _, p := range curRegion.rules.patterns {
matches := findAllIndex(p.regex, line, start == 0, canMatchEnd)
for _, m := range matches {
for i := m[0]; i < m[1]; i++ {
fullHighlights[i] = p.group
}
}
}
for i, h := range fullHighlights {
if i == 0 || h != fullHighlights[i-1] {
// if _, ok := highlights[start+i]; !ok {
highlights[start+i] = h
// }
}
}
if canMatchEnd {
h.lastRegion = curRegion
}
return highlights
}
func (h *Highlighter) highlightEmptyRegion(highlights LineMatch, start int, canMatchEnd bool, lineNum int, line []rune, statesOnly bool) LineMatch {
if len(line) == 0 {
if canMatchEnd {
h.lastRegion = nil
}
return highlights
}
firstLoc := []int{len(line), 0}
var firstRegion *region
for _, r := range h.Def.rules.regions {
loc := findIndex(r.start, nil, line, start == 0, canMatchEnd)
if loc != nil {
if loc[0] < firstLoc[0] {
firstLoc = loc
firstRegion = r
}
}
}
if firstLoc[0] != len(line) {
if !statesOnly {
highlights[start+firstLoc[0]] = firstRegion.limitGroup
}
h.highlightEmptyRegion(highlights, start, false, lineNum, line[:firstLoc[0]], statesOnly)
h.highlightRegion(highlights, start+firstLoc[1], canMatchEnd, lineNum, line[firstLoc[1]:], firstRegion, statesOnly)
return highlights
}
if statesOnly {
if canMatchEnd {
h.lastRegion = nil
}
return highlights
}
fullHighlights := make([]Group, len(line))
for _, p := range h.Def.rules.patterns {
matches := findAllIndex(p.regex, line, start == 0, canMatchEnd)
for _, m := range matches {
for i := m[0]; i < m[1]; i++ {
fullHighlights[i] = p.group
}
}
}
for i, h := range fullHighlights {
if i == 0 || h != fullHighlights[i-1] {
// if _, ok := highlights[start+i]; !ok {
highlights[start+i] = h
// }
}
}
if canMatchEnd {
h.lastRegion = nil
}
return highlights
}
// HighlightString syntax highlights a string
// Use this function for simple syntax highlighting and use the other functions for
// more advanced syntax highlighting. They are optimized for quick rehighlighting of the same
// text with minor changes made
func (h *Highlighter) HighlightString(input string) []LineMatch {
lines := strings.Split(input, "\n")
var lineMatches []LineMatch
for i := 0; i < len(lines); i++ {
line := []rune(lines[i])
highlights := make(LineMatch)
if i == 0 || h.lastRegion == nil {
lineMatches = append(lineMatches, h.highlightEmptyRegion(highlights, 0, true, i, line, false))
} else {
lineMatches = append(lineMatches, h.highlightRegion(highlights, 0, true, i, line, h.lastRegion, false))
}
}
return lineMatches
}
// HighlightStates correctly sets all states for the buffer
func (h *Highlighter) HighlightStates(input LineStates) {
for i := 0; i < input.LinesNum(); i++ {
line := []rune(input.Line(i))
// highlights := make(LineMatch)
if i == 0 || h.lastRegion == nil {
h.highlightEmptyRegion(nil, 0, true, i, line, true)
} else {
h.highlightRegion(nil, 0, true, i, line, h.lastRegion, true)
}
curState := h.lastRegion
input.SetState(i, curState)
}
}
// HighlightMatches sets the matches for each line in between startline and endline
// It sets all other matches in the buffer to nil to conserve memory
// This assumes that all the states are set correctly
func (h *Highlighter) HighlightMatches(input LineStates, startline, endline int) {
for i := startline; i < endline; i++ {
if i >= input.LinesNum() {
break
}
line := []rune(input.Line(i))
highlights := make(LineMatch)
var match LineMatch
if i == 0 || input.State(i-1) == nil {
match = h.highlightEmptyRegion(highlights, 0, true, i, line, false)
} else {
match = h.highlightRegion(highlights, 0, true, i, line, input.State(i-1), false)
}
input.SetMatch(i, match)
}
}
// ReHighlightStates will scan down from `startline` and set the appropriate end of line state
// for each line until it comes across the same state in two consecutive lines
func (h *Highlighter) ReHighlightStates(input LineStates, startline int) {
// lines := input.LineData()
h.lastRegion = nil
if startline > 0 {
h.lastRegion = input.State(startline - 1)
}
for i := startline; i < input.LinesNum(); i++ {
line := []rune(input.Line(i))
// highlights := make(LineMatch)
// var match LineMatch
if i == 0 || h.lastRegion == nil {
h.highlightEmptyRegion(nil, 0, true, i, line, true)
} else {
h.highlightRegion(nil, 0, true, i, line, h.lastRegion, true)
}
curState := h.lastRegion
lastState := input.State(i)
input.SetState(i, curState)
if curState == lastState {
break
}
}
}
// ReHighlightLine will rehighlight the state and match for a single line
func (h *Highlighter) ReHighlightLine(input LineStates, lineN int) {
line := []rune(input.Line(lineN))
highlights := make(LineMatch)
h.lastRegion = nil
if lineN > 0 {
h.lastRegion = input.State(lineN - 1)
}
var match LineMatch
if lineN == 0 || h.lastRegion == nil {
match = h.highlightEmptyRegion(highlights, 0, true, lineN, line, false)
} else {
match = h.highlightRegion(highlights, 0, true, lineN, line, h.lastRegion, false)
}
curState := h.lastRegion
input.SetMatch(lineN, match)
input.SetState(lineN, curState)
}

View File

@@ -0,0 +1,314 @@
package highlight
import (
"fmt"
"regexp"
"gopkg.in/yaml.v2"
)
// A Group represents a syntax group
type Group uint8
// Groups contains all of the groups that are defined
// You can access them in the map via their string name
var Groups map[string]Group
var numGroups Group
// String returns the group name attached to the specific group
func (g Group) String() string {
for k, v := range Groups {
if v == g {
return k
}
}
return ""
}
// A Def is a full syntax definition for a language
// It has a filetype, information about how to detect the filetype based
// on filename or header (the first line of the file)
// Then it has the rules which define how to highlight the file
type Def struct {
*Header
rules *rules
}
type Header struct {
FileType string
FtDetect [2]*regexp.Regexp
}
type File struct {
FileType string
yamlSrc map[interface{}]interface{}
}
// A Pattern is one simple syntax rule
// It has a group that the rule belongs to, as well as
// the regular expression to match the pattern
type pattern struct {
group Group
regex *regexp.Regexp
}
// rules defines which patterns and regions can be used to highlight
// a filetype
type rules struct {
regions []*region
patterns []*pattern
includes []string
}
// A region is a highlighted region (such as a multiline comment, or a string)
// It belongs to a group, and has start and end regular expressions
// A region also has rules of its own that only apply when matching inside the
// region and also rules from the above region do not match inside this region
// Note that a region may contain more regions
type region struct {
group Group
limitGroup Group
parent *region
start *regexp.Regexp
end *regexp.Regexp
skip *regexp.Regexp
rules *rules
}
func init() {
Groups = make(map[string]Group)
}
func ParseFtDetect(file *File) (r [2]*regexp.Regexp, err error) {
rules := file.yamlSrc
loaded := 0
for k, v := range rules {
if k == "detect" {
ftdetect := v.(map[interface{}]interface{})
if len(ftdetect) >= 1 {
syntax, err := regexp.Compile(ftdetect["filename"].(string))
if err != nil {
return r, err
}
r[0] = syntax
}
if len(ftdetect) >= 2 {
header, err := regexp.Compile(ftdetect["header"].(string))
if err != nil {
return r, err
}
r[1] = header
}
loaded++
}
if loaded >= 2 {
break
}
}
return r, err
}
func ParseFile(input []byte) (f *File, err error) {
// This is just so if we have an error, we can exit cleanly and return the parse error to the user
defer func() {
if e := recover(); e != nil {
err = e.(error)
}
}()
var rules map[interface{}]interface{}
if err = yaml.Unmarshal(input, &rules); err != nil {
return nil, err
}
f = new(File)
f.yamlSrc = rules
for k, v := range rules {
if k == "filetype" {
filetype := v.(string)
f.FileType = filetype
break
}
}
return f, err
}
// ParseDef parses an input syntax file into a highlight Def
func ParseDef(f *File, header *Header) (s *Def, err error) {
// This is just so if we have an error, we can exit cleanly and return the parse error to the user
defer func() {
if e := recover(); e != nil {
err = e.(error)
}
}()
rules := f.yamlSrc
s = new(Def)
s.Header = header
for k, v := range rules {
if k == "rules" {
inputRules := v.([]interface{})
rules, err := parseRules(inputRules, nil)
if err != nil {
return nil, err
}
s.rules = rules
}
}
return s, err
}
// ResolveIncludes will sort out the rules for including other filetypes
// You should call this after parsing all the Defs
func ResolveIncludes(def *Def, files []*File) {
resolveIncludesInDef(files, def)
}
func resolveIncludesInDef(files []*File, d *Def) {
for _, lang := range d.rules.includes {
for _, searchFile := range files {
if lang == searchFile.FileType {
searchDef, _ := ParseDef(searchFile, nil)
d.rules.patterns = append(d.rules.patterns, searchDef.rules.patterns...)
d.rules.regions = append(d.rules.regions, searchDef.rules.regions...)
}
}
}
for _, r := range d.rules.regions {
resolveIncludesInRegion(files, r)
r.parent = nil
}
}
func resolveIncludesInRegion(files []*File, region *region) {
for _, lang := range region.rules.includes {
for _, searchFile := range files {
if lang == searchFile.FileType {
searchDef, _ := ParseDef(searchFile, nil)
region.rules.patterns = append(region.rules.patterns, searchDef.rules.patterns...)
region.rules.regions = append(region.rules.regions, searchDef.rules.regions...)
}
}
}
for _, r := range region.rules.regions {
resolveIncludesInRegion(files, r)
r.parent = region
}
}
func parseRules(input []interface{}, curRegion *region) (*rules, error) {
rules := new(rules)
for _, v := range input {
rule := v.(map[interface{}]interface{})
for k, val := range rule {
group := k
switch object := val.(type) {
case string:
if k == "include" {
rules.includes = append(rules.includes, object)
} else {
// Pattern
r, err := regexp.Compile(object)
if err != nil {
return nil, err
}
groupStr := group.(string)
if _, ok := Groups[groupStr]; !ok {
numGroups++
Groups[groupStr] = numGroups
}
groupNum := Groups[groupStr]
rules.patterns = append(rules.patterns, &pattern{groupNum, r})
}
case map[interface{}]interface{}:
// region
region, err := parseRegion(group.(string), object, curRegion)
if err != nil {
return nil, err
}
rules.regions = append(rules.regions, region)
default:
return nil, fmt.Errorf("Bad type %T", object)
}
}
}
return rules, nil
}
func parseRegion(group string, regionInfo map[interface{}]interface{}, prevRegion *region) (*region, error) {
var err error
region := new(region)
if _, ok := Groups[group]; !ok {
numGroups++
Groups[group] = numGroups
}
groupNum := Groups[group]
region.group = groupNum
region.parent = prevRegion
region.start, err = regexp.Compile(regionInfo["start"].(string))
if err != nil {
return nil, err
}
region.end, err = regexp.Compile(regionInfo["end"].(string))
if err != nil {
return nil, err
}
// skip is optional
if _, ok := regionInfo["skip"]; ok {
region.skip, err = regexp.Compile(regionInfo["skip"].(string))
if err != nil {
return nil, err
}
}
// limit-color is optional
if _, ok := regionInfo["limit-group"]; ok {
groupStr := regionInfo["limit-group"].(string)
if _, ok := Groups[groupStr]; !ok {
numGroups++
Groups[groupStr] = numGroups
}
groupNum := Groups[groupStr]
region.limitGroup = groupNum
if err != nil {
return nil, err
}
} else {
region.limitGroup = region.group
}
region.rules, err = parseRules(regionInfo["rules"].([]interface{}), region)
if err != nil {
return nil, err
}
return region, nil
}

View File

@@ -1,368 +1,28 @@
package main
import (
"regexp"
"strings"
import "github.com/zyedidia/micro/cmd/micro/highlight"
"github.com/zyedidia/tcell"
)
var syntaxFiles []*highlight.File
// FileTypeRules represents a complete set of syntax rules for a filetype
type FileTypeRules struct {
filetype string
filename string
text string
}
// SyntaxRule represents a regex to highlight in a certain style
type SyntaxRule struct {
// What to highlight
regex *regexp.Regexp
// Any flags
flags string
// Whether this regex is a start=... end=... regex
startend bool
// How to highlight it
style tcell.Style
}
var syntaxKeys [][2]*regexp.Regexp
var syntaxFiles map[[2]*regexp.Regexp]FileTypeRules
// LoadSyntaxFiles loads the syntax files from the default directory (configDir)
func LoadSyntaxFiles() {
InitColorscheme()
syntaxFiles = make(map[[2]*regexp.Regexp]FileTypeRules)
for _, f := range ListRuntimeFiles(RTSyntax) {
data, err := f.Data()
if err != nil {
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
} else {
LoadSyntaxFile(string(data), f.Name())
LoadSyntaxFile(data, f.Name())
}
}
}
// JoinRule takes a syntax rule (which can be multiple regular expressions)
// and joins it into one regular expression by ORing everything together
func JoinRule(rule string) string {
split := strings.Split(rule, `" "`)
joined := strings.Join(split, ")|(")
joined = "(" + joined + ")"
return joined
}
// LoadSyntaxFile simply gets the filetype of a the syntax file and the source for the
// file and creates FileTypeRules out of it. If this filetype is the one opened by the user
// the rules will be loaded and compiled later
// In this function we are only concerned with loading the syntax and header regexes
func LoadSyntaxFile(text, filename string) {
var err error
lines := strings.Split(string(text), "\n")
// Regex for parsing syntax statements
syntaxParser := regexp.MustCompile(`syntax "(.*?)"\s+"(.*)"+`)
// Regex for parsing header statements
headerParser := regexp.MustCompile(`header "(.*)"`)
// Is there a syntax definition in this file?
hasSyntax := syntaxParser.MatchString(text)
// Is there a header definition in this file?
hasHeader := headerParser.MatchString(text)
var syntaxRegex *regexp.Regexp
var headerRegex *regexp.Regexp
var filetype string
for lineNum, line := range lines {
if (hasSyntax == (syntaxRegex != nil)) && (hasHeader == (headerRegex != nil)) {
// We found what we we're supposed to find
break
}
if strings.TrimSpace(line) == "" ||
strings.TrimSpace(line)[0] == '#' {
// Ignore this line
continue
}
if strings.HasPrefix(line, "syntax") {
// Syntax statement
syntaxMatches := syntaxParser.FindSubmatch([]byte(line))
if len(syntaxMatches) == 3 {
if syntaxRegex != nil {
TermError(filename, lineNum, "Syntax statement redeclaration")
}
filetype = string(syntaxMatches[1])
extensions := JoinRule(string(syntaxMatches[2]))
syntaxRegex, err = regexp.Compile(extensions)
if err != nil {
TermError(filename, lineNum, err.Error())
continue
}
} else {
TermError(filename, lineNum, "Syntax statement is not valid: "+line)
continue
}
} else if strings.HasPrefix(line, "header") {
// Header statement
headerMatches := headerParser.FindSubmatch([]byte(line))
if len(headerMatches) == 2 {
header := JoinRule(string(headerMatches[1]))
headerRegex, err = regexp.Compile(header)
if err != nil {
TermError(filename, lineNum, "Regex error: "+err.Error())
continue
}
} else {
TermError(filename, lineNum, "Header statement is not valid: "+line)
continue
}
}
}
if syntaxRegex != nil {
// Add the current rules to the syntaxFiles variable
regexes := [2]*regexp.Regexp{syntaxRegex, headerRegex}
syntaxKeys = append(syntaxKeys, regexes)
syntaxFiles[regexes] = FileTypeRules{filetype, filename, text}
}
}
// LoadRulesFromFile loads just the syntax rules from a given file
// Only the necessary rules are loaded when the buffer is opened.
// If we load all the rules for every filetype when micro starts, there's a bit of lag
// A rule just explains how to color certain regular expressions
// Example: color comment "//.*"
// This would color all strings that match the regex "//.*" in the comment color defined
// by the colorscheme
func LoadRulesFromFile(text, filename string) []SyntaxRule {
lines := strings.Split(string(text), "\n")
// Regex for parsing standard syntax rules
ruleParser := regexp.MustCompile(`color (.*?)\s+(?:\((.*?)\)\s+)?"(.*)"`)
// Regex for parsing syntax rules with start="..." end="..."
ruleStartEndParser := regexp.MustCompile(`color (.*?)\s+(?:\((.*?)\)\s+)?start="(.*)"\s+end="(.*)"`)
var rules []SyntaxRule
for lineNum, line := range lines {
if strings.TrimSpace(line) == "" ||
strings.TrimSpace(line)[0] == '#' ||
strings.HasPrefix(line, "syntax") ||
strings.HasPrefix(line, "header") {
// Ignore this line
continue
}
// Syntax rule, but it could be standard or start-end
if ruleParser.MatchString(line) {
// Standard syntax rule
// Parse the line
submatch := ruleParser.FindSubmatch([]byte(line))
var color string
var regexStr string
var flags string
if len(submatch) == 4 {
// If len is 4 then the user specified some additional flags to use
color = string(submatch[1])
flags = string(submatch[2])
regexStr = "(?" + flags + ")" + JoinRule(string(submatch[3]))
} else if len(submatch) == 3 {
// If len is 3, no additional flags were given
color = string(submatch[1])
regexStr = JoinRule(string(submatch[2]))
} else {
// If len is not 3 or 4 there is a problem
TermError(filename, lineNum, "Invalid statement: "+line)
continue
}
// Compile the regex
regex, err := regexp.Compile(regexStr)
if err != nil {
TermError(filename, lineNum, err.Error())
continue
}
// Get the style
// The user could give us a "color" that is really a part of the colorscheme
// in which case we should look that up in the colorscheme
// They can also just give us a straight up color
st := defStyle
groups := strings.Split(color, ".")
if len(groups) > 1 {
curGroup := ""
for i, g := range groups {
if i != 0 {
curGroup += "."
}
curGroup += g
if style, ok := colorscheme[curGroup]; ok {
st = style
}
}
} else if style, ok := colorscheme[color]; ok {
st = style
} else {
st = StringToStyle(color)
}
// Add the regex, flags, and style
// False because this is not start-end
rules = append(rules, SyntaxRule{regex, flags, false, st})
} else if ruleStartEndParser.MatchString(line) {
// Start-end syntax rule
submatch := ruleStartEndParser.FindSubmatch([]byte(line))
var color string
var start string
var end string
// Use m and s flags by default
flags := "ms"
if len(submatch) == 5 {
// If len is 5 the user provided some additional flags
color = string(submatch[1])
flags += string(submatch[2])
start = string(submatch[3])
end = string(submatch[4])
} else if len(submatch) == 4 {
// If len is 4 the user did not provide additional flags
color = string(submatch[1])
start = string(submatch[2])
end = string(submatch[3])
} else {
// If len is not 4 or 5 there is a problem
TermError(filename, lineNum, "Invalid statement: "+line)
continue
}
// Compile the regex
regex, err := regexp.Compile("(?" + flags + ")" + "(" + start + ").*?(" + end + ")")
if err != nil {
TermError(filename, lineNum, err.Error())
continue
}
// Get the style
// The user could give us a "color" that is really a part of the colorscheme
// in which case we should look that up in the colorscheme
// They can also just give us a straight up color
st := defStyle
if _, ok := colorscheme[color]; ok {
st = colorscheme[color]
} else {
st = StringToStyle(color)
}
// Add the regex, flags, and style
// True because this is start-end
rules = append(rules, SyntaxRule{regex, flags, true, st})
}
}
return rules
}
// FindFileType finds the filetype for the given buffer
func FindFileType(buf *Buffer) string {
for _, r := range syntaxKeys {
if r[1] != nil && r[1].MatchString(buf.Line(0)) {
// The header statement matches the first line
return syntaxFiles[r].filetype
}
}
for _, r := range syntaxKeys {
if r[0] != nil && r[0].MatchString(buf.Path) {
// The syntax statement matches the extension
return syntaxFiles[r].filetype
}
}
return "Unknown"
}
// GetRules finds the syntax rules that should be used for the buffer
// and returns them. It also returns the filetype of the file
func GetRules(buf *Buffer) []SyntaxRule {
for _, r := range syntaxKeys {
if syntaxFiles[r].filetype == buf.FileType() {
return LoadRulesFromFile(syntaxFiles[r].text, syntaxFiles[r].filename)
}
}
return nil
}
// SyntaxMatches is an alias to a map from character numbers to styles,
// so map[3] represents the style of the third character
type SyntaxMatches [][]tcell.Style
// Match takes a buffer and returns the syntax matches: a 2d array specifying how it should be syntax highlighted
// We match the rules from up `synLinesUp` lines and down `synLinesDown` lines
func Match(v *View) SyntaxMatches {
buf := v.Buf
rules := v.Buf.rules
viewStart := v.Topline
viewEnd := v.Topline + v.Height
if viewEnd > buf.NumLines {
viewEnd = buf.NumLines
}
lines := buf.Lines(viewStart, viewEnd)
matches := make(SyntaxMatches, len(lines))
for i, line := range lines {
matches[i] = make([]tcell.Style, len(line)+1)
for j := range matches[i] {
matches[i][j] = defStyle
}
}
// We don't actually check the entire buffer, just from synLinesUp to synLinesDown
totalStart := v.Topline - synLinesUp
totalEnd := v.Topline + v.Height + synLinesDown
if totalStart < 0 {
totalStart = 0
}
if totalEnd > buf.NumLines {
totalEnd = buf.NumLines
}
str := strings.Join(buf.Lines(totalStart, totalEnd), "\n")
startNum := ToCharPos(Loc{0, totalStart}, v.Buf)
for _, rule := range rules {
if rule.startend {
if indicies := rule.regex.FindAllStringIndex(str, -1); indicies != nil {
for _, value := range indicies {
value[0] = runePos(value[0], str) + startNum
value[1] = runePos(value[1], str) + startNum
startLoc := FromCharPos(value[0], buf)
endLoc := FromCharPos(value[1], buf)
for curLoc := startLoc; curLoc.LessThan(endLoc); curLoc = curLoc.Move(1, buf) {
if curLoc.Y < v.Topline {
continue
}
colNum, lineNum := curLoc.X, curLoc.Y
if lineNum == -1 || colNum == -1 {
continue
}
lineNum -= viewStart
if lineNum >= 0 && lineNum < v.Height {
matches[lineNum][colNum] = rule.style
}
}
}
}
} else {
for lineN, line := range lines {
if indicies := rule.regex.FindAllStringIndex(line, -1); indicies != nil {
for _, value := range indicies {
start := runePos(value[0], line)
end := runePos(value[1], line)
for i := start; i < end; i++ {
matches[lineN][i] = rule.style
}
}
}
}
}
}
return matches
func LoadSyntaxFile(text []byte, filename string) {
f, err := highlight.ParseFile(text)
if err != nil {
TermMessage("Syntax file error: " + filename + ": " + err.Error())
return
}
syntaxFiles = append(syntaxFiles, f)
}

View File

@@ -4,7 +4,6 @@ import (
"bytes"
"io"
"os/exec"
"strings"
)
// Jobs are the way plugins can run processes in the background
@@ -43,10 +42,7 @@ func (f *CallbackFile) Write(data []byte) (int, error) {
// JobStart starts a shell command in the background with the given callbacks
// It returns an *exec.Cmd as the job id
func JobStart(cmd string, onStdout, onStderr, onExit string, userargs ...string) *exec.Cmd {
split := strings.Split(cmd, " ")
cmdArgs := split[1:]
cmdName := split[0]
return JobSpawn(cmdName, cmdArgs, onStdout, onStderr, onExit, userargs...)
return JobSpawn("sh", []string{"-c", cmd}, onStdout, onStderr, onExit, userargs...)
}
// JobSpawn starts a process with args in the background with the given callbacks

View File

@@ -2,9 +2,10 @@ package main
import (
"bufio"
"bytes"
"io"
"unicode/utf8"
"github.com/zyedidia/micro/cmd/micro/highlight"
)
func runeToByteIndex(n int, txt []byte) int {
@@ -28,30 +29,74 @@ func runeToByteIndex(n int, txt []byte) int {
return count
}
type Line struct {
data []byte
state highlight.State
match highlight.LineMatch
rehighlight bool
}
// A LineArray simply stores and array of lines and makes it easy to insert
// and delete in it
type LineArray struct {
lines [][]byte
lines []Line
}
func Append(slice []Line, data ...Line) []Line {
l := len(slice)
if l+len(data) > cap(slice) { // reallocate
// Allocate double what's needed, for future growth.
newSlice := make([]Line, (l+len(data))+10000)
// The copy function is predeclared and works for any slice type.
copy(newSlice, slice)
slice = newSlice
}
slice = slice[0 : l+len(data)]
for i, c := range data {
slice[l+i] = c
}
return slice
}
// NewLineArray returns a new line array from an array of bytes
func NewLineArray(reader io.Reader) *LineArray {
func NewLineArray(size int64, reader io.Reader) *LineArray {
la := new(LineArray)
br := bufio.NewReader(reader)
i := 0
la.lines = make([]Line, 0, 1000)
br := bufio.NewReader(reader)
var loaded int
n := 0
for {
data, err := br.ReadBytes('\n')
if n >= 1000 && loaded >= 0 {
totalLinesNum := int(float64(size) * (float64(n) / float64(loaded)))
newSlice := make([]Line, len(la.lines), totalLinesNum+10000)
// The copy function is predeclared and works for any slice type.
copy(newSlice, la.lines)
la.lines = newSlice
loaded = -1
}
if loaded >= 0 {
loaded += len(data)
}
if err != nil {
if err == io.EOF {
la.lines = append(la.lines, data[:len(data)])
la.lines = Append(la.lines, Line{data[:len(data)], nil, nil, false})
// la.lines = Append(la.lines, Line{data[:len(data)]})
}
// Last line was read
break
} else {
la.lines = append(la.lines, data[:len(data)-1])
// la.lines = Append(la.lines, Line{data[:len(data)-1]})
la.lines = Append(la.lines, Line{data[:len(data)-1], nil, nil, false})
}
i++
n++
}
return la
@@ -59,19 +104,26 @@ func NewLineArray(reader io.Reader) *LineArray {
// Returns the String representation of the LineArray
func (la *LineArray) String() string {
return string(bytes.Join(la.lines, []byte("\n")))
str := ""
for i, l := range la.lines {
str += string(l.data)
if i != len(la.lines)-1 {
str += "\n"
}
}
return str
}
// NewlineBelow adds a newline below the given line number
func (la *LineArray) NewlineBelow(y int) {
la.lines = append(la.lines, []byte(" "))
la.lines = append(la.lines, Line{[]byte(" "), nil, nil, false})
copy(la.lines[y+2:], la.lines[y+1:])
la.lines[y+1] = []byte("")
la.lines[y+1] = Line{[]byte(""), la.lines[y].state, nil, false}
}
// inserts a byte array at a given location
func (la *LineArray) insert(pos Loc, value []byte) {
x, y := runeToByteIndex(pos.X, la.lines[pos.Y]), pos.Y
x, y := runeToByteIndex(pos.X, la.lines[pos.Y].data), pos.Y
// x, y := pos.x, pos.y
for i := 0; i < len(value); i++ {
if value[i] == '\n' {
@@ -87,31 +139,36 @@ func (la *LineArray) insert(pos Loc, value []byte) {
// inserts a byte at a given location
func (la *LineArray) insertByte(pos Loc, value byte) {
la.lines[pos.Y] = append(la.lines[pos.Y], 0)
copy(la.lines[pos.Y][pos.X+1:], la.lines[pos.Y][pos.X:])
la.lines[pos.Y][pos.X] = value
la.lines[pos.Y].data = append(la.lines[pos.Y].data, 0)
copy(la.lines[pos.Y].data[pos.X+1:], la.lines[pos.Y].data[pos.X:])
la.lines[pos.Y].data[pos.X] = value
}
// JoinLines joins the two lines a and b
func (la *LineArray) JoinLines(a, b int) {
la.insert(Loc{len(la.lines[a]), a}, la.lines[b])
la.insert(Loc{len(la.lines[a].data), a}, la.lines[b].data)
la.DeleteLine(b)
}
// Split splits a line at a given position
func (la *LineArray) Split(pos Loc) {
la.NewlineBelow(pos.Y)
la.insert(Loc{0, pos.Y + 1}, la.lines[pos.Y][pos.X:])
la.insert(Loc{0, pos.Y + 1}, la.lines[pos.Y].data[pos.X:])
la.lines[pos.Y+1].state = la.lines[pos.Y].state
la.lines[pos.Y].state = nil
la.lines[pos.Y].match = nil
la.lines[pos.Y+1].match = nil
la.lines[pos.Y].rehighlight = true
la.DeleteToEnd(Loc{pos.X, pos.Y})
}
// removes from start to end
func (la *LineArray) remove(start, end Loc) string {
sub := la.Substr(start, end)
startX := runeToByteIndex(start.X, la.lines[start.Y])
endX := runeToByteIndex(end.X, la.lines[end.Y])
startX := runeToByteIndex(start.X, la.lines[start.Y].data)
endX := runeToByteIndex(end.X, la.lines[end.Y].data)
if start.Y == end.Y {
la.lines[start.Y] = append(la.lines[start.Y][:startX], la.lines[start.Y][endX:]...)
la.lines[start.Y].data = append(la.lines[start.Y].data[:startX], la.lines[start.Y].data[endX:]...)
} else {
for i := start.Y + 1; i <= end.Y-1; i++ {
la.DeleteLine(start.Y + 1)
@@ -125,12 +182,12 @@ func (la *LineArray) remove(start, end Loc) string {
// DeleteToEnd deletes from the end of a line to the position
func (la *LineArray) DeleteToEnd(pos Loc) {
la.lines[pos.Y] = la.lines[pos.Y][:pos.X]
la.lines[pos.Y].data = la.lines[pos.Y].data[:pos.X]
}
// DeleteFromStart deletes from the start of a line to the position
func (la *LineArray) DeleteFromStart(pos Loc) {
la.lines[pos.Y] = la.lines[pos.Y][pos.X+1:]
la.lines[pos.Y].data = la.lines[pos.Y].data[pos.X+1:]
}
// DeleteLine deletes the line number
@@ -140,21 +197,37 @@ func (la *LineArray) DeleteLine(y int) {
// DeleteByte deletes the byte at a position
func (la *LineArray) DeleteByte(pos Loc) {
la.lines[pos.Y] = la.lines[pos.Y][:pos.X+copy(la.lines[pos.Y][pos.X:], la.lines[pos.Y][pos.X+1:])]
la.lines[pos.Y].data = la.lines[pos.Y].data[:pos.X+copy(la.lines[pos.Y].data[pos.X:], la.lines[pos.Y].data[pos.X+1:])]
}
// Substr returns the string representation between two locations
func (la *LineArray) Substr(start, end Loc) string {
startX := runeToByteIndex(start.X, la.lines[start.Y])
endX := runeToByteIndex(end.X, la.lines[end.Y])
startX := runeToByteIndex(start.X, la.lines[start.Y].data)
endX := runeToByteIndex(end.X, la.lines[end.Y].data)
if start.Y == end.Y {
return string(la.lines[start.Y][startX:endX])
return string(la.lines[start.Y].data[startX:endX])
}
var str string
str += string(la.lines[start.Y][startX:]) + "\n"
str += string(la.lines[start.Y].data[startX:]) + "\n"
for i := start.Y + 1; i <= end.Y-1; i++ {
str += string(la.lines[i]) + "\n"
str += string(la.lines[i].data) + "\n"
}
str += string(la.lines[end.Y][:endX])
str += string(la.lines[end.Y].data[:endX])
return str
}
func (la *LineArray) State(lineN int) highlight.State {
return la.lines[lineN].state
}
func (la *LineArray) SetState(lineN int, s highlight.State) {
la.lines[lineN].state = s
}
func (la *LineArray) SetMatch(lineN int, m highlight.LineMatch) {
la.lines[lineN].match = m
}
func (la *LineArray) Match(lineN int) highlight.LineMatch {
return la.lines[lineN].match
}

View File

@@ -6,7 +6,6 @@ import (
"fmt"
"os"
"strconv"
"strings"
"github.com/zyedidia/clipboard"
"github.com/zyedidia/tcell"
@@ -79,7 +78,7 @@ func (m *Messenger) AddLog(msg string) {
func (m *Messenger) getBuffer() *Buffer {
if m.log == nil {
m.log = NewBuffer(strings.NewReader(""), "")
m.log = NewBufferFromString("", "")
m.log.name = "Log"
}
return m.log
@@ -87,36 +86,68 @@ func (m *Messenger) getBuffer() *Buffer {
// Message sends a message to the user
func (m *Messenger) Message(msg ...interface{}) {
m.message = fmt.Sprint(msg...)
m.style = defStyle
displayMessage := fmt.Sprint(msg...)
// only display a new message if there isn't an active prompt
// this is to prevent overwriting an existing prompt to the user
if m.hasPrompt == false {
// if there is no active prompt then style and display the message as normal
m.message = displayMessage
if _, ok := colorscheme["message"]; ok {
m.style = colorscheme["message"]
m.style = defStyle
if _, ok := colorscheme["message"]; ok {
m.style = colorscheme["message"]
}
m.hasMessage = true
}
m.AddLog(m.message)
m.hasMessage = true
// add the message to the log regardless of active prompts
m.AddLog(displayMessage)
}
// Error sends an error message to the user
func (m *Messenger) Error(msg ...interface{}) {
buf := new(bytes.Buffer)
fmt.Fprint(buf, msg...)
m.message = buf.String()
m.style = defStyle.
Foreground(tcell.ColorBlack).
Background(tcell.ColorMaroon)
if _, ok := colorscheme["error-message"]; ok {
m.style = colorscheme["error-message"]
// only display a new message if there isn't an active prompt
// this is to prevent overwriting an existing prompt to the user
if m.hasPrompt == false {
// if there is no active prompt then style and display the message as normal
m.message = buf.String()
m.style = defStyle.
Foreground(tcell.ColorBlack).
Background(tcell.ColorMaroon)
if _, ok := colorscheme["error-message"]; ok {
m.style = colorscheme["error-message"]
}
m.hasMessage = true
}
m.AddLog(m.message)
// add the message to the log regardless of active prompts
m.AddLog(buf.String())
}
func (m *Messenger) PromptText(msg ...interface{}) {
displayMessage := fmt.Sprint(msg...)
// if there is no active prompt then style and display the message as normal
m.message = displayMessage
m.style = defStyle
if _, ok := colorscheme["message"]; ok {
m.style = colorscheme["message"]
}
m.hasMessage = true
// add the message to the log regardless of active prompts
m.AddLog(displayMessage)
}
// YesNoPrompt asks the user a yes or no question (waits for y or n) and returns the result
func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
m.hasPrompt = true
m.Message(prompt)
m.PromptText(prompt)
_, h := screen.Size()
for {
@@ -130,17 +161,19 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
case *tcell.EventKey:
switch e.Key() {
case tcell.KeyRune:
if e.Rune() == 'y' {
if e.Rune() == 'y' || e.Rune() == 'Y' {
m.AddLog("\t--> y")
m.hasPrompt = false
return true, false
} else if e.Rune() == 'n' {
} else if e.Rune() == 'n' || e.Rune() == 'N' {
m.AddLog("\t--> n")
m.hasPrompt = false
return false, false
}
case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
m.AddLog("\t--> (cancel)")
m.Clear()
m.Reset()
m.hasPrompt = false
return false, true
}
@@ -151,7 +184,7 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
// LetterPrompt gives the user a prompt and waits for a one letter response
func (m *Messenger) LetterPrompt(prompt string, responses ...rune) (rune, bool) {
m.hasPrompt = true
m.Message(prompt)
m.PromptText(prompt)
_, h := screen.Size()
for {
@@ -201,7 +234,7 @@ const (
// This function blocks the main loop while waiting for input
func (m *Messenger) Prompt(prompt, placeholder, historyType string, completionTypes ...Completion) (string, bool) {
m.hasPrompt = true
m.Message(prompt)
m.PromptText(prompt)
if _, ok := m.history[historyType]; !ok {
m.history[historyType] = []string{""}
} else {

View File

@@ -11,13 +11,13 @@ import (
"time"
"github.com/go-errors/errors"
"github.com/layeh/gopher-luar"
"github.com/mattn/go-isatty"
"github.com/mitchellh/go-homedir"
"github.com/yuin/gopher-lua"
"github.com/zyedidia/clipboard"
"github.com/zyedidia/tcell"
"github.com/zyedidia/tcell/encoding"
"layeh.com/gopher-luar"
)
const (
@@ -84,30 +84,36 @@ func LoadInput() []*Buffer {
var filename string
var input []byte
var err error
var buffers []*Buffer
args := flag.Args()
buffers := make([]*Buffer, 0, len(args))
if len(flag.Args()) > 0 {
if len(args) > 0 {
// Option 1
// We go through each file and load it
for i := 0; i < len(flag.Args()); i++ {
filename = flag.Args()[i]
for i := 0; i < len(args); i++ {
filename = args[i]
// Check that the file exists
var input *os.File
if _, e := os.Stat(filename); e == nil {
// If it exists we load it into a buffer
input, err = os.Open(filename)
stat, _ := input.Stat()
defer input.Close()
if err != nil {
TermMessage(err)
continue
}
if stat.IsDir() {
TermMessage("Cannot read", filename, "because it is a directory")
continue
}
}
// If the file didn't exist, input will be empty, and we'll open an empty buffer
if input != nil {
buffers = append(buffers, NewBuffer(input, filename))
buffers = append(buffers, NewBuffer(input, FSize(input), filename))
} else {
buffers = append(buffers, NewBuffer(strings.NewReader(""), filename))
buffers = append(buffers, NewBufferFromString("", filename))
}
}
} else if !isatty.IsTerminal(os.Stdin.Fd()) {
@@ -119,10 +125,10 @@ func LoadInput() []*Buffer {
TermMessage("Error reading from stdin: ", err)
input = []byte{}
}
buffers = append(buffers, NewBuffer(strings.NewReader(string(input)), filename))
buffers = append(buffers, NewBufferFromString(string(input), filename))
} else {
// Option 3, just open an empty buffer
buffers = append(buffers, NewBuffer(strings.NewReader(string(input)), filename))
buffers = append(buffers, NewBufferFromString(string(input), filename))
}
return buffers
@@ -196,6 +202,14 @@ func InitScreen() {
// RedrawAll redraws everything -- all the views and the messenger
func RedrawAll() {
messenger.Clear()
w, h := screen.Size()
for x := 0; x < w; x++ {
for y := 0; y < h; y++ {
screen.SetContent(x, y, ' ', nil, defStyle)
}
}
for _, v := range tabs[curTab].views {
v.Display()
}
@@ -217,14 +231,11 @@ func LoadAll() {
InitCommands()
InitBindings()
LoadSyntaxFiles()
InitColorscheme()
for _, tab := range tabs {
for _, v := range tab.views {
v.Buf.UpdateRules()
if v.Buf.Settings["syntax"].(bool) {
v.matches = Match(v)
}
}
}
}
@@ -303,6 +314,7 @@ func main() {
screen.Fini()
os.Exit(1)
}
for _, buf := range buffers {
// For each buffer we create a new tab and place the view in that tab
tab := NewTabFromView(NewView(buf))
@@ -366,6 +378,7 @@ func main() {
L.SetGlobal("ListRuntimeFiles", luar.New(L, PluginListRuntimeFiles))
L.SetGlobal("AddRuntimeFile", luar.New(L, PluginAddRuntimeFile))
L.SetGlobal("AddRuntimeFilesFromDirectory", luar.New(L, PluginAddRuntimeFilesFromDirectory))
L.SetGlobal("AddRuntimeFileFromMemory", luar.New(L, PluginAddRuntimeFileFromMemory))
jobs = make(chan JobFunction, 100)
events = make(chan tcell.Event, 100)
@@ -373,26 +386,20 @@ func main() {
LoadPlugins()
// Load the syntax files, including the colorscheme
LoadSyntaxFiles()
for _, t := range tabs {
for _, v := range t.views {
v.Buf.FindFileType()
v.Buf.UpdateRules()
for _, pl := range loadedPlugins {
for pl := range loadedPlugins {
_, err := Call(pl+".onViewOpen", v)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)
continue
}
}
if v.Buf.Settings["syntax"].(bool) {
v.matches = Match(v)
}
}
}
InitColorscheme()
// Here is the event loop which runs in a separate thread
go func() {
for {
@@ -428,26 +435,32 @@ func main() {
for event != nil {
switch e := event.(type) {
case *tcell.EventResize:
for _, t := range tabs {
t.Resize()
}
case *tcell.EventMouse:
if e.Buttons() == tcell.Button1 {
// If the user left clicked we check a couple things
_, h := screen.Size()
x, y := e.Position()
if y == h-1 && messenger.message != "" && globalSettings["infobar"].(bool) {
// If the user clicked in the bottom bar, and there is a message down there
// we copy it to the clipboard.
// Often error messages are displayed down there so it can be useful to easily
// copy the message
clipboard.WriteAll(messenger.message, "primary")
break
}
if !searching {
if e.Buttons() == tcell.Button1 {
// If the user left clicked we check a couple things
_, h := screen.Size()
x, y := e.Position()
if y == h-1 && messenger.message != "" && globalSettings["infobar"].(bool) {
// If the user clicked in the bottom bar, and there is a message down there
// we copy it to the clipboard.
// Often error messages are displayed down there so it can be useful to easily
// copy the message
clipboard.WriteAll(messenger.message, "primary")
break
}
if CurView().mouseReleased {
// We loop through each view in the current tab and make sure the current view
// is the one being clicked in
for _, v := range tabs[curTab].views {
if x >= v.x && x < v.x+v.Width && y >= v.y && y < v.y+v.Height {
tabs[curTab].CurView = v.Num
if CurView().mouseReleased {
// We loop through each view in the current tab and make sure the current view
// is the one being clicked in
for _, v := range tabs[curTab].views {
if x >= v.x && x < v.x+v.Width && y >= v.y && y < v.y+v.Height {
tabs[curTab].CurView = v.Num
}
}
}
}
@@ -475,7 +488,6 @@ func main() {
default:
event = nil
}
}
}
}

View File

@@ -6,11 +6,11 @@ import (
"os"
"strings"
"github.com/layeh/gopher-luar"
"github.com/yuin/gopher-lua"
"layeh.com/gopher-luar"
)
var loadedPlugins []string
var loadedPlugins map[string]string
// Call calls the lua function 'function'
// If it does not exist nothing happens, if there is an error,
@@ -112,32 +112,39 @@ func LuaFunctionJob(function string) func(string, ...string) {
}
}
// luaPluginName convert a human-friendly plugin name into a valid lua variable name.
func luaPluginName(name string) string {
return strings.Replace(name, "-", "_", -1)
}
// LoadPlugins loads the pre-installed plugins and the plugins located in ~/.config/micro/plugins
func LoadPlugins() {
loadedPlugins = make(map[string]string)
for _, plugin := range ListRuntimeFiles(RTPlugin) {
alreadyExists := false
pluginName := plugin.Name()
for _, pl := range loadedPlugins {
if pl == pluginName {
alreadyExists = true
break
}
if _, ok := loadedPlugins[pluginName]; ok {
continue
}
if !alreadyExists {
data, err := plugin.Data()
if err != nil {
TermMessage("Error loading plugin: " + pluginName)
continue
}
pluginDef := "\nlocal P = {}\n" + pluginName + " = P\nsetmetatable(" + pluginName + ", {__index = _G})\nsetfenv(1, P)\n"
if err := L.DoString(pluginDef + string(data)); err != nil {
TermMessage(err)
continue
}
loadedPlugins = append(loadedPlugins, pluginName)
data, err := plugin.Data()
if err != nil {
TermMessage("Error loading plugin: " + pluginName)
continue
}
pluginLuaName := luaPluginName(pluginName)
pluginDef := "\nlocal P = {}\n" + pluginLuaName + " = P\nsetmetatable(" + pluginLuaName + ", {__index = _G})\nsetfenv(1, P)\n"
if err := L.DoString(pluginDef + string(data)); err != nil {
TermMessage(err)
continue
}
loadedPlugins[pluginName] = pluginLuaName
}
if _, err := os.Stat(configDir + "/init.lua"); err == nil {
@@ -146,6 +153,6 @@ func LoadPlugins() {
if err := L.DoString(pluginDef + string(data)); err != nil {
TermMessage(err)
}
loadedPlugins = append(loadedPlugins, "init")
loadedPlugins["init"] = "init"
}
}

View File

@@ -358,8 +358,8 @@ func GetInstalledVersions(withCore bool) PluginVersions {
result = append(result, newStaticPluginVersion(CorePluginName, Version))
}
for _, name := range loadedPlugins {
version := GetInstalledPluginVersion(name)
for name, lpname := range loadedPlugins {
version := GetInstalledPluginVersion(lpname)
if pv := newStaticPluginVersion(name, version); pv != nil {
result = append(result, pv)
}
@@ -561,7 +561,9 @@ func (pv PluginVersions) install() {
func UninstallPlugin(name string) {
if err := os.RemoveAll(filepath.Join(configDir, "plugins", name)); err != nil {
messenger.Error(err)
return
}
delete(loadedPlugins, name)
}
// Install installs the plugin
@@ -582,7 +584,9 @@ func (pl PluginPackage) Install() {
func UpdatePlugins(plugins []string) {
// if no plugins are specified, update all installed plugins.
if len(plugins) == 0 {
plugins = loadedPlugins
for name := range loadedPlugins {
plugins = append(plugins, name)
}
}
messenger.AddLog("Checking for plugin updates")

View File

@@ -37,6 +37,19 @@ type namedFile struct {
name string
}
// a file with the data stored in memory
type memoryFile struct {
name string
data []byte
}
func (mf memoryFile) Name() string {
return mf.name
}
func (mf memoryFile) Data() ([]byte, error) {
return mf.data, nil
}
func (rf realFile) Name() string {
fn := filepath.Base(string(rf))
return fn[:len(fn)-len(filepath.Ext(fn))]
@@ -120,7 +133,7 @@ func InitRuntimeFiles() {
}
add(RTColorscheme, "colorschemes", "*.micro")
add(RTSyntax, "syntax", "*.micro")
add(RTSyntax, "syntax", "*.yaml")
add(RTHelp, "help", "*.md")
// Search configDir for plugin-scripts
@@ -187,3 +200,8 @@ func PluginAddRuntimeFilesFromDirectory(plugin, filetype, directory, pattern str
AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
}
}
// PluginAddRuntimeFileFromMemory adds a file to the runtime files for a plugin from a given string
func PluginAddRuntimeFileFromMemory(plugin, filetype, filename, data string) {
AddRuntimeFile(filetype, memoryFile{filename, []byte(data)})
}

File diff suppressed because one or more lines are too long

View File

@@ -27,8 +27,8 @@ func BeginSearch(searchStr string) {
searching = true
messenger.response = searchStr
messenger.cursorx = Count(searchStr)
messenger.hasPrompt = true
messenger.Message("Find: ")
messenger.hasPrompt = true
}
// EndSearch stops the current search
@@ -86,6 +86,8 @@ func HandleSearchEvent(event tcell.Event, v *View) {
Search(messenger.response, v, true)
v.Relocate()
return
}
@@ -144,8 +146,5 @@ func Search(searchStr string, v *View, down bool) {
v.Cursor.SetSelectionStart(FromCharPos(charPos+runePos(match[0], str), v.Buf))
v.Cursor.SetSelectionEnd(FromCharPos(charPos+runePos(match[1], str), v.Buf))
v.Cursor.Loc = v.Cursor.CurSelection[1]
if v.Relocate() {
v.matches = Match(v)
}
lastSearch = searchStr
}

View File

@@ -175,31 +175,36 @@ func GetOption(name string) interface{} {
// Note that colorscheme is a global only option
func DefaultGlobalSettings() map[string]interface{} {
return map[string]interface{}{
"autoindent": true,
"autosave": false,
"colorcolumn": float64(0),
"colorscheme": "default",
"cursorline": true,
"eofnewline": false,
"ignorecase": false,
"indentchar": " ",
"infobar": true,
"ruler": true,
"savecursor": false,
"saveundo": false,
"scrollspeed": float64(2),
"scrollmargin": float64(3),
"softwrap": false,
"splitRight": true,
"splitBottom": true,
"statusline": true,
"syntax": true,
"tabsize": float64(4),
"tabstospaces": false,
"autoindent": true,
"keepautoindent": false,
"autosave": false,
"colorcolumn": float64(0),
"colorscheme": "default",
"cursorline": true,
"eofnewline": false,
"rmtrailingws": false,
"ignorecase": false,
"indentchar": " ",
"infobar": true,
"ruler": true,
"savecursor": false,
"saveundo": false,
"scrollspeed": float64(2),
"scrollmargin": float64(3),
"softwrap": false,
"splitRight": true,
"splitBottom": true,
"statusline": true,
"syntax": true,
"tabmovement": false,
"tabsize": float64(4),
"tabstospaces": false,
"termtitle": false,
"pluginchannels": []string{
"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json",
},
"pluginrepos": []string{},
"useprimary": true,
}
}
@@ -207,26 +212,30 @@ func DefaultGlobalSettings() map[string]interface{} {
// Note that filetype is a local only option
func DefaultLocalSettings() map[string]interface{} {
return map[string]interface{}{
"autoindent": true,
"autosave": false,
"colorcolumn": float64(0),
"cursorline": true,
"eofnewline": false,
"filetype": "Unknown",
"ignorecase": false,
"indentchar": " ",
"ruler": true,
"savecursor": false,
"saveundo": false,
"scrollspeed": float64(2),
"scrollmargin": float64(3),
"softwrap": false,
"splitRight": true,
"splitBottom": true,
"statusline": true,
"syntax": true,
"tabsize": float64(4),
"tabstospaces": false,
"autoindent": true,
"keepautoindent": false,
"autosave": false,
"colorcolumn": float64(0),
"cursorline": true,
"eofnewline": false,
"rmtrailingws": false,
"filetype": "Unknown",
"ignorecase": false,
"indentchar": " ",
"ruler": true,
"savecursor": false,
"saveundo": false,
"scrollspeed": float64(2),
"scrollmargin": float64(3),
"softwrap": false,
"splitRight": true,
"splitBottom": true,
"statusline": true,
"syntax": true,
"tabmovement": false,
"tabsize": float64(4),
"tabstospaces": false,
"useprimary": true,
}
}
@@ -271,13 +280,11 @@ func SetOption(option, value string) error {
globalSettings[option] = nativeValue
if option == "colorscheme" {
LoadSyntaxFiles()
// LoadSyntaxFiles()
InitColorscheme()
for _, tab := range tabs {
for _, view := range tab.views {
view.Buf.UpdateRules()
if view.Buf.Settings["syntax"].(bool) {
view.matches = Match(view)
}
}
}
}
@@ -335,16 +342,19 @@ func SetLocalOption(option, value string, view *View) error {
if option == "statusline" {
view.ToggleStatusLine()
if buf.Settings["syntax"].(bool) {
view.matches = Match(view)
}
}
if option == "filetype" {
LoadSyntaxFiles()
// LoadSyntaxFiles()
InitColorscheme()
buf.UpdateRules()
if buf.Settings["syntax"].(bool) {
view.matches = Match(view)
}
if option == "syntax" {
if !nativeValue.(bool) {
buf.ClearMatches()
} else {
buf.highlighter.HighlightStates(buf)
}
}

View File

@@ -1,6 +1,6 @@
package main
// SpltType specifies whether a split is horizontal or vertical
// SplitType specifies whether a split is horizontal or vertical
type SplitType bool
const (
@@ -255,7 +255,6 @@ func (s *SplitTree) ResizeSplits() {
}
n.view.ToggleTabbar()
n.view.matches = Match(n.view)
} else if n, ok := node.(*SplitTree); ok {
if s.kind == VerticalSplit {
if !n.lockWidth {

View File

@@ -36,9 +36,12 @@ func (sline *Statusline) Display() {
// Add the filetype
file += " " + sline.view.Buf.FileType()
rightText := helpBinding + " for help "
if sline.view.Type == vtHelp {
rightText = helpBinding + " to close help "
rightText := ""
if len(helpBinding) > 0 {
rightText = helpBinding + " for help "
if sline.view.Type == vtHelp {
rightText = helpBinding + " to close help "
}
}
statusLineStyle := defStyle.Reverse(true)

View File

@@ -6,6 +6,8 @@ import (
"github.com/zyedidia/tcell"
)
var tabBarOffset int
type Tab struct {
// This contains all the views in this tab
// There is generally only one view per tab, but you can have
@@ -87,13 +89,17 @@ func TabbarString() (string, map[int]int) {
} else {
str += " "
}
str += t.views[t.CurView].Buf.GetName()
buf := t.views[t.CurView].Buf
str += buf.GetName()
if buf.IsModified {
str += " +"
}
if i == curTab {
str += "]"
} else {
str += " "
}
indicies[len(str)-1] = i + 1
indicies[Count(str)-1] = i + 1
str += " "
}
return str, indicies
@@ -118,7 +124,7 @@ func TabbarHandleMouseEvent(event tcell.Event) bool {
return false
}
str, indicies := TabbarString()
if x >= len(str) {
if x+tabBarOffset >= len(str) {
return false
}
var tabnum int
@@ -128,7 +134,7 @@ func TabbarHandleMouseEvent(event tcell.Event) bool {
}
sort.Ints(keys)
for _, k := range keys {
if x <= k {
if x+tabBarOffset <= k {
tabnum = indicies[k] - 1
break
}
@@ -147,7 +153,7 @@ func DisplayTabs() {
return
}
str, _ := TabbarString()
str, indicies := TabbarString()
tabBarStyle := defStyle.Reverse(true)
if style, ok := colorscheme["tabbar"]; ok {
@@ -157,6 +163,98 @@ func DisplayTabs() {
// Maybe there is a unicode filename?
fileRunes := []rune(str)
w, _ := screen.Size()
tooWide := (w < len(fileRunes))
// if the entire tab-bar is longer than the screen is wide,
// then it should be truncated appropriately to keep the
// active tab visible on the UI.
if tooWide == true {
// first we have to work out where the selected tab is
// out of the total length of the tab bar. this is done
// by extracting the hit-areas from the indicies map
// that was constructed by `TabbarString()`
var keys []int
for offset := range indicies {
keys = append(keys, offset)
}
// sort them to be in ascending order so that values will
// correctly reflect the displayed ordering of the tabs
sort.Ints(keys)
// record the offset of each tab and the previous tab so
// we can find the position of the tab's hit-box.
previousTabOffset := 0
currentTabOffset := 0
for _, k := range keys {
tabIndex := indicies[k] - 1
if tabIndex == curTab {
currentTabOffset = k
break
}
// this is +2 because there are two padding spaces that aren't accounted
// for in the display. please note that this is for cosmetic purposes only.
previousTabOffset = k + 2
}
// get the width of the hitbox of the active tab, from there calculate the offsets
// to the left and right of it to approximately center it on the tab bar display.
centeringOffset := (w - (currentTabOffset - previousTabOffset))
leftBuffer := previousTabOffset - (centeringOffset / 2)
rightBuffer := currentTabOffset + (centeringOffset / 2)
// check to make sure we haven't overshot the bounds of the string,
// if we have, then take that remainder and put it on the left side
overshotRight := rightBuffer - len(fileRunes)
if overshotRight > 0 {
leftBuffer = leftBuffer + overshotRight
}
overshotLeft := leftBuffer - 0
if overshotLeft < 0 {
leftBuffer = 0
rightBuffer = leftBuffer + (w - 1)
} else {
rightBuffer = leftBuffer + (w - 2)
}
if rightBuffer > len(fileRunes)-1 {
rightBuffer = len(fileRunes) - 1
}
// construct a new buffer of text to put the
// newly formatted tab bar text into.
var displayText []rune
// if the left-side of the tab bar isn't at the start
// of the constructed tab bar text, then show that are
// more tabs to the left by displaying a "+"
if leftBuffer != 0 {
displayText = append(displayText, '+')
}
// copy the runes in from the original tab bar text string
// into the new display buffer
for x := leftBuffer; x < rightBuffer; x++ {
displayText = append(displayText, fileRunes[x])
}
// if there is more text to the right of the right-most
// column in the tab bar text, then indicate there are more
// tabs to the right by displaying a "+"
if rightBuffer < len(fileRunes)-1 {
displayText = append(displayText, '+')
}
// now store the offset from zero of the left-most text
// that is being displayed. This is to ensure that when
// clicking on the tab bar, the correct tab gets selected.
tabBarOffset = leftBuffer
// use the constructed buffer as the display buffer to print
// onscreen.
fileRunes = displayText
} else {
tabBarOffset = 0
}
// iterate over the width of the terminal display and for each column,
// write a character into the tab display area with the appropriate style.
for x := 0; x < w; x++ {
if x < len(fileRunes) {
screen.SetContent(x, 0, fileRunes[x], nil, tabBarStyle)

View File

@@ -59,6 +59,12 @@ func Max(a, b int) int {
return b
}
func FSize(f *os.File) int64 {
fi, _ := f.Stat()
// get the size
return fi.Size()
}
// IsWordChar returns whether or not the string is a 'word character'
// If it is a unicode character, then it does not match
// Word characters are defined as [A-Za-z0-9_]
@@ -76,6 +82,16 @@ func IsWhitespace(c rune) bool {
return c == ' ' || c == '\t' || c == '\n'
}
// IsStrWhitespace returns true if the given string is all whitespace
func IsStrWhitespace(str string) bool {
for _, c := range str {
if !IsWhitespace(c) {
return false
}
}
return true
}
// Contains returns whether or not a string array contains a given string
func Contains(list []string, a string) bool {
for _, b := range list {
@@ -174,7 +190,7 @@ func StringWidth(str string, tabsize int) int {
switch ch {
case '\t':
ts := tabsize - (lineIdx % tabsize)
sw += ts - 1
sw += ts
lineIdx += ts
case '\n':
lineIdx = 0

View File

@@ -6,17 +6,21 @@ import (
"strings"
"time"
"github.com/mattn/go-runewidth"
"github.com/mitchellh/go-homedir"
"github.com/zyedidia/tcell"
)
type ViewType int
type ViewType struct {
kind int
readonly bool // The file cannot be edited
scratch bool // The file cannot be saved
}
const (
vtDefault ViewType = iota
vtHelp
vtLog
var (
vtDefault = ViewType{0, false, false}
vtHelp = ViewType{1, true, true}
vtLog = ViewType{2, true, true}
vtScratch = ViewType{3, false, true}
)
// The View struct stores information about a view into a buffer.
@@ -84,8 +88,7 @@ type View struct {
// Same here, just to keep track for mouse move events
tripleClick bool
// Syntax highlighting matches
matches SyntaxMatches
cellview *CellView
splitNode *LeafNode
}
@@ -105,6 +108,7 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View {
v.Width = w
v.Height = h
v.cellview = new(CellView)
v.ToggleTabbar()
@@ -120,7 +124,7 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View {
v.Height--
}
for _, pl := range loadedPlugins {
for pl := range loadedPlugins {
_, err := Call(pl+".onViewOpen", v)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)
@@ -183,9 +187,9 @@ func (v *View) ScrollUp(n int) {
// ScrollDown scrolls the view down n lines (if possible)
func (v *View) ScrollDown(n int) {
// Try to scroll by n but if it would overflow, scroll by 1
if v.Topline+n <= v.Buf.NumLines-v.Height {
if v.Topline+n <= v.Buf.NumLines {
v.Topline += n
} else if v.Topline < v.Buf.NumLines-v.Height {
} else if v.Topline < v.Buf.NumLines-1 {
v.Topline++
}
}
@@ -195,18 +199,19 @@ func (v *View) ScrollDown(n int) {
// causing them to lose the unsaved changes
func (v *View) CanClose() bool {
if v.Type == vtDefault && v.Buf.IsModified {
var char rune
var choice bool
var canceled bool
if v.Buf.Settings["autosave"].(bool) {
char = 'y'
choice = true
} else {
char, canceled = messenger.LetterPrompt("Save changes to "+v.Buf.GetName()+" before closing? (y,n,esc) ", 'y', 'n')
choice, canceled = messenger.YesNoPrompt("Save changes to " + v.Buf.GetName() + " before closing? (y,n,esc) ")
}
if !canceled {
if char == 'y' {
//if char == 'y' {
if choice {
v.Save(true)
return true
} else if char == 'n' {
} else {
return true
}
}
@@ -230,8 +235,6 @@ func (v *View) OpenBuffer(buf *Buffer) {
v.Center(false)
v.messages = make(map[string][]GutterMessage)
v.matches = Match(v)
// Set mouseReleased to true because we assume the mouse is not being pressed when
// the editor is opened
v.mouseReleased = true
@@ -243,15 +246,22 @@ func (v *View) Open(filename string) {
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
file, err := os.Open(filename)
fileInfo, _ := os.Stat(filename)
if err == nil && fileInfo.IsDir() {
messenger.Error(filename, " is a directory")
return
}
defer file.Close()
var buf *Buffer
if err != nil {
messenger.Message(err.Error())
// File does not exist -- create an empty buffer with that name
buf = NewBuffer(strings.NewReader(""), filename)
buf = NewBufferFromString("", filename)
} else {
buf = NewBuffer(file, filename)
buf = NewBuffer(file, FSize(file), filename)
}
v.OpenBuffer(buf)
}
@@ -269,7 +279,6 @@ func (v *View) ReOpen() {
screen.Clear()
v.Buf.ReOpen()
v.Relocate()
v.matches = Match(v)
}
}
@@ -304,6 +313,9 @@ func (v *View) VSplitIndex(buf *Buffer, splitIndex int) {
// GetSoftWrapLocation gets the location of a visual click on the screen and converts it to col,line
func (v *View) GetSoftWrapLocation(vx, vy int) (int, int) {
if !v.Buf.Settings["softwrap"].(bool) {
if vy >= v.Buf.NumLines {
vy = v.Buf.NumLines - 1
}
vx = v.Cursor.GetCharPosInLine(vy, vx)
return vx, vy
}
@@ -311,6 +323,9 @@ func (v *View) GetSoftWrapLocation(vx, vy int) (int, int) {
screenX, screenY := 0, v.Topline
for lineN := v.Topline; lineN < v.Bottomline(); lineN++ {
line := v.Buf.Line(lineN)
if lineN >= v.Buf.NumLines {
return 0, v.Buf.NumLines - 1
}
colN := 0
for _, ch := range line {
@@ -418,9 +433,6 @@ func (v *View) MoveToMouseClick(x, y int) {
v.ScrollDown(1)
y = v.Height + v.Topline - 1
}
if y >= v.Buf.NumLines {
y = v.Buf.NumLines - 1
}
if y < 0 {
y = 0
}
@@ -447,9 +459,6 @@ func (v *View) HandleEvent(event tcell.Event) {
v.Buf.CheckModTime()
switch e := event.(type) {
case *tcell.EventResize:
// Window resized
tabs[v.TabNum].Resize()
case *tcell.EventKey:
// Check first if input is a key binding, if it is we 'eat' the input and don't insert a rune
isBinding := false
@@ -487,7 +496,7 @@ func (v *View) HandleEvent(event tcell.Event) {
v.Buf.Insert(v.Cursor.Loc, string(e.Rune()))
v.Cursor.Right()
for _, pl := range loadedPlugins {
for pl := range loadedPlugins {
_, err := Call(pl+".onRune", string(e.Rune()), v)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)
@@ -529,6 +538,7 @@ func (v *View) HandleEvent(event tcell.Event) {
v.doubleClick = false
v.Cursor.SelectLine()
v.Cursor.CopySelection("primary")
} else {
// Double click
v.lastClickTime = time.Now()
@@ -537,6 +547,7 @@ func (v *View) HandleEvent(event tcell.Event) {
v.tripleClick = false
v.Cursor.SelectWord()
v.Cursor.CopySelection("primary")
}
} else {
v.doubleClick = false
@@ -556,6 +567,7 @@ func (v *View) HandleEvent(event tcell.Event) {
v.Cursor.AddWordToSelection()
} else {
v.Cursor.SetSelectionEnd(v.Cursor.Loc)
v.Cursor.CopySelection("primary")
}
}
case tcell.Button2:
@@ -576,6 +588,7 @@ func (v *View) HandleEvent(event tcell.Event) {
if !v.doubleClick && !v.tripleClick {
v.MoveToMouseClick(x, y)
v.Cursor.SetSelectionEnd(v.Cursor.Loc)
v.Cursor.CopySelection("primary")
}
v.mouseReleased = true
}
@@ -592,6 +605,12 @@ func (v *View) HandleEvent(event tcell.Event) {
if relocate {
v.Relocate()
// We run relocate again because there's a bug with relocating with softwrap
// when for example you jump to the bottom of the buffer and it tries to
// calculate where to put the topline so that the bottom line is at the bottom
// of the terminal and it runs into problems with visual lines vs real lines.
// This is (hopefully) a temporary solution
v.Relocate()
}
}
@@ -631,7 +650,7 @@ func (v *View) openHelp(helpPage string) {
if data, err := FindRuntimeFile(RTHelp, helpPage).Data(); err != nil {
TermMessage("Unable to load help text", helpPage, "\n", err)
} else {
helpBuffer := NewBuffer(strings.NewReader(string(data)), helpPage+".md")
helpBuffer := NewBufferFromString(string(data), helpPage+".md")
helpBuffer.name = "Help"
if v.Type == vtHelp {
@@ -643,34 +662,23 @@ func (v *View) openHelp(helpPage string) {
}
}
func (v *View) drawCell(x, y int, ch rune, combc []rune, style tcell.Style) {
if x >= v.x && x < v.x+v.Width && y >= v.y && y < v.y+v.Height {
screen.SetContent(x, y, ch, combc, style)
}
}
// DisplayView renders the view to the screen
func (v *View) DisplayView() {
if v.Buf.Settings["softwrap"].(bool) && v.leftCol != 0 {
v.leftCol = 0
}
if v.Type == vtLog {
// Log views should always follow the cursor...
v.Relocate()
}
if v.Buf.Settings["syntax"].(bool) {
v.matches = Match(v)
}
// The charNum we are currently displaying
// starts at the start of the viewport
charNum := Loc{0, v.Topline}
// Convert the length of buffer to a string, and get the length of the string
// We are going to have to offset by that amount
maxLineLength := len(strconv.Itoa(v.Buf.NumLines))
// We need to know the string length of the largest line number
// so we can pad appropriately when displaying line numbers
maxLineNumLength := len(strconv.Itoa(v.Buf.NumLines))
if v.Buf.Settings["ruler"] == true {
// + 1 for the little space after the line number
v.lineNumOffset = maxLineLength + 1
v.lineNumOffset = maxLineNumLength + 1
} else {
v.lineNumOffset = 0
}
@@ -686,44 +694,52 @@ func (v *View) DisplayView() {
v.lineNumOffset += 2
}
divider := 0
if v.x != 0 {
// One space for the extra split divider
v.lineNumOffset++
divider = 1
}
// These represent the current screen coordinates
screenX, screenY := v.x, v.y-1
xOffset := v.x + v.lineNumOffset
yOffset := v.y
highlightStyle := defStyle
curLineN := 0
height := v.Height
width := v.Width
left := v.leftCol
top := v.Topline
// ViewLine is the current line from the top of the viewport
for viewLine := 0; viewLine < v.Height; viewLine++ {
screenY++
screenX = v.x
v.cellview.Draw(v.Buf, top, height, left, width-v.lineNumOffset)
// This is the current line number of the buffer that we are drawing
curLineN = viewLine + v.Topline
if screenY-v.y >= v.Height {
break
screenX := v.x
realLineN := top - 1
visualLineN := 0
var line []*Char
for visualLineN, line = range v.cellview.lines {
var firstChar *Char
if len(line) > 0 {
firstChar = line[0]
}
if v.x != 0 {
// Draw the split divider
v.drawCell(screenX, screenY, '|', nil, defStyle.Reverse(true))
screenX++
}
// If the buffer is smaller than the view height we have to clear all this space
if curLineN >= v.Buf.NumLines {
for i := screenX; i < v.x+v.Width; i++ {
v.drawCell(i, screenY, ' ', nil, defStyle)
var softwrapped bool
if firstChar != nil {
if firstChar.realLoc.Y == realLineN {
softwrapped = true
}
continue
realLineN = firstChar.realLoc.Y
} else {
realLineN++
}
line := v.Buf.Line(curLineN)
colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64))
if colorcolumn != 0 {
style := GetColor("color-column")
fg, _, _ := style.Decompose()
st := defStyle.Background(fg)
screen.SetContent(xOffset+colorcolumn, yOffset+visualLineN, ' ', nil, st)
}
screenX = v.x
// If there are gutter messages we need to display the '>>' symbol here
if hasGutterMessages {
@@ -731,7 +747,7 @@ func (v *View) DisplayView() {
msgOnLine := false
for k := range v.messages {
for _, msg := range v.messages[k] {
if msg.lineNum == curLineN {
if msg.lineNum == realLineN {
msgOnLine = true
gutterStyle := defStyle
switch msg.kind {
@@ -748,11 +764,11 @@ func (v *View) DisplayView() {
gutterStyle = style
}
}
v.drawCell(screenX, screenY, '>', nil, gutterStyle)
screen.SetContent(screenX, yOffset+visualLineN, '>', nil, gutterStyle)
screenX++
v.drawCell(screenX, screenY, '>', nil, gutterStyle)
screen.SetContent(screenX, yOffset+visualLineN, '>', nil, gutterStyle)
screenX++
if v.Cursor.Y == curLineN && !messenger.hasPrompt {
if v.Cursor.Y == realLineN && !messenger.hasPrompt {
messenger.Message(msg.msg)
messenger.gutterMessage = true
}
@@ -761,11 +777,11 @@ func (v *View) DisplayView() {
}
// If there is no message on this line we just display an empty offset
if !msgOnLine {
v.drawCell(screenX, screenY, ' ', nil, defStyle)
screen.SetContent(screenX, yOffset+visualLineN, ' ', nil, defStyle)
screenX++
v.drawCell(screenX, screenY, ' ', nil, defStyle)
screen.SetContent(screenX, yOffset+visualLineN, ' ', nil, defStyle)
screenX++
if v.Cursor.Y == curLineN && messenger.gutterMessage {
if v.Cursor.Y == realLineN && messenger.gutterMessage {
messenger.Reset()
messenger.gutterMessage = false
}
@@ -779,194 +795,149 @@ func (v *View) DisplayView() {
lineNumStyle = style
}
if style, ok := colorscheme["current-line-number"]; ok {
if curLineN == v.Cursor.Y && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() {
if realLineN == v.Cursor.Y && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() {
lineNumStyle = style
}
}
lineNum := strconv.Itoa(curLineN + 1)
lineNum := strconv.Itoa(realLineN + 1)
// Write the spaces before the line number if necessary
for i := 0; i < maxLineLength-len(lineNum); i++ {
v.drawCell(screenX, screenY, ' ', nil, lineNumStyle)
for i := 0; i < maxLineNumLength-len(lineNum); i++ {
screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle)
screenX++
}
// Write the actual line number
for _, ch := range lineNum {
v.drawCell(screenX, screenY, ch, nil, lineNumStyle)
screenX++
if softwrapped && visualLineN != 0 {
// Pad without the line number because it was written on the visual line before
for range lineNum {
screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle)
screenX++
}
} else {
// Write the actual line number
for _, ch := range lineNum {
screen.SetContent(screenX+divider, yOffset+visualLineN, ch, nil, lineNumStyle)
screenX++
}
}
// Write the extra space
v.drawCell(screenX, screenY, ' ', nil, lineNumStyle)
screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle)
screenX++
}
// Now we actually draw the line
colN := 0
strWidth := 0
tabSize := int(v.Buf.Settings["tabsize"].(float64))
for _, ch := range line {
if v.Buf.Settings["softwrap"].(bool) {
if screenX-v.x >= v.Width {
screenY++
for i := 0; i < v.lineNumOffset; i++ {
screen.SetContent(v.x+i, screenY, ' ', nil, lineNumStyle)
}
screenX = v.x + v.lineNumOffset
}
}
var lastChar *Char
cursorSet := false
for _, char := range line {
if char != nil {
lineStyle := char.style
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN && colN == v.Cursor.X {
v.DisplayCursor(screenX-v.leftCol, screenY)
}
lineStyle := defStyle
if v.Buf.Settings["syntax"].(bool) {
// Syntax highlighting is enabled
highlightStyle = v.matches[viewLine][colN]
}
if v.Cursor.HasSelection() &&
(charNum.GreaterEqual(v.Cursor.CurSelection[0]) && charNum.LessThan(v.Cursor.CurSelection[1]) ||
charNum.LessThan(v.Cursor.CurSelection[0]) && charNum.GreaterEqual(v.Cursor.CurSelection[1])) {
// The current character is selected
lineStyle = defStyle.Reverse(true)
if style, ok := colorscheme["selection"]; ok {
lineStyle = style
}
} else {
lineStyle = highlightStyle
}
// We need to display the background of the linestyle with the correct color if cursorline is enabled
// and this is the current view and there is no selection on this line and the cursor is on this line
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
if style, ok := colorscheme["cursor-line"]; ok {
colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64))
if colorcolumn != 0 && char.visualLoc.X == colorcolumn {
style := GetColor("color-column")
fg, _, _ := style.Decompose()
lineStyle = lineStyle.Background(fg)
}
}
if ch == '\t' {
// If the character we are displaying is a tab, we need to do a bunch of special things
// First the user may have configured an `indent-char` to be displayed to show that this
// is a tab character
lineIndentStyle := defStyle
if style, ok := colorscheme["indent-char"]; ok && v.Buf.Settings["indentchar"].(string) != " " {
lineIndentStyle = style
}
charLoc := char.realLoc
if v.Cursor.HasSelection() &&
(charNum.GreaterEqual(v.Cursor.CurSelection[0]) && charNum.LessThan(v.Cursor.CurSelection[1]) ||
charNum.LessThan(v.Cursor.CurSelection[0]) && charNum.GreaterEqual(v.Cursor.CurSelection[1])) {
lineIndentStyle = defStyle.Reverse(true)
(charLoc.GreaterEqual(v.Cursor.CurSelection[0]) && charLoc.LessThan(v.Cursor.CurSelection[1]) ||
charLoc.LessThan(v.Cursor.CurSelection[0]) && charLoc.GreaterEqual(v.Cursor.CurSelection[1])) {
// The current character is selected
lineStyle = defStyle.Reverse(true)
if style, ok := colorscheme["selection"]; ok {
lineIndentStyle = style
lineStyle = style
}
}
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
if style, ok := colorscheme["cursor-line"]; ok {
fg, _, _ := style.Decompose()
lineIndentStyle = lineIndentStyle.Background(fg)
}
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
v.Cursor.Y == char.realLoc.Y && v.Cursor.X == char.realLoc.X && !cursorSet {
screen.ShowCursor(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y)
cursorSet = true
}
// Here we get the indent char
indentChar := []rune(v.Buf.Settings["indentchar"].(string))
if screenX-v.x-v.leftCol >= v.lineNumOffset {
v.drawCell(screenX-v.leftCol, screenY, indentChar[0], nil, lineIndentStyle)
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num &&
!v.Cursor.HasSelection() && v.Cursor.Y == realLineN {
style := GetColor("cursor-line")
fg, _, _ := style.Decompose()
lineStyle = lineStyle.Background(fg)
}
// Now the tab has to be displayed as a bunch of spaces
visLoc := strWidth
remainder := tabSize - (visLoc % tabSize)
for i := 0; i < remainder-1; i++ {
screenX++
if screenX-v.x-v.leftCol >= v.lineNumOffset {
v.drawCell(screenX-v.leftCol, screenY, ' ', nil, lineStyle)
}
}
strWidth += remainder
} else if runewidth.RuneWidth(ch) > 1 {
if screenX-v.x-v.leftCol >= v.lineNumOffset {
v.drawCell(screenX, screenY, ch, nil, lineStyle)
}
for i := 0; i < runewidth.RuneWidth(ch)-1; i++ {
screenX++
if screenX-v.x-v.leftCol >= v.lineNumOffset {
v.drawCell(screenX-v.leftCol, screenY, '<', nil, lineStyle)
}
}
strWidth += StringWidth(string(ch), tabSize)
} else {
if screenX-v.x-v.leftCol >= v.lineNumOffset {
v.drawCell(screenX-v.leftCol, screenY, ch, nil, lineStyle)
}
strWidth += StringWidth(string(ch), tabSize)
screen.SetContent(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y, char.drawChar, nil, lineStyle)
lastChar = char
}
charNum = charNum.Move(1, v.Buf)
screenX++
colN++
}
// Here we are at a newline
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN && colN == v.Cursor.X {
v.DisplayCursor(screenX-v.leftCol, screenY)
}
// The newline may be selected, in which case we should draw the selection style
// with a space to represent it
lastX := 0
var realLoc Loc
var visualLoc Loc
var cx, cy int
if lastChar != nil {
lastX = xOffset + lastChar.visualLoc.X + lastChar.width
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
v.Cursor.Y == lastChar.realLoc.Y && v.Cursor.X == lastChar.realLoc.X+1 {
screen.ShowCursor(lastX, yOffset+lastChar.visualLoc.Y)
cx, cy = lastX, yOffset+lastChar.visualLoc.Y
}
realLoc = Loc{lastChar.realLoc.X, realLineN}
visualLoc = Loc{lastX - xOffset, lastChar.visualLoc.Y}
} else if len(line) == 0 {
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
v.Cursor.Y == realLineN {
screen.ShowCursor(xOffset, yOffset+visualLineN)
cx, cy = xOffset, yOffset+visualLineN
}
lastX = xOffset
realLoc = Loc{0, realLineN}
visualLoc = Loc{0, visualLineN}
}
if v.Cursor.HasSelection() &&
(charNum.GreaterEqual(v.Cursor.CurSelection[0]) && charNum.LessThan(v.Cursor.CurSelection[1]) ||
charNum.LessThan(v.Cursor.CurSelection[0]) && charNum.GreaterEqual(v.Cursor.CurSelection[1])) {
(realLoc.GreaterEqual(v.Cursor.CurSelection[0]) && realLoc.LessThan(v.Cursor.CurSelection[1]) ||
realLoc.LessThan(v.Cursor.CurSelection[0]) && realLoc.GreaterEqual(v.Cursor.CurSelection[1])) {
// The current character is selected
selectStyle := defStyle.Reverse(true)
if style, ok := colorscheme["selection"]; ok {
selectStyle = style
}
v.drawCell(screenX, screenY, ' ', nil, selectStyle)
screenX++
screen.SetContent(xOffset+visualLoc.X, yOffset+visualLoc.Y, ' ', nil, selectStyle)
}
charNum = charNum.Move(1, v.Buf)
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num &&
!v.Cursor.HasSelection() && v.Cursor.Y == realLineN {
for i := lastX; i < xOffset+v.Width; i++ {
style := GetColor("cursor-line")
fg, _, _ := style.Decompose()
style = style.Background(fg)
if !(tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && i == cx && yOffset+visualLineN == cy) {
screen.SetContent(i, yOffset+visualLineN, ' ', nil, style)
}
}
}
}
for i := 0; i < v.Width; i++ {
lineStyle := defStyle
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
if style, ok := colorscheme["cursor-line"]; ok {
fg, _, _ := style.Decompose()
lineStyle = lineStyle.Background(fg)
}
}
if screenX-v.x-v.leftCol+i >= v.lineNumOffset {
colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64))
if colorcolumn != 0 && screenX-v.lineNumOffset+i == colorcolumn-1 {
if style, ok := colorscheme["color-column"]; ok {
fg, _, _ := style.Decompose()
lineStyle = lineStyle.Background(fg)
}
}
v.drawCell(screenX-v.leftCol+i, screenY, ' ', nil, lineStyle)
}
if divider != 0 {
dividerStyle := defStyle
if style, ok := colorscheme["divider"]; ok {
dividerStyle = style
}
for i := 0; i < v.Height; i++ {
screen.SetContent(v.x, yOffset+i, '|', nil, dividerStyle.Reverse(true))
}
}
}
// DisplayCursor draws the current buffer's cursor to the screen
func (v *View) DisplayCursor(x, y int) {
// screen.ShowCursor(v.x+v.Cursor.GetVisualX()+v.lineNumOffset-v.leftCol, y)
screen.ShowCursor(x, y)
}
// Display renders the view, the cursor, and statusline
func (v *View) Display() {
if globalSettings["termtitle"].(bool) {
screen.SetTitle("micro: " + v.Buf.GetName())
}
v.DisplayView()
// Don't draw the cursor if it is out of the viewport or if it has a selection
if (v.Cursor.Y-v.Topline < 0 || v.Cursor.Y-v.Topline > v.Height-1) || v.Cursor.HasSelection() {
if (v.Cursor.Y-v.Topline < 0 || v.Cursor.Y-v.Topline > v.Height-1) || (v.Cursor.HasSelection() && v.Num == tabs[curTab].CurView) {
screen.HideCursor()
}
_, screenH := screen.Size()

View File

@@ -1,5 +1,5 @@
# Runtime files for Micro
This directory will be embedded in the Go binary for portability, but it may just as well be put in `~/.config/micro`. If you would like to make your own colorschemes
and syntax files, you can put in in `~/.config/micro/colorschemes` and `~/.config/micro/syntax` respectively.
and syntax files, you can put them in `~/.config/micro/colorschemes` and `~/.config/micro/syntax` respectively.

View File

@@ -4,6 +4,7 @@ color-link identifier "#F9EE98,#1D1F21"
color-link constant "#FF73FD,#1D1F21"
color-link constant.string "#A8FF60,#1D1F21"
color-link statement "#96CBFE,#1D1F21"
color-link symbol "#96CBFE,#1D1F21"
color-link preproc "#62B1FE,#1D1F21"
color-link type "#C6C5FE,#1D1F21"
color-link special "#A6E22E,#1D1F21"
@@ -11,6 +12,7 @@ color-link underlined "#D33682,#1D1F21"
color-link error "bold #FF4444,#1D1F21"
color-link todo "bold #FF8844,#1D1F21"
color-link statusline "#1D1F21,#C5C8C6"
color-link tabbar "#1D1F21,#C5C8C6"
color-link indent-char "#505050,#1D1F21"
color-link line-number "#656866,#232526"
color-link current-line-number "#656866,#1D1F21"
@@ -18,3 +20,7 @@ color-link gutter-error "#FF4444,#1D1F21"
color-link gutter-warning "#EEEE77,#1D1F21"
color-link cursor-line "#2D2F31"
color-link color-column "#2D2F31"
#color-link symbol.brackets "#96CBFE,#1D1F21"
#No extended types (bool in C, etc.)
#color-link type.extended "default"
#Plain brackets

View File

@@ -5,16 +5,20 @@ color-link constant.string "136,231"
color-link constant.number "131,231"
color-link identifier "133,231"
color-link statement "32,231"
color-link symbol "32,231"
color-link preproc "28,231"
color-link type "61,231"
color-link special "167,231"
color-link error "231, 160"
color-link underlined "underline 241,231"
color-link todo "246,231"
color-link statusline "241,254"
color-link tabbar "241,254"
color-link gutter-error "197,231"
color-link gutter-warning "134,231"
color-link line-number "246,254"
color-link cursor-line "254"
color-link color-column "254"
#No extended types (bool in C, &c.) and plain brackets
color-link type.extended "default"
color-link symbol.brackets "default"

View File

@@ -0,0 +1,40 @@
#CaptainMcClellan's personal color scheme.
#16 colour version.
color-link comment "bold black"
color-link constant "cyan"
color-link constant.bool "bold cyan"
color-link constant.bool.true "bold green"
color-link constant.bool.false "bold red"
color-link constant.string "yellow"
color-link constant.string.url "underline blue, white"
#color-link constant.number "constant"
color-link constant.specialChar "bold magenta"
color-link identifier "bold red"
color-link identifier.macro "bold red"
color-link identifier.var "bold blue"
#color-link identifier.class "bold green"
color-link identifier.class "bold white"
color-link statement "bold yellow"
color-link symbol "red"
color-link symbol.brackets "blue"
color-link symbol.tag "bold blue"
color-link symbol.tag.extended "bold green"
color-link preproc "bold cyan"
color-link type "green"
color-link type.keyword "bold green"
color-link special "magenta"
color-link ignore "default"
color-link error "bold ,brightred"
color-link todo "underline black,brightyellow"
color-link indent-char ",brightgreen"
color-link line-number "green"
color-link line-number.scrollbar "green"
color-link statusline "white,blue"
color-link tabbar "white,blue"
color-link current-line-number "red"
color-link current-line-number.scroller "red"
color-link gutter-error ",red"
color-link gutter-warning "red"
color-link color-column "cyan"
color-link underlined.url "underline blue, white"
color-link divider "blue"

View File

@@ -0,0 +1,37 @@
#CaptainMcClellan's personal color scheme.
#Paper version
color-link default "black,white"
color-link comment "bold black"
color-link constant "cyan"
color-link constant.bool "bold cyan"
color-link constant.bool.true "bold green"
color-link constant.bool.false "bold red"
color-link constant.string "bold yellow"
color-link constant.string.url "underline blue, white"
color-link constant.number "constant"
color-link constant.specialChar "bold magenta"
color-link identifier "bold red"
color-link identifier.macro "bold red"
color-link identifier.var "bold blue"
color-link identifier.class "bold green"
color-link preproc "bold cyan"
color-link statement "bold yellow"
color-link symbol "red"
color-link symbol.brackets "blue"
color-link type "green"
color-link type.keyword "bold green"
color-link special "magenta"
color-link ignore "default"
color-link error ",brightred"
color-link todo "black,brightyellow"
color-link indent-char ",brightgreen"
color-link line-number "green"
color-link line-number.scrollbar "green"
color-link statusline "white,blue"
color-link tabbar "white,blue"
color-link current-line-number "red"
color-link current-line-number.scroller "red"
color-link gutter-error ",red"
color-link gutter-warning "red"
color-link color-column "cyan"
color-link underlined.url "underline blue, white"

View File

@@ -0,0 +1,36 @@
#CaptainMcClellan's personal colour scheme.
#Full colour edition.
color-link default "#aaaaaa,#1e2124"
color-link comment "bold #555555"
color-link constant "#008888"
#color-link constant.string "#888800"
color-link constant.string "#a85700"
color-link constant.specialChar "bold #ccccff"
color-link identifier "bold #e34234"
color-link identifier.macro "bold #e34234"
color-link identifier.var "bold #5757ff"
color-link identifier.class "bold #ffffff"
color-link statement "bold #ffff55"
color-link symbol "#722f37"
color-link symbol.brackets "#4169e1"
color-link symbol.tag "#5757ff"
color-link preproc "bold #55ffff"
color-link type "#3eb489"
color-link type.keyword "bold #bdecb6"
color-link special "#b57edc"
color-link ignore "default"
color-link error "bold ,#e34234"
color-link todo "bold underline #888888,#f26522"
color-link indent-char ",#bdecb6"
color-link line-number "#bdecb6,#36393e"
color-link line-number.scrollbar "#3eb489"
color-link statusline "#aaaaaa,#8a496b"
color-link tabbar "#aaaaaa,#8a496b"
color-link current-line-number "bold #e34234,#424549"
color-link current-line-number.scroller "red"
color-link gutter-error ",#e34234"
color-link gutter-warning "#e34234"
color-link color-column "#f26522"
color-link constant.bool "bold #55ffff"
color-link constant.bool.true "bold #85ff85"
color-link constant.bool.false "bold #ff8585"

View File

@@ -0,0 +1,25 @@
#A colorscheme based on Code::Blocks IDE
#but with a white background.
color-link default "black,white"
color-link comment "bold black"
color-link constant "blue"
color-link constant.number "bold magenta"
color-link constant.string "bold blue"
color-link identifier "black"
color-link preproc "green"
color-link statement "blue"
color-link symbol "red"
color-link symbol.brackets "blue"
color-link type "blue"
color-link special "magenta"
color-link ignore "default"
color-link error "bold white,brightred"
color-link todo "bold black,brightyellow"
color-link indent-char "bold black"
color-link line-number "black,white"
color-link statusline "white,red"
color-link tabbar "white,red"
color-link current-line-number "red,black"
color-link gutter-error ",red"
color-link gutter-warning "red"
color-link color-column "black"

View File

@@ -0,0 +1,23 @@
#Theme based on Code::Blocks IDE's default syntax highlighting.
color-link comment "bold black"
color-link constant "blue"
color-link constant.string "bold blue"
color-link constant.number "bold magenta"
color-link identifier "default"
color-link preproc "green"
color-link statement "blue"
color-link symbol "red"
color-link symbol.brackets "blue"
color-link type "blue"
color-link special "magenta"
color-link ignore "default"
color-link error ",brightred"
color-link todo "bold black,brightyellow"
color-link indent-char "bold black"
color-link line-number "black,white"
color-link statusline "white,red"
color-link tabbar "white,red"
color-link current-line-number "red"
color-link gutter-error ",red"
color-link gutter-warning "red"
color-link color-column "white"

View File

@@ -6,6 +6,7 @@ color-link constant "#AE81FF,#282828"
color-link constant.string "#E6DB74,#282828"
color-link constant.string.char "#BDE6AD,#282828"
color-link statement "#F92672,#282828"
color-link symbol "#F92672,#282828"
color-link preproc "#CB4B16,#282828"
color-link type "#66D9EF,#282828"
color-link special "#A6E22E,#282828"
@@ -13,6 +14,7 @@ color-link underlined "#D33682,#282828"
color-link error "bold #CB4B16,#282828"
color-link todo "bold #D33682,#282828"
color-link statusline "#282828,#F8F8F2"
color-link tabbar "#282828,#f8f8f2"
color-link indent-char "#505050,#282828"
color-link line-number "#AAAAAA,#323232"
color-link current-line-number "#AAAAAA,#282828"
@@ -20,3 +22,6 @@ color-link gutter-error "#CB4B16,#282828"
color-link gutter-warning "#E6DB74,#282828"
color-link cursor-line "#323232"
color-link color-column "#323232"
#No extended types; plain brackets
color-link type.extended "default"
color-link symbol.brackets "default"

View File

@@ -0,0 +1,30 @@
#Flamepoint theme
#By CaptainMcClellan
color-link default ""
color-link comment ""
color-link constant ""
color-link constant.bool ""
color-link constant.bool.true ""
color-link constant.bool.false ""
color-link constant.number ""
color-link constant.specialChar ""
color-link constant.string ""
color-link constant.string.url "underline"
color-link identifier ""
color-link identifier.var ""
color-link preproc ""
color-link special ""
color-link statement ""
color-link symbol ""
color-link symbol.brackets ""
color-link symbol.tag ""
color-link type ""
color-link type.keyword ""
color-link error ""
color-link todo ""
color-link cursor-line ""
color-link statusline ""
color-link tabbar ""
color-link color-column ""
color-link gutter-error ""
color-link gutter-warning ""

View File

@@ -0,0 +1 @@
#Funky Cactus theme in true colour.

View File

@@ -0,0 +1,31 @@
#Funky Cactus theme
color-link comment "bold black"
color-link constant "cyan"
color-link constant.bool "bold cyan"
color-link constant.bool.true "bold green"
color-link constant.bool.false "bold red"
color-link constant.string "yellow"
color-link constant.number "constant"
color-link constant.specialChar "bold magenta"
color-link identifier "bold red"
color-link identifier.macro "bold red"
color-link identifier.var "bold blue"
color-link identifier.class "bold green"
color-link preproc "bold cyan"
color-link statement "bold yellow"
color-link symbol "red"
color-link symbol.brackets "blue"
color-link type "green"
color-link type.keyword "bold green"
color-link special "magenta"
color-link ignore "default"
color-link error "bold ,brightred"
color-link todo "underline ,brightyellow"
color-link indent-char "bold ,brightgreen"
color-link line-number "green"
color-link statusline "black,green"
color-link tabbar "black,magenta"
color-link current-line-number "bold magenta"
color-link gutter-error ",red"
color-link gutter-warning "red"
color-link color-column "bold green"

View File

@@ -0,0 +1,23 @@
#Gameboy theme
color-link default "#3f3f3f,#bfc180"
color-link comment "#7d7343"
color-link constant "#7d7343"
color-link identifier "#ddde7d"
color-link preproc "#ddde7d,#7d7343"
color-link special "#7d7343"
color-link statement "#7d7343"
color-link symbol "#7d7343"
color-link type "#7d7343"
color-link error "#ddde7d,#7d7343"
color-link todo "#7d7343,#ddde7d"
color-link statusline "#ddde7d,#7d7343"
color-link tabbar "#ddde7d,#7d7343"
color-link color-column "#7d7343"
color-link line-number "#ddde7d,#7d7343"
color-link current-line-number "#3f3f3f,#bfc180"
color-link gutter-error "#ddde7d,#7d7343"
color-link gutter-warning "default"
#3f3f3f
#7d7343
#bfc180
#ddde76

View File

@@ -0,0 +1,21 @@
#Geany Alternate theme
color-link default "#000000,#fefefe"
color-link comment "#808080"
color-link constant "default"
color-link constant.bool "#003030"
color-link constant.number "#300008"
color-link constant.string "#008000"
color-link identifier "default"
color-link preproc "#bbbb77"
color-link special "#003030"
color-link statement "#003030"
color-link symbol "#300008"
color-link symbol.tag "bold #4e9d71"
color-link type "#003030"
color-link error "#a52a2a"
color-link todo "#ffa500"
color-link line-number "#000000,#d0d0d0"
color-link current-line-number "#000000,#d0d0d0"
color-link color-column "#c2ebc2"
color-link cursor-line "#f0f0f0"
color-link type.extended "default"

View File

@@ -0,0 +1,23 @@
#Geany
color-link comment "red"
color-link constant "default"
color-link constant.number
color-link constant.string "bold yellow"
color-link identifier "default"
color-link preproc "cyan"
color-link special "blue"
color-link statement "blue"
color-link symbol "default"
color-link symbol.tag "bold blue"
color-link type "blue"
color-link type.extended "default"
color-link error "red"
color-link todo "bold cyan"
color-link indent-char "bold black"
color-link line-number ""
color-link current-line-number ""
color-link statusline "black,white"
color-link tabbar "black,white"
color-link color-column "bold geren"
color-link gutter-error ",red"
color-link gutter-warning "red"

View File

@@ -0,0 +1,24 @@
#True color theme based on Github's syntax highlighting.
#Warning, this is based on how it rendered in my Firefox!
#Yours may look different.
color-link comment "bold #969896"
color-link constant "#0086B9"
color-link constant.number "#0086B9"
color-link constant.specialChar "bold #1836BD"
color-link constant.string "bold #1836BD"
color-link constant.bool "#0086B9"
color-link identifier "#A71D5D"
color-link preproc "bold #A71D5D"
color-link special "#A71D5D"
color-link statement "#A71D5D"
color-link symbol "default"
color-link type "#A71D5D"
color-link error "bold ,#E34234"
color-link todo "white"
color-link indent-char "default"
color-link line-number "bold #969896"
color-link current-line-number "bold #969896"
color-link gutter-error "bold ,#E34234"
color-link gutter-warning "bold #f26522"
color-link statusline "bold #c8c9cb,#24292e"
color-link tabbar "bold #c8c9cb,#24292e"

View File

@@ -0,0 +1,24 @@
#Theme based on Github's syntax highlighting.
color-link comment "bold black"
color-link constant "cyan"
color-link constant.number "cyan"
color-link constant.specialChar "bold blue"
color-link constant.string "bold blue"
color-link constant.bool "cyan"
color-link identifier "magenta"
color-link preproc "bold magenta"
color-link special "magenta"
color-link statement "magenta"
color-link symbol "default"
color-link type "magenta"
color-link error "bold ,brightred"
color-link todo "white"
color-link indent-char "default"
color-link line-number "bold black"
color-link current-line-number "bold black"
color-link gutter-error ",red"
color-link gutter-warning "bold yellow"
color-link statusline "bold white,black"
color-link tabbar "bold white,black"
#Plain brackets.
#color-link symbol.brackets "default"

View File

@@ -0,0 +1,21 @@
color-link default "#ebdbb2,#282828"
color-link comment "#928374,#282828"
color-link symbol "#d79921,#282828"
color-link constant "#d3869b,#282828"
color-link constant.string "#b8bb26,#282828"
color-link constant.string.char "#b8bb26,#282828"
color-link identifier "#8ec07c,#282828"
color-link statement "#fb4934,#282828"
color-link preproc "#fb4934,235"
color-link type "#fb4934,#282828"
color-link special "#d79921,#282828"
color-link underlined "underline #282828"
color-link error "#9d0006,#282828"
color-link gutter-error "#fb4934,#282828"
color-link gutter-warning "#d79921,#282828"
color-link line-number "#665c54,#282828"
color-link current-line-number "#665c54,#3c3836"
color-link cursor-line "#3c3836"
color-link color-column "#79740e"
color-link statusline "#ebdbb2,#665c54"
color-link tabbar "#ebdbb2,#665c54"

View File

@@ -4,6 +4,7 @@ color-link constant "175,235"
color-link constant.string "142,235"
color-link identifier "109,235"
color-link statement "124,235"
color-link symbol "124,235"
color-link preproc "72,235"
color-link type "214,235"
color-link special "172,235"
@@ -14,3 +15,5 @@ color-link line-number "243,237"
color-link current-line-number "172,237"
color-link cursor-line "237"
color-link color-column "237"
color-link statusline "223,237"
color-link tabbar "223,237"

View File

@@ -0,0 +1,25 @@
#Midnight Commander inspired theme.
color-link default "white,blue"
color-link comment "bold black"
color-link constant "bold white"
color-link constant.string "bold yellow"
color-link identifier "bold red"
color-link statement "bold cyan"
color-link symbol "white"
color-link symbol.brackets "white"
color-link symbol.tag "bold green"
color-link preproc "black,cyan"
color-link type "green"
color-link special "magenta"
color-link ignore "default"
color-link error ",brightred"
color-link todo ",brightyellow"
color-link indent-char ",cyan"
color-link line-number "green"
color-link statusline "black,cyan"
color-link tabbar "black,cyan"
color-link current-line-number "black,cyan"
color-link cursor-line "black,cyan"
color-link gutter-error ",red"
color-link gutter-warning "red"
color-link color-column "cyan"

View File

@@ -0,0 +1,5 @@
#Monochrome Paper theme.
#Edit your files on a white background without colors.
color-link default "black,white"
color-link statusline "white,black"
color-link tabbar "white,black"

View File

@@ -0,0 +1,3 @@
#Monochrome
#This makes micro use only the terminal's default
# foreground and background colours.

View File

@@ -5,6 +5,7 @@ color-link constant "#AE81FF,#282828"
color-link constant.string "#E6DB74,#282828"
color-link constant.string.char "#BDE6AD,#282828"
color-link statement "#F92672,#282828"
color-link symbol "#F92672,#282828"
color-link preproc "#CB4B16,#282828"
color-link type "#66D9EF,#282828"
color-link special "#A6E22E,#282828"
@@ -12,6 +13,7 @@ color-link underlined "#D33682,#282828"
color-link error "bold #CB4B16,#282828"
color-link todo "bold #D33682,#282828"
color-link statusline "#282828,#F8F8F2"
color-link tabbar "#282828,#F8F8F2"
color-link indent-char "#505050,#282828"
color-link line-number "#AAAAAA,#323232"
color-link current-line-number "#AAAAAA,#282828"
@@ -19,3 +21,7 @@ color-link gutter-error "#CB4B16,#282828"
color-link gutter-warning "#E6DB74,#282828"
color-link cursor-line "#323232"
color-link color-column "#323232"
#No extended types; Plain brackets.
color-link type.extended "default"
#color-link symbol.brackets "default"
color-link symbol.tag "#AE81FF,#282828"

View File

@@ -0,0 +1,30 @@
#Colorscheme styled after default Debian nano.
color-link comment "bold blue"
color-link comment.bright "cyan"
color-link constant "red"
color-link constant.bool "yellow"
color-link constant.bool.true "bold green"
color-link constant.bool.false "bold red"
color-link constant.number "default"
color-link constant.specialChar "bold magenta"
color-link constant.string "bold yellow"
color-link identifier "bold blue"
color-link identifier.macro "bold red"
color-link statement "bold green"
color-link symbol "green"
#color-link symbol.tag "blue"
color-link preproc "brightcyan"
color-link type "green"
color-link special "magenta"
color-link ignore "default"
color-link error "white,black"
color-link todo "bold cyan"
color-link indent-char ",green"
color-link line-number "default"
color-link current-line-number "default"
color-link gutter-error ",white"
color-link gutter-warning "white"
color-link cursor-line "default"
color-link color-column "white"
#No extended types ( bool in C ); Plain brackets
color-link type.extended "default"

View File

@@ -0,0 +1,30 @@
#NES
#A color theme only using NES pallette colours
color-link default ""
color-link comment ""
color-link constant ""
color-link constant.bool ""
color-link constant.bool.true ""
color-link constant.bool.false ""
color-link constant.number ""
color-link constant.specialChar ""
color-link constant.string ""
color-link constant.string.url "underline"
color-link identifier ""
color-link identifier.var ""
color-link preproc ""
color-link special ""
color-link statement ""
color-link symbol ""
color-link symbol.brackets ""
color-link symbol.tag ""
color-link type ""
color-link type.keyword ""
color-link error ""
color-link todo ""
color-link cursor-line ""
color-link statusline ""
color-link tabbar ""
color-link color-column ""
color-link gutter-error ""
color-link gutter-warning ""

View File

@@ -0,0 +1,22 @@
#Paper theme, true color edition
#Edit on an *actual* white background!
color-link default "#000000,#efefef"
color-link comment ""
color-link constant ""
color-link constant.string ""
color-link constant.string.url "underline #0000dd"
color-link identifier ""
color-link identifier.var ""
color-link special ""
color-link statement ""
color-link symbol ""
color-link symbol.brackets ""
color-link symbol.tag ""
color-link type ""
color-link statusline ""
color-link tabbar ""
color-link error ""
color-link todo ""
color-link color-column ""
color-link gutter-error ""
color-link gutter-warning ""

View File

@@ -0,0 +1,27 @@
#Paper theme, Edit on a white background.
color-link default "black,white"
color-link comment "bold black"
color-link constant "cyan"
color-link constant.string "bold green"
color-link identifier "blue"
color-link identifier.macro "bold red"
color-link identifier.var "bold blue"
color-link identifier.class "bold green"
color-link statement "green"
color-link symbol "red"
color-link symbol.brackets "default"
color-link symbol.tag "bold blue"
color-link preproc "bold cyan"
color-link type "green"
color-link special "magenta"
color-link ignore "default"
color-link error ",brightred"
color-link todo ",brightyellow"
color-link indent-char ",brightgreen"
color-link line-number "black"
color-link statusline "white,black"
color-link tabbar "white,black"
color-link current-line-number "blue"
color-link gutter-error ",red"
color-link gutter-warning "red"
color-link color-column "black"

View File

@@ -2,6 +2,7 @@ color-link comment "blue"
color-link constant "red"
color-link identifier "cyan"
color-link statement "yellow"
color-link symbol "yellow"
color-link preproc "magenta"
color-link type "green"
color-link special "magenta"
@@ -13,5 +14,12 @@ color-link line-number "yellow"
color-link current-line-number "red"
color-link gutter-error ",red"
color-link gutter-warning "red"
color-link cursor-line "white"
#Cursor line causes readability issues. Disabled for now.
#color-link cursor-line "white,black"
color-link color-column "white"
#No extended types. (bool in C)
color-link type.extended "default"
#No bracket highlighting.
color-link symbol.brackets "default"
#Color shebangs the comment color
color-link preproc.shebang "comment"

View File

@@ -3,6 +3,7 @@ color-link comment "#586E75,#002833"
color-link identifier "#268BD2,#002833"
color-link constant "#2AA198,#002833"
color-link statement "#859900,#002833"
color-link symbol "#859900,#002833"
color-link preproc "#CB4B16,#002833"
color-link type "#B58900,#002833"
color-link special "#DC322F,#002833"
@@ -10,6 +11,7 @@ color-link underlined "#D33682,#002833"
color-link error "bold #CB4B16,#002833"
color-link todo "bold #D33682,#002833"
color-link statusline "#003541,#839496"
color-link tabbar "#003541,#839496"
color-link indent-char "#586E75,#002833"
color-link line-number "#586E75,#003541"
color-link current-line-number "#586E75,#002833"
@@ -17,3 +19,5 @@ color-link gutter-error "#003541,#CB4B16"
color-link gutter-warning "#CB4B16,#002833"
color-link cursor-line "#003541"
color-link color-column "#003541"
color-link type.extended "default"
color-link symbol.brackets "default"

View File

@@ -1,18 +1,23 @@
color-link comment "brightgreen"
color-link comment "bold brightgreen"
color-link constant "cyan"
color-link constant.specialChar "red"
color-link identifier "blue"
color-link statement "green"
color-link symbol "green"
color-link preproc "brightred"
color-link type "yellow"
color-link special "red"
color-link special "blue"
color-link underlined "magenta"
color-link error "bold brightred"
color-link todo "bold magenta"
color-link statusline "black,brightblue"
color-link tabbar "black,brightblue"
color-link indent-char "black"
color-link line-number "brightgreen,black"
color-link current-line-number "brightgreen,default"
color-link line-number "bold brightgreen,black"
color-link current-line-number "bold brightgreen,default"
color-link gutter-error "black,brightred"
color-link gutter-warning "brightred,default"
color-link cursor-line "black"
color-link color-column "black"
color-link type.extended "default"
color-link symbol.brackets "default"

View File

@@ -0,0 +1,23 @@
#Symbian
color-link default "#000000,#ff8a00"
color-link comment "#8c0000"
color-link constant "#8c0000"
color-link identifier "#ffff8c"
color-link preproc "#ffff8c,#8c0000"
color-link special "#8c0000"
color-link statement "#8c0000"
color-link symbol "#8c0000"
color-link type "#8c0000"
color-link error "#ffff8c,#8c0000"
color-link todo "#8c0000,#ffff8c"
color-link statusline "#ffff8c,#8c0000"
color-link tabbar "#ffff8c,#8c0000"
color-link color-column "#8c0000"
color-link line-number "#ffff8c,#8c0000"
color-link current-line-number "#000000,#ff8a00"
color-link gutter-error "#ffff8c,#8c0000"
color-link gutter-warning "default"
#000000
#8c0000
#ff8a00
#ffff8c

View File

@@ -5,6 +5,7 @@ color-link constant.number "116,237"
color-link constant "181,237"
color-link identifier "223,237"
color-link statement "223,237"
color-link symbol "223,237"
color-link preproc "223,237"
color-link type "187,237"
color-link special "181,237"
@@ -12,6 +13,7 @@ color-link underlined "188,237"
color-link error "115,236"
color-link todo "bold 254,237"
color-link statusline "186,236"
color-link tabbar "186,236"
color-link indent-char "238,237"
color-link line-number "248,238"
color-link gutter-error "237,174"

View File

@@ -5,13 +5,18 @@ This help page aims to cover two aspects of micro's syntax highlighting engine:
- How to create colorschemes and use them
- How to create syntax files to add to the list of languages micro can highlight
### Colorschemes
## Colorschemes
Micro comes with a number of colorschemes by default. Here is the list:
* simple: this is the simplest colorscheme. It uses 16 colors which are
set by your terminal
* mc: A 16-color theme based on the look and feel of GNU Midnight Commander.
This will look great used in conjunction with Midnight Commander.
* nano: A 16-color theme loosely based on GNU nano's syntax highlighting.
* monokai: this is the monokai colorscheme; you may recognize it as
Sublime Text's default colorscheme. It requires true color to
look perfect, but the 256 color approximation looks very good as well.
@@ -19,25 +24,57 @@ Micro comes with a number of colorschemes by default. Here is the list:
* zenburn: The 'zenburn' colorscheme and works well with 256 color terminals
* solarized: this is the solarized colorscheme.
* solarized: this is the solarized colorscheme.
You should have the solarized color palette in your terminal to use it.
* solarized-tc: this is the solarized colorscheme for true color; just
make sure your terminal supports true color before using it and that the
* solarized-tc: this is the solarized colorscheme for true color; just
make sure your terminal supports true color before using it and that the
MICRO_TRUECOLOR environment variable is set to 1 before starting micro.
* atom-dark-tc: this colorscheme is based off of Atom's "dark" colorscheme.
It requires true color to look good.
To enable one of these colorschemes just run the command `set colorscheme solarized`.
(or whichever one you choose).
* cmc-16: A very nice 16-color theme. Written by contributor CaptainMcClellan
(Collin Warren.) Licensed under the same license as the rest of the themes.
* cmc-paper: Basically cmc-16, but on a white background. ( Actually light grey on most
ANSI (16-color) terminals.)
* cmc-tc: A true colour variant of the cmc theme.
It requires true color to look its best. Use cmc-16 if your terminal doesn't support true color.
* codeblocks: A colorscheme based on the Code::Blocks IDE's default syntax highlighting.
* codeblocks-paper: Same as codeblocks, but on a white background. ( Actually light grey. )
* github-tc: A colorscheme based on Github's syntax highlighting. Requires true color to look its best.
* paper-tc: A nice minimalist theme with a light background, good for editing documents on.
Requires true color to look its best. Not to be confused with `-paper` suffixed themes.
* geany: Colorscheme based on geany's default highlighting.
* geany-alt-tc: Based on an alternate theme bundled with geany.
* flamepoint-tc: A fire inspired, high intensity true color theme written by CaptainMcClellan.
As with all the other `-tc` suffixed themes, it looks its best on a
To enable one of these colorschemes just press CtrlE in micro and type `set colorscheme solarized`.
(or whichever one you choose). You can also use `set colorscheme monochrome` if you'd prefer
to have just the terminal's default foreground and background colors.
Note: This provides no syntax highlighting!
See `help gimmickcolors` for a list of some true colour themes that are more
just for fun than for serious use. ( Though feel free if you want! )
---
### Creating a Colorscheme
Micro's colorschemes are also extremely simple to create. The default ones can be found
[here](https://github.com/zyedidia/micro/tree/master/runtime/colorschemes).
They are only about 18 lines in total.
They are only about 18-30 lines in total.
Basically to create the colorscheme you need to link highlight groups with actual colors.
This is done using the `color-link` command.
@@ -84,7 +121,8 @@ If the user's terminal supports true color, then you can also specify colors exa
their hex codes. If the terminal is not true color but micro is told to use a true color colorscheme
it will attempt to map the colors to the available 256 colors.
Generally colorschemes which require true color terminals to look good are marked with a `-tc` suffix.
Generally colorschemes which require true color terminals to look good are marked with a `-tc` suffix
and colorschemes which supply a white background are marked with a `-paper` suffix.
---
@@ -95,63 +133,172 @@ Here is a list of the colorscheme groups that you can use:
* identifier
* constant
* statement
* symbol
* preproc
* type
* special
* underlined
* error
* todo
* statusline (color of the statusline)
* indent-char (color of the character which indicates tabs if the option is enabled)
* statusline ( Color of the statusline)
* tabbar ( Color of the tabbar that lists open files.)
* indent-char ( Color of the character which indicates tabs if the option is enabled)
* line-number
* gutter-error
* gutter-warning
* cursor-line
* current-line-number
* color-column
* ignore
* divider ( Color of the divider between vertical splits. )
Colorschemes can be placed in the `~/.config/micro/colorschemes` directory to be used.
### Syntax files
The syntax files specify how to highlight certain languages.
The first statement in a syntax file will probably the syntax statement. This tells micro
what language the syntax file is for and how to detect a file in that language.
Essentially, it's just
```
syntax "Name of language" "\.extension$"
```
For the extension, micro will just compare that regex to the filename and if it matches then it
will use the syntax rules defined in the remainder of the file.
There is also a possibility to use a header statement which is a regex that micro will compare
with the first line of the file. This is almost only used for shebangs at the top of shell scripts
which don't have any extension (see sh.micro for an example).
Colorschemes must be placed in the `~/.config/micro/colorschemes` directory to be used.
---
The rest of a syntax file is very simple and is essentially a list of regexes specifying how to highlight
different expressions.
In addition to the main colorscheme groups, there are subgroups that you can
specify by adding `.subgroup` to the group. If you're creating your own
custom syntax files, you can make use of your own subgroups.
It is recommended that when creating a syntax file you use the colorscheme groups (see above) to
highlight different expressions. You may also hard code colors, but that may not look good depending
on what terminal colorscheme the user has installed.
If micro can't match the subgroup, it'll default to the root group, so
it's safe and recommended to use subgroups in your custom syntax files.
Here is an example to highlight comments (expressions starting with `//`):
For example if `constant.string` is found in your colorscheme, micro will
use that for highlighting strings. If it's not found, it will use constant
instead. Micro tries to match the largest set of groups it can find in the
colorscheme definitions, so if, for examle `constant.bool.true` is found then
micro will use that. If `constant.bool.true` is not found but `constant.bool`
is found micro will use `constant.bool`. If not, it uses `constant`.
Here's a list of subgroups used in micro's built-in syntax files.
* comment.bright ( Some filetypes have distinctions between types of comments.)
* constant.bool
* constant.bool.true
* constant.bool.false
* constant.number
* constant.specialChar
* constant.string
* constant.string.url
* identifier.class ( Also used for functions. )
* identifier.macro
* identifier.var
* preproc.shebang ( The #! at the beginning of a file that tells the os what script interpreter to use. )
* symbol.brackets ( {}()[] and sometimes <> )
* symbol.operator ( Color operator symbols differently. )
* symbol.tag ( For html tags, among other things.)
* type.keyword ( If you want a special highlight for keywords like `private` )
In the future, plugins may also be able to use color groups for styling.
## Syntax files
The syntax files is written in yaml-format and specify how to highlight languages.
Micro's builtin syntax highlighting tries very hard to be sane, sensible
and provide ample coverage of the meaningful elements of a language. Micro has
syntax files built int for over 100 languages now. However, there may be
situations where you find Micro's highlighting to be insufficient or not to
your liking. Good news is you can create syntax files (.micro extension), place them in
`~/.config/micro/syntax` and Micro will use those instead.
### Filetype defintion
You must start the syntax file by declaring the filetype:
```
color comment "//.*"
filetype: go
```
This will highlight the regex `//.*` in the color that the user's colorscheme has linked to the comment
group.
#### Detect definition
Note that this regex only matches the current line. Here is an example for multiline comments (`/* comment */`):
Then you must provide information about how to detect the filetype:
```
color comment start="/\*" end="\*/"
detect:
filename: "\\.go$"
```
Micro will match this regex against a given filename to detect the filetype. You may also
provide an optional `header` regex that will check the first line of the file. For example:
```
detect:
filename: "\\.ya?ml$"
header: "%YAML"
```
#### Syntax rules
Next you must provide the syntax highlighting rules. There are two types of rules: patterns and regions.
A pattern is matched on a single line and usually a single word as well. A region highlights between two
patterns over multiple lines and may have rules of its own inside the region.
Here are some example patterns in Go:
```
rules:
- special: "\\b(break|case|continue|default|go|goto|range|return)\\b"
- statement: "\\b(else|for|if|switch)\\b"
- preproc: "\\b(package|import|const|var|type|struct|func|go|defer|iota)\\b"
```
The order of patterns does matter as patterns lower in the file will overwrite the ones defined above them.
And here are some example regions for Go:
```
- constant.string:
start: "\""
end: "\""
rules:
- constant.specialChar: "%."
- constant.specialChar: "\\\\[abfnrtv'\\\"\\\\]"
- constant.specialChar: "\\\\([0-7]{3}|x[A-Fa-f0-9]{2}|u[A-Fa-f0-9]{4}|U[A-Fa-f0-9]{8})"
- comment:
start: "//"
end: "$"
rules:
- todo: "(TODO|XXX|FIXME):?"
- comment:
start: "/\\*"
end: "\\*/"
rules:
- todo: "(TODO|XXX|FIXME):?"
```
Notice how the regions may contain rules inside of them. Any inner rules that are matched are then skipped when searching
for the end of the region. For example, when highlighting `"foo \" bar"`, since `\"` is matched by an inner rule in the
region, it is skipped. Likewise for `"foo \\" bar`, since `\\` is matched by an inner rule, it is skipped, and then the `"`
is found and the string ends at the correct place.
You may also explicitly mark skip regexes if you don't want them to be highlighted. For example:
```
- constant.string:
start: "\""
end: "\""
skip: "\\."
rules: []
```
#### Includes
You may also include rules from other syntax files as embedded languages. For example, the following is possible
for html:
```
- default:
start: "<script.*?>"
end: "</script.*?>"
rules:
- include: "javascript"
- default:
start: "<style.*?>"
end: "</style.*?>"
rules:
- include: "css"
```

View File

@@ -42,6 +42,10 @@ Here are the possible commands that you can use.
* `tab filename`: opens the given file in a new tab.
* `tabswitch tab`: This command will switch to the specified tab.
The `tab` can either be a tab number, or a name of a tab.
* `log`: opens a log of all messages and debug statements.
* `plugin install plugin_name`: installs the given plugin.

141
runtime/help/defaultkeys.md Normal file
View File

@@ -0,0 +1,141 @@
#Default Keys
Below are simple charts of the default hotkeys and their functions.
For more information about binding custom hotkeys or changing
default bindings, please run `>help keybindings`
Please remember that *all* keys here are rebindable!
If you don't like it, you can change it!
(We are not responsible for you forgetting what you bind keys to.
Do not open an issue because you forgot your keybindings.)
#Power user
+--------+---------------------------------------------------------+
| Ctrl+E | Switch to the micro command prompt to run a command. |
| | (See `>help commands` for a list of commands. ) |
+--------+---------------------------------------------------------+
| Ctrl+B | Run shell commands in micro's current working directory.|
+--------+---------------------------------------------------------+
#Navigation
+--------+---------------------------------------------------------+
| Key | Description of function |
|--------+---------------------------------------------------------+
| Arrows | Move the cursor around your current document. |
| | (Yes this is rebindable to the vim keys if you want.) |
+--------+---------------------------------------------------------+
| Shift+ | Move and select text. |
| Arrows | |
+--------+---------------------------------------------------------+
| Home | Move to the beginning of the current line. (Naturally.) |
+--------+---------------------------------------------------------+
| End | Move to the end of the current line. |
+--------+---------------------------------------------------------+
| PageUp | Move cursor up lines quickly. |
+--------+---------------------------------------------------------+
| PageDn | Move cursor down lines quickly. |
+--------+---------------------------------------------------------+
| Ctrl+L | Jump to line in current file. ( Prompts for line # ) |
+--------+---------------------------------------------------------+
| Ctrl+W | Move between splits open in current tab. |
| | (See vsplit and hsplit in `>help commands`) |
+--------+---------------------------------------------------------+
| Ctrl+T | Open a new tab. |
+--------+---------------------------------------------------------+
| Alt+, | Move to the previous tab in the tablist. |
| | (This works like moving between file buffers in nano) |
+--------+---------------------------------------------------------+
| Alt+. | Move to the next tab in the tablist. |
+--------+---------------------------------------------------------+
#Find Operations
+--------+---------------------------------------------------------+
| Ctrl+F | Find text in current file. ( Prompts for text to find.) |
+--------+---------------------------------------------------------+
| Ctrl+N | Find next instance of current search in current file. |
+--------+---------------------------------------------------------+
| Ctrl+P | Find prev instance of current search in current file. |
+--------+---------------------------------------------------------+
#File Operations
+--------+---------------------------------------------------------+
| Ctrl+Q | Close current file. ( Quits micro if last file open. ) |
+--------+---------------------------------------------------------+
| Ctrl+O | Open a file. ( Prompts you to input filename. ) |
+--------+---------------------------------------------------------+
| Ctrl+S | Save current file. |
+--------+---------------------------------------------------------+
#Text operations
+--------+---------------------------------------------------------+
| Ctrl+A | Select all text in current file. |
+--------+---------------------------------------------------------+
| Ctrl+X | Cut selected text. |
+--------+---------------------------------------------------------+
| Ctrl+C | Copy selected text. |
+--------+---------------------------------------------------------+
| Ctrl+V | Paste selected text. |
+--------+---------------------------------------------------------+
| Ctrl+K | Cut current line. ( Can then be pasted with Ctrl+V) |
+--------+---------------------------------------------------------+
| Ctrl+D | Duplicate current line. |
+--------+---------------------------------------------------------+
| Ctrl+Z | Undo actions. |
+--------+---------------------------------------------------------+
| Ctrl+Y | Redo actions. |
+--------+---------------------------------------------------------+
#Other
+--------+---------------------------------------------------------+
| Ctrl+G | Open the help file. |
+--------+---------------------------------------------------------+
| Ctrl+H | Alternate backspace. |
| | (Some old terminals don't support the Backspace key .) |
+--------+---------------------------------------------------------+
| Ctrl+R | Toggle the line number ruler. ( On the lefthand side.) |
+--------+---------------------------------------------------------+
#Emacs style actions
+--------+---------------------------------------------------------+
| Alt+F | Move to the end of the next word. (To the next space.) |
+--------+---------------------------------------------------------+
| Alt+B | Move to the beginning of the previous word. |
+--------+---------------------------------------------------------+
| Alt+A | Alternate Home key. ( Move to beginning of line. ) |
+--------+---------------------------------------------------------+
| Alt+E | Alternate End key. ( Move to the end of line.) |
+--------+---------------------------------------------------------+
| Alt+P | Move cursor up. ( Same as up key. ) |
+--------+---------------------------------------------------------+
| Alt+N | Move cursor down. ( Same as down key. ) |
+--------+---------------------------------------------------------+
#Function keys.
Warning! The function keys may not work in all terminals!
+--------+---------------------------------------------------------+
| F1 | Open help. |
+--------+---------------------------------------------------------+
| F2 | Save current file. |
+--------+---------------------------------------------------------+
| F3 | Find in current file. ( Same as Ctrl+F ) |
+--------+---------------------------------------------------------+
| F4 | Close current file. (Quit if only file.) |
+--------+---------------------------------------------------------+
| F7 | Find in current file. (Same as Ctrl+F) |
+--------+---------------------------------------------------------+
| F10 | Close current file. |
+--------+---------------------------------------------------------+
#Macros
Micro supports the use of keyboard macros. Simply press Ctrl+U to
begin recording a macro and press Ctrl+U to stop recording.
Press Ctrl+J to run your recorded macro.

View File

@@ -0,0 +1,14 @@
# Gimmick colors
We have included a few colorschemes that are for fun:
* funky-cactus: I don't know why I made this. (Written by CaptainMcClellan)
* gameboy-tc: Colorscheme based on the olive green original Gameboy!
* nes-tc: A colorscheme and syntax highlighting using only colors in the
Nintendo Entertainment System color palette.
* symbian-tc: Colorscheme based on SymbOS's GUI.
* matrix: Pretend it's 1981 with a colorscheme based on a monochrome
IBM 5151. ( Does not include the ghosting and trailing. )
Check the plugin repo periodically for gimmick-color extension packs
and genuine additional themes.

View File

@@ -1,5 +1,6 @@
# Micro help text
Thank you for downloading and using micro.
Micro is a terminal-based text editor that aims to be easy to use and intuitive,
while also taking advantage of the full capabilities of modern terminals.
@@ -12,9 +13,11 @@ See the next section for more information about documentation and help.
Press CtrlQ to quit, and CtrlS to save. Press CtrlE to start typing commands
and you can see which commands are available by pressing tab, or by
viewing the help topic `> help commands`. When I write `> ...` I mean press
CtrlE and then type whatever is there.
CtrlE and then type whatever is there.
Move the cursor around with the mouse or the arrow keys.
Move the cursor around with the mouse or the arrow keys. Type `>help defaultkeys` to
get a quick, easy overview of the default hotkeys and what they do. For more info
on rebinding keys, see type `>help keybindings`
If the colorscheme doesn't look good, you can change it with `> set colorscheme ...`.
You can press tab to see the available colorschemes, or see more information with
@@ -34,6 +37,7 @@ Here are the possible help topics that you can read:
* tutorial: A brief tutorial which gives an overview of all the other help topics
* keybindings: Gives a full list of the default keybindings as well as how to rebind them
* defaultkeys: Gives a more straight-forward list of the hotkey commands and what they do.
* commands: Gives a list of all the commands and what they do
* options: Gives a list of all the options you can customize
* plugins: Explains how micro's plugin system works and how to create your own plugins

View File

@@ -1,89 +1,15 @@
# Keybindings
Here are the default keybindings in json format. You can rebind them to your liking, following the same format.
Micro has a plethora of hotkeys that make it easy and powerful to use and all
hotkeys are fully customizable to your liking.
Custom keybindings are stored internally in micro if changed with the `>bind` command or
you can also be added in the file `~/.config/micro/bindings.json` as discussed below.
For a list of the default keybindings in the json format used by micro, please see
the end of this file. For a more user-friendly list with explanations of what the default
hotkeys are and what they do, please see `>help defaultkeys`
```json
{
"Up": "CursorUp",
"Down": "CursorDown",
"Right": "CursorRight",
"Left": "CursorLeft",
"ShiftUp": "SelectUp",
"ShiftDown": "SelectDown",
"ShiftLeft": "SelectLeft",
"ShiftRight": "SelectRight",
"AltLeft": "WordLeft",
"AltRight": "WordRight",
"AltShiftRight": "SelectWordRight",
"AltShiftLeft": "SelectWordLeft",
"AltUp": "MoveLinesUp",
"AltDown": "MoveLinesDown",
"CtrlLeft": "StartOfLine",
"CtrlRight": "EndOfLine",
"CtrlShiftLeft": "SelectToStartOfLine",
"CtrlShiftRight": "SelectToEndOfLine",
"CtrlUp": "CursorStart",
"CtrlDown": "CursorEnd",
"CtrlShiftUp": "SelectToStart",
"CtrlShiftDown": "SelectToEnd",
"Enter": "InsertNewline",
"Space": "InsertSpace",
"CtrlH": "Backspace",
"Backspace": "Backspace",
"Alt-CtrlH": "DeleteWordLeft",
"Alt-Backspace": "DeleteWordLeft",
"Tab": "IndentSelection,InsertTab",
"Backtab": "OutdentSelection",
"CtrlO": "OpenFile",
"CtrlS": "Save",
"CtrlF": "Find",
"CtrlN": "FindNext",
"CtrlP": "FindPrevious",
"CtrlZ": "Undo",
"CtrlY": "Redo",
"CtrlC": "Copy",
"CtrlX": "Cut",
"CtrlK": "CutLine",
"CtrlD": "DuplicateLine",
"CtrlV": "Paste",
"CtrlA": "SelectAll",
"CtrlT": "AddTab",
"CtrlRightSq": "PreviousTab",
"CtrlBackslash": "NextTab",
"Home": "StartOfLine",
"End": "EndOfLine",
"CtrlHome": "CursorStart",
"CtrlEnd": "CursorEnd",
"PageUp": "CursorPageUp",
"PageDown": "CursorPageDown",
"CtrlG": "ToggleHelp",
"CtrlR": "ToggleRuler",
"CtrlL": "JumpLine",
"Delete": "Delete",
"CtrlB": "ShellMode",
"CtrlQ": "Quit",
"CtrlE": "CommandMode",
"CtrlW": "NextSplit",
"CtrlU": "ToggleMacro",
"CtrlJ": "PlayMacro",
// Emacs-style keybindings
"Alt-f": "WordRight",
"Alt-b": "WordLeft",
"Alt-a": "StartOfLine",
"Alt-e": "EndOfLine",
"Alt-p": "CursorUp",
"Alt-n": "CursorDown",
// Integration with file managers
"F1": "ToggleHelp",
"F2": "Save",
"F4": "Quit",
"F7": "Find",
"F10": "Quit",
"Esc": "Escape",
}
```
If `~/.config/micro/bindings.json` does not exist, you can simply create it.
Micro will know what to do with it.
You can use the alt keys + arrows to move word by word.
Ctrl left and right move the cursor to the start and end of the line, and
@@ -106,6 +32,9 @@ following in the `bindings.json` file.
}
```
In addition to editing your `~/.config/micro/bindings.json`, you can run
`>bind <keycombo> <action>` For a list of bindable actions, see below.
You can also chain commands when rebinding. For example, if you want Alt-s to save
and quit you can bind it like so:
@@ -115,6 +44,11 @@ and quit you can bind it like so:
}
```
# Unbinding keys
It is also possible to disable any of the default key bindings by use of the
`UnbindKey` action in the user's `bindings.json` file.
# Bindable actions and bindable keys
The list of default keybindings contains most of the possible actions and keys
@@ -154,6 +88,7 @@ Delete
Center
InsertTab
Save
SaveAll
SaveAs
Find
FindNext
@@ -196,6 +131,7 @@ HSplit
PreviousSplit
ToggleMacro
PlayMacro
UnbindKey
```
Here is the list of all possible keys you can bind:
@@ -326,6 +262,95 @@ Escape
Enter
```
# Default keybinding configuration.
```json
{
"Up": "CursorUp",
"Down": "CursorDown",
"Right": "CursorRight",
"Left": "CursorLeft",
"ShiftUp": "SelectUp",
"ShiftDown": "SelectDown",
"ShiftLeft": "SelectLeft",
"ShiftRight": "SelectRight",
"AltLeft": "WordLeft",
"AltRight": "WordRight",
"AltShiftRight": "SelectWordRight",
"AltShiftLeft": "SelectWordLeft",
"AltUp": "MoveLinesUp",
"AltDown": "MoveLinesDown",
"CtrlLeft": "StartOfLine",
"CtrlRight": "EndOfLine",
"CtrlShiftLeft": "SelectToStartOfLine",
"ShiftHome": "SelectToStartOfLine",
"CtrlShiftRight": "SelectToEndOfLine",
"ShiftEnd": "SelectToEndOfLine",
"CtrlUp": "CursorStart",
"CtrlDown": "CursorEnd",
"CtrlShiftUp": "SelectToStart",
"CtrlShiftDown": "SelectToEnd",
"Enter": "InsertNewline",
"Space": "InsertSpace",
"CtrlH": "Backspace",
"Backspace": "Backspace",
"Alt-CtrlH": "DeleteWordLeft",
"Alt-Backspace": "DeleteWordLeft",
"Tab": "IndentSelection,InsertTab",
"Backtab": "OutdentSelection",
"CtrlO": "OpenFile",
"CtrlS": "Save",
"CtrlF": "Find",
"CtrlN": "FindNext",
"CtrlP": "FindPrevious",
"CtrlZ": "Undo",
"CtrlY": "Redo",
"CtrlC": "Copy",
"CtrlX": "Cut",
"CtrlK": "CutLine",
"CtrlD": "DuplicateLine",
"CtrlV": "Paste",
"CtrlA": "SelectAll",
"CtrlT": "AddTab",
"Alt,": "PreviousTab",
"Alt.": "NextTab",
"Home": "StartOfLine",
"End": "EndOfLine",
"CtrlHome": "CursorStart",
"CtrlEnd": "CursorEnd",
"PageUp": "CursorPageUp",
"PageDown": "CursorPageDown",
"CtrlG": "ToggleHelp",
"CtrlR": "ToggleRuler",
"CtrlL": "JumpLine",
"Delete": "Delete",
"CtrlB": "ShellMode",
"CtrlQ": "Quit",
"CtrlE": "CommandMode",
"CtrlW": "NextSplit",
"CtrlU": "ToggleMacro",
"CtrlJ": "PlayMacro",
// Emacs-style keybindings
"Alt-f": "WordRight",
"Alt-b": "WordLeft",
"Alt-a": "StartOfLine",
"Alt-e": "EndOfLine",
"Alt-p": "CursorUp",
"Alt-n": "CursorDown",
// Integration with file managers
"F1": "ToggleHelp",
"F2": "Save",
"F3": "Find",
"F4": "Quit",
"F7": "Find",
"F10": "Quit",
"Esc": "Escape",
}
```
#Final notes
Note: On some old terminal emulators and on Windows machines, `CtrlH` should be used
for backspace.

View File

@@ -32,6 +32,10 @@ Here are the options that you can set:
default value: `false`
* `rmtrailingws`: micro will automatically trim trailing whitespaces at eol.
default value: `false`
* `tabsize`: sets the tab size to `option`
default value: `4`
@@ -61,6 +65,11 @@ Here are the options that you can set:
default value: `off`
* `tabmovement`: navigate spaces at the beginning of lines as if they are tabs (e.g. move over 4 spaces at once).
This option only does anything if `tabstospaces` is on.
default value: `off`
* `autoindent`: when creating a new line use the same indentation as the
previous line
@@ -99,17 +108,17 @@ Here are the options that you can set:
* `softwrap`: should micro wrap lines that are too long to fit on the screen
default value: `off`
default value: `off`
* `splitRight`: when a vertical split is created, should it be created to the right of
the current split?
default value: `on`
default value: `on`
* `splitRight`: when a horizontal split is created, should it be created below the
* `splitBottom`: when a horizontal split is created, should it be created below the
current split?
default value: `on`
default value: `on`
* `autosave`: micro will save the buffer every 8 seconds automatically.
Micro also will automatically save and quit when you exit without asking.
@@ -123,13 +132,28 @@ Here are the options that you can set:
metadata about the given plugin. See the `Plugin Manager` section of the `plugins` help topic
for more information.
default value: `https://github.com/micro-editor/plugin-channel`
default value: `https://github.com/micro-editor/plugin-channel`
* `pluginrepos`: contains all the 'repositories' micro's plugin manager will search for
plugins in. A repository consists of a `repo.json` file which contains metadata for a
single plugin.
default value: ` `
default value: ` `
* `useprimary` (only useful on Linux): defines whether or not micro will use the primary clipboard to copy selections
in the background. This does not affect the normal clipboard using Ctrl-C and Ctrl-V.
default value: `on`
* `keepautoindent`: when using autoindent, whitespace is added for you. This option determines if
when you move to the next line without any insertions the whitespace that was added should be deleted.
By default the autoindent whitespace is deleted if the line was left empty.
default value: `off`
* `termtitle`: defines whether or not your terminal's title will be set by micro when opened.
default value: `off`
---
@@ -143,6 +167,12 @@ Default plugin options:
default value: `on`
* `ftoptions`: by default, micro will set some options based on the filetype. At the moment, micro will
use tabs for makefiles and spaces for python files regardless of your settings. If you would like to
disable this behavior turn this option off.
default value: `on`
Any option you set in the editor will be saved to the file
~/.config/micro/settings.json so, in effect, your configuration file will be
created for you. If you'd like to take your configuration with you to another

View File

@@ -51,6 +51,12 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...)
* `messenger`: lets you send messages to the user or create prompts
* `NewBuffer(text, path string) *Buffer`: creates a new buffer from a given reader with a given path
* `GetLeadingWhitespace() bool`: returns the leading whitespace of the given string
* `IsWordChar(str string) bool`: returns whether or not the string is a 'word character'
* `RuneStr(r rune) string`: returns a string containing the given rune
* `Loc(x, y int) Loc`: returns a new `Loc` struct
@@ -67,7 +73,7 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...)
* `SetOption(option, value string)`: sets the given option to the value. This will
set the option globally, unless it is a local only option.
* `SetLocalOption(option, value string, buffer *Buffer)`: sets the given option to
* `SetLocalOption(option, value string, view *View)`: sets the given option to
the value locally in the given buffer
* `BindKey(key, action string)`: binds `key` to `action`
@@ -88,9 +94,11 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...)
`waitToClose` bool only applies if `interactive` is true and means that it should wait before
returning to the editor.
* `ToCharPos(loc Loc, buf *Buffer) int`: returns the character position of a given x, y location.
* `ToCharPos(loc Loc, buf *Buffer) int`: returns the character position of a given x, y location
* `ByteOffset(loc Loc, buf *Buffer) int`: exactly like `ToCharPos` except it it counts bytes instead of runes.
* `Reload`: (Re)load everything
* `ByteOffset(loc Loc, buf *Buffer) int`: exactly like `ToCharPos` except it it counts bytes instead of runes
* `JobSpawn(cmdName string, cmdArgs []string, onStdout, onStderr, onExit string, userargs ...string)`:
Starts running the given process in the background. `onStdout` `onStderr` and `onExit`
@@ -99,8 +107,8 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...)
`userargs` are the arguments which will get passed to the callback functions
* `JobStart(cmd string, onStdout, onStderr, onExit string, userargs ...string)`:
Starts running the given shell command in the background.
This function is a shorthand for `JobSpawn`.
Starts running the given shell command in the background. Note that the command execute
is first parsed by a shell when using this command. It is executed with `sh -c`.
* `JobSend(cmd *exec.Cmd, data string)`: send a string into the stdin of the job process
@@ -130,8 +138,8 @@ If you want a standard prompt, just use `messenger.Prompt(prompt, "", 0)`
# Adding help files, syntax files, or colorschemes in your plugin
You can use the `AddRuntimeFile(name, type, path string)` function to add various kinds of
files to your plugin. For example, if you'd like to add a help topic and to your plugin
called `test`, you would create the `test.md` file for example, and runt the function:
files to your plugin. For example, if you'd like to add a help topic to your plugin
called `test`, you would create a `test.md` file, and call the function:
```lua
AddRuntimeFile("test", "help", "test.md")
@@ -139,6 +147,8 @@ AddRuntimeFile("test", "help", "test.md")
Use `AddRuntimeFilesFromDirectory(name, type, dir, pattern)` to add a number of files
to the runtime.
To read the content of a runtime file use `ReadRuntimeFile(fileType, name string)`
or `ListRuntimeFiles(fileType string)` for all runtime files.
# Autocomplete command arguments

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Stepets
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,109 @@
# utf8.lua
one-file pure-lua 5.1 regex library
This library _is_ the simple way to add utf8 support into your application.
Some examples from http://www.lua.org/manual/5.1/manual.html#5.4 :
```Lua
local utf8 = require "utf8"
local s = "hello world from Lua"
for w in string.gmatch(s, "%a+") do
print(w)
end
--[[
hello
world
from
Lua
]]--
s = "Привет, мир, от Lua"
for w in utf8.gmatch(s, "[^%p%d%s%c]+") do
print(w)
end
--[[
Привет
мир
от
Lua
]]--
local t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
for k,v in pairs(t) do
print(k,v)
end
--[[
to Lua
from world
]]--
t = {}
s = "从=世界, 到=Lua"
for k, v in utf8.gmatch(s, "([^%p%s%c]+)=([^%p%s%c]+)") do
t[k] = v
end
for k,v in pairs(t) do
print(k,v)
end
--[[
到 Lua
从 世界
]]--
local x = string.gsub("hello world", "(%w+)", "%1 %1")
print(x)
--hello hello world world
x = utf8.gsub("Ahoj světe", "([^%p%s%c]+)", "%1 %1")
print(x)
--Ahoj Ahoj světe světe
x = string.gsub("hello world", "%w+", "%0 %0", 1)
print(x)
--hello hello world
x = utf8.gsub("Ahoj světe", "[^%p%s%c]+", "%0 %0", 1)
print(x)
--Ahoj Ahoj světe
x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
print(x)
--world hello Lua from
x = utf8.gsub("γεια κόσμο από Lua", "([^%p%s%c]+)%s*([^%p%s%c]+)", "%2 %1")
print(x)
--κόσμο γεια Lua από
```
Notice, there are some classes that can work only with latin(ASCII) symbols,
for details see: https://github.com/Stepets/utf8.lua/blob/master/utf8.lua#L470
Of course you can do this trick:
```Lua
for k,v in pairs(utf8) do
string[k] = v
end
```
But this can lead to very strange errors. You were warned.
A little bit more interesting examples:
```Lua
local utf8 = require 'utf8'
for k,v in pairs(utf8) do
string[k] = v
end
local str = "пыщпыщ ололоо я водитель нло"
print(str:find("(.л.+)н"))
-- 8 26 ололоо я водитель
print(str:gsub("ло+", "보라"))
-- пыщпыщ о보라보라 я водитель н보라 3
print(str:match("^п[лопыщ ]*я"))
-- пыщпыщ ололоо я
```

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,17 @@
if GetOption("ftoptions") == nil then
AddOption("ftoptions", true)
end
function onViewOpen(view)
if not GetOption("ftoptions") then
return
end
local ft = view.Buf.Settings["filetype"]
if ft == "makefile" or ft == "go" then
SetOption("tabstospaces", "off")
elseif ft == "python" then
elseif ft == "python" or ft == "python2" or ft == "python3" then
SetOption("tabstospaces", "on")
end
end

View File

@@ -12,27 +12,43 @@ end
function runLinter()
local ft = CurView().Buf:FileType()
local file = CurView().Buf.Path
local devnull = "/dev/null"
local temp = os.getenv("TMPDIR")
local dir = DirectoryName(file)
if OS == "windows" then
devnull = "NUL"
temp = os.getenv("TEMP")
else
devnull = "/dev/null"
end
if ft == "go" then
lint("gobuild", "go build -o " .. devnull, "%f:%l: %m")
lint("golint", "golint " .. CurView().Buf.Path, "%f:%l:%d+: %m")
lint("gobuild", "go", {"build", "-o", devnull}, "%f:%l: %m")
lint("golint", "golint", {file}, "%f:%l:%d+: %m")
elseif ft == "lua" then
lint("luacheck", "luacheck --no-color " .. file, "%f:%l:%d+: %m")
lint("luacheck", "luacheck", {"--no-color", file}, "%f:%l:%d+: %m")
elseif ft == "python" then
lint("pyflakes", "pyflakes " .. file, "%f:%l:.-:? %m")
lint("pyflakes", "pyflakes", {file}, "%f:%l:.-:? %m")
lint("mypy", "mypy", {file}, "%f:%l: %m")
lint("pylint", "pylint", {"--output-format=parseable", "--reports=no", file}, "%f:%l: %m")
elseif ft == "c" then
lint("gcc", "gcc -fsyntax-only -Wall -Wextra " .. file, "%f:%l:%d+:.+: %m")
lint("gcc", "gcc", {"-fsyntax-only", "-Wall", "-Wextra", file}, "%f:%l:%d+:.+: %m")
elseif ft == "c++" then
lint("gcc", "gcc", {"-fsyntax-only","-std=c++14", "-Wall", "-Wextra", file}, "%f:%l:%d+:.+: %m")
elseif ft == "swift" and OS == "darwin" then
lint("switfc", "xcrun", {"swiftc", file}, "%f:%l:%d+:.+: %m")
elseif ft == "swift" and OS == "linux" then
lint("switfc", "swiftc", {file}, "%f:%l:%d+:.+: %m")
elseif ft == "Objective-C" then
lint("clang", "xcrun", {"clang", "-fsyntax-only", "-Wall", "-Wextra", file}, "%f:%l:%d+:.+: %m")
elseif ft == "d" then
lint("dmd", "dmd -color=off -o- -w -wi -c " .. file, "%f%(%l%):.+: %m")
lint("dmd", "dmd", {"-color=off", "-o-", "-w", "-wi", "-c", file}, "%f%(%l%):.+: %m")
elseif ft == "java" then
lint("javac", "javac -d " .. temp .. " " .. file, "%f:%l: error: %m")
lint("javac", "javac", {"-d", dir, file}, "%f:%l: error: %m")
elseif ft == "javascript" then
lint("jshint", "jshint " .. file, "%f: line %l,.+, %m")
lint("jshint", "jshint", {file}, "%f: line %l,.+, %m")
elseif ft == "nim" then
lint("nim", "nim", {"check", "--listFullPaths", "--stdout", "--hints:off", file}, "%f.%l, %d+. %m")
elseif string.match(ft, "literate") then
lint("literate", "lit", {"-c", file}, "%f:%l:%m")
elseif ft == "yaml" then
lint("yaml", "yamllint", {"--format", "parsable", file}, "%f:%l:%d+:.+ %m")
end
end
@@ -44,10 +60,10 @@ function onSave(view)
end
end
function lint(linter, cmd, errorformat)
function lint(linter, cmd, args, errorformat)
CurView():ClearGutterMessages(linter)
JobStart(cmd, "", "", "linter.onExit", linter, errorformat)
JobSpawn(cmd, args, "", "", "linter.onExit", linter, errorformat)
end
function onExit(output, linter, errorformat)

View File

@@ -0,0 +1,5 @@
# Literate Micro
Support for reading `.lit` files from [zyedidia/Literate](https://github.com/zyedidia/Literate).
This plugin will automatically detect the filetype and highlight the correct language inside the code blocks.

View File

@@ -0,0 +1,53 @@
VERSION = "1.0.0"
function startswith(str, start)
return string.sub(str,1,string.len(start))==start
end
function endswith(str, endStr)
return endStr=='' or string.sub(str,-string.len(endStr))==endStr
end
function split(string, sep)
local sep, fields = sep or ":", {}
local pattern = string.format("([^%s]+)", sep)
string:gsub(pattern, function(c) fields[#fields+1] = c end)
return fields
end
function onViewOpen(view)
if not endswith(view.Buf.Path, ".lit") then
return
end
local codetype = "unknown"
for i=1,view.Buf.NumLines do
local line = view.Buf:Line(i-1)
if startswith(line, "@code_type") then
codetype = split(line, " ")[2]
break
end
end
local syntaxFile = ""
syntaxFile = syntaxFile .. "filetype: literate-" .. codetype .. "\n"
syntaxFile = syntaxFile .. "detect:\n"
syntaxFile = syntaxFile .. " filename: \"\\\\.lit$\"\n"
syntaxFile = syntaxFile .. "rules:\n"
syntaxFile = syntaxFile .. " - include: \"markdown\"\n"
syntaxFile = syntaxFile .. " - special: \"^(@s|@title|@code_type|@comment_type|@include|@change|@change_end)\"\n"
syntaxFile = syntaxFile .. " - special: \"(@add_css|@overwrite_css|@colorscheme|@compiler|@error_format|@book)\"\n"
syntaxFile = syntaxFile .. " - default:\n"
syntaxFile = syntaxFile .. " start: \"---.*$\"\n"
syntaxFile = syntaxFile .. " end: \"---$\"\n"
syntaxFile = syntaxFile .. " limit-group: \"identifier\"\n"
syntaxFile = syntaxFile .. " rules:\n"
syntaxFile = syntaxFile .. " - special:\n"
syntaxFile = syntaxFile .. " start: \"@\\\\{\"\n"
syntaxFile = syntaxFile .. " end: \"\\\\}\"\n"
syntaxFile = syntaxFile .. " rules: []\n"
syntaxFile = syntaxFile .. " - include: " .. codetype .. "\n"
AddRuntimeFileFromMemory("literate", "syntax", "literate.yaml", syntaxFile)
Reload()
end

View File

@@ -1,20 +0,0 @@
## Syntax highlighting for Dockerfiles
syntax "dockerfile" "Dockerfile[^/]*$" "\.dockerfile$"
## Keywords
color keyword (i) "^(FROM|MAINTAINER|RUN|CMD|LABEL|EXPOSE|ENV|ADD|COPY|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD|ARG|HEALTHCHECK|STOPSIGNAL|SHELL)[[:space:]]"
## Brackets & parenthesis
color statement "(\(|\)|\[|\])"
## Double ampersand
color special "&&"
## Comments
color comment (i) "^[[:space:]]*#.*$"
## Strings, single-quoted
color constant.string "'([^']|(\\'))*'" "%[qw]\{[^}]*\}" "%[qw]\([^)]*\)" "%[qw]<[^>]*>" "%[qw]\[[^]]*\]" "%[qw]\$[^$]*\$" "%[qw]\^[^^]*\^" "%[qw]![^!]*!"
## Strings, double-quoted
color constant.string ""([^"]|(\\"))*"" "%[QW]?\{[^}]*\}" "%[QW]?\([^)]*\)" "%[QW]?<[^>]*>" "%[QW]?\[[^]]*\]" "%[QW]?\$[^$]*\$" "%[QW]?\^[^^]*\^" "%[QW]?![^!]*!"

View File

@@ -1,15 +1,22 @@
micro syntax files
Copyright (C) 2016+ Zachary Yedidia et al.
Micro's syntax files are licensed under the MIT "Expat" License:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Copyright (c) 2016: Zachary Yedidia, Collin Warren, et al.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,4 +0,0 @@
export
:=
error

View File

@@ -1,3 +1,31 @@
# Syntax Files
Here are micro's syntax files.
Each yaml file specifies how to detect the filetype based on file extension or headers (first line of the file).
Then there are patterns and regions linked to highlight groups which tell micro how to highlight that filetype.
Making your own syntax files is very simple. I recommend you check the file after you are finished with the
[`syntax_checker.go`](./syntax_checker.go) program (located in this directory). Just place your yaml syntax
file in the current directory and run `go run syntax_checker.go` and it will check every file. If there are no
errors it will print `No issues!`.
You can read more about how to write syntax files (and colorschemes) in the [colors](../help/colors.md) documentation.
# Legacy '.micro' filetype
Micro used to use the `.micro` filetype for syntax files which is no longer supported. If you have `.micro`
syntax files that you would like to convert to the new filetype, you can use the [`syntax_converter.go`](./syntax_converter.go) program (also located in this directory):
```
$ go run syntax_converter.go c.micro > c.yaml
```
Most the the syntax files here have been converted using that tool.
Note that the tool isn't perfect and though it is unlikely, you may run into some small issues that you will have to fix manually
(about 4 files from this directory had issues after being converted).
=======
# Micro syntax highlighting files
These are the syntax highlighting files for micro. To install them, just
@@ -7,12 +35,11 @@ They are taken from Nano, specifically from [this repository](https://github.com
Micro syntax files are almost identical to Nano's, except for some key differences:
* Micro does not use `icolor`. Instead, for a case insensitive match, use the case insensitive flag (`i`) in the regular expression
* For example, `icolor green ".*"` would become `color green (i) ".*"`
* For example, `icolor green ".*"` would become `color green "(?i).*"`
# Using with colorschemes
Not all of these files have been converted to use micro's colorscheme feature. Most of them just hardcode the colors, which
can be problematic depending on the colorscheme you use.
Not all of these files have been converted to use micro's colorscheme feature. Most of them just hardcode the colors, which can be problematic depending on the colorscheme you use.
Here is a list of the files that have been converted to properly use colorschemes:
@@ -33,6 +60,7 @@ Here is a list of the files that have been converted to properly use colorscheme
* sh
* git
* tex
* solidity
# License

View File

@@ -1,44 +0,0 @@
# Apache files
syntax "apacheconf" "httpd\.conf|mime\.types|vhosts\.d\\*|\.htaccess"
color yellow ".+"
color brightcyan "(AcceptMutex|AcceptPathInfo|AccessFileName|Action|AddAlt|AddAltByEncoding|AddAltByType|AddCharset|AddDefaultCharset|AddDescription|AddEncoding)"
color brightcyan "(AddHandler|AddIcon|AddIconByEncoding|AddIconByType|AddInputFilter|AddLanguage|AddModuleInfo|AddOutputFilter|AddOutputFilterByType|AddType|Alias|AliasMatch)"
color brightcyan "(Allow|AllowCONNECT|AllowEncodedSlashes|AllowOverride|Anonymous|Anonymous_Authoritative|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID)"
color brightcyan "(Anonymous_VerifyEmail|AssignUserID|AuthAuthoritative|AuthDBMAuthoritative|AuthDBMGroupFile|AuthDBMType|AuthDBMUserFile|AuthDigestAlgorithm)"
color brightcyan "(AuthDigestDomain|AuthDigestFile|AuthDigestGroupFile|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestQop|AuthDigestShmemSize)"
color brightcyan "(AuthGroupFile|AuthLDAPAuthoritative|AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases)"
color brightcyan "(AuthLDAPEnabled|AuthLDAPFrontPageHack|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserIsDN|AuthLDAPUrl|AuthName|AuthType|AuthUserFile)"
color brightcyan "(BrowserMatch|BrowserMatchNoCase|BS2000Account|BufferedLogs|CacheDefaultExpire|CacheDirLength|CacheDirLevels|CacheDisable|CacheEnable|CacheExpiryCheck)"
color brightcyan "(CacheFile|CacheForceCompletion|CacheGcClean|CacheGcDaily|CacheGcInterval|CacheGcMemUsage|CacheGcUnused|CacheIgnoreCacheControl|CacheIgnoreHeaders)"
color brightcyan "(CacheIgnoreNoLastMod|CacheLastModifiedFactor|CacheMaxExpire|CacheMaxFileSize|CacheMinFileSize|CacheNegotiatedDocs|CacheRoot|CacheSize|CacheTimeMargin)"
color brightcyan "(CGIMapExtension|CharsetDefault|CharsetOptions|CharsetSourceEnc|CheckSpelling|ChildPerUserID|ContentDigest|CookieDomain|CookieExpires|CookieLog|CookieName)"
color brightcyan "(CookieStyle|CookieTracking|CoreDumpDirectory|CustomLog|Dav|DavDepthInfinity|DavLockDB|DavMinTimeout|DefaultIcon|DefaultLanguage|DefaultType)"
color brightcyan "(DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize|Deny|Directory|DirectoryIndex|DirectoryMatch|DirectorySlash)"
color brightcyan "(DocumentRoot|DumpIOInput|DumpIOOutput|EnableExceptionHook|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|Example|ExpiresActive|ExpiresByType)"
color brightcyan "(ExpiresDefault|ExtendedStatus|ExtFilterDefine|ExtFilterOptions|FileETag|Files|FilesMatch|ForceLanguagePriority|ForceType|ForensicLog|Group|Header)"
color brightcyan "(HeaderName|HostnameLookups|IdentityCheck|IfDefine|IfModule|IfVersion|ImapBase|ImapDefault|ImapMenu|Include|IndexIgnore|IndexOptions|IndexOrderDefault)"
color brightcyan "(ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer|KeepAlive|KeepAliveTimeout)"
color brightcyan "(LanguagePriority|LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize)"
color brightcyan "(LDAPTrustedCA|LDAPTrustedCAType|Limit|LimitExcept|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine)"
color brightcyan "(LimitXMLRequestBody|Listen|ListenBackLog|LoadFile|LoadModule|Location|LocationMatch|LockFile|LogFormat|LogLevel|MaxClients|MaxKeepAliveRequests)"
color brightcyan "(MaxMemFree|MaxRequestsPerChild|MaxRequestsPerThread|MaxSpareServers|MaxSpareThreads|MaxThreads|MaxThreadsPerChild|MCacheMaxObjectCount|MCacheMaxObjectSize)"
color brightcyan "(MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize|MetaDir|MetaFiles|MetaSuffix|MimeMagicFile|MinSpareServers|MinSpareThreads)"
color brightcyan "(MMapFile|ModMimeUsePathInfo|MultiviewsMatch|NameVirtualHost|NoProxy|NumServers|NWSSLTrustedCerts|NWSSLUpgradeable|Options|Order|PassEnv|PidFile)"
color brightcyan "(ProtocolEcho|Proxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyIOBufferSize|ProxyMatch|ProxyMaxForwards|ProxyPass|ProxyPassReverse)"
color brightcyan "(ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxyTimeout|ProxyVia|ReadmeName|Redirect|RedirectMatch)"
color brightcyan "(RedirectPermanent|RedirectTemp|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|RequestHeader)"
color brightcyan "(Require|RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule|RLimitCPU|RLimitMEM|RLimitNPROC)"
color brightcyan "(Satisfy|ScoreBoardFile|Script|ScriptAlias|ScriptAliasMatch|ScriptInterpreterSource|ScriptLog|ScriptLogBuffer|ScriptLogLength|ScriptSock|SecureListen)"
color brightcyan "(SendBufferSize|ServerAdmin|ServerAlias|ServerLimit|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetEnv|SetEnvIf|SetEnvIfNoCase|SetHandler)"
color brightcyan "(SetInputFilter|SetOutputFilter|SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|SSLCACertificateFile|SSLCACertificatePath)"
color brightcyan "(SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLEngine|SSLMutex|SSLOptions)"
color brightcyan "(SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite)"
color brightcyan "(SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire)"
color brightcyan "(SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth|StartServers|StartThreads|SuexecUserGroup|ThreadLimit)"
color brightcyan "(ThreadsPerChild|ThreadStackSize|TimeOut|TraceEnable|TransferLog|TypesConfig|UnsetEnv|UseCanonicalName|User|UserDir|VirtualDocumentRoot)"
color brightcyan "(VirtualDocumentRootIP|VirtualHost|VirtualScriptAlias|VirtualScriptAliasIP|Win32DisableAcceptEx|XBitHack)"
color yellow "<[^>]+>"
color brightcyan "</?[A-Za-z]+"
color brightcyan "(<|</|>)"
color green "\"(\\.|[^\"])*\""
color white "#.*"

View File

@@ -0,0 +1,59 @@
filetype: apacheconf
detect:
filename: "httpd\\.conf|mime\\.types|vhosts\\.d\\\\*|\\.htaccess"
rules:
- identifier: "(AcceptMutex|AcceptPathInfo|AccessFileName|Action|AddAlt|AddAltByEncoding|AddAltByType|AddCharset|AddDefaultCharset|AddDescription|AddEncoding)"
- identifier: "(AddHandler|AddIcon|AddIconByEncoding|AddIconByType|AddInputFilter|AddLanguage|AddModuleInfo|AddOutputFilter|AddOutputFilterByType|AddType|Alias|AliasMatch)"
- identifier: "(Allow|AllowCONNECT|AllowEncodedSlashes|AllowOverride|Anonymous|Anonymous_Authoritative|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID)"
- identifier: "(Anonymous_VerifyEmail|AssignUserID|AuthAuthoritative|AuthDBMAuthoritative|AuthDBMGroupFile|AuthDBMType|AuthDBMUserFile|AuthDigestAlgorithm)"
- identifier: "(AuthDigestDomain|AuthDigestFile|AuthDigestGroupFile|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestQop|AuthDigestShmemSize)"
- identifier: "(AuthGroupFile|AuthLDAPAuthoritative|AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases)"
- identifier: "(AuthLDAPEnabled|AuthLDAPFrontPageHack|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserIsDN|AuthLDAPUrl|AuthName|AuthType|AuthUserFile)"
- identifier: "(BrowserMatch|BrowserMatchNoCase|BS2000Account|BufferedLogs|CacheDefaultExpire|CacheDirLength|CacheDirLevels|CacheDisable|CacheEnable|CacheExpiryCheck)"
- identifier: "(CacheFile|CacheForceCompletion|CacheGcClean|CacheGcDaily|CacheGcInterval|CacheGcMemUsage|CacheGcUnused|CacheIgnoreCacheControl|CacheIgnoreHeaders)"
- identifier: "(CacheIgnoreNoLastMod|CacheLastModifiedFactor|CacheMaxExpire|CacheMaxFileSize|CacheMinFileSize|CacheNegotiatedDocs|CacheRoot|CacheSize|CacheTimeMargin)"
- identifier: "(CGIMapExtension|CharsetDefault|CharsetOptions|CharsetSourceEnc|CheckSpelling|ChildPerUserID|ContentDigest|CookieDomain|CookieExpires|CookieLog|CookieName)"
- identifier: "(CookieStyle|CookieTracking|CoreDumpDirectory|CustomLog|Dav|DavDepthInfinity|DavLockDB|DavMinTimeout|DefaultIcon|DefaultLanguage|DefaultType)"
- identifier: "(DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize|Deny|Directory|DirectoryIndex|DirectoryMatch|DirectorySlash)"
- identifier: "(DocumentRoot|DumpIOInput|DumpIOOutput|EnableExceptionHook|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|Example|ExpiresActive|ExpiresByType)"
- identifier: "(ExpiresDefault|ExtendedStatus|ExtFilterDefine|ExtFilterOptions|FileETag|Files|FilesMatch|ForceLanguagePriority|ForceType|ForensicLog|Group|Header)"
- identifier: "(HeaderName|HostnameLookups|IdentityCheck|IfDefine|IfModule|IfVersion|ImapBase|ImapDefault|ImapMenu|Include|IndexIgnore|IndexOptions|IndexOrderDefault)"
- identifier: "(ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer|KeepAlive|KeepAliveTimeout)"
- identifier: "(LanguagePriority|LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize)"
- identifier: "(LDAPTrustedCA|LDAPTrustedCAType|Limit|LimitExcept|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine)"
- identifier: "(LimitXMLRequestBody|Listen|ListenBackLog|LoadFile|LoadModule|Location|LocationMatch|LockFile|LogFormat|LogLevel|MaxClients|MaxKeepAliveRequests)"
- identifier: "(MaxMemFree|MaxRequestsPerChild|MaxRequestsPerThread|MaxSpareServers|MaxSpareThreads|MaxThreads|MaxThreadsPerChild|MCacheMaxObjectCount|MCacheMaxObjectSize)"
- identifier: "(MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize|MetaDir|MetaFiles|MetaSuffix|MimeMagicFile|MinSpareServers|MinSpareThreads)"
- identifier: "(MMapFile|ModMimeUsePathInfo|MultiviewsMatch|NameVirtualHost|NoProxy|NumServers|NWSSLTrustedCerts|NWSSLUpgradeable|Options|Order|PassEnv|PidFile)"
- identifier: "(ProtocolEcho|Proxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyIOBufferSize|ProxyMatch|ProxyMaxForwards|ProxyPass|ProxyPassReverse)"
- identifier: "(ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxyTimeout|ProxyVia|ReadmeName|Redirect|RedirectMatch)"
- identifier: "(RedirectPermanent|RedirectTemp|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|RequestHeader)"
- identifier: "(Require|RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule|RLimitCPU|RLimitMEM|RLimitNPROC)"
- identifier: "(Satisfy|ScoreBoardFile|Script|ScriptAlias|ScriptAliasMatch|ScriptInterpreterSource|ScriptLog|ScriptLogBuffer|ScriptLogLength|ScriptSock|SecureListen)"
- identifier: "(SendBufferSize|ServerAdmin|ServerAlias|ServerLimit|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetEnv|SetEnvIf|SetEnvIfNoCase|SetHandler)"
- identifier: "(SetInputFilter|SetOutputFilter|SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|SSLCACertificateFile|SSLCACertificatePath)"
- identifier: "(SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLEngine|SSLMutex|SSLOptions)"
- identifier: "(SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite)"
- identifier: "(SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire)"
- identifier: "(SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth|StartServers|StartThreads|SuexecUserGroup|ThreadLimit)"
- identifier: "(ThreadsPerChild|ThreadStackSize|TimeOut|TraceEnable|TransferLog|TypesConfig|UnsetEnv|UseCanonicalName|User|UserDir|VirtualDocumentRoot)"
- identifier: "(VirtualDocumentRootIP|VirtualHost|VirtualScriptAlias|VirtualScriptAliasIP|Win32DisableAcceptEx|XBitHack)"
- symbol.tag: "<[^>]+>"
- identifier: "</?[A-Za-z]+"
- identifier: "(<|</|>)"
- constant.string:
start: "\""
end: "\""
skip: "\\\\."
rules:
- constant.specialChar: "\\\\."
- comment:
start: "#"
end: "$"
rules:
- todo: "(TODO|XXX|FIXME):?"

View File

@@ -1,116 +0,0 @@
## FILENAME: arduino.nanorc
##
## DESCRIPTION: The arduino.nanorc syntax files allows syntax highlighting
## for Arduino sketch files in the GNU nano text editor.
##
## Maintainer: Nicholas Wilde
## Version: 0.1
## DATE: 06/23/2011
##
## HOMEPAGE: http://code.google.com/p/arduino-nano-editor-syntax/
##
## COMMENTS: -Most of the code was taken from the c.nanorc code found with
## GNU nano 2.2.6.
## -Direction was taken from the arduino vim syntax code by johannes
## <https://bitbucket.org/johannes/arduino-vim-syntax/>
## -Tested on Ubuntu Server 11.04 Natty Narwhal and GNU nano 2.2.6
##
## DIRECTIONS: For Ubuntu Server 11.04 Natty Narwhal:
## -Move this file <arduino.nanorc> to the nano directory
## /usr/share/nano/
## -Add arduino.nanorc reference to the nanorc settings file
## /etc/nanorc
## ...
## ## Arduino
## /usr/share/nano/arduino.nanorc
## ...
syntax "ino" "\.?ino$"
##
color brightred "\<[A-Z_][0-9A-Z_]+\>"
##
color green "\<((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\>"
## Constants
green (i) "\<(HIGH|LOW|INPUT|OUTPUT)\>"
## Serial Print
red (i) "\<(DEC|BIN|HEX|OCT|BYTE)\>"
## PI Constants
green (i) "\<(PI|HALF_PI|TWO_PI)\>"
## ShiftOut
green (i) "\<(LSBFIRST|MSBFIRST)\>"
## Attach Interrupt
green (i) "\<(CHANGE|FALLING|RISING)\>"
## Analog Reference
green (i) "\<(DEFAULT|EXTERNAL|INTERNAL|INTERNAL1V1|INTERNAL2V56)\>"
## === FUNCTIONS === ##
## Data Types
color green "\<(boolean|byte|char|float|int|long|word)\>"
## Control Structions
color brightyellow "\<(case|class|default|do|double|else|false|for|if|new|null|private|protected|public|short|signed|static|String|switch|this|throw|try|true|unsigned|void|while)\>"
color magenta "\<(goto|continue|break|return)\>"
## Math
color brightyellow "\<(abs|acos|asin|atan|atan2|ceil|constrain|cos|degrees|exp|floor|log|map|max|min|radians|random|randomSeed|round|sin|sq|sqrt|tan)\>"
## Bits & Bytes
color brightyellow "\<(bitRead|bitWrite|bitSet|bitClear|bit|highByte|lowByte)\>"
## Analog I/O
color brightyellow "\<(analogReference|analogRead|analogWrite)\>"
## External Interrupts
color brightyellow "\<(attachInterrupt|detachInterrupt)\>"
## Time
color brightyellow "\<(delay|delayMicroseconds|millis|micros)\>"
## Digital I/O
color brightyellow "\<(pinMode|digitalWrite|digitalRead)\>"
## Interrupts
color brightyellow "\<(interrupts|noInterrupts)\>"
## Advanced I/O
color brightyellow "\<(noTone|pulseIn|shiftIn|shiftOut|tone)\>"
## Serial
color magenta "\<(Serial|Serial1|Serial2|Serial3|begin|end|peek|read|print|println|available|flush)\>"
## Structure
color brightyellow "\<(setup|loop)\>"
##
color brightcyan "^[[:space:]]*#[[:space:]]*(define|include(_next)?|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma)"
##
color brightmagenta "'([^']|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
## GCC builtins
color cyan "__attribute__[[:space:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
## String highlighting. You will in general want your comments and
## strings to come last, because syntax highlighting rules will be
## applied in the order they are read in.
color brightyellow "<[^= ]*>" ""(\\.|[^"])*""
## This string is VERY resource intensive!
color brightyellow start=""(\\.|[^"])*\\[[:space:]]*$" end="^(\\.|[^"])*""
## Comments
color brightblue "//.*"
color brightblue start="/\*" end="\*/"
## Trailing whitespace
color ,green "[[:space:]]+$"

101
runtime/syntax/arduino.yaml Normal file
View File

@@ -0,0 +1,101 @@
filetype: ino
detect:
filename: "\\.?ino$"
rules:
- identifier: "\\b[A-Z_][0-9A-Z_]+\\b"
##
- type: "\\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\\b"
## Constants
- constant: "(?i)\\b(HIGH|LOW|INPUT|OUTPUT)\\b"
## Serial Print
- constant: "(?i)\\b(DEC|BIN|HEX|OCT|BYTE)\\b"
## PI Constants
- constant: "(?i)\\b(PI|HALF_PI|TWO_PI)\\b"
## ShiftOut
- constant: "(?i)\\b(LSBFIRST|MSBFIRST)\\b"
## Attach Interrupt
- constant: "(?i)\\b(CHANGE|FALLING|RISING)\\b"
## Analog Reference
- constant: "(?i)\\b(DEFAULT|EXTERNAL|INTERNAL|INTERNAL1V1|INTERNAL2V56)\\b"
## === FUNCTIONS === ##
## Data Types
- type: "\\b(boolean|byte|char|float|int|long|word)\\b"
## Control Structions
- statement: "\\b(case|class|default|do|double|else|false|for|if|new|null|private|protected|public|short|signed|static|String|switch|this|throw|try|true|unsigned|void|while)\\b"
- statement: "\\b(goto|continue|break|return)\\b"
## Math
- identifier: "\\b(abs|acos|asin|atan|atan2|ceil|constrain|cos|degrees|exp|floor|log|map|max|min|radians|random|randomSeed|round|sin|sq|sqrt|tan)\\b"
## Bits & Bytes
- identifier: "\\b(bitRead|bitWrite|bitSet|bitClear|bit|highByte|lowByte)\\b"
## Analog I/O
- identifier: "\\b(analogReference|analogRead|analogWrite)\\b"
## External Interrupts
- identifier: "\\b(attachInterrupt|detachInterrupt)\\b"
## Time
- identifier: "\\b(delay|delayMicroseconds|millis|micros)\\b"
## Digital I/O
- identifier: "\\b(pinMode|digitalWrite|digitalRead)\\b"
## Interrupts
- identifier: "\\b(interrupts|noInterrupts)\\b"
## Advanced I/O
- identifier: "\\b(noTone|pulseIn|shiftIn|shiftOut|tone)\\b"
## Serial
- identifier: "\\b(Serial|Serial1|Serial2|Serial3|begin|end|peek|read|print|println|available|flush)\\b"
## Structure
- identifier: "\\b(setup|loop)\\b"
##
- statement: "^[[:space:]]*#[[:space:]]*(define|include(_next)?|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma)"
## GCC builtins
- constant: "(__attribute__[[:space:]]*\\(\\([^)]*\\)\\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__)"
- constant.string:
start: "\""
end: "\""
skip: "\\\\."
rules:
- constant.specialChar: "\\\\."
- constant.string:
start: "'"
end: "'"
skip: "\\\\."
rules:
- preproc: "..+"
- constant.specialChar: "\\\\."
- comment:
start: "//"
end: "$"
rules:
- todo: "(TODO|XXX|FIXME):?"
- comment:
start: "/\\*"
end: "\\*/"
rules:
- todo: "(TODO|XXX|FIXME):?"

View File

@@ -1,47 +0,0 @@
syntax "asciidoc" "\.(asc|asciidoc|adoc)$"
# main header
color red "^====+$"
# h1
color red "^==[[:space:]].*$"
color red "^----+$"
# h2
color magenta "^===[[:space:]].*$"
color magenta "^~~~~+$"
# h4
color green "^====[[:space:]].*$"
color green "^\^\^\^\^+$"
# h5
color brightblue "^=====[[:space:]].*$"
color brightblue "^\+\+\+\++$"
# attributes
color brightgreen ":.*:"
color brightred "\{[a-z0-9]*\}"
color red "\\\{[a-z0-9]*\}"
color red "\+\+\+\{[a-z0-9]*\}\+\+\+"
# Paragraph Title
color yellow "^\..*$"
# source
color magenta "^\[(source,.+|NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]"
# Other markup
color yellow ".*[[:space:]]\+$"
color yellow "_[^_]+_"
color yellow "\*[^\*]+\*"
color yellow "\+[^\+]+\+"
color yellow "`[^`]+`"
color yellow "\^[^\^]+\^"
color yellow "~[^~]+~"
color yellow "'[^']+'"
color cyan "`{1,2}[^']+'{1,2}"
# bullets
color brightmagenta "^[[:space:]]*[\*\.-]{1,5}[[:space:]]"
# anchors
color brightwhite "\[\[.*\]\]"
color brightwhite "<<.*>>"

View File

@@ -0,0 +1,51 @@
filetype: asciidoc
detect:
filename: "\\.(asc|asciidoc|adoc)$"
rules:
# main header
- preproc: "^====+$"
# h1
- statement: "^==[[:space:]].*$"
- statement: "^----+$"
# h2
- symbol: "^===[[:space:]].*$"
- symbol: "^~~~~+$"
# h4
- type: "^====[[:space:]].*$"
- type: "^\\^\\^\\^\\^+$"
# h5
- constant: "^=====[[:space:]].*$"
- constant: "^\\+\\+\\+\\++$"
# attributes
- type.keyword: ":.*:"
- identifier.macro: "\\{[a-z0-9]*\\}"
- identifier: "\\\\\\{[a-z0-9]*\\}"
- identifier: "\\+\\+\\+\\{[a-z0-9]*\\}\\+\\+\\+"
# Paragraph Title
- statement: "^\\..*$"
# source
- identifier: "^\\[(source,.+|NOTE|TIP|IMPORTANT|WARNING|CAUTION)\\]"
# Other markup
- constant.string: ".*[[:space:]]\\+$"
- constant.string: "_[^_]+_"
- constant.string: "\\*[^\\*]+\\*"
- constant.string: "\\+[^\\+]+\\+"
- constant.string: "`[^`]+`"
- constant.string: "\\^[^\\^]+\\^"
- constant.string: "~[^~]+~"
- constant.string: "'[^']+'"
- constant: "`{1,2}[^']+'{1,2}"
# bullets
- symbol: "^[[:space:]]*[\\*\\.-]{1,5}[[:space:]]"
# anchors
- "bold default": "\\[\\[.*\\]\\]"
- "bold default": "<<.*>>"

View File

@@ -1,93 +0,0 @@
## Made by Nickolay Ilyushin <nickolay02@inbox.ru>. Next line is from previous (first) version (no need for modifications :P)
syntax "asm" "\.(S|s|asm)$"
# This file is made for NASM assembly
## Instructions
# x86
color statement "\b(?i)(mov|aaa|aad|aam|aas|adc|add|and|call|cbw|clc|cld|cli|cmc|cmp|cmpsb|cmpsw|cwd|daa|das|dec|div|esc|hlt|idiv|imul|in|inc|int|into|iret|ja|jae|jb|jbe|jc|je|jg|jge|jl|jle|jna|jnae|jnb|jnbe|jnc|jne|jng|jnge|jnl|jnle|jno|jnp|jns|jnz|jo|jp|jpe|jpo|js|jz|jcxz|jmp|lahf|lds|lea|les|lock|lodsb|lodsw|loop|loope|loopne|loopnz|loopz|movsb|movsw|mul|neg|nop|or|pop|popf|push|pushf|rcl|rcr|rep|repe|repne|repnz|repz|ret|retn|retf|rol|ror|sahf|sal|sar|sbb|scasb|scasw|shl|shr|stc|std|sti|stosb|stosw|sub|test|wait|xchg|xlat|xor)(?-i)\b"
color statement "\b(?i)(bound|enter|ins|leave|outs|popa|pusha)(?-i)\b"
color statement "\b(?i)(arpl|clts|lar|lgdt|lidt|lldt|lmsw|loadall|lsl|ltr|sgdt|sidt|sldt|smsw|str|verr|verw)(?-i)\b"
color statement "\b(?i)(bsf|bsr|bt|btc|btr|bts|cdq|cmpsd|cwde|insd|iret|iretd|iretf|jecxz|lfs|lgs|lss|lodsd|loopw|loopew|loopnew|loopnzw|loopzw|loopd|looped|loopned|loopnzd|loopzd|cr|tr|dr|movsd|movsx|movzx|outsd|popad|popfd|pushad|pushfd|scasd|seta|setae|setb|setbe|setc|sete|setg|setge|setl|setle|setna|setnae|setnb|setnbe|setnc|setne|setng|setnge|setnl|setnle|setno|setnp|setns|setnz|seto|setp|setpe|setpo|sets|setz|shdl|shrd|stosd)(?-i)\b"
color statement "\b(?i)(bswap|cmpxcgh|invd|invlpg|wbinvd|xadd)(?-i)\b"
color statement "\b(?i)(cpuid|cmpxchg8b|rdmsr|rdtsc|wrmsr|rsm)(?-i)\b"
color statement "\b(?i)(rdpmc)(?-i)\b"
color statement "\b(?i)(syscall|sysret)(?-i)\b"
color statement "\b(?i)(cmova|cmovae|cmovb|cmovbe|cmovc|cmove|cmovg|cmovge|cmovl|cmovle|cmovna|cmovnae|cmovnb|cmovnbe|cmovnc|cmovne|cmovng|cmovnge|cmovnle|cmovno|cmovpn|cmovns|cmovnz|cmovo|cmovp|cmovpe|cmovpo|cmovs|cmovz|sysenter|sysexit|ud2)(?-i)\b"
color statement "\b(?i)(maskmovq|movntps|movntq|prefetch0|prefetch1|prefetch2|prefetchnta|sfence)(?-i)\b"
color statement "\b(?i)(clflush|lfence|maskmovdqu|mfence|movntdq|movnti|movntpd|pause)(?-i)\b"
color statement "\b(?i)(monitor|mwait)(?-i)\b"
color statement "\b(?i)(cdqe|cqo|cmpsq|cmpxchg16b|iretq|jrcxz|lodsq|movsdx|popfq|pushfq|rdtscp|scasq|stosq|swapgs)(?-i)\b"
color statement "\b(?i)(clgi|invlpga|skinit|stgi|vmload|vmmcall|vmrun|vmsave)(?-i)\b"
color statement "\b(?i)(vmptrdl|vmptrst|vmclear|vmread|vmwrite|vmcall|vmlaunch|vmresume|vmxoff|vmxon)(?-i)\b"
color statement "\b(?i)(lzcnt|popcnt)(?-i)\b"
color statement "\b(?i)(bextr|blcfill|blci|blcic|blcmask|blcs|blsfill|blsic|t1mskc|tzmsk)(?-i)\b"
# x87
color statement "\b(?i)(f2xm1|fabs|fadd|faddp|fbld|fbstp|fchs|fclex|fcom|fcomp|fcompp|fdecstp|fdisi|fdiv|fvidp|fdivr|fdivrp|feni|ffree|fiadd|ficom|ficomp|fidiv|fidivr|fild|fimul|fincstp|finit|fist|fistp|fisub|fisubr|fld|fld1|fldcw|fldenv|fldenvw|fldl2e|fldl2t|fldlg2|fldln2|fldpi|fldz|fmul|fmulp|fnclex|fndisi|fneni|fninit|fnop|fnsave|fnsavenew|fnstcw|fnstenv|fnstenvw|fnstsw|fpatan|fprem|fptan|frndint|frstor|frstorw|fsave|fsavew|fscale|fsqrt|fst|fstcw|fstenv|fstenvw|fstp|fstpsw|fsub|fsubp|fsubr|fsubrp|ftst|fwait|fxam|fxch|fxtract|fyl2x|fyl2xp1)(?-i)\b"
color statement "\b(?i)(fsetpm)(?-i)\b"
color statement "\b(?i)(fcos|fldenvd|fsaved|fstenvd|fprem1|frstord|fsin|fsincos|fstenvd|fucom|fucomp|fucompp)(?-i)\b"
color statement "\b(?i)(fcmovb|fcmovbe|fcmove|fcmove|fcmovnb|fcmovnbe|fcmovne|fcmovnu|fcmovu)(?-i)\b"
color statement "\b(?i)(fcomi|fcomip|fucomi|fucomip)(?-i)\b"
color statement "\b(?i)(fxrstor|fxsave)(?-i)\b"
color statement "\b(?i)(fisttp)(?-i)\b"
color statement "\b(?i)(ffreep)(?-i)\b"
# SIMD
color statement "\b(?i)(emms|movd|movq|packssdw|packsswb|packuswb|paddb|paddw|paddd|paddsb|paddsw|paddusb|paddusw|pand|pandn|por|pxor|pcmpeqb|pcmpeqw|pcmpeqd|pcmpgtb|pcmpgtw|pcmpgtd|pmaddwd|pmulhw|pmullw|psllw|pslld|psllq|psrad|psraw|psrlw|psrld|psrlq|psubb|psubw|psubd|psubsb|psubsw|psubusb|punpckhbw|punpckhwd|punpckhdq|punkcklbw|punpckldq|punpcklwd)(?-i)\b"
color statement "\b(?i)(paveb|paddsiw|pmagw|pdistib|psubsiw|pmwzb|pmulhrw|pmvnzb|pmvlzb|pmvgezb|pmulhriw|pmachriw)(?-i)\b"
color statement "\b(?i)(femms|pavgusb|pf2id|pfacc|pfadd|pfcmpeq|pfcmpge|pfcmpgt|pfmax|pfmin|pfmul|pfrcp|pfrcpit1|pfrcpit2|pfrsqit1|pfrsqrt|pfsub|pfsubr|pi2fd|pmulhrw|prefetch|prefetchw)(?-i)\b"
color statement "\b(?i)(pf2iw|pfnacc|pfpnacc|pi2fw|pswapd)(?-i)\b"
color statement "\b(?i)(pfrsqrtv|pfrcpv)(?-i)\b"
color statement "\b(?i)(addps|addss|cmpps|cmpss|comiss|cvtpi2ps|cvtps2pi|cvtsi2ss|cvtss2si|cvttps2pi|cvttss2si|divps|divss|ldmxcsr|maxps|maxss|minps|minss|movaps|movhlps|movhps|movlhps|movlps|movmskps|movntps|movss|movups|mulps|mulss|rcpps|rcpss|rsqrtps|rsqrtss|shufps|sqrtps|sqrtss|stmxcsr|subps|subss|ucomiss|unpckhps|unpcklps)(?-i)\b"
color statement "\b(?i)(andnps|andps|orps|pavgb|pavgw|pextrw|pinsrw|pmaxsw|pmaxub|pminsw|pminub|pmovmskb|pmulhuw|psadbw|pshufw|xorps)(?-i)\b"
color statement "\b(?i)(movups|movss|movlps|movhlps|movlps|unpcklps|unpckhps|movhps|movlhps|prefetchnta|prefetch0|prefetch1|prefetch2|nop|movaps|cvtpi2ps|cvtsi2ss|cvtps2pi|cvttss2si|cvtps2pi|cvtss2si|ucomiss|comiss|sqrtps|sqrtss|rsqrtps|rsqrtss|rcpps|andps|orps|xorps|addps|addss|mulps|mulss|subps|subss|minps|minss|divps|divss|maxps|maxss|pshufw|ldmxcsr|stmxcsr|sfence|cmpps|cmpss|pinsrw|pextrw|shufps|pmovmskb|pminub|pmaxub|pavgb|pavgw|pmulhuw|movntq|pminsw|pmaxsw|psadbw|maskmovq)(?-i)\b"
color statement "\b(?i)(addpd|addsd|addnpd|cmppd|cmpsd)(?-i)\b"
color statement "\b(?i)(addpd|addsd|andnpd|andpd|cmppd|cmpsd|comisd|cvtdq2pd|cvtdq2ps|cvtpd2dq|cvtpd2pi|cvtpd2ps|cvtpi2pd|cvtps2dq|cvtps2pd|cvtsd2si|cvtsd2ss|cvtsi2sd|cvtss2sd|cvttpd2dq|cvttpd2pi|cvttps2dq|cvttsd2si|divpd|divsd|maxpd|maxsd|minpd|minsd|movapd|movhpd|movlpd|movmskpd|movsd|movupd|mulpd|mulsd|orpd|shufpd|sqrtpd|sqrtsd|subpd|subsd|ucomisd|unpckhpd|unpcklpd|xorpd)(?-i)\b"
color statement "\b(?i)(movdq2q|movdqa|movdqu|movq2dq|paddq|psubq|pmuludq|pshufhw|pshuflw|pshufd|pslldq|psrldq|punpckhqdq|punpcklqdq)(?-i)\b"
color statement "\b(?i)(addsubpd|addsubps|haddpd|haddps|hsubpd|hsubps|movddup|movshdup|movsldu)(?-i)\b"
color statement "\b(?i)(lddqu)(?-i)\b"
color statement "\b(?i)(psignw|psignd|psignb|pshufb|pmulhrsw|pmaddubsw|phsubw|phsubsw|phsubd|phaddw|phaddsw|phaddd|palignr|pabsw|pabsd|pabsb)(?-i)\b"
color statement "\b(?i)(dpps|dppd|blendps|blendpd|blendvps|blendvpd|roundps|roundss|roundpd|roundsd|insertps|extractps)(?-i)\b"
color statement "\b(?i)(mpsadbw|phminposuw|pmulld|pmuldq|pblendvb|pblendw|pminsb|pmaxsb|pminuw|pmaxuw|pminud|pmaxud|pminsd|pmaxsd|pinsrb|pinsrd/pinsrq|pextrb|pextrw|pextrd/pextrq|pmovsxbw|pmovzxbw|pmovsxbd|pmovzxbd|pmovsxbq|pmovzxbq|pmovsxwd|pmovzxwd|pmovsxwq|pmovzxwq|pmovsxdq|pmovzxdq|ptest|pcmpeqq|packusdw|movntdqa)(?-i)\b"
color statement "\b(?i)(extrq|insertq|movntsd|movntss)(?-i)\b"
color statement "\b(?i)(crc32|pcmpestri|pcmpestrm|pcmpistri|pcmpistrm|pcmpgtq)(?-i)\b"
color statement "\b(?i)(vfmaddpd|vfmaddps|vfmaddsd|vfmaddss|vfmaddsubpd|vfmaddsubps|vfmsubaddpd|vfmsubaddps|vfmsubpd|vfmsubps|vfmsubsd|vfmsubss|vfnmaddpd|vfnmaddps|vfnmaddsd|vfnmaddss|vfnmsubps|vfnmsubsd|vfnmsubss)(?-i)\b"
# Crypto
color statement "\b(?i)(aesenc|aesenclast|aesdec|aesdeclast|aeskeygenassist|aesimc)(?-i)\b"
color statement "\b(?i)(sha1rnds4|sha1nexte|sha1msg1|sha1msg2|sha256rnds2|sha256msg1|sha256msg2)(?-i)\b"
# Undocumented
color statement "\b(?i)(aam|aad|salc|icebp|loadall|loadalld|ud1)(?-i)\b"
## Registers
color identifier "\b(?i)(al|ah|bl|bh|cl|ch|dl|dh|bpl|sil|r8b|r9b|r10b|r11b|dil|spl|r12b|r13b|r14b|r15)(?-i)\b"
color identifier "\b(?i)(cw|sw|tw|fp_ds|fp_opc|fp_ip|fp_dp|fp_cs|cs|ss|ds|es|fs|gs|gdtr|idtr|tr|ldtr|ax|bx|cx|dx|bp|si|r8w|r9w|r10w|r11w|di|sp|r12w|r13w|r14w|r15w|ip)(?-i)\b"
color identifier "\b(?i)(fp_dp|fp_ip|eax|ebx|ecx|edx|ebp|esi|r8d|r9d|r10d|r11d|edi|esp|r12d|r13d|r14d|r15d|eip|eflags|mxcsr)(?-i)\b"
color identifier "\b(?i)(mm0|mm1|mm2|mm3|mm4|mm5|mm6|mm7|rax|rbx|rcx|rdx|rbp|rsi|r8|r9|r10|r11|rdi|rsp|r12|r13|r14|r15|rip|rflags|cr0|cr1|cr2|cr3|cr4|cr5|cr6|cr7|cr8|cr9|cr10|cr11|cr12|cr13|cr14|cr15|msw|dr0|dr1|dr2|dr3|r4|dr5|dr6|dr7|dr8|dr9|dr10|dr11|dr12|dr13|dr14|dr15)(?-i)\b"
color identifier "\b(?i)(st0|st1|st2|st3|st4|st5|st6|st7)(?-i)\b"
color identifier "\b(?i)(xmm0|xmm1|xmm2|xmm3|xmm4|xmm5|xmm6|xmm7|xmm8|xmm9|xmm10|xmm11|xmm12|xmm13|xmm14|xmm15)(?-i)\b"
color identifier "\b(?i)(ymm0|ymm1|ymm2|ymm3|ymm4|ymm5|ymm6|ymm7|ymm8|ymm9|ymm10|ymm11|ymm12|ymm13|ymm14|ymm15)(?-i)\b"
color identifier "\b(?i)(zmm0|zmm1|zmm2|zmm3|zmm4|zmm5|zmm6|zmm7|zmm8|zmm9|zmm10|zmm11|zmm12|zmm13|zmm14|zmm15|zmm16|zmm17|zmm18|zmm19|zmm20|zmm21|zmm22|zmm23|zmm24|zmm25|zmm26|zmm27|zmm28|zmm29|zmm30|zmm31)(?-i)\b"
## Constants
# Number - it works
color constant.number "\b(|h|A|0x)+[0-9]+(|h|A)+\b"
color constant.number "\b0x[0-9 a-f A-F]+\b"
## Preprocessor (NASM)
color preproc "%+(\+|\?|\?\?|)[a-z A-Z 0-9]+"
color preproc "%\[[. a-z A-Z 0-9]*\]"
## Other
color statement "\b(?i)(extern|global|section|segment|_start|\.text|\.data|\.bss)(?-i)\b"
color statement "\b(?i)(db|dw|dd|dq|dt|ddq|do)(?-i)\b"
color identifier "[a-z A-Z 0-9 _]+:"
# String
color constant.string ""(\\.|[^"])*""
color constant.string "'(\\.|[^'])*'"
## Comments
color comment ";.*"

110
runtime/syntax/asm.yaml Normal file
View File

@@ -0,0 +1,110 @@
filetype: asm
detect:
filename: "\\.(S|s|asm)$"
rules:
# This file is made for NASM assembly
## Instructions
# x86
- statement: "\\b(?i)(mov|aaa|aad|aam|aas|adc|add|and|call|cbw|clc|cld|cli|cmc|cmp|cmpsb|cmpsw|cwd|daa|das|dec|div|esc|hlt|idiv|imul|in|inc|int|into|iret|ja|jae|jb|jbe|jc|je|jg|jge|jl|jle|jna|jnae|jnb|jnbe|jnc|jne|jng|jnge|jnl|jnle|jno|jnp|jns|jnz|jo|jp|jpe|jpo|js|jz|jcxz|jmp|lahf|lds|lea|les|lock|lodsb|lodsw|loop|loope|loopne|loopnz|loopz|movsb|movsw|mul|neg|nop|or|pop|popf|push|pushf|rcl|rcr|rep|repe|repne|repnz|repz|ret|retn|retf|rol|ror|sahf|sal|sar|sbb|scasb|scasw|shl|shr|stc|std|sti|stosb|stosw|sub|test|wait|xchg|xlat|xor)(?-i)\\b"
- statement: "\\b(?i)(bound|enter|ins|leave|outs|popa|pusha)(?-i)\\b"
- statement: "\\b(?i)(arpl|clts|lar|lgdt|lidt|lldt|lmsw|loadall|lsl|ltr|sgdt|sidt|sldt|smsw|str|verr|verw)(?-i)\\b"
- statement: "\\b(?i)(bsf|bsr|bt|btc|btr|bts|cdq|cmpsd|cwde|insd|iret|iretd|iretf|jecxz|lfs|lgs|lss|lodsd|loopw|loopew|loopnew|loopnzw|loopzw|loopd|looped|loopned|loopnzd|loopzd|cr|tr|dr|movsd|movsx|movzx|outsd|popad|popfd|pushad|pushfd|scasd|seta|setae|setb|setbe|setc|sete|setg|setge|setl|setle|setna|setnae|setnb|setnbe|setnc|setne|setng|setnge|setnl|setnle|setno|setnp|setns|setnz|seto|setp|setpe|setpo|sets|setz|shdl|shrd|stosd)(?-i)\\b"
- statement: "\\b(?i)(bswap|cmpxcgh|invd|invlpg|wbinvd|xadd)(?-i)\\b"
- statement: "\\b(?i)(cpuid|cmpxchg8b|rdmsr|rdtsc|wrmsr|rsm)(?-i)\\b"
- statement: "\\b(?i)(rdpmc)(?-i)\\b"
- statement: "\\b(?i)(syscall|sysret)(?-i)\\b"
- statement: "\\b(?i)(cmova|cmovae|cmovb|cmovbe|cmovc|cmove|cmovg|cmovge|cmovl|cmovle|cmovna|cmovnae|cmovnb|cmovnbe|cmovnc|cmovne|cmovng|cmovnge|cmovnle|cmovno|cmovpn|cmovns|cmovnz|cmovo|cmovp|cmovpe|cmovpo|cmovs|cmovz|sysenter|sysexit|ud2)(?-i)\\b"
- statement: "\\b(?i)(maskmovq|movntps|movntq|prefetch0|prefetch1|prefetch2|prefetchnta|sfence)(?-i)\\b"
- statement: "\\b(?i)(clflush|lfence|maskmovdqu|mfence|movntdq|movnti|movntpd|pause)(?-i)\\b"
- statement: "\\b(?i)(monitor|mwait)(?-i)\\b"
- statement: "\\b(?i)(cdqe|cqo|cmpsq|cmpxchg16b|iretq|jrcxz|lodsq|movsdx|popfq|pushfq|rdtscp|scasq|stosq|swapgs)(?-i)\\b"
- statement: "\\b(?i)(clgi|invlpga|skinit|stgi|vmload|vmmcall|vmrun|vmsave)(?-i)\\b"
- statement: "\\b(?i)(vmptrdl|vmptrst|vmclear|vmread|vmwrite|vmcall|vmlaunch|vmresume|vmxoff|vmxon)(?-i)\\b"
- statement: "\\b(?i)(lzcnt|popcnt)(?-i)\\b"
- statement: "\\b(?i)(bextr|blcfill|blci|blcic|blcmask|blcs|blsfill|blsic|t1mskc|tzmsk)(?-i)\\b"
# x87
- statement: "\\b(?i)(f2xm1|fabs|fadd|faddp|fbld|fbstp|fchs|fclex|fcom|fcomp|fcompp|fdecstp|fdisi|fdiv|fvidp|fdivr|fdivrp|feni|ffree|fiadd|ficom|ficomp|fidiv|fidivr|fild|fimul|fincstp|finit|fist|fistp|fisub|fisubr|fld|fld1|fldcw|fldenv|fldenvw|fldl2e|fldl2t|fldlg2|fldln2|fldpi|fldz|fmul|fmulp|fnclex|fndisi|fneni|fninit|fnop|fnsave|fnsavenew|fnstcw|fnstenv|fnstenvw|fnstsw|fpatan|fprem|fptan|frndint|frstor|frstorw|fsave|fsavew|fscale|fsqrt|fst|fstcw|fstenv|fstenvw|fstp|fstpsw|fsub|fsubp|fsubr|fsubrp|ftst|fwait|fxam|fxch|fxtract|fyl2x|fyl2xp1)(?-i)\\b"
- statement: "\\b(?i)(fsetpm)(?-i)\\b"
- statement: "\\b(?i)(fcos|fldenvd|fsaved|fstenvd|fprem1|frstord|fsin|fsincos|fstenvd|fucom|fucomp|fucompp)(?-i)\\b"
- statement: "\\b(?i)(fcmovb|fcmovbe|fcmove|fcmove|fcmovnb|fcmovnbe|fcmovne|fcmovnu|fcmovu)(?-i)\\b"
- statement: "\\b(?i)(fcomi|fcomip|fucomi|fucomip)(?-i)\\b"
- statement: "\\b(?i)(fxrstor|fxsave)(?-i)\\b"
- statement: "\\b(?i)(fisttp)(?-i)\\b"
- statement: "\\b(?i)(ffreep)(?-i)\\b"
# SIMD
- statement: "\\b(?i)(emms|movd|movq|packssdw|packsswb|packuswb|paddb|paddw|paddd|paddsb|paddsw|paddusb|paddusw|pand|pandn|por|pxor|pcmpeqb|pcmpeqw|pcmpeqd|pcmpgtb|pcmpgtw|pcmpgtd|pmaddwd|pmulhw|pmullw|psllw|pslld|psllq|psrad|psraw|psrlw|psrld|psrlq|psubb|psubw|psubd|psubsb|psubsw|psubusb|punpckhbw|punpckhwd|punpckhdq|punkcklbw|punpckldq|punpcklwd)(?-i)\\b"
- statement: "\\b(?i)(paveb|paddsiw|pmagw|pdistib|psubsiw|pmwzb|pmulhrw|pmvnzb|pmvlzb|pmvgezb|pmulhriw|pmachriw)(?-i)\\b"
- statement: "\\b(?i)(femms|pavgusb|pf2id|pfacc|pfadd|pfcmpeq|pfcmpge|pfcmpgt|pfmax|pfmin|pfmul|pfrcp|pfrcpit1|pfrcpit2|pfrsqit1|pfrsqrt|pfsub|pfsubr|pi2fd|pmulhrw|prefetch|prefetchw)(?-i)\\b"
- statement: "\\b(?i)(pf2iw|pfnacc|pfpnacc|pi2fw|pswapd)(?-i)\\b"
- statement: "\\b(?i)(pfrsqrtv|pfrcpv)(?-i)\\b"
- statement: "\\b(?i)(addps|addss|cmpps|cmpss|comiss|cvtpi2ps|cvtps2pi|cvtsi2ss|cvtss2si|cvttps2pi|cvttss2si|divps|divss|ldmxcsr|maxps|maxss|minps|minss|movaps|movhlps|movhps|movlhps|movlps|movmskps|movntps|movss|movups|mulps|mulss|rcpps|rcpss|rsqrtps|rsqrtss|shufps|sqrtps|sqrtss|stmxcsr|subps|subss|ucomiss|unpckhps|unpcklps)(?-i)\\b"
- statement: "\\b(?i)(andnps|andps|orps|pavgb|pavgw|pextrw|pinsrw|pmaxsw|pmaxub|pminsw|pminub|pmovmskb|pmulhuw|psadbw|pshufw|xorps)(?-i)\\b"
- statement: "\\b(?i)(movups|movss|movlps|movhlps|movlps|unpcklps|unpckhps|movhps|movlhps|prefetchnta|prefetch0|prefetch1|prefetch2|nop|movaps|cvtpi2ps|cvtsi2ss|cvtps2pi|cvttss2si|cvtps2pi|cvtss2si|ucomiss|comiss|sqrtps|sqrtss|rsqrtps|rsqrtss|rcpps|andps|orps|xorps|addps|addss|mulps|mulss|subps|subss|minps|minss|divps|divss|maxps|maxss|pshufw|ldmxcsr|stmxcsr|sfence|cmpps|cmpss|pinsrw|pextrw|shufps|pmovmskb|pminub|pmaxub|pavgb|pavgw|pmulhuw|movntq|pminsw|pmaxsw|psadbw|maskmovq)(?-i)\\b"
- statement: "\\b(?i)(addpd|addsd|addnpd|cmppd|cmpsd)(?-i)\\b"
- statement: "\\b(?i)(addpd|addsd|andnpd|andpd|cmppd|cmpsd|comisd|cvtdq2pd|cvtdq2ps|cvtpd2dq|cvtpd2pi|cvtpd2ps|cvtpi2pd|cvtps2dq|cvtps2pd|cvtsd2si|cvtsd2ss|cvtsi2sd|cvtss2sd|cvttpd2dq|cvttpd2pi|cvttps2dq|cvttsd2si|divpd|divsd|maxpd|maxsd|minpd|minsd|movapd|movhpd|movlpd|movmskpd|movsd|movupd|mulpd|mulsd|orpd|shufpd|sqrtpd|sqrtsd|subpd|subsd|ucomisd|unpckhpd|unpcklpd|xorpd)(?-i)\\b"
- statement: "\\b(?i)(movdq2q|movdqa|movdqu|movq2dq|paddq|psubq|pmuludq|pshufhw|pshuflw|pshufd|pslldq|psrldq|punpckhqdq|punpcklqdq)(?-i)\\b"
- statement: "\\b(?i)(addsubpd|addsubps|haddpd|haddps|hsubpd|hsubps|movddup|movshdup|movsldu)(?-i)\\b"
- statement: "\\b(?i)(lddqu)(?-i)\\b"
- statement: "\\b(?i)(psignw|psignd|psignb|pshufb|pmulhrsw|pmaddubsw|phsubw|phsubsw|phsubd|phaddw|phaddsw|phaddd|palignr|pabsw|pabsd|pabsb)(?-i)\\b"
- statement: "\\b(?i)(dpps|dppd|blendps|blendpd|blendvps|blendvpd|roundps|roundss|roundpd|roundsd|insertps|extractps)(?-i)\\b"
- statement: "\\b(?i)(mpsadbw|phminposuw|pmulld|pmuldq|pblendvb|pblendw|pminsb|pmaxsb|pminuw|pmaxuw|pminud|pmaxud|pminsd|pmaxsd|pinsrb|pinsrd/pinsrq|pextrb|pextrw|pextrd/pextrq|pmovsxbw|pmovzxbw|pmovsxbd|pmovzxbd|pmovsxbq|pmovzxbq|pmovsxwd|pmovzxwd|pmovsxwq|pmovzxwq|pmovsxdq|pmovzxdq|ptest|pcmpeqq|packusdw|movntdqa)(?-i)\\b"
- statement: "\\b(?i)(extrq|insertq|movntsd|movntss)(?-i)\\b"
- statement: "\\b(?i)(crc32|pcmpestri|pcmpestrm|pcmpistri|pcmpistrm|pcmpgtq)(?-i)\\b"
- statement: "\\b(?i)(vfmaddpd|vfmaddps|vfmaddsd|vfmaddss|vfmaddsubpd|vfmaddsubps|vfmsubaddpd|vfmsubaddps|vfmsubpd|vfmsubps|vfmsubsd|vfmsubss|vfnmaddpd|vfnmaddps|vfnmaddsd|vfnmaddss|vfnmsubps|vfnmsubsd|vfnmsubss)(?-i)\\b"
# Crypto
- statement: "\\b(?i)(aesenc|aesenclast|aesdec|aesdeclast|aeskeygenassist|aesimc)(?-i)\\b"
- statement: "\\b(?i)(sha1rnds4|sha1nexte|sha1msg1|sha1msg2|sha256rnds2|sha256msg1|sha256msg2)(?-i)\\b"
# Undocumented
- statement: "\\b(?i)(aam|aad|salc|icebp|loadall|loadalld|ud1)(?-i)\\b"
## Registers
- identifier: "\\b(?i)(al|ah|bl|bh|cl|ch|dl|dh|bpl|sil|r8b|r9b|r10b|r11b|dil|spl|r12b|r13b|r14b|r15)(?-i)\\b"
- identifier: "\\b(?i)(cw|sw|tw|fp_ds|fp_opc|fp_ip|fp_dp|fp_cs|cs|ss|ds|es|fs|gs|gdtr|idtr|tr|ldtr|ax|bx|cx|dx|bp|si|r8w|r9w|r10w|r11w|di|sp|r12w|r13w|r14w|r15w|ip)(?-i)\\b"
- identifier: "\\b(?i)(fp_dp|fp_ip|eax|ebx|ecx|edx|ebp|esi|r8d|r9d|r10d|r11d|edi|esp|r12d|r13d|r14d|r15d|eip|eflags|mxcsr)(?-i)\\b"
- identifier: "\\b(?i)(mm0|mm1|mm2|mm3|mm4|mm5|mm6|mm7|rax|rbx|rcx|rdx|rbp|rsi|r8|r9|r10|r11|rdi|rsp|r12|r13|r14|r15|rip|rflags|cr0|cr1|cr2|cr3|cr4|cr5|cr6|cr7|cr8|cr9|cr10|cr11|cr12|cr13|cr14|cr15|msw|dr0|dr1|dr2|dr3|r4|dr5|dr6|dr7|dr8|dr9|dr10|dr11|dr12|dr13|dr14|dr15)(?-i)\\b"
- identifier: "\\b(?i)(st0|st1|st2|st3|st4|st5|st6|st7)(?-i)\\b"
- identifier: "\\b(?i)(xmm0|xmm1|xmm2|xmm3|xmm4|xmm5|xmm6|xmm7|xmm8|xmm9|xmm10|xmm11|xmm12|xmm13|xmm14|xmm15)(?-i)\\b"
- identifier: "\\b(?i)(ymm0|ymm1|ymm2|ymm3|ymm4|ymm5|ymm6|ymm7|ymm8|ymm9|ymm10|ymm11|ymm12|ymm13|ymm14|ymm15)(?-i)\\b"
- identifier: "\\b(?i)(zmm0|zmm1|zmm2|zmm3|zmm4|zmm5|zmm6|zmm7|zmm8|zmm9|zmm10|zmm11|zmm12|zmm13|zmm14|zmm15|zmm16|zmm17|zmm18|zmm19|zmm20|zmm21|zmm22|zmm23|zmm24|zmm25|zmm26|zmm27|zmm28|zmm29|zmm30|zmm31)(?-i)\\b"
## Constants
# Number - it works
- constant.number: "\\b(|h|A|0x)+[0-9]+(|h|A)+\\b"
- constant.number: "\\b0x[0-9 a-f A-F]+\\b"
## Preprocessor (NASM)
- preproc: "%+(\\+|\\?|\\?\\?|)[a-z A-Z 0-9]+"
- preproc: "%\\[[. a-z A-Z 0-9]*\\]"
## Other
- statement: "\\b(?i)(extern|global|section|segment|_start|\\.text|\\.data|\\.bss)(?-i)\\b"
- statement: "\\b(?i)(db|dw|dd|dq|dt|ddq|do)(?-i)\\b"
- identifier: "[a-z A-Z 0-9 _]+:"
- constant.string:
start: "\""
end: "\""
skip: "\\\\."
rules:
- constant.specialChar: "\\\\."
- constant.string:
start: "'"
end: "'"
skip: "\\\\."
rules:
- constant.specialChar: "\\\\."
- comment:
start: ";"
end: "$"
rules:
- todo: "(TODO|XXX|FIXME):?"

View File

@@ -1,25 +0,0 @@
syntax "awk" "\.awk$"
header "^#!.*bin/(env +)?awk( |$)"
color brightyellow "\$[A-Za-z0-9_!@#$*?-]+"
color brightyellow "\<(ARGC|ARGIND|ARGV|BINMODE|CONVFMT|ENVIRON|ERRNO|FIELDWIDTHS)\>"
color brightyellow "\<(FILENAME|FNR|FS|IGNORECASE|LINT|NF|NR|OFMT|OFS|ORS)\>"
color brightyellow "\<(PROCINFO|RS|RT|RSTART|RLENGTH|SUBSEP|TEXTDOMAIN)\>"
color brightblue "\<(function|extension|BEGIN|END)\>"
color red "[-+*/%^|!=&<>?;:]|\\|\[|\]"
color cyan "\<(for|if|while|do|else|in|delete|exit)\>"
color cyan "\<(break|continue|return)\>"
color brightblue "\<(close|getline|next|nextfile|print|printf|system|fflush)\>"
color brightblue "\<(atan2|cos|exp|int|log|rand|sin|sqrt|srand)\>"
color brightblue "\<(asort|asorti|gensub|gsub|index|length|match)\>"
color brightblue "\<(split|sprintf|strtonum|sub|substr|tolower|toupper)\>"
color brightblue "\<(mktime|strftime|systime)\>"
color brightblue "\<(and|compl|lshift|or|rshift|xor)\>"
color brightblue "\<(bindtextdomain|dcgettext|dcngettext)\>"
color magenta "/.*[^\\]/"
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'"
color magenta "\\."
color brightblack "(^|[[:space:]])#([^{].*)?$"
color brightwhite,cyan "TODO:?"
color ,green "[[:space:]]+$"
color ,red " + +| + +"

44
runtime/syntax/awk.yaml Normal file
View File

@@ -0,0 +1,44 @@
filetype: awk
detect:
filename: "\\.awk$"
header: "^#!.*bin/(env +)?awk( |$)"
rules:
- preproc: "\\$[A-Za-z0-9_!@#$*?\\-]+"
- preproc: "\\b(ARGC|ARGIND|ARGV|BINMODE|CONVFMT|ENVIRON|ERRNO|FIELDWIDTHS)\\b"
- preproc: "\\b(FILENAME|FNR|FS|IGNORECASE|LINT|NF|NR|OFMT|OFS|ORS)\\b"
- preproc: "\\b(PROCINFO|RS|RT|RSTART|RLENGTH|SUBSEP|TEXTDOMAIN)\\b"
- identifier.class: "\\b(function|extension|BEGIN|END)\\b"
- symbol.operator: "[\\-+*/%^|!=&<>?;:]|\\\\|\\[|\\]"
- statement: "\\b(for|if|while|do|else|in|delete|exit)\\b"
- special: "\\b(break|continue|return)\\b"
- statement: "\\b(close|getline|next|nextfile|print|printf|system|fflush)\\b"
- statement: "\\b(atan2|cos|exp|int|log|rand|sin|sqrt|srand)\\b"
- statement: "\\b(asort|asorti|gensub|gsub|index|length|match)\\b"
- statement: "\\b(split|sprintf|strtonum|sub|substr|tolower|toupper)\\b"
- statement: "\\b(mktime|strftime|systime)\\b"
- statement: "\\b(and|compl|lshift|or|rshift|xor)\\b"
- statement: "\\b(bindtextdomain|dcgettext|dcngettext)\\b"
- special: "/.*[^\\\\]/"
- constant.string:
start: "\""
end: "\""
skip: "\\\\."
rules:
- constant.specialChar: "\\\\."
- constant.string:
start: "'"
end: "'"
skip: "\\\\."
rules:
- constant.specialChar: "\\\\."
- comment:
start: "#"
end: "$"
rules:
- todo: "(TODO|XXX|FIXME):?"

28
runtime/syntax/c++.yaml Normal file
View File

@@ -0,0 +1,28 @@
filetype: c++
detect:
filename: "\\.c(c|pp|xx)$|\\.h(h|pp|xx)$|\\.ii?$|\\.(def)$"
rules:
- identifier: "\\b[A-Z_][0-9A-Z_]+\\b"
- type: "\\b(auto|float|double|bool|char|int|short|long|sizeof|enum|void|static|const|constexpr|struct|union|typedef|extern|(un)?signed|inline)\\b"
- type: "\\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\\b"
- statement: "\\b(class|namespace|template|public|protected|private|typename|this|friend|virtual|using|mutable|volatile|register|explicit)\\b"
- statement: "\\b(for|if|while|do|else|case|default|switch)\\b"
- statement: "\\b(try|throw|catch|operator|new|delete)\\b"
- special: "\\b(goto|continue|break|return)\\b"
- preproc: "^[[:space:]]*#[[:space:]]*(define|pragma|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)"
- constant: "'([^'\\\\]|(\\\\[\"'abfnrtv\\\\]))'|'\\\\(([0-3]?[0-7]{1,2}))'|'\\\\x[0-9A-Fa-f]{1,2}'"
- statement: "__attribute__[[:space:]]*\\(\\([^)]*\\)\\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
- symbol.operator: "[.:;,+*|=!\\%]|<|>|/|-|&"
- symbol.brackets: "[(){}]|\\[|\\]"
- constant.number: "\\b[0-9]+\\b|\\b0x[0-9A-Fa-f]+\\b"
- constant.bool: "\\b(true|false)\\b|NULL"
- constant.string: "\"(\\\\.|[^\"])*\""
- comment: "//.*"
- comment:
start: "/\\*"
end: "\\*/"
rules: []
- indent-char.whitespace: "[[:space:]]+$"

View File

@@ -1,40 +0,0 @@
## Here is an example for C/C++.
##
syntax "c" "\.(c(c|pp|xx)?|C)$" "\.(h(h|pp|xx)?|H)$" "\.ii?$" "\.(def)$"
color identifier "\b[A-Z_][0-9A-Z_]+\b"
color type "\b(float|double|bool|char|int|short|long|sizeof|enum|void|static|const|struct|union|typedef|extern|(un)?signed|inline)\b"
color type "\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\b"
color statement "\b(class|namespace|template|public|protected|private|typename|this|friend|virtual|using|mutable|volatile|register|explicit)\b"
color statement "\b(for|if|while|do|else|case|default|switch)\b"
color statement "\b(try|throw|catch|operator|new|delete)\b"
color statement "\b(goto|continue|break|return)\b"
color preproc "^[[:space:]]*#[[:space:]]*(define|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)"
color constant "'([^'\\]|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
##
## GCC builtins
color statement "__attribute__[[:space:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
#Operator Color
color statement "[.:;,+*|=!\%]" "<" ">" "/" "-" "&"
#Parenthetical Color
# color magenta "[(){}]" "\[" "\]"
color constant.number "\b[0-9]+\b" "\b0x[0-9A-Fa-f]+\b"
##
## String highlighting. You will in general want your brightblacks and
## strings to come last, because syntax highlighting rules will be
## applied in the order they are read in.
color constant.string ""(\\.|[^"])*""
##
## This string is VERY resource intensive!
#color cyan start=""(\\.|[^"])*\\[[:space:]]*$" end="^(\\.|[^"])*""
## Comment highlighting
color comment "//.*"
color comment start="/\*" end="\*/"
## Trailing whitespace
#color ,green "[[:space:]]+$"

54
runtime/syntax/c.yaml Normal file
View File

@@ -0,0 +1,54 @@
filetype: c
detect:
filename: "(\\.(c|C)$|\\.(h|H)$|\\.ii?$|\\.(def)$)"
rules:
- identifier: "\\b[A-Z_][0-9A-Z_]+\\b"
- type: "\\b(float|double|char|int|short|long|sizeof|enum|void|static|const|struct|union|typedef|extern|(un)?signed|inline)\\b"
- type: "\\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\\b"
- type.extended: "\\b(bool)\\b"
- statement: "\\b(typename|mutable|volatile|register|explicit)\\b"
- statement: "\\b(for|if|while|do|else|case|default|switch)\\b"
- statement: "\\b(try|throw|catch|operator|new|delete)\\b"
- statement: "\\b(goto|continue|break|return)\\b"
- preproc: "^[[:space:]]*#[[:space:]]*(define|pragma|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)"
- constant: "'([^'\\\\]|(\\\\[\"'abfnrtv\\\\]))'"
- constant: "'\\\\(([0-3]?[0-7]{1,2}))'"
- constant: "'\\\\x[0-9A-Fa-f]{1,2}'"
# GCC builtins
- statement: "__attribute__[[:space:]]*\\(\\([^)]*\\)\\)"
- statement: "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
# Operator Color
- symbol.operator: "([.:;,+*|=!\\%]|<|>|/|-|&)"
- symbol.brackets: "[(){}]|\\[|\\]"
- constant.number: "(\\b[0-9]+\\b|\\b0x[0-9A-Fa-f]+\\b)"
- constant.number: "NULL"
- constant.string:
start: "\""
end: "\""
skip: "\\\\."
rules:
- constant.specialChar: "\\\\."
- constant.string:
start: "'"
end: "'"
skip: "\\\\."
rules:
- preproc: "..+"
- constant.specialChar: "\\\\."
- comment:
start: "//"
end: "$"
rules:
- todo: "(TODO|XXX|FIXME):?"
- comment:
start: "/\\*"
end: "\\*/"
rules:
- todo: "(TODO|XXX|FIXME):?"

Some files were not shown because too many files have changed in this diff Show More