Terminal: hyper link mode: handle relative paths better
* We were trying relative paths as is, which means checking them with Terminal's current working directory. Now we use the CWD of the active process. * In case the path is relative, add a context menu item "Copy absolute path".
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
#include <UTF8.h>
|
#include <UTF8.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
|
#include "ActiveProcessInfo.h"
|
||||||
#include "Shell.h"
|
#include "Shell.h"
|
||||||
#include "TermConst.h"
|
#include "TermConst.h"
|
||||||
#include "TerminalBuffer.h"
|
#include "TerminalBuffer.h"
|
||||||
@@ -52,6 +53,7 @@ static const uint32 kAutoScroll = 'AScr';
|
|||||||
|
|
||||||
static const uint32 kMessageOpenLink = 'OLnk';
|
static const uint32 kMessageOpenLink = 'OLnk';
|
||||||
static const uint32 kMessageCopyLink = 'CLnk';
|
static const uint32 kMessageCopyLink = 'CLnk';
|
||||||
|
static const uint32 kMessageCopyAbsolutePath = 'CAbs';
|
||||||
static const uint32 kMessageMenuClosed = 'MClo';
|
static const uint32 kMessageMenuClosed = 'MClo';
|
||||||
|
|
||||||
|
|
||||||
@@ -638,6 +640,7 @@ TermView::HyperLinkState::HyperLinkState(TermView* view)
|
|||||||
fURLCharClassifier(kURLAdditionalWordCharacters),
|
fURLCharClassifier(kURLAdditionalWordCharacters),
|
||||||
fPathComponentCharClassifier(
|
fPathComponentCharClassifier(
|
||||||
BString(kDefaultAdditionalWordCharacters).RemoveFirst("/")),
|
BString(kDefaultAdditionalWordCharacters).RemoveFirst("/")),
|
||||||
|
fCurrentDirectory(),
|
||||||
fHighlight(),
|
fHighlight(),
|
||||||
fHighlightActive(false)
|
fHighlightActive(false)
|
||||||
{
|
{
|
||||||
@@ -648,6 +651,12 @@ TermView::HyperLinkState::HyperLinkState(TermView* view)
|
|||||||
void
|
void
|
||||||
TermView::HyperLinkState::Entered()
|
TermView::HyperLinkState::Entered()
|
||||||
{
|
{
|
||||||
|
ActiveProcessInfo activeProcessInfo;
|
||||||
|
if (fView->GetActiveProcessInfo(activeProcessInfo))
|
||||||
|
fCurrentDirectory = activeProcessInfo.CurrentDirectory();
|
||||||
|
else
|
||||||
|
fCurrentDirectory.Truncate(0);
|
||||||
|
|
||||||
_UpdateHighlight();
|
_UpdateHighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -792,9 +801,9 @@ TermView::HyperLinkState::_GetHyperLinkAt(BPoint where, bool pathPrefixOnly,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// check, whether the file exists
|
// check, whether the file exists
|
||||||
struct stat st;
|
BString actualPath;
|
||||||
if (lstat(text, &st) == 0) {
|
if (_EntryExists(text, actualPath)) {
|
||||||
_link = HyperLink(text, HyperLink::TYPE_PATH);
|
_link = HyperLink(text, actualPath, HyperLink::TYPE_PATH);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,8 +822,8 @@ TermView::HyperLinkState::_GetHyperLinkAt(BPoint where, bool pathPrefixOnly,
|
|||||||
if (!textBuffer->PreviousLinePos(_end))
|
if (!textBuffer->PreviousLinePos(_end))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (lstat(text, &st) == 0) {
|
if (_EntryExists(text, actualPath)) {
|
||||||
_link = HyperLink(text, HyperLink::TYPE_PATH);
|
_link = HyperLink(text, actualPath, HyperLink::TYPE_PATH);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -832,8 +841,10 @@ TermView::HyperLinkState::_GetHyperLinkAt(BPoint where, bool pathPrefixOnly,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
path.Truncate(colonIndex);
|
path.Truncate(colonIndex);
|
||||||
if (lstat(path, &st) == 0) {
|
if (_EntryExists(path, actualPath)) {
|
||||||
_link = HyperLink(text,
|
BString address = path == actualPath
|
||||||
|
? text : BString(fCurrentDirectory) << '/' << text;
|
||||||
|
_link = HyperLink(text, address,
|
||||||
i == 0
|
i == 0
|
||||||
? HyperLink::TYPE_PATH_WITH_LINE
|
? HyperLink::TYPE_PATH_WITH_LINE
|
||||||
: HyperLink::TYPE_PATH_WITH_LINE_AND_COLUMN);
|
: HyperLink::TYPE_PATH_WITH_LINE_AND_COLUMN);
|
||||||
@@ -845,6 +856,25 @@ TermView::HyperLinkState::_GetHyperLinkAt(BPoint where, bool pathPrefixOnly,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
TermView::HyperLinkState::_EntryExists(const BString& path,
|
||||||
|
BString& _actualPath) const
|
||||||
|
{
|
||||||
|
if (path.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (path[0] == '/' || fCurrentDirectory.IsEmpty()) {
|
||||||
|
_actualPath = path;
|
||||||
|
} else {
|
||||||
|
_actualPath.Truncate(0);
|
||||||
|
_actualPath << fCurrentDirectory << '/' << path;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
return lstat(_actualPath, &st) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TermView::HyperLinkState::_UpdateHighlight()
|
TermView::HyperLinkState::_UpdateHighlight()
|
||||||
{
|
{
|
||||||
@@ -947,9 +977,12 @@ TermView::HyperLinkMenuState::Prepare(BPoint point, const HyperLink& link)
|
|||||||
case HyperLink::TYPE_PATH:
|
case HyperLink::TYPE_PATH:
|
||||||
case HyperLink::TYPE_PATH_WITH_LINE:
|
case HyperLink::TYPE_PATH_WITH_LINE:
|
||||||
case HyperLink::TYPE_PATH_WITH_LINE_AND_COLUMN:
|
case HyperLink::TYPE_PATH_WITH_LINE_AND_COLUMN:
|
||||||
menuBuilder
|
menuBuilder.AddItem(B_TRANSLATE("Open path"), kMessageOpenLink);
|
||||||
.AddItem(B_TRANSLATE("Open path"), kMessageOpenLink)
|
menuBuilder.AddItem(B_TRANSLATE("Copy path"), kMessageCopyLink);
|
||||||
.AddItem(B_TRANSLATE("Copy path"), kMessageCopyLink);
|
if (fLink.Text() != fLink.Address()) {
|
||||||
|
menuBuilder.AddItem(B_TRANSLATE("Copy absolute path"),
|
||||||
|
kMessageCopyAbsolutePath);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
menu->SetTargetForItems(fView);
|
menu->SetTargetForItems(fView);
|
||||||
@@ -974,22 +1007,27 @@ TermView::HyperLinkMenuState::MessageReceived(BMessage* message)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case kMessageCopyLink:
|
case kMessageCopyLink:
|
||||||
|
case kMessageCopyAbsolutePath:
|
||||||
|
{
|
||||||
if (fLink.IsValid()) {
|
if (fLink.IsValid()) {
|
||||||
|
BString toCopy = message->what == kMessageCopyLink
|
||||||
|
? fLink.Text() : fLink.Address();
|
||||||
|
|
||||||
if (!be_clipboard->Lock())
|
if (!be_clipboard->Lock())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
be_clipboard->Clear();
|
be_clipboard->Clear();
|
||||||
|
|
||||||
if (BMessage *data = be_clipboard->Data()) {
|
if (BMessage *data = be_clipboard->Data()) {
|
||||||
data->AddData("text/plain", B_MIME_TYPE,
|
data->AddData("text/plain", B_MIME_TYPE, toCopy.String(),
|
||||||
fLink.Address().String(),
|
toCopy.Length());
|
||||||
fLink.Address().Length());
|
|
||||||
be_clipboard->Commit();
|
be_clipboard->Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
be_clipboard->Unlock();
|
be_clipboard->Unlock();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
case kMessageMenuClosed:
|
case kMessageMenuClosed:
|
||||||
fView->_NextState(fView->fDefaultState);
|
fView->_NextState(fView->fDefaultState);
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ private:
|
|||||||
bool _GetHyperLinkAt(BPoint where,
|
bool _GetHyperLinkAt(BPoint where,
|
||||||
bool pathPrefixOnly, HyperLink& _link,
|
bool pathPrefixOnly, HyperLink& _link,
|
||||||
TermPos& _start, TermPos& _end);
|
TermPos& _start, TermPos& _end);
|
||||||
|
bool _EntryExists(const BString& path,
|
||||||
|
BString& _actualPath) const;
|
||||||
|
|
||||||
void _UpdateHighlight();
|
void _UpdateHighlight();
|
||||||
void _UpdateHighlight(BPoint where, int32 modifiers);
|
void _UpdateHighlight(BPoint where, int32 modifiers);
|
||||||
@@ -142,6 +144,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
DefaultCharClassifier fURLCharClassifier;
|
DefaultCharClassifier fURLCharClassifier;
|
||||||
DefaultCharClassifier fPathComponentCharClassifier;
|
DefaultCharClassifier fPathComponentCharClassifier;
|
||||||
|
BString fCurrentDirectory;
|
||||||
TermViewHighlight fHighlight;
|
TermViewHighlight fHighlight;
|
||||||
bool fHighlightActive;
|
bool fHighlightActive;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user