Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for svn status in prompt #2582

Closed
wants to merge 5 commits into from

Conversation

samdmarshall
Copy link
Contributor

This is to add support for displaying the output of svn status in a prompt similar to the way git and hg status get displayed. I tried to match the styling and conventions as best as I could, please let me know if there is any glaring issues with it.

Note: I wrote this against fish 2.2.0, so it doesn't take advantage of any of the new string manipulation features as there hasn't been published release that includes support for that yet. I would be happy to update this once a new release is made.

# ==============================

# SVN status symbols
# Do not change these! These are the expected characters that are output from `svn status`, they are taken from `svn help status`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these aren't supposed to be changed, why are they variables?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed like this was the most efficient way to access them for parsing, I don't like they are global defines but there didn't seem to be a more efficient way of doing this when the helper function they get used in will be called many times.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about either adding them as local variables to the function they are used in or doing a switch/case there? Or make a list of these characters, another of the names and then map them via index:

set __fish_svn_status_chars A C D I M N R # ...
set __fish_svn_statuses added conflicted deleted ignored modified replaced # ...
echo $__fish_svn_prompt_char_{$__fish_svn_statuses(contains -i -- $status $__fish_svn_status_chars)}

(untested, the parser might barf on that)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think setting them as local variables is going to take that much time. In my experience most fishscript is taking the most time in calls to external tools (the hg_prompt was particularly bad about that, to the point that we've added custom code to find the .hg directory). Even though svn seems reasonably quick, it's still a few forks.

My gut tells me that optimization here is achieved by replacing grep or math (which forks to bc), not via defining variables.

If you wish to measure, fish has a nice "-p" option to output profiling data (though do keep in mind that even non-interactive fish will still read all config files).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this gets called 7x in a pretty tight loop i was worried that a local variable setup/teardown would cause a bit of unwanted overhead to an already expensive function call. If you think that is fine, I can make that change but I am concerned about the performance of doing this.

Edit: Ok then I'll give that a try and update the PR.

@faho
Copy link
Member

faho commented Dec 9, 2015

The sed and grep calls could be replaced with string (not in a release yet, unfortunately).

# 2. swap the ":" back to newline characters so we can perform a column based `cut`
# 3. cut out the current column of characters
# 4. remove spaces and newline characters
set -l column_status (echo $svn_status_lines | tr ':' '\n' | cut -c $col | tr -d ' \n')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use printf "%s\n" $svn_status_lines and you can nix replacing the newlines.

What happens is that fish will split command substitutions on newlines, making every line one argument, which then leads to svn_status_lines becoming a list with each line as one element. When you then hand it to echo, it'll read the arguments and echo them out separated by spaces. printf won't do that, instead using the format string once per argument.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. OK i will look at changing that. I remember reading there was some funky-ness with handling multi-line strings in a variable in fish shell (and experiencing some of that myself). And came to this code as it "worked". Thanks!

@faho faho self-assigned this Dec 9, 2015
@faho
Copy link
Member

faho commented Dec 9, 2015

I'll have to test this now. Any nice svn repo to try?

@samdmarshall
Copy link
Contributor Author

Heh, the only public one that comes to mind is the llvm repos. This seems most work out of the svn repos I use at work.

end

# get the current revision number
set -l repo_revision_number (command svn info | grep "Last Changed Rev: " | sed "s=Last Changed Rev: ==")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hurray for localization - this won't work if your language isn't english. A simple workaround is of course to set -lx LC_ALL C set -lx LANGUAGE en (it seems svn will read that, ignoring existing conventions) here, though I'd rather have a less hackish solution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would svnversion work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did notice there seems to be a function in fish shell for fetching the revision number of a repo but I didn't use it because it also spits out some other strings and I wasn't sure if it was half-implemented or not.

As for the grep strings, I was basing this off the source of the svn command printing out what appear to be english strings.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did notice there seems to be a function in fish shell for fetching the revision number

__fish_print_svn_rev? That has the same issue as it does basically the same thing.

As for the grep strings, I was basing this off the source of the svn command printing out what appear to be english strings.

They are english strings if your locale is english. Mine is german, so it'll print german strings (e.g. "Letzte geänderte Rev").

I'm trying to find a portable way to get svn information (i.e. the svn counterpart to git rev-parse or hg status), but I'm not coming up with much. svnversion might fit the bill, but I'm not sure if it prints everything you want here, svnlook is another, but it works only with repositories, not working copies.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will look at using svnversion here and see if it satisfied the needs. Maybe the function should be refactored to use svnversion then I should call that instead of implementing it twice.

it looks like this might work for using svnversion:

svnversion | sed -e 's=[^0-9:]*==g' -e 's=^.*:==' but i'd have to test it out a bit first.

Edit: Now realizing that the second -e in the sed might not be necessary and be removing desired data to display to the user. I'm ok with removing that second sed expression, if you think that would be locale agnostic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with removing that second sed expression, if you think that would be locale agnostic.

I'm not sure why it wouldn't be - svnversion for me outputs "255122M", though that's on a fresh checkout of llvm (I don't use svn). It doesn't seem to distinguish between "object modified" and "object missing" (ie. deleted) like svnstatus does, though, and that's localized as well.

If you'd like to use string, it'd look like svnversion | string replace -r '([0-9]*).*' '$1'.

Edit: Another way to get the revision seems to be svn info --show-item last-changed-revision, which seems to purely output the number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to use string however since I don't use a development build of fish shell i wanted to avoid maintaining this twice until a formal release is made.

As for the localized status of svn status the code I looked at from the build of svn apple ships has hardcoded text strings in english for the bits of the output i am attempting to remove. I recognize that isn't sufficient for the numerous platforms that fish shell supports -- I don't know how to approach the problem to tackle this in a more agnostic manner.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for the localized status of svn status the code I looked at from the build of svn apple ships has hardcoded text strings in english for the bits of the output i am attempting to remove.

I haven't actually gotten any localized output from svn status - maybe that's not a thing anymore? (It looks like "! CODE_OWNERS.TXT" because I've removed that file to test)

I'm not quite sure how to cause a conflict to happen which might trigger some actual language.

Did you see the suggestion about svn info --show-item last-changed-revision? (There's also the option of getting xml output, but parsing that in shell is not an enviable task)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did see the suggestion, however that doesn't work for my version of svn, (doesn't recognize the --show-item flag). I think I'm going to go with the svnversion | sed -e 's=[^0-9:]*==g' command and try to get this PR updated today to reflect the changes we have discussed.

@faho faho mentioned this pull request Dec 9, 2015
…or changes to _fish_svn_prompt to optimize execution
@samdmarshall
Copy link
Contributor Author

OK I've updated with changes we discussed, how does it look now?

@samdmarshall
Copy link
Contributor Author

Sorry about that, when i tried it out again I think i forgot to add the \n into the printf formatter not realizing that would make a significant difference in output handling. That should be fixed now.

@faho
Copy link
Member

faho commented Dec 10, 2015

The svn status thing is still not perfect, but given that I haven't been able to trigger it and that I don't know of any better way to do it, it's probably okay.

I'll test the new version a bit more and if it passes I'll merge.

@samdmarshall
Copy link
Contributor Author

OK, once a release of fish shell is made with the new string stuff I'll submit another PR converting the code over to using that where it can. That might give a bit more control around the filtering the additional lines out of svn status, I couldn't work out a simple way of doing it without introducing a lot of overhead with a set of awk commands or similar.

@faho
Copy link
Member

faho commented Dec 10, 2015

That last commit changed the time from 255357 to 258585 (fish -p profile -c "__fish_svn_prompt")- in other words barely, if at all, measurable.

I've managed to get a 20% improvement, though, by removing the `math´ call.


# the default separator is empty
set -l prompt_separator ""
for index in (seq (math "$col - $last_column"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're not using $index inside the loop, you can just do seq $last_column $col. Or am I missing anything?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like it iterates an extra time when doing seq $last_column $col vs seq (math "$col - $last_column")

@faho
Copy link
Member

faho commented Dec 10, 2015

I've merged this now since it's nice code that works and the time is dominated by the svn calls (I can't seem to replicate the math thing anymore). I've squashed it to f5dfebb.

Thanks for the nice work and quick response!

@faho faho closed this Dec 10, 2015
@samdmarshall samdmarshall deleted the sdm-svn-prompt branch December 10, 2015 17:21
@faho faho added the release notes Something that is or should be mentioned in the release notes label Dec 11, 2015
@faho faho added this to the next-2.x milestone Dec 11, 2015
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
release notes Something that is or should be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants