let menu ?(max_per_page=15) ?(always_there=[]) ~sentence items =
  (* let item_number = List.length items in *)
  let items_splitted =
    let split_number = max_per_page - (List.length always_there) in
    let rec split acc l =
      let left, right = List.split_n l split_number in
      match right with
      | [] -> List.rev (left :: acc)
      | more -> split (left :: acc) more
    in
    split [] items
  in
  let number_of_menus = List.length items_splitted in
  let rec menu_loop nth =
    let items =
      always_there @ (List.nth items_splitted nth |> Option.value ~default:[])
    in
    let available_chars =
      List.filter interaction_chars (fun c ->
          List.for_all items (fun (k, _, _) -> k <> Some c)) in
    let filled_items =
      let n = ref 0 in
      List.map items ~f:(function
        | None, l, v -> (incr n; List.nth available_chars !n, l, v)
        | Some k, l, v -> Some k, l, v)
    in
    let can_previous, can_next =
      match number_of_menus, nth with
      | 1, 0 -> falsefalse
      | _, 0 -> falsetrue
      | n, t when t = n - 1 -> truefalse
      | _, _ -> truetrue
    in
    Log.(sentence % sp
         % (if nth = 0 && number_of_menus = 1
            then empty
            else brakets (i (nth + 1) % s "/" % i number_of_menus)) % n
         % s (get_key_question ()) % n
         % concat
           (List.map filled_items ~f:(function
              | (Some k, l, v) -> sf "* [%c]: " k % l % n
              | None, _, _ -> s "ERROR, wrong usage of `menu`"))
         % (if can_previous then sf "* [<]: previous screen" % n else empty)
         % (if can_next then sf "* [>]: next screen" % n else empty)
         @ normal);
    get_key ()
    >>= fun key ->
    pressed key;
    begin match key with
    | '<' when can_previous -> menu_loop (nth - 1)
    | '>' when can_next -> menu_loop (nth + 1)
    | other ->
      begin match List.find filled_items (fun (k, _, _) -> k = Some key) with
      | Some (_, _, v) -> return v
      | None ->
        Log.(sf "Cannot understand: %c, try again please." key @ normal);
        menu_loop nth
      end
    end
  in
  menu_loop 0