Defining scope for custom Sublime Text 2 snippets - scope

While trying to write my own snippets for Sublime Text 2, I ran into the following two problems:
Finding scope keys. I figured out that I can look through my packages one by one and find references to a declared "scope" property. For example in ~/Library/Application Support/Sublime Text 2/Packages/JavaScript/Comments.tmPreferences (a file in my HTML package) there's these two lines:
<key>scope</key>
<string>source.js</string>
So if I want my current snippet to work on javascript files, I define my scope like:
<scope>source.js</scope>
I'm assuming all these scope keys are defined on-the-fly based on what Packages I have installed. Does Sublime Text build a list anywhere that I can more easily reference? Perusing through a bunch of package files seems overly tedious.
Defining multiple scope properties. This I've figured out, and the following line allows my snippet to work in both HTML and JavaScript files.
<scope>text.html, source.js</scope>

Here is a list of scopes to use in Sublime Text 2 snippets -
ActionScript: source.actionscript.2
AppleScript: source.applescript
ASP: source.asp
Batch FIle: source.dosbatch
C#: source.cs
C++: source.c++
Clojure: source.clojure
CoffeeScript: source.coffee
CSS: source.css
D: source.d
Diff: source.diff
Erlang: source.erlang
Go: source.go
GraphViz: source.dot
Groovy: source.groovy
Haskell: source.haskell
HTML: text.html(.basic)
JSP: text.html.jsp
Java: source.java
Java Properties: source.java-props
Java Doc: text.html.javadoc
JSON: source.json
Javascript: source.js
BibTex: source.bibtex
Latex Log: text.log.latex
Latex Memoir: text.tex.latex.memoir
Latex: text.tex.latex
LESS: source.css.less
TeX: text.tex
Lisp: source.lisp
Lua: source.lua
MakeFile: source.makefile
Markdown: text.html.markdown
Multi Markdown: text.html.markdown.multimarkdown
Matlab: source.matlab
Objective-C: source.objc
Objective-C++: source.objc++
OCaml campl4: source.camlp4.ocaml
OCaml: source.ocaml
OCamllex: source.ocamllex
Perl: source.perl
PHP: source.php
Regular Expression(python): source.regexp.python
Python: source.python
R Console: source.r-console
R: source.r
Ruby on Rails: source.ruby.rails
Ruby HAML: text.haml
SQL(Ruby): source.sql.ruby
Regular Expression: source.regexp
RestructuredText: text.restructuredtext
Ruby: source.ruby
SASS: source.sass
Scala: source.scala
Shell Script: source.shell
SQL: source.sql
Stylus: source.stylus
TCL: source.tcl
HTML(TCL): text.html.tcl
Plain text: text.plain
Textile: text.html.textile
XML: text.xml
XSL: text.xml.xsl
YAML: source.yaml
If anything is missing, add it in this gist https://gist.github.com/4705378.

View Current Scope of Cursor Position
Place your cursor in the file where you wish to know the scope.
Use this keyboard-shortcut:
Windows: ctrl+shift+alt+p
Mac: ctrl+shift+p
The current scope will be displayed in the left side of the status bar on Windows, or in a popup window on Mac.
Use these as the <scope> key in your foo.sublime-snippet file.
The returned scopes are listed generic to specific. Choose the scope(s) which best "scoped" the snippet to where it should be available to tab trigger.

There's a package called Scope Hunter, by Isaac Muse, which is really helpful for this.
It can show you the scope under any cursor in a document, which I've found really helpful when debugging my own snippets. Sometimes it's very detailed; a sample scope from my frontmost document:
Scope: text.tex.latex
meta.function.environment.list.latex
meta.function.environment.general.latex
meta.function.environment.math.latex
string.other.math.block.environment.latex
meta.group.braces.tex
meta.space-after-command.latex
(Wrapped for ease of reading)
I wouldn't have been able to find that if I spent a week picking SL2 apart, but this package gets it in seconds. Highly recommended.
This level of detail also means that you can define snippets in a very granular way, if you want. For example, the meta.function.environment.list.latex corresponds broadly to lists in LaTeX, so I have a snippet that inserts a new \item when I press super+enter in a list environment, but nobody else. I can target snippets much more effectively than with blind guesswork.
The source code is in Github, or you can install it through Package Control.

Actually, you can use the Ctrl+Alt+Shift+P (without using Scope Hunter) and it will show you the scope on the bottom bar on the left side right after the Col/Line information. It's pretty small print but it's there.

To answer, #1, look in the syntax's .tmLanguage file, look for the key: scopeName. This is what the syntax uses for the snippet's scope value.
For example, an excerpt from nathos / sass-textmate-bundle
<key>scopeName</key>
<string>source.sass</string>
So you would use source.sass in your snippet.
Here is more info on defining a syntax

Related

pgfopts: arguments with spaces don't play well with babel

If I define a new package like this
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myPlanning}[2022/07/16 my Planning class]
\LoadClass[french]{article}
\RequirePackage{pgfopts}
\pgfkeys{
/myOrg/.cd,
lang/.initial = english , lang/.store in = \myOrg#lang,
title/.initial = title , title/.store in = \myOrg#title,
}
\ProcessPgfOptions{/myOrg}
\RequirePackage[\myOrg#lang]{babel}
and I try to compile this document
\documentclass[lang=french,title={truc bidul}]{myPlanning}
\begin{document}
some text here
\end{document}
I get the following error:
This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex)
restricted \write18 enabled.
entering extended mode
(./Test.tex
LaTeX2e <2021-11-15> patch level 1
L3 programming layer <2022-01-21>
(/home/hylkema/texmf/tex/latex/local/Org/myPlanning.cls
Document Class: myPlanning 2022/07/16 my Planning class
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/pgfopts/pgfopts.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.t
ex))))) (/usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty
(/usr/share/texlive/texmf-dist/tex/generic/babel/txtbabel.def)
(/usr/share/texlive/texmf-dist/tex/generic/babel-french/french.ldf)
! LaTeX Error: Missing \begin{document}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.4261 \ifin#\edef\bbl#tempc{\bbl#tempb}\fi}
?
However, if I compile this (No spaces in the title argument):
\documentclass[lang=french,title=truc]{myPlanning}
\begin{document}
some text here
\end{document}
It compiles fine with no errors.
What's more, the first document with spaces in the title argument compiles fine if I remove the \RequirePackage[\myOrg#lang]{babel} line from the package definition.
Is this a known problem and is there a solution ?
Thanks for your help,
Jouke
Update: The underlying issue was fixed in upstream babel on 2022-11-24 and should be resolved in the next release.
The issue is not the key=value parser but a code block of babel that tries to detect whether the wrong language is loaded if it got both options from the \documentclass and options when the package was called. That being said, pgfopts isn't up-to-date with current LaTeX (there were substantial changes to the option-system about a year ago that pgfopts has not yet followed suit), the only solutions to key=value options that are compatible to my knowledge are the builtin mechanism and expkv-opt.
But as I said, neither will solve your issue. Using main=\myOrg#lang in the options of babel however will, as if you used the main-option the problematic code of babel will not be used. So if you change your class to the following the only (admittedly strange) warning regarding your options you'll get will be
LaTeX Warning: Unused global option(s):
[french].
(but that stems from your strange usage of \LoadClass, in which article will add french to the unused options list though it isn't in the global options list, hence babel will not pick it up and remove it from said list).
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myPlanning}[2022/07/16 my Planning class]
\LoadClassWithOptions{article}
\RequirePackage{pgfopts}
\pgfkeys{
/myOrg/.cd
,lang/.initial = english
,lang/.store in = \myOrg#lang
,title/.initial = title
,title/.store in = \myOrg#title,
}
\ProcessPgfOptions{/myOrg}
\RequirePackage[main=\myOrg#lang]{babel}

Vim error E745 'Using a List as a Number' when creating `Latex` snippet in `neosnippet`

I am using neosnippet to create a snippet for a latex template. The snippet is rather long, and I keep getting a strange error E745 Using a List as a Number when I try to expand the snippet.
Here is the error message that neovim is putting out.
[dein] Error occurred while executing hook: neosnippet.vim
[dein] Vim(let):E745: Using a List as a Number
Error detected while processing function <SNR>346 snippets_expand ...
Line 11
E15: invalid expression:
E15: invalid expression
The actual snippet itself is below--it is quite long. Now when I take this long snippet out of the snippet file, all other snippets work fine. So it seems somewhere I am using a character I am not supposed to use or something. Or perhaps something is not properly escaped, etc.
All of my other latex snippets work just fine, but there are also much shorter. Does anyone have any ideas about why this snippet is causing so much trouble?
Here is the latex snippet.
\documentclass{book}
\addtolength{\topmargin}{-.5in}
\addtolength{\headsep}{.5in}
\oddsidemargin=.5in
\evensidemargin=.5in
\textwidth=5.5in
\usepackage{
amsmath,% AMS basic math stuff
amsthm,% AMS theorem defining stuff
amsfonts,% defines the blackboard bold fonts for \Z, \R, etc
longtable,% used to create the tcproof environment below
verbatim,% allows for verbatim output, and also covering up stuff in comments
xspace,% adds an extra space an the end of some commands
multicol,% allows multicolumn output
tikz,% creates the tikzpicture drawing environment
charter,% changes the default font to charter
framed,% used to color in the TIscreen environment below
bm,
mathrsfs}
\usepackage{pifont}
\usepackage[colorlinks,unicode]{hyperref}
\newcommand{\R}{\mathbb{R}}
\newcommand{\Q}{\mathbb{Q}}
\newcommand{\Z}{\mathbb{Z}}
\newcommand{\N}{\mathbb{N}}
\newcommand{\Tau}{\bm{\mathcal{T}}}
\newcommand{\Taup}{\bm{\mathcal{T}^{\prime}}}
\newcommand{\Bp}{\mathscr{B}^{\prime}}
\newcommand{\B}{\mathscr{B}}
\newcommand{\CCp}{\mathscr{C}^{\prime}}
\newcommand{\CC}{\mathscr{C}}
\newcommand{\Ltop}{\R_{\mathscr{L}}}
\newcommand{\Ktop}{\R_{\mathscr{K}}}
\DeclareMathOperator{\lcm}{lcm}
\newcommand{\cl}[1]{[#1]}
\newcommand{\st}{\mid}
\newcommand{\eq}{\stackrel{?}{=}}
\newcommand{\divq}{\stackrel{?}{|}}
\newcommand{\forwards}{\mbox{``$\Longrightarrow$''}\xspace}
\newcommand{\backwards}{\mbox{``$\Longleftarrow$''}\xspace}
\newcommand{\define}[1]{\textbf{#1}}
\newcommand{\threeven}{pretty\xspace}
\newcommand{\throd}{normal\xspace}
\newcommand{\throve}{ugly\xspace}
\DeclareMathSymbol{\nmid}{\mathrel}{AMSb}{"2D}
\newcommand{\notdiv}{\nmid}
\renewcommand{\tilde}{\widetilde}
\renewcommand{\thefootnote}{\fnsymbol{footnote}}
\def\endclass#1{\par\noindent\hrulefill\fbox{\tiny This is where we
ended on #1}\hrulefill\vskip 5pt plus 1pt\par }
\pagestyle{headings}
\makeatletter
\edef\today{%
\the\year/\two#digits{\the\month}/\two#digits{\the\day}}
\renewcommand{\#evenhead}{\emph{Ordinary Differential Equations - Arnold}
(v. \today)
\hfill Krishna Bhogaonker \hfill \thepage}
\renewcommand{\#oddhead}{(version \today) \hfill \thepage}
\makeatother
\DeclareMathSymbol{\varnothing}{\mathord}{AMSb}{"3F}
\renewcommand{\emptyset}{\varnothing}
\colorlet{shadecolor}{gray!35}
\newenvironment{TIscreen}
{\begin{center}\tt
\renewcommand{\in}[1]{##1\\}
\newcommand{\out}[1]{\mbox{}\hfill##1\\}
\begin{minipage}{2in}\begin{snugshade}}
{\end{snugshade}\end{minipage}\end{center}}
\newenvironment{tcproof}[1]
{\smallskip\par\begin{longtable}{#{}p{.45\textwidth}p{.45\textwidth}#{}}
\multicolumn{2}{#{}l}{\emph{#1}}\\[\smallskipamount]
Assertion & Justification \endfirsthead
Assertion & Justification \endhead
\hline }
{\end{longtable}\qed\smallskip\par}
\newtheorem{lemma}{Lemma}[section]
\newtheorem{theorem}[lemma]{Theorem}
\newtheorem{cor}[lemma]{Corollary}
\newtheorem*{scholium}{Scholium}
\theoremstyle{definition}
\newtheorem{definition}[lemma]{Definition}
\newtheorem{example}[lemma]{Example}
\newenvironment{comments}{}{}
\makeatletter
\define#key{hide}{scholium}[true]{\renewenvironment{scholium}{\comment}{\endcomment}}
\define#key{hide}{proof}[true]{\renewenvironment{proof}{\comment}{\endcomment}}
\define#key{hide}{lemma}[true]{\renewenvironment{lemma}{\comment}{\endcomment}}
\define#key{hide}{comments}[true]{\renewenvironment{comments}{\comment}{\endcomment}}
\define#key{hide}{cor}[true]{\renewenvironment{cor}{\comment}{\endcomment}}
\define#key{hide}{definition}[true]{\renewenvironment{definition}{\comment}{\endcomment}}
\define#key{hide}{example}[true]{\renewenvironment{example}{\comment}{\endcomment}}
\define#key{hide}{theorem}[true]{\renewenvironment{theorem}{\comment}{\endcomment}}
\newcommand{\HideEnvirons}[1]{\setkeys{hide}{#1}}
\define#key{show}{scholium}[true]{\define#key{hide}{scholium}{}}
\define#key{show}{proof}[true]{\define#key{hide}{proof}{}}
\define#key{show}{lemma}[true]{\define#key{hide}{lemma}{}}
\define#key{show}{comments}[true]{\define#key{hide}{comments}{}}
\define#key{show}{cor}[true]{\define#key{hide}{cor}{}}
\define#key{show}{definition}[true]{\define#key{hide}{definition}{}}
\define#key{show}{example}[true]{\define#key{hide}{example}{}}
\define#key{show}{theorem}[true]{\define#key{hide}{theorem}{}}
\newcommand{\ShowEnvirons}[1]
{\setkeys{show}{#1}\HideEnvirons{%
comments,
cor,
definition,
example,
proof,
theorem,
lemma,
scholium
}}
\makeatother
\begin{document}
\tableofcontents
\newpage
\chapter{Basic Concepts}
${0}
\end{document}
Okay, I talked to the developer and he indicated the problem had to do with the backquotes in this section of the document.
\newcommand{\forwards}{\mbox{````$\Longrightarrow$''}\xspace}
\newcommand{\backwards}{\mbox{````$\Longleftarrow$''}\xspace}
I updated the neosnippet plugin and also changed the latex code as well. Now things work fine.

Checking values with Cucumber and Watir

I've been trying to get started with Cucumber and Watir. I've done the installation and written/copied a simple 'feature'. However, I'm not getting anywhere with checking what's on a page.
This my feature:
Feature: Search Google
In order to make sure people can find my documentation
I want to check it is listed on the first page in Google
Scenario: Searching for JS.Class docs
Given I have opened "http://www.google.com/"
When I search for "JS.Class"
Then I should see a link to "http://jsclass.jcoglan.com/" with text "JS.Class v3.0"
My env.rb file looks like this
require 'watir'
require 'rspec'
And this is my search_steps.rb
#ie
Given /^I have opened "([^\"]*)"$/ do |url|
#ie = Watir::IE.new
#ie.goto(url)
end
When /^I search for "([^\"]*)"$/ do |arg1|
#ie.text_field(:name, "q").set(arg1)
#ie.button(:name, "btnG").click
end
Then /^I should see a link to "([^\"]*)" with text "([^\"]*)"$/ do |arg1, text|
puts arg1
# #ie.text.should include(arg1)
#ie.close
end
When I uncomment the line '#ie.text.should include(arg1)' I get this error thrown.
Then I should see a link to "http://jsclass.jcoglan.com/" with text "JS.Class v3.0" # features/step_definitions/search_steps.rb:13
true
undefined method `split' for ["http://jsclass.jcoglan.com/"]:Array (NoMethodError)
./features/step_definitions/search_steps.rb:17:in `/^I should see a link to "([^\"]*)" with text "([^\"]*)"$/'
features\search.feature:8:in `Then I should see a link to "http://jsclass.jcoglan.com/" with text "JS.Class v3.0"'
Failing Scenarios:
cucumber features\search.feature:5 # Scenario: Searching for JS.Class docs
Right now the Then function isn't doing its job. If I comment out the line then all it's really doing is writing out some text.
The gems I have include the following cucumber <1.1.9>, rspec <2.9.0>, watir<2.0.4> and watir-webdriver <0.5.3>
The version of ruby I have is: ruby 1.9.3p125.
I'm running this on Windows 7 Ultimate.
I'm wondering if I'm missing a gem or something. Reading the message implies that I'm calling a method it can't find but I've found quite a few pages on the web that use this method.
Any help, guidance or pointers in the right direction are gratefully welcomed.
The problem is that if you (manually) look at the text of the Google search results, you will noticed that there is no text "http://jsclass.jcoglan.com/". So, as expected, the test will fail.
To fix this, you can correct the call to the step by removing the 'http://':
Then I should see a link to "jsclass.jcoglan.com/" with text "JS.Class v3.0"
That said, it would be more robust if you actually make check for the link using the following code. Checking that the text is somewhere on the page can lead to false positives (see the latest post on WatirMelon)
#ie.link(:url => arg1, :text => text).exists?.should be true

How to concatenate SVG files lengthwise from linux command line?

I have a series of square SVG files that I would like to arrange lengthwise into one super long SVG file.
I attempted to use imagemagick to combine them. Based on this page:
http://linux.about.com/library/cmd/blcmdl1_ImageMagick.htm
and this
http://www.imagemagick.org/Usage/compose/
I tried this command
composite 'file1.svg' 'file2.svg' +adjoin 'outputfile.svg'
However, I received the following error message:
composite: unrecognized option '+adjoin' # error/composite.c/CompositeImageCommand/565.
I tried several other imagemagick commands (convert, display), but had no success. How can I combine these files on the command line? Is there an inkscape command that does this?
There's currently no convenient way to do this with only the command line and no custom scripting.
Closest pre-written thing I could find currently (4-16-2012) is https://github.com/astraw/svg_stack, which lets you write commands of the form:
svg_stack.py --direction=h --margin=100 red_ball.svg blue_triangle.svg > shapes.svg
to concatenate.
It should be pretty easy if you're willing to use a scripting language. For each file, just add a prefix to all id tags; so in file 1, id="circle" becomes id="file1_circle", and in file 2, id="circle" becomes id="file2_circle".
In most cases you would get away with a trivial search and replace (find id=" and replace it with id="fileX_) although it is possible to have cases where this won't work (specifically if that find string appears in an item of text, for example).
If you want to do this 'the proper way', you'll need an XML parser (such as XMLReader in PHP).

How do I get the HTML in an element using Capybara?

I’m writing a cucumber test where I want to get the HTML in an element.
For example:
within 'table' do
# this works
find('//tr[2]//td[7]').text.should == "these are the comments"
# I want something like this (there is no "html" method)
find('//tr[2]//td[7]').html.should == "these are the <b>comments</b>"
end
Anyone know how to do this?
You can call HTML DOM innerHTML Property:
find('//tr[2]//td[7]')['innerHTML']
Should work for any browser or driver.
You can check all available properties on w3schools
This post is old, but I think I found a way if you still need this.
To access the Nokogiri node from the Capybara element (using Capybara 1.0.0beta1, Nokogiri 1.4.4) try this:
elem = find('//tr[2]//td[10]')
node = elem.native
#This will give you a Nokogiri XML element
node.children[1].attributes["href"].value.should == "these are the <b>comments</b>"
The last part may vary for you, but you should be able to find the HTML somewhere in that node variable
In my environment, find returns a Capybara::Element - that responds to the :native method as Eric Hu mentioned above, which returns a Selenium::WebDriver::Element (for me). Then :text gets the contents, so it could be as simple as:
results = find(:xpath, "//td[#id='#{cell_id}']")
contents = results.native.text
if you're looking for the contents of a table cell. There's no content, inner_html, inner_text, or node methods on a Capybara::Element. Assuming people aren't just making things up, perhaps you get something different back from find depending on what else you have loaded with Capybara.
Looks like you can do (node).native.inner_html to get the HTML content, for example with HTML like this:
<div><strong>Some</strong> HTML</div>
You could do the following:
find('div').native.inner_html
=> '<strong>Some</strong> HTML'
I ran into the same issue as Cyril Duchon-Doris, and per https://github.com/teampoltergeist/poltergeist/issues/629 the way to access the HTML of an Capybara::Poltergeist::Node is via the outerHTML property, e.g.:
find('//tr[2]//td[7]')['outerHTML']
Most of the other answers work only in Racktest (as they use Racktest-specific features).
If your driver supports javascript evaluation (like Selenium) you can use innerHTML :
html = page.evaluate_script("document.getElementById('my_id').innerHTML")
If you're using the Poltergeist driver, these methods will allow you to inspect what matches:
http://www.rubydoc.info/gems/poltergeist/1.5.1/Capybara/Poltergeist/Node
For example:
page.find('[name="form-field"]').native.value == 'something'
try calling find('//tr[2]//td[10]').node on it to get at the actual nokogiri object
Well, Capybara uses Nokogiri to parse, so this page might be appropriate:
http://nokogiri.org/Nokogiri/XML/Node.html
I believe content is the method you are looking for.
You could also switch to capybara-ui and do the following:
# define your widget, in this case in your role
class User < Capybara::UI::Role
widget :seventh_cell, [:xpath, '//tr[2]//td[7]']
end
# then in your tests
role = User.new
expect(role.widget(:seventh_cell).html).to eq(<h1>My html</h1>)

Resources