package ecaml

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file minor_mode.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
open! Core
open! Import

module Q = struct
  include Q

  let abbrev_mode = "abbrev-mode" |> Symbol.intern
  let buffer_read_only = "buffer-read-only" |> Symbol.intern
  let define_minor_mode = "define-minor-mode" |> Symbol.intern
  let goto_address_mode = "goto-address-mode" |> Symbol.intern
  let read_only_mode = "read-only-mode" |> Symbol.intern
  let url_handler_mode = "url-handler-mode" |> Symbol.intern
  let view_mode = "view-mode" |> Symbol.intern
  let visual_line_mode = "visual-line-mode" |> Symbol.intern
end


type t =
  { function_name : Symbol.t
  ; variable_name : Symbol.t
  }
[@@deriving fields, sexp_of]

let create ?variable_name function_name =
  { function_name; variable_name = Option.value variable_name ~default:function_name }
;;

let compare_name = Comparable.lift Symbol.compare_name ~f:function_name
let abbrev = { function_name = Q.abbrev_mode; variable_name = Q.abbrev_mode }

let goto_address =
  { function_name = Q.goto_address_mode; variable_name = Q.goto_address_mode }
;;

let read_only = { function_name = Q.read_only_mode; variable_name = Q.buffer_read_only }
let view = { function_name = Q.view_mode; variable_name = Q.view_mode }

let url_handler =
  { function_name = Q.url_handler_mode; variable_name = Q.url_handler_mode }
;;

let visual_line =
  { function_name = Q.visual_line_mode; variable_name = Q.visual_line_mode }
;;

let is_enabled t =
  Current_buffer.value { symbol = t.variable_name; type_ = Value.Type.bool }
  |> Option.value ~default:false
;;

let disable t = Symbol.funcall1_i t.function_name (0 |> Value.of_int_exn)
let enable t = Symbol.funcall1_i t.function_name (1 |> Value.of_int_exn)

let temporarily_disable sync_or_async t ~f =
  if is_enabled t
  then (
    disable t;
    Sync_or_async.protect [%here] sync_or_async ~f ~finally:(fun () -> enable t))
  else f ()
;;

let all_minor_modes = ref []

module Private = struct
  let all_minor_modes () = !all_minor_modes |> List.sort ~compare:compare_name
end

let define_minor_mode
      name
      here
      ~docstring
      ?(define_keys = [])
      ?mode_line
      ~global
      ?(initialize = fun () -> ())
      ()
  =
  let docstring = docstring |> String.strip in
  require_nonempty_docstring here ~docstring;
  let keymap_var = Var.Wrap.(concat [ name |> Symbol.name; "-map" ] <: Keymap.t) in
  Current_buffer.set_value keymap_var (Keymap.create ());
  let keymap = Current_buffer.value_exn keymap_var in
  List.iter define_keys ~f:(fun (keys, symbol) ->
    Keymap.define_key keymap (Key_sequence.create_exn keys) (Symbol symbol));
  let docstring =
    concat [ docstring; "\n\n"; Documentation.Special_sequence.keymap keymap_var.symbol ]
  in
  Form.Blocking.eval_i
    (Form.list
       [ Q.define_minor_mode |> Form.symbol
       ; name |> Form.symbol
       ; docstring |> String.strip |> Form.string
       ; Q.K.lighter |> Form.symbol
       ; Option.value_map
           mode_line
           ~f:(fun mode_line -> String.concat [ " "; mode_line ] |> Form.string)
           ~default:Form.nil
       ; Q.K.keymap |> Form.symbol
       ; Var.symbol_as_value keymap_var |> Form.of_value_exn
       ; Q.K.global |> Form.symbol
       ; Value.of_bool global |> Form.of_value_exn
       ; Form.list
           [ Q.funcall |> Form.symbol
           ; Form.quote (Defun.lambda_nullary_nil here initialize |> Function.to_value)
           ]
       ]);
  let t = { function_name = name; variable_name = name } in
  all_minor_modes := t :: !all_minor_modes;
  t
;;

let keymap t =
  List.Assoc.find
    (Current_buffer.value_exn Keymap.minor_mode_map_alist)
    t.function_name
    ~equal:Symbol.equal
;;

let keymap_exn t =
  match keymap t with
  | Some x -> x
  | None -> raise_s [%message "minor mode has no keymap" ~minor_mode:(t : t)]
;;
OCaml

Innovation. Community. Security.