package dunolint
A linter for build files in dune projects
Install
Dune Dependency
Authors
Maintainers
Sources
dunolint-0.0.20250310.tbz
sha256=b44119c96aeabb960e852711c2f20ae43f0011e796f05e012141ba980a5b58f6
sha512=5bf76732adc940db6cac0875e94c3eaff436288faba95388b9675c68b3f30f5362e01f289fc8a096325f7db812ace273773a1e051ab7d7ace3b8db4a57a0e070
doc/src/dunolint.vendor_git_pager/git_pager.ml.html
Source file git_pager.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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
(*********************************************************************************) (* Git_pager - Show diffs in the terminal with the user's configured git pager *) (* Copyright (C) 2024-2025 Mathieu Barbin <mathieu.barbin@gmail.com> *) (* *) (* This file is part of Git_pager. *) (* *) (* Git_pager is free software; you can redistribute it and/or modify it *) (* under the terms of the GNU Lesser General Public License as published by *) (* the Free Software Foundation either version 3 of the License, or any later *) (* version, with the LGPL-3.0 Linking Exception. *) (* *) (* Git_pager 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 Lesser General Public License *) (* and the file `NOTICE.md` at the root of this repository for more details. *) (* *) (* You should have received a copy of the GNU Lesser General Public License *) (* and the LGPL-3.0 Linking Exception along with this library. If not, see *) (* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively. *) (*********************************************************************************) module Unix = UnixLabels type t = { output_kind : [ `Tty | `Pager | `Other ] ; color : [ `Auto | `Always | `Never ] ; write_end : Out_channel.t } let should_force_color { output_kind; color; write_end = _ } = match output_kind, color with | `Pager, `Auto -> (* This is the only case in which Git on its own would make the wrong decision if we did nothing to help. If we ran the command in a terminal, Git would normally color it, but because we are sending its output to a pipe, the [auto] strategy is confused and Git disables the colors. In all other cases we return [false]. It doesn't mean we'll get no color, it just means we let Git decide on its own. *) true | `Pager, (`Always | `Never) | (`Other | `Tty), (`Always | `Auto | `Never) -> false ;; let write_end t = t.write_end module Process_status = struct type t = Unix.process_status = | WEXITED of int | WSIGNALED of int | WSTOPPED of int [@@deriving sexp_of] end let get_git_pager () = let ((in_ch, _) as process) = Unix.open_process_args "git" [| "git"; "var"; "GIT_PAGER" |] in let output = In_channel.input_all in_ch in match Unix.close_process process with | WEXITED 0 -> output |> String.strip | (WEXITED _ | WSIGNALED _ | WSTOPPED _) as process_status -> Err.raise Pp.O. [ Pp.text "Failed to get the value of " ++ Pp_tty.kwd (module String) "GIT_PAGER" ++ Pp.text "." ; Err.pp_of_sexp (Process_status.sexp_of_t process_status) ] ;; let get_git_color () = let ((in_ch, _) as process) = Unix.open_process_args "git" [| "git"; "config"; "--get"; "color.ui" |] in let output = In_channel.input_all in_ch in match Unix.close_process process with | WEXITED (0 | 1) -> (match output |> String.strip with | "" | "auto" -> `Auto | "always" -> `Always | "never" -> `Never | other -> Err.raise Pp.O. [ Pp.text "Unexpected " ++ Pp_tty.kwd (module String) "git color.ui" ++ Pp.text " value " ++ Pp_tty.id (module String) other ++ Pp.text "." ]) | (WEXITED _ | WSIGNALED _ | WSTOPPED _) as process_status -> Err.raise Pp.O. [ Pp.text "Failed to get the value of " ++ Pp_tty.kwd (module String) "color.ui" ++ Pp.text "." ; Err.pp_of_sexp (Process_status.sexp_of_t process_status) ] ;; let git_pager = lazy (get_git_pager ()) let get_git_color = lazy (get_git_color ()) let rec waitpid_non_intr pid = try Unix.waitpid ~mode:[] pid with | Unix.Unix_error (EINTR, _, _) -> waitpid_non_intr pid ;; let run ~f = let git_pager = force git_pager in let color = force get_git_color in let stdout_isatty = Unix.isatty Unix.stdout in let pager_is_disabled = (not stdout_isatty) || String.equal git_pager "cat" in let output_kind = match pager_is_disabled, stdout_isatty with | true, true -> `Tty | true, false -> `Other | false, true -> `Pager | false, false -> assert false in match output_kind with | `Tty | `Other -> f { output_kind; color; write_end = stdout } | `Pager -> let process_env = let env = Unix.environment () in if Array.exists env ~f:(fun s -> String.is_prefix s ~prefix:"LESS=") then env else Array.append env [| "LESS=FRX" |] in let pager_in, pager_out = Unix.pipe ~cloexec:true () in let process = Unix.create_process_env ~prog:git_pager ~args:[| git_pager |] ~env:process_env ~stdin:pager_in ~stdout:Unix.stdout ~stderr:Unix.stderr in let out_ch = Unix.out_channel_of_descr pager_out in Exn.protect ~f:(fun () -> let res = f { output_kind; color; write_end = out_ch } in Out_channel.flush out_ch; res) ~finally:(fun () -> Out_channel.close out_ch; match waitpid_non_intr process |> snd with | WEXITED 0 -> () | WSIGNALED signal when Int.equal signal Stdlib.Sys.sigpipe -> () | (WEXITED _ | WSIGNALED _ | WSTOPPED _) as process_status -> Err.raise Pp.O. [ Pp.text "Call to " ++ Pp_tty.kwd (module String) "GIT_PAGER" ++ Pp.text "failed." ; Err.pp_of_sexp (Process_status.sexp_of_t process_status) ]) ;;
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>