improve pasting

This commit is contained in:
joshuaboud 2021-12-15 17:42:21 -04:00
parent 78b9d7bf4a
commit 765fdff846
No known key found for this signature in database
GPG Key ID: 17EFB59E2A8BF50E
2 changed files with 113 additions and 84 deletions

View File

@ -676,6 +676,25 @@ export class NavWindow {
keepers.push(response) keepers.push(response)
} }
proc.input(JSON.stringify(keepers) + "\n", true); proc.input(JSON.stringify(keepers) + "\n", true);
} else if (payload.hasOwnProperty("choices")) {
let choices = {};
for (let choice of payload["choices"]) {
choices[choice[0]] = {
label: choice[1],
internal_name: choice[0],
type: "radio",
default: false
}
}
choices[payload["choices"][0][0]].default = true;
this.stop_load();
let response = await this.modal_prompt.prompt(payload["message"], choices);
this.start_load();
if (response === null) {
proc.input(JSON.stringify("abort") + "\n");
return;
}
proc.input(JSON.stringify(response) + "\n", true);
} else { } else {
var user_response = await this.modal_prompt.confirm(payload["message"]); var user_response = await this.modal_prompt.confirm(payload["message"]);
proc.input(JSON.stringify(user_response) + "\n", true); proc.input(JSON.stringify(user_response) + "\n", true);

View File

@ -1,20 +1,20 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Cockpit Navigator - A File System Browser for Cockpit. Cockpit Navigator - A File System Browser for Cockpit.
Copyright (C) 2021 Josh Boudreau <jboudreau@45drives.com> Copyright (C) 2021 Josh Boudreau <jboudreau@45drives.com>
This file is part of Cockpit Navigator. This file is part of Cockpit Navigator.
Cockpit Navigator is free software: you can redistribute it and/or modify Cockpit Navigator is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Cockpit Navigator is distributed in the hope that it will be useful, Cockpit Navigator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>. along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
""" """
""" """
@ -28,87 +28,97 @@ from optparse import OptionParser
import json import json
import subprocess import subprocess
def prompt_user(message, wants_response, conflicts = None): def prompt_user(message, wants_response, conflicts = None, choices = None):
payload = { payload = {
"wants-response": wants_response, "wants-response": wants_response,
"message": message "message": message
} }
if conflicts != None: if conflicts != None:
payload["conflicts"] = conflicts payload["conflicts"] = conflicts
print(json.dumps(payload) + "\n") if choices != None:
if wants_response: payload["choices"] = choices
response = json.loads(input()) print(json.dumps(payload) + "\n")
if isinstance(response, str) and response == "abort": if wants_response:
sys.exit(0) response = json.loads(input())
return response if isinstance(response, str) and response == "abort":
return sys.exit(0)
return response
return
def split_paths_at_cwd(paths, cwd): def split_paths_at_cwd(paths, cwd):
response = [] response = []
for path in paths: for path in paths:
response.append(cwd + "/./" + os.path.relpath(path, cwd)) response.append(cwd + "/./" + os.path.relpath(path, cwd))
return response return response
def recursive_get_conflicts(input_array, cwd, dest): def recursive_get_conflicts(input_array, cwd, dest):
conflicts = [] conflicts = []
non_conflicts = [] non_conflicts = []
for source in input_array: for source in input_array:
if os.path.isdir(source): if os.path.isdir(source):
child_nodes = os.listdir(source) child_nodes = os.listdir(source)
child_paths = [] child_paths = []
for node in child_nodes: for node in child_nodes:
child_paths.append(source + "/" + node) child_paths.append(source + "/" + node)
(more_conflicts, more_non_conflicts) = recursive_get_conflicts(child_paths, cwd, dest) (more_conflicts, more_non_conflicts) = recursive_get_conflicts(child_paths, cwd, dest)
conflicts += more_conflicts conflicts += more_conflicts
non_conflicts += more_non_conflicts non_conflicts += more_non_conflicts
continue continue
dest_path = dest + "/" + os.path.relpath(source, cwd) dest_path = dest + "/" + os.path.relpath(source, cwd)
if os.path.exists(dest_path): if os.path.exists(dest_path):
conflicts.append((source, dest_path)) conflicts.append((source, dest_path))
else: else:
non_conflicts.append(source) non_conflicts.append(source)
return (conflicts, non_conflicts) return (conflicts, non_conflicts)
def filter_existing(args, cwd): def filter_existing(args, cwd):
sources = args[:-1] sources = args[:-1]
dest = args[-1] dest = args[-1]
(conflicts, non_conflicts) = recursive_get_conflicts(sources, cwd, dest) (conflicts, non_conflicts) = recursive_get_conflicts(sources, cwd, dest)
if len(conflicts): if len(conflicts):
conflicts = prompt_user("Overwrite?", True, conflicts) choice = prompt_user("Conflicts Found", True, choices=[("skip-conflicts", "Skip Conflicts"), ("select", "Overwrite Selectively"), ("overwrite", "Overwrite All")])
non_conflicts.extend(conflicts) if choice == "overwrite":
if not len(non_conflicts): non_conflicts.extend(map(lambda x: x[0], conflicts))
sys.exit(0) # exit if nothing to copy elif choice == "select":
filtered_args = [*split_paths_at_cwd(non_conflicts, cwd), dest] conflicts = prompt_user("Overwrite?", True, conflicts)
return filtered_args non_conflicts.extend(conflicts)
elif choice == "skip-conflicts":
pass
else: # cancelled
sys.exit(0)
if not len(non_conflicts):
sys.exit(0) # exit if nothing to copy
filtered_args = [*split_paths_at_cwd(non_conflicts, cwd), dest]
return filtered_args
def paste(cmd, args): def paste(cmd, args):
try: try:
child = subprocess.Popen( child = subprocess.Popen(
[*cmd, *args], [*cmd, *args],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True
) )
except Exception as e: except Exception as e:
prompt_user(str(e), False) prompt_user(str(e), False)
sys.exit(1) sys.exit(1)
child.wait() child.wait()
if child.returncode: if child.returncode:
stdout, stderr = child.communicate() stdout, stderr = child.communicate()
prompt_user(stdout + stderr, False) prompt_user(stdout + stderr, False)
sys.exit(child.returncode) sys.exit(child.returncode)
def main(): def main():
parser = OptionParser() parser = OptionParser()
parser.add_option("-m", "--move", help="remove source files", action="store_true", dest="move", default=False) parser.add_option("-m", "--move", help="remove source files", action="store_true", dest="move", default=False)
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
cwd = args[0] cwd = args[0]
filtered_args = filter_existing(args[1:], cwd) filtered_args = filter_existing(args[1:], cwd)
if options.move: if options.move:
paste(["rsync", "-aI", "--relative", "--remove-source-files"], filtered_args) paste(["rsync", "-aI", "--relative", "--remove-source-files"], filtered_args)
else: else:
paste(["rsync", "-aI", "--relative"], filtered_args) paste(["rsync", "-aI", "--relative"], filtered_args)
sys.exit(0) sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":
main() main()