From ebe260dbbc3f20e52f58d55e9eb764e0f7d31730 Mon Sep 17 00:00:00 2001 From: Darren Li Date: Sun, 30 Jun 2024 13:40:02 +1000 Subject: [PATCH] Cross platform compat --- bin/params.ml | 9 +++ bin/path_open.ml | 205 +++++++++++++++++++++++++---------------------- bin/xdg_utils.ml | 52 ++++++------ 3 files changed, 145 insertions(+), 121 deletions(-) diff --git a/bin/params.ml b/bin/params.ml index 2f6e68e..9772703 100644 --- a/bin/params.ml +++ b/bin/params.ml @@ -84,3 +84,12 @@ let blink_on_duration : Mtime.span = Mtime.Span.(140 * ms) let cwd = Sys.getcwd () let cwd_with_trailing_sep = cwd ^ Filename.dir_sep + +let os_typ : [ `Darwin | `Linux | `Windows ] = + if Sys.win32 then ( + `Windows + ) else ( + match String.lowercase_ascii (CCUnix.call_stdout "uname") with + | "darwin" -> `Darwin + | _ -> `Linux + ) diff --git a/bin/path_open.ml b/bin/path_open.ml index e460ed0..f797f50 100644 --- a/bin/path_open.ml +++ b/bin/path_open.ml @@ -8,111 +8,124 @@ let pandoc_supported_format ~path = let cmd = xdg_open_cmd ~path in Proc_utils.run_in_background cmd |> ignore +let compute_most_unique_word_and_residing_page_num index found_phrase = + let page_nums = found_phrase + |> List.map (fun word -> + word.Search_result.found_word_pos + |> (fun pos -> Index.loc_of_pos pos index) + |> Index.Loc.line_loc + |> Index.Line_loc.page_num + ) + |> List.sort_uniq Int.compare + in + let frequency_of_word_of_page_ci : int String_map.t Int_map.t = + List.fold_left (fun acc page_num -> + let m = Misc_utils.frequencies_of_words_ci + (Index.words_of_page_num page_num index) + in + Int_map.add page_num m acc + ) + Int_map.empty + page_nums + in + found_phrase + |> List.map (fun word -> + let page_num = + Index.loc_of_pos word.Search_result.found_word_pos index + |> Index.Loc.line_loc + |> Index.Line_loc.page_num + in + let m = Int_map.find page_num frequency_of_word_of_page_ci in + let freq = + String_map.fold (fun word_on_page_ci freq acc_freq -> + if + CCString.find ~sub:word.Search_result.found_word_ci word_on_page_ci >= 0 + then ( + acc_freq + freq + ) else ( + acc_freq + ) + ) + m + 0 + in + (word, page_num, freq) + ) + |> List.fold_left (fun best x -> + let (_x_word, _x_page_num, x_freq) = x in + match best with + | None -> Some x + | Some (_best_word, _best_page_num, best_freq) -> ( + if x_freq < best_freq then + Some x + else + best + ) + ) + None + |> Option.get + |> (fun (word, page_num, _freq) -> + (word.found_word, page_num)) + let pdf index ~path ~search_result = let path = Filename.quote path in - let fallback = xdg_open_cmd ~path in + let fallback = + match Params.os_typ with + | `Linux -> xdg_open_cmd ~path + | `Darwin -> Fmt.str "open %s" path + | `Windows -> Fmt.str {|start "" %s|} path + in let cmd = match search_result with | None -> fallback | Some search_result -> ( let found_phrase = Search_result.found_phrase search_result in - let page_nums = found_phrase - |> List.map (fun word -> - word.Search_result.found_word_pos - |> (fun pos -> Index.loc_of_pos pos index) - |> Index.Loc.line_loc - |> Index.Line_loc.page_num - ) - |> List.sort_uniq Int.compare - in - let frequency_of_word_of_page_ci : int String_map.t Int_map.t = - List.fold_left (fun acc page_num -> - let m = Misc_utils.frequencies_of_words_ci - (Index.words_of_page_num page_num index) - in - Int_map.add page_num m acc - ) - Int_map.empty - page_nums - in - let (most_unique_word, most_unique_word_page_num) = - found_phrase - |> List.map (fun word -> - let page_num = - Index.loc_of_pos word.Search_result.found_word_pos index - |> Index.Loc.line_loc - |> Index.Line_loc.page_num - in - let m = Int_map.find page_num frequency_of_word_of_page_ci in - let freq = - String_map.fold (fun word_on_page_ci freq acc_freq -> - if - CCString.find ~sub:word.Search_result.found_word_ci word_on_page_ci >= 0 - then ( - acc_freq + freq - ) else ( - acc_freq - ) - ) - m - 0 - in - (word, page_num, freq) - ) - |> List.fold_left (fun best x -> - let (_x_word, _x_page_num, x_freq) = x in - match best with - | None -> Some x - | Some (_best_word, _best_page_num, best_freq) -> ( - if x_freq < best_freq then - Some x + match Params.os_typ with + | `Linux -> ( + match Xdg_utils.default_desktop_file_path `PDF with + | None -> fallback + | Some viewer_desktop_file_path -> ( + let (most_unique_word, most_unique_word_page_num) = + compute_most_unique_word_and_residing_page_num index found_phrase + in + let flatpak_package_name = + let s = Filename.basename viewer_desktop_file_path in + Option.value ~default:s + (CCString.chop_suffix ~suf:".desktop" s) + in + let viewer_desktop_file_path_lowercase_ascii = + String.lowercase_ascii viewer_desktop_file_path + in + let contains sub = + CCString.find ~sub viewer_desktop_file_path_lowercase_ascii >= 0 + in + let make_command name args = + if contains "flatpak" then + Fmt.str "flatpak run %s %s" flatpak_package_name args else - best - ) - ) - None - |> Option.get - |> (fun (word, page_num, _freq) -> - (word.found_word, page_num)) - in - match Xdg_utils.default_desktop_file_path `PDF with - | None -> fallback - | Some viewer_desktop_file_path -> ( - let flatpak_package_name = - let s = Filename.basename viewer_desktop_file_path in - Option.value ~default:s - (CCString.chop_suffix ~suf:".desktop" s) - in - let viewer_desktop_file_path_lowercase_ascii = - String.lowercase_ascii viewer_desktop_file_path - in - let contains sub = - CCString.find ~sub viewer_desktop_file_path_lowercase_ascii >= 0 - in - let make_command name args = - if contains "flatpak" then - Fmt.str "flatpak run %s %s" flatpak_package_name args - else - Fmt.str "%s %s" name args - in - let page_num = most_unique_word_page_num + 1 in - if contains "okular" then - make_command "okular" - (Fmt.str "--page %d --find %s %s" page_num most_unique_word path) - else if contains "evince" then - make_command "evince" - (Fmt.str "--page-index %d --find %s %s" page_num most_unique_word path) - else if contains "xreader" then - make_command "xreader" - (Fmt.str "--page-index %d --find %s %s" page_num most_unique_word path) - else if contains "atril" then - make_command "atril" - (Fmt.str "--page-index %d --find %s %s" page_num most_unique_word path) - else if contains "mupdf" then - make_command "mupdf" (Fmt.str "%s %d" path page_num) - else - fallback + Fmt.str "%s %s" name args + in + let page_num = most_unique_word_page_num + 1 in + if contains "okular" then + make_command "okular" + (Fmt.str "--page %d --find %s %s" page_num most_unique_word path) + else if contains "evince" then + make_command "evince" + (Fmt.str "--page-index %d --find %s %s" page_num most_unique_word path) + else if contains "xreader" then + make_command "xreader" + (Fmt.str "--page-index %d --find %s %s" page_num most_unique_word path) + else if contains "atril" then + make_command "atril" + (Fmt.str "--page-index %d --find %s %s" page_num most_unique_word path) + else if contains "mupdf" then + make_command "mupdf" (Fmt.str "%s %d" path page_num) + else + fallback + ) ) + | `Darwin -> fallback + | `Windows -> fallback ) in Proc_utils.run_in_background cmd |> ignore diff --git a/bin/xdg_utils.ml b/bin/xdg_utils.ml index afa8c9e..41da62e 100644 --- a/bin/xdg_utils.ml +++ b/bin/xdg_utils.ml @@ -44,30 +44,32 @@ let default_desktop_file_path (typ : [ `PDF ]) = ) let cache_home = - if Sys.win32 then ( - let local_app_data = "LOCALAPPDATA" in - match Sys.getenv_opt local_app_data with - | None -> ( - Misc_utils.exit_with_error_msg - (Fmt.str "environment variable %%%s%% is not set" local_app_data); - ) - | Some x -> x - ) else ( - let home_dir = - match Sys.getenv_opt "HOME" with + match Params.os_typ with + | `Windows -> ( + let local_app_data = "LOCALAPPDATA" in + match Sys.getenv_opt local_app_data with | None -> ( - Misc_utils.exit_with_error_msg "environment variable HOME is not set"; + Misc_utils.exit_with_error_msg + (Fmt.str "environment variable %%%s%% is not set" local_app_data); ) - | Some home -> home - in - match String.lowercase_ascii (CCUnix.call_stdout "uname") with - | "darwin" -> ( - Filename.concat home_dir - (Filename.concat "Library" "Application Support") - ) - | _ -> ( - match Sys.getenv_opt "XDG_CACHE_HOME" with - | None -> Filename.concat home_dir ".cache" - | Some x -> x - ) - ) + | Some x -> x + ) + | `Linux | `Darwin as x -> ( + let home_dir = + match Sys.getenv_opt "HOME" with + | None -> ( + Misc_utils.exit_with_error_msg "environment variable HOME is not set"; + ) + | Some home -> home + in + match (x :> [ `Linux | `Darwin ]) with + | `Linux -> ( + match Sys.getenv_opt "XDG_CACHE_HOME" with + | None -> Filename.concat home_dir ".cache" + | Some x -> x + ) + | `Darwin -> ( + Filename.concat home_dir + (Filename.concat "Library" "Application Support") + ) + )