1local info = {
2 version = 1.002,
3 comment = "file handler for textadept for context/metafun",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files",
7}
8
9local lexer = require("scite-context-lexer")
10local context = lexer.context
11
12local char, format, gsub = string.char, string.format, string.gsub
13
14
15
16
17
18
19
20io.encodings = {
21 "UTF-8",
22 "ASCII",
23 "UTF-16",
24}
25
26
27
28local sevenbitascii = { }
29for i=127,255 do
30 sevenbitascii[char(i)] = format("0x%02X",i)
31end
32
33local function setsevenbitascii(buffer)
34
35 local representation = buffer.representation
36 for k, v in next, sevenbitascii do
37 representation[k] = v
38 end
39end
40
41
42
43
44local oldrunner = textadept.run
45local runner = require("textadept-context-runner")
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66local SEPARATOR = { "" }
67local newmenu = { }
68local newkeys = { }
69
70do
71
72 newmenu.file = {
73
74 title = "_File",
75
76 { "_New", buffer.new },
77 { "_Open", io.open_file },
78 { "Open _Recent", io.open_recent_file },
79 { "Re_load", io.reload_file },
80 { "_Save", io.save_file },
81 { "Save _As", io.save_file_as },
82 { "Save All", io.save_all_files },
83
84 SEPARATOR,
85
86 { "_Close", io.close_buffer },
87 { "Close All", io.close_all_buffers },
88
89
90
91
92
93
94 SEPARATOR,
95
96 { _L["_Quit"], quit },
97
98 }
99
100
101
102 newkeys[OSX and "mn" or "cn"] = buffer.new
103 newkeys[OSX and "mo" or "co"] = io.open_file
104 newkeys[OSX and "cmo" or "cao"] = io.open_recent_file
105 newkeys[OSX and "ms" or "cs"] = io.save_file
106 newkeys[OSX and "mS" or "cS"] = io.save_file_as
107 newkeys[OSX and "mw" or "cw"] = io.close_buffer
108 newkeys[OSX and "mW" or "cW"] = io.close_all_buffers
109
110end
111
112do
113
114 local function complete_symbol()
115 textadept.editing.autocomplete(buffer:get_lexer(true))
116 end
117
118 newmenu.edit = {
119
120 title = "_Edit",
121
122 SEPARATOR,
123
124 { "_Undo", buffer.undo },
125 { "_Redo", buffer.redo },
126
127 SEPARATOR,
128
129 { "Cu_t", buffer.cut },
130 { "_Copy", buffer.copy },
131 { "_Paste", buffer.paste },
132 { "_Delete", buffer.clear },
133 { "Select _All", buffer.select_all },
134
135 SEPARATOR,
136
137 { "Duplicate _Line", buffer.line_duplicate },
138
139 SEPARATOR,
140
141 { "Toggle _Block Comment", runner.blockcomment },
142 { "_Upper Case Selection", buffer.upper_case },
143 { "_Lower Case Selection", buffer.lower_case },
144
145 }
146
147 newkeys[OSX and "mz" or "cz"] = buffer.undo
148 newkeys[OSX and "my" or "cy"] = buffer.redo
149 newkeys[OSX and "mx" or "cx"] = buffer.cut
150 newkeys[OSX and "mc" or "cc"] = buffer.copy
151 newkeys[OSX and "mv" or "cv"] = buffer.paste
152 newkeys[OSX and "ma" or "ca"] = buffer.select_all
153
154 newkeys[OSX and "mD" or "cD"] = textadept.editing.select_word
155 newkeys[OSX and "mN" or "cN"] = textadept.editing.select_line
156 newkeys[OSX and "mP" or "cP"] = textadept.editing.select_paragraph
157
158 newkeys["del"] = buffer.clear
159 newkeys["cy"] = buffer.redo
160
161 newkeys[OSX and "md" or "cd"] = buffer.line_duplicate
162 newkeys[OSX and "cu" or "cau"] = buffer.upper_case
163 newkeys[OSX and "cU" or "caU"] = buffer.lower_case
164
165 newkeys[OSX and "mq" or "cq"] = runner.blockcomment
166
167 newkeys[OSX and "ml" or "cl"] = buffer.line_delete
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193 newkeys.fn = OSX and function() return true end or nil
194
195 newkeys[OSX and "c@" or "c "] = complete_symbol
196
197end
198
199do
200
201 local function find_in_file()
202 ui.find.in_files = false
203 ui.find.focus()
204 end
205
206 local function find_in_files()
207 ui.find.in_files = true
208 ui.find.focus()
209 end
210
211 local function find_next_in_files()
212 ui.find.goto_file_found(false,true)
213 end
214
215 local function find_previous_in_files()
216 ui.find.goto_file_found(false,false)
217 end
218
219 newmenu.search = {
220
221 title = "_Search",
222
223 SEPARATOR,
224
225 { "_Find", find_in_file },
226 { "Find _Next", ui.find.find_next },
227 { "Find _Previous", ui.find.find_prev },
228 { "_Replace", ui.find.replace },
229 { "Replace _All", ui.find.replace_all },
230 { "Find _Incremental", ui.find.find_incremental },
231
232 SEPARATOR,
233
234 { "Find in Fi_les", find_in_files },
235 { "Goto Nex_t File Found", find_next_in_files },
236 { "Goto Previou_s File Found", find_previous_in_files },
237
238 SEPARATOR,
239
240 { "_Jump to", textadept.editing.goto_line }
241
242 }
243
244
245
246
247 newkeys[OSX and "mf" or "cf"] = find_in_file
248 newkeys[OSX and "mg" or "cg"] = ui.find.find_next
249 newkeys[OSX and "mG" or "cG"] = ui.find.find_prev
250 newkeys[OSX and "mg" or "cg"] = textadept.editing.goto_line
251
252 newkeys["f3"] = not OSX and ui.find.find_next or nil
253 newkeys["sf3"] = not OSX and ui.find.find_prev or nil
254
255 newkeys[OSX and "cr" or "car"] = ui.find.replace
256 newkeys[OSX and "cR" or "caR"] = ui.find.replace_all
257 newkeys[OSX and "cmf" or "caf"] = ui.find.find_incremental
258
259 newkeys[OSX and "mF" or "cF"] = find_in_files
260 newkeys[OSX and "cmg" or "cag"] = find_next_in_files
261 newkeys[OSX and "cmG" or "caG"] = find_previous_in_files
262
263end
264
265do
266
267 io.quick_open_max = 5000
268
269 local function isdir(path)
270 return path and path ~= "" and lfs.attributes(path,"mode") == "directory"
271 end
272
273 local function resolveroot(path)
274 local path = runner.resultof("mtxrun --resolve-path TEXMFCONTEXT")
275 if path then
276 return string.match(path,"(.-)%s$")
277 end
278 end
279
280 local function opencurrentdirectory()
281 local path = buffer.filename
282 if path and path ~= "" then
283 path = string.match(path,"^(.+)[/\\]")
284 if isdir(path) then
285 io.quick_open(path)
286 end
287 end
288 end
289
290 local function openuserdirectory()
291 local path = resolveroot("TEXMFPROJECT")
292 if isdir(path) then
293 io.quick_open(path .. "/tex/context/user")
294 end
295 end
296
297 local function openbasedirectory()
298 local path = resolveroot("TEXMFCONTEXT")
299 if isdir(path) then
300 io.quick_open(path .. "/tex/context/base/mkiv")
301 end
302 end
303
304 local started = false
305
306 local function startservice()
307 if WIN32 then
308 os.execute([[cmd /c start /min "Context Documentation" mtxrun --script server --auto]])
309 else
310 os.execute([[mtxrun --script server --start > ~/context-wwwserver.log &]])
311 end
312 started = true
313 end
314
315 local function showcommand()
316
317
318
319 local start = buffer.selection_n_start[0]
320 local stop = buffer.selection_n_end[0]
321 if start == stop then
322 buffer:set_target_range(buffer:word_start_position(start,true),buffer:word_end_position(stop,true))
323 else
324 buffer:set_target_range(start,stop)
325 end
326 local word = buffer.target_text
327 os.execute(format([[mtxrun --gethelp --url="http://localhost:8088/mtx-server-ctx-help.lua?command=%s"]],word or ""))
328 end
329
330 newmenu.tools = {
331
332 title = "_Tools",
333
334 SEPARATOR,
335
336 { "Check Source", runner.check },
337 { "Process Source", runner.process },
338 { "Preview Result", runner.preview },
339 { "Show Log File", runner.install("logfile") },
340 { "Quit", runner.quit },
341
342 SEPARATOR,
343
344 { "Open Current Directory", opencurrentdirectory },
345 { "Open User Directory", openuserdirectory },
346 { "Open Base Directory", openbasedirectory },
347
348 SEPARATOR,
349
350 { "Purge Files", runner.install("purge") },
351 { "Clear Cache", runner.install("clear") },
352 { "Generate File Database", runner.install("generate") },
353 { "Generate Font Database", runner.install("fonts") },
354
355 SEPARATOR,
356
357 { "Typeset Listing", runner.install("listing") },
358 { "Process and Arrange", runner.install("arrange") },
359
360 SEPARATOR,
361
362 { "Start Document Service", startservice },
363 { "Goto Document Service", showcommand },
364
365 SEPARATOR,
366
367 { "Show Unicodes", runner.unicodes },
368
369
370
371
372
373
374
375
376
377}
378
379
380 newkeys[OSX and "mr" or "cr"] = runner.process
381 newkeys[OSX and "mp" or "cp"] = runner.preview
382
383
384 newkeys["f7"] = runner.process
385 newkeys["f12"] = runner.process
386
387 newkeys["f2"] = runner.unicodes
388
389end
390
391do
392
393 local function use_tabs()
394 buffer.use_tabs = not buffer.use_tabs
395 events.emit(events.UPDATE_UI)
396 end
397
398 local function set_eol_mode_crlf()
399 set_eol_mode(buffer.EOL_CRLF)
400 end
401
402 local function set_eol_mode_lf()
403 set_eol_mode(buffer.EOL_LF)
404 end
405
406 local function show_eol()
407 buffer.view_eol = not buffer.view_eol
408 end
409
410 local function wrap_mode()
411 buffer.wrap_mode = buffer.wrap_mode == 0 and buffer.WRAP_WHITESPACE or 0
412 end
413
414 function show_white_space()
415 buffer.view_ws = buffer.view_ws == 0 and buffer.WS_VISIBLEALWAYS or 0
416 end
417
418 local function update_lexing()
419 buffer:colourise(0,-1)
420 end
421
422 function set_endoding_utf8()
423 set_encoding("UTF-8")
424 end
425
426 function set_encoding_ascii()
427 set_encoding("ASCII")
428 end
429
430 function set_endoding_utf16le()
431 set_encoding("UTF-16LE")
432 end
433
434 function set_endoding_utf16Be()
435 set_encoding("UTF-16BE")
436 end
437
438 function goto_prev_buffer()
439 view:goto_buffer(-1)
440 end
441
442 function goto_next_buffer()
443 view:goto_buffer(1)
444 end
445
446 newmenu.buffer = {
447
448 title = "_Buffer",
449
450 SEPARATOR,
451
452 { "_Previous Buffer", goto_prev_buffer },
453 { "_Next Buffer", goto_next_buffer },
454 { "_Switch to Buffer", ui.switch_buffer },
455
456 SEPARATOR,
457
458 { "_Toggle Use Tabs", use_tabs },
459 {
460 title = "EOL Mode",
461
462 { "_CRLF", set_eol_mode_crlf },
463 { "_LF", set_eol_mode_lf },
464 },
465 {
466 title = "Encoding",
467
468 { "_ASCII", set_encoding_ascii },
469 { "_UTF-8", set_encoding_utf8 },
470 { "UTF-16-_BE", set_encoding_utf16le },
471 { "UTF-16-_LE", set_encoding_utf16be },
472 },
473
474 SEPARATOR,
475
476 { "Toggle View _EOL", show_eol },
477 { "Toggle _Wrap Mode", wrap_mode },
478 { "Toggle View _Spacing", show_whitespace },
479
480 SEPARATOR,
481
482 { "Select _Lexer", textadept.file_types.select_lexer },
483 { "Refresh _Syntax Highlighting", update_lexing }
484
485 }
486
487 newkeys["f5"] = update_lexing
488
489 newkeys[OSX and "mp" or "cs\t"] = goto_prev_buffer
490 newkeys[OSX and "mn" or "c\t"] = goto_next_buffer
491 newkeys[OSX and "mb" or "cb"] = ui.switch_buffer
492
493end
494
495do
496
497 local function toggle_current_fold()
498 buffer:toggle_fold(buffer:line_from_position(buffer.current_pos))
499 end
500
501 local function toggle_show_guides()
502 local off = buffer.indentation_guides == 0
503 buffer.indentation_guides = off and buffer.IV_LOOKBOTH or 0
504 end
505
506 local function toggle_virtual_space()
507 local off = buffer.virtual_space_options == 0
508 buffer.virtual_space_options = off and buffer.VS_USERACCESSIBLE or 0
509 end
510
511 local function reset_zoom()
512 buffer.zoom = 0
513 end
514
515 newmenu.view = {
516
517 title = "_View",
518
519 SEPARATOR,
520
521 { "Toggle Current _Fold" , toggle_current_fold },
522
523 SEPARATOR,
524
525 { "Toggle Show In_dent Guides", toggle_show_guides },
526 { "Toggle _Virtual Space", toggle_virtual_space },
527
528 SEPARATOR,
529
530 { "Zoom _In", buffer.zoom_in },
531 { "Zoom _Out", buffer.zoom_out },
532 { "_Reset Zoom", reset_zoom },
533
534 }
535
536 newkeys[OSX and "m=" or "c="] = buffer.zoom_in
537 newkeys[OSX and "m-" or "c-"] = buffer.zoom_out
538 newkeys[OSX and "m0" or "c0"] = reset_zoom
539
540end
541
542do
543
544
545
546 local template = "\n\trelease info: %s\t\n\n\tcopyright: %s\t\n\n\tvariant: ConTeXt related editing\t\n\n\tadapted by: Hans Hagen\t"
547
548 function show_about()
549 ui.dialogs.msgbox {
550 title = "about",
551 informative_text = format(template,(gsub(_RELEASE,"%s+"," ")),(gsub(_COPYRIGHT,"%s+"," ")))
552 }
553 end
554
555 local function open_url(url)
556 local cmd = (WIN32 and 'start ""') or (OSX and "open") or "xdg-open"
557 os.spawn(format('%s "%s"', cmd, url))
558 end
559
560
561 newmenu.help = {
562
563 title = "_Help",
564
565 SEPARATOR,
566
567 { "ConTeXt garden wiki", function() open_url("http://www.contextgarden.net") end },
568
569
570
571 { "_About", show_about }
572
573 }
574
575end
576
577do
578
579
580
581 table.insert(textadept.menu.context_menu, SEPARATOR)
582
583 table.insert(textadept.menu.context_menu, { "wrap", runner.wrap })
584 table.insert(textadept.menu.context_menu, { "unwrap", runner.unwrap })
585 table.insert(textadept.menu.context_menu, { "sort", runner.sort })
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600 newkeys[OSX and "mm" or "cm"] = runner.wrap
601
602end
603
604do
605
606 local function replace(oldmenu,newmenu)
607 local n = #newmenu
608 local o = #oldmenu
609 for i=1,n do
610 oldmenu[i] = newmenu[i]
611 end
612 for i=o,n+1,-1 do
613 oldmenu[i] = nil
614 end
615 end
616
617 replace(textadept.menu.menubar [_L["_File"]], newmenu.file)
618 replace(textadept.menu.menubar [_L["_Edit"]], newmenu.edit)
619 replace(textadept.menu.menubar [_L["_Search"]], newmenu.search)
620 replace(textadept.menu.menubar [_L["_Tools"]], newmenu.tools)
621 replace(textadept.menu.menubar [_L["_Buffer"]], newmenu.buffer)
622 replace(textadept.menu.menubar [_L["_View"]], newmenu.view)
623 replace(textadept.menu.menubar [_L["_Help"]], newmenu.help)
624
625 local char = string.char
626
627 local combi = {
628 "c", "m", "a",
629 "cm", "ca", "ma",
630 }
631
632 local pad = {
633 "esc", "del", "bs",
634 "up", "down", "left", "right",
635 "end", "home",
636 "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
637 }
638
639 local s = "s"
640
641 for i=1,#combi do
642 local c = combi[i]
643 for i=0x20,0x40 do
644 local ci = char(i)
645 keys[ c..ci] = nil
646 keys[s..c..ci] = nil
647 end
648 for i=0x41,0x5A do
649 local ci = char(i)
650 keys[ c..ci] = nil
651 end
652 for i=0x5B,0x60 do
653 local ci = char(i)
654 keys[ c..ci] = nil
655 keys[s..c..ci] = nil
656 end
657 for i=0x61,0x7A do
658 local ci = char(i)
659 keys[ c..ci] = nil
660 end
661 for i=0x7B,0x7F do
662 local ci = char(i)
663 keys[ c..ci] = nil
664 keys[s..c..ci] = nil
665 end
666 for i=1,#pad do
667 local pi = pad[i]
668 keys[ c..pi] = nil
669 keys[s..c..pi] = nil
670 end
671 end
672
673 for k, v in next, newkeys do
674 keys[k] = v
675 end
676
677
678
679 events.connect(events.INITIALIZED, function()
680 for i=1,#_BUFFERS do
681 local buffer = _BUFFERS[i]
682 if buffer._type == OUTPUT_BUFFER then
683 view:goto_buffer(i)
684 io.close_buffer()
685 return
686 end
687 end
688 end)
689
690end
691
692
693
694
695local dummyrunner = function() end
696local extensions = textadept.file_types.extensions
697local specifications = runner.specifications
698local setters = { }
699local defaults = {
700 check = dummyrunner,
701 process = dummyrunner,
702 preview = dummyrunner,
703}
704
705setmetatable(specifications, { __index = defaults })
706
707function context.install(specification)
708 local suffixes = specification.suffixes
709 if suffixes then
710 local lexer = specification.lexer
711 local setter = specification.setter
712 local encoding = specification.encoding
713 for i=1,#suffixes do
714 local suffix = suffixes[i]
715 if lexer and extensions then
716 extensions[suffix] = lexer
717 end
718 specifications[suffix] = specification
719 if lexer then
720 setters[lexer] = function()
721 if encoding == "7-BIT-ASCII" then
722 setsevenbitascii(buffer)
723 end
724 if setter then
725 setter(lexer)
726 end
727 end
728 end
729 end
730 end
731end
732
733
734
735local function synchronize(lexer)
736 if lexer then
737 local setter = lexer and setters[lexer]
738 if setter then
739 local action = context.synchronize
740 if action then
741 action()
742 end
743
744 setter(lexer)
745 else
746
747 end
748 end
749end
750
751events.connect(events.FILE_OPENED,function(filename)
752 synchronize(buffer:get_lexer())
753end)
754
755events.connect(events.LEXER_LOADED,function(lexer)
756 synchronize(lexer)
757end)
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827 |