package ecaml

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

Source file help.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
open! Core
open! Import

let get_text_of_help ~invoke_help =
  Echo_area.inhibit_messages Sync invoke_help;
  let help_buf = Buffer.find ~name:"*Help*" |> Option.value_exn in
  Current_buffer.set_temporarily Sync help_buf ~f:(fun () ->
    Current_buffer.contents ()
    |> Text.to_utf8_bytes
    |> String.split_lines
    |> List.filter_map ~f:(fun line ->
      if (am_running_inline_test && String.is_prefix line ~prefix:"Implemented at")
      || String.( = ) "[back]" (String.strip line)
      then None
      else Some line)
    |> concat ~sep:"\n"
    |> String.strip)
;;

let describe_function = Funcall.Wrap.("describe-function" <: Symbol.t @-> return nil)

let sort_keybindings text =
  let is_start_of_keybindings =
    let regexp =
      Regexp.of_rx
        Rx.(
          Seq
            [ Line Start
            ; Exactly "key"
            ; One_or_more (Exactly " ")
            ; Exactly "binding"
            ; Line End
            ])
    in
    fun line -> Regexp.does_match regexp (Text.of_utf8_bytes line)
  in
  let lines = String.split_lines text in
  match List.findi lines ~f:(fun _ -> is_start_of_keybindings) with
  | None -> text
  | Some (index, _) ->
    let mode_description, key_bindings = List.split_n lines (index + 2) in
    String.concat
      ~sep:"\n"
      (List.concat
         [ mode_description
         ; key_bindings
           |> List.filter ~f:(not << String.is_empty)
           |> List.sort ~compare:String.compare
         ])
;;

let describe_function_text ?(obscure_symbol = false) symbol =
  let s =
    get_text_of_help ~invoke_help:(fun () -> describe_function symbol) |> sort_keybindings
  in
  if obscure_symbol
  then
    String.Search_pattern.replace_all
      (String.Search_pattern.create (Symbol.name symbol))
      ~in_:s
      ~with_:"<SYMBOL>"
  else s
;;

let describe_key = Funcall.Wrap.("describe-key" <: Key_sequence.t @-> return nil)

let describe_key_text key_sequence =
  get_text_of_help ~invoke_help:(fun () -> describe_key key_sequence)
;;

let describe_minor_mode = Funcall.Wrap.("describe-minor-mode" <: Symbol.t @-> return nil)

let describe_minor_mode_text symbol =
  get_text_of_help ~invoke_help:(fun () -> describe_minor_mode symbol)
;;

let describe_variable = Funcall.Wrap.("describe-variable" <: Symbol.t @-> return nil)

let describe_variable_text symbol =
  get_text_of_help ~invoke_help:(fun () -> describe_variable symbol)
;;

let where_is_internal =
  Funcall.Wrap.(
    "where-is-internal"
    <: Symbol.t @-> nil_or Keymap.t @-> bool @-> return (nil_or Key_sequence.t))
;;

let where_is symbol = where_is_internal symbol None true

let where_is_string symbol =
  Option.value_map
    (where_is symbol)
    ~f:Key_sequence.description
    ~default:(Symbol.name symbol)
;;
OCaml

Innovation. Community. Security.