abo-abo / swiper

Ivy - a generic completion frontend for Emacs, Swiper - isearch with an overview, and more. Oh, man!
https://oremacs.com/swiper/
2.31k stars 338 forks source link

Get relative file paths #1103

Open it6 opened 7 years ago

it6 commented 7 years ago

Is there a way to get relative file path based on current file you are in?

basil-conto commented 7 years ago

Can you please elaborate on what you mean by "get" and what you intend to do with this path? Both find-file (and counsel-find-file, by extension) begin filename completion in the current default-directory, for example, so anything you enter is completed relative to the same parent directory as the currently visited file until a different directory is specified.

it6 commented 7 years ago

Say I am in fileA in the following project structure, I want to import fileB into fileA using relative path

|---- src/
       |-----folder1/
                  |------fileA
       |------folder2/
                  |------folder3/
                             |-----fileB

I need to copy path as ../folder2/folder3/fileB

abo-abo commented 7 years ago

Press DEL to go one level up.

it6 commented 7 years ago

I need to copy relative file path of fileB (../folder2/folder3/fileB) into fileA

jeberger commented 7 years ago

There is a file-relative-name function in emacs, so you can probably do it with (file-relative-name fileB (file-name-directory fileA))

it6 commented 6 years ago

I found this snippet really helpful, it is integrated with ivy.

;;----------------------------------------------------------------------------
;; insert relative/full path between two files
;;----------------------------------------------------------------------------
(defun bjm/insert-file-name (filename &optional args)
  "Insert name of file FILENAME into buffer after point, takes ARGS.

  Prefixed with \\[universal-argument], expand the file name to
  its fully canocalized path.  See `expand-file-name'.

  Prefixed with \\[negative-argument], use relative path to file
  name from current directory, `default-directory'.  See
  `file-relative-name'.

  The default with no prefix is to insert the file name exactly as
  it appears in the minibuffer prompt."
  ;; Based on insert-file in Emacs -- ashawley 20080926
  (interactive "*fInsert file name: \nP")
  (cond ((eq '- args)
         (insert (expand-file-name filename)))
        ((not (null args))
         (insert filename))
        (t
         (insert (file-relative-name filename)))))

(global-set-key (kbd "C-c i p") 'bjm/insert-file-name)

Is there any way to extend this so I can open counsel-git prompt instead ?

abo-abo commented 6 years ago

Is there any way to extend this so I can open counsel-git prompt instead ?

Can you elaborate? You open counsel-find-file, then press C-c i p to call counsel-git? Why?

it6 commented 6 years ago

The current snippet above lets me insert relative file path using counsel-find-file

for example import-counsel-find-file

Instead of opening counsel-find-file and navigating directories, I would like to open prompt with counsel-git and start typing any file name in my git project.

Also anything like this already exists in counsel?

Again the whole idea is not to open a file, but to insert a relative path to any file in the project.

Dickby commented 6 years ago

why would you want to do that? With. projectile for example you just have to enter the file name. And you allready can just type the "relative directory" in counsel-find-file like ../bin/ Maybe i misunderstood the problem!?

basil-conto commented 6 years ago

Also anything like this already exists in counsel?

No, but the usual mechanism/approach is to use custom actions, e.g.

(ivy-add-actions
 #'counsel-git
 '(("I" my-insert-relative "insert relative")))

Where my-insert-relative is a custom function which takes a completion candidate and acts on it as you desire.

The problem with counsel-git is that it let-binds default-directory around the entire ivy-read call, so there is currently no reliable way to determine the default-directory of the buffer from which counsel-git was called, which is needed to calculate a relative file path. This is, I think, a separate bug in its own right.