From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Aleksandr Vityazev via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#73357: [PATCH] Make vc-clone interactive Date: Thu, 24 Oct 2024 15:31:59 +0300 Message-ID: <87wmhx4r7k.fsf@disroot.org> References: <875xqrlr3b.fsf@disroot.org> <86ploz935f.fsf@gnu.org> <87y13nk39b.fsf@disroot.org> <87ed59tkpk.fsf@posteo.net> <871q12fhf2.fsf@disroot.org> <87jzesulk7.fsf@posteo.net> <87y131ffox.fsf@disroot.org> <86msj9wmna.fsf@gnu.org> <874j516bwk.fsf@disroot.org> <87sesl93xe.fsf@posteo.net> <87a5et4u90.fsf@melete.silentflame.com> Reply-To: Aleksandr Vityazev Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="19910"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: Dmitry Gutov , Philip Kaludercic , Eli Zaretskii , 73357@debbugs.gnu.org To: Sean Whitton Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Thu Oct 24 14:33:08 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1t3x1X-0004tf-Sl for geb-bug-gnu-emacs@m.gmane-mx.org; Thu, 24 Oct 2024 14:33:08 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t3x13-0003Bf-6J; Thu, 24 Oct 2024 08:32:37 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t3x0y-0003BT-MG for bug-gnu-emacs@gnu.org; Thu, 24 Oct 2024 08:32:32 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t3x0x-00088x-Cp for bug-gnu-emacs@gnu.org; Thu, 24 Oct 2024 08:32:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:References:In-Reply-To:From:To:Subject; bh=f10l7Tezvpd2vxofMvZGBWEnPf1JS6IokY0v5I2yn3o=; b=L0a+MHPrgxMWq+U2pa2AivlvQaHaF7+R74k4S3BpNAgId0fIYzmqoA0tSaYpixKJxftFSOCPbuGUyCNGgF6MNGuUUEQWXi7W3aECJZzyZssWdmvjqVBH4XIy2CjbbQLQMQG0r/Atshv/A2+jEJaq2fXTaVC5jR452a7uvOp4KpaHbL92I5bRA83xLfmTY2jLXsimOEhVq2kln55U++Mk2xBO7iReOwKssGqn8oleg3zoc6HhE4ZIc7ChI6MXLEvSxXnZSDrEHZyNT9M3HWx4JlhcTr4SrIKpFHF/eGF8T7yCHbmJzxACxoww9Elph16dG/+jTrOf5CyHHw2B7Rg6tw==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1t3x1R-0000op-TQ for bug-gnu-emacs@gnu.org; Thu, 24 Oct 2024 08:33:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Aleksandr Vityazev Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 24 Oct 2024 12:33:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 73357 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 73357-submit@debbugs.gnu.org id=B73357.17297731643123 (code B ref 73357); Thu, 24 Oct 2024 12:33:01 +0000 Original-Received: (at 73357) by debbugs.gnu.org; 24 Oct 2024 12:32:44 +0000 Original-Received: from localhost ([127.0.0.1]:33972 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1t3x19-0000oH-22 for submit@debbugs.gnu.org; Thu, 24 Oct 2024 08:32:44 -0400 Original-Received: from layka.disroot.org ([178.21.23.139]:35794) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1t3x12-0000no-Sy for 73357@debbugs.gnu.org; Thu, 24 Oct 2024 08:32:42 -0400 Original-Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 4B07A251D2; Thu, 24 Oct 2024 14:32:04 +0200 (CEST) X-Virus-Scanned: SPAM Filter at disroot.org Original-Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id I5mbncc0DtHA; Thu, 24 Oct 2024 14:32:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1729773122; bh=ar8LYfFIUoKtcy45ZbcQHeh6BEV6NUUADZyqAJdU4bE=; h=From:To:Cc:Subject:In-Reply-To:References:Date; b=FbNjNV01K1OBjyL7s9ZsUQavr/E3bewpYaowPeWzWqxNg4z5dRQKqaSkZc6A5R9r9 WP/y+D/SUF+6Y2tm3TE2WVoEn3RaX/cLEq6LWRYk7TtEHktTb4/M2gc9v7UEpiq/2a KlWVAVf9u+BCLN0AFGDibslUTeEMjWA5VFEOMQsOqXcITNK2fkCz2z6ESkcQfWDtZp wh613NcMbRFoBHjY+bB3c8FoPdPx/3TFYQNN/Z0Ibyo2k4oumgrK2rBd9/LbmP78TF bY5cPY5m09ahN6hJtiIaLs2i8NwoRE4REVTtOgWdaXz2FU/okxSMSbPHhNgsb+y3N7 kg5lStqHlfJGA== In-Reply-To: <87a5et4u90.fsf@melete.silentflame.com> (Sean Whitton's message of "Thu, 24 Oct 2024 19:26:19 +0800") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:294184 Archived-At: --=-=-= Content-Type: text/plain On 2024-10-24 19:26, Sean Whitton wrote: Hello, > Hello, > > On Thu 24 Oct 2024 at 10:43am GMT, Philip Kaludercic wrote: > >> Aleksandr Vityazev writes: >> >> [...] >> >>>>> V4 patches: >>>> >>>> Thanks. >>>> >>>> Dmitry, any comments, or should I install this? >>> >>> Just a gentle ping, any news on this bug? >> >> FWIW as the vc-clone author, I think we can apply it, but Dmitry is the >> VC maintainer so he should have the last word. > > I'm the new VC maintainer. > > Aleksandr, thank you for this. Some comments on v4: > > - The commit message of the first patch doesn't completely follow the > guidelines in CONTRIBUTE. I think M-q will fix it. fixed > - I also find the ... thing hard to read because it's separated by > other changes. Would you mind just writing out the changes twice? fixed > - vc-heuristic-alist should probaby have ':version 31.1' fixed > - Inserting vc-guess-backend right at the top doesn't seem right. There > is already a section "Code for deducing what fileset and backend to > assume". Moved to suggested section > - I think that vc-guess-backend should be called vc-guess-url-backend or > similar. 'vc-guess-backend' is too generic. Renamed to vc-guess-url-backend > - I'm not really convinced by the OPEN-DIR argument. You specifically > say that it's for scripting purposes, but then, the script can just > call find-file :) Is there some reason why it's better as an > argument? I don't have a strong opinion on this. I originally proposed this: (when (file-directory-p directory) (if (called-interactively-p 'interactive) (find-file directory) directory)) The OPEN-DIR argument was suggested by Philip, and I agreed with him, since the option is also good. I'm fine with both options, I'll do as you say. V5 patches: --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Move-package-vc-heuristic-alist-and-related-to-vc.patch Content-Description: [PATCH] Move package-vc-heuristic-alist and related to vc.el >From 7072d2002a4b0852ba6d133f1f4728fc7d25ccc6 Mon Sep 17 00:00:00 2001 Message-ID: <7072d2002a4b0852ba6d133f1f4728fc7d25ccc6.1729772961.git.avityazev@disroot.org> From: Aleksandr Vityazev Date: Thu, 24 Oct 2024 15:11:44 +0300 Subject: [PATCH] Move package-vc-heuristic-alist and related to vc.el * lisp/emacs-lisp/package-vc (package-vc--backend-type) (package-vc-heuristic-alist, package-vc--guess-backend): Rename to vc-backend-type, vc-heuristic-alist, vc-guess-backend accordingly and move into lisp/vc/vc.el. (package-vc-heuristic-alist): Make obsolete. (package-vc-default-backend): Set type to vc-backend-type. (package-vc--clone, package-vc--read-package-name) (package-vc-install, package-vc-checkout): Use vc-guess-backend. * lisp/vc/vc (vc-backend-type, vc-heuristic-alist) (vc-guess-backend): New defconst, defcustom and defun accordingly. Rename and move here from lisp/emacs-lisp/package-vc.el. --- lisp/emacs-lisp/package-vc.el | 77 ++++------------------------------- lisp/vc/vc.el | 62 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 68 deletions(-) diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el index 894bc9c8c37..6ea55c1baef 100644 --- a/lisp/emacs-lisp/package-vc.el +++ b/lisp/emacs-lisp/package-vc.el @@ -63,61 +63,9 @@ package-vc (defconst package-vc--elpa-packages-version 1 "Version number of the package specification format understood by package-vc.") -(defconst package-vc--backend-type - `(choice :convert-widget - ,(lambda (widget) - (let (opts) - (dolist (be vc-handled-backends) - (when (or (vc-find-backend-function be 'clone) - (alist-get 'clone (get be 'vc-functions))) - (push (widget-convert (list 'const be)) opts))) - (widget-put widget :args opts)) - widget)) - "The type of VC backends that support cloning package VCS repositories.") - -(defcustom package-vc-heuristic-alist - `((,(rx bos "http" (? "s") "://" - (or (: (? "www.") "github.com" - "/" (+ (or alnum "-" "." "_")) - "/" (+ (or alnum "-" "." "_"))) - (: "codeberg.org" - "/" (+ (or alnum "-" "." "_")) - "/" (+ (or alnum "-" "." "_"))) - (: (? "www.") "gitlab" (+ "." (+ alnum)) - "/" (+ (or alnum "-" "." "_")) - "/" (+ (or alnum "-" "." "_"))) - (: "git.sr.ht" - "/~" (+ (or alnum "-" "." "_")) - "/" (+ (or alnum "-" "." "_"))) - (: "git." (or "savannah" "sv") "." (? "non") "gnu.org/" - (or "r" "git") "/" - (+ (or alnum "-" "." "_")) (? "/"))) - (or (? "/") ".git") eos) - . Git) - (,(rx bos "http" (? "s") "://" - (or (: "hg.sr.ht" - "/~" (+ (or alnum "-" "." "_")) - "/" (+ (or alnum "-" "." "_"))) - (: "hg." (or "savannah" "sv") "." (? "non") "gnu.org/hgweb/" - (+ (or alnum "-" "." "_")) (? "/"))) - eos) - . Hg) - (,(rx bos "http" (? "s") "://" - (or (: "bzr." (or "savannah" "sv") "." (? "non") "gnu.org/r/" - (+ (or alnum "-" "." "_")) (? "/"))) - eos) - . Bzr)) - "Alist mapping repository URLs to VC backends. -`package-vc-install' consults this alist to determine the VC -backend from the repository URL when you call it without -specifying a backend. Each element of the alist has the form -\(URL-REGEXP . BACKEND). `package-vc-install' will use BACKEND of -the first association for which the URL of the repository matches -the URL-REGEXP of the association. If no match is found, -`package-vc-install' uses `package-vc-default-backend' instead." - :type `(alist :key-type (regexp :tag "Regular expression matching URLs") - :value-type ,package-vc--backend-type) - :version "29.1") +(define-obsolete-variable-alias + 'package-vc-heuristic-alist + 'vc-heuristic-alist "31.1") (defcustom package-vc-default-backend 'Git "Default VC backend to use for cloning package repositories. @@ -127,7 +75,7 @@ package-vc-default-backend The value must be a member of `vc-handled-backends' that supports the `clone' VC function." - :type package-vc--backend-type + :type vc-backend-type :version "29.1") (defcustom package-vc-register-as-project t @@ -626,13 +574,6 @@ package-vc--unpack-1 ""))) t)) -(defun package-vc--guess-backend (url) - "Guess the VC backend for URL. -This function will internally query `package-vc-heuristic-alist' -and return nil if it cannot reasonably guess." - (and url (alist-get url package-vc-heuristic-alist - nil nil #'string-match-p))) - (declare-function project-remember-projects-under "project" (dir &optional recursive)) (defun package-vc--clone (pkg-desc pkg-spec dir rev) @@ -646,7 +587,7 @@ package-vc--clone (unless (file-exists-p dir) (make-directory (file-name-directory dir) t) (let ((backend (or (plist-get pkg-spec :vc-backend) - (package-vc--guess-backend url) + (vc-guess-url-backend url) (plist-get (alist-get (package-desc-archive pkg-desc) package-vc--archive-data-alist nil nil #'string=) @@ -753,7 +694,7 @@ package-vc--read-package-name ;; pointing towards a repository, and use that as a backup (and-let* ((extras (package-desc-extras (cadr pkg))) (url (alist-get :url extras)) - ((package-vc--guess-backend url))))))) + ((vc-guess-url-backend url))))))) (not allow-url))) (defun package-vc--read-package-desc (prompt &optional installed) @@ -917,7 +858,7 @@ package-vc-install (cdr package) rev)) ((and-let* (((stringp package)) - (backend (or backend (package-vc--guess-backend package)))) + (backend (or backend (vc-guess-url-backend package)))) (package-vc--unpack (package-desc-create :name (or name (intern (file-name-base package))) @@ -930,7 +871,7 @@ package-vc-install (or (package-vc--desc->spec (cadr desc)) (and-let* ((extras (package-desc-extras (cadr desc))) (url (alist-get :url extras)) - (backend (package-vc--guess-backend url))) + (backend (vc-guess-url-backend url))) (list :vc-backend backend :url url)) (user-error "Package `%s' has no VC data" package)) rev))) @@ -958,7 +899,7 @@ package-vc-checkout (let ((pkg-spec (or (package-vc--desc->spec pkg-desc) (and-let* ((extras (package-desc-extras pkg-desc)) (url (alist-get :url extras)) - (backend (package-vc--guess-backend url))) + (backend (vc-guess-url-backend url))) (list :vc-backend backend :url url)) (user-error "Package `%s' has no VC data" (package-desc-name pkg-desc))))) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 6498b8522fd..8a8eb6fcfc7 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -944,6 +944,61 @@ vc-allow-rewriting-published-history (const :tag "Allow without prompting" t)) :version "31.1") +(defconst vc-backend-type + `(choice :convert-widget + ,(lambda (widget) + (let (opts) + (dolist (be vc-handled-backends) + (when (or (vc-find-backend-function be 'clone) + (alist-get 'clone (get be 'vc-functions))) + (push (widget-convert (list 'const be)) opts))) + (widget-put widget :args opts)) + widget)) + "The type of VC backends that support cloning VCS repositories.") + +(defcustom vc-heuristic-alist + `((,(rx bos "http" (? "s") "://" + (or (: (? "www.") "github.com" + "/" (+ (or alnum "-" "." "_")) + "/" (+ (or alnum "-" "." "_"))) + (: "codeberg.org" + "/" (+ (or alnum "-" "." "_")) + "/" (+ (or alnum "-" "." "_"))) + (: (? "www.") "gitlab" (+ "." (+ alnum)) + "/" (+ (or alnum "-" "." "_")) + "/" (+ (or alnum "-" "." "_"))) + (: "git.sr.ht" + "/~" (+ (or alnum "-" "." "_")) + "/" (+ (or alnum "-" "." "_"))) + (: "git." (or "savannah" "sv") "." (? "non") "gnu.org/" + (or "r" "git") "/" + (+ (or alnum "-" "." "_")) (? "/"))) + (or (? "/") ".git") eos) + . Git) + (,(rx bos "http" (? "s") "://" + (or (: "hg.sr.ht" + "/~" (+ (or alnum "-" "." "_")) + "/" (+ (or alnum "-" "." "_"))) + (: "hg." (or "savannah" "sv") "." (? "non") "gnu.org/hgweb/" + (+ (or alnum "-" "." "_")) (? "/"))) + eos) + . Hg) + (,(rx bos "http" (? "s") "://" + (or (: "bzr." (or "savannah" "sv") "." (? "non") "gnu.org/r/" + (+ (or alnum "-" "." "_")) (? "/"))) + eos) + . Bzr)) + "Alist mapping repository URLs to VC backends. +`vc-clone' consults this alist to determine the VC +backend from the repository URL when you call it without +specifying a backend. Each element of the alist has the form +\(URL-REGEXP . BACKEND). `vc-clone' will use BACKEND of +the first association for which the URL of the repository matches +the URL-REGEXP of the association." + :type `(alist :key-type (regexp :tag "Regular expression matching URLs") + :value-type ,vc-backend-type) + :version "31.1") + ;; File property caching @@ -1033,6 +1088,13 @@ vc-backend-for-registration (vc-call-backend bk 'create-repo)) (throw 'found bk)))) +(defun vc-guess-url-backend (url) + "Guess the VC backend for URL. +This function will internally query `vc-heuristic-alist' +and return nil if it cannot reasonably guess." + (and url (alist-get url vc-heuristic-alist + nil nil #'string-match-p))) + ;;;###autoload (defun vc-responsible-backend (file &optional no-error) "Return the name of a backend system that is responsible for FILE. -- 2.46.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Make-vc-clone-interactive.patch Content-Description: [PATCH] Make vc-clone interactive >From a64134c73086f5067d1f360dad0ab48267750fd1 Mon Sep 17 00:00:00 2001 Message-ID: From: Aleksandr Vityazev Date: Thu, 24 Oct 2024 15:19:34 +0300 Subject: [PATCH] Make vc-clone interactive * lisp/vc/vc.el (vc-clone): Make interactive. Add optional argument OPEN-DIR. Mention these changes in the doc string. (vc--remotes-history): New defvar. * etc/NEWS: Announce these changes. --- etc/NEWS | 10 ++++++++++ lisp/vc/vc.el | 54 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 64e4f22b9d3..12053fffc57 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -614,6 +614,16 @@ even though Emacs thinks it is dangerous. So far, this applies only to using 'e' from Log View mode for Git. +*** 'vc-clone' is now an interactive command. +When called interactively, 'vc-clone' now prompts for the remote +repository address, the backend for cloning, if it has not been +determined automatically according to the URL, and the directory to +clone the repository into. + +*** 'vc-clone' now accepts an optional argument OPEN-DIR. +When the argument is non-nil, the function switches to a buffer visiting +directory to which the repository was cloned. + * New Modes and Packages in Emacs 31.1 diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 8a8eb6fcfc7..975f7f40b15 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3876,7 +3876,9 @@ vc-check-headers (interactive) (vc-call-backend (vc-backend buffer-file-name) 'check-headers)) -(defun vc-clone (remote &optional backend directory rev) +(defvar vc--remotes-history) + +(defun vc-clone (remote &optional backend directory rev open-dir) "Clone repository REMOTE using version-control BACKEND, into DIRECTORY. If successful, return the string with the directory of the checkout; otherwise return nil. @@ -3886,20 +3888,42 @@ vc-clone If BACKEND is nil or omitted, the function iterates through every known backend in `vc-handled-backends' until one succeeds to clone REMOTE. If REV is non-nil, it indicates a specific revision to check out after -cloning; the syntax of REV depends on what BACKEND accepts." - (setq directory (expand-file-name (or directory default-directory))) - (if backend - (progn - (unless (memq backend vc-handled-backends) - (error "Unknown VC backend %s" backend)) - (vc-call-backend backend 'clone remote directory rev)) - (catch 'ok - (dolist (backend vc-handled-backends) - (ignore-error vc-not-supported - (when-let* ((res (vc-call-backend - backend 'clone - remote directory rev))) - (throw 'ok res))))))) +cloning; the syntax of REV depends on what BACKEND accepts. +If OPEN-DIR is non-nil, switches to a buffer visiting DIRECTORY to +which the repository was cloned. It would be useful in scripts, but not +in regular code. +If called interactively, prompt for REMOTE, DIRECTORY and BACKEND, +if BACKEND has not been automatically determined according to the REMOTE +URL, in the minibuffer." + (interactive + (let* ((url (read-string "Remote: " nil 'vc--remotes-history)) + (backend (or (vc-guess-url-backend url) + (intern (completing-read + "Backend: " vc-handled-backends nil t))))) + (list url backend + (read-directory-name + "Clone into new or empty directory: " nil nil + (lambda (dir) (or (not (file-exists-p dir)) + (directory-empty-p dir)))) + nil t))) + (let* ((directory (expand-file-name (or directory default-directory))) + (backend (or backend (vc-guess-url-backend remote))) + (directory (if backend + (progn + (unless (memq backend vc-handled-backends) + (error "Unknown VC backend %s" backend)) + (vc-call-backend backend 'clone remote directory rev)) + (catch 'ok + (dolist (backend vc-handled-backends) + (ignore-error vc-not-supported + (when-let ((res (vc-call-backend + backend 'clone + remote directory rev))) + (throw 'ok res)))))))) + (when (file-directory-p directory) + (when open-dir + (find-file directory)) + directory))) (declare-function log-view-current-tag "log-view" (&optional pos)) (defun vc-default-last-change (_backend file line) -- 2.46.0 --=-=-= Content-Type: text/plain -- Best regards, Aleksandr Vityazev --=-=-=--